]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistview.cpp
Make PageUp/PageDown work in Dolphin's new view engine
[dolphin.git] / src / kitemviews / kitemlistview.cpp
index be03606cea158deac84f66867b79954f5a4bcc37..b6af42849da49acad3e455c761b2b25da0adf6d9 100644 (file)
@@ -201,13 +201,19 @@ qreal KItemListView::maximumScrollOffset() const
 
 void KItemListView::setItemOffset(qreal offset)
 {
+    if (m_layouter->itemOffset() == offset) {
+        return;
+    }
+
     m_layouter->setItemOffset(offset);
     if (m_header) {
         m_header->setPos(-offset, 0);
     }
-    if (!m_layoutTimer->isActive()) {
-        doLayout(NoAnimation);
-    }
+
+    // Don't check whether the m_layoutTimer is active: Changing the
+    // item offset must always trigger a synchronous layout, otherwise
+    // the smooth-scrolling might get jerky.
+    doLayout(NoAnimation);
 }
 
 qreal KItemListView::itemOffset() const
@@ -349,20 +355,55 @@ void KItemListView::setGeometry(const QRectF& rect)
         return;
     }
 
-    if (m_model->count() > 0) {
-        prepareLayoutForIncreasedItemCount(rect.size(), LayouterSize);
+    const QSizeF newSize = rect.size();
+    if (m_itemSize.isEmpty()) {
+        // The item size is dynamic:
+        // Changing the geometry does not require to do an expensive
+        // update of the visible-roles sizes, only the stretched sizes
+        // need to be adjusted to the new size.
+        updateStretchedVisibleRolesSizes();
+        
+        if (m_useHeaderWidths) {
+            QSizeF dynamicItemSize = m_layouter->itemSize();
+    
+            if (m_itemSize.width() < 0) {
+                const qreal requiredWidth = visibleRolesSizesWidthSum();
+                if (newSize.width() > requiredWidth) {
+                    dynamicItemSize.setWidth(newSize.width());
+                }
+                const qreal headerWidth = qMax(newSize.width(), requiredWidth);
+                m_header->resize(headerWidth, m_header->size().height());
+            }
+    
+            if (m_itemSize.height() < 0) {
+                const qreal requiredHeight = visibleRolesSizesHeightSum();
+                if (newSize.height() > requiredHeight) {
+                    dynamicItemSize.setHeight(newSize.height());
+                }
+                // TODO: KItemListHeader is not prepared for vertical alignment
+            }
+    
+            m_layouter->setItemSize(dynamicItemSize);
+        }
+        
+        // Triggering a synchronous layout is fine from a performance point of view,
+        // as with dynamic item sizes no moving animation must be done.
+        m_layouter->setSize(newSize);
+        doLayout(Animation);
     } else {
-        m_layouter->setSize(rect.size());
-    }
+        // The item size is not dynamic and most probably the geometry change results
+        // in animated position changes of the items. Trigger an asynchronous relayout
+        // with m_layoutTimer to prevent performance bottlenecks.
+        if (m_model->count() > 0) {
+            prepareLayoutForIncreasedItemCount(newSize, LayouterSize);
+        } else {
+            m_layouter->setSize(newSize);
+        }
 
-    if (!m_layoutTimer->isActive()) {
-        m_layoutTimer->start();
+        if (!m_layoutTimer->isActive()) {
+            m_layoutTimer->start();
+        }
     }
-
-    // Changing the geometry does not require to do an expensive
-    // update of the visible-roles sizes, only the stretched sizes
-    // need to be adjusted to the new size.
-    updateStretchedVisibleRolesSizes();
 }
 
 int KItemListView::itemAt(const QPointF& pos) const
@@ -383,6 +424,10 @@ int KItemListView::itemAt(const QPointF& pos) const
 
 bool KItemListView::isAboveSelectionToggle(int index, const QPointF& pos) const
 {
+    if (!m_enabledSelectionToggles) {
+        return false;
+    }
+
     const KItemListWidget* widget = m_visibleItems.value(index);
     if (widget) {
         const QRectF selectionToggleRect = widget->selectionToggleRect();
@@ -697,34 +742,6 @@ QList<KItemListWidget*> KItemListView::visibleItemListWidgets() const
     return m_visibleItems.values();
 }
 
-void KItemListView::resizeEvent(QGraphicsSceneResizeEvent* event)
-{
-    QGraphicsWidget::resizeEvent(event);
-    if (m_itemSize.isEmpty() && m_useHeaderWidths) {
-        QSizeF dynamicItemSize = m_layouter->itemSize();
-        const QSizeF newSize = event->newSize();
-
-        if (m_itemSize.width() < 0) {
-            const qreal requiredWidth = visibleRolesSizesWidthSum();
-            if (newSize.width() > requiredWidth) {
-                dynamicItemSize.setWidth(newSize.width());
-            }
-            const qreal headerWidth = qMax(newSize.width(), requiredWidth);
-            m_header->resize(headerWidth, m_header->size().height());
-        }
-
-        if (m_itemSize.height() < 0) {
-            const qreal requiredHeight = visibleRolesSizesHeightSum();
-            if (newSize.height() > requiredHeight) {
-                dynamicItemSize.setHeight(newSize.height());
-            }
-            // TODO: KItemListHeader is not prepared for vertical alignment
-        }
-
-        m_layouter->setItemSize(dynamicItemSize);
-    }
-}
-
 void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
 {
     updateVisibleRolesSizes(itemRanges);
@@ -771,15 +788,23 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
         }
 
         m_layouter->markAsDirty();
-        if (m_model->count() == count && maximumScrollOffset() > size().height()) {
-            const int scrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
-            QSizeF layouterSize = m_layouter->size();
-            if (scrollOrientation() == Qt::Vertical) {
-                layouterSize.rwidth() -= scrollBarExtent;
-            } else {
-                layouterSize.rheight() -= scrollBarExtent;
+        if (m_model->count() == count && m_activeTransactions == 0) {
+            // Check whether a scrollbar is required to show the inserted items. In this case
+            // the size of the layouter will be decreased before calling doLayout(): This prevents
+            // an unnecessary temporary animation due to the geometry change of the inserted scrollbar.
+            const bool verticalScrollOrientation = (scrollOrientation() == Qt::Vertical);
+            const bool decreaseLayouterSize = ( verticalScrollOrientation && maximumScrollOffset() > size().height()) ||
+                                              (!verticalScrollOrientation && maximumScrollOffset() > size().width());
+            if (decreaseLayouterSize) {
+                const int scrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+                QSizeF layouterSize = m_layouter->size();
+                if (verticalScrollOrientation) {
+                    layouterSize.rwidth() -= scrollBarExtent;
+                } else {
+                    layouterSize.rheight() -= scrollBarExtent;
+                }
+                m_layouter->setSize(layouterSize);
             }
-            m_layouter->setSize(layouterSize);
         }
 
         if (!hasMultipleRanges) {
@@ -863,7 +888,14 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
 
         m_layouter->markAsDirty();
         if (!hasMultipleRanges) {
+            // The decrease-layout-size optimization in KItemListView::slotItemsInserted()
+            // assumes an updated geometry. If items are removed during an active transaction,
+            // the transaction will be temporary deactivated so that doLayout() triggers a
+            // geometry update if necessary.
+            const int activeTransactions = m_activeTransactions;
+            m_activeTransactions = 0;
             doLayout(Animation, index, -count);
+            m_activeTransactions = activeTransactions;
         }
     }