From 6c56852fd1f044792df9c91b29c219ff022857ca Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 28 Feb 2022 13:44:47 +0100 Subject: QQuickTableView: change cellAtPos() so that any loaded cell is found The current implementation would only find cells that were inside the bounding rect of the view. By changing the function so that it also find cells that are halfway outside the view (as long as they are loaded), it becomes useful also for implementing selection support (finding cells under the current selection, even those cells that are halfway outside the viewport). Task-number: QTBUG-100696 Change-Id: Ie54dc9b8773e7295ead0c9644dbbc5052b8e40fc Reviewed-by: Shawn Rutledge --- src/quick/items/qquicktableview.cpp | 24 +++++---- .../quick/qquicktableview/tst_qquicktableview.cpp | 58 ++++++++++++++-------- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index e5a4eae4ce..ff3ef6638d 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -556,8 +556,8 @@ /*! \qmlmethod Point QtQuick::TableView::cellAtPos(point position, bool includeSpacing) - Returns the cell at the given \a position in the view. If no cell intersects with - \a position, the return value will be \c point(-1, -1). + Returns the cell at the given \a position in the view. If no \l {isRowLoaded()}{loaded} + cell intersects with \a position, the return value will be \c point(-1, -1). If \a includeSpacing is set to \c true, a cell's bounding box will be considered to include half the adjacent \l rowSpacing and \l columnSpacing on each side. The @@ -4014,27 +4014,29 @@ QPoint QQuickTableView::cellAtPos(const QPointF &position, bool includeSpacing) { Q_D(const QQuickTableView); - if (!boundingRect().contains(position)) + const QPointF localPos = mapToItem(d->contentItem, position); + if (!d->loadedTableOuterRect.contains(localPos)) return QPoint(-1, -1); const qreal hSpace = d->cellSpacing.width(); const qreal vSpace = d->cellSpacing.height(); - qreal currentColumnEnd = d->loadedTableOuterRect.x() - contentX(); - qreal currentRowEnd = d->loadedTableOuterRect.y() - contentY(); + qreal currentColumnEnd = d->loadedTableOuterRect.x(); + qreal currentRowEnd = d->loadedTableOuterRect.y(); + int foundColumn = -1; int foundRow = -1; for (const int column : d->loadedColumns) { currentColumnEnd += d->getEffectiveColumnWidth(column); - if (position.x() < currentColumnEnd) { + if (localPos.x() < currentColumnEnd) { foundColumn = column; break; } currentColumnEnd += hSpace; - if (!includeSpacing && position.x() < currentColumnEnd) { + if (!includeSpacing && localPos.x() < currentColumnEnd) { // Hit spacing return QPoint(-1, -1); - } else if (includeSpacing && position.x() < currentColumnEnd - (hSpace / 2)) { + } else if (includeSpacing && localPos.x() < currentColumnEnd - (hSpace / 2)) { foundColumn = column; break; } @@ -4042,16 +4044,16 @@ QPoint QQuickTableView::cellAtPos(const QPointF &position, bool includeSpacing) for (const int row : d->loadedRows) { currentRowEnd += d->getEffectiveRowHeight(row); - if (position.y() < currentRowEnd) { + if (localPos.y() < currentRowEnd) { foundRow = row; break; } currentRowEnd += vSpace; - if (!includeSpacing && position.y() < currentRowEnd) { + if (!includeSpacing && localPos.y() < currentRowEnd) { // Hit spacing return QPoint(-1, -1); } - if (includeSpacing && position.y() < currentRowEnd - (vSpace / 2)) { + if (includeSpacing && localPos.y() < currentRowEnd - (vSpace / 2)) { foundRow = row; break; } diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp index c6eda28529..cdcd704f98 100644 --- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp +++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp @@ -3070,9 +3070,10 @@ void tst_QQuickTableView::replaceModel() void tst_QQuickTableView::cellAtPos_data() { QTest::addColumn("contentStartPos"); - QTest::addColumn("position"); + QTest::addColumn("localPos"); QTest::addColumn("includeSpacing"); QTest::addColumn("expectedCell"); + QTest::addColumn("margins"); const int spacing = 10; const QPointF cellSize(100, 50); @@ -3085,49 +3086,62 @@ void tst_QQuickTableView::cellAtPos_data() return QPointF(x, y); }; - QTest::newRow("1") << QPointF(0, 0) << cellStart(0, 0) << false << QPoint(0, 0); - QTest::newRow("2") << QPointF(0, 0) << cellStart(1, 0) << false << QPoint(1, 0); - QTest::newRow("3") << QPointF(0, 0) << cellStart(0, 1) << false << QPoint(0, 1); - QTest::newRow("4") << QPointF(0, 0) << cellStart(1, 1) << false << QPoint(1, 1); + QTest::newRow("1") << QPointF(0, 0) << cellStart(0, 0) << false << QPoint(0, 0) << QSizeF(0, 0); + QTest::newRow("2") << QPointF(0, 0) << cellStart(1, 0) << false << QPoint(1, 0) << QSizeF(0, 0); + QTest::newRow("3") << QPointF(0, 0) << cellStart(0, 1) << false << QPoint(0, 1) << QSizeF(0, 0); + QTest::newRow("4") << QPointF(0, 0) << cellStart(1, 1) << false << QPoint(1, 1) << QSizeF(0, 0); - QTest::newRow("5") << QPointF(0, 0) << cellStart(1, 1) - quadSpace << false << QPoint(-1, -1); - QTest::newRow("6") << QPointF(0, 0) << cellStart(0, 0) + cellSize + quadSpace << false << QPoint(-1, -1); - QTest::newRow("7") << QPointF(0, 0) << cellStart(0, 1) + cellSize + quadSpace << false << QPoint(-1, -1); + QTest::newRow("5") << QPointF(0, 0) << cellStart(1, 1) - quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0); + QTest::newRow("6") << QPointF(0, 0) << cellStart(0, 0) + cellSize + quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0); + QTest::newRow("7") << QPointF(0, 0) << cellStart(0, 1) + cellSize + quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0); - QTest::newRow("8") << QPointF(0, 0) << cellStart(1, 1) - quadSpace << true << QPoint(1, 1); - QTest::newRow("9") << QPointF(0, 0) << cellStart(0, 0) + cellSize + quadSpace << true << QPoint(0, 0); - QTest::newRow("10") << QPointF(0, 0) << cellStart(0, 1) + cellSize + quadSpace << true << QPoint(0, 1); + QTest::newRow("8") << QPointF(0, 0) << cellStart(1, 1) - quadSpace << true << QPoint(1, 1) << QSizeF(0, 0); + QTest::newRow("9") << QPointF(0, 0) << cellStart(0, 0) + cellSize + quadSpace << true << QPoint(0, 0) << QSizeF(0, 0); + QTest::newRow("10") << QPointF(0, 0) << cellStart(0, 1) + cellSize + quadSpace << true << QPoint(0, 1) << QSizeF(0, 0); - QTest::newRow("11") << cellStart(50, 50) << cellStart(0, 0) << false << QPoint(50, 50); - QTest::newRow("12") << cellStart(50, 50) << cellStart(4, 4) << false << QPoint(54, 54); - QTest::newRow("13") << cellStart(50, 50) << cellStart(4, 4) - quadSpace << false << QPoint(-1, -1); - QTest::newRow("14") << cellStart(50, 50) << cellStart(4, 4) + cellSize + quadSpace << false << QPoint(-1, -1); - QTest::newRow("15") << cellStart(50, 50) << cellStart(4, 4) - quadSpace << true << QPoint(54, 54); - QTest::newRow("16") << cellStart(50, 50) << cellStart(4, 4) + cellSize + quadSpace << true << QPoint(54, 54); + QTest::newRow("11") << cellStart(50, 50) << cellStart(50, 50) << false << QPoint(50, 50) << QSizeF(0, 0); + QTest::newRow("12") << cellStart(50, 50) << cellStart(54, 54) << false << QPoint(54, 54) << QSizeF(0, 0); + QTest::newRow("13") << cellStart(50, 50) << cellStart(54, 54) - quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0); + QTest::newRow("14") << cellStart(50, 50) << cellStart(54, 54) + cellSize + quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0); + QTest::newRow("15") << cellStart(50, 50) << cellStart(54, 54) - quadSpace << true << QPoint(54, 54) << QSizeF(0, 0); + QTest::newRow("16") << cellStart(50, 50) << cellStart(54, 54) + cellSize + quadSpace << true << QPoint(54, 54) << QSizeF(0, 0); - QTest::newRow("17") << cellStart(50, 50) + halfCell << cellStart(0, 0) << false << QPoint(50, 50); - QTest::newRow("18") << cellStart(50, 50) + halfCell << cellStart(1, 1) << false << QPoint(51, 51); - QTest::newRow("19") << cellStart(50, 50) + halfCell << cellStart(4, 4) << false << QPoint(54, 54); + QTest::newRow("17") << cellStart(50, 50) + halfCell << cellStart(50, 50) << false << QPoint(50, 50) << QSizeF(0, 0); + QTest::newRow("18") << cellStart(50, 50) + halfCell << cellStart(51, 51) << false << QPoint(51, 51) << QSizeF(0, 0); + QTest::newRow("19") << cellStart(50, 50) + halfCell << cellStart(54, 54) << false << QPoint(54, 54) << QSizeF(0, 0); + + QTest::newRow("20") << QPointF(0, 0) << cellStart(0, 0) << false << QPoint(0, 0) << QSizeF(150, 150); + QTest::newRow("20") << QPointF(0, 0) << cellStart(5, 5) << false << QPoint(5, 5) << QSizeF(150, 150); + + QTest::newRow("20") << QPointF(-150, -150) << cellStart(0, 0) << false << QPoint(0, 0) << QSizeF(150, 150); + QTest::newRow("21") << QPointF(-150, -150) << cellStart(4, 0) + halfCell << false << QPoint(4, 0) << QSizeF(150, 150); + QTest::newRow("22") << QPointF(-150, -150) << cellStart(0, 4) + halfCell << false << QPoint(0, 4) << QSizeF(150, 150); + QTest::newRow("23") << QPointF(-150, -150) << cellStart(4, 4) + halfCell << false << QPoint(4, 4) << QSizeF(150, 150); } void tst_QQuickTableView::cellAtPos() { QFETCH(QPointF, contentStartPos); - QFETCH(QPointF, position); + QFETCH(QPointF, localPos); QFETCH(bool, includeSpacing); QFETCH(QPoint, expectedCell); + QFETCH(QSizeF, margins); LOAD_TABLEVIEW("plaintableview.qml"); auto model = TestModelAsVariant(100, 100); tableView->setModel(model); tableView->setRowSpacing(10); tableView->setColumnSpacing(10); + tableView->setLeftMargin(margins.width()); + tableView->setLeftMargin(margins.height()); + tableView->setTopMargin(margins.height()); tableView->setContentX(contentStartPos.x()); tableView->setContentY(contentStartPos.y()); WAIT_UNTIL_POLISHED; - QPoint cell = tableView->cellAtPos(position, includeSpacing); + const QPointF posInView = tableView->mapFromItem(tableView->contentItem(), localPos); + QPoint cell = tableView->cellAtPos(posInView, includeSpacing); QCOMPARE(cell, expectedCell); } -- cgit v1.2.3