src/corelib/animation/qabstractanimation.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 QtCore module 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 /*!
       
    43     \class QAbstractAnimation
       
    44     \ingroup animation
       
    45     \brief The QAbstractAnimation class is the base of all animations.
       
    46     \since 4.6
       
    47 
       
    48     The class defines the functions for the functionality shared by
       
    49     all animations. By inheriting this class, you can create custom
       
    50     animations that plug into the rest of the animation framework.
       
    51 
       
    52     The progress of an animation is given by its current time
       
    53     (currentTime()), which is measured in milliseconds from the start
       
    54     of the animation (0) to its end (duration()). The value is updated
       
    55     automatically while the animation is running. It can also be set
       
    56     directly with setCurrentTime().
       
    57 
       
    58     At any point an animation is in one of three states:
       
    59     \l{QAbstractAnimation::}{Running},
       
    60     \l{QAbstractAnimation::}{Stopped}, or
       
    61     \l{QAbstractAnimation::}{Paused}--as defined by the
       
    62     \l{QAbstractAnimation::}{State} enum. The current state can be
       
    63     changed by calling start(), stop(), pause(), or resume(). An
       
    64     animation will always reset its \l{currentTime()}{current time}
       
    65     when it is started. If paused, it will continue with the same
       
    66     current time when resumed. When an animation is stopped, it cannot
       
    67     be resumed, but will keep its current time (until started again).
       
    68     QAbstractAnimation will emit stateChanged() whenever its state
       
    69     changes.
       
    70 
       
    71     An animation can loop any number of times by setting the loopCount
       
    72     property. When an animation's current time reaches its duration(),
       
    73     it will reset the current time and keep running. A loop count of 1
       
    74     (the default value) means that the animation will run one time.
       
    75     Note that a duration of -1 means that the animation will run until
       
    76     stopped; the current time will increase indefinitely. When the
       
    77     current time equals duration() and the animation is in its
       
    78     final loop, the \l{QAbstractAnimation::}{Stopped} state is
       
    79     entered, and the finished() signal is emitted.
       
    80 
       
    81     QAbstractAnimation provides pure virtual functions used by
       
    82     subclasses to track the progress of the animation: duration() and
       
    83     updateCurrentTime(). The duration() function lets you report a
       
    84     duration for the animation (as discussed above). The animation
       
    85     framework calls updateCurrentTime() when current time has changed.
       
    86     By reimplementing this function, you can track the animation
       
    87     progress. Note that neither the interval between calls nor the
       
    88     number of calls to this function are defined; though, it will
       
    89     normally be 60 updates per second.
       
    90 
       
    91     By reimplementing updateState(), you can track the animation's
       
    92     state changes, which is particularly useful for animations that
       
    93     are not driven by time.
       
    94 
       
    95     \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework}
       
    96 */
       
    97 
       
    98 /*!
       
    99     \enum QAbstractAnimation::DeletionPolicy
       
   100 
       
   101     \value KeepWhenStopped The animation will not be deleted when stopped.
       
   102     \value DeleteWhenStopped The animation will be automatically deleted when
       
   103     stopped.
       
   104 */
       
   105 
       
   106 /*!
       
   107     \fn QAbstractAnimation::finished()
       
   108 
       
   109     QAbstractAnimation emits this signal after the animation has stopped and
       
   110     has reached the end.
       
   111 
       
   112     This signal is emitted after stateChanged().
       
   113 
       
   114     \sa stateChanged()
       
   115 */
       
   116 
       
   117 /*!
       
   118     \fn QAbstractAnimation::stateChanged(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
       
   119 
       
   120     QAbstractAnimation emits this signal whenever the state of the animation has
       
   121     changed from \a oldState to \a newState. This signal is emitted after the virtual
       
   122     updateState() function is called.
       
   123 
       
   124     \sa updateState()
       
   125 */
       
   126 
       
   127 /*!
       
   128     \fn QAbstractAnimation::currentLoopChanged(int currentLoop)
       
   129 
       
   130     QAbstractAnimation emits this signal whenever the current loop
       
   131     changes. \a currentLoop is the current loop.
       
   132 
       
   133     \sa currentLoop(), loopCount()
       
   134 */
       
   135 
       
   136 /*!
       
   137     \fn QAbstractAnimation::directionChanged(QAbstractAnimation::Direction newDirection);
       
   138 
       
   139     QAbstractAnimation emits this signal whenever the direction has been
       
   140     changed. \a newDirection is the new direction.
       
   141 
       
   142     \sa direction
       
   143 */
       
   144 
       
   145 #include "qabstractanimation.h"
       
   146 #include "qanimationgroup.h"
       
   147 
       
   148 #include <QtCore/qdebug.h>
       
   149 
       
   150 #include "qabstractanimation_p.h"
       
   151 
       
   152 #include <QtCore/qmath.h>
       
   153 #include <QtCore/qthreadstorage.h>
       
   154 #include <QtCore/qcoreevent.h>
       
   155 #include <QtCore/qpointer.h>
       
   156 
       
   157 #ifndef QT_NO_ANIMATION
       
   158 
       
   159 #define DEFAULT_TIMER_INTERVAL 16
       
   160 
       
   161 #ifdef Q_WS_WIN
       
   162     /// Fix for Qt 4.7
       
   163     //on windows if you're currently dragging a widget an inner eventloop was started by the system
       
   164     //to make sure that this timer is getting fired, we need to make sure to use the system timers
       
   165     //that will send a WM_TIMER event. We do that by settings the timer interval to 11
       
   166     //It is 16 because QEventDispatcherWin32Private::registerTimer specifically checks if the interval
       
   167     //is greater than 11 to determine if it should use a system timer (or the multimedia timer).
       
   168 #define STARTSTOP_TIMER_DELAY 16
       
   169 #else
       
   170 #define STARTSTOP_TIMER_DELAY 0
       
   171 #endif
       
   172 
       
   173 
       
   174 QT_BEGIN_NAMESPACE
       
   175 
       
   176 Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
       
   177 
       
   178 QUnifiedTimer::QUnifiedTimer() :
       
   179     QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
       
   180     currentAnimationIdx(0), consistentTiming(false), isPauseTimerActive(false),
       
   181     runningLeafAnimations(0)
       
   182 {
       
   183 }
       
   184 
       
   185 QUnifiedTimer *QUnifiedTimer::instance()
       
   186 {
       
   187     QUnifiedTimer *inst;
       
   188     if (!unifiedTimer()->hasLocalData()) {
       
   189         inst = new QUnifiedTimer;
       
   190         unifiedTimer()->setLocalData(inst);
       
   191     } else {
       
   192         inst = unifiedTimer()->localData();
       
   193     }
       
   194     return inst;
       
   195 }
       
   196 
       
   197 void QUnifiedTimer::ensureTimerUpdate(QAbstractAnimation *animation)
       
   198 {
       
   199     if (isPauseTimerActive) {
       
   200         updateAnimationsTime();
       
   201     } else {
       
   202         // this code is needed when ensureTimerUpdate is called from setState because we update
       
   203         // the currentTime when an animation starts running (otherwise we could remove it)
       
   204         animation->setCurrentTime(animation->currentTime());
       
   205     }
       
   206 }
       
   207 
       
   208 void QUnifiedTimer::updateAnimationsTime()
       
   209 {
       
   210     // ignore consistentTiming in case the pause timer is active
       
   211     const int delta = (consistentTiming && !isPauseTimerActive) ?
       
   212                         timingInterval : time.elapsed() - lastTick;
       
   213     lastTick = time.elapsed();
       
   214 
       
   215     //we make sure we only call update time if the time has actually changed
       
   216     //it might happen in some cases that the time doesn't change because events are delayed
       
   217     //when the CPU load is high
       
   218     if (delta) {
       
   219         for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
       
   220             QAbstractAnimation *animation = animations.at(currentAnimationIdx);
       
   221             int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
       
   222                           + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
       
   223             animation->setCurrentTime(elapsed);
       
   224         }
       
   225         currentAnimationIdx = 0;
       
   226     }
       
   227 }
       
   228 
       
   229 void QUnifiedTimer::restartAnimationTimer()
       
   230 {
       
   231     if (runningLeafAnimations == 0 && !runningPauseAnimations.isEmpty()) {
       
   232         int closestTimeToFinish = closestPauseAnimationTimeToFinish();
       
   233         animationTimer.start(closestTimeToFinish, this);
       
   234         isPauseTimerActive = true;
       
   235     } else if (!animationTimer.isActive() || isPauseTimerActive) {
       
   236         animationTimer.start(timingInterval, this);
       
   237         isPauseTimerActive = false;
       
   238     }
       
   239 }
       
   240 
       
   241 void QUnifiedTimer::timerEvent(QTimerEvent *event)
       
   242 {
       
   243     if (event->timerId() == startStopAnimationTimer.timerId()) {
       
   244         startStopAnimationTimer.stop();
       
   245 
       
   246         //we transfer the waiting animations into the "really running" state
       
   247         animations += animationsToStart;
       
   248         animationsToStart.clear();
       
   249         if (animations.isEmpty()) {
       
   250             animationTimer.stop();
       
   251             isPauseTimerActive = false;
       
   252             // invalidate the start reference time
       
   253             time = QTime();
       
   254         } else {
       
   255             restartAnimationTimer();
       
   256             if (!time.isValid()) {
       
   257                 lastTick = 0;
       
   258                 time.start();
       
   259             }
       
   260         }
       
   261     } else if (event->timerId() == animationTimer.timerId()) {
       
   262         // update current time on all top level animations
       
   263         updateAnimationsTime();
       
   264         restartAnimationTimer();
       
   265     }
       
   266 }
       
   267 
       
   268 void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation, bool isTopLevel)
       
   269 {
       
   270     registerRunningAnimation(animation);
       
   271     if (isTopLevel) {
       
   272         Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer);
       
   273         QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true;
       
   274         animationsToStart << animation;
       
   275         if (!startStopAnimationTimer.isActive())
       
   276             startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this);
       
   277     }
       
   278 }
       
   279 
       
   280 void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
       
   281 {
       
   282     unregisterRunningAnimation(animation);
       
   283 
       
   284     if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer)
       
   285         return;
       
   286 
       
   287     int idx = animations.indexOf(animation);
       
   288     if (idx != -1) {
       
   289         animations.removeAt(idx);
       
   290         // this is needed if we unregister an animation while its running
       
   291         if (idx <= currentAnimationIdx)
       
   292             --currentAnimationIdx;
       
   293 
       
   294         if (animations.isEmpty() && !startStopAnimationTimer.isActive())
       
   295             startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this);
       
   296     } else {
       
   297         animationsToStart.removeOne(animation);
       
   298     }
       
   299     QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false;
       
   300 }
       
   301 
       
   302 void QUnifiedTimer::registerRunningAnimation(QAbstractAnimation *animation)
       
   303 {
       
   304     if (QAbstractAnimationPrivate::get(animation)->isGroup)
       
   305         return;
       
   306 
       
   307     if (QAbstractAnimationPrivate::get(animation)->isPause)
       
   308         runningPauseAnimations << animation;
       
   309     else
       
   310         runningLeafAnimations++;
       
   311 }
       
   312 
       
   313 void QUnifiedTimer::unregisterRunningAnimation(QAbstractAnimation *animation)
       
   314 {
       
   315     if (QAbstractAnimationPrivate::get(animation)->isGroup)
       
   316         return;
       
   317 
       
   318     if (QAbstractAnimationPrivate::get(animation)->isPause)
       
   319         runningPauseAnimations.removeOne(animation);
       
   320     else
       
   321         runningLeafAnimations--;
       
   322     Q_ASSERT(runningLeafAnimations >= 0);
       
   323 }
       
   324 
       
   325 int QUnifiedTimer::closestPauseAnimationTimeToFinish()
       
   326 {
       
   327     int closestTimeToFinish = INT_MAX;
       
   328     for (int i = 0; i < runningPauseAnimations.size(); ++i) {
       
   329         QAbstractAnimation *animation = runningPauseAnimations.at(i);
       
   330         int timeToFinish;
       
   331 
       
   332         if (animation->direction() == QAbstractAnimation::Forward)
       
   333             timeToFinish = animation->duration() - animation->currentTime();
       
   334         else
       
   335             timeToFinish = animation->currentTime();
       
   336 
       
   337         if (timeToFinish < closestTimeToFinish)
       
   338             closestTimeToFinish = timeToFinish;
       
   339     }
       
   340     return closestTimeToFinish;
       
   341 }
       
   342 
       
   343 void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
       
   344 {
       
   345     Q_Q(QAbstractAnimation);
       
   346     if (state == newState)
       
   347         return;
       
   348 
       
   349     QAbstractAnimation::State oldState = state;
       
   350     int oldCurrentTime = currentTime;
       
   351     int oldCurrentLoop = currentLoop;
       
   352     QAbstractAnimation::Direction oldDirection = direction;
       
   353 
       
   354     // check if we should Rewind
       
   355     if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running)
       
   356         && oldState == QAbstractAnimation::Stopped) {
       
   357             //here we reset the time if needed
       
   358             //we don't call setCurrentTime because this might change the way the animation
       
   359             //behaves: changing the state or changing the current value
       
   360             totalCurrentTime = currentTime = (direction == QAbstractAnimation::Forward) ?
       
   361                 0 : (loopCount == -1 ? q->duration() : q->totalDuration());
       
   362     }
       
   363 
       
   364     state = newState;
       
   365     QWeakPointer<QAbstractAnimation> guard(q);
       
   366 
       
   367     q->updateState(oldState, newState);
       
   368     if (!guard)
       
   369         return;
       
   370 
       
   371     //this is to be safe if updateState changes the state
       
   372     if (state == oldState)
       
   373         return;
       
   374 
       
   375     // Notify state change
       
   376     emit q->stateChanged(oldState, newState);
       
   377     if (!guard)
       
   378         return;
       
   379 
       
   380     switch (state) {
       
   381     case QAbstractAnimation::Paused:
       
   382         if (hasRegisteredTimer)
       
   383             // currentTime needs to be updated if pauseTimer is active
       
   384             QUnifiedTimer::instance()->ensureTimerUpdate(q);
       
   385         if (!guard)
       
   386             return;
       
   387         //here we're sure that we were in running state before and that the
       
   388         //animation is currently registered
       
   389         QUnifiedTimer::instance()->unregisterAnimation(q);
       
   390         break;
       
   391     case QAbstractAnimation::Running:
       
   392         {
       
   393             bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped;
       
   394             QUnifiedTimer::instance()->registerAnimation(q, isTopLevel);
       
   395 
       
   396             // this ensures that the value is updated now that the animation is running
       
   397             if (oldState == QAbstractAnimation::Stopped) {
       
   398                 if (isTopLevel)
       
   399                     // currentTime needs to be updated if pauseTimer is active
       
   400                     QUnifiedTimer::instance()->ensureTimerUpdate(q);
       
   401             }
       
   402         }
       
   403         break;
       
   404     case QAbstractAnimation::Stopped:
       
   405         // Leave running state.
       
   406         int dura = q->duration();
       
   407         if (!guard)
       
   408             return;
       
   409 
       
   410         if (deleteWhenStopped)
       
   411             q->deleteLater();
       
   412 
       
   413         if (oldState == QAbstractAnimation::Running)
       
   414             QUnifiedTimer::instance()->unregisterAnimation(q);
       
   415 
       
   416         if (dura == -1 || loopCount < 0
       
   417             || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount))
       
   418             || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
       
   419                 emit q->finished();
       
   420         }
       
   421         break;
       
   422     }
       
   423 }
       
   424 
       
   425 /*!
       
   426     Constructs the QAbstractAnimation base class, and passes \a parent to
       
   427     QObject's constructor.
       
   428 
       
   429     \sa QVariantAnimation, QAnimationGroup
       
   430 */
       
   431 QAbstractAnimation::QAbstractAnimation(QObject *parent)
       
   432     : QObject(*new QAbstractAnimationPrivate, 0)
       
   433 {
       
   434     // Allow auto-add on reparent
       
   435     setParent(parent);
       
   436 }
       
   437 
       
   438 /*!
       
   439     \internal
       
   440 */
       
   441 QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
       
   442     : QObject(dd, 0)
       
   443 {
       
   444     // Allow auto-add on reparent
       
   445    setParent(parent);
       
   446 }
       
   447 
       
   448 /*!
       
   449     Stops the animation if it's running, then destroys the
       
   450     QAbstractAnimation. If the animation is part of a QAnimationGroup, it is
       
   451     automatically removed before it's destroyed.
       
   452 */
       
   453 QAbstractAnimation::~QAbstractAnimation()
       
   454 {
       
   455     Q_D(QAbstractAnimation);
       
   456     //we can't call stop here. Otherwise we get pure virtual calls
       
   457     if (d->state != Stopped) {
       
   458         QAbstractAnimation::State oldState = d->state;
       
   459         d->state = Stopped;
       
   460         emit stateChanged(oldState, d->state);
       
   461         if (oldState == QAbstractAnimation::Running)
       
   462             QUnifiedTimer::instance()->unregisterAnimation(this);
       
   463     }
       
   464 }
       
   465 
       
   466 /*!
       
   467     \property QAbstractAnimation::state
       
   468     \brief state of the animation.
       
   469 
       
   470     This property describes the current state of the animation. When the
       
   471     animation state changes, QAbstractAnimation emits the stateChanged()
       
   472     signal.
       
   473 */
       
   474 QAbstractAnimation::State QAbstractAnimation::state() const
       
   475 {
       
   476     Q_D(const QAbstractAnimation);
       
   477     return d->state;
       
   478 }
       
   479 
       
   480 /*!
       
   481     If this animation is part of a QAnimationGroup, this function returns a
       
   482     pointer to the group; otherwise, it returns 0.
       
   483 
       
   484     \sa QAnimationGroup::addAnimation()
       
   485 */
       
   486 QAnimationGroup *QAbstractAnimation::group() const
       
   487 {
       
   488     Q_D(const QAbstractAnimation);
       
   489     return d->group;
       
   490 }
       
   491 
       
   492 /*!
       
   493     \enum QAbstractAnimation::State
       
   494 
       
   495     This enum describes the state of the animation.
       
   496 
       
   497     \value Stopped The animation is not running. This is the initial state
       
   498     of QAbstractAnimation, and the state QAbstractAnimation reenters when finished. The current
       
   499     time remain unchanged until either setCurrentTime() is
       
   500     called, or the animation is started by calling start().
       
   501 
       
   502     \value Paused The animation is paused (i.e., temporarily
       
   503     suspended). Calling resume() will resume animation activity.
       
   504 
       
   505     \value Running The animation is running. While control is in the event
       
   506     loop, QAbstractAnimation will update its current time at regular intervals,
       
   507     calling updateCurrentTime() when appropriate.
       
   508 
       
   509     \sa state(), stateChanged()
       
   510 */
       
   511 
       
   512 /*!
       
   513     \enum QAbstractAnimation::Direction
       
   514 
       
   515     This enum describes the direction of the animation when in \l Running state.
       
   516 
       
   517     \value Forward The current time of the animation increases with time (i.e.,
       
   518     moves from 0 and towards the end / duration).
       
   519 
       
   520     \value Backward The current time of the animation decreases with time (i.e.,
       
   521     moves from the end / duration and towards 0).
       
   522 
       
   523     \sa direction
       
   524 */
       
   525 
       
   526 /*!
       
   527     \property QAbstractAnimation::direction
       
   528     \brief the direction of the animation when it is in \l Running
       
   529     state.
       
   530 
       
   531     This direction indicates whether the time moves from 0 towards the
       
   532     animation duration, or from the value of the duration and towards 0 after
       
   533     start() has been called.
       
   534 
       
   535     By default, this property is set to \l Forward.
       
   536 */
       
   537 QAbstractAnimation::Direction QAbstractAnimation::direction() const
       
   538 {
       
   539     Q_D(const QAbstractAnimation);
       
   540     return d->direction;
       
   541 }
       
   542 void QAbstractAnimation::setDirection(Direction direction)
       
   543 {
       
   544     Q_D(QAbstractAnimation);
       
   545     if (d->direction == direction)
       
   546         return;
       
   547 
       
   548     if (state() == Stopped) {
       
   549         if (direction == Backward) {
       
   550             d->currentTime = duration();
       
   551             d->currentLoop = d->loopCount - 1;
       
   552         } else {
       
   553             d->currentTime = 0;
       
   554             d->currentLoop = 0;
       
   555         }
       
   556     }
       
   557 
       
   558     // the commands order below is important: first we need to setCurrentTime with the old direction,
       
   559     // then update the direction on this and all children and finally restart the pauseTimer if needed
       
   560     if (d->hasRegisteredTimer)
       
   561         QUnifiedTimer::instance()->ensureTimerUpdate(this);
       
   562 
       
   563     d->direction = direction;
       
   564     updateDirection(direction);
       
   565 
       
   566     if (d->hasRegisteredTimer)
       
   567         // needed to update the timer interval in case of a pause animation
       
   568         QUnifiedTimer::instance()->restartAnimationTimer();
       
   569 
       
   570     emit directionChanged(direction);
       
   571 }
       
   572 
       
   573 /*!
       
   574     \property QAbstractAnimation::duration
       
   575     \brief the duration of the animation.
       
   576 
       
   577     If the duration is -1, it means that the duration is undefined.
       
   578     In this case, loopCount is ignored.
       
   579 */
       
   580 
       
   581 /*!
       
   582     \property QAbstractAnimation::loopCount
       
   583     \brief the loop count of the animation
       
   584 
       
   585     This property describes the loop count of the animation as an integer.
       
   586     By default this value is 1, indicating that the animation
       
   587     should run once only, and then stop. By changing it you can let the
       
   588     animation loop several times. With a value of 0, the animation will not
       
   589     run at all, and with a value of -1, the animation will loop forever
       
   590     until stopped.
       
   591     It is not supported to have loop on an animation that has an undefined
       
   592     duration. It will only run once.
       
   593 */
       
   594 int QAbstractAnimation::loopCount() const
       
   595 {
       
   596     Q_D(const QAbstractAnimation);
       
   597     return d->loopCount;
       
   598 }
       
   599 void QAbstractAnimation::setLoopCount(int loopCount)
       
   600 {
       
   601     Q_D(QAbstractAnimation);
       
   602     d->loopCount = loopCount;
       
   603 }
       
   604 
       
   605 /*!
       
   606     \property QAbstractAnimation::currentLoop
       
   607     \brief the current loop of the animation
       
   608 
       
   609     This property describes the current loop of the animation. By default,
       
   610     the animation's loop count is 1, and so the current loop will
       
   611     always be 0. If the loop count is 2 and the animation runs past its
       
   612     duration, it will automatically rewind and restart at current time 0, and
       
   613     current loop 1, and so on.
       
   614 
       
   615     When the current loop changes, QAbstractAnimation emits the
       
   616     currentLoopChanged() signal.
       
   617 */
       
   618 int QAbstractAnimation::currentLoop() const
       
   619 {
       
   620     Q_D(const QAbstractAnimation);
       
   621     return d->currentLoop;
       
   622 }
       
   623 
       
   624 /*!
       
   625     \fn virtual int QAbstractAnimation::duration() const = 0
       
   626 
       
   627     This pure virtual function returns the duration of the animation, and
       
   628     defines for how long QAbstractAnimation should update the current
       
   629     time. This duration is local, and does not include the loop count.
       
   630 
       
   631     A return value of -1 indicates that the animation has no defined duration;
       
   632     the animation should run forever until stopped. This is useful for
       
   633     animations that are not time driven, or where you cannot easily predict
       
   634     its duration (e.g., event driven audio playback in a game).
       
   635 
       
   636     If the animation is a parallel QAnimationGroup, the duration will be the longest
       
   637     duration of all its animations. If the animation is a sequential QAnimationGroup,
       
   638     the duration will be the sum of the duration of all its animations.
       
   639     \sa loopCount
       
   640 */
       
   641 
       
   642 /*!
       
   643     Returns the total and effective duration of the animation, including the
       
   644     loop count.
       
   645 
       
   646     \sa duration(), currentTime
       
   647 */
       
   648 int QAbstractAnimation::totalDuration() const
       
   649 {
       
   650     int dura = duration();
       
   651     if (dura <= 0)
       
   652         return dura;
       
   653     int loopcount = loopCount();
       
   654     if (loopcount < 0)
       
   655         return -1;
       
   656     return dura * loopcount;
       
   657 }
       
   658 
       
   659 /*!
       
   660     \property QAbstractAnimation::currentTime
       
   661     \brief the current time and progress of the animation
       
   662 
       
   663     This property describes the animation's current time. You can change the
       
   664     current time by calling setCurrentTime, or you can call start() and let
       
   665     the animation run, setting the current time automatically as the animation
       
   666     progresses.
       
   667 
       
   668     The animation's current time starts at 0, and ends at duration(). If the
       
   669     animation's loopCount is larger than 1, the current time will rewind and
       
   670     start at 0 again for the consecutive loops. If the animation has a pause.
       
   671     currentTime will also include the duration of the pause.
       
   672 
       
   673     \sa loopCount
       
   674  */
       
   675 int QAbstractAnimation::currentTime() const
       
   676 {
       
   677     Q_D(const QAbstractAnimation);
       
   678     return d->currentTime;
       
   679 }
       
   680 void QAbstractAnimation::setCurrentTime(int msecs)
       
   681 {
       
   682     Q_D(QAbstractAnimation);
       
   683     msecs = qMax(msecs, 0);
       
   684 
       
   685     // Calculate new time and loop.
       
   686     int dura = duration();
       
   687     int totalDura = dura <= 0 ? dura : ((d->loopCount < 0) ? -1 : dura * d->loopCount);
       
   688     if (totalDura != -1)
       
   689         msecs = qMin(totalDura, msecs);
       
   690     d->totalCurrentTime = msecs;
       
   691 
       
   692     // Update new values.
       
   693     int oldLoop = d->currentLoop;
       
   694     d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
       
   695     if (d->currentLoop == d->loopCount) {
       
   696         //we're at the end
       
   697         d->currentTime = qMax(0, dura);
       
   698         d->currentLoop = qMax(0, d->loopCount - 1);
       
   699     } else {
       
   700         if (d->direction == Forward) {
       
   701             d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
       
   702         } else {
       
   703             d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
       
   704             if (d->currentTime == dura)
       
   705                 --d->currentLoop;
       
   706         }
       
   707     }
       
   708 
       
   709     updateCurrentTime(d->currentTime);
       
   710     if (d->currentLoop != oldLoop)
       
   711         emit currentLoopChanged(d->currentLoop);
       
   712 
       
   713     // All animations are responsible for stopping the animation when their
       
   714     // own end state is reached; in this case the animation is time driven,
       
   715     // and has reached the end.
       
   716     if ((d->direction == Forward && d->totalCurrentTime == totalDura)
       
   717         || (d->direction == Backward && d->totalCurrentTime == 0)) {
       
   718         stop();
       
   719     }
       
   720 }
       
   721 
       
   722 /*!
       
   723     Starts the animation. The \a policy argument says whether or not the
       
   724     animation should be deleted when it's done. When the animation starts, the
       
   725     stateChanged() signal is emitted, and state() returns Running. When control
       
   726     reaches the event loop, the animation will run by itself, periodically
       
   727     calling updateCurrentTime() as the animation progresses.
       
   728 
       
   729     If the animation is currently stopped or has already reached the end,
       
   730     calling start() will rewind the animation and start again from the beginning.
       
   731     When the animation reaches the end, the animation will either stop, or
       
   732     if the loop level is more than 1, it will rewind and continue from the beginning.
       
   733 
       
   734     If the animation is already running, this function does nothing.
       
   735 
       
   736     \sa stop(), state()
       
   737 */
       
   738 void QAbstractAnimation::start(DeletionPolicy policy)
       
   739 {
       
   740     Q_D(QAbstractAnimation);
       
   741     if (d->state == Running)
       
   742         return;
       
   743     d->deleteWhenStopped = policy;
       
   744     d->setState(Running);
       
   745 }
       
   746 
       
   747 /*!
       
   748     Stops the animation. When the animation is stopped, it emits the stateChanged()
       
   749     signal, and state() returns Stopped. The current time is not changed.
       
   750 
       
   751     If the animation stops by itself after reaching the end (i.e.,
       
   752     currentTime() == duration() and currentLoop() > loopCount() - 1), the
       
   753     finished() signal is emitted.
       
   754 
       
   755     \sa start(), state()
       
   756  */
       
   757 void QAbstractAnimation::stop()
       
   758 {
       
   759     Q_D(QAbstractAnimation);
       
   760 
       
   761     d->setState(Stopped);
       
   762 }
       
   763 
       
   764 /*!
       
   765     Pauses the animation. When the animation is paused, state() returns Paused.
       
   766     The value of currentTime will remain unchanged until resume() or start()
       
   767     is called. If you want to continue from the current time, call resume().
       
   768 
       
   769     \sa start(), state(), resume()
       
   770  */
       
   771 void QAbstractAnimation::pause()
       
   772 {
       
   773     Q_D(QAbstractAnimation);
       
   774     if (d->state == Stopped) {
       
   775         qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
       
   776         return;
       
   777     }
       
   778 
       
   779     d->setState(Paused);
       
   780 }
       
   781 
       
   782 /*!
       
   783     Resumes the animation after it was paused. When the animation is resumed,
       
   784     it emits the resumed() and stateChanged() signals. The currenttime is not
       
   785     changed.
       
   786 
       
   787     \sa start(), pause(), state()
       
   788  */
       
   789 void QAbstractAnimation::resume()
       
   790 {
       
   791     Q_D(QAbstractAnimation);
       
   792     if (d->state != Paused) {
       
   793         qWarning("QAbstractAnimation::resume: "
       
   794                  "Cannot resume an animation that is not paused");
       
   795         return;
       
   796     }
       
   797 
       
   798     d->setState(Running);
       
   799 }
       
   800 
       
   801 /*!
       
   802     \reimp
       
   803 */
       
   804 bool QAbstractAnimation::event(QEvent *event)
       
   805 {
       
   806     return QObject::event(event);
       
   807 }
       
   808 
       
   809 /*!
       
   810     \fn virtual void QAbstractAnimation::updateCurrentTime(int currentTime) = 0;
       
   811 
       
   812     This pure virtual function is called every time the animation's
       
   813     \a currentTime changes.
       
   814 
       
   815     \sa updateState()
       
   816 */
       
   817 
       
   818 /*!
       
   819     This virtual function is called by QAbstractAnimation when the state
       
   820     of the animation is changed from \a oldState to \a newState.
       
   821 
       
   822     \sa start(), stop(), pause(), resume()
       
   823 */
       
   824 void QAbstractAnimation::updateState(QAbstractAnimation::State oldState,
       
   825                                      QAbstractAnimation::State newState)
       
   826 {
       
   827     Q_UNUSED(oldState);
       
   828     Q_UNUSED(newState);
       
   829 }
       
   830 
       
   831 /*!
       
   832     This virtual function is called by QAbstractAnimation when the direction
       
   833     of the animation is changed. The \a direction argument is the new direction.
       
   834 
       
   835     \sa setDirection(), direction()
       
   836 */
       
   837 void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
       
   838 {
       
   839     Q_UNUSED(direction);
       
   840 }
       
   841 
       
   842 
       
   843 QT_END_NAMESPACE
       
   844 
       
   845 #include "moc_qabstractanimation.cpp"
       
   846 
       
   847 #endif //QT_NO_ANIMATION