QTreeView: optimize Private::intersectedRect()
The implementation for QTreeViewPrivate::intersectedRect() calculated the view rect for every single index which is not needed: - when the row is spanned, the first item spans the complete viewport - the x-position of an index in the same column but different row is the same so no need to re-calculate the boundaries again (similar to the implementation in QTableView) This reduces the visualRect() call count from n*m to n+m Task-number: QTBUG-124173 Change-Id: I651b2ff9b6d4e68a82f32b3f5c3c0e746f88ce5e Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
parent
64b6a2aa70
commit
2f9c72028d
@ -1412,13 +1412,48 @@ QRect QTreeViewPrivate::intersectedRect(const QRect rect, const QModelIndex &top
|
||||
const auto parentIdx = topLeft.parent();
|
||||
executePostedLayout();
|
||||
QRect updateRect;
|
||||
for (int r = topLeft.row(); r <= bottomRight.row(); ++r) {
|
||||
if (isRowHidden(model->index(r, 0, parentIdx)))
|
||||
int left = std::numeric_limits<int>::max();
|
||||
int right = std::numeric_limits<int>::min();
|
||||
for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
|
||||
const auto idxCol0 = model->index(row, 0, parentIdx);
|
||||
if (isRowHidden(idxCol0))
|
||||
continue;
|
||||
for (int c = topLeft.column(); c <= bottomRight.column(); ++c) {
|
||||
const QModelIndex idx(model->index(r, c, parentIdx));
|
||||
updateRect |= visualRect(idx, SingleSection);
|
||||
QRect rowRect;
|
||||
if (left != std::numeric_limits<int>::max()) {
|
||||
// we already know left and right boundary of the rect to update
|
||||
rowRect = visualRect(idxCol0, FullRow);
|
||||
if (!rowRect.intersects(rect))
|
||||
continue;
|
||||
rowRect = QRect(left, rowRect.top(), right, rowRect.bottom());
|
||||
} else if (!spanningIndexes.isEmpty() && spanningIndexes.contains(idxCol0)) {
|
||||
// isFirstColumnSpanned re-creates the child index so take a shortcut here
|
||||
// spans the whole row, therefore ask for FullRow instead for every cell
|
||||
rowRect = visualRect(idxCol0, FullRow);
|
||||
if (!rowRect.intersects(rect))
|
||||
continue;
|
||||
} else {
|
||||
for (int col = topLeft.column(); col <= bottomRight.column(); ++col) {
|
||||
if (header->isSectionHidden(col))
|
||||
continue;
|
||||
const QModelIndex idx(model->index(row, col, parentIdx));
|
||||
const QRect idxRect = visualRect(idx, SingleSection);
|
||||
if (idxRect.isNull())
|
||||
continue;
|
||||
// early exit when complete row is out of viewport
|
||||
if (idxRect.top() > rect.bottom() && idxRect.bottom() < rect.top())
|
||||
break;
|
||||
if (!idxRect.intersects(rect))
|
||||
continue;
|
||||
rowRect = rowRect.united(idxRect);
|
||||
if (rowRect.left() < rect.left() && rowRect.right() > rect.right())
|
||||
break;
|
||||
}
|
||||
left = std::min(left, rowRect.left());
|
||||
right = std::max(right, rowRect.right());
|
||||
}
|
||||
updateRect = updateRect.united(rowRect);
|
||||
if (updateRect.contains(rect)) // already full rect covered?
|
||||
break;
|
||||
}
|
||||
return rect.intersected(updateRect);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user