aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-10-31 16:10:03 +0100
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-12-08 23:25:20 +0100
commit52cbcd947db2219aecb2f6cb59bc6676a7c61e48 (patch)
tree09835ffc85ef313dfafbdb29305cf4cc83e3d290
parente43638c8a830b9ade737b361fa471381b3afdb11 (diff)
QQuickTableView: support multi-selection
Implement support for doing multiple selections in TableView by holding down the shift modifier while dragging. [ChangeLog][Quick][TableView] Added multi-selection support if using a SelectionRectangle and holding down the shift-modifier. Change-Id: Ife622aeea2ed60a5741df01f3aac2fb647108aa9 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r--src/quick/items/qquickselectable_p.h2
-rw-r--r--src/quick/items/qquicktableview.cpp23
-rw-r--r--src/quick/items/qquicktableview_p_p.h4
-rw-r--r--src/quicktemplates/qquickselectionrectangle.cpp13
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml28
5 files changed, 56 insertions, 14 deletions
diff --git a/src/quick/items/qquickselectable_p.h b/src/quick/items/qquickselectable_p.h
index 0381b73f69..726352719f 100644
--- a/src/quick/items/qquickselectable_p.h
+++ b/src/quick/items/qquickselectable_p.h
@@ -25,7 +25,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickSelectable
public:
virtual QQuickItem *selectionPointerHandlerTarget() const = 0;
- virtual bool canStartSelection(const QPointF &pos) = 0;
+ virtual bool startSelection(const QPointF &pos) = 0;
virtual void setSelectionStartPos(const QPointF &pos) = 0;
virtual void setSelectionEndPos(const QPointF &pos) = 0;
virtual void clearSelection() = 0;
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index b52922fbee..d4e4305fb3 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -1517,11 +1517,18 @@ QQuickItem *QQuickTableViewPrivate::selectionPointerHandlerTarget() const
return const_cast<QQuickTableView *>(q_func())->contentItem();
}
-bool QQuickTableViewPrivate::canStartSelection(const QPointF &pos)
+bool QQuickTableViewPrivate::startSelection(const QPointF &pos)
{
+ Q_Q(QQuickTableView);
Q_UNUSED(pos);
// Only allow a selection if it doesn't conflict with resizing
- return resizeHandler->state() == QQuickTableViewResizeHandler::Listening;
+ const bool canStartSelection = resizeHandler->state() == QQuickTableViewResizeHandler::Listening;
+ if (canStartSelection) {
+ selectionStartCell = QPoint(-1, -1);
+ selectionEndCell = QPoint(-1, -1);
+ q->closeEditor();
+ }
+ return canStartSelection;
}
void QQuickTableViewPrivate::setSelectionStartPos(const QPointF &pos)
@@ -4633,12 +4640,12 @@ void QQuickTableViewPrivate::init()
positionYAnimation.stop();
if (!q->isInteractive())
- handleTap(tapHandler->point().pressPosition());
+ handleTap(tapHandler->point());
});
QObject::connect(tapHandler, &QQuickTapHandler::singleTapped, [this, q, tapHandler] {
if (q->isInteractive())
- handleTap(tapHandler->point().pressPosition());
+ handleTap(tapHandler->point());
});
QObject::connect(tapHandler, &QQuickTapHandler::doubleTapped, [this, q, tapHandler] {
@@ -4660,13 +4667,15 @@ void QQuickTableViewPrivate::init()
});
}
-void QQuickTableViewPrivate::handleTap(const QPointF &pos)
+void QQuickTableViewPrivate::handleTap(const QQuickHandlerPoint &point)
{
Q_Q(QQuickTableView);
if (keyNavigationEnabled)
q->forceActiveFocus(Qt::MouseFocusReason);
+ if (point.modifiers() != Qt::NoModifier)
+ return;
if (resizableRows && hoverHandler->m_row != -1)
return;
if (resizableColumns && hoverHandler->m_column != -1)
@@ -4679,14 +4688,14 @@ void QQuickTableViewPrivate::handleTap(const QPointF &pos)
prevIndex = selectionModel->currentIndex();
if (pointerNavigationEnabled) {
clearSelection();
- setCurrentIndexFromTap(pos);
+ setCurrentIndexFromTap(point.position());
}
}
if (editTriggers != QQuickTableView::NoEditTriggers)
q->closeEditor();
- const QModelIndex tappedIndex = q->modelIndex(q->cellAtPosition(pos));
+ const QModelIndex tappedIndex = q->modelIndex(q->cellAtPosition(point.position()));
if (canEdit(tappedIndex, false)) {
if (editTriggers & QQuickTableView::SingleTapped)
q->edit(tappedIndex);
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index 54730fbc64..40763b340e 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -548,7 +548,7 @@ public:
int serializedModelIndex,
QObject *object, bool init);
- void handleTap(const QPointF &pos);
+ void handleTap(const QQuickHandlerPoint &point);
void setCurrentIndexFromTap(const QPointF &pos);
void setCurrentIndex(const QPoint &cell);
bool setCurrentIndexFromKeyEvent(QKeyEvent *e);
@@ -557,7 +557,7 @@ public:
// QQuickSelectable
QQuickItem *selectionPointerHandlerTarget() const override;
- bool canStartSelection(const QPointF &pos) override;
+ bool startSelection(const QPointF &pos) override;
void setSelectionStartPos(const QPointF &pos) override;
void setSelectionEndPos(const QPointF &pos) override;
void clearSelection() override;
diff --git a/src/quicktemplates/qquickselectionrectangle.cpp b/src/quicktemplates/qquickselectionrectangle.cpp
index 9e9fa60710..28f495d525 100644
--- a/src/quicktemplates/qquickselectionrectangle.cpp
+++ b/src/quicktemplates/qquickselectionrectangle.cpp
@@ -182,7 +182,9 @@ QQuickSelectionRectanglePrivate::QQuickSelectionRectanglePrivate()
QObject::connect(m_tapHandler, &QQuickTapHandler::longPressed, [this]() {
const QPointF pos = m_tapHandler->point().pressPosition();
- if (!m_selectable->canStartSelection(pos))
+ const auto modifiers = m_tapHandler->point().modifiers();
+
+ if (!m_selectable->startSelection(pos))
return;
if (handleUnderPos(pos) != nullptr) {
// Don't allow press'n'hold to start a new
@@ -199,7 +201,8 @@ QQuickSelectionRectanglePrivate::QQuickSelectionRectanglePrivate()
}
}
- m_selectable->clearSelection();
+ if (!modifiers.testFlag(Qt::ShiftModifier))
+ m_selectable->clearSelection();
m_selectable->setSelectionStartPos(pos);
m_selectable->setSelectionEndPos(pos);
updateHandles();
@@ -209,11 +212,13 @@ QQuickSelectionRectanglePrivate::QQuickSelectionRectanglePrivate()
QObject::connect(m_dragHandler, &QQuickDragHandler::activeChanged, [this]() {
const QPointF startPos = m_dragHandler->centroid().pressPosition();
const QPointF dragPos = m_dragHandler->centroid().position();
+ const auto modifiers = m_dragHandler->centroid().modifiers();
if (m_dragHandler->active()) {
- if (!m_selectable->canStartSelection(startPos))
+ if (!m_selectable->startSelection(startPos))
return;
- m_selectable->clearSelection();
+ if (!modifiers.testFlag(Qt::ShiftModifier))
+ m_selectable->clearSelection();
m_selectable->setSelectionStartPos(startPos);
m_selectable->setSelectionEndPos(dragPos);
m_draggedHandle = nullptr;
diff --git a/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml b/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml
index 9203528d07..4a1e08f478 100644
--- a/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml
@@ -198,8 +198,36 @@ TestCase {
mousePress(tableView, 1, 1, Qt.LeftButton)
mousePress(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000)
verify(!tableView.selectionModel.hasSelection)
+
}
+// TODO: enable this test when mouseDrag sends modifiers for all mouse events
+// (including mouseMove)
+// function test_multi_selection() {
+// let tableView = createTemporaryObject(tableviewComp, testCase)
+// verify(tableView)
+// let selectionRectangle = tableView.selectionRectangle
+// verify(selectionRectangle)
+// verify(!tableView.selectionModel.hasSelection)
+
+// selectionRectangle.selectionMode = SelectionRectangle.Drag
+
+// 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)))
+
+// // Hold down shift, and drag again to do a multi-selection
+// mouseDrag(tableView, 1, cellHeight + 5, (cellWidth * 2) - 2, 1, Qt.LeftButton, Qt.ShiftModifier)
+// verify(tableView.selectionModel.hasSelection)
+// compare(tableView.selectionModel.selectedIndexes.length, 4)
+// verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0)))
+// verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1)))
+// verify(tableView.selectionModel.isSelected(tableView.model.index(1, 0)))
+// verify(tableView.selectionModel.isSelected(tableView.model.index(1, 1)))
+// }
+
function test_pressAndHold_data() {
return [
{ tag: "resize enabled", resizeEnabled: true },