1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquicktimeline_p.h"
5
6#include <QtCore/qmath.h>
7#include <QtGui/qpainter.h>
8#include <QtQuick/private/qquickitem_p.h>
9
10QT_BEGIN_NAMESPACE
11
12class QQuickTimelinePrivate : public QObjectPrivate
13{
14 Q_DECLARE_PUBLIC(QQuickTimeline)
15public:
16 QQuickTimelinePrivate() : enabled(false), componentComplete(false)
17 {
18 }
19
20 qreal startFrame = 0;
21 qreal endFrame = 0;
22 qreal currentFrame = 0;
23
24 bool enabled:1;
25 bool componentComplete:1;
26
27protected:
28 void init();
29 void disable();
30
31 static void append_keyframe(QQmlListProperty<QQuickKeyframeGroup> *list, QQuickKeyframeGroup *a);
32 static qsizetype keyframe_count(QQmlListProperty<QQuickKeyframeGroup> *list);
33 static QQuickKeyframeGroup* keyframe_at(QQmlListProperty<QQuickKeyframeGroup> *list, qsizetype pos);
34 static void clear_keyframes(QQmlListProperty<QQuickKeyframeGroup> *list);
35
36 static void append_animation(QQmlListProperty<QQuickTimelineAnimation> *list, QQuickTimelineAnimation *a);
37 static qsizetype animation_count(QQmlListProperty<QQuickTimelineAnimation> *list);
38 static QQuickTimelineAnimation* animation_at(QQmlListProperty<QQuickTimelineAnimation> *list, qsizetype pos);
39 static void clear_animations(QQmlListProperty<QQuickTimelineAnimation> *list);
40
41 QList<QQuickKeyframeGroup *> keyframeGroups;
42 QList<QQuickTimelineAnimation *> animations;
43};
44
45void QQuickTimelinePrivate::init()
46{
47 for (auto keyFrames : keyframeGroups) {
48 keyFrames->init();
49 keyFrames->setProperty(currentFrame);
50 }
51}
52
53void QQuickTimelinePrivate::disable()
54{
55 for (auto keyFrames : keyframeGroups)
56 keyFrames->resetDefaultValue();
57}
58
59void QQuickTimelinePrivate::append_keyframe(QQmlListProperty<QQuickKeyframeGroup> *list, QQuickKeyframeGroup *a)
60{
61 auto q = static_cast<QQuickTimeline *>(list->object);
62 q->d_func()->keyframeGroups.append(t: a);
63}
64
65qsizetype QQuickTimelinePrivate::keyframe_count(QQmlListProperty<QQuickKeyframeGroup> *list)
66{
67 auto q = static_cast<QQuickTimeline *>(list->object);
68 return q->d_func()->keyframeGroups.size();
69}
70
71QQuickKeyframeGroup* QQuickTimelinePrivate::keyframe_at(QQmlListProperty<QQuickKeyframeGroup> *list, qsizetype pos)
72{
73 auto q = static_cast<QQuickTimeline *>(list->object);
74 return q->d_func()->keyframeGroups.at(i: pos);
75}
76
77void QQuickTimelinePrivate::clear_keyframes(QQmlListProperty<QQuickKeyframeGroup> *list)
78{
79 auto q = static_cast<QQuickTimeline *>(list->object);
80 while (q->d_func()->keyframeGroups.size()) {
81 QQuickKeyframeGroup *firstKeyframe = q->d_func()->keyframeGroups.at(i: 0);
82 q->d_func()->keyframeGroups.removeAll(t: firstKeyframe);
83 }
84}
85
86void QQuickTimelinePrivate::append_animation(QQmlListProperty<QQuickTimelineAnimation> *list, QQuickTimelineAnimation *a)
87{
88 auto q = static_cast<QQuickTimeline *>(list->object);
89 a->setTargetObject(q);
90 q->d_func()->animations.append(t: a);
91}
92
93qsizetype QQuickTimelinePrivate::animation_count(QQmlListProperty<QQuickTimelineAnimation> *list)
94{
95 auto q = static_cast<QQuickTimeline *>(list->object);
96 return q->d_func()->animations.size();
97}
98
99QQuickTimelineAnimation* QQuickTimelinePrivate::animation_at(QQmlListProperty<QQuickTimelineAnimation> *list, qsizetype pos)
100{
101 auto q = static_cast<QQuickTimeline *>(list->object);
102 return q->d_func()->animations.at(i: pos);
103}
104
105void QQuickTimelinePrivate::clear_animations(QQmlListProperty<QQuickTimelineAnimation> *list)
106{
107 auto q = static_cast<QQuickTimeline *>(list->object);
108 while (q->d_func()->animations.size()) {
109 QQuickTimelineAnimation *firstAnimation = q->d_func()->animations.at(i: 0);
110 q->d_func()->animations.removeAll(t: firstAnimation);
111 }
112}
113
114/*!
115 \qmltype Timeline
116 \inherits QtObject
117 \instantiates QQuickTimeline
118 \inqmlmodule QtQuick.Timeline
119 \ingroup qtqmltypes
120
121 \brief A timeline.
122
123 Specifies a timeline with a range of keyframes that contain values for the
124 properties of an object. The timeline allows specifying the values of items
125 depending on keyframes and their easing curves.
126
127 A timeline can be either used for animations or to control the behavior of
128 items.
129
130 For example, it is possible to create a progress bar where the current frame
131 reflects the progress.
132*/
133
134/*!
135 \qmlproperty double Timeline::startFrame
136
137 The start of the timeline.
138*/
139
140/*!
141 \qmlproperty double Timeline::endFrame
142
143 The end of the timeline.
144*/
145
146/*!
147 \qmlproperty double Timeline::currentFrame
148
149 The current keyframe on the timeline. The current keyframe can be animated
150 or a binding can be attached to it. Using bindings allows controlling
151 the behavior of components.
152*/
153
154/*!
155 \qmlproperty list Timeline::keyframes
156 \readonly
157
158 This property contains the keyframe groups attached to the timeline.
159 Each keyframe group contains a list of keyframes for a specific item
160 and property.
161*/
162
163/*!
164 \qmlproperty list Timeline::animations
165 \readonly
166
167 A list of animations attached to the timeline.
168*/
169
170/*!
171 \qmlproperty bool Timeline::enabled
172
173 Whether the timeline is enabled.
174
175 When the timeline is disabled, all items will have their regular values.
176 When the timeline is enabled, the values of items are determined by the
177 current frame and the keyframes.
178
179 Only one timeline should be active at a particular time.
180*/
181
182QQuickTimeline::QQuickTimeline(QObject *parent) : QObject(*(new QQuickTimelinePrivate), parent)
183{
184}
185
186QQmlListProperty<QQuickKeyframeGroup> QQuickTimeline::keyframeGroups()
187{
188 Q_D(QQuickTimeline);
189
190 return { this, &d->keyframeGroups, QQuickTimelinePrivate::append_keyframe,
191 QQuickTimelinePrivate::keyframe_count,
192 QQuickTimelinePrivate::keyframe_at,
193 QQuickTimelinePrivate::clear_keyframes };
194}
195
196QQmlListProperty<QQuickTimelineAnimation> QQuickTimeline::animations()
197{
198 Q_D(QQuickTimeline);
199
200 return { this, &d->animations, QQuickTimelinePrivate::append_animation,
201 QQuickTimelinePrivate::animation_count,
202 QQuickTimelinePrivate::animation_at,
203 QQuickTimelinePrivate::clear_animations };
204}
205
206bool QQuickTimeline::enabled() const
207{
208 Q_D(const QQuickTimeline);
209 return d->enabled;
210}
211
212void QQuickTimeline::setEnabled(bool b)
213{
214 Q_D(QQuickTimeline);
215 if (d->enabled == b)
216 return;
217 d->enabled = b;
218
219 if (d->componentComplete) {
220 if (b)
221 init();
222 else
223 reset();
224 }
225
226 emit enabledChanged();
227}
228
229qreal QQuickTimeline::startFrame() const
230{
231 Q_D(const QQuickTimeline);
232 return d->startFrame;
233}
234
235void QQuickTimeline::setStartFrame(qreal frame)
236{
237 Q_D(QQuickTimeline);
238 if (d->startFrame == frame)
239 return;
240 d->startFrame = frame;
241 emit startFrameChanged();
242}
243
244qreal QQuickTimeline::endFrame() const
245{
246 Q_D(const QQuickTimeline);
247 return d->endFrame;
248}
249
250void QQuickTimeline::setEndFrame(qreal frame)
251{
252 Q_D(QQuickTimeline);
253 if (d->endFrame == frame)
254 return;
255 d->endFrame = frame;
256 emit endFrameChanged();
257}
258
259qreal QQuickTimeline::currentFrame() const
260{
261 Q_D(const QQuickTimeline);
262 return d->currentFrame;
263}
264
265void QQuickTimeline::setCurrentFrame(qreal frame)
266{
267 Q_D(QQuickTimeline);
268 if (d->currentFrame == frame)
269 return;
270 d->currentFrame = frame;
271
272 reevaluate();
273
274 emit currentFrameChanged();
275}
276
277void QQuickTimeline::reevaluate()
278{
279 Q_D(QQuickTimeline);
280
281 if (d->componentComplete && d->enabled)
282 for (auto keyFrames : d->keyframeGroups)
283 keyFrames->setProperty(d->currentFrame);
284}
285
286void QQuickTimeline::init()
287{
288 Q_D(QQuickTimeline);
289
290 if (d->componentComplete)
291 d->init();
292}
293
294void QQuickTimeline::reset()
295{
296 Q_D(QQuickTimeline);
297
298 if (d->componentComplete)
299 d->disable();
300}
301
302QList<QQuickTimelineAnimation *> QQuickTimeline::getAnimations() const
303{
304 Q_D(const QQuickTimeline);
305
306 return d->animations;
307}
308
309void QQuickTimeline::classBegin()
310{
311 Q_D(QQuickTimeline);
312 d->componentComplete = false;
313}
314
315void QQuickTimeline::componentComplete()
316{
317 Q_D(QQuickTimeline);
318 d->componentComplete = true;
319
320 if (d->enabled)
321 init();
322}
323
324QT_END_NAMESPACE
325

source code of qtquicktimeline/src/timeline/qquicktimeline.cpp