]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Provide scrollbar for large items
authorPeter Penz <peter.penz19@gmail.com>
Sun, 25 Sep 2011 17:52:33 +0000 (19:52 +0200)
committerPeter Penz <peter.penz19@gmail.com>
Sun, 25 Sep 2011 17:55:42 +0000 (19:55 +0200)
If an item does not fit into the available width/height a scrollbar
should be provided (e.g. typically this represents the horizontal
scrollbar in the details-view where the width can be larger than
the than the visible width).

Currently the interaction with the scrollbar is not implemented but
this will be a quite minor task in comparison to this patch.

12 files changed:
src/kitemviews/kfileitemlistview.cpp
src/kitemviews/kfileitemlistview.h
src/kitemviews/kitemlistcontainer.cpp
src/kitemviews/kitemlistcontainer.h
src/kitemviews/kitemlistcontroller.cpp
src/kitemviews/kitemlistcontroller.h
src/kitemviews/kitemlistview.cpp
src/kitemviews/kitemlistview.h
src/kitemviews/kitemlistviewanimation.cpp
src/kitemviews/kitemlistviewanimation_p.h
src/kitemviews/kitemlistviewlayouter.cpp
src/kitemviews/kitemlistviewlayouter_p.h

index 68bd7bde91a9ae37807cbedb50264990cf6ad7de..50f28fe5b85b989585251421b3d5141bc8f06cc3 100644 (file)
@@ -167,7 +167,7 @@ QSizeF KFileItemListView::itemSizeHint(int index) const
     return QSize();
 }
 
-QHash<QByteArray, QSizeF> KFileItemListView::visibleRoleSizes() const
+QHash<QByteArray, QSizeF> KFileItemListView::visibleRolesSizes() const
 {
     QElapsedTimer timer;
     timer.start();
@@ -293,7 +293,7 @@ void KFileItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& p
     triggerVisibleIndexRangeUpdate();
 }
 
-void KFileItemListView::onOffsetChanged(qreal current, qreal previous)
+void KFileItemListView::onScrollOffsetChanged(qreal current, qreal previous)
 {
     Q_UNUSED(current);
     Q_UNUSED(previous);
@@ -353,7 +353,6 @@ void KFileItemListView::resizeEvent(QGraphicsSceneResizeEvent* event)
 {
     KItemListView::resizeEvent(event);
     triggerVisibleIndexRangeUpdate();
-    markVisibleRolesSizesAsDirty();
 }
 
 void KFileItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
@@ -435,8 +434,6 @@ QSizeF KFileItemListView::visibleRoleSizeHint(int index, const QByteArray& role)
     }
 
     if (role == "name") {
-        Q_ASSERT(values.contains("expansionLevel"));
-
         // Increase the width by the expansion-toggle and the current expansion level
         const int expansionLevel = values.value("expansionLevel", 0).toInt();
         width += option.margin + expansionLevel * itemSize().height() + KIconLoader::SizeSmall;
index 77bfa21ed3068cad69ff41dfdcbe1a4527a2aa41..696322f8f1ff9696d166966750a9735d471d7b2c 100644 (file)
@@ -61,7 +61,7 @@ public:
     virtual QSizeF itemSizeHint(int index) const;
 
     /** @reimp */
-    virtual QHash<QByteArray, QSizeF> visibleRoleSizes() const;
+    virtual QHash<QByteArray, QSizeF> visibleRolesSizes() const;
 
     /** @reimp */
     virtual QPixmap createDragPixmap(const QSet<int>& indexes) const;
@@ -72,7 +72,7 @@ protected:
     virtual void onModelChanged(KItemModelBase* current, KItemModelBase* previous);
     virtual void onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous);
     virtual void onItemSizeChanged(const QSizeF& current, const QSizeF& previous);
-    virtual void onOffsetChanged(qreal current, qreal previous);
+    virtual void onScrollOffsetChanged(qreal current, qreal previous);
     virtual void onVisibleRolesChanged(const QList<QByteArray>& current, const QList<QByteArray>& previous);
     virtual void onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous);
     virtual void onTransactionBegin();
index 65ddcb5455ef5c17bc5ab00b814be5c914d5dd38..3237187b43381bb2d1553f7ccafaf1d4db775e45 100644 (file)
@@ -122,7 +122,7 @@ void KItemListContainer::scrollContentsBy(int dx, int dy)
 
     const QScrollBar* scrollBar = (view->scrollOrientation() == Qt::Vertical)
                                   ? verticalScrollBar() : horizontalScrollBar();
-    const qreal currentOffset = view->offset();
+    const qreal currentOffset = view->scrollOffset();
     if (static_cast<int>(currentOffset) == scrollBar->value()) {
         // The current offset is already synchronous to the scrollbar
         return;
@@ -156,9 +156,9 @@ void KItemListContainer::scrollContentsBy(int dx, int dy)
         m_smoothScrollingAnimation->setEndValue(endOffset);
         m_smoothScrollingAnimation->setEasingCurve(animRunning ? QEasingCurve::OutQuad : QEasingCurve::InOutQuad);
         m_smoothScrollingAnimation->start();
-        view->setOffset(startOffset);
+        view->setScrollOffset(startOffset);
     } else {
-        view->setOffset(endOffset);
+        view->setScrollOffset(endOffset);
     }
 }
 
@@ -238,16 +238,20 @@ void KItemListContainer::slotViewChanged(KItemListView* current, KItemListView*
     QGraphicsScene* scene = static_cast<QGraphicsView*>(viewport())->scene();
     if (previous) {
         scene->removeItem(previous);
-        disconnect(previous, SIGNAL(offsetChanged(qreal,qreal)), this, SLOT(updateScrollBars()));
-        disconnect(previous, SIGNAL(maximumOffsetChanged(qreal,qreal)), this, SLOT(updateScrollBars()));
-        disconnect(previous, SIGNAL(scrollTo(qreal)), this, SLOT(scrollTo(qreal)));
+        disconnect(previous, SIGNAL(scrollOffsetChanged(qreal,qreal)),        this, SLOT(updateScrollOffsetScrollBar()));
+        disconnect(previous, SIGNAL(maximumScrollOffsetChanged(qreal,qreal)), this, SLOT(updateScrollOffsetScrollBar()));
+        disconnect(previous, SIGNAL(itemOffsetChanged(qreal,qreal)),          this, SLOT(updateItemOffsetScrollBar()));
+        disconnect(previous, SIGNAL(maximumItemOffsetChanged(qreal,qreal)),   this, SLOT(updateItemOffsetScrollBar()));
+        disconnect(previous, SIGNAL(scrollTo(qreal)),                         this, SLOT(scrollTo(qreal)));
         m_smoothScrollingAnimation->setTargetObject(0);
     }
     if (current) {
         scene->addItem(current);
-        connect(current, SIGNAL(offsetChanged(qreal,qreal)), this, SLOT(updateScrollBars()));
-        connect(current, SIGNAL(maximumOffsetChanged(qreal,qreal)), this, SLOT(updateScrollBars()));
-        connect(current, SIGNAL(scrollTo(qreal)), this, SLOT(scrollTo(qreal)));
+        connect(current, SIGNAL(scrollOffsetChanged(qreal,qreal)),        this, SLOT(updateScrollOffsetScrollBar()));
+        connect(current, SIGNAL(maximumScrollOffsetChanged(qreal,qreal)), this, SLOT(updateScrollOffsetScrollBar()));
+        connect(current, SIGNAL(itemOffsetChanged(qreal,qreal)),          this, SLOT(updateItemOffsetScrollBar()));
+        connect(current, SIGNAL(maximumItemOffsetChanged(qreal,qreal)),   this, SLOT(updateItemOffsetScrollBar()));
+        connect(current, SIGNAL(scrollTo(qreal)),                         this, SLOT(scrollTo(qreal)));
         m_smoothScrollingAnimation->setTargetObject(current);
     }
 }
@@ -275,33 +279,30 @@ void KItemListContainer::scrollTo(qreal offset)
     scrollBar->setValue(offset);
 }
 
-void KItemListContainer::updateScrollBars()
+void KItemListContainer::updateScrollOffsetScrollBar()
 {
     const KItemListView* view = m_controller->view();
     if (!view) {
         return;
     }
 
-    QScrollBar* scrollBar = 0;
+    QScrollBar* scrollOffsetScrollBar = 0;
     int singleStep = 0;
     int pageStep = 0;
-    QScrollBar* otherScrollBar = 0;
     if (view->scrollOrientation() == Qt::Vertical) {
-        scrollBar = verticalScrollBar();
+        scrollOffsetScrollBar = verticalScrollBar();
         singleStep = view->itemSize().height();
         pageStep = view->size().height();
-        otherScrollBar = horizontalScrollBar();
     } else {
-        scrollBar = horizontalScrollBar();
+        scrollOffsetScrollBar = horizontalScrollBar();
         singleStep = view->itemSize().width();
         pageStep = view->size().width();
-        otherScrollBar = verticalScrollBar();
     }
 
-    const int value = view->offset();
-    const int maximum = qMax(0, int(view->maximumOffset() - pageStep));
+    const int value = view->scrollOffset();
+    const int maximum = qMax(0, int(view->maximumScrollOffset() - pageStep));
     if (m_smoothScrollingAnimation->state() == QAbstractAnimation::Running) {
-        if (maximum == scrollBar->maximum()) {
+        if (maximum == scrollOffsetScrollBar->maximum()) {
             // The value has been changed by the animation, no update
             // of the scrollbars is required as their target state will be
             // reached with the end of the animation.
@@ -314,15 +315,41 @@ void KItemListContainer::updateScrollBars()
         m_smoothScrollingAnimation->stop();
     }
 
-    scrollBar->setSingleStep(singleStep);
-    scrollBar->setPageStep(pageStep);
-    scrollBar->setMinimum(0);
-    scrollBar->setMaximum(maximum);
-    scrollBar->setValue(value);
+    scrollOffsetScrollBar->setSingleStep(singleStep);
+    scrollOffsetScrollBar->setPageStep(pageStep);
+    scrollOffsetScrollBar->setMinimum(0);
+    scrollOffsetScrollBar->setMaximum(maximum);
+    scrollOffsetScrollBar->setValue(value);
+}
+
+void KItemListContainer::updateItemOffsetScrollBar()
+{
+    const KItemListView* view = m_controller->view();
+    if (!view) {
+        return;
+    }
+
+    QScrollBar* itemOffsetScrollBar = 0;
+    int singleStep = 0;
+    int pageStep = 0;
+    if (view->scrollOrientation() == Qt::Vertical) {
+        itemOffsetScrollBar = horizontalScrollBar();
+        singleStep = view->itemSize().width() / 10;
+        pageStep = view->size().width();
+    } else {
+        itemOffsetScrollBar = verticalScrollBar();
+        singleStep = view->itemSize().height() / 10;
+        pageStep = view->size().height();
+    }
+
+    const int value = view->itemOffset();
+    const int maximum = qMax(0, int(view->maximumItemOffset() - pageStep));
 
-    // Make sure that the other scroll bar is hidden
-    otherScrollBar->setMaximum(0);
-    otherScrollBar->setValue(0);
+    itemOffsetScrollBar->setSingleStep(singleStep);
+    itemOffsetScrollBar->setPageStep(pageStep);
+    itemOffsetScrollBar->setMinimum(0);
+    itemOffsetScrollBar->setMaximum(maximum);
+    itemOffsetScrollBar->setValue(value);
 }
 
 void KItemListContainer::updateGeometries()
@@ -344,7 +371,8 @@ void KItemListContainer::updateGeometries()
     static_cast<KItemListContainerViewport*>(viewport())->scene()->setSceneRect(0, 0, rect.width(), rect.height());
     static_cast<KItemListContainerViewport*>(viewport())->viewport()->setGeometry(QRect(0, 0, rect.width(), rect.height()));
 
-    updateScrollBars();
+    updateScrollOffsetScrollBar();
+    updateItemOffsetScrollBar();
 }
 
 void KItemListContainer::initialize()
@@ -361,7 +389,7 @@ void KItemListContainer::initialize()
     QGraphicsView* graphicsView = new KItemListContainerViewport(new QGraphicsScene(this), this);
     setViewport(graphicsView);
 
-    m_smoothScrollingAnimation = new QPropertyAnimation(this, "offset");
+    m_smoothScrollingAnimation = new QPropertyAnimation(this, "scrollOffset");
     m_smoothScrollingAnimation->setDuration(300);
     connect(m_smoothScrollingAnimation, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)),
             this, SLOT(slotAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State)));
index 333f01de75bb63965cf9b9c744c3279187fb5caa..36ac9753e9476ea6762862aeeff05e82ff2f607b 100644 (file)
@@ -62,7 +62,8 @@ private slots:
     void slotViewChanged(KItemListView* current, KItemListView* previous);
     void slotAnimationStateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
     void scrollTo(qreal offset);
-    void updateScrollBars();
+    void updateScrollOffsetScrollBar();
+    void updateItemOffsetScrollBar();
 
 private:
     void initialize();
index 4a81eaaa59037244e1f29c05e08957d70fdba235..13ced1aacbe346185479e1b43801284933693dad 100644 (file)
@@ -91,7 +91,7 @@ void KItemListController::setView(KItemListView* view)
 
     KItemListView* oldView = m_view;
     if (oldView) {
-        disconnect(oldView, SIGNAL(offsetChanged(qreal,qreal)), this, SLOT(slotViewOffsetChanged(qreal,qreal)));
+        disconnect(oldView, SIGNAL(scrollOffsetChanged(qreal,qreal)), this, SLOT(slotViewScrollOffsetChanged(qreal,qreal)));
     }
 
     m_view = view;
@@ -99,7 +99,7 @@ void KItemListController::setView(KItemListView* view)
     if (m_view) {
         m_view->setController(this);
         m_view->setModel(m_model);
-        connect(m_view, SIGNAL(offsetChanged(qreal,qreal)), this, SLOT(slotViewOffsetChanged(qreal,qreal)));
+        connect(m_view, SIGNAL(scrollOffsetChanged(qreal,qreal)), this, SLOT(slotViewScrollOffsetChanged(qreal,qreal)));
     }
 
     emit viewChanged(m_view, oldView);
@@ -331,14 +331,14 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const
         KItemListRubberBand* rubberBand = m_view->rubberBand();
         QPointF startPos = m_pressedMousePos;
         if (m_view->scrollOrientation() == Qt::Vertical) {
-            startPos.ry() += m_view->offset();
+            startPos.ry() += m_view->scrollOffset();
             if (m_view->itemSize().width() < 0) {
                 // Use a special rubberband for views that have only one column and
                 // expand the rubberband to use the whole width of the view.
                 startPos.setX(0);
             }
         } else {
-            startPos.rx() += m_view->offset();
+            startPos.rx() += m_view->scrollOffset();
         }
 
         m_oldSelection = m_selectionManager->selectedItems();
@@ -371,14 +371,14 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent* event, const
         if (rubberBand->isActive()) {
             QPointF endPos = transform.map(event->pos());
             if (m_view->scrollOrientation() == Qt::Vertical) {
-                endPos.ry() += m_view->offset();
+                endPos.ry() += m_view->scrollOffset();
                 if (m_view->itemSize().width() < 0) {
                     // Use a special rubberband for views that have only one column and
                     // expand the rubberband to use the whole width of the view.
                     endPos.setX(m_view->size().width());
                 }
             } else {
-                endPos.rx() += m_view->offset();
+                endPos.rx() += m_view->scrollOffset();
             }
             rubberBand->setEndPosition(endPos);
         }
@@ -625,7 +625,7 @@ bool KItemListController::processEvent(QEvent* event, const QTransform& transfor
     return false;
 }
 
-void KItemListController::slotViewOffsetChanged(qreal current, qreal previous)
+void KItemListController::slotViewScrollOffsetChanged(qreal current, qreal previous)
 {
     if (!m_view) {
         return;
@@ -662,9 +662,9 @@ void KItemListController::slotRubberBandChanged()
 
     const bool scrollVertical = (m_view->scrollOrientation() == Qt::Vertical);
     if (scrollVertical) {
-        rubberBandRect.translate(0, -m_view->offset());
+        rubberBandRect.translate(0, -m_view->scrollOffset());
     } else {
-        rubberBandRect.translate(-m_view->offset(), 0);
+        rubberBandRect.translate(-m_view->scrollOffset(), 0);
     }
 
     if (!m_oldSelection.isEmpty()) {
index 80c7505817233b544ac9e5ebe1e17d24b3f26114..8ef045ea3e91b7aaf867484d10931bc0ea8f6767 100644 (file)
@@ -135,7 +135,7 @@ signals:
     void viewChanged(KItemListView* current, KItemListView* previous);
 
 private slots:
-    void slotViewOffsetChanged(qreal current, qreal previous);
+    void slotViewScrollOffsetChanged(qreal current, qreal previous);
 
     /**
      * Is invoked when the rubberband boundaries have been changed and will select
index 0a346b094bebfa17c3b4a1d8baf39ad5d78b1ae8..6d96c099911624314baea458a81792be49715d0d 100644 (file)
@@ -69,8 +69,10 @@ KItemListView::KItemListView(QGraphicsWidget* parent) :
     m_layouter(0),
     m_animation(0),
     m_layoutTimer(0),
-    m_oldOffset(0),
-    m_oldMaximumOffset(0),
+    m_oldScrollOffset(0),
+    m_oldMaximumScrollOffset(0),
+    m_oldItemOffset(0),
+    m_oldMaximumItemOffset(0),
     m_skipAutoScrollForRubberBand(false),
     m_rubberBand(0),
     m_mousePos(),
@@ -133,12 +135,14 @@ void KItemListView::setItemSize(const QSizeF& itemSize)
 
     m_itemSize = itemSize;
 
-    if (!markVisibleRolesSizesAsDirty()) {
-        if (itemSize.width() < previousSize.width() || itemSize.height() < previousSize.height()) {
-            prepareLayoutForIncreasedItemCount(itemSize, ItemSize);
-        } else {
-            m_layouter->setItemSize(itemSize);
-        }
+    if (itemSize.isEmpty()) {
+        updateVisibleRoleSizes();
+    }
+
+    if (itemSize.width() < previousSize.width() || itemSize.height() < previousSize.height()) {
+        prepareLayoutForIncreasedItemCount(itemSize, ItemSize);
+    } else {
+        m_layouter->setItemSize(itemSize);
     }
 
     m_sizeHintResolver->clearCache();
@@ -151,34 +155,49 @@ QSizeF KItemListView::itemSize() const
     return m_itemSize;
 }
 
-void KItemListView::setOffset(qreal offset)
+void KItemListView::setScrollOffset(qreal offset)
 {
     if (offset < 0) {
         offset = 0;
     }
 
-    const qreal previousOffset = m_layouter->offset();
+    const qreal previousOffset = m_layouter->scrollOffset();
     if (offset == previousOffset) {
         return;
     }
 
-    m_layouter->setOffset(offset);
-    m_animation->setOffset(offset);
+    m_layouter->setScrollOffset(offset);
+    m_animation->setScrollOffset(offset);
     if (!m_layoutTimer->isActive()) {
         doLayout(NoAnimation, 0, 0);
         update();
     }
-    onOffsetChanged(offset, previousOffset);
+    onScrollOffsetChanged(offset, previousOffset);
+}
+
+qreal KItemListView::scrollOffset() const
+{
+    return m_layouter->scrollOffset();
+}
+
+qreal KItemListView::maximumScrollOffset() const
+{
+    return m_layouter->maximumScrollOffset();
+}
+
+void KItemListView::setItemOffset(qreal offset)
+{
+    m_layouter->setItemOffset(offset);
 }
 
-qreal KItemListView::offset() const
+qreal KItemListView::itemOffset() const
 {
-    return m_layouter->offset();
+    return m_layouter->itemOffset();
 }
 
-qreal KItemListView::maximumOffset() const
+qreal KItemListView::maximumItemOffset() const
 {
-    return m_layouter->maximumOffset();
+    return m_layouter->maximumItemOffset();
 }
 
 void KItemListView::setVisibleRoles(const QList<QByteArray>& roles)
@@ -198,7 +217,7 @@ void KItemListView::setVisibleRoles(const QList<QByteArray>& roles)
     m_layouter->markAsDirty();
     onVisibleRolesChanged(roles, previousRoles);
 
-    markVisibleRolesSizesAsDirty();
+    updateVisibleRoleSizes();
     updateLayout();
 
     if (m_header) {
@@ -320,10 +339,6 @@ void KItemListView::setGeometry(const QRectF& rect)
         return;
     }
 
-    if (m_itemSize.isEmpty()) {
-        m_layouter->setItemSize(QSizeF());
-    }
-
     if (m_model->count() > 0) {
         prepareLayoutForIncreasedItemCount(rect.size(), LayouterSize);
     } else {
@@ -333,6 +348,8 @@ void KItemListView::setGeometry(const QRectF& rect)
     if (!m_layoutTimer->isActive()) {
         m_layoutTimer->start();
     }
+
+    updateVisibleRoleSizes();
 }
 
 int KItemListView::itemAt(const QPointF& pos) const
@@ -387,7 +404,7 @@ QSizeF KItemListView::itemSizeHint(int index) const
     return itemSize();
 }
 
-QHash<QByteArray, QSizeF> KItemListView::visibleRoleSizes() const
+QHash<QByteArray, QSizeF> KItemListView::visibleRolesSizes() const
 {
     return QHash<QByteArray, QSizeF>();
 }
@@ -445,9 +462,9 @@ void KItemListView::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
 
         const QPointF topLeft = rubberBandRect.topLeft();
         if (scrollOrientation() == Qt::Vertical) {
-            rubberBandRect.moveTo(topLeft.x(), topLeft.y() - offset());
+            rubberBandRect.moveTo(topLeft.x(), topLeft.y() - scrollOffset());
         } else {
-            rubberBandRect.moveTo(topLeft.x() - offset(), topLeft.y());
+            rubberBandRect.moveTo(topLeft.x() - scrollOffset(), topLeft.y());
         }
 
         QStyleOptionRubberBand opt;
@@ -494,7 +511,7 @@ void KItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& previ
     Q_UNUSED(previous);
 }
 
-void KItemListView::onOffsetChanged(qreal current, qreal previous)
+void KItemListView::onScrollOffsetChanged(qreal current, qreal previous)
 {
     Q_UNUSED(current);
     Q_UNUSED(previous);
@@ -585,19 +602,9 @@ void KItemListView::resizeEvent(QGraphicsSceneResizeEvent* event)
     updateHeaderWidth();
 }
 
-bool KItemListView::markVisibleRolesSizesAsDirty()
-{
-    const bool dirty = m_itemSize.isEmpty();
-    if (dirty && !m_useHeaderWidths) {
-        m_visibleRolesSizes.clear();
-        m_layouter->setItemSize(QSizeF());
-    }
-    return dirty;
-}
-
 void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
 {
-    markVisibleRolesSizesAsDirty();
+    updateVisibleRoleSizes();
 
     const bool hasMultipleRanges = (itemRanges.count() > 1);
     if (hasMultipleRanges) {
@@ -641,7 +648,7 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
         }
 
         m_layouter->markAsDirty();
-        if (m_model->count() == count && maximumOffset() > size().height()) {
+        if (m_model->count() == count && maximumScrollOffset() > size().height()) {
             kDebug() << "Scrollbar required, skipping layout";
             const int scrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
             QSizeF layouterSize = m_layouter->size();
@@ -670,7 +677,7 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
 
 void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
 {
-    markVisibleRolesSizesAsDirty();
+    updateVisibleRoleSizes();
 
     const bool hasMultipleRanges = (itemRanges.count() > 1);
     if (hasMultipleRanges) {
@@ -754,7 +761,7 @@ void KItemListView::slotItemsChanged(const KItemRangeList& itemRanges,
 {
     const bool updateSizeHints = itemSizeHintUpdateRequired(roles);
     if (updateSizeHints) {
-        markVisibleRolesSizesAsDirty();
+        updateVisibleRoleSizes();
     }
 
     foreach (const KItemRange& itemRange, itemRanges) {
@@ -802,7 +809,7 @@ void KItemListView::slotCurrentChanged(int current, int previous)
 
     if (!viewGeometry.contains(currentBoundingRect)) {
         // Make sure that the new current item is fully visible in the view.
-        qreal newOffset = offset();
+        qreal newOffset = scrollOffset();
         if (currentBoundingRect.top() < viewGeometry.top()) {
             Q_ASSERT(scrollOrientation() == Qt::Vertical);
             newOffset += currentBoundingRect.top() - viewGeometry.top();
@@ -819,7 +826,7 @@ void KItemListView::slotCurrentChanged(int current, int previous)
             }
         }
 
-        if (newOffset != offset()) {
+        if (newOffset != scrollOffset()) {
             emit scrollTo(newOffset);
         }
     }
@@ -917,10 +924,10 @@ void KItemListView::slotVisibleRoleWidthChanged(const QByteArray& role,
         QSizeF roleSize = m_visibleRolesSizes.value(role);
         roleSize.setWidth(currentWidth);
         m_visibleRolesSizes.insert(role, roleSize);
-    }
 
-    m_layouter->setItemSize(QSizeF()); // Forces an update in applyDynamicItemSize()
-    updateLayout();
+        updateVisibleRoleSizes();
+        updateLayout();
+    }
 }
 
 void KItemListView::triggerAutoScrolling()
@@ -973,7 +980,7 @@ void KItemListView::triggerAutoScrolling()
     // the autoscrolling may not get skipped anymore until a new rubberband is created
     m_skipAutoScrollForRubberBand = false;
 
-    setOffset(offset() + m_autoScrollIncrement);
+    setScrollOffset(scrollOffset() + m_autoScrollIncrement);
 
    // Trigger the autoscroll timer which will periodically call
    // triggerAutoScrolling()
@@ -1057,7 +1064,7 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha
         return;
     }
 
-    applyDynamicItemSize();
+    //markVisibleRolesSizesAsDirty();
 
     const int firstVisibleIndex = m_layouter->firstVisibleIndex();
     const int lastVisibleIndex = m_layouter->lastVisibleIndex();
@@ -1066,13 +1073,13 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha
         return;
     }
 
-    // Do a sanity check of the offset-property: When properties of the itemlist-view have been changed
+    // Do a sanity check of the scroll-offset property: When properties of the itemlist-view have been changed
     // it might be possible that the maximum offset got changed too. Assure that the full visible range
     // is still shown if the maximum offset got decreased.
     const qreal visibleOffsetRange = (scrollOrientation() == Qt::Horizontal) ? size().width() : size().height();
-    const qreal maxOffsetToShowFullRange = maximumOffset() - visibleOffsetRange;
-    if (offset() > maxOffsetToShowFullRange) {
-        m_layouter->setOffset(qMax(qreal(0), maxOffsetToShowFullRange));
+    const qreal maxOffsetToShowFullRange = maximumScrollOffset() - visibleOffsetRange;
+    if (scrollOffset() > maxOffsetToShowFullRange) {
+        m_layouter->setScrollOffset(qMax(qreal(0), maxOffsetToShowFullRange));
     }
 
     // Determine all items that are completely invisible and might be
@@ -1187,16 +1194,28 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha
 
 void KItemListView::emitOffsetChanges()
 {
-    const qreal newOffset = m_layouter->offset();
-    if (m_oldOffset != newOffset) {
-        emit offsetChanged(newOffset, m_oldOffset);
-        m_oldOffset = newOffset;
+    const qreal newScrollOffset = m_layouter->scrollOffset();
+    if (m_oldScrollOffset != newScrollOffset) {
+        emit scrollOffsetChanged(newScrollOffset, m_oldScrollOffset);
+        m_oldScrollOffset = newScrollOffset;
+    }
+
+    const qreal newMaximumScrollOffset = m_layouter->maximumScrollOffset();
+    if (m_oldMaximumScrollOffset != newMaximumScrollOffset) {
+        emit maximumScrollOffsetChanged(newMaximumScrollOffset, m_oldMaximumScrollOffset);
+        m_oldMaximumScrollOffset = newMaximumScrollOffset;
     }
 
-    const qreal newMaximumOffset = m_layouter->maximumOffset();
-    if (m_oldMaximumOffset != newMaximumOffset) {
-        emit maximumOffsetChanged(newMaximumOffset, m_oldMaximumOffset);
-        m_oldMaximumOffset = newMaximumOffset;
+    const qreal newItemOffset = m_layouter->itemOffset();
+    if (m_oldItemOffset != newItemOffset) {
+        emit itemOffsetChanged(newItemOffset, m_oldItemOffset);
+        m_oldItemOffset = newItemOffset;
+    }
+
+    const qreal newMaximumItemOffset = m_layouter->maximumItemOffset();
+    if (m_oldMaximumItemOffset != newMaximumItemOffset) {
+        emit maximumItemOffsetChanged(newMaximumItemOffset, m_oldMaximumItemOffset);
+        m_oldMaximumItemOffset = newMaximumItemOffset;
     }
 }
 
@@ -1317,50 +1336,6 @@ void KItemListView::setLayouterSize(const QSizeF& size, SizeType sizeType)
     }
 }
 
-void KItemListView::applyDynamicItemSize()
-{
-    if (!m_itemSize.isEmpty()) {
-        return;
-    }
-
-    if (m_visibleRolesSizes.isEmpty()) {
-        m_visibleRolesSizes = visibleRoleSizes();
-        if (m_header) {
-            m_header->setVisibleRolesWidths(headerRolesWidths());
-        }
-    }
-
-    if (m_layouter->itemSize().isEmpty()) {
-        // Calculate the maximum size of an item by considering the
-        // visible role sizes and apply them to the layouter.
-        qreal requiredWidth = 0;
-        qreal requiredHeight = 0;
-
-        QHashIterator<QByteArray, QSizeF> it(m_visibleRolesSizes);
-        while (it.hasNext()) {
-            it.next();
-            const QSizeF& visibleRoleSize = it.value();
-            requiredWidth  += visibleRoleSize.width();
-            requiredHeight += visibleRoleSize.height();
-        }
-
-        QSizeF dynamicItemSize = m_itemSize;
-        if (dynamicItemSize.width() <= 0) {
-            dynamicItemSize.setWidth(qMax(requiredWidth, size().width()));
-        }
-        if (dynamicItemSize.height() <= 0) {
-            dynamicItemSize.setHeight(qMax(requiredHeight, size().height()));
-        }
-
-        m_layouter->setItemSize(dynamicItemSize);
-
-        // Update the role sizes for all visible widgets
-        foreach (KItemListWidget* widget, visibleItemListWidgets()) {
-            widget->setVisibleRolesSizes(m_visibleRolesSizes);
-        }
-    }
-}
-
 void KItemListView::updateWidgetProperties(KItemListWidget* widget, int index)
 {
     widget->setVisibleRoles(m_visibleRoles);
@@ -1406,6 +1381,46 @@ QHash<QByteArray, qreal> KItemListView::headerRolesWidths() const
     return rolesWidths;
 }
 
+void KItemListView::updateVisibleRoleSizes()
+{
+    if (!m_itemSize.isEmpty() || m_useHeaderWidths) {
+        return;
+    }
+
+    m_visibleRolesSizes = visibleRolesSizes();
+    if (m_header) {
+        m_header->setVisibleRolesWidths(headerRolesWidths());
+    }
+
+    // Calculate the maximum size of an item by considering the
+    // visible role sizes and apply them to the layouter.
+    qreal requiredWidth = 0;
+    qreal requiredHeight = 0;
+
+    QHashIterator<QByteArray, QSizeF> it(m_visibleRolesSizes);
+    while (it.hasNext()) {
+        it.next();
+        const QSizeF& visibleRoleSize = it.value();
+        requiredWidth  += visibleRoleSize.width();
+        requiredHeight += visibleRoleSize.height();
+    }
+
+    QSizeF dynamicItemSize = m_itemSize;
+    if (dynamicItemSize.width() <= 0) {
+        dynamicItemSize.setWidth(qMax(requiredWidth, size().width()));
+    }
+    if (dynamicItemSize.height() <= 0) {
+        dynamicItemSize.setHeight(qMax(requiredHeight, size().height()));
+    }
+
+    m_layouter->setItemSize(dynamicItemSize);
+
+    // Update the role sizes for all visible widgets
+    foreach (KItemListWidget* widget, visibleItemListWidgets()) {
+        widget->setVisibleRolesSizes(m_visibleRolesSizes);
+    }
+}
+
 int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldInc)
 {
     int inc = 0;
@@ -1433,6 +1448,7 @@ int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldIn
 }
 
 
+
 KItemListCreatorBase::~KItemListCreatorBase()
 {
     qDeleteAll(m_recycleableWidgets);
index 75a298a1e79c0fd33f3490b592ac770f05e5ef64..d6b0d5a77692a45564ffdbe932123a0eecf96c50 100644 (file)
@@ -65,7 +65,7 @@ class LIBDOLPHINPRIVATE_EXPORT KItemListView : public QGraphicsWidget
 {
     Q_OBJECT
 
-    Q_PROPERTY(qreal offset READ offset WRITE setOffset)
+    Q_PROPERTY(qreal scrollOffset READ scrollOffset WRITE setScrollOffset)
 
 public:
     KItemListView(QGraphicsWidget* parent = 0);
@@ -78,10 +78,15 @@ public:
     QSizeF itemSize() const;
 
     // TODO: add note that offset is not checked against maximumOffset, only against 0.
-    void setOffset(qreal offset);
-    qreal offset() const;
+    void setScrollOffset(qreal offset);
+    qreal scrollOffset() const;
 
-    qreal maximumOffset() const;
+    qreal maximumScrollOffset() const;
+
+    void setItemOffset(qreal scrollOffset);
+    qreal itemOffset() const;
+
+    qreal maximumItemOffset() const;
 
     void setVisibleRoles(const QList<QByteArray>& roles);
     QList<QByteArray> visibleRoles() const;
@@ -159,7 +164,7 @@ public:
      *         is empty. This allows to have dynamic but equal role sizes between
      *         all items. Per default an empty hash is returned.
      */
-    virtual QHash<QByteArray, QSizeF> visibleRoleSizes() const;
+    virtual QHash<QByteArray, QSizeF> visibleRolesSizes() const;
 
     /**
      * @return The bounding rectangle of the item relative to the top/left of
@@ -193,8 +198,10 @@ public:
     virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
 
 signals:
-    void offsetChanged(qreal current, qreal previous);
-    void maximumOffsetChanged(qreal current, qreal previous);
+    void scrollOffsetChanged(qreal current, qreal previous);
+    void maximumScrollOffsetChanged(qreal current, qreal previous);
+    void itemOffsetChanged(qreal current, qreal previous);
+    void maximumItemOffsetChanged(qreal current, qreal previous);
     void scrollTo(qreal newOffset);
 
 protected:
@@ -215,7 +222,7 @@ protected:
 
     virtual void onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous);
     virtual void onItemSizeChanged(const QSizeF& current, const QSizeF& previous);
-    virtual void onOffsetChanged(qreal current, qreal previous);
+    virtual void onScrollOffsetChanged(qreal current, qreal previous);
     virtual void onVisibleRolesChanged(const QList<QByteArray>& current, const QList<QByteArray>& previous);
     virtual void onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous);
 
@@ -232,15 +239,6 @@ protected:
 
     QList<KItemListWidget*> visibleItemListWidgets() const;
 
-    /**
-     * Marks the visible roles as dirty so that they will get updated when doing the next
-     * layout. The visible roles will only get marked as dirty if an empty item-size is
-     * given and if the roles have not already been customized by the user by adjusting
-     * the view-header.
-     * @return True if the visible roles have been marked as dirty.
-     */
-    bool markVisibleRolesSizesAsDirty();
-
     /** @reimp */
     virtual void resizeEvent(QGraphicsSceneResizeEvent* event);
 
@@ -320,12 +318,6 @@ private:
      */
     void setLayouterSize(const QSizeF& size, SizeType sizeType);
 
-    /**
-     * Updates the m_visibleRoleSizes property and applies the dynamic
-     * size to the layouter.
-     */
-    void applyDynamicItemSize();
-
     /**
      * Helper method for createWidget() and setWidgetIndex() to update the properties
      * of the itemlist widget.
@@ -343,6 +335,13 @@ private:
      */
     QHash<QByteArray, qreal> headerRolesWidths() const;
 
+    /**
+     * Updates m_visibleRoleSizes by calling KItemListView::visibleRoleSizes()
+     * if the m_itemRect is empty and no custom header-widths are used
+     * (see m_useHeaderWidths).
+     */
+    void updateVisibleRoleSizes();
+
     /**
      * Helper function for triggerAutoScrolling().
      * @param pos    Logical position of the mouse relative to the range.
@@ -377,8 +376,10 @@ private:
     KItemListViewAnimation* m_animation;
 
     QTimer* m_layoutTimer; // Triggers an asynchronous doLayout() call.
-    qreal m_oldOffset;
-    qreal m_oldMaximumOffset;
+    qreal m_oldScrollOffset;
+    qreal m_oldMaximumScrollOffset;
+    qreal m_oldItemOffset;
+    qreal m_oldMaximumItemOffset;
 
     bool m_skipAutoScrollForRubberBand;
     KItemListRubberBand* m_rubberBand;
index 449d557f90d103f28bd2c063076adadc6a87c193..9b122ee8c4af43a49c2152adfb630562bdc84237 100644 (file)
@@ -29,7 +29,7 @@
 KItemListViewAnimation::KItemListViewAnimation(QObject* parent) :
     QObject(parent),
     m_scrollOrientation(Qt::Vertical),
-    m_offset(0),
+    m_scrollOffset(0),
     m_animation()
 {
 }
@@ -51,10 +51,10 @@ Qt::Orientation KItemListViewAnimation::scrollOrientation() const
     return m_scrollOrientation;
 }
 
-void KItemListViewAnimation::setOffset(qreal offset)
+void KItemListViewAnimation::setScrollOffset(qreal offset)
 {
-    const qreal diff = m_offset - offset;
-    m_offset = offset;
+    const qreal diff = m_scrollOffset - offset;
+    m_scrollOffset = offset;
 
     // The change of the offset requires that the position of all
     // animated QGraphicsWidgets get adjusted. An exception is made
@@ -108,9 +108,9 @@ void KItemListViewAnimation::setOffset(qreal offset)
     }
 }
 
-qreal KItemListViewAnimation::offset() const
+qreal KItemListViewAnimation::scrollOffset() const
 {
-    return m_offset;
+    return m_scrollOffset;
 }
 
 void KItemListViewAnimation::start(QGraphicsWidget* widget, AnimationType type, const QVariant& endValue)
index 0bf54d296340837a6b42d40a4099525ddd46bde0..b3a95a871017c37b487705010a1575bb4bcd9b24 100644 (file)
@@ -49,8 +49,8 @@ public:
     void setScrollOrientation(Qt::Orientation orientation);
     Qt::Orientation scrollOrientation() const;
 
-    void setOffset(qreal offset);
-    qreal offset() const;
+    void setScrollOffset(qreal scrollOffset);
+    qreal scrollOffset() const;
 
     void start(QGraphicsWidget* widget, AnimationType type, const QVariant& endValue = QVariant());
 
@@ -70,7 +70,7 @@ private:
     enum { AnimationTypeCount = 4 };
 
     Qt::Orientation m_scrollOrientation;
-    qreal m_offset;
+    qreal m_scrollOffset;
     QHash<QGraphicsWidget*, QPropertyAnimation*> m_animation[AnimationTypeCount];
 };
 
index eaf175a513a733ef2f8df2da5707a3b2d2652169..f829824f08a8609e2499d9549777911a3ca5d836 100644 (file)
@@ -42,8 +42,10 @@ KItemListViewLayouter::KItemListViewLayouter(QObject* parent) :
     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_firstVisibleGroupIndex(-1),
@@ -112,17 +114,42 @@ qreal KItemListViewLayouter::headerHeight() const
     return m_headerHeight;
 }
 
-void KItemListViewLayouter::setOffset(qreal offset)
+void KItemListViewLayouter::setScrollOffset(qreal offset)
 {
-    if (m_offset != offset) {
-        m_offset = offset;
+    if (m_scrollOffset != offset) {
+        m_scrollOffset = offset;
         m_visibleIndexesDirty = true;
     }
 }
 
-qreal KItemListViewLayouter::offset() const
+qreal KItemListViewLayouter::scrollOffset() const
 {
-    return m_offset;
+    return m_scrollOffset;
+}
+
+qreal KItemListViewLayouter::maximumScrollOffset() const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    return m_maximumScrollOffset;
+}
+
+void KItemListViewLayouter::setItemOffset(qreal offset)
+{
+    if (m_itemOffset != offset) {
+        m_itemOffset = offset;
+        m_visibleIndexesDirty = true;
+    }
+}
+
+qreal KItemListViewLayouter::itemOffset() const
+{
+    return m_itemOffset;
+}
+
+qreal KItemListViewLayouter::maximumItemOffset() const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    return m_maximumItemOffset;
 }
 
 void KItemListViewLayouter::setModel(const KItemModelBase* model)
@@ -151,12 +178,6 @@ const KItemListSizeHintResolver* KItemListViewLayouter::sizeHintResolver() const
     return m_sizeHintResolver;
 }
 
-qreal KItemListViewLayouter::maximumOffset() const
-{
-    const_cast<KItemListViewLayouter*>(this)->doLayout();
-    return m_maximumOffset;
-}
-
 int KItemListViewLayouter::firstVisibleIndex() const
 {
     const_cast<KItemListViewLayouter*>(this)->doLayout();
@@ -182,15 +203,13 @@ QRectF KItemListViewLayouter::itemBoundingRect(int index) const
         const QRectF& b = m_itemBoundingRects[index];
         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;
     }
 
     QRectF bounds = m_itemBoundingRects[index];
-    QPointF pos = bounds.topLeft();
-    pos.ry() -= m_offset;
-    bounds.moveTo(pos);
+    bounds.moveTo(bounds.topLeft() - QPointF(m_itemOffset, m_scrollOffset));
     return bounds;
 }
 
@@ -251,9 +270,11 @@ void KItemListViewLayouter::doLayout()
         if (itemCount > m_columnCount) {
             // 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;
@@ -303,7 +324,13 @@ void KItemListViewLayouter::doLayout()
                                       m_itemBoundingRects.end());
         }
 
-        m_maximumOffset = (itemCount > 0) ? m_itemBoundingRects.last().bottom() : 0;
+        if (itemCount > 0) {
+            m_maximumScrollOffset = m_itemBoundingRects.last().bottom();
+            m_maximumItemOffset = m_columnCount * m_columnWidth;
+        } else {
+            m_maximumScrollOffset = 0;
+            m_maximumItemOffset = 0;
+        }
 
         m_grouped = !m_model->groupRole().isEmpty();
         /*if (m_grouped) {
@@ -354,7 +381,7 @@ void KItemListViewLayouter::updateVisibleIndexes()
     // Calculate the first visible index:
     // 1. Guess the index by using the minimum row height
     const int maxIndex = m_model->count() - 1;
-    m_firstVisibleIndex = int(m_offset / minimumHeight) * m_columnCount;
+    m_firstVisibleIndex = int(m_scrollOffset / minimumHeight) * m_columnCount;
 
     // 2. Decrease the index by checking the real row heights
     int prevRowIndex = m_firstVisibleIndex - m_columnCount;
@@ -362,7 +389,7 @@ void KItemListViewLayouter::updateVisibleIndexes()
         prevRowIndex -= m_columnCount;
     }
 
-    const qreal top = m_offset + m_headerHeight;
+    const qreal top = m_scrollOffset + m_headerHeight;
     while (prevRowIndex >= 0 && m_itemBoundingRects[prevRowIndex].bottom() >= top) {
         m_firstVisibleIndex = prevRowIndex;
         prevRowIndex -= m_columnCount;
@@ -371,7 +398,7 @@ void KItemListViewLayouter::updateVisibleIndexes()
 
     // Calculate the last visible index
     const int visibleHeight = horizontalScrolling ? m_size.width() : m_size.height();
-    const qreal bottom = m_offset + visibleHeight;
+    const qreal bottom = m_scrollOffset + visibleHeight;
     m_lastVisibleIndex = m_firstVisibleIndex; // first visible row, first column
     int nextRowIndex = m_lastVisibleIndex + m_columnCount;
     while (nextRowIndex <= maxIndex && m_itemBoundingRects[nextRowIndex].y() <= bottom) {
@@ -404,7 +431,7 @@ void KItemListViewLayouter::updateGroupedVisibleIndexes()
     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) {
+        if (m_groups[i].y >= m_scrollOffset) {
             groupIndex = i - 1;
             break;
         }
@@ -413,7 +440,7 @@ void KItemListViewLayouter::updateGroupedVisibleIndexes()
     // 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());
+    const int invisibleRowCount = int(m_scrollOffset - 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
@@ -431,7 +458,7 @@ void KItemListViewLayouter::updateGroupedVisibleIndexes()
     m_firstVisibleIndex = qBound(0, m_firstVisibleIndex, maxIndex);
 
     // 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
+    const qreal visibleBottom = m_scrollOffset + m_size.height(); // TODO: respect Qt::Horizontal alignment
     while ((groupIndex < lastGroupIndex) && (m_groups[groupIndex + 1].y < visibleBottom)) {
         ++groupIndex;
     }
index 18ffb4caabe271aa65d8647bfb6cfd25d3270904..c81995d9b4417f109f90fe0f4c97128eaf625b49 100644 (file)
@@ -56,8 +56,15 @@ public:
     qreal headerHeight() const;
 
     // TODO: add note that offset can be < 0 or > maximumOffset!
-    void setOffset(qreal offset);
-    qreal offset() const;
+    void setScrollOffset(qreal scrollOffset);
+    qreal scrollOffset() const;
+
+    qreal maximumScrollOffset() const;
+
+    void setItemOffset(qreal scrollOffset);
+    qreal itemOffset() const;
+
+    qreal maximumItemOffset() const;
 
     void setModel(const KItemModelBase* model);
     const KItemModelBase* model() const;
@@ -65,7 +72,6 @@ public:
     void setSizeHintResolver(const KItemListSizeHintResolver* sizeHintResolver);
     const KItemListSizeHintResolver* sizeHintResolver() const;
 
-    qreal maximumOffset() const;
 
     // TODO: mention that return value is -1 if count == 0
     int firstVisibleIndex() const;
@@ -107,8 +113,11 @@ private:
     const KItemModelBase* m_model;
     const KItemListSizeHintResolver* m_sizeHintResolver;
 
-    qreal m_offset;
-    qreal m_maximumOffset;
+    qreal m_scrollOffset;
+    qreal m_maximumScrollOffset;
+
+    qreal m_itemOffset;
+    qreal m_maximumItemOffset;
 
     int m_firstVisibleIndex;
     int m_lastVisibleIndex;