Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qtimeline.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qtimeline.h"
5
6#include <private/qproperty_p.h>
7#include <private/qobject_p.h>
8#include <QtCore/qcoreevent.h>
9#include <QtCore/qmath.h>
10#include <QtCore/qelapsedtimer.h>
11
13
15{
16 Q_DECLARE_PUBLIC(QTimeLine)
17public:
21
22 int startTime = 0;
23 void setDuration(int duration) { q_func()->setDuration(duration); }
26 int startFrame = 0;
27 int endFrame = 0;
28 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, updateInterval, 1000 / 25)
31
32 void setCurrentTimeForwardToQ(int time) { q_func()->setCurrentTime(time); }
35 int timerId = 0;
36
37 void setDirection(QTimeLine::Direction direction) { q_func()->setDirection(direction); }
42 {
43 Q_Q(QTimeLine);
44 if (newState != state)
45 emit q->stateChanged(state = newState, QTimeLine::QPrivateSignal());
46 }
47
48 void setCurrentTime(int msecs);
49};
50
55{
56 Q_Q(QTimeLine);
57 currentTime.removeBindingUnlessInWrapper();
58 auto previousCurrentTime = currentTime.value();
59
60 qreal lastValue = q->currentValue();
61 int lastFrame = q->currentFrame();
62
63 // Determine if we are looping.
64 int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
65 int loopCountNow = elapsed / duration;
66
67 bool looping = (loopCountNow != currentLoopCount);
68#ifdef QTIMELINE_DEBUG
69 qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCountNow"
70 << loopCountNow << "currentLoopCount" << currentLoopCount << "looping" << looping;
71#endif
72 if (looping)
73 currentLoopCount = loopCountNow;
74
75 // Normalize msecs to be between 0 and duration, inclusive.
76 currentTime.setValueBypassingBindings(elapsed % duration);
77 if (direction.value() == QTimeLine::Backward)
78 currentTime.setValueBypassingBindings(duration - currentTime);
79
80 // Check if we have reached the end of loopcount.
81 bool finished = false;
82 if (loopCount && currentLoopCount >= loopCount) {
83 finished = true;
84 currentTime.setValueBypassingBindings((direction == QTimeLine::Backward) ? 0 : duration);
85 currentLoopCount = loopCount - 1;
86 }
87
88 int currentFrame = q->frameForTime(currentTime);
89#ifdef QTIMELINE_DEBUG
90 qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime" << currentTime << currentFrame;
91#endif
92 if (!qFuzzyCompare(lastValue, q->currentValue()))
93 emit q->valueChanged(q->currentValue(), QTimeLine::QPrivateSignal());
94 if (lastFrame != currentFrame) {
95 const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame);
96 if (looping && !finished && transitionframe != currentFrame) {
97#ifdef QTIMELINE_DEBUG
98 qDebug("QTimeLinePrivate::setCurrentTime: transitionframe");
99#endif
100 emit q->frameChanged(transitionframe, QTimeLine::QPrivateSignal());
101 }
102#ifdef QTIMELINE_DEBUG
103 else {
104 QByteArray reason;
105 if (!looping)
106 reason += " not looping";
107 if (finished) {
108 if (!reason.isEmpty())
109 reason += " and";
110 reason += " finished";
111 }
112 if (transitionframe == currentFrame) {
113 if (!reason.isEmpty())
114 reason += " and";
115 reason += " transitionframe is equal to currentFrame: " + QByteArray::number(currentFrame);
116 }
117 qDebug("QTimeLinePrivate::setCurrentTime: not transitionframe because %s", reason.constData());
118 }
119#endif
120 emit q->frameChanged(currentFrame, QTimeLine::QPrivateSignal());
121 }
122 if (finished && state == QTimeLine::Running) {
123 q->stop();
124 emit q->finished(QTimeLine::QPrivateSignal());
125 }
126 if (currentTime.value() != previousCurrentTime)
127 currentTime.notify();
128}
130{
131 Q_D(QTimeLine);
132 return &d->currentTime;
133}
134
263{
265}
266
271{
272 Q_D(QTimeLine);
273
274 if (d->state == Running)
275 stop();
276}
277
284{
285 Q_D(const QTimeLine);
286 return d->state;
287}
288
298{
299 Q_D(const QTimeLine);
300 return d->loopCount;
301}
302
304{
305 Q_D(QTimeLine);
306 d->loopCount = count;
307}
308
310{
311 Q_D(QTimeLine);
312 return &d->loopCount;
313}
314
330{
331 Q_D(const QTimeLine);
332 return d->direction;
333}
335{
336 Q_D(QTimeLine);
337 auto previousDirection = d->direction.value();
338 d->direction.setValue(direction);
339 d->startTime = d->currentTime;
340 d->timer.start();
341 if (previousDirection != d->direction.value())
342 d->direction.notify();
343}
344
346{
347 Q_D(QTimeLine);
348 return &d->direction;
349}
350
364{
365 Q_D(const QTimeLine);
366 return d->duration;
367}
368void QTimeLine::setDuration(int duration)
369{
370 Q_D(QTimeLine);
371 if (duration <= 0) {
372 qWarning("QTimeLine::setDuration: cannot set duration <= 0");
373 return;
374 }
375 if (duration == d->duration) {
376 d->duration.removeBindingUnlessInWrapper();
377 return;
378 }
379 d->duration.setValue(duration);
380 d->duration.notify();
381}
382
384{
385 Q_D(QTimeLine);
386 return &d->duration;
387}
388
396{
397 Q_D(const QTimeLine);
398 return d->startFrame;
399}
400
408{
409 Q_D(QTimeLine);
410 d->startFrame = frame;
411}
412
420{
421 Q_D(const QTimeLine);
422 return d->endFrame;
423}
424
432{
433 Q_D(QTimeLine);
434 d->endFrame = frame;
435}
436
448void QTimeLine::setFrameRange(int startFrame, int endFrame)
449{
450 Q_D(QTimeLine);
451 d->startFrame = startFrame;
452 d->endFrame = endFrame;
453}
454
467{
468 Q_D(const QTimeLine);
469 return d->updateInterval;
470}
472{
473 Q_D(QTimeLine);
474 d->updateInterval = interval;
475}
477{
478 Q_D(QTimeLine);
479 return &d->updateInterval;
480}
481
494{
495 Q_D(const QTimeLine);
496 return d->easingCurve;
497}
498
500{
501 Q_D(QTimeLine);
502 d->easingCurve = curve;
503}
504
506{
507 Q_D(QTimeLine);
508 return &d->easingCurve;
509}
510
527{
528 Q_D(const QTimeLine);
529 return d->currentTime;
530}
532{
533 Q_D(QTimeLine);
534 d->startTime = 0;
535 d->currentLoopCount = 0;
536 d->timer.restart();
537 d->setCurrentTime(msec);
538}
539
546{
547 Q_D(const QTimeLine);
548 return frameForTime(d->currentTime);
549}
550
557{
558 Q_D(const QTimeLine);
559 return valueForTime(d->currentTime);
560}
561
569int QTimeLine::frameForTime(int msec) const
570{
571 Q_D(const QTimeLine);
572 if (d->direction == Forward)
573 return d->startFrame + int((d->endFrame - d->startFrame) * valueForTime(msec));
574 return d->startFrame + qCeil((d->endFrame - d->startFrame) * valueForTime(msec));
575}
576
588{
589 Q_D(const QTimeLine);
590 msec = qBound(0, msec, d->duration.value());
591
592 qreal value = msec / qreal(d->duration.value());
593 return d->easingCurve.value().valueForProgress(value);
594}
595
610{
611 Q_D(QTimeLine);
612 if (d->timerId) {
613 qWarning("QTimeLine::start: already running");
614 return;
615 }
616 int curTime = 0;
617 if (d->direction == Backward)
618 curTime = d->duration;
619 d->timerId = startTimer(d->updateInterval);
620 d->startTime = curTime;
621 d->currentLoopCount = 0;
622 d->timer.start();
623 d->setState(Running);
624 d->setCurrentTime(curTime);
625}
626
638{
639 Q_D(QTimeLine);
640 if (d->timerId) {
641 qWarning("QTimeLine::resume: already running");
642 return;
643 }
644 d->timerId = startTimer(d->updateInterval);
645 d->startTime = d->currentTime;
646 d->timer.start();
647 d->setState(Running);
648}
649
656{
657 Q_D(QTimeLine);
658 if (d->timerId)
659 killTimer(d->timerId);
660 d->setState(NotRunning);
661 d->timerId = 0;
662}
663
672void QTimeLine::setPaused(bool paused)
673{
674 Q_D(QTimeLine);
675 if (d->state == NotRunning) {
676 qWarning("QTimeLine::setPaused: Not running");
677 return;
678 }
679 if (paused && d->state != Paused) {
680 d->startTime = d->currentTime;
681 killTimer(d->timerId);
682 d->timerId = 0;
683 d->setState(Paused);
684 } else if (!paused && d->state == Paused) {
685 // Same as resume()
686 d->timerId = startTimer(d->updateInterval);
687 d->startTime = d->currentTime;
688 d->timer.start();
689 d->setState(Running);
690 }
691}
692
702{
703 Q_D(QTimeLine);
704 setDirection(d->direction == Forward ? Backward : Forward);
705}
706
711{
712 Q_D(QTimeLine);
713 if (event->timerId() != d->timerId) {
714 event->ignore();
715 return;
716 }
717 event->accept();
718
719 if (d->direction == Forward) {
720 d->setCurrentTime(d->startTime + d->timer.elapsed());
721 } else {
722 d->setCurrentTime(d->startTime - d->timer.elapsed());
723 }
724}
725
727
728#include "moc_qtimeline.cpp"
\inmodule QtCore
Definition qproperty.h:809
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qobject.h:90
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
Definition qobject.cpp:1792
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1872
void setCurrentTimeForwardToQ(int time)
Definition qtimeline.cpp:32
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, duration, &QTimeLinePrivate::setDuration, 1000) int startFrame=0
void setDirection(QTimeLine::Direction direction)
Definition qtimeline.cpp:37
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, QEasingCurve, easingCurve, QEasingCurve::InOutSine) int startTime=0
void setCurrentTime(int msecs)
Definition qtimeline.cpp:54
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, currentTime, &QTimeLinePrivate::setCurrentTimeForwardToQ, 0) int timerId=0
void setDuration(int duration)
Definition qtimeline.cpp:23
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, QTimeLine::Direction, direction, &QTimeLinePrivate::setDirection, QTimeLine::Forward) QTimeLine void setState(QTimeLine::State newState)
Definition qtimeline.cpp:41
QElapsedTimer timer
Definition qtimeline.cpp:18
\inmodule QtCore
Definition qtimeline.h:19
int currentTime
the current time of the time line.
Definition qtimeline.h:24
int loopCount
the number of times the timeline should loop before it's finished.
Definition qtimeline.h:26
void timerEvent(QTimerEvent *event) override
\reimp
int currentFrame() const
Returns the frame corresponding to the current time.
QTimeLine(int duration=1000, QObject *parent=nullptr)
Constructs a timeline with a duration of duration milliseconds.
int startFrame() const
Returns the start frame, which is the frame corresponding to the start of the timeline (i....
qreal currentValue() const
Returns the value corresponding to the current time.
State state() const
Returns the state of the timeline.
void setPaused(bool paused)
If paused is true, the timeline is paused, causing QTimeLine to enter Paused state.
int duration
the total duration of the timeline in milliseconds.
Definition qtimeline.h:21
QBindable< int > bindableCurrentTime()
int frameForTime(int msec) const
Returns the frame corresponding to the time msec.
void setEasingCurve(const QEasingCurve &curve)
int endFrame() const
Returns the end frame, which is the frame corresponding to the end of the timeline (i....
void setUpdateInterval(int interval)
QBindable< QEasingCurve > bindableEasingCurve()
int updateInterval
the time in milliseconds between each time QTimeLine updates its current time.
Definition qtimeline.h:23
QBindable< int > bindableLoopCount()
virtual qreal valueForTime(int msec) const
Returns the timeline value for the time msec.
QBindable< int > bindableDuration()
void start()
Starts the timeline.
void setLoopCount(int count)
void setDirection(Direction direction)
void setStartFrame(int frame)
Sets the start frame, which is the frame corresponding to the start of the timeline (i....
Direction direction
the direction of the timeline when QTimeLine is in \l Running state.
Definition qtimeline.h:25
QBindable< int > bindableUpdateInterval()
State
This enum describes the state of the timeline.
Definition qtimeline.h:30
void setFrameRange(int startFrame, int endFrame)
Sets the timeline's frame counter to start at startFrame, and end and endFrame.
void setCurrentTime(int msec)
QBindable< Direction > bindableDirection()
QEasingCurve easingCurve
Definition qtimeline.h:28
void setDuration(int duration)
void stop()
Stops the timeline, causing QTimeLine to enter NotRunning state.
void toggleDirection()
Toggles the direction of the timeline.
Direction
This enum describes the direction of the timeline when in \l Running state.
Definition qtimeline.h:35
void setEndFrame(int frame)
Sets the end frame, which is the frame corresponding to the end of the timeline (i....
virtual ~QTimeLine()
Destroys the timeline.
void resume()
Resumes the timeline from the current time.
\inmodule QtCore
Definition qcoreevent.h:359
direction
else opt state
[0]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
qint64 startTime
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
int qCeil(T v)
Definition qmath.h:36
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLenum GLenum GLsizei count
struct _cl_event * event
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(...)
Definition qproperty.h:1264
#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(...)
static double elapsed(qint64 after, qint64 before)
#define emit
double qreal
Definition qtypes.h:92
static double currentTime()
QFrame frame
[0]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent