summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp60
-rw-r--r--src/gui/itemviews/qitemselectionmodel_p.h2
-rw-r--r--tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp30
3 files changed, 66 insertions, 26 deletions
diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp
index 0f35ac1..06c345f 100644
--- a/src/gui/itemviews/qitemselectionmodel.cpp
+++ b/src/gui/itemviews/qitemselectionmodel.cpp
@@ -590,31 +590,43 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
emit q->currentColumnChanged(currentIndex, old);
}
- // update selectionsx
- QModelIndex tl = model->index(start, 0, parent);
- QModelIndex br = model->index(end, model->columnCount(parent) - 1, parent);
- recursiveDeselect(QItemSelectionRange(tl, br));
- finalize();
-}
-
-void QItemSelectionModelPrivate::recursiveDeselect(const QItemSelectionRange &range)
-{
- Q_Q(QItemSelectionModel);
-
- QItemSelection sel(range.topLeft(), range.bottomRight());
- q->select(sel, QItemSelectionModel::Deselect);
-
- QModelIndexList idxList = range.indexes();
- QModelIndexList::const_iterator it = idxList.begin();
- for (; it != idxList.end(); ++it)
- {
- if (!model->hasChildren(*it))
- continue;
-
- const QModelIndex &firstChild = it->child(0,0);
- const QModelIndex &lastChild = it->child(model->rowCount(*it) - 1, model->columnCount(*it) - 1);
- recursiveDeselect(QItemSelectionRange(firstChild, lastChild));
+ QItemSelection deselected;
+ QItemSelection::iterator it = currentSelection.begin();
+ while (it != currentSelection.end()) {
+ if (it->topLeft().parent() != parent) { // Check parents until reaching root or contained in range
+ QModelIndex itParent = it->topLeft().parent();
+ while (itParent.isValid() && itParent.parent() != parent)
+ itParent = itParent.parent();
+
+ if (parent.isValid() && start <= itParent.row() && itParent.row() <= end) {
+ deselected.append(*it);
+ it = currentSelection.erase(it);
+ } else {
+ ++it;
+ }
+ } else if (start <= it->bottom() && it->bottom() <= end // Full inclusion
+ && start <= it->top() && it->top() <= end) {
+ deselected.append(*it);
+ it = currentSelection.erase(it);
+ } else if (start <= it->top() && it->top() <= end) { // Top intersection
+ deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->left(), it->parent())));
+ it = currentSelection.insert(it, QItemSelectionRange(model->index(end + 1, it->left(), it->parent()),
+ it->bottomRight()));
+ it = currentSelection.erase(++it);
+ } else if (start <= it->bottom() && it->bottom() <= end) { // Bottom intersection
+ deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight()));
+ it = currentSelection.insert(it, QItemSelectionRange(it->topLeft(),
+ model->index(start - 1, it->right(), it->parent())));
+ it = currentSelection.erase(++it);
+ } else {
+ if (it->top() < start && end < it->bottom()) // Middle intersection (do nothing)
+ deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()),
+ model->index(end, it->left(), it->parent())));
+ ++it;
+ }
}
+
+ emit q->selectionChanged(QItemSelection(), deselected);
}
/*!
diff --git a/src/gui/itemviews/qitemselectionmodel_p.h b/src/gui/itemviews/qitemselectionmodel_p.h
index 8176d4c..18ad506 100644
--- a/src/gui/itemviews/qitemselectionmodel_p.h
+++ b/src/gui/itemviews/qitemselectionmodel_p.h
@@ -77,8 +77,6 @@ public:
void _q_layoutAboutToBeChanged();
void _q_layoutChanged();
- void recursiveDeselect(const QItemSelectionRange &range);
-
inline void remove(QList<QItemSelectionRange> &r)
{
QList<QItemSelectionRange>::const_iterator it = r.constBegin();
diff --git a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp
index 05e23f1..ec21f79 100644
--- a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp
+++ b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp
@@ -2209,6 +2209,36 @@ void tst_QItemSelectionModel::task232634_childrenDeselectionSignal()
QSignalSpy deselectSpy(&selectionModel, SIGNAL(selectionChanged(const QItemSelection& , const QItemSelection&)));
model.removeRows(0, 1, root);
QVERIFY(deselectSpy.count() == 1);
+
+ // More testing stress for the patch.
+ model.clear();
+ selectionModel.clear();
+
+ parentItem = model.invisibleRootItem();
+ for (int i = 0; i < 2; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ parentItem->appendRow(item);
+ }
+ for (int i = 0; i < 2; ++i) {
+ parentItem = model.invisibleRootItem()->child(i, 0);
+ for (int j = 0; j < 2; ++j) {
+ QStandardItem *item = new QStandardItem(QString("item %0.%1").arg(i).arg(j));
+ parentItem->appendRow(item);
+ }
+ }
+
+ sel = model.index(0, 0).child(0, 0);
+ selectionModel.select(sel, QItemSelectionModel::Select);
+ QModelIndex sel2 = model.index(1, 0).child(0, 0);
+ selectionModel.select(sel2, QItemSelectionModel::Select);
+
+ QVERIFY(selectionModel.selection().contains(sel));
+ QVERIFY(selectionModel.selection().contains(sel2));
+ deselectSpy.clear();
+ model.removeRow(0, model.index(0, 0));
+ QVERIFY(deselectSpy.count() == 1);
+ QVERIFY(!selectionModel.selection().contains(sel));
+ QVERIFY(selectionModel.selection().contains(sel2));
}
QTEST_MAIN(tst_QItemSelectionModel)