aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquicktableview.cpp233
-rw-r--r--src/quick/items/qquicktableview_p.h5
-rw-r--r--src/quick/items/qquicktableview_p_p.h5
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp161
4 files changed, 365 insertions, 39 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index af4373317b..2b49200eaa 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -665,50 +665,179 @@ void QQuickTableViewPrivate::updateContentHeight()
q->QQuickFlickable::setContentHeight(estimatedHeight);
}
-void QQuickTableViewPrivate::enforceTableAtOrigin()
-{
- // Gaps before the first row/column can happen if rows/columns
- // changes size while flicking e.g because of spacing changes or
- // changes to a column maxWidth/row maxHeight. Check for this, and
- // move the whole table rect accordingly.
- bool layoutNeeded = false;
- const qreal flickMargin = 50;
-
- const bool noMoreColumns = nextVisibleEdgeIndexAroundLoadedTable(Qt::LeftEdge) == kEdgeIndexAtEnd;
- const bool noMoreRows = nextVisibleEdgeIndexAroundLoadedTable(Qt::TopEdge) == kEdgeIndexAtEnd;
-
- if (noMoreColumns) {
- if (!qFuzzyIsNull(loadedTableOuterRect.left())) {
- // There are no more columns, but the table rect
- // is not at origin. So we move it there.
- loadedTableOuterRect.moveLeft(0);
- layoutNeeded = true;
+void QQuickTableViewPrivate::updateExtents()
+{
+ // When rows or columns outside the viewport are removed or added, or a rebuild
+ // forces us to guesstimate a new top-left, the edges of the table might end up
+ // out of sync with the edges of the content view. We detect this situation here, and
+ // move the origin to ensure that there will never be gaps at the end of the table.
+ // Normally we detect that the size of the whole table is not going to be equal to the
+ // size of the content view already when we load the last row/column, and especially
+ // before it's flicked completely inside the viewport. For those cases we simply adjust
+ // the origin/endExtent, to give a smooth flicking experience.
+ // But if flicking fast (e.g with a scrollbar), it can happen that the viewport ends up
+ // outside the end of the table in just one viewport update. To avoid a "blink" in the
+ // viewport when that happens, we "move" the loaded table into the viewport to cover it.
+ Q_Q(QQuickTableView);
+
+ bool tableMovedHorizontally = false;
+ bool tableMovedVertically = false;
+
+ const int nextLeftColumn = nextVisibleEdgeIndexAroundLoadedTable(Qt::LeftEdge);
+ const int nextRightColumn = nextVisibleEdgeIndexAroundLoadedTable(Qt::RightEdge);
+ const int nextTopRow = nextVisibleEdgeIndexAroundLoadedTable(Qt::TopEdge);
+ const int nextBottomRow = nextVisibleEdgeIndexAroundLoadedTable(Qt::BottomEdge);
+
+ 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.
+ if (loadedTableOuterRect.left() > viewportRect.left()) {
+ // We have a blank area at the left end of the viewport. In that case we don't have time to
+ // wait for the viewport to move (after changing origin), since that will take an extra
+ // update cycle, which will be visible as a blink. Instead, unless the blank spot is just
+ // us overshooting, we brute force the loaded table inside the already existing viewport.
+ if (loadedTableOuterRect.left() > origin.x()) {
+ const qreal diff = loadedTableOuterRect.left() - origin.x();
+ loadedTableOuterRect.moveLeft(loadedTableOuterRect.left() - diff);
+ loadedTableInnerRect.moveLeft(loadedTableInnerRect.left() - diff);
+ tableMovedHorizontally = true;
+ }
}
- } else {
- if (loadedTableOuterRect.left() <= 0) {
- // The table rect is at origin, or outside. But we still have
- // more visible columns to the left. So we need to make some
- // space so that they can be flicked in.
- loadedTableOuterRect.moveLeft(flickMargin);
- layoutNeeded = true;
+ 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
+ // the rest of the columns will occupy, and move the origin accordingly.
+ const int columnsRemaining = nextLeftColumn + 1;
+ const qreal remainingColumnWidths = columnsRemaining * averageEdgeSize.width();
+ 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.
+ if (loadedTableOuterRect.right() < viewportRect.right()) {
+ // We have a blank area at the right end of the viewport. In that case we don't have time to
+ // wait for the viewport to move (after changing endExtent), since that will take an extra
+ // update cycle, which will be visible as a blink. Instead, unless the blank spot is just
+ // us overshooting, we brute force the loaded table inside the already existing viewport.
+ const qreal w = qMin(viewportRect.right(), q->contentWidth() + endExtent.width());
+ if (loadedTableOuterRect.right() < w) {
+ const qreal diff = loadedTableOuterRect.right() - w;
+ loadedTableOuterRect.moveRight(loadedTableOuterRect.right() - diff);
+ loadedTableInnerRect.moveRight(loadedTableInnerRect.right() - diff);
+ tableMovedHorizontally = true;
+ }
}
+ 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
+ // has set a fixed content width.
+ const int columnsRemaining = tableSize.width() - nextRightColumn;
+ const qreal remainingColumnWidths = columnsRemaining * averageEdgeSize.width();
+ const qreal remainingSpacing = columnsRemaining * cellSpacing.width();
+ const qreal estimatedRemainingWidth = remainingColumnWidths + remainingSpacing;
+ const qreal pixelsOutsideContentWidth = loadedTableOuterRect.right() - q->contentWidth();
+ endExtent.rwidth() = pixelsOutsideContentWidth + estimatedRemainingWidth;
+ hData.markExtentsDirty();
}
- if (noMoreRows) {
- if (!qFuzzyIsNull(loadedTableOuterRect.top())) {
- loadedTableOuterRect.moveTop(0);
- layoutNeeded = true;
+ 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.
+ if (loadedTableOuterRect.top() > viewportRect.top()) {
+ // We have a blank area at the top of the viewport. In that case we don't have time to
+ // wait for the viewport to move (after changing origin), since that will take an extra
+ // update cycle, which will be visible as a blink. Instead, unless the blank spot is just
+ // us overshooting, we brute force the loaded table inside the already existing viewport.
+ if (loadedTableOuterRect.top() > origin.y()) {
+ const qreal diff = loadedTableOuterRect.top() - origin.y();
+ loadedTableOuterRect.moveTop(loadedTableOuterRect.top() - diff);
+ loadedTableInnerRect.moveTop(loadedTableInnerRect.top() - diff);
+ tableMovedVertically = true;
+ }
}
- } else {
- if (loadedTableOuterRect.top() <= 0) {
- loadedTableOuterRect.moveTop(flickMargin);
- layoutNeeded = true;
+ 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
+ // the rest of the rows will occupy, and move the origin accordingly.
+ const int rowsRemaining = nextTopRow + 1;
+ const qreal remainingRowHeights = rowsRemaining * averageEdgeSize.height();
+ 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.
+ if (loadedTableOuterRect.bottom() < viewportRect.bottom()) {
+ // We have a blank area at the bottom of the viewport. In that case we don't have time to
+ // wait for the viewport to move (after changing endExtent), since that will take an extra
+ // update cycle, which will be visible as a blink. Instead, unless the blank spot is just
+ // us overshooting, we brute force the loaded table inside the already existing viewport.
+ const qreal h = qMin(viewportRect.bottom(), q->contentHeight() + endExtent.height());
+ if (loadedTableOuterRect.bottom() < h) {
+ const qreal diff = loadedTableOuterRect.bottom() - h;
+ loadedTableOuterRect.moveBottom(loadedTableOuterRect.bottom() - diff);
+ loadedTableInnerRect.moveBottom(loadedTableInnerRect.bottom() - diff);
+ tableMovedVertically = true;
+ }
+ }
+ 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
+ // has set a fixed content height.
+ const int rowsRemaining = tableSize.height() - nextBottomRow;
+ const qreal remainingRowHeigts = rowsRemaining * averageEdgeSize.height();
+ const qreal remainingSpacing = rowsRemaining * cellSpacing.height();
+ const qreal estimatedRemainingHeight = remainingRowHeigts + remainingSpacing;
+ const qreal pixelsOutsideContentHeight = loadedTableOuterRect.bottom() - q->contentHeight();
+ endExtent.rheight() = pixelsOutsideContentHeight + estimatedRemainingHeight;
+ vData.markExtentsDirty();
+ }
+
+ if (tableMovedHorizontally || tableMovedVertically) {
+ qCDebug(lcTableViewDelegateLifecycle) << "move table to" << loadedTableOuterRect;
+
+ // relayoutTableItems() will take care of moving the existing
+ // delegate items into the new loadedTableOuterRect.
+ relayoutTableItems();
+
+ // Inform the sync children that they need to rebuild to stay in sync
+ for (auto syncChild : qAsConst(syncChildren)) {
+ auto syncChild_d = syncChild->d_func();
+ syncChild_d->scheduledRebuildOptions |= RebuildOption::ViewportOnly;
+ if (tableMovedHorizontally)
+ syncChild_d->scheduledRebuildOptions |= RebuildOption::CalculateNewTopLeftColumn;
+ if (tableMovedVertically)
+ syncChild_d->scheduledRebuildOptions |= RebuildOption::CalculateNewTopLeftRow;
}
}
- if (layoutNeeded) {
- qCDebug(lcTableViewDelegateLifecycle);
- relayoutTableItems();
+ if (hData.minExtentDirty || vData.minExtentDirty) {
+ qCDebug(lcTableViewDelegateLifecycle) << "move origin and endExtent to:" << origin << 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.
+ updateBeginningEnd();
}
}
@@ -1413,7 +1542,6 @@ void QQuickTableViewPrivate::processLoadRequest()
switch (loadRequest.edge()) {
case Qt::LeftEdge:
case Qt::TopEdge:
- enforceTableAtOrigin();
break;
case Qt::RightEdge:
updateAverageEdgeSize();
@@ -1424,6 +1552,7 @@ void QQuickTableViewPrivate::processLoadRequest()
updateContentHeight();
break;
}
+ updateExtents();
drainReusePoolAfterLoadRequest();
}
@@ -1638,6 +1767,14 @@ void QQuickTableViewPrivate::beginRebuildTable()
else if (rebuildOptions & RebuildOption::ViewportOnly)
releaseLoadedItems(reusableFlag);
+ if (rebuildOptions & RebuildOption::All) {
+ origin = QPointF(0, 0);
+ endExtent = QSizeF(0, 0);
+ hData.markExtentsDirty();
+ vData.markExtentsDirty();
+ updateBeginningEnd();
+ }
+
loadedColumns.clear();
loadedRows.clear();
loadedTableOuterRect = QRect();
@@ -1704,6 +1841,7 @@ void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
updateAverageEdgeSize();
updateContentWidth();
updateContentHeight();
+ updateExtents();
}
void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
@@ -2283,7 +2421,6 @@ void QQuickTableViewPrivate::modelResetCallback()
void QQuickTableViewPrivate::scheduleRebuildIfFastFlick()
{
Q_Q(QQuickTableView);
-
// If the viewport has moved more than one page vertically or horizontally, we switch
// strategy from refilling edges around the current table to instead rebuild the table
// from scratch inside the new viewport. This will greatly improve performance when flicking
@@ -2374,6 +2511,26 @@ QQuickTableView::QQuickTableView(QQuickTableViewPrivate &dd, QQuickItem *parent)
setFlag(QQuickItem::ItemIsFocusScope);
}
+qreal QQuickTableView::minXExtent() const
+{
+ return QQuickFlickable::minXExtent() - d_func()->origin.x();
+}
+
+qreal QQuickTableView::maxXExtent() const
+{
+ return QQuickFlickable::maxXExtent() - d_func()->endExtent.width();
+}
+
+qreal QQuickTableView::minYExtent() const
+{
+ return QQuickFlickable::minYExtent() - d_func()->origin.y();
+}
+
+qreal QQuickTableView::maxYExtent() const
+{
+ return QQuickFlickable::maxYExtent() - d_func()->endExtent.height();
+}
+
int QQuickTableView::rows() const
{
return d_func()->tableSize.height();
diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h
index 3d46221574..3b113efa4f 100644
--- a/src/quick/items/qquicktableview_p.h
+++ b/src/quick/items/qquicktableview_p.h
@@ -147,6 +147,11 @@ private:
Q_DISABLE_COPY(QQuickTableView)
Q_DECLARE_PRIVATE(QQuickTableView)
+ qreal minXExtent() const override;
+ qreal maxXExtent() const override;
+ qreal minYExtent() const override;
+ qreal maxYExtent() const override;
+
Q_PRIVATE_SLOT(d_func(), void _q_componentFinalized())
};
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index 748a1478ec..b66ac66dec 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -251,6 +251,9 @@ public:
QRectF loadedTableOuterRect;
QRectF loadedTableInnerRect;
+ QPointF origin = QPointF(0, 0);
+ QSizeF endExtent = QSizeF(0, 0);
+
QRectF viewportRect = QRectF(0, 0, -1, -1);
QSize tableSize;
@@ -350,7 +353,7 @@ public:
void updateAverageEdgeSize();
void forceLayout();
- void enforceTableAtOrigin();
+ void updateExtents();
void syncLoadedTableRectFromLoadedTable();
void syncLoadedTableFromLoadRequest();
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 0f5ad57127..d03f08ec6a 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -123,6 +123,9 @@ private slots:
void checkContentWidthAndHeight();
void checkPageFlicking();
void checkExplicitContentWidthAndHeight();
+ void checkExtents_origin();
+ void checkExtents_endExtent();
+ void checkExtents_moveTableToEdge();
void checkContentXY();
void noDelegate();
void changeDelegateDuringUpdate();
@@ -760,6 +763,164 @@ void tst_QQuickTableView::checkExplicitContentWidthAndHeight()
QCOMPARE(tableView->contentHeight(), 1000);
}
+void tst_QQuickTableView::checkExtents_origin()
+{
+ // Check that if the beginning of the content view doesn't match the
+ // actual size of the table, origin will be adjusted to make it fit.
+ LOAD_TABLEVIEW("contentwidthheight.qml");
+
+ const int rows = 10;
+ const int columns = rows;
+ const qreal columnWidth = 100;
+ const qreal rowHeight = 100;
+ const qreal actualTableSize = columns * columnWidth;
+
+ // Set a content size that is far too large
+ // compared to the size of the table.
+ tableView->setContentWidth(actualTableSize * 2);
+ tableView->setContentHeight(actualTableSize * 2);
+ tableView->setRowSpacing(0);
+ tableView->setColumnSpacing(0);
+ tableView->setLeftMargin(0);
+ tableView->setRightMargin(0);
+ tableView->setTopMargin(0);
+ tableView->setBottomMargin(0);
+
+ auto model = TestModelAsVariant(rows, columns);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Flick slowly to column 5 (to avoid rebuilds). Flick two columns at a
+ // time to ensure that we create a gap before TableView gets a chance to
+ // adjust endExtent first. This gap on the right side will make TableView
+ // move the table to move to the edge. Because of this, the table will not
+ // be aligned at the start of the content view when we next flick back again.
+ // And this will cause origin to move.
+ for (int x = 0; x <= 6; x += 2) {
+ tableView->setContentX(x * columnWidth);
+ tableView->setContentY(x * rowHeight);
+ }
+
+ // Check that the table has now been moved one column to the right
+ // (One column because that's how far outside the table we ended up flicking above).
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.right(), actualTableSize + columnWidth);
+
+ // Flick back one column at a time so that TableView detects that the first
+ // column is not at the origin before the "table move" logic kicks in. This
+ // will make TableView adjust the origin.
+ for (int x = 6; x >= 0; x -= 1) {
+ tableView->setContentX(x * columnWidth);
+ tableView->setContentY(x * rowHeight);
+ }
+
+ // The origin will be moved with the same offset that the table was
+ // moved on the right side earlier, which is one column length.
+ QCOMPARE(tableViewPrivate->origin.x(), columnWidth);
+ QCOMPARE(tableViewPrivate->origin.y(), rowHeight);
+}
+
+void tst_QQuickTableView::checkExtents_endExtent()
+{
+ // Check that if we the content view size doesn't match the actual size
+ // of the table, endExtent will be adjusted to make it fit (so that
+ // e.g the the flicking will bounce to a stop at the edge of the table).
+ LOAD_TABLEVIEW("contentwidthheight.qml");
+
+ const int rows = 10;
+ const int columns = rows;
+ const qreal columnWidth = 100;
+ const qreal rowHeight = 100;
+ const qreal actualTableSize = columns * columnWidth;
+
+ // Set a content size that is far too large
+ // compared to the size of the table.
+ tableView->setContentWidth(actualTableSize * 2);
+ tableView->setContentHeight(actualTableSize * 2);
+ tableView->setRowSpacing(0);
+ tableView->setColumnSpacing(0);
+ tableView->setLeftMargin(0);
+ tableView->setRightMargin(0);
+ tableView->setTopMargin(0);
+ tableView->setBottomMargin(0);
+
+ auto model = TestModelAsVariant(rows, columns);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Flick slowly to column 5 (to avoid rebuilds). This will flick the table to
+ // the last column in the model. But since there still is a lot space left in
+ // the content view, endExtent will be set accordingly to compensate.
+ for (int x = 1; x <= 5; x++)
+ tableView->setContentX(x * columnWidth);
+ QCOMPARE(tableViewPrivate->rightColumn(), columns - 1);
+ qreal expectedEndExtentWidth = actualTableSize - tableView->contentWidth();
+ QCOMPARE(tableViewPrivate->endExtent.width(), expectedEndExtentWidth);
+
+ for (int y = 1; y <= 5; y++)
+ tableView->setContentY(y * rowHeight);
+ QCOMPARE(tableViewPrivate->bottomRow(), rows - 1);
+ qreal expectedEndExtentHeight = actualTableSize - tableView->contentHeight();
+ QCOMPARE(tableViewPrivate->endExtent.height(), expectedEndExtentHeight);
+}
+
+void tst_QQuickTableView::checkExtents_moveTableToEdge()
+{
+ // Check that if we the content view size doesn't match the actual
+ // size of the table, and we fast-flick the viewport to outside
+ // the table, we end up moving the table back into the viewport to
+ // avoid any visual glitches.
+ LOAD_TABLEVIEW("contentwidthheight.qml");
+
+ const int rows = 10;
+ const int columns = rows;
+ const qreal columnWidth = 100;
+ const qreal rowHeight = 100;
+ const qreal actualTableSize = columns * columnWidth;
+
+ // Set a content size that is far to large
+ // compared to the size of the table.
+ tableView->setContentWidth(actualTableSize * 2);
+ tableView->setContentHeight(actualTableSize * 2);
+ tableView->setRowSpacing(0);
+ tableView->setColumnSpacing(0);
+ tableView->setLeftMargin(0);
+ tableView->setRightMargin(0);
+ tableView->setTopMargin(0);
+ tableView->setBottomMargin(0);
+
+ auto model = TestModelAsVariant(rows, columns);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Flick slowly to column 5 (to avoid rebuilds). Flick two columns at a
+ // time to ensure that we create a gap before TableView gets a chance to
+ // adjust endExtent first. This gap on the right side will make TableView
+ // move the table to the edge (in addition to adjusting the extents, but that
+ // will happen in a subsequent polish, and is not for this test verify).
+ for (int x = 0; x <= 6; x += 2)
+ tableView->setContentX(x * columnWidth);
+ QCOMPARE(tableViewPrivate->rightColumn(), columns - 1);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect, tableViewPrivate->viewportRect);
+
+ for (int y = 0; y <= 6; y += 2)
+ tableView->setContentY(y * rowHeight);
+ QCOMPARE(tableViewPrivate->bottomRow(), rows - 1);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect, tableViewPrivate->viewportRect);
+
+ for (int x = 6; x >= 0; x -= 2)
+ tableView->setContentX(x * columnWidth);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect, tableViewPrivate->viewportRect);
+
+ for (int y = 6; y >= 0; y -= 2)
+ tableView->setContentY(y * rowHeight);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect, tableViewPrivate->viewportRect);
+}
+
void tst_QQuickTableView::checkContentXY()
{
// Check that you can bind contentX and contentY to