QAbstractItemView: execute posted layouts before painting

tst_QListView::moveLastRow asserts now and again, unless only that test
function is running. We repeat failing test functions individually, so
this never blocked CI.

The reason seems to be that we get a paint event only for the viewport,
after the item model's structure has been changed by the test. Moving
rows does trigger a delayed layout, and in some circumstances the
entire view is updated, rather than just the viewport. But if only the
viewport is updated, then layout execution in QAbstractItemView::event
never happens, and the data structure that the paintEvent implementation
relies on is outdated and contains invalid item pointers, resulting in
an assert.

If we need to execute delayed layouts when the entire view gets painted,
then we also need to execute them when only the viewport gets painted.

Change-Id: Ibb46c2315825d99c82b884226817c494a3d95975
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit 85ab3f26656b2b51eaa5b5247cc0d90d401fd8df)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2023-02-26 16:45:10 +01:00 committed by Qt Cherry-pick Bot
parent 84f5dcf4ec
commit acb0cb62fe

View File

@ -1709,6 +1709,12 @@ bool QAbstractItemView::viewportEvent(QEvent *event)
{
Q_D(QAbstractItemView);
switch (event->type()) {
case QEvent::Paint:
// Similar to pre-painting in QAbstractItemView::event to update scrollbar
// visibility, make sure that all pending layout requests have been executed
// so that the view's data structures are up-to-date before rendering.
d->executePostedLayout();
break;
case QEvent::HoverMove:
case QEvent::HoverEnter:
d->setHoverIndex(indexAt(static_cast<QHoverEvent*>(event)->position().toPoint()));