From 6c2355f45772a9f623fa24662b7c3781bdca88af Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 18 Apr 2023 15:33:58 +0200 Subject: Fix setting combo data with QSortFilterProxyModel qtbase/c27d2a57a441f9a1ce760e71635bd4c96882249d caused the code to go through QStandardItemPrivate::setItemData() which does not handle the special treatment of Qt::EditRole completely. In the constructor of QStandardItemData; map Qt::EditRole to Qt::DisplayRole to fix this as is done in setData(). Adapt the existing tst_QStandardItemModel::getSetItemData() to check whether both roles are received in the dataChanged() signal. Fixes: QTBUG-112326 Change-Id: I133d058bacc3388c612c5b4fb18b54f5ef5cb56f Reviewed-by: Samuel Gaist Reviewed-by: David Faure (cherry picked from commit 936fe007ee97ebfcab5fda749bcbbf333744ca9e) Reviewed-by: Qt Cherry-pick Bot --- src/gui/itemmodels/qstandarditemmodel_p.h | 6 +- .../qstandarditemmodel/tst_qstandarditemmodel.cpp | 84 ++++++++++++++-------- 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/gui/itemmodels/qstandarditemmodel_p.h b/src/gui/itemmodels/qstandarditemmodel_p.h index def6c20727..f25aa44116 100644 --- a/src/gui/itemmodels/qstandarditemmodel_p.h +++ b/src/gui/itemmodels/qstandarditemmodel_p.h @@ -32,8 +32,10 @@ class QStandardItemData { public: inline QStandardItemData() : role(-1) {} - inline QStandardItemData(int r, const QVariant &v) : role(r), value(v) {} - inline QStandardItemData(const std::pair &p) : role(p.first), value(p.second) {} + inline QStandardItemData(int r, const QVariant &v) : + role(r == Qt::EditRole ? Qt::DisplayRole : r), value(v) {} + inline QStandardItemData(const std::pair &p) : + role(p.first == Qt::EditRole ? Qt::DisplayRole : p.first), value(p.second) {} int role; QVariant value; inline bool operator==(const QStandardItemData &other) const { return role == other.role && value == other.value; } diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp index 07fc074577..73e74b2229 100644 --- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp +++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp @@ -5,12 +5,17 @@ #include #include #include +#include #include #include #include #include +#include + +using namespace Qt::StringLiterals; + class tst_QStandardItemModel : public QObject { Q_OBJECT @@ -87,6 +92,7 @@ private slots: void indexFromItem(); void itemFromIndex(); void getSetItemPrototype(); + void getSetItemData_data(); void getSetItemData(); void setHeaderLabels_data(); void setHeaderLabels(); @@ -1025,33 +1031,49 @@ void tst_QStandardItemModel::getSetItemPrototype() QCOMPARE(model.itemPrototype(), nullptr); } +using RoleMap = QMap; +using RoleList = QList; + +static RoleMap getSetItemDataRoleMap(int textRole) +{ + return {{textRole, "text"_L1}, + {Qt::StatusTipRole, "statusTip"_L1}, + {Qt::ToolTipRole, "toolTip"_L1}, + {Qt::WhatsThisRole, "whatsThis"_L1}, + {Qt::SizeHintRole, QSize{64, 48}}, + {Qt::FontRole, QFont{}}, + {Qt::TextAlignmentRole, int(Qt::AlignLeft|Qt::AlignVCenter)}, + {Qt::BackgroundRole, QColor(Qt::blue)}, + {Qt::ForegroundRole, QColor(Qt::green)}, + {Qt::CheckStateRole, int(Qt::PartiallyChecked)}, + {Qt::AccessibleTextRole, "accessibleText"_L1}, + {Qt::AccessibleDescriptionRole, "accessibleDescription"_L1}}; +} + +void tst_QStandardItemModel::getSetItemData_data() +{ + QTest::addColumn("itemData"); + QTest::addColumn("expectedItemData"); + QTest::addColumn("expectedRoles"); + + // QTBUG-112326: verify that text data set using Qt::EditRole is mapped to + // Qt::DisplayRole and both roles are in the changed signal + const RoleMap expectedItemData = getSetItemDataRoleMap(Qt::DisplayRole); + RoleList expectedRoles = expectedItemData.keys() << Qt::EditRole; + std::sort(expectedRoles.begin(), expectedRoles.end()); + + QTest::newRow("DisplayRole") << expectedItemData + << expectedItemData << expectedRoles; + + QTest::newRow("EditRole") << getSetItemDataRoleMap(Qt::EditRole) + << expectedItemData << expectedRoles; +} + void tst_QStandardItemModel::getSetItemData() { - QMap roles; - QLatin1String text("text"); - roles.insert(Qt::DisplayRole, text); - QLatin1String statusTip("statusTip"); - roles.insert(Qt::StatusTipRole, statusTip); - QLatin1String toolTip("toolTip"); - roles.insert(Qt::ToolTipRole, toolTip); - QLatin1String whatsThis("whatsThis"); - roles.insert(Qt::WhatsThisRole, whatsThis); - QSize sizeHint(64, 48); - roles.insert(Qt::SizeHintRole, sizeHint); - QFont font; - roles.insert(Qt::FontRole, font); - Qt::Alignment textAlignment(Qt::AlignLeft|Qt::AlignVCenter); - roles.insert(Qt::TextAlignmentRole, int(textAlignment)); - QColor backgroundColor(Qt::blue); - roles.insert(Qt::BackgroundRole, backgroundColor); - QColor textColor(Qt::green); - roles.insert(Qt::ForegroundRole, textColor); - Qt::CheckState checkState(Qt::PartiallyChecked); - roles.insert(Qt::CheckStateRole, int(checkState)); - QLatin1String accessibleText("accessibleText"); - roles.insert(Qt::AccessibleTextRole, accessibleText); - QLatin1String accessibleDescription("accessibleDescription"); - roles.insert(Qt::AccessibleDescriptionRole, accessibleDescription); + QFETCH(RoleMap, itemData); + QFETCH(RoleMap, expectedItemData); + QFETCH(RoleList, expectedRoles); QStandardItemModel model; model.insertRows(0, 1); @@ -1060,11 +1082,17 @@ void tst_QStandardItemModel::getSetItemData() QSignalSpy modelDataChangedSpy( &model, &QStandardItemModel::dataChanged); - QVERIFY(model.setItemData(idx, roles)); + QVERIFY(model.setItemData(idx, itemData)); QCOMPARE(modelDataChangedSpy.size(), 1); - QVERIFY(model.setItemData(idx, roles)); + const QVariantList &args = modelDataChangedSpy.constFirst(); + QCOMPARE(args.size(), 3); + auto roleList = args.at(2).value >(); + std::sort(roleList.begin(), roleList.end()); + QCOMPARE(roleList, expectedRoles); + + QVERIFY(model.setItemData(idx, itemData)); QCOMPARE(modelDataChangedSpy.size(), 1); //it was already changed once - QCOMPARE(model.itemData(idx), roles); + QCOMPARE(model.itemData(idx), expectedItemData); } void tst_QStandardItemModel::setHeaderLabels_data() -- cgit v1.2.1