]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistview.cpp
Layout optimizations
[dolphin.git] / src / kitemviews / kitemlistview.cpp
index d090184746d0a2af4ebe68f632a5c8f6e3c4b24a..451e5183369c460cae44352f4358c7263768a781 100644 (file)
@@ -55,6 +55,7 @@ KItemListView::KItemListView(QGraphicsWidget* parent) :
     m_enabledSelectionToggles(false),
     m_grouped(false),
     m_activeTransactions(0),
+    m_endTransactionAnimationHint(Animation),
     m_itemSize(),
     m_controller(0),
     m_model(0),
@@ -125,6 +126,8 @@ void KItemListView::setScrollOrientation(Qt::Orientation orientation)
             it.next();
             it.value()->setScrollOrientation(orientation);
         }
+        updateGroupHeaderHeight();
+
     }
 
     doLayout(NoAnimation);
@@ -148,7 +151,9 @@ void KItemListView::setItemSize(const QSizeF& itemSize)
     // Skip animations when the number of rows or columns
     // are changed in the grid layout. Although the animation
     // engine can handle this usecase, it looks obtrusive.
-    const bool animate = !changesItemGridLayout(m_layouter->size(), itemSize);
+    const bool animate = !changesItemGridLayout(m_layouter->size(),
+                                                itemSize,
+                                                m_layouter->itemMargin());
     
     m_itemSize = itemSize;
 
@@ -263,7 +268,7 @@ void KItemListView::setAutoScroll(bool enabled)
 {
     if (enabled && !m_autoScrollTimer) {
         m_autoScrollTimer = new QTimer(this);
-        m_autoScrollTimer->setSingleShot(false);
+        m_autoScrollTimer->setSingleShot(true);
         connect(m_autoScrollTimer, SIGNAL(timeout()), this, SLOT(triggerAutoScrolling()));
         m_autoScrollTimer->start(InitialAutoScrollDelay);
     } else if (!enabled && m_autoScrollTimer) {
@@ -331,14 +336,31 @@ void KItemListView::setStyleOption(const KItemListStyleOption& option)
     const KItemListStyleOption previousOption = m_styleOption;
     m_styleOption = option;
 
+    bool animate = true;    
+    const QSizeF margin(option.horizontalMargin, option.verticalMargin);
+    if (margin != m_layouter->itemMargin()) {
+        // Skip animations when the number of rows or columns
+        // are changed in the grid layout. Although the animation
+        // engine can handle this usecase, it looks obtrusive.
+        animate = !changesItemGridLayout(m_layouter->size(),
+                                         m_layouter->itemSize(),
+                                         margin);
+        m_layouter->setItemMargin(margin);
+    }
+
+    if (m_grouped) {
+        updateGroupHeaderHeight();
+    }
+
     QHashIterator<int, KItemListWidget*> it(m_visibleItems);
     while (it.hasNext()) {
         it.next();
         it.value()->setStyleOption(option);
     }
 
-    m_sizeHintResolver->clearCache();
-    doLayout(Animation);
+    m_sizeHintResolver->clearCache();   
+    doLayout(animate ? Animation : NoAnimation);
+
     onStyleOptionChanged(option, previousOption);
 }
 
@@ -391,7 +413,9 @@ void KItemListView::setGeometry(const QRectF& rect)
         m_layouter->setSize(newSize);
         doLayout(Animation);
     } else {
-        const bool animate = !changesItemGridLayout(newSize, m_layouter->itemSize());        
+        const bool animate = !changesItemGridLayout(newSize,
+                                                    m_layouter->itemSize(),
+                                                    m_layouter->itemMargin());        
         m_layouter->setSize(newSize);
         
         if (animate) {
@@ -548,7 +572,8 @@ void KItemListView::endTransaction()
 
     if (m_activeTransactions == 0) {
         onTransactionEnd();
-        doLayout(NoAnimation);
+        doLayout(m_endTransactionAnimationHint);
+        m_endTransactionAnimationHint = Animation;
     }
 }
 
@@ -557,7 +582,6 @@ bool KItemListView::isTransactionActive() const
     return m_activeTransactions > 0;
 }
 
-
 void KItemListView::setHeaderShown(bool show)
 {
 
@@ -893,7 +917,7 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
             // geometry update if necessary.
             const int activeTransactions = m_activeTransactions;
             m_activeTransactions = 0;
-            doLayout(animateChangedItemCount(count) ? Animation : NoAnimation, index, -count);            
+            doLayout(animateChangedItemCount(count) ? Animation : NoAnimation, index, -count);
             m_activeTransactions = activeTransactions;
         }
     }
@@ -978,12 +1002,7 @@ void KItemListView::slotGroupedSortingChanged(bool current)
     m_layouter->markAsDirty();
 
     if (m_grouped) {
-        // Apply the height of the header to the layouter
-        const qreal groupHeaderHeight = m_styleOption.fontMetrics.height() +
-                                        m_styleOption.margin * 2;
-        m_layouter->setGroupHeaderHeight(groupHeaderHeight);
-
-        updateVisibleGroupHeaders();
+        updateGroupHeaderHeight();
     } else {
         // Clear all visible headers
         QMutableHashIterator<KItemListWidget*, KItemListGroupHeader*> it (m_visibleGroups);
@@ -1287,7 +1306,16 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha
         m_layoutTimer->stop();
     }
 
-    if (!m_model || m_model->count() < 0 || m_activeTransactions > 0) {
+    if (m_activeTransactions > 0) {
+        if (hint == NoAnimation) {
+            // As soon as at least one property change should be done without animation,
+            // the whole transaction will be marked as not animated.
+            m_endTransactionAnimationHint = NoAnimation;
+        }
+        return;
+    }
+
+    if (!m_model || m_model->count() < 0) {
         return;
     }
 
@@ -1482,8 +1510,9 @@ bool KItemListView::moveWidget(KItemListWidget* widget,const QRectF& itemBounds)
         // one row in the vertical scroll-orientation or one column in the horizontal scroll-orientation.
         // Otherwise instead of a moving-animation a create-animation on the new position will be used
         // instead. This is done to prevent overlapping (and confusing) moving-animations.
-        const qreal xMax = m_itemSize.width();
-        const qreal yMax = m_itemSize.height();
+        const QSizeF itemMargin = m_layouter->itemMargin();
+        const qreal xMax = m_itemSize.width() + itemMargin.width();
+        const qreal yMax = m_itemSize.height() + itemMargin.height();
         qreal xDiff = qAbs(oldPos.x() - newPos.x());
         qreal yDiff = qAbs(oldPos.y() - newPos.y());
         if (scrollOrientation() == Qt::Vertical) {
@@ -1608,13 +1637,13 @@ void KItemListView::updateGroupHeaderForWidget(KItemListWidget* widget)
         return;
     }
 
-    KItemListGroupHeader* header = m_visibleGroups.value(widget);
-    if (!header) {
-        header = m_groupHeaderCreator->create(this);
-        header->setParentItem(widget);
-        m_visibleGroups.insert(widget, header);
+    KItemListGroupHeader* groupHeader = m_visibleGroups.value(widget);
+    if (!groupHeader) {
+        groupHeader = m_groupHeaderCreator->create(this);
+        groupHeader->setParentItem(widget);
+        m_visibleGroups.insert(widget, groupHeader);
     }
-    Q_ASSERT(header->parentItem() == widget);
+    Q_ASSERT(groupHeader->parentItem() == widget);
 
     // Determine the shown data for the header by doing a binary
     // search in the groups-list
@@ -1630,18 +1659,18 @@ void KItemListView::updateGroupHeaderForWidget(KItemListWidget* widget)
         }
     } while (groups.at(mid).first != index && min <= max);
 
-    header->setData(groups.at(mid).second);
-    header->setRole(model()->sortRole());
-    header->setStyleOption(m_styleOption);
-    header->setScrollOrientation(scrollOrientation());
+    groupHeader->setData(groups.at(mid).second);
+    groupHeader->setRole(model()->sortRole());
+    groupHeader->setStyleOption(m_styleOption);
+    groupHeader->setScrollOrientation(scrollOrientation());
 
-    header->show();
+    groupHeader->show();
 }
 
 void KItemListView::updateGroupHeaderLayout(KItemListWidget* widget)
 {
-    KItemListGroupHeader* header = m_visibleGroups.value(widget);
-    Q_ASSERT(header);
+    KItemListGroupHeader* groupHeader = m_visibleGroups.value(widget);
+    Q_ASSERT(groupHeader);
 
     const int index = widget->index();
     const QRectF groupHeaderRect = m_layouter->groupHeaderRect(index);
@@ -1651,8 +1680,8 @@ void KItemListView::updateGroupHeaderLayout(KItemListWidget* widget)
     // group header position to the relative position.
     const QPointF groupHeaderPos(groupHeaderRect.x() - itemRect.x(),
                                  - groupHeaderRect.height());
-    header->setPos(groupHeaderPos);
-    header->resize(groupHeaderRect.size());
+    groupHeader->setPos(groupHeaderPos);
+    groupHeader->resize(groupHeaderRect.size());
 }
 
 void KItemListView::recycleGroupHeaderForWidget(KItemListWidget* widget)
@@ -1838,7 +1867,9 @@ QRectF KItemListView::headerBoundaries() const
     return m_header ? m_header->geometry() : QRectF();
 }
 
-bool KItemListView::changesItemGridLayout(const QSizeF& newGridSize, const QSizeF& newItemSize) const
+bool KItemListView::changesItemGridLayout(const QSizeF& newGridSize,
+                                          const QSizeF& newItemSize,
+                                          const QSizeF& newItemMargin) const
 {
     if (newItemSize.isEmpty() || newGridSize.isEmpty()) {
         return false;
@@ -1847,16 +1878,28 @@ bool KItemListView::changesItemGridLayout(const QSizeF& newGridSize, const QSize
     if (m_layouter->scrollOrientation() == Qt::Vertical) {
         const qreal itemWidth = m_layouter->itemSize().width();
         if (itemWidth > 0) {
-            const int oldColumnCount = m_layouter->size().width() / itemWidth;
-            const int newColumnCount = newGridSize.width() / newItemSize.width();
-            return oldColumnCount != newColumnCount;
+            const int newColumnCount = itemsPerSize(newGridSize.width(),
+                                                    newItemSize.width(),
+                                                    newItemMargin.width());
+            if (m_model->count() > newColumnCount) {
+                const int oldColumnCount = itemsPerSize(m_layouter->size().width(),
+                                                        itemWidth,
+                                                        m_layouter->itemMargin().width());
+                return oldColumnCount != newColumnCount;
+            }
         }       
     } else {
         const qreal itemHeight = m_layouter->itemSize().height();
         if (itemHeight > 0) {
-            const int oldRowCount = m_layouter->size().height() / itemHeight;
-            const int newRowCount = newGridSize.height() / newItemSize.height();
-            return oldRowCount != newRowCount;
+            const int newRowCount = itemsPerSize(newGridSize.height(),
+                                                 newItemSize.height(),
+                                                 newItemMargin.height());
+            if (m_model->count() > newRowCount) {
+                const int oldRowCount = itemsPerSize(m_layouter->size().height(),
+                                                     itemHeight,
+                                                     m_layouter->itemMargin().height());
+                return oldRowCount != newRowCount;
+            }
         }               
     }
     
@@ -1876,6 +1919,29 @@ 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();
+}
+
+void KItemListView::updateGroupHeaderHeight()
+{
+    qreal groupHeaderHeight = m_styleOption.fontMetrics.height();
+    groupHeaderHeight += (scrollOrientation() == Qt::Vertical)
+                         ? m_styleOption.padding * 4 : m_styleOption.padding * 2;
+    m_layouter->setGroupHeaderHeight(groupHeaderHeight);
+
+    updateVisibleGroupHeaders();
+}
+
 int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldInc)
 {
     int inc = 0;
@@ -1902,6 +1968,13 @@ int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldIn
     return inc;
 }
 
+int KItemListView::itemsPerSize(qreal size, qreal itemSize, qreal itemMargin)
+{
+    const qreal availableSize = size - itemMargin;
+    const int count = availableSize / (itemSize + itemMargin);
+    return count;
+}
+
 
 
 KItemListCreatorBase::~KItemListCreatorBase()