tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QtTest/QtTest>
       
    43 
       
    44 #include <QtCore/qpropertyanimation.h>
       
    45 #include <QtCore/qvariantanimation.h>
       
    46 #include <QtGui/qwidget.h>
       
    47 
       
    48 //TESTED_CLASS=QPropertyAnimation
       
    49 //TESTED_FILES=
       
    50 
       
    51 class UncontrolledAnimation : public QPropertyAnimation
       
    52 {
       
    53     Q_OBJECT
       
    54 public:
       
    55     int duration() const { return -1; /* not time driven */ }
       
    56 
       
    57 protected:
       
    58     void updateCurrentTime(int currentTime)
       
    59     {
       
    60         QPropertyAnimation::updateCurrentTime(currentTime);
       
    61         if (currentTime >= QPropertyAnimation::duration() || currentLoop() >= 1)
       
    62             stop();
       
    63     }
       
    64 };
       
    65 
       
    66 class MyObject : public QObject
       
    67 {
       
    68     Q_OBJECT
       
    69     Q_PROPERTY(qreal x READ x WRITE setX)
       
    70 public:
       
    71     MyObject() : m_x(0) { }
       
    72     qreal x() const { return m_x; }
       
    73     void setX(qreal x) { m_x = x; }
       
    74 private:
       
    75     qreal m_x;
       
    76 };
       
    77 
       
    78 class DummyPropertyAnimation : public QPropertyAnimation
       
    79 {
       
    80 public:
       
    81     DummyPropertyAnimation(QObject *parent = 0) : QPropertyAnimation(parent)
       
    82     {
       
    83         setTargetObject(&o);
       
    84         this->setPropertyName("x");
       
    85         setEndValue(100);
       
    86     }
       
    87 
       
    88     MyObject o;
       
    89 };
       
    90 
       
    91 
       
    92 class tst_QPropertyAnimation : public QObject
       
    93 {
       
    94   Q_OBJECT
       
    95 public:
       
    96     tst_QPropertyAnimation();
       
    97     virtual ~tst_QPropertyAnimation();
       
    98 
       
    99 public Q_SLOTS:
       
   100     void init();
       
   101     void cleanup();
       
   102 
       
   103 private slots:
       
   104     void construction();
       
   105     void setCurrentTime_data();
       
   106     void setCurrentTime();
       
   107     void statesAndSignals_data();
       
   108     void statesAndSignals();
       
   109     void deletion1();
       
   110     void deletion2();
       
   111     void deletion3();
       
   112     void duration0();
       
   113     void noStartValue();
       
   114     void noStartValueWithLoop();
       
   115     void startWhenAnotherIsRunning();
       
   116     void easingcurve_data();
       
   117     void easingcurve();
       
   118     void startWithoutStartValue();
       
   119     void startBackwardWithoutEndValue();
       
   120     void playForwardBackward();
       
   121     void interpolated();
       
   122     void setStartEndValues_data();
       
   123     void setStartEndValues();
       
   124     void zeroDurationStart();
       
   125     void operationsInStates_data();
       
   126     void operationsInStates();
       
   127     void oneKeyValue();
       
   128     void updateOnSetKeyValues();
       
   129     void restart();
       
   130     void valueChanged();
       
   131     void twoAnimations();
       
   132     void deletedInUpdateCurrentTime();
       
   133     void totalDuration();
       
   134 };
       
   135 
       
   136 tst_QPropertyAnimation::tst_QPropertyAnimation()
       
   137 {
       
   138 }
       
   139 
       
   140 tst_QPropertyAnimation::~tst_QPropertyAnimation()
       
   141 {
       
   142 }
       
   143 
       
   144 void tst_QPropertyAnimation::init()
       
   145 {
       
   146     qRegisterMetaType<QAbstractAnimation::State>("QAbstractAnimation::State");
       
   147     qRegisterMetaType<QAbstractAnimation::DeletionPolicy>("QAbstractAnimation::DeletionPolicy");
       
   148 }
       
   149 
       
   150 void tst_QPropertyAnimation::cleanup()
       
   151 {
       
   152 }
       
   153 
       
   154 class AnimationObject : public QObject
       
   155 {
       
   156     Q_OBJECT
       
   157     Q_PROPERTY(int value READ value WRITE setValue)
       
   158     Q_PROPERTY(qreal realValue READ realValue WRITE setRealValue)
       
   159 public:
       
   160     AnimationObject(int startValue = 0)
       
   161         : v(startValue), rv(startValue)
       
   162     { }
       
   163 
       
   164     int value() const { return v; }
       
   165     void setValue(int value) { v = value; }
       
   166 
       
   167     qreal realValue() const { return rv; }
       
   168     void setRealValue(qreal value) { rv = value; }
       
   169 
       
   170     int v;
       
   171     qreal rv;
       
   172 };
       
   173 
       
   174 
       
   175 void tst_QPropertyAnimation::construction()
       
   176 {
       
   177     QPropertyAnimation panimation;
       
   178 }
       
   179 
       
   180 void tst_QPropertyAnimation::setCurrentTime_data()
       
   181 {
       
   182     QTest::addColumn<int>("duration");
       
   183     QTest::addColumn<int>("loopCount");
       
   184     QTest::addColumn<int>("currentTime");
       
   185     QTest::addColumn<int>("testCurrentTime");
       
   186     QTest::addColumn<int>("testCurrentLoop");
       
   187 
       
   188     QTest::newRow("-1") << -1 << 1 << 0 << 0 << 0;
       
   189     QTest::newRow("0")  <<  0 << 1 << 0 << 0 << 0;
       
   190     QTest::newRow("1")  <<  0 << 1 << 1 << 0 << 0;
       
   191     QTest::newRow("2")  <<  0 << 2 << 1 << 0 << 0;
       
   192     QTest::newRow("3")  <<  1 << 1 << 0 << 0 << 0;
       
   193     QTest::newRow("4")  <<  1 << 1 << 1 << 1 << 0;
       
   194     QTest::newRow("5")  <<  1 << 2 << 1 << 0 << 1;
       
   195     QTest::newRow("6")  <<  1 << 2 << 2 << 1 << 1;
       
   196     QTest::newRow("7")  <<  1 << 2 << 3 << 1 << 1;
       
   197     QTest::newRow("8")  <<  1 << 3 << 2 << 0 << 2;
       
   198     QTest::newRow("9")  <<  1 << 3 << 3 << 1 << 2;
       
   199     QTest::newRow("a") <<  10 << 1 << 0 << 0 << 0;
       
   200     QTest::newRow("b") <<  10 << 1 << 1 << 1 << 0;
       
   201     QTest::newRow("c") <<  10 << 1 << 10 << 10 << 0;
       
   202     QTest::newRow("d") <<  10 << 2 << 10 << 0 << 1;
       
   203     QTest::newRow("e") <<  10 << 2 << 11 << 1 << 1;
       
   204     QTest::newRow("f") <<  10 << 2 << 20 << 10 << 1;
       
   205     QTest::newRow("g") <<  10 << 2 << 21 << 10 << 1;
       
   206     QTest::newRow("negloop 0") <<  10 << -1 << 0 << 0 << 0;
       
   207     QTest::newRow("negloop 1") <<  10 << -1 << 10 << 0 << 1;
       
   208     QTest::newRow("negloop 2") <<  10 << -1 << 15 << 5 << 1;
       
   209     QTest::newRow("negloop 3") <<  10 << -1 << 20 << 0 << 2;
       
   210     QTest::newRow("negloop 4") <<  10 << -1 << 30 << 0 << 3;
       
   211 }
       
   212 
       
   213 void tst_QPropertyAnimation::setCurrentTime()
       
   214 {
       
   215     QFETCH(int, duration);
       
   216     QFETCH(int, loopCount);
       
   217     QFETCH(int, currentTime);
       
   218     QFETCH(int, testCurrentTime);
       
   219     QFETCH(int, testCurrentLoop);
       
   220 
       
   221     QPropertyAnimation animation;
       
   222     if (duration < 0)
       
   223         QTest::ignoreMessage(QtWarningMsg, "QVariantAnimation::setDuration: cannot set a negative duration");
       
   224     animation.setDuration(duration);
       
   225     animation.setLoopCount(loopCount);
       
   226     animation.setCurrentTime(currentTime);
       
   227 
       
   228     QCOMPARE(animation.currentTime(), testCurrentTime);
       
   229     QCOMPARE(animation.currentLoop(), testCurrentLoop);
       
   230 }
       
   231 
       
   232 void tst_QPropertyAnimation::statesAndSignals_data()
       
   233 {
       
   234     QTest::addColumn<bool>("uncontrolled");
       
   235     QTest::newRow("normal animation") << false;
       
   236     QTest::newRow("animation with undefined duration")  <<  true;
       
   237 }
       
   238 
       
   239 void tst_QPropertyAnimation::statesAndSignals()
       
   240 {
       
   241     QFETCH(bool, uncontrolled);
       
   242     QPropertyAnimation *anim;
       
   243     if (uncontrolled)
       
   244         anim = new UncontrolledAnimation;
       
   245     else
       
   246         anim = new DummyPropertyAnimation;
       
   247     anim->setDuration(100);
       
   248 
       
   249     QSignalSpy finishedSpy(anim, SIGNAL(finished()));
       
   250     QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
       
   251     QSignalSpy currentLoopSpy(anim, SIGNAL(currentLoopChanged(int)));
       
   252 
       
   253     anim->setCurrentTime(1);
       
   254     anim->setCurrentTime(100);
       
   255     QCOMPARE(finishedSpy.count(), 0);
       
   256     QCOMPARE(runningSpy.count(), 0);
       
   257     QCOMPARE(currentLoopSpy.count(), 0);
       
   258     QCOMPARE(anim->state(), QAnimationGroup::Stopped);
       
   259 
       
   260     anim->setLoopCount(3);
       
   261     anim->setCurrentTime(101);
       
   262 
       
   263     if (uncontrolled)
       
   264         QSKIP("Uncontrolled animations don't handle looping", SkipSingle);
       
   265 
       
   266     QCOMPARE(currentLoopSpy.count(), 1);
       
   267     QCOMPARE(anim->currentLoop(), 1);
       
   268 
       
   269     anim->setCurrentTime(0);
       
   270     QCOMPARE(currentLoopSpy.count(), 2);
       
   271     QCOMPARE(anim->currentLoop(), 0);
       
   272 
       
   273     anim->start();
       
   274     QCOMPARE(anim->state(), QAnimationGroup::Running);
       
   275     QCOMPARE(runningSpy.count(), 1); //anim must have started
       
   276     QCOMPARE(anim->currentLoop(), 0);
       
   277     runningSpy.clear();
       
   278 
       
   279     anim->stop();
       
   280     QCOMPARE(anim->state(), QAnimationGroup::Stopped);
       
   281     QCOMPARE(runningSpy.count(), 1); //anim must have stopped
       
   282     QCOMPARE(finishedSpy.count(), 0);
       
   283     QCOMPARE(anim->currentTime(), 0);
       
   284     QCOMPARE(anim->currentLoop(), 0);
       
   285     QCOMPARE(currentLoopSpy.count(), 2);
       
   286     runningSpy.clear();
       
   287 
       
   288     anim->start();
       
   289     QTest::qWait(1000);
       
   290     QCOMPARE(anim->state(), QAnimationGroup::Stopped);
       
   291     QCOMPARE(runningSpy.count(), 2); //started and stopped again
       
   292     runningSpy.clear();
       
   293     QCOMPARE(finishedSpy.count(), 1);
       
   294     QCOMPARE(anim->currentTime(), 100);
       
   295     QCOMPARE(anim->currentLoop(), 2);
       
   296     QCOMPARE(currentLoopSpy.count(), 4);
       
   297 
       
   298     anim->start(); // auto-rewinds
       
   299     QCOMPARE(anim->state(), QAnimationGroup::Running);
       
   300     QCOMPARE(anim->currentTime(), 0);
       
   301     QCOMPARE(anim->currentLoop(), 0);
       
   302     QCOMPARE(currentLoopSpy.count(), 5);
       
   303     QCOMPARE(runningSpy.count(), 1); // anim has started
       
   304     QCOMPARE(finishedSpy.count(), 1);
       
   305     QCOMPARE(anim->currentLoop(), 0);
       
   306     runningSpy.clear();
       
   307 
       
   308     QTest::qWait(1000);
       
   309 
       
   310     QCOMPARE(currentLoopSpy.count(), 7);
       
   311     QCOMPARE(anim->state(), QAnimationGroup::Stopped);
       
   312     QCOMPARE(anim->currentLoop(), 2);
       
   313     QCOMPARE(runningSpy.count(), 1); // anim has stopped
       
   314     QCOMPARE(finishedSpy.count(), 2);
       
   315     QCOMPARE(anim->currentTime(), 100);
       
   316 
       
   317     delete anim;
       
   318 }
       
   319 
       
   320 void tst_QPropertyAnimation::deletion1()
       
   321 {
       
   322     QObject *object = new QWidget;
       
   323     QPointer<QPropertyAnimation> anim = new QPropertyAnimation(object, "minimumWidth");
       
   324 
       
   325     //test that the animation is deleted correctly depending of the deletion flag passed in start()
       
   326     QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
       
   327     QSignalSpy finishedSpy(anim, SIGNAL(finished()));
       
   328     anim->setStartValue(10);
       
   329     anim->setEndValue(20);
       
   330     anim->setDuration(200);
       
   331     anim->start();
       
   332     QCOMPARE(runningSpy.count(), 1);
       
   333     QCOMPARE(finishedSpy.count(), 0);
       
   334 
       
   335     QVERIFY(anim);
       
   336     QCOMPARE(anim->state(), QAnimationGroup::Running);
       
   337     QTest::qWait(100);
       
   338     QVERIFY(anim);
       
   339     QCOMPARE(anim->state(), QAnimationGroup::Running);
       
   340     QTest::qWait(150);
       
   341     QVERIFY(anim); //The animation should not have been deleted
       
   342     QCOMPARE(anim->state(), QAnimationGroup::Stopped);
       
   343     QCOMPARE(runningSpy.count(), 2);
       
   344     QCOMPARE(finishedSpy.count(), 1);
       
   345 
       
   346     anim->start(QVariantAnimation::DeleteWhenStopped);
       
   347     QVERIFY(anim);
       
   348     QCOMPARE(anim->state(), QAnimationGroup::Running);
       
   349     QTest::qWait(100);
       
   350     QVERIFY(anim);
       
   351     QCOMPARE(anim->state(), QAnimationGroup::Running);
       
   352     QTest::qWait(150);
       
   353     QVERIFY(!anim);  //The animation must have been deleted
       
   354     QCOMPARE(runningSpy.count(), 4);
       
   355     QCOMPARE(finishedSpy.count(), 2);
       
   356     delete object;
       
   357 }
       
   358 
       
   359 void tst_QPropertyAnimation::deletion2()
       
   360 {
       
   361     //test that the animation get deleted if the object is deleted
       
   362     QObject *object = new QWidget;
       
   363     QPointer<QPropertyAnimation> anim = new QPropertyAnimation(object,"minimumWidth");
       
   364     anim->setStartValue(10);
       
   365     anim->setEndValue(20);
       
   366     anim->setDuration(200);
       
   367 
       
   368     QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
       
   369     QSignalSpy finishedSpy(anim, SIGNAL(finished()));
       
   370 
       
   371     anim->setStartValue(10);
       
   372     anim->setEndValue(20);
       
   373     anim->setDuration(200);
       
   374     anim->start();
       
   375 
       
   376     QTest::qWait(50);
       
   377     QVERIFY(anim);
       
   378     QCOMPARE(anim->state(), QAnimationGroup::Running);
       
   379 
       
   380     QCOMPARE(runningSpy.count(), 1);
       
   381     QCOMPARE(finishedSpy.count(), 0);
       
   382 
       
   383     //we can't call deletaLater directly because the delete would only happen in the next loop of _this_ event loop
       
   384     QTimer::singleShot(0, object, SLOT(deleteLater()));
       
   385     QTest::qWait(50);
       
   386 
       
   387     QVERIFY(anim->targetObject() == 0);
       
   388 }
       
   389 
       
   390 void tst_QPropertyAnimation::deletion3()
       
   391 {
       
   392     //test that the stopped signal is emit when the animation is destroyed
       
   393     QObject *object = new QWidget;
       
   394     QPropertyAnimation *anim = new QPropertyAnimation(object,"minimumWidth");
       
   395     anim->setStartValue(10);
       
   396     anim->setEndValue(20);
       
   397     anim->setDuration(200);
       
   398 
       
   399     QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
       
   400     QSignalSpy finishedSpy(anim, SIGNAL(finished()));
       
   401     anim->start();
       
   402 
       
   403     QTest::qWait(50);
       
   404     QCOMPARE(anim->state(), QAnimationGroup::Running);
       
   405     QCOMPARE(runningSpy.count(), 1);
       
   406     QCOMPARE(finishedSpy.count(), 0);
       
   407     delete anim;
       
   408     QCOMPARE(runningSpy.count(), 2);
       
   409     QCOMPARE(finishedSpy.count(), 0);
       
   410 }
       
   411 
       
   412 void tst_QPropertyAnimation::duration0()
       
   413 {
       
   414     QObject o;
       
   415     o.setProperty("ole", 42);
       
   416     QCOMPARE(o.property("ole").toInt(), 42);
       
   417 
       
   418     QPropertyAnimation animation(&o, "ole");
       
   419     animation.setEndValue(43);
       
   420     QVERIFY(!animation.currentValue().isValid());
       
   421     QCOMPARE(animation.currentValue().toInt(), 0);
       
   422     animation.setStartValue(42);
       
   423     QVERIFY(animation.currentValue().isValid());
       
   424     QCOMPARE(animation.currentValue().toInt(), 42);
       
   425 
       
   426     QCOMPARE(o.property("ole").toInt(), 42);
       
   427     animation.setDuration(0);
       
   428     QCOMPARE(animation.currentValue().toInt(), 43); //it is at the end
       
   429     animation.start();
       
   430     QCOMPARE(animation.state(), QAnimationGroup::Stopped);
       
   431     QCOMPARE(animation.currentTime(), 0);
       
   432     QCOMPARE(o.property("ole").toInt(), 43);
       
   433 }
       
   434 
       
   435 class StartValueTester : public QObject
       
   436 {
       
   437     Q_OBJECT
       
   438     Q_PROPERTY(int ole READ ole WRITE setOle)
       
   439 public:
       
   440     StartValueTester() : o(0) { }
       
   441     int ole() const { return o; }
       
   442     void setOle(int v) { o = v; values << v; }
       
   443 
       
   444     int o;
       
   445     QList<int> values;
       
   446 };
       
   447 
       
   448 void tst_QPropertyAnimation::noStartValue()
       
   449 {
       
   450     StartValueTester o;
       
   451     o.setProperty("ole", 42);
       
   452     o.values.clear();
       
   453 
       
   454     QPropertyAnimation a(&o, "ole");
       
   455     a.setEndValue(420);
       
   456     a.setDuration(250);
       
   457     a.start();
       
   458 
       
   459     QTest::qWait(300);
       
   460 
       
   461     QCOMPARE(o.values.first(), 42);
       
   462     QCOMPARE(o.values.last(), 420);
       
   463 }
       
   464 
       
   465 void tst_QPropertyAnimation::noStartValueWithLoop()
       
   466 {
       
   467     StartValueTester o;
       
   468     o.setProperty("ole", 42);
       
   469     o.values.clear();
       
   470 
       
   471     QPropertyAnimation a(&o, "ole");
       
   472     a.setEndValue(420);
       
   473     a.setDuration(250);
       
   474     a.setLoopCount(2);
       
   475     a.start();
       
   476 
       
   477     a.setCurrentTime(250);
       
   478     QCOMPARE(o.values.first(), 42);
       
   479     QCOMPARE(a.currentValue().toInt(), 42);
       
   480     QCOMPARE(o.values.last(), 42);
       
   481 
       
   482     a.setCurrentTime(500);
       
   483     QCOMPARE(a.currentValue().toInt(), 420);
       
   484 }
       
   485 
       
   486 void tst_QPropertyAnimation::startWhenAnotherIsRunning()
       
   487 {
       
   488     StartValueTester o;
       
   489     o.setProperty("ole", 42);
       
   490     o.values.clear();
       
   491 
       
   492     {
       
   493         //normal case: the animation finishes and is deleted
       
   494         QPointer<QVariantAnimation> anim = new QPropertyAnimation(&o, "ole");
       
   495         anim->setEndValue(100);
       
   496         QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
       
   497         anim->start(QVariantAnimation::DeleteWhenStopped);
       
   498         QTest::qWait(anim->duration() + 50);
       
   499         QCOMPARE(runningSpy.count(), 2); //started and then stopped
       
   500         QVERIFY(!anim);
       
   501     }
       
   502 
       
   503     {
       
   504         QPointer<QVariantAnimation> anim = new QPropertyAnimation(&o, "ole");
       
   505         anim->setEndValue(100);
       
   506         QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
       
   507         anim->start(QVariantAnimation::DeleteWhenStopped);
       
   508         QTest::qWait(anim->duration()/2);
       
   509         QPointer<QVariantAnimation> anim2 = new QPropertyAnimation(&o, "ole");
       
   510         anim2->setEndValue(100);
       
   511         QCOMPARE(runningSpy.count(), 1);
       
   512         QCOMPARE(anim->state(), QVariantAnimation::Running);
       
   513 
       
   514         //anim2 will interrupt anim1
       
   515         QMetaObject::invokeMethod(anim2, "start", Qt::QueuedConnection, Q_ARG(QAbstractAnimation::DeletionPolicy, QVariantAnimation::DeleteWhenStopped));
       
   516         QTest::qWait(50);
       
   517         QVERIFY(!anim); //anim should have been deleted
       
   518         QVERIFY(anim2);
       
   519         QTest::qWait(anim2->duration());
       
   520         QVERIFY(!anim2); //anim2 is finished: it should have been deleted by now
       
   521         QVERIFY(!anim);
       
   522     }
       
   523 
       
   524 }
       
   525 
       
   526 // copy  from easing.cpp in case that function changes definition
       
   527 static qreal easeInOutBack(qreal t)
       
   528 {
       
   529     qreal s = 1.70158;
       
   530     qreal t_adj = 2.0f * (qreal)t;
       
   531     if (t_adj < 1) {
       
   532         s *= 1.525f;
       
   533         return 1.0/2*(t_adj*t_adj*((s+1)*t_adj - s));
       
   534     } else {
       
   535         t_adj -= 2;
       
   536         s *= 1.525f;
       
   537         return 1.0/2*(t_adj*t_adj*((s+1)*t_adj + s) + 2);
       
   538     }
       
   539 }
       
   540 
       
   541 void tst_QPropertyAnimation::easingcurve_data()
       
   542 {
       
   543     QTest::addColumn<int>("currentTime");
       
   544     QTest::addColumn<int>("expectedvalue");
       
   545 
       
   546     QTest::newRow("interpolation1") << 0 << 0;
       
   547     QTest::newRow("interpolation2") << 1000 << 1000;
       
   548     QTest::newRow("extrapolationbelow") << 250 << -99;
       
   549     QTest::newRow("extrapolationabove") << 750 << 1099;
       
   550 }
       
   551 
       
   552 void tst_QPropertyAnimation::easingcurve()
       
   553 {
       
   554     QFETCH(int, currentTime);
       
   555     QFETCH(int, expectedvalue);
       
   556     QObject o;
       
   557     o.setProperty("ole", 42);
       
   558     QCOMPARE(o.property("ole").toInt(), 42);
       
   559 
       
   560     QPropertyAnimation pAnimation(&o, "ole");
       
   561     pAnimation.setStartValue(0);
       
   562     pAnimation.setEndValue(1000);
       
   563     pAnimation.setDuration(1000);
       
   564 
       
   565     // this easingcurve assumes that we extrapolate before startValue and after endValue
       
   566     QEasingCurve easingCurve;
       
   567     easingCurve.setCustomType(easeInOutBack);
       
   568     pAnimation.setEasingCurve(easingCurve);
       
   569     pAnimation.start();
       
   570     pAnimation.pause();
       
   571     pAnimation.setCurrentTime(currentTime);
       
   572     QCOMPARE(o.property("ole").toInt(), expectedvalue);
       
   573 }
       
   574 
       
   575 void tst_QPropertyAnimation::startWithoutStartValue()
       
   576 {
       
   577     QObject o;
       
   578     o.setProperty("ole", 42);
       
   579     QCOMPARE(o.property("ole").toInt(), 42);
       
   580 
       
   581     QPropertyAnimation anim(&o, "ole");
       
   582     anim.setEndValue(100);
       
   583 
       
   584     anim.start();
       
   585 
       
   586     QTest::qWait(100);
       
   587     int current = anim.currentValue().toInt();
       
   588     //it is somewhere in the animation
       
   589     QVERIFY(current > 42);
       
   590     QVERIFY(current < 100);
       
   591 
       
   592     QTest::qWait(200);
       
   593     QCOMPARE(anim.state(), QVariantAnimation::Stopped);
       
   594     current = anim.currentValue().toInt();
       
   595     QCOMPARE(current, 100);
       
   596     QCOMPARE(o.property("ole").toInt(), current);
       
   597 
       
   598     anim.setEndValue(110);
       
   599     anim.start();
       
   600     current = anim.currentValue().toInt();
       
   601     // the default start value will reevaluate the current property
       
   602     // and set it to the end value of the last iteration
       
   603     QCOMPARE(current, 100);
       
   604     QTest::qWait(100);
       
   605     current = anim.currentValue().toInt();
       
   606     //it is somewhere in the animation
       
   607     QVERIFY(current >= 100);
       
   608     QVERIFY(current <= 110);
       
   609 }
       
   610 
       
   611 void tst_QPropertyAnimation::startBackwardWithoutEndValue()
       
   612 {
       
   613     QObject o;
       
   614     o.setProperty("ole", 42);
       
   615     QCOMPARE(o.property("ole").toInt(), 42);
       
   616 
       
   617     QPropertyAnimation anim(&o, "ole");
       
   618     anim.setStartValue(100);
       
   619     anim.setDirection(QAbstractAnimation::Backward);
       
   620 
       
   621     //we start without an end value
       
   622     anim.start();
       
   623     QCOMPARE(anim.state(), QAbstractAnimation::Running);
       
   624     QCOMPARE(o.property("ole").toInt(), 42); //the initial value
       
   625 
       
   626     QTest::qWait(100);
       
   627     int current = anim.currentValue().toInt();
       
   628     //it is somewhere in the animation
       
   629     QVERIFY(current > 42);
       
   630     QVERIFY(current < 100);
       
   631 
       
   632     QTest::qWait(200);
       
   633     QCOMPARE(anim.state(), QVariantAnimation::Stopped);
       
   634     current = anim.currentValue().toInt();
       
   635     QCOMPARE(current, 100);
       
   636     QCOMPARE(o.property("ole").toInt(), current);
       
   637 
       
   638     anim.setStartValue(110);
       
   639     anim.start();
       
   640     current = anim.currentValue().toInt();
       
   641     // the default start value will reevaluate the current property
       
   642     // and set it to the end value of the last iteration
       
   643     QCOMPARE(current, 100);
       
   644     QTest::qWait(100);
       
   645     current = anim.currentValue().toInt();
       
   646     //it is somewhere in the animation
       
   647     QVERIFY(current >= 100);
       
   648     QVERIFY(current <= 110);
       
   649 }
       
   650 
       
   651 
       
   652 void tst_QPropertyAnimation::playForwardBackward()
       
   653 {
       
   654     QObject o;
       
   655     o.setProperty("ole", 0);
       
   656     QCOMPARE(o.property("ole").toInt(), 0);
       
   657 
       
   658     QPropertyAnimation anim(&o, "ole");
       
   659     anim.setStartValue(0);
       
   660     anim.setEndValue(100);
       
   661     anim.start();
       
   662     QTest::qWait(anim.duration() + 50);
       
   663     QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
       
   664     QCOMPARE(anim.currentTime(), anim.duration());
       
   665 
       
   666     //the animation is at the end
       
   667     anim.setDirection(QVariantAnimation::Backward);
       
   668     anim.start();
       
   669     QCOMPARE(anim.state(), QAbstractAnimation::Running);
       
   670     QTest::qWait(anim.duration() + 50);
       
   671     QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
       
   672     QCOMPARE(anim.currentTime(), 0);
       
   673 
       
   674     //the direction is backward
       
   675     //restarting should jump to the end
       
   676     anim.start();
       
   677     QCOMPARE(anim.state(), QAbstractAnimation::Running);
       
   678     QCOMPARE(anim.currentTime(), anim.duration());
       
   679     QTest::qWait(anim.duration() + 50);
       
   680     QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
       
   681     QCOMPARE(anim.currentTime(), 0);
       
   682 }
       
   683 
       
   684 struct Number
       
   685 {
       
   686     Number() {}
       
   687     Number(int n)
       
   688         : n(n) {}
       
   689 
       
   690     Number(const Number &other)
       
   691         : n(other.n){}
       
   692 
       
   693     Number &operator=(const Number &other) {
       
   694         n = other.n;
       
   695         return *this;
       
   696     }
       
   697     bool operator==(const Number &other) const {
       
   698         return n == other.n;
       
   699     }
       
   700 
       
   701     int n;
       
   702 };
       
   703 
       
   704 Q_DECLARE_METATYPE(Number)
       
   705 Q_DECLARE_METATYPE(QAbstractAnimation::State)
       
   706 
       
   707 QVariant numberInterpolator(const Number &f, const Number &t, qreal progress)
       
   708 {
       
   709     return qVariantFromValue<Number>(Number(f.n + (t.n - f.n)*progress));
       
   710 }
       
   711 
       
   712 QVariant xaxisQPointInterpolator(const QPointF &f, const QPointF &t, qreal progress)
       
   713 {
       
   714     return QPointF(f.x() + (t.x() - f.x())*progress, f.y());
       
   715 }
       
   716 
       
   717 void tst_QPropertyAnimation::interpolated()
       
   718 {
       
   719     QObject o;
       
   720     o.setProperty("point", QPointF()); //this will avoid warnings
       
   721     o.setProperty("number", qVariantFromValue<Number>(Number(42)));
       
   722     QCOMPARE(qVariantValue<Number>(o.property("number")), Number(42));
       
   723     {
       
   724     qRegisterAnimationInterpolator<Number>(numberInterpolator);
       
   725     QPropertyAnimation anim(&o, "number");
       
   726     anim.setStartValue(qVariantFromValue<Number>(Number(0)));
       
   727     anim.setEndValue(qVariantFromValue<Number>(Number(100)));
       
   728     anim.setDuration(1000);
       
   729     anim.start();
       
   730     anim.pause();
       
   731     anim.setCurrentTime(100);
       
   732     Number t(qVariantValue<Number>(o.property("number")));
       
   733     QCOMPARE(t, Number(10));
       
   734     anim.setCurrentTime(500);
       
   735     QCOMPARE(qVariantValue<Number>(o.property("number")), Number(50));
       
   736     }
       
   737     {
       
   738     qRegisterAnimationInterpolator<QPointF>(xaxisQPointInterpolator);
       
   739     QPropertyAnimation anim(&o, "point");
       
   740     anim.setStartValue(QPointF(0,0));
       
   741     anim.setEndValue(QPointF(100, 100));
       
   742     anim.setDuration(1000);
       
   743     anim.start();
       
   744     anim.pause();
       
   745     anim.setCurrentTime(100);
       
   746     QCOMPARE(o.property("point"), QVariant(QPointF(10, 0)));
       
   747     anim.setCurrentTime(500);
       
   748     QCOMPARE(o.property("point"), QVariant(QPointF(50, 0)));
       
   749     }
       
   750     {
       
   751     // unregister it and see if we get back the default behaviour
       
   752     qRegisterAnimationInterpolator<QPointF>(0);
       
   753     QPropertyAnimation anim(&o, "point");
       
   754     anim.setStartValue(QPointF(0,0));
       
   755     anim.setEndValue(QPointF(100, 100));
       
   756     anim.setDuration(1000);
       
   757     anim.start();
       
   758     anim.pause();
       
   759     anim.setCurrentTime(100);
       
   760     QCOMPARE(o.property("point").toPointF(), QPointF(10, 10));
       
   761     anim.setCurrentTime(500);
       
   762     QCOMPARE(o.property("point").toPointF(), QPointF(50, 50));
       
   763     }
       
   764 
       
   765     {
       
   766     // Interpolate a qreal property with a int interpolator
       
   767     AnimationObject o1;
       
   768     o1.setRealValue(42.42);
       
   769     QPropertyAnimation anim(&o1, "realValue");
       
   770     anim.setStartValue(0);
       
   771     anim.setEndValue(100);
       
   772     anim.start();
       
   773     QCOMPARE(o1.realValue(), qreal(0));
       
   774     anim.setCurrentTime(250);
       
   775     QCOMPARE(o1.realValue(), qreal(100));
       
   776     }
       
   777 }
       
   778 
       
   779 Q_DECLARE_METATYPE(QVariant)
       
   780 
       
   781 void tst_QPropertyAnimation::setStartEndValues_data()
       
   782 {
       
   783     QTest::addColumn<QByteArray>("propertyName");
       
   784     QTest::addColumn<QVariant>("initialValue");
       
   785     QTest::addColumn<QVariant>("startValue");
       
   786     QTest::addColumn<QVariant>("endValue");
       
   787 
       
   788     QTest::newRow("dynamic property")  << QByteArray("ole") << QVariant(42) << QVariant(0) << QVariant(10);
       
   789     QTest::newRow("real property, with unmatching types") << QByteArray("x") << QVariant(42.) << QVariant(0) << QVariant(10.);
       
   790 }
       
   791 
       
   792 void tst_QPropertyAnimation::setStartEndValues()
       
   793 {
       
   794     MyObject object;
       
   795     QFETCH(QByteArray, propertyName);
       
   796     QFETCH(QVariant, initialValue);
       
   797     QFETCH(QVariant, startValue);
       
   798     QFETCH(QVariant, endValue);
       
   799 
       
   800     //this tests the start value, end value and default start value
       
   801     object.setProperty(propertyName, initialValue);
       
   802     QPropertyAnimation anim(&object, propertyName);
       
   803     QVariantAnimation::KeyValues values;
       
   804     QCOMPARE(anim.keyValues(), values);
       
   805 
       
   806     //let's add a start value
       
   807     anim.setStartValue(startValue);
       
   808     values << QVariantAnimation::KeyValue(0, startValue);
       
   809     QCOMPARE(anim.keyValues(), values);
       
   810 
       
   811     anim.setEndValue(endValue);
       
   812     values << QVariantAnimation::KeyValue(1, endValue);
       
   813     QCOMPARE(anim.keyValues(), values);
       
   814 
       
   815     //now we can play with objects
       
   816     QCOMPARE(object.property(propertyName).toDouble(), initialValue.toDouble());
       
   817     anim.start();
       
   818     QVERIFY(anim.startValue().isValid());
       
   819     QCOMPARE(object.property(propertyName), anim.startValue());
       
   820     anim.setCurrentTime(anim.duration()/2);
       
   821     QCOMPARE(object.property(propertyName).toDouble(), (startValue.toDouble() + endValue.toDouble())/2 ); //just in the middle of the animation
       
   822     anim.setCurrentTime(anim.duration()); //we go to the end of the animation
       
   823     QCOMPARE(anim.state(), QAnimationGroup::Stopped); //it should have stopped
       
   824     QVERIFY(anim.endValue().isValid());
       
   825     QCOMPARE(object.property(propertyName), anim.endValue()); //end of the animations
       
   826 
       
   827     //now we remove the explicit start value and test the implicit one
       
   828     anim.stop();
       
   829     object.setProperty(propertyName, initialValue);
       
   830 
       
   831     //let's reset the start value
       
   832     values.remove(0);
       
   833     anim.setStartValue(QVariant());
       
   834     QCOMPARE(anim.keyValues(), values);
       
   835     QVERIFY(!anim.startValue().isValid());
       
   836 
       
   837     anim.start();
       
   838     QCOMPARE(object.property(propertyName), initialValue);
       
   839     anim.setCurrentTime(anim.duration()/2);
       
   840     QCOMPARE(object.property(propertyName).toDouble(), (initialValue.toDouble() + endValue.toDouble())/2 ); //just in the middle of the animation
       
   841     anim.setCurrentTime(anim.duration()); //we go to the end of the animation
       
   842     QCOMPARE(anim.state(), QAnimationGroup::Stopped); //it should have stopped
       
   843     QVERIFY(anim.endValue().isValid());
       
   844     QCOMPARE(object.property(propertyName), anim.endValue()); //end of the animations
       
   845 
       
   846     //now we set back the startValue
       
   847     anim.setStartValue(startValue);
       
   848     QVERIFY(anim.startValue().isValid());
       
   849     anim.start();
       
   850     QCOMPARE(object.property(propertyName), startValue);
       
   851 }
       
   852 
       
   853 void tst_QPropertyAnimation::zeroDurationStart()
       
   854 {
       
   855     DummyPropertyAnimation anim;
       
   856     QSignalSpy spy(&anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
       
   857     anim.setDuration(0);
       
   858     QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
       
   859     anim.start();
       
   860     //the animation stops immediately
       
   861     QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
       
   862     QCOMPARE(spy.count(), 2);
       
   863 
       
   864     //let's check the first state change
       
   865     const QVariantList firstChange = spy.first();
       
   866     //old state
       
   867     QCOMPARE(qVariantValue<QAbstractAnimation::State>(firstChange.first()), QAbstractAnimation::Stopped);
       
   868     //new state
       
   869     QCOMPARE(qVariantValue<QAbstractAnimation::State>(firstChange.last()), QAbstractAnimation::Running);
       
   870 
       
   871     //let's check the first state change
       
   872     const QVariantList secondChange = spy.last();
       
   873     //old state
       
   874     QCOMPARE(qVariantValue<QAbstractAnimation::State>(secondChange.first()), QAbstractAnimation::Running);
       
   875     //new state
       
   876     QCOMPARE(qVariantValue<QAbstractAnimation::State>(secondChange.last()), QAbstractAnimation::Stopped);
       
   877 }
       
   878 
       
   879 #define Pause 1
       
   880 #define Start 2
       
   881 #define Resume 3
       
   882 #define Stop 4
       
   883 
       
   884 void tst_QPropertyAnimation::operationsInStates_data()
       
   885 {
       
   886     QTest::addColumn<QAbstractAnimation::State>("originState");
       
   887     QTest::addColumn<int>("operation");
       
   888     QTest::addColumn<QString>("expectedWarning");
       
   889     QTest::addColumn<QAbstractAnimation::State>("expectedState");
       
   890 
       
   891     QString pauseWarn(QLatin1String("QAbstractAnimation::pause: Cannot pause a stopped animation"));
       
   892     QString resumeWarn(QLatin1String("QAbstractAnimation::resume: Cannot resume an animation that is not paused"));
       
   893 
       
   894     QTest::newRow("S-pause")  << QAbstractAnimation::Stopped << Pause << pauseWarn << QAbstractAnimation::Stopped;
       
   895     QTest::newRow("S-start")  << QAbstractAnimation::Stopped << Start << QString() << QAbstractAnimation::Running;
       
   896     QTest::newRow("S-resume") << QAbstractAnimation::Stopped << Resume << resumeWarn << QAbstractAnimation::Stopped;
       
   897     QTest::newRow("S-stop")   << QAbstractAnimation::Stopped << Stop << QString() << QAbstractAnimation::Stopped;
       
   898 
       
   899     QTest::newRow("P-pause")  << QAbstractAnimation::Paused << Pause << QString() << QAbstractAnimation::Paused;
       
   900     QTest::newRow("P-start")  << QAbstractAnimation::Paused << Start << QString() << QAbstractAnimation::Running;
       
   901     QTest::newRow("P-resume") << QAbstractAnimation::Paused << Resume << QString() << QAbstractAnimation::Running;
       
   902     QTest::newRow("P-stop")   << QAbstractAnimation::Paused << Stop << QString() << QAbstractAnimation::Stopped;
       
   903 
       
   904     QTest::newRow("R-pause")  << QAbstractAnimation::Running << Pause << QString() << QAbstractAnimation::Paused;
       
   905     QTest::newRow("R-start")  << QAbstractAnimation::Running << Start << QString() << QAbstractAnimation::Running;
       
   906     QTest::newRow("R-resume") << QAbstractAnimation::Running << Resume << resumeWarn << QAbstractAnimation::Running;
       
   907     QTest::newRow("R-stop")   << QAbstractAnimation::Running << Stop << QString() << QAbstractAnimation::Stopped;
       
   908 }
       
   909 
       
   910 void tst_QPropertyAnimation::operationsInStates()
       
   911 {
       
   912 /**
       
   913  *           | pause()    |start()    |resume()   |stop()
       
   914  * ----------+------------+-----------+-----------+-------------------+
       
   915  * Stopped   | Stopped    |Running    |Stopped    |Stopped            |
       
   916  *          _| qWarning   |restart    |qWarning   |                   |
       
   917  * Paused    | Paused     |Running    |Running    |Stopped            |
       
   918  *          _|            |           |           |                   |
       
   919  * Running   | Paused     |Running    |Running    |Stopped            |
       
   920  *           |            |restart    |qWarning   |                   |
       
   921  * ----------+------------+-----------+-----------+-------------------+
       
   922 **/
       
   923 
       
   924     QFETCH(QAbstractAnimation::State, originState);
       
   925     QFETCH(int, operation);
       
   926     QFETCH(QString, expectedWarning);
       
   927     QFETCH(QAbstractAnimation::State, expectedState);
       
   928 
       
   929     QObject o;
       
   930     o.setProperty("ole", 42);
       
   931     QPropertyAnimation anim(&o, "ole");
       
   932     anim.setEndValue(100);
       
   933     QSignalSpy spy(&anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
       
   934 
       
   935     anim.stop();
       
   936     switch (originState) {
       
   937     case QAbstractAnimation::Stopped:
       
   938     break;
       
   939     case QAbstractAnimation::Paused:
       
   940         anim.start();
       
   941         anim.pause();
       
   942     break;
       
   943     case QAbstractAnimation::Running:
       
   944         anim.start();
       
   945     break;
       
   946     }
       
   947     if (!expectedWarning.isEmpty()) {
       
   948         QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning));
       
   949     }
       
   950     QCOMPARE(anim.state(), originState);
       
   951     switch (operation) {
       
   952     case Pause:
       
   953         anim.pause();
       
   954     break;
       
   955     case Start:
       
   956         anim.start();
       
   957     break;
       
   958     case Resume:
       
   959         anim.resume();
       
   960     break;
       
   961     case Stop:
       
   962         anim.stop();
       
   963     break;
       
   964     }
       
   965 
       
   966     QCOMPARE(anim.state(), expectedState);
       
   967 }
       
   968 #undef Pause
       
   969 #undef Start
       
   970 #undef Resume
       
   971 #undef Stop
       
   972 
       
   973 void tst_QPropertyAnimation::oneKeyValue()
       
   974 {
       
   975     QObject o;
       
   976     o.setProperty("ole", 42);
       
   977     QCOMPARE(o.property("ole").toInt(), 42);
       
   978 
       
   979     QPropertyAnimation animation(&o, "ole");
       
   980     animation.setStartValue(43);
       
   981     animation.setEndValue(44);
       
   982     animation.setDuration(100);
       
   983 
       
   984     animation.setCurrentTime(0);
       
   985 
       
   986     QVERIFY(animation.currentValue().isValid());
       
   987     QCOMPARE(animation.currentValue().toInt(), 43);
       
   988     QCOMPARE(o.property("ole").toInt(), 42);
       
   989 
       
   990     // remove the last key value
       
   991     animation.setKeyValueAt(1.0, QVariant());
       
   992 
       
   993     // we will neither interpolate, nor update the current value
       
   994     // since there is only one 1 key value defined
       
   995     animation.setCurrentTime(100);
       
   996 
       
   997     // the animation should not have been modified
       
   998     QVERIFY(animation.currentValue().isValid());
       
   999     QCOMPARE(animation.currentValue().toInt(), 43);
       
  1000     QCOMPARE(o.property("ole").toInt(), 42);
       
  1001 }
       
  1002 
       
  1003 void tst_QPropertyAnimation::updateOnSetKeyValues()
       
  1004 {
       
  1005     QObject o;
       
  1006     o.setProperty("ole", 100);
       
  1007     QCOMPARE(o.property("ole").toInt(), 100);
       
  1008 
       
  1009     QPropertyAnimation animation(&o, "ole");
       
  1010     animation.setStartValue(100);
       
  1011     animation.setEndValue(200);
       
  1012     animation.setDuration(100);
       
  1013 
       
  1014     animation.setCurrentTime(50);
       
  1015     QCOMPARE(animation.currentValue().toInt(), 150);
       
  1016     animation.setKeyValueAt(0.0, 300);
       
  1017     QCOMPARE(animation.currentValue().toInt(), 250);
       
  1018 
       
  1019     o.setProperty("ole", 100);
       
  1020     QPropertyAnimation animation2(&o, "ole");
       
  1021     QVariantAnimation::KeyValues kValues;
       
  1022     kValues << QVariantAnimation::KeyValue(0.0, 100) << QVariantAnimation::KeyValue(1.0, 200);
       
  1023     animation2.setKeyValues(kValues);
       
  1024     animation2.setDuration(100);
       
  1025     animation2.setCurrentTime(50);
       
  1026     QCOMPARE(animation2.currentValue().toInt(), 150);
       
  1027 
       
  1028     kValues.clear();
       
  1029     kValues << QVariantAnimation::KeyValue(0.0, 300) << QVariantAnimation::KeyValue(1.0, 200);
       
  1030     animation2.setKeyValues(kValues);
       
  1031 
       
  1032     QCOMPARE(animation2.currentValue().toInt(), animation.currentValue().toInt());
       
  1033 }
       
  1034 
       
  1035 
       
  1036 //this class will 'throw' an error in the test lib
       
  1037 // if the property ole is set to ErrorValue
       
  1038 class MyErrorObject : public QObject
       
  1039 {
       
  1040     Q_OBJECT
       
  1041     Q_PROPERTY(int ole READ ole WRITE setOle)
       
  1042 public:
       
  1043 
       
  1044     static const int ErrorValue = 10000;
       
  1045 
       
  1046     MyErrorObject() : m_ole(0) { }
       
  1047     int ole() const { return m_ole; }
       
  1048     void setOle(int o)
       
  1049     {
       
  1050         QVERIFY(o != ErrorValue);
       
  1051         m_ole = o;
       
  1052     }
       
  1053 
       
  1054 private:
       
  1055     int m_ole;
       
  1056 
       
  1057 
       
  1058 };
       
  1059 
       
  1060 void tst_QPropertyAnimation::restart()
       
  1061 {
       
  1062     //here we check that be restarting an animation
       
  1063     //it doesn't get an bogus intermediate value (end value)
       
  1064     //because the time is not yet reset to 0
       
  1065     MyErrorObject o;
       
  1066     o.setOle(100);
       
  1067     QCOMPARE(o.property("ole").toInt(), 100);
       
  1068 
       
  1069     QPropertyAnimation anim(&o, "ole");
       
  1070     anim.setEndValue(200);
       
  1071     anim.start();
       
  1072     anim.setCurrentTime(anim.duration());
       
  1073     QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
       
  1074     QCOMPARE(o.property("ole").toInt(), 200);
       
  1075 
       
  1076     //we'll check that the animation never gets a wrong value when starting it
       
  1077     //after having changed the end value
       
  1078     anim.setEndValue(MyErrorObject::ErrorValue);
       
  1079     anim.start();
       
  1080 }
       
  1081 
       
  1082 void tst_QPropertyAnimation::valueChanged()
       
  1083 {
       
  1084     qRegisterMetaType<QVariant>("QVariant");
       
  1085 
       
  1086     //we check that we receive the valueChanged signal
       
  1087     MyErrorObject o;
       
  1088     o.setOle(0);
       
  1089     QCOMPARE(o.property("ole").toInt(), 0);
       
  1090     QPropertyAnimation anim(&o, "ole");
       
  1091     anim.setEndValue(5);
       
  1092     anim.setDuration(1000);
       
  1093     QSignalSpy spy(&anim, SIGNAL(valueChanged(QVariant)));
       
  1094     anim.start();
       
  1095 
       
  1096     QTest::qWait(anim.duration() + 50);
       
  1097 
       
  1098     QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
       
  1099     QCOMPARE(anim.currentTime(), anim.duration());
       
  1100 
       
  1101     //let's check that the values go forward
       
  1102     QCOMPARE(spy.count(), 6); //we should have got everything from 0 to 5
       
  1103     for (int i = 0; i < spy.count(); ++i) {
       
  1104         QCOMPARE(qvariant_cast<QVariant>(spy.at(i).first()).toInt(), i);
       
  1105     }
       
  1106 }
       
  1107 
       
  1108 //this class will help us make sure that 2 animations started
       
  1109 //at the same time also end at the same time
       
  1110 class MySyncObject : public MyErrorObject
       
  1111 {
       
  1112     Q_OBJECT
       
  1113 public:
       
  1114     MySyncObject() : anim(this, "ole")
       
  1115     {
       
  1116         anim.setEndValue(1000);
       
  1117     }
       
  1118 public slots:
       
  1119     void checkAnimationFinished()
       
  1120     {
       
  1121         QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
       
  1122         QCOMPARE(ole(), 1000);
       
  1123     }
       
  1124 
       
  1125 public:
       
  1126     QPropertyAnimation anim;
       
  1127 };
       
  1128 
       
  1129 void tst_QPropertyAnimation::twoAnimations()
       
  1130 {
       
  1131     MySyncObject o1, o2;
       
  1132     o1.setOle(0);
       
  1133     o2.setOle(0);
       
  1134 
       
  1135     //when the animation in o1 is finished
       
  1136     //the animation in o2 should stop around the same time
       
  1137     //We use a queued connection to check just after the tick from the common timer
       
  1138     //the other way is true too
       
  1139     QObject::connect(&o1.anim, SIGNAL(finished()),
       
  1140         &o2, SLOT(checkAnimationFinished()), Qt::QueuedConnection);
       
  1141     QObject::connect(&o2.anim, SIGNAL(finished()),
       
  1142         &o1, SLOT(checkAnimationFinished()), Qt::QueuedConnection);
       
  1143 
       
  1144     o1.anim.start();
       
  1145     o2.anim.start();
       
  1146 
       
  1147     QTest::qWait(o1.anim.duration() + 50);
       
  1148     QCOMPARE(o1.anim.state(), QAbstractAnimation::Stopped);
       
  1149     QCOMPARE(o2.anim.state(), QAbstractAnimation::Stopped);
       
  1150 
       
  1151     QCOMPARE(o1.ole(), 1000);
       
  1152     QCOMPARE(o2.ole(), 1000);
       
  1153 }
       
  1154 
       
  1155 class MyComposedAnimation : public QPropertyAnimation
       
  1156 {
       
  1157     Q_OBJECT
       
  1158 public:
       
  1159     MyComposedAnimation(QObject *target, const QByteArray &propertyName, const QByteArray &innerPropertyName)
       
  1160         : QPropertyAnimation(target, propertyName)
       
  1161     {
       
  1162         innerAnim = new QPropertyAnimation(target, innerPropertyName);
       
  1163         this->setEndValue(1000);
       
  1164         innerAnim->setEndValue(1000);
       
  1165         innerAnim->setDuration(duration() + 100);
       
  1166     }
       
  1167 
       
  1168     void start()
       
  1169     {
       
  1170         QPropertyAnimation::start();
       
  1171         innerAnim->start();
       
  1172     }
       
  1173 
       
  1174     void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
       
  1175     {
       
  1176         QPropertyAnimation::updateState(oldState, newState);
       
  1177         if (newState == QAbstractAnimation::Stopped)
       
  1178             delete innerAnim;
       
  1179     }
       
  1180 
       
  1181 public:
       
  1182     QPropertyAnimation *innerAnim;
       
  1183 };
       
  1184 
       
  1185 void tst_QPropertyAnimation::deletedInUpdateCurrentTime()
       
  1186 {
       
  1187     // this test case reproduces an animation being deleted in the updateCurrentTime of
       
  1188     // another animation(was causing segfault).
       
  1189     // the deleted animation must have been started after the animation that is deleting.
       
  1190     AnimationObject o;
       
  1191     o.setValue(0);
       
  1192     o.setRealValue(0.0);
       
  1193 
       
  1194     MyComposedAnimation composedAnimation(&o, "value", "realValue");
       
  1195     composedAnimation.start();
       
  1196     QCOMPARE(composedAnimation.state(), QAbstractAnimation::Running);
       
  1197     QTest::qWait(composedAnimation.duration() + 50);
       
  1198 
       
  1199     QCOMPARE(composedAnimation.state(), QAbstractAnimation::Stopped);
       
  1200     QCOMPARE(o.value(), 1000);
       
  1201 }
       
  1202 
       
  1203 void tst_QPropertyAnimation::totalDuration()
       
  1204 {
       
  1205     QPropertyAnimation anim;
       
  1206     QCOMPARE(anim.totalDuration(), 250);
       
  1207     anim.setLoopCount(2);
       
  1208     QCOMPARE(anim.totalDuration(), 2*250);
       
  1209     anim.setLoopCount(-1);
       
  1210     QCOMPARE(anim.totalDuration(), -1);
       
  1211     anim.setDuration(0);
       
  1212     QCOMPARE(anim.totalDuration(), 0);
       
  1213 }
       
  1214 
       
  1215 
       
  1216 QTEST_MAIN(tst_QPropertyAnimation)
       
  1217 #include "tst_qpropertyanimation.moc"