1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
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     (currentLoopTime()), 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 newState, QAbstractAnimation::State oldState)
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 #define STARTSTOP_TIMER_DELAY 0
161 
162 QT_BEGIN_NAMESPACE
163 
164 #ifndef QT_NO_THREAD
Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer * >,unifiedTimer)165 Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
166 #endif
167 
168 QUnifiedTimer::QUnifiedTimer() :
169     QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
170     currentAnimationIdx(0), insideTick(false), consistentTiming(false), slowMode(false),
171     slowdownFactor(5.0f), isPauseTimerActive(false), runningLeafAnimations(0)
172 {
173     time.invalidate();
174     driver = &defaultDriver;
175 }
176 
177 
instance(bool create)178 QUnifiedTimer *QUnifiedTimer::instance(bool create)
179 {
180     QUnifiedTimer *inst;
181 #ifndef QT_NO_THREAD
182     if (create && !unifiedTimer()->hasLocalData()) {
183         inst = new QUnifiedTimer;
184         unifiedTimer()->setLocalData(inst);
185     } else {
186         inst = unifiedTimer()->localData();
187     }
188 #else
189     static QUnifiedTimer unifiedTimer;
190     inst = &unifiedTimer;
191 #endif
192     return inst;
193 }
194 
instance()195 QUnifiedTimer *QUnifiedTimer::instance()
196 {
197     return instance(true);
198 }
199 
ensureTimerUpdate()200 void QUnifiedTimer::ensureTimerUpdate()
201 {
202     QUnifiedTimer *inst = QUnifiedTimer::instance(false);
203     if (inst && inst->isPauseTimerActive)
204         inst->updateAnimationsTime();
205 }
206 
updateAnimationsTime()207 void QUnifiedTimer::updateAnimationsTime()
208 {
209     //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations
210     if(insideTick)
211         return;
212 
213     qint64 totalElapsed = time.elapsed();
214     // ignore consistentTiming in case the pause timer is active
215     int delta = (consistentTiming && !isPauseTimerActive) ?
216                         timingInterval : totalElapsed - lastTick;
217     if (slowMode) {
218         if (slowdownFactor > 0)
219             delta = qRound(delta / slowdownFactor);
220         else
221             delta = 0;
222     }
223 
224     lastTick = totalElapsed;
225 
226     //we make sure we only call update time if the time has actually changed
227     //it might happen in some cases that the time doesn't change because events are delayed
228     //when the CPU load is high
229     if (delta) {
230         insideTick = true;
231         for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
232             QAbstractAnimation *animation = animations.at(currentAnimationIdx);
233             int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
234                           + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
235             animation->setCurrentTime(elapsed);
236         }
237         insideTick = false;
238         currentAnimationIdx = 0;
239     }
240 }
241 
updateAnimationTimer()242 void QUnifiedTimer::updateAnimationTimer()
243 {
244     QUnifiedTimer *inst = QUnifiedTimer::instance(false);
245     if (inst)
246         inst->restartAnimationTimer();
247 }
248 
restartAnimationTimer()249 void QUnifiedTimer::restartAnimationTimer()
250 {
251     if (runningLeafAnimations == 0 && !runningPauseAnimations.isEmpty()) {
252         int closestTimeToFinish = closestPauseAnimationTimeToFinish();
253         if (closestTimeToFinish < 0) {
254             qDebug() << runningPauseAnimations;
255             qDebug() << closestPauseAnimationTimeToFinish();
256         }
257         driver->stop();
258         animationTimer.start(closestTimeToFinish, this);
259         isPauseTimerActive = true;
260     } else if (!driver->isRunning() || isPauseTimerActive) {
261         driver->start();
262         isPauseTimerActive = false;
263     } else if (runningLeafAnimations == 0)
264         driver->stop();
265 }
266 
setTimingInterval(int interval)267 void QUnifiedTimer::setTimingInterval(int interval)
268 {
269     timingInterval = interval;
270 
271     if (driver->isRunning() && !isPauseTimerActive) {
272         //we changed the timing interval
273         driver->stop();
274         driver->start();
275     }
276 }
277 
278 
timerEvent(QTimerEvent * event)279 void QUnifiedTimer::timerEvent(QTimerEvent *event)
280 {
281     //in the case of consistent timing we make sure the orders in which events come is always the same
282    //for that purpose we do as if the startstoptimer would always fire before the animation timer
283     if ((consistentTiming && startStopAnimationTimer.isActive()) ||
284         event->timerId() == startStopAnimationTimer.timerId()) {
285         startStopAnimationTimer.stop();
286 
287         //we transfer the waiting animations into the "really running" state
288         animations += animationsToStart;
289         animationsToStart.clear();
290         if (animations.isEmpty()) {
291             animationTimer.stop();
292             isPauseTimerActive = false;
293             // invalidate the start reference time
294             time.invalidate();
295         } else {
296             restartAnimationTimer();
297             if (!time.isValid()) {
298                 lastTick = 0;
299                 time.start();
300             }
301         }
302     }
303 
304     if (event->timerId() == animationTimer.timerId()) {
305         // update current time on all top level animations
306         updateAnimationsTime();
307         restartAnimationTimer();
308     }
309 }
310 
registerAnimation(QAbstractAnimation * animation,bool isTopLevel)311 void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation, bool isTopLevel)
312 {
313     QUnifiedTimer *inst = instance(true); //we create the instance if needed
314     inst->registerRunningAnimation(animation);
315     if (isTopLevel) {
316         Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer);
317         QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true;
318         inst->animationsToStart << animation;
319         if (!inst->startStopAnimationTimer.isActive())
320             inst->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, inst);
321     }
322 }
323 
unregisterAnimation(QAbstractAnimation * animation)324 void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
325 {
326     QUnifiedTimer *inst = QUnifiedTimer::instance(false);
327     if (inst) {
328         //at this point the unified timer should have been created
329         //but it might also have been already destroyed in case the application is shutting down
330 
331         inst->unregisterRunningAnimation(animation);
332 
333         if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer)
334             return;
335 
336         int idx = inst->animations.indexOf(animation);
337         if (idx != -1) {
338             inst->animations.removeAt(idx);
339             // this is needed if we unregister an animation while its running
340             if (idx <= inst->currentAnimationIdx)
341                 --inst->currentAnimationIdx;
342 
343             if (inst->animations.isEmpty() && !inst->startStopAnimationTimer.isActive())
344                 inst->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, inst);
345         } else {
346             inst->animationsToStart.removeOne(animation);
347         }
348     }
349     QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false;
350 }
351 
registerRunningAnimation(QAbstractAnimation * animation)352 void QUnifiedTimer::registerRunningAnimation(QAbstractAnimation *animation)
353 {
354     if (QAbstractAnimationPrivate::get(animation)->isGroup)
355         return;
356 
357     if (QAbstractAnimationPrivate::get(animation)->isPause) {
358         runningPauseAnimations << animation;
359     } else
360         runningLeafAnimations++;
361 }
362 
unregisterRunningAnimation(QAbstractAnimation * animation)363 void QUnifiedTimer::unregisterRunningAnimation(QAbstractAnimation *animation)
364 {
365     if (QAbstractAnimationPrivate::get(animation)->isGroup)
366         return;
367 
368     if (QAbstractAnimationPrivate::get(animation)->isPause)
369         runningPauseAnimations.removeOne(animation);
370     else
371         runningLeafAnimations--;
372     Q_ASSERT(runningLeafAnimations >= 0);
373 }
374 
closestPauseAnimationTimeToFinish()375 int QUnifiedTimer::closestPauseAnimationTimeToFinish()
376 {
377     int closestTimeToFinish = INT_MAX;
378     for (int i = 0; i < runningPauseAnimations.size(); ++i) {
379         QAbstractAnimation *animation = runningPauseAnimations.at(i);
380         int timeToFinish;
381 
382         if (animation->direction() == QAbstractAnimation::Forward)
383             timeToFinish = animation->duration() - animation->currentLoopTime();
384         else
385             timeToFinish = animation->currentLoopTime();
386 
387         if (timeToFinish < closestTimeToFinish)
388             closestTimeToFinish = timeToFinish;
389     }
390     return closestTimeToFinish;
391 }
392 
installAnimationDriver(QAnimationDriver * d)393 void QUnifiedTimer::installAnimationDriver(QAnimationDriver *d)
394 {
395     if (driver) {
396 
397         if (driver->isRunning()) {
398             qWarning("QUnifiedTimer: Cannot change animation driver while animations are running");
399             return;
400         }
401 
402         if (driver != &defaultDriver)
403             delete driver;
404     }
405 
406     driver = d;
407 }
408 
409 /*!
410    \class QAnimationDriver
411 
412    \brief The QAnimationDriver class is used to exchange the mechanism that drives animations.
413 
414    The default animation system is driven by a timer that fires at regular intervals.
415    In some scenarios, it is better to drive the animation based on other synchronization
416    mechanisms, such as the vertical refresh rate of the screen.
417 
418    \internal
419  */
420 
QAnimationDriver(QObject * parent)421 QAnimationDriver::QAnimationDriver(QObject *parent)
422     : QObject(*(new QAnimationDriverPrivate), parent)
423 {
424 }
425 
QAnimationDriver(QAnimationDriverPrivate & dd,QObject * parent)426 QAnimationDriver::QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent)
427     : QObject(dd, parent)
428 {
429 }
430 
431 
432 /*!
433     Advances the animation based on the current time. This function should
434     be continuously called by the driver while the animation is running.
435 
436     \internal
437  */
advance()438 void QAnimationDriver::advance()
439 {
440     QUnifiedTimer *instance = QUnifiedTimer::instance();
441 
442     // update current time on all top level animations
443     instance->updateAnimationsTime();
444     instance->restartAnimationTimer();
445 }
446 
447 
448 /*!
449     Installs this animation driver. The animation driver is thread local and
450     will only apply for the thread its installed in.
451 
452     \internal
453  */
install()454 void QAnimationDriver::install()
455 {
456     QUnifiedTimer *timer = QUnifiedTimer::instance(true);
457     timer->installAnimationDriver(this);
458 }
459 
isRunning() const460 bool QAnimationDriver::isRunning() const
461 {
462     return d_func()->running;
463 }
464 
465 
start()466 void QAnimationDriver::start()
467 {
468     Q_D(QAnimationDriver);
469     if (!d->running) {
470         started();
471         d->running = true;
472     }
473 }
474 
475 
stop()476 void QAnimationDriver::stop()
477 {
478     Q_D(QAnimationDriver);
479     if (d->running) {
480         stopped();
481         d->running = false;
482     }
483 }
484 
485 /*!
486     \fn QAnimationDriver::started()
487 
488     This function is called by the animation framework to notify the driver
489     that it should start running.
490 
491     \internal
492  */
493 
494 /*!
495     \fn QAnimationDriver::stopped()
496 
497     This function is called by the animation framework to notify the driver
498     that it should stop running.
499 
500     \internal
501  */
502 
503 /*!
504    The default animation driver just spins the timer...
505  */
QDefaultAnimationDriver(QUnifiedTimer * timer)506 QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer)
507     : QAnimationDriver(0), m_unified_timer(timer)
508 {
509 }
510 
timerEvent(QTimerEvent * e)511 void QDefaultAnimationDriver::timerEvent(QTimerEvent *e)
512 {
513     Q_ASSERT(e->timerId() == m_timer.timerId());
514     Q_UNUSED(e); // if the assertions are disabled
515     advance();
516 }
517 
started()518 void QDefaultAnimationDriver::started()
519 {
520     m_timer.start(m_unified_timer->timingInterval, this);
521 }
522 
stopped()523 void QDefaultAnimationDriver::stopped()
524 {
525     m_timer.stop();
526 }
527 
528 
529 
setState(QAbstractAnimation::State newState)530 void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
531 {
532     Q_Q(QAbstractAnimation);
533     if (state == newState)
534         return;
535 
536     if (loopCount == 0)
537         return;
538 
539     QAbstractAnimation::State oldState = state;
540     int oldCurrentTime = currentTime;
541     int oldCurrentLoop = currentLoop;
542     QAbstractAnimation::Direction oldDirection = direction;
543 
544     // check if we should Rewind
545     if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running)
546         && oldState == QAbstractAnimation::Stopped) {
547             //here we reset the time if needed
548             //we don't call setCurrentTime because this might change the way the animation
549             //behaves: changing the state or changing the current value
550             totalCurrentTime = currentTime = (direction == QAbstractAnimation::Forward) ?
551                 0 : (loopCount == -1 ? q->duration() : q->totalDuration());
552     }
553 
554     state = newState;
555     QWeakPointer<QAbstractAnimation> guard(q);
556 
557     //(un)registration of the animation must always happen before calls to
558     //virtual function (updateState) to ensure a correct state of the timer
559     bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped;
560     if (oldState == QAbstractAnimation::Running) {
561         if (newState == QAbstractAnimation::Paused && hasRegisteredTimer)
562             QUnifiedTimer::ensureTimerUpdate();
563         //the animation, is not running any more
564         QUnifiedTimer::unregisterAnimation(q);
565     } else if (newState == QAbstractAnimation::Running) {
566         QUnifiedTimer::registerAnimation(q, isTopLevel);
567     }
568 
569     q->updateState(newState, oldState);
570     if (!guard || newState != state) //this is to be safe if updateState changes the state
571         return;
572 
573     // Notify state change
574     emit q->stateChanged(newState, oldState);
575     if (!guard || newState != state) //this is to be safe if updateState changes the state
576         return;
577 
578     switch (state) {
579     case QAbstractAnimation::Paused:
580         break;
581     case QAbstractAnimation::Running:
582         {
583 
584             // this ensures that the value is updated now that the animation is running
585             if (oldState == QAbstractAnimation::Stopped) {
586                 if (isTopLevel) {
587                     // currentTime needs to be updated if pauseTimer is active
588                     QUnifiedTimer::ensureTimerUpdate();
589                     q->setCurrentTime(totalCurrentTime);
590                 }
591             }
592         }
593         break;
594     case QAbstractAnimation::Stopped:
595         // Leave running state.
596         int dura = q->duration();
597 
598         if (deleteWhenStopped)
599             q->deleteLater();
600 
601         if (dura == -1 || loopCount < 0
602             || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount))
603             || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
604                 emit q->finished();
605         }
606         break;
607     }
608 }
609 
610 /*!
611     Constructs the QAbstractAnimation base class, and passes \a parent to
612     QObject's constructor.
613 
614     \sa QVariantAnimation, QAnimationGroup
615 */
QAbstractAnimation(QObject * parent)616 QAbstractAnimation::QAbstractAnimation(QObject *parent)
617     : QObject(*new QAbstractAnimationPrivate, 0)
618 {
619     // Allow auto-add on reparent
620     setParent(parent);
621 }
622 
623 /*!
624     \internal
625 */
QAbstractAnimation(QAbstractAnimationPrivate & dd,QObject * parent)626 QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
627     : QObject(dd, 0)
628 {
629     // Allow auto-add on reparent
630    setParent(parent);
631 }
632 
633 /*!
634     Stops the animation if it's running, then destroys the
635     QAbstractAnimation. If the animation is part of a QAnimationGroup, it is
636     automatically removed before it's destroyed.
637 */
~QAbstractAnimation()638 QAbstractAnimation::~QAbstractAnimation()
639 {
640     Q_D(QAbstractAnimation);
641     //we can't call stop here. Otherwise we get pure virtual calls
642     if (d->state != Stopped) {
643         QAbstractAnimation::State oldState = d->state;
644         d->state = Stopped;
645         emit stateChanged(oldState, d->state);
646         if (oldState == QAbstractAnimation::Running)
647             QUnifiedTimer::unregisterAnimation(this);
648     }
649 }
650 
651 /*!
652     \property QAbstractAnimation::state
653     \brief state of the animation.
654 
655     This property describes the current state of the animation. When the
656     animation state changes, QAbstractAnimation emits the stateChanged()
657     signal.
658 */
state() const659 QAbstractAnimation::State QAbstractAnimation::state() const
660 {
661     Q_D(const QAbstractAnimation);
662     return d->state;
663 }
664 
665 /*!
666     If this animation is part of a QAnimationGroup, this function returns a
667     pointer to the group; otherwise, it returns 0.
668 
669     \sa QAnimationGroup::addAnimation()
670 */
group() const671 QAnimationGroup *QAbstractAnimation::group() const
672 {
673     Q_D(const QAbstractAnimation);
674     return d->group;
675 }
676 
677 /*!
678     \enum QAbstractAnimation::State
679 
680     This enum describes the state of the animation.
681 
682     \value Stopped The animation is not running. This is the initial state
683     of QAbstractAnimation, and the state QAbstractAnimation reenters when finished. The current
684     time remain unchanged until either setCurrentTime() is
685     called, or the animation is started by calling start().
686 
687     \value Paused The animation is paused (i.e., temporarily
688     suspended). Calling resume() will resume animation activity.
689 
690     \value Running The animation is running. While control is in the event
691     loop, QAbstractAnimation will update its current time at regular intervals,
692     calling updateCurrentTime() when appropriate.
693 
694     \sa state(), stateChanged()
695 */
696 
697 /*!
698     \enum QAbstractAnimation::Direction
699 
700     This enum describes the direction of the animation when in \l Running state.
701 
702     \value Forward The current time of the animation increases with time (i.e.,
703     moves from 0 and towards the end / duration).
704 
705     \value Backward The current time of the animation decreases with time (i.e.,
706     moves from the end / duration and towards 0).
707 
708     \sa direction
709 */
710 
711 /*!
712     \property QAbstractAnimation::direction
713     \brief the direction of the animation when it is in \l Running
714     state.
715 
716     This direction indicates whether the time moves from 0 towards the
717     animation duration, or from the value of the duration and towards 0 after
718     start() has been called.
719 
720     By default, this property is set to \l Forward.
721 */
direction() const722 QAbstractAnimation::Direction QAbstractAnimation::direction() const
723 {
724     Q_D(const QAbstractAnimation);
725     return d->direction;
726 }
setDirection(Direction direction)727 void QAbstractAnimation::setDirection(Direction direction)
728 {
729     Q_D(QAbstractAnimation);
730     if (d->direction == direction)
731         return;
732 
733     if (state() == Stopped) {
734         if (direction == Backward) {
735             d->currentTime = duration();
736             d->currentLoop = d->loopCount - 1;
737         } else {
738             d->currentTime = 0;
739             d->currentLoop = 0;
740         }
741     }
742 
743     // the commands order below is important: first we need to setCurrentTime with the old direction,
744     // then update the direction on this and all children and finally restart the pauseTimer if needed
745     if (d->hasRegisteredTimer)
746         QUnifiedTimer::ensureTimerUpdate();
747 
748     d->direction = direction;
749     updateDirection(direction);
750 
751     if (d->hasRegisteredTimer)
752         // needed to update the timer interval in case of a pause animation
753         QUnifiedTimer::updateAnimationTimer();
754 
755     emit directionChanged(direction);
756 }
757 
758 /*!
759     \property QAbstractAnimation::duration
760     \brief the duration of the animation.
761 
762     If the duration is -1, it means that the duration is undefined.
763     In this case, loopCount is ignored.
764 */
765 
766 /*!
767     \property QAbstractAnimation::loopCount
768     \brief the loop count of the animation
769 
770     This property describes the loop count of the animation as an integer.
771     By default this value is 1, indicating that the animation
772     should run once only, and then stop. By changing it you can let the
773     animation loop several times. With a value of 0, the animation will not
774     run at all, and with a value of -1, the animation will loop forever
775     until stopped.
776     It is not supported to have loop on an animation that has an undefined
777     duration. It will only run once.
778 */
loopCount() const779 int QAbstractAnimation::loopCount() const
780 {
781     Q_D(const QAbstractAnimation);
782     return d->loopCount;
783 }
setLoopCount(int loopCount)784 void QAbstractAnimation::setLoopCount(int loopCount)
785 {
786     Q_D(QAbstractAnimation);
787     d->loopCount = loopCount;
788 }
789 
790 /*!
791     \property QAbstractAnimation::currentLoop
792     \brief the current loop of the animation
793 
794     This property describes the current loop of the animation. By default,
795     the animation's loop count is 1, and so the current loop will
796     always be 0. If the loop count is 2 and the animation runs past its
797     duration, it will automatically rewind and restart at current time 0, and
798     current loop 1, and so on.
799 
800     When the current loop changes, QAbstractAnimation emits the
801     currentLoopChanged() signal.
802 */
currentLoop() const803 int QAbstractAnimation::currentLoop() const
804 {
805     Q_D(const QAbstractAnimation);
806     return d->currentLoop;
807 }
808 
809 /*!
810     \fn virtual int QAbstractAnimation::duration() const = 0
811 
812     This pure virtual function returns the duration of the animation, and
813     defines for how long QAbstractAnimation should update the current
814     time. This duration is local, and does not include the loop count.
815 
816     A return value of -1 indicates that the animation has no defined duration;
817     the animation should run forever until stopped. This is useful for
818     animations that are not time driven, or where you cannot easily predict
819     its duration (e.g., event driven audio playback in a game).
820 
821     If the animation is a parallel QAnimationGroup, the duration will be the longest
822     duration of all its animations. If the animation is a sequential QAnimationGroup,
823     the duration will be the sum of the duration of all its animations.
824     \sa loopCount
825 */
826 
827 /*!
828     Returns the total and effective duration of the animation, including the
829     loop count.
830 
831     \sa duration(), currentTime
832 */
totalDuration() const833 int QAbstractAnimation::totalDuration() const
834 {
835     int dura = duration();
836     if (dura <= 0)
837         return dura;
838     int loopcount = loopCount();
839     if (loopcount < 0)
840         return -1;
841     return dura * loopcount;
842 }
843 
844 /*!
845     Returns the current time inside the current loop. It can go from 0 to duration().
846 
847     \sa duration(), currentTime
848 */
849 
currentLoopTime() const850 int QAbstractAnimation::currentLoopTime() const
851 {
852     Q_D(const QAbstractAnimation);
853     return d->currentTime;
854 }
855 
856 /*!
857     \property QAbstractAnimation::currentTime
858     \brief the current time and progress of the animation
859 
860     This property describes the animation's current time. You can change the
861     current time by calling setCurrentTime, or you can call start() and let
862     the animation run, setting the current time automatically as the animation
863     progresses.
864 
865     The animation's current time starts at 0, and ends at totalDuration().
866 
867     \sa loopCount, currentLoopTime()
868  */
currentTime() const869 int QAbstractAnimation::currentTime() const
870 {
871     Q_D(const QAbstractAnimation);
872     return d->totalCurrentTime;
873 }
setCurrentTime(int msecs)874 void QAbstractAnimation::setCurrentTime(int msecs)
875 {
876     Q_D(QAbstractAnimation);
877     msecs = qMax(msecs, 0);
878 
879     // Calculate new time and loop.
880     int dura = duration();
881     int totalDura = dura <= 0 ? dura : ((d->loopCount < 0) ? -1 : dura * d->loopCount);
882     if (totalDura != -1)
883         msecs = qMin(totalDura, msecs);
884     d->totalCurrentTime = msecs;
885 
886     // Update new values.
887     int oldLoop = d->currentLoop;
888     d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
889     if (d->currentLoop == d->loopCount) {
890         //we're at the end
891         d->currentTime = qMax(0, dura);
892         d->currentLoop = qMax(0, d->loopCount - 1);
893     } else {
894         if (d->direction == Forward) {
895             d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
896         } else {
897             d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
898             if (d->currentTime == dura)
899                 --d->currentLoop;
900         }
901     }
902 
903     updateCurrentTime(d->currentTime);
904     if (d->currentLoop != oldLoop)
905         emit currentLoopChanged(d->currentLoop);
906 
907     // All animations are responsible for stopping the animation when their
908     // own end state is reached; in this case the animation is time driven,
909     // and has reached the end.
910     if ((d->direction == Forward && d->totalCurrentTime == totalDura)
911         || (d->direction == Backward && d->totalCurrentTime == 0)) {
912         stop();
913     }
914 }
915 
916 /*!
917     Starts the animation. The \a policy argument says whether or not the
918     animation should be deleted when it's done. When the animation starts, the
919     stateChanged() signal is emitted, and state() returns Running. When control
920     reaches the event loop, the animation will run by itself, periodically
921     calling updateCurrentTime() as the animation progresses.
922 
923     If the animation is currently stopped or has already reached the end,
924     calling start() will rewind the animation and start again from the beginning.
925     When the animation reaches the end, the animation will either stop, or
926     if the loop level is more than 1, it will rewind and continue from the beginning.
927 
928     If the animation is already running, this function does nothing.
929 
930     \sa stop(), state()
931 */
start(DeletionPolicy policy)932 void QAbstractAnimation::start(DeletionPolicy policy)
933 {
934     Q_D(QAbstractAnimation);
935     if (d->state == Running)
936         return;
937     d->deleteWhenStopped = policy;
938     d->setState(Running);
939 }
940 
941 /*!
942     Stops the animation. When the animation is stopped, it emits the stateChanged()
943     signal, and state() returns Stopped. The current time is not changed.
944 
945     If the animation stops by itself after reaching the end (i.e.,
946     currentLoopTime() == duration() and currentLoop() > loopCount() - 1), the
947     finished() signal is emitted.
948 
949     \sa start(), state()
950  */
stop()951 void QAbstractAnimation::stop()
952 {
953     Q_D(QAbstractAnimation);
954 
955     if (d->state == Stopped)
956         return;
957 
958     d->setState(Stopped);
959 }
960 
961 /*!
962     Pauses the animation. When the animation is paused, state() returns Paused.
963     The value of currentTime will remain unchanged until resume() or start()
964     is called. If you want to continue from the current time, call resume().
965 
966     \sa start(), state(), resume()
967  */
pause()968 void QAbstractAnimation::pause()
969 {
970     Q_D(QAbstractAnimation);
971     if (d->state == Stopped) {
972         qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
973         return;
974     }
975 
976     d->setState(Paused);
977 }
978 
979 /*!
980     Resumes the animation after it was paused. When the animation is resumed,
981     it emits the resumed() and stateChanged() signals. The currenttime is not
982     changed.
983 
984     \sa start(), pause(), state()
985  */
resume()986 void QAbstractAnimation::resume()
987 {
988     Q_D(QAbstractAnimation);
989     if (d->state != Paused) {
990         qWarning("QAbstractAnimation::resume: "
991                  "Cannot resume an animation that is not paused");
992         return;
993     }
994 
995     d->setState(Running);
996 }
997 
998 /*!
999     If \a paused is true, the animation is paused.
1000     If \a paused is false, the animation is resumed.
1001 
1002     \sa state(), pause(), resume()
1003 */
setPaused(bool paused)1004 void QAbstractAnimation::setPaused(bool paused)
1005 {
1006     if (paused)
1007         pause();
1008     else
1009         resume();
1010 }
1011 
1012 
1013 /*!
1014     \reimp
1015 */
event(QEvent * event)1016 bool QAbstractAnimation::event(QEvent *event)
1017 {
1018     return QObject::event(event);
1019 }
1020 
1021 /*!
1022     \fn virtual void QAbstractAnimation::updateCurrentTime(int currentTime) = 0;
1023 
1024     This pure virtual function is called every time the animation's
1025     \a currentTime changes.
1026 
1027     \sa updateState()
1028 */
1029 
1030 /*!
1031     This virtual function is called by QAbstractAnimation when the state
1032     of the animation is changed from \a oldState to \a newState.
1033 
1034     \sa start(), stop(), pause(), resume()
1035 */
updateState(QAbstractAnimation::State newState,QAbstractAnimation::State oldState)1036 void QAbstractAnimation::updateState(QAbstractAnimation::State newState,
1037                                      QAbstractAnimation::State oldState)
1038 {
1039     Q_UNUSED(oldState);
1040     Q_UNUSED(newState);
1041 }
1042 
1043 /*!
1044     This virtual function is called by QAbstractAnimation when the direction
1045     of the animation is changed. The \a direction argument is the new direction.
1046 
1047     \sa setDirection(), direction()
1048 */
updateDirection(QAbstractAnimation::Direction direction)1049 void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
1050 {
1051     Q_UNUSED(direction);
1052 }
1053 
1054 
1055 QT_END_NAMESPACE
1056 
1057 #include "moc_qabstractanimation.cpp"
1058 
1059 #endif //QT_NO_ANIMATION
1060