diff options
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/qquicktableview.cpp | 113 | ||||
-rw-r--r-- | src/quick/items/qquicktableview_p_p.h | 20 |
2 files changed, 101 insertions, 32 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index fd8af19805..8dce0149f6 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -805,7 +805,7 @@ void QQuickTableViewPrivate::cancelLoadRequest() loadRequest.markAsDone(); model->cancel(modelIndexAtCell(loadRequest.currentCell())); - if (tableInvalid) { + if (rebuildState == RebuildState::NotStarted) { // No reason to rollback already loaded edge items // since we anyway are about to reload all items. return; @@ -857,13 +857,77 @@ void QQuickTableViewPrivate::processLoadRequest() qCDebug(lcTableViewDelegateLifecycle()) << "request completed! Table:" << tableLayoutToString(); } +void QQuickTableViewPrivate::processRebuildTable() +{ + moveToNextRebuildState(); + + if (rebuildState == RebuildState::LoadInitalTable) { + beginRebuildTable(); + if (!moveToNextRebuildState()) + return; + } + + if (rebuildState == RebuildState::VerifyTable) { + if (loadedItems.isEmpty()) { + qCDebug(lcTableViewDelegateLifecycle()) << "no items loaded, meaning empty model or no delegate"; + rebuildState = RebuildState::Done; + return; + } + if (!moveToNextRebuildState()) + return; + } + + if (rebuildState == RebuildState::LayoutTable) { + layoutAfterLoadingInitialTable(); + if (!moveToNextRebuildState()) + return; + } + + if (rebuildState == RebuildState::LoadAndUnloadAfterLayout) { + loadAndUnloadVisibleEdges(); + if (!moveToNextRebuildState()) + return; + } + + if (rebuildState == RebuildState::PreloadColumns) { + if (loadedTable.right() < tableSize.width() - 1) + loadEdge(Qt::RightEdge, QQmlIncubator::AsynchronousIfNested); + if (!moveToNextRebuildState()) + return; + } + + if (rebuildState == RebuildState::PreloadRows) { + if (loadedTable.bottom() < tableSize.height() - 1) + loadEdge(Qt::BottomEdge, QQmlIncubator::AsynchronousIfNested); + if (!moveToNextRebuildState()) + return; + } + + if (rebuildState == RebuildState::MovePreloadedItemsToPool) { + while (Qt::Edge edge = nextEdgeToUnload(viewportRect)) + unloadEdge(edge); + if (!moveToNextRebuildState()) + return; + } + + Q_TABLEVIEW_ASSERT(rebuildState == RebuildState::Done, int(rebuildState)); +} + +bool QQuickTableViewPrivate::moveToNextRebuildState() +{ + if (loadRequest.isActive()) { + // Items are still loading async, which means + // that the current state is not yet done. + return false; + } + rebuildState = RebuildState(int(rebuildState) + 1); + qCDebug(lcTableViewDelegateLifecycle()) << int(rebuildState); + return true; +} + void QQuickTableViewPrivate::beginRebuildTable() { Q_Q(QQuickTableView); - qCDebug(lcTableViewDelegateLifecycle()); - - tableInvalid = false; - tableRebuilding = true; releaseLoadedItems(); loadedTable = QRect(); @@ -879,21 +943,16 @@ void QQuickTableViewPrivate::beginRebuildTable() loadAndUnloadVisibleEdges(); } -void QQuickTableViewPrivate::endRebuildTable() +void QQuickTableViewPrivate::layoutAfterLoadingInitialTable() { - tableRebuilding = false; - - if (rowHeightProvider.isNull() && columnWidthProvider.isNull()) { - // Since we have no size providers, we need to calculate the size - // of each row and column based on the size of the delegate items. + if (rowHeightProvider.isNull() || columnWidthProvider.isNull()) { + // Since we don't have both size providers, we need to calculate the + // size of each row and column based on the size of the delegate items. // This couldn't be done while we were loading the initial rows and // columns, since during the process, we didn't have all the items - // available yet for the calculation. So we mark that it needs to be - // done now, from within updatePolish(). - columnRowPositionsInvalid = true; + // available yet for the calculation. So we do it now. + relayoutTable(); } - - qCDebug(lcTableViewDelegateLifecycle()) << tableLayoutToString(); } void QQuickTableViewPrivate::loadInitialTopLeftItem() @@ -1020,7 +1079,7 @@ void QQuickTableViewPrivate::drainReusePoolAfterLoadRequest() } void QQuickTableViewPrivate::invalidateTable() { - tableInvalid = true; + rebuildState = RebuildState::NotStarted; if (loadRequest.isActive()) cancelLoadRequest(); q_func()->polish(); @@ -1056,19 +1115,13 @@ void QQuickTableViewPrivate::updatePolish() if (!viewportRect.isValid()) return; - if (tableInvalid) { - beginRebuildTable(); - if (loadRequest.isActive()) - return; + if (rebuildState != RebuildState::Done) { + processRebuildTable(); + return; } - if (tableRebuilding) - endRebuildTable(); - - if (loadedItems.isEmpty()) { - qCDebug(lcTableViewDelegateLifecycle()) << "no items loaded, meaning empty model or no delegate"; + if (loadedItems.isEmpty()) return; - } if (columnRowPositionsInvalid) relayoutTable(); @@ -1499,7 +1552,8 @@ qreal QQuickTableView::explicitContentWidth() const { Q_D(const QQuickTableView); - if (d->tableInvalid && d->explicitContentWidth.isNull) { + if (d->rebuildState == QQuickTableViewPrivate::RebuildState::NotStarted + && d->explicitContentWidth.isNull) { // The table is pending to be rebuilt. Since we don't // know the contentWidth before this is done, we do the // rebuild now, instead of waiting for the polish event. @@ -1523,7 +1577,8 @@ qreal QQuickTableView::explicitContentHeight() const { Q_D(const QQuickTableView); - if (d->tableInvalid && d->explicitContentHeight.isNull) { + if (d->rebuildState == QQuickTableViewPrivate::RebuildState::NotStarted + && d->explicitContentHeight.isNull) { // The table is pending to be rebuilt. Since we don't // know the contentHeight before this is done, we do the // rebuild now, instead of waiting for the polish event. diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h index 936d8b8207..53fd936195 100644 --- a/src/quick/items/qquicktableview_p_p.h +++ b/src/quick/items/qquicktableview_p_p.h @@ -163,6 +163,18 @@ public: } }; + enum class RebuildState { + NotStarted = 0, + LoadInitalTable, + VerifyTable, + LayoutTable, + LoadAndUnloadAfterLayout, + PreloadColumns, + PreloadRows, + MovePreloadedItemsToPool, + Done + }; + public: QQuickTableViewPrivate(); ~QQuickTableViewPrivate() override; @@ -196,6 +208,7 @@ public: QSize tableSize; + RebuildState rebuildState = RebuildState::NotStarted; TableEdgeLoadRequest loadRequest; QPoint contentSizeBenchMarkPoint = QPoint(-1, -1); @@ -205,8 +218,6 @@ public: QQmlTableInstanceModel::ReusableFlag reusableFlag = QQmlTableInstanceModel::Reusable; bool blockItemCreatedCallback = false; - bool tableInvalid = false; - bool tableRebuilding = false; bool columnRowPositionsInvalid = false; bool layoutWarningIssued = false; bool polishing = false; @@ -289,8 +300,11 @@ public: void drainReusePoolAfterLoadRequest(); void cancelLoadRequest(); void processLoadRequest(); + + void processRebuildTable(); + bool moveToNextRebuildState(); void beginRebuildTable(); - void endRebuildTable(); + void layoutAfterLoadingInitialTable(); void invalidateTable(); void invalidateColumnRowPositions(); |