From 4214d705a20db54e591d2e46ea66ed1b4c834d47 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 8 Jan 2024 13:54:22 +0100 Subject: [PATCH] TableView: start a new selection when using Qt::ShiftModifier If no selection exists in TableView from before, and the user shift-clicks on a cell, then start a new selection from the current cell towards the clicked cell. This is already how it works if a selection is started using the keyboard, and also standard selection behavior for other item view implementations outside of Qt (e.g Finder on macOS). Fixes: QTBUG-120628 Pick-to: 6.6 6.5 Change-Id: I2fd34e680eed9992dd7c405fbd58ae4f5b0834ec Reviewed-by: Santhosh Kumar (cherry picked from commit aecb62403eb067ac882c5e9e95a94a03c2e2903d) Reviewed-by: Qt Cherry-pick Bot --- src/quick/items/qquicktableview.cpp | 15 +++++++-- .../qquickselectionrectangle.cpp | 11 +++++-- .../controls/data/tst_selectionrectangle.qml | 31 ++++++++++++++----- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index 2e2be92006..1e913ac10e 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -1645,6 +1645,7 @@ bool QQuickTableViewPrivate::startSelection(const QPointF &pos) void QQuickTableViewPrivate::setSelectionStartPos(const QPointF &pos) { + Q_Q(QQuickTableView); if (loadedItems.isEmpty()) return; if (!selectionModel) { @@ -1663,12 +1664,20 @@ void QQuickTableViewPrivate::setSelectionStartPos(const QPointF &pos) } const QRect prevSelection = selection(); - const QPoint clampedCell = clampedCellAtPos(pos); + + QPoint clampedCell; + if (pos.x() == -1) { + // Special case: use current cell as start cell + clampedCell = q->cellAtIndex(selectionModel->currentIndex()); + } else { + clampedCell = clampedCellAtPos(pos); + if (cellIsValid(clampedCell)) + setCurrentIndex(clampedCell); + } + if (!cellIsValid(clampedCell)) return; - setCurrentIndex(clampedCell); - switch (selectionBehavior) { case QQuickTableView::SelectCells: selectionStartCell = clampedCell; diff --git a/src/quicktemplates/qquickselectionrectangle.cpp b/src/quicktemplates/qquickselectionrectangle.cpp index 29df45978d..58e7c2e752 100644 --- a/src/quicktemplates/qquickselectionrectangle.cpp +++ b/src/quicktemplates/qquickselectionrectangle.cpp @@ -196,9 +196,14 @@ QQuickSelectionRectanglePrivate::QQuickSelectionRectanglePrivate() return; if (modifiers & Qt::ShiftModifier) { - // Extend the existing selection towards the pressed cell - if (!m_active) - return; + // Extend the selection towards the pressed cell. If there is no + // existing selection, start a new selection from the current item + // to the pressed item. + if (!m_active) { + if (!m_selectable->startSelection(pos)) + return; + m_selectable->setSelectionStartPos(QPoint{-1, -1}); + } m_selectable->setSelectionEndPos(pos); updateHandles(); updateActiveState(true); diff --git a/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml b/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml index dad165f251..541324ecb6 100644 --- a/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml +++ b/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml @@ -318,7 +318,14 @@ TestCase { verify(tableView.selectionModel.isSelected(tableView.selectionModel.model.index(0, 1))) } - function test_tableView_contiguousSelection() { + function test_tableView_contiguousSelection_data() { + return [ + { startFromCurrentIndex: false }, + { startFromCurrentIndex: true }, + ] + } + + function test_tableView_contiguousSelection(data) { let tableView = createTemporaryObject(tableviewComp, testCase) verify(tableView) let selectionRectangle = tableView.selectionRectangle @@ -327,13 +334,21 @@ TestCase { selectionRectangle.selectionMode = SelectionRectangle.Drag tableView.selectionMode = TableView.ContiguousSelection - // Select two cells by dragging - verify(!tableView.selectionModel.hasSelection) - mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton) - verify(tableView.selectionModel.hasSelection) - compare(tableView.selectionModel.selectedIndexes.length, 2) - verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0))) - verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1))) + if (data.startFromCurrentIndex) { + // Click on a cell to set current index, but set no selection. + // A later shift-click should then start a new selection from the + // current cell. + mouseClick(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier) + verify(!tableView.selectionModel.hasSelection) + compare(tableView.selectionModel.currentIndex, tableView.index(0, 0)) + } else { + // Start a new selection by dragging on two cells + mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton) + verify(tableView.selectionModel.hasSelection) + compare(tableView.selectionModel.selectedIndexes.length, 2) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0))) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1))) + } // A shift click should extend the selection mouseClick(tableView, (cellWidth * 4) - 3, 1, Qt.LeftButton, Qt.ShiftModifier)