1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://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 https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://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 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 /*!
41     \class QAbstractAnimation
42     \inmodule QtCore
43     \ingroup animation
44     \brief The QAbstractAnimation class is the base of all animations.
45     \since 4.6
46 
47     The class defines the functions for the functionality shared by
48     all animations. By inheriting this class, you can create custom
49     animations that plug into the rest of the animation framework.
50 
51     The progress of an animation is given by its current time
52     (currentLoopTime()), which is measured in milliseconds from the start
53     of the animation (0) to its end (duration()). The value is updated
54     automatically while the animation is running. It can also be set
55     directly with setCurrentTime().
56 
57     At any point an animation is in one of three states:
58     \l{QAbstractAnimation::}{Running},
59     \l{QAbstractAnimation::}{Stopped}, or
60     \l{QAbstractAnimation::}{Paused}--as defined by the
61     \l{QAbstractAnimation::}{State} enum. The current state can be
62     changed by calling start(), stop(), pause(), or resume(). An
63     animation will always reset its \l{currentTime()}{current time}
64     when it is started. If paused, it will continue with the same
65     current time when resumed. When an animation is stopped, it cannot
66     be resumed, but will keep its current time (until started again).
67     QAbstractAnimation will emit stateChanged() whenever its state
68     changes.
69 
70     An animation can loop any number of times by setting the loopCount
71     property. When an animation's current time reaches its duration(),
72     it will reset the current time and keep running. A loop count of 1
73     (the default value) means that the animation will run one time.
74     Note that a duration of -1 means that the animation will run until
75     stopped; the current time will increase indefinitely. When the
76     current time equals duration() and the animation is in its
77     final loop, the \l{QAbstractAnimation::}{Stopped} state is
78     entered, and the finished() signal is emitted.
79 
80     QAbstractAnimation provides pure virtual functions used by
81     subclasses to track the progress of the animation: duration() and
82     updateCurrentTime(). The duration() function lets you report a
83     duration for the animation (as discussed above). The animation
84     framework calls updateCurrentTime() when current time has changed.
85     By reimplementing this function, you can track the animation
86     progress. Note that neither the interval between calls nor the
87     number of calls to this function are defined; though, it will
88     normally be 60 updates per second.
89 
90     By reimplementing updateState(), you can track the animation's
91     state changes, which is particularly useful for animations that
92     are not driven by time.
93 
94     \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework}
95 */
96 
97 /*!
98     \enum QAbstractAnimation::DeletionPolicy
99 
100     \value KeepWhenStopped The animation will not be deleted when stopped.
101     \value DeleteWhenStopped The animation will be automatically deleted when
102     stopped.
103 */
104 
105 /*!
106     \fn void QAbstractAnimation::finished()
107 
108     QAbstractAnimation emits this signal after the animation has stopped and
109     has reached the end.
110 
111     This signal is emitted after stateChanged().
112 
113     \sa stateChanged()
114 */
115 
116 /*!
117     \fn void QAbstractAnimation::stateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
118 
119     QAbstractAnimation emits this signal whenever the state of the animation has
120     changed from \a oldState to \a newState. This signal is emitted after the virtual
121     updateState() function is called.
122 
123     \sa updateState()
124 */
125 
126 /*!
127     \fn void QAbstractAnimation::currentLoopChanged(int currentLoop)
128 
129     QAbstractAnimation emits this signal whenever the current loop
130     changes. \a currentLoop is the current loop.
131 
132     \sa currentLoop(), loopCount()
133 */
134 
135 /*!
136     \fn void QAbstractAnimation::directionChanged(QAbstractAnimation::Direction newDirection);
137 
138     QAbstractAnimation emits this signal whenever the direction has been
139     changed. \a newDirection is the new direction.
140 
141     \sa direction
142 */
143 
144 #include "qabstractanimation.h"
145 #include "qanimationgroup.h"
146 
147 #include <QtCore/qdebug.h>
148 
149 #include "qabstractanimation_p.h"
150 
151 #include <QtCore/qmath.h>
152 #include <QtCore/qthreadstorage.h>
153 #include <QtCore/qcoreevent.h>
154 #include <QtCore/qpointer.h>
155 #include <QtCore/qscopedvaluerollback.h>
156 
157 #define DEFAULT_TIMER_INTERVAL 16
158 #define PAUSE_TIMER_COARSE_THRESHOLD 2000
159 
160 QT_BEGIN_NAMESPACE
161 
162 typedef QList<QAbstractAnimationTimer*>::ConstIterator TimerListConstIt;
163 typedef QList<QAbstractAnimation*>::ConstIterator AnimationListConstIt;
164 
165 /*!
166   \class QAbstractAnimationTimer
167   \inmodule QtCore
168   \brief QAbstractAnimationTimer is the base class for animation timers.
169   \internal
170 
171   Subclass QAbstractAnimationTimer to provide an animation timer that is run by
172   QUnifiedTimer and can in turn be used to run any number of animations.
173 
174   Currently two subclasses have been implemented: QAnimationTimer to drive the Qt C++
175   animation framework (QAbstractAnimation and subclasses) and QDeclarativeAnimationTimer
176   to drive the Qt QML animation framework.
177 */
178 
179 /*!
180     \fn virtual void QAbstractAnimationTimer::updateAnimationsTime(qint64 delta) = 0;
181     \internal
182 
183     This pure virtual function is called when the animation timer needs to update
184     the current time for all animations it is running.
185 */
186 
187 /*!
188     \fn virtual void QAbstractAnimationTimer::restartAnimationTimer() = 0;
189     \internal
190 
191     This pure virtual function restarts the animation timer as needed.
192 
193     Classes implementing this function may choose to pause or resume the timer
194     as appropriate, or conditionally restart it.
195 */
196 
197 /*!
198     \fn virtual int QAbstractAnimationTimer::runningAnimationCount() = 0;
199     \internal
200 
201     This pure virtual function returns the number of animations the timer is running.
202     This information is useful for profiling.
203 */
204 
205 /*!
206     \class QUnifiedTimer
207     \inmodule QtCore
208     \brief QUnifiedTimer provides a unified timing mechanism for animations in Qt C++ and QML.
209     \internal
210 
211     QUnifiedTimer allows animations run by Qt to share a single timer. This keeps animations
212     visually in sync, as well as being more efficient than running numerous timers.
213 
214     QUnifiedTimer drives animations indirectly, via QAbstractAnimationTimer.
215 */
216 
Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer * >,unifiedTimer)217 Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
218 
219 QUnifiedTimer::QUnifiedTimer() :
220     QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
221     currentAnimationIdx(0), insideTick(false), insideRestart(false), consistentTiming(false), slowMode(false),
222     startTimersPending(false), stopTimerPending(false),
223     slowdownFactor(5.0f), profilerCallback(nullptr),
224     driverStartTime(0), temporalDrift(0)
225 {
226     time.invalidate();
227     driver = &defaultDriver;
228 }
229 
230 
instance(bool create)231 QUnifiedTimer *QUnifiedTimer::instance(bool create)
232 {
233     QUnifiedTimer *inst;
234     if (create && !unifiedTimer()->hasLocalData()) {
235         inst = new QUnifiedTimer;
236         unifiedTimer()->setLocalData(inst);
237     } else {
238         inst = unifiedTimer() ? unifiedTimer()->localData() : 0;
239     }
240     return inst;
241 }
242 
instance()243 QUnifiedTimer *QUnifiedTimer::instance()
244 {
245     return instance(true);
246 }
247 
maybeUpdateAnimationsToCurrentTime()248 void QUnifiedTimer::maybeUpdateAnimationsToCurrentTime()
249 {
250     if (elapsed() - lastTick > 50)
251         updateAnimationTimers(-1);
252 }
253 
elapsed() const254 qint64 QUnifiedTimer::elapsed() const
255 {
256     if (driver->isRunning())
257         return driverStartTime + driver->elapsed();
258     else if (time.isValid())
259         return time.elapsed() + temporalDrift;
260 
261     // Reaching here would normally indicate that the function is called
262     // under the wrong circumstances as neither pauses nor actual animations
263     // are running and there should be no need to query for elapsed().
264     return 0;
265 }
266 
startAnimationDriver()267 void QUnifiedTimer::startAnimationDriver()
268 {
269     if (driver->isRunning()) {
270         qWarning("QUnifiedTimer::startAnimationDriver: driver is already running...");
271         return;
272     }
273     // Set the start time to the currently elapsed() value before starting.
274     // This means we get the animation system time including the temporal drift
275     // which is what we want.
276     driverStartTime = elapsed();
277     driver->start();
278 }
279 
stopAnimationDriver()280 void QUnifiedTimer::stopAnimationDriver()
281 {
282     if (!driver->isRunning()) {
283         qWarning("QUnifiedTimer::stopAnimationDriver: driver is not running");
284         return;
285     }
286     // Update temporal drift. Since the driver is running, elapsed() will
287     // return the total animation time in driver-time. Subtract the current
288     // wall time to get the delta.
289     temporalDrift = elapsed() - time.elapsed();
290     driver->stop();
291 }
292 
updateAnimationTimers(qint64 currentTick)293 void QUnifiedTimer::updateAnimationTimers(qint64 currentTick)
294 {
295     //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations
296     if(insideTick)
297         return;
298 
299     qint64 totalElapsed = currentTick > 0 ? currentTick : elapsed();
300 
301     // ignore consistentTiming in case the pause timer is active
302     qint64 delta = (consistentTiming && !pauseTimer.isActive()) ?
303                         timingInterval : totalElapsed - lastTick;
304     if (slowMode) {
305         if (slowdownFactor > 0)
306             delta = qRound(delta / slowdownFactor);
307         else
308             delta = 0;
309     }
310 
311     lastTick = totalElapsed;
312 
313     //we make sure we only call update time if the time has actually advanced
314     //* it might happen in some cases that the time doesn't change because events are delayed
315     //  when the CPU load is high
316     //* it might happen in some cases that the delta is negative because the animation driver
317     //  advances faster than time.elapsed()
318     if (delta > 0) {
319         QScopedValueRollback<bool> guard(insideTick, true);
320         if (profilerCallback)
321             profilerCallback(delta);
322         for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.count(); ++currentAnimationIdx) {
323             QAbstractAnimationTimer *animation = animationTimers.at(currentAnimationIdx);
324             animation->updateAnimationsTime(delta);
325         }
326         currentAnimationIdx = 0;
327     }
328 }
329 
runningAnimationCount()330 int QUnifiedTimer::runningAnimationCount()
331 {
332     int count = 0;
333     for (int i = 0; i < animationTimers.count(); ++i)
334         count += animationTimers.at(i)->runningAnimationCount();
335     return count;
336 }
337 
registerProfilerCallback(void (* cb)(qint64))338 void QUnifiedTimer::registerProfilerCallback(void (*cb)(qint64))
339 {
340     profilerCallback = cb;
341 }
342 
localRestart()343 void QUnifiedTimer::localRestart()
344 {
345     if (insideRestart)
346         return;
347 
348     if (!pausedAnimationTimers.isEmpty() && (animationTimers.count() + animationTimersToStart.count() == pausedAnimationTimers.count())) {
349         driver->stop();
350         int closestTimeToFinish = closestPausedAnimationTimerTimeToFinish();
351         // use a precise timer if the pause will be short
352         Qt::TimerType timerType = closestTimeToFinish < PAUSE_TIMER_COARSE_THRESHOLD ? Qt::PreciseTimer : Qt::CoarseTimer;
353         pauseTimer.start(closestTimeToFinish, timerType, this);
354     } else if (!driver->isRunning()) {
355         if (pauseTimer.isActive())
356             pauseTimer.stop();
357         startAnimationDriver();
358     }
359 
360 }
361 
restart()362 void QUnifiedTimer::restart()
363 {
364     {
365         QScopedValueRollback<bool> guard(insideRestart, true);
366         for (int i = 0; i < animationTimers.count(); ++i)
367             animationTimers.at(i)->restartAnimationTimer();
368     }
369 
370     localRestart();
371 }
372 
setTimingInterval(int interval)373 void QUnifiedTimer::setTimingInterval(int interval)
374 {
375     timingInterval = interval;
376 
377     if (driver->isRunning() && !pauseTimer.isActive()) {
378         //we changed the timing interval
379         stopAnimationDriver();
380         startAnimationDriver();
381     }
382 }
383 
startTimers()384 void QUnifiedTimer::startTimers()
385 {
386     startTimersPending = false;
387 
388     //we transfer the waiting animations into the "really running" state
389     animationTimers += animationTimersToStart;
390     animationTimersToStart.clear();
391     if (!animationTimers.isEmpty()) {
392         if (!time.isValid()) {
393             lastTick = 0;
394             time.start();
395             temporalDrift = 0;
396             driverStartTime = 0;
397         }
398         localRestart();
399     }
400 }
401 
stopTimer()402 void QUnifiedTimer::stopTimer()
403 {
404     stopTimerPending = false;
405     if (animationTimers.isEmpty()) {
406         stopAnimationDriver();
407         pauseTimer.stop();
408         // invalidate the start reference time
409         time.invalidate();
410     }
411 }
412 
timerEvent(QTimerEvent * event)413 void QUnifiedTimer::timerEvent(QTimerEvent *event)
414 {
415     //in the case of consistent timing we make sure the order in which events come is always the same
416     //for that purpose we do as if the startstoptimer would always fire before the animation timer
417     if (consistentTiming) {
418         if (stopTimerPending)
419             stopTimer();
420         if (startTimersPending)
421             startTimers();
422     }
423 
424     if (event->timerId() == pauseTimer.timerId()) {
425         // update current time on all timers
426         updateAnimationTimers(-1);
427         restart();
428     }
429 }
430 
startAnimationTimer(QAbstractAnimationTimer * timer)431 void QUnifiedTimer::startAnimationTimer(QAbstractAnimationTimer *timer)
432 {
433     if (timer->isRegistered)
434         return;
435     timer->isRegistered = true;
436 
437     QUnifiedTimer *inst = instance(true); //we create the instance if needed
438     inst->animationTimersToStart << timer;
439     if (!inst->startTimersPending) {
440         inst->startTimersPending = true;
441         QMetaObject::invokeMethod(inst, "startTimers", Qt::QueuedConnection);
442     }
443 }
444 
stopAnimationTimer(QAbstractAnimationTimer * timer)445 void QUnifiedTimer::stopAnimationTimer(QAbstractAnimationTimer *timer)
446 {
447     QUnifiedTimer *inst = QUnifiedTimer::instance(false);
448     if (inst) {
449         //at this point the unified timer should have been created
450         //but it might also have been already destroyed in case the application is shutting down
451 
452         if (!timer->isRegistered)
453             return;
454         timer->isRegistered = false;
455 
456         int idx = inst->animationTimers.indexOf(timer);
457         if (idx != -1) {
458             inst->animationTimers.removeAt(idx);
459             // this is needed if we unregister an animation while its running
460             if (idx <= inst->currentAnimationIdx)
461                 --inst->currentAnimationIdx;
462 
463             if (inst->animationTimers.isEmpty() && !inst->stopTimerPending) {
464                 inst->stopTimerPending = true;
465                 QMetaObject::invokeMethod(inst, "stopTimer", Qt::QueuedConnection);
466             }
467         } else {
468             inst->animationTimersToStart.removeOne(timer);
469         }
470     }
471 }
472 
pauseAnimationTimer(QAbstractAnimationTimer * timer,int duration)473 void QUnifiedTimer::pauseAnimationTimer(QAbstractAnimationTimer *timer, int duration)
474 {
475     QUnifiedTimer *inst = QUnifiedTimer::instance();
476     if (!timer->isRegistered)
477         inst->startAnimationTimer(timer);
478 
479     bool timerWasPaused = timer->isPaused;
480     timer->isPaused = true;
481     timer->pauseDuration = duration;
482     if (!timerWasPaused)
483         inst->pausedAnimationTimers << timer;
484     inst->localRestart();
485 }
486 
resumeAnimationTimer(QAbstractAnimationTimer * timer)487 void QUnifiedTimer::resumeAnimationTimer(QAbstractAnimationTimer *timer)
488 {
489     if (!timer->isPaused)
490         return;
491 
492     timer->isPaused = false;
493     QUnifiedTimer *inst = QUnifiedTimer::instance();
494     inst->pausedAnimationTimers.removeOne(timer);
495     inst->localRestart();
496 }
497 
closestPausedAnimationTimerTimeToFinish()498 int QUnifiedTimer::closestPausedAnimationTimerTimeToFinish()
499 {
500     int closestTimeToFinish = INT_MAX;
501     for (TimerListConstIt it = pausedAnimationTimers.constBegin(), cend = pausedAnimationTimers.constEnd(); it != cend; ++it) {
502         const int timeToFinish = (*it)->pauseDuration;
503         if (timeToFinish < closestTimeToFinish)
504             closestTimeToFinish = timeToFinish;
505     }
506     return closestTimeToFinish;
507 }
508 
installAnimationDriver(QAnimationDriver * d)509 void QUnifiedTimer::installAnimationDriver(QAnimationDriver *d)
510 {
511     if (driver != &defaultDriver) {
512         qWarning("QUnifiedTimer: animation driver already installed...");
513         return;
514     }
515 
516     bool running = driver->isRunning();
517     if (running)
518         stopAnimationDriver();
519     driver = d;
520     if (running)
521         startAnimationDriver();
522 }
523 
uninstallAnimationDriver(QAnimationDriver * d)524 void QUnifiedTimer::uninstallAnimationDriver(QAnimationDriver *d)
525 {
526     if (driver != d) {
527         qWarning("QUnifiedTimer: trying to uninstall a driver that is not installed...");
528         return;
529     }
530 
531     bool running = driver->isRunning();
532     if (running)
533         stopAnimationDriver();
534     driver = &defaultDriver;
535     if (running)
536         startAnimationDriver();
537 }
538 
539 /*!
540     Returns \c true if \a d is the currently installed animation driver
541     and is not the default animation driver (which can never be uninstalled).
542 */
canUninstallAnimationDriver(QAnimationDriver * d)543 bool QUnifiedTimer::canUninstallAnimationDriver(QAnimationDriver *d)
544 {
545     return d == driver && driver != &defaultDriver;
546 }
547 
548 #if QT_CONFIG(thread)
Q_GLOBAL_STATIC(QThreadStorage<QAnimationTimer * >,animationTimer)549 Q_GLOBAL_STATIC(QThreadStorage<QAnimationTimer *>, animationTimer)
550 #endif
551 
552 QAnimationTimer::QAnimationTimer() :
553     QAbstractAnimationTimer(), lastTick(0),
554     currentAnimationIdx(0), insideTick(false),
555     startAnimationPending(false), stopTimerPending(false),
556     runningLeafAnimations(0)
557 {
558 }
559 
instance(bool create)560 QAnimationTimer *QAnimationTimer::instance(bool create)
561 {
562     QAnimationTimer *inst;
563 #if QT_CONFIG(thread)
564     if (create && !animationTimer()->hasLocalData()) {
565         inst = new QAnimationTimer;
566         animationTimer()->setLocalData(inst);
567     } else {
568         inst = animationTimer() ? animationTimer()->localData() : 0;
569     }
570 #else
571     Q_UNUSED(create);
572     static QAnimationTimer animationTimer;
573     inst = &animationTimer;
574 #endif
575     return inst;
576 }
577 
instance()578 QAnimationTimer *QAnimationTimer::instance()
579 {
580     return instance(true);
581 }
582 
ensureTimerUpdate()583 void QAnimationTimer::ensureTimerUpdate()
584 {
585     QAnimationTimer *inst = QAnimationTimer::instance(false);
586     QUnifiedTimer *instU = QUnifiedTimer::instance(false);
587     if (instU && inst && inst->isPaused)
588         instU->updateAnimationTimers(-1);
589 }
590 
updateAnimationsTime(qint64 delta)591 void QAnimationTimer::updateAnimationsTime(qint64 delta)
592 {
593     //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations
594     if (insideTick)
595         return;
596 
597     lastTick += delta;
598 
599     //we make sure we only call update time if the time has actually changed
600     //it might happen in some cases that the time doesn't change because events are delayed
601     //when the CPU load is high
602     if (delta) {
603         QScopedValueRollback<bool> guard(insideTick, true);
604         for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
605             QAbstractAnimation *animation = animations.at(currentAnimationIdx);
606             int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
607                           + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
608             animation->setCurrentTime(elapsed);
609         }
610         currentAnimationIdx = 0;
611     }
612 }
613 
updateAnimationTimer()614 void QAnimationTimer::updateAnimationTimer()
615 {
616     QAnimationTimer *inst = QAnimationTimer::instance(false);
617     if (inst)
618         inst->restartAnimationTimer();
619 }
620 
restartAnimationTimer()621 void QAnimationTimer::restartAnimationTimer()
622 {
623     if (runningLeafAnimations == 0 && !runningPauseAnimations.isEmpty())
624         QUnifiedTimer::pauseAnimationTimer(this, closestPauseAnimationTimeToFinish());
625     else if (isPaused)
626         QUnifiedTimer::resumeAnimationTimer(this);
627     else if (!isRegistered)
628         QUnifiedTimer::startAnimationTimer(this);
629 }
630 
startAnimations()631 void QAnimationTimer::startAnimations()
632 {
633     if (!startAnimationPending)
634         return;
635     startAnimationPending = false;
636 
637     //force timer to update, which prevents large deltas for our newly added animations
638     QUnifiedTimer::instance()->maybeUpdateAnimationsToCurrentTime();
639 
640     //we transfer the waiting animations into the "really running" state
641     animations += animationsToStart;
642     animationsToStart.clear();
643     if (!animations.isEmpty())
644         restartAnimationTimer();
645 }
646 
stopTimer()647 void QAnimationTimer::stopTimer()
648 {
649     stopTimerPending = false;
650     bool pendingStart = startAnimationPending && animationsToStart.size() > 0;
651     if (animations.isEmpty() && !pendingStart) {
652         QUnifiedTimer::resumeAnimationTimer(this);
653         QUnifiedTimer::stopAnimationTimer(this);
654         // invalidate the start reference time
655         lastTick = 0;
656     }
657 }
658 
registerAnimation(QAbstractAnimation * animation,bool isTopLevel)659 void QAnimationTimer::registerAnimation(QAbstractAnimation *animation, bool isTopLevel)
660 {
661     QAnimationTimer *inst = instance(true); //we create the instance if needed
662     inst->registerRunningAnimation(animation);
663     if (isTopLevel) {
664         Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer);
665         QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true;
666         inst->animationsToStart << animation;
667         if (!inst->startAnimationPending) {
668             inst->startAnimationPending = true;
669             QMetaObject::invokeMethod(inst, "startAnimations", Qt::QueuedConnection);
670         }
671     }
672 }
673 
unregisterAnimation(QAbstractAnimation * animation)674 void QAnimationTimer::unregisterAnimation(QAbstractAnimation *animation)
675 {
676     QAnimationTimer *inst = QAnimationTimer::instance(false);
677     if (inst) {
678         //at this point the unified timer should have been created
679         //but it might also have been already destroyed in case the application is shutting down
680 
681         inst->unregisterRunningAnimation(animation);
682 
683         if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer)
684             return;
685 
686         int idx = inst->animations.indexOf(animation);
687         if (idx != -1) {
688             inst->animations.removeAt(idx);
689             // this is needed if we unregister an animation while its running
690             if (idx <= inst->currentAnimationIdx)
691                 --inst->currentAnimationIdx;
692 
693             if (inst->animations.isEmpty() && !inst->stopTimerPending) {
694                 inst->stopTimerPending = true;
695                 QMetaObject::invokeMethod(inst, "stopTimer", Qt::QueuedConnection);
696             }
697         } else {
698             inst->animationsToStart.removeOne(animation);
699         }
700     }
701     QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false;
702 }
703 
registerRunningAnimation(QAbstractAnimation * animation)704 void QAnimationTimer::registerRunningAnimation(QAbstractAnimation *animation)
705 {
706     if (QAbstractAnimationPrivate::get(animation)->isGroup)
707         return;
708 
709     if (QAbstractAnimationPrivate::get(animation)->isPause) {
710         runningPauseAnimations << animation;
711     } else
712         runningLeafAnimations++;
713 }
714 
unregisterRunningAnimation(QAbstractAnimation * animation)715 void QAnimationTimer::unregisterRunningAnimation(QAbstractAnimation *animation)
716 {
717     if (QAbstractAnimationPrivate::get(animation)->isGroup)
718         return;
719 
720     if (QAbstractAnimationPrivate::get(animation)->isPause)
721         runningPauseAnimations.removeOne(animation);
722     else
723         runningLeafAnimations--;
724     Q_ASSERT(runningLeafAnimations >= 0);
725 }
726 
closestPauseAnimationTimeToFinish()727 int QAnimationTimer::closestPauseAnimationTimeToFinish()
728 {
729     int closestTimeToFinish = INT_MAX;
730     for (AnimationListConstIt it = runningPauseAnimations.constBegin(), cend = runningPauseAnimations.constEnd(); it != cend; ++it) {
731         const QAbstractAnimation *animation = *it;
732         int timeToFinish;
733 
734         if (animation->direction() == QAbstractAnimation::Forward)
735             timeToFinish = animation->duration() - animation->currentLoopTime();
736         else
737             timeToFinish = animation->currentLoopTime();
738 
739         if (timeToFinish < closestTimeToFinish)
740             closestTimeToFinish = timeToFinish;
741     }
742     return closestTimeToFinish;
743 }
744 
745 /*!
746    \class QAnimationDriver
747    \inmodule QtCore
748 
749    \brief The QAnimationDriver class is used to exchange the mechanism that drives animations.
750 
751    The default animation system is driven by a timer that fires at regular intervals.
752    In some scenarios, it is better to drive the animation based on other synchronization
753    mechanisms, such as the vertical refresh rate of the screen.
754 
755    \internal
756  */
757 
QAnimationDriver(QObject * parent)758 QAnimationDriver::QAnimationDriver(QObject *parent)
759     : QObject(*(new QAnimationDriverPrivate), parent)
760 {
761 }
762 
QAnimationDriver(QAnimationDriverPrivate & dd,QObject * parent)763 QAnimationDriver::QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent)
764     : QObject(dd, parent)
765 {
766 }
767 
~QAnimationDriver()768 QAnimationDriver::~QAnimationDriver()
769 {
770     QUnifiedTimer *timer = QUnifiedTimer::instance(false);
771     if (timer && timer->canUninstallAnimationDriver(this))
772         uninstall();
773 }
774 
775 
776 #if QT_DEPRECATED_SINCE(5, 13)
777 /*!
778     Sets the time at which an animation driver should start at.
779 
780     This is to take into account that pauses can occur in running
781     animations which will stop the driver, but the time still
782     increases.
783 
784     \obsolete
785 
786     This logic is now handled internally in the animation system.
787  */
setStartTime(qint64)788 void QAnimationDriver::setStartTime(qint64)
789 {
790 }
791 
792 /*!
793     Returns the start time of the animation.
794 
795     \obsolete
796 
797     This logic is now handled internally in the animation system.
798  */
startTime() const799 qint64 QAnimationDriver::startTime() const
800 {
801     return 0;
802 }
803 #endif
804 
805 
806 /*!
807     Advances the animation based to the specified \a timeStep. This function should
808     be continuously called by the driver subclasses while the animation is running.
809 
810     If \a timeStep is positive, it will be used as the current time in the
811     calculations; otherwise, the current clock time will be used.
812 
813     Since 5.4, the timeStep argument is ignored and elapsed() will be
814     used instead in combination with the internal time offsets of the
815     animation system.
816  */
817 
advanceAnimation(qint64 timeStep)818 void QAnimationDriver::advanceAnimation(qint64 timeStep)
819 {
820     QUnifiedTimer *instance = QUnifiedTimer::instance();
821 
822     // update current time on all top level animations
823     instance->updateAnimationTimers(timeStep);
824     instance->restart();
825 }
826 
827 
828 
829 /*!
830     Advances the animation. This function should be continously called
831     by the driver while the animation is running.
832  */
833 
advance()834 void QAnimationDriver::advance()
835 {
836     advanceAnimation(-1);
837 }
838 
839 
840 
841 /*!
842     Installs this animation driver. The animation driver is thread local and
843     will only apply for the thread its installed in.
844  */
845 
install()846 void QAnimationDriver::install()
847 {
848     QUnifiedTimer *timer = QUnifiedTimer::instance(true);
849     timer->installAnimationDriver(this);
850 }
851 
852 
853 
854 /*!
855     Uninstalls this animation driver.
856  */
857 
uninstall()858 void QAnimationDriver::uninstall()
859 {
860     QUnifiedTimer *timer = QUnifiedTimer::instance(true);
861     timer->uninstallAnimationDriver(this);
862 }
863 
isRunning() const864 bool QAnimationDriver::isRunning() const
865 {
866     return d_func()->running;
867 }
868 
869 
start()870 void QAnimationDriver::start()
871 {
872     Q_D(QAnimationDriver);
873     if (!d->running) {
874         d->running = true;
875         d->timer.start();
876         emit started();
877     }
878 }
879 
880 
stop()881 void QAnimationDriver::stop()
882 {
883     Q_D(QAnimationDriver);
884     if (d->running) {
885         d->running = false;
886         emit stopped();
887     }
888 }
889 
890 
891 /*!
892     \fn qint64 QAnimationDriver::elapsed() const
893 
894     Returns the number of milliseconds since the animations was started.
895  */
896 
elapsed() const897 qint64 QAnimationDriver::elapsed() const
898 {
899     Q_D(const QAnimationDriver);
900     return d->running ? d->timer.elapsed() : 0;
901 }
902 
903 /*!
904     \fn QAnimationDriver::started()
905 
906     This signal is emitted by the animation framework to notify the driver
907     that continuous animation has started.
908 
909     \internal
910  */
911 
912 /*!
913     \fn QAnimationDriver::stopped()
914 
915     This signal is emitted by the animation framework to notify the driver
916     that continuous animation has stopped.
917 
918     \internal
919  */
920 
921 /*!
922    The default animation driver just spins the timer...
923  */
QDefaultAnimationDriver(QUnifiedTimer * timer)924 QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer)
925     : QAnimationDriver(nullptr), m_unified_timer(timer)
926 {
927     connect(this, SIGNAL(started()), this, SLOT(startTimer()));
928     connect(this, SIGNAL(stopped()), this, SLOT(stopTimer()));
929 }
930 
timerEvent(QTimerEvent * e)931 void QDefaultAnimationDriver::timerEvent(QTimerEvent *e)
932 {
933     Q_ASSERT(e->timerId() == m_timer.timerId());
934     Q_UNUSED(e); // if the assertions are disabled
935     advance();
936 }
937 
startTimer()938 void QDefaultAnimationDriver::startTimer()
939 {
940     // always use a precise timer to drive animations
941     m_timer.start(m_unified_timer->timingInterval, Qt::PreciseTimer, this);
942 }
943 
stopTimer()944 void QDefaultAnimationDriver::stopTimer()
945 {
946     m_timer.stop();
947 }
948 
949 
950 
setState(QAbstractAnimation::State newState)951 void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
952 {
953     Q_Q(QAbstractAnimation);
954     if (state == newState)
955         return;
956 
957     if (loopCount == 0)
958         return;
959 
960     QAbstractAnimation::State oldState = state;
961     int oldCurrentTime = currentTime;
962     int oldCurrentLoop = currentLoop;
963     QAbstractAnimation::Direction oldDirection = direction;
964 
965     // check if we should Rewind
966     if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running)
967         && oldState == QAbstractAnimation::Stopped) {
968             //here we reset the time if needed
969             //we don't call setCurrentTime because this might change the way the animation
970             //behaves: changing the state or changing the current value
971             totalCurrentTime = currentTime = (direction == QAbstractAnimation::Forward) ?
972                 0 : (loopCount == -1 ? q->duration() : q->totalDuration());
973     }
974 
975     state = newState;
976     QPointer<QAbstractAnimation> guard(q);
977 
978     //(un)registration of the animation must always happen before calls to
979     //virtual function (updateState) to ensure a correct state of the timer
980     bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped;
981     if (oldState == QAbstractAnimation::Running) {
982         if (newState == QAbstractAnimation::Paused && hasRegisteredTimer)
983             QAnimationTimer::ensureTimerUpdate();
984         //the animation, is not running any more
985         QAnimationTimer::unregisterAnimation(q);
986     } else if (newState == QAbstractAnimation::Running) {
987         QAnimationTimer::registerAnimation(q, isTopLevel);
988     }
989 
990     q->updateState(newState, oldState);
991     if (!guard || newState != state) //this is to be safe if updateState changes the state
992         return;
993 
994     // Notify state change
995     emit q->stateChanged(newState, oldState);
996     if (!guard || newState != state) //this is to be safe if updateState changes the state
997         return;
998 
999     switch (state) {
1000     case QAbstractAnimation::Paused:
1001         break;
1002     case QAbstractAnimation::Running:
1003         {
1004 
1005             // this ensures that the value is updated now that the animation is running
1006             if (oldState == QAbstractAnimation::Stopped) {
1007                 if (isTopLevel) {
1008                     // currentTime needs to be updated if pauseTimer is active
1009                     QAnimationTimer::ensureTimerUpdate();
1010                     q->setCurrentTime(totalCurrentTime);
1011                 }
1012             }
1013         }
1014         break;
1015     case QAbstractAnimation::Stopped:
1016         // Leave running state.
1017         int dura = q->duration();
1018 
1019         if (deleteWhenStopped)
1020             q->deleteLater();
1021 
1022         if (dura == -1 || loopCount < 0
1023             || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount))
1024             || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
1025                 emit q->finished();
1026         }
1027         break;
1028     }
1029 }
1030 
1031 /*!
1032     Constructs the QAbstractAnimation base class, and passes \a parent to
1033     QObject's constructor.
1034 
1035     \sa QVariantAnimation, QAnimationGroup
1036 */
QAbstractAnimation(QObject * parent)1037 QAbstractAnimation::QAbstractAnimation(QObject *parent)
1038     : QObject(*new QAbstractAnimationPrivate, nullptr)
1039 {
1040     // Allow auto-add on reparent
1041     setParent(parent);
1042 }
1043 
1044 /*!
1045     \internal
1046 */
QAbstractAnimation(QAbstractAnimationPrivate & dd,QObject * parent)1047 QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
1048     : QObject(dd, nullptr)
1049 {
1050     // Allow auto-add on reparent
1051    setParent(parent);
1052 }
1053 
1054 /*!
1055     Stops the animation if it's running, then destroys the
1056     QAbstractAnimation. If the animation is part of a QAnimationGroup, it is
1057     automatically removed before it's destroyed.
1058 */
~QAbstractAnimation()1059 QAbstractAnimation::~QAbstractAnimation()
1060 {
1061     Q_D(QAbstractAnimation);
1062     //we can't call stop here. Otherwise we get pure virtual calls
1063     if (d->state != Stopped) {
1064         QAbstractAnimation::State oldState = d->state;
1065         d->state = Stopped;
1066         emit stateChanged(d->state, oldState);
1067         if (oldState == QAbstractAnimation::Running)
1068             QAnimationTimer::unregisterAnimation(this);
1069     }
1070     if (d->group)
1071         d->group->removeAnimation(this);
1072 }
1073 
1074 /*!
1075     \property QAbstractAnimation::state
1076     \brief state of the animation.
1077 
1078     This property describes the current state of the animation. When the
1079     animation state changes, QAbstractAnimation emits the stateChanged()
1080     signal.
1081 */
state() const1082 QAbstractAnimation::State QAbstractAnimation::state() const
1083 {
1084     Q_D(const QAbstractAnimation);
1085     return d->state;
1086 }
1087 
1088 /*!
1089     If this animation is part of a QAnimationGroup, this function returns a
1090     pointer to the group; otherwise, it returns \nullptr.
1091 
1092     \sa QAnimationGroup::addAnimation()
1093 */
group() const1094 QAnimationGroup *QAbstractAnimation::group() const
1095 {
1096     Q_D(const QAbstractAnimation);
1097     return d->group;
1098 }
1099 
1100 /*!
1101     \enum QAbstractAnimation::State
1102 
1103     This enum describes the state of the animation.
1104 
1105     \value Stopped The animation is not running. This is the initial state
1106     of QAbstractAnimation, and the state QAbstractAnimation reenters when finished. The current
1107     time remain unchanged until either setCurrentTime() is
1108     called, or the animation is started by calling start().
1109 
1110     \value Paused The animation is paused (i.e., temporarily
1111     suspended). Calling resume() will resume animation activity.
1112 
1113     \value Running The animation is running. While control is in the event
1114     loop, QAbstractAnimation will update its current time at regular intervals,
1115     calling updateCurrentTime() when appropriate.
1116 
1117     \sa state(), stateChanged()
1118 */
1119 
1120 /*!
1121     \enum QAbstractAnimation::Direction
1122 
1123     This enum describes the direction of the animation when in \l Running state.
1124 
1125     \value Forward The current time of the animation increases with time (i.e.,
1126     moves from 0 and towards the end / duration).
1127 
1128     \value Backward The current time of the animation decreases with time (i.e.,
1129     moves from the end / duration and towards 0).
1130 
1131     \sa direction
1132 */
1133 
1134 /*!
1135     \property QAbstractAnimation::direction
1136     \brief the direction of the animation when it is in \l Running
1137     state.
1138 
1139     This direction indicates whether the time moves from 0 towards the
1140     animation duration, or from the value of the duration and towards 0 after
1141     start() has been called.
1142 
1143     By default, this property is set to \l Forward.
1144 */
direction() const1145 QAbstractAnimation::Direction QAbstractAnimation::direction() const
1146 {
1147     Q_D(const QAbstractAnimation);
1148     return d->direction;
1149 }
setDirection(Direction direction)1150 void QAbstractAnimation::setDirection(Direction direction)
1151 {
1152     Q_D(QAbstractAnimation);
1153     if (d->direction == direction)
1154         return;
1155 
1156     if (state() == Stopped) {
1157         if (direction == Backward) {
1158             d->currentTime = duration();
1159             d->currentLoop = d->loopCount - 1;
1160         } else {
1161             d->currentTime = 0;
1162             d->currentLoop = 0;
1163         }
1164     }
1165 
1166     // the commands order below is important: first we need to setCurrentTime with the old direction,
1167     // then update the direction on this and all children and finally restart the pauseTimer if needed
1168     if (d->hasRegisteredTimer)
1169         QAnimationTimer::ensureTimerUpdate();
1170 
1171     d->direction = direction;
1172     updateDirection(direction);
1173 
1174     if (d->hasRegisteredTimer)
1175         // needed to update the timer interval in case of a pause animation
1176         QAnimationTimer::updateAnimationTimer();
1177 
1178     emit directionChanged(direction);
1179 }
1180 
1181 /*!
1182     \property QAbstractAnimation::duration
1183     \brief the duration of the animation.
1184 
1185     If the duration is -1, it means that the duration is undefined.
1186     In this case, loopCount is ignored.
1187 */
1188 
1189 /*!
1190     \property QAbstractAnimation::loopCount
1191     \brief the loop count of the animation
1192 
1193     This property describes the loop count of the animation as an integer.
1194     By default this value is 1, indicating that the animation
1195     should run once only, and then stop. By changing it you can let the
1196     animation loop several times. With a value of 0, the animation will not
1197     run at all, and with a value of -1, the animation will loop forever
1198     until stopped.
1199     It is not supported to have loop on an animation that has an undefined
1200     duration. It will only run once.
1201 */
loopCount() const1202 int QAbstractAnimation::loopCount() const
1203 {
1204     Q_D(const QAbstractAnimation);
1205     return d->loopCount;
1206 }
setLoopCount(int loopCount)1207 void QAbstractAnimation::setLoopCount(int loopCount)
1208 {
1209     Q_D(QAbstractAnimation);
1210     d->loopCount = loopCount;
1211 }
1212 
1213 /*!
1214     \property QAbstractAnimation::currentLoop
1215     \brief the current loop of the animation
1216 
1217     This property describes the current loop of the animation. By default,
1218     the animation's loop count is 1, and so the current loop will
1219     always be 0. If the loop count is 2 and the animation runs past its
1220     duration, it will automatically rewind and restart at current time 0, and
1221     current loop 1, and so on.
1222 
1223     When the current loop changes, QAbstractAnimation emits the
1224     currentLoopChanged() signal.
1225 */
currentLoop() const1226 int QAbstractAnimation::currentLoop() const
1227 {
1228     Q_D(const QAbstractAnimation);
1229     return d->currentLoop;
1230 }
1231 
1232 /*!
1233     \fn virtual int QAbstractAnimation::duration() const = 0
1234 
1235     This pure virtual function returns the duration of the animation, and
1236     defines for how long QAbstractAnimation should update the current
1237     time. This duration is local, and does not include the loop count.
1238 
1239     A return value of -1 indicates that the animation has no defined duration;
1240     the animation should run forever until stopped. This is useful for
1241     animations that are not time driven, or where you cannot easily predict
1242     its duration (e.g., event driven audio playback in a game).
1243 
1244     If the animation is a parallel QAnimationGroup, the duration will be the longest
1245     duration of all its animations. If the animation is a sequential QAnimationGroup,
1246     the duration will be the sum of the duration of all its animations.
1247     \sa loopCount
1248 */
1249 
1250 /*!
1251     Returns the total and effective duration of the animation, including the
1252     loop count.
1253 
1254     \sa duration(), currentTime
1255 */
totalDuration() const1256 int QAbstractAnimation::totalDuration() const
1257 {
1258     int dura = duration();
1259     if (dura <= 0)
1260         return dura;
1261     int loopcount = loopCount();
1262     if (loopcount < 0)
1263         return -1;
1264     return dura * loopcount;
1265 }
1266 
1267 /*!
1268     Returns the current time inside the current loop. It can go from 0 to duration().
1269 
1270     \sa duration(), currentTime
1271 */
1272 
currentLoopTime() const1273 int QAbstractAnimation::currentLoopTime() const
1274 {
1275     Q_D(const QAbstractAnimation);
1276     return d->currentTime;
1277 }
1278 
1279 /*!
1280     \property QAbstractAnimation::currentTime
1281     \brief the current time and progress of the animation
1282 
1283     This property describes the animation's current time. You can change the
1284     current time by calling setCurrentTime, or you can call start() and let
1285     the animation run, setting the current time automatically as the animation
1286     progresses.
1287 
1288     The animation's current time starts at 0, and ends at totalDuration().
1289 
1290     \sa loopCount, currentLoopTime()
1291  */
currentTime() const1292 int QAbstractAnimation::currentTime() const
1293 {
1294     Q_D(const QAbstractAnimation);
1295     return d->totalCurrentTime;
1296 }
setCurrentTime(int msecs)1297 void QAbstractAnimation::setCurrentTime(int msecs)
1298 {
1299     Q_D(QAbstractAnimation);
1300     msecs = qMax(msecs, 0);
1301 
1302     // Calculate new time and loop.
1303     int dura = duration();
1304     int totalDura = dura <= 0 ? dura : ((d->loopCount < 0) ? -1 : dura * d->loopCount);
1305     if (totalDura != -1)
1306         msecs = qMin(totalDura, msecs);
1307     d->totalCurrentTime = msecs;
1308 
1309     // Update new values.
1310     int oldLoop = d->currentLoop;
1311     d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
1312     if (d->currentLoop == d->loopCount) {
1313         //we're at the end
1314         d->currentTime = qMax(0, dura);
1315         d->currentLoop = qMax(0, d->loopCount - 1);
1316     } else {
1317         if (d->direction == Forward) {
1318             d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
1319         } else {
1320             d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
1321             if (d->currentTime == dura)
1322                 --d->currentLoop;
1323         }
1324     }
1325 
1326     updateCurrentTime(d->currentTime);
1327     if (d->currentLoop != oldLoop)
1328         emit currentLoopChanged(d->currentLoop);
1329 
1330     // All animations are responsible for stopping the animation when their
1331     // own end state is reached; in this case the animation is time driven,
1332     // and has reached the end.
1333     if ((d->direction == Forward && d->totalCurrentTime == totalDura)
1334         || (d->direction == Backward && d->totalCurrentTime == 0)) {
1335         stop();
1336     }
1337 }
1338 
1339 /*!
1340     Starts the animation. The \a policy argument says whether or not the
1341     animation should be deleted when it's done. When the animation starts, the
1342     stateChanged() signal is emitted, and state() returns Running. When control
1343     reaches the event loop, the animation will run by itself, periodically
1344     calling updateCurrentTime() as the animation progresses.
1345 
1346     If the animation is currently stopped or has already reached the end,
1347     calling start() will rewind the animation and start again from the beginning.
1348     When the animation reaches the end, the animation will either stop, or
1349     if the loop level is more than 1, it will rewind and continue from the beginning.
1350 
1351     If the animation is already running, this function does nothing.
1352 
1353     \sa stop(), state()
1354 */
start(DeletionPolicy policy)1355 void QAbstractAnimation::start(DeletionPolicy policy)
1356 {
1357     Q_D(QAbstractAnimation);
1358     if (d->state == Running)
1359         return;
1360     d->deleteWhenStopped = policy;
1361     d->setState(Running);
1362 }
1363 
1364 /*!
1365     Stops the animation. When the animation is stopped, it emits the stateChanged()
1366     signal, and state() returns Stopped. The current time is not changed.
1367 
1368     If the animation stops by itself after reaching the end (i.e.,
1369     currentLoopTime() == duration() and currentLoop() > loopCount() - 1), the
1370     finished() signal is emitted.
1371 
1372     \sa start(), state()
1373  */
stop()1374 void QAbstractAnimation::stop()
1375 {
1376     Q_D(QAbstractAnimation);
1377 
1378     if (d->state == Stopped)
1379         return;
1380 
1381     d->setState(Stopped);
1382 }
1383 
1384 /*!
1385     Pauses the animation. When the animation is paused, state() returns Paused.
1386     The value of currentTime will remain unchanged until resume() or start()
1387     is called. If you want to continue from the current time, call resume().
1388 
1389     \sa start(), state(), resume()
1390  */
pause()1391 void QAbstractAnimation::pause()
1392 {
1393     Q_D(QAbstractAnimation);
1394     if (d->state == Stopped) {
1395         qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
1396         return;
1397     }
1398 
1399     d->setState(Paused);
1400 }
1401 
1402 /*!
1403     Resumes the animation after it was paused. When the animation is resumed,
1404     it emits the resumed() and stateChanged() signals. The currenttime is not
1405     changed.
1406 
1407     \sa start(), pause(), state()
1408  */
resume()1409 void QAbstractAnimation::resume()
1410 {
1411     Q_D(QAbstractAnimation);
1412     if (d->state != Paused) {
1413         qWarning("QAbstractAnimation::resume: "
1414                  "Cannot resume an animation that is not paused");
1415         return;
1416     }
1417 
1418     d->setState(Running);
1419 }
1420 
1421 /*!
1422     If \a paused is true, the animation is paused.
1423     If \a paused is false, the animation is resumed.
1424 
1425     \sa state(), pause(), resume()
1426 */
setPaused(bool paused)1427 void QAbstractAnimation::setPaused(bool paused)
1428 {
1429     if (paused)
1430         pause();
1431     else
1432         resume();
1433 }
1434 
1435 
1436 /*!
1437     \reimp
1438 */
event(QEvent * event)1439 bool QAbstractAnimation::event(QEvent *event)
1440 {
1441     return QObject::event(event);
1442 }
1443 
1444 /*!
1445     \fn virtual void QAbstractAnimation::updateCurrentTime(int currentTime) = 0;
1446 
1447     This pure virtual function is called every time the animation's
1448     \a currentTime changes.
1449 
1450     \sa updateState()
1451 */
1452 
1453 /*!
1454     This virtual function is called by QAbstractAnimation when the state
1455     of the animation is changed from \a oldState to \a newState.
1456 
1457     \sa start(), stop(), pause(), resume()
1458 */
updateState(QAbstractAnimation::State newState,QAbstractAnimation::State oldState)1459 void QAbstractAnimation::updateState(QAbstractAnimation::State newState,
1460                                      QAbstractAnimation::State oldState)
1461 {
1462     Q_UNUSED(oldState);
1463     Q_UNUSED(newState);
1464 }
1465 
1466 /*!
1467     This virtual function is called by QAbstractAnimation when the direction
1468     of the animation is changed. The \a direction argument is the new direction.
1469 
1470     \sa setDirection(), direction()
1471 */
updateDirection(QAbstractAnimation::Direction direction)1472 void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
1473 {
1474     Q_UNUSED(direction);
1475 }
1476 
1477 
1478 QT_END_NAMESPACE
1479 
1480 #include "moc_qabstractanimation.cpp"
1481 #include "moc_qabstractanimation_p.cpp"
1482