aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquicktableview
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2021-05-14 12:14:03 +0200
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2021-06-03 10:30:53 +0200
commit87b6def42a4341a4c6ac697458dd06836818b43b (patch)
tree5e4596145e654f23ea37e122ce5954d03b776ad0 /tests/auto/quick/qquicktableview
parentd1313feb83b52e58d1a0a4f51fd58668ff99c575 (diff)
Selection support: make TableView selectable
Let QQuickTableView implement the QQuickSelectable interface. The functions implemented from the interface will be used by a SelectionRectangle in Controls to enable selecting cells in the table visually using pointer drag and selection handles. Change-Id: I6e87ffdc63a97a9dd83b8279fa08762772ce4e03 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'tests/auto/quick/qquicktableview')
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml4
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp197
2 files changed, 199 insertions, 2 deletions
diff --git a/tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml b/tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml
index efa0befaf5..9972d34d44 100644
--- a/tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml
+++ b/tests/auto/quick/qquicktableview/data/tableviewwithselected1.qml
@@ -62,8 +62,8 @@ Item {
id: tableViewDelegate
Rectangle {
objectName: "tableViewDelegate"
- implicitWidth: 100
- implicitHeight: 100
+ implicitWidth: 20
+ implicitHeight: 20
required property bool selected
color: selected ? "lightgray" : "green"
}
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index dece7e53d9..340c44fdb5 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -202,6 +202,10 @@ private slots:
void checkSelectionModelWithRequiredSelectedProperty();
void checkSelectionModelWithUnrequiredSelectedProperty();
void removeAndAddSelectionModel();
+ void testSelectableStartPosEndPos_data();
+ void testSelectableStartPosEndPos();
+ void testSelectableStartPosEndPosOutsideView();
+ void testSelectableScrollTowardsPos();
};
tst_QQuickTableView::tst_QQuickTableView()
@@ -3566,6 +3570,199 @@ void tst_QQuickTableView::removeAndAddSelectionModel()
QCOMPARE(selected, true);
}
+void tst_QQuickTableView::testSelectableStartPosEndPos_data()
+{
+ QTest::addColumn<QPoint>("endCellDist");
+
+ QTest::newRow("single cell") << QPoint(0, 0);
+
+ QTest::newRow("left to right") << QPoint(1, 0);
+ QTest::newRow("left to right") << QPoint(2, 0);
+ QTest::newRow("right to left") << QPoint(-1, 0);
+ QTest::newRow("right to left") << QPoint(-2, 0);
+
+ QTest::newRow("top to bottom") << QPoint(0, 1);
+ QTest::newRow("top to bottom") << QPoint(0, 2);
+ QTest::newRow("bottom to top") << QPoint(0, -1);
+ QTest::newRow("bottom to top") << QPoint(0, -2);
+
+ QTest::newRow("diagonal top left to bottom right") << QPoint(1, 1);
+ QTest::newRow("diagonal top left to bottom right") << QPoint(2, 2);
+ QTest::newRow("diagonal bottom left to top right") << QPoint(-1, -1);
+ QTest::newRow("diagonal bottom left to top right") << QPoint(-2, -2);
+ QTest::newRow("diagonal top right to bottom left") << QPoint(-1, 1);
+ QTest::newRow("diagonal top right to bottom left") << QPoint(-2, 2);
+ QTest::newRow("diagonal bottom right to top left") << QPoint(1, -1);
+ QTest::newRow("diagonal bottom right to top left") << QPoint(2, -2);
+}
+
+void tst_QQuickTableView::testSelectableStartPosEndPos()
+{
+ // Check that the TableView implement QQuickSelectableInterface setSelectionStartPos, setSelectionEndPos
+ // and clearSelection correctly. Do this by calling setSelectionStartPos/setSelectionEndPos on top of
+ // different cells, and see that we end up with the expected selections.
+ QFETCH(QPoint, endCellDist);
+ LOAD_TABLEVIEW("tableviewwithselected1.qml");
+
+ TestModel model(10, 10);
+ QItemSelectionModel selectionModel(&model);
+
+ tableView->setModel(QVariant::fromValue(&model));
+ tableView->setSelectionModel(&selectionModel);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(selectionModel.hasSelection(), false);
+
+ const QPoint startCell(5, 5);
+ const QPoint endCell = startCell + endCellDist;
+ const QPoint endCellWrapped = startCell - endCellDist;
+
+ const QQuickItem *startItem = tableView->itemAtCell(startCell);
+ const QQuickItem *endItem = tableView->itemAtCell(endCell);
+ const QQuickItem *endItemWrapped = tableView->itemAtCell(endCellWrapped);
+ QVERIFY(startItem);
+ QVERIFY(endItem);
+ QVERIFY(endItemWrapped);
+
+ const QPointF startPos(startItem->x(), startItem->y());
+ const QPointF endPos(endItem->x(), endItem->y());
+ const QPointF endPosWrapped(endItemWrapped->x(), endItemWrapped->y());
+
+ tableViewPrivate->setSelectionStartPos(startPos);
+ tableViewPrivate->setSelectionEndPos(endPos);
+
+ QCOMPARE(selectionModel.hasSelection(), true);
+
+ const int x1 = qMin(startCell.x(), endCell.x());
+ const int x2 = qMax(startCell.x(), endCell.x());
+ const int y1 = qMin(startCell.y(), endCell.y());
+ const int y2 = qMax(startCell.y(), endCell.y());
+
+ for (int x = x1; x < x2; ++x) {
+ for (int y = y1; y < y2; ++y) {
+ const auto index = model.index(y, x);
+ QVERIFY(selectionModel.isSelected(index));
+ }
+ }
+
+ const int expectedCount = (x2 - x1 + 1) * (y2 - y1 + 1);
+ const int actualCount = selectionModel.selectedIndexes().count();
+ QCOMPARE(actualCount, expectedCount);
+
+ // Wrap the selection
+ tableViewPrivate->setSelectionEndPos(endPosWrapped);
+
+ for (int x = x2; x < x1; ++x) {
+ for (int y = y2; y < y1; ++y) {
+ const auto index = model.index(y, x);
+ QVERIFY(selectionModel.isSelected(index));
+ }
+ }
+
+ const int actualCountAfterWrap = selectionModel.selectedIndexes().count();
+ QCOMPARE(actualCountAfterWrap, expectedCount);
+
+ tableViewPrivate->clearSelection();
+ QCOMPARE(selectionModel.hasSelection(), false);
+}
+
+void tst_QQuickTableView::testSelectableStartPosEndPosOutsideView()
+{
+ // Call setSelectionStartPos and setSelectionEndPos with positions outside the view.
+ // This should first of all not crash, but instead just clamp the selection to the
+ // cells that are visible inside the view.
+ LOAD_TABLEVIEW("tableviewwithselected1.qml");
+
+ TestModel model(10, 10);
+ QItemSelectionModel selectionModel(&model);
+
+ tableView->setModel(QVariant::fromValue(&model));
+ tableView->setSelectionModel(&selectionModel);
+
+ WAIT_UNTIL_POLISHED;
+
+ const QPoint centerCell(5, 5);
+ const QQuickItem *centerItem = tableView->itemAtCell(centerCell);
+ QVERIFY(centerItem);
+
+ const QPointF centerPos(centerItem->x(), centerItem->y());
+ const QPointF outsideLeft(-100, centerPos.y());
+ const QPointF outsideRight(tableView->width() + 100, centerPos.y());
+ const QPointF outsideTop(centerPos.x(), -100);
+ const QPointF outsideBottom(centerPos.x(), tableView->height() + 100);
+
+ tableViewPrivate->setSelectionStartPos(centerPos);
+
+ tableViewPrivate->setSelectionEndPos(outsideLeft);
+ for (int x = 0; x <= centerCell.x(); ++x) {
+ const auto index = model.index(centerCell.y(), x);
+ QVERIFY(selectionModel.isSelected(index));
+ }
+
+ tableViewPrivate->setSelectionEndPos(outsideRight);
+ for (int x = centerCell.x(); x < model.columnCount(); ++x) {
+ const auto index = model.index(centerCell.y(), x);
+ QVERIFY(selectionModel.isSelected(index));
+ }
+
+ tableViewPrivate->setSelectionEndPos(outsideTop);
+ for (int y = 0; y <= centerCell.y(); ++y) {
+ const auto index = model.index(y, centerCell.x());
+ QVERIFY(selectionModel.isSelected(index));
+ }
+
+ tableViewPrivate->setSelectionEndPos(outsideBottom);
+ for (int y = centerCell.y(); y < model.rowCount(); ++y) {
+ const auto index = model.index(y, centerCell.x());
+ QVERIFY(selectionModel.isSelected(index));
+ }
+}
+
+void tst_QQuickTableView::testSelectableScrollTowardsPos()
+{
+ // Check that TableView will implement the scrollTowardsSelectionPoint function
+ // correctly, and move the content item towards the given position
+ LOAD_TABLEVIEW("tableviewwithselected1.qml");
+
+ TestModel model(200, 200);
+ QItemSelectionModel selectionModel(&model);
+
+ tableView->setModel(QVariant::fromValue(&model));
+ tableView->setSelectionModel(&selectionModel);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->contentX(), 0);
+ QCOMPARE(tableView->contentY(), 0);
+
+ const QSizeF step(1, 1);
+ const QPointF topLeft(-100, -100);
+ const QPointF topRight(tableView->width() + 100, -100);
+ const QPointF bottomLeft(-100, tableView->height() + 100);
+ const QPointF bottomRight(tableView->width() + 100, tableView->height() + 100);
+
+ tableViewPrivate->scrollTowardsSelectionPoint(topRight, step);
+ QCOMPARE(tableView->contentX(), step.width());
+ QCOMPARE(tableView->contentY(), 0);
+
+ tableViewPrivate->scrollTowardsSelectionPoint(bottomRight, step);
+ QCOMPARE(tableView->contentX(), step.width() * 2);
+ QCOMPARE(tableView->contentY(), step.height());
+
+ tableViewPrivate->scrollTowardsSelectionPoint(bottomLeft, step);
+ QCOMPARE(tableView->contentX(), step.width());
+ QCOMPARE(tableView->contentY(), step.height() * 2);
+
+ tableViewPrivate->scrollTowardsSelectionPoint(topLeft, step);
+ QCOMPARE(tableView->contentX(), 0);
+ QCOMPARE(tableView->contentY(), step.height());
+
+ tableViewPrivate->scrollTowardsSelectionPoint(topLeft, step);
+ QCOMPARE(tableView->contentX(), 0);
+ QCOMPARE(tableView->contentY(), 0);
+}
+
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"