From 6c1388ee5a3c4796d7ce09f0cbbc1700ab574ce4 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 20 Oct 2009 10:39:42 +0200 Subject: Fixed wrong scrolling in QListView with hidden rows in ListMode The flow positions in ScrollPerItem mode did not take the hidden rows into account when configuring the vertical scroll bar. A mapping between the scroll bar value and the flow position has been added. Auto-test included. Task-number: QTBUG-2233 Reviewed-by: Thierry --- src/gui/itemviews/qlistview.cpp | 24 +++++++++++++++++------- src/gui/itemviews/qlistview_p.h | 1 + tests/auto/qlistview/tst_qlistview.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 1d9b6e0..88002e0 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -1900,7 +1900,7 @@ void QListModeViewBase::updateVerticalScrollBar(const QSize &step) if (verticalScrollMode() == QAbstractItemView::ScrollPerItem && ((flow() == QListView::TopToBottom && !isWrapping()) || (flow() == QListView::LeftToRight && isWrapping()))) { - const int steps = (flow() == QListView::TopToBottom ? flowPositions : segmentPositions).count() - 1; + const int steps = (flow() == QListView::TopToBottom ? scrollValueMap : segmentPositions).count() - 1; if (steps > 0) { const int pageSteps = perItemScrollingPageSteps(viewport()->height(), contentsSize.height(), isWrapping()); verticalScrollBar()->setSingleStep(1); @@ -1939,7 +1939,7 @@ int QListModeViewBase::verticalScrollToValue(int index, QListView::ScrollHint hi bool above, bool below, const QRect &area, const QRect &rect) const { if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { - int value = qBound(0, verticalScrollBar()->value(), flowPositions.count() - 1); + int value = qBound(0, scrollValueMap.at(verticalScrollBar()->value()), flowPositions.count() - 1); if (above) hint = QListView::PositionAtTop; else if (below) @@ -1986,9 +1986,9 @@ int QListModeViewBase::verticalOffset() const } } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) { int value = verticalScrollBar()->value(); - if (value > flowPositions.count()) + if (value > scrollValueMap.count()) return 0; - return flowPositions.at(value) - spacing(); + return flowPositions.at(scrollValueMap.at(value)) - spacing(); } } return QCommonListViewBase::verticalOffset(); @@ -2043,8 +2043,8 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) if (vertical && flow() == QListView::TopToBottom && dy != 0) { int currentValue = qBound(0, verticalValue, max); int previousValue = qBound(0, currentValue + dy, max); - int currentCoordinate = flowPositions.at(currentValue); - int previousCoordinate = flowPositions.at(previousValue); + int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue)); + int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue)); dy = previousCoordinate - currentCoordinate; } else if (horizontal && flow() == QListView::LeftToRight && dx != 0) { int currentValue = qBound(0, horizontalValue, max); @@ -2113,6 +2113,7 @@ QPoint QListModeViewBase::initStaticLayout(const QListViewLayoutInfo &info) segmentPositions.clear(); segmentStartRows.clear(); segmentExtents.clear(); + scrollValueMap.clear(); x = info.bounds.left() + info.spacing; y = info.bounds.top() + info.spacing; segmentPositions.append(info.flow == QListView::LeftToRight ? y : x); @@ -2204,6 +2205,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) deltaSegPosition = 0; } // save the flow position of this item + scrollValueMap.append(flowPositions.count()); flowPositions.append(flowPosition); // prepare for the next item deltaSegPosition = qMax(deltaSegHint, deltaSegPosition); @@ -2229,6 +2231,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) // if it is the last batch, save the end of the segments if (info.last == info.max) { segmentExtents.append(flowPosition); + scrollValueMap.append(flowPositions.count()); flowPositions.append(flowPosition); segmentPositions.append(info.wrap ? segPosition + deltaSegPosition : INT_MAX); } @@ -2306,7 +2309,14 @@ QRect QListModeViewBase::mapToViewport(const QRect &rect) const int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const { - const QVector positions = (wrap ? segmentPositions : flowPositions); + QVector positions; + if (wrap) + positions = segmentPositions; + else { + positions.reserve(scrollValueMap.size()); + foreach (int itemShown, scrollValueMap) + positions.append(flowPositions.at(itemShown)); + } if (positions.isEmpty() || bounds <= length) return positions.count(); if (uniformItemSizes()) { diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index b6785da..de4c7f3 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -205,6 +205,7 @@ public: QVector segmentPositions; QVector segmentStartRows; QVector segmentExtents; + QVector scrollValueMap; // used when laying out in batches int batchSavedPosition; diff --git a/tests/auto/qlistview/tst_qlistview.cpp b/tests/auto/qlistview/tst_qlistview.cpp index 3ee6889..ed02317 100644 --- a/tests/auto/qlistview/tst_qlistview.cpp +++ b/tests/auto/qlistview/tst_qlistview.cpp @@ -117,6 +117,7 @@ private slots: void shiftSelectionWithNonUniformItemSizes(); void clickOnViewportClearsSelection(); void task262152_setModelColumnNavigate(); + void taskQTBUG_2233_scrollHiddenRows(); }; // Testing get/set functions @@ -1790,7 +1791,31 @@ void tst_QListView::task262152_setModelColumnNavigate() } +void tst_QListView::taskQTBUG_2233_scrollHiddenRows() +{ + const int rowCount = 200; + + QListView view; + QStringListModel model(&view); + QStringList list; + for (int i = 0; i < rowCount; ++i) + list << QString::fromAscii("Item %1").arg(i); + + model.setStringList(list); + view.setModel(&model); + view.setViewMode(QListView::ListMode); + view.setFlow(QListView::TopToBottom); + for (int i = 0; i < rowCount / 2; ++i) + view.setRowHidden(2 * i, true); + view.resize(250, 130); + for (int i = 0; i < 10; ++i) { + view.verticalScrollBar()->setValue(i); + QModelIndex index = view.indexAt(QPoint(20,0)); + QVERIFY(index.isValid()); + QCOMPARE(index.row(), 2 * i + 1); + } +} QTEST_MAIN(tst_QListView) #include "tst_qlistview.moc" -- cgit v0.12