Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / quick / items / qquicklistview.cpp
index 960565a..21ff2c7 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtDeclarative module of the Qt Toolkit.
 **
@@ -35,6 +34,7 @@
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
@@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE
 #define QML_FLICK_SNAPONETHRESHOLD 30
 #endif
 
+//#define DEBUG_DELEGATE_LIFECYCLE
+
 class FxListItemSG;
 
 class QQuickListViewPrivate : public QQuickItemViewPrivate
@@ -93,17 +95,16 @@ public:
     virtual void initializeViewItem(FxViewItem *item);
     virtual void releaseItem(FxViewItem *item);
     virtual void repositionPackageItemAt(QQuickItem *item, int index);
-    virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem);
-    virtual void resetFirstItemPosition();
-    virtual void moveItemBy(FxViewItem *item, qreal forwards, qreal backwards);
+    virtual void resetFirstItemPosition(qreal pos = 0.0);
+    virtual void adjustFirstItem(qreal forwards, qreal backwards, int);
 
     virtual void createHighlight();
     virtual void updateHighlight();
     virtual void resetHighlightPosition();
 
     virtual void setPosition(qreal pos);
-    virtual void layoutVisibleItems();
-    bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, FxViewItem *firstVisible, InsertionsResult *);
+    virtual void layoutVisibleItems(int fromModelIndex = 0);
+    virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems);
 
     virtual void updateSections();
     QQuickItem *getSectionItem(const QString &section);
@@ -602,7 +603,9 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
     FxListItemSG *item = 0;
     qreal pos = itemEnd;
     while (modelIndex < model->count() && pos <= fillTo) {
-//        qDebug() << "refill: append item" << modelIndex << "pos" << pos;
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+        qDebug() << "refill: append item" << modelIndex << "pos" << pos;
+#endif
         if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, doBuffer))))
             break;
         item->setPosition(pos);
@@ -612,8 +615,14 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
         ++modelIndex;
         changed = true;
     }
+
+    if (doBuffer && requestedIndex != -1) // already waiting for an item
+        return changed;
+
     while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
-//        qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+        qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+#endif
         if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, doBuffer))))
             break;
         --visibleIndex;
@@ -642,8 +651,9 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
         if (item->attached->delayRemove())
             break;
         if (item->size() > 0) {
-//            qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
-
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+            qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
+#endif
             // remove this item and all zero-sized items before it
             while (item) {
                 if (item->index != -1)
@@ -663,7 +673,9 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
     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();
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+        qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position();
+#endif
         visibleItems.removeLast();
         releaseItem(item);
         changed = true;
@@ -689,7 +701,7 @@ void QQuickListViewPrivate::visibleItemsChanged()
     updateUnrequestedPositions();
 }
 
-void QQuickListViewPrivate::layoutVisibleItems()
+void QQuickListViewPrivate::layoutVisibleItems(int fromModelIndex)
 {
     if (!visibleItems.isEmpty()) {
         const qreal from = isContentFlowReversed() ? -position() - size() : position();
@@ -702,8 +714,10 @@ void QQuickListViewPrivate::layoutVisibleItems()
         firstItem->item->setVisible(firstItem->endPosition() >= from && firstItem->position() <= to);
         for (int i=1; i < visibleItems.count(); ++i) {
             FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.at(i));
-            item->setPosition(pos);
-            item->item->setVisible(item->endPosition() >= from && item->position() <= to);
+            if (item->index >= fromModelIndex) {
+                item->setPosition(pos);
+                item->item->setVisible(item->endPosition() >= from && item->position() <= to);
+            }
             pos += item->size() + spacing;
             sum += item->size();
             fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
@@ -734,23 +748,18 @@ void QQuickListViewPrivate::repositionPackageItemAt(QQuickItem *item, int index)
     }
 }
 
-void QQuickListViewPrivate::resetItemPosition(FxViewItem *item, FxViewItem *toItem)
-{
-    if (item == toItem)
-        return;
-    static_cast<FxListItemSG*>(item)->setPosition(toItem->position());
-}
-
-void QQuickListViewPrivate::resetFirstItemPosition()
+void QQuickListViewPrivate::resetFirstItemPosition(qreal pos)
 {
     FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.first());
-    item->setPosition(0);
+    item->setPosition(pos);
 }
 
-void QQuickListViewPrivate::moveItemBy(FxViewItem *item, qreal forwards, qreal backwards)
+void QQuickListViewPrivate::adjustFirstItem(qreal forwards, qreal backwards, int)
 {
+    if (!visibleItems.count())
+        return;
     qreal diff = forwards - backwards;
-    static_cast<FxListItemSG*>(item)->setPosition(item->position() + diff);
+    static_cast<FxListItemSG*>(visibleItems.first())->setPosition(visibleItems.first()->position() + diff);
 }
 
 void QQuickListViewPrivate::createHighlight()
@@ -1826,7 +1835,7 @@ void QQuickListView::setSpacing(qreal spacing)
     if (spacing != d->spacing) {
         d->spacing = spacing;
         d->forceLayout = true;
-        d->layout();
+        polish();
         emit spacingChanged();
     }
 }
@@ -2192,14 +2201,6 @@ void QQuickListView::viewportMoved()
         return;
     d->inViewportMoved = true;
 
-    // Set visibility of items to eliminate cost of items outside the visible area.
-    qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
-    qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
-    for (int i = 0; i < d->visibleItems.count(); ++i) {
-        FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i));
-        item->item->setVisible(item->endPosition() >= from && item->position() <= to);
-    }
-
     if (yflick())
         d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
     else if (d->isRightToLeft())
@@ -2208,6 +2209,15 @@ void QQuickListView::viewportMoved()
         d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
 
     d->refill();
+
+    // Set visibility of items to eliminate cost of items outside the visible area.
+    qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
+    qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
+    for (int i = 0; i < d->visibleItems.count(); ++i) {
+        FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i));
+        item->item->setVisible(item->endPosition() >= from && item->position() <= to);
+    }
+
     if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
         d->moveReason = QQuickListViewPrivate::Mouse;
     if (d->moveReason != QQuickListViewPrivate::SetIndex) {
@@ -2369,12 +2379,12 @@ void QQuickListView::updateSections()
         d->updateSections();
         if (d->itemCount) {
             d->forceLayout = true;
-            d->layout();
+            polish();
         }
     }
 }
 
-bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, FxViewItem *firstVisible, InsertionsResult *insertResult)
+bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, ChangeResult *insertResult, QList<FxViewItem *> *addedItems)
 {
     int modelIndex = change.index;
     int count = change.count;
@@ -2414,8 +2424,8 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
                                                 : visibleItems.last()->endPosition()+spacing;
     }
 
-    int prevAddedCount = insertResult->addedItems.count();
-    if (firstVisible && pos < firstVisible->position()) {
+    int prevVisibleCount = visibleItems.count();
+    if (insertResult->visiblePos.isValid() && pos < insertResult->visiblePos) {
         // Insert items before the visible item.
         int insertionIdx = index;
         int i = 0;
@@ -2424,26 +2434,24 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
         for (i = count-1; i >= 0; --i) {
             if (pos > from && insertionIdx < visibleIndex) {
                 // item won't be visible, just note the size for repositioning
-                insertResult->sizeAddedBeforeVisible += averageSize + spacing;
+                insertResult->sizeChangesBeforeVisiblePos += averageSize + spacing;
                 pos -= averageSize + spacing;
             } else {
                 // item is before first visible e.g. in cache buffer
                 FxViewItem *item = 0;
-                if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
-                    if (item->index > modelIndex + i)
-                        insertResult->movedBackwards.append(item);
+                if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
                     item->index = modelIndex + i;
-                }
                 if (!item)
                     item = createItem(modelIndex + i);
                 if (!item)
                     return false;
 
                 visibleItems.insert(insertionIdx, item);
-                if (!change.isMove()) {
-                    insertResult->addedItems.append(item);
-                    insertResult->sizeAddedBeforeVisible += item->size();
-                }
+                if (insertionIdx == 0)
+                    insertResult->changedFirstItem = true;
+                if (!change.isMove())
+                    addedItems->append(item);
+                insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing;
                 pos -= item->size() + spacing;
             }
             index++;
@@ -2453,19 +2461,19 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
         int to = buffer+tempPos+size();
         for (i = 0; i < count && pos <= to; ++i) {
             FxViewItem *item = 0;
-            if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
-                if (item->index > modelIndex + i)
-                    insertResult->movedBackwards.append(item);
+            if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
                 item->index = modelIndex + i;
-            }
             if (!item)
                 item = createItem(modelIndex + i);
             if (!item)
                 return false;
 
             visibleItems.insert(index, item);
+            if (index == 0)
+                insertResult->changedFirstItem = true;
             if (!change.isMove())
-                insertResult->addedItems.append(item);
+                addedItems->append(item);
+            insertResult->sizeChangesAfterVisiblePos += item->size() + spacing;
             pos += item->size() + spacing;
             ++index;
         }
@@ -2479,7 +2487,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
 
     updateVisibleIndex();
 
-    return insertResult->addedItems.count() > prevAddedCount;
+    return visibleItems.count() > prevVisibleCount;
 }
 
 
@@ -2550,6 +2558,19 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
     \bold Note: methods should only be called after the Component has completed.
 */
 
+/*!
+    \qmlmethod Item QtQuick2::ListView::itemAt(int x, int y)
+
+    Returns the visible item containing the point \a x, \a y in content
+    coordinates.  If there is no item at the point specified, or the item is
+    not visible null is returned.
+
+    If the item is outside the visible area, null is returned, regardless of
+    whether an item will exist at that point when scrolled into view.
+
+    \bold Note: methods should only be called after the Component has completed.
+*/
+
 QQuickListViewAttached *QQuickListView::qmlAttachedProperties(QObject *obj)
 {
     return new QQuickListViewAttached(obj);