Skip to content

Conversation

@BLumia
Copy link
Member

@BLumia BLumia commented Jul 18, 2025

修正 RoleGroupModel 的若干问题,包括 hasChildren() 不正确,无法被QTreeView支持,QAbstractItemModelTester运行失败等.

Summary by Sourcery

Fix numerous issues in RoleGroupModel by adding boundary checks, proper hasChildren support, robust index/data/mapping logic, and enhance group display formatting, ensuring compatibility with QTreeView and QAbstractItemModelTester.

Bug Fixes:

  • Correct index() to return invalid indices for out-of-range or empty data scenarios
  • Prevent invalid dataChanged emissions when child index is not found
  • Fix mapToSource and mapFromSource to return invalid for unmapped or out-of-range indices
  • Address incorrect hasChildren behavior at root, group, and child levels

Enhancements:

  • Introduce hasChildren override to support QTreeView hierarchy checks
  • Add boundary checks in rowCount, parent, and index methods to prevent invalid access
  • Enhance data() for group nodes to display "value (count)" and delegate other roles to first item

Tests:

  • Add QAbstractItemModelTester validation to ensure compliance with Qt model/view conventions
  • Introduce deep index, scrolling boundary, and hasChildren tests covering various edge cases

修正 RoleGroupModel 的若干问题,包括 hasChildren() 不正确,无法被
QTreeView支持,QAbstractItemModelTester运行失败等.

Log:
@BLumia BLumia requested review from 18202781743 and tsic404 July 18, 2025 06:27
@sourcery-ai
Copy link

sourcery-ai bot commented Jul 18, 2025

Reviewer's Guide

This PR refactors RoleGroupModel to correct grouping logic, tighten index/data safety checks, enhance data presentation for group nodes, and implement hasChildren, accompanied by an expanded test suite verifying model behavior under various scenarios.

Sequence diagram for data retrieval in RoleGroupModel::data()

sequenceDiagram
    participant View
    participant RoleGroupModel
    participant SourceModel
    View->>RoleGroupModel: data(index, role)
    alt index is invalid
        RoleGroupModel-->>View: return QVariant()
    else index is group node (internalId == -1)
        RoleGroupModel->>SourceModel: index(list->first(), 0).data(role)
        alt role == Qt::DisplayRole
            RoleGroupModel-->>View: return group label with count
        else
            RoleGroupModel-->>View: return first item's data
        end
    else index is child node
        RoleGroupModel->>SourceModel: index(list->value(index.row()), 0).data(role)
        RoleGroupModel-->>View: return child data
    end
Loading

Sequence diagram for hasChildren() logic in RoleGroupModel

sequenceDiagram
    participant View
    participant RoleGroupModel
    View->>RoleGroupModel: hasChildren(parent)
    alt no sourceModel
        RoleGroupModel-->>View: false
    else parent is invalid (root)
        RoleGroupModel-->>View: m_rowMap.size() > 0
    else parent is group node (internalId == -1)
        RoleGroupModel-->>View: list && list->size() > 0
    else parent is child node
        RoleGroupModel-->>View: false
    end
Loading

Class diagram for updated RoleGroupModel

classDiagram
    class QAbstractProxyModel
    class RoleGroupModel {
        +int rowCount(const QModelIndex &parent) const
        +int columnCount(const QModelIndex &parent) const
        +QVariant data(const QModelIndex &index, int role) const
        +bool hasChildren(const QModelIndex &parent) const
        +bool hasIndex(int row, int column, const QModelIndex &parent) const
        +QModelIndex index(int row, int column, const QModelIndex &parent) const
        +QModelIndex parent(const QModelIndex &child) const
        +QModelIndex mapToSource(const QModelIndex &proxyIndex) const
        +QModelIndex mapFromSource(const QModelIndex &sourceIndex) const
        +void setSourceModel(QAbstractItemModel *model)
        +QHash<int, QByteArray> roleNames() const
        +void rebuildTreeSource()
        -QList<QList<int>*> m_rowMap
        -QHash<QString, QList<int>*> m_map
        -int m_roleForDeduplication
    }
    QAbstractProxyModel <|-- RoleGroupModel
Loading

Class diagram for QModelIndex usage in RoleGroupModel

classDiagram
    class QModelIndex {
        +int row() const
        +int column() const
        +bool isValid() const
        +QVariant data(int role) const
        +QModelIndex parent() const
        +quintptr internalId() const
    }
    class RoleGroupModel
    RoleGroupModel --> QModelIndex : uses
Loading

File-Level Changes

Change Details Files
Expanded test coverage with full Qt model compliance and edge-case scenarios
  • Added QAbstractItemModelTester include
  • Introduced IndexMethodDeepTest for deep indexing edge cases
  • Added ModelTesterValidation to ensure overall model correctness
  • Created HasChildrenTest to validate hasChildren behavior
  • Implemented ScrollingBoundaryTest for out-of-range access simulation
tests/panels/dock/taskmanager/rolegroupmodeltests.cpp
Fixed grouping logic in setSourceModel and dataChanged propagation
  • Appended new source rows to lists inside both new-group and existing-group branches
  • Moved list->append before endInsertRows to maintain correct row mapping
  • Guarded dataChanged emission by validating childRow index >= 0
panels/dock/taskmanager/rolegroupmodel.cpp
Added comprehensive bounds and validity checks, and refined data() behavior
  • Validated parent.row() and child indices in rowCount, index, parent, mapToSource, and mapFromSource
  • Early-return for invalid QModelIndex in data(), index, parent and mapping methods
  • Extended data() to distinguish group vs child nodes and display "group (count)" labels
panels/dock/taskmanager/rolegroupmodel.cpp
Implemented hasChildren override with correct root/group/child logic
  • Declared hasChildren in header as override
  • Defined hasChildren in cpp to return true only when groups or children exist
panels/dock/taskmanager/rolegroupmodel.h
panels/dock/taskmanager/rolegroupmodel.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

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 @BLumia - I've reviewed your changes - here's some feedback:

  • You should add handlers for rowsRemoved and modelReset on the source model so that m_map/m_rowMap stay in sync when items are deleted or the model is reset.
  • Allocating QList* by hand risks memory leaks and complicates ownership; consider using value containers (e.g. QList<QList> or QVector<QVector>) instead of raw pointers.
  • Relying on internalId() == -1 to distinguish group vs child nodes is not obvious—introduce helper methods or an explicit flag to clarify index/parent logic and reduce duplication.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- You should add handlers for rowsRemoved and modelReset on the source model so that m_map/m_rowMap stay in sync when items are deleted or the model is reset.
- Allocating QList<int>* by hand risks memory leaks and complicates ownership; consider using value containers (e.g. QList<QList<int>> or QVector<QVector<int>>) instead of raw pointers.
- Relying on internalId() == -1 to distinguish group vs child nodes is not obvious—introduce helper methods or an explicit flag to clarify index/parent logic and reduce duplication.

## Individual Comments

### Comment 1
<location> `tests/panels/dock/taskmanager/rolegroupmodeltests.cpp:211` </location>
<code_context>
+// 测试 hasChildren 方法的正确性
</code_context>

<issue_to_address>
Comprehensive hasChildren() test, but missing test for invalid parent index.

Please add a test for hasChildren() with an invalid parent index to verify correct handling of out-of-range or dangling indices.
</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.

Comment on lines +211 to +220
RoleGroupModel groupModel(&model, role);

// 初始状态:没有数据,根节点不应该有子节点
EXPECT_FALSE(groupModel.hasChildren());
EXPECT_FALSE(groupModel.hasChildren(QModelIndex()));

// 添加第一个项目
QStandardItem *item1 = new QStandardItem;
item1->setData(QString("firefox.desktop"), role);
item1->setData(QString("Firefox - 页面1"), Qt::DisplayRole);
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Comprehensive hasChildren() test, but missing test for invalid parent index.

Please add a test for hasChildren() with an invalid parent index to verify correct handling of out-of-range or dangling indices.

@deepin-ci-robot
Copy link

[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 ba91781 into linuxdeepin:master Jul 21, 2025
9 of 10 checks passed
@BLumia BLumia deleted the rolegroupmodel-fix branch July 21, 2025 08:26
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