Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquicktransition.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant reason:default
4
6
13
14#include <private/qquickanimatorjob_p.h>
15
16#include "private/qparallelanimationgroupjob_p.h"
17
19
20/*!
21 \qmltype Transition
22 \nativetype QQuickTransition
23 \inqmlmodule QtQuick
24 \ingroup qtquick-transitions-animations
25 \brief Defines animated transitions that occur on state changes.
26
27 A Transition defines the animations to be applied when a \l State change occurs.
28
29 For example, the following \l Rectangle has two states: the default state, and
30 an added "moved" state. In the "moved state, the rectangle's position changes
31 to (50, 50). The added Transition specifies that when the rectangle
32 changes between the default and the "moved" state, any changes
33 to the \c x and \c y properties should be animated, using an \c Easing.InOutQuad.
34
35 \snippet qml/transition.qml 0
36
37 Notice the example does not require \l{PropertyAnimation::}{to} and
38 \l{PropertyAnimation::}{from} values for the NumberAnimation. As a convenience,
39 these properties are automatically set to the values of \c x and \c y before
40 and after the state change; the \c from values are provided by
41 the current values of \c x and \c y, and the \c to values are provided by
42 the PropertyChanges object. If you wish, you can provide \l{PropertyAnimation::}{to} and
43 \l{PropertyAnimation::}{from} values anyway to override the default values.
44
45 By default, a Transition's animations are applied for any state change in the
46 parent item. The Transition \l {Transition::}{from} and \l {Transition::}{to}
47 values can be set to restrict the animations to only be applied when changing
48 from one particular state to another.
49
50 Top-level animations within a transition are run in parallel. To run them
51 sequentially, define them within a SequentialAnimation:
52
53 \snippet qml/transition-reversible.qml sequential animations
54
55 To define multiple Transitions, specify \l Item::transitions as a list:
56
57 \snippet qml/transitions-list.qml list of transitions
58
59 If multiple Transitions are specified, only a single (best-matching)
60 Transition will be applied for any particular state change. In the
61 example above, if the Rectangle enters a state other than \c "middleRight"
62 or \c "bottomLeft", the third Transition will be carried out, meaning the
63 icon will be moved to the starting point.
64
65 If a state change has a Transition that matches the same property as a
66 \l Behavior, the Transition animation overrides the \l Behavior for that
67 state change.
68
69 \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation#States}{States example}, {Qt Quick States}, {Qt Qml}
70*/
71
72//ParallelAnimationWrapper allows us to do a "callback" when the animation finishes, rather than connecting
73//and disconnecting signals and slots frequently
75{
76public:
78 QQuickTransitionManager *manager;
79
80protected:
81 void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override;
82};
83
85{
86 Q_DECLARE_PUBLIC(QQuickTransition)
87public:
94
97
98 QString fromState;
99 QString toState;
105protected:
106
107 static void append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a);
108 static qsizetype animation_count(QQmlListProperty<QQuickAbstractAnimation> *list);
109 static QQuickAbstractAnimation* animation_at(QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype pos);
110 static void clear_animations(QQmlListProperty<QQuickAbstractAnimation> *list);
111 static void removeLast_animation(QQmlListProperty<QQuickAbstractAnimation> *list);
112 static void replace_animation(
113 QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype pos,
114 QQuickAbstractAnimation *a);
115
117};
118
119void QQuickTransitionPrivate::append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a)
120{
121 QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
122 q->d_func()->animations.append(a);
123 if (a)
124 a->setDisableUserControl();
125}
126
127qsizetype QQuickTransitionPrivate::animation_count(QQmlListProperty<QQuickAbstractAnimation> *list)
128{
129 QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
130 return q->d_func()->animations.size();
131}
132
133QQuickAbstractAnimation* QQuickTransitionPrivate::animation_at(QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype pos)
134{
135 QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
136 return q->d_func()->animations.at(pos);
137}
138
139void QQuickTransitionPrivate::clear_animations(QQmlListProperty<QQuickAbstractAnimation> *list)
140{
141 QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
142 q->d_func()->animations.clear();
143}
144
145void QQuickTransitionPrivate::removeLast_animation(QQmlListProperty<QQuickAbstractAnimation> *list)
146{
147 QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
148 q->d_func()->animations.removeLast();
149}
150
151void QQuickTransitionPrivate::replace_animation(
152 QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype pos, QQuickAbstractAnimation *a)
153{
154 QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
155 QQuickTransitionPrivate *d = q->d_func();
156 if (d->animations.length() <= pos)
157 d->animations.resize(pos + 1, nullptr);
158 d->animations[pos] = a;
159 if (a)
160 a->setDisableUserControl();
161}
162
163void QQuickTransitionInstance::animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
164{
165 if (!m_transition)
166 return;
167
168 QQuickTransitionPrivate *transition = QQuickTransitionPrivate::get(m_transition);
169 transition->animationStateChanged(newState);
170}
171
172void QQuickTransitionPrivate::animationStateChanged(QAbstractAnimationJob::State newState)
173{
174 Q_Q(QQuickTransition);
175
176 if (newState == QAbstractAnimationJob::Running) {
177 runningInstanceCount++;
178 if (runningInstanceCount == 1)
179 emit q->runningChanged();
180 } else if (newState == QAbstractAnimationJob::Stopped) {
181 runningInstanceCount--;
182 if (runningInstanceCount == 0)
183 emit q->runningChanged();
184 }
185}
186
187void ParallelAnimationWrapper::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState)
188{
189 QParallelAnimationGroupJob::updateState(newState, oldState);
190 if (newState == Stopped && (duration() == -1
191 || (direction() == QAbstractAnimationJob::Forward && currentLoopTime() == duration())
192 || (direction() == QAbstractAnimationJob::Backward && currentLoopTime() == 0)))
193 {
194 manager->complete();
195 }
196}
197
198QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransition *transition, QAbstractAnimationJob *anim)
200 , m_anim(anim)
201{
202 anim->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
203}
204
210
212{
213 if (m_anim)
214 m_anim->start();
215}
216
218{
219 if (m_anim)
220 m_anim->stop();
221}
222
224{
225 if (m_anim)
226 m_anim->complete();
227}
228
230{
231 return m_anim && m_anim->state() == QAbstractAnimationJob::Running;
232}
233
234QQuickTransition::QQuickTransition(QObject *parent)
235 : QObject(*(new QQuickTransitionPrivate), parent)
236{
237}
238
239QQuickTransition::~QQuickTransition()
240{
241}
242
243void QQuickTransition::setReversed(bool r)
244{
245 Q_D(QQuickTransition);
246 d->reversed = r;
247}
248
249QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::ActionList &actions,
250 QList<QQmlProperty> &after,
251 QQuickTransitionManager *manager,
252 QObject *defaultTarget)
253{
254 Q_D(QQuickTransition);
255
256 qmlExecuteDeferred(this);
257
258 ParallelAnimationWrapper *group = new ParallelAnimationWrapper();
259 group->manager = manager;
260
261 QQuickAbstractAnimation::TransitionDirection direction = d->reversed ? QQuickAbstractAnimation::Backward : QQuickAbstractAnimation::Forward;
262 int start = d->reversed ? d->animations.size() - 1 : 0;
263 int end = d->reversed ? -1 : d->animations.size();
264
265 for (int i = start; i != end; d->reversed ? --i : ++i) {
266 QQuickAbstractAnimation *anim = d->animations.at(i);
267 if (!anim)
268 continue;
269
270 QAbstractAnimationJob *job = anim->transition(actions, after, direction, defaultTarget);
271 if (!job)
272 continue;
273
274 if (anim->threadingModel() == QQuickAbstractAnimation::RenderThread)
275 job = new QQuickAnimatorProxyJob(job, anim);
276
277 d->reversed ? group->prependAnimation(job) : group->appendAnimation(job);
278 }
279
280 group->setDirection(d->reversed ? QAbstractAnimationJob::Backward : QAbstractAnimationJob::Forward);
281
282 QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(this, group);
283 return wrapper;
284}
285
286/*!
287 \qmlproperty string QtQuick::Transition::from
288 \qmlproperty string QtQuick::Transition::to
289
290 These properties indicate the state changes that trigger the transition.
291
292 The default values for these properties is "*" (that is, any state).
293
294 For example, the following transition has not set the \c to and \c from
295 properties, so the animation is always applied when changing between
296 the two states (i.e. when the mouse is pressed and released).
297
298 \snippet qml/transition-from-to.qml 0
299
300 If the transition was changed to this:
301
302 \snippet qml/transition-from-to-modified.qml modified transition
303
304 The animation would only be applied when changing from the default state
305 to the "brighter" state (i.e. when the mouse is pressed, but not on release).
306
307 Multiple \c to and \c from values can be set by using a comma-separated
308 string.
309
310 \sa reversible
311*/
312QString QQuickTransition::fromState() const
313{
314 Q_D(const QQuickTransition);
315 return d->fromState;
316}
317
318void QQuickTransition::setFromState(const QString &f)
319{
320 Q_D(QQuickTransition);
321 if (f == d->fromState)
322 return;
323
324 d->fromState = f;
325 emit fromChanged();
326}
327
328/*!
329 \qmlproperty bool QtQuick::Transition::reversible
330 This property holds whether the transition should be automatically
331 reversed when the conditions that triggered this transition are reversed.
332
333 The default value is false.
334
335 By default, transitions run in parallel and are applied to all state
336 changes if the \l from and \l to states have not been set. In this
337 situation, the transition is automatically applied when a state change
338 is reversed, and it is not necessary to set this property to reverse
339 the transition.
340
341 However, if a SequentialAnimation is used, or if the \l from or \l to
342 properties have been set, this property will need to be set to reverse
343 a transition when a state change is reverted. For example, the following
344 transition applies a sequential animation when the mouse is pressed,
345 and reverses the sequence of the animation when the mouse is released:
346
347 \snippet qml/transition-reversible.qml 0
348
349 If the transition did not set the \c to and \c reversible values, then
350 on the mouse release, the transition would play the PropertyAnimation
351 before the ColorAnimation instead of reversing the sequence.
352*/
353bool QQuickTransition::reversible() const
354{
355 Q_D(const QQuickTransition);
356 return d->reversible;
357}
358
359void QQuickTransition::setReversible(bool r)
360{
361 Q_D(QQuickTransition);
362 if (r == d->reversible)
363 return;
364
365 d->reversible = r;
366 emit reversibleChanged();
367}
368
369QString QQuickTransition::toState() const
370{
371 Q_D(const QQuickTransition);
372 return d->toState;
373}
374
375void QQuickTransition::setToState(const QString &t)
376{
377 Q_D(QQuickTransition);
378 if (t == d->toState)
379 return;
380
381 d->toState = t;
382 emit toChanged();
383}
384
385/*!
386 \qmlproperty bool QtQuick::Transition::enabled
387
388 This property holds whether the Transition will be run when moving
389 from the \c from state to the \c to state.
390
391 By default a Transition is enabled.
392
393 Note that in some circumstances disabling a Transition may cause an
394 alternative Transition to be used in its place. In the following
395 example, although the first Transition has been set to animate changes
396 from "state1" to "state2", this transition has been disabled by setting
397 \c enabled to \c false, so any such state change will actually be animated
398 by the second Transition instead.
399
400 \qml
401 Item {
402 states: [
403 State { name: "state1" },
404 State { name: "state2" }
405 ]
406 transitions: [
407 Transition { from: "state1"; to: "state2"; enabled: false },
408 Transition {
409 // ...
410 }
411 ]
412 }
413 \endqml
414*/
415
416bool QQuickTransition::enabled() const
417{
418 Q_D(const QQuickTransition);
419 return d->enabled;
420}
421
422void QQuickTransition::setEnabled(bool enabled)
423{
424 Q_D(QQuickTransition);
425 if (d->enabled == enabled)
426 return;
427 d->enabled = enabled;
428 emit enabledChanged();
429}
430
431/*!
432 \qmlproperty bool QtQuick::Transition::running
433 \readonly
434
435 This property holds whether the transition is currently running.
436
437 \note Unlike Animation::running, this property is read only,
438 and can not be used to control the transition.
439*/
440bool QQuickTransition::running() const
441{
442 Q_D(const QQuickTransition);
443 return d->runningInstanceCount;
444}
445
446
447/*!
448 \qmlproperty list<Animation> QtQuick::Transition::animations
449 \qmldefault
450
451 This property holds a list of the animations to be run for this transition.
452
453 \snippet qml/transition-animation.qml 0
454
455 The top-level animations are run in parallel. To run them sequentially,
456 define them within a SequentialAnimation:
457
458 \snippet qml/transition-reversible.qml sequential animations
459*/
460QQmlListProperty<QQuickAbstractAnimation> QQuickTransition::animations()
461{
462 Q_D(QQuickTransition);
463 return QQmlListProperty<QQuickAbstractAnimation>(
464 this, &d->animations,
465 QQuickTransitionPrivate::append_animation,
466 QQuickTransitionPrivate::animation_count,
467 QQuickTransitionPrivate::animation_at,
468 QQuickTransitionPrivate::clear_animations,
469 QQuickTransitionPrivate::replace_animation,
470 QQuickTransitionPrivate::removeLast_animation);
471}
472
473QT_END_NAMESPACE
474
475//#include <qquicktransition.moc>
476
477#include "moc_qquicktransition_p.cpp"
\qmltype Transition \nativetype QQuickTransition \inqmlmodule QtQuick
void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override
QQuickTransitionManager * manager
QQuickTransitionInstance(QQuickTransition *transition, QAbstractAnimationJob *anim)
void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) override
static void replace_animation(QQmlListProperty< QQuickAbstractAnimation > *list, qsizetype pos, QQuickAbstractAnimation *a)
QAbstractAnimationJob::State state
static qsizetype animation_count(QQmlListProperty< QQuickAbstractAnimation > *list)
QList< QPointer< QQuickAbstractAnimation > > animations
static void clear_animations(QQmlListProperty< QQuickAbstractAnimation > *list)
static void append_animation(QQmlListProperty< QQuickAbstractAnimation > *list, QQuickAbstractAnimation *a)
static void removeLast_animation(QQmlListProperty< QQuickAbstractAnimation > *list)
static QQuickAbstractAnimation * animation_at(QQmlListProperty< QQuickAbstractAnimation > *list, qsizetype pos)