aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquicktableview.cpp194
-rw-r--r--src/quick/items/qquicktableview_p_p.h14
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp155
3 files changed, 201 insertions, 162 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index b1900c5b7a..0b5bebb7ba 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -377,36 +377,6 @@ Q_LOGGING_CATEGORY(lcTableViewDelegateLifecycle, "qt.quick.tableview.lifecycle")
static const Qt::Edge allTableEdges[] = { Qt::LeftEdge, Qt::RightEdge, Qt::TopEdge, Qt::BottomEdge };
-static QLine rectangleEdge(const QRect &rect, Qt::Edge tableEdge)
-{
- switch (tableEdge) {
- case Qt::LeftEdge:
- return QLine(rect.topLeft(), rect.bottomLeft());
- case Qt::RightEdge:
- return QLine(rect.topRight(), rect.bottomRight());
- case Qt::TopEdge:
- return QLine(rect.topLeft(), rect.topRight());
- case Qt::BottomEdge:
- return QLine(rect.bottomLeft(), rect.bottomRight());
- }
- return QLine();
-}
-
-static QRect expandedRect(const QRect &rect, Qt::Edge edge, int increment)
-{
- switch (edge) {
- case Qt::LeftEdge:
- return rect.adjusted(-increment, 0, 0, 0);
- case Qt::RightEdge:
- return rect.adjusted(0, 0, increment, 0);
- case Qt::TopEdge:
- return rect.adjusted(0, -increment, 0, 0);
- case Qt::BottomEdge:
- return rect.adjusted(0, 0, 0, increment);
- }
- return QRect();
-}
-
const QPoint QQuickTableViewPrivate::kLeft = QPoint(-1, 0);
const QPoint QQuickTableViewPrivate::kRight = QPoint(1, 0);
const QPoint QQuickTableViewPrivate::kUp = QPoint(0, -1);
@@ -427,8 +397,8 @@ QQuickTableViewPrivate::~QQuickTableViewPrivate()
QString QQuickTableViewPrivate::tableLayoutToString() const
{
return QString(QLatin1String("table cells: (%1,%2) -> (%3,%4), item count: %5, table rect: %6,%7 x %8,%9"))
- .arg(loadedTable.topLeft().x()).arg(loadedTable.topLeft().y())
- .arg(loadedTable.bottomRight().x()).arg(loadedTable.bottomRight().y())
+ .arg(leftColumn()).arg(topRow())
+ .arg(rightColumn()).arg(bottomRow())
.arg(loadedItems.count())
.arg(loadedTableOuterRect.x())
.arg(loadedTableOuterRect.y())
@@ -489,7 +459,7 @@ void QQuickTableViewPrivate::updateContentWidth()
}
const qreal thresholdBeforeAdjust = 0.1;
- int currentRightColumn = loadedTable.right();
+ int currentRightColumn = rightColumn();
if (currentRightColumn > contentSizeBenchMarkPoint.x()) {
contentSizeBenchMarkPoint.setX(currentRightColumn);
@@ -526,7 +496,7 @@ void QQuickTableViewPrivate::updateContentHeight()
}
const qreal thresholdBeforeAdjust = 0.1;
- int currentBottomRow = loadedTable.bottom();
+ int currentBottomRow = bottomRow();
if (currentBottomRow > contentSizeBenchMarkPoint.y()) {
contentSizeBenchMarkPoint.setY(currentBottomRow);
@@ -561,7 +531,7 @@ void QQuickTableViewPrivate::enforceTableAtOrigin()
bool layoutNeeded = false;
const qreal flickMargin = 50;
- if (loadedTable.x() == 0 && loadedTableOuterRect.x() > 0) {
+ if (leftColumn() == 0 && loadedTableOuterRect.x() > 0) {
// The table is at the beginning, but not at the edge of the
// content view. So move the table to origin.
loadedTableOuterRect.moveLeft(0);
@@ -569,15 +539,15 @@ void QQuickTableViewPrivate::enforceTableAtOrigin()
} else if (loadedTableOuterRect.x() < 0) {
// The table is outside the beginning of the content view. Move
// the whole table inside, and make some room for flicking.
- loadedTableOuterRect.moveLeft(loadedTable.x() == 0 ? 0 : flickMargin);
+ loadedTableOuterRect.moveLeft(leftColumn() == 0 ? 0 : flickMargin);
layoutNeeded = true;
}
- if (loadedTable.y() == 0 && loadedTableOuterRect.y() > 0) {
+ if (topRow() == 0 && loadedTableOuterRect.y() > 0) {
loadedTableOuterRect.moveTop(0);
layoutNeeded = true;
} else if (loadedTableOuterRect.y() < 0) {
- loadedTableOuterRect.moveTop(loadedTable.y() == 0 ? 0 : flickMargin);
+ loadedTableOuterRect.moveTop(topRow() == 0 ? 0 : flickMargin);
layoutNeeded = true;
}
@@ -589,8 +559,8 @@ void QQuickTableViewPrivate::enforceTableAtOrigin()
void QQuickTableViewPrivate::updateAverageEdgeSize()
{
- int bottomCell = loadedTable.bottom();
- int rightCell = loadedTable.right();
+ int bottomCell = bottomRow();
+ int rightCell = rightColumn();
qreal accRowSpacing = bottomCell * cellSpacing.height();
qreal accColumnSpacing = rightCell * cellSpacing.width();
averageEdgeSize.setHeight((loadedTableOuterRect.bottom() - accRowSpacing) / (bottomCell + 1));
@@ -599,9 +569,11 @@ void QQuickTableViewPrivate::updateAverageEdgeSize()
void QQuickTableViewPrivate::syncLoadedTableRectFromLoadedTable()
{
- QRectF topLeftRect = loadedTableItem(loadedTable.topLeft())->geometry();
- QRectF bottomRightRect = loadedTableItem(loadedTable.bottomRight())->geometry();
- loadedTableOuterRect = topLeftRect.united(bottomRightRect);
+ const QPoint topLeft = QPoint(leftColumn(), topRow());
+ const QPoint bottomRight = QPoint(rightColumn(), bottomRow());
+ QRectF topLeftRect = loadedTableItem(topLeft)->geometry();
+ QRectF bottomRightRect = loadedTableItem(bottomRight)->geometry();
+ loadedTableOuterRect = QRectF(topLeftRect.topLeft(), bottomRightRect.bottomRight());
loadedTableInnerRect = QRectF(topLeftRect.bottomRight(), bottomRightRect.topLeft());
}
@@ -609,18 +581,19 @@ void QQuickTableViewPrivate::syncLoadedTableFromLoadRequest()
{
if (loadRequest.edge() == Qt::Edge(0)) {
// No edge means we're loading the top-left item
- loadedTable = QRect(loadRequest.firstCell(), loadRequest.lastCell());
+ loadedColumns.insert(loadRequest.firstCell().x(), 0);
+ loadedRows.insert(loadRequest.firstCell().y(), 0);
return;
}
switch (loadRequest.edge()) {
case Qt::LeftEdge:
- case Qt::TopEdge:
- loadedTable.setTopLeft(loadRequest.firstCell());
- break;
case Qt::RightEdge:
+ loadedColumns.insert(loadRequest.firstCell().x(), 0);
+ break;
+ case Qt::TopEdge:
case Qt::BottomEdge:
- loadedTable.setBottomRight(loadRequest.lastCell());
+ loadedRows.insert(loadRequest.firstCell().y(), 0);
break;
}
}
@@ -776,23 +749,38 @@ void QQuickTableViewPrivate::unloadItems(const QLine &items)
}
}
+int QQuickTableViewPrivate::nextVisibleEdgeIndexAroundLoadedTable(Qt::Edge edge)
+{
+ switch (edge) {
+ case Qt::LeftEdge:
+ return leftColumn() - 1;
+ case Qt::RightEdge:
+ return rightColumn() + 1;
+ case Qt::TopEdge:
+ return topRow() - 1;
+ case Qt::BottomEdge:
+ return bottomRow() + 1;
+ }
+ return -1;
+}
+
bool QQuickTableViewPrivate::canLoadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const
{
switch (tableEdge) {
case Qt::LeftEdge:
- if (loadedTable.topLeft().x() == 0)
+ if (leftColumn() == 0)
return false;
return loadedTableOuterRect.left() > fillRect.left() + cellSpacing.width();
case Qt::RightEdge:
- if (loadedTable.bottomRight().x() >= tableSize.width() - 1)
+ if (rightColumn() == tableSize.width() - 1)
return false;
return loadedTableOuterRect.right() < fillRect.right() - cellSpacing.width();
case Qt::TopEdge:
- if (loadedTable.topLeft().y() == 0)
+ if (topRow() == 0)
return false;
return loadedTableOuterRect.top() > fillRect.top() + cellSpacing.height();
case Qt::BottomEdge:
- if (loadedTable.bottomRight().y() >= tableSize.height() - 1)
+ if (bottomRow() == tableSize.height() - 1)
return false;
return loadedTableOuterRect.bottom() < fillRect.bottom() - cellSpacing.height();
}
@@ -806,19 +794,19 @@ bool QQuickTableViewPrivate::canUnloadTableEdge(Qt::Edge tableEdge, const QRectF
// they are needed as anchor point for further layouting.
switch (tableEdge) {
case Qt::LeftEdge:
- if (loadedTable.width() <= 1)
+ if (loadedColumns.count() <= 1)
return false;
return loadedTableInnerRect.left() <= fillRect.left();
case Qt::RightEdge:
- if (loadedTable.width() <= 1)
+ if (loadedColumns.count() <= 1)
return false;
return loadedTableInnerRect.right() >= fillRect.right();
case Qt::TopEdge:
- if (loadedTable.height() <= 1)
+ if (loadedRows.count() <= 1)
return false;
return loadedTableInnerRect.top() <= fillRect.top();
case Qt::BottomEdge:
- if (loadedTable.height() <= 1)
+ if (loadedRows.count() <= 1)
return false;
return loadedTableInnerRect.bottom() >= fillRect.bottom();
}
@@ -864,8 +852,10 @@ qreal QQuickTableViewPrivate::sizeHintForColumn(int column)
{
// Find the widest cell in the column, and return its width
qreal columnWidth = 0;
- for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row)
+ for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r) {
+ const int row = r.key();
columnWidth = qMax(columnWidth, cellWidth(QPoint(column, row)));
+ }
return columnWidth;
}
@@ -874,8 +864,10 @@ qreal QQuickTableViewPrivate::sizeHintForRow(int row)
{
// Find the highest cell in the row, and return its height
qreal rowHeight = 0;
- for (int column = loadedTable.left(); column <= loadedTable.right(); ++column)
+ for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c) {
+ const int column = c.key();
rowHeight = qMax(rowHeight, cellHeight(QPoint(column, row)));
+ }
return rowHeight;
}
@@ -902,7 +894,6 @@ void QQuickTableViewPrivate::calculateTableSize()
qreal QQuickTableViewPrivate::resolveColumnWidth(int column)
{
- Q_TABLEVIEW_ASSERT(column >= loadedTable.left() && column <= loadedTable.right(), column);
qreal columnWidth = -1;
if (!columnWidthProvider.isUndefined()) {
@@ -948,7 +939,6 @@ qreal QQuickTableViewPrivate::resolveColumnWidth(int column)
qreal QQuickTableViewPrivate::resolveRowHeight(int row)
{
- Q_TABLEVIEW_ASSERT(row >= loadedTable.top() && row <= loadedTable.bottom(), row);
qreal rowHeight = -1;
if (!rowHeightProvider.isUndefined()) {
@@ -1011,11 +1001,13 @@ void QQuickTableViewPrivate::relayoutTableItems()
qreal nextColumnX = loadedTableOuterRect.x();
qreal nextRowY = loadedTableOuterRect.y();
- for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
+ for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c) {
+ const int column = c.key();
// Adjust the geometry of all cells in the current column
const qreal width = resolveColumnWidth(column);
- for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r) {
+ const int row = r.key();
auto item = loadedTableItem(QPoint(column, row));
QRectF geometry = item->geometry();
geometry.moveLeft(nextColumnX);
@@ -1026,11 +1018,13 @@ void QQuickTableViewPrivate::relayoutTableItems()
nextColumnX += width + cellSpacing.width();
}
- for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r) {
+ const int row = r.key();
// Adjust the geometry of all cells in the current row
const qreal height = resolveRowHeight(row);
- for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
+ for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c) {
+ const int column = c.key();
auto item = loadedTableItem(QPoint(column, row));
QRectF geometry = item->geometry();
geometry.moveTop(nextRowY);
@@ -1042,8 +1036,10 @@ void QQuickTableViewPrivate::relayoutTableItems()
}
if (Q_UNLIKELY(lcTableViewDelegateLifecycle().isDebugEnabled())) {
- for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
- for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c) {
+ const int column = c.key();
+ for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r) {
+ const int row = r.key();
QPoint cell = QPoint(column, row);
qCDebug(lcTableViewDelegateLifecycle()) << "relayout item:" << cell << loadedTableItem(cell)->geometry();
}
@@ -1053,11 +1049,12 @@ void QQuickTableViewPrivate::relayoutTableItems()
void QQuickTableViewPrivate::layoutVerticalEdge(Qt::Edge tableEdge)
{
- int column = (tableEdge == Qt::LeftEdge) ? loadedTable.left() : loadedTable.right();
+ int column = (tableEdge == Qt::LeftEdge) ? leftColumn() : rightColumn();
QPoint neighbourDirection = (tableEdge == Qt::LeftEdge) ? kRight : kLeft;
qreal width = resolveColumnWidth(column);
- for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r) {
+ const int row = r.key();
auto fxTableItem = loadedTableItem(QPoint(column, row));
auto const neighbourItem = itemNextTo(fxTableItem, neighbourDirection);
@@ -1080,11 +1077,12 @@ void QQuickTableViewPrivate::layoutVerticalEdge(Qt::Edge tableEdge)
void QQuickTableViewPrivate::layoutHorizontalEdge(Qt::Edge tableEdge)
{
- int row = (tableEdge == Qt::TopEdge) ? loadedTable.top() : loadedTable.bottom();
+ int row = (tableEdge == Qt::TopEdge) ? topRow() : bottomRow();
QPoint neighbourDirection = (tableEdge == Qt::TopEdge) ? kDown : kUp;
qreal height = resolveRowHeight(row);
- for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
+ for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c) {
+ const int column = c.key();
auto fxTableItem = loadedTableItem(QPoint(column, row));
auto const neighbourItem = itemNextTo(fxTableItem, neighbourDirection);
@@ -1232,14 +1230,14 @@ void QQuickTableViewPrivate::processRebuildTable()
&& reusableFlag == QQmlTableInstanceModel::Reusable);
if (rebuildState == RebuildState::PreloadColumns) {
- if (preload && loadedTable.right() < tableSize.width() - 1)
+ if (preload && rightColumn() < tableSize.width() - 1)
loadEdge(Qt::RightEdge, QQmlIncubator::AsynchronousIfNested);
if (!moveToNextRebuildState())
return;
}
if (rebuildState == RebuildState::PreloadRows) {
- if (preload && loadedTable.bottom() < tableSize.height() - 1)
+ if (preload && bottomRow() < tableSize.height() - 1)
loadEdge(Qt::BottomEdge, QQmlIncubator::AsynchronousIfNested);
if (!moveToNextRebuildState())
return;
@@ -1289,7 +1287,7 @@ void QQuickTableViewPrivate::beginRebuildTable()
topLeft.ry() = qBound(0, newRow, tableSize.height() - 1);
topLeftPos.ry() = topLeft.y() * (averageEdgeSize.height() + cellSpacing.height());
} else {
- topLeft.ry() = qBound(0, loadedTable.topLeft().y(), tableSize.height() - 1);
+ topLeft.ry() = qBound(0, topRow(), tableSize.height() - 1);
topLeftPos.ry() = loadedTableOuterRect.topLeft().y();
}
if (rebuildOptions & RebuildOption::CalculateNewTopLeftColumn) {
@@ -1297,14 +1295,15 @@ void QQuickTableViewPrivate::beginRebuildTable()
topLeft.rx() = qBound(0, newColumn, tableSize.width() - 1);
topLeftPos.rx() = topLeft.x() * (averageEdgeSize.width() + cellSpacing.width());
} else {
- topLeft.rx() = qBound(0, loadedTable.topLeft().x(), tableSize.width() - 1);
+ topLeft.rx() = qBound(0, leftColumn(), tableSize.width() - 1);
topLeftPos.rx() = loadedTableOuterRect.topLeft().x();
}
} else {
Q_TABLEVIEW_UNREACHABLE(rebuildOptions);
}
- loadedTable = QRect();
+ loadedColumns.clear();
+ loadedRows.clear();
loadedTableOuterRect = QRect();
loadedTableInnerRect = QRect();
contentSizeBenchMarkPoint = QPoint(-1, -1);
@@ -1351,15 +1350,44 @@ void QQuickTableViewPrivate::loadInitialTopLeftItem(const QPoint &cell, const QP
void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
{
- unloadItems(rectangleEdge(loadedTable, edge));
- loadedTable = expandedRect(loadedTable, edge, -1);
+ qCDebug(lcTableViewDelegateLifecycle) << edge;
+
+ switch (edge) {
+ case Qt::LeftEdge:
+ case Qt::RightEdge: {
+ const int column = edge == Qt::LeftEdge ? leftColumn() : rightColumn();
+ unloadItems(QLine(column, topRow(), column, bottomRow()));
+ loadedColumns.remove(column);
+ break; }
+ case Qt::TopEdge:
+ case Qt::BottomEdge: {
+ const int row = edge == Qt::TopEdge ? topRow() : bottomRow();
+ unloadItems(QLine(leftColumn(), row, rightColumn(), row));
+ loadedRows.remove(row);
+ break; }
+ }
+
syncLoadedTableRectFromLoadedTable();
qCDebug(lcTableViewDelegateLifecycle) << tableLayoutToString();
}
void QQuickTableViewPrivate::loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode)
{
- QLine cellsToLoad = rectangleEdge(expandedRect(loadedTable, edge, 1), edge);
+ const int edgeIndex = nextVisibleEdgeIndexAroundLoadedTable(edge);
+ qCDebug(lcTableViewDelegateLifecycle) << edge << edgeIndex;
+ QLine cellsToLoad;
+
+ switch (edge) {
+ case Qt::LeftEdge:
+ case Qt::RightEdge:
+ cellsToLoad = QLine(edgeIndex, topRow(), edgeIndex, bottomRow());
+ break;
+ case Qt::TopEdge:
+ case Qt::BottomEdge:
+ cellsToLoad = QLine(leftColumn(), edgeIndex, rightColumn(), edgeIndex);
+ break;
+ }
+
loadRequest.begin(cellsToLoad, edge, incubationMode);
processLoadRequest();
}
@@ -1446,8 +1474,8 @@ void QQuickTableViewPrivate::drainReusePoolAfterLoadRequest()
// in with varying sizes, causing some items not to be resued immediately), we multiply the
// value by 2. Note that we also add an extra +1 to the column count, because the number of
// visible columns will fluctuate between +1/-1 while flicking.
- const int w = loadedTable.width();
- const int h = loadedTable.height();
+ const int w = loadedColumns.count();
+ const int h = loadedRows.count();
const int minTime = int(std::ceil(w > h ? qreal(w + 1) / h : qreal(h + 1) / w));
const int maxTime = minTime * 2;
tableModel->drainReusableItemsPool(maxTime);
@@ -1596,6 +1624,12 @@ void QQuickTableViewPrivate::syncRebuildOptions()
rebuildOptions = scheduledRebuildOptions;
scheduledRebuildOptions = RebuildOption::None;
rebuildScheduled = false;
+
+ if (loadedItems.isEmpty()) {
+ // If we have no items from before, we cannot just rebuild the viewport, but need
+ // to rebuild everything, since we have no top-left loaded item to start from.
+ rebuildOptions.setFlag(RebuildOption::All);
+ }
}
void QQuickTableViewPrivate::syncDelegate()
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index 2ed04f8d29..ed6f8026a2 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -213,13 +213,14 @@ public:
QVariant assignedModel = QVariant(int(0));
QQmlComponent *assignedDelegate = nullptr;
- // loadedTable describes the table cells that are currently loaded (from top left
+ // loadedRows/Columns describes the rows and columns that are currently loaded (from top left
// row/column to bottom right row/column). loadedTableOuterRect describes the actual
- // pixels that those cells cover, and is matched agains the viewport to determine when
+ // pixels that all the loaded delegate items cover, and is matched agains the viewport to determine when
// we need to fill up with more rows/columns. loadedTableInnerRect describes the pixels
// that the loaded table covers if you remove one row/column on each side of the table, and
// is used to determine rows/columns that are no longer visible and can be unloaded.
- QRect loadedTable;
+ QMap<int, int> loadedColumns;
+ QMap<int, int> loadedRows;
QRectF loadedTableOuterRect;
QRectF loadedTableInnerRect;
@@ -283,6 +284,11 @@ public:
qreal resolveColumnWidth(int column);
qreal resolveRowHeight(int row);
+ inline int topRow() const { return loadedRows.firstKey(); }
+ inline int bottomRow() const { return loadedRows.lastKey(); }
+ inline int leftColumn() const { return loadedColumns.firstKey(); }
+ inline int rightColumn() const { return loadedColumns.lastKey(); }
+
void relayoutTable();
void relayoutTableItems();
@@ -299,6 +305,8 @@ public:
void syncLoadedTableRectFromLoadedTable();
void syncLoadedTableFromLoadRequest();
+ int nextVisibleEdgeIndexAroundLoadedTable(Qt::Edge edge);
+
bool canLoadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const;
bool canUnloadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const;
Qt::Edge nextEdgeToLoad(const QRectF rect);
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index a3b9aa4c03..d2ec9948c9 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -251,8 +251,9 @@ void tst_QQuickTableView::checkPreload()
WAIT_UNTIL_POLISHED;
if (reuseItems) {
- QSize visibleTableSize = tableViewPrivate->loadedTable.size();
- int expectedPoolSize = visibleTableSize.height() + visibleTableSize.width() + 1;
+ const int rowCount = tableViewPrivate->loadedRows.count();
+ const int columnCount = tableViewPrivate->loadedColumns.count();
+ const int expectedPoolSize = rowCount + columnCount + 1;
QCOMPARE(tableViewPrivate->tableModel->poolSize(), expectedPoolSize);
} else {
QCOMPARE(tableViewPrivate->tableModel->poolSize(), 0);
@@ -321,10 +322,9 @@ void tst_QQuickTableView::checkColumnWidthWithoutProvider()
WAIT_UNTIL_POLISHED;
- QRect table = tableViewPrivate->loadedTable;
- for (int column = table.left(); column <= table.right(); ++column) {
+ for (const int column : tableViewPrivate->loadedColumns.keys()) {
const qreal expectedColumnWidth = tableViewPrivate->sizeHintForColumn(column);
- for (int row = table.top(); row <= table.bottom(); ++row) {
+ for (const int row : tableViewPrivate->loadedRows.keys()) {
const auto item = tableViewPrivate->loadedTableItem(QPoint(column, row))->item;
QCOMPARE(item->width(), expectedColumnWidth);
}
@@ -414,10 +414,9 @@ void tst_QQuickTableView::checkRowHeightWithoutProvider()
WAIT_UNTIL_POLISHED;
- QRect table = tableViewPrivate->loadedTable;
- for (int row = table.top(); row <= table.bottom(); ++row) {
+ for (const int row : tableViewPrivate->loadedRows.keys()) {
const qreal expectedRowHeight = tableViewPrivate->sizeHintForRow(row);
- for (int column = table.left(); column <= table.right(); ++column) {
+ for (const int column : tableViewPrivate->loadedColumns.keys()) {
const auto item = tableViewPrivate->loadedTableItem(QPoint(column, row))->item;
QCOMPARE(item->height(), expectedRowHeight);
}
@@ -565,8 +564,8 @@ void tst_QQuickTableView::checkContentWidthAndHeight()
const int largeSizeCellCountInView = qCeil(tableView->width() / cellSizeLarge);
const int columnCount = smallCellCount + largeSizeCellCountInView;
- QCOMPARE(tableViewPrivate->loadedTable.left(), smallCellCount);
- QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->leftColumn(), smallCellCount);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
const qreal firstHalfLength = smallCellCount * cellSizeSmall;
const qreal secondHalfOneScreenLength = largeSizeCellCountInView * cellSizeLarge;
@@ -618,17 +617,18 @@ void tst_QQuickTableView::checkPageFlicking()
const int cellWidth = 100;
const int cellHeight = 50;
auto model = TestModelAsVariant(10000, 10000);
+ const auto &loadedRows = tableViewPrivate->loadedRows;
+ const auto &loadedColumns = tableViewPrivate->loadedColumns;
tableView->setModel(model);
WAIT_UNTIL_POLISHED;
// Sanity check startup table
- QRect tableRect = tableViewPrivate->loadedTable;
- QCOMPARE(tableRect.x(), 0);
- QCOMPARE(tableRect.y(), 0);
- QCOMPARE(tableRect.width(), tableView->width() / cellWidth);
- QCOMPARE(tableRect.height(), tableView->height() / cellHeight);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(loadedRows.count(), tableView->height() / cellHeight);
+ QCOMPARE(loadedColumns.count(), tableView->width() / cellWidth);
// Since all cells have the same size, the average row/column
// size found by TableView should be exactly equal to this.
@@ -652,11 +652,10 @@ void tst_QQuickTableView::checkPageFlicking()
WAIT_UNTIL_POLISHED;
- tableRect = tableViewPrivate->loadedTable;
- QCOMPARE(tableRect.x(), flickToColumn);
- QCOMPARE(tableRect.y(), 0);
- QCOMPARE(tableRect.width(), tableView->width() / cellWidth);
- QCOMPARE(tableRect.height(), tableView->height() / cellHeight);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->leftColumn(), flickToColumn);
+ QCOMPARE(loadedColumns.count(), tableView->width() / cellWidth);
+ QCOMPARE(loadedRows.count(), tableView->height() / cellHeight);
// Flick 5000 rows down as well. Since flicking down should only calculate a new row (but
// keep the current column), we deliberatly change the average width to check that it's
@@ -675,11 +674,10 @@ void tst_QQuickTableView::checkPageFlicking()
WAIT_UNTIL_POLISHED;
- tableRect = tableViewPrivate->loadedTable;
- QCOMPARE(tableRect.x(), flickToRow);
- QCOMPARE(tableRect.y(), flickToColumn);
- QCOMPARE(tableRect.width(), tableView->width() / cellWidth);
- QCOMPARE(tableRect.height(), tableView->height() / cellHeight);
+ QCOMPARE(tableViewPrivate->topRow(), flickToColumn);
+ QCOMPARE(tableViewPrivate->leftColumn(), flickToRow);
+ QCOMPARE(loadedRows.count(), tableView->height() / cellHeight);
+ QCOMPARE(loadedColumns.count(), tableView->width() / cellWidth);
}
void tst_QQuickTableView::checkExplicitContentWidthAndHeight()
@@ -729,8 +727,8 @@ void tst_QQuickTableView::checkContentXY()
// Check that we end up at the correct top-left cell:
const qreal delegateWidth = tableViewPrivate->loadedItems.values().first()->item->width();
const int expectedCellXY = qCeil(expectedXY / delegateWidth);
- QCOMPARE(tableViewPrivate->loadedTable.left(), expectedCellXY);
- QCOMPARE(tableViewPrivate->loadedTable.top(), expectedCellXY);
+ QCOMPARE(tableViewPrivate->leftColumn(), expectedCellXY);
+ QCOMPARE(tableViewPrivate->topRow(), expectedCellXY);
}
void tst_QQuickTableView::noDelegate()
@@ -1004,7 +1002,8 @@ void tst_QQuickTableView::fillTableViewButNothingMore()
auto const topLeftFxItem = tableViewPrivate->loadedTableItem(QPoint(0, 0));
auto const topLeftItem = topLeftFxItem->item;
- auto const bottomRightFxItem = tableViewPrivate->loadedTableItem(tableViewPrivate->loadedTable.bottomRight());
+ auto const bottomRightLoadedCell = QPoint(tableViewPrivate->rightColumn(), tableViewPrivate->bottomRow());
+ auto const bottomRightFxItem = tableViewPrivate->loadedTableItem(bottomRightLoadedCell);
auto const bottomRightItem = bottomRightFxItem->item;
const QPoint bottomRightCell = getContextRowAndColumn(bottomRightItem.data());
@@ -1182,15 +1181,13 @@ void tst_QQuickTableView::flick()
WAIT_UNTIL_POLISHED;
- const QRect loadedTable = tableViewPrivate->loadedTable;
+ const int expectedTableLeft = int(cellsToFlick - int((margins.left() + spacing.width()) / cellWidth));
+ const int expectedTableTop = int(cellsToFlick - int((margins.top() + spacing.height()) / cellHeight));
- const int expectedTableLeft = cellsToFlick - int((margins.left() + spacing.width()) / cellWidth);
- const int expectedTableTop = cellsToFlick - int((margins.top() + spacing.height()) / cellHeight);
-
- QCOMPARE(loadedTable.left(), expectedTableLeft);
- QCOMPARE(loadedTable.right(), expectedTableLeft + visualColumnCount);
- QCOMPARE(loadedTable.top(), expectedTableTop);
- QCOMPARE(loadedTable.bottom(), expectedTableTop + visualRowCount);
+ QCOMPARE(tableViewPrivate->leftColumn(), expectedTableLeft);
+ QCOMPARE(tableViewPrivate->rightColumn(), expectedTableLeft + visualColumnCount);
+ QCOMPARE(tableViewPrivate->topRow(), expectedTableTop);
+ QCOMPARE(tableViewPrivate->bottomRow(), expectedTableTop + visualRowCount);
}
}
@@ -1252,10 +1249,10 @@ void tst_QQuickTableView::flickOvershoot()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.right(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), 0);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
// Flick table out of view right
tableView->setContentX(tableWidth + outsideMargin);
@@ -1264,10 +1261,10 @@ void tst_QQuickTableView::flickOvershoot()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.left(), columnCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->leftColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
// Flick table out of view on top
tableView->setContentX(0);
@@ -1276,10 +1273,10 @@ void tst_QQuickTableView::flickOvershoot()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.bottom(), 0);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), 0);
// Flick table out of view at the bottom
tableView->setContentX(0);
@@ -1288,10 +1285,10 @@ void tst_QQuickTableView::flickOvershoot()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.top(), rowCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
// Flick table out of view left and top at the same time
tableView->setContentX(-tableView->width() - outsideMargin);
@@ -1300,10 +1297,10 @@ void tst_QQuickTableView::flickOvershoot()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.right(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.bottom(), 0);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), 0);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), 0);
// Flick table back to origo
tableView->setContentX(0);
@@ -1312,10 +1309,10 @@ void tst_QQuickTableView::flickOvershoot()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
// Flick table out of view right and bottom at the same time
tableView->setContentX(tableWidth + outsideMargin);
@@ -1324,10 +1321,10 @@ void tst_QQuickTableView::flickOvershoot()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.left(), columnCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.top(), rowCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->leftColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
// Flick table back to origo
tableView->setContentX(0);
@@ -1336,10 +1333,10 @@ void tst_QQuickTableView::flickOvershoot()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
- QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
- QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
}
void tst_QQuickTableView::checkRowColumnCount()
@@ -1353,6 +1350,8 @@ void tst_QQuickTableView::checkRowColumnCount()
const qreal delegateWidth = 100;
const qreal delegateHeight = 50;
auto model = TestModelAsVariant(100, 100);
+ const auto &loadedRows = tableViewPrivate->loadedRows;
+ const auto &loadedColumns = tableViewPrivate->loadedColumns;
tableView->setModel(model);
@@ -1360,17 +1359,15 @@ void tst_QQuickTableView::checkRowColumnCount()
// We expect that the number of created items after start-up should match
//the size of the visible table, pluss one extra preloaded row and column.
- const QSize visibleTableSize = tableViewPrivate->loadedTable.size();
const int qmlCountAfterInit = view->rootObject()->property(maxDelegateCountProp).toInt();
- const int expectedCount = (visibleTableSize.width() + 1) * (visibleTableSize.height() + 1);
+ const int expectedCount = (loadedColumns.count() + 1) * (loadedRows.count() + 1);
QCOMPARE(qmlCountAfterInit, expectedCount);
// This test will keep track of the maximum number of delegate items TableView
// had to show at any point while flicking (in countingtableview.qml). Because
// of the geometries chosen for TableView and the delegate, only complete columns
// will be shown at start-up.
- const QRect loadedTable = tableViewPrivate->loadedTable;
- QVERIFY(loadedTable.height() > loadedTable.width());
+ QVERIFY(loadedRows.count() > loadedColumns.count());
QCOMPARE(tableViewPrivate->loadedTableOuterRect.width(), tableView->width());
QCOMPARE(tableViewPrivate->loadedTableOuterRect.height(), tableView->height());
@@ -1619,8 +1616,8 @@ void tst_QQuickTableView::checkIfDelegatesAreReused()
fxItem->item->setProperty("reusedCount", 0);
}
- const int visibleColumnCount = tableViewPrivate->loadedTable.width();
- const int visibleRowCount = tableViewPrivate->loadedTable.height();
+ const int visibleColumnCount = tableViewPrivate->loadedColumns.count();
+ const int visibleRowCount = tableViewPrivate->loadedRows.count();
const int delegateCountAfterInit = view->rootObject()->property(kDelegatesCreatedCountProp).toInt();
for (int column = 1; column <= (visibleColumnCount * pageFlickCount); ++column) {
@@ -1687,7 +1684,7 @@ void tst_QQuickTableView::checkIfDelegatesAreReusedAsymmetricTableSize()
// Since we have flicked half a delegate to the left, the number of visible
// columns is now one more than the column count were when we started the test.
- const int visibleColumnCount = tableViewPrivate->loadedTable.width();
+ const int visibleColumnCount = tableViewPrivate->loadedColumns.count();
QCOMPARE(visibleColumnCount, columnCount + 1);
// We expect no items to have been pooled so far
@@ -1887,7 +1884,7 @@ void tst_QQuickTableView::checkChangingModelFromDelegate()
// We now expect two rows in the table, one more than initially
QCOMPARE(tableViewPrivate->tableSize.height(), 2);
- QCOMPARE(tableViewPrivate->loadedTable.height(), 2);
+ QCOMPARE(tableViewPrivate->loadedRows.count(), 2);
// And since the QML code tried to add another row as well, we
// expect rebuildScheduled to be true, and a polish event to be pending.
@@ -1897,7 +1894,7 @@ void tst_QQuickTableView::checkChangingModelFromDelegate()
// After handling the polish event, we expect also the third row to now be added
QCOMPARE(tableViewPrivate->tableSize.height(), 3);
- QCOMPARE(tableViewPrivate->loadedTable.height(), 3);
+ QCOMPARE(tableViewPrivate->loadedRows.count(), 3);
}
void tst_QQuickTableView::checkRebuildViewportOnly()
@@ -1982,8 +1979,8 @@ void tst_QQuickTableView::checkTableviewInsideAsyncLoader()
const qreal delegateHeight = 50;
int expectedColumns = qCeil(tableView->width() / delegateWidth);
int expectedRows = qCeil(tableView->height() / delegateHeight);
- QCOMPARE(tableViewPrivate->loadedTable.width(), expectedColumns);
- QCOMPARE(tableViewPrivate->loadedTable.height(), expectedRows);
+ QCOMPARE(tableViewPrivate->loadedColumns.count(), expectedColumns);
+ QCOMPARE(tableViewPrivate->loadedRows.count(), expectedRows);
// Check that the loader was still in a loading state while TableView was creating
// delegate items. If we delayed creating delegate items until we got the first