From 8ec406b2296abdbdc8606fa955a2f8feb5254b1f Mon Sep 17 00:00:00 2001 From: ChunLin Wang Date: Thu, 26 Aug 2021 21:15:31 +0800 Subject: Fix QListView assert when the last row is moved in IconMode After the last row is moved, 0 will be returned when obtaining row and column data. At this time, QListView::doitemslayout will not call d->doitemslayout, so the QBspTree data structure will not be cleaned up, leaving a stale tree structure behind. This will trigger an assert during paintEvent handling if QListView is set to IconMode In QListView::ListMode the test for a valid model index doesn't use an assert. Call QListViewPrivate::clear explicitly if the column count is 0 so that the QBspTree and other data structures are cleared. Add a test case that simulates this scenario by implementing a model that returns a 0 column count for an index after the model structure was changed through a move of rows. Done-with: Volker Hilsheimer Fixes: QTBUG-95463 Change-Id: I36419be5459b8ced930c619f538482ea1db4ad03 Reviewed-by: Volker Hilsheimer (cherry picked from commit ca69e5aeef2fef540e687475ac00a4f332fdc5f3) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/itemviews/qlistview.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/widgets/itemviews/qlistview.cpp') diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 68d5d7612f..f9e3082962 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1575,12 +1575,14 @@ void QListView::doItemsLayout() setState(ExpandingState); if (d->model->columnCount(d->root) > 0) { // no columns means no contents d->resetBatchStartRow(); - if (layoutMode() == SinglePass) + if (layoutMode() == SinglePass) { d->doItemsLayout(d->model->rowCount(d->root)); // layout everything - else if (!d->batchLayoutTimer.isActive()) { + } else if (!d->batchLayoutTimer.isActive()) { if (!d->doItemsLayout(d->batchSize)) // layout is done d->batchLayoutTimer.start(0, this); // do a new batch as fast as possible } + } else { // clear the QBspTree generated by the last layout + d->clear(); } QAbstractItemView::doItemsLayout(); setState(oldState); // restoring the oldState -- cgit v1.2.3