aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBea Lam <bea.lam@nokia.com>2012-02-21 14:44:21 +1000
committerQt by Nokia <qt-info@nokia.com>2012-02-28 10:57:03 +0100
commit328c100ab3fc4d5ddccb0d19af9d7e87bd849f0b (patch)
tree5d20e04e97fc9818d966557a4115cde3ae505026 /src
parent60cae093d7e27e92198d626dc3df19dea9799faf (diff)
Separate view transition functionality into new file
Move most of the view transition functionality from qquickitemview* into qquickitemviewtransition*. - Move QQuickViewTransitionAttached - Move QQuickItemViewTransitionManager, rename to QQuickItemViewTransitionJob - Move FxViewItem transition-specific features into new QQuickViewItem - Move transition-specific functions like transitionNextReposition() and canTransition() into QQuickItemViewTransitioner which holds all the transition objects now Also mention in docs that there's no defined order for choosing between multiple matching displaced transitions. Change-Id: I8701c0d40d2af152c5d432a4c8de646854c76ea2 Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src')
-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);
}
}