aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2020-10-19 23:25:22 +0200
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2020-10-26 11:58:30 +0100
commit0135942bb3dffeed15aa78ca01f480575d85acef (patch)
tree5ebcf91ef193c4331f2abf7ddb3f47764979d0d5
parent2fe4bbd0aef2efb825802ad21a93c43323e1bb87 (diff)
TableView: ensure we rebuild the sync view, even when flicking on a sync view child
When two table views are connect through the syncView property, both views will flick when you flick on either of them. This also means that if you fast-flick more than a page on the sync view child, the sync view needs to rebuild, like if you did the fast-flick directly on the sync view. Because we updated the sync view's viewportRect too soon while fast-flicking on the the sync child, we didn't detect that it was a fast-flick, and that a rebuild was needed. The result is that you could sometimes end up with the views getting out-of-sync. This patch will allow TableView to only move the viewport without updating the internal viewportRect while flicking. The viewportRect will instead be sync-ed at a later point, like we do when you flick on the sync view directly. This will ensure that we rebuild if needed, also while fast-flicking on the child view. Task-number: QTBUG-87821 Change-Id: Ifc74473eb43406acaa8e24880066fb4ca89d3a4e Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> (cherry picked from commit b5501e9043cabcbf74d3d53b424ece5deb706a27)
-rw-r--r--src/quick/items/qquicktableview.cpp13
-rw-r--r--src/quick/items/qquicktableview_p_p.h1
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp37
3 files changed, 49 insertions, 2 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 3f5912e344..7b73fcb393 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -1886,6 +1886,8 @@ void QQuickTableViewPrivate::beginRebuildTable()
viewportRect.moveTop(syncView->d_func()->viewportRect.top());
}
+ syncViewportRect();
+
if (!model) {
qCDebug(lcTableViewDelegateLifecycle()) << "no model found, leaving table empty";
return;
@@ -2252,9 +2254,8 @@ void QQuickTableViewPrivate::syncWithPendingChanges()
// we're e.g in the middle of e.g loading a new row. Since this will lead to
// unpredicted behavior, and possibly a crash, we need to postpone taking
// such assignments into effect until we're in a state that allows it.
- Q_Q(QQuickTableView);
- viewportRect = QRectF(q->contentX(), q->contentY(), q->width(), q->height());
+ syncViewportRect();
syncModel();
syncDelegate();
syncSyncView();
@@ -2599,6 +2600,14 @@ void QQuickTableViewPrivate::setLocalViewportY(qreal contentY)
q->setContentY(contentY);
}
+void QQuickTableViewPrivate::syncViewportRect()
+{
+ // Sync viewportRect so that it contains the actual geometry of the viewport
+ Q_Q(QQuickTableView);
+ viewportRect = QRectF(q->contentX(), q->contentY(), q->width(), q->height());
+ qCDebug(lcTableViewDelegateLifecycle) << viewportRect;
+}
+
void QQuickTableViewPrivate::syncViewportPosRecursive()
{
Q_Q(QQuickTableView);
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index 6c5abcf414..403a77c3ea 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -433,6 +433,7 @@ public:
void scheduleRebuildIfFastFlick();
void setLocalViewportX(qreal contentX);
void setLocalViewportY(qreal contentY);
+ void syncViewportRect();
void syncViewportPosRecursive();
void fetchMoreData();
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 6339e5a59d..54f73c6e0c 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -175,6 +175,7 @@ private slots:
void checkSyncView_differentSizedModels();
void checkSyncView_connect_late_data();
void checkSyncView_connect_late();
+ void checkSyncView_pageFlicking();
void delegateWithRequiredProperties();
void checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable();
void replaceModel();
@@ -2694,6 +2695,42 @@ void tst_QQuickTableView::checkSyncView_connect_late()
QCOMPARE(tableViewHVPrivate->loadedTableOuterRect, tableViewPrivate->loadedTableOuterRect);
}
+void tst_QQuickTableView::checkSyncView_pageFlicking()
+{
+ // Check that we rebuild the syncView (instead of refilling
+ // edges), if the sync child moves more than a page (the size of TableView).
+ // The point is that it shouldn't matter if you fast-flick the
+ // sync view itself, or a sync child. Either way, the sync view
+ // needs to rebuild. This, in turn, will eventually rebuild the
+ // sync children as well when they sync up later.
+ LOAD_TABLEVIEW("syncviewsimple.qml");
+ GET_QML_TABLEVIEW(tableViewH);
+ GET_QML_TABLEVIEW(tableViewV);
+ GET_QML_TABLEVIEW(tableViewHV);
+ QQuickTableView *views[] = {tableViewH, tableViewV, tableViewHV};
+
+ auto model = TestModelAsVariant(100, 100);
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Move the viewport more than a "page"
+ tableViewHV->setContentX(tableViewHV->width() * 2);
+
+ QVERIFY(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::ViewportOnly);
+ QVERIFY(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn);
+ QVERIFY(!(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow));
+
+ WAIT_UNTIL_POLISHED;
+
+ tableViewHV->setContentY(tableViewHV->height() * 2);
+
+ QVERIFY(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::ViewportOnly);
+ QVERIFY(!(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn));
+ QVERIFY(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow);
+}
+
void tst_QQuickTableView::checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable()
{
LOAD_TABLEVIEW("plaintableview.qml");