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>
This commit is contained in:
parent
e43638c8a8
commit
52cbcd947d
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,6 +201,7 @@ QQuickSelectionRectanglePrivate::QQuickSelectionRectanglePrivate()
|
|||
}
|
||||
}
|
||||
|
||||
if (!modifiers.testFlag(Qt::ShiftModifier))
|
||||
m_selectable->clearSelection();
|
||||
m_selectable->setSelectionStartPos(pos);
|
||||
m_selectable->setSelectionEndPos(pos);
|
||||
|
@ -209,10 +212,12 @@ 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;
|
||||
if (!modifiers.testFlag(Qt::ShiftModifier))
|
||||
m_selectable->clearSelection();
|
||||
m_selectable->setSelectionStartPos(startPos);
|
||||
m_selectable->setSelectionEndPos(dragPos);
|
||||
|
|
|
@ -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 },
|
||||
|
|
Loading…
Reference in New Issue