diff options
-rw-r--r-- | src/widgets/itemviews/qlistview.cpp | 26 | ||||
-rw-r--r-- | tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp | 62 |
2 files changed, 84 insertions, 4 deletions
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index b7a4ec3925..f3fd3e75a1 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1846,8 +1846,17 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded && qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded; - if (bothScrollBarsAuto && contentsSize.width() - qq->verticalScrollBar()->width() <= viewport()->width() - && contentsSize.height() - qq->horizontalScrollBar()->height() <= viewport()->height()) { + const QSize viewportSize(viewport()->width() + (qq->verticalScrollBar()->maximum() > 0 ? qq->verticalScrollBar()->width() : 0), + viewport()->height() + (qq->horizontalScrollBar()->maximum() > 0 ? qq->horizontalScrollBar()->height() : 0)); + + bool verticalWantsToShow = contentsSize.height() > viewportSize.height(); + bool horizontalWantsToShow; + if (verticalWantsToShow) + horizontalWantsToShow = contentsSize.width() > viewportSize.width() - qq->verticalScrollBar()->width(); + else + horizontalWantsToShow = contentsSize.width() > viewportSize.width(); + + if (bothScrollBarsAuto && !horizontalWantsToShow) { // break the infinite loop described above by setting the range to 0, 0. // QAbstractScrollArea will then hide the scroll bar for us horizontalScrollBar()->setRange(0, 0); @@ -1868,8 +1877,17 @@ void QCommonListViewBase::updateVerticalScrollBar(const QSize &step) const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded && qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded; - if (bothScrollBarsAuto && contentsSize.width() - qq->verticalScrollBar()->width() <= viewport()->width() - && contentsSize.height() - qq->horizontalScrollBar()->height() <= viewport()->height()) { + const QSize viewportSize(viewport()->width() + (qq->verticalScrollBar()->maximum() > 0 ? qq->verticalScrollBar()->width() : 0), + viewport()->height() + (qq->horizontalScrollBar()->maximum() > 0 ? qq->horizontalScrollBar()->height() : 0)); + + bool horizontalWantsToShow = contentsSize.width() > viewportSize.width(); + bool verticalWantsToShow; + if (horizontalWantsToShow) + verticalWantsToShow = contentsSize.height() > viewportSize.height() - qq->horizontalScrollBar()->height(); + else + verticalWantsToShow = contentsSize.height() > viewportSize.height(); + + if (bothScrollBarsAuto && !verticalWantsToShow) { // break the infinite loop described above by setting the range to 0, 0. // QAbstractScrollArea will then hide the scroll bar for us verticalScrollBar()->setRange(0, 0); diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index cea08435c9..32ca5ea7b7 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -47,6 +47,7 @@ #include <QtWidgets/QScrollBar> #include <QtWidgets/QDialog> #include <QtWidgets/QStyledItemDelegate> +#include <QtWidgets/QStyleFactory> #if defined(Q_OS_WIN) || defined(Q_OS_WINCE) # include <windows.h> @@ -2348,11 +2349,34 @@ void tst_QListView::testViewOptions() QCOMPARE(options.decorationPosition, QStyleOptionViewItem::Top); } +// make sure we have no transient scroll bars +class TempStyleSetter +{ +public: + TempStyleSetter() + : m_oldStyle(qApp->style()) + { + m_oldStyle->setParent(0); + QListView tempView; + if (QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, tempView.horizontalScrollBar())) + QApplication::setStyle(QStyleFactory::create("Fusion")); + } + + ~TempStyleSetter() + { + QApplication::setStyle(m_oldStyle); + } +private: + QStyle* m_oldStyle; +}; + void tst_QListView::taskQTBUG_39902_mutualScrollBars() { QWidget window; window.resize(400, 300); QListView *view = new QListView(&window); + // make sure we have no transient scroll bars + TempStyleSetter styleSetter; QStandardItemModel model(200, 1); const QSize itemSize(100, 20); for (int i = 0; i < model.rowCount(); ++i) @@ -2370,6 +2394,44 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars() view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2); // this will end up in a stack overflow, if QTBUG-39902 is not fixed QTest::qWait(100); + + // these tests do not apply with transient scroll bars enabled + QVERIFY (!view->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, view->horizontalScrollBar())); + + // make it double as large, no scroll bars should be visible + view->resize((itemSize.width() + view->frameWidth() * 2) * 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2); + QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); + QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); + + // make it half the size, both scroll bars should be visible + view->resize((itemSize.width() + view->frameWidth() * 2) / 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) / 2); + QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); + QTRY_VERIFY(view->verticalScrollBar()->isVisible()); + + // make it double as large, no scroll bars should be visible + view->resize((itemSize.width() + view->frameWidth() * 2) * 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2); + QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); + QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); + + // now, coming from the double size, resize it to the exactly matching size, still no scroll bars should be visible again + view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2); + QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); + QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); + + // now remove just one single pixel in height -> both scroll bars will show up since they depend on each other + view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2 - 1); + QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); + QTRY_VERIFY(view->verticalScrollBar()->isVisible()); + + // now remove just one single pixel in with -> both scroll bars will show up since they depend on each other + view->resize(itemSize.width() + view->frameWidth() * 2 - 1, model.rowCount() * itemSize.height() + view->frameWidth() * 2); + QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); + QTRY_VERIFY(view->verticalScrollBar()->isVisible()); + + // finally, coming from a size being to small, resize back to the exactly matching size -> both scroll bars should disappear again + view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2); + QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); + QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); } QTEST_MAIN(tst_QListView) |