summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Beldi <v.ronin@yahoo.it>2021-07-20 15:49:33 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-07-21 00:36:32 +0000
commit1693779f05731668d0177d9941a00ed67eba4f20 (patch)
tree0891ef74fd8076234b5dd278fe1dce17c3e7126f
parenta48fee3aa46d29f9e06da2df75aca9bf8acadf5e (diff)
emit layoutAboutToBeChanged timely
layoutAboutToBeChanged must be called before persistentIndexList as the user might create persistent indexes as a response to the signal Fixes: QTBUG-93466 Change-Id: I73c24501f536ef9b6092c3374821497f0a8f0de4 Reviewed-by: David Faure <david.faure@kdab.com> (cherry picked from commit 1dcfb09c5bf431bf8b065ac038bd1fc618a68f96) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel.cpp30
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp12
-rw-r--r--tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp40
-rw-r--r--tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp37
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp35
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h1
-rw-r--r--tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp30
-rw-r--r--tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp80
-rw-r--r--tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp36
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp68
-rw-r--r--tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp71
-rw-r--r--tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp69
12 files changed, 492 insertions, 17 deletions
diff --git a/src/corelib/itemmodels/qtransposeproxymodel.cpp b/src/corelib/itemmodels/qtransposeproxymodel.cpp
index 899f93c2a5..558ec45b73 100644
--- a/src/corelib/itemmodels/qtransposeproxymodel.cpp
+++ b/src/corelib/itemmodels/qtransposeproxymodel.cpp
@@ -64,6 +64,7 @@ QModelIndex QTransposeProxyModelPrivate::uncheckedMapFromSource(const QModelInde
void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_Q(QTransposeProxyModel);
+ Q_ASSERT(layoutChangeProxyIndexes.size() == layoutChangePersistentIndexes.size());
QModelIndexList toList;
toList.reserve(layoutChangePersistentIndexes.size());
for (const QPersistentModelIndex &persistIdx : qAsConst(layoutChangePersistentIndexes))
@@ -83,9 +84,26 @@ void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIn
emit q->layoutChanged(proxyParents, proxyHint);
}
-void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
+void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_Q(QTransposeProxyModel);
+ QList<QPersistentModelIndex> proxyParents;
+ proxyParents.reserve(sourceParents.size());
+ for (const QPersistentModelIndex &parent : sourceParents) {
+ if (!parent.isValid()) {
+ proxyParents << QPersistentModelIndex();
+ continue;
+ }
+ const QModelIndex mappedParent = q->mapFromSource(parent);
+ Q_ASSERT(mappedParent.isValid());
+ proxyParents << mappedParent;
+ }
+ QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
+ if (hint == QAbstractItemModel::VerticalSortHint)
+ proxyHint = QAbstractItemModel::HorizontalSortHint;
+ else if (hint == QAbstractItemModel::HorizontalSortHint)
+ proxyHint = QAbstractItemModel::VerticalSortHint;
+ emit q->layoutAboutToBeChanged(proxyParents, proxyHint);
const QModelIndexList proxyPersistentIndexes = q->persistentIndexList();
layoutChangeProxyIndexes.clear();
layoutChangePersistentIndexes.clear();
@@ -98,16 +116,6 @@ void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersiste
Q_ASSERT(srcPersistentIndex.isValid());
layoutChangePersistentIndexes << srcPersistentIndex;
}
- QList<QPersistentModelIndex> proxyParents;
- proxyParents.reserve(parents.size());
- for (auto& srcParent : parents)
- proxyParents << q->mapFromSource(srcParent);
- QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
- if (hint == QAbstractItemModel::VerticalSortHint)
- proxyHint = QAbstractItemModel::HorizontalSortHint;
- else if (hint == QAbstractItemModel::HorizontalSortHint)
- proxyHint = QAbstractItemModel::VerticalSortHint;
- emit q->layoutAboutToBeChanged(proxyParents, proxyHint);
}
void QTransposeProxyModelPrivate::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index ca7439b08c..f04cfe45d9 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -373,7 +373,7 @@ void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int en
if (column != 0)
return;
- int count = end - start + 1;
+ const int count = end - start + 1;
QList<QPair<QListWidgetItem *, int>> sorting(count);
for (int i = 0; i < count; ++i) {
sorting[i].first = items.at(start + i);
@@ -399,7 +399,12 @@ void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int en
int newRow = qMax<qsizetype>(lit - tmp.begin(), 0);
lit = tmp.insert(lit, item);
if (newRow != oldRow) {
- changed = true;
+ if (!changed) {
+ emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
+ oldPersistentIndexes = persistentIndexList();
+ newPersistentIndexes = oldPersistentIndexes;
+ changed = true;
+ }
for (int j = i + 1; j < count; ++j) {
int otherRow = sorting.at(j).second;
if (oldRow < otherRow && newRow >= otherRow)
@@ -425,10 +430,9 @@ void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int en
}
if (changed) {
- emit layoutAboutToBeChanged();
items = tmp;
changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
- emit layoutChanged();
+ emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
}
}
diff --git a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
index 90972caa57..0188768db5 100644
--- a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
@@ -118,7 +118,7 @@ private Q_SLOTS:
void shouldPropagateDropAfterLastRow();
void qtbug91788();
void qtbug91878();
-
+ void createPersistentOnLayoutAboutToBeChanged();
private:
QStandardItemModel mod;
QStandardItemModel mod2;
@@ -860,6 +860,44 @@ void tst_QConcatenateTablesProxyModel::qtbug91878()
QCOMPARE(pm.rowCount(), 4);
}
+void tst_QConcatenateTablesProxyModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QStandardItemModel model1(3, 1);
+ QStandardItemModel model2(3, 1);
+ for (int row = 0; row < 3; ++row) {
+ model1.setData(model1.index(row, 0), row);
+ model2.setData(model2.index(row, 0), row + 5);
+ }
+ QConcatenateTablesProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.addSourceModel(&model1);
+ proxy.addSourceModel(&model2);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged);
+ connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &proxy](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(proxy.index(row, 0));
+ });
+ connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toInt(), 2);
+ });
+ QVERIFY(model1.setData(model1.index(1, 0), -1));
+ model1.sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
QTEST_GUILESS_MAIN(tst_QConcatenateTablesProxyModel)
#include "tst_qconcatenatetablesproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp b/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp
index 4828df8b94..3f93938ed9 100644
--- a/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp
@@ -77,7 +77,7 @@ private slots:
void itemData();
void persistIndexOnLayoutChange();
-
+ void createPersistentOnLayoutAboutToBeChanged();
protected:
void verifyIdentity(QAbstractItemModel *model, const QModelIndex &parent = QModelIndex());
@@ -494,5 +494,40 @@ void tst_QIdentityProxyModel::persistIndexOnLayoutChange()
QVERIFY(persistentIndex.isValid());
}
+void tst_QIdentityProxyModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QStandardItemModel model(3, 1);
+ for (int row = 0; row < 3; ++row)
+ model.setData(model.index(row, 0), row, Qt::UserRole);
+ model.setSortRole(Qt::UserRole);
+ QIdentityProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged);
+ connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &proxy](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(proxy.index(row, 0));
+ });
+ connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data(Qt::UserRole).toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data(Qt::UserRole).toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data(Qt::UserRole).toInt(), 2);
+ });
+ model.setData(model.index(1, 0), -1, Qt::UserRole);
+ model.sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
QTEST_MAIN(tst_QIdentityProxyModel)
#include "tst_qidentityproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
index d937a708e9..6da65e59e8 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
@@ -5487,4 +5487,39 @@ void tst_QSortFilterProxyModel::filterRegularExpressionBinding()
QVERIFY(proxyModel.bindableFilterCaseSensitivity().hasBinding());
}
+void tst_QSortFilterProxyModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QStandardItemModel model(3, 1);
+ for (int row = 0; row < 3; ++row)
+ model.setData(model.index(row, 0), row, Qt::UserRole);
+ QSortFilterProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ proxy.setSortRole(Qt::UserRole);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged);
+ connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &proxy](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(proxy.index(row, 0));
+ });
+ connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data(Qt::UserRole).toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data(Qt::UserRole).toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data(Qt::UserRole).toInt(), 2);
+ });
+ model.setData(model.index(1, 0), -1, Qt::UserRole);
+ proxy.sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h
index 63b328c41d..baad28ec06 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h
@@ -55,6 +55,7 @@ private slots:
void sort();
void sortHierarchy_data();
void sortHierarchy();
+ void createPersistentOnLayoutAboutToBeChanged();
void insertRows_data();
void insertRows();
diff --git a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
index 79ad4145a2..5fe8784768 100644
--- a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
@@ -93,6 +93,7 @@ private slots:
void itemData();
void setItemData();
+ void createPersistentOnLayoutAboutToBeChanged();
};
void tst_QStringListModel::moveRowsInvalid_data()
@@ -447,5 +448,34 @@ void tst_QStringListModel::supportedDragDropActions()
QCOMPARE(model.supportedDropActions(), Qt::CopyAction | Qt::MoveAction);
}
+void tst_QStringListModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QStringListModel model(QStringList{QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3")});
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(&model, &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(&model, &QAbstractItemModel::layoutChanged);
+ connect(&model, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &model](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(model.index(row, 0));
+ });
+ connect(&model, &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toString(), QStringLiteral("1"));
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toString(), QStringLiteral("0"));
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toString(), QStringLiteral("3"));
+ });
+ model.setData(model.index(1, 0), QStringLiteral("0"));
+ model.sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
QTEST_MAIN(tst_QStringListModel)
#include "tst_qstringlistmodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp b/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp
index 8e8d1ec709..f577c3c41b 100644
--- a/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp
@@ -84,6 +84,8 @@ private Q_SLOTS:
void setItemData();
void moveRowsBase();
void moveColumnsProxy();
+ void sortPersistentIndex();
+ void createPersistentOnLayoutAboutToBeChanged();
private:
void testTransposed(
const QAbstractItemModel *const baseModel,
@@ -343,6 +345,84 @@ void tst_QTransposeProxyModel::removeColumnBase()
delete model;
}
+void tst_QTransposeProxyModel::sortPersistentIndex()
+{
+ QStringListModel model(QStringList{QStringLiteral("Alice"), QStringLiteral("Charlie"), QStringLiteral("Bob")});
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ QPersistentModelIndex aliceIdx = proxy.index(0, 0);
+ QPersistentModelIndex bobIdx = proxy.index(0, 2);
+ QPersistentModelIndex charlieIdx = proxy.index(0, 1);
+ connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&aliceIdx, &bobIdx, &charlieIdx](){
+ QCOMPARE(aliceIdx.row(), 0);
+ QCOMPARE(aliceIdx.column(), 0);
+ QCOMPARE(aliceIdx.data().toString(), QStringLiteral("Alice"));
+ QCOMPARE(bobIdx.row(), 0);
+ QCOMPARE(bobIdx.column(), 2);
+ QCOMPARE(bobIdx.data().toString(), QStringLiteral("Bob"));
+ QCOMPARE(charlieIdx.row(), 0);
+ QCOMPARE(charlieIdx.column(), 1);
+ QCOMPARE(charlieIdx.data().toString(), QStringLiteral("Charlie"));
+ });
+ connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&aliceIdx, &bobIdx, &charlieIdx](){
+ QCOMPARE(aliceIdx.row(), 0);
+ QCOMPARE(aliceIdx.column(), 0);
+ QCOMPARE(aliceIdx.data().toString(), QStringLiteral("Alice"));
+ QCOMPARE(bobIdx.row(), 0);
+ QCOMPARE(bobIdx.column(), 1);
+ QCOMPARE(bobIdx.data().toString(), QStringLiteral("Bob"));
+ QCOMPARE(charlieIdx.row(), 0);
+ QCOMPARE(charlieIdx.column(), 2);
+ QCOMPARE(charlieIdx.data().toString(), QStringLiteral("Charlie"));
+ });
+ model.sort(0);
+ QCOMPARE(aliceIdx.row(), 0);
+ QCOMPARE(aliceIdx.column(), 0);
+ QCOMPARE(aliceIdx.data().toString(), QStringLiteral("Alice"));
+ QCOMPARE(bobIdx.row(), 0);
+ QCOMPARE(bobIdx.column(), 1);
+ QCOMPARE(bobIdx.data().toString(), QStringLiteral("Bob"));
+ QCOMPARE(charlieIdx.row(), 0);
+ QCOMPARE(charlieIdx.column(), 2);
+ QCOMPARE(charlieIdx.data().toString(), QStringLiteral("Charlie"));
+}
+
+void tst_QTransposeProxyModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QStandardItemModel model(3, 1);
+ for (int row = 0; row < 3; ++row)
+ model.setData(model.index(row, 0), row, Qt::UserRole);
+ model.setSortRole(Qt::UserRole);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged);
+ connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &proxy](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(proxy.index(0, row));
+ });
+ connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 0);
+ QCOMPARE(idxList.at(0).column(), 1);
+ QCOMPARE(idxList.at(0).data(Qt::UserRole).toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data(Qt::UserRole).toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 0);
+ QCOMPARE(idxList.at(2).column(), 2);
+ QCOMPARE(idxList.at(2).data(Qt::UserRole).toInt(), 2);
+ });
+ model.setData(model.index(1, 0), -1, Qt::UserRole);
+ model.sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
void tst_QTransposeProxyModel::insertColumnBase_data()
{
QTest::addColumn<QAbstractItemModel *>("model");
diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
index 7fc2c473de..7758a5d5cc 100644
--- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
+++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
@@ -138,6 +138,7 @@ private slots:
void taskQTBUG_45114_setItemData();
void setItemPersistentIndex();
void signalsOnTakeItem();
+ void createPersistentOnLayoutAboutToBeChanged();
private:
QStandardItemModel *m_model = nullptr;
QPersistentModelIndex persistent;
@@ -1785,5 +1786,40 @@ void tst_QStandardItemModel::signalsOnTakeItem() // QTBUG-89145
QCOMPARE(m.index(1, 0).data(), QVariant());
}
+void tst_QStandardItemModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QStandardItemModel model;
+ QAbstractItemModelTester mTester(&model, nullptr);
+ model.insertColumn(0);
+ QCOMPARE(model.columnCount(), 1);
+ model.insertRows(0, 3);
+ for (int row = 0; row < 3; ++row)
+ model.setData(model.index(row, 0), row);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(&model, &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(&model, &QAbstractItemModel::layoutChanged);
+ connect(&model, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &model](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(model.index(row, 0));
+ });
+ connect(&model, &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toInt(), 2);
+ });
+ model.setData(model.index(1, 0), -1);
+ model.sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
QTEST_MAIN(tst_QStandardItemModel)
#include "tst_qstandarditemmodel.moc"
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
index 48b0cb8d6b..b121766265 100644
--- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -118,6 +118,8 @@ private slots:
void QTBUG14363_completerWithAnyKeyPressedEditTriggers();
void mimeData();
void QTBUG50891_ensureSelectionModelSignalConnectionsAreSet();
+ void createPersistentOnLayoutAboutToBeChanged();
+ void createPersistentOnLayoutAboutToBeChangedAutoSort();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void clearItemData();
#endif
@@ -1844,6 +1846,72 @@ void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet()
}
+void tst_QListWidget::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QListWidget widget;
+ QCOMPARE(widget.model()->columnCount(), 1);
+ widget.model()->insertRows(0, 3);
+ for (int row = 0; row < 3; ++row)
+ widget.model()->setData(widget.model()->index(row, 0), row);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(widget.model(), &QAbstractItemModel::layoutChanged);
+ connect(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &widget](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(widget.model()->index(row, 0));
+ });
+ connect(widget.model(), &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toInt(), 2);
+ });
+ widget.model()->setData(widget.model()->index(1, 0), -1);
+ widget.model()->sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
+void tst_QListWidget::createPersistentOnLayoutAboutToBeChangedAutoSort() // QTBUG-93466
+{
+ QListWidget widget;
+ QCOMPARE(widget.model()->columnCount(), 1);
+ widget.model()->insertRows(0, 3);
+ for (int row = 0; row < 3; ++row)
+ widget.model()->setData(widget.model()->index(row, 0), row);
+ widget.setSortingEnabled(true);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(widget.model(), &QAbstractItemModel::layoutChanged);
+ connect(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &widget](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(widget.model()->index(row, 0));
+ });
+ connect(widget.model(), &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toInt(), 2);
+ });
+ widget.model()->setData(widget.model()->index(1, 0), -1);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void tst_QListWidget::clearItemData()
{
diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
index 6ee923662e..b827d87910 100644
--- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
@@ -91,6 +91,8 @@ private slots:
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void clearItemData();
#endif
+ void createPersistentOnLayoutAboutToBeChanged();
+ void createPersistentOnLayoutAboutToBeChangedAutoSort();
private:
std::unique_ptr<QTableWidget> testWidget;
@@ -1756,5 +1758,74 @@ void tst_QTableWidget::clearItemData()
}
#endif
+void tst_QTableWidget::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QTableWidget widget;
+ widget.model()->insertColumn(0);
+ QCOMPARE(widget.model()->columnCount(), 1);
+ widget.model()->insertRows(0, 3);
+ for (int row = 0; row < 3; ++row)
+ widget.model()->setData(widget.model()->index(row, 0), row);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(widget.model(), &QAbstractItemModel::layoutChanged);
+ connect(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &widget](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(widget.model()->index(row, 0));
+ });
+ connect(widget.model(), &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toInt(), 2);
+ });
+ widget.model()->setData(widget.model()->index(1, 0), -1);
+ widget.model()->sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
+void tst_QTableWidget::createPersistentOnLayoutAboutToBeChangedAutoSort() // QTBUG-93466
+{
+ QTableWidget widget;
+ widget.model()->insertColumn(0);
+ QCOMPARE(widget.model()->columnCount(), 1);
+ widget.model()->insertRows(0, 3);
+ for (int row = 0; row < 3; ++row)
+ widget.model()->setData(widget.model()->index(row, 0), row);
+ widget.sortByColumn(0, Qt::AscendingOrder);
+ widget.setSortingEnabled(true);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(widget.model(), &QAbstractItemModel::layoutChanged);
+ connect(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &widget](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(widget.model()->index(row, 0));
+ });
+ connect(widget.model(), &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toInt(), 2);
+ });
+ widget.model()->setData(widget.model()->index(1, 0), -1);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
QTEST_MAIN(tst_QTableWidget)
#include "tst_qtablewidget.moc"
diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
index 4cfea81572..367bba4ee0 100644
--- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
@@ -152,6 +152,8 @@ private slots:
void testVisualItemRect();
void reparentHiddenItem();
void persistentChildIndex();
+ void createPersistentOnLayoutAboutToBeChanged();
+ void createPersistentOnLayoutAboutToBeChangedAutoSort();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void clearItemData();
#endif
@@ -3641,5 +3643,72 @@ void tst_QTreeWidget::clearItemData()
}
#endif
+void tst_QTreeWidget::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
+{
+ QTreeWidget widget;
+ QCOMPARE(widget.model()->columnCount(), 1);
+ widget.model()->insertRows(0, 3);
+ for (int row = 0; row < 3; ++row)
+ widget.model()->setData(widget.model()->index(row, 0), row);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(widget.model(), &QAbstractItemModel::layoutChanged);
+ connect(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &widget](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(widget.model()->index(row, 0));
+ });
+ connect(widget.model(), &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toInt(), 2);
+ });
+ widget.model()->setData(widget.model()->index(1, 0), -1);
+ widget.model()->sort(0);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
+void tst_QTreeWidget::createPersistentOnLayoutAboutToBeChangedAutoSort() // QTBUG-93466
+{
+ QTreeWidget widget;
+ QCOMPARE(widget.model()->columnCount(), 1);
+ widget.model()->insertRows(0, 3);
+ for (int row = 0; row < 3; ++row)
+ widget.model()->setData(widget.model()->index(row, 0), row);
+ widget.sortByColumn(0, Qt::AscendingOrder);
+ widget.setSortingEnabled(true);
+ QList<QPersistentModelIndex> idxList;
+ QSignalSpy layoutAboutToBeChangedSpy(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(widget.model(), &QAbstractItemModel::layoutChanged);
+ connect(widget.model(), &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &widget](){
+ idxList.clear();
+ for (int row = 0; row < 3; ++row)
+ idxList << QPersistentModelIndex(widget.model()->index(row, 0));
+ });
+ connect(widget.model(), &QAbstractItemModel::layoutChanged, this, [&idxList](){
+ QCOMPARE(idxList.size(), 3);
+ QCOMPARE(idxList.at(0).row(), 1);
+ QCOMPARE(idxList.at(0).column(), 0);
+ QCOMPARE(idxList.at(0).data().toInt(), 0);
+ QCOMPARE(idxList.at(1).row(), 0);
+ QCOMPARE(idxList.at(1).column(), 0);
+ QCOMPARE(idxList.at(1).data().toInt(), -1);
+ QCOMPARE(idxList.at(2).row(), 2);
+ QCOMPARE(idxList.at(2).column(), 0);
+ QCOMPARE(idxList.at(2).data().toInt(), 2);
+ });
+ widget.model()->setData(widget.model()->index(1, 0), -1);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+}
+
QTEST_MAIN(tst_QTreeWidget)
#include "tst_qtreewidget.moc"