aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickgridview.cpp
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-05-06 15:05:59 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2022-05-10 11:24:30 +0000
commitd0d6f70c91b1463e9f5b7a25d4e391cffb4fa5af (patch)
treebba4f771f310e03130ed4d35a04188e10a1d44e4 /src/quick/items/qquickgridview.cpp
parent7ea4e48b69326b9092f4e0724a7f1e2a6a16d8df (diff)
QQuickGridView: return accurate row position when no rows are available
QQuickGridViewPrivate::rowPosAt() returns the position of a row for a given index. At start-up, when no rows are yet loaded, a plain "(modelIndex / columns) * rowSize()" fallback calculation is sufficient. But as the user flicks around, and new rows are moving into the viewport, the current logic shifts to rely on the position of an already visible row to calculate the position of a new one. This is because the fallback calculation above will assume that row 0 always starts at contentY == 0, which is not always true for GridView - sometimes it will place rows outside the content item to make room for rows that were added after start-up. Likewise, if the cellWidth/Height changes, it might force existing rows to be placed outside the content item. So using an already loaded row as a reference becomes more accurate, especially when flicking slowly. The problem is that the fallback calculation is not only used at start-up. It's also used when e.g moving the content item a long distance in one go by e.g setting contentY directly, call positionViewAtBeginning(), or scroll using a ScrollBar. In that case, there will be no existing rows to rely on, since they have all been moved out of the viewport. Instead the error prone fallback calculation will be used. This patch will therefore adjust the fallback calculation to take all the necessary information into account, so that rowAtPos() returns the right position of a row, even when no rows are available as a reference. This will fix at least two bugs that happen because row 0 actually starts at a negative contentY, rather than at contentY == 0. Fixes: QTBUG-91461 Fixes: QTBUG-92868 Pick-to: 6.3 6.2 Change-Id: I21be6846809ddedf3dba0c3212693e8063411166 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quick/items/qquickgridview.cpp')
-rw-r--r--src/quick/items/qquickgridview.cpp22
1 files changed, 20 insertions, 2 deletions
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index b26a349a58..3d4d377d79 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -349,9 +349,27 @@ qreal QQuickGridViewPrivate::rowPosAt(int modelIndex) const
return lastItem->rowPos() + rows * rowSize();
}
}
- return (modelIndex / columns) * rowSize();
-}
+ qreal rowPos = ((modelIndex / columns) * rowSize());
+
+ if (flow == QQuickGridView::FlowLeftToRight && verticalLayoutDirection == QQuickItemView::TopToBottom) {
+ // Add the effective startpos of row 0. Start by subtracting minExtent, which will contain the
+ // height of the rows outside the beginning of the content item. (Rows can end up outside if
+ // e.g flicking the viewport a long way down, changing cellSize, and then flick back).
+ // NOTE: It's not clearly understood why the flow == QQuickGridView::FlowLeftToRight guard is
+ // needed, since the flow shouldn't normally affect the y postition of an index. But without
+ // it, several auto tests start failing, so we keep it until this part is better understood.
+ rowPos -= minExtent;
+ // minExtent will also contain the size of the topMargin (vData.startMargin), the header, and
+ // the highlightRangeStart. Those should be added before the start of row 0. So we need to subtract
+ // them from the rowPos. But only the largest of topMargin and highlightRangeStart will need
+ // to be taken into account, since having a topMargin will also ensure that currentItem ends
+ // up within the requested highlight range when view is positioned at the beginning.
+ rowPos += qMax(vData.startMargin, highlightRangeStart) + headerSize();
+ }
+
+ return rowPos;
+}
qreal QQuickGridViewPrivate::snapPosAt(qreal pos) const
{