Skip to content
Open
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
34 changes: 33 additions & 1 deletion panels/dock/taskmanager/dockglobalelementmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand All @@ -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<int> &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();
Comment thread
18202781743 marked this conversation as resolved.
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);
}

Expand Down
27 changes: 16 additions & 11 deletions panels/dock/taskmanager/rolecombinemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<int> &roles){
Q_UNUSED(roles)
QPair<int,int> 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());
}
}
}
});
Expand Down
26 changes: 20 additions & 6 deletions tests/panels/dock/taskmanager/combinemodela.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}
}
}

Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions tests/panels/dock/taskmanager/combinemodela.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class TestModelA : public QAbstractListModel
QHash<int, QByteArray> 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);
Expand Down
26 changes: 20 additions & 6 deletions tests/panels/dock/taskmanager/combinemodelb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}
}
}

Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions tests/panels/dock/taskmanager/combinemodelb.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class TestModelB : public QAbstractListModel
QHash<int, QByteArray> 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);
Expand Down
55 changes: 55 additions & 0 deletions tests/panels/dock/taskmanager/rolecombinemodeltests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<QByteArray, int> 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");
}
Loading