diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2012-10-02 18:15:33 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-10-04 12:15:49 +0200 |
commit | f37d3e2cd9aae156dc58a0e9f057e78dadda7b93 (patch) | |
tree | 23ca056d1f438f1df9b116a7ae43281183a2a6cf | |
parent | 65f6ad26ed167b9baf0e63ba0b36f56a3de9c635 (diff) |
Fix segfault when delegates change properties on editors.
The solution is similar to that
in b84e180263d0da3d1e6967fcf759225a778ea6ea which affected
QSortFilterProxyModel.
Task-number: QTBUG-25370
Change-Id: I6bbb9d9786bcb2c9fa8027ab8a7cc13664784b8d
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
-rw-r--r-- | src/widgets/itemviews/qabstractitemview.cpp | 8 | ||||
-rw-r--r-- | tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp | 56 |
2 files changed, 62 insertions, 2 deletions
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index e34123a1d2..b30bdbbc6b 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -4118,8 +4118,12 @@ void QAbstractItemViewPrivate::updateEditorData(const QModelIndex &tl, const QMo // we are counting on having relatively few editors const bool checkIndexes = tl.isValid() && br.isValid(); const QModelIndex parent = tl.parent(); - QIndexEditorHash::const_iterator it = indexEditorHash.constBegin(); - for (; it != indexEditorHash.constEnd(); ++it) { + // QTBUG-25370: We need to copy the indexEditorHash, because while we're + // iterating over it, we are calling methods which can allow user code to + // call a method on *this which can modify the member indexEditorHash. + const QIndexEditorHash indexEditorHashCopy = indexEditorHash; + QIndexEditorHash::const_iterator it = indexEditorHashCopy.constBegin(); + for (; it != indexEditorHashCopy.constEnd(); ++it) { QWidget *editor = it.value().widget.data(); const QModelIndex index = it.key(); if (it.value().isStatic || !editor || !index.isValid() || diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 3be28b8e9b..8ccd13ff3e 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -226,6 +226,7 @@ private slots: void QTBUG6753_selectOnSelection(); void testDelegateDestroyEditor(); void testClickedSignal(); + void testChangeEditorState(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -1534,5 +1535,60 @@ void tst_QAbstractItemView::testClickedSignal() } +class StateChangeDelegate : public QItemDelegate { + Q_OBJECT + +public: + explicit StateChangeDelegate(QObject* parent = 0) : + QItemDelegate(parent) + {} + + void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE { + static bool w = true; + editor->setEnabled(w); + w = !w; + } +}; + +class StateChangeModel : public QStandardItemModel { + Q_OBJECT + +public: + explicit StateChangeModel(QObject *parent = 0) : + QStandardItemModel(parent) + {} + + void emitDataChanged() { + emit dataChanged(index(0, 0), index(0, 1)); + } +}; + + +void tst_QAbstractItemView::testChangeEditorState() +{ + // Test for QTBUG-25370 + StateChangeModel model; + { + QStandardItem* item = new QStandardItem("a"); + model.setItem(0, 0, item); + } + { + QStandardItem* item = new QStandardItem("b"); + model.setItem(0, 1, item); + } + + QTableView view; + view.setEditTriggers(QAbstractItemView::CurrentChanged); + view.setItemDelegate(new StateChangeDelegate); + view.setModel(&model); + view.show(); + QApplication::setActiveWindow(&view); + QVERIFY(QTest::qWaitForWindowActive(&view)); + QCOMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow()); + + model.emitDataChanged(); + // No segfault - the test passes. +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" |