Fix, test and document animation started/stopped signals.
authorMichael Brasser <michael.brasser@nokia.com>
Fri, 6 Jul 2012 01:43:41 +0000 (11:43 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 11 Jul 2012 15:37:55 +0000 (17:37 +0200)
Rename completed to stopped (as it is not only emitted
on completion). Ensure that the started and stopped signals
are emitted at the right times. Document the signals.

Task-number: QTBUG-14968
Change-Id: Icd3babcef2c9e544476592a26e6b9e58a21ebe95
Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>
src/quick/util/qquickanimation.cpp
src/quick/util/qquickanimation_p.h
tests/auto/quick/qquickanimations/data/signals.qml [new file with mode: 0644]
tests/auto/quick/qquickanimations/tst_qquickanimations.cpp

index ebdde58..5d7e21d 100644 (file)
@@ -175,7 +175,7 @@ void QQuickAbstractAnimationPrivate::commence()
         animationInstance->start();
         if (animationInstance->isStopped()) {
             running = false;
-            emit q->completed();
+            emit q->stopped();
         }
     }
 }
@@ -193,6 +193,31 @@ QQmlProperty QQuickAbstractAnimationPrivate::createProperty(QObject *obj, const
     return prop;
 }
 
+/*!
+    \qmlsignal QtQuick2::Animation::onStarted()
+
+    This signal handler is called when the animation begins.
+
+    It is only triggered for top-level, standalone animations. It will not be
+    triggered for animations in a Behavior or Transition, or animations
+    that are part of an animation group.
+*/
+
+/*!
+    \qmlsignal QtQuick2::Animation::onStopped()
+
+    This signal handler is called when the animation ends.
+
+    The animation may have been stopped manually, or may have run to completion.
+
+    It is only triggered for top-level, standalone animations. It will not be
+    triggered for animations in a Behavior or Transition, or animations
+    that are part of an animation group.
+
+    If \l alwaysRunToEnd is true, onStopped will not be called until the animation
+    has completed its current iteration.
+*/
+
 void QQuickAbstractAnimation::setRunning(bool r)
 {
     Q_D(QQuickAbstractAnimation);
@@ -231,9 +256,10 @@ void QQuickAbstractAnimation::setRunning(bool r)
                 d->animationInstance->setLoopCount(d->animationInstance->currentLoop() + d->loopCount);
             supressStart = true;    //we want the animation to continue, rather than restart
         }
-        if (!supressStart)
+        if (!supressStart) {
             d->commence();
-        emit started();
+            emit started();
+        }
     } else {
         if (d->paused) {
             d->paused = false; //reset paused state to false when stopped
@@ -246,9 +272,9 @@ void QQuickAbstractAnimation::setRunning(bool r)
                     d->animationInstance->setLoopCount(d->animationInstance->currentLoop()+1);    //finish the current loop
             } else {
                 d->animationInstance->stop();
+                emit stopped();
             }
         }
-        emit completed();
     }
 
     emit runningChanged(d->running);
@@ -608,9 +634,11 @@ void QQuickAbstractAnimationPrivate::animationFinished(QAbstractAnimationJob*)
 {
     Q_Q(QQuickAbstractAnimation);
     q->setRunning(false);
-    if (alwaysRunToEnd && loopCount != 1) {
+    if (alwaysRunToEnd) {
+        emit q->stopped();
         //restore the proper loopCount for the next run
-        animationInstance->setLoopCount(loopCount);
+        if (loopCount != 1)
+            animationInstance->setLoopCount(loopCount);
     }
 }
 
index 0fd746c..0f8e118 100644 (file)
@@ -106,7 +106,7 @@ public:
 
 Q_SIGNALS:
     void started();
-    void completed();
+    void stopped();
     void runningChanged(bool);
     void pausedChanged(bool);
     void alwaysRunToEndChanged(bool);
diff --git a/tests/auto/quick/qquickanimations/data/signals.qml b/tests/auto/quick/qquickanimations/data/signals.qml
new file mode 100644 (file)
index 0000000..c91ad93
--- /dev/null
@@ -0,0 +1,30 @@
+import QtQuick 2.0
+
+
+Item {
+    id: wrapper
+    width: 400; height: 400
+
+    function start() { animation.start() }
+    function stop() { animation.stop() }
+    property alias alwaysRunToEnd: animation.alwaysRunToEnd
+
+    property int startedCount: 0
+    property int stoppedCount: 0
+
+    Rectangle {
+        id: greenRect
+        width: 50; height: 50
+        color: "green"
+
+        NumberAnimation on x {
+            id: animation
+            from: 0
+            to: 100
+            duration: 200
+
+            onStarted: ++startedCount
+            onStopped: ++stoppedCount
+        }
+    }
+}
index 8cfdf74..b5ab04c 100644 (file)
@@ -97,6 +97,7 @@ private slots:
     void dontStart();
     void easingProperties();
     void rotation();
+    void startStopSignals();
     void runningTrueBug();
     void nonTransitionBug();
     void registrationBug();
@@ -1196,6 +1197,59 @@ void tst_qquickanimations::rotation()
     QTIMED_COMPARE(rr->rotation() + rr2->rotation() + rr3->rotation() + rr4->rotation(), qreal(370*4));
 }
 
+void tst_qquickanimations::startStopSignals()
+{
+    QQmlEngine engine;
+    QQmlComponent c(&engine, testFileUrl("signals.qml"));
+    QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+    QVERIFY(root);
+
+    QCOMPARE(root->property("startedCount").toInt(), 1);    //autostart
+    QCOMPARE(root->property("stoppedCount").toInt(), 0);
+
+    QMetaObject::invokeMethod(root, "stop");
+
+    QCOMPARE(root->property("startedCount").toInt(), 1);
+    QCOMPARE(root->property("stoppedCount").toInt(), 1);
+
+    QMetaObject::invokeMethod(root, "start");
+
+    QCOMPARE(root->property("startedCount").toInt(), 2);
+    QCOMPARE(root->property("stoppedCount").toInt(), 1);
+
+    QTest::qWait(100);
+
+    QCOMPARE(root->property("startedCount").toInt(), 2);
+    QCOMPARE(root->property("stoppedCount").toInt(), 1);
+
+    QTest::qWait(100);
+
+    QTRY_COMPARE(root->property("stoppedCount").toInt(), 2);
+    QCOMPARE(root->property("startedCount").toInt(), 2);
+
+    root->setProperty("alwaysRunToEnd", true);
+
+    QMetaObject::invokeMethod(root, "start");
+
+    QCOMPARE(root->property("startedCount").toInt(), 3);
+    QCOMPARE(root->property("stoppedCount").toInt(), 2);
+
+    QTest::qWait(100);
+
+    QCOMPARE(root->property("startedCount").toInt(), 3);
+    QCOMPARE(root->property("stoppedCount").toInt(), 2);
+
+    QMetaObject::invokeMethod(root, "stop");
+
+    QCOMPARE(root->property("startedCount").toInt(), 3);
+    QCOMPARE(root->property("stoppedCount").toInt(), 2);
+
+    QTest::qWait(100);
+
+    QTRY_COMPARE(root->property("stoppedCount").toInt(), 3);
+    QCOMPARE(root->property("startedCount").toInt(), 3);
+}
+
 void tst_qquickanimations::runningTrueBug()
 {
     //ensure we start correctly when "running: true" is explicitly set