Skip to content

fix(qml): correct dropdown sizing - #721

Open
mhduiy wants to merge 1 commit into
masterfrom
bug-377521-dropdown-sizing
Open

mhduiy wants to merge 1 commit into
masterfrom
bug-377521-dropdown-sizing

Conversation

@mhduiy

@mhduiy mhduiy commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

PMS: BUG-377521

Summary

  • Measure realized visible dropdown items and retain the maximum width.
  • Size the list from realized visible row height and laid-out content.
  • Remove the ComboBox delegate implicit-width dependency on popup width.

Verification

  • Build: cmake --build build6 -j8
  • Smoke: custom hidden-row ComboBox popup, 170px height with no extra arrows.

Summary by Sourcery

Fix QML dropdown sizing so popup dimensions accurately reflect visible rows and content.

Bug Fixes:

  • Correct dropdown sizing when rows are hidden or not yet realized by measuring visible content and using the realized row height.
  • Ensure ComboBox popup width is determined by its content rather than a delegate dependency on popup width.

Enhancements:

  • Improve list view sizing and scrolling behavior based on realized content and measured visible item widths.

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mhduiy

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

sourcery-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR fixes dropdown sizing by measuring realized visible delegates for intrinsic width and row height, using those measurements to calculate list geometry and scrolling, and removing the delegate’s dependency on the popup width so the popup can grow to fit its content.

Sequence diagram for dropdown content measurement and sizing

sequenceDiagram
    participant ComboBox
    participant Popup
    participant ArrowListView
    participant ListView
    participant Delegate

    ComboBox->>Popup: implicitWidth
    Popup->>ArrowListView: sizedHeight
    ArrowListView->>ListView: contentHeight
    ListView->>Delegate: itemAtIndex(i)
    Delegate-->>ArrowListView: visible height and implicitWidth
    ArrowListView->>ArrowListView: calculate rowHeight and itemMaxWidth
    ArrowListView-->>Popup: implicitWidth and implicitHeight
    Popup-->>ComboBox: sized dropdown geometry
Loading

File-Level Changes

Change Details Files
Derive popup/list height from realized visible rows instead of assuming the first delegate represents the content.
  • Add a visible positive-height rowHeight fallback to the style height.
  • Use laid-out content height when available, otherwise calculate capped height and arrow-strip space from rowHeight.
  • Update scrolling and implicit-height behavior to reflect actual content overflow.
qt6/src/qml/ArrowListView.qml
Track the maximum width of realized visible delegates and use it to size the list.
  • Accumulate delegate implicit widths as items are realized or children change.
  • Reset and refresh measurements when the model count changes, and refresh delegate widths on layout changes.
  • Skip hidden delegates so hidden rows do not affect sizing.
qt6/src/qml/ArrowListView.qml
Break the circular dependency between ComboBox delegate width and popup width.
  • Let each delegate retain its intrinsic content width while the list stretches realized items to the viewport.
  • Include popup horizontal margins in the flat ComboBox implicit width calculation.
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

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="qt6/src/qml/ArrowListView.qml" line_range="20-26" />
<code_context>
-    // Full height of the list, to size a popup before it is mapped.
+    // Height of a visible realized row, or the style height before one exists:
+    // row 0 can be a row hidden by a visible role, and its height is 0.
+    readonly property real rowHeight: {
+        if (itemsView.contentHeight > 0) {
+            for (var i = 0; i < itemsView.count; ++i) {
+                const item = itemsView.itemAtIndex(i)
+                if (item && item.visible && item.height > 0)
+                    return item.height
+            }
+        }
+        return itemHeight
</code_context>
<issue_to_address>
**Mixed row heights mis-size the menu**

When visible delegates have different heights and the first realized visible row is not representative of the first `maxVisibleItems` rows, `rowHeight` uses that first row, and `implicitHeight` multiplies it by `maxVisibleItems`. A short first row clips later taller rows, while a tall first row can leave room for too many shorter rows and keep `interactive` false; users see fewer or more rows than intended, without the expected scroll controls.

Size the viewport using the summed heights of the first `maxVisibleItems` visible rows, so the height cap and scrolling threshold reflect the actual rows.

Also at `qt6/src/qml/ArrowListView.qml:66-67`.
</issue_to_address>

### Comment 2
<location path="qt6/src/qml/ComboBox.qml" line_range="177" />
<code_context>
         rightMargin: DS.Style.popup.margin
         palette: control.palette
-        implicitWidth: control.flat ? Math.max(contentItem.implicitWidth, control.width) : control.width
+        implicitWidth: control.flat ? Math.max(contentItem.implicitWidth + leftMargin + rightMargin, control.width) : control.width
         // 60 is a temporary viewport so the list can realize one row and be measured.
         implicitHeight: (contentItem.sizedHeight > 0 ? contentItem.sizedHeight : 2 * DS.Style.arrowListView.itemHeight)
</code_context>
<issue_to_address>
**Popup width uses placement margins**

When a flat ComboBox has content wider than its control and the popup margin differs from its horizontal content padding, the `implicitWidth` formula adds `leftMargin` and `rightMargin`, which constrain window-edge placement rather than pad content. The popup becomes wider than needed when margins exceed padding, or clips content when they are smaller.

Use the popup's horizontal content padding, not its placement margins, in the width calculation.
</issue_to_address>

### Comment 3
<location path="qt6/src/qml/ArrowListView.qml" line_range="39" />
<code_context>
         const arrowStrips = itemsView.count > maxVisibleItems
                 ? 2 * (DS.Style.arrowListView.stepButtonIconSize.height + contentLayout.spacing) : 0
-        return Math.min(itemsView.count, maxVisibleItems) * (measured > 0 ? measured : itemHeight) + arrowStrips
+        return Math.min(itemsView.count, maxVisibleItems) * rowHeight + arrowStrips
     }

</code_context>
<issue_to_address>
**Hidden rows leave blank popup**

When the model has items but every delegate is hidden, `sizedHeight` falls back to `count * rowHeight` when `contentHeight` is zero, so an all-hidden model still opens a nonzero-height blank popup.

Return zero once layout confirms there are no visible rows, while retaining the estimate only before rows have been realized.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread qt6/src/qml/ArrowListView.qml Outdated
Comment thread qt6/src/qml/ComboBox.qml Outdated
Comment thread qt6/src/qml/ArrowListView.qml Outdated
@mhduiy
mhduiy force-pushed the bug-377521-dropdown-sizing branch 2 times, most recently from 3f77146 to 8403c94 Compare October 15, 2026 05:46
Comment thread qt6/src/qml/ArrowListView.qml Outdated
if (!item || !item.visible)
continue
item.width = itemsView.width
if (item.implicitWidth > itemMaxWidth)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

itemMaxWidth可能在这个循环里触发多次,可以用临时变量存储中间值,

}
interactive: itemsView.count > maxVisibleItems
implicitHeight: itemsView.count > 0 ? Math.min(contentHeight, maxVisibleItems * control.rowHeight) : 0
implicitWidth: itemMaxWidth

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

implicitWidth重构与原来的逻辑是一样的吧,只是多了个visible的判断么?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

算是,重复逻辑都抽出到refreshContentItemWidth中,

另外就是主要是修复了一个循环依赖,popup, menuitem 相互取宽度,导致最终算出来的宽度是错误的。
删除 implicitWidth: Math.max(DS.Style.control.implicitWidth(control), popup.implicitWidth - DS.Style.popup.margin * 2)

Comment thread qt6/src/qml/ArrowListView.qml Outdated
// Full height of the list, to size a popup before it is mapped.
// Height of a visible realized row, or the style height before one exists:
// row 0 can be a row hidden by a visible role, and its height is 0.
readonly property real rowHeight: {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

rowHeight不暴露出去吧?加上下划线标识私有变量,

1. Measure realized visible items and retain their maximum width.
2. Use visible row height and laid-out content to size the list.
3. Keep ComboBox delegate implicit width independent of popup width.

Log: Correct dropdown width measurement and height sizing
Influence: Improve dropdown sizing and item visibility.

fix(qml): 修正下拉列表尺寸计算

1. 测量已创建的可见项并保留最大宽度。
2. 使用可见项行高和布局后的内容计算列表高度。
3. 移除组合框委托隐式宽度对弹窗宽度的依赖。

Log: 修正下拉列表宽度测量和高度计算
PMS: BUG-377521
Influence: 改善下拉列表尺寸和选项显示。
@mhduiy
mhduiy force-pushed the bug-377521-dropdown-sizing branch from 8403c94 to 47eefcd Compare October 15, 2026 08:22
@deepin-ci-robot

Copy link
Copy Markdown
Contributor

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 97 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 97 分,大于 70 分通过阈值,代码质量符合要求。本次变更正确修复了下拉列表尺寸计算问题,逻辑清晰,无安全漏洞。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 语法正确,逻辑清晰,无需修改。建议在sizedHeight中当contentHeight > 0时返回implicitHeight处添加注释说明此时arrowStrips已包含在布局高度中。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. qt6/src/qml/ArrowListView.qml:61 - itemMaxWidth属性缺少注释说明其作为最大宽度缓存的设计意图

建议: 代码结构清晰,注释完整。建议为itemMaxWidth属性和refreshContentItemWidth中的缓存逻辑添加简短注释,提升可维护性。


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. qt6/src/qml/ArrowListView.qml:18 - _rowHeight readonly binding在依赖变化时重新遍历items,对大数据量列表可能产生性能开销

建议: 性能良好,资源使用合理。对于大数据量列表场景,可考虑将_rowHeight的计算结果缓存,避免每次binding重新求值时遍历。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 存在0个安全漏洞。QML UI代码无安全风险,无需安全加固。


💡 改进建议代码示例

// ArrowListView.qml - 建议为itemMaxWidth添加注释
// 缓存已测量项的最大隐式宽度,避免每次从零计算
property real itemMaxWidth: 0

// ComboBox.qml - 当前实现已正确修复循环依赖问题
// delegate不再依赖popup.implicitWidth,消除循环依赖
delegate: MenuItem {
    useIndicatorPadding: true
    // implicitWidth已移除,由refreshContentItemWidth统一测量
}

本报告由 AI 代码审查工具自动生成

@deepin-bot

deepin-bot Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

TAG Bot

New tag: 6.7.51
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #723

This branch has not been deployed

No deployments
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