aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquicktableview.cpp
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2023-11-06 14:06:43 +0100
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2023-11-09 13:08:05 +0100
commitbff7aca8695e4cacc252d0235dc70cf3a46c032e (patch)
tree5343d8e1fe2b13ee67c53a091a053ef0be6e86ac /src/quick/items/qquicktableview.cpp
parent425c65a27b1c712226697bed8709705b9914cc8a (diff)
TableView: don't emit rows and columns changed while rebuilding
We should be careful about emitting signals while we do a rebuild. The reason is that the application might listen to those signals and change Flickable properties (especially contentX/Y) behind TableView's back. A bug is seen from this if the application is setting a very large contentY upon receiving rowsChanged(). In that case TableView will not detect that it should do a "fast-flick" directly to the new contentY, but instead start to loadAndUnloadVisibleEdges() until it reaches the current viewport. And this can take a really long time, and therefore block the UI. This patch will wait to emit rows/columnsChanged until we're done rebuilding. At that point, it's safe to change properties such as contentX/Y from the application. The main usecase this patch is solving, is to be able to always position the viewport on the last row as new rows are added to the model. This can now be done by listening to onRowsChanged or onContentHeightChanged, and position the viewport at the end. The included auto test will therefore test this exact use case. Pick-to: 6.6 6.5 6.2 Fixes: QTBUG-118897 Change-Id: I6124fbd0e7097a2bbb89c887fe594c3028726aa7 Reviewed-by: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
Diffstat (limited to 'src/quick/items/qquicktableview.cpp')
-rw-r--r--src/quick/items/qquicktableview.cpp22
1 files changed, 6 insertions, 16 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 8376e092af..5c1355de9c 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -2773,21 +2773,6 @@ qreal QQuickTableViewPrivate::sizeHintForRow(int row) const
return rowHeight;
}
-void QQuickTableViewPrivate::updateTableSize()
-{
- // tableSize is the same as row and column count, and will always
- // be the same as the number of rows and columns in the model.
- Q_Q(QQuickTableView);
-
- const QSize prevTableSize = tableSize;
- tableSize = calculateTableSize();
-
- if (prevTableSize.width() != tableSize.width())
- emit q->columnsChanged();
- if (prevTableSize.height() != tableSize.height())
- emit q->rowsChanged();
-}
-
QSize QQuickTableViewPrivate::calculateTableSize()
{
QSize size(0, 0);
@@ -3330,6 +3315,7 @@ void QQuickTableViewPrivate::processRebuildTable()
Q_TABLEVIEW_UNREACHABLE(rebuildOptions);
}
+ tableSizeBeforeRebuild = tableSize;
edgesBeforeRebuild = loadedItems.isEmpty() ? QMargins()
: QMargins(q->leftColumn(), q->topRow(), q->rightColumn(), q->bottomRow());
}
@@ -3398,6 +3384,10 @@ void QQuickTableViewPrivate::processRebuildTable()
}
if (rebuildState == RebuildState::Done) {
+ if (tableSizeBeforeRebuild.width() != tableSize.width())
+ emit q->columnsChanged();
+ if (tableSizeBeforeRebuild.height() != tableSize.height())
+ emit q->rowsChanged();
if (edgesBeforeRebuild.left() != q->leftColumn())
emit q->leftColumnChanged();
if (edgesBeforeRebuild.right() != q->rightColumn())
@@ -3547,7 +3537,7 @@ void QQuickTableViewPrivate::calculateTopLeft(QPoint &topLeftCell, QPointF &topL
void QQuickTableViewPrivate::loadInitialTable()
{
- updateTableSize();
+ tableSize = calculateTableSize();
if (positionXAnimation.isRunning()) {
positionXAnimation.stop();