Improve QListView scroll bar calculation.
When both scroll bar's policies are set to ScrollBarAsNeeded, make sure the scroll bars are shown if needed and not show if not. Even the corner case, where one scroll bar's visibility depends on the other, is handled properly. Task-number: QTBUG-45470 Change-Id: I11d6ccf7c0b51644a5ce2d5c3fc59e2e4812755d Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com> Reviewed-by: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
This commit is contained in:
parent
cca5cce205
commit
52c122e616
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user