Skip to content
Merged
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
95 changes: 55 additions & 40 deletions panels/dock/taskmanager/dockgroupmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,48 +18,63 @@ DockGroupModel::DockGroupModel(QAbstractItemModel *sourceModel, int role, QObjec
, AbstractTaskManagerInterface(this)
, m_roleForDeduplication(role)
{
connect(this, &QAbstractItemModel::rowsInserted, this, [this](const QModelIndex &parent, int first, int last) {
Q_UNUSED(first)
Q_UNUSED(last)
if (!parent.isValid())
return;
Q_EMIT dataChanged(index(parent.row(), 0), index(parent.row(), 0), {TaskManager::WindowsRole});
});
connect(this, &QAbstractItemModel::rowsRemoved, this, [this](const QModelIndex &parent, int first, int last) {
if (!parent.isValid())
return;

// Update m_currentActiveWindow when windows are removed
int parentRow = parent.row();
if (m_currentActiveWindow.contains(parentRow)) {
int currentActive = m_currentActiveWindow.value(parentRow);
int windowCount = RoleGroupModel::rowCount(parent);

// Check if the current active window was removed
if (currentActive >= first && currentActive <= last) {
// Current active window was removed, reset to first window
resetActiveWindow(parentRow);
} else if (currentActive > last) {
// Current active window is after the removed range, shift it back
int removedCount = last - first + 1;
m_currentActiveWindow[parentRow] = currentActive - removedCount;
connect(
Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider introducing a queuedConnect helper to eliminate repetitive connect boilerplate and simplify the constructor.

Here’s one way to collapse the repeated boiler-plate while keeping all behavior intact:

  1. Add a small queuedConnect() helper in your .cpp (above your ctor):
namespace {
template<typename Sender, typename Signal, typename Receiver, typename Slot>
QMetaObject::Connection queuedConnect(Sender* s,
                                      Signal   sig,
                                      Receiver* r,
                                      Slot     slot)
{
    return QObject::connect(s, sig, r, slot, Qt::QueuedConnection);
}
}
  1. Replace each connect(..., Qt::QueuedConnection) with:
queuedConnect(this, &QAbstractItemModel::rowsInserted, this,
    [this](const QModelIndex &parent, int /*first*/, int /*last*/) {
        if (!parent.isValid()) return;
        Q_EMIT dataChanged(
            index(parent.row(), 0),
            index(parent.row(), 0),
            { TaskManager::WindowsRole }
        );
    }
);

queuedConnect(this, &QAbstractItemModel::rowsRemoved, this,
    [this](const QModelIndex &parent, int first, int last) {
        if (!parent.isValid()) return;
        const int row = parent.row();
        if (m_currentActiveWindow.contains(row)) {
            int cur = m_currentActiveWindow[row];
            if (cur >= first && cur <= last)
                resetActiveWindow(row);
            else if (cur > last)
                m_currentActiveWindow[row] = cur - (last - first + 1);
        }
        Q_EMIT dataChanged(
            index(row, 0),
            index(row, 0),
            { TaskManager::WindowsRole }
        );
    }
);

queuedConnect(this, &QAbstractItemModel::dataChanged, this,
    [this](const QModelIndex &topLeft, const QModelIndex&, const QList<int> &roles){
        auto p = topLeft.parent();
        if (!p.isValid()) return;
        int row = p.row();
        Q_EMIT dataChanged(index(row, 0), index(row, 0), roles);
        if (roles.contains(TaskManager::ActiveRole))
            m_currentActiveWindow.insert(row, topLeft.row());
    }
);

This:

  • Removes the repeated , Qt::QueuedConnection overload on each call
  • Keeps each lambda exactly as-is
  • Makes your constructor much shorter and easier to scan

this,
&QAbstractItemModel::rowsInserted,
this,
[this](const QModelIndex &parent, int first, int last) {
Q_UNUSED(first)
Copy link

Choose a reason for hiding this comment

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

suggestion (bug_risk): Emitting dataChanged for only the first column may miss updates for other columns.

If your model has multiple columns, limiting dataChanged to column 0 may cause the UI to miss updates for other columns. Please confirm whether the model is single-column or update the signal to cover all relevant columns.

Suggested implementation:

        int colCount = columnCount(parent);
        if (colCount > 0) {
            Q_EMIT dataChanged(index(parent.row(), 0), index(parent.row(), colCount - 1), {TaskManager::WindowsRole});
        }

If columnCount() is not accessible in this context, you may need to use this->columnCount(parent) or ensure you have a valid model pointer. Also, if the model is guaranteed to be single-column, you can leave the code as-is, but this change will ensure all columns are updated if there are multiple.

Q_UNUSED(last)
if (!parent.isValid())
return;
Q_EMIT dataChanged(index(parent.row(), 0), index(parent.row(), 0), {TaskManager::WindowsRole});
},
Qt::QueuedConnection);
connect(
this,
&QAbstractItemModel::rowsRemoved,
this,
[this](const QModelIndex &parent, int first, int last) {
if (!parent.isValid())
return;

// Update m_currentActiveWindow when windows are removed
int parentRow = parent.row();
if (m_currentActiveWindow.contains(parentRow)) {
int currentActive = m_currentActiveWindow.value(parentRow);
int windowCount = RoleGroupModel::rowCount(parent);

// Check if the current active window was removed
if (currentActive >= first && currentActive <= last) {
// Current active window was removed, reset to first window
resetActiveWindow(parentRow);
} else if (currentActive > last) {
// Current active window is after the removed range, shift it back
int removedCount = last - first + 1;
m_currentActiveWindow[parentRow] = currentActive - removedCount;
}
Copy link

Choose a reason for hiding this comment

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

question (bug_risk): Guard clause may skip legitimate updates for top-level items.

This guard prevents updates to top-level items. If updates to these items are required, consider revising this condition.

// If currentActive < first, no change needed
}
// If currentActive < first, no change needed
}

Q_EMIT dataChanged(index(parent.row(), 0), index(parent.row(), 0), {TaskManager::WindowsRole});
});

connect(this, &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles) {
Q_UNUSED(bottomRight)
if (!topLeft.parent().isValid())
return;
auto parentRow = topLeft.parent().row();
Q_EMIT dataChanged(index(parentRow, 0), index(parentRow, 0), roles);

if (roles.contains(TaskManager::ActiveRole))
m_currentActiveWindow.insert(parentRow, topLeft.row());
});
Q_EMIT dataChanged(index(parent.row(), 0), index(parent.row(), 0), {TaskManager::WindowsRole});
},
Qt::QueuedConnection);

connect(
this,
&QAbstractItemModel::dataChanged,
this,
[this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles) {
Q_UNUSED(bottomRight)
if (!topLeft.parent().isValid())
return;
auto parentRow = topLeft.parent().row();
Q_EMIT dataChanged(index(parentRow, 0), index(parentRow, 0), roles);

if (roles.contains(TaskManager::ActiveRole))
m_currentActiveWindow.insert(parentRow, topLeft.row());
},
Qt::QueuedConnection);
}

QVariant DockGroupModel::data(const QModelIndex &index, int role) const
Expand Down