summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp13
-rw-r--r--tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp66
2 files changed, 79 insertions, 0 deletions
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"