aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquicktableview.cpp37
-rw-r--r--src/quick/items/qquicktableview_p_p.h8
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp54
3 files changed, 86 insertions, 13 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index e1ec5aff75..a1a5520239 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -771,13 +771,11 @@ void QQuickTableViewPrivate::layoutHorizontalEdge(Qt::Edge tableEdge)
void QQuickTableViewPrivate::layoutTopLeftItem()
{
- // ###todo: support starting with other top-left items than 0,0
const QPoint cell = loadRequest.firstCell();
- Q_TABLEVIEW_ASSERT(cell == QPoint(0, 0), loadRequest.toString());
auto topLeftItem = loadedTableItem(cell);
auto item = topLeftItem->item;
- item->setPosition(QPoint(tableMargins.left(), tableMargins.top()));
+ item->setPosition(loadRequest.startPosition());
item->setSize(QSizeF(resolveColumnWidth(cell.x()), resolveRowHeight(cell.y())));
topLeftItem->setVisible(true);
qCDebug(lcTableViewDelegateLifecycle) << "geometry:" << topLeftItem->geometry();
@@ -938,18 +936,35 @@ void QQuickTableViewPrivate::beginRebuildTable()
if (loadRequest.isActive())
cancelLoadRequest();
- releaseLoadedItems(QQmlTableInstanceModel::NotReusable);
+ QPoint topLeft;
+ QPointF topLeftPos;
+ calculateTableSize();
+
+ if (rebuildOptions & RebuildOption::All) {
+ releaseLoadedItems(QQmlTableInstanceModel::NotReusable);
+ topLeft = QPoint(0, 0);
+ topLeftPos = QPointF(tableMargins.left(), tableMargins.top());
+ q->setContentX(0);
+ q->setContentY(0);
+ } else if (rebuildOptions & RebuildOption::ViewportOnly) {
+ // Rebuild the table without flicking the content view back to origin, and
+ // start building from the same top left item that is currently showing
+ // (unless it has been removed from the model).
+ releaseLoadedItems(reusableFlag);
+ topLeft = loadedTable.topLeft();
+ topLeftPos = loadedTableOuterRect.topLeft();
+ topLeft.setX(qMin(topLeft.x(), tableSize.width() - 1));
+ topLeft.setY(qMin(topLeft.y(), tableSize.height() - 1));
+ } else {
+ Q_TABLEVIEW_UNREACHABLE(rebuildOptions);
+ }
loadedTable = QRect();
loadedTableOuterRect = QRect();
loadedTableInnerRect = QRect();
contentSizeBenchMarkPoint = QPoint(-1, -1);
- q->setContentX(0);
- q->setContentY(0);
-
- calculateTableSize();
- loadInitialTopLeftItem();
+ loadInitialTopLeftItem(topLeft, topLeftPos);
loadAndUnloadVisibleEdges();
}
@@ -965,7 +980,7 @@ void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
}
}
-void QQuickTableViewPrivate::loadInitialTopLeftItem()
+void QQuickTableViewPrivate::loadInitialTopLeftItem(const QPoint &cell, const QPointF &pos)
{
Q_TABLEVIEW_ASSERT(loadedItems.isEmpty(), "");
@@ -980,7 +995,7 @@ void QQuickTableViewPrivate::loadInitialTopLeftItem()
// Load top-left item. After loaded, loadItemsInsideRect() will take
// care of filling out the rest of the table.
- loadRequest.begin(QPoint(0, 0), QQmlIncubator::AsynchronousIfNested);
+ loadRequest.begin(cell, pos, QQmlIncubator::AsynchronousIfNested);
processLoadRequest();
}
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index 81127adae4..1e8c10c285 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -86,7 +86,7 @@ public:
// done by QQuickTableView.
public:
- void begin(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode)
+ void begin(const QPoint &cell, const QPointF &pos, QQmlIncubator::IncubationMode incubationMode)
{
Q_ASSERT(!active);
active = true;
@@ -95,6 +95,7 @@ public:
mode = incubationMode;
cellCount = 1;
currentIndex = 0;
+ startPos = pos;
qCDebug(lcTableViewDelegateLifecycle()) << "begin top-left:" << toString();
}
@@ -125,6 +126,8 @@ public:
inline Qt::Edge edge() { return tableEdge; }
inline QQmlIncubator::IncubationMode incubationMode() { return mode; }
+ inline QPointF startPosition() { return startPos; }
+
QString toString()
{
QString str;
@@ -154,6 +157,7 @@ public:
int cellCount = 0;
bool active = false;
QQmlIncubator::IncubationMode mode = QQmlIncubator::AsynchronousIfNested;
+ QPointF startPos;
QPoint cellAt(int index)
{
@@ -304,7 +308,7 @@ public:
void unloadItem(const QPoint &cell);
void unloadItems(const QLine &items);
- void loadInitialTopLeftItem();
+ void loadInitialTopLeftItem(const QPoint &cell, const QPointF &pos);
void loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode);
void unloadEdge(Qt::Edge edge);
void loadAndUnloadVisibleEdges();
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 99534ddb50..e5b06051a5 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -130,6 +130,7 @@ private slots:
void checkContextPropertiesQQmlListProperyModel();
void checkRowAndColumnChangedButNotIndex();
void checkChangingModelFromDelegate();
+ void checkRebuildViewportOnly();
};
tst_QQuickTableView::tst_QQuickTableView()
@@ -1666,6 +1667,59 @@ void tst_QQuickTableView::checkChangingModelFromDelegate()
QCOMPARE(tableViewPrivate->loadedTable.height(), 3);
}
+void tst_QQuickTableView::checkRebuildViewportOnly()
+{
+ // Check that we only rebuild from the current top-left cell
+ // when you add or remove rows and columns. There should be
+ // no need to do a rebuild from scratch in such cases.
+ LOAD_TABLEVIEW("countingtableview.qml");
+
+ const char *propName = "delegatesCreatedCount";
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+
+ TestModel model(100, 100);
+ tableView->setModel(QVariant::fromValue(&model));
+
+ WAIT_UNTIL_POLISHED;
+
+ // Flick to row/column 50, 50
+ tableView->setContentX(delegateWidth * 50);
+ tableView->setContentY(delegateHeight * 50);
+
+ // Set reuse items to false, just to make it easier to
+ // check the number of items created during a rebuild.
+ tableView->setReuseItems(false);
+ const int itemCountBeforeRebuild = tableViewPrivate->loadedItems.count();
+
+ // Since all cells have the same size, we expect that we end up creating
+ // the same amount of items that were already showing before, even after
+ // adding or removing rows and columns.
+ view->rootObject()->setProperty(propName, 0);
+ model.insertRow(51);
+ WAIT_UNTIL_POLISHED;
+ int countAfterRebuild = view->rootObject()->property(propName).toInt();
+ QCOMPARE(countAfterRebuild, itemCountBeforeRebuild);
+
+ view->rootObject()->setProperty(propName, 0);
+ model.removeRow(51);
+ WAIT_UNTIL_POLISHED;
+ countAfterRebuild = view->rootObject()->property(propName).toInt();
+ QCOMPARE(countAfterRebuild, itemCountBeforeRebuild);
+
+ view->rootObject()->setProperty(propName, 0);
+ model.insertColumn(51);
+ WAIT_UNTIL_POLISHED;
+ countAfterRebuild = view->rootObject()->property(propName).toInt();
+ QCOMPARE(countAfterRebuild, itemCountBeforeRebuild);
+
+ view->rootObject()->setProperty(propName, 0);
+ model.removeColumn(51);
+ WAIT_UNTIL_POLISHED;
+ countAfterRebuild = view->rootObject()->property(propName).toInt();
+ QCOMPARE(countAfterRebuild, itemCountBeforeRebuild);
+}
+
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"