summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Penz <peter.penz19@gmail.com>2012-02-05 18:14:17 (GMT)
committerPeter Penz <peter.penz19@gmail.com>2012-02-05 18:21:58 (GMT)
commit81034de5074071d45bd4da212c80fb3dd5ea4933 (patch)
tree8a183541a0da0b822b182a83a2fd20166b13fc54
parent5a45d5d32128ea525e0a392f96a9e8c1b914c788 (diff)
Fix potential endless loop in layout
Usecase: - No scrollbar is shown - Window size will be decreased so that a scrollbar gets necessary The decreased window size minus the space required for the scrollbar results in a relayout of the items. In 99 % of all cases a decreased window size won't result in showing more items in parallel in comparison to a larger window size. However in the remaining 1 % this can happen (e.g. see bug 293318 for a sample). This results in an endless loop as now no scrollbar is required anymore, the layout changes again, the scrollbar is required again, ... BUG: 293318 FIXED-IN: 4.8.1
-rw-r--r--dolphin/src/kitemviews/kitemlistcontainer.cpp34
-rw-r--r--dolphin/src/kitemviews/kitemlistcontainer.h7
-rw-r--r--dolphin/src/kitemviews/kitemlistview.cpp13
-rw-r--r--dolphin/src/kitemviews/kitemlistview.h8
4 files changed, 62 insertions, 0 deletions
diff --git a/dolphin/src/kitemviews/kitemlistcontainer.cpp b/dolphin/src/kitemviews/kitemlistcontainer.cpp
index 58f2e3c..b480b44 100644
--- a/dolphin/src/kitemviews/kitemlistcontainer.cpp
+++ b/dolphin/src/kitemviews/kitemlistcontainer.cpp
@@ -234,11 +234,19 @@ void KItemListContainer::updateScrollOffsetScrollBar()
const int value = view->scrollOffset();
const int maximum = qMax(0, int(view->maximumScrollOffset() - pageStep));
if (smoothScroller->requestScrollBarUpdate(maximum)) {
+ const bool updatePolicy = (scrollOffsetScrollBar->maximum() > 0 && maximum == 0)
+ || horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOn;
+
scrollOffsetScrollBar->setSingleStep(singleStep);
scrollOffsetScrollBar->setPageStep(pageStep);
scrollOffsetScrollBar->setMinimum(0);
scrollOffsetScrollBar->setMaximum(maximum);
scrollOffsetScrollBar->setValue(value);
+
+ if (updatePolicy) {
+ // Prevent a potential endless layout loop (see bug #293318).
+ updateScrollOffsetScrollBarPolicy();
+ }
}
}
@@ -320,6 +328,32 @@ void KItemListContainer::updateSmoothScrollers(Qt::Orientation orientation)
}
}
+void KItemListContainer::updateScrollOffsetScrollBarPolicy()
+{
+ const KItemListView* view = m_controller->view();
+ Q_ASSERT(view);
+ const bool vertical = (view->scrollOrientation() == Qt::Vertical);
+
+ QStyleOption option;
+ option.initFrom(this);
+ const int scrollBarInc = style()->pixelMetric(QStyle::PM_ScrollBarExtent, &option, this);
+
+ QSizeF newViewSize = m_controller->view()->size();
+ if (vertical) {
+ newViewSize.rwidth() += scrollBarInc;
+ } else {
+ newViewSize.rheight() += scrollBarInc;
+ }
+
+ const Qt::ScrollBarPolicy policy = view->scrollBarRequired(newViewSize)
+ ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAsNeeded;
+ if (vertical) {
+ setVerticalScrollBarPolicy(policy);
+ } else {
+ setHorizontalScrollBarPolicy(policy);
+ }
+}
+
void KItemListContainer::initialize()
{
if (m_controller) {
diff --git a/dolphin/src/kitemviews/kitemlistcontainer.h b/dolphin/src/kitemviews/kitemlistcontainer.h
index 4d6eadb..b41f48a 100644
--- a/dolphin/src/kitemviews/kitemlistcontainer.h
+++ b/dolphin/src/kitemviews/kitemlistcontainer.h
@@ -70,6 +70,13 @@ private:
void updateGeometries();
void updateSmoothScrollers(Qt::Orientation orientation);
+ /**
+ * Helper method for updateScrollOffsetScrollBar(). Updates the scrollbar-policy
+ * to Qt::ScrollBarAlwaysOn for cases where turning off the scrollbar might lead
+ * to an endless layout loop (see bug #293318).
+ */
+ void updateScrollOffsetScrollBarPolicy();
+
private:
KItemListController* m_controller;
diff --git a/dolphin/src/kitemviews/kitemlistview.cpp b/dolphin/src/kitemviews/kitemlistview.cpp
index c671a2e..52d8577 100644
--- a/dolphin/src/kitemviews/kitemlistview.cpp
+++ b/dolphin/src/kitemviews/kitemlistview.cpp
@@ -1880,6 +1880,19 @@ bool KItemListView::animateChangedItemCount(int changedItemCount) const
return changedItemCount <= maximum * 2 / 3;
}
+
+bool KItemListView::scrollBarRequired(const QSizeF& size) const
+{
+ const QSizeF oldSize = m_layouter->size();
+
+ m_layouter->setSize(size);
+ const qreal maxOffset = m_layouter->maximumScrollOffset();
+ m_layouter->setSize(oldSize);
+
+ return m_layouter->scrollOrientation() == Qt::Vertical ? maxOffset > size.height()
+ : maxOffset > size.width();
+}
+
int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldInc)
{
int inc = 0;
diff --git a/dolphin/src/kitemviews/kitemlistview.h b/dolphin/src/kitemviews/kitemlistview.h
index 9c34dab..e675df2 100644
--- a/dolphin/src/kitemviews/kitemlistview.h
+++ b/dolphin/src/kitemviews/kitemlistview.h
@@ -462,6 +462,13 @@ private:
bool animateChangedItemCount(int changedItemCount) const;
/**
+ * @return True if a scrollbar for the given scroll-orientation is required
+ * when using a size of \p size for the view. Calling the method is rather
+ * expansive as a temporary relayout needs to be done.
+ */
+ bool scrollBarRequired(const QSizeF& size) const;
+
+ /**
* Helper function for triggerAutoScrolling().
* @param pos Logical position of the mouse relative to the range.
* @param range Range of the visible area.
@@ -512,6 +519,7 @@ private:
KItemListHeader* m_header;
bool m_useHeaderWidths;
+ friend class KItemListContainer; // Accesses scrollBarRequired()
friend class KItemListController;
friend class KItemListControllerTest;
};