aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquicktableview.cpp
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2019-10-22 15:30:20 +0200
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2019-11-12 14:46:41 +0100
commit8952800c68743d0c98e3f638a5bafef1e78fa1d9 (patch)
tree5650a01d792b7d5897c4ce1622df813827be0d9f /src/quick/items/qquicktableview.cpp
parent06267f90a2ec6e67c754f1b9fd2a516c37fd784e (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.cpp55
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;