]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistviewlayouter.cpp
Compact view: Padding- and margin-improvements for grouped alignments
[dolphin.git] / src / kitemviews / kitemlistviewlayouter.cpp
index 4e7a910873430185b8f69fd43168a006e3da1aff..de78b763677bdfb3b5a937d2a6d50780fd419576 100644 (file)
@@ -33,6 +33,7 @@ KItemListViewLayouter::KItemListViewLayouter(QObject* parent) :
     m_scrollOrientation(Qt::Vertical),
     m_size(),
     m_itemSize(128, 128),
+    m_itemMargin(),
     m_headerHeight(0),
     m_model(0),
     m_sizeHintResolver(0),
@@ -47,6 +48,7 @@ KItemListViewLayouter::KItemListViewLayouter(QObject* parent) :
     m_columnCount(0),
     m_groupItemIndexes(),
     m_groupHeaderHeight(0),
+    m_groupHeaderMargin(0),
     m_itemRects()
 {
 }
@@ -94,6 +96,19 @@ QSizeF KItemListViewLayouter::itemSize() const
     return m_itemSize;
 }
 
+void KItemListViewLayouter::setItemMargin(const QSizeF& margin)
+{
+    if (m_itemMargin != margin) {
+        m_itemMargin = margin;
+        m_dirty = true;
+    }
+}
+
+QSizeF KItemListViewLayouter::itemMargin() const
+{
+    return m_itemMargin;
+}
+
 void KItemListViewLayouter::setHeaderHeight(qreal height)
 {
     if (m_headerHeight != height) {
@@ -120,6 +135,19 @@ qreal KItemListViewLayouter::groupHeaderHeight() const
     return m_groupHeaderHeight;
 }
 
+void KItemListViewLayouter::setGroupHeaderMargin(qreal margin)
+{
+    if (m_groupHeaderMargin != margin) {
+        m_groupHeaderMargin = margin;
+        m_dirty = true;
+    }
+}
+
+qreal KItemListViewLayouter::groupHeaderMargin() const
+{
+    return m_groupHeaderMargin;
+}
+
 void KItemListViewLayouter::setScrollOffset(qreal offset)
 {
     if (m_scrollOffset != offset) {
@@ -229,14 +257,36 @@ QRectF KItemListViewLayouter::groupHeaderRect(int index) const
         return QRectF();
     }
 
-    pos.ry() -= m_groupHeaderHeight;
-
     QSizeF size;
     if (m_scrollOrientation == Qt::Vertical) {
         pos.rx() = 0;
+        pos.ry() -= m_groupHeaderHeight;
         size = QSizeF(m_size.width(), m_groupHeaderHeight);
     } else {
-        size = QSizeF(minimumGroupHeaderWidth(), m_groupHeaderHeight);
+        pos.rx() -= m_itemMargin.width();
+        pos.ry() = 0;
+        
+        // Determine the maximum width used in the
+        // current column. As the scroll-direction is
+        // Qt::Horizontal and m_itemRects is accessed directly,
+        // the logical height represents the visual width.
+        qreal width = minimumGroupHeaderWidth();
+        const qreal y = m_itemRects[index].y();
+        const int maxIndex = m_itemRects.count() - 1;
+        while (index <= maxIndex) {
+            QRectF bounds = m_itemRects[index];
+            if (bounds.y() != y) {
+                break;
+            }
+            
+            if (bounds.height() > width) {
+                width = bounds.height();
+            }
+            
+            ++index;           
+        }
+        
+        size = QSizeF(width, m_size.height());
     }
     return QRectF(pos, size);
 }
@@ -276,24 +326,39 @@ void KItemListViewLayouter::doLayout()
         m_visibleIndexesDirty = true;
 
         QSizeF itemSize = m_itemSize;
+        QSizeF itemMargin = m_itemMargin;
         QSizeF size = m_size;
+        
+        const bool grouped = createGroupHeaders();
 
         const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
         if (horizontalScrolling) {
+            // Flip everything so that the layout logically can work like having
+            // a vertical scrolling
             itemSize.setWidth(m_itemSize.height());
             itemSize.setHeight(m_itemSize.width());
+            itemMargin.setWidth(m_itemMargin.height());
+            itemMargin.setHeight(m_itemMargin.width());
             size.setWidth(m_size.height());
             size.setHeight(m_size.width());
+            
+            if (grouped) {
+                // In the horizontal scrolling case all groups are aligned
+                // at the top, which decreases the available height. For the
+                // flipped data this means that the width must be decreased.
+                size.rwidth() -= m_groupHeaderHeight;
+            }
         }
 
-        m_columnWidth = itemSize.width();
-        m_columnCount = qMax(1, int(size.width() / m_columnWidth));
-        m_xPosInc = 0;
+        m_columnWidth = itemSize.width() + itemMargin.width();
+        const qreal widthForColumns = size.width() - itemMargin.width();
+        m_columnCount = qMax(1, int(widthForColumns / m_columnWidth));
+        m_xPosInc = itemMargin.width();
 
         const int itemCount = m_model->count();
-        if (itemCount > m_columnCount) {
+        if (itemCount > m_columnCount && m_columnWidth >= 32) {
             // Apply the unused width equally to each column
-            const qreal unusedWidth = size.width() - m_columnCount * m_columnWidth;
+            const qreal unusedWidth = widthForColumns - m_columnCount * m_columnWidth;
             if (unusedWidth > 0) {
                 const qreal columnInc = unusedWidth / (m_columnCount + 1);
                 m_columnWidth += columnInc;
@@ -308,11 +373,9 @@ void KItemListViewLayouter::doLayout()
 
         m_itemRects.reserve(itemCount);
 
-        qreal y = m_headerHeight;
+        qreal y = m_headerHeight + itemMargin.height();
         int rowIndex = 0;
 
-        const bool grouped = createGroupHeaders();
-
         int index = 0;
         while (index < itemCount) {
             qreal x = m_xPosInc;
@@ -326,10 +389,19 @@ void KItemListViewLayouter::doLayout()
                 }
 
                 if (m_groupItemIndexes.contains(index)) {
+                    // The item is the first item of a group.
+                    // Increase the y-position to provide space
+                    // for the group header.
+                    if (index == 0) {
+                        // The first group header should be aligned on top
+                        y -= itemMargin.height();
+                    } else {
+                        // Only add a margin if there has been added another
+                        // group already before
+                        y += m_groupHeaderMargin;
+                    }
+                    
                     if (!horizontalScrolling) {
-                        // The item is the first item of a group.
-                        // Increase the y-position to provide space
-                        // for the group header.
                         y += m_groupHeaderHeight;
                     }
                 }
@@ -384,12 +456,12 @@ void KItemListViewLayouter::doLayout()
                 }
             }
 
-            y += maxItemHeight;
+            y += maxItemHeight + itemMargin.height();
             ++rowIndex;
         }
         if (m_itemRects.count() > itemCount) {
             m_itemRects.erase(m_itemRects.begin() + itemCount,
-                                      m_itemRects.end());
+                              m_itemRects.end());
         }
 
         if (itemCount > 0) {
@@ -403,6 +475,8 @@ void KItemListViewLayouter::doLayout()
                 --index;
             }
 
+            m_maximumScrollOffset += itemMargin.height();
+
             m_maximumItemOffset = m_columnCount * m_columnWidth;
         } else {
             m_maximumScrollOffset = 0;
@@ -512,7 +586,7 @@ bool KItemListViewLayouter::createGroupHeaders()
 
 qreal KItemListViewLayouter::minimumGroupHeaderWidth() const
 {
-    return m_groupHeaderHeight * 15 / 2;
+    return 100;
 }
 
 #include "kitemlistviewlayouter_p.moc"