Skip to content

fix(dock): fix wrong docked app icons after login - #1696

Open
Ivy233 wants to merge 1 commit into
linuxdeepin:masterfrom
Ivy233:fix/dock-docked-app-wrong-icon
Open

fix(dock): fix wrong docked app icons after login#1696
Ivy233 wants to merge 1 commit into
linuxdeepin:masterfrom
Ivy233:fix/dock-docked-app-wrong-icon

Conversation

@Ivy233

@Ivy233 Ivy233 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
  1. Track rowsInserted of the apps model in DockGlobalElementModel to keep the cached sourceRow of docked items in sync while the apps model is rebuilt at startup; only rowsRemoved was handled before, so inserted rows made docked items resolve to the wrong app and show the wrong icon/name
  2. Handle apps-model modelReset by re-resolving every cached sourceRow by desktopId
  3. Guard DockGlobalElementModel::data() against an out-of-range cached sourceRow and re-resolve it on demand
  4. Include IconNameRole/NameRole in dataChanged when a dock row switches its source between the apps model and the active-app model, so QML delegates refresh the icon/name
  5. Drop invalid dataChanged (row -1) in DockItemModel before forwarding to QML

Log: fix docked app icon/name showing another app's data after login

Influence:

  1. Verify docked app icons are correct right after login/restart
  2. Verify icons stay correct while apps are installed/uninstalled/launched
  3. Verify dock item name/tooltip matches the hovered app
  4. Verify window split and group modes still work

fix(dock): 修复登录后驻留应用图标显示错误

  1. 在 DockGlobalElementModel 中跟踪应用模型的行插入(rowsInserted),使 驻留项缓存的 sourceRow 在启动期应用模型重建时保持同步;此前仅处理行删除,
    插入的行会使驻留项解析到错误的应用,显示错误的图标/名称
  2. 应用模型整体重建(modelReset)时按 desktopId 重新解析所有缓存的 sourceRow
  3. DockGlobalElementModel::data() 对越界的缓存 sourceRow 增加保护,并按需 重新解析
  4. 驻留行在应用模型与运行应用模型之间切换时,dataChanged 补充 IconNameRole/NameRole,确保 QML 委托刷新图标/名称
  5. DockItemModel 转发 dataChanged 前过滤无效索引(row 为 -1)

Log: 修复登录后驻留应用图标/名称显示为其他应用数据的问题

Influence:

  1. 验证重启登录后驻留应用图标正确
  2. 验证应用安装/卸载、启动过程中图标仍正确
  3. 验证驻留项名称/悬浮提示与所悬停应用一致
  4. 验证窗口拆分/分组模式正常

PMS: BUG-372179

Summary by Sourcery

Ensure docked app entries resolve to the correct application after login by keeping cached source rows in sync with the apps model and guarding against invalid indices.

Bug Fixes:

  • Prevent docked app icons and names from pointing to the wrong application when the apps model is rebuilt at startup or changes over time.
  • Avoid crashes or incorrect state when cached source rows become out of range by re-resolving them or returning safe defaults.
  • Stop propagating invalid dataChanged signals from the dock item model to QML when the source indices are not valid.

Enhancements:

  • Propagate icon/name-related roles in dataChanged notifications so QML delegates update dock item visuals consistently after source model switches or dock loads.

1. Track rowsInserted of the apps model in DockGlobalElementModel to keep
the cached sourceRow of docked items in sync while the apps model is
rebuilt at startup; only rowsRemoved was handled before, so inserted rows
made docked items resolve to the wrong app and show the wrong icon/name
2. Handle apps-model modelReset by re-resolving every cached sourceRow by
desktopId
3. Guard DockGlobalElementModel::data() against an out-of-range cached
sourceRow and re-resolve it on demand
4. Include IconNameRole/NameRole in dataChanged when a dock row switches
its source between the apps model and the active-app model, so QML
delegates refresh the icon/name
5. Drop invalid dataChanged (row -1) in DockItemModel before forwarding
to QML

Log: fix docked app icon/name showing another app's data after login

Influence:
1. Verify docked app icons are correct right after login/restart
2. Verify icons stay correct while apps are installed/uninstalled/launched
3. Verify dock item name/tooltip matches the hovered app
4. Verify window split and group modes still work

fix(dock): 修复登录后驻留应用图标显示错误

1. 在 DockGlobalElementModel 中跟踪应用模型的行插入(rowsInserted),使
驻留项缓存的 sourceRow 在启动期应用模型重建时保持同步;此前仅处理行删除,
插入的行会使驻留项解析到错误的应用,显示错误的图标/名称
2. 应用模型整体重建(modelReset)时按 desktopId 重新解析所有缓存的
sourceRow
3. DockGlobalElementModel::data() 对越界的缓存 sourceRow 增加保护,并按需
重新解析
4. 驻留行在应用模型与运行应用模型之间切换时,dataChanged 补充
IconNameRole/NameRole,确保 QML 委托刷新图标/名称
5. DockItemModel 转发 dataChanged 前过滤无效索引(row 为 -1)

Log: 修复登录后驻留应用图标/名称显示为其他应用数据的问题

Influence:
1. 验证重启登录后驻留应用图标正确
2. 验证应用安装/卸载、启动过程中图标仍正确
3. 验证驻留项名称/悬浮提示与所悬停应用一致
4. 验证窗口拆分/分组模式正常

PMS: BUG-372179
@deepin-ci-robot

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Ivy233

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 Aug 11, 2026

Copy link
Copy Markdown

Reviewer's Guide

Keeps docked items’ cached mappings in sync with the apps model, hardens bounds checking when resolving roles, ensures icon/name roles are emitted when sources change, and filters invalid dataChanged signals before forwarding to QML so docked icons/names stay correct after login and during model rebuilds.

Sequence diagram for dock model updates keeping docked icons in sync

sequenceDiagram
    actor User
    participant AppsModel
    participant ActiveAppModel
    participant DockGlobalElementModel
    participant DockItemModel
    participant QMLDelegate

    rect rgb(235,235,255)
        AppsModel->>DockGlobalElementModel: rowsInserted(parent, first, last)
        DockGlobalElementModel->>DockGlobalElementModel: update m_data cached sourceRow
    end

    rect rgb(235,255,235)
        AppsModel->>DockGlobalElementModel: modelReset
        DockGlobalElementModel->>AppsModel: match(DesktopIdRole, id)
        AppsModel-->>DockGlobalElementModel: matching index
        DockGlobalElementModel->>DockGlobalElementModel: update cached sourceRow
    end

    rect rgb(255,235,235)
        ActiveAppModel->>DockGlobalElementModel: rowsInserted(parent, first, last)
        DockGlobalElementModel->>DockGlobalElementModel: switch dock row source
        DockGlobalElementModel-->>DockItemModel: dataChanged(pIndex, pIndex, IconNameRole, NameRole,...)
        DockItemModel->>DockItemModel: [!m_isUpdating && indices valid]
        DockItemModel-->>QMLDelegate: dataChanged(pIndex, pIndex, IconNameRole, NameRole,...)
    end

    rect rgb(235,245,245)
        QMLDelegate->>DockItemModel: data(index, NameRole)
        DockItemModel->>DockGlobalElementModel: data(index, NameRole)
        DockGlobalElementModel->>DockGlobalElementModel: [model == m_appsModel]
        DockGlobalElementModel->>DockGlobalElementModel: [row < 0 || row >= rowCount]
        DockGlobalElementModel->>AppsModel: match(DesktopIdRole, id)
        AppsModel-->>DockGlobalElementModel: matching index
        DockGlobalElementModel-->>DockItemModel: data(NameRole)
        DockItemModel-->>QMLDelegate: data(NameRole)
    end
Loading

File-Level Changes

Change Details Files
Keep cached dock item source rows aligned with the apps model and re-resolve them on full model rebuilds.
  • Connect DockGlobalElementModel to apps-model rowsInserted to shift cached sourceRow indices when rows are inserted.
  • Handle apps-model modelReset by rematching each dock item’s desktopId to its row and updating cached sourceRow, or marking it invalid when not found.
panels/dock/taskmanager/dockglobalelementmodel.cpp
Harden DockGlobalElementModel::data() against stale or out-of-range cached rows and ensure correct role propagation to QML.
  • Before accessing data, re-resolve apps-model rows by desktopId when cached sourceRow is out of range and guard all role paths with row bounds checks, returning empty/fallback values when invalid.
  • Extend dataChanged emissions when dock items switch between apps and active-app models or are loaded to include IconNameRole and NameRole so delegates refresh icon/name correctly.
panels/dock/taskmanager/dockglobalelementmodel.cpp
Prevent invalid dataChanged signals from reaching QML in DockItemModel.
  • Short-circuit DockItemModel’s dataChanged handler when updates occur during internal updates or when the incoming model indexes are invalid, avoiding bogus updates for row -1.
panels/dock/taskmanager/dockitemmodel.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

@Ivy233
Ivy233 marked this pull request as ready for review August 11, 2026 09:44

@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 left some high level feedback:

  • In DockGlobalElementModel::data(), when you re-resolve the apps-model row via match() for out-of-range cached rows, you only update the local row variable; consider writing the resolved row back into m_data so subsequent accesses don’t repeatedly perform a match and so the cache is actually corrected.
  • The repeated row < 0 || row >= model->rowCount() checks and model->index(row, 0) calls in DockGlobalElementModel::data() could be refactored into a small helper to centralize bounds checking and index retrieval, reducing duplication and the risk of future inconsistencies.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In DockGlobalElementModel::data(), when you re-resolve the apps-model row via match() for out-of-range cached rows, you only update the local `row` variable; consider writing the resolved row back into `m_data` so subsequent accesses don’t repeatedly perform a match and so the cache is actually corrected.
- The repeated `row < 0 || row >= model->rowCount()` checks and `model->index(row, 0)` calls in DockGlobalElementModel::data() could be refactored into a small helper to centralize bounds checking and index retrieval, reducing duplication and the risk of future inconsistencies.

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.

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:85分

■ 【总体评价】

代码修复了任务栏模型索引越界崩溃问题,但存在因异步连接导致的严重时序逻辑错误
逻辑修复思路正确但因QueuedConnection引发的信号时序双重偏移问题扣15分

■ 【详细分析】

  • 1.语法逻辑(存在严重错误)✕

DockGlobalElementModel 构造函数中,对 rowsInsertedmodelReset 信号均使用了 Qt::QueuedConnection 进行异步处理。在应用模型启动重建时,底层通常会先触发 modelReset,随后触发多次 rowsInserted。由于异步队列的存在,modelReset 的槽函数会先执行,将缓存行号修正为正确的绝对行号;随后排队的 rowsInserted 槽函数执行时,会错误地将已经正确的行号再次加上 insertedCount,导致索引二次漂移并越界崩溃。
潜在问题:异步信号处理顺序导致索引双重偏移越界
建议:将 rowsInsertedmodelReset 的连接方式改为 Qt::DirectConnection,或者在 modelReset 槽中设置一个标志位,在紧接着的 rowsInserted 中忽略处理,亦或取消监听 rowsInserted,完全依赖 modelReset 进行全量重定位

  • 2.代码质量(良好)✓

使用了 C++14 的泛型 lambda 和 std::for_each,代码简洁。注释详尽,准确描述了修复的背景和原因。data() 函数中针对不同角色增加了防御性编程,dockitemmodel.cpp 中也补充了索引有效性校验,整体符合规范。
建议:无

  • 3.代码性能(无性能问题)✓

modelReset 中的 match 调用复杂度为 O(N),data() 中的容错 match 仅在越界时触发,任务栏固定项数量和模型行数均在极小常数范围内,不会造成性能瓶颈。
建议:无

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码属于本地桌面 UI 模型层,不涉及网络请求、文件系统操作、命令执行或敏感数据处理,不存在外部输入注入或信息泄露风险。
建议:无

■ 【改进建议代码示例】

diff --git a/panels/dock/taskmanager/dockglobalelementmodel.cpp b/panels/dock/taskmanager/dockglobalelementmodel.cpp
index 23de5c700..8f9a12b41 100644
--- a/panels/dock/taskmanager/dockglobalelementmodel.cpp
+++ b/panels/dock/taskmanager/dockglobalelementmodel.cpp
@@ -58,7 +58,7 @@ DockGlobalElementModel::DockGlobalElementModel(QAbstractItemModel *appsModel, Do
+    // Keep the cached apps-model sourceRow in sync when apps are inserted.
+    // Use DirectConnection to prevent race conditions with modelReset signals in the event loop.
+    connect(
+        m_appsModel,
+        &QAbstractItemModel::rowsInserted,
+        this,
+        [this](const QModelIndex &parent, int first, int last) {
+            // Guard against spurious rowsInserted signals immediately following a modelReset
+            if (m_isResetting) return;
+            
+            Q_UNUSED(parent)
+            const int insertedCount = (last - first) + 1;
+            std::for_each(m_data.begin(), m_data.end(), [this, first, insertedCount](auto &data) {
+                if (std::get<1>(data) == m_appsModel && std::get<2>(data) >= first) {
+                    data = std::make_tuple(std::get<0>(data), std::get<1>(data), std::get<2>(data) + insertedCount);
+                }
+            });
+        },
+        Qt::DirectConnection);
+
+    // Apps model full rebuild (modelReset): re-resolve every cached sourceRow.
+    connect(
+        m_appsModel,
+        &QAbstractItemModel::modelReset,
+        this,
+        [this]() {
+            m_isResetting = true;
+            for (auto &data : m_data) {
+                if (std::get<1>(data) != m_appsModel)
+                    continue;
+                const auto id = std::get<0>(data);
+                auto res = m_appsModel->match(m_appsModel->index(0, 0), TaskManager::DesktopIdRole, id, 1, Qt::MatchExactly);
+                std::get<2>(data) = res.isEmpty() ? -1 : res.first().row();
+            }
+            // Reset the flag after all pending rowsInserted signals are processed
+            QMetaObject::invokeMethod(this, [this]() { m_isResetting = false; }, Qt::QueuedConnection);
+        },
+        Qt::DirectConnection);

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.

2 participants