From 6eb8f6fc66ebf1604457d56ffaeb7020affbb220 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 10 Sep 2014 09:39:13 +0200 Subject: QListView: Catch stack overflow on mutual scrollbar calculation. Backport of fc4993be1fa7673016b6e5d81134463f163051f6 from Qt 5. Task-number: QTBUG-39902 Task-number: QTBUG-38517 Change-Id: I66b2c7304423dd65d67158ae0dc70ad12e4fa783 Reviewed-by: Christoph Schleifenbaum Reviewed-by: Marc Mutz --- src/gui/itemviews/qlistview.cpp | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'src/gui/itemviews') diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index df908e28a5..ff1bfb3b76 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -1870,14 +1870,44 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) { horizontalScrollBar()->setSingleStep(step.width() + spacing()); horizontalScrollBar()->setPageStep(viewport()->width()); - horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width()); + + // If both scroll bars are set to auto, we might end up in a situation with enough space + // for the actual content. But still one of the scroll bars will become enabled due to + // the other one using the space. The other one will become invisible in the same cycle. + // -> Infinite loop, QTBUG-39902 + 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()) { + // 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); + } else { + horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width()); + } } void QCommonListViewBase::updateVerticalScrollBar(const QSize &step) { verticalScrollBar()->setSingleStep(step.height() + spacing()); verticalScrollBar()->setPageStep(viewport()->height()); - verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height()); + + // If both scroll bars are set to auto, we might end up in a situation with enough space + // for the actual content. But still one of the scroll bars will become enabled due to + // the other one using the space. The other one will become invisible in the same cycle. + // -> Infinite loop, QTBUG-39902 + 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()) { + // 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); + } else { + verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height()); + } } void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/) -- cgit v1.2.3