diff options
author | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2019-12-23 15:44:48 +0100 |
---|---|---|
committer | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2020-03-28 09:03:18 +0100 |
commit | 8de62d34321cd827e60b0a7b6e7434070de301ae (patch) | |
tree | 048f18f000b6d9235057d800e5f3d79be35a5570 /src/widgets/itemviews/qtableview.cpp | |
parent | b8be5b4002bd6163851bbae397171ebbf632f02f (diff) |
QAbstractItemView::dataChanged(): optimize call to QWidget::update()
When topLeft and bottomRight are different in QAIV::dataChanged(), the
current implementation simply calls QWidget::update() without checking
if the affected cells are visible. This results in a big performance hit
when cells are updated frequently.
Now try to compute the exact update rect by iterating through the
modified indexes.
Fixes: QTBUG-58580
Change-Id: I97de567d494e40ed8cdb1ea1f5b3cf3a2f60455e
Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch>
Diffstat (limited to 'src/widgets/itemviews/qtableview.cpp')
-rw-r--r-- | src/widgets/itemviews/qtableview.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 81fceba8dc..c3ccfac5be 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -669,6 +669,52 @@ void QTableViewPrivate::trimHiddenSelections(QItemSelectionRange *range) const *range = QItemSelectionRange(topLeft, bottomRight); } +QRect QTableViewPrivate::intersectedRect(const QRect rect, const QModelIndex &topLeft, const QModelIndex &bottomRight) const +{ + Q_Q(const QTableView); + + using minMaxPair = std::pair<int, int>; + const auto calcMinMax = [q, rect](QHeaderView *hdr, int startIdx, int endIdx, minMaxPair bounds) -> minMaxPair + { + minMaxPair ret(std::numeric_limits<int>::max(), std::numeric_limits<int>::min()); + if (hdr->sectionsMoved()) { + for (int i = startIdx; i <= endIdx; ++i) { + const int start = hdr->sectionViewportPosition(i); + const int end = start + hdr->sectionSize(i); + ret.first = std::min(start, ret.first); + ret.second = std::max(end, ret.second); + if (ret.first <= bounds.first && ret.second >= bounds.second) + break; + } + } else { + if (q->isRightToLeft() && q->horizontalHeader() == hdr) + std::swap(startIdx, endIdx); + ret.first = hdr->sectionViewportPosition(startIdx); + ret.second = hdr->sectionViewportPosition(endIdx) + + hdr->sectionSize(endIdx); + } + return ret; + }; + + const auto yVals = calcMinMax(verticalHeader, topLeft.row(), bottomRight.row(), + minMaxPair(rect.top(), rect.bottom())); + if (yVals.first == yVals.second) // all affected rows are hidden + return QRect(); + + // short circuit: check if no row is inside rect + const QRect colRect(QPoint(rect.left(), yVals.first), + QPoint(rect.right(), yVals.second)); + const QRect intersected = rect.intersected(colRect); + if (intersected.isNull()) + return QRect(); + + const auto xVals = calcMinMax(horizontalHeader, topLeft.column(), bottomRight.column(), + minMaxPair(rect.left(), rect.right())); + const QRect updateRect(QPoint(xVals.first, yVals.first), + QPoint(xVals.second, yVals.second)); + return rect.intersected(updateRect); +} + /*! \internal Sets the span for the cell at (\a row, \a column). |