Fix QStandardItemModel signals on takeChild

takeItem and takeChild do not signal the change correctly to the
external world, this change fixes the problem

Fixes: QTBUG-89145
Change-Id: Ib4844ace53007068a2cd62eba64df99e6e45fdc0
Reviewed-by: David Faure <david.faure@kdab.com>
(cherry picked from commit 811a6c6b77a94d86e28a0b00079e02a863391108)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Luca Beldi 2021-05-11 10:24:43 +01:00 committed by Qt Cherry-pick Bot
parent aba4da8a0e
commit 838b1d1b76
2 changed files with 75 additions and 3 deletions

View File

@ -1893,10 +1893,35 @@ QStandardItem *QStandardItem::takeChild(int row, int column)
QStandardItem *item = nullptr;
int index = d->childIndex(row, column);
if (index != -1) {
QModelIndex changedIdx;
item = d->children.at(index);
if (item)
item->d_func()->setParentAndModel(nullptr, nullptr);
if (item && d->model) {
QStandardItemPrivate *const item_d = item->d_func();
const int savedRows = item_d->rows;
const int savedCols = item_d->columns;
const QVector<QStandardItem*> savedChildren = item_d->children;
if (savedRows > 0) {
d->model->d_func()->rowsAboutToBeRemoved(item, 0, savedRows - 1);
item_d->rows = 0;
item_d->children = QVector<QStandardItem*>(); //slightly faster than clear
d->model->d_func()->rowsRemoved(item, 0, savedRows);
}
if (savedCols > 0) {
d->model->d_func()->columnsAboutToBeRemoved(item, 0, savedCols - 1);
item_d->columns = 0;
if (!item_d->children.isEmpty())
item_d->children = QVector<QStandardItem*>(); //slightly faster than clear
d->model->d_func()->columnsRemoved(item, 0, savedCols);
}
item_d->rows = savedRows;
item_d->columns = savedCols;
item_d->children = savedChildren;
changedIdx = d->model->indexFromItem(item);
item_d->setParentAndModel(nullptr, nullptr);
}
d->children.replace(index, nullptr);
if (changedIdx.isValid())
d->model->dataChanged(changedIdx, changedIdx);
}
return item;
}

View File

@ -137,7 +137,7 @@ private slots:
void taskQTBUG_45114_setItemData();
void setItemPersistentIndex();
void signalsOnTakeItem();
private:
QStandardItemModel *m_model = nullptr;
QPersistentModelIndex persistent;
@ -1738,5 +1738,52 @@ void tst_QStandardItemModel::setItemPersistentIndex()
QVERIFY(!persistentIndex.isValid());
}
void tst_QStandardItemModel::signalsOnTakeItem() // QTBUG-89145
{
QStandardItemModel m;
m.insertColumns(0, 2);
m.insertRows(0, 5);
for (int i = 0; i < m.rowCount(); ++i) {
for (int j = 0; j < m.columnCount(); ++j)
m.setData(m.index(i, j), i + j);
}
const QModelIndex parentIndex = m.index(1, 0);
m.insertColumns(0, 2, parentIndex);
m.insertRows(0, 2, parentIndex);
for (int i = 0; i < m.rowCount(parentIndex); ++i) {
for (int j = 0; j < m.columnCount(parentIndex); ++j)
m.setData(m.index(i, j, parentIndex), i + j + 100);
}
QAbstractItemModelTester mTester(&m, nullptr);
QSignalSpy columnsRemovedSpy(&m, &QAbstractItemModel::columnsRemoved);
QSignalSpy columnsAboutToBeRemovedSpy(&m, &QAbstractItemModel::columnsAboutToBeRemoved);
QSignalSpy rowsRemovedSpy(&m, &QAbstractItemModel::rowsRemoved);
QSignalSpy rowsAboutToBeRemovedSpy(&m, &QAbstractItemModel::rowsAboutToBeRemoved);
QSignalSpy *const removeSpies[] = {&columnsRemovedSpy, &columnsAboutToBeRemovedSpy, &rowsRemovedSpy, &rowsAboutToBeRemovedSpy};
QSignalSpy dataChangedSpy(&m, &QAbstractItemModel::dataChanged);
QStandardItem *const takenItem = m.takeItem(1, 0);
for (auto &&spy : removeSpies) {
QCOMPARE(spy->count(), 1);
const auto spyArgs = spy->takeFirst();
QCOMPARE(spyArgs.at(0).value<QModelIndex>(), parentIndex);
QCOMPARE(spyArgs.at(1).toInt(), 0);
QCOMPARE(spyArgs.at(2).toInt(), 1);
}
QCOMPARE(dataChangedSpy.count(), 1);
const auto dataChangedSpyArgs = dataChangedSpy.takeFirst();
QCOMPARE(dataChangedSpyArgs.at(0).value<QModelIndex>(), m.index(1, 0));
QCOMPARE(dataChangedSpyArgs.at(1).value<QModelIndex>(), m.index(1, 0));
QCOMPARE(takenItem->data(Qt::EditRole).toInt(), 1);
QCOMPARE(takenItem->rowCount(), 2);
QCOMPARE(takenItem->columnCount(), 2);
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j)
QCOMPARE(takenItem->child(i, j)->data(Qt::EditRole).toInt(), i + j + 100);
}
QCOMPARE(takenItem->model(), nullptr);
QCOMPARE(takenItem->child(0, 0)->model(), nullptr);
QCOMPARE(m.index(1, 0).data(), QVariant());
}
QTEST_MAIN(tst_QStandardItemModel)
#include "tst_qstandarditemmodel.moc"