diff options
author | Martin Jones <martin.jones@nokia.com> | 2010-02-18 06:06:36 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2010-02-18 06:06:36 (GMT) |
commit | 4630cca1d2c5fa0553f46cec3566b88e91215070 (patch) | |
tree | ca3ef0717f09c15cb686053b61b0fc2bf60f5a46 /src | |
parent | c8e266aaf21f470fd45ac61244466583b503fda2 (diff) | |
parent | f9cf46d7198a47cbe50bcbf315b9d0718439086b (diff) | |
download | Qt-4630cca1d2c5fa0553f46cec3566b88e91215070.zip Qt-4630cca1d2c5fa0553f46cec3566b88e91215070.tar.gz Qt-4630cca1d2c5fa0553f46cec3566b88e91215070.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-qml
Diffstat (limited to 'src')
-rw-r--r-- | src/declarative/graphicsitems/qmlgraphicsflipable.cpp | 2 | ||||
-rw-r--r-- | src/declarative/graphicsitems/qmlgraphicspositioners.cpp | 8 | ||||
-rw-r--r-- | src/declarative/util/qmlanimation.cpp | 928 | ||||
-rw-r--r-- | src/declarative/util/qmlanimation_p.h | 56 | ||||
-rw-r--r-- | src/declarative/util/qmlanimation_p_p.h | 50 | ||||
-rw-r--r-- | src/declarative/util/qmlbehavior.cpp | 8 | ||||
-rw-r--r-- | src/declarative/util/qmlstateoperations.cpp | 2 | ||||
-rw-r--r-- | src/declarative/util/qmltransition.cpp | 9 |
8 files changed, 583 insertions, 480 deletions
diff --git a/src/declarative/graphicsitems/qmlgraphicsflipable.cpp b/src/declarative/graphicsitems/qmlgraphicsflipable.cpp index 4116817..6857eae 100644 --- a/src/declarative/graphicsitems/qmlgraphicsflipable.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsflipable.cpp @@ -94,7 +94,7 @@ public: } transitions: Transition { - NumberAnimation { matchProperties: "angle"; duration: 2000 } + NumberAnimation { properties: "angle"; duration: 2000 } } MouseRegion { diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp index 142cdce..4905a30 100644 --- a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp +++ b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp @@ -361,7 +361,7 @@ Column { Column { move: Transition { NumberAnimation { - matchProperties: "y" + properties: "y" ease: "easeOutBounce" } } @@ -470,7 +470,7 @@ Row { id: positioner move: Transition { NumberAnimation { - matchProperties: "x" + properties: "x" ease: "easeOutBounce" } } @@ -592,7 +592,7 @@ Grid { Grid { move: Transition { NumberAnimation { - matchProperties: "x,y" + properties: "x,y" ease: "easeOutBounce" } } @@ -737,7 +737,7 @@ Flow { id: positioner move: Transition { NumberAnimation { - matchProperties: "x,y" + properties: "x,y" ease: "easeOutBounce" } } diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index 6609c73..249bd8e 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -210,11 +210,16 @@ bool QmlAbstractAnimation::isRunning() const return d->running; } +//commence is called to start an animation when it is used as a +//simple animation, and not as part of a transition void QmlAbstractAnimationPrivate::commence() { Q_Q(QmlAbstractAnimation); - q->prepare(userProperty.value); + QmlStateActions actions; + QmlMetaProperties properties; + q->transition(actions, properties, QmlAbstractAnimation::Forward); + q->qtAnimation()->start(); if (q->qtAnimation()->state() != QAbstractAnimation::Running) { running = false; @@ -238,14 +243,17 @@ QmlMetaProperty QmlAbstractAnimationPrivate::createProperty(QObject *obj, const void QmlAbstractAnimation::setRunning(bool r) { Q_D(QmlAbstractAnimation); - - if (r == false) - d->avoidPropertyValueSourceStart = true; + if (!d->componentComplete) { + d->running = r; + if (r == false) + d->avoidPropertyValueSourceStart = true; + return; + } if (d->running == r) return; - if (d->group) { + if (d->group || d->disableUserControl) { qWarning("QmlAbstractAnimation: setRunning() cannot be used on non-root animation nodes"); return; } @@ -262,10 +270,7 @@ void QmlAbstractAnimation::setRunning(bool r) this, SLOT(timelineComplete())); d->connectedTimeLine = true; } - if (d->componentComplete) - d->commence(); - else - d->startOnCompletion = true; + d->commence(); emit started(); } else { if (d->alwaysRunToEnd) { @@ -304,7 +309,7 @@ void QmlAbstractAnimation::setPaused(bool p) if (d->paused == p) return; - if (d->group) { + if (d->group || d->disableUserControl) { qWarning("QmlAbstractAnimation: setPaused() cannot be used on non-root animation nodes"); return; } @@ -315,7 +320,7 @@ void QmlAbstractAnimation::setPaused(bool p) else qtAnimation()->resume(); - emit pausedChanged(d->running); + emit pausedChanged(d->paused); } void QmlAbstractAnimation::classBegin() @@ -327,9 +332,11 @@ void QmlAbstractAnimation::classBegin() void QmlAbstractAnimation::componentComplete() { Q_D(QmlAbstractAnimation); - if (d->startOnCompletion) - d->commence(); d->componentComplete = true; + if (d->running) { + d->running = false; + setRunning(true); + } } /*! @@ -534,17 +541,32 @@ void QmlAbstractAnimation::complete() void QmlAbstractAnimation::setTarget(const QmlMetaProperty &p) { Q_D(QmlAbstractAnimation); - if (d->userProperty.isNull) - d->userProperty = p; + d->defaultProperty = p; if (!d->avoidPropertyValueSourceStart) setRunning(true); } -//prepare is called before an animation begins -//(when an animation is used as a simple animation, and not as part of a transition) -void QmlAbstractAnimation::prepare(QmlMetaProperty &) +/* + we rely on setTarget only being called when used as a value source + so this function allows us to do the same thing as setTarget without + that assumption +*/ +void QmlAbstractAnimation::setDefaultTarget(const QmlMetaProperty &p) +{ + Q_D(QmlAbstractAnimation); + d->defaultProperty = p; +} + +/* + don't allow start/stop/pause/resume to be manually invoked, + because something else (like a Behavior) already has control + over the animation. +*/ +void QmlAbstractAnimation::setDisableUserControl() { + Q_D(QmlAbstractAnimation); + d->disableUserControl = true; } void QmlAbstractAnimation::transition(QmlStateActions &actions, @@ -685,7 +707,7 @@ void QmlColorAnimation::setFrom(const QColor &f) } /*! - \qmlproperty color ColorAnimation::from + \qmlproperty color ColorAnimation::to This property holds the ending color. */ QColor QmlColorAnimation::to() const @@ -819,7 +841,7 @@ QML_DEFINE_TYPE(Qt,4,6,ScriptAction,QmlScriptAction) Set \c thewebview.url to the value set for the destination state: \code - PropertyAction { matchTargets: thewebview; matchProperties: "url" } + PropertyAction { target: thewebview; property: "url" } \endcode The PropertyAction is immediate - @@ -866,25 +888,10 @@ void QmlPropertyAction::setTarget(QObject *o) Q_D(QmlPropertyAction); if (d->target == o) return; - d->target = o; - if (d->target && !d->propertyName.isEmpty()) { - d->userProperty = d->createProperty(d->target, d->propertyName, this); - } else { - d->userProperty.invalidate(); - } - emit targetChanged(d->target, d->propertyName); } -/*! - \qmlproperty string PropertyAction::property - This property holds an explicit property to animated. - - The exact effect of the \c property property depends on how the animation - is being used. Refer to the \l animation documentation for details. -*/ - QString QmlPropertyAction::property() const { Q_D(const QmlPropertyAction); @@ -896,29 +903,24 @@ void QmlPropertyAction::setProperty(const QString &n) Q_D(QmlPropertyAction); if (d->propertyName == n) return; - d->propertyName = n; - if (d->target && !d->propertyName.isEmpty()) { - d->userProperty = d->createProperty(d->target, d->propertyName, this); - } else { - d->userProperty.invalidate(); - } - emit targetChanged(d->target, d->propertyName); } /*! - \qmlproperty string PropertyAction::matchProperties - This property holds a comma-separated list of property names this action - will match against. These names are used in conjunction with matchTargets - to create a list of properties that the action will set, assuming those - properties have changed. + \qmlproperty string PropertyAction::property + \qmlproperty string PropertyAction::properties + \qmlproperty Object PropertyAction::target + \qmlproperty list<Object> PropertyAction::targets - This property is typically used for an action appearing as part of a Transition. + These properties are used as a set to determine which properties should be + affected by this action. - By default, no property names will be matched. + The details of how these properties are interpreted in different situations + is covered in the \l{PropertyAnimation::properties}{corresponding} PropertyAnimation + documentation. - \sa matchTargets PropertyAnimation::matchProperties + \sa exclude */ QString QmlPropertyAction::properties() const { @@ -935,18 +937,6 @@ void QmlPropertyAction::setProperties(const QString &p) emit propertiesChanged(p); } -/*! - \qmlproperty list<Object> PropertyAction::matchTargets - This property holds a list of objects this action will match against. - These objects are used in conjunction with matchProperties to create a list of properties - that the action will set, assuming those properties have changed. - - This property is typically used for an action appearing as part of a Transition. - - By default, all changing targets will be matched. - - \sa exclude matchProperties PropertyAnimation::matchTargets -*/ QList<QObject *> *QmlPropertyAction::targets() { Q_D(QmlPropertyAction); @@ -956,7 +946,7 @@ QList<QObject *> *QmlPropertyAction::targets() /*! \qmlproperty list<Object> PropertyAction::exclude This property holds the objects not to be affected by this animation. - \sa matchTargets + \sa targets */ QList<QObject *> *QmlPropertyAction::exclude() { @@ -984,29 +974,12 @@ void QmlPropertyAction::setValue(const QVariant &v) } } -void QmlPropertyActionPrivate::doAction() -{ - property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); -} - QAbstractAnimation *QmlPropertyAction::qtAnimation() { Q_D(QmlPropertyAction); return d->spa; } -void QmlPropertyAction::prepare(QmlMetaProperty &p) -{ - Q_D(QmlPropertyAction); - - if (d->userProperty.isNull) - d->property = p; - else - d->property = d->userProperty; - - d->spa->setAnimAction(&d->proxy, QAbstractAnimation::KeepWhenStopped); -} - void QmlPropertyAction::transition(QmlStateActions &actions, QmlMetaProperties &modified, TransitionDirection direction) @@ -1029,31 +1002,42 @@ void QmlPropertyAction::transition(QmlStateActions &actions, QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(',')); for (int ii = 0; ii < props.count(); ++ii) props[ii] = props.at(ii).trimmed(); + if (!d->propertyName.isEmpty()) + props << d->propertyName; - bool hasSelectors = !props.isEmpty() || !d->targets.isEmpty() || !d->exclude.isEmpty(); - bool hasTarget = !d->propertyName.isEmpty() || d->target; + QList<QObject*> targets = d->targets; + if (d->target) + targets.append(d->target); - if (hasSelectors && hasTarget) { - qmlInfo(this) << tr("matchTargets/matchProperties/exclude and target/property are mutually exclusive."); - return; + bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty(); + + if (d->defaultProperty.isValid() && !hasSelectors) { + props << d->defaultProperty.name(); + targets << d->defaultProperty.object(); } QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction; bool hasExplicit = false; - if (hasTarget && d->value.isValid()) { - QmlAction myAction; - myAction.property = d->createProperty(target(), d->propertyName, this); - if (myAction.property.isValid()) { - myAction.toValue = d->value; - data->actions << myAction; - hasExplicit = true; - for (int ii = 0; ii < actions.count(); ++ii) { - QmlAction &action = actions[ii]; - if (action.property.object() == myAction.property.object() && - myAction.property.name() == action.property.name()) { - modified << action.property; - break; //### any chance there could be multiples? + //an explicit animation has been specified + if (d->value.isValid()) { + for (int i = 0; i < props.count(); ++i) { + for (int j = 0; j < targets.count(); ++j) { + QmlAction myAction; + myAction.property = d->createProperty(targets.at(j), props.at(i), this); + if (myAction.property.isValid()) { + myAction.toValue = d->value; + QmlPropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyType()); + data->actions << myAction; + hasExplicit = true; + for (int ii = 0; ii < actions.count(); ++ii) { + QmlAction &action = actions[ii]; + if (action.property.object() == myAction.property.object() && + myAction.property.name() == action.property.name()) { + modified << action.property; + break; //### any chance there could be multiples? + } + } } } } @@ -1069,31 +1053,18 @@ void QmlPropertyAction::transition(QmlStateActions &actions, QString sPropertyName = action.specifiedProperty; bool same = (obj == sObj); - if ((d->targets.isEmpty() || d->targets.contains(obj) || (!same && d->targets.contains(sObj))) && + if ((targets.isEmpty() || targets.contains(obj) || (!same && targets.contains(sObj))) && (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) && (props.contains(propertyName) || (!same && props.contains(sPropertyName)))) { QmlAction myAction = action; if (d->value.isValid()) myAction.toValue = d->value; + QmlPropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyType()); modified << action.property; data->actions << myAction; action.fromValue = myAction.toValue; - } else if (d->userProperty.isValid() && - !hasSelectors && !hasTarget) { - if ((d->userProperty.value.object() == obj || (!same && d->userProperty.value.object() == sObj)) && - (d->userProperty.value.name() == propertyName || (!same && d->userProperty.value.name() == sPropertyName))) { - //### same as above. merge - QmlAction myAction = action; - - if (d->value.isValid()) - myAction.toValue = d->value; - - modified << action.property; - data->actions << myAction; - action.fromValue = myAction.toValue; - } } } @@ -1161,24 +1132,7 @@ void QmlParentActionPrivate::init() /*! \qmlproperty Item ParentAction::target - This property holds an explicit target item to reparent. - */ -QmlGraphicsItem *QmlParentAction::object() const -{ - Q_D(const QmlParentAction); - return d->pcTarget; -} - -void QmlParentAction::setObject(QmlGraphicsItem *target) -{ - Q_D(QmlParentAction); - d->pcTarget = target; -} - -/*! - \qmlproperty Item ParentAction::matchTarget - This property holds the item this action will match against -- the item - that the action will reparent, assuming its parent has changed. + This property holds a target item to reparent. In the following example, \c myItem will be reparented by the ParentAction, while \c myOtherItem will not. @@ -1196,24 +1150,23 @@ void QmlParentAction::setObject(QmlGraphicsItem *target) Transition { SequentialAnimation { PropertyAnimation { ... } - ParentAction { matchTargets: myItem } + ParentAction { target: myItem } PropertyAnimation { ... } } } \endqml - This property is typically used for an action appearing as part of a Transition. */ -QmlGraphicsItem *QmlParentAction::matchTarget() const +QmlGraphicsItem *QmlParentAction::object() const { Q_D(const QmlParentAction); return d->pcTarget; } -void QmlParentAction::setMatchTarget(QmlGraphicsItem *target) +void QmlParentAction::setObject(QmlGraphicsItem *target) { Q_D(QmlParentAction); - d->pcMatchTarget = target; + d->pcTarget = target; } /*! @@ -1277,17 +1230,27 @@ void QmlParentAction::transition(QmlStateActions &actions, QmlParentActionData *data = new QmlParentActionData; - if (d->pcTarget && d->pcMatchTarget) { - qmlInfo(this) << tr("matchTarget and target are mutually exclusive."); - return; + //### need to correctly handle modified/done + + bool hasExplicit = false; + if (d->pcTarget && d->pcParent) { + data->reverse = false; + QmlAction myAction; + QmlParentChange *pc = new QmlParentChange; + pc->setObject(d->pcTarget); + pc->setParent(d->pcParent); + myAction.event = pc; + data->pc = pc; + data->actions << myAction; + hasExplicit = true; } + if (!hasExplicit) for (int ii = 0; ii < actions.count(); ++ii) { QmlAction &action = actions[ii]; if (action.event && action.event->typeName() == QLatin1String("ParentChange") - && !d->pcTarget - && (!d->pcMatchTarget || static_cast<QmlParentChange*>(action.event)->object() == d->pcMatchTarget)) { + && (!d->pcTarget || static_cast<QmlParentChange*>(action.event)->object() == d->pcTarget)) { QmlAction myAction = action; data->reverse = action.reverseEvent; //### this logic differs from PropertyAnimation @@ -1308,17 +1271,6 @@ void QmlParentAction::transition(QmlStateActions &actions, } } - if (d->pcTarget && d->pcParent) { - data->reverse = false; - QmlAction myAction; - QmlParentChange *pc = new QmlParentChange; - pc->setObject(d->pcTarget); - pc->setParent(d->pcParent); - myAction.event = pc; - data->pc = pc; - data->actions << myAction; - } - if (data->actions.count()) { d->cpa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped); } else { @@ -1336,7 +1288,7 @@ QML_DEFINE_TYPE(Qt,4,6,ParentAction,QmlParentAction) Animate a set of properties over 200ms, from their values in the start state to their values in the end state of the transition: \code - NumberAnimation { matchProperties: "x,y,scale"; duration: 200 } + NumberAnimation { properties: "x,y,scale"; duration: 200 } \endcode */ @@ -1376,7 +1328,7 @@ void QmlNumberAnimation::setFrom(qreal f) /*! \qmlproperty real NumberAnimation::to This property holds the ending value. - If not set, then the value defined in the end state of the transition. + If not set, then the value defined in the end state of the transition or Behavior. */ qreal QmlNumberAnimation::to() const { @@ -1434,7 +1386,7 @@ void QmlVector3dAnimation::setFrom(QVector3D f) /*! \qmlproperty real Vector3dAnimation::to This property holds the ending value. - If not set, then the value defined in the end state of the transition. + If not set, then the value defined in the end state of the transition or Behavior. */ QVector3D QmlVector3dAnimation::to() const { @@ -1449,6 +1401,177 @@ void QmlVector3dAnimation::setTo(QVector3D t) QML_DEFINE_TYPE(Qt,4,6,Vector3dAnimation,QmlVector3dAnimation) +/*! + \qmlclass RotationAnimation QmlRotationAnimation + \inherits PropertyAnimation + \brief The RotationAnimation element allows you to animate rotations. + + RotationAnimation is a specialized PropertyAnimation that gives control + over the direction of rotation. + + The RotationAnimation in the following example ensures that we always take + the shortest rotation path when switching between our states. + \qml + states: { + State { name: "180"; PropertyChanges { target: myItem; rotation: 180 } } + State { name: "-180"; PropertyChanges { target: myItem; rotation: -180 } } + State { name: "180"; PropertyChanges { target: myItem; rotation: 270 } } + } + transition: Transition { + RotationAnimation { direction: RotationAnimation.Shortest } + } + \endqml + + By default, when used in a transition RotationAnimation will rotate all + properties named "rotation" or "angle". You can override this by providing + your own properties via \c properties or \c property. +*/ + +/*! + \internal + \class QmlRotationAnimation +*/ + +QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress) +{ + qreal newt = t; + qreal diff = t-f; + while(diff > 180.0){ + newt -= 360.0; + diff -= 360.0; + } + while(diff < -180.0){ + newt += 360.0; + diff += 360.0; + } + return QVariant(f + (newt - f) * progress); +} + +QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress) +{ + qreal newt = t; + qreal diff = t-f; + while(diff < 0.0){ + newt += 360.0; + diff += 360.0; + } + return QVariant(f + (newt - f) * progress); +} + +QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress) +{ + qreal newt = t; + qreal diff = t-f; + while(diff > 0.0){ + newt -= 360.0; + diff -= 360.0; + } + return QVariant(f + (newt - f) * progress); +} + +QmlRotationAnimation::QmlRotationAnimation(QObject *parent) +: QmlPropertyAnimation(*(new QmlRotationAnimationPrivate), parent) +{ + Q_D(QmlRotationAnimation); + d->interpolatorType = QMetaType::QReal; + d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateShortestRotation); + d->defaultProperties = QLatin1String("rotation,angle"); +} + +QmlRotationAnimation::~QmlRotationAnimation() +{ +} + +/*! + \qmlproperty real RotationAnimation::from + This property holds the starting value. + If not set, then the value defined in the start state of the transition. +*/ +qreal QmlRotationAnimation::from() const +{ + Q_D(const QmlRotationAnimation); + return d->from.toReal(); +} + +void QmlRotationAnimation::setFrom(qreal f) +{ + QmlPropertyAnimation::setFrom(f); +} + +/*! + \qmlproperty real RotationAnimation::to + This property holds the ending value. + If not set, then the value defined in the end state of the transition or Behavior. +*/ +qreal QmlRotationAnimation::to() const +{ + Q_D(const QmlRotationAnimation); + return d->to.toReal(); +} + +void QmlRotationAnimation::setTo(qreal t) +{ + QmlPropertyAnimation::setTo(t); +} + +/*! + \qmlproperty enum RotationAnimation::direction + The direction in which to rotate. + Possible values are Numerical, Clockwise, Counterclockwise, + or Shortest. + + \list + \row + \o Numerical + \o Rotate by linearly interpolating between the two numbers. + A rotation from 10 to 350 will rotate 340 degrees clockwise. + \row + \o Clockwise + \o Rotate clockwise between the two values + \row + \o Counterclockwise + \o Rotate counterclockwise between the two values + \row + \o Shortest + \o Rotate in the direction that produces the shortest animation path. + A rotation from 10 to 350 will rotate 20 degrees counterclockwise. + \list + + The default direction is Shortest. +*/ +QmlRotationAnimation::RotationDirection QmlRotationAnimation::direction() const +{ + Q_D(const QmlRotationAnimation); + return d->direction; +} + +void QmlRotationAnimation::setDirection(QmlRotationAnimation::RotationDirection direction) +{ + Q_D(QmlRotationAnimation); + if (d->direction == direction) + return; + + d->direction = direction; + switch(d->direction) { + case Clockwise: + d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateClockwiseRotation); + break; + case Counterclockwise: + d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateCounterclockwiseRotation); + break; + case Shortest: + d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateShortestRotation); + break; + default: + d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); + break; + } + + emit directionChanged(); +} + +QML_DEFINE_TYPE(Qt,4,6,RotationAnimation,QmlRotationAnimation) + QmlAnimationGroup::QmlAnimationGroup(QObject *parent) : QmlAbstractAnimation(*(new QmlAnimationGroupPrivate), parent) { @@ -1495,18 +1618,6 @@ QmlSequentialAnimation::~QmlSequentialAnimation() { } -void QmlSequentialAnimation::prepare(QmlMetaProperty &p) -{ - Q_D(QmlAnimationGroup); - if (d->userProperty.isNull) - d->property = p; - else - d->property = d->userProperty; - - for (int i = 0; i < d->animations.size(); ++i) - d->animations.at(i)->prepare(d->property); -} - QAbstractAnimation *QmlSequentialAnimation::qtAnimation() { Q_D(QmlAnimationGroup); @@ -1526,13 +1637,10 @@ void QmlSequentialAnimation::transition(QmlStateActions &actions, from = d->animations.count() - 1; } - //needed for Behavior - if (d->userProperty.isValid()) { - for (int i = 0; i < d->animations.count(); ++i) - d->animations.at(i)->setTarget(d->userProperty); - } - + bool valid = d->defaultProperty.isValid(); for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) { + if (valid) + d->animations.at(ii)->setDefaultTarget(d->defaultProperty); d->animations.at(ii)->transition(actions, modified, direction); } } @@ -1574,18 +1682,6 @@ QmlParallelAnimation::~QmlParallelAnimation() { } -void QmlParallelAnimation::prepare(QmlMetaProperty &p) -{ - Q_D(QmlAnimationGroup); - if (d->userProperty.isNull) - d->property = p; - else - d->property = d->userProperty; - - for (int i = 0; i < d->animations.size(); ++i) - d->animations.at(i)->prepare(d->property); -} - QAbstractAnimation *QmlParallelAnimation::qtAnimation() { Q_D(QmlAnimationGroup); @@ -1597,14 +1693,10 @@ void QmlParallelAnimation::transition(QmlStateActions &actions, TransitionDirection direction) { Q_D(QmlAnimationGroup); - - //needed for Behavior - if (d->userProperty.isValid()) { - for (int i = 0; i < d->animations.count(); ++i) - d->animations.at(i)->setTarget(d->userProperty); - } - + bool valid = d->defaultProperty.isValid(); for (int ii = 0; ii < d->animations.count(); ++ii) { + if (valid) + d->animations.at(ii)->setDefaultTarget(d->defaultProperty); d->animations.at(ii)->transition(actions, modified, direction); } } @@ -1668,12 +1760,56 @@ void QmlPropertyAnimationPrivate::convertVariant(QVariant &variant, int type) \inherits Animation \brief The PropertyAnimation element allows you to animate property changes. - Animate theObject's size property over 200ms, from its current size to 20-by-20: - \code + PropertyAnimation provides a way to animate changes to a property's value. It can + be used in many different situations: + \list + \o In a Transition + + Animate any objects that have changed their x or y properties in the target state using + an InOutQuad easing curve: + \qml + Transition { PropertyAnimation { properties: "x,y"; easing: "InOutQuad" } } + \endqml + \o In a Behavior + + Animate all changes to a rectangle's x property. + \qml + Rectangle { + x: Behavior { PropertyAnimation {} } + } + \endqml + \o As a property value source + + Repeatedly animate the rectangle's x property. + \qml + Rectangle { + x: SequentialAnimation { + repeat: true + PropertyAnimation { to: 50 } + PropertyAnimation { to: 0 } + } + } + \endqml + \o In a signal handler + + Fade out \c theObject when clicked: + \qml + MouseRegion { + anchors.fill: theObject + onClicked: PropertyAnimation { target: theObject; property: "opacity"; to: 0 } + } + \endqml + \o Standalone + + Animate \c theObject's size property over 200ms, from its current size to 20-by-20: + \qml PropertyAnimation { target: theObject; property: "size"; to: "20x20"; duration: 200 } - \endcode + \endqml + \endlist - For an introduction to animation in QML, see \l{QML Animation}. + Depending on how the animation is used, the set of properties normally used will be + different. For more information see the individual property documentation, as well + as the \l{QML Animation} introduction. */ QmlPropertyAnimation::QmlPropertyAnimation(QObject *parent) @@ -1683,6 +1819,13 @@ QmlPropertyAnimation::QmlPropertyAnimation(QObject *parent) d->init(); } +QmlPropertyAnimation::QmlPropertyAnimation(QmlPropertyAnimationPrivate &dd, QObject *parent) +: QmlAbstractAnimation(dd, parent) +{ + Q_D(QmlPropertyAnimation); + d->init(); +} + QmlPropertyAnimation::~QmlPropertyAnimation() { } @@ -1744,7 +1887,7 @@ void QmlPropertyAnimation::setFrom(const QVariant &f) /*! \qmlproperty real PropertyAnimation::to This property holds the ending value. - If not set, then the value defined in the end state of the transition. + If not set, then the value defined in the end state of the transition or Behavior. */ QVariant QmlPropertyAnimation::to() const { @@ -1955,16 +2098,6 @@ void QmlPropertyAnimation::setEasing(const QString &e) emit easingChanged(e); } -/*! - \qmlproperty Object PropertyAnimation::target - This property holds an explicit target object to animate. - - target is used in conjunction with property to determine - what property should be animated. - - \sa property matchTargets -*/ - QObject *QmlPropertyAnimation::target() const { Q_D(const QmlPropertyAnimation); @@ -1976,27 +2109,10 @@ void QmlPropertyAnimation::setTarget(QObject *o) Q_D(QmlPropertyAnimation); if (d->target == o) return; - d->target = o; - if (d->target && !d->propertyName.isEmpty()) { - d->userProperty = d->createProperty(d->target, d->propertyName, this); - } else { - d->userProperty.invalidate(); - } - emit targetChanged(d->target, d->propertyName); } -/*! - \qmlproperty string PropertyAnimation::property - This property holds an explicit property name to animate. - - property is used in conjunction with target to determine - what property should be animated. - - \sa target matchProperties -*/ - QString QmlPropertyAnimation::property() const { Q_D(const QmlPropertyAnimation); @@ -2008,46 +2124,10 @@ void QmlPropertyAnimation::setProperty(const QString &n) Q_D(QmlPropertyAnimation); if (d->propertyName == n) return; - d->propertyName = n; - if (d->target && !d->propertyName.isEmpty()) { - d->userProperty = d->createProperty(d->target, d->propertyName, this); - } else { - d->userProperty.invalidate(); - } - emit targetChanged(d->target, d->propertyName); } -/*! - \qmlproperty string PropertyAnimation::matchProperties - This property holds a comma-separated list of property names this animation - will match against. These names are used in conjunction with matchTargets - to create a list of properties that the animation will animate, assuming those - properties have changed. - - In the following example, the change in 'x' will be animated by the transition, while - the change in 'y' will not. - \qml - State { - PropertyChanges { - target: myItem - x: 15; y: 15 - } - } - Transition { - PropertyAnimation { - matchProperties: "x" - } - } - \endqml - - This property is typically used for an animation appearing as part of a Transition. - - By default, no property names will be matched. - - \sa matchTargets PropertyAction::matchTargets -*/ QString QmlPropertyAnimation::properties() const { Q_D(const QmlPropertyAnimation); @@ -2065,37 +2145,86 @@ void QmlPropertyAnimation::setProperties(const QString &prop) } /*! - \qmlproperty list<Object> PropertyAnimation::matchTargets - This property holds a list of objects this animation will match against. - These objects are used in conjunction with matchProperties to create a list of properties - that the animation will animate, assuming those properties have changed. + \qmlproperty string PropertyAnimation::property + \qmlproperty string PropertyAnimation::properties + \qmlproperty Object PropertyAnimation::target + \qmlproperty list<Object> PropertyAnimation::targets - In the following example, the changes to \c myItem will be animated by the transition, while - the changes to \c myOtherItem will not. + These properties are used as a set to determine which properties should be animated. + The singular and plural forms are functionally identical, e.g. \qml - State { - PropertyChanges { - target: myItem - x: 15; y: 15 - } - PropertyChanges { - target: myOtherItem - x: 30; y: 30 - } - } - Transition { - PropertyAnimation { - matchTargets: myItem - matchProperties: "x,y" - } - } + NumberAnimation { target: theItem; property: "x"; to: 500 } \endqml + has the same meaning as + \qml + NumberAnimation { targets: theItem; properties: "x"; to: 500 } + \endqml + The singular forms are slightly optimized, so if you do have only a single target/property + to animate you should try to use them. - This property is typically used for an animation appearing as part of a Transition. + In many cases these properties do not need to be explicitly specified -- they can be + inferred from the animation framework. + \table 80% + \row + \o Value Source / Behavior + \o When an animation is used as a value source or in a Behavior, the default target and property + name to be animated can both be inferred. + \qml + Rectangle { + id: theRect + width: 100; height: 100 + color: Qt.rgba(0,0,1) + x: NumberAnimation { to: 500; repeat: true } //animate theRect's x property + y: Behavior { NumberAnimation {} } //animate theRect's y property + } + \endqml + \row + \o Transition + \o When used in a transition, a property animation is assumed to match \e all targets + but \e no properties. In practice, that means you need to specify at least the properties + in order for the animation to do anything. + \qml + Rectangle { + id: theRect + width: 100; height: 100 + color: Qt.rgba(0,0,1) + Item { id: uselessItem } + states: State { + name: "state1" + PropertyChanges { target: theRect; x: 200; y: 200; z: 4 } + PropertyChanges { target: uselessItem; x: 10; y: 10; z: 2 } + } + transitions: Transition { + //animate both theRect's and uselessItem's x and y to their final values + NumberAnimation { properties: "x,y" } + + //animate theRect's z to its final value + NumberAnimation { target: theRect; property: "z" } + } + } + \endqml + \row + \o Standalone + \o When an animation is used standalone, both the target and property need to be + explicitly specified. + \qml + Rectangle { + id: theRect + width: 100; height: 100 + color: Qt.rgba(0,0,1) + //need to explicitly specify target and property + NumberAnimation { id: theAnim; target: theRect; property: "x" to: 500 } + MouseRegion { + anchors.fill: parent + onClicked: theAnim.start() + } + } + \endqml + \endtable + + As seen in the above example, properties is specified as a comma-separated string of property names to animate. - By default, all changing targets will be matched. - - \sa exclude matchProperties + \sa exclude */ QList<QObject *> *QmlPropertyAnimation::targets() { @@ -2106,7 +2235,7 @@ QList<QObject *> *QmlPropertyAnimation::targets() /*! \qmlproperty list<Object> PropertyAnimation::exclude This property holds the items not to be affected by this animation. - \sa matchTargets + \sa targets */ QList<QObject *> *QmlPropertyAnimation::exclude() { @@ -2114,60 +2243,59 @@ QList<QObject *> *QmlPropertyAnimation::exclude() return &d->exclude; } -void QmlPropertyAnimationPrivate::valueChanged(qreal r) -{ - if (!fromSourced) { - if (!fromIsDefined) { - from = property.read(); - convertVariant(from, interpolatorType ? interpolatorType : property.propertyType()); - //### check for invalid variant if using property type - } - fromSourced = true; - } - - if (r == 1.) { - property.write(to, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); - } else { - if (interpolator) - property.write(interpolator(from.constData(), to.constData(), r), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); - } -} - QAbstractAnimation *QmlPropertyAnimation::qtAnimation() { Q_D(QmlPropertyAnimation); return d->va; } -void QmlPropertyAnimation::prepare(QmlMetaProperty &p) +struct PropertyUpdater : public QmlTimeLineValue { - Q_D(QmlPropertyAnimation); - if (d->userProperty.isNull) - d->property = p; - else - d->property = d->userProperty; - - if (!d->rangeIsSet) { - d->va->setStartValue(qreal(0)); - d->va->setEndValue(qreal(1)); - d->rangeIsSet = true; - } - - int propType = d->property.propertyType(); - d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : propType); - if (d->fromIsDefined) - d->convertVariant(d->from, d->interpolatorType ? d->interpolatorType : propType); - - if (!d->interpolatorType) { - //### check for invalid variants - d->interpolator = QVariantAnimationPrivate::getInterpolator(propType); + QmlStateActions actions; + int interpolatorType; //for Number/ColorAnimation + int prevInterpolatorType; //for generic + QVariantAnimation::Interpolator interpolator; + bool reverse; + bool fromSourced; + bool fromDefined; + bool *wasDeleted; + PropertyUpdater() : wasDeleted(0) {} + ~PropertyUpdater() { if (wasDeleted) *wasDeleted = true; } + void setValue(qreal v) + { + bool deleted = false; + wasDeleted = &deleted; + if (reverse) //QVariantAnimation sends us 1->0 when reversed, but we are expecting 0->1 + v = 1 - v; + QmlTimeLineValue::setValue(v); + for (int ii = 0; ii < actions.count(); ++ii) { + QmlAction &action = actions[ii]; + + if (v == 1.) + action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); + else { + if (!fromSourced && !fromDefined) { + action.fromValue = action.property.read(); + if (interpolatorType) + QmlPropertyAnimationPrivate::convertVariant(action.fromValue, interpolatorType); + } + if (!interpolatorType) { + int propType = action.property.propertyType(); + if (!prevInterpolatorType || prevInterpolatorType != propType) { + prevInterpolatorType = propType; + interpolator = QVariantAnimationPrivate::getInterpolator(prevInterpolatorType); + } + } + if (interpolator) + action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); + } + if (deleted) + return; + } + wasDeleted = 0; + fromSourced = true; } - - d->fromSourced = false; - d->value.QmlTimeLineValue::setValue(0.); - d->va->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped); - d->va->setFromSourcedValue(&d->fromSourced); -} +}; void QmlPropertyAnimation::transition(QmlStateActions &actions, QmlMetaProperties &modified, @@ -2176,90 +2304,59 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, Q_D(QmlPropertyAnimation); Q_UNUSED(direction); - struct PropertyUpdater : public QmlTimeLineValue - { - QmlStateActions actions; - int interpolatorType; //for Number/ColorAnimation - int prevInterpolatorType; //for generic - QVariantAnimation::Interpolator interpolator; - bool reverse; - bool *wasDeleted; - PropertyUpdater() : wasDeleted(0) {} - ~PropertyUpdater() { if (wasDeleted) *wasDeleted = true; } - void setValue(qreal v) - { - bool deleted = false; - wasDeleted = &deleted; - if (reverse) //QVariantAnimation sends us 1->0 when reversed, but we are expecting 0->1 - v = 1 - v; - QmlTimeLineValue::setValue(v); - for (int ii = 0; ii < actions.count(); ++ii) { - QmlAction &action = actions[ii]; - - if (v == 1.) - action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); - else { - if (action.fromValue.isNull()) { - action.fromValue = action.property.read(); - if (interpolatorType) - QmlPropertyAnimationPrivate::convertVariant(action.fromValue, interpolatorType); - } - if (!interpolatorType) { - int propType = action.property.propertyType(); - if (!prevInterpolatorType || prevInterpolatorType != propType) { - prevInterpolatorType = propType; - interpolator = QVariantAnimationPrivate::getInterpolator(prevInterpolatorType); - } - } - if (interpolator) - action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); - } - if (deleted) - return; - } - wasDeleted = 0; - } - }; - QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(',')); for (int ii = 0; ii < props.count(); ++ii) props[ii] = props.at(ii).trimmed(); + if (!d->propertyName.isEmpty()) + props << d->propertyName; - bool hasSelectors = !props.isEmpty() || !d->targets.isEmpty() || !d->exclude.isEmpty(); - bool hasTarget = !d->propertyName.isEmpty() || d->target; + QList<QObject*> targets = d->targets; + if (d->target) + targets.append(d->target); - if (hasSelectors && hasTarget) { - qmlInfo(this) << tr("matchTargets/matchProperties/exclude and target/property are mutually exclusive."); - return; + bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty(); + bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ? true : false; + + if (d->defaultProperty.isValid() && !hasSelectors) { + props << d->defaultProperty.name(); + targets << d->defaultProperty.object(); } - bool useType = (props.isEmpty() && d->propertyName.isEmpty() && d->defaultToInterpolatorType) ? true : false; + if (props.isEmpty() && !d->defaultProperties.isEmpty()) { + props << d->defaultProperties.split(QLatin1Char(',')); + } PropertyUpdater *data = new PropertyUpdater; data->interpolatorType = d->interpolatorType; data->interpolator = d->interpolator; data->reverse = direction == Backward ? true : false; + data->fromSourced = false; + data->fromDefined = d->fromIsDefined; bool hasExplicit = false; //an explicit animation has been specified - if (hasTarget && d->toIsDefined) { - QmlAction myAction; - myAction.property = d->createProperty(target(), d->propertyName, this); - if (myAction.property.isValid()) { - if (d->fromIsDefined) { - d->convertVariant(d->from, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); - myAction.fromValue = d->from; - } - d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); - myAction.toValue = d->to; - data->actions << myAction; - hasExplicit = true; - for (int ii = 0; ii < actions.count(); ++ii) { - QmlAction &action = actions[ii]; - if (action.property.object() == myAction.property.object() && - myAction.property.name() == action.property.name()) { - modified << action.property; - break; //### any chance there could be multiples? + if (d->toIsDefined) { + for (int i = 0; i < props.count(); ++i) { + for (int j = 0; j < targets.count(); ++j) { + QmlAction myAction; + myAction.property = d->createProperty(targets.at(j), props.at(i), this); + if (myAction.property.isValid()) { + if (d->fromIsDefined) { + myAction.fromValue = d->from; + d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); + } + myAction.toValue = d->to; + d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); + data->actions << myAction; + hasExplicit = true; + for (int ii = 0; ii < actions.count(); ++ii) { + QmlAction &action = actions[ii]; + if (action.property.object() == myAction.property.object() && + myAction.property.name() == action.property.name()) { + modified << action.property; + break; //### any chance there could be multiples? + } + } } } } @@ -2275,7 +2372,7 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, QString sPropertyName = action.specifiedProperty; bool same = (obj == sObj); - if ((d->targets.isEmpty() || d->targets.contains(obj) || (!same && d->targets.contains(sObj))) && + if ((targets.isEmpty() || targets.contains(obj) || (!same && targets.contains(sObj))) && (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) && (props.contains(propertyName) || (!same && props.contains(sPropertyName)) || (useType && action.property.propertyType() == d->interpolatorType))) { @@ -2295,29 +2392,7 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, data->actions << myAction; action.fromValue = myAction.toValue; - } else if (d->userProperty.isValid() && - !hasSelectors && !hasTarget) { - if ((d->userProperty.value.object() == obj || (!same && d->userProperty.value.object() == sObj)) && - (d->userProperty.value.name() == propertyName || (!same && d->userProperty.value.name() == sPropertyName))) { - //### same as above. merge - QmlAction myAction = action; - - if (d->fromIsDefined) - myAction.fromValue = d->from; - else - myAction.fromValue = QVariant(); - if (d->toIsDefined) - myAction.toValue = d->to; - - d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); - d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); - - modified << action.property; - - data->actions << myAction; - action.fromValue = myAction.toValue; - } - } + } } if (data->actions.count()) { @@ -2327,6 +2402,7 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, d->rangeIsSet = true; } d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); + d->va->setFromSourcedValue(&data->fromSourced); } else { delete data; } diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h index 6a69e4d..02902b0 100644 --- a/src/declarative/util/qmlanimation_p.h +++ b/src/declarative/util/qmlanimation_p.h @@ -94,7 +94,8 @@ public: QmlAnimationGroup *group() const; void setGroup(QmlAnimationGroup *); - virtual void setTarget(const QmlMetaProperty &); + void setDefaultTarget(const QmlMetaProperty &); + void setDisableUserControl(); void classBegin(); void componentComplete(); @@ -123,11 +124,13 @@ public: virtual void transition(QmlStateActions &actions, QmlMetaProperties &modified, TransitionDirection direction); - virtual void prepare(QmlMetaProperty &); virtual QAbstractAnimation *qtAnimation() = 0; private Q_SLOTS: void timelineComplete(); + +private: + virtual void setTarget(const QmlMetaProperty &); }; class QmlPauseAnimationPrivate; @@ -186,8 +189,8 @@ class QmlPropertyAction : public QmlAbstractAnimation Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged) - Q_PROPERTY(QString matchProperties READ properties WRITE setProperties NOTIFY propertiesChanged) - Q_PROPERTY(QList<QObject *>* matchTargets READ targets) + Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged) + Q_PROPERTY(QList<QObject *>* targets READ targets) Q_PROPERTY(QList<QObject *>* exclude READ exclude) Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) @@ -220,7 +223,6 @@ protected: QmlMetaProperties &modified, TransitionDirection direction); virtual QAbstractAnimation *qtAnimation(); - virtual void prepare(QmlMetaProperty &); }; class QmlGraphicsItem; @@ -231,8 +233,7 @@ class QmlParentAction : public QmlAbstractAnimation Q_DECLARE_PRIVATE(QmlParentAction) Q_PROPERTY(QmlGraphicsItem *target READ object WRITE setObject) - Q_PROPERTY(QmlGraphicsItem *matchTarget READ matchTarget WRITE setMatchTarget) - Q_PROPERTY(QmlGraphicsItem *parent READ parent WRITE setParent) + Q_PROPERTY(QmlGraphicsItem *parent READ parent WRITE setParent) //### newParent public: QmlParentAction(QObject *parent=0); @@ -241,9 +242,6 @@ public: QmlGraphicsItem *object() const; void setObject(QmlGraphicsItem *); - QmlGraphicsItem *matchTarget() const; - void setMatchTarget(QmlGraphicsItem *); - QmlGraphicsItem *parent() const; void setParent(QmlGraphicsItem *); @@ -266,8 +264,8 @@ class Q_AUTOTEST_EXPORT QmlPropertyAnimation : public QmlAbstractAnimation Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged) Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged) - Q_PROPERTY(QString matchProperties READ properties WRITE setProperties NOTIFY propertiesChanged) - Q_PROPERTY(QList<QObject *>* matchTargets READ targets) + Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged) + Q_PROPERTY(QList<QObject *>* targets READ targets) Q_PROPERTY(QList<QObject *>* exclude READ exclude) public: @@ -299,11 +297,11 @@ public: QList<QObject *> *exclude(); protected: + QmlPropertyAnimation(QmlPropertyAnimationPrivate &dd, QObject *parent); virtual void transition(QmlStateActions &actions, QmlMetaProperties &modified, TransitionDirection direction); virtual QAbstractAnimation *qtAnimation(); - virtual void prepare(QmlMetaProperty &); Q_SIGNALS: void durationChanged(int); @@ -370,6 +368,35 @@ public: void setTo(QVector3D); }; +class QmlRotationAnimationPrivate; +class Q_AUTOTEST_EXPORT QmlRotationAnimation : public QmlPropertyAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlRotationAnimation) + Q_ENUMS(RotationDirection) + + Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged) + Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged) + Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged) + +public: + QmlRotationAnimation(QObject *parent=0); + virtual ~QmlRotationAnimation(); + + qreal from() const; + void setFrom(qreal); + + qreal to() const; + void setTo(qreal); + + enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise }; + RotationDirection direction() const; + void setDirection(RotationDirection direction); + +Q_SIGNALS: + void directionChanged(); +}; + class QmlAnimationGroupPrivate; class QmlAnimationGroup : public QmlAbstractAnimation { @@ -401,7 +428,6 @@ protected: QmlMetaProperties &modified, TransitionDirection direction); virtual QAbstractAnimation *qtAnimation(); - virtual void prepare(QmlMetaProperty &); }; class QmlParallelAnimation : public QmlAnimationGroup @@ -418,7 +444,6 @@ protected: QmlMetaProperties &modified, TransitionDirection direction); virtual QAbstractAnimation *qtAnimation(); - virtual void prepare(QmlMetaProperty &); }; QT_END_NAMESPACE @@ -434,6 +459,7 @@ QML_DECLARE_TYPE(QmlNumberAnimation) QML_DECLARE_TYPE(QmlSequentialAnimation) QML_DECLARE_TYPE(QmlParallelAnimation) QML_DECLARE_TYPE(QmlVector3dAnimation) +QML_DECLARE_TYPE(QmlRotationAnimation) QT_END_HEADER diff --git a/src/declarative/util/qmlanimation_p_p.h b/src/declarative/util/qmlanimation_p_p.h index d680194..a1181ed 100644 --- a/src/declarative/util/qmlanimation_p_p.h +++ b/src/declarative/util/qmlanimation_p_p.h @@ -108,6 +108,8 @@ public: { if (state() == Running) stop(); + if (policy == DeleteWhenStopped) + delete animAction; animAction = action; policy = p; } @@ -126,12 +128,12 @@ protected: animAction = 0; } } - } else if (newState == Stopped && policy == DeleteWhenStopped) { + } /*else if (newState == Stopped && policy == DeleteWhenStopped) { if (!running) { delete animAction; animAction = 0; } - } + }*/ } private: @@ -151,6 +153,8 @@ public: { if (state() == Running) stop(); + if (policy == DeleteWhenStopped) + delete animValue; animValue = value; policy = p; } @@ -165,16 +169,17 @@ protected: animValue->setValue(value.toReal()); } virtual void updateState(State newState, State oldState) - { + { QVariantAnimation::updateState(newState, oldState); if (newState == Running) { //check for new from every loop if (fromSourced) *fromSourced = false; - } else if (newState == Stopped && policy == DeleteWhenStopped) { + } /*else if (newState == Stopped && policy == DeleteWhenStopped) { delete animValue; animValue = 0; - } + }*/ //### we get a stop each loop if we are in a group + //### top-level animation is the only reliable one for this } private: @@ -204,24 +209,22 @@ class QmlAbstractAnimationPrivate : public QObjectPrivate public: QmlAbstractAnimationPrivate() : running(false), paused(false), alwaysRunToEnd(false), repeat(false), - connectedTimeLine(false), componentComplete(true), startOnCompletion(false), - avoidPropertyValueSourceStart(false), group(0) {} + connectedTimeLine(false), componentComplete(true), + avoidPropertyValueSourceStart(false), disableUserControl(false), group(0) {} bool running:1; bool paused:1; bool alwaysRunToEnd:1; bool repeat:1; bool connectedTimeLine:1; - bool componentComplete:1; - bool startOnCompletion:1; bool avoidPropertyValueSourceStart:1; + bool disableUserControl:1; void commence(); - QmlNullableValue<QmlMetaProperty> userProperty; + QmlMetaProperty defaultProperty; - QmlMetaProperty property; QmlAnimationGroup *group; static QmlMetaProperty createProperty(QObject *obj, const QString &str, QObject *infoObj); @@ -265,7 +268,7 @@ class QmlPropertyActionPrivate : public QmlAbstractAnimationPrivate Q_DECLARE_PUBLIC(QmlPropertyAction) public: QmlPropertyActionPrivate() - : QmlAbstractAnimationPrivate(), target(0), proxy(this), spa(0) {} + : QmlAbstractAnimationPrivate(), target(0), spa(0) {} void init(); @@ -277,10 +280,6 @@ public: QmlNullableValue<QVariant> value; - void doAction(); - - QAnimationActionProxy<QmlPropertyActionPrivate, - &QmlPropertyActionPrivate::doAction> proxy; QActionAnimation *spa; }; @@ -289,12 +288,11 @@ class QmlParentActionPrivate : public QmlAbstractAnimationPrivate Q_DECLARE_PUBLIC(QmlParentAction) public: QmlParentActionPrivate() - : QmlAbstractAnimationPrivate(), pcTarget(0), pcMatchTarget(0), pcParent(0) {} + : QmlAbstractAnimationPrivate(), pcTarget(0), pcParent(0) {} void init(); QmlGraphicsItem *pcTarget; - QmlGraphicsItem *pcMatchTarget; QmlGraphicsItem *pcParent; void doAction(); @@ -346,8 +344,7 @@ class QmlPropertyAnimationPrivate : public QmlAbstractAnimationPrivate public: QmlPropertyAnimationPrivate() : QmlAbstractAnimationPrivate(), target(0), fromSourced(false), fromIsDefined(false), toIsDefined(false), - rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0), - value(this, &QmlPropertyAnimationPrivate::valueChanged) {} + rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0) {} void init(); @@ -361,6 +358,7 @@ public: QString properties; QList<QObject *> targets; QList<QObject *> exclude; + QString defaultProperties; bool fromSourced; bool fromIsDefined:1; @@ -371,14 +369,20 @@ public: QVariantAnimation::Interpolator interpolator; QmlTimeLineValueAnimator *va; - virtual void valueChanged(qreal); - - QmlTimeLineValueProxy<QmlPropertyAnimationPrivate> value; static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress); static void convertVariant(QVariant &variant, int type); }; +class QmlRotationAnimationPrivate : public QmlPropertyAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlRotationAnimation) +public: + QmlRotationAnimationPrivate() : direction(QmlRotationAnimation::Shortest) {} + + QmlRotationAnimation::RotationDirection direction; +}; + QT_END_NAMESPACE #endif // QMLANIMATION_P_H diff --git a/src/declarative/util/qmlbehavior.cpp b/src/declarative/util/qmlbehavior.cpp index e8feeaa..276e2d0 100644 --- a/src/declarative/util/qmlbehavior.cpp +++ b/src/declarative/util/qmlbehavior.cpp @@ -124,8 +124,10 @@ void QmlBehavior::setAnimation(QmlAbstractAnimation *animation) } d->animation = animation; - if (d->animation) - d->animation->setTarget(d->property); + if (d->animation) { + d->animation->setDefaultTarget(d->property); + d->animation->setDisableUserControl(); + } } /*! @@ -183,7 +185,7 @@ void QmlBehavior::setTarget(const QmlMetaProperty &property) d->property = property; d->currentValue = property.read(); if (d->animation) - d->animation->setTarget(property); + d->animation->setDefaultTarget(property); } QT_END_NAMESPACE diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp index cefe2bc..b68a59c 100644 --- a/src/declarative/util/qmlstateoperations.cpp +++ b/src/declarative/util/qmlstateoperations.cpp @@ -403,7 +403,7 @@ QString QmlStateChangeScript::typeName() const so you can animate them as you would normally changes to these properties: \qml //animate our anchor changes - NumberAnimation { matchTargets: content; matchProperties: "x,y,width,height" } + NumberAnimation { targets: content; properties: "x,y,width,height" } \endqml For more information on anchors see \l {anchor-layout}{Anchor Layouts}. diff --git a/src/declarative/util/qmltransition.cpp b/src/declarative/util/qmltransition.cpp index 215fc91..d9e4bed 100644 --- a/src/declarative/util/qmltransition.cpp +++ b/src/declarative/util/qmltransition.cpp @@ -86,6 +86,7 @@ public: , reversed(false), reversible(false), endState(0) { animations.parent = this; + group.trans = this; } QString fromState; @@ -95,11 +96,6 @@ public: ParallelAnimationWrapper group; QmlTransitionManager *endState; - void init() - { - group.trans = this; - } - void complete() { endState->complete(); @@ -121,6 +117,7 @@ void QmlTransitionPrivate::AnimationList::append(QmlAbstractAnimation *a) { QmlConcreteList<QmlAbstractAnimation *>::append(a); parent->group.addAnimation(a->qtAnimation()); + a->setDisableUserControl(); } void ParallelAnimationWrapper::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) @@ -139,8 +136,6 @@ QML_DEFINE_TYPE(Qt,4,6,Transition,QmlTransition) QmlTransition::QmlTransition(QObject *parent) : QObject(*(new QmlTransitionPrivate), parent) { - Q_D(QmlTransition); - d->init(); } QmlTransition::~QmlTransition() |