diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2019-10-22 15:30:20 +0200 |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2019-11-12 14:46:41 +0100 |
commit | 8952800c68743d0c98e3f638a5bafef1e78fa1d9 (patch) | |
tree | 5650a01d792b7d5897c4ce1622df813827be0d9f /src/quick/items/qquicktableview.cpp | |
parent | 06267f90a2ec6e67c754f1b9fd2a516c37fd784e (diff) |
QQuickTableView::forceLayout(): rebuild table if the size of the model has changed
An assert will trigger if forceLayout() is called while the model is
being reset. The reason is that the forceLayout() schedules a relayout
which assumes that the size of the model hasn't changed. But while
layouting, it will try to fetch data from the model according to the
old size, which will trigger an assert.
This patch will add an extra path to forceLayout() that checks if the
size of the model has changed, and if so, schedule a complete
rebuild instead of just a relayout.
Fixes: QTBUG-79395
Change-Id: If61658912d9e90c1a5aef9bc28083da20fa6ec76
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quick/items/qquicktableview.cpp')
-rw-r--r-- | src/quick/items/qquicktableview.cpp | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index 295c6898bc..01eb852ecd 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -871,17 +871,13 @@ void QQuickTableViewPrivate::syncLoadedTableRectFromLoadedTable() loadedTableInnerRect = QRectF(topLeftRect.bottomRight(), bottomRightRect.topLeft()); } -void QQuickTableViewPrivate::forceLayout() +QQuickTableViewPrivate::RebuildOptions QQuickTableViewPrivate::checkForVisibilityChanges() { - if (loadedItems.isEmpty()) - return; - - clearEdgeSizeCache(); - RebuildOptions rebuildOptions = RebuildOption::LayoutOnly; - // Go through all columns from first to last, find the columns that used // to be hidden and not loaded, and check if they should become visible // (and vice versa). If there is a change, we need to rebuild. + RebuildOptions rebuildOptions = RebuildOption::None; + for (int column = leftColumn(); column <= rightColumn(); ++column) { const bool wasVisibleFromBefore = loadedColumns.contains(column); const bool isVisibleNow = !qFuzzyIsNull(getColumnWidth(column)); @@ -916,6 +912,28 @@ void QQuickTableViewPrivate::forceLayout() break; } + return rebuildOptions; +} + +void QQuickTableViewPrivate::forceLayout() +{ + if (loadedItems.isEmpty()) + return; + + clearEdgeSizeCache(); + RebuildOptions rebuildOptions = RebuildOption::None; + + const QSize actualTableSize = calculateTableSize(); + if (tableSize != actualTableSize) { + // This can happen if the app is calling forceLayout while + // the model is updated, but before we're notified about it. + rebuildOptions = RebuildOption::All; + } else { + rebuildOptions = checkForVisibilityChanges(); + if (!rebuildOptions) + rebuildOptions = RebuildOption::LayoutOnly; + } + scheduleRebuildTable(rebuildOptions); auto rootView = rootSyncView(); @@ -1183,19 +1201,14 @@ qreal QQuickTableViewPrivate::sizeHintForRow(int row) return rowHeight; } -void QQuickTableViewPrivate::calculateTableSize() +void QQuickTableViewPrivate::updateTableSize() { // tableSize is the same as row and column count, and will always // be the same as the number of rows and columns in the model. Q_Q(QQuickTableView); - QSize prevTableSize = tableSize; - if (tableModel) - tableSize = QSize(tableModel->columns(), tableModel->rows()); - else if (model) - tableSize = QSize(1, model->count()); - else - tableSize = QSize(0, 0); + const QSize prevTableSize = tableSize; + tableSize = calculateTableSize(); if (prevTableSize.width() != tableSize.width()) emit q->columnsChanged(); @@ -1203,6 +1216,16 @@ void QQuickTableViewPrivate::calculateTableSize() emit q->rowsChanged(); } +QSize QQuickTableViewPrivate::calculateTableSize() +{ + if (tableModel) + return QSize(tableModel->columns(), tableModel->rows()); + else if (model) + return QSize(1, model->count()); + + return QSize(0, 0); +} + qreal QQuickTableViewPrivate::getColumnLayoutWidth(int column) { // Return the column width specified by the application, or go @@ -1755,7 +1778,7 @@ void QQuickTableViewPrivate::calculateTopLeft(QPoint &topLeftCell, QPointF &topL void QQuickTableViewPrivate::beginRebuildTable() { - calculateTableSize(); + updateTableSize(); QPoint topLeft; QPointF topLeftPos; |