QTreeView: fix performance regression from accessibility updates
When expanding items in a tree view, the model as seen by accessibility changes size and structure, and needs to be reset. This was done in 6a4afebc5ce8db69a6c9fb398cada31e6bad5e3c by emitting a ModelReset update at the end of QTreeViewPrivate::layout when laying out the items had changed the number of visible items. However, QTreeViewPrivate::layout is called both recursively, and in a loop when expanding all items, or expanding items to a certain depth, resulting in a heavy performance hit when each recursion or iteration causes the accessibility bridge to rebuild its representation from scratch. Instead, we now only store a flag that the model has to be reset in QTreeViewPrivate::layout, and then trigger the reset in the function that call layout, after the laying out is complete. Fixes: QTBUG-122054 Pick-to: 6.7 6.6 Change-Id: Icb8384b56a4727c8c5050a1d501aebb55f48aafe Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
16c27a83f0
commit
a86321cb66
@ -2145,6 +2145,7 @@ void QTreeView::doItemsLayout()
|
|||||||
}
|
}
|
||||||
QAbstractItemView::doItemsLayout();
|
QAbstractItemView::doItemsLayout();
|
||||||
d->header->doItemsLayout();
|
d->header->doItemsLayout();
|
||||||
|
d->updateAccessibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2708,6 +2709,7 @@ void QTreeView::expandAll()
|
|||||||
d->layout(-1, true);
|
d->layout(-1, true);
|
||||||
updateGeometries();
|
updateGeometries();
|
||||||
d->viewport->update();
|
d->viewport->update();
|
||||||
|
d->updateAccessibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2831,6 +2833,7 @@ void QTreeView::expandToDepth(int depth)
|
|||||||
|
|
||||||
updateGeometries();
|
updateGeometries();
|
||||||
d->viewport->update();
|
d->viewport->update();
|
||||||
|
d->updateAccessibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -3142,6 +3145,7 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
|
|||||||
beginAnimatedOperation();
|
beginAnimatedOperation();
|
||||||
#endif // animation
|
#endif // animation
|
||||||
}
|
}
|
||||||
|
updateAccessibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QTreeViewPrivate::insertViewItems(int pos, int count, const QTreeViewItem &viewItem)
|
void QTreeViewPrivate::insertViewItems(int pos, int count, const QTreeViewItem &viewItem)
|
||||||
@ -3350,6 +3354,21 @@ void QTreeViewPrivate::columnsRemoved(const QModelIndex &parent, int start, int
|
|||||||
QAbstractItemViewPrivate::columnsRemoved(parent, start, end);
|
QAbstractItemViewPrivate::columnsRemoved(parent, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QTreeViewPrivate::updateAccessibility()
|
||||||
|
{
|
||||||
|
#if QT_CONFIG(accessibility)
|
||||||
|
Q_Q(QTreeView);
|
||||||
|
if (pendingAccessibilityUpdate) {
|
||||||
|
pendingAccessibilityUpdate = false;
|
||||||
|
if (QAccessible::isActive()) {
|
||||||
|
QAccessibleTableModelChangeEvent event(q, QAccessibleTableModelChangeEvent::ModelReset);
|
||||||
|
QAccessible::updateAccessibility(&event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
creates and initialize the viewItem structure of the children of the element \li
|
creates and initialize the viewItem structure of the children of the element \li
|
||||||
|
|
||||||
@ -3374,11 +3393,8 @@ void QTreeViewPrivate::layout(int i, bool recursiveExpanding, bool afterIsUninit
|
|||||||
// QAccessibleTree's rowCount implementation uses viewItems.size(), so
|
// QAccessibleTree's rowCount implementation uses viewItems.size(), so
|
||||||
// we need to invalidate any cached accessibility data structures if
|
// we need to invalidate any cached accessibility data structures if
|
||||||
// that value changes during the run of this function.
|
// that value changes during the run of this function.
|
||||||
const auto resetModelIfNeeded = qScopeGuard([oldViewItemsSize = viewItems.size(), this, q]{
|
const auto resetModelIfNeeded = qScopeGuard([oldViewItemsSize = viewItems.size(), this]{
|
||||||
if (oldViewItemsSize != viewItems.size() && QAccessible::isActive()) {
|
pendingAccessibilityUpdate |= oldViewItemsSize != viewItems.size();
|
||||||
QAccessibleTableModelChangeEvent event(q, QAccessibleTableModelChangeEvent::ModelReset);
|
|
||||||
QAccessible::updateAccessibility(&event);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -258,6 +258,12 @@ public:
|
|||||||
// tree position
|
// tree position
|
||||||
int treePosition;
|
int treePosition;
|
||||||
|
|
||||||
|
// pending accessibility update
|
||||||
|
#if QT_CONFIG(accessibility)
|
||||||
|
bool pendingAccessibilityUpdate = false;
|
||||||
|
#endif
|
||||||
|
void updateAccessibility();
|
||||||
|
|
||||||
QMetaObject::Connection animationConnection;
|
QMetaObject::Connection animationConnection;
|
||||||
QMetaObject::Connection selectionmodelConnection;
|
QMetaObject::Connection selectionmodelConnection;
|
||||||
std::array<QMetaObject::Connection, 2> modelConnections;
|
std::array<QMetaObject::Connection, 2> modelConnections;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user