147 #include <QtCore/qdebug.h>
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>
157 #define DEFAULT_TIMER_INTERVAL 16
158 #define PAUSE_TIMER_COARSE_THRESHOLD 2000
219 QUnifiedTimer::QUnifiedTimer() :
221 currentAnimationIdx(0), insideTick(
false), insideRestart(
false), consistentTiming(
false), slowMode(
false),
222 startTimersPending(
false), stopTimerPending(
false), allowNegativeDelta(
false),
223 slowdownFactor(5.0f), profilerCallback(
nullptr),
224 driverStartTime(0), temporalDrift(0)
227 driver = &defaultDriver;
234 if (
create && !unifiedTimer()->hasLocalData()) {
236 unifiedTimer()->setLocalData(inst);
238 inst = unifiedTimer() ? unifiedTimer()->localData() :
nullptr;
257 return driverStartTime + driver->
elapsed();
259 return time.
elapsed() + temporalDrift;
270 qWarning(
"QUnifiedTimer::startAnimationDriver: driver is already running...");
283 qWarning(
"QUnifiedTimer::stopAnimationDriver: driver is not running");
303 timingInterval : totalElapsed - lastTick;
305 if (slowdownFactor > 0)
306 delta =
qRound(delta / slowdownFactor);
311 lastTick = totalElapsed;
318 if (delta != 0 && (allowNegativeDelta || delta > 0)) {
320 if (profilerCallback)
321 profilerCallback(delta);
322 for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.
count(); ++currentAnimationIdx) {
326 currentAnimationIdx = 0;
333 for (
int i = 0;
i < animationTimers.
count(); ++
i)
340 profilerCallback =
cb;
343 void QUnifiedTimer::localRestart()
348 if (!pausedAnimationTimers.
isEmpty() && (animationTimers.
count() + animationTimersToStart.
count() == pausedAnimationTimers.
count())) {
350 int closestTimeToFinish = closestPausedAnimationTimerTimeToFinish();
353 pauseTimer.
start(closestTimeToFinish, timerType,
this);
366 for (
int i = 0;
i < animationTimers.
count(); ++
i)
375 timingInterval = interval;
384 void QUnifiedTimer::startTimers()
386 startTimersPending =
false;
389 animationTimers += animationTimersToStart;
390 animationTimersToStart.
clear();
391 if (!animationTimers.
isEmpty()) {
402 void QUnifiedTimer::stopTimer()
404 stopTimerPending =
false;
405 if (animationTimers.
isEmpty()) {
417 if (consistentTiming) {
418 if (stopTimerPending)
420 if (startTimersPending)
433 if (
timer->isRegistered)
435 timer->isRegistered =
true;
438 inst->animationTimersToStart <<
timer;
439 if (!inst->startTimersPending) {
440 inst->startTimersPending =
true;
452 if (!
timer->isRegistered)
454 timer->isRegistered =
false;
460 if (idx <= inst->currentAnimationIdx)
461 --inst->currentAnimationIdx;
463 if (inst->animationTimers.
isEmpty() && !inst->stopTimerPending) {
464 inst->stopTimerPending =
true;
476 if (!
timer->isRegistered)
479 bool timerWasPaused =
timer->isPaused;
480 timer->isPaused =
true;
481 timer->pauseDuration = duration;
483 inst->pausedAnimationTimers <<
timer;
484 inst->localRestart();
489 if (!
timer->isPaused)
492 timer->isPaused =
false;
495 inst->localRestart();
498 int QUnifiedTimer::closestPausedAnimationTimerTimeToFinish()
500 int closestTimeToFinish = INT_MAX;
502 const int timeToFinish = (*it)->pauseDuration;
503 if (timeToFinish < closestTimeToFinish)
504 closestTimeToFinish = timeToFinish;
506 return closestTimeToFinish;
511 if (driver != &defaultDriver) {
512 qWarning(
"QUnifiedTimer: animation driver already installed...");
521 allowNegativeDelta = driver->
property(
"allowNegativeDelta").
toBool();
529 qWarning(
"QUnifiedTimer: trying to uninstall a driver that is not installed...");
536 driver = &defaultDriver;
537 allowNegativeDelta =
false;
548 return d == driver && driver != &defaultDriver;
551 #if QT_CONFIG(thread)
555 QAnimationTimer::QAnimationTimer() :
557 currentAnimationIdx(0), insideTick(
false),
558 startAnimationPending(
false), stopTimerPending(
false),
559 runningLeafAnimations(0)
566 #if QT_CONFIG(thread)
567 if (
create && !animationTimer()->hasLocalData()) {
569 animationTimer()->setLocalData(inst);
571 inst = animationTimer() ? animationTimer()->localData() :
nullptr;
576 inst = &animationTimer;
590 if (instU && inst && inst->
isPaused)
607 for (currentAnimationIdx = 0; currentAnimationIdx < animations.
count(); ++currentAnimationIdx) {
613 currentAnimationIdx = 0;
626 if (runningLeafAnimations == 0 && !runningPauseAnimations.
isEmpty())
634 void QAnimationTimer::startAnimations()
636 if (!startAnimationPending)
638 startAnimationPending =
false;
644 animations += animationsToStart;
645 animationsToStart.
clear();
650 void QAnimationTimer::stopTimer()
652 stopTimerPending =
false;
653 bool pendingStart = startAnimationPending && animationsToStart.
size() > 0;
654 if (animations.
isEmpty() && !pendingStart) {
665 inst->registerRunningAnimation(
animation);
670 if (!inst->startAnimationPending) {
671 inst->startAnimationPending =
true;
684 inst->unregisterRunningAnimation(
animation);
693 if (idx <= inst->currentAnimationIdx)
694 --inst->currentAnimationIdx;
696 if (inst->animations.
isEmpty() && !inst->stopTimerPending) {
697 inst->stopTimerPending =
true;
715 runningLeafAnimations++;
726 runningLeafAnimations--;
727 Q_ASSERT(runningLeafAnimations >= 0);
730 int QAnimationTimer::closestPauseAnimationTimeToFinish()
732 int closestTimeToFinish = INT_MAX;
742 if (timeToFinish < closestTimeToFinish)
743 closestTimeToFinish = timeToFinish;
745 return closestTimeToFinish;
774 if (
timer &&
timer->canUninstallAnimationDriver(
this))
817 timer->installAnimationDriver(
this);
829 timer->uninstallAnimationDriver(
this);
834 return d_func()->running;
868 return d->running ?
d->timer.elapsed() : 0;
906 void QDefaultAnimationDriver::startTimer()
912 void QDefaultAnimationDriver::stopTimer()
929 int oldCurrentTime = currentTime;
930 int oldCurrentLoop = currentLoop;
936 const int oldTotalCurrentTime = totalCurrentTime;
941 0 : (loopCount == -1 ?
q->duration() :
q->totalDuration());
942 if (totalCurrentTime != oldTotalCurrentTime)
943 totalCurrentTime.notify();
982 q->setCurrentTime(totalCurrentTime);
989 int dura =
q->duration();
991 if (deleteWhenStopped)
994 if (dura == -1 || loopCount < 0
1044 d->group->removeAnimation(
this);
1132 return d->direction;
1138 d->direction.removeBindingUnlessInWrapper();
1143 const int oldCurrentLoop =
d->currentLoop;
1147 d->currentLoop =
d->loopCount - 1;
1156 if (
d->hasRegisteredTimer)
1162 if (
d->hasRegisteredTimer)
1166 if (
d->currentLoop != oldCurrentLoop)
1167 d->currentLoop.notify();
1168 d->direction.notify();
1175 return &
d->direction;
1202 return d->loopCount;
1213 return &
d->loopCount;
1232 return d->currentLoop;
1238 return &
d->currentLoop;
1273 return dura * loopcount;
1285 return d->currentTime;
1308 return d->totalCurrentTime;
1314 return &
d->totalCurrentTime;
1320 msecs = qMax(msecs, 0);
1324 int totalDura = dura <= 0 ? dura : ((
d->loopCount < 0) ? -1 : dura *
d->loopCount);
1325 if (totalDura != -1)
1326 msecs = qMin(totalDura, msecs);
1328 const int oldCurrentTime =
d->totalCurrentTime;
1329 d->totalCurrentTime = msecs;
1332 int oldLoop =
d->currentLoop;
1333 d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
1334 if (
d->currentLoop ==
d->loopCount) {
1336 d->currentTime = qMax(0, dura);
1337 d->currentLoop = qMax(0,
d->loopCount - 1);
1340 d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
1342 d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
1343 if (
d->currentTime == dura)
1344 d->currentLoop =
d->currentLoop - 1;
1349 if (
d->currentLoop != oldLoop)
1350 d->currentLoop.notify();
1356 if (oldCurrentTime !=
d->totalCurrentTime)
1357 d->totalCurrentTime.notify();
1361 if ((
d->direction ==
Forward &&
d->totalCurrentTime == totalDura)
1362 || (
d->direction ==
Backward &&
d->totalCurrentTime == 0)) {
1388 d->deleteWhenStopped =
policy;
1423 qWarning(
"QAbstractAnimation::pause: Cannot pause a stopped animation");
1441 qWarning(
"QAbstractAnimation::resume: "
1442 "Cannot resume an animation that is not paused");
1508 #include "moc_qabstractanimation.cpp"
1509 #include "moc_qabstractanimation_p.cpp"
small capitals from c petite p scientific i
[1]
The QAbstractAnimation class is the base of all animations.
State state
state of the animation.
Direction direction
the direction of the animation when it is in \l Running state.
QBindable< Direction > bindableDirection()
virtual void updateCurrentTime(int currentTime)=0
void start(QAbstractAnimation::DeletionPolicy policy=KeepWhenStopped)
bool event(QEvent *event) override
int loopCount
the loop count of the animation
QAbstractAnimation(QObject *parent=nullptr)
int totalDuration() const
void setLoopCount(int loopCount)
QBindable< int > bindableCurrentLoop() const
int currentLoopTime() const
void setDirection(Direction direction)
int currentLoop
the current loop of the animation
virtual void updateDirection(QAbstractAnimation::Direction direction)
int currentTime
the current time and progress of the animation
void setCurrentTime(int msecs)
virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
QBindable< QAbstractAnimation::State > bindableState() const
QBindable< int > bindableCurrentTime()
void stateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
virtual ~QAbstractAnimation()
QBindable< int > bindableLoopCount()
QAnimationGroup * group() const
int duration
the duration of the animation.
static QAbstractAnimationPrivate * get(QAbstractAnimation *q)
virtual ~QAbstractAnimationPrivate()
QAbstractAnimationTimer is the base class for animation timers.
virtual void restartAnimationTimer()=0
virtual int runningAnimationCount()=0
The QAnimationDriver class is used to exchange the mechanism that drives animations.
virtual qint64 elapsed() const
QAnimationDriver(QObject *parent=nullptr)
The QAnimationGroup class is an abstract base class for groups of animations.
static void unregisterAnimation(QAbstractAnimation *animation)
static void updateAnimationTimer()
void updateAnimationsTime(qint64 delta) override
void restartAnimationTimer() override
static void ensureTimerUpdate()
static void registerAnimation(QAbstractAnimation *animation, bool isTopLevel)
static QAnimationTimer * instance()
void start(int msec, QObject *obj)
int timerId() const noexcept
bool isActive() const noexcept
QBindable is a wrapper class around binding-enabled properties. It allows type-safe operations while ...
QDefaultAnimationDriver(QUnifiedTimer *timer)
void timerEvent(QTimerEvent *e) override
void invalidate() noexcept
qint64 elapsed() const noexcept
bool isValid() const noexcept
The QEvent class is the base class of all event classes. Event objects contain event parameters.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void removeAt(qsizetype i)
bool removeOne(const AT &t)
const_reference at(qsizetype i) const noexcept
const_iterator constBegin() const noexcept
qsizetype count() const noexcept
const_iterator constEnd() const noexcept
The QObject class is the base class of all Qt objects.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
virtual bool event(QEvent *event)
void setParent(QObject *parent)
QVariant property(const char *name) const
The QPointer class is a template class that provides guarded pointers to QObject.
The QScopedValueRollback class resets a variable to its previous value on destruction.
The QThreadStorage class provides per-thread data storage.
The QTimerEvent class contains parameters that describe a timer event.
QUnifiedTimer provides a unified timing mechanism for animations in Qt C++ and QML.
static void stopAnimationTimer(QAbstractAnimationTimer *timer)
void installAnimationDriver(QAnimationDriver *driver)
void setTimingInterval(int interval)
static void startAnimationTimer(QAbstractAnimationTimer *timer)
void startAnimationDriver()
void maybeUpdateAnimationsToCurrentTime()
void registerProfilerCallback(void(*cb)(qint64))
static void resumeAnimationTimer(QAbstractAnimationTimer *timer)
bool canUninstallAnimationDriver(QAnimationDriver *driver)
int runningAnimationCount()
void timerEvent(QTimerEvent *) override
void updateAnimationTimers()
static QUnifiedTimer * instance()
static void pauseAnimationTimer(QAbstractAnimationTimer *timer, int duration)
void stopAnimationDriver()
void uninstallAnimationDriver(QAnimationDriver *driver)
int duration
the duration of the animation
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
const PluginKeyMapConstIterator cend
Q_CORE_EXPORT void beginPropertyUpdateGroup()
Q_CORE_EXPORT void endPropertyUpdateGroup()
#define DEFAULT_TIMER_INTERVAL
QT_BEGIN_NAMESPACE typedef QList< QAbstractAnimationTimer * >::ConstIterator TimerListConstIt
QList< QAbstractAnimation * >::ConstIterator AnimationListConstIt
#define PAUSE_TIMER_COARSE_THRESHOLD
int qRound(qfloat16 d) noexcept
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
GLenum GLenum GLsizei count
GLdouble GLdouble GLdouble GLdouble q
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
QPropertyAnimation * animation
[0]
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent