From defe418c16e5e79033812752416efa874c70e622 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 21 Oct 2010 10:37:46 +0200 Subject: Make sure d->ranges does not have invalid ranges before processing it. Reviewed-by: gabi Merge-request: 831 --- src/gui/itemviews/qitemselectionmodel.cpp | 13 +++++ .../tst_qitemselectionmodel.cpp | 66 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index f848321..e69cd65 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -1059,6 +1059,19 @@ void QItemSelectionModel::select(const QItemSelection &selection, QItemSelection // store old selection QItemSelection sel = selection; + // If d->ranges is non-empty when the source model is reset the persistent indexes + // it contains will be invalid. We can't clear them in a modelReset slot because that might already + // be too late if another model observer is connected to the same modelReset slot and is invoked first + // it might call select() on this selection model before any such QItemSelectionModelPrivate::_q_modelReset() slot + // is invoked, so it would not be cleared yet. We clear it invalid ranges in it here. + QItemSelection::iterator it = d->ranges.begin(); + while (it != d->ranges.end()) { + if (!it->isValid()) + it = d->ranges.erase(it); + else + ++it; + } + QItemSelection old = d->ranges; old.merge(d->currentSelection, d->currentCommand); diff --git a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp index 3b2a716..8058294 100644 --- a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -95,6 +95,8 @@ private slots: void QTBUG5671_layoutChangedWithAllSelected(); void QTBUG2804_layoutChangedTreeSelection(); + void testValidRangesInSelectionsAfterReset(); + private: QAbstractItemModel *model; QItemSelectionModel *selection; @@ -2353,6 +2355,70 @@ void tst_QItemSelectionModel::QTBUG2804_layoutChangedTreeSelection() QCOMPARE(selModel.selectedIndexes().count(), 4); } +class SelectionObserver : public QObject +{ + Q_OBJECT +public: + SelectionObserver(QAbstractItemModel *model, QObject *parent = 0) + : QObject(parent), m_model(model), m_selectionModel(0) + { + connect(model, SIGNAL(modelReset()), SLOT(modelReset())); + } + + void setSelectionModel(QItemSelectionModel *selectionModel) + { + m_selectionModel = selectionModel; + connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged(QItemSelection,QItemSelection))); + } + + private slots: + void modelReset() + { + const QModelIndex idx = m_model->index(2, 0); + QVERIFY(idx.isValid()); + m_selectionModel->select(QItemSelection(idx, idx), QItemSelectionModel::Clear); + } + + void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) + { + foreach(const QItemSelectionRange &range, selected) + QVERIFY(range.isValid()); + foreach(const QItemSelectionRange &range, deselected) + QVERIFY(range.isValid()); + } + +private: + QAbstractItemModel *m_model; + QItemSelectionModel *m_selectionModel; +}; + +void tst_QItemSelectionModel::testValidRangesInSelectionsAfterReset() +{ + QStringListModel model; + + QStringList strings; + strings << "one" + << "two" + << "three" + << "four" + << "five"; + + model.setStringList(strings); + + SelectionObserver observer(&model); + + QItemSelectionModel selectionModel(&model); + + selectionModel.select(QItemSelection(model.index(1, 0), model.index(3, 0)), QItemSelectionModel::Select); + + // Cause d->ranges to contain something. + model.insertRows(2, 1); + + observer.setSelectionModel(&selectionModel); + + model.setStringList(strings); + +} QTEST_MAIN(tst_QItemSelectionModel) #include "tst_qitemselectionmodel.moc" -- cgit v0.12