aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2024-08-16 11:15:18 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-08-22 20:21:13 +0000
commitb45356c73299281b16831567dadcb61e7de064f4 (patch)
tree4bac28111721a9857c9de1ca3a6bdb552a63e8c7
parent2ecfee540999aeedc44405ad0f172cddcccc6a45 (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.cpp28
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();
+ }
}
}