111#include <QtCore/qdebug.h>
115#include <QtCore/qmath.h>
116#include <QtCore/qcoreevent.h>
117#include <QtCore/qpointer.h>
118#include <QtCore/qscopedvaluerollback.h>
120#define DEFAULT_TIMER_INTERVAL 16
121#define PAUSE_TIMER_COARSE_THRESHOLD 2000
180QUnifiedTimer::QUnifiedTimer() :
182 currentAnimationIdx(0), insideTick(
false), insideRestart(
false), consistentTiming(
false), slowMode(
false),
183 startTimersPending(
false), stopTimerPending(
false), allowNegativeDelta(
false),
184 slowdownFactor(5.0f), profilerCallback(
nullptr),
185 driverStartTime(0), temporalDrift(0)
188 driver = &defaultDriver;
197 static thread_local std::unique_ptr<QUnifiedTimer> unifiedTimer;
198 if (
create && !unifiedTimer) {
200 unifiedTimer.reset(inst);
202 inst = unifiedTimer.get();
221 return driverStartTime + driver->
elapsed();
223 return time.
elapsed() + temporalDrift;
234 qWarning(
"QUnifiedTimer::startAnimationDriver: driver is already running...");
247 qWarning(
"QUnifiedTimer::stopAnimationDriver: driver is not running");
267 timingInterval : totalElapsed - lastTick;
269 if (slowdownFactor > 0)
270 delta =
qRound(delta / slowdownFactor);
275 lastTick = totalElapsed;
282 if (delta != 0 && (allowNegativeDelta || delta > 0)) {
284 if (profilerCallback)
285 profilerCallback(delta);
286 for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.
size(); ++currentAnimationIdx) {
290 currentAnimationIdx = 0;
297 for (
int i = 0;
i < animationTimers.
size(); ++
i)
304 profilerCallback =
cb;
307void QUnifiedTimer::localRestart()
312 if (!pausedAnimationTimers.
isEmpty() && (animationTimers.
size() + animationTimersToStart.
size() == pausedAnimationTimers.
size())) {
314 int closestTimeToFinish = closestPausedAnimationTimerTimeToFinish();
317 pauseTimer.
start(closestTimeToFinish, timerType,
this);
330 for (
int i = 0;
i < animationTimers.
size(); ++
i)
339 timingInterval = interval;
348void QUnifiedTimer::startTimers()
350 startTimersPending =
false;
353 animationTimers += animationTimersToStart;
354 animationTimersToStart.
clear();
355 if (!animationTimers.
isEmpty()) {
366void QUnifiedTimer::stopTimer()
368 stopTimerPending =
false;
369 if (animationTimers.
isEmpty()) {
381 if (consistentTiming) {
382 if (stopTimerPending)
384 if (startTimersPending)
397 if (
timer->isRegistered)
399 timer->isRegistered =
true;
402 inst->animationTimersToStart <<
timer;
403 if (!inst->startTimersPending) {
404 inst->startTimersPending =
true;
416 if (!
timer->isRegistered)
418 timer->isRegistered =
false;
422 inst->animationTimers.
removeAt(idx);
424 if (idx <= inst->currentAnimationIdx)
425 --inst->currentAnimationIdx;
427 if (inst->animationTimers.
isEmpty() && !inst->stopTimerPending) {
428 inst->stopTimerPending =
true;
440 if (!
timer->isRegistered)
443 bool timerWasPaused =
timer->isPaused;
444 timer->isPaused =
true;
445 timer->pauseDuration = duration;
447 inst->pausedAnimationTimers <<
timer;
448 inst->localRestart();
453 if (!
timer->isPaused)
456 timer->isPaused =
false;
459 inst->localRestart();
462int QUnifiedTimer::closestPausedAnimationTimerTimeToFinish()
464 int closestTimeToFinish = INT_MAX;
466 const int timeToFinish = (*it)->pauseDuration;
467 if (timeToFinish < closestTimeToFinish)
468 closestTimeToFinish = timeToFinish;
470 return closestTimeToFinish;
475 if (driver != &defaultDriver) {
476 qWarning(
"QUnifiedTimer: animation driver already installed...");
485 allowNegativeDelta = driver->
property(
"allowNegativeDelta").
toBool();
493 qWarning(
"QUnifiedTimer: trying to uninstall a driver that is not installed...");
500 driver = &defaultDriver;
501 allowNegativeDelta =
false;
512 return d == driver && driver != &defaultDriver;
515QAnimationTimer::QAnimationTimer() :
517 currentAnimationIdx(0), insideTick(
false),
518 startAnimationPending(
false), stopTimerPending(
false),
519 runningLeafAnimations(0)
530 static thread_local std::unique_ptr<QAnimationTimer> animationTimer;
531 if (
create && !animationTimer) {
533 animationTimer.reset(inst);
535 inst = animationTimer.get();
540 inst = &animationTimer;
554 if (instU && inst && inst->
isPaused)
571 for (currentAnimationIdx = 0; currentAnimationIdx < animations.
size(); ++currentAnimationIdx) {
577 currentAnimationIdx = 0;
590 if (runningLeafAnimations == 0 && !runningPauseAnimations.
isEmpty())
598void QAnimationTimer::startAnimations()
600 if (!startAnimationPending)
602 startAnimationPending =
false;
608 animations += animationsToStart;
609 animationsToStart.
clear();
614void QAnimationTimer::stopTimer()
616 stopTimerPending =
false;
617 bool pendingStart = startAnimationPending && animationsToStart.
size() > 0;
618 if (animations.
isEmpty() && !pendingStart) {
629 inst->registerRunningAnimation(
animation);
634 if (!inst->startAnimationPending) {
635 inst->startAnimationPending =
true;
648 inst->unregisterRunningAnimation(
animation);
657 if (idx <= inst->currentAnimationIdx)
658 --inst->currentAnimationIdx;
660 if (inst->animations.
isEmpty() && !inst->stopTimerPending) {
661 inst->stopTimerPending =
true;
679 runningLeafAnimations++;
690 runningLeafAnimations--;
691 Q_ASSERT(runningLeafAnimations >= 0);
694int QAnimationTimer::closestPauseAnimationTimeToFinish()
696 int closestTimeToFinish = INT_MAX;
706 if (timeToFinish < closestTimeToFinish)
707 closestTimeToFinish = timeToFinish;
709 return closestTimeToFinish;
738 if (
timer &&
timer->canUninstallAnimationDriver(
this))
781 timer->installAnimationDriver(
this);
793 timer->uninstallAnimationDriver(
this);
798 return d_func()->running;
832 return d->running ?
d->timer.elapsed() : 0;
873void QDefaultAnimationDriver::startTimer()
879void QDefaultAnimationDriver::stopTimer()
912 int oldCurrentLoop = currentLoop;
918 const int oldTotalCurrentTime = totalCurrentTime;
923 0 : (loopCount == -1 ?
q->duration() :
q->totalDuration());
924 if (totalCurrentTime != oldTotalCurrentTime)
925 totalCurrentTime.notify();
964 q->setCurrentTime(totalCurrentTime);
971 int dura =
q->duration();
973 if (deleteWhenStopped)
976 if (dura == -1 || loopCount < 0
1026 d->group->removeAnimation(
this);
1114 return d->direction;
1120 d->direction.removeBindingUnlessInWrapper();
1125 const int oldCurrentLoop =
d->currentLoop;
1129 d->currentLoop =
d->loopCount - 1;
1138 if (
d->hasRegisteredTimer)
1144 if (
d->hasRegisteredTimer)
1148 if (
d->currentLoop != oldCurrentLoop)
1149 d->currentLoop.notify();
1150 d->direction.notify();
1156 return &
d->direction;
1183 return d->loopCount;
1194 return &
d->loopCount;
1213 return d->currentLoop;
1219 return &
d->currentLoop;
1254 return dura * loopcount;
1266 return d->currentTime;
1289 return d->totalCurrentTime;
1295 return &
d->totalCurrentTime;
1301 msecs =
qMax(msecs, 0);
1305 int totalDura = dura <= 0 ? dura : ((
d->loopCount < 0) ? -1 : dura *
d->loopCount);
1306 if (totalDura != -1)
1307 msecs =
qMin(totalDura, msecs);
1309 const int oldCurrentTime =
d->totalCurrentTime;
1310 d->totalCurrentTime = msecs;
1313 int oldLoop =
d->currentLoop;
1314 d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
1315 if (
d->currentLoop ==
d->loopCount) {
1317 d->currentTime =
qMax(0, dura);
1318 d->currentLoop =
qMax(0,
d->loopCount - 1);
1321 d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
1323 d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
1324 if (
d->currentTime == dura)
1325 d->currentLoop =
d->currentLoop - 1;
1330 if (
d->currentLoop != oldLoop)
1331 d->currentLoop.notify();
1337 if (oldCurrentTime !=
d->totalCurrentTime)
1338 d->totalCurrentTime.notify();
1342 if ((
d->direction ==
Forward &&
d->totalCurrentTime == totalDura)
1343 || (
d->direction ==
Backward &&
d->totalCurrentTime == 0)) {
1369 d->deleteWhenStopped =
policy;
1404 qWarning(
"QAbstractAnimation::pause: Cannot pause a stopped animation");
1422 qWarning(
"QAbstractAnimation::resume: "
1423 "Cannot resume an animation that is not paused");
1489#include "moc_qabstractanimation.cpp"
1490#include "moc_qabstractanimation_p.cpp"
QAbstractAnimationPrivate()
static QAbstractAnimationPrivate * get(QAbstractAnimation *q)
virtual ~QAbstractAnimationPrivate()
virtual void restartAnimationTimer()=0
~QAbstractAnimationTimer() override
QAbstractAnimationTimer()
virtual int runningAnimationCount()=0
State state
state of the animation.
Direction direction
the direction of the animation when it is in \l Running state.
State
This enum describes the state of the animation.
void resume()
Resumes the animation after it was paused.
QBindable< Direction > bindableDirection()
void setPaused(bool)
If paused is true, the animation is paused.
void stop()
Stops the animation.
DeletionPolicy
\value KeepWhenStopped The animation will not be deleted when stopped.
virtual void updateCurrentTime(int currentTime)=0
This pure virtual function is called every time the animation's currentTime changes.
void start(QAbstractAnimation::DeletionPolicy policy=KeepWhenStopped)
Starts the animation.
bool event(QEvent *event) override
\reimp
int loopCount
the loop count of the animation
QAbstractAnimation(QObject *parent=nullptr)
Constructs the QAbstractAnimation base class, and passes parent to QObject's constructor.
int totalDuration() const
Returns the total and effective duration of the animation, including the loop count.
void setLoopCount(int loopCount)
QBindable< int > bindableCurrentLoop() const
int currentLoopTime() const
Returns the current time inside the current loop.
void setDirection(Direction direction)
int currentLoop
the current loop of the animation
virtual void updateDirection(QAbstractAnimation::Direction direction)
This virtual function is called by QAbstractAnimation when the direction of the animation is changed.
int currentTime
the current time and progress of the animation
void setCurrentTime(int msecs)
virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
This virtual function is called by QAbstractAnimation when the state of the animation is changed from...
Direction
This enum describes the direction of the animation when in \l Running state.
QBindable< QAbstractAnimation::State > bindableState() const
QBindable< int > bindableCurrentTime()
void pause()
Pauses the animation.
void stateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
QAbstractAnimation emits this signal whenever the state of the animation has changed from oldState to...
virtual ~QAbstractAnimation()
Stops the animation if it's running, then destroys the QAbstractAnimation.
QBindable< int > bindableLoopCount()
QAnimationGroup * group() const
If this animation is part of a QAnimationGroup, this function returns a pointer to the group; otherwi...
int duration
the duration of the animation.
QAnimationDriverPrivate()
~QAnimationDriverPrivate() override
void install()
Installs this animation driver.
virtual qint64 elapsed() const
Returns the number of milliseconds since the animations was started.
void started()
This signal is emitted by the animation framework to notify the driver that continuous animation has ...
virtual void advance()
Advances the animation.
void advanceAnimation()
Advances the animation.
QAnimationDriver(QObject *parent=nullptr)
void stopped()
This signal is emitted by the animation framework to notify the driver that continuous animation has ...
void uninstall()
Uninstalls this animation driver.
static void unregisterAnimation(QAbstractAnimation *animation)
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()
void start(int msec, QObject *obj)
\obsolete Use chrono overload instead.
int timerId() const noexcept
Returns the timer's ID.
void stop()
Stops the timer.
bool isActive() const noexcept
Returns true if the timer is running and has not been stopped; otherwise returns false.
~QDefaultAnimationDriver() override
QDefaultAnimationDriver(QUnifiedTimer *timer)
The default animation driver just spins the timer...
void timerEvent(QTimerEvent *e) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
void invalidate() noexcept
Marks this QElapsedTimer object as invalid.
qint64 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
void start() noexcept
Starts this timer.
bool isValid() const noexcept
Returns false if the timer has never been started or invalidated by a call to invalidate().
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
const_iterator constEnd() const noexcept
QObject * parent() const
Returns a pointer to the parent object.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
void setParent(QObject *parent)
Makes the object a child of parent.
QVariant property(const char *name) const
Returns the value of the object's name property.
RAII class around Qt::beginPropertyUpdateGroup()/Qt::endPropertyUpdateGroup().
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)
Returns true if d is the currently installed animation driver and is not the default animation driver...
int runningAnimationCount()
void timerEvent(QTimerEvent *) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
void updateAnimationTimers()
~QUnifiedTimer() override
static QUnifiedTimer * instance()
static void pauseAnimationTimer(QAbstractAnimationTimer *timer, int duration)
void stopAnimationDriver()
void uninstallAnimationDriver(QAnimationDriver *driver)
int duration
the duration of the animation
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
QSet< QString >::iterator it
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
const PluginKeyMapConstIterator cend
Combined button and popup list for selecting options.
#define DEFAULT_TIMER_INTERVAL
QT_BEGIN_NAMESPACE typedef QList< QAbstractAnimationTimer * >::ConstIterator TimerListConstIt
QList< QAbstractAnimation * >::ConstIterator AnimationListConstIt
#define PAUSE_TIMER_COARSE_THRESHOLD
static Q_CONSTINIT QBasicAtomicInt running
int qRound(qfloat16 d) noexcept
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
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)
static double elapsed(qint64 after, qint64 before)
static double currentTime()
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent