Refactor ListView and GridView implementations
authorBea Lam <bea.lam@nokia.com>
Tue, 5 Jul 2011 05:07:05 +0000 (15:07 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 20 Jul 2011 06:22:07 +0000 (08:22 +0200)
Places common code into QSGItemView.

Change-Id: Ic310dbe7e16774163ba393860da64a0da7d4ea0a
Reviewed-on: http://codereview.qt.nokia.com/1200
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Bea Lam <bea.lam@nokia.com>
src/declarative/items/items.pri
src/declarative/items/qsggridview.cpp
src/declarative/items/qsggridview_p.h
src/declarative/items/qsgitemview.cpp [new file with mode: 0644]
src/declarative/items/qsgitemview_p.h [new file with mode: 0644]
src/declarative/items/qsgitemview_p_p.h [new file with mode: 0644]
src/declarative/items/qsglistview.cpp
src/declarative/items/qsglistview_p.h
tests/auto/declarative/qsggridview/tst_qsggridview.cpp

index bf92025..7819980 100644 (file)
@@ -66,6 +66,8 @@ HEADERS += \
     $$PWD/qsgspriteimage_p.h \
     $$PWD/qsgevent.h \
     $$PWD/qsgdragtarget_p.h \
+    $$PWD/qsgitemview_p.h \
+    $$PWD/qsgitemview_p_p.h
 
 SOURCES += \
     $$PWD/qsgevents.cpp \
@@ -109,6 +111,7 @@ SOURCES += \
     $$PWD/qsgsprite.cpp \
     $$PWD/qsgspriteimage.cpp \
     $$PWD/qsgdragtarget.cpp \
+    $$PWD/qsgitemview.cpp
 
 SOURCES += \
     $$PWD/qsgshadereffectitem.cpp \
index 9c67246..ab02dea 100644 (file)
@@ -42,6 +42,7 @@
 #include "qsggridview_p.h"
 #include "qsgvisualitemmodel_p.h"
 #include "qsgflickable_p_p.h"
+#include "qsgitemview_p_p.h"
 
 #include <private/qdeclarativesmoothedanimation_p_p.h>
 #include <private/qlistmodelinterface_p.h>
@@ -55,43 +56,52 @@ QT_BEGIN_NAMESPACE
 
 //----------------------------------------------------------------------------
 
-class FxGridItemSG
+class FxGridItemSG : public FxViewItem
 {
 public:
-    FxGridItemSG(QSGItem *i, QSGGridView *v) : item(i), view(v) {
+    FxGridItemSG(QSGItem *i, QSGGridView *v, bool own) : FxViewItem(i, own), view(v) {
         attached = static_cast<QSGGridViewAttached*>(qmlAttachedPropertiesObject<QSGGridView>(item));
         if (attached)
-            attached->setView(view);
+            static_cast<QSGGridViewAttached*>(attached)->setView(view);
     }
+
     ~FxGridItemSG() {}
 
+    qreal position() const {
+        return rowPos();
+    }
+
+    qreal endPosition() const {
+        return endRowPos();
+    }
+
+    qreal size() const {
+        return view->flow() == QSGGridView::LeftToRight ? view->cellHeight() : view->cellWidth();
+    }
+
+    qreal sectionSize() const {
+        return 0.0;
+    }
+
     qreal rowPos() const {
-        qreal rowPos = 0;
-        if (view->flow() == QSGGridView::LeftToRight) {
-            rowPos = item->y();
-        } else {
-            if (view->effectiveLayoutDirection() == Qt::RightToLeft)
-                rowPos = -view->cellWidth()-item->x();
-            else
-                rowPos = item->x();
-        }
-        return rowPos;
+        if (view->flow() == QSGGridView::LeftToRight)
+            return item->y();
+        else
+            return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -view->cellWidth()-item->x() : item->x());
     }
+
     qreal colPos() const {
-        qreal colPos = 0;
         if (view->flow() == QSGGridView::LeftToRight) {
             if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
                 int colSize = view->cellWidth();
                 int columns = view->width()/colSize;
-                colPos = colSize * (columns-1) - item->x();
+                return colSize * (columns-1) - item->x();
             } else {
-                colPos = item->x();
+                return item->x();
             }
         } else {
-            colPos = item->y();
+            return item->y();
         }
-
-        return colPos;
     }
     qreal endRowPos() const {
         if (view->flow() == QSGGridView::LeftToRight) {
@@ -123,464 +133,289 @@ public:
                 y >= item->y() && y < item->y() + view->cellHeight());
     }
 
-    QSGItem *item;
     QSGGridView *view;
-    QSGGridViewAttached *attached;
-    int index;
 };
 
 //----------------------------------------------------------------------------
 
-class QSGGridViewPrivate : public QSGFlickablePrivate
+class QSGGridViewPrivate : public QSGItemViewPrivate
 {
     Q_DECLARE_PUBLIC(QSGGridView)
 
 public:
-    QSGGridViewPrivate()
-    : currentItem(0), layoutDirection(Qt::LeftToRight), flow(QSGGridView::LeftToRight)
-    , visibleIndex(0) , currentIndex(-1)
-    , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
-    , highlightRangeStart(0), highlightRangeEnd(0)
-    , highlightRange(QSGGridView::NoHighlightRange)
-    , highlightComponent(0), highlight(0), trackedItem(0)
-    , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
-    , highlightMoveDuration(150)
-    , footerComponent(0), footer(0), headerComponent(0), header(0)
-    , bufferMode(BufferBefore | BufferAfter), snapMode(QSGGridView::NoSnap)
-    , ownModel(false), wrap(false), autoHighlight(true)
-    , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
-    , deferredRelease(false), haveHighlightRange(false), currentIndexCleared(false)
-    , highlightRangeStartValid(false), highlightRangeEndValid(false) {}
-
-    void init();
-    void clear();
-    FxGridItemSG *createItem(int modelIndex);
-    void releaseItem(FxGridItemSG *item);
-    void refill(qreal from, qreal to, bool doBuffer=false);
-
-    void updateGrid();
-    void scheduleLayout();
-    void layout();
-    void updateUnrequestedIndexes();
-    void updateUnrequestedPositions();
-    void updateTrackedItem();
-    void createHighlight();
-    void updateHighlight();
-    void updateCurrent(int modelIndex);
-    void updateHeader();
-    void updateFooter();
-    void fixupPosition();
-
-    FxGridItemSG *visibleItem(int modelIndex) const {
-        if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
-            for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
-                FxGridItemSG *item = visibleItems.at(i);
-                if (item->index == modelIndex)
-                    return item;
-            }
-        }
-        return 0;
-    }
-
-    bool isRightToLeftTopToBottom() const {
-        Q_Q(const QSGGridView);
-        return flow == QSGGridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
-    }
+    virtual Qt::Orientation layoutOrientation() const;
+    virtual bool isContentFlowReversed() const;
+    bool isRightToLeftTopToBottom() const;
+
+    virtual qreal startPosition() const;
+    virtual qreal positionAt(int index) const;
+    virtual qreal endPosition() const;
+    virtual qreal endPositionAt(int index) const;
+    virtual qreal lastPosition() const;
+
+    qreal originPosition() const;
+    int rowSize() const;
+    int colSize() const;
+    qreal colPosAt(int modelIndex) const;
+    qreal rowPosAt(int modelIndex) const;
+    qreal snapPosAt(qreal pos) const;
+    FxViewItem *snapItemAt(qreal pos) const;
+    int snapIndex() const;
+
+    virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer);
+    virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo);
+    virtual void visibleItemsChanged();
+
+    virtual FxViewItem *newViewItem(int index, QSGItem *item);
+    virtual void repositionPackageItemAt(QSGItem *item, int index);
+
+    virtual void createHighlight();
+    virtual void updateHighlight();
+    virtual void resetHighlightPosition();
+
+    virtual void setPosition(qreal pos);
+    virtual void layoutVisibleItems();
+
+    virtual qreal headerSize() const;
+    virtual qreal footerSize() const;
+    virtual void updateHeader();
+    virtual void updateFooter();
+
+    virtual void changedVisibleIndex(int newIndex);
+    virtual void initializeCurrentItem();
+
+    virtual void updateViewport();
+    virtual void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+    virtual void fixupPosition();
+    virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+    virtual void flick(QSGItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+                        QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
 
-    void regenerate() {
-        Q_Q(QSGGridView);
-        if (q->isComponentComplete()) {
-            clear();
-            updateGrid();
-            setPosition(0);
-            q->refill();
-            updateCurrent(currentIndex);
-        }
-    }
+    QSGGridView::Flow flow;
+    int cellWidth;
+    int cellHeight;
+    int columns;
+    QSGGridView::SnapMode snapMode;
 
-    void mirrorChange() {
-        Q_Q(QSGGridView);
-        regenerate();
-        emit q->effectiveLayoutDirectionChanged();
-    }
+    QSmoothedAnimation *highlightXAnimator;
+    QSmoothedAnimation *highlightYAnimator;
 
-    qreal position() const {
-        Q_Q(const QSGGridView);
-        return flow == QSGGridView::LeftToRight ? q->contentY() : q->contentX();
-    }
-    void setPosition(qreal pos) {
-        Q_Q(QSGGridView);
-        if (flow == QSGGridView::LeftToRight) {
-            q->QSGFlickable::setContentY(pos);
-            q->QSGFlickable::setContentX(0);
-        } else {
-            if (q->effectiveLayoutDirection() == Qt::LeftToRight)
-                q->QSGFlickable::setContentX(pos);
-            else
-                q->QSGFlickable::setContentX(-pos-size());
-            q->QSGFlickable::setContentY(0);
-        }
-    }
-    int size() const {
-        Q_Q(const QSGGridView);
-        return flow == QSGGridView::LeftToRight ? q->height() : q->width();
-    }
-    qreal originPosition() const {
-        qreal pos = 0;
-        if (!visibleItems.isEmpty())
-            pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
-        return pos;
-    }
+    QSGGridViewPrivate()
+        : flow(QSGGridView::LeftToRight)
+        , cellWidth(100), cellHeight(100), columns(1)
+        , snapMode(QSGGridView::NoSnap)
+        , highlightXAnimator(0), highlightYAnimator(0)
+    {}
+};
 
-    qreal lastPosition() const {
-        qreal pos = 0;
-        if (model && model->count())
-            pos = rowPosAt(model->count() - 1) + rowSize();
-        return pos;
-    }
+Qt::Orientation QSGGridViewPrivate::layoutOrientation() const
+{
+    return flow == QSGGridView::LeftToRight ? Qt::Vertical : Qt::Horizontal;
+}
 
-    qreal startPosition() const {
-        return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
-    }
+bool QSGGridViewPrivate::isContentFlowReversed() const
+{
+    return isRightToLeftTopToBottom();
+}
 
-    qreal endPosition() const {
-        return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
+bool QSGGridViewPrivate::isRightToLeftTopToBottom() const
+{
+    Q_Q(const QSGGridView);
+    return flow == QSGGridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
+}
 
-    }
+void QSGGridViewPrivate::changedVisibleIndex(int newIndex)
+{
+    visibleIndex = newIndex / columns * columns;
+}
 
-    bool isValid() const {
-        return model && model->count() && model->isValid();
+void QSGGridViewPrivate::setPosition(qreal pos)
+{
+    Q_Q(QSGGridView);
+    if (flow == QSGGridView::LeftToRight) {
+        q->QSGFlickable::setContentY(pos);
+        q->QSGFlickable::setContentX(0);
+    } else {
+        if (q->effectiveLayoutDirection() == Qt::LeftToRight)
+            q->QSGFlickable::setContentX(pos);
+        else
+            q->QSGFlickable::setContentX(-pos-size());
+        q->QSGFlickable::setContentY(0);
     }
+}
 
-    int rowSize() const {
-        return flow == QSGGridView::LeftToRight ? cellHeight : cellWidth;
-    }
-    int colSize() const {
-        return flow == QSGGridView::LeftToRight ? cellWidth : cellHeight;
-    }
+qreal QSGGridViewPrivate::originPosition() const
+{
+    qreal pos = 0;
+    if (!visibleItems.isEmpty())
+        pos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
+    return pos;
+}
 
-    qreal colPosAt(int modelIndex) const {
-        if (FxGridItemSG *item = visibleItem(modelIndex))
-            return item->colPos();
-        if (!visibleItems.isEmpty()) {
-            if (modelIndex < visibleIndex) {
-                int count = (visibleIndex - modelIndex) % columns;
-                int col = visibleItems.first()->colPos() / colSize();
-                col = (columns - count + col) % columns;
-                return col * colSize();
-            } else {
-                int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
-                return visibleItems.last()->colPos() - count * colSize();
-            }
-        } else {
-            return (modelIndex % columns) * colSize();
-        }
-        return 0;
-    }
-    qreal rowPosAt(int modelIndex) const {
-        if (FxGridItemSG *item = visibleItem(modelIndex))
-            return item->rowPos();
-        if (!visibleItems.isEmpty()) {
-            if (modelIndex < visibleIndex) {
-                int firstCol = visibleItems.first()->colPos() / colSize();
-                int col = visibleIndex - modelIndex + (columns - firstCol - 1);
-                int rows = col / columns;
-                return visibleItems.first()->rowPos() - rows * rowSize();
-            } else {
-                int count = modelIndex - visibleItems.last()->index;
-                int col = visibleItems.last()->colPos() + count * colSize();
-                int rows = col / (columns * colSize());
-                return visibleItems.last()->rowPos() + rows * rowSize();
-            }
-        } else {
-            qreal pos = (modelIndex / columns) * rowSize();
-            if (header)
-                pos += headerSize();
-            return pos;
-        }
-        return 0;
-    }
+qreal QSGGridViewPrivate::lastPosition() const
+{
+    qreal pos = 0;
+    if (model && model->count())
+        pos = rowPosAt(model->count() - 1) + rowSize();
+    return pos;
+}
 
-    FxGridItemSG *firstVisibleItem() const {
-        const qreal pos = isRightToLeftTopToBottom() ? -position()-size() : position();
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxGridItemSG *item = visibleItems.at(i);
-            if (item->index != -1 && item->endRowPos() > pos)
-                return item;
-        }
-        return visibleItems.count() ? visibleItems.first() : 0;
-    }
+qreal QSGGridViewPrivate::startPosition() const
+{
+    return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
+}
 
-    int lastVisibleIndex() const {
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxGridItemSG *item = visibleItems.at(i);
-            if (item->index != -1)
-                return item->index;
-        }
-        return -1;
-    }
-
-    // Map a model index to visibleItems list index.
-    // These may differ if removed items are still present in the visible list,
-    // e.g. doing a removal animation
-    int mapFromModel(int modelIndex) const {
-        if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
-            return -1;
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxGridItemSG *listItem = visibleItems.at(i);
-            if (listItem->index == modelIndex)
-                return i + visibleIndex;
-            if (listItem->index > modelIndex)
-                return -1;
-        }
-        return -1; // Not in visibleList
-    }
-
-    qreal snapPosAt(qreal pos) const {
-        Q_Q(const QSGGridView);
-        qreal snapPos = 0;
-        if (!visibleItems.isEmpty()) {
-            pos += rowSize()/2;
-            snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
-            snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
-            qreal maxExtent;
-            qreal minExtent;
-            if (isRightToLeftTopToBottom()) {
-                maxExtent = q->minXExtent();
-                minExtent = q->maxXExtent();
-            } else {
-                maxExtent = flow == QSGGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
-                minExtent = flow == QSGGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
-            }
-            if (snapPos > maxExtent)
-                snapPos = maxExtent;
-            if (snapPos < minExtent)
-                snapPos = minExtent;
-        }
-        return snapPos;
-    }
+qreal QSGGridViewPrivate::positionAt(int index) const
+{
+    return rowPosAt(index);
+}
 
-    FxGridItemSG *snapItemAt(qreal pos) {
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxGridItemSG *item = visibleItems[i];
-            if (item->index == -1)
-                continue;
-            qreal itemTop = item->rowPos();
-            if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
-                return item;
-        }
-        return 0;
-    }
-
-    int snapIndex() {
-        int index = currentIndex;
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxGridItemSG *item = visibleItems[i];
-            if (item->index == -1)
-                continue;
-            qreal itemTop = item->rowPos();
-            if (itemTop >= highlight->rowPos()-rowSize()/2 && itemTop < highlight->rowPos()+rowSize()/2) {
-                index = item->index;
-                if (item->colPos() >= highlight->colPos()-colSize()/2 && item->colPos() < highlight->colPos()+colSize()/2)
-                    return item->index;
-            }
-        }
-        return index;
-    }
+qreal QSGGridViewPrivate::endPosition() const
+{
+    return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
 
-    qreal headerSize() const {
-        if (!header)
-            return 0.0;
+}
 
-        return flow == QSGGridView::LeftToRight
-                       ? header->item->height()
-                       : header->item->width();
-    }
+qreal QSGGridViewPrivate::endPositionAt(int index) const
+{
+    return rowPosAt(index) + rowSize();
+}
 
+int QSGGridViewPrivate::rowSize() const {
+    return flow == QSGGridView::LeftToRight ? cellHeight : cellWidth;
+}
+int QSGGridViewPrivate::colSize() const {
+    return flow == QSGGridView::LeftToRight ? cellWidth : cellHeight;
+}
 
-    virtual void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
-        Q_Q(const QSGGridView);
-        QSGFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
-        if (item == q) {
-            if (newGeometry.height() != oldGeometry.height()
-                || newGeometry.width() != oldGeometry.width()) {
-                if (q->isComponentComplete()) {
-                    updateGrid();
-                    scheduleLayout();
-                }
-            }
-        } else if ((header && header->item == item) || (footer && footer->item == item)) {
-            if (header)
-                updateHeader();
-            if (footer)
-                updateFooter();
+qreal QSGGridViewPrivate::colPosAt(int modelIndex) const
+{
+    if (FxViewItem *item = visibleItem(modelIndex))
+        return static_cast<FxGridItemSG*>(item)->colPos();
+    if (!visibleItems.isEmpty()) {
+        if (modelIndex < visibleIndex) {
+            int count = (visibleIndex - modelIndex) % columns;
+            int col = static_cast<FxGridItemSG*>(visibleItems.first())->colPos() / colSize();
+            col = (columns - count + col) % columns;
+            return col * colSize();
+        } else {
+            int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
+            return static_cast<FxGridItemSG*>(visibleItems.last())->colPos() - count * colSize();
         }
+    } else {
+        return (modelIndex % columns) * colSize();
     }
+    return 0;
+}
 
-    void positionViewAtIndex(int index, int mode);
-    virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
-    virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
-                QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
-
-    // for debugging only
-    void checkVisible() const {
-        int skip = 0;
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxGridItemSG *listItem = visibleItems.at(i);
-            if (listItem->index == -1) {
-                ++skip;
-            } else if (listItem->index != visibleIndex + i - skip) {
-                for (int j = 0; j < visibleItems.count(); j++)
-                    qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
-                qFatal("index %d %d %d", visibleIndex, i, listItem->index);
-            }
+qreal QSGGridViewPrivate::rowPosAt(int modelIndex) const
+{
+    if (FxViewItem *item = visibleItem(modelIndex))
+        return static_cast<FxGridItemSG*>(item)->rowPos();
+    if (!visibleItems.isEmpty()) {
+        if (modelIndex < visibleIndex) {
+            FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
+            int firstCol = firstItem->colPos() / colSize();
+            int col = visibleIndex - modelIndex + (columns - firstCol - 1);
+            int rows = col / columns;
+            return firstItem->rowPos() - rows * rowSize();
+        } else {
+            FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
+            int count = modelIndex - lastItem->index;
+            int col = lastItem->colPos() + count * colSize();
+            int rows = col / (columns * colSize());
+            return lastItem->rowPos() + rows * rowSize();
         }
+    } else {
+        qreal pos = (modelIndex / columns) * rowSize();
+        if (header)
+            pos += headerSize();
+        return pos;
     }
+    return 0;
+}
 
-    QDeclarativeGuard<QSGVisualModel> model;
-    QVariant modelVariant;
-    QList<FxGridItemSG*> visibleItems;
-    QHash<QSGItem*,int> unrequestedItems;
-    FxGridItemSG *currentItem;
-    Qt::LayoutDirection layoutDirection;
-    QSGGridView::Flow flow;
-    int visibleIndex;
-    int currentIndex;
-    int cellWidth;
-    int cellHeight;
-    int columns;
-    int requestedIndex;
-    int itemCount;
-    qreal highlightRangeStart;
-    qreal highlightRangeEnd;
-    QSGGridView::HighlightRangeMode highlightRange;
-    QDeclarativeComponent *highlightComponent;
-    FxGridItemSG *highlight;
-    FxGridItemSG *trackedItem;
-    enum MovementReason { Other, SetIndex, Mouse };
-    MovementReason moveReason;
-    int buffer;
-    QSmoothedAnimation *highlightXAnimator;
-    QSmoothedAnimation *highlightYAnimator;
-    int highlightMoveDuration;
-    QDeclarativeComponent *footerComponent;
-    FxGridItemSG *footer;
-    QDeclarativeComponent *headerComponent;
-    FxGridItemSG *header;
-    enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
-    int bufferMode;
-    QSGGridView::SnapMode snapMode;
-
-    bool ownModel : 1;
-    bool wrap : 1;
-    bool autoHighlight : 1;
-    bool fixCurrentVisibility : 1;
-    bool lazyRelease : 1;
-    bool layoutScheduled : 1;
-    bool deferredRelease : 1;
-    bool haveHighlightRange : 1;
-    bool currentIndexCleared : 1;
-    bool highlightRangeStartValid : 1;
-    bool highlightRangeEndValid : 1;
-};
 
-void QSGGridViewPrivate::init()
+qreal QSGGridViewPrivate::snapPosAt(qreal pos) const
 {
-    Q_Q(QSGGridView);
-    QSGItemPrivate::get(contentItem)->childrenDoNotOverlap = true;
-    QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
-    q->setFlag(QSGItem::ItemIsFocusScope);
-    q->setFlickableDirection(QSGFlickable::VerticalFlick);
-    addItemChangeListener(this, Geometry);
+    Q_Q(const QSGGridView);
+    qreal snapPos = 0;
+    if (!visibleItems.isEmpty()) {
+        pos += rowSize()/2;
+        snapPos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
+        snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
+        qreal maxExtent;
+        qreal minExtent;
+        if (isRightToLeftTopToBottom()) {
+            maxExtent = q->minXExtent();
+            minExtent = q->maxXExtent();
+        } else {
+            maxExtent = flow == QSGGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
+            minExtent = flow == QSGGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
+        }
+        if (snapPos > maxExtent)
+            snapPos = maxExtent;
+        if (snapPos < minExtent)
+            snapPos = minExtent;
+    }
+    return snapPos;
 }
 
-void QSGGridViewPrivate::clear()
+FxViewItem *QSGGridViewPrivate::snapItemAt(qreal pos) const
 {
-    for (int i = 0; i < visibleItems.count(); ++i)
-        releaseItem(visibleItems.at(i));
-    visibleItems.clear();
-    visibleIndex = 0;
-    releaseItem(currentItem);
-    currentItem = 0;
-    createHighlight();
-    trackedItem = 0;
-    itemCount = 0;
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        FxViewItem *item = visibleItems.at(i);
+        if (item->index == -1)
+            continue;
+        qreal itemTop = item->position();
+        if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
+            return item;
+    }
+    return 0;
 }
 
-FxGridItemSG *QSGGridViewPrivate::createItem(int modelIndex)
+int QSGGridViewPrivate::snapIndex() const
 {
-    Q_Q(QSGGridView);
-    // create object
-    requestedIndex = modelIndex;
-    FxGridItemSG *listItem = 0;
-    if (QSGItem *item = model->item(modelIndex, false)) {
-        listItem = new FxGridItemSG(item, q);
-        listItem->index = modelIndex;
-        if (model->completePending()) {
-            // complete
-            listItem->item->setZ(1);
-            listItem->item->setParentItem(q->contentItem());
-            model->completeItem();
-        } else {
-            listItem->item->setParentItem(q->contentItem());
+    int index = currentIndex;
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
+        if (item->index == -1)
+            continue;
+        qreal itemTop = item->position();
+        FxGridItemSG *hItem = static_cast<FxGridItemSG*>(highlight);
+        if (itemTop >= hItem->rowPos()-rowSize()/2 && itemTop < hItem->rowPos()+rowSize()/2) {
+            index = item->index;
+            if (item->colPos() >= hItem->colPos()-colSize()/2 && item->colPos() < hItem->colPos()+colSize()/2)
+                return item->index;
         }
-        unrequestedItems.remove(listItem->item);
     }
-    requestedIndex = -1;
-    return listItem;
+    return index;
 }
 
-
-void QSGGridViewPrivate::releaseItem(FxGridItemSG *item)
+FxViewItem *QSGGridViewPrivate::newViewItem(int modelIndex, QSGItem *item)
 {
     Q_Q(QSGGridView);
-    if (!item || !model)
-        return;
-    if (trackedItem == item) {
-        QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
-        QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
-        trackedItem = 0;
-    }
-    if (model->release(item->item) == 0) {
-        // item was not destroyed, and we no longer reference it.
-        unrequestedItems.insert(item->item, model->indexOf(item->item, q));
-    }
-    delete item;
+    Q_UNUSED(modelIndex);
+    return new FxGridItemSG(item, q, false);
 }
 
-void QSGGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+bool QSGGridViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer)
 {
-    Q_Q(QSGGridView);
-    if (!isValid() || !q->isComponentComplete())
-        return;
-    itemCount = model->count();
-    qreal bufferFrom = from - buffer;
-    qreal bufferTo = to + buffer;
-    qreal fillFrom = from;
-    qreal fillTo = to;
-    if (doBuffer && (bufferMode & BufferAfter))
-        fillTo = bufferTo;
-    if (doBuffer && (bufferMode & BufferBefore))
-        fillFrom = bufferFrom;
-
-    bool changed = false;
-
     int colPos = colPosAt(visibleIndex);
     int rowPos = rowPosAt(visibleIndex);
-    int modelIndex = visibleIndex;
     if (visibleItems.count()) {
-        rowPos = visibleItems.last()->rowPos();
-        colPos = visibleItems.last()->colPos() + colSize();
+        FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
+        rowPos = lastItem->rowPos();
+        colPos = lastItem->colPos() + colSize();
         if (colPos > colSize() * (columns-1)) {
             colPos = 0;
             rowPos += rowSize();
         }
-        int i = visibleItems.count() - 1;
-        while (i > 0 && visibleItems.at(i)->index == -1)
-            --i;
-        modelIndex = visibleItems.at(i)->index + 1;
     }
 
+    int modelIndex = findLastVisibleIndex();
+    modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
+
     if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
         || fillTo < rowPosAt(visibleIndex) - rowSize())) {
         // We've jumped more than a page.  Estimate which items are now
@@ -601,15 +436,12 @@ void QSGGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
     }
 
     int colNum = colPos / colSize();
-
     FxGridItemSG *item = 0;
+    bool changed = false;
 
-    // Item creation and release is staggered in order to avoid
-    // creating/releasing multiple items in one frame
-    // while flicking (as much as possible).
     while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
 //        qDebug() << "refill: append item" << modelIndex;
-        if (!(item = createItem(modelIndex)))
+        if (!(item = static_cast<FxGridItemSG*>(createItem(modelIndex))))
             break;
         item->setPosition(colPos, rowPos);
         visibleItems.append(item);
@@ -627,17 +459,19 @@ void QSGGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
     }
 
     if (visibleItems.count()) {
-        rowPos = visibleItems.first()->rowPos();
-        colPos = visibleItems.first()->colPos() - colSize();
+        FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
+        rowPos = firstItem->rowPos();
+        colPos = firstItem->colPos() - colSize();
         if (colPos < 0) {
             colPos = colSize() * (columns - 1);
             rowPos -= rowSize();
         }
     }
+
     colNum = colPos / colSize();
     while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
 //        qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
-        if (!(item = createItem(visibleIndex-1)))
+        if (!(item = static_cast<FxGridItemSG*>(createItem(visibleIndex-1))))
             break;
         --visibleIndex;
         item->setPosition(colPos, rowPos);
@@ -654,87 +488,69 @@ void QSGGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
             break;
     }
 
-    if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
-        while (visibleItems.count() > 1
-               && (item = visibleItems.first())
-                    && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
-            if (item->attached->delayRemove())
-                break;
+    return changed;
+}
+
+bool QSGGridViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
+{
+    FxGridItemSG *item = 0;
+    bool changed = false;
+
+    while (visibleItems.count() > 1
+           && (item = static_cast<FxGridItemSG*>(visibleItems.first()))
+                && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
+        if (item->attached->delayRemove())
+            break;
 //            qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
-            if (item->index != -1)
-                visibleIndex++;
-            visibleItems.removeFirst();
-            releaseItem(item);
-            changed = true;
-        }
-        while (visibleItems.count() > 1
-               && (item = visibleItems.last())
-                    && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
-            if (item->attached->delayRemove())
-                break;
-//            qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
-            visibleItems.removeLast();
-            releaseItem(item);
-            changed = true;
-        }
-        deferredRelease = false;
-    } else {
-        deferredRelease = true;
+        if (item->index != -1)
+            visibleIndex++;
+        visibleItems.removeFirst();
+        releaseItem(item);
+        changed = true;
     }
-    if (changed) {
-        if (header)
-            updateHeader();
-        if (footer)
-            updateFooter();
-        if (flow == QSGGridView::LeftToRight)
-            q->setContentHeight(endPosition() - startPosition());
-        else
-            q->setContentWidth(endPosition() - startPosition());
-    } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
-        refill(from, to, true);
+    while (visibleItems.count() > 1
+           && (item = static_cast<FxGridItemSG*>(visibleItems.last()))
+                && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
+        if (item->attached->delayRemove())
+            break;
+//            qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+        visibleItems.removeLast();
+        releaseItem(item);
+        changed = true;
     }
-    lazyRelease = false;
+
+    return changed;
 }
 
-void QSGGridViewPrivate::updateGrid()
+void QSGGridViewPrivate::visibleItemsChanged()
 {
     Q_Q(QSGGridView);
-    columns = (int)qMax((flow == QSGGridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
-    if (isValid()) {
-        if (flow == QSGGridView::LeftToRight)
-            q->setContentHeight(endPosition() - startPosition());
-        else
-            q->setContentWidth(lastPosition() - originPosition());
-    }
+
+    updateHeader();
+    updateFooter();
+    updateViewport();
 }
 
-void QSGGridViewPrivate::scheduleLayout()
+void QSGGridViewPrivate::updateViewport()
 {
     Q_Q(QSGGridView);
-    if (!layoutScheduled) {
-        layoutScheduled = true;
-        q->polish();
-    }
+    columns = (int)qMax((flow == QSGGridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
+    QSGItemViewPrivate::updateViewport();
 }
 
-void QSGGridViewPrivate::layout()
+void QSGGridViewPrivate::layoutVisibleItems()
 {
-    Q_Q(QSGGridView);
-    layoutScheduled = false;
-    if (!isValid() && !visibleItems.count()) {
-        clear();
-        return;
-    }
     if (visibleItems.count()) {
-        qreal rowPos = visibleItems.first()->rowPos();
-        qreal colPos = visibleItems.first()->colPos();
+        FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
+        qreal rowPos = firstItem->rowPos();
+        qreal colPos = firstItem->colPos();
         int col = visibleIndex % columns;
         if (colPos != col * colSize()) {
             colPos = col * colSize();
-            visibleItems.first()->setPosition(colPos, rowPos);
+            firstItem->setPosition(colPos, rowPos);
         }
         for (int i = 1; i < visibleItems.count(); ++i) {
-            FxGridItemSG *item = visibleItems.at(i);
+            FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
             colPos += colSize();
             if (colPos > colSize() * (columns-1)) {
                 colPos = 0;
@@ -743,68 +559,25 @@ void QSGGridViewPrivate::layout()
             item->setPosition(colPos, rowPos);
         }
     }
-    if (header)
-        updateHeader();
-    if (footer)
-        updateFooter();
-    q->refill();
-    updateHighlight();
-    moveReason = Other;
-    if (flow == QSGGridView::LeftToRight) {
-        q->setContentHeight(endPosition() - startPosition());
-        fixupY();
-    } else {
-        q->setContentWidth(endPosition() - startPosition());
-        fixupX();
-    }
-    updateUnrequestedPositions();
 }
 
-void QSGGridViewPrivate::updateUnrequestedIndexes()
+void QSGGridViewPrivate::repositionPackageItemAt(QSGItem *item, int index)
 {
     Q_Q(QSGGridView);
-    QHash<QSGItem*,int>::iterator it;
-    for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
-        *it = model->indexOf(it.key(), q);
-}
-
-void QSGGridViewPrivate::updateUnrequestedPositions()
-{
-    QHash<QSGItem*,int>::const_iterator it;
-    for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
-        QSGItem *item = it.key();
-        if (flow == QSGGridView::LeftToRight) {
-            item->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
-        } else {
+    qreal pos = position();
+    if (flow == QSGGridView::LeftToRight) {
+        if (item->y() + item->height() > pos && item->y() < pos + q->height())
+            item->setPos(QPointF(colPosAt(index), rowPosAt(index)));
+    } else {
+        if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
             if (isRightToLeftTopToBottom())
-                item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it)));
+                item->setPos(QPointF(-rowPosAt(index)-item->width(), colPosAt(index)));
             else
-                item->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
+                item->setPos(QPointF(rowPosAt(index), colPosAt(index)));
         }
     }
 }
 
-void QSGGridViewPrivate::updateTrackedItem()
-{
-    Q_Q(QSGGridView);
-    FxGridItemSG *item = currentItem;
-    if (highlight)
-        item = highlight;
-
-    if (trackedItem && item != trackedItem) {
-        QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
-        QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
-        trackedItem = 0;
-    }
-
-    if (!trackedItem && item) {
-        trackedItem = item;
-        QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
-        QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
-    }
-    if (trackedItem)
-        q->trackedPositionChanged();
-}
 
 void QSGGridViewPrivate::createHighlight()
 {
@@ -813,51 +586,31 @@ void QSGGridViewPrivate::createHighlight()
     if (highlight) {
         if (trackedItem == highlight)
             trackedItem = 0;
-        highlight->item->setParentItem(0);
-        highlight->item->deleteLater();
         delete highlight;
         highlight = 0;
+
         delete highlightXAnimator;
         delete highlightYAnimator;
         highlightXAnimator = 0;
         highlightYAnimator = 0;
+
         changed = true;
     }
 
     if (currentItem) {
-        QSGItem *item = 0;
-        if (highlightComponent) {
-            QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
-            QObject *nobj = highlightComponent->create(highlightContext);
-            if (nobj) {
-                QDeclarative_setParent_noEvent(highlightContext, nobj);
-                item = qobject_cast<QSGItem *>(nobj);
-                if (!item)
-                    delete nobj;
-            } else {
-                delete highlightContext;
-            }
-        } else {
-            item = new QSGItem;
-            QDeclarative_setParent_noEvent(item, q->contentItem());
-            item->setParentItem(q->contentItem());
-        }
+        QSGItem *item = createHighlightItem();
         if (item) {
-            QDeclarative_setParent_noEvent(item, q->contentItem());
-            item->setParentItem(q->contentItem());
-            highlight = new FxGridItemSG(item, q);
-            if (currentItem && autoHighlight)
-                highlight->setPosition(currentItem->colPos(), currentItem->rowPos());
+            FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true);
+            if (autoHighlight)
+                resetHighlightPosition();
             highlightXAnimator = new QSmoothedAnimation(q);
-            highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
+            highlightXAnimator->target = QDeclarativeProperty(item, QLatin1String("x"));
             highlightXAnimator->userDuration = highlightMoveDuration;
             highlightYAnimator = new QSmoothedAnimation(q);
-            highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y"));
+            highlightYAnimator->target = QDeclarativeProperty(item, QLatin1String("y"));
             highlightYAnimator->userDuration = highlightMoveDuration;
-            if (autoHighlight) {
-                highlightXAnimator->restart();
-                highlightYAnimator->restart();
-            }
+
+            highlight = newHighlight;
             changed = true;
         }
     }
@@ -875,150 +628,131 @@ void QSGGridViewPrivate::updateHighlight()
         highlightYAnimator->to = currentItem->item->y();
         highlight->item->setWidth(currentItem->item->width());
         highlight->item->setHeight(currentItem->item->height());
+
         highlightXAnimator->restart();
         highlightYAnimator->restart();
     }
     updateTrackedItem();
 }
 
-void QSGGridViewPrivate::updateCurrent(int modelIndex)
+void QSGGridViewPrivate::resetHighlightPosition()
 {
-    Q_Q(QSGGridView);
-    if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
-        if (currentItem) {
-            currentItem->attached->setIsCurrentItem(false);
-            releaseItem(currentItem);
-            currentItem = 0;
-            currentIndex = modelIndex;
-            emit q->currentIndexChanged();
-            updateHighlight();
-        } else if (currentIndex != modelIndex) {
-            currentIndex = modelIndex;
-            emit q->currentIndexChanged();
-        }
-        return;
+    if (highlight && currentItem) {
+        FxGridItemSG *cItem = static_cast<FxGridItemSG*>(currentItem);
+        static_cast<FxGridItemSG*>(highlight)->setPosition(cItem->colPos(), cItem->rowPos());
     }
+}
 
-    if (currentItem && currentIndex == modelIndex) {
-        updateHighlight();
-        return;
-    }
+qreal QSGGridViewPrivate::headerSize() const
+{
+    if (!header)
+        return 0.0;
+    return flow == QSGGridView::LeftToRight ? header->item->height() : header->item->width();
+}
 
-    FxGridItemSG *oldCurrentItem = currentItem;
-    currentIndex = modelIndex;
-    currentItem = createItem(modelIndex);
-    fixCurrentVisibility = true;
-    if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
-        oldCurrentItem->attached->setIsCurrentItem(false);
-    if (currentItem) {
-        currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
-        currentItem->item->setFocus(true);
-        currentItem->attached->setIsCurrentItem(true);
-    }
-    updateHighlight();
-    emit q->currentIndexChanged();
-    releaseItem(oldCurrentItem);
+qreal QSGGridViewPrivate::footerSize() const
+{
+    if (!footer)
+        return 0.0;
+    return flow == QSGGridView::LeftToRight? footer->item->height() : footer->item->width();
 }
 
 void QSGGridViewPrivate::updateFooter()
 {
     Q_Q(QSGGridView);
-    if (!footer && footerComponent) {
-        QSGItem *item = 0;
-        QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
-        QObject *nobj = footerComponent->create(context);
-        if (nobj) {
-            QDeclarative_setParent_noEvent(context, nobj);
-            item = qobject_cast<QSGItem *>(nobj);
-            if (!item)
-                delete nobj;
-        } else {
-            delete context;
-        }
-        if (item) {
-            QDeclarative_setParent_noEvent(item, q->contentItem());
-            item->setParentItem(q->contentItem());
-            item->setZ(1);
-            QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
-            itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
-            footer = new FxGridItemSG(item, q);
-        }
+
+    if (!footer) {
+        QSGItem *item = createComponentItem(footerComponent, true);
+        if (!item)
+            return;
+        item->setZ(1);
+        footer = new FxGridItemSG(item, q, true);
     }
-    if (footer) {
-        qreal colOffset = 0;
-        qreal rowOffset;
-        if (isRightToLeftTopToBottom()) {
-            rowOffset = footer->item->width()-cellWidth;
+
+    FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(footer);
+    qreal colOffset = 0;
+    qreal rowOffset;
+    if (isRightToLeftTopToBottom()) {
+        rowOffset = gridItem->item->width()-cellWidth;
+    } else {
+        rowOffset = 0;
+        if (q->effectiveLayoutDirection() == Qt::RightToLeft)
+            colOffset = gridItem->item->width()-cellWidth;
+    }
+    if (visibleItems.count()) {
+        qreal endPos = lastPosition();
+        if (findLastVisibleIndex() == model->count()-1) {
+            gridItem->setPosition(colOffset, endPos + rowOffset);
         } else {
-            rowOffset = 0;
-            if (q->effectiveLayoutDirection() == Qt::RightToLeft)
-                colOffset = footer->item->width()-cellWidth;
+            qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
+            if (endPos <= visiblePos || gridItem->endPosition() < endPos + rowOffset)
+                gridItem->setPosition(colOffset, endPos + rowOffset);
         }
-        if (visibleItems.count()) {
-            qreal endPos = lastPosition();
-            if (lastVisibleIndex() == model->count()-1) {
-                footer->setPosition(colOffset, endPos + rowOffset);
-            } else {
-                qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
-                if (endPos <= visiblePos || footer->endRowPos() < endPos + rowOffset)
-                    footer->setPosition(colOffset, endPos + rowOffset);
-            }
-        } else {
-            qreal endPos = 0;
-            if (header) {
-                endPos += (flow == QSGGridView::LeftToRight) ? header->item->height() : header->item->width();
-            }
-            footer->setPosition(colOffset, endPos);
+    } else {
+        qreal endPos = 0;
+        if (header) {
+            endPos += headerSize();
         }
+        gridItem->setPosition(colOffset, endPos);
     }
 }
 
 void QSGGridViewPrivate::updateHeader()
 {
     Q_Q(QSGGridView);
-    if (!header && headerComponent) {
-        QSGItem *item = 0;
-        QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
-        QObject *nobj = headerComponent->create(context);
-        if (nobj) {
-            QDeclarative_setParent_noEvent(context, nobj);
-            item = qobject_cast<QSGItem *>(nobj);
-            if (!item)
-                delete nobj;
-        } else {
-            delete context;
-        }
-        if (item) {
-            QDeclarative_setParent_noEvent(item, q->contentItem());
-            item->setParentItem(q->contentItem());
-            item->setZ(1);
-            QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
-            itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
-            header = new FxGridItemSG(item, q);
-        }
+
+    if (!header) {
+        QSGItem *item = createComponentItem(headerComponent, true);
+        if (!item)
+            return;
+        item->setZ(1);
+        header = new FxGridItemSG(item, q, true);
     }
-    if (header) {
-        qreal colOffset = 0;
-        qreal rowOffset;
-        if (isRightToLeftTopToBottom()) {
-            rowOffset = -cellWidth;
+
+    FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(header);
+    qreal colOffset = 0;
+    qreal rowOffset;
+    if (isRightToLeftTopToBottom()) {
+        rowOffset = -cellWidth;
+    } else {
+        rowOffset = -headerSize();
+        if (q->effectiveLayoutDirection() == Qt::RightToLeft)
+            colOffset = gridItem->item->width()-cellWidth;
+    }
+    if (visibleItems.count()) {
+        qreal startPos = originPosition();
+        if (visibleIndex == 0) {
+            gridItem->setPosition(colOffset, startPos + rowOffset);
         } else {
-            rowOffset = -headerSize();
-            if (q->effectiveLayoutDirection() == Qt::RightToLeft)
-                colOffset = header->item->width()-cellWidth;
+            qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
+            qreal headerPos = isRightToLeftTopToBottom() ? gridItem->rowPos() + cellWidth - headerSize() : gridItem->rowPos();
+            if (tempPos <= startPos || headerPos > startPos + rowOffset)
+                gridItem->setPosition(colOffset, startPos + rowOffset);
         }
-        if (visibleItems.count()) {
-            qreal startPos = originPosition();
-            if (visibleIndex == 0) {
-                header->setPosition(colOffset, startPos + rowOffset);
-            } else {
-                qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
-                qreal headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
-                if (tempPos <= startPos || headerPos > startPos + rowOffset)
-                    header->setPosition(colOffset, startPos + rowOffset);
-            }
-        } else {
-            header->setPosition(colOffset, 0);
+    } else {
+        gridItem->setPosition(colOffset, 0);
+    }
+}
+
+void QSGGridViewPrivate::initializeCurrentItem()
+{
+    if (currentItem && currentIndex >= 0) {
+        FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(currentItem);
+        if (gridItem)
+            gridItem->setPosition(colPosAt(currentIndex), rowPosAt(currentIndex));
+    }
+}
+
+void QSGGridViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+    Q_Q(QSGGridView);
+    QSGItemViewPrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+    if (!q->isComponentComplete())
+        return;
+    if (item == q) {
+        if (newGeometry.height() != oldGeometry.height() || newGeometry.width() != oldGeometry.width()) {
+            updateViewport();
+            scheduleLayout();
         }
     }
 }
@@ -1056,37 +790,37 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
 
     if (snapMode != QSGGridView::NoSnap) {
         qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position();
-        FxGridItemSG *topItem = snapItemAt(tempPosition+highlightStart);
-        FxGridItemSG *bottomItem = snapItemAt(tempPosition+highlightEnd);
+        FxViewItem *topItem = snapItemAt(tempPosition+highlightStart);
+        FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
         qreal pos;
         if (topItem && bottomItem && haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange) {
-            qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent);
-            qreal bottomPos = qMax(bottomItem->rowPos() - highlightEnd, -minExtent);
+            qreal topPos = qMin(topItem->position() - highlightStart, -maxExtent);
+            qreal bottomPos = qMax(bottomItem->position() - highlightEnd, -minExtent);
             pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
         } else if (topItem) {
             qreal headerPos = 0;
             if (header)
-                headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
+                headerPos = isRightToLeftTopToBottom() ? static_cast<FxGridItemSG*>(header)->rowPos() + cellWidth - headerSize() : static_cast<FxGridItemSG*>(header)->rowPos();
             if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2) {
                 pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart;
             } else {
                 if (isRightToLeftTopToBottom())
-                    pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
+                    pos = qMax(qMin(-topItem->position() + highlightStart - size(), -maxExtent), -minExtent);
                 else
-                    pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
+                    pos = qMax(qMin(topItem->position() - highlightStart, -maxExtent), -minExtent);
             }
         } else if (bottomItem) {
             if (isRightToLeftTopToBottom())
-                pos = qMax(qMin(-bottomItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
+                pos = qMax(qMin(-bottomItem->position() + highlightStart - size(), -maxExtent), -minExtent);
             else
-                pos = qMax(qMin(bottomItem->rowPos() - highlightStart, -maxExtent), -minExtent);
+                pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent);
         } else {
-            QSGFlickablePrivate::fixup(data, minExtent, maxExtent);
+            QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
             return;
         }
         if (currentItem && haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange) {
             updateHighlight();
-            qreal currPos = currentItem->rowPos();
+            qreal currPos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
             if (isRightToLeftTopToBottom())
                 pos = -pos-size(); // Transform Pos if required
             if (pos < currPos + rowSize() - highlightEnd)
@@ -1111,7 +845,7 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
     } else if (haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange) {
         if (currentItem) {
             updateHighlight();
-            qreal pos = currentItem->rowPos();
+            qreal pos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
             if (viewPos < pos + rowSize() - highlightEnd)
                 viewPos = pos + rowSize() - highlightEnd;
             if (viewPos > pos - highlightStart)
@@ -1130,7 +864,7 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
             vTime = timeline.time();
         }
     } else {
-        QSGFlickablePrivate::fixup(data, minExtent, maxExtent);
+        QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
     }
     data.inOvershoot = false;
     fixupMode = Normal;
@@ -1144,7 +878,7 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
     moveReason = Mouse;
     if ((!haveHighlightRange || highlightRange != QSGGridView::StrictlyEnforceRange)
         && snapMode == QSGGridView::NoSnap) {
-        QSGFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
+        QSGItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
         return;
     }
     qreal maxDistance = 0;
@@ -1153,8 +887,8 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
     if (velocity > 0) {
         if (data.move.value() < minExtent) {
             if (snapMode == QSGGridView::SnapOneRow) {
-                if (FxGridItemSG *item = firstVisibleItem())
-                    maxDistance = qAbs(item->rowPos() + dataValue);
+                if (FxViewItem *item = firstVisibleItem())
+                    maxDistance = qAbs(item->position() + dataValue);
             } else {
                 maxDistance = qAbs(minExtent - data.move.value());
             }
@@ -1238,338 +972,38 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
 //----------------------------------------------------------------------------
 
 QSGGridView::QSGGridView(QSGItem *parent)
-    : QSGFlickable(*(new QSGGridViewPrivate), parent)
-{
-    Q_D(QSGGridView);
-    d->init();
-}
-
-QSGGridView::~QSGGridView()
-{
-    Q_D(QSGGridView);
-    d->clear();
-    if (d->ownModel)
-        delete d->model;
-    delete d->header;
-    delete d->footer;
-}
-
-// For internal use
-int QSGGridView::modelCount() const
-{
-    Q_D(const QSGGridView);
-    return d->model->count();
-}
-
-QVariant QSGGridView::model() const
-{
-    Q_D(const QSGGridView);
-    return d->modelVariant;
-}
-
-void QSGGridView::setModel(const QVariant &model)
-{
-    Q_D(QSGGridView);
-    if (d->modelVariant == model)
-        return;
-    if (d->model) {
-        disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
-        disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
-        disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
-        disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
-        disconnect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
-        disconnect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
-    }
-    d->clear();
-    d->modelVariant = model;
-    QObject *object = qvariant_cast<QObject*>(model);
-    QSGVisualModel *vim = 0;
-    if (object && (vim = qobject_cast<QSGVisualModel *>(object))) {
-        if (d->ownModel) {
-            delete d->model;
-            d->ownModel = false;
-        }
-        d->model = vim;
-    } else {
-        if (!d->ownModel) {
-            d->model = new QSGVisualDataModel(qmlContext(this), this);
-            d->ownModel = true;
-        }
-        if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
-            dataModel->setModel(model);
-    }
-    if (d->model) {
-        d->bufferMode = QSGGridViewPrivate::BufferBefore | QSGGridViewPrivate::BufferAfter;
-        if (isComponentComplete()) {
-            refill();
-            if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
-                setCurrentIndex(0);
-            } else {
-                d->moveReason = QSGGridViewPrivate::SetIndex;
-                d->updateCurrent(d->currentIndex);
-                if (d->highlight && d->currentItem) {
-                    if (d->autoHighlight)
-                        d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
-                    d->updateTrackedItem();
-                }
-                d->moveReason = QSGGridViewPrivate::Other;
-            }
-        }
-        connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
-        connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
-        connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
-        connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
-        connect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
-        connect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
-        emit countChanged();
-    }
-    emit modelChanged();
-}
-
-QDeclarativeComponent *QSGGridView::delegate() const
-{
-    Q_D(const QSGGridView);
-    if (d->model) {
-        if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
-            return dataModel->delegate();
-    }
-
-    return 0;
-}
-
-void QSGGridView::setDelegate(QDeclarativeComponent *delegate)
+    : QSGItemView(*(new QSGGridViewPrivate), parent)
 {
-    Q_D(QSGGridView);
-    if (delegate == this->delegate())
-        return;
-
-    if (!d->ownModel) {
-        d->model = new QSGVisualDataModel(qmlContext(this));
-        d->ownModel = true;
-    }
-    if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model)) {
-        int oldCount = dataModel->count();
-        dataModel->setDelegate(delegate);
-        if (isComponentComplete()) {
-            for (int i = 0; i < d->visibleItems.count(); ++i)
-                d->releaseItem(d->visibleItems.at(i));
-            d->visibleItems.clear();
-            d->releaseItem(d->currentItem);
-            d->currentItem = 0;
-            refill();
-            d->moveReason = QSGGridViewPrivate::SetIndex;
-            d->updateCurrent(d->currentIndex);
-            if (d->highlight && d->currentItem) {
-                if (d->autoHighlight)
-                    d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
-                d->updateTrackedItem();
-            }
-            d->moveReason = QSGGridViewPrivate::Other;
-        }
-        if (oldCount != dataModel->count())
-            emit countChanged();
-        emit delegateChanged();
-    }
-}
-
-int QSGGridView::currentIndex() const
-{
-    Q_D(const QSGGridView);
-    return d->currentIndex;
-}
-
-void QSGGridView::setCurrentIndex(int index)
-{
-    Q_D(QSGGridView);
-    if (d->requestedIndex >= 0) // currently creating item
-        return;
-    d->currentIndexCleared = (index == -1);
-    if (index == d->currentIndex)
-        return;
-    if (isComponentComplete() && d->isValid()) {
-        d->moveReason = QSGGridViewPrivate::SetIndex;
-        d->updateCurrent(index);
-    } else {
-        d->currentIndex = index;
-        emit currentIndexChanged();
-    }
-}
-
-QSGItem *QSGGridView::currentItem()
-{
-    Q_D(QSGGridView);
-    if (!d->currentItem)
-        return 0;
-    return d->currentItem->item;
-}
-
-QSGItem *QSGGridView::highlightItem()
-{
-    Q_D(QSGGridView);
-    if (!d->highlight)
-        return 0;
-    return d->highlight->item;
-}
-
-int QSGGridView::count() const
-{
-    Q_D(const QSGGridView);
-    if (d->model)
-        return d->model->count();
-    return 0;
-}
-
-QDeclarativeComponent *QSGGridView::highlight() const
-{
-    Q_D(const QSGGridView);
-    return d->highlightComponent;
-}
-
-void QSGGridView::setHighlight(QDeclarativeComponent *highlight)
-{
-    Q_D(QSGGridView);
-    if (highlight != d->highlightComponent) {
-        d->highlightComponent = highlight;
-        d->updateCurrent(d->currentIndex);
-        emit highlightChanged();
-    }
 }
 
-bool QSGGridView::highlightFollowsCurrentItem() const
+QSGGridView::~QSGGridView()
 {
-    Q_D(const QSGGridView);
-    return d->autoHighlight;
 }
 
 void QSGGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
 {
     Q_D(QSGGridView);
     if (d->autoHighlight != autoHighlight) {
-        d->autoHighlight = autoHighlight;
-        if (autoHighlight) {
-            d->updateHighlight();
-        } else if (d->highlightXAnimator) {
+        if (!autoHighlight && d->highlightXAnimator) {
             d->highlightXAnimator->stop();
             d->highlightYAnimator->stop();
         }
+        QSGItemView::setHighlightFollowsCurrentItem(autoHighlight);
     }
 }
 
-int QSGGridView::highlightMoveDuration() const
-{
-    Q_D(const QSGGridView);
-    return d->highlightMoveDuration;
-}
-
 void QSGGridView::setHighlightMoveDuration(int duration)
 {
     Q_D(QSGGridView);
     if (d->highlightMoveDuration != duration) {
-        d->highlightMoveDuration = duration;
         if (d->highlightYAnimator) {
-            d->highlightXAnimator->userDuration = d->highlightMoveDuration;
-            d->highlightYAnimator->userDuration = d->highlightMoveDuration;
+            d->highlightXAnimator->userDuration = duration;
+            d->highlightYAnimator->userDuration = duration;
         }
-        emit highlightMoveDurationChanged();
-    }
-}
-
-qreal QSGGridView::preferredHighlightBegin() const
-{
-    Q_D(const QSGGridView);
-    return d->highlightRangeStart;
-}
-
-void QSGGridView::setPreferredHighlightBegin(qreal start)
-{
-    Q_D(QSGGridView);
-    d->highlightRangeStartValid = true;
-    if (d->highlightRangeStart == start)
-        return;
-    d->highlightRangeStart = start;
-    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
-    emit preferredHighlightBeginChanged();
-}
-
-void QSGGridView::resetPreferredHighlightBegin()
-{
-    Q_D(QSGGridView);
-    d->highlightRangeStartValid = false;
-    if (d->highlightRangeStart == 0)
-        return;
-    d->highlightRangeStart = 0;
-    emit preferredHighlightBeginChanged();
-}
-
-qreal QSGGridView::preferredHighlightEnd() const
-{
-    Q_D(const QSGGridView);
-    return d->highlightRangeEnd;
-}
-
-void QSGGridView::setPreferredHighlightEnd(qreal end)
-{
-    Q_D(QSGGridView);
-    d->highlightRangeEndValid = true;
-    if (d->highlightRangeEnd == end)
-        return;
-    d->highlightRangeEnd = end;
-    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
-    emit preferredHighlightEndChanged();
-}
-
-void QSGGridView::resetPreferredHighlightEnd()
-{
-    Q_D(QSGGridView);
-    d->highlightRangeEndValid = false;
-    if (d->highlightRangeEnd == 0)
-        return;
-    d->highlightRangeEnd = 0;
-    emit preferredHighlightEndChanged();
-}
-
-QSGGridView::HighlightRangeMode QSGGridView::highlightRangeMode() const
-{
-    Q_D(const QSGGridView);
-    return d->highlightRange;
-}
-
-void QSGGridView::setHighlightRangeMode(HighlightRangeMode mode)
-{
-    Q_D(QSGGridView);
-    if (d->highlightRange == mode)
-        return;
-    d->highlightRange = mode;
-    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
-    emit highlightRangeModeChanged();
-}
-
-Qt::LayoutDirection QSGGridView::layoutDirection() const
-{
-    Q_D(const QSGGridView);
-    return d->layoutDirection;
-}
-
-void QSGGridView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
-{
-    Q_D(QSGGridView);
-    if (d->layoutDirection != layoutDirection) {
-        d->layoutDirection = layoutDirection;
-        d->regenerate();
-        emit layoutDirectionChanged();
-        emit effectiveLayoutDirectionChanged();
+        QSGItemView::setHighlightMoveDuration(duration);
     }
 }
 
-Qt::LayoutDirection QSGGridView::effectiveLayoutDirection() const
-{
-    Q_D(const QSGGridView);
-    if (d->effectiveLayoutMirror)
-        return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
-    else
-        return d->layoutDirection;
-}
-
 QSGGridView::Flow QSGGridView::flow() const
 {
     Q_D(const QSGGridView);
@@ -1583,10 +1017,10 @@ void QSGGridView::setFlow(Flow flow)
         d->flow = flow;
         if (d->flow == LeftToRight) {
             setContentWidth(-1);
-            setFlickableDirection(QSGFlickable::VerticalFlick);
+            setFlickableDirection(VerticalFlick);
         } else {
             setContentHeight(-1);
-            setFlickableDirection(QSGFlickable::HorizontalFlick);
+            setFlickableDirection(HorizontalFlick);
         }
         setContentX(0);
         setContentY(0);
@@ -1595,37 +1029,6 @@ void QSGGridView::setFlow(Flow flow)
     }
 }
 
-bool QSGGridView::isWrapEnabled() const
-{
-    Q_D(const QSGGridView);
-    return d->wrap;
-}
-
-void QSGGridView::setWrapEnabled(bool wrap)
-{
-    Q_D(QSGGridView);
-    if (d->wrap == wrap)
-        return;
-    d->wrap = wrap;
-    emit keyNavigationWrapsChanged();
-}
-
-int QSGGridView::cacheBuffer() const
-{
-    Q_D(const QSGGridView);
-    return d->buffer;
-}
-
-void QSGGridView::setCacheBuffer(int buffer)
-{
-    Q_D(QSGGridView);
-    if (d->buffer != buffer) {
-        d->buffer = buffer;
-        if (isComponentComplete())
-            refill();
-        emit cacheBufferChanged();
-    }
-}
 
 int QSGGridView::cellWidth() const
 {
@@ -1638,9 +1041,9 @@ void QSGGridView::setCellWidth(int cellWidth)
     Q_D(QSGGridView);
     if (cellWidth != d->cellWidth && cellWidth > 0) {
         d->cellWidth = qMax(1, cellWidth);
-        d->updateGrid();
+        d->updateViewport();
         emit cellWidthChanged();
-        d->layout();
+        d->layoutVisibleItems();
     }
 }
 
@@ -1655,9 +1058,9 @@ void QSGGridView::setCellHeight(int cellHeight)
     Q_D(QSGGridView);
     if (cellHeight != d->cellHeight && cellHeight > 0) {
         d->cellHeight = qMax(1, cellHeight);
-        d->updateGrid();
+        d->updateViewport();
         emit cellHeightChanged();
-        d->layout();
+        d->layoutVisibleItems();
     }
 }
 
@@ -1676,90 +1079,17 @@ void QSGGridView::setSnapMode(SnapMode mode)
     }
 }
 
-QDeclarativeComponent *QSGGridView::footer() const
-{
-    Q_D(const QSGGridView);
-    return d->footerComponent;
-}
-
-void QSGGridView::setFooter(QDeclarativeComponent *footer)
-{
-    Q_D(QSGGridView);
-    if (d->footerComponent != footer) {
-        if (d->footer) {
-            // XXX todo - the original did scene()->removeItem().  Why?
-            d->footer->item->setParentItem(0);
-            d->footer->item->deleteLater();
-            delete d->footer;
-            d->footer = 0;
-        }
-        d->footerComponent = footer;
-        if (isComponentComplete()) {
-            d->updateFooter();
-            d->updateGrid();
-            d->fixupPosition();
-        }
-        emit footerChanged();
-    }
-}
-
-QDeclarativeComponent *QSGGridView::header() const
-{
-    Q_D(const QSGGridView);
-    return d->headerComponent;
-}
-
-void QSGGridView::setHeader(QDeclarativeComponent *header)
-{
-    Q_D(QSGGridView);
-    if (d->headerComponent != header) {
-        if (d->header) {
-            // XXX todo - the original did scene()->removeItem().  Why?
-            d->header->item->setParentItem(0);
-            d->header->item->deleteLater();
-            delete d->header;
-            d->header = 0;
-        }
-        d->headerComponent = header;
-        if (isComponentComplete()) {
-            d->updateHeader();
-            d->updateFooter();
-            d->updateGrid();
-            d->fixupPosition();
-        }
-        emit headerChanged();
-    }
-}
-
-void QSGGridView::setContentX(qreal pos)
-{
-    Q_D(QSGGridView);
-    // Positioning the view manually should override any current movement state
-    d->moveReason = QSGGridViewPrivate::Other;
-    QSGFlickable::setContentX(pos);
-}
-
-void QSGGridView::setContentY(qreal pos)
-{
-    Q_D(QSGGridView);
-    // Positioning the view manually should override any current movement state
-    d->moveReason = QSGGridViewPrivate::Other;
-    QSGFlickable::setContentY(pos);
-}
-
-void QSGGridView::updatePolish() 
-{
-    Q_D(QSGGridView);
-    QSGFlickable::updatePolish();
-    d->layout();
-}
 
 void QSGGridView::viewportMoved()
 {
     Q_D(QSGGridView);
-    QSGFlickable::viewportMoved();
+    QSGItemView::viewportMoved();
     if (!d->itemCount)
         return;
+    if (d->inViewportMoved)
+        return;
+    d->inViewportMoved = true;
+
     d->lazyRelease = true;
     if (d->flickingHorizontally || d->flickingVertically) {
         if (yflick()) {
@@ -1776,36 +1106,37 @@ void QSGGridView::viewportMoved()
                 d->bufferMode = QSGGridViewPrivate::BufferAfter;
         }
     }
-    refill();
+    d->refill();
     if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
         d->moveReason = QSGGridViewPrivate::Mouse;
     if (d->moveReason != QSGGridViewPrivate::SetIndex) {
         if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
             // reposition highlight
-            qreal pos = d->highlight->rowPos();
+            qreal pos = d->highlight->position();
             qreal viewPos;
             qreal highlightStart;
             qreal highlightEnd;
             if (d->isRightToLeftTopToBottom()) {
+                viewPos = -d->position()-d->size();
                 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
                 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
-                viewPos = -d->position()-d->size();
             } else {
+                viewPos = d->position();
                 highlightStart = d->highlightRangeStart;
                 highlightEnd = d->highlightRangeEnd;
-                viewPos = d->position();
             }
-            if (pos > viewPos + highlightEnd - d->rowSize())
-                pos = viewPos + highlightEnd - d->rowSize();
+            if (pos > viewPos + highlightEnd - d->highlight->size())
+                pos = viewPos + highlightEnd - d->highlight->size();
             if (pos < viewPos + highlightStart)
                 pos = viewPos + highlightStart;
-            d->highlight->setPosition(d->highlight->colPos(), qRound(pos));
+
+            static_cast<FxGridItemSG*>(d->highlight)->setPosition(static_cast<FxGridItemSG*>(d->highlight)->colPos(), qRound(pos));
 
             // update current index
             int idx = d->snapIndex();
             if (idx >= 0 && idx != d->currentIndex) {
                 d->updateCurrent(idx);
-                if (d->currentItem && d->currentItem->colPos() != d->highlight->colPos() && d->autoHighlight) {
+                if (d->currentItem && static_cast<FxGridItemSG*>(d->currentItem)->colPos() != static_cast<FxGridItemSG*>(d->highlight)->colPos() && d->autoHighlight) {
                     if (d->flow == LeftToRight)
                         d->highlightXAnimator->to = d->currentItem->item->x();
                     else
@@ -1814,120 +1145,8 @@ void QSGGridView::viewportMoved()
             }
         }
     }
-}
-
-qreal QSGGridView::minYExtent() const
-{
-    Q_D(const QSGGridView);
-    if (d->flow == QSGGridView::TopToBottom)
-        return QSGFlickable::minYExtent();
-    qreal extent = -d->startPosition();
-    if (d->header && d->visibleItems.count())
-        extent += d->header->item->height();
-    if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
-        extent += d->highlightRangeStart;
-        extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
-    }
-    return extent;
-}
-
-qreal QSGGridView::maxYExtent() const
-{
-    Q_D(const QSGGridView);
-    if (d->flow == QSGGridView::TopToBottom)
-        return QSGFlickable::maxYExtent();
-    qreal extent;
-    if (!d->model || !d->model->count()) {
-        extent = 0;
-    } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
-        extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
-        if (d->highlightRangeEnd != d->highlightRangeStart)
-            extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
-    } else {
-        extent = -(d->endPosition() - height());
-    }
-    if (d->footer)
-        extent -= d->footer->item->height();
-    const qreal minY = minYExtent();
-    if (extent > minY)
-        extent = minY;
-    return extent;
-}
-
-qreal QSGGridView::minXExtent() const
-{
-    Q_D(const QSGGridView);
-    if (d->flow == QSGGridView::LeftToRight)
-        return QSGFlickable::minXExtent();
-    qreal extent = -d->startPosition();
-    qreal highlightStart;
-    qreal highlightEnd;
-    qreal endPositionFirstItem;
-    if (d->isRightToLeftTopToBottom()) {
-        endPositionFirstItem = d->rowPosAt(d->model->count()-1);
-        highlightStart = d->highlightRangeStartValid
-                ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
-                : d->size() - (d->lastPosition()-endPositionFirstItem);
-        highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
-        if (d->footer && d->visibleItems.count())
-            extent += d->footer->item->width();
-    } else {
-        endPositionFirstItem = d->rowPosAt(0)+d->rowSize();
-        highlightStart = d->highlightRangeStart;
-        highlightEnd = d->highlightRangeEnd;
-        if (d->header && d->visibleItems.count())
-            extent += d->header->item->width();
-    }
-    if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
-        extent += highlightStart;
-        extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
-    }
-    return extent;
-}
-
-qreal QSGGridView::maxXExtent() const
-{
-    Q_D(const QSGGridView);
-    if (d->flow == QSGGridView::LeftToRight)
-        return QSGFlickable::maxXExtent();
-    qreal extent;
-    qreal highlightStart;
-    qreal highlightEnd;
-    qreal lastItemPosition = 0;
-    if (d->isRightToLeftTopToBottom()){
-        highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
-        highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
-        lastItemPosition = d->endPosition();
-    } else {
-        highlightStart = d->highlightRangeStart;
-        highlightEnd = d->highlightRangeEnd;
-        lastItemPosition = 0;
-        if (d->model && d->model->count())
-            lastItemPosition = d->rowPosAt(d->model->count()-1);
-    }
-    if (!d->model || !d->model->count()) {
-        extent = 0;
-    } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
-        extent = -(lastItemPosition - highlightStart);
-        if (highlightEnd != highlightStart)
-            extent = d->isRightToLeftTopToBottom()
-                    ? qMax(extent, -(d->endPosition() - highlightEnd + 1))
-                    : qMin(extent, -(d->endPosition() - highlightEnd + 1));
-    } else {
-        extent = -(d->endPosition() - width());
-    }
-    if (d->isRightToLeftTopToBottom()) {
-        if (d->header)
-            extent -= d->header->item->width();
-    } else {
-        if (d->footer)
-            extent -= d->footer->item->width();
-    }
 
-    const qreal minX = minXExtent();
-    if (extent > minX)
-        extent = minX;
-    return extent;
+    d->inViewportMoved = false;
 }
 
 void QSGGridView::keyPressEvent(QKeyEvent *event)
@@ -1959,7 +1178,7 @@ void QSGGridView::keyPressEvent(QKeyEvent *event)
     }
     d->moveReason = QSGGridViewPrivate::Other;
     event->ignore();
-    QSGFlickable::keyPressEvent(event);
+    QSGItemView::keyPressEvent(event);
 }
 
 void QSGGridView::moveCurrentIndexUp()
@@ -2066,214 +1285,6 @@ void QSGGridView::moveCurrentIndexRight()
     }
 }
 
-void QSGGridViewPrivate::positionViewAtIndex(int index, int mode)
-{
-    Q_Q(QSGGridView);
-    if (!isValid())
-        return;
-    if (mode < QSGGridView::Beginning || mode > QSGGridView::Contain)
-        return;
-
-    int idx = qMax(qMin(index, model->count()-1), 0);
-
-    if (layoutScheduled)
-        layout();
-    qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position();
-    FxGridItemSG *item = visibleItem(idx);
-    qreal maxExtent;
-    if (flow == QSGGridView::LeftToRight)
-        maxExtent = -q->maxYExtent();
-    else
-        maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
-    if (!item) {
-        int itemPos = rowPosAt(idx);
-        // save the currently visible items in case any of them end up visible again
-        QList<FxGridItemSG*> oldVisible = visibleItems;
-        visibleItems.clear();
-        visibleIndex = idx - idx % columns;
-        if (flow == QSGGridView::LeftToRight)
-            maxExtent = -q->maxYExtent();
-        else
-            maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
-        setPosition(qMin(qreal(itemPos), maxExtent));
-        // now release the reference to all the old visible items.
-        for (int i = 0; i < oldVisible.count(); ++i)
-            releaseItem(oldVisible.at(i));
-        item = visibleItem(idx);
-    }
-    if (item) {
-        qreal itemPos = item->rowPos();
-        switch (mode) {
-        case QSGGridView::Beginning:
-            pos = itemPos;
-            if (index < 0 && header) {
-                pos -= flow == QSGGridView::LeftToRight
-                            ? header->item->height()
-                            : header->item->width();
-            }
-            break;
-        case QSGGridView::Center:
-            pos = itemPos - (size() - rowSize())/2;
-            break;
-        case QSGGridView::End:
-            pos = itemPos - size() + rowSize();
-            if (index >= model->count() && footer) {
-                pos += flow == QSGGridView::LeftToRight
-                            ? footer->item->height()
-                            : footer->item->width();
-            }
-            break;
-        case QSGGridView::Visible:
-            if (itemPos > pos + size())
-                pos = itemPos - size() + rowSize();
-            else if (item->endRowPos() < pos)
-                pos = itemPos;
-            break;
-        case QSGGridView::Contain:
-            if (item->endRowPos() > pos + size())
-                pos = itemPos - size() + rowSize();
-            if (itemPos < pos)
-                pos = itemPos;
-        }
-        pos = qMin(pos, maxExtent);
-        qreal minExtent;
-        if (flow == QSGGridView::LeftToRight)
-            minExtent = -q->minYExtent();
-        else
-            minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent();
-        pos = qMax(pos, minExtent);
-        moveReason = QSGGridViewPrivate::Other;
-        q->cancelFlick();
-        setPosition(pos);
-    }
-    fixupPosition();
-}
-
-void QSGGridView::positionViewAtIndex(int index, int mode)
-{
-    Q_D(QSGGridView);
-    if (!d->isValid() || index < 0 || index >= d->model->count())
-        return;
-    d->positionViewAtIndex(index, mode);
-}
-
-void QSGGridView::positionViewAtBeginning()
-{
-    Q_D(QSGGridView);
-    if (!d->isValid())
-        return;
-    d->positionViewAtIndex(-1, Beginning);
-}
-
-void QSGGridView::positionViewAtEnd()
-{
-    Q_D(QSGGridView);
-    if (!d->isValid())
-        return;
-    d->positionViewAtIndex(d->model->count(), End);
-}
-
-int QSGGridView::indexAt(qreal x, qreal y) const
-{
-    Q_D(const QSGGridView);
-    for (int i = 0; i < d->visibleItems.count(); ++i) {
-        const FxGridItemSG *listItem = d->visibleItems.at(i);
-        if(listItem->contains(x, y))
-            return listItem->index;
-    }
-
-    return -1;
-}
-
-void QSGGridView::componentComplete()
-{
-    Q_D(QSGGridView);
-    QSGFlickable::componentComplete();
-    d->updateHeader();
-    d->updateFooter();
-    d->updateGrid();
-    if (d->isValid()) {
-        refill();
-        d->moveReason = QSGGridViewPrivate::SetIndex;
-        if (d->currentIndex < 0 && !d->currentIndexCleared)
-            d->updateCurrent(0);
-        else
-            d->updateCurrent(d->currentIndex);
-        if (d->highlight && d->currentItem) {
-            if (d->autoHighlight)
-                d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
-            d->updateTrackedItem();
-        }
-        d->moveReason = QSGGridViewPrivate::Other;
-        d->fixupPosition();
-    }
-}
-
-void QSGGridView::trackedPositionChanged()
-{
-    Q_D(QSGGridView);
-    if (!d->trackedItem || !d->currentItem)
-        return;
-    if (d->moveReason == QSGGridViewPrivate::SetIndex) {
-        const qreal trackedPos = d->trackedItem->rowPos();
-        qreal viewPos;
-        qreal highlightStart;
-        qreal highlightEnd;
-        if (d->isRightToLeftTopToBottom()) {
-            viewPos = -d->position()-d->size();
-            highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
-            highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
-        } else {
-            viewPos = d->position();
-            highlightStart = d->highlightRangeStart;
-            highlightEnd = d->highlightRangeEnd;
-        }
-        qreal pos = viewPos;
-        if (d->haveHighlightRange) {
-            if (d->highlightRange == StrictlyEnforceRange) {
-                if (trackedPos > pos + highlightEnd - d->rowSize())
-                    pos = trackedPos - highlightEnd + d->rowSize();
-                if (trackedPos < pos + highlightStart)
-                    pos = trackedPos - highlightStart;
-            } else {
-                if (trackedPos < d->startPosition() + highlightStart) {
-                    pos = d->startPosition();
-                } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + highlightEnd) {
-                    pos = d->endPosition() - d->size() + 1;
-                    if (pos < d->startPosition())
-                        pos = d->startPosition();
-                } else {
-                    if (trackedPos < viewPos + highlightStart) {
-                        pos = trackedPos - highlightStart;
-                    } else if (trackedPos > viewPos + highlightEnd - d->rowSize()) {
-                        pos = trackedPos - highlightEnd + d->rowSize();
-                    }
-                }
-            }
-        } else {
-            if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) {
-                pos = qMax(trackedPos, d->currentItem->rowPos());
-            } else if (d->trackedItem->endRowPos() >= viewPos + d->size()
-                && d->currentItem->endRowPos() >= viewPos + d->size()) {
-                if (d->trackedItem->endRowPos() <= d->currentItem->endRowPos()) {
-                    pos = d->trackedItem->endRowPos() - d->size() + 1;
-                    if (d->rowSize() > d->size())
-                        pos = trackedPos;
-                } else {
-                    pos = d->currentItem->endRowPos() - d->size() + 1;
-                    if (d->rowSize() > d->size())
-                        pos = d->currentItem->rowPos();
-                }
-            }
-        }
-        if (viewPos != pos) {
-            cancelFlick();
-            d->calcVelocity = true;
-            d->setPosition(pos);
-            d->calcVelocity = false;
-        }
-    }
-}
 
 void QSGGridView::itemsInserted(int modelIndex, int count)
 {
@@ -2294,9 +1305,9 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
                 // Insert before visible items
                 d->visibleIndex += count;
                 for (int i = 0; i < d->visibleItems.count(); ++i) {
-                    FxGridItemSG *listItem = d->visibleItems.at(i);
-                    if (listItem->index != -1 && listItem->index >= modelIndex)
-                        listItem->index += count;
+                    FxViewItem *item = d->visibleItems.at(i);
+                    if (item->index != -1 && item->index >= modelIndex)
+                        item->index += count;
                 }
             }
             if (d->currentIndex >= modelIndex) {
@@ -2327,12 +1338,14 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
     if (d->visibleItems.count()) {
         index -= d->visibleIndex;
         if (index < d->visibleItems.count()) {
-            colPos = d->visibleItems.at(index)->colPos();
-            rowPos = d->visibleItems.at(index)->rowPos();
+            FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(d->visibleItems.at(index));
+            colPos = gridItem->colPos();
+            rowPos = gridItem->rowPos();
         } else {
             // appending items to visible list
-            colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
-            rowPos = d->visibleItems.at(index-1)->rowPos();
+            FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(d->visibleItems.at(index-1));
+            colPos = gridItem->colPos() + d->colSize();
+            rowPos = gridItem->rowPos();
             if (colPos > d->colSize() * (d->columns-1)) {
                 colPos = 0;
                 rowPos += d->rowSize();
@@ -2344,9 +1357,9 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
 
     // Update the indexes of the following visible items.
     for (int i = 0; i < d->visibleItems.count(); ++i) {
-        FxGridItemSG *listItem = d->visibleItems.at(i);
-        if (listItem->index != -1 && listItem->index >= modelIndex)
-            listItem->index += count;
+        FxViewItem *item = d->visibleItems.at(i);
+        if (item->index != -1 && item->index >= modelIndex)
+            item->index += count;
     }
 
     bool addedVisible = false;
@@ -2357,7 +1370,7 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
             d->scheduleLayout();
             addedVisible = true;
         }
-        FxGridItemSG *item = d->createItem(modelIndex + i);
+        FxGridItemSG *item = static_cast<FxGridItemSG*>(d->createItem(modelIndex + i));
         d->visibleItems.insert(index, item);
         item->setPosition(colPos, rowPos);
         added.append(item);
@@ -2379,7 +1392,7 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
 
     // update visibleIndex
     d->visibleIndex = 0;
-    for (QList<FxGridItemSG*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+    for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
         if ((*it)->index != -1) {
             d->visibleIndex = (*it)->index;
             break;
@@ -2391,7 +1404,7 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
         d->currentIndex += count;
         if (d->currentItem) {
             d->currentItem->index = d->currentIndex;
-            d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
+            static_cast<FxGridItemSG*>(d->currentItem)->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
         }
         emit currentIndexChanged();
     } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
@@ -2417,9 +1430,9 @@ void QSGGridView::itemsRemoved(int modelIndex, int count)
     bool removedVisible = false;
 
     // Remove the items from the visible list, skipping anything already marked for removal
-    QList<FxGridItemSG*>::Iterator it = d->visibleItems.begin();
+    QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
     while (it != d->visibleItems.end()) {
-        FxGridItemSG *item = *it;
+        FxViewItem *item = *it;
         if (item->index == -1 || item->index < modelIndex) {
             // already removed, or before removed items
             if (item->index < modelIndex && !removedVisible) {
@@ -2487,23 +1500,6 @@ void QSGGridView::itemsRemoved(int modelIndex, int count)
     emit countChanged();
 }
 
-void QSGGridView::destroyRemoved()
-{
-    Q_D(QSGGridView);
-    for (QList<FxGridItemSG*>::Iterator it = d->visibleItems.begin();
-            it != d->visibleItems.end();) {
-        FxGridItemSG *listItem = *it;
-        if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
-            d->releaseItem(listItem);
-            it = d->visibleItems.erase(it);
-        } else {
-            ++it;
-        }
-    }
-
-    // Correct the positioning of the items
-    d->layout();
-}
 
 void QSGGridView::itemsMoved(int from, int to, int count)
 {
@@ -2512,15 +1508,15 @@ void QSGGridView::itemsMoved(int from, int to, int count)
         return;
     QHash<int,FxGridItemSG*> moved;
 
-    FxGridItemSG *firstItem = d->firstVisibleItem();
+    FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(d->firstVisibleItem());
 
-    QList<FxGridItemSG*>::Iterator it = d->visibleItems.begin();
+    QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
     while (it != d->visibleItems.end()) {
-        FxGridItemSG *item = *it;
+        FxViewItem *item = *it;
         if (item->index >= from && item->index < from + count) {
             // take the items that are moving
             item->index += (to-from);
-            moved.insert(item->index, item);
+            moved.insert(item->index, static_cast<FxGridItemSG*>(item));
             it = d->visibleItems.erase(it);
         } else {
             if (item->index > from && item->index != -1) {
@@ -2537,12 +1533,12 @@ void QSGGridView::itemsMoved(int from, int to, int count)
     int endIndex = d->visibleIndex;
     it = d->visibleItems.begin();
     while (it != d->visibleItems.end()) {
-        FxGridItemSG *item = *it;
+        FxViewItem *item = *it;
         if (remaining && item->index >= to && item->index < to + count) {
             // place items in the target position, reusing any existing items
             FxGridItemSG *movedItem = moved.take(item->index);
             if (!movedItem)
-                movedItem = d->createItem(item->index);
+                movedItem = static_cast<FxGridItemSG*>(d->createItem(item->index));
             it = d->visibleItems.insert(it, movedItem);
             if (it == d->visibleItems.begin() && firstItem)
                 movedItem->setPosition(firstItem->colPos(), firstItem->rowPos());
@@ -2594,61 +1590,7 @@ void QSGGridView::itemsMoved(int from, int to, int count)
         d->releaseItem(item);
     }
 
-    d->layout();
-}
-
-void QSGGridView::modelReset()
-{
-    Q_D(QSGGridView);
-    d->clear();
-    refill();
-    d->moveReason = QSGGridViewPrivate::SetIndex;
-    d->updateCurrent(d->currentIndex);
-    if (d->highlight && d->currentItem) {
-        if (d->autoHighlight)
-            d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
-        d->updateTrackedItem();
-    }
-    d->moveReason = QSGGridViewPrivate::Other;
-
-    emit countChanged();
-}
-
-void QSGGridView::createdItem(int index, QSGItem *item)
-{
-    Q_D(QSGGridView);
-    if (d->requestedIndex != index) {
-        item->setParentItem(this);
-        d->unrequestedItems.insert(item, index);
-        if (d->flow == QSGGridView::LeftToRight) {
-            item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
-        } else {
-            item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
-        }
-    }
-}
-
-void QSGGridView::destroyingItem(QSGItem *item)
-{
-    Q_D(QSGGridView);
-    d->unrequestedItems.remove(item);
-}
-
-void QSGGridView::animStopped()
-{
-    Q_D(QSGGridView);
-    d->bufferMode = QSGGridViewPrivate::NoBuffer;
-    if (d->haveHighlightRange && d->highlightRange == QSGGridView::StrictlyEnforceRange)
-        d->updateHighlight();
-}
-
-void QSGGridView::refill()
-{
-    Q_D(QSGGridView);
-    if (d->isRightToLeftTopToBottom())
-        d->refill(-d->position()-d->size()+1, -d->position());
-    else
-        d->refill(d->position(), d->position()+d->size()-1);
+    d->layoutVisibleItems();
 }
 
 
index 8c167c8..ae4ce34 100644 (file)
@@ -43,7 +43,7 @@
 #ifndef QSGGRIDVIEW_P_H
 #define QSGGRIDVIEW_P_H
 
-#include "qsgflickable_p.h"
+#include "qsgitemview_p.h"
 
 #include <private/qdeclarativeguard_p.h>
 
@@ -55,98 +55,32 @@ QT_MODULE(Declarative)
 class QSGVisualModel;
 class QSGGridViewAttached;
 class QSGGridViewPrivate;
-class Q_AUTOTEST_EXPORT QSGGridView : public QSGFlickable
+class Q_AUTOTEST_EXPORT QSGGridView : public QSGItemView
 {
     Q_OBJECT
     Q_DECLARE_PRIVATE(QSGGridView)
 
-    Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
-    Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
-    Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
-    Q_PROPERTY(QSGItem *currentItem READ currentItem NOTIFY currentIndexChanged)
-    Q_PROPERTY(int count READ count NOTIFY countChanged)
-
-    Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
-    Q_PROPERTY(QSGItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
-    Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem)
-    Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
-
-    Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
-    Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
-    Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
-
     Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
-    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
-    Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
-    Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
-    Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
     Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
     Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
 
     Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
 
-    Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
-    Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
-
-    Q_ENUMS(HighlightRangeMode)
     Q_ENUMS(SnapMode)
     Q_ENUMS(Flow)
-    Q_ENUMS(PositionMode)
     Q_CLASSINFO("DefaultProperty", "data")
 
 public:
     QSGGridView(QSGItem *parent=0);
     ~QSGGridView();
 
-    QVariant model() const;
-    int modelCount() const;
-    void setModel(const QVariant &);
-
-    QDeclarativeComponent *delegate() const;
-    void setDelegate(QDeclarativeComponent *);
-
-    int currentIndex() const;
-    void setCurrentIndex(int idx);
-
-    QSGItem *currentItem();
-    QSGItem *highlightItem();
-    int count() const;
-
-    QDeclarativeComponent *highlight() const;
-    void setHighlight(QDeclarativeComponent *highlight);
-
-    bool highlightFollowsCurrentItem() const;
-    void setHighlightFollowsCurrentItem(bool);
-
-    int highlightMoveDuration() const;
-    void setHighlightMoveDuration(int);
-
-    enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
-    HighlightRangeMode highlightRangeMode() const;
-    void setHighlightRangeMode(HighlightRangeMode mode);
-
-    qreal preferredHighlightBegin() const;
-    void setPreferredHighlightBegin(qreal);
-    void resetPreferredHighlightBegin();
-
-    qreal preferredHighlightEnd() const;
-    void setPreferredHighlightEnd(qreal);
-    void resetPreferredHighlightEnd();
-
-    Qt::LayoutDirection layoutDirection() const;
-    void setLayoutDirection(Qt::LayoutDirection);
-    Qt::LayoutDirection effectiveLayoutDirection() const;
+    virtual void setHighlightFollowsCurrentItem(bool);
+    virtual void setHighlightMoveDuration(int);
 
     enum Flow { LeftToRight, TopToBottom };
     Flow flow() const;
     void setFlow(Flow);
 
-    bool isWrapEnabled() const;
-    void setWrapEnabled(bool);
-
-    int cacheBuffer() const;
-    void setCacheBuffer(int);
-
     int cellWidth() const;
     void setCellWidth(int);
 
@@ -157,22 +91,6 @@ public:
     SnapMode snapMode() const;
     void setSnapMode(SnapMode mode);
 
-    QDeclarativeComponent *footer() const;
-    void setFooter(QDeclarativeComponent *);
-
-    QDeclarativeComponent *header() const;
-    void setHeader(QDeclarativeComponent *);
-
-    virtual void setContentX(qreal pos);
-    virtual void setContentY(qreal pos);
-
-    enum PositionMode { Beginning, Center, End, Visible, Contain };
-
-    Q_INVOKABLE void positionViewAtIndex(int index, int mode);
-    Q_INVOKABLE int indexAt(qreal x, qreal y) const;
-    Q_INVOKABLE void positionViewAtBeginning();
-    Q_INVOKABLE void positionViewAtEnd();
-
     static QSGGridViewAttached *qmlAttachedProperties(QObject *);
 
 public Q_SLOTS:
@@ -182,58 +100,28 @@ public Q_SLOTS:
     void moveCurrentIndexRight();
 
 Q_SIGNALS:
-    void countChanged();
-    void currentIndexChanged();
     void cellWidthChanged();
     void cellHeightChanged();
-    void highlightChanged();
-    void highlightItemChanged();
-    void preferredHighlightBeginChanged();
-    void preferredHighlightEndChanged();
-    void highlightRangeModeChanged();
     void highlightMoveDurationChanged();
-    void modelChanged();
-    void delegateChanged();
     void flowChanged();
-    void layoutDirectionChanged();
-    void effectiveLayoutDirectionChanged();
-    void keyNavigationWrapsChanged();
-    void cacheBufferChanged();
     void snapModeChanged();
-    void headerChanged();
-    void footerChanged();
 
 protected:
-    virtual void updatePolish();
     virtual void viewportMoved();
-    virtual qreal minYExtent() const;
-    virtual qreal maxYExtent() const;
-    virtual qreal minXExtent() const;
-    virtual qreal maxXExtent() const;
     virtual void keyPressEvent(QKeyEvent *);
-    virtual void componentComplete();
 
 private Q_SLOTS:
-    void trackedPositionChanged();
     void itemsInserted(int index, int count);
     void itemsRemoved(int index, int count);
     void itemsMoved(int from, int to, int count);
-    void modelReset();
-    void destroyRemoved();
-    void createdItem(int index, QSGItem *item);
-    void destroyingItem(QSGItem *item);
-    void animStopped();
-
-private:
-    void refill();
 };
 
-class QSGGridViewAttached : public QObject
+class QSGGridViewAttached : public QSGItemViewAttached
 {
     Q_OBJECT
 public:
     QSGGridViewAttached(QObject *parent)
-        : QObject(parent), m_view(0), m_isCurrent(false), m_delayRemove(false) {}
+        : QSGItemViewAttached(parent), m_view(0) {}
     ~QSGGridViewAttached() {}
 
     Q_PROPERTY(QSGGridView *view READ view NOTIFY viewChanged)
@@ -245,38 +133,11 @@ public:
         }
     }
 
-    Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
-    bool isCurrentItem() const { return m_isCurrent; }
-    void setIsCurrentItem(bool c) {
-        if (m_isCurrent != c) {
-            m_isCurrent = c;
-            emit currentItemChanged();
-        }
-    }
-
-    Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
-    bool delayRemove() const { return m_delayRemove; }
-    void setDelayRemove(bool delay) {
-        if (m_delayRemove != delay) {
-            m_delayRemove = delay;
-            emit delayRemoveChanged();
-        }
-    }
-
-    void emitAdd() { emit add(); }
-    void emitRemove() { emit remove(); }
-
 Q_SIGNALS:
-    void currentItemChanged();
-    void delayRemoveChanged();
-    void add();
-    void remove();
     void viewChanged();
 
 public:
     QDeclarativeGuard<QSGGridView> m_view;
-    bool m_isCurrent : 1;
-    bool m_delayRemove : 1;
 };
 
 
diff --git a/src/declarative/items/qsgitemview.cpp b/src/declarative/items/qsgitemview.cpp
new file mode 100644 (file)
index 0000000..df242ac
--- /dev/null
@@ -0,0 +1,1363 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying ** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgitemview_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+FxViewItem::FxViewItem(QSGItem *i, bool own)
+    : item(i), ownItem(own), index(-1)
+{
+}
+
+FxViewItem::~FxViewItem()
+{
+    if (ownItem && item) {
+        item->setParentItem(0);
+        item->deleteLater();
+        item = 0;
+    }
+}
+
+QSGItemView::QSGItemView(QSGFlickablePrivate &dd, QSGItem *parent)
+    : QSGFlickable(dd, parent)
+{
+    Q_D(QSGItemView);
+    d->init();
+}
+
+QSGItemView::~QSGItemView()
+{
+    Q_D(QSGItemView);
+    d->clear();
+    if (d->ownModel)
+        delete d->model;
+    delete d->header;
+    delete d->footer;
+}
+
+
+QSGItem *QSGItemView::currentItem() const
+{
+    Q_D(const QSGItemView);
+    if (!d->currentItem)
+        return 0;
+    return d->currentItem->item;
+}
+
+QVariant QSGItemView::model() const
+{
+    Q_D(const QSGItemView);
+    return d->modelVariant;
+}
+
+void QSGItemView::setModel(const QVariant &model)
+{
+    Q_D(QSGItemView);
+    if (d->modelVariant == model)
+        return;
+    if (d->model) {
+        disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+        disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+        disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+        disconnect(d->model, SIGNAL(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
+        disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+        disconnect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
+        disconnect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
+    }
+
+    QSGVisualModel *oldModel = d->model;
+
+    d->clear();
+    d->setPosition(0);
+    d->model = 0;
+    d->modelVariant = model;
+
+    QObject *object = qvariant_cast<QObject*>(model);
+    QSGVisualModel *vim = 0;
+    if (object && (vim = qobject_cast<QSGVisualModel *>(object))) {
+        if (d->ownModel) {
+            delete oldModel;
+            d->ownModel = false;
+        }
+        d->model = vim;
+    } else {
+        if (!d->ownModel) {
+            d->model = new QSGVisualDataModel(qmlContext(this), this);
+            d->ownModel = true;
+        } else {
+            d->model = oldModel;
+        }
+        if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
+            dataModel->setModel(model);
+    }
+
+    if (d->model) {
+        d->bufferMode = QSGItemViewPrivate::BufferBefore | QSGItemViewPrivate::BufferAfter;
+        if (isComponentComplete()) {
+            updateSections();
+            d->refill();
+            if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
+                setCurrentIndex(0);
+            } else {
+                d->moveReason = QSGItemViewPrivate::SetIndex;
+                d->updateCurrent(d->currentIndex);
+                if (d->highlight && d->currentItem) {
+                    if (d->autoHighlight)
+                        d->resetHighlightPosition();
+                    d->updateTrackedItem();
+                }
+                d->moveReason = QSGItemViewPrivate::Other;
+            }
+            d->updateViewport();
+        }
+        connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+        connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+        connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+        connect(d->model, SIGNAL(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
+        connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+        connect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
+        connect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
+        emit countChanged();
+    }
+    emit modelChanged();
+}
+
+QDeclarativeComponent *QSGItemView::delegate() const
+{
+    Q_D(const QSGItemView);
+    if (d->model) {
+        if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
+            return dataModel->delegate();
+    }
+
+    return 0;
+}
+
+void QSGItemView::setDelegate(QDeclarativeComponent *delegate)
+{
+    Q_D(QSGItemView);
+    if (delegate == this->delegate())
+        return;
+    if (!d->ownModel) {
+        d->model = new QSGVisualDataModel(qmlContext(this));
+        d->ownModel = true;
+    }
+    if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model)) {
+        int oldCount = dataModel->count();
+        dataModel->setDelegate(delegate);
+        if (isComponentComplete()) {
+            for (int i = 0; i < d->visibleItems.count(); ++i)
+                d->releaseItem(d->visibleItems.at(i));
+            d->visibleItems.clear();
+            d->releaseItem(d->currentItem);
+            d->currentItem = 0;
+            updateSections();
+            d->refill();
+            d->moveReason = QSGItemViewPrivate::SetIndex;
+            d->updateCurrent(d->currentIndex);
+            if (d->highlight && d->currentItem) {
+                if (d->autoHighlight)
+                    d->resetHighlightPosition();
+                d->updateTrackedItem();
+            }
+            d->moveReason = QSGItemViewPrivate::Other;
+            d->updateViewport();
+        }
+        if (oldCount != dataModel->count())
+            emit countChanged();
+    }
+    emit delegateChanged();
+}
+
+
+int QSGItemView::count() const
+{
+    Q_D(const QSGItemView);
+    if (d->model)
+        return d->model->count();
+    return 0;
+}
+
+int QSGItemView::currentIndex() const
+{
+    Q_D(const QSGItemView);
+    return d->currentIndex;
+}
+
+void QSGItemView::setCurrentIndex(int index)
+{
+    Q_D(QSGItemView);
+    if (d->requestedIndex >= 0)  // currently creating item
+        return;
+    d->currentIndexCleared = (index == -1);
+    if (index == d->currentIndex)
+        return;
+    if (isComponentComplete() && d->isValid()) {
+        d->moveReason = QSGItemViewPrivate::SetIndex;
+        d->updateCurrent(index);
+    } else if (d->currentIndex != index) {
+        d->currentIndex = index;
+        emit currentIndexChanged();
+    }
+}
+
+
+bool QSGItemView::isWrapEnabled() const
+{
+    Q_D(const QSGItemView);
+    return d->wrap;
+}
+
+void QSGItemView::setWrapEnabled(bool wrap)
+{
+    Q_D(QSGItemView);
+    if (d->wrap == wrap)
+        return;
+    d->wrap = wrap;
+    emit keyNavigationWrapsChanged();
+}
+
+int QSGItemView::cacheBuffer() const
+{
+    Q_D(const QSGItemView);
+    return d->buffer;
+}
+
+void QSGItemView::setCacheBuffer(int b)
+{
+    Q_D(QSGItemView);
+    if (d->buffer != b) {
+        d->buffer = b;
+        if (isComponentComplete()) {
+            d->bufferMode = QSGItemViewPrivate::BufferBefore | QSGItemViewPrivate::BufferAfter;
+            d->refill();
+        }
+        emit cacheBufferChanged();
+    }
+}
+
+
+Qt::LayoutDirection QSGItemView::layoutDirection() const
+{
+    Q_D(const QSGItemView);
+    return d->layoutDirection;
+}
+
+void QSGItemView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+    Q_D(QSGItemView);
+    if (d->layoutDirection != layoutDirection) {
+        d->layoutDirection = layoutDirection;
+        d->regenerate();
+        emit layoutDirectionChanged();
+        emit effectiveLayoutDirectionChanged();
+    }
+}
+
+Qt::LayoutDirection QSGItemView::effectiveLayoutDirection() const
+{
+    Q_D(const QSGItemView);
+    if (d->effectiveLayoutMirror)
+        return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+    else
+        return d->layoutDirection;
+}
+
+
+QDeclarativeComponent *QSGItemView::header() const
+{
+    Q_D(const QSGItemView);
+    return d->headerComponent;
+}
+
+void QSGItemView::setHeader(QDeclarativeComponent *headerComponent)
+{
+    Q_D(QSGItemView);
+    if (d->headerComponent != headerComponent) {
+        delete d->header;
+        d->header = 0;
+        d->headerComponent = headerComponent;
+
+        d->minExtentDirty = true;
+        d->maxExtentDirty = true;
+
+        if (isComponentComplete()) {
+            d->updateHeader();
+            d->updateFooter();
+            d->updateViewport();
+            d->fixupPosition();
+        }
+        emit headerChanged();
+    }
+}
+
+QDeclarativeComponent *QSGItemView::footer() const
+{
+    Q_D(const QSGItemView);
+    return d->footerComponent;
+}
+
+void QSGItemView::setFooter(QDeclarativeComponent *footerComponent)
+{
+    Q_D(QSGItemView);
+    if (d->footerComponent != footerComponent) {
+        delete d->footer;
+        d->footer = 0;
+        d->footerComponent = footerComponent;
+
+        if (isComponentComplete()) {
+            d->updateFooter();
+            d->updateViewport();
+            d->fixupPosition();
+        }
+        emit footerChanged();
+    }
+}
+
+QDeclarativeComponent *QSGItemView::highlight() const
+{
+    Q_D(const QSGItemView);
+    return d->highlightComponent;
+}
+
+void QSGItemView::setHighlight(QDeclarativeComponent *highlightComponent)
+{
+    Q_D(QSGItemView);
+    if (highlightComponent != d->highlightComponent) {
+        d->highlightComponent = highlightComponent;
+        d->createHighlight();
+        if (d->currentItem)
+            d->updateHighlight();
+        emit highlightChanged();
+    }
+}
+
+QSGItem *QSGItemView::highlightItem() const
+{
+    Q_D(const QSGItemView);
+    if (!d->highlight)
+        return 0;
+    return d->highlight->item;
+}
+
+bool QSGItemView::highlightFollowsCurrentItem() const
+{
+    Q_D(const QSGItemView);
+    return d->autoHighlight;
+}
+
+void QSGItemView::setHighlightFollowsCurrentItem(bool autoHighlight)
+{
+    Q_D(QSGItemView);
+    if (d->autoHighlight != autoHighlight) {
+        d->autoHighlight = autoHighlight;
+        if (autoHighlight)
+            d->updateHighlight();
+        emit highlightFollowsCurrentItemChanged();
+    }
+}
+
+QSGItemView::HighlightRangeMode QSGItemView::highlightRangeMode() const
+{
+    Q_D(const QSGItemView);
+    return static_cast<QSGItemView::HighlightRangeMode>(d->highlightRange);
+}
+
+void QSGItemView::setHighlightRangeMode(HighlightRangeMode mode)
+{
+    Q_D(QSGItemView);
+    if (d->highlightRange == mode)
+        return;
+    d->highlightRange = mode;
+    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+    emit highlightRangeModeChanged();
+}
+
+//###Possibly rename these properties, since they are very useful even without a highlight?
+qreal QSGItemView::preferredHighlightBegin() const
+{
+    Q_D(const QSGItemView);
+    return d->highlightRangeStart;
+}
+
+void QSGItemView::setPreferredHighlightBegin(qreal start)
+{
+    Q_D(QSGItemView);
+    d->highlightRangeStartValid = true;
+    if (d->highlightRangeStart == start)
+        return;
+    d->highlightRangeStart = start;
+    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+    emit preferredHighlightBeginChanged();
+}
+
+void QSGItemView::resetPreferredHighlightBegin()
+{
+    Q_D(QSGItemView);
+    d->highlightRangeStartValid = false;
+    if (d->highlightRangeStart == 0)
+        return;
+    d->highlightRangeStart = 0;
+    emit preferredHighlightBeginChanged();
+}
+
+qreal QSGItemView::preferredHighlightEnd() const
+{
+    Q_D(const QSGItemView);
+    return d->highlightRangeEnd;
+}
+
+void QSGItemView::setPreferredHighlightEnd(qreal end)
+{
+    Q_D(QSGItemView);
+    d->highlightRangeEndValid = true;
+    if (d->highlightRangeEnd == end)
+        return;
+    d->highlightRangeEnd = end;
+    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+    emit preferredHighlightEndChanged();
+}
+
+void QSGItemView::resetPreferredHighlightEnd()
+{
+    Q_D(QSGItemView);
+    d->highlightRangeEndValid = false;
+    if (d->highlightRangeEnd == 0)
+        return;
+    d->highlightRangeEnd = 0;
+    emit preferredHighlightEndChanged();
+}
+
+int QSGItemView::highlightMoveDuration() const
+{
+    Q_D(const QSGItemView);
+    return d->highlightMoveDuration;
+}
+
+void QSGItemView::setHighlightMoveDuration(int duration)
+{
+    Q_D(QSGItemView);
+    if (d->highlightMoveDuration != duration) {
+        d->highlightMoveDuration = duration;
+        emit highlightMoveDurationChanged();
+    }
+}
+
+void QSGItemViewPrivate::positionViewAtIndex(int index, int mode)
+{
+    Q_Q(QSGItemView);
+    if (!isValid())
+        return;
+    if (mode < QSGItemView::Beginning || mode > QSGItemView::Contain)
+        return;
+    int idx = qMax(qMin(index, model->count()-1), 0);
+
+    if (layoutScheduled)
+        layout();
+    qreal pos = isContentFlowReversed() ? -position() - size() : position();
+    FxViewItem *item = visibleItem(idx);
+    qreal maxExtent;
+    if (layoutOrientation() == Qt::Vertical)
+        maxExtent = -q->maxYExtent();
+    else
+        maxExtent = isContentFlowReversed() ? q->minXExtent()-size(): -q->maxXExtent();
+    if (!item) {
+        int itemPos = positionAt(idx);
+        changedVisibleIndex(idx);
+        // save the currently visible items in case any of them end up visible again
+        QList<FxViewItem *> oldVisible = visibleItems;
+        visibleItems.clear();
+        setPosition(qMin(qreal(itemPos), maxExtent));
+        // now release the reference to all the old visible items.
+        for (int i = 0; i < oldVisible.count(); ++i)
+            releaseItem(oldVisible.at(i));
+        item = visibleItem(idx);
+    }
+    if (item) {
+        const qreal itemPos = item->position();
+        switch (mode) {
+        case QSGItemView::Beginning:
+            pos = itemPos;
+            if (index < 0 && header)
+                pos -= headerSize();
+            break;
+        case QSGItemView::Center:
+            pos = itemPos - (size() - item->size())/2;
+            break;
+        case QSGItemView::End:
+            pos = itemPos - size() + item->size();
+            if (index >= model->count() && footer)
+                pos += footerSize();
+            break;
+        case QSGItemView::Visible:
+            if (itemPos > pos + size())
+                pos = itemPos - size() + item->size();
+            else if (item->endPosition() < pos)
+                pos = itemPos;
+            break;
+        case QSGItemView::Contain:
+            if (item->endPosition() > pos + size())
+                pos = itemPos - size() + item->size();
+            if (itemPos < pos)
+                pos = itemPos;
+        }
+        pos = qMin(pos, maxExtent);
+        qreal minExtent;
+        if (layoutOrientation() == Qt::Vertical)
+            minExtent = -q->minYExtent();
+        else
+            minExtent = isContentFlowReversed() ? q->maxXExtent()-size(): -q->minXExtent();
+        pos = qMax(pos, minExtent);
+        moveReason = QSGItemViewPrivate::Other;
+        q->cancelFlick();
+        setPosition(pos);
+
+        if (highlight) {
+            if (autoHighlight)
+                resetHighlightPosition();
+            updateHighlight();
+        }
+    }
+    fixupPosition();
+}
+
+void QSGItemView::positionViewAtIndex(int index, int mode)
+{
+    Q_D(QSGItemView);
+    if (!d->isValid() || index < 0 || index >= d->model->count())
+        return;
+    d->positionViewAtIndex(index, mode);
+}
+
+
+void QSGItemView::positionViewAtBeginning()
+{
+    Q_D(QSGItemView);
+    if (!d->isValid())
+        return;
+    d->positionViewAtIndex(-1, Beginning);
+}
+
+void QSGItemView::positionViewAtEnd()
+{
+    Q_D(QSGItemView);
+    if (!d->isValid())
+        return;
+    d->positionViewAtIndex(d->model->count(), End);
+}
+
+int QSGItemView::indexAt(qreal x, qreal y) const
+{
+    Q_D(const QSGItemView);
+    for (int i = 0; i < d->visibleItems.count(); ++i) {
+        const FxViewItem *item = d->visibleItems.at(i);
+        if (item->contains(x, y))
+            return item->index;
+    }
+
+    return -1;
+}
+
+
+// for debugging only
+void QSGItemViewPrivate::checkVisible() const
+{
+    int skip = 0;
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        FxViewItem *item = visibleItems.at(i);
+        if (item->index == -1) {
+            ++skip;
+        } else if (item->index != visibleIndex + i - skip) {
+            qFatal("index %d %d %d", visibleIndex, i, item->index);
+        }
+    }
+}
+
+
+
+void QSGItemViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+    Q_Q(QSGItemView);
+    QSGFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+    if (!q->isComponentComplete())
+        return;
+
+    if (header && header->item == item)
+        updateHeader();
+    else if (footer && footer->item == item)
+        updateFooter();
+
+    if (currentItem && currentItem->item == item)
+        updateHighlight();
+    if (trackedItem && trackedItem->item == item)
+        q->trackedPositionChanged();
+}
+
+void QSGItemView::destroyRemoved()
+{
+    Q_D(QSGItemView);
+    for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
+            it != d->visibleItems.end();) {
+        FxViewItem *item = *it;
+        if (item->index == -1 && item->attached->delayRemove() == false) {
+            d->releaseItem(item);
+            it = d->visibleItems.erase(it);
+        } else {
+            ++it;
+        }
+    }
+
+    // Correct the positioning of the items
+    d->updateSections();
+    d->layout();
+}
+
+void QSGItemView::itemsChanged(int, int)
+{
+    Q_D(QSGItemView);
+    d->updateSections();
+    d->layout();
+}
+
+void QSGItemView::modelReset()
+{
+    Q_D(QSGItemView);
+    d->moveReason = QSGItemViewPrivate::SetIndex;
+    d->regenerate();
+    if (d->highlight && d->currentItem) {
+        if (d->autoHighlight)
+            d->resetHighlightPosition();
+        d->updateTrackedItem();
+    }
+    d->moveReason = QSGItemViewPrivate::Other;
+
+    emit countChanged();
+}
+
+void QSGItemView::createdItem(int index, QSGItem *item)
+{
+    Q_D(QSGItemView);
+    if (d->requestedIndex != index) {
+        item->setParentItem(contentItem());
+        d->unrequestedItems.insert(item, index);
+        d->repositionPackageItemAt(item, index);
+    }
+}
+
+void QSGItemView::destroyingItem(QSGItem *item)
+{
+    Q_D(QSGItemView);
+    d->unrequestedItems.remove(item);
+}
+
+void QSGItemView::animStopped()
+{
+    Q_D(QSGItemView);
+    d->bufferMode = QSGItemViewPrivate::NoBuffer;
+    if (d->haveHighlightRange && d->highlightRange == QSGItemView::StrictlyEnforceRange)
+        d->updateHighlight();
+}
+
+
+void QSGItemView::trackedPositionChanged()
+{
+    Q_D(QSGItemView);
+    if (!d->trackedItem || !d->currentItem)
+        return;
+    if (d->moveReason == QSGItemViewPrivate::SetIndex) {
+        qreal trackedPos = d->trackedItem->position();
+        qreal trackedSize = d->trackedItem->size();
+        if (d->trackedItem != d->currentItem) {
+            trackedPos -= d->currentItem->sectionSize();
+            trackedSize += d->currentItem->sectionSize();
+        }
+        qreal viewPos;
+        qreal highlightStart;
+        qreal highlightEnd;
+        if (d->isContentFlowReversed()) {
+            viewPos = -d->position()-d->size();
+            highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
+            highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
+        } else {
+            viewPos = d->position();
+            highlightStart = d->highlightRangeStart;
+            highlightEnd = d->highlightRangeEnd;
+        }
+        qreal pos = viewPos;
+        if (d->haveHighlightRange) {
+            if (d->highlightRange == StrictlyEnforceRange) {
+                if (trackedPos > pos + highlightEnd - d->trackedItem->size())
+                    pos = trackedPos - highlightEnd + d->trackedItem->size();
+                if (trackedPos < pos + highlightStart)
+                    pos = trackedPos - highlightStart;
+            } else {
+                if (trackedPos < d->startPosition() + highlightStart) {
+                    pos = d->startPosition();
+                } else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + highlightEnd) {
+                    pos = d->endPosition() - d->size() + 1;
+                    if (pos < d->startPosition())
+                        pos = d->startPosition();
+                } else {
+                    if (trackedPos < viewPos + highlightStart) {
+                        pos = trackedPos - highlightStart;
+                    } else if (trackedPos > viewPos + highlightEnd - trackedSize) {
+                        pos = trackedPos - highlightEnd + trackedSize;
+                    }
+                }
+            }
+        } else {
+            if (trackedPos < viewPos && d->currentItem->position() < viewPos) {
+                pos = qMax(trackedPos, d->currentItem->position());
+            } else if (d->trackedItem->endPosition() >= viewPos + d->size()
+                && d->currentItem->endPosition() >= viewPos + d->size()) {
+                if (d->trackedItem->endPosition() <= d->currentItem->endPosition()) {
+                    pos = d->trackedItem->endPosition() - d->size() + 1;
+                    if (trackedSize > d->size())
+                        pos = trackedPos;
+                } else {
+                    pos = d->currentItem->endPosition() - d->size() + 1;
+                    if (d->currentItem->size() > d->size())
+                        pos = d->currentItem->position();
+                }
+            }
+        }
+        if (viewPos != pos) {
+            cancelFlick();
+            d->calcVelocity = true;
+            d->setPosition(pos);
+            d->calcVelocity = false;
+        }
+    }
+}
+
+
+void QSGItemView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+    Q_D(QSGItemView);
+    d->maxExtentDirty = true;
+    d->minExtentDirty = true;
+    QSGFlickable::geometryChanged(newGeometry, oldGeometry);
+}
+
+
+qreal QSGItemView::minYExtent() const
+{
+    Q_D(const QSGItemView);
+    if (d->layoutOrientation() == Qt::Horizontal)
+        return QSGFlickable::minYExtent();
+
+    if (d->minExtentDirty) {
+        d->minExtent = -d->startPosition();
+        if (d->header && d->visibleItems.count())
+            d->minExtent += d->headerSize();
+        if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+            d->minExtent += d->highlightRangeStart;
+            if (d->visibleItem(0))
+                d->minExtent -= d->visibleItem(0)->sectionSize();
+            d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1));
+        }
+        d->minExtentDirty = false;
+    }
+
+    return d->minExtent;
+}
+
+qreal QSGItemView::maxYExtent() const
+{
+    Q_D(const QSGItemView);
+    if (d->layoutOrientation() == Qt::Horizontal)
+        return height();
+
+    if (d->maxExtentDirty) {
+        if (!d->model || !d->model->count()) {
+            d->maxExtent = d->header ? -d->headerSize() : 0;
+            d->maxExtent += height();
+        } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+            d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
+            if (d->highlightRangeEnd != d->highlightRangeStart)
+                d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1));
+        } else {
+            d->maxExtent = -(d->endPosition() - height() + 1);
+        }
+
+        if (d->footer)
+            d->maxExtent -= d->footerSize();
+        qreal minY = minYExtent();
+        if (d->maxExtent > minY)
+            d->maxExtent = minY;
+        d->maxExtentDirty = false;
+    }
+    return d->maxExtent;
+}
+
+qreal QSGItemView::minXExtent() const
+{
+    Q_D(const QSGItemView);
+    if (d->layoutOrientation() == Qt::Vertical)
+        return QSGFlickable::minXExtent();
+
+    if (d->minExtentDirty) {
+        d->minExtent = -d->startPosition();
+        qreal highlightStart;
+        qreal highlightEnd;
+        qreal endPositionFirstItem = 0;
+        if (d->isContentFlowReversed()) {
+            if (d->model && d->model->count())
+                endPositionFirstItem = d->positionAt(d->model->count()-1);
+            else if (d->header)
+                d->minExtent += d->headerSize();
+            highlightStart = d->highlightRangeStartValid
+                    ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
+                    : d->size() - (d->lastPosition()-endPositionFirstItem);
+            highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
+            if (d->footer)
+                d->minExtent += d->footerSize();
+            qreal maxX = maxXExtent();
+            if (d->minExtent < maxX)
+                d->minExtent = maxX;
+        } else {
+            endPositionFirstItem = d->endPositionAt(0);
+            highlightStart = d->highlightRangeStart;
+            highlightEnd = d->highlightRangeEnd;
+            if (d->header && d->visibleItems.count())
+                d->minExtent += d->headerSize();
+        }
+        if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+            d->minExtent += highlightStart;
+            d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1));
+        }
+        d->minExtentDirty = false;
+    }
+
+    return d->minExtent;
+}
+
+qreal QSGItemView::maxXExtent() const
+{
+    Q_D(const QSGItemView);
+    if (d->layoutOrientation() == Qt::Vertical)
+        return width();
+
+    if (d->maxExtentDirty) {
+        qreal highlightStart;
+        qreal highlightEnd;
+        qreal lastItemPosition = 0;
+        d->maxExtent = 0;
+        if (d->isContentFlowReversed()) {
+            highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
+            highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
+            lastItemPosition = d->endPosition();
+        } else {
+            highlightStart = d->highlightRangeStart;
+            highlightEnd = d->highlightRangeEnd;
+            if (d->model && d->model->count())
+                lastItemPosition = d->positionAt(d->model->count()-1);
+        }
+        if (!d->model || !d->model->count()) {
+            if (!d->isContentFlowReversed())
+                d->maxExtent = d->header ? -d->headerSize() : 0;
+            d->maxExtent += width();
+        } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+            d->maxExtent = -(lastItemPosition - highlightStart);
+            if (highlightEnd != highlightStart) {
+                d->maxExtent = d->isContentFlowReversed()
+                        ? qMax(d->maxExtent, -(d->endPosition() - highlightEnd + 1))
+                        : qMin(d->maxExtent, -(d->endPosition() - highlightEnd + 1));
+            }
+        } else {
+            d->maxExtent = -(d->endPosition() - width() + 1);
+        }
+        if (d->isContentFlowReversed()) {
+            if (d->header && d->visibleItems.count())
+                d->maxExtent -= d->headerSize();
+        } else {
+            if (d->footer)
+                d->maxExtent -= d->footerSize();
+            qreal minX = minXExtent();
+            if (d->maxExtent > minX)
+                d->maxExtent = minX;
+        }
+        d->maxExtentDirty = false;
+    }
+
+    return d->maxExtent;
+}
+
+void QSGItemView::setContentX(qreal pos)
+{
+    Q_D(QSGItemView);
+    // Positioning the view manually should override any current movement state
+    d->moveReason = QSGItemViewPrivate::Other;
+    QSGFlickable::setContentX(pos);
+}
+
+void QSGItemView::setContentY(qreal pos)
+{
+    Q_D(QSGItemView);
+    // Positioning the view manually should override any current movement state
+    d->moveReason = QSGItemViewPrivate::Other;
+    QSGFlickable::setContentY(pos);
+}
+
+
+void QSGItemView::updatePolish()
+{
+    Q_D(QSGItemView);
+    QSGFlickable::updatePolish();
+    d->layout();
+}
+
+void QSGItemView::componentComplete()
+{
+    Q_D(QSGItemView);
+    QSGFlickable::componentComplete();
+
+    updateSections();
+    d->updateHeader();
+    d->updateFooter();
+    d->updateViewport();
+    if (d->isValid()) {
+        d->refill();
+        d->moveReason = QSGItemViewPrivate::SetIndex;
+        if (d->currentIndex < 0 && !d->currentIndexCleared)
+            d->updateCurrent(0);
+        else
+            d->updateCurrent(d->currentIndex);
+        if (d->highlight && d->currentItem) {
+            if (d->autoHighlight)
+                d->resetHighlightPosition();
+            d->updateTrackedItem();
+        }
+        d->moveReason = QSGItemViewPrivate::Other;
+        d->fixupPosition();
+    }
+}
+
+
+
+QSGItemViewPrivate::QSGItemViewPrivate()
+    : itemCount(0)
+    , buffer(0), bufferMode(BufferBefore | BufferAfter)
+    , layoutDirection(Qt::LeftToRight)
+    , moveReason(Other)
+    , visibleIndex(0)
+    , currentIndex(-1), currentItem(0)
+    , trackedItem(0), requestedIndex(-1)
+    , highlightComponent(0), highlight(0)
+    , highlightRange(QSGItemView::NoHighlightRange)
+    , highlightRangeStart(0), highlightRangeEnd(0)
+    , highlightMoveDuration(150)
+    , headerComponent(0), header(0), footerComponent(0), footer(0)
+    , minExtent(0), maxExtent(0)
+    , ownModel(false), wrap(false), lazyRelease(false), deferredRelease(false)
+    , layoutScheduled(false), inViewportMoved(false), currentIndexCleared(false)
+    , haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
+    , minExtentDirty(true), maxExtentDirty(true)
+{
+}
+
+bool QSGItemViewPrivate::isValid() const
+{
+    return model && model->count() && model->isValid();
+}
+
+qreal QSGItemViewPrivate::position() const
+{
+    Q_Q(const QSGItemView);
+    return layoutOrientation() == Qt::Vertical ? q->contentY() : q->contentX();
+}
+
+qreal QSGItemViewPrivate::size() const
+{
+    Q_Q(const QSGItemView);
+    return layoutOrientation() == Qt::Vertical ? q->height() : q->width();
+}
+
+int QSGItemViewPrivate::findLastVisibleIndex(int defaultValue) const
+{
+    if (visibleItems.count()) {
+        int i = visibleItems.count() - 1;
+        while (i > 0 && visibleItems.at(i)->index == -1)
+            --i;
+        if (visibleItems.at(i)->index != -1)
+            return visibleItems.at(i)->index;
+    }
+    return defaultValue;
+}
+
+FxViewItem *QSGItemViewPrivate::visibleItem(int modelIndex) const {
+    if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+        for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+            FxViewItem *item = visibleItems.at(i);
+            if (item->index == modelIndex)
+                return item;
+        }
+    }
+    return 0;
+}
+
+FxViewItem *QSGItemViewPrivate::firstVisibleItem() const {
+    const qreal pos = isContentFlowReversed() ? -position()-size() : position();
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        FxViewItem *item = visibleItems.at(i);
+        if (item->index != -1 && item->endPosition() > pos)
+            return item;
+    }
+    return visibleItems.count() ? visibleItems.first() : 0;
+}
+
+// Map a model index to visibleItems list index.
+// These may differ if removed items are still present in the visible list,
+// e.g. doing a removal animation
+int QSGItemViewPrivate::mapFromModel(int modelIndex) const
+{
+    if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+        return -1;
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        FxViewItem *item = visibleItems.at(i);
+        if (item->index == modelIndex)
+            return i + visibleIndex;
+        if (item->index > modelIndex)
+            return -1;
+    }
+    return -1; // Not in visibleList
+}
+
+void QSGItemViewPrivate::init()
+{
+    Q_Q(QSGItemView);
+    QSGItemPrivate::get(contentItem)->childrenDoNotOverlap = true;
+    q->setFlag(QSGItem::ItemIsFocusScope);
+    addItemChangeListener(this, Geometry);
+    QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
+    q->setFlickableDirection(QSGFlickable::VerticalFlick);
+}
+
+void QSGItemViewPrivate::updateCurrent(int modelIndex)
+{
+    Q_Q(QSGItemView);
+    if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+        if (currentItem) {
+            currentItem->attached->setIsCurrentItem(false);
+            releaseItem(currentItem);
+            currentItem = 0;
+            currentIndex = modelIndex;
+            emit q->currentIndexChanged();
+            updateHighlight();
+        } else if (currentIndex != modelIndex) {
+            currentIndex = modelIndex;
+            emit q->currentIndexChanged();
+        }
+        return;
+    }
+
+    if (currentItem && currentIndex == modelIndex) {
+        updateHighlight();
+        return;
+    }
+
+    FxViewItem *oldCurrentItem = currentItem;
+    currentIndex = modelIndex;
+    currentItem = createItem(modelIndex);
+    if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+        oldCurrentItem->attached->setIsCurrentItem(false);
+    if (currentItem) {
+        currentItem->item->setFocus(true);
+        currentItem->attached->setIsCurrentItem(true);
+        initializeCurrentItem();
+    }
+
+    updateHighlight();
+    emit q->currentIndexChanged();
+    releaseItem(oldCurrentItem);
+}
+
+void QSGItemViewPrivate::clear()
+{
+    timeline.clear();
+
+    for (int i = 0; i < visibleItems.count(); ++i)
+        releaseItem(visibleItems.at(i));
+    visibleItems.clear();
+    visibleIndex = 0;
+
+    releaseItem(currentItem);
+    currentItem = 0;
+    createHighlight();
+    trackedItem = 0;
+
+    minExtentDirty = true;
+    maxExtentDirty = true;
+    itemCount = 0;
+}
+
+
+void QSGItemViewPrivate::mirrorChange()
+{
+    Q_Q(QSGItemView);
+    regenerate();
+    emit q->effectiveLayoutDirectionChanged();
+}
+
+void QSGItemViewPrivate::refill()
+{
+    if (isContentFlowReversed())
+        refill(-position()-size()+1, -position());
+    else
+        refill(position(), position()+size()-1);
+}
+
+void QSGItemViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+{
+    Q_Q(QSGItemView);
+    if (!isValid() || !q->isComponentComplete())
+        return;
+
+    itemCount = model->count();
+    qreal bufferFrom = from - buffer;
+    qreal bufferTo = to + buffer;
+    qreal fillFrom = from;
+    qreal fillTo = to;
+    if (doBuffer && (bufferMode & BufferAfter))
+        fillTo = bufferTo;
+    if (doBuffer && (bufferMode & BufferBefore))
+        fillFrom = bufferFrom;
+
+    // Item creation and release is staggered in order to avoid
+    // creating/releasing multiple items in one frame
+    // while flicking (as much as possible).
+
+    bool changed = addVisibleItems(fillFrom, fillTo, doBuffer);
+
+    if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
+        if (removeNonVisibleItems(bufferFrom, bufferTo))
+            changed = true;
+        deferredRelease = false;
+    } else {
+        deferredRelease = true;
+    }
+
+    if (changed) {
+        minExtentDirty = true;
+        maxExtentDirty = true;
+        visibleItemsChanged();
+    } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
+        refill(from, to, true);
+    }
+
+    lazyRelease = false;
+}
+
+void QSGItemViewPrivate::regenerate()
+{
+    Q_Q(QSGItemView);
+    if (q->isComponentComplete()) {
+        delete header;
+        header = 0;
+        delete footer;
+        footer = 0;
+        updateHeader();
+        updateFooter();
+        clear();
+        updateViewport();
+        setPosition(0);
+        refill();
+        updateCurrent(currentIndex);
+    }
+}
+
+void QSGItemViewPrivate::scheduleLayout()
+{
+    Q_Q(QSGItemView);
+    if (!layoutScheduled) {
+        layoutScheduled = true;
+        q->polish();
+    }
+}
+
+void QSGItemViewPrivate::updateViewport()
+{
+    Q_Q(QSGItemView);
+    if (isValid()) {
+        if (layoutOrientation() == Qt::Vertical)
+            q->setContentHeight(endPosition() - startPosition() + 1);
+        else
+            q->setContentWidth(endPosition() - startPosition() + 1);
+    }
+}
+
+void QSGItemViewPrivate::layout()
+{
+    Q_Q(QSGItemView);
+    layoutScheduled = false;
+    if (!isValid() && !visibleItems.count()) {
+        clear();
+        setPosition(0);
+        return;
+    }
+
+    layoutVisibleItems();
+    refill();
+
+    minExtentDirty = true;
+    maxExtentDirty = true;
+
+    updateHighlight();
+    if (!q->isMoving() && !q->isFlicking()) {
+        fixupPosition();
+        refill();
+    }
+
+    updateHeader();
+    updateFooter();
+    updateViewport();
+    updateUnrequestedPositions();
+}
+
+FxViewItem *QSGItemViewPrivate::createItem(int modelIndex)
+{
+    Q_Q(QSGItemView);
+
+    requestedIndex = modelIndex;
+    FxViewItem *viewItem = 0;
+
+    if (QSGItem *item = model->item(modelIndex, false)) {
+        viewItem = newViewItem(modelIndex, item);
+        if (viewItem) {
+            viewItem->index = modelIndex;
+            if (model->completePending()) {
+                // complete
+                viewItem->item->setZ(1);
+                viewItem->item->setParentItem(q->contentItem());
+                model->completeItem();
+            } else {
+                viewItem->item->setParentItem(q->contentItem());
+            }
+            // do other set up for the new item that should not happen
+            // until after bindings are evaluated
+            initializeViewItem(viewItem);
+
+            unrequestedItems.remove(viewItem->item);
+        }
+    }
+    requestedIndex = -1;
+    return viewItem;
+}
+
+
+void QSGItemViewPrivate::releaseItem(FxViewItem *item)
+{
+    Q_Q(QSGItemView);
+    if (!item || !model)
+        return;
+    if (trackedItem == item)
+        trackedItem = 0;
+    QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item->item);
+    itemPrivate->removeItemChangeListener(this, QSGItemPrivate::Geometry);
+    if (model->release(item->item) == 0) {
+        // item was not destroyed, and we no longer reference it.
+        unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+    }
+    delete item;
+}
+
+QSGItem *QSGItemViewPrivate::createHighlightItem()
+{
+    return createComponentItem(highlightComponent, true, true);
+}
+
+QSGItem *QSGItemViewPrivate::createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault)
+{
+    Q_Q(QSGItemView);
+
+    QSGItem *item = 0;
+    if (component) {
+        QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+        QObject *nobj = component->create(context);
+        if (nobj) {
+            QDeclarative_setParent_noEvent(context, nobj);
+            item = qobject_cast<QSGItem *>(nobj);
+            if (!item)
+                delete nobj;
+        } else {
+            delete context;
+        }
+    } else if (createDefault) {
+        item = new QSGItem;
+    }
+    if (item) {
+        QDeclarative_setParent_noEvent(item, q->contentItem());
+        item->setParentItem(q->contentItem());
+        if (receiveItemGeometryChanges) {
+            QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
+            itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
+        }
+    }
+    return item;
+}
+
+void QSGItemViewPrivate::updateTrackedItem()
+{
+    Q_Q(QSGItemView);
+    FxViewItem *item = currentItem;
+    if (highlight)
+        item = highlight;
+    trackedItem = item;
+
+    if (trackedItem)
+        q->trackedPositionChanged();
+}
+
+void QSGItemViewPrivate::updateUnrequestedIndexes()
+{
+    Q_Q(QSGItemView);
+    for (QHash<QSGItem*,int>::iterator it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+        *it = model->indexOf(it.key(), q);
+}
+
+void QSGItemViewPrivate::updateUnrequestedPositions()
+{
+    for (QHash<QSGItem*,int>::const_iterator it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+        repositionPackageItemAt(it.key(), it.value());
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgitemview_p.h b/src/declarative/items/qsgitemview_p.h
new file mode 100644 (file)
index 0000000..fb95e4f
--- /dev/null
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGITEMVIEW_P_H
+#define QSGITEMVIEW_P_H
+
+#include "qsgflickable_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+
+class QSGItemViewPrivate;
+
+class Q_AUTOTEST_EXPORT QSGItemView : public QSGFlickable
+{
+    Q_OBJECT
+
+    Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+    Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+    Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+    Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+    Q_PROPERTY(QSGItem *currentItem READ currentItem NOTIFY currentIndexChanged)
+
+    Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
+    Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+
+    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
+    Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+
+    Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
+    Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
+
+    Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
+    Q_PROPERTY(QSGItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
+    Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
+    Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+    Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
+    Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
+    Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
+
+    Q_ENUMS(HighlightRangeMode)
+    Q_ENUMS(PositionMode)
+
+public:
+    QSGItemView(QSGFlickablePrivate &dd, QSGItem *parent = 0);
+    ~QSGItemView();
+
+    QVariant model() const;
+    void setModel(const QVariant &);
+
+    QDeclarativeComponent *delegate() const;
+    void setDelegate(QDeclarativeComponent *);
+
+    int count() const;
+
+    int currentIndex() const;
+    void setCurrentIndex(int idx);
+
+    QSGItem *currentItem() const;
+
+    bool isWrapEnabled() const;
+    void setWrapEnabled(bool);
+
+    int cacheBuffer() const;
+    void setCacheBuffer(int);
+
+    Qt::LayoutDirection layoutDirection() const;
+    void setLayoutDirection(Qt::LayoutDirection);
+    Qt::LayoutDirection effectiveLayoutDirection() const;
+
+    QDeclarativeComponent *footer() const;
+    void setFooter(QDeclarativeComponent *);
+
+    QDeclarativeComponent *header() const;
+    void setHeader(QDeclarativeComponent *);
+
+    QDeclarativeComponent *highlight() const;
+    void setHighlight(QDeclarativeComponent *);
+
+    QSGItem *highlightItem() const;
+
+    bool highlightFollowsCurrentItem() const;
+    virtual void setHighlightFollowsCurrentItem(bool);
+
+    enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+    HighlightRangeMode highlightRangeMode() const;
+    void setHighlightRangeMode(HighlightRangeMode mode);
+
+    qreal preferredHighlightBegin() const;
+    void setPreferredHighlightBegin(qreal);
+    void resetPreferredHighlightBegin();
+
+    qreal preferredHighlightEnd() const;
+    void setPreferredHighlightEnd(qreal);
+    void resetPreferredHighlightEnd();
+
+    int highlightMoveDuration() const;
+    virtual void setHighlightMoveDuration(int);
+
+    enum PositionMode { Beginning, Center, End, Visible, Contain };
+
+    Q_INVOKABLE void positionViewAtIndex(int index, int mode);
+    Q_INVOKABLE int indexAt(qreal x, qreal y) const;
+    Q_INVOKABLE void positionViewAtBeginning();
+    Q_INVOKABLE void positionViewAtEnd();
+
+    virtual void setContentX(qreal pos);
+    virtual void setContentY(qreal pos);
+
+signals:
+    void modelChanged();
+    void delegateChanged();
+    void countChanged();
+    void currentIndexChanged();
+
+    void keyNavigationWrapsChanged();
+    void cacheBufferChanged();
+
+    void layoutDirectionChanged();
+    void effectiveLayoutDirectionChanged();
+
+    void headerChanged();
+    void footerChanged();
+
+    void highlightChanged();
+    void highlightItemChanged();
+    void highlightFollowsCurrentItemChanged();
+    void highlightRangeModeChanged();
+    void preferredHighlightBeginChanged();
+    void preferredHighlightEndChanged();
+    void highlightMoveDurationChanged();
+
+protected:
+    virtual void updatePolish();
+    virtual void componentComplete();
+    virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+    virtual qreal minYExtent() const;
+    virtual qreal maxYExtent() const;
+    virtual qreal minXExtent() const;
+    virtual qreal maxXExtent() const;
+
+protected slots:
+    virtual void updateSections() {}
+    void destroyRemoved();
+    void itemsChanged(int index, int count);
+    void createdItem(int index, QSGItem *item);
+    void modelReset();
+    void destroyingItem(QSGItem *item);
+    void animStopped();
+    void trackedPositionChanged();
+
+private:
+    Q_DECLARE_PRIVATE(QSGItemView)
+};
+
+
+class Q_AUTOTEST_EXPORT QSGItemViewAttached : public QObject
+{
+    Q_OBJECT
+
+    Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+    Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
+
+    Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
+    Q_PROPERTY(QString previousSection READ prevSection NOTIFY prevSectionChanged)
+    Q_PROPERTY(QString nextSection READ nextSection NOTIFY nextSectionChanged)
+
+public:
+    QSGItemViewAttached(QObject *parent)
+        : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
+    ~QSGItemViewAttached() {}
+
+    bool isCurrentItem() const { return m_isCurrent; }
+    void setIsCurrentItem(bool c) {
+        if (m_isCurrent != c) {
+            m_isCurrent = c;
+            emit currentItemChanged();
+        }
+    }
+
+    bool delayRemove() const { return m_delayRemove; }
+    void setDelayRemove(bool delay) {
+        if (m_delayRemove != delay) {
+            m_delayRemove = delay;
+            emit delayRemoveChanged();
+        }
+    }
+
+    QString section() const { return m_section; }
+    void setSection(const QString &sect) {
+        if (m_section != sect) {
+            m_section = sect;
+            emit sectionChanged();
+        }
+    }
+
+    QString prevSection() const { return m_prevSection; }
+    void setPrevSection(const QString &sect) {
+        if (m_prevSection != sect) {
+            m_prevSection = sect;
+            emit prevSectionChanged();
+        }
+    }
+
+    QString nextSection() const { return m_nextSection; }
+    void setNextSection(const QString &sect) {
+        if (m_nextSection != sect) {
+            m_nextSection = sect;
+            emit nextSectionChanged();
+        }
+    }
+
+    void emitAdd() { emit add(); }
+    void emitRemove() { emit remove(); }
+
+signals:
+    void currentItemChanged();
+    void delayRemoveChanged();
+
+    void add();
+    void remove();
+
+    void sectionChanged();
+    void prevSectionChanged();
+    void nextSectionChanged();
+
+public:
+    bool m_isCurrent : 1;
+    bool m_delayRemove : 1;
+
+    // current only used by list view
+    mutable QString m_section;
+    QString m_prevSection;
+    QString m_nextSection;
+};
+
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QSGITEMVIEW_P_H
+
diff --git a/src/declarative/items/qsgitemview_p_p.h b/src/declarative/items/qsgitemview_p_p.h
new file mode 100644 (file)
index 0000000..aa1d14d
--- /dev/null
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGITEMVIEW_P_P_H
+#define QSGITEMVIEW_P_P_H
+
+#include "qsgitemview_p.h"
+#include "qsgflickable_p_p.h"
+#include "qsgvisualitemmodel_p.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class FxViewItem
+{
+public:
+    FxViewItem(QSGItem *, bool own);
+    ~FxViewItem();
+
+    // these are positions and sizes along the current direction of scrolling/flicking
+    virtual qreal position() const = 0;
+    virtual qreal endPosition() const = 0;
+    virtual qreal size() const = 0;
+    virtual qreal sectionSize() const = 0;
+
+    virtual bool contains(qreal x, qreal y) const = 0;
+
+    QSGItem *item;
+    bool ownItem;
+    int index;
+    QSGItemViewAttached *attached;
+};
+
+class QSGItemViewPrivate : public QSGFlickablePrivate
+{
+    Q_DECLARE_PUBLIC(QSGItemView)
+public:
+    QSGItemViewPrivate();
+
+    enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
+    enum MovementReason { Other, SetIndex, Mouse };
+
+    bool isValid() const;
+    qreal position() const;
+    qreal size() const;
+    int findLastVisibleIndex(int defaultValue = -1) const;
+    FxViewItem *visibleItem(int modelIndex) const;
+    FxViewItem *firstVisibleItem() const;
+    int mapFromModel(int modelIndex) const;
+
+    virtual void init();
+    virtual void updateCurrent(int modelIndex);
+    virtual void clear();
+    virtual void regenerate();
+    virtual void updateViewport();
+    void layout();
+    void refill();
+    void refill(qreal from, qreal to, bool doBuffer = false);
+    void scheduleLayout();
+    void mirrorChange();
+
+    FxViewItem *createItem(int modelIndex);
+    virtual void releaseItem(FxViewItem *item);
+
+    QSGItem *createHighlightItem();
+    QSGItem *createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault = false);
+
+    void updateTrackedItem();
+    void updateUnrequestedIndexes();
+    void updateUnrequestedPositions();
+    void positionViewAtIndex(int index, int mode);
+
+    void checkVisible() const;
+
+    QDeclarativeGuard<QSGVisualModel> model;
+    QVariant modelVariant;
+    int itemCount;
+    int buffer;
+    int bufferMode;
+    Qt::LayoutDirection layoutDirection;
+
+    MovementReason moveReason;
+
+    QList<FxViewItem *> visibleItems;
+    int visibleIndex;
+    int currentIndex;
+    FxViewItem *currentItem;
+    FxViewItem *trackedItem;
+    QHash<QSGItem*,int> unrequestedItems;
+    int requestedIndex;
+
+    // XXX split into struct
+    QDeclarativeComponent *highlightComponent;
+    FxViewItem *highlight;
+    int highlightRange;     // enum value
+    qreal highlightRangeStart;
+    qreal highlightRangeEnd;
+    int highlightMoveDuration;
+
+    QDeclarativeComponent *headerComponent;
+    FxViewItem *header;
+    QDeclarativeComponent *footerComponent;
+    FxViewItem *footer;
+
+    mutable qreal minExtent;
+    mutable qreal maxExtent;
+
+    bool ownModel : 1;
+    bool wrap : 1;
+    bool lazyRelease : 1;
+    bool deferredRelease : 1;
+    bool layoutScheduled : 1;
+    bool inViewportMoved : 1;
+    bool currentIndexCleared : 1;
+    bool haveHighlightRange : 1;
+    bool autoHighlight : 1;
+    bool highlightRangeStartValid : 1;
+    bool highlightRangeEndValid : 1;
+    mutable bool minExtentDirty : 1;
+    mutable bool maxExtentDirty : 1;
+
+protected:
+    virtual Qt::Orientation layoutOrientation() const = 0;
+    virtual bool isContentFlowReversed() const = 0;
+
+    virtual qreal startPosition() const = 0;
+    virtual qreal positionAt(int index) const = 0;
+    virtual qreal endPosition() const = 0;
+    virtual qreal endPositionAt(int index) const = 0;
+    virtual qreal lastPosition() const  = 0;
+
+    virtual qreal headerSize() const = 0;
+    virtual qreal footerSize() const = 0;
+    virtual void updateHeader() = 0;
+    virtual void updateFooter() = 0;
+
+    virtual void createHighlight() = 0;
+    virtual void updateHighlight() = 0;
+    virtual void resetHighlightPosition() = 0;
+
+    virtual void setPosition(qreal pos) = 0;
+    virtual void fixupPosition() = 0;
+
+    virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer) = 0;
+    virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo) = 0;
+    virtual void visibleItemsChanged() = 0;
+
+    virtual FxViewItem *newViewItem(int index, QSGItem *item) = 0;
+    virtual void initializeViewItem(FxViewItem *) {}
+    virtual void repositionPackageItemAt(QSGItem *item, int index) = 0;
+
+    virtual void layoutVisibleItems() = 0;
+
+    virtual void updateSections() {}
+    virtual void changedVisibleIndex(int newIndex) = 0;
+    virtual void initializeCurrentItem() {}
+
+    virtual void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGITEMVIEW_P_P_H
index 3e8f02c..f190e17 100644 (file)
@@ -40,7 +40,7 @@
 ****************************************************************************/
 
 #include "qsglistview_p.h"
-#include "qsgflickable_p_p.h"
+#include "qsgitemview_p_p.h"
 #include "qsgvisualitemmodel_p.h"
 
 #include <QtDeclarative/qdeclarativeexpression.h>
@@ -89,15 +89,17 @@ QString QSGViewSection::sectionString(const QString &value)
 
 //----------------------------------------------------------------------------
 
-class FxListItemSG
+class FxListItemSG : public FxViewItem
 {
 public:
-    FxListItemSG(QSGItem *i, QSGListView *v) : item(i), section(0), view(v) {
+    FxListItemSG(QSGItem *i, QSGListView *v, bool own) : FxViewItem(i, own), section(0), view(v) {
         attached = static_cast<QSGListViewAttached*>(qmlAttachedPropertiesObject<QSGListView>(item));
         if (attached)
-            attached->setView(view);
+            static_cast<QSGListViewAttached*>(attached)->setView(view);
     }
+
     ~FxListItemSG() {}
+
     qreal position() const {
         if (section) {
             if (view->orientation() == QSGListView::Vertical)
@@ -171,580 +173,385 @@ public:
                 y >= item->y() && y < item->y() + item->height());
     }
 
-    QSGItem *item;
     QSGItem *section;
     QSGListView *view;
-    QSGListViewAttached *attached;
-    int index;
 };
 
 //----------------------------------------------------------------------------
 
-class QSGListViewPrivate : public QSGFlickablePrivate
+class QSGListViewPrivate : public QSGItemViewPrivate
 {
     Q_DECLARE_PUBLIC(QSGListView)
-
 public:
-    QSGListViewPrivate()
-        : currentItem(0), orient(QSGListView::Vertical), layoutDirection(Qt::LeftToRight)
-        , visiblePos(0), visibleIndex(0)
-        , averageSize(100.0), currentIndex(-1), requestedIndex(-1)
-        , itemCount(0), highlightRangeStart(0), highlightRangeEnd(0)
-        , highlightComponent(0), highlight(0), trackedItem(0)
-        , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0)
-        , sectionCriteria(0), spacing(0.0)
-        , highlightMoveSpeed(400), highlightMoveDuration(-1)
-        , highlightResizeSpeed(400), highlightResizeDuration(-1), highlightRange(QSGListView::NoHighlightRange)
-        , snapMode(QSGListView::NoSnap), overshootDist(0.0)
-        , footerComponent(0), footer(0), headerComponent(0), header(0)
-        , bufferMode(BufferBefore | BufferAfter)
-        , ownModel(false), wrap(false), autoHighlight(true), haveHighlightRange(false)
-        , correctFlick(false), inFlickCorrection(false), lazyRelease(false)
-        , deferredRelease(false), layoutScheduled(false), currentIndexCleared(false)
-        , inViewportMoved(false)
-        , highlightRangeStartValid(false), highlightRangeEndValid(false)
-        , minExtentDirty(true), maxExtentDirty(true)
-    {}
-
-    void init();
-    void clear();
-    FxListItemSG *createItem(int modelIndex);
-    void releaseItem(FxListItemSG *item);
-
-    FxListItemSG *visibleItem(int modelIndex) const {
-        if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
-            for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
-                FxListItemSG *item = visibleItems.at(i);
-                if (item->index == modelIndex)
-                    return item;
-            }
-        }
-        return 0;
-    }
-
-    FxListItemSG *firstVisibleItem() const {
-        const qreal pos = isRightToLeft() ? -position()-size() : position();
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxListItemSG *item = visibleItems.at(i);
-            if (item->index != -1 && item->endPosition() > pos)
-                return item;
-        }
-        return visibleItems.count() ? visibleItems.first() : 0;
-    }
+    virtual Qt::Orientation layoutOrientation() const;
+    virtual bool isContentFlowReversed() const;
+    bool isRightToLeft() const;
+
+    virtual qreal startPosition() const;
+    virtual qreal positionAt(int index) const;
+    virtual qreal endPosition() const;
+    virtual qreal endPositionAt(int index) const;
+    virtual qreal lastPosition() const;
+
+    qreal originPosition() const;
+    FxViewItem *nextVisibleItem() const;
+    FxViewItem *itemBefore(int modelIndex) const;
+    QString sectionAt(int modelIndex);
+    qreal snapPosAt(qreal pos);
+    FxViewItem *snapItemAt(qreal pos);
+
+    virtual void init();
+    virtual void clear();
+
+    virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer);
+    virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo);
+    virtual void visibleItemsChanged();
+
+    virtual FxViewItem *newViewItem(int index, QSGItem *item);
+    virtual void initializeViewItem(FxViewItem *item);
+    virtual void releaseItem(FxViewItem *item);
+    virtual void repositionPackageItemAt(QSGItem *item, int index);
+
+    virtual void createHighlight();
+    virtual void updateHighlight();
+    virtual void resetHighlightPosition();
+
+    virtual void setPosition(qreal pos);
+    virtual void layoutVisibleItems();
+
+    virtual void updateSections();
+    void createSection(FxListItemSG *);
+    void updateCurrentSection();
 
-    FxListItemSG *nextVisibleItem() const {
-        const qreal pos = isRightToLeft() ? -position()-size() : position();
-        bool foundFirst = false;
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxListItemSG *item = visibleItems.at(i);
-            if (item->index != -1) {
-                if (foundFirst)
-                    return item;
-                else if (item->position() < pos && item->endPosition() > pos)
-                    foundFirst = true;
-            }
-        }
-        return 0;
-    }
+    virtual qreal headerSize() const;
+    virtual qreal footerSize() const;
+    virtual void updateHeader();
+    virtual void updateFooter();
 
-    // Returns the item before modelIndex, if created.
-    // May return an item marked for removal.
-    FxListItemSG *itemBefore(int modelIndex) const {
-        if (modelIndex < visibleIndex)
-            return 0;
-        int idx = 1;
-        int lastIndex = -1;
-        while (idx < visibleItems.count()) {
-            FxListItemSG *item = visibleItems.at(idx);
-            if (item->index != -1)
-                lastIndex = item->index;
-            if (item->index == modelIndex)
-                return visibleItems.at(idx-1);
-            ++idx;
-        }
-        if (lastIndex == modelIndex-1)
-            return visibleItems.last();
-        return 0;
-    }
+    virtual void changedVisibleIndex(int newIndex);
+    virtual void initializeCurrentItem();
 
-    void regenerate() {
-        Q_Q(QSGListView);
-        if (q->isComponentComplete()) {
-            if (header) {
-                // XXX todo - the original did scene()->removeItem().  Why?
-                header->item->setParentItem(0);
-                header->item->deleteLater();
-                delete header;
-                header = 0;
-            }
-            if (footer) {
-                // XXX todo - the original did scene()->removeItem().  Why?
-                footer->item->setParentItem(0);
-                footer->item->deleteLater();
-                delete footer;
-                footer = 0;
-            }
-            updateHeader();
-            updateFooter();
-            clear();
-            setPosition(0);
-            q->refill();
-            updateCurrent(currentIndex);
-        }
-    }
+    void updateAverage();
 
-    void mirrorChange() {
-        Q_Q(QSGListView);
-        regenerate();
-        emit q->effectiveLayoutDirectionChanged();
-    }
+    void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+    virtual void fixupPosition();
+    virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+    virtual void flick(QSGItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+                        QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
 
-    bool isRightToLeft() const {
-        Q_Q(const QSGListView);
-        return orient == QSGListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
-    }
+    QSGListView::Orientation orient;
+    qreal visiblePos;
+    qreal averageSize;
+    qreal spacing;
+    QSGListView::SnapMode snapMode;
 
-    qreal position() const {
-        Q_Q(const QSGListView);
-        return orient == QSGListView::Vertical ? q->contentY() : q->contentX();
-    }
-    void setPosition(qreal pos) {
-        Q_Q(QSGListView);
-        if (orient == QSGListView::Vertical) {
-            q->QSGFlickable::setContentY(pos);
-        } else {
-            if (isRightToLeft())
-                q->QSGFlickable::setContentX(-pos-size());
-            else
-                q->QSGFlickable::setContentX(pos);
-        }
-    }
-    qreal size() const {
-        Q_Q(const QSGListView);
-        return orient == QSGListView::Vertical ? q->height() : q->width();
-    }
+    QSmoothedAnimation *highlightPosAnimator;
+    QSmoothedAnimation *highlightSizeAnimator;
+    qreal highlightMoveSpeed;
+    qreal highlightResizeSpeed;
+    int highlightResizeDuration;
 
-    qreal originPosition() const {
-        qreal pos = 0;
-        if (!visibleItems.isEmpty()) {
-            pos = (*visibleItems.constBegin())->position();
-            if (visibleIndex > 0)
-                pos -= visibleIndex * (averageSize + spacing);
-        }
-        return pos;
-    }
+    QSGViewSection *sectionCriteria;
+    QString currentSection;
+    static const int sectionCacheSize = 4;
+    QSGItem *sectionCache[sectionCacheSize];
 
-    qreal lastPosition() const {
-        qreal pos = 0;
-        if (!visibleItems.isEmpty()) {
-            int invisibleCount = visibleItems.count() - visibleIndex;
-            for (int i = visibleItems.count()-1; i >= 0; --i) {
-                if (visibleItems.at(i)->index != -1) {
-                    invisibleCount = model->count() - visibleItems.at(i)->index - 1;
-                    break;
-                }
-            }
-            pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
-        } else if (model && model->count()) {
-            pos = model->count() * averageSize + (model->count()-1) * spacing;
-        }
-        return pos;
-    }
+    qreal overshootDist;
+    bool correctFlick : 1;
+    bool inFlickCorrection : 1;
 
-    qreal startPosition() const {
-        return isRightToLeft() ? -lastPosition()-1 : originPosition();
-    }
+    QSGListViewPrivate()
+        : orient(QSGListView::Vertical)
+        , visiblePos(0)
+        , averageSize(100.0), spacing(0.0)
+        , snapMode(QSGListView::NoSnap)
+        , highlightPosAnimator(0), highlightSizeAnimator(0)
+        , highlightMoveSpeed(400), highlightResizeSpeed(400), highlightResizeDuration(-1)
+        , sectionCriteria(0)
+        , overshootDist(0.0), correctFlick(false), inFlickCorrection(false)
+    {}
+};
 
-    qreal endPosition() const {
-        return isRightToLeft() ? -originPosition()-1 : lastPosition();
-    }
-
-    qreal positionAt(int modelIndex) const {
-        if (FxListItemSG *item = visibleItem(modelIndex))
-            return item->position();
-        if (!visibleItems.isEmpty()) {
-            if (modelIndex < visibleIndex) {
-                int count = visibleIndex - modelIndex;
-                qreal cs = 0;
-                if (modelIndex == currentIndex && currentItem) {
-                    cs = currentItem->size() + spacing;
-                    --count;
-                }
-                return (*visibleItems.constBegin())->position() - count * (averageSize + spacing) - cs;
-            } else {
-                int idx = visibleItems.count() - 1;
-                while (idx >= 0 && visibleItems.at(idx)->index == -1)
-                    --idx;
-                if (idx < 0)
-                    idx = visibleIndex;
-                else
-                    idx = visibleItems.at(idx)->index;
-                int count = modelIndex - idx - 1;
-                return (*(--visibleItems.constEnd()))->endPosition() + spacing + count * (averageSize + spacing) + 1;
-            }
-        }
-        return 0;
-    }
+bool QSGListViewPrivate::isContentFlowReversed() const
+{
+    return isRightToLeft();
+}
 
-    qreal endPositionAt(int modelIndex) const {
-        if (FxListItemSG *item = visibleItem(modelIndex))
-            return item->endPosition();
-        if (!visibleItems.isEmpty()) {
-            if (modelIndex < visibleIndex) {
-                int count = visibleIndex - modelIndex;
-                return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing - 1;
-            } else {
-                int idx = visibleItems.count() - 1;
-                while (idx >= 0 && visibleItems.at(idx)->index == -1)
-                    --idx;
-                if (idx < 0)
-                    idx = visibleIndex;
-                else
-                    idx = visibleItems.at(idx)->index;
-                int count = modelIndex - idx - 1;
-                return (*(--visibleItems.constEnd()))->endPosition() + count * (averageSize + spacing);
-            }
-        }
-        return 0;
-    }
+Qt::Orientation QSGListViewPrivate::layoutOrientation() const
+{
+    return static_cast<Qt::Orientation>(orient);
+}
 
-    QString sectionAt(int modelIndex) {
-        if (FxListItemSG *item = visibleItem(modelIndex))
-            return item->attached->section();
+bool QSGListViewPrivate::isRightToLeft() const
+{
+    Q_Q(const QSGListView);
+    return orient == QSGListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
+}
 
-        QString section;
-        if (sectionCriteria) {
-            QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
-            section = sectionCriteria->sectionString(propValue);
+FxViewItem *QSGListViewPrivate::nextVisibleItem() const
+{
+    const qreal pos = isRightToLeft() ? -position()-size() : position();
+    bool foundFirst = false;
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        FxViewItem *item = visibleItems.at(i);
+        if (item->index != -1) {
+            if (foundFirst)
+                return item;
+            else if (item->position() < pos && item->endPosition() > pos)
+                foundFirst = true;
         }
-
-        return section;
     }
+    return 0;
+}
 
-    bool isValid() const {
-        return model && model->count() && model->isValid();
-    }
+// Returns the item before modelIndex, if created.
+// May return an item marked for removal.
+FxViewItem *QSGListViewPrivate::itemBefore(int modelIndex) const
+{
+    if (modelIndex < visibleIndex)
+        return 0;
+    int idx = 1;
+    int lastIndex = -1;
+    while (idx < visibleItems.count()) {
+        FxViewItem *item = visibleItems.at(idx);
+        if (item->index != -1)
+            lastIndex = item->index;
+        if (item->index == modelIndex)
+            return visibleItems.at(idx-1);
+        ++idx;
+    }
+    if (lastIndex == modelIndex-1)
+        return visibleItems.last();
+    return 0;
+}
 
-    qreal snapPosAt(qreal pos) {
-        if (FxListItemSG *snapItem = snapItemAt(pos))
-            return snapItem->position();
-        if (visibleItems.count()) {
-            qreal firstPos = visibleItems.first()->position();
-            qreal endPos = visibleItems.last()->position();
-            if (pos < firstPos) {
-                return firstPos - qRound((firstPos - pos) / averageSize) * averageSize;
-            } else if (pos > endPos)
-                return endPos + qRound((pos - endPos) / averageSize) * averageSize;
-        }
-        return qRound((pos - originPosition()) / averageSize) * averageSize + originPosition();
+void QSGListViewPrivate::setPosition(qreal pos)
+{
+    Q_Q(QSGListView);
+    if (orient == QSGListView::Vertical) {
+        q->QSGFlickable::setContentY(pos);
+    } else {
+        if (isRightToLeft())
+            q->QSGFlickable::setContentX(-pos-size());
+        else
+            q->QSGFlickable::setContentX(pos);
     }
+}
 
-    FxListItemSG *snapItemAt(qreal pos) {
-        FxListItemSG *snapItem = 0;
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxListItemSG *item = visibleItems[i];
-            if (item->index == -1)
-                continue;
-            qreal itemTop = item->position();
-            if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size() - 1)
-                return item;
-            if (itemTop+item->size()/2 >= pos && itemTop-item->size()/2 < pos)
-                snapItem = item;
-        }
-        return snapItem;
+qreal QSGListViewPrivate::originPosition() const
+{
+    qreal pos = 0;
+    if (!visibleItems.isEmpty()) {
+        pos = (*visibleItems.constBegin())->position();
+        if (visibleIndex > 0)
+            pos -= visibleIndex * (averageSize + spacing);
     }
+    return pos;
+}
 
-    int lastVisibleIndex() const {
-        int lastIndex = -1;
+qreal QSGListViewPrivate::lastPosition() const
+{
+    qreal pos = 0;
+    if (!visibleItems.isEmpty()) {
+        int invisibleCount = visibleItems.count() - visibleIndex;
         for (int i = visibleItems.count()-1; i >= 0; --i) {
-            FxListItemSG *listItem = visibleItems.at(i);
-            if (listItem->index != -1) {
-                lastIndex = listItem->index;
+            if (visibleItems.at(i)->index != -1) {
+                invisibleCount = model->count() - visibleItems.at(i)->index - 1;
                 break;
             }
         }
-        return lastIndex;
+        pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
+    } else if (model && model->count()) {
+        pos = model->count() * averageSize + (model->count()-1) * spacing;
     }
+    return pos;
+}
 
-    // map a model index to visibleItems index.
-    int mapFromModel(int modelIndex) const {
-        if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
-            return -1;
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxListItemSG *listItem = visibleItems.at(i);
-            if (listItem->index == modelIndex)
-                return i;
-            if (listItem->index > modelIndex)
-                return -1;
+qreal QSGListViewPrivate::startPosition() const
+{
+    return isRightToLeft() ? -lastPosition()-1 : originPosition();
+}
+
+qreal QSGListViewPrivate::endPosition() const
+{
+    return isRightToLeft() ? -originPosition()-1 : lastPosition();
+}
+
+qreal QSGListViewPrivate::positionAt(int modelIndex) const
+{
+    if (FxViewItem *item = visibleItem(modelIndex))
+        return item->position();
+    if (!visibleItems.isEmpty()) {
+        if (modelIndex < visibleIndex) {
+            int count = visibleIndex - modelIndex;
+            qreal cs = 0;
+            if (modelIndex == currentIndex && currentItem) {
+                cs = currentItem->size() + spacing;
+                --count;
+            }
+            return (*visibleItems.constBegin())->position() - count * (averageSize + spacing) - cs;
+        } else {
+            int count = modelIndex - findLastVisibleIndex(visibleIndex) - 1;
+            return (*(--visibleItems.constEnd()))->endPosition() + spacing + count * (averageSize + spacing) + 1;
         }
-        return -1; // Not in visibleList
     }
+    return 0;
+}
 
-    void updateViewport() {
-        Q_Q(QSGListView);
-        if (orient == QSGListView::Vertical) {
-            q->setContentHeight(endPosition() - startPosition() + 1);
+qreal QSGListViewPrivate::endPositionAt(int modelIndex) const
+{
+    if (FxViewItem *item = visibleItem(modelIndex))
+        return item->endPosition();
+    if (!visibleItems.isEmpty()) {
+        if (modelIndex < visibleIndex) {
+            int count = visibleIndex - modelIndex;
+            return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing - 1;
         } else {
-            q->setContentWidth(endPosition() - startPosition() + 1);
+            int count = modelIndex - findLastVisibleIndex(visibleIndex) - 1;
+            return (*(--visibleItems.constEnd()))->endPosition() + count * (averageSize + spacing);
         }
     }
+    return 0;
+}
 
-    void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
-        Q_Q(QSGListView);
-        QSGFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
-        if (!q->isComponentComplete())
-            return;
-        if (item != contentItem && (!highlight || item != highlight->item)) {
-            if ((orient == QSGListView::Vertical && newGeometry.height() != oldGeometry.height())
-                || (orient == QSGListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
-                scheduleLayout();
-            }
-        }
-        if ((header && header->item == item) || (footer && footer->item == item)) {
-            if (header)
-                updateHeader();
-            if (footer)
-                updateFooter();
-        }
-        if (currentItem && currentItem->item == item)
-            updateHighlight();
-        if (trackedItem && trackedItem->item == item)
-            q->trackedPositionChanged();
+QString QSGListViewPrivate::sectionAt(int modelIndex)
+{
+    if (FxViewItem *item = visibleItem(modelIndex))
+        return item->attached->section();
+
+    QString section;
+    if (sectionCriteria) {
+        QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
+        section = sectionCriteria->sectionString(propValue);
     }
 
-    // for debugging only
-    void checkVisible() const {
-        int skip = 0;
-        for (int i = 0; i < visibleItems.count(); ++i) {
-            FxListItemSG *listItem = visibleItems.at(i);
-            if (listItem->index == -1) {
-                ++skip;
-            } else if (listItem->index != visibleIndex + i - skip) {
-                qFatal("index %d %d %d", visibleIndex, i, listItem->index);
-            }
-        }
+    return section;
+}
+
+qreal QSGListViewPrivate::snapPosAt(qreal pos)
+{
+    if (FxViewItem *snapItem = snapItemAt(pos))
+        return snapItem->position();
+    if (visibleItems.count()) {
+        qreal firstPos = (*visibleItems.constBegin())->position();
+        qreal endPos = (*(--visibleItems.constEnd()))->position();
+        if (pos < firstPos) {
+            return firstPos - qRound((firstPos - pos) / averageSize) * averageSize;
+        } else if (pos > endPos)
+            return endPos + qRound((pos - endPos) / averageSize) * averageSize;
     }
+    return qRound((pos - originPosition()) / averageSize) * averageSize + originPosition();
+}
 
-    void refill(qreal from, qreal to, bool doBuffer = false);
-    void scheduleLayout();
-    void layout();
-    void updateUnrequestedIndexes();
-    void updateUnrequestedPositions();
-    void updateTrackedItem();
-    void createHighlight();
-    void updateHighlight();
-    void createSection(FxListItemSG *);
-    void updateSections();
-    void updateCurrentSection();
-    void updateCurrent(int);
-    void updateAverage();
-    void updateHeader();
-    void updateFooter();
-    void fixupPosition();
-    void positionViewAtIndex(int index, int mode);
-    virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
-    virtual void flick(QSGFlickablePrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
-                        QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
+FxViewItem *QSGListViewPrivate::snapItemAt(qreal pos)
+{
+    FxViewItem *snapItem = 0;
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        FxViewItem *item = visibleItems.at(i);
+        if (item->index == -1)
+            continue;
+        qreal itemTop = item->position();
+        if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size() - 1)
+            return item;
+        if (itemTop+item->size()/2 >= pos && itemTop-item->size()/2 < pos)
+            snapItem = item;
+    }
+    return snapItem;
+}
 
-    QDeclarativeGuard<QSGVisualModel> model;
-    QVariant modelVariant;
-    QList<FxListItemSG*> visibleItems;
-    QHash<QSGItem*,int> unrequestedItems;
-    FxListItemSG *currentItem;
-    QSGListView::Orientation orient;
-    Qt::LayoutDirection layoutDirection;
-    qreal visiblePos;
-    int visibleIndex;
-    qreal averageSize;
-    int currentIndex;
-    int requestedIndex;
-    int itemCount;
-    qreal highlightRangeStart;
-    qreal highlightRangeEnd;
-    QDeclarativeComponent *highlightComponent;
-    FxListItemSG *highlight;
-    FxListItemSG *trackedItem;
-    enum MovementReason { Other, SetIndex, Mouse };
-    MovementReason moveReason;
-    int buffer;
-    QSmoothedAnimation *highlightPosAnimator;
-    QSmoothedAnimation *highlightSizeAnimator;
-    QSGViewSection *sectionCriteria;
-    QString currentSection;
-    static const int sectionCacheSize = 4;
-    QSGItem *sectionCache[sectionCacheSize];
-    qreal spacing;
-    qreal highlightMoveSpeed;
-    int highlightMoveDuration;
-    qreal highlightResizeSpeed;
-    int highlightResizeDuration;
-    QSGListView::HighlightRangeMode highlightRange;
-    QSGListView::SnapMode snapMode;
-    qreal overshootDist;
-    QDeclarativeComponent *footerComponent;
-    FxListItemSG *footer;
-    QDeclarativeComponent *headerComponent;
-    FxListItemSG *header;
-    enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
-    int bufferMode;
-    mutable qreal minExtent;
-    mutable qreal maxExtent;
-
-    bool ownModel : 1;
-    bool wrap : 1;
-    bool autoHighlight : 1;
-    bool haveHighlightRange : 1;
-    bool correctFlick : 1;
-    bool inFlickCorrection : 1;
-    bool lazyRelease : 1;
-    bool deferredRelease : 1;
-    bool layoutScheduled : 1;
-    bool currentIndexCleared : 1;
-    bool inViewportMoved : 1;
-    bool highlightRangeStartValid : 1;
-    bool highlightRangeEndValid : 1;
-    mutable bool minExtentDirty : 1;
-    mutable bool maxExtentDirty : 1;
-};
+void QSGListViewPrivate::changedVisibleIndex(int newIndex)
+{
+    visiblePos = positionAt(newIndex);
+    visibleIndex = newIndex;
+}
 
 void QSGListViewPrivate::init()
 {
-    Q_Q(QSGListView);
-    QSGItemPrivate::get(contentItem)->childrenDoNotOverlap = true;
-    q->setFlag(QSGItem::ItemIsFocusScope);
-    addItemChangeListener(this, Geometry);
-    QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
-    q->setFlickableDirection(QSGFlickable::VerticalFlick);
     ::memset(sectionCache, 0, sizeof(QSGItem*) * sectionCacheSize);
 }
 
 void QSGListViewPrivate::clear()
 {
-    timeline.clear();
-    for (int i = 0; i < visibleItems.count(); ++i)
-        releaseItem(visibleItems.at(i));
-    visibleItems.clear();
     for (int i = 0; i < sectionCacheSize; ++i) {
         delete sectionCache[i];
         sectionCache[i] = 0;
     }
-    visiblePos = header ? header->size() : 0;
-    visibleIndex = 0;
-    releaseItem(currentItem);
-    currentItem = 0;
-    createHighlight();
-    trackedItem = 0;
-    minExtentDirty = true;
-    maxExtentDirty = true;
-    itemCount = 0;
+    visiblePos = header ? headerSize() : 0;
+    QSGItemViewPrivate::clear();
 }
 
-FxListItemSG *QSGListViewPrivate::createItem(int modelIndex)
+FxViewItem *QSGListViewPrivate::newViewItem(int modelIndex, QSGItem *item)
 {
     Q_Q(QSGListView);
-    // create object
-    requestedIndex = modelIndex;
-    FxListItemSG *listItem = 0;
-    if (QSGItem *item = model->item(modelIndex, false)) {
-        listItem = new FxListItemSG(item, q);
-        listItem->index = modelIndex;
-        // initialise attached properties
-        if (sectionCriteria) {
-            QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
-            listItem->attached->m_section = sectionCriteria->sectionString(propValue);
-            if (modelIndex > 0) {
-                if (FxListItemSG *item = itemBefore(modelIndex))
-                    listItem->attached->m_prevSection = item->attached->section();
-                else
-                    listItem->attached->m_prevSection = sectionAt(modelIndex-1);
-            }
-            if (modelIndex < model->count()-1) {
-                if (FxListItemSG *item = visibleItem(modelIndex+1))
-                    listItem->attached->m_nextSection = item->attached->section();
-                else
-                    listItem->attached->m_nextSection = sectionAt(modelIndex+1);
-            }
-        }
-        if (model->completePending()) {
-            // complete
-            listItem->item->setZ(1);
-            listItem->item->setParentItem(q->contentItem());
-            model->completeItem();
-        } else {
-            listItem->item->setParentItem(q->contentItem());
+
+    FxListItemSG *listItem = new FxListItemSG(item, q, false);
+    listItem->index = modelIndex;
+
+    // initialise attached properties
+    if (sectionCriteria) {
+        QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
+        listItem->attached->m_section = sectionCriteria->sectionString(propValue);
+        if (modelIndex > 0) {
+            if (FxViewItem *item = itemBefore(modelIndex))
+                listItem->attached->m_prevSection = item->attached->section();
+            else
+                listItem->attached->m_prevSection = sectionAt(modelIndex-1);
         }
-        QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
-        itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
-        if (sectionCriteria && sectionCriteria->delegate()) {
-            if (listItem->attached->m_prevSection != listItem->attached->m_section)
-                createSection(listItem);
+        if (modelIndex < model->count()-1) {
+            if (FxViewItem *item = visibleItem(modelIndex+1))
+                listItem->attached->m_nextSection = static_cast<QSGListViewAttached*>(item->attached)->section();
+            else
+                listItem->attached->m_nextSection = sectionAt(modelIndex+1);
         }
-        unrequestedItems.remove(listItem->item);
     }
-    requestedIndex = -1;
 
     return listItem;
 }
 
-void QSGListViewPrivate::releaseItem(FxListItemSG *item)
+void QSGListViewPrivate::initializeViewItem(FxViewItem *item)
 {
-    Q_Q(QSGListView);
-    if (!item || !model)
-        return;
-    if (trackedItem == item)
-        trackedItem = 0;
     QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item->item);
-    itemPrivate->removeItemChangeListener(this, QSGItemPrivate::Geometry);
-    if (model->release(item->item) == 0) {
-        // item was not destroyed, and we no longer reference it.
-        unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+    itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
+
+    if (sectionCriteria && sectionCriteria->delegate()) {
+        if (item->attached->m_prevSection != item->attached->m_section)
+            createSection(static_cast<FxListItemSG*>(item));
     }
-    if (item->section) {
-        int i = 0;
-        do {
-            if (!sectionCache[i]) {
-                sectionCache[i] = item->section;
-                sectionCache[i]->setVisible(false);
-                item->section = 0;
-                break;
-            }
-            ++i;
-        } while (i < sectionCacheSize);
-        delete item->section;
+}
+
+void QSGListViewPrivate::releaseItem(FxViewItem *item)
+{
+    if (item) {
+        FxListItemSG* listItem = static_cast<FxListItemSG*>(item);
+        if (listItem->section) {
+            int i = 0;
+            do {
+                if (!sectionCache[i]) {
+                    sectionCache[i] = listItem->section;
+                    sectionCache[i]->setVisible(false);
+                    listItem->section = 0;
+                    break;
+                }
+                ++i;
+            } while (i < sectionCacheSize);
+            delete listItem->section;
+        }
     }
-    delete item;
+    QSGItemViewPrivate::releaseItem(item);
 }
 
-void QSGListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+bool QSGListViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer)
 {
-    Q_Q(QSGListView);
-    if (!isValid() || !q->isComponentComplete())
-        return;
-    itemCount = model->count();
-    qreal bufferFrom = from - buffer;
-    qreal bufferTo = to + buffer;
-    qreal fillFrom = from;
-    qreal fillTo = to;
-    if (doBuffer && (bufferMode & BufferAfter))
-        fillTo = bufferTo;
-    if (doBuffer && (bufferMode & BufferBefore))
-        fillFrom = bufferFrom;
-
-    bool haveValidItems = false;
-    int modelIndex = visibleIndex;
     qreal itemEnd = visiblePos-1;
-    if (!visibleItems.isEmpty()) {
+    if (visibleItems.count()) {
         visiblePos = (*visibleItems.constBegin())->position();
         itemEnd = (*(--visibleItems.constEnd()))->endPosition() + spacing;
-        int i = visibleItems.count() - 1;
-        while (i > 0 && visibleItems.at(i)->index == -1)
-            --i;
-        if (visibleItems.at(i)->index != -1) {
-            haveValidItems = true;
-            modelIndex = visibleItems.at(i)->index + 1;
-        }
     }
 
+    int modelIndex = findLastVisibleIndex();
+    bool haveValidItems = modelIndex >= 0;
+    modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
+
     if (haveValidItems && (fillFrom > itemEnd+averageSize+spacing
         || fillTo < visiblePos - averageSize - spacing)) {
         // We've jumped more than a page.  Estimate which items are now
@@ -771,7 +578,7 @@ void QSGListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
     qreal pos = itemEnd + 1;
     while (modelIndex < model->count() && pos <= fillTo) {
 //        qDebug() << "refill: append item" << modelIndex << "pos" << pos;
-        if (!(item = createItem(modelIndex)))
+        if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex))))
             break;
         item->setPosition(pos);
         pos += item->size() + spacing;
@@ -783,7 +590,7 @@ void QSGListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
     }
     while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos-1 >= fillFrom) {
 //        qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
-        if (!(item = createItem(visibleIndex-1)))
+        if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1))))
             break;
         --visibleIndex;
         visiblePos -= item->size() + spacing;
@@ -794,143 +601,90 @@ void QSGListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
             break;
     }
 
-    if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
-        while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < bufferFrom) {
-            if (item->attached->delayRemove())
-                break;
+    return changed;
+}
+
+bool QSGListViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
+{
+    FxViewItem *item = 0;
+    bool changed = false;
+
+    while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < bufferFrom) {
+        if (item->attached->delayRemove())
+            break;
 //            qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
-            if (item->index != -1)
-                visibleIndex++;
-            visibleItems.removeFirst();
-            releaseItem(item);
-            changed = true;
-        }
-        while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
-            if (item->attached->delayRemove())
-                break;
+        if (item->index != -1)
+            visibleIndex++;
+        visibleItems.removeFirst();
+        releaseItem(item);
+        changed = true;
+    }
+    while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
+        if (item->attached->delayRemove())
+            break;
 //            qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position();
-            visibleItems.removeLast();
-            releaseItem(item);
-            changed = true;
-        }
-        deferredRelease = false;
-    } else {
-        deferredRelease = true;
-    }
-    if (changed) {
-        minExtentDirty = true;
-        maxExtentDirty = true;
-        if (visibleItems.count())
-            visiblePos = (*visibleItems.constBegin())->position();
-        updateAverage();
-        if (currentIndex >= 0 && currentItem && !visibleItem(currentIndex)) {
-            currentItem->setPosition(positionAt(currentIndex));
-            updateHighlight();
-        }
-
-        if (sectionCriteria)
-            updateCurrentSection();
-        if (header)
-            updateHeader();
-        if (footer)
-            updateFooter();
-        updateViewport();
-        updateUnrequestedPositions();
-    } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
-        refill(from, to, true);
+        visibleItems.removeLast();
+        releaseItem(item);
+        changed = true;
     }
-    lazyRelease = false;
+
+    return changed;
 }
 
-void QSGListViewPrivate::scheduleLayout()
+void QSGListViewPrivate::visibleItemsChanged()
 {
-    Q_Q(QSGListView);
-    if (!layoutScheduled) {
-        layoutScheduled = true;
-        q->polish();
+    if (visibleItems.count())
+        visiblePos = (*visibleItems.constBegin())->position();
+    updateAverage();
+    if (currentIndex >= 0 && currentItem && !visibleItem(currentIndex)) {
+        static_cast<FxListItemSG*>(currentItem)->setPosition(positionAt(currentIndex));
+        updateHighlight();
     }
+    if (sectionCriteria)
+        updateCurrentSection();
+    updateHeader();
+    updateFooter();
+    updateViewport();
+    updateUnrequestedPositions();
 }
 
-void QSGListViewPrivate::layout()
+void QSGListViewPrivate::layoutVisibleItems()
 {
-    Q_Q(QSGListView);
-    layoutScheduled = false;
-    if (!isValid() && !visibleItems.count()) {
-        clear();
-        setPosition(0);
-        return;
-    }
     if (!visibleItems.isEmpty()) {
-        bool fixedCurrent = currentItem && visibleItems.first()->item == currentItem->item;
-        qreal sum = visibleItems.first()->size();
-        qreal pos = visibleItems.first()->position() + visibleItems.first()->size() + spacing;
+        bool fixedCurrent = currentItem && (*visibleItems.constBegin())->item == currentItem->item;
+        qreal sum = (*visibleItems.constBegin())->size();
+        qreal pos = (*visibleItems.constBegin())->position() + (*visibleItems.constBegin())->size() + spacing;
         for (int i=1; i < visibleItems.count(); ++i) {
-            FxListItemSG *item = visibleItems.at(i);
+            FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.at(i));
             item->setPosition(pos);
             pos += item->size() + spacing;
             sum += item->size();
             fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
         }
         averageSize = qRound(sum / visibleItems.count());
-        // move current item if it is not a visible item.
-        if (currentIndex >= 0 && currentItem && !fixedCurrent)
-            currentItem->setPosition(positionAt(currentIndex));
-    }
-    q->refill();
-    minExtentDirty = true;
-    maxExtentDirty = true;
-    updateHighlight();
-    if (!q->isMoving() && !q->isFlicking()) {
-        fixupPosition();
-        q->refill();
-    }
-    if (header)
-        updateHeader();
-    if (footer)
-        updateFooter();
-    updateViewport();
-}
 
-void QSGListViewPrivate::updateUnrequestedIndexes()
-{
-    Q_Q(QSGListView);
-    QHash<QSGItem*,int>::iterator it;
-    for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
-        *it = model->indexOf(it.key(), q);
-}
-
-void QSGListViewPrivate::updateUnrequestedPositions()
-{
-    Q_Q(QSGListView);
-    if (unrequestedItems.count()) {
-        qreal pos = position();
-        QHash<QSGItem*,int>::const_iterator it;
-        for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
-            QSGItem *item = it.key();
-            if (orient == QSGListView::Vertical) {
-                if (item->y() + item->height() > pos && item->y() < pos + q->height())
-                    item->setY(positionAt(*it));
-            } else {
-                if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
-                    if (isRightToLeft())
-                        item->setX(-positionAt(*it)-item->width());
-                    else
-                        item->setX(positionAt(*it));
-                }
-            }
+        // move current item if it is not a visible item.
+        if (currentIndex >= 0 && currentItem && !fixedCurrent) {
+            static_cast<FxListItemSG*>(currentItem)->setPosition(positionAt(currentIndex));
         }
     }
 }
 
-void QSGListViewPrivate::updateTrackedItem()
+void QSGListViewPrivate::repositionPackageItemAt(QSGItem *item, int index)
 {
     Q_Q(QSGListView);
-    FxListItemSG *item = currentItem;
-    if (highlight)
-        item = highlight;
-    trackedItem = item;
-    if (trackedItem)
-        q->trackedPositionChanged();
+    qreal pos = position();
+    if (orient == QSGListView::Vertical) {
+        if (item->y() + item->height() > pos && item->y() < pos + q->height())
+            item->setY(positionAt(index));
+    } else {
+        if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
+            if (isRightToLeft())
+                item->setX(-positionAt(index)-item->width());
+            else
+                item->setX(positionAt(index));
+        }
+    }
 }
 
 void QSGListViewPrivate::createHighlight()
@@ -940,61 +694,39 @@ void QSGListViewPrivate::createHighlight()
     if (highlight) {
         if (trackedItem == highlight)
             trackedItem = 0;
-        highlight->item->setParentItem(0);
-        highlight->item->deleteLater();
         delete highlight;
         highlight = 0;
+
         delete highlightPosAnimator;
         delete highlightSizeAnimator;
         highlightPosAnimator = 0;
         highlightSizeAnimator = 0;
+
         changed = true;
     }
 
     if (currentItem) {
-        QSGItem *item = 0;
-        if (highlightComponent) {
-            QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
-            QObject *nobj = highlightComponent->create(highlightContext);
-            if (nobj) {
-                QDeclarative_setParent_noEvent(highlightContext, nobj);
-                item = qobject_cast<QSGItem *>(nobj);
-                if (!item)
-                    delete nobj;
-            } else {
-                delete highlightContext;
-            }
-        } else {
-            item = new QSGItem;
-        }
+        QSGItem *item = createHighlightItem();
         if (item) {
-            QDeclarative_setParent_noEvent(item, q->contentItem());
-            item->setParentItem(q->contentItem());
-            highlight = new FxListItemSG(item, q);
-            if (currentItem && autoHighlight) {
-                if (orient == QSGListView::Vertical) {
-                    highlight->item->setHeight(currentItem->item->height());
-                } else {
-                    highlight->item->setWidth(currentItem->item->width());
-                }
-                highlight->setPosition(currentItem->itemPosition());
+            FxListItemSG *newHighlight = new FxListItemSG(item, q, true);
+
+            if (autoHighlight) {
+                newHighlight->setSize(static_cast<FxListItemSG*>(currentItem)->itemSize());
+                newHighlight->setPosition(static_cast<FxListItemSG*>(currentItem)->itemPosition());
             }
-            QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
-            itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
             const QLatin1String posProp(orient == QSGListView::Vertical ? "y" : "x");
             highlightPosAnimator = new QSmoothedAnimation(q);
-            highlightPosAnimator->target = QDeclarativeProperty(highlight->item, posProp);
+            highlightPosAnimator->target = QDeclarativeProperty(item, posProp);
             highlightPosAnimator->velocity = highlightMoveSpeed;
             highlightPosAnimator->userDuration = highlightMoveDuration;
+
             const QLatin1String sizeProp(orient == QSGListView::Vertical ? "height" : "width");
             highlightSizeAnimator = new QSmoothedAnimation(q);
             highlightSizeAnimator->velocity = highlightResizeSpeed;
             highlightSizeAnimator->userDuration = highlightResizeDuration;
-            highlightSizeAnimator->target = QDeclarativeProperty(highlight->item, sizeProp);
-            if (autoHighlight) {
-                highlightPosAnimator->restart();
-                highlightSizeAnimator->restart();
-            }
+            highlightSizeAnimator->target = QDeclarativeProperty(item, sizeProp);
+
+            highlight = newHighlight;
             changed = true;
         }
     }
@@ -1008,10 +740,11 @@ void QSGListViewPrivate::updateHighlight()
         createHighlight();
     if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
         // auto-update highlight
+        FxListItemSG *listItem = static_cast<FxListItemSG*>(currentItem);
         highlightPosAnimator->to = isRightToLeft()
-                ? -currentItem->itemPosition()-currentItem->itemSize()
-                : currentItem->itemPosition();
-        highlightSizeAnimator->to = currentItem->itemSize();
+                ? -listItem->itemPosition()-listItem->itemSize()
+                : listItem->itemPosition();
+        highlightSizeAnimator->to = listItem->itemSize();
         if (orient == QSGListView::Vertical) {
             if (highlight->item->width() == 0)
                 highlight->item->setWidth(currentItem->item->width());
@@ -1019,12 +752,19 @@ void QSGListViewPrivate::updateHighlight()
             if (highlight->item->height() == 0)
                 highlight->item->setHeight(currentItem->item->height());
         }
+
         highlightPosAnimator->restart();
         highlightSizeAnimator->restart();
     }
     updateTrackedItem();
 }
 
+void QSGListViewPrivate::resetHighlightPosition()
+{
+    if (highlight && currentItem)
+        static_cast<FxListItemSG*>(highlight)->setPosition(static_cast<FxListItemSG*>(currentItem)->itemPosition());
+}
+
 void QSGListViewPrivate::createSection(FxListItemSG *listItem)
 {
     Q_Q(QSGListView);
@@ -1093,14 +833,14 @@ void QSGListViewPrivate::updateSections()
         QSGListViewAttached *prevAtt = 0;
         int idx = -1;
         for (int i = 0; i < visibleItems.count(); ++i) {
-            QSGListViewAttached *attached = visibleItems.at(i)->attached;
+            QSGListViewAttached *attached = static_cast<QSGListViewAttached*>(visibleItems.at(i)->attached);
             attached->setPrevSection(prevSection);
             if (visibleItems.at(i)->index != -1) {
                 QString propValue = model->stringValue(visibleItems.at(i)->index, sectionCriteria->property());
                 attached->setSection(sectionCriteria->sectionString(propValue));
                 idx = visibleItems.at(i)->index;
             }
-            createSection(visibleItems.at(i));
+            createSection(static_cast<FxListItemSG*>(visibleItems.at(i)));
             if (prevAtt)
                 prevAtt->setNextSection(attached->section());
             prevSection = attached->section();
@@ -1133,63 +873,36 @@ void QSGListViewPrivate::updateCurrentSection()
     if (index < visibleItems.count())
         newSection = visibleItems.at(index)->attached->section();
     else
-        newSection = visibleItems.first()->attached->section();
+        newSection = (*visibleItems.constBegin())->attached->section();
     if (newSection != currentSection) {
         currentSection = newSection;
         emit q->currentSectionChanged();
     }
 }
 
-void QSGListViewPrivate::updateCurrent(int modelIndex)
+void QSGListViewPrivate::initializeCurrentItem()
 {
-    Q_Q(QSGListView);
-    if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
-        if (currentItem) {
-            currentItem->attached->setIsCurrentItem(false);
-            releaseItem(currentItem);
-            currentItem = 0;
-            currentIndex = modelIndex;
-            emit q->currentIndexChanged();
-            updateHighlight();
-        } else if (currentIndex != modelIndex) {
-            currentIndex = modelIndex;
-            emit q->currentIndexChanged();
-        }
-        return;
-    }
-
-    if (currentItem && currentIndex == modelIndex) {
-        updateHighlight();
-        return;
-    }
-    FxListItemSG *oldCurrentItem = currentItem;
-    currentIndex = modelIndex;
-    currentItem = createItem(modelIndex);
-    if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
-        oldCurrentItem->attached->setIsCurrentItem(false);
     if (currentItem) {
-        if (modelIndex == visibleIndex - 1 && visibleItems.count()) {
+        FxListItemSG *listItem = static_cast<FxListItemSG *>(currentItem);
+
+        if (currentIndex == visibleIndex - 1 && visibleItems.count()) {
             // We can calculate exact postion in this case
-            currentItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing);
+            listItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing);
         } else {
             // Create current item now and position as best we can.
             // Its position will be corrected when it becomes visible.
-            currentItem->setPosition(positionAt(modelIndex));
+            listItem->setPosition(positionAt(currentIndex));
         }
-        currentItem->item->setFocus(true);
-        currentItem->attached->setIsCurrentItem(true);
+
         // Avoid showing section delegate twice.  We still need the section heading so that
         // currentItem positioning works correctly.
         // This is slightly sub-optimal, but section heading caching minimizes the impact.
-        if (currentItem->section)
-            currentItem->section->setVisible(false);
+        if (listItem->section)
+            listItem->section->setVisible(false);
+
         if (visibleItems.isEmpty())
-            averageSize = currentItem->size();
+            averageSize = listItem->size();
     }
-    updateHighlight();
-    emit q->currentIndexChanged();
-    // Release the old current item
-    releaseItem(oldCurrentItem);
 }
 
 void QSGListViewPrivate::updateAverage()
@@ -1202,83 +915,82 @@ void QSGListViewPrivate::updateAverage()
     averageSize = qRound(sum / visibleItems.count());
 }
 
+qreal QSGListViewPrivate::headerSize() const
+{
+    return header ? header->size() : 0.0;
+}
+
+qreal QSGListViewPrivate::footerSize() const
+{
+    return footer ? footer->size() : 0.0;
+}
+
 void QSGListViewPrivate::updateFooter()
 {
     Q_Q(QSGListView);
-    if (!footer && footerComponent) {
-        QSGItem *item = 0;
-        QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
-        QObject *nobj = footerComponent->create(context);
-        if (nobj) {
-            QDeclarative_setParent_noEvent(context, nobj);
-            item = qobject_cast<QSGItem *>(nobj);
-            if (!item)
-                delete nobj;
-        } else {
-            delete context;
-        }
-        if (item) {
-            QDeclarative_setParent_noEvent(item, q->contentItem());
-            item->setParentItem(q->contentItem());
-            item->setZ(1);
-            QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
-            itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
-            footer = new FxListItemSG(item, q);
-        }
+
+    if (!footer) {
+        QSGItem *item = createComponentItem(footerComponent, true);
+        if (!item)
+            return;
+        item->setZ(1);
+        footer = new FxListItemSG(item, q, true);
     }
-    if (footer) {
-        if (visibleItems.count()) {
-            qreal endPos = lastPosition() + 1;
-            if (lastVisibleIndex() == model->count()-1) {
-                footer->setPosition(endPos);
-            } else {
-                qreal visiblePos = position() + q->height();
-                if (endPos <= visiblePos || footer->position() < endPos)
-                    footer->setPosition(endPos);
-            }
+
+    FxListItemSG *listItem = static_cast<FxListItemSG*>(footer);
+    if (visibleItems.count()) {
+        qreal endPos = lastPosition() + 1;
+        if (findLastVisibleIndex() == model->count()-1) {
+            listItem->setPosition(endPos);
         } else {
-            footer->setPosition(visiblePos);
+            qreal visiblePos = position() + q->height();
+            if (endPos <= visiblePos || listItem->position() < endPos)
+                listItem->setPosition(endPos);
         }
+    } else {
+        listItem->setPosition(visiblePos);
     }
 }
 
 void QSGListViewPrivate::updateHeader()
 {
     Q_Q(QSGListView);
-    if (!header && headerComponent) {
-        QSGItem *item = 0;
-        QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
-        QObject *nobj = headerComponent->create(context);
-        if (nobj) {
-            QDeclarative_setParent_noEvent(context, nobj);
-            item = qobject_cast<QSGItem *>(nobj);
-            if (!item)
-                delete nobj;
-        } else {
-            delete context;
-        }
-        if (item) {
-            QDeclarative_setParent_noEvent(item, q->contentItem());
-            item->setParentItem(q->contentItem());
-            item->setZ(1);
-            QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
-            itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
-            header = new FxListItemSG(item, q);
-        }
+    if (!header) {
+        QSGItem *item = createComponentItem(headerComponent, true);
+        if (!item)
+            return;
+        item->setZ(1);
+        header = new FxListItemSG(item, q, true);
     }
-    if (header) {
+
+    FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
+    if (listItem) {
         if (visibleItems.count()) {
             qreal startPos = originPosition();
             if (visibleIndex == 0) {
-                header->setPosition(startPos - header->size());
+                listItem->setPosition(startPos - headerSize());
             } else {
-                if (position() <= startPos || header->position() > startPos - header->size())
-                    header->setPosition(startPos - header->size());
+                if (position() <= startPos || listItem->position() > startPos - headerSize())
+                    listItem->setPosition(startPos - headerSize());
             }
         } else {
             if (itemCount == 0)
-                visiblePos = header->size();
-            header->setPosition(0);
+                visiblePos = headerSize();
+            listItem->setPosition(0);
+        }
+    }
+}
+
+void QSGListViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+    Q_Q(QSGListView);
+    QSGItemViewPrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+    if (!q->isComponentComplete())
+        return;
+    if (item != contentItem && (!highlight || item != highlight->item)) {
+        if ((orient == QSGListView::Vertical && newGeometry.height() != oldGeometry.height())
+            || (orient == QSGListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
+            scheduleLayout();
         }
     }
 }
@@ -1320,9 +1032,9 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
     if (currentItem && haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange
             && moveReason != QSGListViewPrivate::SetIndex) {
         updateHighlight();
-        qreal pos = currentItem->itemPosition();
-        if (viewPos < pos + currentItem->itemSize() - highlightEnd)
-            viewPos = pos + currentItem->itemSize() - highlightEnd;
+        qreal pos = static_cast<FxListItemSG*>(currentItem)->itemPosition();
+        if (viewPos < pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightEnd)
+            viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightEnd;
         if (viewPos > pos - highlightStart)
             viewPos = pos - highlightStart;
         if (isRightToLeft())
@@ -1340,12 +1052,12 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
         vTime = timeline.time();
     } else if (snapMode != QSGListView::NoSnap && moveReason != QSGListViewPrivate::SetIndex) {
         qreal tempPosition = isRightToLeft() ? -position()-size() : position();
-        FxListItemSG *topItem = snapItemAt(tempPosition+highlightStart);
-        FxListItemSG *bottomItem = snapItemAt(tempPosition+highlightEnd);
+        FxViewItem *topItem = snapItemAt(tempPosition+highlightStart);
+        FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
         qreal pos;
         bool isInBounds = -position() > maxExtent && -position() < minExtent;
         if (topItem && isInBounds) {
-            if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2) {
+            if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+headerSize()/2) {
                 pos = isRightToLeft() ? - header->position() + highlightStart - size() : header->position() - highlightStart;
             } else {
                 if (isRightToLeft())
@@ -1359,7 +1071,7 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
             else
                 pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent);
         } else {
-            QSGFlickablePrivate::fixup(data, minExtent, maxExtent);
+            QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
             return;
         }
 
@@ -1375,7 +1087,7 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
             vTime = timeline.time();
         }
     } else {
-        QSGFlickablePrivate::fixup(data, minExtent, maxExtent);
+        QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
     }
     data.inOvershoot = false;
     fixupMode = Normal;
@@ -1390,7 +1102,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
     moveReason = Mouse;
     if ((!haveHighlightRange || highlightRange != QSGListView::StrictlyEnforceRange) && snapMode == QSGListView::NoSnap) {
         correctFlick = true;
-        QSGFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
+        QSGItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
         return;
     }
     qreal maxDistance = 0;
@@ -1399,7 +1111,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
     if (velocity > 0) {
         if (data.move.value() < minExtent) {
             if (snapMode == QSGListView::SnapOneItem) {
-                if (FxListItemSG *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem())
+                if (FxViewItem *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem())
                     maxDistance = qAbs(item->position() + dataValue);
             } else {
                 maxDistance = qAbs(minExtent - data.move.value());
@@ -1410,7 +1122,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
     } else {
         if (data.move.value() > maxExtent) {
             if (snapMode == QSGListView::SnapOneItem) {
-                if (FxListItemSG *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem())
+                if (FxViewItem *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem())
                     maxDistance = qAbs(item->position() + dataValue);
             } else {
                 maxDistance = qAbs(maxExtent - data.move.value());
@@ -1529,304 +1241,32 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
         correctFlick = false;
         timeline.reset(data.move);
         fixup(data, minExtent, maxExtent);
-    }
-}
-
-//----------------------------------------------------------------------------
-
-QSGListView::QSGListView(QSGItem *parent)
-    : QSGFlickable(*(new QSGListViewPrivate), parent)
-{
-    Q_D(QSGListView);
-    d->init();
-}
-
-QSGListView::~QSGListView()
-{
-    Q_D(QSGListView);
-    d->clear();
-    if (d->ownModel)
-        delete d->model;
-    delete d->header;
-    delete d->footer;
-}
-
-QVariant QSGListView::model() const
-{
-    Q_D(const QSGListView);
-    return d->modelVariant;
-}
-
-void QSGListView::setModel(const QVariant &model)
-{
-    Q_D(QSGListView);
-    if (d->modelVariant == model)
-        return;
-    if (d->model) {
-        disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
-        disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
-        disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
-        disconnect(d->model, SIGNAL(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
-        disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
-        disconnect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
-        disconnect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
-    }
-    d->clear();
-    QSGVisualModel *oldModel = d->model;
-    d->model = 0;
-    d->setPosition(0);
-    d->modelVariant = model;
-    QObject *object = qvariant_cast<QObject*>(model);
-    QSGVisualModel *vim = 0;
-    if (object && (vim = qobject_cast<QSGVisualModel *>(object))) {
-        if (d->ownModel) {
-            delete oldModel;
-            d->ownModel = false;
-        }
-        d->model = vim;
-    } else {
-        if (!d->ownModel) {
-            d->model = new QSGVisualDataModel(qmlContext(this), this);
-            d->ownModel = true;
-        } else {
-            d->model = oldModel;
-        }
-        if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
-            dataModel->setModel(model);
-    }
-    if (d->model) {
-        d->bufferMode = QSGListViewPrivate::BufferBefore | QSGListViewPrivate::BufferAfter;
-        if (isComponentComplete()) {
-            updateSections();
-            refill();
-            if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
-                setCurrentIndex(0);
-            } else {
-                d->moveReason = QSGListViewPrivate::SetIndex;
-                d->updateCurrent(d->currentIndex);
-                if (d->highlight && d->currentItem) {
-                    if (d->autoHighlight)
-                        d->highlight->setPosition(d->currentItem->position());
-                    d->updateTrackedItem();
-                }
-            }
-            d->updateViewport();
-        }
-        connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
-        connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
-        connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
-        connect(d->model, SIGNAL(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
-        connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
-        connect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
-        connect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
-        emit countChanged();
-    }
-    emit modelChanged();
-}
-
-QDeclarativeComponent *QSGListView::delegate() const
-{
-    Q_D(const QSGListView);
-    if (d->model) {
-        if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
-            return dataModel->delegate();
-    }
-
-    return 0;
-}
-
-void QSGListView::setDelegate(QDeclarativeComponent *delegate)
-{
-    Q_D(QSGListView);
-    if (delegate == this->delegate())
-        return;
-    if (!d->ownModel) {
-        d->model = new QSGVisualDataModel(qmlContext(this));
-        d->ownModel = true;
-    }
-    if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model)) {
-        int oldCount = dataModel->count();
-        dataModel->setDelegate(delegate);
-        if (isComponentComplete()) {
-            for (int i = 0; i < d->visibleItems.count(); ++i)
-                d->releaseItem(d->visibleItems.at(i));
-            d->visibleItems.clear();
-            d->releaseItem(d->currentItem);
-            d->currentItem = 0;
-            updateSections();
-            refill();
-            d->moveReason = QSGListViewPrivate::SetIndex;
-            d->updateCurrent(d->currentIndex);
-            if (d->highlight && d->currentItem) {
-                if (d->autoHighlight)
-                    d->highlight->setPosition(d->currentItem->position());
-                d->updateTrackedItem();
-            }
-            d->updateViewport();
-        }
-        if (oldCount != dataModel->count())
-            emit countChanged();
-    }
-    emit delegateChanged();
-}
-
-int QSGListView::currentIndex() const
-{
-    Q_D(const QSGListView);
-    return d->currentIndex;
-}
-
-void QSGListView::setCurrentIndex(int index)
-{
-    Q_D(QSGListView);
-    if (d->requestedIndex >= 0)  // currently creating item
-        return;
-    d->currentIndexCleared = (index == -1);
-    if (index == d->currentIndex)
-        return;
-    if (isComponentComplete() && d->isValid()) {
-        d->moveReason = QSGListViewPrivate::SetIndex;
-        d->updateCurrent(index);
-    } else if (d->currentIndex != index) {
-        d->currentIndex = index;
-        emit currentIndexChanged();
-    }
-}
-
-QSGItem *QSGListView::currentItem()
-{
-    Q_D(QSGListView);
-    if (!d->currentItem)
-        return 0;
-    return d->currentItem->item;
-}
-
-QSGItem *QSGListView::highlightItem()
-{
-    Q_D(QSGListView);
-    if (!d->highlight)
-        return 0;
-    return d->highlight->item;
-}
-
-int QSGListView::count() const
-{
-    Q_D(const QSGListView);
-    if (d->model)
-        return d->model->count();
-    return 0;
-}
-
-QDeclarativeComponent *QSGListView::highlight() const
-{
-    Q_D(const QSGListView);
-    return d->highlightComponent;
-}
-
-void QSGListView::setHighlight(QDeclarativeComponent *highlight)
-{
-    Q_D(QSGListView);
-    if (highlight != d->highlightComponent) {
-        d->highlightComponent = highlight;
-        d->createHighlight();
-        if (d->currentItem)
-            d->updateHighlight();
-        emit highlightChanged();
-    }
-}
-
-bool QSGListView::highlightFollowsCurrentItem() const
-{
-    Q_D(const QSGListView);
-    return d->autoHighlight;
-}
-
-void QSGListView::setHighlightFollowsCurrentItem(bool autoHighlight)
-{
-    Q_D(QSGListView);
-    if (d->autoHighlight != autoHighlight) {
-        d->autoHighlight = autoHighlight;
-        if (autoHighlight) {
-            d->updateHighlight();
-        } else {
-            if (d->highlightPosAnimator)
-                d->highlightPosAnimator->stop();
-            if (d->highlightSizeAnimator)
-                d->highlightSizeAnimator->stop();
-        }
-        emit highlightFollowsCurrentItemChanged();
-    }
-}
-
-//###Possibly rename these properties, since they are very useful even without a highlight?
-qreal QSGListView::preferredHighlightBegin() const
-{
-    Q_D(const QSGListView);
-    return d->highlightRangeStart;
-}
-
-void QSGListView::setPreferredHighlightBegin(qreal start)
-{
-    Q_D(QSGListView);
-    d->highlightRangeStartValid = true;
-    if (d->highlightRangeStart == start)
-        return;
-    d->highlightRangeStart = start;
-    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
-    emit preferredHighlightBeginChanged();
-}
-
-void QSGListView::resetPreferredHighlightBegin()
-{
-    Q_D(QSGListView);
-    d->highlightRangeStartValid = false;
-    if (d->highlightRangeStart == 0)
-        return;
-    d->highlightRangeStart = 0;
-    emit preferredHighlightBeginChanged();
-}
-
-qreal QSGListView::preferredHighlightEnd() const
-{
-    Q_D(const QSGListView);
-    return d->highlightRangeEnd;
-}
-
-void QSGListView::setPreferredHighlightEnd(qreal end)
-{
-    Q_D(QSGListView);
-    d->highlightRangeEndValid = true;
-    if (d->highlightRangeEnd == end)
-        return;
-    d->highlightRangeEnd = end;
-    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
-    emit preferredHighlightEndChanged();
+    }
 }
 
-void QSGListView::resetPreferredHighlightEnd()
+//----------------------------------------------------------------------------
+
+QSGListView::QSGListView(QSGItem *parent)
+    : QSGItemView(*(new QSGListViewPrivate), parent)
 {
-    Q_D(QSGListView);
-    d->highlightRangeEndValid = false;
-    if (d->highlightRangeEnd == 0)
-        return;
-    d->highlightRangeEnd = 0;
-    emit preferredHighlightEndChanged();
 }
 
-QSGListView::HighlightRangeMode QSGListView::highlightRangeMode() const
+QSGListView::~QSGListView()
 {
-    Q_D(const QSGListView);
-    return d->highlightRange;
 }
 
-void QSGListView::setHighlightRangeMode(HighlightRangeMode mode)
+void QSGListView::setHighlightFollowsCurrentItem(bool autoHighlight)
 {
     Q_D(QSGListView);
-    if (d->highlightRange == mode)
-        return;
-    d->highlightRange = mode;
-    d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
-    emit highlightRangeModeChanged();
+    if (d->autoHighlight != autoHighlight) {
+        if (!autoHighlight) {
+            if (d->highlightPosAnimator)
+                d->highlightPosAnimator->stop();
+            if (d->highlightSizeAnimator)
+                d->highlightSizeAnimator->stop();
+        }
+        QSGItemView::setHighlightFollowsCurrentItem(autoHighlight);
+    }
 }
 
 qreal QSGListView::spacing() const
@@ -1856,7 +1296,7 @@ void QSGListView::setOrientation(QSGListView::Orientation orientation)
     Q_D(QSGListView);
     if (d->orient != orientation) {
         d->orient = orientation;
-        if (d->orient == QSGListView::Vertical) {
+        if (d->orient == Vertical) {
             setContentWidth(-1);
             setFlickableDirection(VerticalFlick);
             setContentX(0);
@@ -1870,66 +1310,6 @@ void QSGListView::setOrientation(QSGListView::Orientation orientation)
     }
 }
 
-Qt::LayoutDirection QSGListView::layoutDirection() const
-{
-    Q_D(const QSGListView);
-    return d->layoutDirection;
-}
-
-void QSGListView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
-{
-    Q_D(QSGListView);
-    if (d->layoutDirection != layoutDirection) {
-        d->layoutDirection = layoutDirection;
-        d->regenerate();
-        emit layoutDirectionChanged();
-        emit effectiveLayoutDirectionChanged();
-    }
-}
-
-Qt::LayoutDirection QSGListView::effectiveLayoutDirection() const
-{
-    Q_D(const QSGListView);
-    if (d->effectiveLayoutMirror)
-        return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
-    else
-        return d->layoutDirection;
-}
-
-bool QSGListView::isWrapEnabled() const
-{
-    Q_D(const QSGListView);
-    return d->wrap;
-}
-
-void QSGListView::setWrapEnabled(bool wrap)
-{
-    Q_D(QSGListView);
-    if (d->wrap == wrap)
-        return;
-    d->wrap = wrap;
-    emit keyNavigationWrapsChanged();
-}
-
-int QSGListView::cacheBuffer() const
-{
-    Q_D(const QSGListView);
-    return d->buffer;
-}
-
-void QSGListView::setCacheBuffer(int b)
-{
-    Q_D(QSGListView);
-    if (d->buffer != b) {
-        d->buffer = b;
-        if (isComponentComplete()) {
-            d->bufferMode = QSGListViewPrivate::BufferBefore | QSGListViewPrivate::BufferAfter;
-            refill();
-        }
-        emit cacheBufferChanged();
-    }
-}
-
 QSGViewSection *QSGListView::sectionCriteria()
 {
     Q_D(QSGListView);
@@ -1948,13 +1328,13 @@ QString QSGListView::currentSection() const
 
 qreal QSGListView::highlightMoveSpeed() const
 {
-    Q_D(const QSGListView);\
+    Q_D(const QSGListView);
     return d->highlightMoveSpeed;
 }
 
 void QSGListView::setHighlightMoveSpeed(qreal speed)
 {
-    Q_D(QSGListView);\
+    Q_D(QSGListView);
     if (d->highlightMoveSpeed != speed) {
         d->highlightMoveSpeed = speed;
         if (d->highlightPosAnimator)
@@ -1963,32 +1343,25 @@ void QSGListView::setHighlightMoveSpeed(qreal speed)
     }
 }
 
-int QSGListView::highlightMoveDuration() const
-{
-    Q_D(const QSGListView);
-    return d->highlightMoveDuration;
-}
-
 void QSGListView::setHighlightMoveDuration(int duration)
 {
-    Q_D(QSGListView);\
+    Q_D(QSGListView);
     if (d->highlightMoveDuration != duration) {
-        d->highlightMoveDuration = duration;
         if (d->highlightPosAnimator)
-            d->highlightPosAnimator->userDuration = d->highlightMoveDuration;
-        emit highlightMoveDurationChanged();
+            d->highlightPosAnimator->userDuration = duration;
+        QSGItemView::setHighlightMoveDuration(duration);
     }
 }
 
 qreal QSGListView::highlightResizeSpeed() const
 {
-    Q_D(const QSGListView);\
+    Q_D(const QSGListView);
     return d->highlightResizeSpeed;
 }
 
 void QSGListView::setHighlightResizeSpeed(qreal speed)
 {
-    Q_D(QSGListView);\
+    Q_D(QSGListView);
     if (d->highlightResizeSpeed != speed) {
         d->highlightResizeSpeed = speed;
         if (d->highlightSizeAnimator)
@@ -2005,7 +1378,7 @@ int QSGListView::highlightResizeDuration() const
 
 void QSGListView::setHighlightResizeDuration(int duration)
 {
-    Q_D(QSGListView);\
+    Q_D(QSGListView);
     if (d->highlightResizeDuration != duration) {
         d->highlightResizeDuration = duration;
         if (d->highlightSizeAnimator)
@@ -2029,92 +1402,10 @@ void QSGListView::setSnapMode(SnapMode mode)
     }
 }
 
-QDeclarativeComponent *QSGListView::footer() const
-{
-    Q_D(const QSGListView);
-    return d->footerComponent;
-}
-
-void QSGListView::setFooter(QDeclarativeComponent *footer)
-{
-    Q_D(QSGListView);
-    if (d->footerComponent != footer) {
-        if (d->footer) {
-            // XXX todo - the original did scene()->removeItem().  Why?
-            d->footer->item->setParentItem(0);
-            d->footer->item->deleteLater();
-            delete d->footer;
-            d->footer = 0;
-        }
-        d->footerComponent = footer;
-        d->minExtentDirty = true;
-        d->maxExtentDirty = true;
-        if (isComponentComplete()) {
-            d->updateFooter();
-            d->updateViewport();
-            d->fixupPosition();
-        }
-        emit footerChanged();
-    }
-}
-
-QDeclarativeComponent *QSGListView::header() const
-{
-    Q_D(const QSGListView);
-    return d->headerComponent;
-}
-
-void QSGListView::setHeader(QDeclarativeComponent *header)
-{
-    Q_D(QSGListView);
-    if (d->headerComponent != header) {
-        if (d->header) {
-            // XXX todo - the original did scene()->removeItem().  Why?
-            d->header->item->setParentItem(0);
-            d->header->item->deleteLater();
-            delete d->header;
-            d->header = 0;
-        }
-        d->headerComponent = header;
-        d->minExtentDirty = true;
-        d->maxExtentDirty = true;
-        if (isComponentComplete()) {
-            d->updateHeader();
-            d->updateFooter();
-            d->updateViewport();
-            d->fixupPosition();
-        }
-        emit headerChanged();
-    }
-}
-
-void QSGListView::setContentX(qreal pos)
-{
-    Q_D(QSGListView);
-    // Positioning the view manually should override any current movement state
-    d->moveReason = QSGListViewPrivate::Other;
-    QSGFlickable::setContentX(pos);
-}
-
-void QSGListView::setContentY(qreal pos)
-{
-    Q_D(QSGListView);
-    // Positioning the view manually should override any current movement state
-    d->moveReason = QSGListViewPrivate::Other;
-    QSGFlickable::setContentY(pos);
-}
-
-void QSGListView::updatePolish()
-{
-    Q_D(QSGListView);
-    QSGFlickable::updatePolish();
-    d->layout();
-}
-
 void QSGListView::viewportMoved()
 {
     Q_D(QSGListView);
-    QSGFlickable::viewportMoved();
+    QSGItemView::viewportMoved();
     if (!d->itemCount)
         return;
     // Recursion can occur due to refill changing the content size.
@@ -2122,7 +1413,7 @@ void QSGListView::viewportMoved()
         return;
     d->inViewportMoved = true;
     d->lazyRelease = true;
-    refill();
+    d->refill();
     if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
         d->moveReason = QSGListViewPrivate::Mouse;
     if (d->moveReason != QSGListViewPrivate::SetIndex) {
@@ -2147,10 +1438,10 @@ void QSGListView::viewportMoved()
             if (pos < viewPos + highlightStart)
                 pos = viewPos + highlightStart;
             d->highlightPosAnimator->stop();
-            d->highlight->setPosition(qRound(pos));
+            static_cast<FxListItemSG*>(d->highlight)->setPosition(qRound(pos));
 
             // update current index
-            if (FxListItemSG *snapItem = d->snapItemAt(d->highlight->position())) {
+            if (FxViewItem *snapItem = d->snapItemAt(d->highlight->position())) {
                 if (snapItem->index >= 0 && snapItem->index != d->currentIndex)
                     d->updateCurrent(snapItem->index);
             }
@@ -2197,146 +1488,6 @@ void QSGListView::viewportMoved()
     d->inViewportMoved = false;
 }
 
-qreal QSGListView::minYExtent() const
-{
-    Q_D(const QSGListView);
-    if (d->orient == QSGListView::Horizontal)
-        return QSGFlickable::minYExtent();
-    if (d->minExtentDirty) {
-        d->minExtent = -d->startPosition();
-        if (d->header && d->visibleItems.count())
-            d->minExtent += d->header->size();
-        if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
-            d->minExtent += d->highlightRangeStart;
-            if (d->sectionCriteria) {
-                if (d->visibleItem(0))
-                    d->minExtent -= d->visibleItem(0)->sectionSize();
-            }
-            d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1));
-        }
-        d->minExtentDirty = false;
-    }
-
-    return d->minExtent;
-}
-
-qreal QSGListView::maxYExtent() const
-{
-    Q_D(const QSGListView);
-    if (d->orient == QSGListView::Horizontal)
-        return height();
-    if (d->maxExtentDirty) {
-        if (!d->model || !d->model->count()) {
-            d->maxExtent = d->header ? -d->header->size() : 0;
-            d->maxExtent += height();
-        } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
-            d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
-            if (d->highlightRangeEnd != d->highlightRangeStart)
-                d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1));
-        } else {
-            d->maxExtent = -(d->endPosition() - height() + 1);
-        }
-        if (d->footer)
-            d->maxExtent -= d->footer->size();
-        qreal minY = minYExtent();
-        if (d->maxExtent > minY)
-            d->maxExtent = minY;
-        d->maxExtentDirty = false;
-    }
-    return d->maxExtent;
-}
-
-qreal QSGListView::minXExtent() const
-{
-    Q_D(const QSGListView);
-    if (d->orient == QSGListView::Vertical)
-        return QSGFlickable::minXExtent();
-    if (d->minExtentDirty) {
-        d->minExtent = -d->startPosition();
-        qreal highlightStart;
-        qreal highlightEnd;
-        qreal endPositionFirstItem = 0;
-        if (d->isRightToLeft()) {
-            if (d->model && d->model->count())
-                endPositionFirstItem = d->positionAt(d->model->count()-1);
-            else if (d->header)
-                d->minExtent += d->header->size();
-            highlightStart = d->highlightRangeStartValid
-                    ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
-                    : d->size() - (d->lastPosition()-endPositionFirstItem);
-            highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
-            if (d->footer)
-                d->minExtent += d->footer->size();
-            qreal maxX = maxXExtent();
-            if (d->minExtent < maxX)
-                d->minExtent = maxX;
-        } else {
-            endPositionFirstItem = d->endPositionAt(0);
-            highlightStart = d->highlightRangeStart;
-            highlightEnd = d->highlightRangeEnd;
-            if (d->header && d->visibleItems.count())
-                d->minExtent += d->header->size();
-        }
-        if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
-            d->minExtent += highlightStart;
-            d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1));
-        }
-        d->minExtentDirty = false;
-    }
-
-    return d->minExtent;
-}
-
-qreal QSGListView::maxXExtent() const
-{
-    Q_D(const QSGListView);
-    if (d->orient == QSGListView::Vertical)
-        return width();
-    if (d->maxExtentDirty) {
-        qreal highlightStart;
-        qreal highlightEnd;
-        qreal lastItemPosition = 0;
-        d->maxExtent = 0;
-        if (d->isRightToLeft()) {
-            highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
-            highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
-            lastItemPosition = d->endPosition();
-        } else {
-            highlightStart = d->highlightRangeStart;
-            highlightEnd = d->highlightRangeEnd;
-            if (d->model && d->model->count())
-                lastItemPosition = d->positionAt(d->model->count()-1);
-        }
-        if (!d->model || !d->model->count()) {
-            if (!d->isRightToLeft())
-                d->maxExtent = d->header ? -d->header->size() : 0;
-            d->maxExtent += width();
-        } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
-            d->maxExtent = -(lastItemPosition - highlightStart);
-            if (highlightEnd != highlightStart) {
-                d->maxExtent = d->isRightToLeft()
-                        ? qMax(d->maxExtent, -(d->endPosition() - highlightEnd + 1))
-                        : qMin(d->maxExtent, -(d->endPosition() - highlightEnd + 1));
-            }
-        } else {
-            d->maxExtent = -(d->endPosition() - width() + 1);
-        }
-        if (d->isRightToLeft()) {
-            if (d->header && d->visibleItems.count())
-                d->maxExtent -= d->header->size();
-        } else {
-            if (d->footer)
-                d->maxExtent -= d->footer->size();
-            qreal minX = minXExtent();
-            if (d->maxExtent > minX)
-                d->maxExtent = minX;
-        }
-        d->maxExtentDirty = false;
-    }
-
-    return d->maxExtent;
-}
-
 void QSGListView::keyPressEvent(QKeyEvent *event)
 {
     Q_D(QSGListView);
@@ -2366,21 +1517,18 @@ void QSGListView::keyPressEvent(QKeyEvent *event)
         }
     }
     event->ignore();
-    QSGFlickable::keyPressEvent(event);
+    QSGItemView::keyPressEvent(event);
 }
 
-void QSGListView::geometryChanged(const QRectF &newGeometry,
-                                  const QRectF &oldGeometry)
+void QSGListView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
 {
     Q_D(QSGListView);
-    d->maxExtentDirty = true;
-    d->minExtentDirty = true;
     if (d->isRightToLeft() && d->orient == QSGListView::Horizontal) {
         // maintain position relative to the right edge
         int dx = newGeometry.width() - oldGeometry.width();
         setContentX(contentX() - dx);
     }
-    QSGFlickable::geometryChanged(newGeometry, oldGeometry);
+    QSGItemView::geometryChanged(newGeometry, oldGeometry);
 }
 
 
@@ -2406,147 +1554,6 @@ void QSGListView::decrementCurrentIndex()
     }
 }
 
-void QSGListViewPrivate::positionViewAtIndex(int index, int mode)
-{
-    Q_Q(QSGListView);
-    if (!isValid())
-        return;
-    if (mode < QSGListView::Beginning || mode > QSGListView::Contain)
-        return;
-    int idx = qMax(qMin(index, model->count()-1), 0);
-
-    if (layoutScheduled)
-        layout();
-    qreal pos = isRightToLeft() ? -position() - size() : position();
-    FxListItemSG *item = visibleItem(idx);
-    qreal maxExtent;
-    if (orient == QSGListView::Vertical)
-        maxExtent = -q->maxYExtent();
-    else
-        maxExtent = isRightToLeft() ? q->minXExtent()-size(): -q->maxXExtent();
-    if (!item) {
-        int itemPos = positionAt(idx);
-        // save the currently visible items in case any of them end up visible again
-        QList<FxListItemSG*> oldVisible = visibleItems;
-        visibleItems.clear();
-        visiblePos = itemPos;
-        visibleIndex = idx;
-        setPosition(qMin(qreal(itemPos), maxExtent));
-        // now release the reference to all the old visible items.
-        for (int i = 0; i < oldVisible.count(); ++i)
-            releaseItem(oldVisible.at(i));
-        item = visibleItem(idx);
-    }
-    if (item) {
-        const qreal itemPos = item->position();
-        switch (mode) {
-        case QSGListView::Beginning:
-            pos = itemPos;
-            if (index < 0 && header)
-                pos -= header->size();
-            break;
-        case QSGListView::Center:
-            pos = itemPos - (size() - item->size())/2;
-            break;
-        case QSGListView::End:
-            pos = itemPos - size() + item->size();
-            if (index >= model->count() && footer)
-                pos += footer->size();
-            break;
-        case QSGListView::Visible:
-            if (itemPos > pos + size())
-                pos = itemPos - size() + item->size();
-            else if (item->endPosition() < pos)
-                pos = itemPos;
-            break;
-        case QSGListView::Contain:
-            if (item->endPosition() > pos + size())
-                pos = itemPos - size() + item->size();
-            if (itemPos < pos)
-                pos = itemPos;
-        }
-        pos = qMin(pos, maxExtent);
-        qreal minExtent;
-        if (orient == QSGListView::Vertical) {
-            minExtent = -q->minYExtent();
-        } else {
-            minExtent = isRightToLeft() ? q->maxXExtent()-size(): -q->minXExtent();
-        }
-        pos = qMax(pos, minExtent);
-        moveReason = QSGListViewPrivate::Other;
-        q->cancelFlick();
-        setPosition(pos);
-        if (highlight) {
-            if (autoHighlight) {
-                highlight->setPosition(currentItem->itemPosition());
-                highlight->setSize(currentItem->itemSize());
-            }
-            updateHighlight();
-        }
-    }
-    fixupPosition();
-}
-
-void QSGListView::positionViewAtIndex(int index, int mode)
-{
-    Q_D(QSGListView);
-    if (!d->isValid() || index < 0 || index >= d->model->count())
-        return;
-    d->positionViewAtIndex(index, mode);
-}
-
-void QSGListView::positionViewAtBeginning()
-{
-    Q_D(QSGListView);
-    if (!d->isValid())
-        return;
-    d->positionViewAtIndex(-1, Beginning);
-}
-
-void QSGListView::positionViewAtEnd()
-{
-    Q_D(QSGListView);
-    if (!d->isValid())
-        return;
-    d->positionViewAtIndex(d->model->count(), End);
-}
-
-int QSGListView::indexAt(qreal x, qreal y) const
-{
-    Q_D(const QSGListView);
-    for (int i = 0; i < d->visibleItems.count(); ++i) {
-        const FxListItemSG *listItem = d->visibleItems.at(i);
-        if(listItem->contains(x, y))
-            return listItem->index;
-    }
-
-    return -1;
-}
-
-void QSGListView::componentComplete()
-{
-    Q_D(QSGListView);
-    QSGFlickable::componentComplete();
-    updateSections();
-    d->updateHeader();
-    d->updateFooter();
-    if (d->isValid()) {
-        refill();
-        d->moveReason = QSGListViewPrivate::SetIndex;
-        if (d->currentIndex < 0 && !d->currentIndexCleared)
-            d->updateCurrent(0);
-        else
-            d->updateCurrent(d->currentIndex);
-        if (d->highlight && d->currentItem) {
-            if (d->autoHighlight)
-                d->highlight->setPosition(d->currentItem->position());
-            d->updateTrackedItem();
-        }
-        d->moveReason = QSGListViewPrivate::Other;
-        d->fixupPosition();
-    }
-}
-
 void QSGListView::updateSections()
 {
     Q_D(QSGListView);
@@ -2561,86 +1568,6 @@ void QSGListView::updateSections()
     }
 }
 
-void QSGListView::refill()
-{
-    Q_D(QSGListView);
-    if (d->isRightToLeft())
-        d->refill(-d->position()-d->size()+1, -d->position());
-    else
-        d->refill(d->position(), d->position()+d->size()-1);
-}
-
-void QSGListView::trackedPositionChanged()
-{
-    Q_D(QSGListView);
-    if (!d->trackedItem || !d->currentItem)
-        return;
-    if (d->moveReason == QSGListViewPrivate::SetIndex) {
-        qreal trackedPos = qCeil(d->trackedItem->position());
-        qreal trackedSize = d->trackedItem->size();
-        if (d->trackedItem != d->currentItem) {
-            trackedPos -= d->currentItem->sectionSize();
-            trackedSize += d->currentItem->sectionSize();
-        }
-        qreal viewPos;
-        qreal highlightStart;
-        qreal highlightEnd;
-        if (d->isRightToLeft()) {
-            viewPos = -d->position()-d->size();
-            highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
-            highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
-        } else {
-            viewPos = d->position();
-            highlightStart = d->highlightRangeStart;
-            highlightEnd = d->highlightRangeEnd;
-        }
-        qreal pos = viewPos;
-        if (d->haveHighlightRange) {
-            if (d->highlightRange == StrictlyEnforceRange) {
-                if (trackedPos > pos + highlightEnd - d->trackedItem->size())
-                    pos = trackedPos - highlightEnd + d->trackedItem->size();
-                if (trackedPos < pos + highlightStart)
-                    pos = trackedPos - highlightStart;
-            } else {
-                if (trackedPos < d->startPosition() + highlightStart) {
-                    pos = d->startPosition();
-                } else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + highlightEnd) {
-                    pos = d->endPosition() - d->size() + 1;
-                    if (pos < d->startPosition())
-                        pos = d->startPosition();
-                } else {
-                    if (trackedPos < viewPos + highlightStart) {
-                        pos = trackedPos - highlightStart;
-                    } else if (trackedPos > viewPos + highlightEnd - trackedSize) {
-                        pos = trackedPos - highlightEnd + trackedSize;
-                    }
-                }
-            }
-        } else {
-            if (trackedPos < viewPos && d->currentItem->position() < viewPos) {
-                pos = d->currentItem->position() < trackedPos ? trackedPos : d->currentItem->position();
-            } else if (d->trackedItem->endPosition() >= viewPos + d->size()
-                        && d->currentItem->endPosition() >= viewPos + d->size()) {
-                if (d->trackedItem->endPosition() <= d->currentItem->endPosition()) {
-                    pos = d->trackedItem->endPosition() - d->size() + 1;
-                     if (trackedSize > d->size())
-                        pos = trackedPos;
-                } else {
-                    pos = d->currentItem->endPosition() - d->size() + 1;
-                    if (d->currentItem->size() > d->size())
-                        pos = d->currentItem->position();
-                }
-            }
-        }
-        if (viewPos != pos) {
-            cancelFlick();
-            d->calcVelocity = true;
-            d->setPosition(pos);
-            d->calcVelocity = false;
-        }
-    }
-}
-
 void QSGListView::itemsInserted(int modelIndex, int count)
 {
     Q_D(QSGListView);
@@ -2667,9 +1594,9 @@ void QSGListView::itemsInserted(int modelIndex, int count)
                 // Insert before visible items
                 d->visibleIndex += count;
                 for (int i = 0; i < d->visibleItems.count(); ++i) {
-                    FxListItemSG *listItem = d->visibleItems.at(i);
-                    if (listItem->index != -1 && listItem->index >= modelIndex)
-                        listItem->index += count;
+                    FxViewItem *item = d->visibleItems.at(i);
+                    if (item->index != -1 && item->index >= modelIndex)
+                        item->index += count;
                 }
             }
             if (d->currentIndex >= modelIndex) {
@@ -2692,14 +1619,14 @@ void QSGListView::itemsInserted(int modelIndex, int count)
         pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
                                                 : d->visibleItems.last()->endPosition()+d->spacing+1;
     } else if (d->itemCount == 0 && d->header) {
-        pos = d->header->size();
+        pos = d->headerSize();
     }
 
     int initialPos = pos;
     int diff = 0;
     QList<FxListItemSG*> added;
     bool addedVisible = false;
-    FxListItemSG *firstVisible = d->firstVisibleItem();
+    FxViewItem *firstVisible = d->firstVisibleItem();
     if (firstVisible && pos < firstVisible->position()) {
         // Insert items before the visible item.
         int insertionIdx = index;
@@ -2710,7 +1637,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
                 d->scheduleLayout();
                 addedVisible = true;
             }
-            FxListItemSG *item = d->createItem(modelIndex + i);
+            FxListItemSG *item = static_cast<FxListItemSG*>(d->createItem(modelIndex + i));
             d->visibleItems.insert(insertionIdx, item);
             pos -= item->size() + d->spacing;
             item->setPosition(pos);
@@ -2720,7 +1647,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
             // If we didn't insert all our new items - anything
             // before the current index is not visible - remove it.
             while (insertionIdx--) {
-                FxListItemSG *item = d->visibleItems.takeFirst();
+                FxListItemSG *item = static_cast<FxListItemSG*>(d->visibleItems.takeFirst());
                 if (item->index != -1)
                     d->visibleIndex++;
                 d->releaseItem(item);
@@ -2728,7 +1655,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
         } else {
             // adjust pos of items before inserted items.
             for (int i = insertionIdx-1; i >= 0; i--) {
-                FxListItemSG *listItem = d->visibleItems.at(i);
+                FxListItemSG *listItem = static_cast<FxListItemSG*>(d->visibleItems.at(i));
                 listItem->setPosition(listItem->position() - (initialPos - pos));
             }
         }
@@ -2740,7 +1667,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
                 d->scheduleLayout();
                 addedVisible = true;
             }
-            FxListItemSG *item = d->createItem(modelIndex + i);
+            FxListItemSG *item = static_cast<FxListItemSG*>(d->createItem(modelIndex + i));
             d->visibleItems.insert(index, item);
             item->setPosition(pos);
             added.append(item);
@@ -2760,7 +1687,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
         d->currentIndex += count;
         if (d->currentItem) {
             d->currentItem->index = d->currentIndex;
-            d->currentItem->setPosition(d->currentItem->position() + diff);
+            static_cast<FxListItemSG *>(d->currentItem)->setPosition(static_cast<FxListItemSG *>(d->currentItem)->position() + diff);
         }
         emit currentIndexChanged();
     } else if (!d->itemCount && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
@@ -2768,11 +1695,11 @@ void QSGListView::itemsInserted(int modelIndex, int count)
     }
     // Update the indexes of the following visible items.
     for (; index < d->visibleItems.count(); ++index) {
-        FxListItemSG *listItem = d->visibleItems.at(index);
-        if (d->currentItem && listItem->item != d->currentItem->item)
-            listItem->setPosition(listItem->position() + diff);
-        if (listItem->index != -1)
-            listItem->index += count;
+        FxViewItem *item = d->visibleItems.at(index);
+        if (d->currentItem && item->item != d->currentItem->item)
+            static_cast<FxListItemSG*>(item)->setPosition(item->position() + diff);
+        if (item->index != -1)
+            item->index += count;
     }
     // everything is in order now - emit add() signal
     for (int j = 0; j < added.count(); ++j)
@@ -2792,13 +1719,13 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
     d->updateUnrequestedIndexes();
     d->itemCount -= count;
 
-    FxListItemSG *firstVisible = d->firstVisibleItem();
+    FxViewItem *firstVisible = d->firstVisibleItem();
     int preRemovedSize = 0;
     bool removedVisible = false;
     // Remove the items from the visible list, skipping anything already marked for removal
-    QList<FxListItemSG*>::Iterator it = d->visibleItems.begin();
+    QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
     while (it != d->visibleItems.end()) {
-        FxListItemSG *item = *it;
+        FxViewItem *item = *it;
         if (item->index == -1 || item->index < modelIndex) {
             // already removed, or before removed items
             ++it;
@@ -2829,7 +1756,7 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
     }
 
     if (firstVisible && d->visibleItems.first() != firstVisible)
-        d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + preRemovedSize);
+        static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + preRemovedSize);
 
     // fix current
     if (d->currentIndex >= modelIndex + count) {
@@ -2865,7 +1792,7 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
         d->timeline.clear();
         if (removedVisible && d->itemCount == 0) {
             d->visibleIndex = 0;
-            d->visiblePos = d->header ? d->header->size() : 0;
+            d->visiblePos = d->header ? d->headerSize() : 0;
             d->setPosition(0);
             d->updateHeader();
             d->updateFooter();
@@ -2880,25 +1807,6 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
     emit countChanged();
 }
 
-void QSGListView::destroyRemoved()
-{
-    Q_D(QSGListView);
-    for (QList<FxListItemSG*>::Iterator it = d->visibleItems.begin();
-            it != d->visibleItems.end();) {
-        FxListItemSG *listItem = *it;
-        if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
-            d->releaseItem(listItem);
-            it = d->visibleItems.erase(it);
-        } else {
-            ++it;
-        }
-    }
-
-    // Correct the positioning of the items
-    d->updateSections();
-    d->layout();
-}
-
 void QSGListView::itemsMoved(int from, int to, int count)
 {
     Q_D(QSGListView);
@@ -2907,19 +1815,19 @@ void QSGListView::itemsMoved(int from, int to, int count)
     d->updateUnrequestedIndexes();
 
     if (d->visibleItems.isEmpty()) {
-        refill();
+        d->refill();
         return;
     }
 
     d->moveReason = QSGListViewPrivate::Other;
-    FxListItemSG *firstVisible = d->firstVisibleItem();
+    FxViewItem *firstVisible = d->firstVisibleItem();
     qreal firstItemPos = firstVisible->position();
-    QHash<int,FxListItemSG*> moved;
+    QHash<int,FxViewItem*> moved;
     int moveBy = 0;
 
-    QList<FxListItemSG*>::Iterator it = d->visibleItems.begin();
+    QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
     while (it != d->visibleItems.end()) {
-        FxListItemSG *item = *it;
+        FxViewItem *item = *it;
         if (item->index >= from && item->index < from + count) {
             // take the items that are moving
             item->index += (to-from);
@@ -2939,10 +1847,10 @@ void QSGListView::itemsMoved(int from, int to, int count)
     int endIndex = d->visibleIndex;
     it = d->visibleItems.begin();
     while (it != d->visibleItems.end()) {
-        FxListItemSG *item = *it;
+        FxViewItem *item = *it;
         if (remaining && item->index >= to && item->index < to + count) {
             // place items in the target position, reusing any existing items
-            FxListItemSG *movedItem = moved.take(item->index);
+            FxViewItem *movedItem = moved.take(item->index);
             if (!movedItem)
                 movedItem = d->createItem(item->index);
             if (item->index <= firstVisible->index)
@@ -2964,7 +1872,7 @@ void QSGListView::itemsMoved(int from, int to, int count)
 
     // If we have moved items to the end of the visible items
     // then add any existing moved items that we have
-    while (FxListItemSG *item = moved.take(endIndex+1)) {
+    while (FxViewItem *item = moved.take(endIndex+1)) {
         d->visibleItems.append(item);
         ++endIndex;
     }
@@ -2990,70 +1898,19 @@ void QSGListView::itemsMoved(int from, int to, int count)
     // Whatever moved items remain are no longer visible items.
     while (moved.count()) {
         int idx = moved.begin().key();
-        FxListItemSG *item = moved.take(idx);
+        FxViewItem *item = moved.take(idx);
         if (d->currentItem && item->item == d->currentItem->item)
-            item->setPosition(d->positionAt(idx));
+            static_cast<FxListItemSG*>(item)->setPosition(d->positionAt(idx));
         d->releaseItem(item);
     }
 
     // Ensure we don't cause an ugly list scroll.
-    d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + moveBy);
-
-    d->updateSections();
-    d->layout();
-}
+    static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + moveBy);
 
-void QSGListView::itemsChanged(int, int)
-{
-    Q_D(QSGListView);
     d->updateSections();
     d->layout();
 }
 
-void QSGListView::modelReset()
-{
-    Q_D(QSGListView);
-    d->moveReason = QSGListViewPrivate::SetIndex;
-    d->regenerate();
-    if (d->highlight && d->currentItem) {
-        if (d->autoHighlight)
-            d->highlight->setPosition(d->currentItem->position());
-        d->updateTrackedItem();
-    }
-    d->moveReason = QSGListViewPrivate::Other;
-    emit countChanged();
-}
-
-void QSGListView::createdItem(int index, QSGItem *item)
-{
-    Q_D(QSGListView);
-    if (d->requestedIndex != index) {
-        item->setParentItem(contentItem());
-        d->unrequestedItems.insert(item, index);
-        if (d->orient == QSGListView::Vertical) {
-            item->setY(d->positionAt(index));
-        } else {
-            if (d->isRightToLeft())
-                item->setX(-d->positionAt(index)-item->width());
-            else
-                item->setX(d->positionAt(index));
-        }
-    }
-}
-
-void QSGListView::destroyingItem(QSGItem *item)
-{
-    Q_D(QSGListView);
-    d->unrequestedItems.remove(item);
-}
-
-void QSGListView::animStopped()
-{
-    Q_D(QSGListView);
-    d->bufferMode = QSGListViewPrivate::NoBuffer;
-    if (d->haveHighlightRange && d->highlightRange == QSGListView::StrictlyEnforceRange)
-        d->updateHighlight();
-}
 
 QSGListViewAttached *QSGListView::qmlAttachedProperties(QObject *obj)
 {
index 8560225..e45e16b 100644 (file)
@@ -43,7 +43,7 @@
 #ifndef QSGLISTVIEW_P_H
 #define QSGLISTVIEW_P_H
 
-#include "qsgflickable_p.h"
+#include "qsgitemview_p.h"
 
 #include <private/qdeclarativeguard_p.h>
 
@@ -90,84 +90,33 @@ private:
 class QSGVisualModel;
 class QSGListViewAttached;
 class QSGListViewPrivate;
-class Q_AUTOTEST_EXPORT QSGListView : public QSGFlickable
+class Q_AUTOTEST_EXPORT QSGListView : public QSGItemView
 {
     Q_OBJECT
     Q_DECLARE_PRIVATE(QSGListView)
 
-    Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
-    Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
-    Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
-    Q_PROPERTY(QSGItem *currentItem READ currentItem NOTIFY currentIndexChanged)
-    Q_PROPERTY(int count READ count NOTIFY countChanged)
-
-    Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
-    Q_PROPERTY(QSGItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
-    Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
+    // XXX deprecate these two properties (only duration should be necessary)
     Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged)
-    Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
     Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged)
-    Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged)
 
-    Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
-    Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
-    Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+    Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged)
 
     Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
     Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
-    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
-    Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
-    Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
-    Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+
     Q_PROPERTY(QSGViewSection *section READ sectionCriteria CONSTANT)
     Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
 
     Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
 
-    Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
-    Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
-
-    Q_ENUMS(HighlightRangeMode)
     Q_ENUMS(Orientation)
     Q_ENUMS(SnapMode)
-    Q_ENUMS(PositionMode)
     Q_CLASSINFO("DefaultProperty", "data")
 
 public:
     QSGListView(QSGItem *parent=0);
     ~QSGListView();
 
-    QVariant model() const;
-    void setModel(const QVariant &);
-
-    QDeclarativeComponent *delegate() const;
-    void setDelegate(QDeclarativeComponent *);
-
-    int currentIndex() const;
-    void setCurrentIndex(int idx);
-
-    QSGItem *currentItem();
-    QSGItem *highlightItem();
-    int count() const;
-
-    QDeclarativeComponent *highlight() const;
-    void setHighlight(QDeclarativeComponent *highlight);
-
-    bool highlightFollowsCurrentItem() const;
-    void setHighlightFollowsCurrentItem(bool);
-
-    enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
-    HighlightRangeMode highlightRangeMode() const;
-    void setHighlightRangeMode(HighlightRangeMode mode);
-
-    qreal preferredHighlightBegin() const;
-    void setPreferredHighlightBegin(qreal);
-    void resetPreferredHighlightBegin();
-
-    qreal preferredHighlightEnd() const;
-    void setPreferredHighlightEnd(qreal);
-    void resetPreferredHighlightEnd();
-
     qreal spacing() const;
     void setSpacing(qreal spacing);
 
@@ -175,115 +124,62 @@ public:
     Orientation orientation() const;
     void setOrientation(Orientation);
 
-    Qt::LayoutDirection layoutDirection() const;
-    void setLayoutDirection(Qt::LayoutDirection);
-    Qt::LayoutDirection effectiveLayoutDirection() const;
-
-    bool isWrapEnabled() const;
-    void setWrapEnabled(bool);
-
-    int cacheBuffer() const;
-    void setCacheBuffer(int);
-
     QSGViewSection *sectionCriteria();
     QString currentSection() const;
 
+    virtual void setHighlightFollowsCurrentItem(bool);
+
     qreal highlightMoveSpeed() const;
     void setHighlightMoveSpeed(qreal);
 
-    int highlightMoveDuration() const;
-    void setHighlightMoveDuration(int);
-
     qreal highlightResizeSpeed() const;
     void setHighlightResizeSpeed(qreal);
 
     int highlightResizeDuration() const;
     void setHighlightResizeDuration(int);
 
+    virtual void setHighlightMoveDuration(int);
+
     enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
     SnapMode snapMode() const;
     void setSnapMode(SnapMode mode);
 
-    QDeclarativeComponent *footer() const;
-    void setFooter(QDeclarativeComponent *);
-
-    QDeclarativeComponent *header() const;
-    void setHeader(QDeclarativeComponent *);
-
-    virtual void setContentX(qreal pos);
-    virtual void setContentY(qreal pos);
-
     static QSGListViewAttached *qmlAttachedProperties(QObject *);
 
-    enum PositionMode { Beginning, Center, End, Visible, Contain };
-
-    Q_INVOKABLE void positionViewAtIndex(int index, int mode);
-    Q_INVOKABLE int indexAt(qreal x, qreal y) const;
-    Q_INVOKABLE void positionViewAtBeginning();
-    Q_INVOKABLE void positionViewAtEnd();
-
 public Q_SLOTS:
     void incrementCurrentIndex();
     void decrementCurrentIndex();
 
 Q_SIGNALS:
-    void countChanged();
     void spacingChanged();
     void orientationChanged();
-    void layoutDirectionChanged();
-    void effectiveLayoutDirectionChanged();
-    void currentIndexChanged();
     void currentSectionChanged();
     void highlightMoveSpeedChanged();
-    void highlightMoveDurationChanged();
     void highlightResizeSpeedChanged();
     void highlightResizeDurationChanged();
-    void highlightChanged();
-    void highlightItemChanged();
-    void modelChanged();
-    void delegateChanged();
-    void highlightFollowsCurrentItemChanged();
-    void preferredHighlightBeginChanged();
-    void preferredHighlightEndChanged();
-    void highlightRangeModeChanged();
-    void keyNavigationWrapsChanged();
-    void cacheBufferChanged();
     void snapModeChanged();
-    void headerChanged();
-    void footerChanged();
 
 protected:
-    virtual void updatePolish();
     virtual void viewportMoved();
-    virtual qreal minYExtent() const;
-    virtual qreal maxYExtent() const;
-    virtual qreal minXExtent() const;
-    virtual qreal maxXExtent() const;
     virtual void keyPressEvent(QKeyEvent *);
     virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry);
-    virtual void componentComplete();
 
-private Q_SLOTS:
+protected Q_SLOTS:
     void updateSections();
-    void refill();
-    void trackedPositionChanged();
+
+private Q_SLOTS:
     void itemsInserted(int index, int count);
     void itemsRemoved(int index, int count);
     void itemsMoved(int from, int to, int count);
-    void itemsChanged(int index, int count);
-    void modelReset();
-    void destroyRemoved();
-    void createdItem(int index, QSGItem *item);
-    void destroyingItem(QSGItem *item);
-    void animStopped();
 };
 
-class QSGListViewAttached : public QObject
+class QSGListViewAttached : public QSGItemViewAttached
 {
     Q_OBJECT
+
 public:
     QSGListViewAttached(QObject *parent)
-        : QObject(parent), m_view(0), m_isCurrent(false), m_delayRemove(false) {}
+        : QSGItemViewAttached(parent), m_view(0) {}
     ~QSGListViewAttached() {}
 
     Q_PROPERTY(QSGListView *view READ view NOTIFY viewChanged)
@@ -295,71 +191,11 @@ public:
         }
     }
 
-    Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
-    bool isCurrentItem() const { return m_isCurrent; }
-    void setIsCurrentItem(bool c) {
-        if (m_isCurrent != c) {
-            m_isCurrent = c;
-            emit currentItemChanged();
-        }
-    }
-
-    Q_PROPERTY(QString previousSection READ prevSection NOTIFY prevSectionChanged)
-    QString prevSection() const { return m_prevSection; }
-    void setPrevSection(const QString &sect) {
-        if (m_prevSection != sect) {
-            m_prevSection = sect;
-            emit prevSectionChanged();
-        }
-    }
-
-    Q_PROPERTY(QString nextSection READ nextSection NOTIFY nextSectionChanged)
-    QString nextSection() const { return m_nextSection; }
-    void setNextSection(const QString &sect) {
-        if (m_nextSection != sect) {
-            m_nextSection = sect;
-            emit nextSectionChanged();
-        }
-    }
-
-    Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
-    QString section() const { return m_section; }
-    void setSection(const QString &sect) {
-        if (m_section != sect) {
-            m_section = sect;
-            emit sectionChanged();
-        }
-    }
-
-    Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
-    bool delayRemove() const { return m_delayRemove; }
-    void setDelayRemove(bool delay) {
-        if (m_delayRemove != delay) {
-            m_delayRemove = delay;
-            emit delayRemoveChanged();
-        }
-    }
-
-    void emitAdd() { emit add(); }
-    void emitRemove() { emit remove(); }
-
 Q_SIGNALS:
-    void currentItemChanged();
-    void sectionChanged();
-    void prevSectionChanged();
-    void nextSectionChanged();
-    void delayRemoveChanged();
-    void add();
-    void remove();
     void viewChanged();
 
 public:
     QDeclarativeGuard<QSGListView> m_view;
-    mutable QString m_section;
-    QString m_prevSection;
-    QString m_nextSection;
-    bool m_isCurrent : 1;
-    bool m_delayRemove : 1;
 };
 
 
index ab202e0..5310632 100644 (file)
@@ -1236,7 +1236,7 @@ void tst_QSGGridView::positionViewAtIndex()
     // Position on an item that would leave empty space if positioned at the top
     gridview->positionViewAtIndex(31, QSGGridView::Beginning);
     QTRY_COMPARE(gridview->indexAt(120, 630), 31);
-    QTRY_COMPARE(gridview->contentY(), 520.);
+    QTRY_COMPARE(gridview->contentY(), 521.);   // 520 then +1 so bottom edge of last item is visible
 
     // Confirm items positioned correctly
     itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
@@ -1354,7 +1354,7 @@ void tst_QSGGridView::positionViewAtIndex()
 
     // positionViewAtEnd
     gridview->positionViewAtEnd();
-    QTRY_COMPARE(gridview->contentX(), 430.);
+    QTRY_COMPARE(gridview->contentX(), 400.);   // 8*80 - 240   (8 columns)
 
     gridview->setContentX(80);
     canvas->rootObject()->setProperty("showFooter", true);