diff --git a/panels/dock/taskmanager/dockglobalelementmodel.cpp b/panels/dock/taskmanager/dockglobalelementmodel.cpp index 23de5c700..c08648e04 100644 --- a/panels/dock/taskmanager/dockglobalelementmodel.cpp +++ b/panels/dock/taskmanager/dockglobalelementmodel.cpp @@ -72,6 +72,14 @@ DockGlobalElementModel::DockGlobalElementModel(QAbstractItemModel *appsModel, Do data = std::make_tuple(std::get<0>(data), std::get<1>(data), std::get<2>(data) + insertedCount); } }); + + for (auto &data : m_data) { + if (std::get<1>(data) != m_appsModel || std::get<2>(data) != -1) + 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(); + } }, Qt::QueuedConnection); @@ -234,7 +242,7 @@ DockGlobalElementModel::DockGlobalElementModel(QAbstractItemModel *appsModel, Do }); if (it == m_data.end()) - return; + continue; auto pos = it - m_data.constBegin(); auto oldRoles = roles; @@ -248,6 +256,30 @@ DockGlobalElementModel::DockGlobalElementModel(QAbstractItemModel *appsModel, Do }, Qt::QueuedConnection); + connect( + m_appsModel, + &QAbstractItemModel::dataChanged, + this, + [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList &roles) { + int first = topLeft.row(), last = bottomRight.row(); + for (int i = first; i <= last; i++) { + auto id = m_appsModel->index(i, 0).data(TaskManager::DesktopIdRole).toString(); + if (id.isEmpty()) + continue; + + auto it = std::find_if(m_data.begin(), m_data.end(), [&id](const auto &data) { + return std::get<0>(data) == id; + }); + + if (it == m_data.end()) + continue; + + auto pos = it - m_data.begin(); + Q_EMIT dataChanged(index(pos, 0), index(pos, 0), roles); + } + }, + Qt::QueuedConnection); + QMetaObject::invokeMethod(this, &DockGlobalElementModel::loadDockedElements, Qt::QueuedConnection); } diff --git a/panels/dock/taskmanager/rolecombinemodel.cpp b/panels/dock/taskmanager/rolecombinemodel.cpp index bb5345180..657c63b87 100644 --- a/panels/dock/taskmanager/rolecombinemodel.cpp +++ b/panels/dock/taskmanager/rolecombinemodel.cpp @@ -181,22 +181,27 @@ RoleCombineModel::RoleCombineModel(QAbstractItemModel* major, QAbstractItemModel connect(m_minor, &QAbstractItemModel::dataChanged, this, [this, majorRoles, func](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList &roles){ Q_UNUSED(roles) + QPair minorPair; for (int i = topLeft.row(); i <= bottomRight.row(); i++) { for (int j = topLeft.column(); j <= bottomRight.column(); j++) { - auto majorPos = m_indexMap.key(qMakePair(i, j), qMakePair(-1, -1)); - if (-1 == majorPos.first && -1 == majorPos.second) - continue; + minorPair = qMakePair(i, j); + for (auto mapIt = m_indexMap.constBegin(); mapIt != m_indexMap.constEnd(); ++mapIt) { + if (mapIt.value() != minorPair) + continue; - auto majorIndex = sourceModel()->index(majorPos.first, majorPos.second); - if (!majorIndex.isValid()) - continue; + auto majorPos = mapIt.key(); - auto minorIndex = func(majorIndex.data(majorRoles), m_minor); - if (!minorIndex.isValid()) - continue; + auto majorIndex = sourceModel()->index(majorPos.first, majorPos.second); + if (!majorIndex.isValid()) + continue; - m_indexMap[majorPos] = qMakePair(minorIndex.row(), minorIndex.column()); - Q_EMIT dataChanged(majorIndex, majorIndex, m_minorRolesMap.values()); + auto minorIndex = func(majorIndex.data(majorRoles), m_minor); + if (!minorIndex.isValid()) + continue; + + m_indexMap[majorPos] = qMakePair(minorIndex.row(), minorIndex.column()); + Q_EMIT dataChanged(majorIndex, majorIndex, m_minorRolesMap.values()); + } } } }); diff --git a/tests/panels/dock/taskmanager/combinemodela.cpp b/tests/panels/dock/taskmanager/combinemodela.cpp index 9db1915b6..04a51c64b 100644 --- a/tests/panels/dock/taskmanager/combinemodela.cpp +++ b/tests/panels/dock/taskmanager/combinemodela.cpp @@ -4,10 +4,10 @@ #include "combinemodela.h" -DataA::DataA(int id, TestModelA* parent) - : m_id(id) +DataA::DataA(int id, TestModelA* model) + : m_model(model) + , m_id(id) { - Q_UNUSED(parent) } DataA::DataA(int id, const QString &data, TestModelA* model) @@ -31,9 +31,11 @@ void DataA::setData(const QString &data) if (data == m_data) return; m_data = data; - auto index = m_model->match(QModelIndex(), TestModelA::idRole, m_id); - if (index.size() > 0) { - Q_EMIT m_model->dataChanged(index.first(), index.last(), {TestModelA::dataRole}); + for (int row = 0; row < m_model->rowCount(); ++row) { + if (m_model->index(row, 0).data(TestModelA::idRole).toInt() == m_id) { + Q_EMIT m_model->dataChanged(m_model->index(row, 0), m_model->index(row, 0), {TestModelA::dataRole}); + break; + } } } @@ -83,6 +85,18 @@ void TestModelA::addData(DataA *data) endInsertRows(); } +bool TestModelA::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || index.row() >= m_list.size()) + return false; + + if (role != dataRole) + return false; + + m_list[index.row()]->setData(value.toString()); + return true; +} + void TestModelA::removeData(DataA *data) { auto pos = m_list.indexOf(data); diff --git a/tests/panels/dock/taskmanager/combinemodela.h b/tests/panels/dock/taskmanager/combinemodela.h index 8722e8a3d..fc49352ef 100644 --- a/tests/panels/dock/taskmanager/combinemodela.h +++ b/tests/panels/dock/taskmanager/combinemodela.h @@ -38,6 +38,7 @@ class TestModelA : public QAbstractListModel QHash roleNames() const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; void addData(DataA *data); void removeData(DataA *data); diff --git a/tests/panels/dock/taskmanager/combinemodelb.cpp b/tests/panels/dock/taskmanager/combinemodelb.cpp index b0cbd66b0..3a4eac0a3 100644 --- a/tests/panels/dock/taskmanager/combinemodelb.cpp +++ b/tests/panels/dock/taskmanager/combinemodelb.cpp @@ -4,10 +4,10 @@ #include "combinemodelb.h" -DataB::DataB(int id, TestModelB* parent) - : m_id(id) +DataB::DataB(int id, TestModelB* model) + : m_model(model) + , m_id(id) { - Q_UNUSED(parent) } DataB::DataB(int id, const QString &data, TestModelB* model) @@ -31,9 +31,11 @@ void DataB::setData(const QString &data) if (data == m_data) return; m_data = data; - auto index = m_model->match(QModelIndex(), TestModelB::idRole, m_id); - if (index.size() > 0) { - Q_EMIT m_model->dataChanged(index.first(), index.last(), {TestModelB::dataRole}); + for (int row = 0; row < m_model->rowCount(); ++row) { + if (m_model->index(row, 0).data(TestModelB::idRole).toInt() == m_id) { + Q_EMIT m_model->dataChanged(m_model->index(row, 0), m_model->index(row, 0), {TestModelB::dataRole}); + break; + } } } @@ -83,6 +85,18 @@ void TestModelB::addData(DataB *data) endInsertRows(); } +bool TestModelB::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || index.row() >= m_list.size()) + return false; + + if (role != dataRole) + return false; + + m_list[index.row()]->setData(value.toString()); + return true; +} + void TestModelB::removeData(DataB *data) { auto pos = m_list.indexOf(data); diff --git a/tests/panels/dock/taskmanager/combinemodelb.h b/tests/panels/dock/taskmanager/combinemodelb.h index c836daa0d..438ae9a54 100644 --- a/tests/panels/dock/taskmanager/combinemodelb.h +++ b/tests/panels/dock/taskmanager/combinemodelb.h @@ -37,6 +37,7 @@ class TestModelB : public QAbstractListModel QHash roleNames() const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; void addData(DataB *data); void removeData(DataB *data); diff --git a/tests/panels/dock/taskmanager/rolecombinemodeltests.cpp b/tests/panels/dock/taskmanager/rolecombinemodeltests.cpp index e14630150..627935d73 100644 --- a/tests/panels/dock/taskmanager/rolecombinemodeltests.cpp +++ b/tests/panels/dock/taskmanager/rolecombinemodeltests.cpp @@ -356,3 +356,58 @@ TEST(RoleCombineModel, ParentParameterHandlingFix) EXPECT_EQ(model.rowCount(), 1); EXPECT_TRUE(model.index(0, 0).isValid()); } + +// 验证多个major行映射到同一minor行时,minor dataChanged能转发给所有major行 +TEST(RoleCombineModel, MinorDataChangedForwardToAllMappedMajorRows) +{ + TestModelA modelA; + TestModelB modelB; + + RoleCombineModel model(&modelA, &modelB, TestModelA::idRole, [](QVariant data, QAbstractItemModel *model) -> QModelIndex { + auto matches = model->match(model->index(0, 0), TestModelB::idRole, data); + return matches.isEmpty() ? QModelIndex() : matches.first(); + }); + + QSignalSpy spy(&model, &QAbstractItemModel::dataChanged); + + // 添加两个major行,都映射到同一个minor行(id=0) + modelA.addData(new DataA(0, "window1", &modelA)); + modelA.addData(new DataA(0, "window2", &modelA)); + + // 添加对应的minor数据 + modelB.addData(new DataB(0, "appData", &modelB)); + + // 验证两个major行都映射到minor行0 + auto roleNames = model.roleNames(); + auto roleNamesA = modelA.roleNames(); + auto roleNamesB = modelB.roleNames(); + QHash names2Role; + for (auto roleName : roleNames.keys()) { + names2Role.insert(roleNames.value(roleName), roleName); + } + int bDataRole = names2Role.value(roleNamesB.value(TestModelB::dataRole)); + + // Verify initial mapping works + ASSERT_EQ(model.rowCount(), 2) << "Model should have 2 rows"; + ASSERT_TRUE(model.index(0, 0).isValid()) << "Major row 0 should be valid"; + ASSERT_TRUE(model.index(1, 0).isValid()) << "Major row 1 should be valid"; + ASSERT_NE(bDataRole, -1) << "bData role not found in combined model"; + + EXPECT_EQ(model.index(0, 0).data(bDataRole).toString(), "appData"); + EXPECT_EQ(model.index(1, 0).data(bDataRole).toString(), "appData"); + + // 修改minor数据,触发dataChanged + spy.clear(); + + // Verify DataB::setData emits dataChanged on modelB + QSignalSpy spyB(&modelB, &QAbstractItemModel::dataChanged); + modelB.setData(modelB.index(0), "newAppData", TestModelB::dataRole); + EXPECT_EQ(spyB.count(), 1) << "modelB should emit dataChanged when setData is called"; + + // Now check if RoleCombineModel forwarded the signal + EXPECT_EQ(spy.count(), 2) << "Should emit dataChanged for both major rows mapping to the same minor row"; + + // 验证数据已更新 + EXPECT_EQ(model.index(0, 0).data(bDataRole).toString(), "newAppData"); + EXPECT_EQ(model.index(1, 0).data(bDataRole).toString(), "newAppData"); +}