]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistviewlayouter.cpp
Icon-rectangle and selection-toggle optimizations
[dolphin.git] / src / kitemviews / kitemlistviewlayouter.cpp
index 78688c9414465b6891e9b31de63c96249d1fd49d..2d02b6725102d04b5dc2ddf5dc9c58480eadf0a3 100644 (file)
 
 #include <KDebug>
 
 
 #include <KDebug>
 
-#define KITEMLISTVIEWLAYOUTER_DEBUG
-
-namespace {
-    // TODO
-    const int HeaderHeight = 50;
-};
+// #define KITEMLISTVIEWLAYOUTER_DEBUG
 
 KItemListViewLayouter::KItemListViewLayouter(QObject* parent) :
     QObject(parent),
     m_dirty(true),
     m_visibleIndexesDirty(true),
 
 KItemListViewLayouter::KItemListViewLayouter(QObject* parent) :
     QObject(parent),
     m_dirty(true),
     m_visibleIndexesDirty(true),
-    m_grouped(false),
     m_scrollOrientation(Qt::Vertical),
     m_size(),
     m_itemSize(128, 128),
     m_scrollOrientation(Qt::Vertical),
     m_size(),
     m_itemSize(128, 128),
+    m_itemMargin(),
     m_headerHeight(0),
     m_model(0),
     m_sizeHintResolver(0),
     m_headerHeight(0),
     m_model(0),
     m_sizeHintResolver(0),
-    m_offset(0),
-    m_maximumOffset(0),
+    m_scrollOffset(0),
+    m_maximumScrollOffset(0),
+    m_itemOffset(0),
+    m_maximumItemOffset(0),
     m_firstVisibleIndex(-1),
     m_lastVisibleIndex(-1),
     m_firstVisibleIndex(-1),
     m_lastVisibleIndex(-1),
-    m_firstVisibleGroupIndex(-1),
     m_columnWidth(0),
     m_xPosInc(0),
     m_columnCount(0),
     m_columnWidth(0),
     m_xPosInc(0),
     m_columnCount(0),
-    m_groups(),
-    m_groupIndexes(),
-    m_itemBoundingRects()
+    m_groupItemIndexes(),
+    m_groupHeaderHeight(0),
+    m_itemRects()
 {
 }
 
 {
 }
 
@@ -99,6 +95,19 @@ QSizeF KItemListViewLayouter::itemSize() const
     return m_itemSize;
 }
 
     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) {
 void KItemListViewLayouter::setHeaderHeight(qreal height)
 {
     if (m_headerHeight != height) {
@@ -112,17 +121,55 @@ qreal KItemListViewLayouter::headerHeight() const
     return m_headerHeight;
 }
 
     return m_headerHeight;
 }
 
-void KItemListViewLayouter::setOffset(qreal offset)
+void KItemListViewLayouter::setGroupHeaderHeight(qreal height)
+{
+    if (m_groupHeaderHeight != height) {
+        m_groupHeaderHeight = height;
+        m_dirty = true;
+    }
+}
+
+qreal KItemListViewLayouter::groupHeaderHeight() const
+{
+    return m_groupHeaderHeight;
+}
+
+void KItemListViewLayouter::setScrollOffset(qreal offset)
+{
+    if (m_scrollOffset != offset) {
+        m_scrollOffset = offset;
+        m_visibleIndexesDirty = true;
+    }
+}
+
+qreal KItemListViewLayouter::scrollOffset() const
+{
+    return m_scrollOffset;
+}
+
+qreal KItemListViewLayouter::maximumScrollOffset() const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    return m_maximumScrollOffset;
+}
+
+void KItemListViewLayouter::setItemOffset(qreal offset)
 {
 {
-    if (m_offset != offset) {
-        m_offset = offset;
+    if (m_itemOffset != offset) {
+        m_itemOffset = offset;
         m_visibleIndexesDirty = true;
     }
 }
 
         m_visibleIndexesDirty = true;
     }
 }
 
-qreal KItemListViewLayouter::offset() const
+qreal KItemListViewLayouter::itemOffset() const
 {
 {
-    return m_offset;
+    return m_itemOffset;
+}
+
+qreal KItemListViewLayouter::maximumItemOffset() const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    return m_maximumItemOffset;
 }
 
 void KItemListViewLayouter::setModel(const KItemModelBase* model)
 }
 
 void KItemListViewLayouter::setModel(const KItemModelBase* model)
@@ -151,12 +198,6 @@ const KItemListSizeHintResolver* KItemListViewLayouter::sizeHintResolver() const
     return m_sizeHintResolver;
 }
 
     return m_sizeHintResolver;
 }
 
-qreal KItemListViewLayouter::maximumOffset() const
-{
-    const_cast<KItemListViewLayouter*>(this)->doLayout();
-    return m_maximumOffset;
-}
-
 int KItemListViewLayouter::firstVisibleIndex() const
 {
     const_cast<KItemListViewLayouter*>(this)->doLayout();
 int KItemListViewLayouter::firstVisibleIndex() const
 {
     const_cast<KItemListViewLayouter*>(this)->doLayout();
@@ -169,31 +210,51 @@ int KItemListViewLayouter::lastVisibleIndex() const
     return m_lastVisibleIndex;
 }
 
     return m_lastVisibleIndex;
 }
 
-QRectF KItemListViewLayouter::itemBoundingRect(int index) const
+QRectF KItemListViewLayouter::itemRect(int index) const
 {
     const_cast<KItemListViewLayouter*>(this)->doLayout();
 {
     const_cast<KItemListViewLayouter*>(this)->doLayout();
-    if (index < 0 || index >= m_itemBoundingRects.count()) {
+    if (index < 0 || index >= m_itemRects.count()) {
         return QRectF();
     }
 
     if (m_scrollOrientation == Qt::Horizontal) {
         // Rotate the logical direction which is always vertical by 90°
         // to get the physical horizontal direction
         return QRectF();
     }
 
     if (m_scrollOrientation == Qt::Horizontal) {
         // Rotate the logical direction which is always vertical by 90°
         // to get the physical horizontal direction
-        const QRectF& b = m_itemBoundingRects[index];
+        const QRectF& b = m_itemRects[index];
         QRectF bounds(b.y(), b.x(), b.height(), b.width());
         QPointF pos = bounds.topLeft();
         QRectF bounds(b.y(), b.x(), b.height(), b.width());
         QPointF pos = bounds.topLeft();
-        pos.rx() -= m_offset;
+        pos.rx() -= m_scrollOffset;
         bounds.moveTo(pos);
         return bounds;
     }
 
         bounds.moveTo(pos);
         return bounds;
     }
 
-    QRectF bounds = m_itemBoundingRects[index];
-    QPointF pos = bounds.topLeft();
-    pos.ry() -= m_offset;
-    bounds.moveTo(pos);
+    QRectF bounds = m_itemRects[index];
+    bounds.moveTo(bounds.topLeft() - QPointF(m_itemOffset, m_scrollOffset));
     return bounds;
 }
 
     return bounds;
 }
 
+QRectF KItemListViewLayouter::groupHeaderRect(int index) const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+
+    const QRectF firstItemRect = itemRect(index);
+    QPointF pos = firstItemRect.topLeft();
+    if (pos.isNull()) {
+        return QRectF();
+    }
+
+    pos.ry() -= m_groupHeaderHeight;
+
+    QSizeF size;
+    if (m_scrollOrientation == Qt::Vertical) {
+        pos.rx() = 0;
+        size = QSizeF(m_size.width(), m_groupHeaderHeight);
+    } else {
+        size = QSizeF(minimumGroupHeaderWidth(), m_groupHeaderHeight);
+    }
+    return QRectF(pos, size);
+}
+
 int KItemListViewLayouter::maximumVisibleItems() const
 {
     const_cast<KItemListViewLayouter*>(this)->doLayout();
 int KItemListViewLayouter::maximumVisibleItems() const
 {
     const_cast<KItemListViewLayouter*>(this)->doLayout();
@@ -208,14 +269,10 @@ int KItemListViewLayouter::maximumVisibleItems() const
     return rows * m_columnCount;
 }
 
     return rows * m_columnCount;
 }
 
-int KItemListViewLayouter::itemsPerOffset() const
-{
-    return m_columnCount;
-}
-
 bool KItemListViewLayouter::isFirstGroupItem(int itemIndex) const
 {
 bool KItemListViewLayouter::isFirstGroupItem(int itemIndex) const
 {
-    return m_groupIndexes.contains(itemIndex);
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    return m_groupItemIndexes.contains(itemIndex);
 }
 
 void KItemListViewLayouter::markAsDirty()
 }
 
 void KItemListViewLayouter::markAsDirty()
@@ -233,27 +290,44 @@ void KItemListViewLayouter::doLayout()
         m_visibleIndexesDirty = true;
 
         QSizeF itemSize = m_itemSize;
         m_visibleIndexesDirty = true;
 
         QSizeF itemSize = m_itemSize;
+        QSizeF itemMargin = m_itemMargin;
         QSizeF size = m_size;
         QSizeF size = m_size;
+        
+        const bool grouped = createGroupHeaders();
 
         const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
         if (horizontalScrolling) {
 
         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());
             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());
             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();
 
         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;
             // Apply the unused width equally to each column
             const qreal unusedWidth = size.width() - m_columnCount * m_columnWidth;
-            const qreal columnInc = unusedWidth / (m_columnCount + 1);
-            m_columnWidth += columnInc;
-            m_xPosInc += columnInc;
+            if (unusedWidth > 0) {
+                const qreal columnInc = unusedWidth / (m_columnCount + 1);
+                m_columnWidth += columnInc;
+                m_xPosInc += columnInc;
+            }
         }
 
         int rowCount = itemCount / m_columnCount;
         }
 
         int rowCount = itemCount / m_columnCount;
@@ -261,9 +335,9 @@ void KItemListViewLayouter::doLayout()
             ++rowCount;
         }
 
             ++rowCount;
         }
 
-        m_itemBoundingRects.reserve(itemCount);
+        m_itemRects.reserve(itemCount);
 
 
-        qreal y = m_headerHeight;
+        qreal y = m_headerHeight + itemMargin.height();
         int rowIndex = 0;
 
         int index = 0;
         int rowIndex = 0;
 
         int index = 0;
@@ -271,6 +345,23 @@ void KItemListViewLayouter::doLayout()
             qreal x = m_xPosInc;
             qreal maxItemHeight = itemSize.height();
 
             qreal x = m_xPosInc;
             qreal maxItemHeight = itemSize.height();
 
+            if (grouped) {
+                if (horizontalScrolling) {
+                    // All group headers will always be aligned on the top and not
+                    // flipped like the other properties
+                    x += m_groupHeaderHeight;
+                }
+
+                if (m_groupItemIndexes.contains(index)) {
+                    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;
+                    }
+                }
+            }
+
             int column = 0;
             while (index < itemCount && column < m_columnCount) {
                 qreal requiredItemHeight = itemSize.height();
             int column = 0;
             while (index < itemCount && column < m_columnCount) {
                 qreal requiredItemHeight = itemSize.height();
@@ -283,40 +374,67 @@ void KItemListViewLayouter::doLayout()
                 }
 
                 const QRectF bounds(x, y, itemSize.width(), requiredItemHeight);
                 }
 
                 const QRectF bounds(x, y, itemSize.width(), requiredItemHeight);
-                if (index < m_itemBoundingRects.count()) {
-                    m_itemBoundingRects[index] = bounds;
+                if (index < m_itemRects.count()) {
+                    m_itemRects[index] = bounds;
                 } else {
                 } else {
-                    m_itemBoundingRects.append(bounds);
+                    m_itemRects.append(bounds);
+                }
+
+                if (grouped && horizontalScrolling) {
+                    // When grouping is enabled in the horizontal mode, the header alignment
+                    // looks like this:
+                    //   Header-1 Header-2 Header-3
+                    //   Item 1   Item 4   Item 7
+                    //   Item 2   Item 5   Item 8
+                    //   Item 3   Item 6   Item 9
+                    // In this case 'requiredItemHeight' represents the column-width. We don't
+                    // check the content of the header in the layouter to determine the required
+                    // width, hence assure that at least a minimal width of 15 characters is given
+                    // (in average a character requires the halve width of the font height).
+                    //
+                    // TODO: Let the group headers provide a minimum width and respect this width here
+                    const qreal headerWidth = minimumGroupHeaderWidth();
+                    if (requiredItemHeight < headerWidth) {
+                        requiredItemHeight = headerWidth;
+                    }
                 }
 
                 maxItemHeight = qMax(maxItemHeight, requiredItemHeight);
                 x += m_columnWidth;
                 ++index;
                 ++column;
                 }
 
                 maxItemHeight = qMax(maxItemHeight, requiredItemHeight);
                 x += m_columnWidth;
                 ++index;
                 ++column;
+
+                if (grouped && m_groupItemIndexes.contains(index)) {
+                    // The item represents the first index of a group
+                    // and must aligned in the first column
+                    break;
+                }
             }
 
             }
 
-            y += maxItemHeight;
+            y += maxItemHeight + itemMargin.height();
             ++rowIndex;
         }
             ++rowIndex;
         }
-        if (m_itemBoundingRects.count() > itemCount) {
-            m_itemBoundingRects.erase(m_itemBoundingRects.begin() + itemCount,
-                                      m_itemBoundingRects.end());
+        if (m_itemRects.count() > itemCount) {
+            m_itemRects.erase(m_itemRects.begin() + itemCount,
+                              m_itemRects.end());
         }
 
         }
 
-        m_maximumOffset = (itemCount > 0) ? m_itemBoundingRects.last().bottom() : 0;
+        if (itemCount > 0) {
+            // Calculate the maximum y-range of the last row for m_maximumScrollOffset
+            m_maximumScrollOffset = m_itemRects.last().bottom();
+            const qreal rowY = m_itemRects.last().y();
 
 
-        m_grouped = !m_model->groupRole().isEmpty();
-        /*if (m_grouped) {
-            createGroupHeaders();
-
-            const int lastGroupItemCount = m_model->count() - m_groups.last().firstItemIndex;
-            m_maximumOffset = m_groups.last().y + (lastGroupItemCount / m_columnCount) * m_rowHeight;
-            if (lastGroupItemCount % m_columnCount != 0) {
-                m_maximumOffset += m_rowHeight;
+            int index = m_itemRects.count() - 2;
+            while (index >= 0 && m_itemRects.at(index).bottom() >= rowY) {
+                m_maximumScrollOffset = qMax(m_maximumScrollOffset, m_itemRects.at(index).bottom());
+                --index;
             }
             }
-        } else {*/
-         //   m_maximumOffset = m_minimumRowHeight * rowCount;
-        //}
+
+            m_maximumItemOffset = m_columnCount * m_columnWidth;
+        } else {
+            m_maximumScrollOffset = 0;
+            m_maximumItemOffset = 0;
+        }
 
 #ifdef KITEMLISTVIEWLAYOUTER_DEBUG
         kDebug() << "[TIME] doLayout() for " << m_model->count() << "items:" << timer.elapsed();
 
 #ifdef KITEMLISTVIEWLAYOUTER_DEBUG
         kDebug() << "[TIME] doLayout() for " << m_model->count() << "items:" << timer.elapsed();
@@ -324,11 +442,7 @@ void KItemListViewLayouter::doLayout()
         m_dirty = false;
     }
 
         m_dirty = false;
     }
 
-    if (m_grouped) {
-        updateGroupedVisibleIndexes();
-    } else {
-        updateVisibleIndexes();
-    }
+    updateVisibleIndexes();
 }
 
 void KItemListViewLayouter::updateVisibleIndexes()
 }
 
 void KItemListViewLayouter::updateVisibleIndexes()
@@ -337,7 +451,6 @@ void KItemListViewLayouter::updateVisibleIndexes()
         return;
     }
 
         return;
     }
 
-    Q_ASSERT(!m_grouped);
     Q_ASSERT(!m_dirty);
 
     if (m_model->count() <= 0) {
     Q_ASSERT(!m_dirty);
 
     if (m_model->count() <= 0) {
@@ -347,146 +460,86 @@ void KItemListViewLayouter::updateVisibleIndexes()
         return;
     }
 
         return;
     }
 
-    const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
-    const int minimumHeight =  horizontalScrolling ? m_itemSize.width()
-                                                   : m_itemSize.height();
-
-    // Calculate the first visible index:
-    // 1. Guess the index by using the minimum row height
     const int maxIndex = m_model->count() - 1;
     const int maxIndex = m_model->count() - 1;
-    m_firstVisibleIndex = int(m_offset / minimumHeight) * m_columnCount;
 
 
-    // 2. Decrease the index by checking the real row heights
-    int prevRowIndex = m_firstVisibleIndex - m_columnCount;
-    while (prevRowIndex > maxIndex) {
-        prevRowIndex -= m_columnCount;
-    }
+    // Calculate the first visible index that is fully visible
+    int min = 0;
+    int max = maxIndex;
+    int mid = 0;
+    do {
+        mid = (min + max) / 2;
+        if (m_itemRects[mid].top() < m_scrollOffset) {
+            min = mid + 1;
+        } else {
+            max = mid - 1;
+        }
+    } while (min <= max);
+
+    if (mid > 0) {
+        // Include the row before the first fully visible index, as it might
+        // be partly visible
+        if (m_itemRects[mid].top() >= m_scrollOffset) {
+            --mid;
+            Q_ASSERT(m_itemRects[mid].top() < m_scrollOffset);
+        }
 
 
-    while (prevRowIndex >= 0 && m_itemBoundingRects[prevRowIndex].bottom() >= m_offset) {
-        m_firstVisibleIndex = prevRowIndex;
-        prevRowIndex -= m_columnCount;
-    }
-    m_firstVisibleIndex = qBound(0, m_firstVisibleIndex, maxIndex);
-
-    // Calculate the last visible index
-    const int visibleHeight = horizontalScrolling ? m_size.width() : m_size.height();
-    const qreal bottom = m_offset + visibleHeight;
-    m_lastVisibleIndex = m_firstVisibleIndex; // first visible row, first column
-    int nextRowIndex = m_lastVisibleIndex + m_columnCount;
-    while (nextRowIndex <= maxIndex && m_itemBoundingRects[nextRowIndex].y() <= bottom) {
-        m_lastVisibleIndex = nextRowIndex;
-        nextRowIndex += m_columnCount;
+        const qreal rowTop = m_itemRects[mid].top();
+        while (mid > 0 && m_itemRects[mid - 1].top() == rowTop) {
+            --mid;
+        }
     }
     }
-    m_lastVisibleIndex += m_columnCount - 1; // move it to the last column
-    m_lastVisibleIndex = qBound(0, m_lastVisibleIndex, maxIndex);
-
-    m_visibleIndexesDirty = false;
-}
+    m_firstVisibleIndex = mid;
 
 
-void KItemListViewLayouter::updateGroupedVisibleIndexes()
-{
-    if (!m_visibleIndexesDirty) {
-        return;
+    // Calculate the last visible index that is (at least partly) visible
+    const int visibleHeight = (m_scrollOrientation == Qt::Horizontal) ? m_size.width() : m_size.height();
+    qreal bottom = m_scrollOffset + visibleHeight;
+    if (m_model->groupedSorting()) {
+        bottom += m_groupHeaderHeight;
     }
 
     }
 
-    Q_ASSERT(m_grouped);
-    Q_ASSERT(!m_dirty);
+    min = m_firstVisibleIndex;
+    max = maxIndex;
+    do {
+        mid = (min + max) / 2;
+        if (m_itemRects[mid].y() <= bottom) {
+            min = mid + 1;
+        } else {
+            max = mid - 1;
+        }
+    } while (min <= max);
 
 
-    if (m_model->count() <= 0) {
-        m_firstVisibleIndex = -1;
-        m_lastVisibleIndex = -1;
-        m_visibleIndexesDirty = false;
-        return;
+    while (mid > 0 && m_itemRects[mid].y() > bottom) {
+        --mid;
     }
     }
+    m_lastVisibleIndex = mid;
 
 
-    // Find the first visible group
-    const int lastGroupIndex = m_groups.count() - 1;
-    int groupIndex = lastGroupIndex;
-    for (int i = 1; i < m_groups.count(); ++i) {
-        if (m_groups[i].y >= m_offset) {
-            groupIndex = i - 1;
-            break;
-        }
-    }
+    m_visibleIndexesDirty = false;
+}
 
 
-    // Calculate the first visible index
-    qreal groupY = m_groups[groupIndex].y;
-    m_firstVisibleIndex = m_groups[groupIndex].firstItemIndex;
-    const int invisibleRowCount = int(m_offset - groupY) / int(m_itemSize.height());
-    m_firstVisibleIndex += invisibleRowCount * m_columnCount;
-    if (groupIndex + 1 <= lastGroupIndex) {
-        // Check whether the calculated first visible index remains inside the current
-        // group. If this is not the case let the first element of the next group be the first
-        // visible index.
-        const int nextGroupIndex = m_groups[groupIndex + 1].firstItemIndex;
-        if (m_firstVisibleIndex > nextGroupIndex) {
-            m_firstVisibleIndex = nextGroupIndex;
-        }
+bool KItemListViewLayouter::createGroupHeaders()
+{
+    if (!m_model->groupedSorting()) {
+        return false;
     }
 
     }
 
-    m_firstVisibleGroupIndex = groupIndex;
-
-    const int maxIndex = m_model->count() - 1;
-    m_firstVisibleIndex = qBound(0, m_firstVisibleIndex, maxIndex);
+    m_groupItemIndexes.clear();
 
 
-    // Calculate the last visible index: Find group where the last visible item is shown.
-    const qreal visibleBottom = m_offset + m_size.height(); // TODO: respect Qt::Horizontal alignment
-    while ((groupIndex < lastGroupIndex) && (m_groups[groupIndex + 1].y < visibleBottom)) {
-        ++groupIndex;
+    const QList<QPair<int, QVariant> > groups = m_model->groups();
+    if (groups.isEmpty()) {
+        return false;
     }
 
     }
 
-    groupY = m_groups[groupIndex].y;
-    m_lastVisibleIndex = m_groups[groupIndex].firstItemIndex;
-    const int availableHeight = static_cast<int>(visibleBottom - groupY);
-    int visibleRowCount = availableHeight / int(m_itemSize.height());
-    if (availableHeight % int(m_itemSize.height()) != 0) {
-        ++visibleRowCount;
+    for (int i = 0; i < groups.count(); ++i) {
+        const int firstItemIndex = groups.at(i).first;
+        m_groupItemIndexes.insert(firstItemIndex);
     }
     }
-    m_lastVisibleIndex += visibleRowCount * m_columnCount - 1;
-
-    if (groupIndex + 1 <= lastGroupIndex) {
-        // Check whether the calculate last visible index remains inside the current group.
-        // If this is not the case let the last element of this group be the last visible index.
-        const int nextGroupIndex = m_groups[groupIndex + 1].firstItemIndex;
-        if (m_lastVisibleIndex >= nextGroupIndex) {
-            m_lastVisibleIndex = nextGroupIndex - 1;
-        }
-    }
-    //Q_ASSERT(m_lastVisibleIndex < m_model->count());
-    m_lastVisibleIndex = qBound(0, m_lastVisibleIndex, maxIndex);
 
 
-    m_visibleIndexesDirty = false;
+    return true;
 }
 
 }
 
-void KItemListViewLayouter::createGroupHeaders()
+qreal KItemListViewLayouter::minimumGroupHeaderWidth() const
 {
 {
-    m_groups.clear();
-    m_groupIndexes.clear();
-
-    // TODO:
-    QList<int> numbers;
-    numbers << 0 << 5 << 6 << 13 << 20 << 25 << 30 << 35 << 50;
-
-    qreal y = 0;
-    for (int i = 0; i < numbers.count(); ++i) {
-        if (i > 0) {
-            const int previousGroupItemCount = numbers[i] - m_groups.last().firstItemIndex;
-            int previousGroupRowCount = previousGroupItemCount / m_columnCount;
-            if (previousGroupItemCount % m_columnCount != 0) {
-                ++previousGroupRowCount;
-            }
-            const qreal previousGroupHeight = previousGroupRowCount * m_itemSize.height();
-            y += previousGroupHeight;
-        }
-        y += HeaderHeight;
-
-        ItemGroup itemGroup;
-        itemGroup.firstItemIndex = numbers[i];
-        itemGroup.y = y;
-
-        m_groups.append(itemGroup);
-        m_groupIndexes.insert(itemGroup.firstItemIndex);
-    }
+    return m_groupHeaderHeight * 15 / 2;
 }
 
 #include "kitemlistviewlayouter_p.moc"
 }
 
 #include "kitemlistviewlayouter_p.moc"