Skip to content

fix: prevent palette feedback binding loops - #729

Merged
18202781743 merged 1 commit into
linuxdeepin:masterfrom
18202781743:master
Oct 21, 2026
Merged

18202781743 merged 1 commit into
linuxdeepin:masterfrom
18202781743:master

Conversation

@18202781743

@18202781743 18202781743 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor
  1. Store palette changed connection and disconnect it when control
    changes to avoid stale connections
  2. Add null check for palette pointer before connecting to changed
    signal
  3. Defer updateControlTheme via scheduleControlThemeUpdate using queued
    connection to break binding feedback loops
  4. Add m_controlThemeUpdatePending flag to coalesce multiple update
    requests
  5. Add unit tests for deferred/coalesced palette updates, destruction
    with pending updates, and styled control palette feedback

The palette is both an input and output of the color selector, causing
binding loops when palette changes triggered immediate writes back
to the same palette. Deferring the update to the next event loop
iteration allows existing bindings to finish before notifying again.
The connection cleanup prevents dangling connections when the control's
palette changes.

Influence:

  1. Test controls with palette bindings to D.ColorSelector (Button,
    ToolButton, MenuItem)
  2. Verify no "Binding loop" warnings appear in console
  3. Test theme switching between light and dark modes
  4. Test hover, press, checked, disabled states with palette feedback
  5. Verify selector destruction while a palette update is pending does
    not crash
  6. Confirm palette updates settle and do not trigger continuous event
    processing

fix: 修复调色板反馈导致的绑定循环

  1. 保存调色板 changed 信号连接,在控件切换时断开以避免遗留连接
  2. 连接 changed 信号前增加调色板空指针检查
  3. 通过 scheduleControlThemeUpdate 使用队列连接延迟 updateControlTheme
    以打破绑定反馈循环
  4. 添加 m_controlThemeUpdatePending 标志合并多次更新请求
  5. 添加延迟/合并调色板更新、销毁时存在待处理更新、以及带样式控件调色板反
    馈的单元测试

调色板既是颜色选择器的输入也是输出,当调色板变化立即回写同一调色板时会触
发绑定循环。将更新延迟到下一个事件循环迭代,使已有绑定先完成再通知。连接
清理可避免控件调色板变化时产生悬空连接。

Influence:

  1. 测试使用 D.ColorSelector 调色板绑定的控件(Button、ToolButton、
    MenuItem)
  2. 验证控制台不出现"Binding loop"警告
  3. 测试明暗主题切换
  4. 测试 hover、按下、选中、禁用状态下的调色板反馈
  5. 验证存在待处理调色板更新时销毁选择器不会崩溃
  6. 确认调色板更新能稳定下来,不会触发持续的事件处理

Summary by Sourcery

Prevent palette feedback binding loops by safely managing palette connections and deferring coalesced control theme updates.

Bug Fixes:

  • Prevent palette feedback from causing binding loops during control theme updates.
  • Avoid stale palette signal connections when the associated control changes or its palette is unavailable.
  • Ensure pending palette updates are safely discarded when the selector or control is destroyed.

Enhancements:

  • Defer and coalesce control theme updates so palette changes settle without repeated event processing.

Tests:

  • Add coverage for deferred and coalesced palette updates, pending-update destruction, and palette feedback across styled controls and interaction states.

1. Store palette changed connection and disconnect it when control
changes to avoid stale connections
2. Add null check for palette pointer before connecting to changed
signal
3. Defer updateControlTheme via scheduleControlThemeUpdate using queued
connection to break binding feedback loops
4. Add m_controlThemeUpdatePending flag to coalesce multiple update
requests
5. Add unit tests for deferred/coalesced palette updates, destruction
with pending updates, and styled control palette feedback

The palette is both an input and output of the color selector, causing
binding loops when palette changes triggered immediate writes back
to the same palette. Deferring the update to the next event loop
iteration allows existing bindings to finish before notifying again.
The connection cleanup prevents dangling connections when the control's
palette changes.

Influence:
1. Test controls with palette bindings to D.ColorSelector (Button,
ToolButton, MenuItem)
2. Verify no "Binding loop" warnings appear in console
3. Test theme switching between light and dark modes
4. Test hover, press, checked, disabled states with palette feedback
5. Verify selector destruction while a palette update is pending does
not crash
6. Confirm palette updates settle and do not trigger continuous event
processing

fix: 修复调色板反馈导致的绑定循环

1. 保存调色板 changed 信号连接,在控件切换时断开以避免遗留连接
2. 连接 changed 信号前增加调色板空指针检查
3. 通过 scheduleControlThemeUpdate 使用队列连接延迟 updateControlTheme
以打破绑定反馈循环
4. 添加 m_controlThemeUpdatePending 标志合并多次更新请求
5. 添加延迟/合并调色板更新、销毁时存在待处理更新、以及带样式控件调色板反
馈的单元测试

调色板既是颜色选择器的输入也是输出,当调色板变化立即回写同一调色板时会触
发绑定循环。将更新延迟到下一个事件循环迭代,使已有绑定先完成再通知。连接
清理可避免控件调色板变化时产生悬空连接。

Influence:
1. 测试使用 D.ColorSelector 调色板绑定的控件(Button、ToolButton、
MenuItem)
2. 验证控制台不出现"Binding loop"警告
3. 测试明暗主题切换
4. 测试 hover、按下、选中、禁用状态下的调色板反馈
5. 验证存在待处理调色板更新时销毁选择器不会崩溃
6. 确认调色板更新能稳定下来,不会触发持续的事件处理
@18202781743
18202781743 requested review from BLumia and mhduiy October 20, 2026 13:41
@sourcery-ai

sourcery-ai Bot commented Oct 20, 2026

Copy link
Copy Markdown

Reviewer's Guide

The selector now safely manages palette signal connections and defers/coalesces control theme updates through the event loop, breaking palette input/output binding loops while preserving stable palette synchronization; new tests cover lifecycle safety, feedback stabilization, and styled-control states.

Sequence diagram for deferred palette theme updates

sequenceDiagram
    participant Palette as QQuickPalette
    participant Selector as DQuickControlColorSelector
    participant EventLoop
    participant Binding

    Palette->>Selector: scheduleControlThemeUpdate()
    Selector->>Selector: Check m_controlThemeUpdatePending
    Selector->>EventLoop: invokeMethod(..., Qt::QueuedConnection)
    EventLoop-->>Selector: Run queued callback
    Selector->>Selector: updateControlTheme()
    Selector->>Binding: Notify synchronized palette colors
    Binding-->>Palette: Complete existing binding
Loading

State diagram for coalesced control theme updates

stateDiagram-v2
    [*] --> Idle
    Idle --> UpdatePending: scheduleControlThemeUpdate()
    UpdatePending --> UpdatePending: scheduleControlThemeUpdate() ignored
    UpdatePending --> Idle: Queued callback calls updateControlTheme()
    Idle --> [*]
Loading

File-Level Changes

Change Details Files
Lifecycle-safe palette signal handling is added when the selector’s control changes.
  • Store the palette changed-signal connection and disconnect it before replacing the control.
  • Guard palette signal hookup against a null palette.
  • Route control and palette changes through the deferred update scheduler.
src/private/dquickcontrolpalette.cpp
src/private/dquickcontrolpalette_p.h
Palette-driven theme updates are deferred and coalesced to prevent binding feedback loops.
  • Queue theme updates for the next event-loop iteration.
  • Suppress duplicate pending update requests with a state flag.
  • Retain safe behavior when the selector is destroyed while an update is queued.
src/private/dquickcontrolpalette.cpp
src/private/dquickcontrolpalette_p.h
Regression coverage validates deferred updates, stabilization, destruction safety, and real control feedback scenarios.
  • Test coalescing and deferred notification behavior without binding-loop warnings.
  • Test destruction with a pending palette update.
  • Exercise Button, ToolButton, and MenuItem across theme and interaction states, verifying palette synchronization settles.
tests/ut_colorselector.cpp

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 reviewed your changes and they look great!


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

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

deepin pr auto review

🤖 AI 代码审查报告

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

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次提交通过引入延迟合并机制(scheduleControlThemeUpdate + Qt::QueuedConnection + m_controlThemeUpdatePending 标志) 有效修复了 palette 反馈绑定循环问题。代码逻辑正确,防御性编程到位(null 检查、连接管理、对象生命周期安全), 性能上通过合并多次 palette 变更减少冗余更新,无安全漏洞。测试覆盖充分,包含绑定循环检测、对象销毁安全、 多控件类型回归测试。

🔍 详细分析

1. 语法逻辑 ✅

评价: 语法正确,逻辑清晰 ✅ 通过

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

建议: []


2. 代码质量 ✅

评价: 代码结构清晰,注释完整 ✅ 通过

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

建议: []


3. 代码性能 ✅

评价: 性能良好,资源使用合理 ✅ 通过

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

建议: []


4. 代码安全 🔒

评价: 存在0个安全漏洞 ✅ 通过

🔐 发现 0 个安全漏洞

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

建议: []


💡 改进建议代码示例

// 当前代码已为最佳实践,无需额外修复。 // scheduleControlThemeUpdate() 的延迟合并模式是处理 Qt 绑定循环的标准方案: // // void DQuickControlColorSelector::scheduleControlThemeUpdate() // { //     if (m_controlThemeUpdatePending) //         return; //     m_controlThemeUpdatePending = true; //     QMetaObject::invokeMethod(this, [this] { //         m_controlThemeUpdatePending = false; //         updateControlTheme(); //     }, Qt::QueuedConnection); // }

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

@18202781743

18202781743 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

LD_LIBRARY_PATH=/home/work/dtkwidget/build6/src:/home/work/dtkdeclarative/build6/qt6/src QML_IMPORT_PATH=/home/work/dtkdeclarative/build6/plugins timeout 55s gdb -q -batch -ex 'set debuginfod enabled off' -ex 'set breakpoint pending on' -ex 'break QQmlBinding::printBindingLoopError' -ex run -ex 'bt 55' --args ./build6/examples/exhibition/dtk6-exhibition 2>&1 | tail -85
已复现,并通过 GDB 确认:这是 ColorSelector 与控件 palette 之间的同步反馈,Button.qml:27 是循环被检测到的位置。

Button.qml:27 (qt6/src/qml/Button.qml:27) 中:

palette.windowText: D.ColorSelector.textColor

实际报警调用链为:

绑定计算完成,写入 palette.windowText
→ paletteChanged
→ ColorSelector::updateControlTheme()
→ updateAllColorProperties()
→ updatePropertyFromName() 更新 textColor,发出通知
→ 同一个 windowText 绑定再次执行
→ 前一次绑定尚未退出,Qt 报 Binding loop

关键在 updateControlTheme() (src/private/dquickcontrolpalette.cpp:1017):即使主题没变,也会立即刷新全部颜色。本次调用栈明确经过这个分支。Qt 已对动态属性做同值判断,因此再加一次“颜色相等就返回”不能解决这次问题。

此外,setControl() (src/private/dquickcontrolpalette.cpp:470) 在 Qt 6 下同时监听 QQuickPalette::changed 和控件的 paletteChanged,存在重复刷新路径。Button、ToolButton、MenuItem 等共用该机制,所以会集中出现类似警告。

实现

  • 在 ColorSelector 中增加内部刷新调度函数和 pending 标记;palette 变化时只安排一次事件循环回调,在当前 QML 绑定退出后执行 updateControlTheme()。
  • 两条 palette 通知路径统一进入调度函数,合并同一轮重复通知。回调绑定 selector 的 QObject 生命周期,销毁后自动取消。
  • 初始化时的主题计算,以及 hovered、pressed、disabled 等状态更新仍保持同步。
  • 保留现有 palette.windowText 绑定,维持子控件调色板继承和 DCI 图标取色行为;不改公共 API。

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, BLumia

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

@18202781743
18202781743 merged commit ccb129a into linuxdeepin:master Oct 21, 2026
19 of 20 checks passed
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