Add a new running property to QQuickTransition
authorCharles Yin <yinyunqiao@gmail.com>
Fri, 16 Mar 2012 14:26:58 +0000 (00:26 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 16 Apr 2012 03:26:57 +0000 (05:26 +0200)
This read only property can be used to track the transition running
state. As all animation items inside a Transition item are just
animation defination templetes, so their running properties won't be
updated during the transition animations running, which makes it
hard to know the current running state of a transition animation.

Change-Id: If7fc0616ba384abc6bf2da67c7c639430c3d8fb9
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
src/qml/animations/qabstractanimationjob.cpp
src/qml/animations/qabstractanimationjob_p.h
src/quick/util/qquicktransition.cpp
src/quick/util/qquicktransition_p.h
tests/auto/quick/qquickanimations/tst_qquickanimations.cpp

index fecd8fb..d1b8880 100644 (file)
@@ -567,7 +567,6 @@ void QAbstractAnimationJob::removeAnimationChangeListener(QAnimationJobChangeLis
     changeListeners.removeOne(ChangeListener(listener, changes));
 }
 
-
 QT_END_NAMESPACE
 
 //#include "moc_qabstractanimation2_p.cpp"
index e7d96dd..d26aa86 100644 (file)
@@ -113,7 +113,6 @@ public:
 
     void addAnimationChangeListener(QAnimationJobChangeListener *listener, QAbstractAnimationJob::ChangeTypes);
     void removeAnimationChangeListener(QAnimationJobChangeListener *listener, QAbstractAnimationJob::ChangeTypes);
-
     QAbstractAnimationJob *nextSibling() const { return m_nextSibling; }
     QAbstractAnimationJob *previousSibling() const { return m_previousSibling; }
 
index 5d9a288..0f6ccb2 100644 (file)
@@ -96,34 +96,6 @@ QT_BEGIN_NAMESPACE
     \sa {QML Animation and Transitions}, {declarative/animation/states}{states example}, {qmlstates}{States}, {QtQml}
 */
 
-QQuickTransitionInstance::QQuickTransitionInstance()
-    : m_anim(0)
-{
-}
-
-QQuickTransitionInstance::~QQuickTransitionInstance()
-{
-    delete m_anim;
-}
-
-void QQuickTransitionInstance::start()
-{
-    if (m_anim)
-        m_anim->start();
-}
-
-void QQuickTransitionInstance::stop()
-{
-    if (m_anim)
-        m_anim->stop();
-}
-
-bool QQuickTransitionInstance::isRunning() const
-{
-    return m_anim && m_anim->state() == QAbstractAnimationJob::Running;
-}
-
-
 //ParallelAnimationWrapper allows us to do a "callback" when the animation finishes, rather than connecting
 //and disconnecting signals and slots frequently
 class ParallelAnimationWrapper : public QParallelAnimationGroupJob
@@ -136,21 +108,32 @@ protected:
     virtual void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
 };
 
-class QQuickTransitionPrivate : public QObjectPrivate
+class QQuickTransitionPrivate : public QObjectPrivate, QAnimationJobChangeListener
 {
     Q_DECLARE_PUBLIC(QQuickTransition)
 public:
     QQuickTransitionPrivate()
-    : fromState(QLatin1String("*")), toState(QLatin1String("*")),
-        reversed(false), reversible(false), enabled(true)
+    : fromState(QLatin1String("*")), toState(QLatin1String("*"))
+    , runningInstanceCount(0), state(QAbstractAnimationJob::Stopped)
+    , reversed(false), reversible(false), enabled(true)
     {
     }
 
+    void removeStateChangeListener(QAbstractAnimationJob *anim)
+    {
+        if (anim)
+            anim->removeAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
+    }
+
     QString fromState;
     QString toState;
+    quint32 runningInstanceCount;
+    QAbstractAnimationJob::State state;
     bool reversed;
     bool reversible;
     bool enabled;
+protected:
+    virtual void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State);
 
     static void append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a);
     static int animation_count(QQmlListProperty<QQuickAbstractAnimation> *list);
@@ -187,6 +170,21 @@ void QQuickTransitionPrivate::clear_animations(QQmlListProperty<QQuickAbstractAn
     }
 }
 
+void QQuickTransitionPrivate::animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
+{
+    Q_Q(QQuickTransition);
+
+    if (newState == QAbstractAnimationJob::Running) {
+        if (!runningInstanceCount)
+            emit q->runningChanged();
+        runningInstanceCount++;
+    } else if (newState == QAbstractAnimationJob::Stopped) {
+        runningInstanceCount--;
+        if (!runningInstanceCount)
+            emit q->runningChanged();
+    }
+}
+
 void ParallelAnimationWrapper::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState)
 {
     QParallelAnimationGroupJob::updateState(newState, oldState);
@@ -198,6 +196,34 @@ void ParallelAnimationWrapper::updateState(QAbstractAnimationJob::State newState
     }
 }
 
+QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim)
+    : m_transition(transition)
+    , m_anim(anim)
+{
+}
+
+QQuickTransitionInstance::~QQuickTransitionInstance()
+{
+    m_transition->removeStateChangeListener(m_anim);
+    delete m_anim;
+}
+
+void QQuickTransitionInstance::start()
+{
+    if (m_anim)
+        m_anim->start();
+}
+
+void QQuickTransitionInstance::stop()
+{
+    if (m_anim)
+        m_anim->stop();
+}
+
+bool QQuickTransitionInstance::isRunning() const
+{
+    return m_anim && m_anim->state() == QAbstractAnimationJob::Running;
+}
 
 QQuickTransition::QQuickTransition(QObject *parent)
     : QObject(*(new QQuickTransitionPrivate), parent)
@@ -240,8 +266,8 @@ QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::Action
 
     group->setDirection(d->reversed ? QAbstractAnimationJob::Backward : QAbstractAnimationJob::Forward);
 
-    QQuickTransitionInstance *wrapper = new QQuickTransitionInstance;
-    wrapper->m_anim = group;
+    group->addAnimationChangeListener(d, QAbstractAnimationJob::StateChange);
+    QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(d, group);
     return wrapper;
 }
 
@@ -386,6 +412,20 @@ void QQuickTransition::setEnabled(bool enabled)
 }
 
 /*!
+    \qmlproperty bool QtQuick2::Transition::running
+
+    This property holds whether the transition is currently running.
+
+    This property is read only.
+*/
+bool QQuickTransition::running() const
+{
+    Q_D(const QQuickTransition);
+    return d->runningInstanceCount;
+}
+
+
+/*!
     \qmlproperty list<Animation> QtQuick2::Transition::animations
     \default
 
index ebd82fd..976439c 100644 (file)
@@ -43,6 +43,7 @@
 #define QQUICKTRANSITION_H
 
 #include "qquickstate_p.h"
+#include <private/qabstractanimationjob_p.h>
 #include <qqml.h>
 
 #include <QtCore/qobject.h>
@@ -55,12 +56,11 @@ class QQuickAbstractAnimation;
 class QQuickTransitionPrivate;
 class QQuickTransitionManager;
 class QQuickTransition;
-class QAbstractAnimationJob;
 
 class Q_QUICK_EXPORT QQuickTransitionInstance
 {
 public:
-    QQuickTransitionInstance();
+    QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim);
     ~QQuickTransitionInstance();
 
     void start();
@@ -69,6 +69,7 @@ public:
     bool isRunning() const;
 
 private:
+    QQuickTransitionPrivate *m_transition;
     QAbstractAnimationJob *m_anim;
     friend class QQuickTransition;
 };
@@ -81,6 +82,7 @@ class Q_QUICK_EXPORT QQuickTransition : public QObject
     Q_PROPERTY(QString from READ fromState WRITE setFromState NOTIFY fromChanged)
     Q_PROPERTY(QString to READ toState WRITE setToState NOTIFY toChanged)
     Q_PROPERTY(bool reversible READ reversible WRITE setReversible NOTIFY reversibleChanged)
+    Q_PROPERTY(bool running READ running NOTIFY runningChanged)
     Q_PROPERTY(QQmlListProperty<QQuickAbstractAnimation> animations READ animations)
     Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
     Q_CLASSINFO("DefaultProperty", "animations")
@@ -102,6 +104,8 @@ public:
     bool enabled() const;
     void setEnabled(bool enabled);
 
+    bool running() const;
+
     QQmlListProperty<QQuickAbstractAnimation> animations();
 
     QQuickTransitionInstance *prepare(QQuickStateOperation::ActionList &actions,
@@ -116,6 +120,7 @@ Q_SIGNALS:
     void toChanged();
     void reversibleChanged();
     void enabledChanged();
+    void runningChanged();
 };
 
 QT_END_NAMESPACE
index 166f4b8..878cd55 100644 (file)
@@ -961,11 +961,12 @@ void tst_qquickanimations::disabledTransition()
     QCOMPARE(myRect->x(),qreal(200));
 
     trans->setEnabled(true);
-
+    QSignalSpy runningSpy(trans, SIGNAL(runningChanged()));
     QQuickItemPrivate::get(rect)->setState("");
     QCOMPARE(myRect->x(),qreal(200));
     QTest::qWait(300);
     QTIMED_COMPARE(myRect->x(),qreal(100));
+    QCOMPARE(runningSpy.count(), 2); //stopped, running, stopped
 }
 
 void tst_qquickanimations::invalidDuration()