6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
63
64
65
66
67
68
71
72
73
74
75
76
77
78
79
82
83
84
85
86
87
88
89
92
93
94
95
96
97
98
101
102
103
104
105
106
107
112#include <QtCore/qdebug.h>
116#if defined(Q_OS_WASM)
117#include <QtCore/private/qwasmanimationdriver_p.h>
120#include <QtCore/qmath.h>
121#include <QtCore/qcoreevent.h>
122#include <QtCore/qnumeric.h>
123#include <QtCore/qpointer.h>
124#include <QtCore/qscopedvaluerollback.h>
126#include <QtCore/q26numeric.h>
128#define DEFAULT_TIMER_INTERVAL 16
129#define PAUSE_TIMER_COARSE_THRESHOLD 2000
139
140
141
142int mulSaturating(
int a,
int b)
145 if (qMulOverflow(a, b, &r))
146 return std::numeric_limits<
int>::max();
153
154
155
156
157
158
159
160
161
162
163
164
167
168
169
170
171
172
175
176
177
178
179
180
181
182
185
186
187
188
189
190
193
194
195
196
197
198
199
200
201
202
204QUnifiedTimer::QUnifiedTimer() :
206 currentAnimationIdx(0), insideTick(
false), insideRestart(
false), consistentTiming(
false),
207 startTimersPending(
false), stopTimerPending(
false), allowNegativeDelta(
false),
208 speedModifier(1), profilerCallback(
nullptr),
209 driverStartTime(0), temporalDrift(0)
212 driver = &defaultDriver;
215QUnifiedTimer::~QUnifiedTimer()
218QUnifiedTimer *QUnifiedTimer::instance(
bool create)
221 static thread_local std::unique_ptr<QUnifiedTimer> unifiedTimer;
222 if (create && !unifiedTimer) {
223 inst =
new QUnifiedTimer;
224 unifiedTimer.reset(inst);
226 inst = unifiedTimer.get();
231QUnifiedTimer *QUnifiedTimer::instance()
233 return instance(
true);
236void QUnifiedTimer::maybeUpdateAnimationsToCurrentTime()
238 if (elapsed() - lastTick > 50)
239 updateAnimationTimers();
242qint64 QUnifiedTimer::elapsed()
const
244 if (driver->isRunning())
245 return driverStartTime + driver->elapsed();
246 else if (time.isValid())
247 return time.elapsed() + temporalDrift;
255void QUnifiedTimer::startAnimationDriver()
257 if (driver->isRunning()) {
258 qWarning(
"QUnifiedTimer::startAnimationDriver: driver is already running...");
264 driverStartTime = elapsed();
268void QUnifiedTimer::stopAnimationDriver()
270 if (!driver->isRunning()) {
271 qWarning(
"QUnifiedTimer::stopAnimationDriver: driver is not running");
277 temporalDrift = elapsed() - time.elapsed();
281void QUnifiedTimer::updateAnimationTimers()
287 const qint64 totalElapsed = elapsed();
290 qint64 delta = (consistentTiming && !pauseTimer.isActive()) ?
291 timingInterval : totalElapsed - lastTick;
294 if (speedModifier != 1) {
295 if (speedModifier > 0)
296 delta = qRound(delta * speedModifier);
301 lastTick = totalElapsed;
308 if (delta != 0 && (allowNegativeDelta || delta > 0)) {
309 QScopedValueRollback<
bool> guard(insideTick,
true);
310 if (profilerCallback)
311 profilerCallback(delta);
312 for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.size(); ++currentAnimationIdx) {
313 QAbstractAnimationTimer *animation = animationTimers.at(currentAnimationIdx);
314 animation->updateAnimationsTime(delta);
316 currentAnimationIdx = 0;
320qsizetype QUnifiedTimer::runningAnimationCount()
const
323 for (
const QAbstractAnimationTimer *timer : animationTimers)
324 count += timer->runningAnimationCount();
328void QUnifiedTimer::registerProfilerCallback(
void (*cb)(qint64))
330 profilerCallback = cb;
333void QUnifiedTimer::localRestart()
338 if (!pausedAnimationTimers.isEmpty() && (animationTimers.size() + animationTimersToStart.size() == pausedAnimationTimers.size())) {
340 int closestTimeToFinish = closestPausedAnimationTimerTimeToFinish();
343 pauseTimer.start(closestTimeToFinish, timerType,
this);
344 }
else if (!driver->isRunning()) {
345 if (pauseTimer.isActive())
347 startAnimationDriver();
352void QUnifiedTimer::restart()
355 QScopedValueRollback<
bool> guard(insideRestart,
true);
356 for (
int i = 0; i < animationTimers.size(); ++i)
357 animationTimers.at(i)->restartAnimationTimer();
363void QUnifiedTimer::setTimingInterval(
int interval)
365 timingInterval = interval;
367 if (driver->isRunning() && !pauseTimer.isActive()) {
369 stopAnimationDriver();
370 startAnimationDriver();
374void QUnifiedTimer::startTimers()
376 startTimersPending =
false;
379 animationTimers += animationTimersToStart;
380 animationTimersToStart.clear();
381 if (!animationTimers.isEmpty()) {
382 if (!time.isValid()) {
392void QUnifiedTimer::stopTimer()
394 stopTimerPending =
false;
395 if (animationTimers.isEmpty()) {
396 stopAnimationDriver();
403void QUnifiedTimer::timerEvent(QTimerEvent *event)
407 if (consistentTiming) {
408 if (stopTimerPending)
410 if (startTimersPending)
414 if (event->id() == pauseTimer.id()) {
416 updateAnimationTimers();
421void QUnifiedTimer::startAnimationTimer(QAbstractAnimationTimer *timer)
423 if (timer->isRegistered)
425 timer->isRegistered =
true;
427 QUnifiedTimer *inst = instance(
true);
428 inst->animationTimersToStart << timer;
429 if (!inst->startTimersPending) {
430 inst->startTimersPending =
true;
431 QMetaObject::invokeMethod(inst,
"startTimers", Qt::QueuedConnection);
435void QUnifiedTimer::stopAnimationTimer(QAbstractAnimationTimer *timer)
437 QUnifiedTimer *inst = QUnifiedTimer::instance(
false);
442 if (!timer->isRegistered)
444 timer->isRegistered =
false;
446 int idx = inst->animationTimers.indexOf(timer);
448 inst->animationTimers.removeAt(idx);
450 if (idx <= inst->currentAnimationIdx)
451 --inst->currentAnimationIdx;
453 if (inst->animationTimers.isEmpty() && !inst->stopTimerPending) {
454 inst->stopTimerPending =
true;
455 QMetaObject::invokeMethod(inst,
"stopTimer", Qt::QueuedConnection);
458 inst->animationTimersToStart.removeOne(timer);
463void QUnifiedTimer::pauseAnimationTimer(QAbstractAnimationTimer *timer,
int duration)
465 QUnifiedTimer *inst = QUnifiedTimer::instance();
466 if (!timer->isRegistered)
467 inst->startAnimationTimer(timer);
469 bool timerWasPaused = timer->isPaused;
470 timer->isPaused =
true;
471 timer->pauseDuration = duration;
473 inst->pausedAnimationTimers << timer;
474 inst->localRestart();
477void QUnifiedTimer::resumeAnimationTimer(QAbstractAnimationTimer *timer)
479 if (!timer->isPaused)
482 timer->isPaused =
false;
483 QUnifiedTimer *inst = QUnifiedTimer::instance();
484 inst->pausedAnimationTimers.removeOne(timer);
485 inst->localRestart();
488int QUnifiedTimer::closestPausedAnimationTimerTimeToFinish()
490 int closestTimeToFinish = INT_MAX;
491 for (TimerListConstIt it = pausedAnimationTimers.constBegin(), cend = pausedAnimationTimers.constEnd(); it != cend; ++it) {
492 const int timeToFinish = (*it)->pauseDuration;
493 if (timeToFinish < closestTimeToFinish)
494 closestTimeToFinish = timeToFinish;
496 return closestTimeToFinish;
499void QUnifiedTimer::installAnimationDriver(QAnimationDriver *d)
501 if (driver != &defaultDriver) {
502 qWarning(
"QUnifiedTimer: animation driver already installed...");
506 bool running = driver->isRunning();
508 stopAnimationDriver();
511 allowNegativeDelta = driver->property(
"allowNegativeDelta").toBool();
513 startAnimationDriver();
516void QUnifiedTimer::uninstallAnimationDriver(QAnimationDriver *d)
519 qWarning(
"QUnifiedTimer: trying to uninstall a driver that is not installed...");
523 bool running = driver->isRunning();
525 stopAnimationDriver();
526 driver = &defaultDriver;
527 allowNegativeDelta =
false;
529 startAnimationDriver();
533
534
535
536bool QUnifiedTimer::canUninstallAnimationDriver(QAnimationDriver *d)
538 return d == driver && driver != &defaultDriver;
542 QAbstractAnimationTimer(), lastTick(0),
543 currentAnimationIdx(0), insideTick(
false),
544 startAnimationPending(
false), stopTimerPending(
false),
545 runningLeafAnimations(0)
556 static thread_local std::unique_ptr<QAnimationTimer> animationTimer;
557 if (create && !animationTimer) {
558 inst =
new QAnimationTimer;
559 animationTimer.reset(inst);
561 inst = animationTimer.get();
566 inst = &animationTimer;
579 QUnifiedTimer *instU = QUnifiedTimer::instance(
false);
580 if (instU && inst && inst->isPaused)
581 instU->updateAnimationTimers();
596 QScopedValueRollback<
bool> guard(insideTick,
true);
597 for (currentAnimationIdx = 0; currentAnimationIdx < animations.size(); ++currentAnimationIdx) {
598 QAbstractAnimation *animation = animations.at(currentAnimationIdx);
599 qint64 elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
600 + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
601 animation->setCurrentTime(q26::saturating_cast<
int>(elapsed));
603 currentAnimationIdx = 0;
616 if (runningLeafAnimations == 0 && !runningPauseAnimations.isEmpty())
617 QUnifiedTimer::pauseAnimationTimer(
this, closestPauseAnimationTimeToFinish());
619 QUnifiedTimer::resumeAnimationTimer(
this);
620 else if (!isRegistered)
621 QUnifiedTimer::startAnimationTimer(
this);
626 if (!startAnimationPending)
628 startAnimationPending =
false;
631 QUnifiedTimer::instance()->maybeUpdateAnimationsToCurrentTime();
634 animations += animationsToStart;
635 animationsToStart.clear();
636 if (!animations.isEmpty())
642 stopTimerPending =
false;
643 bool pendingStart = startAnimationPending && animationsToStart.size() > 0;
644 if (animations.isEmpty() && !pendingStart) {
645 QUnifiedTimer::resumeAnimationTimer(
this);
646 QUnifiedTimer::stopAnimationTimer(
this);
655 inst->registerRunningAnimation(animation);
657 Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer);
658 QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer =
true;
659 inst->animationsToStart << animation;
660 if (!inst->startAnimationPending) {
661 inst->startAnimationPending =
true;
662 QMetaObject::invokeMethod(inst,
"startAnimations", Qt::QueuedConnection);
674 inst->unregisterRunningAnimation(animation);
676 if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer)
679 int idx = inst->animations.indexOf(animation);
681 inst->animations.removeAt(idx);
683 if (idx <= inst->currentAnimationIdx)
684 --inst->currentAnimationIdx;
686 if (inst->animations.isEmpty() && !inst->stopTimerPending) {
687 inst->stopTimerPending =
true;
688 QMetaObject::invokeMethod(inst,
"stopTimer", Qt::QueuedConnection);
691 inst->animationsToStart.removeOne(animation);
694 QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer =
false;
697void QAnimationTimer::registerRunningAnimation(QAbstractAnimation *animation)
699 if (QAbstractAnimationPrivate::get(animation)->isGroup)
702 if (QAbstractAnimationPrivate::get(animation)->isPause) {
703 runningPauseAnimations << animation;
705 runningLeafAnimations++;
708void QAnimationTimer::unregisterRunningAnimation(QAbstractAnimation *animation)
710 if (QAbstractAnimationPrivate::get(animation)->isGroup)
713 if (QAbstractAnimationPrivate::get(animation)->isPause)
714 runningPauseAnimations.removeOne(animation);
716 runningLeafAnimations--;
717 Q_ASSERT(runningLeafAnimations >= 0);
722 int closestTimeToFinish = INT_MAX;
723 for (
AnimationListConstIt it = runningPauseAnimations.constBegin(), cend = runningPauseAnimations.constEnd(); it != cend; ++it) {
724 const QAbstractAnimation *animation = *it;
727 if (animation->direction() == QAbstractAnimation::Forward)
728 timeToFinish = animation->duration() - animation->currentLoopTime();
730 timeToFinish = animation->currentLoopTime();
732 if (timeToFinish < closestTimeToFinish)
733 closestTimeToFinish = timeToFinish;
735 return closestTimeToFinish;
739
740
741
742
743
744
745
746
747
748
749
751QAnimationDriver::QAnimationDriver(QObject *parent)
752 : QObject(*(
new QAnimationDriverPrivate), parent)
756QAnimationDriver::QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent)
757 : QObject(dd, parent)
761QAnimationDriver::~QAnimationDriver()
763 QUnifiedTimer *timer = QUnifiedTimer::instance(
false);
764 if (timer && timer->canUninstallAnimationDriver(
this))
769
770
771
772
773
774
776void QAnimationDriver::advanceAnimation()
778 QUnifiedTimer *instance = QUnifiedTimer::instance();
781 instance->updateAnimationTimers();
788
789
790
792void QAnimationDriver::advance()
800
801
802
804void QAnimationDriver::install()
806 QUnifiedTimer *timer = QUnifiedTimer::instance(
true);
807 timer->installAnimationDriver(
this);
813
814
816void QAnimationDriver::uninstall()
818 QUnifiedTimer *timer = QUnifiedTimer::instance(
true);
819 timer->uninstallAnimationDriver(
this);
822bool QAnimationDriver::isRunning()
const
824 return d_func()->running;
828void QAnimationDriver::start()
830 Q_D(QAnimationDriver);
839void QAnimationDriver::stop()
841 Q_D(QAnimationDriver);
850
851
852
853
855qint64 QAnimationDriver::elapsed()
const
857 Q_D(
const QAnimationDriver);
858 return d->running ? d->timer.elapsed() : 0;
862
863
864
865
866
867
868
871
872
873
874
875
876
877
880
881
882
884 : QAnimationDriver(
nullptr), m_unified_timer(timer)
886 connect(
this, &QAnimationDriver::started,
this, &QDefaultAnimationDriver::startTimer);
892 disconnect(
this, &QAnimationDriver::started,
this, &QDefaultAnimationDriver::startTimer);
898 Q_ASSERT(e->id() == m_timer.id());
906 m_timer.start(m_unified_timer->timingInterval, Qt::PreciseTimer,
this);
914QAnimationDriverPrivate::QAnimationDriverPrivate()
917QAnimationDriverPrivate::~QAnimationDriverPrivate()
920QAbstractAnimationTimer::QAbstractAnimationTimer()
923QAbstractAnimationTimer::~QAbstractAnimationTimer()
926QAbstractAnimationPrivate::QAbstractAnimationPrivate()
929QAbstractAnimationPrivate::~QAbstractAnimationPrivate() { }
931void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
933 Q_Q(QAbstractAnimation);
934 const QAbstractAnimation::State oldState = state.valueBypassingBindings();
935 if (oldState == newState)
941 int oldCurrentTime = currentTime;
942 int oldCurrentLoop = currentLoop;
943 QAbstractAnimation::Direction oldDirection = direction;
946 if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running)
947 && oldState == QAbstractAnimation::Stopped) {
948 const int oldTotalCurrentTime = totalCurrentTime;
952 totalCurrentTime = currentTime = (direction == QAbstractAnimation::Forward) ?
953 0 : (loopCount == -1 ? q->duration() : q->totalDuration());
954 if (totalCurrentTime != oldTotalCurrentTime)
955 totalCurrentTime.notify();
958 state.setValueBypassingBindings(newState);
959 QPointer<QAbstractAnimation> guard(q);
963 bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped;
964 if (oldState == QAbstractAnimation::Running) {
965 if (newState == QAbstractAnimation::Paused && hasRegisteredTimer)
966 QAnimationTimer::ensureTimerUpdate();
968 QAnimationTimer::unregisterAnimation(q);
969 }
else if (newState == QAbstractAnimation::Running) {
970 QAnimationTimer::registerAnimation(q, isTopLevel);
973 q->updateState(newState, oldState);
975 if (!guard || newState != state.valueBypassingBindings())
980 emit q->stateChanged(newState, oldState);
982 if (!guard || newState != state.valueBypassingBindings())
986 case QAbstractAnimation::Paused:
988 case QAbstractAnimation::Running:
992 if (oldState == QAbstractAnimation::Stopped) {
995 QAnimationTimer::ensureTimerUpdate();
996 q->setCurrentTime(totalCurrentTime);
1001 case QAbstractAnimation::Stopped:
1003 int dura = q->duration();
1005 if (deleteWhenStopped)
1008 if (dura == -1 || loopCount < 0
1009 || (oldDirection == QAbstractAnimation::Forward
1010 && qint64(oldCurrentTime) * (oldCurrentLoop + 1) == qint64(dura) * loopCount)
1011 || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
1019
1020
1021
1022
1023
1024QAbstractAnimation::QAbstractAnimation(QObject *parent)
1025 : QObject(*
new QAbstractAnimationPrivate,
nullptr)
1032
1033
1034QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
1035 : QObject(dd,
nullptr)
1042
1043
1044
1045
1046QAbstractAnimation::~QAbstractAnimation()
1048 Q_D(QAbstractAnimation);
1050 if (d->state != Stopped) {
1051 QAbstractAnimation::State oldState = d->state;
1054 emit stateChanged(d->state, oldState);
1055 if (oldState == QAbstractAnimation::Running)
1056 QAnimationTimer::unregisterAnimation(
this);
1059 d->group->removeAnimation(
this);
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075QAbstractAnimation::State QAbstractAnimation::state()
const
1077 Q_D(
const QAbstractAnimation);
1081QBindable<QAbstractAnimation::State> QAbstractAnimation::bindableState()
const
1083 Q_D(
const QAbstractAnimation);
1088
1089
1090
1091
1092
1093QAnimationGroup *QAbstractAnimation::group()
const
1095 Q_D(
const QAbstractAnimation);
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144QAbstractAnimation::Direction QAbstractAnimation::direction()
const
1146 Q_D(
const QAbstractAnimation);
1147 return d->direction;
1149void QAbstractAnimation::setDirection(Direction direction)
1151 Q_D(QAbstractAnimation);
1152 if (d->direction == direction) {
1153 d->direction.removeBindingUnlessInWrapper();
1157 const QScopedPropertyUpdateGroup guard;
1158 const int oldCurrentLoop = d->currentLoop;
1159 if (state() == Stopped) {
1160 if (direction == Backward) {
1161 d->currentTime = duration();
1162 d->currentLoop = d->loopCount - 1;
1171 if (d->hasRegisteredTimer)
1172 QAnimationTimer::ensureTimerUpdate();
1174 d->direction = direction;
1175 updateDirection(direction);
1177 if (d->hasRegisteredTimer)
1179 QAnimationTimer::updateAnimationTimer();
1181 if (d->currentLoop != oldCurrentLoop)
1182 d->currentLoop.notify();
1183 d->direction.notify();
1186QBindable<QAbstractAnimation::Direction> QAbstractAnimation::bindableDirection()
1188 Q_D(QAbstractAnimation);
1189 return &d->direction;
1193
1194
1195
1196
1197
1198
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213int QAbstractAnimation::loopCount()
const
1215 Q_D(
const QAbstractAnimation);
1216 return d->loopCount;
1218void QAbstractAnimation::setLoopCount(
int loopCount)
1220 Q_D(QAbstractAnimation);
1221 d->loopCount = loopCount;
1224QBindable<
int> QAbstractAnimation::bindableLoopCount()
1226 Q_D(QAbstractAnimation);
1227 return &d->loopCount;
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243int QAbstractAnimation::currentLoop()
const
1245 Q_D(
const QAbstractAnimation);
1246 return d->currentLoop;
1249QBindable<
int> QAbstractAnimation::bindableCurrentLoop()
const
1251 Q_D(
const QAbstractAnimation);
1252 return &d->currentLoop;
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283int QAbstractAnimation::totalDuration()
const
1285 int dura = duration();
1288 int loopcount = loopCount();
1291 return mulSaturating(dura, loopcount);
1295
1296
1297
1298
1300int QAbstractAnimation::currentLoopTime()
const
1302 Q_D(
const QAbstractAnimation);
1303 return d->currentTime;
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323int QAbstractAnimation::currentTime()
const
1325 Q_D(
const QAbstractAnimation);
1326 return d->totalCurrentTime;
1329QBindable<
int> QAbstractAnimation::bindableCurrentTime()
1331 Q_D(QAbstractAnimation);
1332 return &d->totalCurrentTime;
1335void QAbstractAnimation::setCurrentTime(
int msecs)
1337 Q_D(QAbstractAnimation);
1338 msecs = qMax(msecs, 0);
1341 const int dura = duration();
1342 const int totalLoopCount = d->loopCount;
1343 const int totalDura = dura <= 0
1344 ? dura : ((totalLoopCount < 0) ? -1 : mulSaturating(dura, totalLoopCount));
1345 if (totalDura != -1)
1346 msecs = qMin(totalDura, msecs);
1348 d->totalCurrentTime.removeBindingUnlessInWrapper();
1350 const int oldCurrentTime = d->totalCurrentTime.valueBypassingBindings();
1351 d->totalCurrentTime.setValueBypassingBindings(msecs);
1353 QAbstractAnimation::Direction currentDirection = d->direction;
1356 const int oldLoop = d->currentLoop.valueBypassingBindings();
1357 int newCurrentLoop = (dura <= 0) ? 0 : (msecs / dura);
1358 if (newCurrentLoop == totalLoopCount) {
1360 d->currentTime = qMax(0, dura);
1361 newCurrentLoop = qMax(0, totalLoopCount - 1);
1363 if (currentDirection == Forward) {
1364 d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
1366 d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
1367 if (d->currentTime == dura)
1368 newCurrentLoop = newCurrentLoop - 1;
1371 d->currentLoop.setValueBypassingBindings(newCurrentLoop);
1374 updateCurrentTime(d->currentTime);
1377 newCurrentLoop = d->currentLoop.valueBypassingBindings();
1378 currentDirection = d->direction;
1379 const int newTotalCurrentTime = d->totalCurrentTime.valueBypassingBindings();
1381 if (newCurrentLoop != oldLoop)
1382 d->currentLoop.notify();
1385
1386
1387
1388 if (oldCurrentTime != newTotalCurrentTime)
1389 d->totalCurrentTime.notify();
1393 if ((currentDirection == Forward && newTotalCurrentTime == totalDura)
1394 || (currentDirection == Backward && newTotalCurrentTime == 0)) {
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415void QAbstractAnimation::start(DeletionPolicy policy)
1417 Q_D(QAbstractAnimation);
1418 if (d->state.valueBypassingBindings() == Running)
1420 d->deleteWhenStopped = policy;
1421 d->setState(Running);
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434void QAbstractAnimation::stop()
1436 Q_D(QAbstractAnimation);
1438 if (d->state.valueBypassingBindings() == Stopped)
1441 d->setState(Stopped);
1445
1446
1447
1448
1449
1450
1451void QAbstractAnimation::pause()
1453 Q_D(QAbstractAnimation);
1454 if (d->state.valueBypassingBindings() == Stopped) {
1455 qWarning(
"QAbstractAnimation::pause: Cannot pause a stopped animation");
1459 d->setState(Paused);
1463
1464
1465
1466
1467
1468void QAbstractAnimation::resume()
1470 Q_D(QAbstractAnimation);
1471 if (d->state.valueBypassingBindings() != Paused) {
1472 qWarning(
"QAbstractAnimation::resume: "
1473 "Cannot resume an animation that is not paused");
1477 d->setState(Running);
1481
1482
1483
1484
1485
1486void QAbstractAnimation::setPaused(
bool paused)
1496
1497
1498bool QAbstractAnimation::event(QEvent *event)
1500 return QObject::event(event);
1504
1505
1506
1507
1508
1509
1510
1513
1514
1515
1516
1517
1518void QAbstractAnimation::updateState(QAbstractAnimation::State newState,
1519 QAbstractAnimation::State oldState)
1526
1527
1528
1529
1530
1531void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
1533 Q_UNUSED(direction);
1539#include "moc_qabstractanimation.cpp"
1540#include "moc_qabstractanimation_p.cpp"
static void unregisterAnimation(QAbstractAnimation *animation)
static QAnimationTimer * instance(bool create)
static void updateAnimationTimer()
void updateAnimationsTime(qint64 delta) override
~QAnimationTimer() override
void restartAnimationTimer() override
static void ensureTimerUpdate()
static void registerAnimation(QAbstractAnimation *animation, bool isTopLevel)
static QAnimationTimer * instance()
~QDefaultAnimationDriver() override
void timerEvent(QTimerEvent *e) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
Combined button and popup list for selecting options.
QList< QAbstractAnimation * >::ConstIterator AnimationListConstIt
#define DEFAULT_TIMER_INTERVAL
QT_BEGIN_NAMESPACE typedef QList< QAbstractAnimationTimer * >::ConstIterator TimerListConstIt
#define PAUSE_TIMER_COARSE_THRESHOLD