Skip to content

fix: Fix the issue where the dropdown remains highlighted after being…#569

Open
pengfeixx wants to merge 1 commit intolinuxdeepin:masterfrom
pengfeixx:fix-304991
Open

fix: Fix the issue where the dropdown remains highlighted after being…#569
pengfeixx wants to merge 1 commit intolinuxdeepin:masterfrom
pengfeixx:fix-304991

Conversation

@pengfeixx
Copy link
Contributor

@pengfeixx pengfeixx commented Feb 6, 2026

… moved out

Fix the issue where the dropdown remains highlighted after being moved out

Log: Fix the issue where the dropdown remains highlighted after being moved out
pms: BUG-304991

Summary by Sourcery

Bug Fixes:

  • Prevent dropdown items from remaining highlighted after the mouse moves out of the ComboBox popup content.

@deepin-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: pengfeixx

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai
Copy link

sourcery-ai bot commented Feb 6, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Updates ComboBox dropdown item highlighting logic so items only appear highlighted while the popup content is hovered or a submenu is open, fixing a bug where the dropdown remained highlighted after the cursor left the popup.

Sequence diagram for ComboBox dropdown hover-based highlighting

sequenceDiagram
  actor User
  participant ComboBox
  participant PopupContent
  participant HoverHandler
  participant ListViewDelegate

  User->>ComboBox: open()
  ComboBox->>PopupContent: create_and_show()
  loop for_each_item
    PopupContent->>ListViewDelegate: instantiate_delegate(index)
    ListViewDelegate->>ComboBox: bind_highlighted_to(mouseInPopupContent_or_subMenu_visible_and_highlightedIndex)
  end

  User->>PopupContent: move_mouse_inside()
  PopupContent->>HoverHandler: hover_event(hovered_true)
  HoverHandler->>ComboBox: set_mouseInPopupContent(true)
  ComboBox->>ComboBox: highlightedIndex_changed()
  ComboBox->>ListViewDelegate: reevaluate_highlighted_binding()
  ListViewDelegate->>User: show_item_highlight()

  User->>PopupContent: move_mouse_outside()
  PopupContent->>HoverHandler: hover_event(hovered_false)
  HoverHandler->>ComboBox: set_mouseInPopupContent(false)
  ComboBox->>ListViewDelegate: reevaluate_highlighted_binding()
  ListViewDelegate->>User: remove_item_highlight()

  User->>ListViewDelegate: open_subMenu()
  ListViewDelegate->>ListViewDelegate: subMenu_visible_true
  ListViewDelegate->>User: keep_item_highlighted_while_subMenu_visible()

  User->>ListViewDelegate: close_subMenu()
  ListViewDelegate->>ListViewDelegate: subMenu_visible_false
  ListViewDelegate->>ComboBox: reevaluate_highlighted_binding()
  ComboBox->>ListViewDelegate: item_not_highlighted_when_mouse_not_in_popup_content()
  ListViewDelegate->>User: remove_item_highlight()
Loading

Class diagram for updated ComboBox highlighting properties and handlers

classDiagram
  class ComboBox {
    int maxVisibleItems
    Palette separatorColor
    var horizontalAlignment
    bool mouseInPopupContent
    int highlightedIndex
    onHighlightedIndexChanged()
  }

  class PopupContent {
    ListView view
    HoverHandler hoverHandler
  }

  class HoverHandler {
    bool hovered
    onHoveredChanged()
  }

  class ListView {
    int currentIndex
    int highlightRangeMode
    int highlightMoveDuration
  }

  class ListViewDelegate {
    int index
    bool highlighted
    bool hoverEnabled
    bool autoExclusive
    bool checked
    bool subMenu_visible
  }

  ComboBox --> PopupContent : owns
  PopupContent --> HoverHandler : contains
  PopupContent --> ListView : contains
  ListView --> ListViewDelegate : creates_delegates
  ComboBox --> ListViewDelegate : controls_highlightedIndex
  HoverHandler --> ComboBox : updates_mouseInPopupContent
  ComboBox --> ListViewDelegate : controls_highlighted_via_mouseInPopupContent_and_subMenu_visible
Loading

File-Level Changes

Change Details Files
Gate item highlighting on popup hover/submenu visibility and track hover state within popup content to avoid stale highlighted rows.
  • Add mouseInPopupContent boolean property on the ComboBox to track whether the mouse is over the popup content
  • Change delegate highlighted condition to additionally require mouseInPopupContent or an open subMenu, along with the existing highlightedIndex check
  • Ensure mouseInPopupContent is set to true whenever highlightedIndex changes (e.g., via keyboard navigation) so keyboard highlighting still works
  • Add a HoverHandler to the popup view to toggle mouseInPopupContent based on whether the pointer is over the popup content
qt6/src/qml/ComboBox.qml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Consider resetting mouseInPopupContent when the popup closes (e.g., in the popup’s onVisibleChanged handler) so that keyboard-only closing or programmatic closing does not leave the internal state stuck in true.
  • Using onHighlightedIndexChanged to set mouseInPopupContent = true conflates keyboard-driven highlighting with mouse hover; if the intent is to represent actual mouse presence, it might be clearer to derive this solely from pointer/hover events.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider resetting `mouseInPopupContent` when the popup closes (e.g., in the popup’s `onVisibleChanged` handler) so that keyboard-only closing or programmatic closing does not leave the internal state stuck in `true`.
- Using `onHighlightedIndexChanged` to set `mouseInPopupContent = true` conflates keyboard-driven highlighting with mouse hover; if the intent is to represent actual mouse presence, it might be clearer to derive this solely from pointer/hover events.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : (model[control.textRole] === undefined ? modelData[control.textRole] : model[control.textRole])) : modelData
icon.name: (control.iconNameRole && model[control.iconNameRole] !== undefined) ? model[control.iconNameRole] : null
highlighted: control.highlightedIndex === index
highlighted: (control.mouseInPopupContent || (subMenu && subMenu.visible)) && control.highlightedIndex === index
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combobox,没有subMenu这个场景吧,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个highlighted去掉复制,直接用Menu里的写法,可以么?

… moved out

Fix the issue where the dropdown remains highlighted after being moved out

Log: Fix the issue where the dropdown remains highlighted after being moved out
pms: BUG-304991
@deepin-ci-robot
Copy link
Contributor

deepin pr auto review

这段代码的修改主要是在 ComboBox 中增加了一个 mouseInPopupContent 属性,用于控制下拉列表项的高亮状态。以下是对这段代码的审查意见,包括语法逻辑、代码质量、性能和安全方面的改进建议:

1. 语法逻辑审查

  • 逻辑正确性
    • 代码逻辑基本正确。通过 mouseInPopupContent 标志位,结合 onHighlightedIndexChangedHoverHandler,实现了只有当鼠标进入弹出层内容区域时,才根据 highlightedIndex 显示高亮项。这解决了可能在鼠标未进入弹出层时(例如通过键盘导航)就错误显示高亮的问题。
    • highlighted 绑定逻辑:highlighted: control.mouseInPopupContent && control.highlightedIndex === index 是正确的,只有两个条件都为真时才高亮。

2. 代码质量审查

  • 命名规范:属性名 mouseInPopupContent 清晰表达了其含义,符合驼峰命名法。
  • 代码可读性:代码缩进和格式良好,易于阅读。
  • 注释缺失:新增的 mouseInPopupContent 属性和相关的 onHighlightedIndexChanged 处理逻辑缺少注释,建议添加注释说明其用途和实现原理,以便其他开发者理解。
  • 状态管理:目前 mouseInPopupContent 的状态重置逻辑缺失。当弹出层关闭时,该属性没有被重置为 false。这可能导致下次打开弹出层时,状态不正确。建议监听 popup.closed 信号并在其中重置该属性。

3. 代码性能审查

  • 属性绑定highlighted 属性的绑定依赖于 control.mouseInPopupContentcontrol.highlightedIndex。由于这两个属性变化频率不高(主要在鼠标移动或键盘操作时),因此不会造成严重的性能问题。
  • HoverHandlerHoverHandler 是 Qt Quick 中处理悬停事件的高效方式,比传统的 MouseArea 更轻量且易于使用,性能方面表现良好。

4. 代码安全审查

  • 潜在的状态不一致:如前所述,缺少对 mouseInPopupContent 的重置逻辑可能导致状态不一致。例如,如果用户通过键盘操作改变了 highlightedIndex,然后关闭弹出层,下次打开时 mouseInPopupContent 仍可能为 true(取决于具体的实现细节),导致高亮行为异常。
  • 外部访问风险mouseInPopupContent 是一个公共属性,外部代码可以随意修改它,这可能会破坏组件的内部逻辑。建议将其声明为 property bool mouseInPopupContent: false 的同时,考虑是否需要限制其访问权限(尽管 QML 属性本身没有严格的访问控制,但可以通过文档说明其仅供内部使用)。

改进建议代码

T.ComboBox {
    // ... 其他属性 ...

    // 新增属性,用于标记鼠标是否在弹出层内容区域
    // 建议添加注释说明用途
    property bool mouseInPopupContent: false

    // ... 其他代码 ...

    delegate: ItemDelegate {
        // ... 其他属性 ...

        // 只有当鼠标在弹出层内且当前项是高亮索引时,才高亮显示
        highlighted: control.mouseInPopupContent && control.highlightedIndex === index
        
        // ... 其他属性 ...
    }

    // 当高亮索引改变时,标记鼠标在弹出层内
    // 这通常意味着用户正在通过键盘或鼠标与弹出层交互
    onHighlightedIndexChanged: {
        mouseInPopupContent = true
    }

    // ... 其他代码 ...

    popup: Popup {
        // ... 其他代码 ...

        // 监听弹出层关闭事件,重置鼠标状态标志
        onClosed: {
            control.mouseInPopupContent = false
        }

        contentItem: ListView {
            // ... 其他属性 ...

            // 使用 HoverHandler 监听鼠标悬停状态
            HoverHandler {
                onHoveredChanged: {
                    control.mouseInPopupContent = hovered
                }
            }
        }
    }
}

改进点总结

  1. 添加注释:为 mouseInPopupContent 属性添加了注释,说明其用途。
  2. 状态重置:在 popup.onClosed 中添加了 control.mouseInPopupContent = false,确保每次关闭弹出层时状态都被重置,避免状态残留导致的问题。
  3. 逻辑完善:确保了 mouseInPopupContent 的状态管理更加健壮,无论是通过键盘还是鼠标操作,都能正确反映用户的交互意图。

这些改进将使代码更加健壮、可维护,并减少潜在的 Bug。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants