diff options
author | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2018-06-30 14:49:05 +0200 |
---|---|---|
committer | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2018-09-17 14:01:31 +0000 |
commit | 43ed09fed59d55a8792fad87ef9a75382b5c60ff (patch) | |
tree | 3157cceda4735ec15c51f9b043a4238750b6217a /src | |
parent | 2b177314139b830ca7e2d5bc414131b0dc9fd5b9 (diff) |
QListView: Speedup handling of hidden items
Instead iterating through all rows to get the number of hidden items,
iterate over the hidden items which are fewer items.
Also don't create a temporary vector with visible flow positions by
remembering the count of hidden items before the working index and
adjusting them appropriately which gives a significant performance
boost when working with a large data set.
[ChangeLog][QtWidgets][QListWidget] Speedup handling of hidden items
when working with large data sets
Task-number: QTBUG-68977
Change-Id: I599b6e97945c245f02229145baad8363ec2bf2f5
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/widgets/itemviews/qlistview.cpp | 35 | ||||
-rw-r--r-- | src/widgets/itemviews/qlistview_p.h | 8 |
2 files changed, 27 insertions, 16 deletions
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index e5769940d4..fdac332367 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -2246,8 +2246,8 @@ int QListModeViewBase::verticalScrollToValue(int index, QListView::ScrollHint hi } else { int scrollBarValue = verticalScrollBar()->value(); int numHidden = 0; - for (int i = 0; i < flowPositions.count() - 1 && i <= scrollBarValue; ++i) - if (isHidden(i)) + for (const auto &idx : qAsConst(dd->hiddenRows)) + if (idx.row() <= scrollBarValue) ++numHidden; value = qBound(0, scrollValueMap.at(verticalScrollBar()->value()) - numHidden, flowPositions.count() - 1); } @@ -2687,21 +2687,24 @@ int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int view return scrollValue; itemExtent += spacing(); - QVector<int> visibleFlowPositions; - visibleFlowPositions.reserve(flowPositions.count() - 1); - for (int i = 0; i < flowPositions.count() - 1; i++) { // flowPositions count is +1 larger than actual row count - if (!isHidden(i)) - visibleFlowPositions.append(flowPositions.at(i)); - } - + QVector<int> hiddenRows = dd->hiddenRowIds(); + std::sort(hiddenRows.begin(), hiddenRows.end()); + int hiddenRowsBefore = 0; + for (int i = 0; i < hiddenRows.size() - 1; ++i) + if (hiddenRows.at(i) > index + hiddenRowsBefore) + break; + else + ++hiddenRowsBefore; if (!wrap) { int topIndex = index; const int bottomIndex = topIndex; - const int bottomCoordinate = visibleFlowPositions.at(index); - + const int bottomCoordinate = flowPositions.at(index + hiddenRowsBefore); while (topIndex > 0 && - (bottomCoordinate - visibleFlowPositions.at(topIndex - 1) + itemExtent) <= (viewportSize)) { + (bottomCoordinate - flowPositions.at(topIndex + hiddenRowsBefore - 1) + itemExtent) <= (viewportSize)) { topIndex--; + // will the next one be a hidden row -> skip + while (hiddenRowsBefore > 0 && hiddenRows.at(hiddenRowsBefore - 1) >= topIndex + hiddenRowsBefore - 1) + hiddenRowsBefore--; } const int itemCount = bottomIndex - topIndex + 1; @@ -2720,7 +2723,7 @@ int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int view ? Qt::Horizontal : Qt::Vertical); if (flowOrientation == orientation) { // scrolling in the "flow" direction // ### wrapped scrolling in the flow direction - return visibleFlowPositions.at(index); // ### always pixel based for now + return flowPositions.at(index + hiddenRowsBefore); // ### always pixel based for now } else if (!segmentStartRows.isEmpty()) { // we are scrolling in the "segment" direction int segment = qBinarySearch<int>(segmentStartRows, index, 0, segmentStartRows.count() - 1); int leftSegment = segment; @@ -3354,9 +3357,9 @@ int QListView::visualIndex(const QModelIndex &index) const d->executePostedLayout(); QListViewItem itm = d->indexToListViewItem(index); int visualIndex = d->commonListView->itemIndex(itm); - for (int row = 0; row <= index.row() && visualIndex >= 0; row++) { - if (d->isHidden(row)) - visualIndex--; + for (const auto &idx : qAsConst(d->hiddenRows)) { + if (idx.row() <= index.row()) + --visualIndex; } return visualIndex; } diff --git a/src/widgets/itemviews/qlistview_p.h b/src/widgets/itemviews/qlistview_p.h index 181386d4d0..3f997ef7e3 100644 --- a/src/widgets/itemviews/qlistview_p.h +++ b/src/widgets/itemviews/qlistview_p.h @@ -377,6 +377,14 @@ public: QModelIndex idx = model->index(row, 0, root); return isPersistent(idx) && hiddenRows.contains(idx); } + // helper to avoid checking for isPersistent and creating persistent indexes as above in isHidden + QVector<int> hiddenRowIds() const { + QVector<int> rowIds; + rowIds.reserve(hiddenRows.size()); + for (const auto &idx : hiddenRows) + rowIds += idx.row(); + return rowIds; + } inline bool isHiddenOrDisabled(int row) const { return isHidden(row) || !isIndexEnabled(modelIndex(row)); } void removeCurrentAndDisabled(QVector<QModelIndex> *indexes, const QModelIndex ¤t) const; |