aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/items.pri2
-rw-r--r--src/quick/items/qquickgridview.cpp42
-rw-r--r--src/quick/items/qquickitemsmodule.cpp1
-rw-r--r--src/quick/items/qquickitemview.cpp890
-rw-r--r--src/quick/items/qquickitemview_p.h44
-rw-r--r--src/quick/items/qquickitemview_p_p.h88
-rw-r--r--src/quick/items/qquickitemviewtransition.cpp770
-rw-r--r--src/quick/items/qquickitemviewtransition_p.h201
-rw-r--r--src/quick/items/qquicklistview.cpp42
9 files changed, 1159 insertions, 921 deletions
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index 21bf7cc8c1..54220434b4 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -72,6 +72,7 @@ HEADERS += \
$$PWD/qquickmultipointtoucharea_p.h \
$$PWD/qquickitemview_p.h \
$$PWD/qquickitemview_p_p.h \
+ $$PWD/qquickitemviewtransition_p.h \
$$PWD/qquickscreen_p.h \
$$PWD/qquickwindowmodule_p.h \
$$PWD/qquickwindowmanager_p.h
@@ -124,6 +125,7 @@ SOURCES += \
$$PWD/qquickdroparea.cpp \
$$PWD/qquickmultipointtoucharea.cpp \
$$PWD/qquickitemview.cpp \
+ $$PWD/qquickitemviewtransition.cpp \
$$PWD/qquickwindowmodule.cpp \
$$PWD/qquickscreen.cpp \
$$PWD/qquickwindowmanager.cpp
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index a7e0af487f..fbce0af0c3 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -127,9 +127,6 @@ public:
return (x >= itemX() && x < itemX() + view->cellWidth() &&
y >= itemY() && y < itemY() + view->cellHeight());
}
- QQuickItemView *itemView() const {
- return view;
- }
QQuickGridView *view;
@@ -485,7 +482,7 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
#endif
if (!(item = static_cast<FxGridItemSG*>(createItem(modelIndex, doBuffer))))
break;
- if (!canTransition(FxViewItemTransitionManager::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
+ if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(colPos, rowPos);
item->item->setVisible(!doBuffer);
visibleItems.append(item);
@@ -523,7 +520,7 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
if (!(item = static_cast<FxGridItemSG*>(createItem(visibleIndex-1, doBuffer))))
break;
--visibleIndex;
- if (!canTransition(FxViewItemTransitionManager::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
+ if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(colPos, rowPos);
item->item->setVisible(!doBuffer);
visibleItems.prepend(item);
@@ -1674,6 +1671,10 @@ void QQuickGridView::setSnapMode(SnapMode mode)
the new item that has been added to the view; to animate the added items, set the \l add
property.
+ If an item is displaced by multiple types of operations at the same time, it is not
+ defined as to whether the addDisplaced, moveDisplaced or removeDisplaced transition
+ will be applied.
+
For more details and examples on how to use view transitions, see the ViewTransition
documentation.
@@ -1737,6 +1738,10 @@ void QQuickGridView::setSnapMode(SnapMode mode)
the items that are the actual subjects of the move operation; to animate the moved items, set
the \l move property.
+ If an item is displaced by multiple types of operations at the same time, it is not
+ defined as to whether the addDisplaced, moveDisplaced or removeDisplaced transition
+ will be applied.
+
For more details and examples on how to use view transitions, see the ViewTransition
documentation.
@@ -1804,6 +1809,10 @@ void QQuickGridView::setSnapMode(SnapMode mode)
the item that has actually been removed from the view; to animate the removed items, set the
\l remove property.
+ If an item is displaced by multiple types of operations at the same time, it is not
+ defined as to whether the addDisplaced, moveDisplaced or removeDisplaced transition
+ will be applied.
+
For more details and examples on how to use view transitions, see the ViewTransition
documentation.
@@ -2112,10 +2121,12 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->index >= modelIndex) {
item->index += count;
- if (change.isMove())
- transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, false);
- else
- transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, false);
+ if (transitioner) {
+ if (change.isMove())
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::MoveTransition, false);
+ else
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, false);
+ }
}
}
@@ -2146,7 +2157,8 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
insertResult->changedFirstItem = true;
if (!change.isMove()) {
addedItems->append(item);
- transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, true);
+ if (transitioner)
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, true);
}
insertResult->sizeChangesBeforeVisiblePos += rowSize();
}
@@ -2179,11 +2191,12 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
if (change.isMove()) {
// we know this is a move target, since move displaced items that are
// shuffled into view due to a move would be added in refill()
- if (canTransition(FxViewItemTransitionManager::MoveTransition, true) && newItem)
+ if (newItem && transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true))
movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
} else {
addedItems->append(item);
- transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, true);
+ if (transitioner)
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, true);
}
insertResult->sizeChangesAfterVisiblePos += rowSize();
@@ -2204,6 +2217,9 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult)
{
+ if (!transitioner)
+ return;
+
int markerItemIndex = -1;
for (int i=0; i<visibleItems.count(); i++) {
if (visibleItems[i]->index == afterModelIndex) {
@@ -2231,7 +2247,7 @@ void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
qreal origColPos = gridItem->rowPos();
int indexDiff = gridItem->index - countItemsRemoved;
gridItem->setPosition((indexDiff % columns) * colSize(), (indexDiff / columns) * rowSize());
- transitionNextReposition(gridItem, FxViewItemTransitionManager::RemoveTransition, false);
+ transitioner->transitionNextReposition(gridItem, QQuickItemViewTransitioner::RemoveTransition, false);
gridItem->setPosition(origRowPos, origColPos);
}
}
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index b9e401a231..f50237427b 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -61,6 +61,7 @@
#include "qquickvisualdatamodel_p.h"
#include "qquickgridview_p.h"
#include "qquickpathview_p.h"
+#include "qquickitemviewtransition_p.h"
#include <private/qdeclarativepath_p.h>
#include <private/qdeclarativepathinterpolator_p.h>
#include "qquickpositioners_p.h"
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index d5ce567590..481a0d4360 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -46,21 +46,12 @@ QT_BEGIN_NAMESPACE
FxViewItem::FxViewItem(QQuickItem *i, bool own)
- : item(i), ownItem(own), releaseAfterTransition(false)
- , isTransitionTarget(false)
- , nextTransitionToSet(false)
- , index(-1)
- , transition(0)
- , nextTransitionType(FxViewItemTransitionManager::NoTransition)
+ : QQuickViewItem(i), ownItem(own), releaseAfterTransition(false)
{
}
FxViewItem::~FxViewItem()
{
- if (transition)
- transition->m_item = 0;
- delete transition;
-
if (ownItem && item) {
item->setParentItem(0);
item->deleteLater();
@@ -68,273 +59,6 @@ FxViewItem::~FxViewItem()
}
}
-qreal FxViewItem::itemX() const
-{
- if (nextTransitionType != FxViewItemTransitionManager::NoTransition)
- return nextTransitionToSet ? nextTransitionTo.x() : item->x();
- else if (transition && transition->isActive())
- return transition->m_toPos.x();
- else
- return item->x();
-}
-
-qreal FxViewItem::itemY() const
-{
- // If item is transitioning to some pos, return that dest pos.
- // If item was redirected to some new pos before the current transition finished,
- // return that new pos.
- if (nextTransitionType != FxViewItemTransitionManager::NoTransition)
- return nextTransitionToSet ? nextTransitionTo.y() : item->y();
- else if (transition && transition->isActive())
- return transition->m_toPos.y();
- else
- return item->y();
-}
-
-void FxViewItem::setVisible(bool visible)
-{
- if (!visible && transitionScheduledOrRunning())
- return;
- item->setVisible(visible);
-}
-
-void FxViewItem::setNextTransition(FxViewItemTransitionManager::TransitionType type, bool isTargetItem)
-{
- // Don't reset nextTransitionToSet - once it is set, it cannot be changed
- // until the animation finishes since the itemX() and itemY() may be used
- // to calculate positions for transitions for other items in the view.
- nextTransitionType = type;
- isTransitionTarget = isTargetItem;
-}
-
-bool FxViewItem::transitionScheduledOrRunning() const
-{
- return (transition && transition->isActive())
- || nextTransitionType != FxViewItemTransitionManager::NoTransition;
-}
-
-bool FxViewItem::prepareTransition(const QRectF &viewBounds)
-{
- bool doTransition = false;
-
- switch (nextTransitionType) {
- case FxViewItemTransitionManager::NoTransition:
- {
- return false;
- }
- case FxViewItemTransitionManager::PopulateTransition:
- {
- return true;
- }
- case FxViewItemTransitionManager::AddTransition:
- case FxViewItemTransitionManager::RemoveTransition:
- // For Add targets, do transition if item is moving into visible area
- // For Remove targets, do transition if item is currently in visible area
- if (isTransitionTarget) {
- doTransition = (nextTransitionType == FxViewItemTransitionManager::AddTransition)
- ? viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))
- : viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()));
- if (!doTransition)
- item->setPos(nextTransitionTo);
- } else {
- if (viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()))
- || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))) {
- doTransition = (nextTransitionTo != item->pos());
- } else {
- item->setPos(nextTransitionTo);
- }
- }
- break;
- case FxViewItemTransitionManager::MoveTransition:
- // do transition if moving from or into visible area
- if (nextTransitionTo != item->pos()) {
- doTransition = viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()))
- || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()));
- if (!doTransition)
- item->setPos(nextTransitionTo);
- }
- break;
- }
-
- if (!doTransition)
- resetTransitionData();
- return doTransition;
-}
-
-void FxViewItem::startTransition()
-{
- if (nextTransitionType == FxViewItemTransitionManager::NoTransition)
- return;
-
- if (!transition || transition->m_type != nextTransitionType || transition->m_isTarget != isTransitionTarget) {
- delete transition;
- transition = new FxViewItemTransitionManager;
- }
-
- // if item is not already moving somewhere, set it to not move anywhere
- // so that removed items do not move to the default (0,0)
- if (!nextTransitionToSet)
- moveTo(item->pos());
-
- transition->startTransition(this, nextTransitionType, nextTransitionTo, isTransitionTarget);
- nextTransitionType = FxViewItemTransitionManager::NoTransition;
-}
-
-void FxViewItem::stopTransition()
-{
- if (transition) {
- transition->cancel();
- delete transition;
- transition = 0;
- }
- resetTransitionData();
- finishedTransition();
-}
-
-void FxViewItem::finishedTransition()
-{
- nextTransitionToSet = false;
- nextTransitionTo = QPointF();
-
- if (releaseAfterTransition) {
- QQuickItemViewPrivate *vp = static_cast<QQuickItemViewPrivate*>(QObjectPrivate::get(itemView()));
- vp->releasePendingTransition.removeOne(this);
- vp->releaseItem(this);
- }
-}
-
-void FxViewItem::resetTransitionData()
-{
- nextTransitionType = FxViewItemTransitionManager::NoTransition;
- isTransitionTarget = false;
- nextTransitionTo = QPointF();
- nextTransitionToSet = false;
-}
-
-bool FxViewItem::isPendingRemoval() const
-{
- if (nextTransitionType == FxViewItemTransitionManager::RemoveTransition)
- return isTransitionTarget;
- if (transition && transition->isActive() && transition->m_type == FxViewItemTransitionManager::RemoveTransition)
- return transition->m_isTarget;
- return false;
-}
-
-void FxViewItem::moveTo(const QPointF &pos)
-{
- if (transitionScheduledOrRunning()) {
- nextTransitionTo = pos;
- nextTransitionToSet = true;
- } else {
- item->setPos(pos);
- }
-}
-
-
-FxViewItemTransitionManager::FxViewItemTransitionManager()
- : m_active(false), m_item(0), m_type(FxViewItemTransitionManager::NoTransition), m_isTarget(false)
-{
-}
-
-FxViewItemTransitionManager::~FxViewItemTransitionManager()
-{
-}
-
-bool FxViewItemTransitionManager::isActive() const
-{
- return m_active;
-}
-
-void FxViewItemTransitionManager::startTransition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, const QPointF &to, bool isTargetItem)
-{
- if (!item) {
- qWarning("startTransition(): invalid item");
- return;
- }
-
- QQuickItemViewPrivate *vp = static_cast<QQuickItemViewPrivate*>(QObjectPrivate::get(item->itemView()));
-
- QDeclarativeTransition *trans = 0;
- switch (type) {
- case NoTransition:
- break;
- case PopulateTransition:
- trans = vp->populateTransition;
- break;
- case AddTransition:
- trans = isTargetItem ? vp->addTransition : vp->addDisplacedTransition;
- break;
- case MoveTransition:
- trans = isTargetItem ? vp->moveTransition : vp->moveDisplacedTransition;
- break;
- case RemoveTransition:
- trans = isTargetItem ? vp->removeTransition : vp->removeDisplacedTransition;
- break;
- }
-
- if (!trans) {
- qWarning("QQuickItemView: invalid view transition!");
- return;
- }
-
- m_active = true;
- m_item = item;
- m_toPos = to;
- m_type = type;
- m_isTarget = isTargetItem;
-
- QQuickViewTransitionAttached *attached =
- static_cast<QQuickViewTransitionAttached*>(qmlAttachedPropertiesObject<QQuickViewTransitionAttached>(trans));
- if (attached) {
- attached->m_index = item->index;
- attached->m_item = item->item;
- attached->m_destination = to;
- switch (type) {
- case NoTransition:
- break;
- case PopulateTransition:
- case AddTransition:
- attached->m_targetIndexes = vp->addTransitionIndexes;
- attached->m_targetItems = vp->addTransitionTargets;
- break;
- case MoveTransition:
- attached->m_targetIndexes = vp->moveTransitionIndexes;
- attached->m_targetItems = vp->moveTransitionTargets;
- break;
- case RemoveTransition:
- attached->m_targetIndexes = vp->removeTransitionIndexes;
- attached->m_targetItems = vp->removeTransitionTargets;
- break;
- }
- emit attached->indexChanged();
- emit attached->itemChanged();
- emit attached->destinationChanged();
- emit attached->targetIndexesChanged();
- emit attached->targetItemsChanged();
- }
-
- QDeclarativeStateOperation::ActionList actions;
- actions << QDeclarativeAction(item->item, QLatin1String("x"), QVariant(to.x()));
- actions << QDeclarativeAction(item->item, QLatin1String("y"), QVariant(to.y()));
-
- QDeclarativeTransitionManager::transition(actions, trans, item->item);
-}
-
-void FxViewItemTransitionManager::finished()
-{
- QDeclarativeTransitionManager::finished();
-
- m_active = false;
-
- if (m_item)
- m_item->finishedTransition();
- m_item = 0;
- m_toPos.setX(0);
- m_toPos.setY(0);
- m_type = NoTransition;
- m_isTarget = false;
-}
-
QQuickItemViewChangeSet::QQuickItemViewChangeSet()
: active(false)
@@ -413,363 +137,6 @@ void QQuickItemViewChangeSet::reset()
currentRemoved = false;
}
-
-QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent)
- : QObject(parent), m_index(-1), m_item(0)
-{
-}
-/*!
- \qmlclass ViewTransition QQuickViewTransitionAttached
- \inqmlmodule QtQuick 2
- \ingroup qml-view-elements
- \brief The ViewTransition attached property provides details on items under transition in a view.
-
- With ListView and GridView, it is possible to specify transitions that should be applied whenever
- the items in the view change as a result of modifications to the view's model. They both have the
- following properties that can be set to the appropriate transitions to be run for various
- operations:
-
- \list
- \o \c add and \c addDisplaced - the transitions to run when items are added to the view
- \o \c remove and \c removeDisplaced - the transitions to run when items are removed from the view
- \o \c move and \c moveDisplaced - the transitions to run when items are moved within the view
- (i.e. as a result of a move operation in the model)
- \o \c populate - the transition to run when a view is created, or when the model changes
- \endlist
-
- Such view transitions additionally have access to a ViewTransition attached property that
- provides details of the items that are under transition and the operation that triggered the
- transition. Since view transitions are run once per item, these details can be used to customise
- each transition for each individual item.
-
- The ViewTransition attached property provides the following properties specific to the item to
- which the transition is applied:
-
- \list
- \o ViewTransition.item - the item that is under transition
- \o ViewTransition.index - the index of this item
- \o ViewTransition.destination - the (x,y) point to which this item is moving for the relevant view operation
- \endlist
-
- In addition, ViewTransition provides properties specific to the items which are the target
- of the operation that triggered the transition:
-
- \list
- \o ViewTransition.targetIndexes - the indexes of the target items
- \o ViewTransition.targetItems - the target items themselves
- \endlist
-
- View transitions can be written without referring to any of the attributes listed
- above. These attributes merely provide extra details that are useful for customising view
- transitions.
-
- Following is an introduction to view transitions and the ways in which the ViewTransition
- attached property can be used to augment view transitions.
-
-
- \section2 View transitions: a simple example
-
- Here is a basic example of the use of view transitions. The view below specifies transitions for
- the \c add and \c addDisplaced properties, which will be run when items are added to the view:
-
- \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0
-
- When the space key is pressed, adding an item to the model, the new item will fade in and
- increase in scale over 400 milliseconds as it is added to the view. Also, any item that is
- displaced by the addition of a new item will animate to its new position in the view over
- 400 milliseconds, as specified by the \c addDisplaced transition.
-
- If five items were inserted in succession at index 0, the effect would be this:
-
- \image viewtransitions-basic.gif
-
- Notice that the NumberAnimation objects above do not need to specify a \c target to animate
- the appropriate item. Also, the NumberAnimation in the \c addTransition does not need to specify
- the \c to value to move the item to its correct position in the view. This is because the view
- implicitly sets the \c target and \c to values with the correct item and final item position
- values if these properties are not explicitly defined.
-
- At its simplest, a view transition may just animate an item to its new position following a
- view operation, just as the \c addDisplaced transition does above, or animate some item properties,
- as in the \c add transition above. Additionally, a view transition may make use of the
- ViewTransition attached property to customise animation behavior for different items. Following
- are some examples of how this can be achieved.
-
-
- \section2 Using the ViewTransition attached property
-
- As stated, the various ViewTransition properties provide details specific to the individual item
- being transitioned as well as the operation that triggered the transition. In the animation above,
- five items are inserted in succession at index 0. When the fifth and final insertion takes place,
- adding "Item 4" to the view, the \c add transition is run once (for the inserted item) and the
- \c addDisplaced transition is run four times (once for each of the four existing items in the view).
-
- At this point, if we examined the \c addDisplaced transition that was run for the bottom displaced
- item ("Item 0"), the ViewTransition property values provided to this transition would be as follows:
-
- \table
- \header
- \o Property
- \o Value
- \o Explanation
- \row
- \o ViewTransition.item
- \o "Item 0" delegate instance
- \o The "Item 0" \l Rectangle object itself
- \row
- \o ViewTransition.index
- \o \c int value of 4
- \o The index of "Item 0" within the model following the add operation
- \row
- \o ViewTransition.destination
- \o \l point value of (0, 120)
- \o The position that "Item 0" is moving to
- \row
- \o ViewTransition.targetIndexes
- \o \c int array, just contains the integer "0" (zero)
- \o The index of "Item 4", the new item added to the view
- \row
- \o ViewTransition.targetItems
- \o object array, just contains the "Item 4" delegate instance
- \o The "Item 4" \l Rectangle object - the new item added to the view
- \endtable
-
- The ViewTransition.targetIndexes and ViewTransition.targetItems lists provide the items and
- indexes of all delegate instances that are the targets of the relevant operation. For an add
- operation, these are all the items that are added into the view; for a remove, these are all
- the items removed from the view, and so on. (Note these lists will only contain references to
- items that have been created within the view or its cached items; targets that are not within
- the visible area of the view or within the item cache will not be accessible.)
-
- So, while the ViewTransition.item, ViewTransition.index and ViewTransition.destination values
- vary for each individual transition that is run, the ViewTransition.targetIndexes and
- ViewTransition.targetItems values are the same for every \c add and \c addDisplaced transition
- that is triggered by a particular add operation.
-
-
- \section3 Delaying animations based on index
-
- Since each view transition is run once for each item affected by the transition, the ViewTransition
- properties can be used within a transition to define custom behavior for each item's transition.
- For example, the ListView in the previous example could use this information to create a ripple-type
- effect on the movement of the displaced items.
-
- This can be achieved by modifying the \c addDisplaced transition so that it delays the animation of
- each displaced item based on the difference between its index (provided by ViewTransition.index)
- and the first removed index (provided by ViewTransition.targetIndexes):
-
- \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml 0
-
- Each displaced item delays its animation by an additional 100 milliseconds, producing a subtle
- ripple-type effect when items are displaced by the add, like this:
-
- \image viewtransitions-delayedbyindex.gif
-
-
- \section3 Animating items to intermediate positions
-
- The ViewTransition.item property gives a reference to the item to which the transition is being
- applied. This can be used to access any of the item's attributes, custom \c property values,
- and so on.
-
- Below is a modification of the \c addDisplaced transition from the previous example. It adds a
- ParallelAnimation with nested NumberAnimation objects that reference ViewTransition.item to access
- each item's \c x and \c y values at the start of their transitions. This allows each item to
- animate to an intermediate position relative to its starting point for the transition, before
- animating to its final position in the view:
-
- \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml 0
-
- Now, a displaced item will first move to a position of (20, 50) relative to its starting
- position, and then to its final, correct position in the view:
-
- \image viewtransitions-intermediatemove.gif
-
- Since the final NumberAnimation does not specify a \c to value, the view implicitly sets this
- value to the item's final position in the view, and so this last animation will move this item
- to the correct place. If the transition requires the final position of the item for some calculation,
- this is accessible through ViewTransition.destination.
-
- Instead of using multiple NumberAnimations, you could use a PathAnimation to animate an item over
- a curved path. For example, the \c add transition in the previous example could be augmented with
- a PathAnimation as follows: to animate newly added items along a path:
-
- \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml 0
-
- This animates newly added items along a path. Notice that each path is specified relative to
- each item's final destination point, so that items inserted at different indexes start their
- paths from different positions:
-
- \image viewtransitions-pathanim.gif
-
-
- \section2 Handling interrupted animations
-
- A view transition may be interrupted at any time if a different view transition needs to be
- applied while the original transition is in progress. For example, say Item A is inserted at index 0
- and undergoes an "add" transition; then, Item B is inserted at index 0 in quick succession before
- Item A's transition has finished. Since Item B is inserted before Item A, it will displace Item
- A, causing the view to interrupt Item A's "add" transition mid-way and start an "addDisplaced"
- transition on Item A instead.
-
- For simple animations that simply animate an item's movement to its final destination, this
- interruption is unlikely to require additional consideration. However, if a transition changes other
- properties, this interruption may cause unwanted side effects. Consider the first example on this
- page, repeated below for convenience:
-
- \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0
-
- If multiple items are added in rapid succession, without waiting for a previous transition
- to finish, this is the result:
-
- \image viewtransitions-interruptedbad.gif
-
- Each newly added item undergoes an \c add transition, but before the transition can finish,
- another item is added, displacing the previously added item. Because of this, the \c add
- transition on the previously added item is interrupted and an \c addDisplaced transition is
- started on the item instead. Due to the interruption, the \c opacity and \c scale animations
- have not completed, thus producing items with opacity and scale that are below 1.0.
-
- To fix this, the \c addDisplaced transition should additionally ensure the item properties are
- set to the end values specified in the \c add transition, effectively resetting these values
- whenever an item is displaced. In this case, it means setting the item opacity and scale to 1.0:
-
- \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml 0
-
- Now, when an item's \c add transition is interrupted, its opacity and scale are animated to 1.0
- upon displacement, avoiding the erroneous visual effects from before:
-
- \image viewtransitions-interruptedgood.gif
-
- The same principle applies to any combination of view transitions. An added item may be moved
- before its add transition finishes, or a moved item may be removed before its moved transition
- finishes, and so on; so, the rule of thumb is that every transition should handle the same set of
- properties.
-
-
- \section2 Restrictions regarding ScriptAction
-
- When a view transition is initialized, any property bindings that refer to the ViewTransition
- attached property are evaluated in preparation for the transition. Due to the nature of the
- internal construction of a view transition, the attributes of the ViewTransition attached
- property are only valid for the relevant item when the transition is initialized, and may not be
- valid when the transition is actually run.
-
- Therefore, a ScriptAction within a view transition should not refer to the ViewTransition
- attached property, as it may not refer to the expected values at the time that the ScriptAction
- is actually invoked. Consider the following example:
-
- \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml 0
-
- When the space key is pressed, three items are moved from index 5 to index 1. For each moved
- item, the \c moveTransition sequence presumably animates the item's color to "yellow", then
- animates it to its final position, then changes the item color back to "lightsteelblue" using a
- ScriptAction. However, when run, the transition does not produce the intended result:
-
- \image viewtransitions-scriptactionbad.gif
-
- Only the last moved item is returned to the "lightsteelblue" color; the others remain yellow. This
- is because the ScriptAction is not run until after the transition has already been initialized, by
- which time the ViewTransition.item value has changed to refer to a different item; the item that
- the script had intended to refer to is not the one held by ViewTransition.item at the time the
- ScriptAction is actually invoked.
-
- In this instance, to avoid this issue, the view could set the property using a PropertyAction
- instead:
-
- \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml 0
-
- When the transition is initialized, the PropertyAction \c target will be set to the respective
- ViewTransition.item for the transition and will later run with the correct item target as
- expected.
- */
-
-/*!
- \qmlattachedproperty list QtQuick2::ViewTransition::index
-
- This attached property holds the index of the item that is being
- transitioned.
-
- Note that if the item is being moved, this property holds the index that
- the item is moving to, not from.
-*/
-
-/*!
- \qmlattachedproperty list QtQuick2::ViewTransition::item
-
- This attached property holds the the item that is being transitioned.
-
- \warning This item should not be kept and referred to outside of the transition
- as it may become invalid as the view changes.
-*/
-
-/*!
- \qmlattachedproperty list QtQuick2::ViewTransition::destination
-
- This attached property holds the final destination position for the transitioned
- item within the view.
-
- This property value is a \l point with \c x and \c y properties.
-*/
-
-/*!
- \qmlattachedproperty list QtQuick2::ViewTransition::targetIndexes
-
- This attached property holds a list of the indexes of the items in view
- that are the target of the relevant operation.
-
- The targets are the items that are the subject of the operation. For
- an add operation, these are the items being added; for a remove, these
- are the items being removed; for a move, these are the items being
- moved.
-
- For example, if the transition was triggered by an insert operation
- that added two items at index 1 and 2, this targetIndexes list would
- have the value [1,2].
-
- \note The targetIndexes list only contains the indexes of items that are actually
- in view, or will be in the view once the relevant operation completes.
-
- \sa QtQuick2::ViewTransition::targetIndexes
-*/
-
-/*!
- \qmlattachedproperty list QtQuick2::ViewTransition::targetItems
-
- This attached property holds the list of items in view that are the
- target of the relevant operation.
-
- The targets are the items that are the subject of the operation. For
- an add operation, these are the items being added; for a remove, these
- are the items being removed; for a move, these are the items being
- moved.
-
- For example, if the transition was triggered by an insert operation
- that added two items at index 1 and 2, this targetItems list would
- contain these two items.
-
- \note The targetItems list only contains items that are actually
- in view, or will be in the view once the relevant operation completes.
-
- \warning The objects in this list should not be kept and referred to
- outside of the transition as the items may become invalid. The targetItems
- are only valid when the Transition is initially created; this also means
- they should not be used by ScriptAction objects in the Transition, which are
- not evaluated until the transition is run.
-
- \sa QtQuick2::ViewTransition::targetIndexes
-*/
-QDeclarativeListProperty<QObject> QQuickViewTransitionAttached::targetItems()
-{
- return QDeclarativeListProperty<QObject>(this, m_targetItems);
-}
-
-QQuickViewTransitionAttached *QQuickViewTransitionAttached::qmlAttachedProperties(QObject *obj)
-{
- return new QQuickViewTransitionAttached(obj);
-}
-
-
//-----------------------------------
QQuickItemView::QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent)
@@ -868,9 +235,9 @@ void QQuickItemView::setModel(const QVariant &model)
}
d->updateViewport();
- if (d->populateTransition) {
+ if (d->transitioner && d->transitioner->populateTransition) {
d->forceLayout = true;
- d->usePopulateTransition = true;
+ d->transitioner->setPopulateTransitionEnabled(true);
polish();
}
}
@@ -1229,14 +596,15 @@ void QQuickItemView::setHighlightMoveDuration(int duration)
QDeclarativeTransition *QQuickItemView::populateTransition() const
{
Q_D(const QQuickItemView);
- return d->populateTransition;
+ return d->transitioner ? d->transitioner->populateTransition : 0;
}
void QQuickItemView::setPopulateTransition(QDeclarativeTransition *transition)
{
Q_D(QQuickItemView);
- if (d->populateTransition != transition) {
- d->populateTransition = transition;
+ d->createTransitioner();
+ if (d->transitioner->populateTransition != transition) {
+ d->transitioner->populateTransition = transition;
emit populateTransitionChanged();
}
}
@@ -1244,14 +612,15 @@ void QQuickItemView::setPopulateTransition(QDeclarativeTransition *transition)
QDeclarativeTransition *QQuickItemView::addTransition() const
{
Q_D(const QQuickItemView);
- return d->addTransition;
+ return d->transitioner ? d->transitioner->addTransition : 0;
}
void QQuickItemView::setAddTransition(QDeclarativeTransition *transition)
{
Q_D(QQuickItemView);
- if (d->addTransition != transition) {
- d->addTransition = transition;
+ d->createTransitioner();
+ if (d->transitioner->addTransition != transition) {
+ d->transitioner->addTransition = transition;
emit addTransitionChanged();
}
}
@@ -1259,14 +628,15 @@ void QQuickItemView::setAddTransition(QDeclarativeTransition *transition)
QDeclarativeTransition *QQuickItemView::addDisplacedTransition() const
{
Q_D(const QQuickItemView);
- return d->addDisplacedTransition;
+ return d->transitioner ? d->transitioner->addDisplacedTransition : 0;
}
void QQuickItemView::setAddDisplacedTransition(QDeclarativeTransition *transition)
{
Q_D(QQuickItemView);
- if (d->addDisplacedTransition != transition) {
- d->addDisplacedTransition = transition;
+ d->createTransitioner();
+ if (d->transitioner->addDisplacedTransition != transition) {
+ d->transitioner->addDisplacedTransition = transition;
emit addDisplacedTransitionChanged();
}
}
@@ -1274,14 +644,15 @@ void QQuickItemView::setAddDisplacedTransition(QDeclarativeTransition *transitio
QDeclarativeTransition *QQuickItemView::moveTransition() const
{
Q_D(const QQuickItemView);
- return d->moveTransition;
+ return d->transitioner ? d->transitioner->moveTransition : 0;
}
void QQuickItemView::setMoveTransition(QDeclarativeTransition *transition)
{
Q_D(QQuickItemView);
- if (d->moveTransition != transition) {
- d->moveTransition = transition;
+ d->createTransitioner();
+ if (d->transitioner->moveTransition != transition) {
+ d->transitioner->moveTransition = transition;
emit moveTransitionChanged();
}
}
@@ -1289,14 +660,15 @@ void QQuickItemView::setMoveTransition(QDeclarativeTransition *transition)
QDeclarativeTransition *QQuickItemView::moveDisplacedTransition() const
{
Q_D(const QQuickItemView);
- return d->moveDisplacedTransition;
+ return d->transitioner ? d->transitioner->moveDisplacedTransition : 0;
}
void QQuickItemView::setMoveDisplacedTransition(QDeclarativeTransition *transition)
{
Q_D(QQuickItemView);
- if (d->moveDisplacedTransition != transition) {
- d->moveDisplacedTransition = transition;
+ d->createTransitioner();
+ if (d->transitioner->moveDisplacedTransition != transition) {
+ d->transitioner->moveDisplacedTransition = transition;
emit moveDisplacedTransitionChanged();
}
}
@@ -1304,14 +676,15 @@ void QQuickItemView::setMoveDisplacedTransition(QDeclarativeTransition *transiti
QDeclarativeTransition *QQuickItemView::removeTransition() const
{
Q_D(const QQuickItemView);
- return d->removeTransition;
+ return d->transitioner ? d->transitioner->removeTransition : 0;
}
void QQuickItemView::setRemoveTransition(QDeclarativeTransition *transition)
{
Q_D(QQuickItemView);
- if (d->removeTransition != transition) {
- d->removeTransition = transition;
+ d->createTransitioner();
+ if (d->transitioner->removeTransition != transition) {
+ d->transitioner->removeTransition = transition;
emit removeTransitionChanged();
}
}
@@ -1319,14 +692,15 @@ void QQuickItemView::setRemoveTransition(QDeclarativeTransition *transition)
QDeclarativeTransition *QQuickItemView::removeDisplacedTransition() const
{
Q_D(const QQuickItemView);
- return d->removeDisplacedTransition;
+ return d->transitioner ? d->transitioner->removeDisplacedTransition : 0;
}
void QQuickItemView::setRemoveDisplacedTransition(QDeclarativeTransition *transition)
{
Q_D(QQuickItemView);
- if (d->removeDisplacedTransition != transition) {
- d->removeDisplacedTransition = transition;
+ d->createTransitioner();
+ if (d->transitioner->removeDisplacedTransition != transition) {
+ d->transitioner->removeDisplacedTransition = transition;
emit removeDisplacedTransitionChanged();
}
}
@@ -1465,64 +839,6 @@ void QQuickItemViewPrivate::applyPendingChanges()
layout();
}
-bool QQuickItemViewPrivate::canTransition(FxViewItemTransitionManager::TransitionType type, bool asTarget) const
-{
- switch (type) {
- case FxViewItemTransitionManager::NoTransition:
- break;
- case FxViewItemTransitionManager::PopulateTransition:
- return usePopulateTransition
- && populateTransition && populateTransition->enabled();
- case FxViewItemTransitionManager::AddTransition:
- if (asTarget)
- return addTransition && addTransition->enabled();
- else
- return addDisplacedTransition && addDisplacedTransition->enabled();
- case FxViewItemTransitionManager::MoveTransition:
- if (asTarget)
- return moveTransition && moveTransition->enabled();
- else
- return moveDisplacedTransition && moveDisplacedTransition->enabled();
- case FxViewItemTransitionManager::RemoveTransition:
- if (asTarget)
- return removeTransition && removeTransition->enabled();
- else
- return removeDisplacedTransition && removeDisplacedTransition->enabled();
- }
- return false;
-}
-
-bool QQuickItemViewPrivate::hasItemTransitions() const
-{
- return canTransition(FxViewItemTransitionManager::PopulateTransition, true)
- || canTransition(FxViewItemTransitionManager::AddTransition, true)
- || canTransition(FxViewItemTransitionManager::AddTransition, false)
- || canTransition(FxViewItemTransitionManager::MoveTransition, true)
- || canTransition(FxViewItemTransitionManager::MoveTransition, false)
- || canTransition(FxViewItemTransitionManager::RemoveTransition, true)
- || canTransition(FxViewItemTransitionManager::RemoveTransition, false);
-}
-
-void QQuickItemViewPrivate::transitionNextReposition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, bool isTarget)
-{
- bool matchedTransition = false;
- if (type == FxViewItemTransitionManager::AddTransition) {
- // don't run add transitions for added items while populating
- matchedTransition = !usePopulateTransition && canTransition(type, isTarget);
- } else {
- matchedTransition = canTransition(type, isTarget);
- }
-
- if (matchedTransition) {
- item->setNextTransition(type, isTarget);
- } else {
- // the requested transition type is not valid, but the item is scheduled/in another
- // transition, so cancel it to allow the item to move directly to the correct pos
- if (item->transitionScheduledOrRunning())
- item->stopTransition();
- }
-}
-
int QQuickItemViewPrivate::findMoveKeyIndex(QDeclarativeChangeSet::MoveKey key, const QVector<QDeclarativeChangeSet::Remove> &changes) const
{
for (int i=0; i<changes.count(); i++) {
@@ -1583,8 +899,8 @@ void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &
// start new transitions
bool prevDisableLayout = disableLayout;
if (!disableLayout) {
- FxViewItem *actualItem = hasItemTransitions() ? visibleItem(currentIndex) : 0;
- if (actualItem && actualItem->transition && actualItem->transition->isRunning())
+ FxViewItem *actualItem = transitioner ? visibleItem(currentIndex) : 0;
+ if (actualItem && actualItem->transitionRunning())
disableLayout = true;
}
updateHighlight();
@@ -1602,7 +918,7 @@ void QQuickItemView::destroyRemoved()
it != d->visibleItems.end();) {
FxViewItem *item = *it;
if (item->index == -1 && item->attached->delayRemove() == false) {
- if (d->canTransition(FxViewItemTransitionManager::RemoveTransition, true)) {
+ if (d->transitioner && d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) {
// don't remove from visibleItems until next layout()
d->runDelayedRemoveTransition = true;
QObject::disconnect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()));
@@ -1626,7 +942,8 @@ void QQuickItemView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool r
{
Q_D(QQuickItemView);
if (reset) {
- d->usePopulateTransition = true;
+ if (d->transitioner)
+ d->transitioner->setPopulateTransitionEnabled(true);
d->moveReason = QQuickItemViewPrivate::SetIndex;
d->regenerate();
if (d->highlight && d->currentItem) {
@@ -1636,7 +953,7 @@ void QQuickItemView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool r
}
d->moveReason = QQuickItemViewPrivate::Other;
emit countChanged();
- if (d->populateTransition) {
+ if (d->transitioner && d->transitioner->populateTransition) {
d->forceLayout = true;
polish();
}
@@ -1936,7 +1253,8 @@ void QQuickItemView::componentComplete()
d->updateFooter();
d->updateViewport();
d->setPosition(d->contentStartOffset());
- d->usePopulateTransition = true;
+ if (d->transitioner)
+ d->transitioner->setPopulateTransitionEnabled(true);
if (d->isValid()) {
d->refill();
@@ -1972,19 +1290,21 @@ QQuickItemViewPrivate::QQuickItemViewPrivate()
, highlightRangeStart(0), highlightRangeEnd(0)
, highlightMoveDuration(150)
, headerComponent(0), header(0), footerComponent(0), footer(0)
- , populateTransition(0)
- , addTransition(0), addDisplacedTransition(0)
- , moveTransition(0), moveDisplacedTransition(0)
- , removeTransition(0), removeDisplacedTransition(0)
+ , transitioner(0)
, minExtent(0), maxExtent(0)
, ownModel(false), wrap(false)
, disableLayout(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false)
, haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
, fillCacheBuffer(false), inRequest(false), requestedAsync(false)
- , usePopulateTransition(false), runDelayedRemoveTransition(false)
+ , runDelayedRemoveTransition(false)
{
}
+QQuickItemViewPrivate::~QQuickItemViewPrivate()
+{
+ delete transitioner;
+}
+
bool QQuickItemViewPrivate::isValid() const
{
return model && model->count() && model->isValid();
@@ -2267,15 +1587,17 @@ void QQuickItemViewPrivate::layout()
if (!isValid() && !visibleItems.count()) {
clear();
setPosition(contentStartOffset());
- usePopulateTransition = false;
+ if (transitioner)
+ transitioner->setPopulateTransitionEnabled(false);
return;
}
- if (runDelayedRemoveTransition && canTransition(FxViewItemTransitionManager::RemoveTransition, false)) {
+ if (runDelayedRemoveTransition && transitioner
+ && transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) {
// assume that any items moving now are moving due to the remove - if they schedule
// a different transition, that will override this one anyway
for (int i=0; i<visibleItems.count(); i++)
- transitionNextReposition(visibleItems[i], FxViewItemTransitionManager::RemoveTransition, false);
+ transitioner->transitionNextReposition(visibleItems[i], QQuickItemViewTransitioner::RemoveTransition, false);
}
ChangeResult insertionPosChanges;
@@ -2289,9 +1611,9 @@ void QQuickItemViewPrivate::layout()
}
forceLayout = false;
- if (canTransition(FxViewItemTransitionManager::PopulateTransition, true)) {
+ if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) {
for (int i=0; i<visibleItems.count(); i++)
- transitionNextReposition(visibleItems.at(i), FxViewItemTransitionManager::PopulateTransition, true);
+ transitioner->transitionNextReposition(visibleItems.at(i), QQuickItemViewTransitioner::PopulateTransition, true);
}
layoutVisibleItems();
@@ -2310,11 +1632,11 @@ void QQuickItemViewPrivate::layout()
updateViewport();
updateUnrequestedPositions();
- if (hasItemTransitions()) {
+ if (transitioner) {
// items added in the last refill() may need to be transitioned in - e.g. a remove
// causes items to slide up into view
- if (canTransition(FxViewItemTransitionManager::MoveTransition, false)
- || canTransition(FxViewItemTransitionManager::RemoveTransition, false)) {
+ if (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, false)
+ || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) {
translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges);
}
@@ -2324,8 +1646,7 @@ void QQuickItemViewPrivate::layout()
for (QList<FxViewItem*>::Iterator it = releasePendingTransition.begin();
it != releasePendingTransition.end(); ) {
FxViewItem *item = *it;
- if ( (item->transition && item->transition->isActive())
- || prepareNonVisibleItemTransition(item, viewBounds)) {
+ if (item->transitionRunning() || prepareNonVisibleItemTransition(item, viewBounds)) {
++it;
} else {
releaseItem(item);
@@ -2334,11 +1655,12 @@ void QQuickItemViewPrivate::layout()
}
for (int i=0; i<visibleItems.count(); i++)
- visibleItems[i]->startTransition();
+ visibleItems[i]->startTransition(transitioner);
for (int i=0; i<releasePendingTransition.count(); i++)
- releasePendingTransition[i]->startTransition();
+ releasePendingTransition[i]->startTransition(transitioner);
+ transitioner->setPopulateTransitionEnabled(false);
}
- usePopulateTransition = false;
+
runDelayedRemoveTransition = false;
}
@@ -2441,7 +1763,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
// for each item that was moved directly into the view as a result of a move(),
// find the index it was moved from in order to set its initial position, so that we
// can transition it from this "original" position to its new position in the view
- if (canTransition(FxViewItemTransitionManager::MoveTransition, true)) {
+ if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true)) {
for (int i=0; i<movingIntoView.count(); i++) {
int fromIndex = findMoveKeyIndex(movingIntoView[i].moveKey, removals);
if (fromIndex >= 0) {
@@ -2449,7 +1771,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
repositionItemAt(movingIntoView[i].item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
else
repositionItemAt(movingIntoView[i].item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
- transitionNextReposition(movingIntoView[i].item, FxViewItemTransitionManager::MoveTransition, true);
+ transitioner->transitionNextReposition(movingIntoView[i].item, QQuickItemViewTransitioner::MoveTransition, true);
}
}
}
@@ -2513,10 +1835,12 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo
} else if (item->index >= removal.index + removal.count) {
// after removed items
item->index -= removal.count;
- if (removal.isMove())
- transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, false);
- else
- transitionNextReposition(item, FxViewItemTransitionManager::RemoveTransition, false);
+ if (transitioner) {
+ if (removal.isMove())
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::MoveTransition, false);
+ else
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::RemoveTransition, false);
+ }
++it;
} else {
// removed item
@@ -2550,7 +1874,8 @@ void QQuickItemViewPrivate::removeItem(FxViewItem *item, const QDeclarativeChang
}
if (removal.isMove()) {
currentChanges.removedItems.insert(removal.moveKey(item->index), item);
- transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, true);
+ if (transitioner)
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::MoveTransition, true);
} else {
// track item so it is released later
currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item);
@@ -2598,16 +1923,24 @@ void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirs
}
}
+void QQuickItemViewPrivate::createTransitioner()
+{
+ if (!transitioner) {
+ transitioner = new QQuickItemViewTransitioner;
+ transitioner->setChangeListener(this);
+ }
+}
+
void QQuickItemViewPrivate::prepareVisibleItemTransitions()
{
Q_Q(QQuickItemView);
- if (!hasItemTransitions())
+ if (!transitioner)
return;
- addTransitionIndexes.clear();
- addTransitionTargets.clear();
- moveTransitionIndexes.clear();
- moveTransitionTargets.clear();
+ transitioner->addTransitionIndexes.clear();
+ transitioner->addTransitionTargets.clear();
+ transitioner->moveTransitionIndexes.clear();
+ transitioner->moveTransitionTargets.clear();
QRectF viewBounds(0, position(), q->width(), q->height());
for (int i=0; i<visibleItems.count(); i++) {
@@ -2616,18 +1949,18 @@ void QQuickItemViewPrivate::prepareVisibleItemTransitions()
continue;
if (visibleItems[i]->isTransitionTarget) {
switch (visibleItems[i]->nextTransitionType) {
- case FxViewItemTransitionManager::NoTransition:
+ case QQuickItemViewTransitioner::NoTransition:
break;
- case FxViewItemTransitionManager::PopulateTransition:
- case FxViewItemTransitionManager::AddTransition:
- addTransitionIndexes.append(visibleItems[i]->index);
- addTransitionTargets.append(visibleItems[i]->item);
+ case QQuickItemViewTransitioner::PopulateTransition:
+ case QQuickItemViewTransitioner::AddTransition:
+ transitioner->addTransitionIndexes.append(visibleItems[i]->index);
+ transitioner->addTransitionTargets.append(visibleItems[i]->item);
break;
- case FxViewItemTransitionManager::MoveTransition:
- moveTransitionIndexes.append(visibleItems[i]->index);
- moveTransitionTargets.append(visibleItems[i]->item);
+ case QQuickItemViewTransitioner::MoveTransition:
+ transitioner->moveTransitionIndexes.append(visibleItems[i]->index);
+ transitioner->moveTransitionTargets.append(visibleItems[i]->item);
break;
- case FxViewItemTransitionManager::RemoveTransition:
+ case QQuickItemViewTransitioner::RemoveTransition:
// removed targets won't be in visibleItems, handle these
// in prepareNonVisibleItemTransition()
break;
@@ -2638,10 +1971,13 @@ void QQuickItemViewPrivate::prepareVisibleItemTransitions()
void QQuickItemViewPrivate::prepareRemoveTransitions(QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *> *removedItems)
{
- removeTransitionIndexes.clear();
- removeTransitionTargets.clear();
+ if (!transitioner)
+ return;
- if (canTransition(FxViewItemTransitionManager::RemoveTransition, true)) {
+ transitioner->removeTransitionIndexes.clear();
+ transitioner->removeTransitionTargets.clear();
+
+ if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) {
for (QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *>::Iterator it = removedItems->begin();
it != removedItems->end(); ) {
bool isRemove = it.key().moveId < 0;
@@ -2649,7 +1985,7 @@ void QQuickItemViewPrivate::prepareRemoveTransitions(QHash<QDeclarativeChangeSet
FxViewItem *item = *it;
item->releaseAfterTransition = true;
releasePendingTransition.append(item);
- transitionNextReposition(item, FxViewItemTransitionManager::RemoveTransition, true);
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::RemoveTransition, true);
it = removedItems->erase(it);
} else {
++it;
@@ -2665,18 +2001,21 @@ bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item, co
// removed, or moved to outside of the view, as well as those that are
// displaced to a position outside of the view due to an insert or move.
- if (item->nextTransitionType == FxViewItemTransitionManager::MoveTransition)
+ if (!transitioner)
+ return false;
+
+ if (item->nextTransitionType == QQuickItemViewTransitioner::MoveTransition)
repositionItemAt(item, item->index, 0);
if (!item->prepareTransition(viewBounds))
return false;
if (item->isTransitionTarget) {
- if (item->nextTransitionType == FxViewItemTransitionManager::MoveTransition) {
- moveTransitionIndexes.append(item->index);
- moveTransitionTargets.append(item->item);
- } else if (item->nextTransitionType == FxViewItemTransitionManager::RemoveTransition) {
- removeTransitionIndexes.append(item->index);
- removeTransitionTargets.append(item->item);
+ if (item->nextTransitionType == QQuickItemViewTransitioner::MoveTransition) {
+ transitioner->moveTransitionIndexes.append(item->index);
+ transitioner->moveTransitionTargets.append(item->item);
+ } else if (item->nextTransitionType == QQuickItemViewTransitioner::RemoveTransition) {
+ transitioner->removeTransitionIndexes.append(item->index);
+ transitioner->removeTransitionTargets.append(item->item);
}
}
@@ -2684,6 +2023,15 @@ bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item, co
return true;
}
+void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickViewItem *i)
+{
+ FxViewItem *item = static_cast<FxViewItem *>(i);
+ if (item->releaseAfterTransition) {
+ releasePendingTransition.removeOne(item);
+ releaseItem(item);
+ }
+}
+
/*
This may return 0 if the item is being created asynchronously.
When the item becomes available, refill() will be called and the item
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
index 0d3cd1c3ce..63262f32ab 100644
--- a/src/quick/items/qquickitemview_p.h
+++ b/src/quick/items/qquickitemview_p.h
@@ -324,53 +324,9 @@ public:
QString m_nextSection;
};
-class QQuickViewTransitionAttached : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
- Q_PROPERTY(QQuickItem* item READ item NOTIFY itemChanged)
- Q_PROPERTY(QPointF destination READ destination NOTIFY destinationChanged)
-
- Q_PROPERTY(QList<int> targetIndexes READ targetIndexes NOTIFY targetIndexesChanged)
- Q_PROPERTY(QDeclarativeListProperty<QObject> targetItems READ targetItems NOTIFY targetItemsChanged)
-
-public:
- QQuickViewTransitionAttached(QObject *parent);
-
- int index() const { return m_index; }
- QQuickItem *item() const { return m_item; }
- QPointF destination() const { return m_destination; }
-
- QList<int> targetIndexes() const { return m_targetIndexes; }
- QDeclarativeListProperty<QObject> targetItems();
-
- static QQuickViewTransitionAttached *qmlAttachedProperties(QObject *);
-
-signals:
- void indexChanged();
- void itemChanged();
- void destinationChanged();
-
- void targetIndexesChanged();
- void targetItemsChanged();
-
-private:
- friend class FxViewItemTransitionManager;
- int m_index;
- QQuickItem *m_item;
- QPointF m_destination;
-
- QList<int> m_targetIndexes;
- QList<QObject *> m_targetItems;
-};
-
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickViewTransitionAttached)
-QML_DECLARE_TYPEINFO(QQuickViewTransitionAttached, QML_HAS_ATTACHED_PROPERTIES)
-
QT_END_HEADER
#endif // QQUICKITEMVIEW_P_H
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index fce6e4eba5..57860a43c6 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -43,10 +43,10 @@
#define QQUICKITEMVIEW_P_P_H
#include "qquickitemview_p.h"
+#include "qquickitemviewtransition_p.h"
#include "qquickflickable_p_p.h"
#include "qquickvisualdatamodel_p.h"
#include "qquickvisualitemmodel_p.h"
-#include <private/qdeclarativetransitionmanager_p_p.h>
#include <private/qdeclarativechangeset_p.h>
@@ -57,55 +57,12 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class FxViewItem;
-class FxViewItemTransitionManager : public QDeclarativeTransitionManager
-{
-public:
- enum TransitionType {
- NoTransition,
- PopulateTransition,
- AddTransition,
- MoveTransition,
- RemoveTransition
- };
-
- FxViewItemTransitionManager();
- ~FxViewItemTransitionManager();
-
- bool isActive() const;
- void startTransition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, const QPointF &to, bool isTargetItem);
-
- bool m_active;
- FxViewItem *m_item;
- QPointF m_toPos;
- FxViewItemTransitionManager::TransitionType m_type;
- bool m_isTarget;
-
-protected:
- virtual void finished();
-};
-
-
-class FxViewItem
+class FxViewItem : public QQuickViewItem
{
public:
FxViewItem(QQuickItem *, bool own);
virtual ~FxViewItem();
- qreal itemX() const;
- qreal itemY() const;
-
- void setVisible(bool visible);
-
- void setNextTransition(FxViewItemTransitionManager::TransitionType, bool isTargetItem);
- bool transitionScheduledOrRunning() const;
- bool isPendingRemoval() const;
-
- bool prepareTransition(const QRectF &viewBounds);
- void startTransition();
- void stopTransition();
- void finishedTransition();
-
// these are positions and sizes along the current direction of scrolling/flicking
virtual qreal position() const = 0;
virtual qreal endPosition() const = 0;
@@ -113,23 +70,10 @@ public:
virtual qreal sectionSize() const = 0;
virtual bool contains(qreal x, qreal y) const = 0;
- virtual QQuickItemView *itemView() const = 0;
- QQuickItem *item;
+ QQuickItemViewAttached *attached;
bool ownItem;
bool releaseAfterTransition;
- bool isTransitionTarget;
- bool nextTransitionToSet;
- int index;
- QQuickItemViewAttached *attached;
-
- FxViewItemTransitionManager *transition;
- QPointF nextTransitionTo;
- FxViewItemTransitionManager::TransitionType nextTransitionType;
-
-protected:
- void moveTo(const QPointF &pos);
- void resetTransitionData();
};
@@ -155,11 +99,12 @@ public:
};
-class QQuickItemViewPrivate : public QQuickFlickablePrivate
+class QQuickItemViewPrivate : public QQuickFlickablePrivate, public QQuickItemViewTransitionChangeListener
{
Q_DECLARE_PUBLIC(QQuickItemView)
public:
QQuickItemViewPrivate();
+ ~QQuickItemViewPrivate();
struct ChangeResult {
QDeclarativeNullableValue<qreal> visiblePos;
@@ -243,13 +188,12 @@ public:
void repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos,
FxViewItem *prevFirstVisible, ChangeResult *insertionResult, ChangeResult *removalResult);
+ void createTransitioner();
void prepareVisibleItemTransitions();
void prepareRemoveTransitions(QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *> *removedItems);
bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds);
+ virtual void viewItemTransitionFinished(QQuickViewItem *item);
- bool canTransition(FxViewItemTransitionManager::TransitionType type, bool asTarget) const;
- bool hasItemTransitions() const;
- void transitionNextReposition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, bool isTarget);
int findMoveKeyIndex(QDeclarativeChangeSet::MoveKey key, const QVector<QDeclarativeChangeSet::Remove> &changes) const;
void checkVisible() const;
@@ -281,7 +225,6 @@ public:
FxViewItem *requestedItem;
QQuickItemViewChangeSet currentChanges;
- // XXX split into struct
QDeclarativeComponent *highlightComponent;
FxViewItem *highlight;
int highlightRange; // enum value
@@ -294,27 +237,13 @@ public:
QDeclarativeComponent *footerComponent;
FxViewItem *footer;
- QDeclarativeTransition *populateTransition;
- QDeclarativeTransition *addTransition;
- QDeclarativeTransition *addDisplacedTransition;
- QDeclarativeTransition *moveTransition;
- QDeclarativeTransition *moveDisplacedTransition;
- QDeclarativeTransition *removeTransition;
- QDeclarativeTransition *removeDisplacedTransition;
-
- QList<int> addTransitionIndexes;
- QList<int> moveTransitionIndexes;
- QList<int> removeTransitionIndexes;
- QList<QObject *> addTransitionTargets;
- QList<QObject *> moveTransitionTargets;
- QList<QObject *> removeTransitionTargets;
-
struct MovedItem {
FxViewItem *item;
QDeclarativeChangeSet::MoveKey moveKey;
MovedItem(FxViewItem *i, QDeclarativeChangeSet::MoveKey k)
: item(i), moveKey(k) {}
};
+ QQuickItemViewTransitioner *transitioner;
QList<FxViewItem *> releasePendingTransition;
mutable qreal minExtent;
@@ -333,7 +262,6 @@ public:
bool fillCacheBuffer : 1;
bool inRequest : 1;
bool requestedAsync : 1;
- bool usePopulateTransition : 1;
bool runDelayedRemoveTransition : 1;
protected:
diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp
new file mode 100644
index 0000000000..3e3a99f553
--- /dev/null
+++ b/src/quick/items/qquickitemviewtransition.cpp
@@ -0,0 +1,770 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickitemviewtransition_p.h"
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qdeclarativetransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QQuickItemViewTransitionJob : public QDeclarativeTransitionManager
+{
+public:
+ QQuickItemViewTransitionJob(QQuickItemViewTransitioner *transitioner);
+ ~QQuickItemViewTransitionJob();
+
+ void startTransition(QQuickViewItem *item, QQuickItemViewTransitioner::TransitionType type, const QPointF &to, bool isTargetItem);
+
+ QQuickItemViewTransitioner *m_transitioner;
+ QQuickViewItem *m_item;
+ QPointF m_toPos;
+ QQuickItemViewTransitioner::TransitionType m_type;
+ bool m_isTarget;
+
+protected:
+ virtual void finished();
+};
+
+
+QQuickItemViewTransitionJob::QQuickItemViewTransitionJob(QQuickItemViewTransitioner *transitioner)
+ : m_transitioner(transitioner)
+ , m_item(0), m_type(QQuickItemViewTransitioner::NoTransition), m_isTarget(false)
+{
+}
+
+QQuickItemViewTransitionJob::~QQuickItemViewTransitionJob()
+{
+}
+
+void QQuickItemViewTransitionJob::startTransition(QQuickViewItem *item, QQuickItemViewTransitioner::TransitionType type, const QPointF &to, bool isTargetItem)
+{
+ if (!item) {
+ qWarning("startTransition(): invalid item");
+ return;
+ }
+
+ QDeclarativeTransition *trans = 0;
+ switch (type) {
+ case QQuickItemViewTransitioner::NoTransition:
+ break;
+ case QQuickItemViewTransitioner::PopulateTransition:
+ trans = m_transitioner->populateTransition;
+ break;
+ case QQuickItemViewTransitioner::AddTransition:
+ trans = isTargetItem ? m_transitioner->addTransition : m_transitioner->addDisplacedTransition;
+ break;
+ case QQuickItemViewTransitioner::MoveTransition:
+ trans = isTargetItem ? m_transitioner->moveTransition : m_transitioner->moveDisplacedTransition;
+ break;
+ case QQuickItemViewTransitioner::RemoveTransition:
+ trans = isTargetItem ? m_transitioner->removeTransition : m_transitioner->removeDisplacedTransition;
+ break;
+ }
+
+ if (!trans) {
+ qWarning("QQuickItemView: invalid view transition!");
+ return;
+ }
+
+ m_item = item;
+ m_toPos = to;
+ m_type = type;
+ m_isTarget = isTargetItem;
+
+ QQuickViewTransitionAttached *attached =
+ static_cast<QQuickViewTransitionAttached*>(qmlAttachedPropertiesObject<QQuickViewTransitionAttached>(trans));
+ if (attached) {
+ attached->m_index = item->index;
+ attached->m_item = item->item;
+ attached->m_destination = to;
+ switch (type) {
+ case QQuickItemViewTransitioner::NoTransition:
+ break;
+ case QQuickItemViewTransitioner::PopulateTransition:
+ case QQuickItemViewTransitioner::AddTransition:
+ attached->m_targetIndexes = m_transitioner->addTransitionIndexes;
+ attached->m_targetItems = m_transitioner->addTransitionTargets;
+ break;
+ case QQuickItemViewTransitioner::MoveTransition:
+ attached->m_targetIndexes = m_transitioner->moveTransitionIndexes;
+ attached->m_targetItems = m_transitioner->moveTransitionTargets;
+ break;
+ case QQuickItemViewTransitioner::RemoveTransition:
+ attached->m_targetIndexes = m_transitioner->removeTransitionIndexes;
+ attached->m_targetItems = m_transitioner->removeTransitionTargets;
+ break;
+ }
+ emit attached->indexChanged();
+ emit attached->itemChanged();
+ emit attached->destinationChanged();
+ emit attached->targetIndexesChanged();
+ emit attached->targetItemsChanged();
+ }
+
+ QDeclarativeStateOperation::ActionList actions;
+ actions << QDeclarativeAction(item->item, QLatin1String("x"), QVariant(to.x()));
+ actions << QDeclarativeAction(item->item, QLatin1String("y"), QVariant(to.y()));
+
+ QDeclarativeTransitionManager::transition(actions, trans, item->item);
+}
+
+void QQuickItemViewTransitionJob::finished()
+{
+ QDeclarativeTransitionManager::finished();
+
+ if (m_item)
+ m_item->finishedTransition();
+ if (m_transitioner)
+ m_transitioner->finishedTransition(m_item);
+
+ m_item = 0;
+ m_toPos.setX(0);
+ m_toPos.setY(0);
+ m_type = QQuickItemViewTransitioner::NoTransition;
+ m_isTarget = false;
+}
+
+
+QQuickItemViewTransitioner::QQuickItemViewTransitioner()
+ : populateTransition(0)
+ , addTransition(0), addDisplacedTransition(0)
+ , moveTransition(0), moveDisplacedTransition(0)
+ , removeTransition(0), removeDisplacedTransition(0)
+ , changeListener(0)
+ , usePopulateTransition(false)
+{
+}
+
+bool QQuickItemViewTransitioner::canTransition(QQuickItemViewTransitioner::TransitionType type, bool asTarget) const
+{
+ switch (type) {
+ case QQuickItemViewTransitioner::NoTransition:
+ break;
+ case QQuickItemViewTransitioner::PopulateTransition:
+ return usePopulateTransition
+ && populateTransition && populateTransition->enabled();
+ case QQuickItemViewTransitioner::AddTransition:
+ if (asTarget)
+ return addTransition && addTransition->enabled();
+ else
+ return addDisplacedTransition && addDisplacedTransition->enabled();
+ case QQuickItemViewTransitioner::MoveTransition:
+ if (asTarget)
+ return moveTransition && moveTransition->enabled();
+ else
+ return moveDisplacedTransition && moveDisplacedTransition->enabled();
+ case QQuickItemViewTransitioner::RemoveTransition:
+ if (asTarget)
+ return removeTransition && removeTransition->enabled();
+ else
+ return removeDisplacedTransition && removeDisplacedTransition->enabled();
+ }
+ return false;
+}
+
+void QQuickItemViewTransitioner::transitionNextReposition(QQuickViewItem *item, QQuickItemViewTransitioner::TransitionType type, bool isTarget)
+{
+ bool matchedTransition = false;
+ if (type == QQuickItemViewTransitioner::AddTransition) {
+ // don't run add transitions for added items while populating
+ if (usePopulateTransition)
+ matchedTransition = false;
+ else
+ matchedTransition = canTransition(type, isTarget);
+ } else {
+ matchedTransition = canTransition(type, isTarget);
+ }
+
+ if (matchedTransition) {
+ item->setNextTransition(type, isTarget);
+ } else {
+ // the requested transition type is not valid, but the item is scheduled/in another
+ // transition, so cancel it to allow the item to move directly to the correct pos
+ if (item->transitionScheduledOrRunning())
+ item->stopTransition();
+ }
+}
+
+void QQuickItemViewTransitioner::finishedTransition(QQuickViewItem *item)
+{
+ if (changeListener)
+ changeListener->viewItemTransitionFinished(item);
+}
+
+
+QQuickViewItem::QQuickViewItem(QQuickItem *i)
+ : item(i)
+ , transition(0)
+ , nextTransitionType(QQuickItemViewTransitioner::NoTransition)
+ , index(-1)
+ , isTransitionTarget(false)
+ , nextTransitionToSet(false)
+{
+}
+
+QQuickViewItem::~QQuickViewItem()
+{
+ if (transition) {
+ transition->m_item = 0;
+ transition->m_transitioner = 0;
+ }
+ delete transition;
+}
+
+qreal QQuickViewItem::itemX() const
+{
+ if (nextTransitionType != QQuickItemViewTransitioner::NoTransition)
+ return nextTransitionToSet ? nextTransitionTo.x() : item->x();
+ else if (transition && transition->isRunning())
+ return transition->m_toPos.x();
+ else
+ return item->x();
+}
+
+qreal QQuickViewItem::itemY() const
+{
+ // If item is transitioning to some pos, return that dest pos.
+ // If item was redirected to some new pos before the current transition finished,
+ // return that new pos.
+ if (nextTransitionType != QQuickItemViewTransitioner::NoTransition)
+ return nextTransitionToSet ? nextTransitionTo.y() : item->y();
+ else if (transition && transition->isRunning())
+ return transition->m_toPos.y();
+ else
+ return item->y();
+}
+
+void QQuickViewItem::moveTo(const QPointF &pos)
+{
+ if (transitionScheduledOrRunning()) {
+ nextTransitionTo = pos;
+ nextTransitionToSet = true;
+ } else {
+ item->setPos(pos);
+ }
+}
+
+void QQuickViewItem::setVisible(bool visible)
+{
+ if (!visible && transitionScheduledOrRunning())
+ return;
+ item->setVisible(visible);
+}
+
+bool QQuickViewItem::transitionScheduledOrRunning() const
+{
+ return (transition && transition->isRunning())
+ || nextTransitionType != QQuickItemViewTransitioner::NoTransition;
+}
+
+bool QQuickViewItem::transitionRunning() const
+{
+ return (transition && transition->isRunning());
+}
+
+bool QQuickViewItem::isPendingRemoval() const
+{
+ if (nextTransitionType == QQuickItemViewTransitioner::RemoveTransition)
+ return isTransitionTarget;
+ if (transition && transition->isRunning() && transition->m_type == QQuickItemViewTransitioner::RemoveTransition)
+ return transition->m_isTarget;
+ return false;
+}
+
+bool QQuickViewItem::prepareTransition(const QRectF &viewBounds)
+{
+ bool doTransition = false;
+
+ switch (nextTransitionType) {
+ case QQuickItemViewTransitioner::NoTransition:
+ {
+ return false;
+ }
+ case QQuickItemViewTransitioner::PopulateTransition:
+ {
+ return true;
+ }
+ case QQuickItemViewTransitioner::AddTransition:
+ case QQuickItemViewTransitioner::RemoveTransition:
+ // For Add targets, do transition if item is moving into visible area
+ // For Remove targets, do transition if item is currently in visible area
+ if (isTransitionTarget) {
+ doTransition = (nextTransitionType == QQuickItemViewTransitioner::AddTransition)
+ ? viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))
+ : viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()));
+ if (!doTransition)
+ item->setPos(nextTransitionTo);
+ } else {
+ if (viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()))
+ || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))) {
+ doTransition = (nextTransitionTo != item->pos());
+ } else {
+ item->setPos(nextTransitionTo);
+ }
+ }
+ break;
+ case QQuickItemViewTransitioner::MoveTransition:
+ // do transition if moving from or into visible area
+ if (nextTransitionTo != item->pos()) {
+ doTransition = viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()))
+ || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()));
+ if (!doTransition)
+ item->setPos(nextTransitionTo);
+ }
+ break;
+ }
+
+ if (!doTransition)
+ resetTransitionData();
+ return doTransition;
+}
+
+void QQuickViewItem::startTransition(QQuickItemViewTransitioner *transitioner)
+{
+ if (nextTransitionType == QQuickItemViewTransitioner::NoTransition)
+ return;
+
+ if (!transition || transition->m_type != nextTransitionType || transition->m_isTarget != isTransitionTarget) {
+ delete transition;
+ transition = new QQuickItemViewTransitionJob(transitioner);
+ }
+
+ // if item is not already moving somewhere, set it to not move anywhere
+ // so that removed items do not move to the default (0,0)
+ if (!nextTransitionToSet)
+ moveTo(item->pos());
+
+ transition->startTransition(this, nextTransitionType, nextTransitionTo, isTransitionTarget);
+ nextTransitionType = QQuickItemViewTransitioner::NoTransition;
+}
+
+void QQuickViewItem::stopTransition()
+{
+ if (transition) {
+ transition->cancel();
+ delete transition;
+ transition = 0;
+ }
+ resetTransitionData();
+ finishedTransition();
+}
+
+void QQuickViewItem::setNextTransition(QQuickItemViewTransitioner::TransitionType type, bool isTargetItem)
+{
+ // Don't reset nextTransitionToSet - once it is set, it cannot be changed
+ // until the animation finishes since the itemX() and itemY() may be used
+ // to calculate positions for transitions for other items in the view.
+ nextTransitionType = type;
+ isTransitionTarget = isTargetItem;
+}
+
+void QQuickViewItem::finishedTransition()
+{
+ nextTransitionToSet = false;
+ nextTransitionTo = QPointF();
+}
+
+void QQuickViewItem::resetTransitionData()
+{
+ nextTransitionType = QQuickItemViewTransitioner::NoTransition;
+ isTransitionTarget = false;
+ nextTransitionTo = QPointF();
+ nextTransitionToSet = false;
+}
+
+
+QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent)
+ : QObject(parent), m_item(0), m_index(-1)
+{
+}
+/*!
+ \qmlclass ViewTransition QQuickViewTransitionAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-view-elements
+ \brief The ViewTransition attached property provides details on items under transition in a view.
+
+ With ListView and GridView, it is possible to specify transitions that should be applied whenever
+ the items in the view change as a result of modifications to the view's model. They both have the
+ following properties that can be set to the appropriate transitions to be run for various
+ operations:
+
+ \list
+ \o \c add and \c addDisplaced - the transitions to run when items are added to the view
+ \o \c remove and \c removeDisplaced - the transitions to run when items are removed from the view
+ \o \c move and \c moveDisplaced - the transitions to run when items are moved within the view
+ (i.e. as a result of a move operation in the model)
+ \o \c populate - the transition to run when a view is created, or when the model changes
+ \endlist
+
+ Such view transitions additionally have access to a ViewTransition attached property that
+ provides details of the items that are under transition and the operation that triggered the
+ transition. Since view transitions are run once per item, these details can be used to customise
+ each transition for each individual item.
+
+ The ViewTransition attached property provides the following properties specific to the item to
+ which the transition is applied:
+
+ \list
+ \o ViewTransition.item - the item that is under transition
+ \o ViewTransition.index - the index of this item
+ \o ViewTransition.destination - the (x,y) point to which this item is moving for the relevant view operation
+ \endlist
+
+ In addition, ViewTransition provides properties specific to the items which are the target
+ of the operation that triggered the transition:
+
+ \list
+ \o ViewTransition.targetIndexes - the indexes of the target items
+ \o ViewTransition.targetItems - the target items themselves
+ \endlist
+
+ View transitions can be written without referring to any of the attributes listed
+ above. These attributes merely provide extra details that are useful for customising view
+ transitions.
+
+ Following is an introduction to view transitions and the ways in which the ViewTransition
+ attached property can be used to augment view transitions.
+
+
+ \section2 View transitions: a simple example
+
+ Here is a basic example of the use of view transitions. The view below specifies transitions for
+ the \c add and \c addDisplaced properties, which will be run when items are added to the view:
+
+ \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0
+
+ When the space key is pressed, adding an item to the model, the new item will fade in and
+ increase in scale over 400 milliseconds as it is added to the view. Also, any item that is
+ displaced by the addition of a new item will animate to its new position in the view over
+ 400 milliseconds, as specified by the \c addDisplaced transition.
+
+ If five items were inserted in succession at index 0, the effect would be this:
+
+ \image viewtransitions-basic.gif
+
+ Notice that the NumberAnimation objects above do not need to specify a \c target to animate
+ the appropriate item. Also, the NumberAnimation in the \c addTransition does not need to specify
+ the \c to value to move the item to its correct position in the view. This is because the view
+ implicitly sets the \c target and \c to values with the correct item and final item position
+ values if these properties are not explicitly defined.
+
+ At its simplest, a view transition may just animate an item to its new position following a
+ view operation, just as the \c addDisplaced transition does above, or animate some item properties,
+ as in the \c add transition above. Additionally, a view transition may make use of the
+ ViewTransition attached property to customise animation behavior for different items. Following
+ are some examples of how this can be achieved.
+
+
+ \section2 Using the ViewTransition attached property
+
+ As stated, the various ViewTransition properties provide details specific to the individual item
+ being transitioned as well as the operation that triggered the transition. In the animation above,
+ five items are inserted in succession at index 0. When the fifth and final insertion takes place,
+ adding "Item 4" to the view, the \c add transition is run once (for the inserted item) and the
+ \c addDisplaced transition is run four times (once for each of the four existing items in the view).
+
+ At this point, if we examined the \c addDisplaced transition that was run for the bottom displaced
+ item ("Item 0"), the ViewTransition property values provided to this transition would be as follows:
+
+ \table
+ \header
+ \o Property
+ \o Value
+ \o Explanation
+ \row
+ \o ViewTransition.item
+ \o "Item 0" delegate instance
+ \o The "Item 0" \l Rectangle object itself
+ \row
+ \o ViewTransition.index
+ \o \c int value of 4
+ \o The index of "Item 0" within the model following the add operation
+ \row
+ \o ViewTransition.destination
+ \o \l point value of (0, 120)
+ \o The position that "Item 0" is moving to
+ \row
+ \o ViewTransition.targetIndexes
+ \o \c int array, just contains the integer "0" (zero)
+ \o The index of "Item 4", the new item added to the view
+ \row
+ \o ViewTransition.targetItems
+ \o object array, just contains the "Item 4" delegate instance
+ \o The "Item 4" \l Rectangle object - the new item added to the view
+ \endtable
+
+ The ViewTransition.targetIndexes and ViewTransition.targetItems lists provide the items and
+ indexes of all delegate instances that are the targets of the relevant operation. For an add
+ operation, these are all the items that are added into the view; for a remove, these are all
+ the items removed from the view, and so on. (Note these lists will only contain references to
+ items that have been created within the view or its cached items; targets that are not within
+ the visible area of the view or within the item cache will not be accessible.)
+
+ So, while the ViewTransition.item, ViewTransition.index and ViewTransition.destination values
+ vary for each individual transition that is run, the ViewTransition.targetIndexes and
+ ViewTransition.targetItems values are the same for every \c add and \c addDisplaced transition
+ that is triggered by a particular add operation.
+
+
+ \section3 Delaying animations based on index
+
+ Since each view transition is run once for each item affected by the transition, the ViewTransition
+ properties can be used within a transition to define custom behavior for each item's transition.
+ For example, the ListView in the previous example could use this information to create a ripple-type
+ effect on the movement of the displaced items.
+
+ This can be achieved by modifying the \c addDisplaced transition so that it delays the animation of
+ each displaced item based on the difference between its index (provided by ViewTransition.index)
+ and the first removed index (provided by ViewTransition.targetIndexes):
+
+ \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml 0
+
+ Each displaced item delays its animation by an additional 100 milliseconds, producing a subtle
+ ripple-type effect when items are displaced by the add, like this:
+
+ \image viewtransitions-delayedbyindex.gif
+
+
+ \section3 Animating items to intermediate positions
+
+ The ViewTransition.item property gives a reference to the item to which the transition is being
+ applied. This can be used to access any of the item's attributes, custom \c property values,
+ and so on.
+
+ Below is a modification of the \c addDisplaced transition from the previous example. It adds a
+ ParallelAnimation with nested NumberAnimation objects that reference ViewTransition.item to access
+ each item's \c x and \c y values at the start of their transitions. This allows each item to
+ animate to an intermediate position relative to its starting point for the transition, before
+ animating to its final position in the view:
+
+ \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml 0
+
+ Now, a displaced item will first move to a position of (20, 50) relative to its starting
+ position, and then to its final, correct position in the view:
+
+ \image viewtransitions-intermediatemove.gif
+
+ Since the final NumberAnimation does not specify a \c to value, the view implicitly sets this
+ value to the item's final position in the view, and so this last animation will move this item
+ to the correct place. If the transition requires the final position of the item for some calculation,
+ this is accessible through ViewTransition.destination.
+
+ Instead of using multiple NumberAnimations, you could use a PathAnimation to animate an item over
+ a curved path. For example, the \c add transition in the previous example could be augmented with
+ a PathAnimation as follows: to animate newly added items along a path:
+
+ \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml 0
+
+ This animates newly added items along a path. Notice that each path is specified relative to
+ each item's final destination point, so that items inserted at different indexes start their
+ paths from different positions:
+
+ \image viewtransitions-pathanim.gif
+
+
+ \section2 Handling interrupted animations
+
+ A view transition may be interrupted at any time if a different view transition needs to be
+ applied while the original transition is in progress. For example, say Item A is inserted at index 0
+ and undergoes an "add" transition; then, Item B is inserted at index 0 in quick succession before
+ Item A's transition has finished. Since Item B is inserted before Item A, it will displace Item
+ A, causing the view to interrupt Item A's "add" transition mid-way and start an "addDisplaced"
+ transition on Item A instead.
+
+ For simple animations that simply animate an item's movement to its final destination, this
+ interruption is unlikely to require additional consideration. However, if a transition changes other
+ properties, this interruption may cause unwanted side effects. Consider the first example on this
+ page, repeated below for convenience:
+
+ \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0
+
+ If multiple items are added in rapid succession, without waiting for a previous transition
+ to finish, this is the result:
+
+ \image viewtransitions-interruptedbad.gif
+
+ Each newly added item undergoes an \c add transition, but before the transition can finish,
+ another item is added, displacing the previously added item. Because of this, the \c add
+ transition on the previously added item is interrupted and an \c addDisplaced transition is
+ started on the item instead. Due to the interruption, the \c opacity and \c scale animations
+ have not completed, thus producing items with opacity and scale that are below 1.0.
+
+ To fix this, the \c addDisplaced transition should additionally ensure the item properties are
+ set to the end values specified in the \c add transition, effectively resetting these values
+ whenever an item is displaced. In this case, it means setting the item opacity and scale to 1.0:
+
+ \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml 0
+
+ Now, when an item's \c add transition is interrupted, its opacity and scale are animated to 1.0
+ upon displacement, avoiding the erroneous visual effects from before:
+
+ \image viewtransitions-interruptedgood.gif
+
+ The same principle applies to any combination of view transitions. An added item may be moved
+ before its add transition finishes, or a moved item may be removed before its moved transition
+ finishes, and so on; so, the rule of thumb is that every transition should handle the same set of
+ properties.
+
+
+ \section2 Restrictions regarding ScriptAction
+
+ When a view transition is initialized, any property bindings that refer to the ViewTransition
+ attached property are evaluated in preparation for the transition. Due to the nature of the
+ internal construction of a view transition, the attributes of the ViewTransition attached
+ property are only valid for the relevant item when the transition is initialized, and may not be
+ valid when the transition is actually run.
+
+ Therefore, a ScriptAction within a view transition should not refer to the ViewTransition
+ attached property, as it may not refer to the expected values at the time that the ScriptAction
+ is actually invoked. Consider the following example:
+
+ \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml 0
+
+ When the space key is pressed, three items are moved from index 5 to index 1. For each moved
+ item, the \c moveTransition sequence presumably animates the item's color to "yellow", then
+ animates it to its final position, then changes the item color back to "lightsteelblue" using a
+ ScriptAction. However, when run, the transition does not produce the intended result:
+
+ \image viewtransitions-scriptactionbad.gif
+
+ Only the last moved item is returned to the "lightsteelblue" color; the others remain yellow. This
+ is because the ScriptAction is not run until after the transition has already been initialized, by
+ which time the ViewTransition.item value has changed to refer to a different item; the item that
+ the script had intended to refer to is not the one held by ViewTransition.item at the time the
+ ScriptAction is actually invoked.
+
+ In this instance, to avoid this issue, the view could set the property using a PropertyAction
+ instead:
+
+ \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml 0
+
+ When the transition is initialized, the PropertyAction \c target will be set to the respective
+ ViewTransition.item for the transition and will later run with the correct item target as
+ expected.
+ */
+
+/*!
+ \qmlattachedproperty list QtQuick2::ViewTransition::index
+
+ This attached property holds the index of the item that is being
+ transitioned.
+
+ Note that if the item is being moved, this property holds the index that
+ the item is moving to, not from.
+*/
+
+/*!
+ \qmlattachedproperty list QtQuick2::ViewTransition::item
+
+ This attached property holds the the item that is being transitioned.
+
+ \warning This item should not be kept and referred to outside of the transition
+ as it may become invalid as the view changes.
+*/
+
+/*!
+ \qmlattachedproperty list QtQuick2::ViewTransition::destination
+
+ This attached property holds the final destination position for the transitioned
+ item within the view.
+
+ This property value is a \l point with \c x and \c y properties.
+*/
+
+/*!
+ \qmlattachedproperty list QtQuick2::ViewTransition::targetIndexes
+
+ This attached property holds a list of the indexes of the items in view
+ that are the target of the relevant operation.
+
+ The targets are the items that are the subject of the operation. For
+ an add operation, these are the items being added; for a remove, these
+ are the items being removed; for a move, these are the items being
+ moved.
+
+ For example, if the transition was triggered by an insert operation
+ that added two items at index 1 and 2, this targetIndexes list would
+ have the value [1,2].
+
+ \note The targetIndexes list only contains the indexes of items that are actually
+ in view, or will be in the view once the relevant operation completes.
+
+ \sa QtQuick2::ViewTransition::targetIndexes
+*/
+
+/*!
+ \qmlattachedproperty list QtQuick2::ViewTransition::targetItems
+
+ This attached property holds the list of items in view that are the
+ target of the relevant operation.
+
+ The targets are the items that are the subject of the operation. For
+ an add operation, these are the items being added; for a remove, these
+ are the items being removed; for a move, these are the items being
+ moved.
+
+ For example, if the transition was triggered by an insert operation
+ that added two items at index 1 and 2, this targetItems list would
+ contain these two items.
+
+ \note The targetItems list only contains items that are actually
+ in view, or will be in the view once the relevant operation completes.
+
+ \warning The objects in this list should not be kept and referred to
+ outside of the transition as the items may become invalid. The targetItems
+ are only valid when the Transition is initially created; this also means
+ they should not be used by ScriptAction objects in the Transition, which are
+ not evaluated until the transition is run.
+
+ \sa QtQuick2::ViewTransition::targetIndexes
+*/
+QDeclarativeListProperty<QObject> QQuickViewTransitionAttached::targetItems()
+{
+ return QDeclarativeListProperty<QObject>(this, m_targetItems);
+}
+
+QQuickViewTransitionAttached *QQuickViewTransitionAttached::qmlAttachedProperties(QObject *obj)
+{
+ return new QQuickViewTransitionAttached(obj);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h
new file mode 100644
index 0000000000..c388bed17e
--- /dev/null
+++ b/src/quick/items/qquickitemviewtransition_p.h
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKITEMVIEWTRANSITION_P_P_H
+#define QQUICKITEMVIEWTRANSITION_P_P_H
+
+#include <private/qdeclarativetransitionmanager_p_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QQuickItem;
+class QQuickViewItem;
+class QQuickItemViewTransitionJob;
+
+
+class QQuickItemViewTransitionChangeListener
+{
+public:
+ QQuickItemViewTransitionChangeListener() {}
+ virtual ~QQuickItemViewTransitionChangeListener() {}
+
+ virtual void viewItemTransitionFinished(QQuickViewItem *item) = 0;
+};
+
+
+class QQuickItemViewTransitioner
+{
+public:
+ enum TransitionType {
+ NoTransition,
+ PopulateTransition,
+ AddTransition,
+ MoveTransition,
+ RemoveTransition
+ };
+
+ QQuickItemViewTransitioner();
+ virtual ~QQuickItemViewTransitioner() {}
+
+ bool canTransition(QQuickItemViewTransitioner::TransitionType type, bool asTarget) const;
+ void transitionNextReposition(QQuickViewItem *item, QQuickItemViewTransitioner::TransitionType type, bool isTarget);
+
+ inline void setPopulateTransitionEnabled(bool b) { usePopulateTransition = b; }
+ inline void setChangeListener(QQuickItemViewTransitionChangeListener *obj) { changeListener = obj; }
+
+ QList<int> addTransitionIndexes;
+ QList<int> moveTransitionIndexes;
+ QList<int> removeTransitionIndexes;
+ QList<QObject *> addTransitionTargets;
+ QList<QObject *> moveTransitionTargets;
+ QList<QObject *> removeTransitionTargets;
+
+ QDeclarativeTransition *populateTransition;
+ QDeclarativeTransition *addTransition;
+ QDeclarativeTransition *addDisplacedTransition;
+ QDeclarativeTransition *moveTransition;
+ QDeclarativeTransition *moveDisplacedTransition;
+ QDeclarativeTransition *removeTransition;
+ QDeclarativeTransition *removeDisplacedTransition;
+
+private:
+ friend class QQuickItemViewTransitionJob;
+
+ QQuickItemViewTransitionChangeListener *changeListener;
+ bool usePopulateTransition;
+
+ void finishedTransition(QQuickViewItem *item);
+};
+
+
+/*
+ An item in a view, that can be transitioned using QQuickViewTransitionJob.
+ */
+class QQuickViewItem
+{
+public:
+ QQuickViewItem(QQuickItem *i);
+ virtual ~QQuickViewItem();
+
+ qreal itemX() const;
+ qreal itemY() const;
+
+ void moveTo(const QPointF &pos);
+ void setVisible(bool visible);
+
+ bool transitionScheduledOrRunning() const;
+ bool transitionRunning() const;
+ bool isPendingRemoval() const;
+
+ bool prepareTransition(const QRectF &viewBounds);
+ void startTransition(QQuickItemViewTransitioner *transitioner);
+ void stopTransition();
+
+ QPointF nextTransitionTo;
+ QQuickItem *item;
+ QQuickItemViewTransitionJob *transition;
+ QQuickItemViewTransitioner::TransitionType nextTransitionType;
+ int index;
+ bool isTransitionTarget;
+ bool nextTransitionToSet;
+
+private:
+ friend class QQuickItemViewTransitioner;
+ friend class QQuickItemViewTransitionJob;
+ void setNextTransition(QQuickItemViewTransitioner::TransitionType, bool isTargetItem);
+ void finishedTransition();
+ void resetTransitionData();
+};
+
+
+class QQuickViewTransitionAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ Q_PROPERTY(QQuickItem* item READ item NOTIFY itemChanged)
+ Q_PROPERTY(QPointF destination READ destination NOTIFY destinationChanged)
+
+ Q_PROPERTY(QList<int> targetIndexes READ targetIndexes NOTIFY targetIndexesChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> targetItems READ targetItems NOTIFY targetItemsChanged)
+
+public:
+ QQuickViewTransitionAttached(QObject *parent);
+
+ int index() const { return m_index; }
+ QQuickItem *item() const { return m_item; }
+ QPointF destination() const { return m_destination; }
+
+ QList<int> targetIndexes() const { return m_targetIndexes; }
+ QDeclarativeListProperty<QObject> targetItems();
+
+ static QQuickViewTransitionAttached *qmlAttachedProperties(QObject *);
+
+signals:
+ void indexChanged();
+ void itemChanged();
+ void destinationChanged();
+
+ void targetIndexesChanged();
+ void targetItemsChanged();
+
+private:
+ friend class QQuickItemViewTransitionJob;
+ QPointF m_destination;
+ QList<int> m_targetIndexes;
+ QList<QObject *> m_targetItems;
+
+ QQuickItem *m_item;
+ int m_index;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickViewTransitionAttached)
+QML_DECLARE_TYPEINFO(QQuickViewTransitionAttached, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QQUICKITEMVIEWTRANSITION_P_P_H
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 0e643a13e3..2190952c69 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -316,9 +316,6 @@ public:
return (x >= itemX() && x < itemX() + item->width() &&
y >= itemY() && y < itemY() + item->height());
}
- QQuickItemView *itemView() const {
- return view;
- }
QQuickListView *view;
@@ -643,7 +640,7 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
#endif
if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, doBuffer))))
break;
- if (!canTransition(FxViewItemTransitionManager::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
+ if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(pos);
item->item->setVisible(!doBuffer);
pos += item->size() + spacing;
@@ -663,7 +660,7 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
break;
--visibleIndex;
visiblePos -= item->size() + spacing;
- if (!canTransition(FxViewItemTransitionManager::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
+ if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(visiblePos);
item->item->setVisible(!doBuffer);
visibleItems.prepend(item);
@@ -2341,6 +2338,10 @@ void QQuickListView::setSnapMode(SnapMode mode)
the new item that has been added to the view; to animate the added items, set the \l add
property.
+ If an item is displaced by multiple types of operations at the same time, it is not
+ defined as to whether the addDisplaced, moveDisplaced or removeDisplaced transition
+ will be applied.
+
For more details and examples on how to use view transitions, see the ViewTransition
documentation.
@@ -2405,6 +2406,10 @@ void QQuickListView::setSnapMode(SnapMode mode)
the items that are the actual subjects of the move operation; to animate the moved items, set
the \l move property.
+ If an item is displaced by multiple types of operations at the same time, it is not
+ defined as to whether the addDisplaced, moveDisplaced or removeDisplaced transition
+ will be applied.
+
For more details and examples on how to use view transitions, see the ViewTransition
documentation.
@@ -2472,6 +2477,10 @@ void QQuickListView::setSnapMode(SnapMode mode)
the item that has actually been removed from the view; to animate the removed items, set the
\l remove property.
+ If an item is displaced by multiple types of operations at the same time, it is not
+ defined as to whether the addDisplaced, moveDisplaced or removeDisplaced transition
+ will be applied.
+
For more details and examples on how to use view transitions, see the ViewTransition
documentation.
@@ -2740,7 +2749,8 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
insertResult->changedFirstItem = true;
if (!change.isMove()) {
addedItems->append(item);
- transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, true);
+ if (transitioner)
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, true);
}
insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing;
pos -= item->size() + spacing;
@@ -2766,11 +2776,12 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
if (change.isMove()) {
// we know this is a move target, since move displaced items that are
// shuffled into view due to a move would be added in refill()
- if (canTransition(FxViewItemTransitionManager::MoveTransition, true) && newItem)
+ if (newItem && transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true))
movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
} else {
addedItems->append(item);
- transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, true);
+ if (transitioner)
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, true);
}
insertResult->sizeChangesAfterVisiblePos += item->size() + spacing;
pos += item->size() + spacing;
@@ -2782,10 +2793,12 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
FxViewItem *item = visibleItems.at(index);
if (item->index != -1)
item->index += count;
- if (change.isMove())
- transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, false);
- else
- transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, false);
+ if (transitioner) {
+ if (change.isMove())
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::MoveTransition, false);
+ else
+ transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, false);
+ }
}
updateVisibleIndex();
@@ -2797,6 +2810,9 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
{
Q_UNUSED(insertionResult);
+ if (!transitioner)
+ return;
+
int markerItemIndex = -1;
for (int i=0; i<visibleItems.count(); i++) {
if (visibleItems[i]->index == afterModelIndex) {
@@ -2816,7 +2832,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
if (!listItem->transitionScheduledOrRunning()) {
qreal pos = listItem->position();
listItem->setPosition(pos - sizeRemoved);
- transitionNextReposition(listItem, FxViewItemTransitionManager::RemoveTransition, false);
+ transitioner->transitionNextReposition(listItem, QQuickItemViewTransitioner::RemoveTransition, false);
listItem->setPosition(pos);
}
}