diff options
| author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2024-08-16 11:15:18 +0200 |
|---|---|---|
| committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-08-22 20:21:13 +0000 |
| commit | b45356c73299281b16831567dadcb61e7de064f4 (patch) | |
| tree | 4bac28111721a9857c9de1ca3a6bdb552a63e8c7 | |
| parent | 2ecfee540999aeedc44405ad0f172cddcccc6a45 (diff) | |
QQuickTableView: don't leave the viewport in an overshooting state after resize
If we need to change the extents of the Flickable (that is, which
point should be considered the top-left and bottom-right corner of
the contentItem inside the viewport), it can sometimes happen that
that Flickable is left suspended in an overshooting state (that
is, it looks as if the user dragged the contentItem out-of-bounds,
which will normally make it bounce back upon a release). And this
comes across as a bug.
This patch will therefore call returnToBounds() explicitly whenever
we change the extents (unless the contentItem is being dragged, as
we don't want to interrupt that).
As it stood, we would also call markExtentsDirty() far too often from
updateExtents(), even when the extents didn't change. Depending on
what Flickable does to handle dirty extents, this causes uneccessary
overhead and might slow down performance. It also produces a lot of
superfluous logging output in TableView.
This patch will therefore also check if the extents change before
calling markExtentsDirty() (and as such, avoid calling
returnToBounds() all the time).
Task-number: QTBUG-127809
Pick-to: 6.5 6.2
Change-Id: Id801f3e62b3dcde1b59d49e4efc9d6631d5672bb
Reviewed-by: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
(cherry picked from commit 523c53d33d0d40cf1b71991903a2192c05a926de)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 68a468980fe9831ad81fb382cf9d17a03236d4bb)
| -rw-r--r-- | src/quick/items/qquicktableview.cpp | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index ed0c0f6d39..a603baa923 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -2265,11 +2265,13 @@ void QQuickTableViewPrivate::updateExtents() const int nextTopRow = nextVisibleEdgeIndexAroundLoadedTable(Qt::TopEdge); const int nextBottomRow = nextVisibleEdgeIndexAroundLoadedTable(Qt::BottomEdge); + QPointF prevOrigin = origin; + QSizeF prevEndExtent = endExtent; + if (syncHorizontally) { const auto syncView_d = syncView->d_func(); origin.rx() = syncView_d->origin.x(); endExtent.rwidth() = syncView_d->endExtent.width(); - hData.markExtentsDirty(); } else if (nextLeftColumn == kEdgeIndexAtEnd) { // There are no more columns to load on the left side of the table. // In that case, we ensure that the origin match the beginning of the table. @@ -2286,7 +2288,6 @@ void QQuickTableViewPrivate::updateExtents() } } origin.rx() = loadedTableOuterRect.left(); - hData.markExtentsDirty(); } else if (loadedTableOuterRect.left() <= origin.x() + cellSpacing.width()) { // The table rect is at the origin, or outside, but we still have more // visible columns to the left. So we try to guesstimate how much space @@ -2296,7 +2297,6 @@ void QQuickTableViewPrivate::updateExtents() const qreal remainingSpacing = columnsRemaining * cellSpacing.width(); const qreal estimatedRemainingWidth = remainingColumnWidths + remainingSpacing; origin.rx() = loadedTableOuterRect.left() - estimatedRemainingWidth; - hData.markExtentsDirty(); } else if (nextRightColumn == kEdgeIndexAtEnd) { // There are no more columns to load on the right side of the table. // In that case, we ensure that the end of the content view match the end of the table. @@ -2314,7 +2314,6 @@ void QQuickTableViewPrivate::updateExtents() } } endExtent.rwidth() = loadedTableOuterRect.right() - q->contentWidth(); - hData.markExtentsDirty(); } else if (loadedTableOuterRect.right() >= q->contentWidth() + endExtent.width() - cellSpacing.width()) { // The right-most column is outside the end of the content view, and we // still have more visible columns in the model. This can happen if the application @@ -2325,14 +2324,12 @@ void QQuickTableViewPrivate::updateExtents() const qreal estimatedRemainingWidth = remainingColumnWidths + remainingSpacing; const qreal pixelsOutsideContentWidth = loadedTableOuterRect.right() - q->contentWidth(); endExtent.rwidth() = pixelsOutsideContentWidth + estimatedRemainingWidth; - hData.markExtentsDirty(); } if (syncVertically) { const auto syncView_d = syncView->d_func(); origin.ry() = syncView_d->origin.y(); endExtent.rheight() = syncView_d->endExtent.height(); - vData.markExtentsDirty(); } else if (nextTopRow == kEdgeIndexAtEnd) { // There are no more rows to load on the top side of the table. // In that case, we ensure that the origin match the beginning of the table. @@ -2349,7 +2346,6 @@ void QQuickTableViewPrivate::updateExtents() } } origin.ry() = loadedTableOuterRect.top(); - vData.markExtentsDirty(); } else if (loadedTableOuterRect.top() <= origin.y() + cellSpacing.height()) { // The table rect is at the origin, or outside, but we still have more // visible rows at the top. So we try to guesstimate how much space @@ -2359,7 +2355,6 @@ void QQuickTableViewPrivate::updateExtents() const qreal remainingSpacing = rowsRemaining * cellSpacing.height(); const qreal estimatedRemainingHeight = remainingRowHeights + remainingSpacing; origin.ry() = loadedTableOuterRect.top() - estimatedRemainingHeight; - vData.markExtentsDirty(); } else if (nextBottomRow == kEdgeIndexAtEnd) { // There are no more rows to load on the bottom side of the table. // In that case, we ensure that the end of the content view match the end of the table. @@ -2377,7 +2372,6 @@ void QQuickTableViewPrivate::updateExtents() } } endExtent.rheight() = loadedTableOuterRect.bottom() - q->contentHeight(); - vData.markExtentsDirty(); } else if (loadedTableOuterRect.bottom() >= q->contentHeight() + endExtent.height() - cellSpacing.height()) { // The bottom-most row is outside the end of the content view, and we // still have more visible rows in the model. This can happen if the application @@ -2388,7 +2382,6 @@ void QQuickTableViewPrivate::updateExtents() const qreal estimatedRemainingHeight = remainingRowHeigts + remainingSpacing; const qreal pixelsOutsideContentHeight = loadedTableOuterRect.bottom() - q->contentHeight(); endExtent.rheight() = pixelsOutsideContentHeight + estimatedRemainingHeight; - vData.markExtentsDirty(); } if (tableMovedHorizontally || tableMovedVertically) { @@ -2409,12 +2402,23 @@ void QQuickTableViewPrivate::updateExtents() } } - if (hData.minExtentDirty || vData.minExtentDirty) { - qCDebug(lcTableViewDelegateLifecycle) << "move origin and endExtent to:" << origin << endExtent; + if (prevOrigin != origin || prevEndExtent != endExtent) { + if (prevOrigin != origin) + qCDebug(lcTableViewDelegateLifecycle) << "move origin to:" << origin; + if (prevEndExtent != endExtent) + qCDebug(lcTableViewDelegateLifecycle) << "move endExtent to:" << endExtent; // updateBeginningEnd() will let the new extents take effect. This will also change the // visualArea of the flickable, which again will cause any attached scrollbars to adjust // the position of the handle. Note the latter will cause the viewport to move once more. + hData.markExtentsDirty(); + vData.markExtentsDirty(); updateBeginningEnd(); + if (!q->isMoving()) { + // When we adjust the extents, the viewport can sometimes be left suspended in an + // overshooted state. It will bounce back again once the user clicks inside the + // viewport. But this comes across as a bug, so returnToBounds explicitly. + q->returnToBounds(); + } } } |
