diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-06-01 17:10:43 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-06-03 19:37:46 +0200 |
commit | 5174f979a3df1e24762f1b9829bb983ed4d7402a (patch) | |
tree | a71d794809baf5c60a03f169c43aba3b0f6f9cc5 /tests/auto/widgets | |
parent | 17c1ebf8bfd254ff75cc55e335d1c1fb01da547f (diff) |
QAbstractItemView: add test for mouse selection
Covers all selection modes and various combinations of mouse press, click,
drag, with or without modifiers.
Task-number: QTBUG-59888
Change-Id: Ib8ddc319a89649338d55fbc47e5a7ccfed338af9
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'tests/auto/widgets')
-rw-r--r-- | tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 3d851dc10c..37fa192a05 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -158,6 +158,9 @@ private slots: void dragWithSecondClick(); void selectionCommand_data(); void selectionCommand(); + void mouseSelection_data(); + void mouseSelection(); + private: static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr) { @@ -2739,5 +2742,217 @@ void tst_QAbstractItemView::selectionCommand() QCOMPARE(selectionFlag, view.selectionCommand(QModelIndex(), nullptr)); } +struct SelectionEvent +{ + enum MouseEvent + { Press, Release, Click, Move }; + constexpr SelectionEvent(MouseEvent type, int r = -1) noexcept + : eventType(type), row(r) {} + constexpr SelectionEvent(MouseEvent type, Qt::KeyboardModifiers mod, int r = -1) noexcept + : eventType(type), keyboardModifiers(mod), row(r) {} + MouseEvent eventType = Press; + Qt::KeyboardModifiers keyboardModifiers = Qt::NoModifier; + int row = -1; +}; + +void tst_QAbstractItemView::mouseSelection_data() +{ + QTest::addColumn<QAbstractItemView::SelectionMode>("selectionMode"); + QTest::addColumn<bool>("dragEnabled"); + QTest::addColumn<QList<SelectionEvent>>("selectionEvents"); + QTest::addColumn<QList<int>>("selectedRows"); + + // single selection mode - always one row selected, modifiers ignored + QTest::addRow("Single:Press") << QAbstractItemView::SingleSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1)} + << QList{1}; + QTest::addRow("Single:Click") << QAbstractItemView::SingleSelection << false + << QList{SelectionEvent{SelectionEvent::Click, 1}} + << QList{1}; + QTest::addRow("Single:Press+Drag") << QAbstractItemView::SingleSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1), + SelectionEvent{SelectionEvent::Move, 2}, + SelectionEvent{SelectionEvent::Release}} + << QList{2}; + QTest::addRow("Single:Shift+Click") << QAbstractItemView::SingleSelection << false + << QList{SelectionEvent{SelectionEvent::Click, Qt::ShiftModifier, 2}} + << QList{2}; + QTest::addRow("Single:Ctrl+Click") << QAbstractItemView::SingleSelection << false + << QList{SelectionEvent{SelectionEvent::Click, Qt::ControlModifier, 3}} + << QList{3}; + + // multi selection mode - selection toggles on press, selection can be drag-extended + // modifiers ignored + QTest::addRow("Multi:Press") << QAbstractItemView::MultiSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1)} + << QList{1}; + QTest::addRow("Multi:Press twice") << QAbstractItemView::MultiSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1), + SelectionEvent(SelectionEvent::Press, 1)} + << QList<int>{}; + QTest::addRow("Multi:Click") << QAbstractItemView::MultiSelection << false + << QList{SelectionEvent(SelectionEvent::Click, 2)} + << QList{2}; + QTest::addRow("Multi:Press,Press") << QAbstractItemView::MultiSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 2), + SelectionEvent(SelectionEvent::Press, 3)} + << QList{2, 3}; + QTest::addRow("Multi:Press,Drag") << QAbstractItemView::MultiSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1), + SelectionEvent(SelectionEvent::Move, 5), + SelectionEvent(SelectionEvent::Release)} + << QList{1, 2, 3, 4, 5}; + QTest::addRow("Multi:Press,Drag,Deselect") << QAbstractItemView::MultiSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1), + SelectionEvent(SelectionEvent::Move, 5), + SelectionEvent(SelectionEvent::Release), + SelectionEvent(SelectionEvent::Press, 3)} + << QList{1, 2, 4, 5}; + // drag-select a few indices; then drag-select a larger area that includes the first + QTest::addRow("Multi:Press,Drag;Surround") << QAbstractItemView::MultiSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 3), + SelectionEvent(SelectionEvent::Move, 5), + SelectionEvent(SelectionEvent::Release), + SelectionEvent(SelectionEvent::Press, 1), + SelectionEvent(SelectionEvent::Move, 8), + SelectionEvent(SelectionEvent::Release)} + << QList{1, 2, 3, 4, 5, 6, 7, 8}; + // drag-select a few indices; then try to select more starting with the last -> not working + QTest::addRow("Multi:Press,Drag;Expand") << QAbstractItemView::MultiSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 3), + SelectionEvent(SelectionEvent::Move, 5), + SelectionEvent(SelectionEvent::Release), + SelectionEvent(SelectionEvent::Press, 5), // this will deselect #5 and not select 6/7/8 + SelectionEvent(SelectionEvent::Move, 8), + SelectionEvent(SelectionEvent::Release)} + << QList{3, 4}; + // Multi: Press-dragging a selection should not deselect #QTBUG-59888 + QTest::addRow("Multi:Press-Drag selection") << QAbstractItemView::MultiSelection << true + << QList{SelectionEvent(SelectionEvent::Press, 2), + SelectionEvent(SelectionEvent::Move, 5), + SelectionEvent(SelectionEvent::Release), + SelectionEvent(SelectionEvent::Press, 3), + SelectionEvent(SelectionEvent::Move, 5)} + << QList{2, 3, 4, 5}; + + // Extended selection: Press selects a single item + QTest::addRow("Extended:Press") << QAbstractItemView::ExtendedSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 3)} + << QList{3}; + QTest::addRow("Extended:Press twice") << QAbstractItemView::ExtendedSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 3), + SelectionEvent(SelectionEvent::Press, 3)} + << QList{3}; + QTest::addRow("Extended:Press,Press") << QAbstractItemView::ExtendedSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 2), + SelectionEvent(SelectionEvent::Press, 3)} + << QList{3}; + // Extended selection: press with Ctrl toggles item + QTest::addRow("Extended:Press,Toggle") << QAbstractItemView::ExtendedSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 3), + SelectionEvent(SelectionEvent::Press, Qt::ControlModifier, 3)} + << QList<int>{}; + QTest::addRow("Extended:Press,Add") << QAbstractItemView::ExtendedSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1), + SelectionEvent(SelectionEvent::Press, Qt::ControlModifier, 3)} + << QList{1, 3}; + // Extended selection: Shift creates a range between first and last pressed + QTest::addRow("Extended:Press,Range") << QAbstractItemView::ExtendedSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1), + SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 5)} + << QList{1, 2, 3, 4, 5}; + QTest::addRow("Extended:Press,Range,Fix Range") << QAbstractItemView::ExtendedSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 1), + SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 5), + SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 3)} + << QList{1, 2, 3}; + // Extended: dragging extends the selection + QTest::addRow("Extended:Press,Drag") << QAbstractItemView::ExtendedSelection << false + << QList{SelectionEvent(SelectionEvent::Press, 2), + SelectionEvent(SelectionEvent::Move, 5)} + << QList{2, 3, 4, 5}; + // Extended: Ctrl+Press-dragging in a selection should not deselect #QTBUG-59888 + QTest::addRow("Extended:Ctrl-Drag selection") << QAbstractItemView::ExtendedSelection << true + << QList{SelectionEvent(SelectionEvent::Click, 2), + SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 5), + SelectionEvent(SelectionEvent::Press, Qt::ControlModifier, 3), + SelectionEvent(SelectionEvent::Move, Qt::ControlModifier, 5), + // two moves needed because of distance and state logic in QAbstractItemView + SelectionEvent(SelectionEvent::Move, Qt::ControlModifier, 6)} + << QList{2, 3, 4, 5}; +} + +void tst_QAbstractItemView::mouseSelection() +{ + QFETCH(QAbstractItemView::SelectionMode, selectionMode); + QFETCH(bool, dragEnabled); + QFETCH(QList<SelectionEvent>, selectionEvents); + QFETCH(QList<int>, selectedRows); + + QStandardItemModel model; + QStandardItem *parentItem = model.invisibleRootItem(); + for (int i = 0; i < 10; ++i) { + QStandardItem *item = new QStandardItem(QString("item %0").arg(i)); + item->setDragEnabled(dragEnabled); + item->setEditable(false); + parentItem->appendRow(item); + } + + std::unique_ptr<DragRecorder> dragRecorder(new DragRecorderView<QTreeView>); + QAbstractItemView *view = dragRecorder->view; + QVERIFY(view); + view->setModel(&model); + view->setDragEnabled(dragEnabled); + view->setSelectionMode(selectionMode); + view->show(); + QVERIFY(QTest::qWaitForWindowActive(view)); + + Qt::MouseButton buttonDown = Qt::NoButton; + int targetRow = -1; + QModelIndex pressedIndex; + for (const auto &event : qAsConst(selectionEvents)) { + if (event.row != -1) + targetRow = event.row; + const QModelIndex targetIndex = model.index(targetRow, 0); + const QPoint targetPoint = view->visualRect(targetIndex).center(); + switch (event.eventType) { + case SelectionEvent::Press: + if (buttonDown != Qt::NoButton) { + QTest::mouseRelease(view->viewport(), buttonDown, event.keyboardModifiers, + view->visualRect(pressedIndex).center()); + } + buttonDown = Qt::LeftButton; + pressedIndex = model.index(targetRow, 0); + QTest::mousePress(view->viewport(), buttonDown, event.keyboardModifiers, targetPoint); + break; + case SelectionEvent::Release: + QTest::mouseRelease(view->viewport(), buttonDown, event.keyboardModifiers, targetPoint); + buttonDown = Qt::NoButton; + pressedIndex = QModelIndex(); + break; + case SelectionEvent::Click: + QTest::mouseClick(view->viewport(), Qt::LeftButton, event.keyboardModifiers, targetPoint); + buttonDown = Qt::NoButton; + break; + case SelectionEvent::Move: { + QMouseEvent mouseMoveEvent(QEvent::MouseMove, targetPoint, + Qt::NoButton, buttonDown, event.keyboardModifiers); + QApplication::sendEvent(view->viewport(), &mouseMoveEvent); + } + break; + } + } + + QList<int> actualSelected; + const auto selectedIndexes = dragEnabled ? dragRecorder->draggedIndexes + : view->selectionModel()->selectedIndexes(); + for (auto index : selectedIndexes) + actualSelected << index.row(); + + QEXPECT_FAIL("Multi:Press-Drag selection", "QTBUG-59889", Continue); + QEXPECT_FAIL("Extended:Ctrl-Drag selection", "QTBUG-59889", Continue); + QCOMPARE(actualSelected, selectedRows); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" |