Skip to content

fix: many issues with RoleCombineModel#1189

Merged
BLumia merged 1 commit into
linuxdeepin:masterfrom
BLumia:rolecombinemodel-fix
Jul 18, 2025
Merged

fix: many issues with RoleCombineModel#1189
BLumia merged 1 commit into
linuxdeepin:masterfrom
BLumia:rolecombinemodel-fix

Conversation

@BLumia

@BLumia BLumia commented Jul 16, 2025

Copy link
Copy Markdown
Member

修正 RoleCombineModel 的若干问题,包括索引映射错误,minor
模型变化处理不完整,QAbstractItemModelTester运行失败等.

Summary by Sourcery

Fix various indexing and mapping issues in RoleCombineModel by properly handling rows/columns insertion and removal for both major and minor models, strengthen data access safety and parent handling, and correct combined role mapping logic.

New Features:

  • Implement hasChildren override for flat list support in RoleCombineModel

Bug Fixes:

  • Fix index map updates on rows/columns insertion and removal for major model
  • Handle rowsRemoved and columnsRemoved signals from minor model to keep mappings in sync
  • Prevent crashes on invalid mappings by returning empty QVariant for unmapped roles
  • Use QModelIndex() for beginInsertRows/Columns when parent is invalid to avoid invalid parent handling

Enhancements:

  • Improve role mapping logic to exclude major roles and correctly map minor roles to combined model
  • Add dataChanged emission for affected items after minor model removals

Tests:

  • Add QAbstractItemModelTester integration
  • Introduce new tests covering row removal mapping, invalid parent handling, minor model changes, role mapping, data access safety, and parent parameter handling in RoleCombineModel

修正 RoleCombineModel 的若干问题,包括索引映射错误,minor
模型变化处理不完整,QAbstractItemModelTester运行失败等.

Log:
@BLumia BLumia requested review from 18202781743 and tsic404 July 16, 2025 08:09
@sourcery-ai

sourcery-ai Bot commented Jul 16, 2025

Copy link
Copy Markdown

Reviewer's Guide

This PR overhauls RoleCombineModel’s change-listeners and mapping logic to correctly handle rows/columns inserted or removed from both major and minor models, fixes role-to-key assignments, adds safety checks for data access and flat-list behavior, and introduces comprehensive unit tests (including QAbstractItemModelTester) to validate these fixes.

Sequence diagram for row removal in minor model and mapping update

sequenceDiagram
    participant MinorModel as QAbstractItemModel (minor)
    participant RoleCombineModel
    participant MajorModel as QAbstractItemModel (major)
    MinorModel->>RoleCombineModel: rowsRemoved(parent, first, last)
    loop For each mapping in m_indexMap
        alt Mapping points to removed minor row
            RoleCombineModel->>RoleCombineModel: Try to rebind mapping using func
            alt New mapping valid
                RoleCombineModel->>RoleCombineModel: Update mapping
            else New mapping invalid
                RoleCombineModel->>RoleCombineModel: Remove mapping
            end
        else Mapping points to row after last
            RoleCombineModel->>RoleCombineModel: Adjust mapping row index
        end
    end
    loop For each affected major index
        RoleCombineModel-->>MajorModel: dataChanged(majorIndex, majorIndex, roles)
    end
Loading

Class diagram for updated RoleCombineModel structure

classDiagram
    class QAbstractProxyModel
    class RoleCombineModel {
        +QHash<int, QByteArray> roleNames() const
        +bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const
        +bool hasChildren(const QModelIndex &parent = QModelIndex()) const
        +QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
        +QModelIndex parent(const QModelIndex &child) const
        +int rowCount(const QModelIndex &parent) const
        +int columnCount(const QModelIndex &parent) const
        +QVariant data(const QModelIndex &index, int role) const
        -QMap<QPair<int, int>, QPair<int, int>> m_indexMap
        -QHash<int, int> m_minorRolesMap
        -QHash<int, QByteArray> m_roleNames
        -QAbstractItemModel* m_minor
    }
    QAbstractProxyModel <|-- RoleCombineModel
    class QAbstractItemModel
    RoleCombineModel o-- QAbstractItemModel : sourceModel
    RoleCombineModel o-- QAbstractItemModel : m_minor
Loading

Class diagram for m_indexMap and role mapping logic in RoleCombineModel

classDiagram
    class RoleCombineModel {
        -QMap<QPair<int, int>, QPair<int, int>> m_indexMap
        -QHash<int, int> m_minorRolesMap
    }
    class QPair_int_int {
        +int first
        +int second
    }
    class QMap_QPair_int_int__QPair_int_int {
    }
    class QHash_int_int {
    }
    RoleCombineModel o-- QMap_QPair_int_int__QPair_int_int : m_indexMap
    QMap_QPair_int_int__QPair_int_int o-- QPair_int_int
    RoleCombineModel o-- QHash_int_int : m_minorRolesMap
Loading

File-Level Changes

Change Details Files
Enhanced index mapping updates in response to source model mutations
  • Use QModelIndex() as root for begin/end insert/remove calls
  • Shift existing mappings via QMap when rows/columns are inserted or removed
  • Handle rowsRemoved and columnsRemoved for the minor model with mapping rebuild and dataChanged signals
panels/dock/taskmanager/rolecombinemodel.cpp
Refined role-mapping logic to avoid key conflicts
  • Exclude major model keys when matching minor role names to combined roles
  • Populate m_minorRolesMap with correct combined-to-minor key pairs
panels/dock/taskmanager/rolecombinemodel.cpp
Added safety guards for flat-list behavior and invalid mappings
  • Override hasChildren to only allow root children
  • Return empty QVariant in data() when mapping is invalid
  • Make rowCount/columnCount return zero for valid parent indexes
panels/dock/taskmanager/rolecombinemodel.cpp
panels/dock/taskmanager/rolecombinemodel.h
Expanded unit tests for multiple bug scenarios
  • Include QAbstractItemModelTester in tests
  • Add tests for index mapping after row removal, invalid parent handling, minor model changes, role mapping, data access safety, and parent parameter handling
tests/panels/dock/taskmanager/rolecombinemodeltests.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

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

代码审查意见:

  1. 代码重复:在处理插入和删除行/列的逻辑中,存在大量的代码重复。可以考虑将重复的代码提取到单独的函数中,以减少代码冗余和提高可维护性。

  2. 索引映射更新逻辑:在处理行/列插入和删除时,对索引映射的更新逻辑较为复杂,建议添加注释说明每一步的逻辑,以便于理解和维护。

  3. 数据有效性检查:在data函数中,当从m_indexMap获取映射时,应该检查映射是否有效(即rowcolumn是否为-1),以避免潜在的访问无效索引的问题。

  4. 信号处理:在处理m_minor模型的变化时,特别是删除操作,应该考虑更全面的错误处理,以防止在处理过程中出现异常。

  5. 角色映射修复:在角色映射修复的测试用例中,应该添加更多的断言来验证修复后的角色映射是否正确,而不仅仅是检查大小。

  6. 数据访问安全性修复:在数据访问安全性修复的测试用例中,应该添加更多的断言来验证返回的QVariant对象是否为空,而不仅仅是检查isValid()

  7. 测试用例的覆盖范围:新增的测试用例覆盖了多个方面,但是应该确保每个测试用例都有明确的测试目的和预期结果,以便于理解和维护。

  8. 代码风格和格式:代码中存在一些风格和格式问题,例如注释的格式、变量命名的风格等,应该统一代码风格以提高代码的可读性。

  9. 性能考虑:在处理大量数据时,索引映射的更新可能会影响性能。建议评估是否有必要在每次插入或删除操作时都更新整个映射,或者考虑使用更高效的数据结构来存储映射。

  10. 异常处理:在处理模型变化时,应该添加异常处理逻辑,以防止在处理过程中出现未捕获的异常导致程序崩溃。

总体来说,代码的改进主要集中在减少重复代码、增强错误处理、提高代码可读性和性能优化等方面。

@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 @BLumia - I've reviewed your changes and they look great!

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

### Comment 1
<location> `panels/dock/taskmanager/rolecombinemodel.cpp:244` </location>
<code_context>
+        }
+    });
+
+    connect(m_minor, &QAbstractItemModel::columnsRemoved, this, [this, majorRoles, func](const QModelIndex &parent, int first, int last) {
+        // 当minor模型删除列时,需要更新映射
+        for (auto it = m_indexMap.begin(); it != m_indexMap.end(); ++it) {
+            int minorRow = it.value().first;
+            int minorCol = it.value().second;
+
+            if (minorCol > last) {
+                // 调整后续列的索引
+                int newMinorCol = minorCol - (last - first + 1);
+                it.value().second = newMinorCol;
+            }
+        }
+    });
</code_context>

<issue_to_address>
No handling for mappings that become invalid after minor column removal.

Mappings referencing removed columns are not updated, which may leave invalid entries. Please ensure such mappings are removed or invalidated.
</issue_to_address>

### Comment 2
<location> `panels/dock/taskmanager/rolecombinemodel.cpp:285` </location>
<code_context>
+    // 修复角色映射逻辑:应该映射到新创建的minor角色,而不是major角色
+    auto majorRoleNames = sourceModel()->roleNames();
+
+    std::for_each(minorRolenames.constBegin(), minorRolenames.constEnd(), [&minorRolenames, &majorRoleNames, this](auto &roleName) {
+        int minorRoleKey = minorRolenames.key(roleName);
+
+        // 在组合角色中找到对应的key,但排除major模型已有的key
+        int combinedRoleKey = -1;
+        for (auto it = m_roleNames.constBegin(); it != m_roleNames.constEnd(); ++it) {
+            if (it.value() == roleName && !majorRoleNames.contains(it.key())) {
+                combinedRoleKey = it.key();
+                break;
+            }
+        }
+
+        if (combinedRoleKey != -1) {
+            m_minorRolesMap.insert(combinedRoleKey, minorRoleKey);
+        }
</code_context>

<issue_to_address>
Role mapping logic may not handle duplicate role names across major and minor models.

If major and minor models share a role name but have different keys, the logic skips mapping for keys already in the major model, potentially omitting roles from the combined model. Please confirm if this is intentional.
</issue_to_address>

### Comment 3
<location> `tests/panels/dock/taskmanager/rolecombinemodeltests.cpp:183` </location>
<code_context>
+    EXPECT_EQ(model.index(2, 0).data(bDataRole).toString(), "dataB3");
+}
+
+// 新增测试用例:检测parent参数处理问题
+TEST(RoleCombineModel, InvalidParentHandlingBug)
+{
+    TestModelA modelA;
+    TestModelB modelB;
+
+    RoleCombineModel model(&modelA, &modelB, TestModelA::idRole, [](QVariant data, QAbstractItemModel *model) -> QModelIndex {
+        return QModelIndex();
+    });
+
+    modelA.addData(new DataA(0, "dataA0", &modelA));
</code_context>

<issue_to_address>
Test for invalid parent handling is present but could be more explicit.

Please add assertions to confirm that rowCount and data access remain correct after attempting to add data with an invalid parent.
</issue_to_address>

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.

@@ -24,42 +24,133 @@ RoleCombineModel::RoleCombineModel(QAbstractItemModel* major, QAbstractItemModel
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): No handling for mappings that become invalid after minor column removal.

Mappings referencing removed columns are not updated, which may leave invalid entries. Please ensure such mappings are removed or invalidated.

Comment on lines +285 to +294
std::for_each(minorRolenames.constBegin(), minorRolenames.constEnd(), [&minorRolenames, &majorRoleNames, this](auto &roleName) {
int minorRoleKey = minorRolenames.key(roleName);

// 在组合角色中找到对应的key,但排除major模型已有的key
int combinedRoleKey = -1;
for (auto it = m_roleNames.constBegin(); it != m_roleNames.constEnd(); ++it) {
if (it.value() == roleName && !majorRoleNames.contains(it.key())) {
combinedRoleKey = it.key();
break;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

question: Role mapping logic may not handle duplicate role names across major and minor models.

If major and minor models share a role name but have different keys, the logic skips mapping for keys already in the major model, potentially omitting roles from the combined model. Please confirm if this is intentional.

});

auto tester = new QAbstractItemModelTester(&model, QAbstractItemModelTester::FailureReportingMode::Fatal);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (testing): Test for invalid parent handling is present but could be more explicit.

Please add assertions to confirm that rowCount and data access remain correct after attempting to add data with an invalid parent.

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

@BLumia BLumia merged commit 03beb42 into linuxdeepin:master Jul 18, 2025
7 of 10 checks passed
@BLumia BLumia deleted the rolecombinemodel-fix branch July 18, 2025 06:10
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