Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions panels/dock/taskmanager/dockitemmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ void DockItemModel::setSourceModel(QAbstractItemModel *model)
QAbstractProxyModel::setSourceModel(model);
endResetModel();

connect(sourceModel(), &QAbstractItemModel::modelAboutToBeReset, this, [this]() {
m_isUpdating = true;
beginResetModel();
});
connect(sourceModel(), &QAbstractItemModel::modelReset, this, [this]() {
endResetModel();
m_isUpdating = false;
});

connect(sourceModel(), &QAbstractItemModel::rowsInserted, this, [this](const QModelIndex &parent, int first, int last) {
if (parent.isValid() || m_isUpdating)
return;
Expand Down
21 changes: 17 additions & 4 deletions panels/dock/taskmanager/rolegroupmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

#include "rolegroupmodel.h"

#include <QList>

Check warning on line 7 in panels/dock/taskmanager/rolegroupmodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QList> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <algorithm>

Check warning on line 8 in panels/dock/taskmanager/rolegroupmodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <algorithm> not found. Please note: Cppcheck does not need standard library headers to get proper results.

RoleGroupModel::RoleGroupModel(QAbstractItemModel *sourceModel, int role, QObject *parent)
: QAbstractProxyModel(parent)
Expand Down Expand Up @@ -94,10 +95,22 @@
});

connect(sourceModel(), &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles) {
// TODO: if roles contains m_roleForDeduplication, need update from topLeft 2 bottomRight or just send dataChanged
if (roles.contains(m_roleForDeduplication)) {
rebuildTreeSource();
return;
// An advertised grouping role need not have changed. Keep delegates
// intact for ordinary application updates, including all-role updates.
if (roles.isEmpty() || roles.contains(m_roleForDeduplication)) {
for (int i = topLeft.row(); i <= bottomRight.row(); ++i) {
const auto group = sourceModel()->index(i, 0).data(m_roleForDeduplication).toString();
const auto rows = m_map.value(group, nullptr);
// Empty ids are not grouped, but a row that just lost its id
// must be removed from its previous group.
const bool changed = group.isEmpty()
? std::any_of(m_rowMap.cbegin(), m_rowMap.cend(), [i](const QList<int> *rows) { return rows->contains(i); })

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium · Broad updates stall the dock

When frequent dataChanged signals cover many rows with empty grouping IDs in a large model, std::any_of scans every group and its row list for each such row, making broad updates do work proportional to empty rows times grouped rows and stalling the caller.

Use a direct row-to-group membership lookup instead of scanning every group for each ungrouped row.

Prompt for AI agents
In `panels/dock/taskmanager/rolegroupmodel.cpp` at line 107:

**Broad updates stall the dock**

When frequent `dataChanged` signals cover many rows with empty grouping IDs in a large model, `std::any_of` scans every group and its row list for each such row, making broad updates do work proportional to empty rows times grouped rows and stalling the caller.

Use a direct row-to-group membership lookup instead of scanning every group for each ungrouped row.

: !rows || !rows->contains(i);
if (changed) {
rebuildTreeSource();
return;
}
}
}

for (int i = topLeft.row(); i <= bottomRight.row(); ++i) {
Expand Down
Loading