summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaloyan Chehlarski <[email protected]>2024-08-14 11:36:49 +0200
committerKaloyan Chehlarski <[email protected]>2024-08-21 13:34:12 +0000
commitfb2d64bc57aadf5bf140c72cf7eb2a5f391b7d55 (patch)
tree6aab4b7b9323d5b6752215ad92498ee9a7cbe661
parent23edf01b585e00019685a8d9fb65bfbecd7341c1 (diff)
QAbstractItemView: Fix shift-select after changing index through model
When setting the current index through the related model's QItemSelectionModel::setCurrentIndex(), the selection can also change. However, attempting to shift-select after doing so would produce an unexpected selection, because the internal variable that keeps track of the start index of the current selection would still have its old value. This change moves where said variable is set: instead of doing that in QAbstractItemView::setCurrentIndex(), it is now done inside the currentChanged() slot instead. This slot will get called both when the selection is modified through the QAbstractItemView class itself, as well as when it's modified from the outside (e.g. from the model). Pick-to: 6.2 6.5 6.7 6.8 Fixes: QTBUG-127381 Change-Id: I6d38320e656aa5a102ce079604590672c88ecad1 Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp6
-rw-r--r--src/widgets/itemviews/qtableview.cpp18
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp33
3 files changed, 53 insertions, 4 deletions
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 0b90fedad5b..033fa114c9a 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -1094,8 +1094,6 @@ void QAbstractItemView::setCurrentIndex(const QModelIndex &index)
QItemSelectionModel::SelectionFlags command = selectionCommand(index, nullptr);
d->selectionModel->setCurrentIndex(index, command);
d->currentIndexSet = true;
- if ((command & QItemSelectionModel::Current) == 0)
- d->currentSelectionStartIndex = index;
}
}
@@ -3826,6 +3824,10 @@ void QAbstractItemView::currentChanged(const QModelIndex &current, const QModelI
}
}
+ QItemSelectionModel::SelectionFlags command = selectionCommand(current, nullptr);
+ if ((command & QItemSelectionModel::Current) == 0)
+ d->currentSelectionStartIndex = current;
+
if (current.isValid() && !d->autoScrollTimer.isActive()) {
if (isVisible()) {
if (d->autoScroll)
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index 89ca5c1a51c..db62f13355d 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -3410,7 +3410,14 @@ void QTableViewPrivate::selectRow(int row, bool anchor)
int column = horizontalHeader->logicalIndexAt(q->isRightToLeft() ? viewport->width() : 0);
QModelIndex index = model->index(row, column, root);
QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
- selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
+
+ {
+ // currentSelectionStartIndex gets modified inside QAbstractItemView::currentChanged()
+ const auto startIndex = currentSelectionStartIndex;
+ selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
+ currentSelectionStartIndex = startIndex;
+ }
+
if ((anchor && !(command & QItemSelectionModel::Current))
|| (q->selectionMode() == QTableView::SingleSelection))
currentSelectionStartIndex = model->index(row, column, root);
@@ -3450,7 +3457,14 @@ void QTableViewPrivate::selectColumn(int column, bool anchor)
int row = verticalHeader->logicalIndexAt(0);
QModelIndex index = model->index(row, column, root);
QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
- selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
+
+ {
+ // currentSelectionStartIndex gets modified inside QAbstractItemView::currentChanged()
+ const auto startIndex = currentSelectionStartIndex;
+ selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
+ currentSelectionStartIndex = startIndex;
+ }
+
if ((anchor && !(command & QItemSelectionModel::Current))
|| (q->selectionMode() == QTableView::SingleSelection))
currentSelectionStartIndex = model->index(row, column, root);
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index b208c104a0d..6474e034e9b 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -152,6 +152,7 @@ private slots:
void testSpinBoxAsEditor();
void removeIndexWhileEditing();
void focusNextOnHide();
+ void shiftSelectionAfterModelSetCurrentIndex();
private:
static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr)
@@ -3565,5 +3566,37 @@ void tst_QAbstractItemView::focusNextOnHide()
QVERIFY(lineEdit.hasFocus());
}
+// Tests for QTBUG-127381, where shift-selecting after calling
+// QItemSelectionModel::setCurrentIndex() would produce unexpected results.
+void tst_QAbstractItemView::shiftSelectionAfterModelSetCurrentIndex()
+{
+ QStandardItemModel model(5, 1);
+ QTreeView view;
+ view.setSelectionBehavior(QAbstractItemView::SelectRows);
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ view.setModel(&model);
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ QModelIndex index = model.index(0, 0);
+ view.setCurrentIndex(index);
+ index = model.index(2, 0);
+ view.selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
+
+ QTest::keyPress(&view, Qt::Key_Down, Qt::ShiftModifier);
+
+ QItemSelection selection = view.selectionModel()->selection();
+ QCOMPARE(selection.size(), 1);
+ QCOMPARE(selection.first().top(), 2);
+ QCOMPARE(selection.first().bottom(), 3);
+
+ QTest::keyPress(&view, Qt::Key_Up, Qt::ShiftModifier);
+
+ selection = view.selectionModel()->selection();
+ QCOMPARE(selection.first().top(), 2);
+ QCOMPARE(selection.first().bottom(), 2);
+}
+
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"