populate transition for positioners
authorBea Lam <bea.lam@nokia.com>
Tue, 17 Apr 2012 01:35:14 +0000 (11:35 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 1 May 2012 00:53:21 +0000 (02:53 +0200)
Fix positioners to apply a "populate" transition for initially added
items. This is consistent with ListView and GridView and also fixes the
behaviour from QtQuick 1.x where the positioners were instead running
the "move" transition for initially added items.

Change-Id: Ib43f1141ce3e7379df085c178b684f89b8567403
Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
examples/quick/positioners/positioners-transitions.qml
examples/quick/positioners/positioners.qml
src/quick/items/qquickitemviewtransition.cpp
src/quick/items/qquickpositioners.cpp
src/quick/items/qquickpositioners_p.h
tests/auto/quick/qquickpositioners/data/grid-animated.qml
tests/auto/quick/qquickpositioners/data/horizontal-animated.qml
tests/auto/quick/qquickpositioners/data/transitions.qml
tests/auto/quick/qquickpositioners/data/vertical-animated.qml
tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp

index e573c94..64d5c52 100644 (file)
@@ -44,6 +44,7 @@ Rectangle {
     id: page
     width: 320; height: 480
     property real effectiveOpacity: 1.0
+
     Timer {
         interval: 2000
         running: true
@@ -52,14 +53,17 @@ Rectangle {
     }
 
     Column {
-        id: layout1
         y: 0
-        move: Transition {
-            NumberAnimation { properties: "y"; easing.type: Easing.OutBounce }
+
+        populate: Transition {
+            NumberAnimation { properties: "x,y"; from: 200; duration: 1500; easing.type: Easing.OutBounce }
         }
         add: Transition {
             NumberAnimation { properties: "y"; easing.type: Easing.OutQuad }
         }
+        move: Transition {
+            NumberAnimation { properties: "y"; easing.type: Easing.OutBounce }
+        }
 
         Rectangle { color: "red"; width: 100; height: 50; border.color: "black"; radius: 15 }
 
@@ -92,14 +96,17 @@ Rectangle {
     }
 
     Row {
-        id: layout2
         y: 320
-        move: Transition {
-            NumberAnimation { properties: "x"; easing.type: Easing.OutBounce }
+
+        populate: Transition {
+            NumberAnimation { properties: "x,y"; from: 200; duration: 1500; easing.type: Easing.OutBounce }
         }
         add: Transition {
             NumberAnimation { properties: "x"; easing.type: Easing.OutQuad }
         }
+        move: Transition {
+            NumberAnimation { properties: "x"; easing.type: Easing.OutBounce }
+        }
 
         Rectangle { color: "red"; width: 50; height: 100; border.color: "black"; radius: 15 }
 
@@ -135,13 +142,16 @@ Rectangle {
         x: 120; y: 0
         columns: 3
 
-        move: Transition {
-            NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce }
+        populate: Transition {
+            NumberAnimation { properties: "x,y"; from: 200; duration: 1500; easing.type: Easing.OutBounce }
         }
-
         add: Transition {
             NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce }
         }
+        move: Transition {
+            NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce }
+        }
+
 
         Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 }
 
@@ -188,7 +198,6 @@ Rectangle {
     }
 
     Flow {
-        id: layout4
         x: 120; y: 160; width: 150
 
         //! [move]
@@ -203,6 +212,12 @@ Rectangle {
         }
         //! [add]
 
+        //! [populate]
+        populate: Transition {
+            NumberAnimation { properties: "x,y"; from: 200; duration: 1500; easing.type: Easing.OutBounce }
+        }
+        //! [populate]
+
         Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 }
 
         Rectangle {
index 34caea3..859d6bd 100644 (file)
@@ -50,15 +50,20 @@ import "../../shared" as Examples
     This is a collection of small QML examples relating to positioners. Each example is
     a small QML file emphasizing a particular element or feature.
 
-    Transitions shows animated transistions when showing or hiding items in a positioner.
+    Transitions shows animated transitions when showing or hiding items in a positioner.
     It consists of a scene populated with items in a variety of positioners: Column, Row, Grid and Flow.
     Each positioner has animations described as Transitions.
+
     \snippet examples/quick/positioners/positioners-transitions.qml move
-    The move transition specifies how items inside the positioner will animate when they are displaced by items appearing or disappearing.
+    The move transition specifies how items inside a positioner will animate when they are displaced by the appearance or disappearance of other items.
+
     \snippet examples/quick/positioners/positioners-transitions.qml add
-    The add transition specifies how items will appear when they are added to the positioner.
+    The add transition specifies how items will appear when they are added to a positioner.
+
+    \snippet examples/quick/positioners/positioners-transitions.qml populate
+    The populate transition specifies how items will appear when their parent positioner is first created.
 
-    Attached Properties show using the attached property to determine where in a positioner an item is.
+    Attached Properties shows how the Positioner attached property can be used to determine where an item is within a positioner.
     \snippet examples/quick/positioners/positioners-attachedproperties.qml 0
 */
 
index c680945..c1f1e51 100644 (file)
@@ -577,8 +577,8 @@ QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent)
     operations:
 
     \list
-    \li \c populate - the transition to run when a view is created, or when the model changes
-    \li \c add - the transition to apply to items that are added to the view
+    \li \c populate - the transition to apply to the items created initially for the view, or when the model changes
+    \li \c add - the transition to apply to items that are added to the view after it has been created
     \li \c remove - the transition to apply to items that are removed from the view
     \li \c move - the transition to apply to items that are moved within the view (i.e. as a result
        of a move operation in the model)
@@ -593,7 +593,9 @@ QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent)
     items rather than data models, the following properties are used instead:
 
     \list
-    \li \c add - the transition to apply to items that are created for the positioner, added to
+    \li \c populate - the transition to apply to items that have been added to the positioner at the
+       time of its creation
+    \li \c add - the transition to apply to items that are added to
        or reparented to the positioner, or items that have become \l {Item::}{visible}
     \li \c move - the transition to apply to items that have moved within the positioner, including
        when they are displaced due to the addition or removal of other items, or when items are otherwise
index 97a74c6..37c3ef1 100644 (file)
@@ -195,6 +195,23 @@ void QQuickBasePositioner::setSpacing(qreal s)
     emit spacingChanged();
 }
 
+QQuickTransition *QQuickBasePositioner::populate() const
+{
+    Q_D(const QQuickBasePositioner);
+    return d->transitioner ? d->transitioner->populateTransition : 0;
+}
+
+void QQuickBasePositioner::setPopulate(QQuickTransition *transition)
+{
+    Q_D(QQuickBasePositioner);
+    if (!d->transitioner)
+        d->transitioner = new QQuickItemViewTransitioner;
+    if (d->transitioner->populateTransition != transition) {
+        d->transitioner->populateTransition = transition;
+        emit populateChanged();
+    }
+}
+
 QQuickTransition *QQuickBasePositioner::move() const
 {
     Q_D(const QQuickBasePositioner);
@@ -233,9 +250,14 @@ void QQuickBasePositioner::setAdd(QQuickTransition *add)
 
 void QQuickBasePositioner::componentComplete()
 {
+    Q_D(QQuickBasePositioner);
     QQuickItem::componentComplete();
+    if (d->transitioner)
+        d->transitioner->setPopulateTransitionEnabled(true);
     positionedItems.reserve(childItems().count());
     prePositioning();
+    if (d->transitioner)
+        d->transitioner->setPopulateTransitionEnabled(false);
 }
 
 void QQuickBasePositioner::itemChange(ItemChange change, const ItemChangeData &value)
@@ -301,7 +323,10 @@ void QQuickBasePositioner::prePositioning()
                     if (addedIndex < 0)
                         addedIndex = posItem.index;
                     PositionedItem *theItem = &positionedItems[positionedItems.count()-1];
-                    theItem->transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::AddTransition, true);
+                    if (d->transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true))
+                        theItem->transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::PopulateTransition, true);
+                    else if (!d->transitioner->populateTransitionEnabled())
+                        theItem->transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::AddTransition, true);
                 }
             }
         } else {
@@ -354,7 +379,7 @@ void QQuickBasePositioner::prePositioning()
     }
 
     if (d->transitioner) {
-        QRectF viewBounds;
+        QRectF viewBounds(QPointF(), contentSize);
         for (int i=0; i<positionedItems.count(); i++)
             positionedItems[i].prepareTransition(d->transitioner, viewBounds);
         for (int i=0; i<positionedItems.count(); i++)
@@ -602,13 +627,27 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem)
     \sa Row, Grid, Flow, Positioner, {qml/positioners}{Positioners example}
 */
 /*!
+    \qmlproperty Transition QtQuick2::Column::populate
+
+    This property holds the transition to be run for items that are part of
+    this positioner at the time of its creation. The transition is run when the positioner
+    is first created.
+
+    The transition can use the \l ViewTransition property to access more details about
+    the item that is being added. See the \l ViewTransition documentation for more details
+    and examples on using these transitions.
+
+    \sa add, ViewTransition, {declarative/positioners}{Positioners example}
+*/
+/*!
     \qmlproperty Transition QtQuick2::Column::add
 
     This property holds the transition to be run for items that are added to this
     positioner. For a positioner, this applies to:
 
     \list
-    \li Items that are created or reparented as a child of the positioner
+    \li Items that are created or reparented as a child of the positioner after the
+        positioner has been created
     \li Child items that change their \l visible property from false to true, and thus
        are now visible
     \endlist
@@ -617,7 +656,10 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem)
     the item that is being added. See the \l ViewTransition documentation for more details
     and examples on using these transitions.
 
-    \sa move, ViewTransition, {declarative/positioners}{Positioners example}
+    \note This transition is not applied to the items that already part of the positioner
+    at the time of its creation. In this case, the \l populate transition is applied instead.
+
+    \sa populate, ViewTransition, {declarative/positioners}{Positioners example}
 */
 /*!
     \qmlproperty Transition QtQuick2::Column::move
@@ -635,9 +677,12 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem)
     the item that is being moved. Note, however, that for this move transition, the
     ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when
     this transition is triggered by the addition of other items in the positioner; in other
-    cases, these lists will be empty.
+    cases, these lists will be empty.  See the \l ViewTransition documentation for more details
+    and examples on using these transitions.
 
-    See the \l ViewTransition documentation for more details and examples on using these transitions.
+    \note In QtQuick 1, this transition was applied to all items that were part of the
+    positioner at the time of its creation. From QtQuick 2 onwards, positioners apply the
+    \l populate transition to these items instead.
 
     \sa add, ViewTransition, {qml/positioners}{Positioners example}
 */
@@ -735,13 +780,27 @@ void QQuickColumn::reportConflictingAnchors()
     \sa Column, Grid, Flow, Positioner, {qml/positioners}{Positioners example}
 */
 /*!
+    \qmlproperty Transition QtQuick2::Row::populate
+
+    This property holds the transition to be run for items that are part of
+    this positioner at the time of its creation. The transition is run when the positioner
+    is first created.
+
+    The transition can use the \l ViewTransition property to access more details about
+    the item that is being added. See the \l ViewTransition documentation for more details
+    and examples on using these transitions.
+
+    \sa add, ViewTransition, {declarative/positioners}{Positioners example}
+*/
+/*!
     \qmlproperty Transition QtQuick2::Row::add
 
     This property holds the transition to be run for items that are added to this
     positioner. For a positioner, this applies to:
 
     \list
-    \li Items that are created or reparented as a child of the positioner
+    \li Items that are created or reparented as a child of the positioner after the
+        positioner has been created
     \li Child items that change their \l visible property from false to true, and thus
        are now visible
     \endlist
@@ -750,7 +809,10 @@ void QQuickColumn::reportConflictingAnchors()
     the item that is being added. See the \l ViewTransition documentation for more details
     and examples on using these transitions.
 
-    \sa move, ViewTransition, {declarative/positioners}{Positioners example}
+    \note This transition is not applied to the items that already part of the positioner
+    at the time of its creation. In this case, the \l populate transition is applied instead.
+
+    \sa populate, ViewTransition, {declarative/positioners}{Positioners example}
 */
 /*!
     \qmlproperty Transition QtQuick2::Row::move
@@ -768,9 +830,12 @@ void QQuickColumn::reportConflictingAnchors()
     the item that is being moved. Note, however, that for this move transition, the
     ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when
     this transition is triggered by the addition of other items in the positioner; in other
-    cases, these lists will be empty.
+    cases, these lists will be empty.  See the \l ViewTransition documentation for more details
+    and examples on using these transitions.
 
-    See the \l ViewTransition documentation for more details and examples on using these transitions.
+    \note In QtQuick 1, this transition was applied to all items that were part of the
+    positioner at the time of its creation. From QtQuick 2 onwards, positioners apply the
+    \l populate transition to these items instead.
 
     \sa add, ViewTransition, {qml/positioners}{Positioners example}
 */
@@ -947,13 +1012,27 @@ void QQuickRow::reportConflictingAnchors()
     \sa Flow, Row, Column, Positioner, {qml/positioners}{Positioners example}
 */
 /*!
+    \qmlproperty Transition QtQuick2::Grid::populate
+
+    This property holds the transition to be run for items that are part of
+    this positioner at the time of its creation. The transition is run when the positioner
+    is first created.
+
+    The transition can use the \l ViewTransition property to access more details about
+    the item that is being added. See the \l ViewTransition documentation for more details
+    and examples on using these transitions.
+
+    \sa add, ViewTransition, {declarative/positioners}{Positioners example}
+*/
+/*!
     \qmlproperty Transition QtQuick2::Grid::add
 
     This property holds the transition to be run for items that are added to this
     positioner. For a positioner, this applies to:
 
     \list
-    \li Items that are created or reparented as a child of the positioner
+    \li Items that are created or reparented as a child of the positioner after the
+        positioner has been created
     \li Child items that change their \l visible property from false to true, and thus
        are now visible
     \endlist
@@ -962,7 +1041,10 @@ void QQuickRow::reportConflictingAnchors()
     the item that is being added. See the \l ViewTransition documentation for more details
     and examples on using these transitions.
 
-    \sa move, ViewTransition, {declarative/positioners}{Positioners example}
+    \note This transition is not applied to the items that already part of the positioner
+    at the time of its creation. In this case, the \l populate transition is applied instead.
+
+    \sa populate, ViewTransition, {declarative/positioners}{Positioners example}
 */
 /*!
     \qmlproperty Transition QtQuick2::Grid::move
@@ -980,9 +1062,12 @@ void QQuickRow::reportConflictingAnchors()
     the item that is being moved. Note, however, that for this move transition, the
     ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when
     this transition is triggered by the addition of other items in the positioner; in other
-    cases, these lists will be empty.
+    cases, these lists will be empty.  See the \l ViewTransition documentation for more details
+    and examples on using these transitions.
 
-    See the \l ViewTransition documentation for more details and examples on using these transitions.
+    \note In QtQuick 1, this transition was applied to all items that were part of the
+    positioner at the time of its creation. From QtQuick 2 onwards, positioners apply the
+    \l populate transition to these items instead.
 
     \sa add, ViewTransition, {qml/positioners}{Positioners example}
 */
@@ -1360,13 +1445,27 @@ void QQuickGrid::reportConflictingAnchors()
   \sa Column, Row, Grid, Positioner, {qml/positioners}{Positioners example}
 */
 /*!
+    \qmlproperty Transition QtQuick2::Flow::populate
+
+    This property holds the transition to be run for items that are part of
+    this positioner at the time of its creation. The transition is run when the positioner
+    is first created.
+
+    The transition can use the \l ViewTransition property to access more details about
+    the item that is being added. See the \l ViewTransition documentation for more details
+    and examples on using these transitions.
+
+    \sa add, ViewTransition, {declarative/positioners}{Positioners example}
+*/
+/*!
     \qmlproperty Transition QtQuick2::Flow::add
 
     This property holds the transition to be run for items that are added to this
     positioner. For a positioner, this applies to:
 
     \list
-    \li Items that are created or reparented as a child of the positioner
+    \li Items that are created or reparented as a child of the positioner after the
+        positioner has been created
     \li Child items that change their \l visible property from false to true, and thus
        are now visible
     \endlist
@@ -1375,7 +1474,10 @@ void QQuickGrid::reportConflictingAnchors()
     the item that is being added. See the \l ViewTransition documentation for more details
     and examples on using these transitions.
 
-    \sa move, ViewTransition, {declarative/positioners}{Positioners example}
+    \note This transition is not applied to the items that already part of the positioner
+    at the time of its creation. In this case, the \l populate transition is applied instead.
+
+    \sa populate, ViewTransition, {declarative/positioners}{Positioners example}
 */
 /*!
     \qmlproperty Transition QtQuick2::Flow::move
@@ -1393,9 +1495,12 @@ void QQuickGrid::reportConflictingAnchors()
     the item that is being moved. Note, however, that for this move transition, the
     ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when
     this transition is triggered by the addition of other items in the positioner; in other
-    cases, these lists will be empty.
+    cases, these lists will be empty.  See the \l ViewTransition documentation for more details
+    and examples on using these transitions.
 
-    See the \l ViewTransition documentation for more details and examples on using these transitions.
+    \note In QtQuick 1, this transition was applied to all items that were part of the
+    positioner at the time of its creation. From QtQuick 2 onwards, positioners apply the
+    \l populate transition to these items instead.
 
     \sa add, ViewTransition, {qml/positioners}{Positioners example}
 */
index c13d997..7463d0d 100644 (file)
@@ -93,6 +93,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeIte
     Q_OBJECT
 
     Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+    Q_PROPERTY(QQuickTransition *populate READ populate WRITE setPopulate NOTIFY populateChanged)
     Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged)
     Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged)
 public:
@@ -104,6 +105,9 @@ public:
     qreal spacing() const;
     void setSpacing(qreal);
 
+    QQuickTransition *populate() const;
+    void setPopulate(QQuickTransition *);
+
     QQuickTransition *move() const;
     void setMove(QQuickTransition *);
 
@@ -123,6 +127,7 @@ protected:
 
 Q_SIGNALS:
     void spacingChanged();
+    void populateChanged();
     void moveChanged();
     void addChanged();
 
index b8ee8f9..8a5e438 100644 (file)
@@ -9,6 +9,11 @@ Item {
         objectName: "grid"
         columns: 3
         layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight
+        populate: Transition {
+            NumberAnimation {
+                properties: "x,y";
+            }
+        }
         add: Transition {
             NumberAnimation {
                 properties: "x,y";
index a88c26b..b683670 100644 (file)
@@ -9,6 +9,12 @@ Item {
     Row {
         objectName: "row"
         layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight
+        populate: Transition {
+            enabled: testEnabled ? false : true
+            NumberAnimation {
+                properties: "x";
+            }
+        }
         add: Transition {
             enabled: testEnabled ? false : true
             NumberAnimation {
index e7570de..a1f27bb 100644 (file)
@@ -9,7 +9,8 @@ Rectangle {
 
     property real incrementalSize: 5
 
-    property int targetTransitionsDone
+    property int populateTransitionsDone
+    property int addTransitionsDone
     property int displaceTransitionsDone
 
     property var targetTrans_items: new Object()
@@ -35,16 +36,44 @@ Rectangle {
             model_displacedItems_transitionVia.addItem(name, "")
     }
 
+    Component.onCompleted: {
+        if (dynamicallyPopulate) {
+            for (var i=0; i<30; i++)
+                testModel.addItem("item " + i, "")
+        }
+    }
+
+    Transition {
+        id: populateTransition
+        enabled: usePopulateTransition
+
+        SequentialAnimation {
+            ScriptAction {
+                script: {
+                    root.targetTrans_items[populateTransition.ViewTransition.item.nameData] = populateTransition.ViewTransition.index
+                    root.targetTrans_targetIndexes.push(populateTransition.ViewTransition.targetIndexes)
+                    root.targetTrans_targetItems.push(root.copyList(populateTransition.ViewTransition.targetItems))
+                }
+            }
+            ParallelAnimation {
+                NumberAnimation { properties: "x"; from: targetItems_transitionFrom.x; duration: root.duration }
+                NumberAnimation { properties: "y"; from: targetItems_transitionFrom.y; duration: root.duration }
+            }
+
+            ScriptAction { script: root.populateTransitionsDone += 1 }
+        }
+    }
+
     Transition {
-        id: targetTransition
+        id: addTransition
         enabled: enableAddTransition
 
         SequentialAnimation {
             ScriptAction {
                 script: {
-                    root.targetTrans_items[targetTransition.ViewTransition.item.nameData] = targetTransition.ViewTransition.index
-                    root.targetTrans_targetIndexes.push(targetTransition.ViewTransition.targetIndexes)
-                    root.targetTrans_targetItems.push(root.copyList(targetTransition.ViewTransition.targetItems))
+                    root.targetTrans_items[addTransition.ViewTransition.item.nameData] = addTransition.ViewTransition.index
+                    root.targetTrans_targetIndexes.push(addTransition.ViewTransition.targetIndexes)
+                    root.targetTrans_targetItems.push(root.copyList(addTransition.ViewTransition.targetItems))
                 }
             }
             ParallelAnimation {
@@ -52,7 +81,7 @@ Rectangle {
                 NumberAnimation { properties: "y"; from: targetItems_transitionFrom.y; duration: root.duration }
             }
 
-            ScriptAction { script: root.targetTransitionsDone += 1 }
+            ScriptAction { script: root.addTransitionsDone += 1 }
         }
     }
 
@@ -87,6 +116,7 @@ Rectangle {
         width: 400; height: 400
         Repeater {
             objectName: "repeater"
+            model: testedPositioner == "row" ? testModel : undefined
             Rectangle {
                 property string nameData: name
                 objectName: "wrapper"
@@ -103,7 +133,8 @@ Rectangle {
             }
         }
 
-        add: targetTransition
+        populate: populateTransition
+        add: addTransition
         move: displaced
     }
 
@@ -116,6 +147,7 @@ Rectangle {
         width: 400; height: 400
         Repeater {
             objectName: "repeater"
+            model: testedPositioner == "column" ? testModel : undefined
             Rectangle {
                 property string nameData: name
                 objectName: "wrapper"
@@ -132,7 +164,8 @@ Rectangle {
             }
         }
 
-        add: targetTransition
+        populate: populateTransition
+        add: addTransition
         move: displaced
     }
 
@@ -145,6 +178,7 @@ Rectangle {
         width: 400; height: 400
         Repeater {
             objectName: "repeater"
+            model: testedPositioner == "grid" ? testModel : undefined
             Rectangle {
                 property string nameData: name
                 objectName: "wrapper"
@@ -162,7 +196,8 @@ Rectangle {
             }
         }
 
-        add: targetTransition
+        populate: populateTransition
+        add: addTransition
         move: displaced
     }
 
@@ -175,6 +210,7 @@ Rectangle {
         width: 400; height: 400
         Repeater {
             objectName: "repeater"
+            model: testedPositioner == "flow" ? testModel : undefined
             Rectangle {
                 property string nameData: name
                 objectName: "wrapper"
@@ -191,7 +227,8 @@ Rectangle {
             }
         }
 
-        add: targetTransition
+        populate: populateTransition
+        add: addTransition
         move: displaced
     }
 }
index ecf593c..1ea359e 100644 (file)
@@ -5,6 +5,11 @@ Item {
     height: 480
     Column {
         objectName: "column"
+        populate: Transition {
+            NumberAnimation {
+                properties: "y";
+            }
+        }
         add: Transition {
             NumberAnimation {
                 properties: "y";
index 12b9d66..ee0988f 100644 (file)
@@ -93,6 +93,15 @@ private slots:
     void test_attachedproperties();
     void test_attachedproperties_data();
     void test_attachedproperties_dynamic();
+
+    void populateTransitions_row();
+    void populateTransitions_row_data();
+    void populateTransitions_column();
+    void populateTransitions_column_data();
+    void populateTransitions_grid();
+    void populateTransitions_grid_data();
+    void populateTransitions_flow();
+    void populateTransitions_flow_data();
     void addTransitions_row();
     void addTransitions_row_data();
     void addTransitions_column();
@@ -113,6 +122,8 @@ private slots:
 private:
     QQuickView *createView(const QString &filename, bool wait=true);
 
+    void populateTransitions(const QString &positionerObjectName);
+    void populateTransitions_data();
     void addTransitions(const QString &positionerObjectName);
     void addTransitions_data();
     void moveTransitions(const QString &positionerObjectName);
@@ -123,6 +134,46 @@ private:
     void checkItemPositions(QQuickItem *positioner, QaimModel *model, qreal incrementalSize);
 };
 
+void tst_qquickpositioners::populateTransitions_row()
+{
+    populateTransitions("row");
+}
+
+void tst_qquickpositioners::populateTransitions_row_data()
+{
+    populateTransitions_data();
+}
+
+void tst_qquickpositioners::populateTransitions_column()
+{
+    populateTransitions("column");
+}
+
+void tst_qquickpositioners::populateTransitions_column_data()
+{
+    populateTransitions_data();
+}
+
+void tst_qquickpositioners::populateTransitions_grid()
+{
+    populateTransitions("grid");
+}
+
+void tst_qquickpositioners::populateTransitions_grid_data()
+{
+    populateTransitions_data();
+}
+
+void tst_qquickpositioners::populateTransitions_flow()
+{
+    populateTransitions("flow");
+}
+
+void tst_qquickpositioners::populateTransitions_flow_data()
+{
+    populateTransitions_data();
+}
+
 void tst_qquickpositioners::addTransitions_row()
 {
     addTransitions("row");
@@ -509,6 +560,90 @@ void tst_qquickpositioners::test_horizontal_animated_disabled()
     delete canvas;
 }
 
+void tst_qquickpositioners::populateTransitions(const QString &positionerObjectName)
+{
+    QFETCH(bool, dynamicallyPopulate);
+    QFETCH(bool, usePopulateTransition);
+
+    QPointF targetItems_transitionFrom(-50, -50);
+    QPointF displacedItems_transitionVia(100, 100);
+
+    QaimModel model;
+    if (!dynamicallyPopulate) {
+        for (int i = 0; i < 30; i++)
+            model.addItem("Original item" + QString::number(i), "");
+    }
+
+    QaimModel model_targetItems_transitionFrom;
+    QaimModel model_displacedItems_transitionVia;
+
+    QQuickView *canvas = QQuickViewTestUtil::createView();
+    QQmlContext *ctxt = canvas->rootContext();
+    ctxt->setContextProperty("usePopulateTransition", usePopulateTransition);
+    ctxt->setContextProperty("enableAddTransition", true);
+    ctxt->setContextProperty("dynamicallyPopulate", dynamicallyPopulate);
+    ctxt->setContextProperty("testModel", &model);
+    ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
+    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
+    ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
+    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
+    ctxt->setContextProperty("testedPositioner", positionerObjectName);
+    canvas->setSource(testFileUrl("transitions.qml"));
+
+    QQuickItem *positioner = canvas->rootObject()->findChild<QQuickItem*>(positionerObjectName);
+    QVERIFY(positioner);
+    canvas->show();
+    qApp->processEvents();
+
+    if (!dynamicallyPopulate && usePopulateTransition) {
+        QTRY_COMPARE(canvas->rootObject()->property("populateTransitionsDone").toInt(), model.count());
+        QTRY_COMPARE(canvas->rootObject()->property("addTransitionsDone").toInt(), 0);
+
+        QList<QPair<QString, QString> > targetData;
+        QList<int> targetIndexes;
+        for (int i=0; i<model.count(); i++) {
+            targetData << qMakePair(model.name(i), model.number(i));
+            targetIndexes << i;
+        }
+        QList<QQuickItem *> targetItems = findItems<QQuickItem>(positioner, "wrapper", targetIndexes);
+        model_targetItems_transitionFrom.matchAgainst(targetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos");
+        matchItemsAndIndexes(canvas->rootObject()->property("targetTrans_items").toMap(), model, targetIndexes);
+        matchIndexLists(canvas->rootObject()->property("targetTrans_targetIndexes").toList(), targetIndexes);
+        matchItemLists(canvas->rootObject()->property("targetTrans_targetItems").toList(), targetItems);
+
+    } else if (dynamicallyPopulate) {
+        QTRY_COMPARE(canvas->rootObject()->property("populateTransitionsDone").toInt(), 0);
+        QTRY_COMPARE(canvas->rootObject()->property("addTransitionsDone").toInt(), model.count());
+    } else {
+        QTRY_COMPARE(QQuickItemPrivate::get(positioner)->polishScheduled, false);
+        QTRY_COMPARE(canvas->rootObject()->property("populateTransitionsDone").toInt(), 0);
+        QTRY_COMPARE(canvas->rootObject()->property("addTransitionsDone").toInt(), 0);
+    }
+
+    checkItemPositions(positioner, &model, canvas->rootObject()->property("incrementalSize").toInt());
+
+    // add an item and check this is done with add transition, not populate
+    canvas->rootObject()->setProperty("populateTransitionsDone", 0);
+    canvas->rootObject()->setProperty("addTransitionsDone", 0);
+    model.insertItem(0, "new item", "");
+    QTRY_COMPARE(canvas->rootObject()->property("addTransitionsDone").toInt(), 1);
+    QTRY_COMPARE(canvas->rootObject()->property("populateTransitionsDone").toInt(), 0);
+
+    delete canvas;
+}
+
+void tst_qquickpositioners::populateTransitions_data()
+{
+    QTest::addColumn<bool>("dynamicallyPopulate");
+    QTest::addColumn<bool>("usePopulateTransition");
+
+    QTest::newRow("statically populate") << false << true;
+    QTest::newRow("statically populate, no populate transition") << false << false;
+
+    QTest::newRow("dynamically populate") << true << true;
+    QTest::newRow("dynamically populate, no populate transition") << true << false;
+}
+
 void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
 {
     QFETCH(int, initialItemCount);
@@ -520,13 +655,12 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
     QPointF displacedItems_transitionVia(100, 100);
 
     QaimModel model;
-    for (int i = 0; i < initialItemCount; i++)
-        model.addItem("Original item" + QString::number(i), "");
     QaimModel model_targetItems_transitionFrom;
     QaimModel model_displacedItems_transitionVia;
 
     QQuickView *canvas = QQuickViewTestUtil::createView();
     QQmlContext *ctxt = canvas->rootContext();
+    ctxt->setContextProperty("usePopulateTransition", false);
     ctxt->setContextProperty("enableAddTransition", true);
     ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
     ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
@@ -536,12 +670,15 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
     canvas->show();
     qApp->processEvents();
 
-    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
-
     QQuickItem *positioner = canvas->rootObject()->findChild<QQuickItem*>(positionerObjectName);
     QVERIFY(positioner);
     positioner->findChild<QQuickItem*>("repeater")->setProperty("model", QVariant::fromValue(&model));
+    QTRY_COMPARE(QQuickItemPrivate::get(positioner)->polishScheduled, false);
 
+    for (int i = 0; i < initialItemCount; i++)
+        model.addItem("Original item" + QString::number(i), "");
+
+    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
     QList<QPair<QString, QString> > targetData;
     QList<int> targetIndexes;
     for (int i=0; i<model.count(); i++) {
@@ -550,9 +687,9 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
     }
     QList<QQuickItem *> targetItems = findItems<QQuickItem>(positioner, "wrapper", targetIndexes);
 
-    // check initial add transition
-    // (positioners run the add transition on all items that are initially created for the view)
-    QTRY_COMPARE(canvas->rootObject()->property("targetTransitionsDone").toInt(), initialItemCount);
+    // check add transition was run for first lot of added items
+    QTRY_COMPARE(canvas->rootObject()->property("populateTransitionsDone").toInt(), 0);
+    QTRY_COMPARE(canvas->rootObject()->property("addTransitionsDone").toInt(), initialItemCount);
     QTRY_COMPARE(canvas->rootObject()->property("displaceTransitionsDone").toInt(), 0);
     model_targetItems_transitionFrom.matchAgainst(targetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos");
     matchItemsAndIndexes(canvas->rootObject()->property("targetTrans_items").toMap(), model, targetIndexes);
@@ -560,7 +697,7 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
     matchItemLists(canvas->rootObject()->property("targetTrans_targetItems").toList(), targetItems);
 
     model_targetItems_transitionFrom.clear();
-    canvas->rootObject()->setProperty("targetTransitionsDone", 0);
+    canvas->rootObject()->setProperty("addTransitionsDone", 0);
     canvas->rootObject()->setProperty("targetTrans_items", QVariantMap());
     canvas->rootObject()->setProperty("targetTrans_targetIndexes", QVariantList());
     canvas->rootObject()->setProperty("targetTrans_targetItems", QVariantList());
@@ -577,7 +714,7 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
 
     targetItems = findItems<QQuickItem>(positioner, "wrapper", targetIndexes);
 
-    QTRY_COMPARE(canvas->rootObject()->property("targetTransitionsDone").toInt(), targetData.count());
+    QTRY_COMPARE(canvas->rootObject()->property("addTransitionsDone").toInt(), targetData.count());
     QTRY_COMPARE(canvas->rootObject()->property("displaceTransitionsDone").toInt(), expectedDisplacedIndexes.count());
 
     // check the target and displaced items were animated
@@ -636,6 +773,7 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
 
     QQuickView *canvas = QQuickViewTestUtil::createView();
     QQmlContext *ctxt = canvas->rootContext();
+    ctxt->setContextProperty("usePopulateTransition", false);
     ctxt->setContextProperty("enableAddTransition", QVariant(false));
     ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
     ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
@@ -669,7 +807,7 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
     }
 
     QTRY_COMPARE(canvas->rootObject()->property("displaceTransitionsDone").toInt(), expectedDisplacedIndexes.count());
-    QCOMPARE(canvas->rootObject()->property("targetTransitionsDone").toInt(), 0);
+    QCOMPARE(canvas->rootObject()->property("addTransitionsDone").toInt(), 0);
 
     // check the target and displaced items were animated
     QCOMPARE(model_targetItems_transitionFrom.count(), 0);