diff options
-rw-r--r-- | src/quick/items/qquicktableview.cpp | 122 | ||||
-rw-r--r-- | src/quick/items/qquicktableview_p.h | 13 | ||||
-rw-r--r-- | src/quick/items/qquicktableview_p_p.h | 2 | ||||
-rw-r--r-- | tests/auto/quick/qquicktableview/tst_qquicktableview.cpp | 48 |
4 files changed, 177 insertions, 8 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index c88311cc14..5c89394e62 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -355,6 +355,38 @@ */ /*! + \qmlproperty int QtQuick::TableView::leftColumn + + This property holds the leftmost column that is currently visible inside the view. + + \sa rightColumn, topRow, bottomRow +*/ + +/*! + \qmlproperty int QtQuick::TableView::rightColumn + + This property holds the rightmost column that is currently visible inside the view. + + \sa leftColumn, topRow, bottomRow +*/ + +/*! + \qmlproperty int QtQuick::TableView::topRow + + This property holds the topmost row that is currently visible inside the view. + + \sa leftColumn, rightColumn, bottomRow +*/ + +/*! + \qmlproperty int QtQuick::TableView::bottomRow + + This property holds the bottom-most row that is currently visible inside the view. + + \sa leftColumn, rightColumn, topRow +*/ + +/*! \qmlmethod QtQuick::TableView::positionViewAtCell(point cell, Qt.Alignment alignment, point offset) Positions \l contentX and \l contentY such that \a cell is at the position specified by @@ -1111,6 +1143,8 @@ void QQuickTableViewPrivate::forceLayout() void QQuickTableViewPrivate::syncLoadedTableFromLoadRequest() { + Q_Q(QQuickTableView); + if (loadRequest.edge() == Qt::Edge(0)) { // No edge means we're loading the top-left item loadedColumns.insert(loadRequest.column(), 0); @@ -1120,12 +1154,24 @@ void QQuickTableViewPrivate::syncLoadedTableFromLoadRequest() switch (loadRequest.edge()) { case Qt::LeftEdge: + loadedColumns.insert(loadRequest.column(), 0); + if (rebuildState == RebuildState::Done) + emit q->leftColumnChanged(); + break; case Qt::RightEdge: loadedColumns.insert(loadRequest.column(), 0); + if (rebuildState == RebuildState::Done) + emit q->rightColumnChanged(); break; case Qt::TopEdge: + loadedRows.insert(loadRequest.row(), 0); + if (rebuildState == RebuildState::Done) + emit q->topRowChanged(); + break; case Qt::BottomEdge: loadedRows.insert(loadRequest.row(), 0); + if (rebuildState == RebuildState::Done) + emit q->bottomRowChanged(); break; } } @@ -1776,6 +1822,9 @@ void QQuickTableViewPrivate::processRebuildTable() else Q_TABLEVIEW_UNREACHABLE(rebuildOptions); } + + edgesBeforeRebuild = loadedItems.isEmpty() ? QMargins() + : QMargins(q->leftColumn(), q->topRow(), q->rightColumn(), q->bottomRow()); } moveToNextRebuildState(); @@ -1833,11 +1882,23 @@ void QQuickTableViewPrivate::processRebuildTable() return; } + if (rebuildState == RebuildState::Done) { + if (edgesBeforeRebuild.left() != q->leftColumn()) + emit q->leftColumnChanged(); + if (edgesBeforeRebuild.right() != q->rightColumn()) + emit q->rightColumnChanged(); + if (edgesBeforeRebuild.top() != q->topRow()) + emit q->topRowChanged(); + if (edgesBeforeRebuild.bottom() != q->bottomRow()) + emit q->bottomRowChanged(); + + qCDebug(lcTableViewDelegateLifecycle()) << "current table:" << tableLayoutToString(); + qCDebug(lcTableViewDelegateLifecycle()) << "rebuild completed!"; + qCDebug(lcTableViewDelegateLifecycle()) << "################################################"; + qCDebug(lcTableViewDelegateLifecycle()); + } + Q_TABLEVIEW_ASSERT(rebuildState == RebuildState::Done, int(rebuildState)); - qCDebug(lcTableViewDelegateLifecycle()) << "current table:" << tableLayoutToString(); - qCDebug(lcTableViewDelegateLifecycle()) << "rebuild completed!"; - qCDebug(lcTableViewDelegateLifecycle()) << "################################################"; - qCDebug(lcTableViewDelegateLifecycle()); } bool QQuickTableViewPrivate::moveToNextRebuildState() @@ -2137,24 +2198,45 @@ void QQuickTableViewPrivate::adjustViewportYAccordingToAlignment() void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge) { + Q_Q(QQuickTableView); qCDebug(lcTableViewDelegateLifecycle) << edge; switch (edge) { - case Qt::LeftEdge: + case Qt::LeftEdge: { + const int column = leftColumn(); + for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r) + unloadItem(QPoint(column, r.key())); + loadedColumns.remove(column); + syncLoadedTableRectFromLoadedTable(); + if (rebuildState == RebuildState::Done) + emit q->leftColumnChanged(); + break; } case Qt::RightEdge: { - const int column = edge == Qt::LeftEdge ? leftColumn() : rightColumn(); + const int column = rightColumn(); for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r) unloadItem(QPoint(column, r.key())); loadedColumns.remove(column); syncLoadedTableRectFromLoadedTable(); + if (rebuildState == RebuildState::Done) + emit q->rightColumnChanged(); + break; } + case Qt::TopEdge: { + const int row = topRow(); + for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c) + unloadItem(QPoint(c.key(), row)); + loadedRows.remove(row); + syncLoadedTableRectFromLoadedTable(); + if (rebuildState == RebuildState::Done) + emit q->topRowChanged(); break; } - case Qt::TopEdge: case Qt::BottomEdge: { - const int row = edge == Qt::TopEdge ? topRow() : bottomRow(); + const int row = bottomRow(); for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c) unloadItem(QPoint(c.key(), row)); loadedRows.remove(row); syncLoadedTableRectFromLoadedTable(); + if (rebuildState == RebuildState::Done) + emit q->bottomRowChanged(); break; } } @@ -3088,6 +3170,30 @@ void QQuickTableView::setSyncDirection(Qt::Orientations direction) emit syncDirectionChanged(); } +int QQuickTableView::leftColumn() const +{ + Q_D(const QQuickTableView); + return d->loadedItems.isEmpty() ? -1 : d_func()->leftColumn(); +} + +int QQuickTableView::rightColumn() const +{ + Q_D(const QQuickTableView); + return d->loadedItems.isEmpty() ? -1 : d_func()->rightColumn(); +} + +int QQuickTableView::topRow() const +{ + Q_D(const QQuickTableView); + return d->loadedItems.isEmpty() ? -1 : d_func()->topRow(); +} + +int QQuickTableView::bottomRow() const +{ + Q_D(const QQuickTableView); + return d->loadedItems.isEmpty() ? -1 : d_func()->bottomRow(); +} + void QQuickTableView::positionViewAtCell(const QPoint &cell, Qt::Alignment alignment, const QPointF &offset) { positionViewAtRow(cell.y(), alignment & Qt::AlignVertical_Mask, offset.y()); diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h index 831bf20b0a..2682f4306d 100644 --- a/src/quick/items/qquicktableview_p.h +++ b/src/quick/items/qquicktableview_p.h @@ -81,6 +81,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTableView : public QQuickFlickable Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged) Q_PROPERTY(QQuickTableView *syncView READ syncView WRITE setSyncView NOTIFY syncViewChanged REVISION(2, 14)) Q_PROPERTY(Qt::Orientations syncDirection READ syncDirection WRITE setSyncDirection NOTIFY syncDirectionChanged REVISION(2, 14)) + Q_PROPERTY(int leftColumn READ leftColumn NOTIFY leftColumnChanged REVISION(6, 0)) + Q_PROPERTY(int rightColumn READ rightColumn NOTIFY rightColumnChanged REVISION(6, 0)) + Q_PROPERTY(int topRow READ topRow NOTIFY topRowChanged REVISION(6, 0)) + Q_PROPERTY(int bottomRow READ bottomRow NOTIFY bottomRowChanged REVISION(6, 0)) QML_NAMED_ELEMENT(TableView) QML_ADDED_IN_VERSION(2, 12) @@ -122,6 +126,11 @@ public: Qt::Orientations syncDirection() const; void setSyncDirection(Qt::Orientations direction); + int leftColumn() const; + int rightColumn() const; + int topRow() const; + int bottomRow() const; + Q_INVOKABLE void forceLayout(); Q_INVOKABLE void positionViewAtCell(const QPoint &cell, Qt::Alignment alignment, const QPointF &offset = QPointF()); Q_INVOKABLE void positionViewAtCell(int column, int row, Qt::Alignment alignment, const QPointF &offset = QPointF()); @@ -146,6 +155,10 @@ Q_SIGNALS: void reuseItemsChanged(); Q_REVISION(2, 14) void syncViewChanged(); Q_REVISION(2, 14) void syncDirectionChanged(); + Q_REVISION(6, 0) void leftColumnChanged(); + Q_REVISION(6, 0) void rightColumnChanged(); + Q_REVISION(6, 0) void topRowChanged(); + Q_REVISION(6, 0) void bottomRowChanged(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h index ab53a07dd0..876a175d87 100644 --- a/src/quick/items/qquicktableview_p_p.h +++ b/src/quick/items/qquicktableview_p_p.h @@ -321,6 +321,8 @@ public: Qt::Alignment positionViewAtRowAlignment = Qt::AlignTop; Qt::Alignment positionViewAtColumnAlignment = Qt::AlignLeft; + QMargins edgesBeforeRebuild; + const static QPoint kLeft; const static QPoint kRight; const static QPoint kUp; diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp index 414a76d1db..6e13044390 100644 --- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp +++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp @@ -186,6 +186,8 @@ private slots: void positionViewAtColumn(); void itemAtCell_data(); void itemAtCell(); + void leftRightTopBottomProperties_data(); + void leftRightTopBottomProperties(); }; tst_QQuickTableView::tst_QQuickTableView() @@ -3058,6 +3060,52 @@ void tst_QQuickTableView::itemAtCell() } } +void tst_QQuickTableView::leftRightTopBottomProperties_data() +{ + QTest::addColumn<QPointF>("contentStartPos"); + QTest::addColumn<QMargins>("expectedTable"); + QTest::addColumn<QMargins>("expectedSignalCount"); + + QTest::newRow("1") << QPointF(0, 0) << QMargins(0, 0, 5, 7) << QMargins(0, 0, 1, 1); + QTest::newRow("2") << QPointF(100, 50) << QMargins(1, 1, 6, 8) << QMargins(1, 1, 2, 2); + QTest::newRow("3") << QPointF(220, 120) << QMargins(2, 2, 8, 10) << QMargins(2, 2, 4, 4); + QTest::newRow("4") << QPointF(1000, 1000) << QMargins(9, 19, 15, 27) << QMargins(1, 1, 2, 2); +} + +void tst_QQuickTableView::leftRightTopBottomProperties() +{ + QFETCH(QPointF, contentStartPos); + QFETCH(QMargins, expectedTable); + QFETCH(QMargins, expectedSignalCount); + + LOAD_TABLEVIEW("plaintableview.qml"); + auto model = TestModelAsVariant(100, 100); + tableView->setModel(model); + + QSignalSpy leftSpy(tableView, &QQuickTableView::leftColumnChanged); + QSignalSpy rightSpy(tableView, &QQuickTableView::rightColumnChanged); + QSignalSpy topSpy(tableView, &QQuickTableView::topRowChanged); + QSignalSpy bottomSpy(tableView, &QQuickTableView::bottomRowChanged); + + WAIT_UNTIL_POLISHED; + + tableView->setContentX(contentStartPos.x()); + tableView->setContentY(contentStartPos.y()); + + tableView->polish(); + WAIT_UNTIL_POLISHED; + + QCOMPARE(tableView->leftColumn(), expectedTable.left()); + QCOMPARE(tableView->topRow(), expectedTable.top()); + QCOMPARE(tableView->rightColumn(), expectedTable.right()); + QCOMPARE(tableView->bottomRow(), expectedTable.bottom()); + + QCOMPARE(leftSpy.count(), expectedSignalCount.left()); + QCOMPARE(rightSpy.count(), expectedSignalCount.right()); + QCOMPARE(topSpy.count(), expectedSignalCount.top()); + QCOMPARE(bottomSpy.count(), expectedSignalCount.bottom()); +} + QTEST_MAIN(tst_QQuickTableView) #include "tst_qquicktableview.moc" |