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
Pick-to: 6.2 5.15
Change-Id: I73c24501f536ef9b6092c3374821497f0a8f0de4
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Luca Beldi 2021-07-20 15:49:33 +01:00
parent e1b010ff47
commit 1dcfb09c5b
12 changed files with 492 additions and 17 deletions

View File

@ -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,

View File

@ -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) {
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);
}
}

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -55,6 +55,7 @@ private slots:
void sort();
void sortHierarchy_data();
void sortHierarchy();
void createPersistentOnLayoutAboutToBeChanged();
void insertRows_data();
void insertRows();

View File

@ -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"

View File

@ -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");

View File

@ -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"

View File

@ -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()
{

View File

@ -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"

View File

@ -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"