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
4#include "qquickanimation_p.h"
5#include "qquickanimation_p_p.h"
6
7#include "qquickanimatorjob_p.h"
8
9#include <private/qquickstatechangescript_p.h>
10#include <private/qqmlcontext_p.h>
11
12#include <qqmlpropertyvaluesource.h>
13#include <qqml.h>
14#include <qqmlinfo.h>
15#include <qqmlexpression.h>
16#include <private/qqmlstringconverters_p.h>
17#include <private/qqmlglobal_p.h>
18#include <private/qqmlmetatype_p.h>
19#include <private/qqmlvaluetype_p.h>
20#include <private/qqmlproperty_p.h>
21#include <private/qqmlengine_p.h>
22
23#include <qvariant.h>
24#include <qcolor.h>
25#include <qfile.h>
26#include "private/qparallelanimationgroupjob_p.h"
27#include "private/qsequentialanimationgroupjob_p.h"
28#include <QtCore/qset.h>
29#include <QtCore/qrect.h>
30#include <QtCore/qpoint.h>
31#include <QtCore/qsize.h>
32#include <QtCore/qmath.h>
33
34QT_BEGIN_NAMESPACE
35
36/*!
37 \qmltype Animation
38 \instantiates QQuickAbstractAnimation
39 \inqmlmodule QtQuick
40 \ingroup qtquick-transitions-animations
41 \brief Is the base of all QML animations.
42
43 The Animation type cannot be used directly in a QML file. It exists
44 to provide a set of common properties and methods, available across all the
45 other animation types that inherit from it. Attempting to use the Animation
46 type directly will result in an error.
47*/
48
49QQuickAbstractAnimation::QQuickAbstractAnimation(QObject *parent)
50: QObject(*(new QQuickAbstractAnimationPrivate), parent)
51{
52}
53
54QQuickAbstractAnimation::~QQuickAbstractAnimation()
55{
56 Q_D(QQuickAbstractAnimation);
57 if (d->group)
58 setGroup(nullptr); //remove from group
59 delete d->animationInstance;
60}
61
62QQuickAbstractAnimation::QQuickAbstractAnimation(QQuickAbstractAnimationPrivate &dd, QObject *parent)
63: QObject(dd, parent)
64{
65}
66
67QAbstractAnimationJob* QQuickAbstractAnimation::qtAnimation()
68{
69 Q_D(QQuickAbstractAnimation);
70 return d->animationInstance;
71}
72
73/*!
74 \qmlproperty bool QtQuick::Animation::running
75 This property holds whether the animation is currently running.
76
77 The \c running property can be set to declaratively control whether or not
78 an animation is running. The following example will animate a rectangle
79 whenever the \l MouseArea is pressed.
80
81 \code
82 Rectangle {
83 width: 100; height: 100
84 NumberAnimation on x {
85 running: myMouse.pressed
86 from: 0; to: 100
87 }
88 MouseArea { id: myMouse }
89 }
90 \endcode
91
92 Likewise, the \c running property can be read to determine if the animation
93 is running. In the following example the Text item will indicate whether
94 or not the animation is running.
95
96 \code
97 NumberAnimation { id: myAnimation }
98 Text { text: myAnimation.running ? "Animation is running" : "Animation is not running" }
99 \endcode
100
101 Animations can also be started and stopped imperatively from JavaScript
102 using the \c start() and \c stop() methods.
103
104 By default, animations are not running. Though, when the animations are assigned to properties,
105 as property value sources using the \e on syntax, they are set to running by default.
106*/
107bool QQuickAbstractAnimation::isRunning() const
108{
109 Q_D(const QQuickAbstractAnimation);
110 return d->running;
111}
112
113// the behavior calls this function
114void QQuickAbstractAnimation::notifyRunningChanged(bool running)
115{
116 Q_D(QQuickAbstractAnimation);
117 if (d->disableUserControl && d->running != running) {
118 d->running = running;
119 emit runningChanged(running);
120 }
121}
122
123//commence is called to start an animation when it is used as a
124//simple animation, and not as part of a transition
125void QQuickAbstractAnimationPrivate::commence()
126{
127 Q_Q(QQuickAbstractAnimation);
128
129 QQuickStateActions actions;
130 QQmlProperties properties;
131
132 auto *newInstance = q->transition(actions, modified&: properties, direction: QQuickAbstractAnimation::Forward);
133 Q_ASSERT(newInstance != animationInstance);
134 delete animationInstance;
135 animationInstance = newInstance;
136
137 if (animationInstance) {
138 if (q->threadingModel() == QQuickAbstractAnimation::RenderThread)
139 animationInstance = new QQuickAnimatorProxyJob(animationInstance, q);
140 animationInstance->addAnimationChangeListener(listener: this,
141 QAbstractAnimationJob::Completion | QAbstractAnimationJob::CurrentLoop);
142 emit q->started();
143 animationInstance->start();
144 }
145}
146
147QQmlProperty QQuickAbstractAnimationPrivate::createProperty(QObject *obj, const QString &str, QObject *infoObj, QString *errorMessage)
148{
149 QQmlProperty prop(obj, str, qmlContext(infoObj));
150 if (!prop.isValid()) {
151 const QString message = QQuickAbstractAnimation::tr(s: "Cannot animate non-existent property \"%1\"").arg(a: str);
152 if (errorMessage)
153 *errorMessage = message;
154 else
155 qmlWarning(me: infoObj) << message;
156 return QQmlProperty();
157 } else if (!prop.isWritable()) {
158 const QString message = QQuickAbstractAnimation::tr(s: "Cannot animate read-only property \"%1\"").arg(a: str);
159 if (errorMessage)
160 *errorMessage = message;
161 else
162 qmlWarning(me: infoObj) << message;
163 return QQmlProperty();
164 }
165 return prop;
166}
167
168void QQuickAbstractAnimationPrivate::animationGroupDirty()
169{
170 Q_ASSERT(group != nullptr);
171 if (!componentComplete)
172 return;
173
174 auto *animGroupPriv = static_cast<QQuickAnimationGroupPrivate *>(QQuickAnimationGroupPrivate::get(o: group));
175 if (animGroupPriv->running && !animGroupPriv->animationDirty) {
176 animGroupPriv->animationDirty = true;
177
178 if (animGroupPriv->animationInstance && group->currentTime() == 0) {
179 // restart if the animation didn't proceed yet.
180 animGroupPriv->restartFromCurrentLoop();
181 }
182 }
183
184 // check the animationGroup is one of another animationGroup members
185 if (animGroupPriv->group)
186 animGroupPriv->animationGroupDirty();
187}
188
189/*!
190 \qmlsignal QtQuick::Animation::started()
191
192 This signal is emitted when the animation begins.
193
194 It is only triggered for top-level, standalone animations. It will not be
195 triggered for animations in a Behavior or Transition, or animations
196 that are part of an animation group.
197*/
198
199/*!
200 \qmlsignal QtQuick::Animation::stopped()
201
202 This signal is emitted when the animation ends.
203
204 The animation may have been stopped manually, or may have run to completion.
205
206 It is only triggered for top-level, standalone animations. It will not be
207 triggered for animations in a Behavior or Transition, or animations
208 that are part of an animation group.
209
210 If \l alwaysRunToEnd is true, this signal will not be emitted until the animation
211 has completed its current iteration.
212*/
213
214/*!
215 \qmlsignal QtQuick::Animation::finished()
216 \since 5.12
217
218 This signal is emitted when the animation has finished naturally.
219
220 It is not emitted when \l running is set to \c false, nor for animations whose
221 \l loops property is set to \c Animation.Infinite.
222
223 In addition, it is only emitted for top-level, standalone animations. It
224 will not be emitted for animations in a Behavior or Transition, or
225 animations that are part of an animation group.
226
227 If \l alwaysRunToEnd is true, this signal will not be emitted until the
228 animation has completed its current iteration.
229
230 \sa stopped(), started(), running
231*/
232
233void QQuickAbstractAnimation::setRunning(bool r)
234{
235 Q_D(QQuickAbstractAnimation);
236 if (!d->componentComplete) {
237 d->running = r;
238 if (r == false)
239 d->avoidPropertyValueSourceStart = true;
240 else if (!d->needsDeferredSetRunning)
241 d->needsDeferredSetRunning = true;
242 return;
243 }
244
245 if (d->running == r)
246 return;
247
248 if (d->group || d->disableUserControl) {
249 qmlWarning(me: this) << "setRunning() cannot be used on non-root animation nodes.";
250 return;
251 }
252
253 d->running = r;
254 if (d->running) {
255 bool supressStart = false;
256 if (d->alwaysRunToEnd && d->loopCount != 1
257 && d->animationInstance && d->animationInstance->isRunning()) {
258 //we've restarted before the final loop finished; restore proper loop count
259 if (d->loopCount == -1)
260 d->animationInstance->setLoopCount(d->loopCount);
261 else
262 d->animationInstance->setLoopCount(d->animationInstance->currentLoop() + d->loopCount);
263 supressStart = true; //we want the animation to continue, rather than restart
264 }
265 if (!supressStart)
266 d->commence();
267 } else {
268 if (d->paused) {
269 d->paused = false; //reset paused state to false when stopped
270 emit pausedChanged(d->paused);
271 }
272
273 if (d->animationInstance) {
274 if (d->alwaysRunToEnd) {
275 if (d->loopCount != 1)
276 d->animationInstance->setLoopCount(d->animationInstance->currentLoop()+1); //finish the current loop
277 } else {
278 d->animationInstance->stop();
279 emit stopped();
280 }
281 }
282 }
283
284
285 if (r == d->running) {
286 // This might happen if we start an animation with 0 duration: This will result in that
287 // commence() will emit started(), and then when it starts it will call setCurrentTime(0),
288 // (which is both start and end time of the animation), so it will also end up calling
289 // setRunning(false) (recursively) and stop the animation.
290 // Therefore, the state of d->running will in that case be different than r if we are back in
291 // the root stack frame of the recursive calls to setRunning()
292 emit runningChanged(d->running);
293 }
294}
295
296/*!
297 \qmlproperty bool QtQuick::Animation::paused
298 This property holds whether the animation is currently paused.
299
300 The \c paused property can be set to declaratively control whether or not
301 an animation is paused.
302
303 Animations can also be paused and resumed imperatively from JavaScript
304 using the \c pause() and \c resume() methods.
305
306 By default, animations are not paused.
307*/
308bool QQuickAbstractAnimation::isPaused() const
309{
310 Q_D(const QQuickAbstractAnimation);
311 Q_ASSERT((d->paused && d->running) || !d->paused);
312 return d->paused;
313}
314
315void QQuickAbstractAnimation::setPaused(bool p)
316{
317 Q_D(QQuickAbstractAnimation);
318 if (d->paused == p)
319 return;
320
321 if (!d->running) {
322 qmlWarning(me: this) << "setPaused() cannot be used when animation isn't running.";
323 return;
324 }
325
326 if (d->group || d->disableUserControl) {
327 qmlWarning(me: this) << "setPaused() cannot be used on non-root animation nodes.";
328 return;
329 }
330
331 d->paused = p;
332
333 if (!d->componentComplete || !d->animationInstance)
334 return;
335
336 if (d->paused)
337 d->animationInstance->pause();
338 else
339 d->animationInstance->resume();
340
341 emit pausedChanged(d->paused);
342}
343
344void QQuickAbstractAnimation::classBegin()
345{
346 Q_D(QQuickAbstractAnimation);
347 d->componentComplete = false;
348}
349
350void QQuickAbstractAnimation::componentComplete()
351{
352 Q_D(QQuickAbstractAnimation);
353 d->componentComplete = true;
354 if (d->needsDeferredSetRunning) {
355 if (d->running) {
356 d->running = false;
357 setRunning(true);
358 }
359 if (d->paused) {
360 d->paused = false;
361 setPaused(true);
362 }
363 }
364}
365
366/*!
367 \qmlproperty bool QtQuick::Animation::alwaysRunToEnd
368 This property holds whether the animation should run to completion when it is stopped.
369
370 If this true the animation will complete its current iteration when it
371 is stopped - either by setting the \c running property to false, or by
372 calling the \c stop() method. The \c complete() method is not effected
373 by this value.
374
375 This behavior is most useful when the \c loops property is set, as the
376 animation will finish playing normally but not restart.
377
378 By default, the alwaysRunToEnd property is not set.
379
380 \note alwaysRunToEnd has no effect on animations in a Transition.
381*/
382bool QQuickAbstractAnimation::alwaysRunToEnd() const
383{
384 Q_D(const QQuickAbstractAnimation);
385 return d->alwaysRunToEnd;
386}
387
388void QQuickAbstractAnimation::setAlwaysRunToEnd(bool f)
389{
390 Q_D(QQuickAbstractAnimation);
391 if (d->alwaysRunToEnd == f)
392 return;
393
394 d->alwaysRunToEnd = f;
395 emit alwaysRunToEndChanged(f);
396}
397
398/*!
399 \qmlproperty int QtQuick::Animation::loops
400 This property holds the number of times the animation should play.
401
402 By default, \c loops is 1: the animation will play through once and then stop.
403
404 If set to Animation.Infinite, the animation will continuously repeat until it is explicitly
405 stopped - either by setting the \c running property to false, or by calling
406 the \c stop() method.
407
408 In the following example, the rectangle will spin indefinitely.
409
410 \code
411 Rectangle {
412 width: 100; height: 100; color: "green"
413 RotationAnimation on rotation {
414 loops: Animation.Infinite
415 from: 0
416 to: 360
417 }
418 }
419 \endcode
420*/
421int QQuickAbstractAnimation::loops() const
422{
423 Q_D(const QQuickAbstractAnimation);
424 return d->loopCount;
425}
426
427void QQuickAbstractAnimation::setLoops(int loops)
428{
429 Q_D(QQuickAbstractAnimation);
430 if (loops < 0)
431 loops = -1;
432
433 if (loops == d->loopCount)
434 return;
435
436 d->loopCount = loops;
437 emit loopCountChanged(loops);
438}
439
440int QQuickAbstractAnimation::duration() const
441{
442 Q_D(const QQuickAbstractAnimation);
443 return d->animationInstance ? d->animationInstance->duration() : 0;
444}
445
446int QQuickAbstractAnimation::currentTime()
447{
448 Q_D(QQuickAbstractAnimation);
449 return d->animationInstance ? d->animationInstance->currentLoopTime() : 0;
450}
451
452void QQuickAbstractAnimation::setCurrentTime(int time)
453{
454 Q_D(QQuickAbstractAnimation);
455 if (d->animationInstance)
456 d->animationInstance->setCurrentTime(time);
457 //TODO save value for start?
458}
459
460QQuickAnimationGroup *QQuickAbstractAnimation::group() const
461{
462 Q_D(const QQuickAbstractAnimation);
463 return d->group;
464}
465
466void QQuickAbstractAnimation::setGroup(QQuickAnimationGroup *g, int index)
467{
468 Q_D(QQuickAbstractAnimation);
469 if (d->group == g)
470 return;
471 if (d->group)
472 d->group->d_func()->animations.removeAll(t: this);
473
474 d->group = g;
475
476 if (d->group && !d->group->d_func()->animations.contains(t: this)) {
477 if (index >= 0)
478 d->group->d_func()->animations.insert(i: index, t: this);
479 else
480 d->group->d_func()->animations.append(t: this);
481 }
482}
483
484/*!
485 \qmlmethod QtQuick::Animation::start()
486 \brief Starts the animation
487
488 If the animation is already running, calling this method has no effect. The
489 \c running property will be true following a call to \c start().
490*/
491void QQuickAbstractAnimation::start()
492{
493 setRunning(true);
494}
495
496/*!
497 \qmlmethod QtQuick::Animation::pause()
498 \brief Pauses the animation
499
500 If the animation is already paused or not \c running, calling this method has no effect.
501 The \c paused property will be true following a call to \c pause().
502*/
503void QQuickAbstractAnimation::pause()
504{
505 setPaused(true);
506}
507
508/*!
509 \qmlmethod QtQuick::Animation::resume()
510 \brief Resumes a paused animation
511
512 If the animation is not paused or not \c running, calling this method has no effect.
513 The \c paused property will be false following a call to \c resume().
514*/
515void QQuickAbstractAnimation::resume()
516{
517 setPaused(false);
518}
519
520/*!
521 \qmlmethod QtQuick::Animation::stop()
522 \brief Stops the animation
523
524 If the animation is not running, calling this method has no effect. Both the
525 \c running and \c paused properties will be false following a call to \c stop().
526
527 Normally \c stop() stops the animation immediately, and the animation has
528 no further influence on property values. In this example animation
529 \code
530 Rectangle {
531 NumberAnimation on x { from: 0; to: 100; duration: 500 }
532 }
533 \endcode
534 was stopped at time 250ms, the \c x property will have a value of 50.
535
536 However, if the \c alwaysRunToEnd property is set, the animation will
537 continue running until it completes and then stop. The \c running property
538 will still become false immediately.
539*/
540void QQuickAbstractAnimation::stop()
541{
542 setRunning(false);
543}
544
545/*!
546 \qmlmethod QtQuick::Animation::restart()
547 \brief Restarts the animation
548
549 This is a convenience method, and is equivalent to calling \c stop() and
550 then \c start().
551*/
552void QQuickAbstractAnimation::restart()
553{
554 stop();
555 start();
556}
557
558/*!
559 \qmlmethod QtQuick::Animation::complete()
560 \brief Stops the animation, jumping to the final property values
561
562 If the animation is not running, calling this method has no effect. The
563 \c running property will be false following a call to \c complete().
564
565 Unlike \c stop(), \c complete() immediately fast-forwards the animation to
566 its end. In the following example,
567 \code
568 Rectangle {
569 NumberAnimation on x { from: 0; to: 100; duration: 500 }
570 }
571 \endcode
572 calling \c stop() at time 250ms will result in the \c x property having
573 a value of 50, while calling \c complete() will set the \c x property to
574 100, exactly as though the animation had played the whole way through.
575*/
576void QQuickAbstractAnimation::complete()
577{
578 Q_D(QQuickAbstractAnimation);
579 if (isRunning() && d->animationInstance) {
580 d->animationInstance->setCurrentTime(d->animationInstance->duration());
581 }
582}
583
584void QQuickAbstractAnimation::setTarget(const QQmlProperty &p)
585{
586 Q_D(QQuickAbstractAnimation);
587 d->defaultProperty = p;
588
589 if (!d->avoidPropertyValueSourceStart)
590 setRunning(true);
591}
592
593/*
594 we rely on setTarget only being called when used as a value source
595 so this function allows us to do the same thing as setTarget without
596 that assumption
597*/
598void QQuickAbstractAnimation::setDefaultTarget(const QQmlProperty &p)
599{
600 Q_D(QQuickAbstractAnimation);
601 d->defaultProperty = p;
602}
603
604/*
605 don't allow start/stop/pause/resume to be manually invoked,
606 because something else (like a Behavior) already has control
607 over the animation.
608*/
609void QQuickAbstractAnimation::setDisableUserControl()
610{
611 Q_D(QQuickAbstractAnimation);
612 d->disableUserControl = true;
613}
614
615void QQuickAbstractAnimation::setEnableUserControl()
616{
617 Q_D(QQuickAbstractAnimation);
618 d->disableUserControl = false;
619
620}
621
622bool QQuickAbstractAnimation::userControlDisabled() const
623{
624 Q_D(const QQuickAbstractAnimation);
625 return d->disableUserControl;
626}
627
628QAbstractAnimationJob* QQuickAbstractAnimation::initInstance(QAbstractAnimationJob *animation)
629{
630 Q_D(QQuickAbstractAnimation);
631 animation->setLoopCount(d->loopCount);
632 return animation;
633}
634
635QAbstractAnimationJob* QQuickAbstractAnimation::transition(QQuickStateActions &actions,
636 QQmlProperties &modified,
637 TransitionDirection direction,
638 QObject *defaultTarget)
639{
640 Q_UNUSED(actions);
641 Q_UNUSED(modified);
642 Q_UNUSED(direction);
643 Q_UNUSED(defaultTarget);
644 return nullptr;
645}
646
647void QQuickAbstractAnimationPrivate::animationFinished(QAbstractAnimationJob*)
648{
649 Q_Q(QQuickAbstractAnimation);
650 q->setRunning(false);
651 if (alwaysRunToEnd) {
652 emit q->stopped();
653 //restore the proper loopCount for the next run
654 if (loopCount != 1)
655 animationInstance->setLoopCount(loopCount);
656 }
657 emit q->finished();
658}
659
660QQuickAbstractAnimation::ThreadingModel QQuickAbstractAnimation::threadingModel() const
661{
662 return GuiThread;
663}
664
665/*!
666 \qmltype PauseAnimation
667 \instantiates QQuickPauseAnimation
668 \inqmlmodule QtQuick
669 \ingroup qtquick-transitions-animations
670 \inherits Animation
671 \brief Provides a pause for an animation.
672
673 When used in a SequentialAnimation, PauseAnimation is a step when
674 nothing happens, for a specified duration.
675
676 A 500ms animation sequence, with a 100ms pause between two animations:
677 \code
678 SequentialAnimation {
679 NumberAnimation { ... duration: 200 }
680 PauseAnimation { duration: 100 }
681 NumberAnimation { ... duration: 200 }
682 }
683 \endcode
684
685 \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
686*/
687QQuickPauseAnimation::QQuickPauseAnimation(QObject *parent)
688: QQuickAbstractAnimation(*(new QQuickPauseAnimationPrivate), parent)
689{
690}
691
692QQuickPauseAnimation::~QQuickPauseAnimation()
693{
694}
695
696/*!
697 \qmlproperty int QtQuick::PauseAnimation::duration
698 This property holds the duration of the pause in milliseconds
699
700 The default value is 250.
701*/
702int QQuickPauseAnimation::duration() const
703{
704 Q_D(const QQuickPauseAnimation);
705 return d->duration;
706}
707
708void QQuickPauseAnimation::setDuration(int duration)
709{
710 if (duration < 0) {
711 qmlWarning(me: this) << tr(s: "Cannot set a duration of < 0");
712 return;
713 }
714
715 Q_D(QQuickPauseAnimation);
716 if (d->duration == duration)
717 return;
718 d->duration = duration;
719 emit durationChanged(duration);
720 if (d->group)
721 d->animationGroupDirty();
722}
723
724QAbstractAnimationJob* QQuickPauseAnimation::transition(QQuickStateActions &actions,
725 QQmlProperties &modified,
726 TransitionDirection direction,
727 QObject *defaultTarget)
728{
729 Q_D(QQuickPauseAnimation);
730 Q_UNUSED(actions);
731 Q_UNUSED(modified);
732 Q_UNUSED(direction);
733 Q_UNUSED(defaultTarget);
734
735 return initInstance(animation: new QPauseAnimationJob(d->duration));
736}
737
738/*!
739 \qmltype ColorAnimation
740 \instantiates QQuickColorAnimation
741 \inqmlmodule QtQuick
742 \ingroup qtquick-animation-properties
743 \inherits PropertyAnimation
744 \brief Animates changes in color values.
745
746 ColorAnimation is a specialized PropertyAnimation that defines an
747 animation to be applied when a color value changes.
748
749 Here is a ColorAnimation applied to the \c color property of a \l Rectangle
750 as a property value source. It animates the \c color property's value from
751 its current value to a value of "red", over 1000 milliseconds:
752
753 \snippet qml/coloranimation.qml 0
754
755 Like any other animation type, a ColorAnimation can be applied in a
756 number of ways, including transitions, behaviors and property value
757 sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
758 variety of methods for creating animations.
759
760 For convenience, when a ColorAnimation is used in a \l Transition, it will
761 animate any \c color properties that have been modified during the state
762 change. If a \l{PropertyAnimation::}{property} or
763 \l{PropertyAnimation::}{properties} are explicitly set for the animation,
764 then those are used instead.
765
766 \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
767*/
768QQuickColorAnimation::QQuickColorAnimation(QObject *parent)
769: QQuickPropertyAnimation(parent)
770{
771 Q_D(QQuickPropertyAnimation);
772 d->interpolatorType = QMetaType::QColor;
773 d->defaultToInterpolatorType = true;
774 d->interpolator = QVariantAnimationPrivate::getInterpolator(interpolationType: d->interpolatorType);
775}
776
777QQuickColorAnimation::~QQuickColorAnimation()
778{
779}
780
781/*!
782 \qmlproperty color QtQuick::ColorAnimation::from
783 This property holds the color value at which the animation should begin.
784
785 For example, the following animation is not applied until a color value
786 has reached "#c0c0c0":
787
788 \qml
789 Item {
790 states: [
791 // States are defined here...
792 ]
793
794 transitions: Transition {
795 ColorAnimation { from: "#c0c0c0"; duration: 2000 }
796 }
797 }
798 \endqml
799
800 If the ColorAnimation is defined within a \l Transition or \l Behavior,
801 this value defaults to the value defined in the starting state of the
802 \l Transition, or the current value of the property at the moment the
803 \l Behavior is triggered.
804
805 \sa {Animation and Transitions in Qt Quick}
806*/
807QColor QQuickColorAnimation::from() const
808{
809 Q_D(const QQuickPropertyAnimation);
810 return d->from.value<QColor>();
811}
812
813void QQuickColorAnimation::setFrom(const QColor &f)
814{
815 QQuickPropertyAnimation::setFrom(f);
816}
817
818/*!
819 \qmlproperty color QtQuick::ColorAnimation::to
820
821 This property holds the color value at which the animation should end.
822
823 If the ColorAnimation is defined within a \l Transition or \l Behavior,
824 this value defaults to the value defined in the end state of the
825 \l Transition, or the value of the property change that triggered the
826 \l Behavior.
827
828 \sa {Animation and Transitions in Qt Quick}
829*/
830QColor QQuickColorAnimation::to() const
831{
832 Q_D(const QQuickPropertyAnimation);
833 return d->to.value<QColor>();
834}
835
836void QQuickColorAnimation::setTo(const QColor &t)
837{
838 QQuickPropertyAnimation::setTo(t);
839}
840
841QActionAnimation::QActionAnimation()
842 : QAbstractAnimationJob(), animAction(nullptr)
843{
844}
845
846QActionAnimation::QActionAnimation(QAbstractAnimationAction *action)
847 : QAbstractAnimationJob(), animAction(action)
848{
849}
850
851QActionAnimation::~QActionAnimation()
852{
853 delete animAction;
854}
855
856int QActionAnimation::duration() const
857{
858 return 0;
859}
860
861void QActionAnimation::setAnimAction(QAbstractAnimationAction *action)
862{
863 if (isRunning())
864 stop();
865 animAction = action;
866}
867
868void QActionAnimation::updateCurrentTime(int)
869{
870}
871
872void QActionAnimation::updateState(State newState, State oldState)
873{
874 Q_UNUSED(oldState);
875
876 if (newState == Running) {
877 if (animAction) {
878 animAction->doAction();
879 }
880 }
881}
882
883void QActionAnimation::debugAnimation(QDebug d) const
884{
885 d << "ActionAnimation(" << Qt::hex << (const void *) this << Qt::dec << ")";
886
887 if (animAction) {
888 int indentLevel = 1;
889 const QAbstractAnimationJob *job = this;
890 while ((job = job->group()))
891 ++indentLevel;
892 animAction->debugAction(d, indentLevel);
893 }
894}
895
896/*!
897 \qmltype ScriptAction
898 \instantiates QQuickScriptAction
899 \inqmlmodule QtQuick
900 \ingroup qtquick-transitions-animations
901 \inherits Animation
902 \brief Defines scripts to be run during an animation.
903
904 ScriptAction can be used to run a script at a specific point in an animation.
905
906 \qml
907 SequentialAnimation {
908 NumberAnimation {
909 // ...
910 }
911 ScriptAction { script: doSomething(); }
912 NumberAnimation {
913 // ...
914 }
915 }
916 \endqml
917
918 When used as part of a Transition, you can also target a specific
919 StateChangeScript to run using the \c scriptName property.
920
921 \snippet qml/states/statechangescript.qml state and transition
922
923 \sa StateChangeScript
924*/
925QQuickScriptAction::QQuickScriptAction(QObject *parent)
926 :QQuickAbstractAnimation(*(new QQuickScriptActionPrivate), parent)
927{
928}
929
930QQuickScriptAction::~QQuickScriptAction()
931{
932}
933
934QQuickScriptActionPrivate::QQuickScriptActionPrivate()
935 : QQuickAbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false){}
936
937/*!
938 \qmlproperty script QtQuick::ScriptAction::script
939 This property holds the script to run.
940*/
941QQmlScriptString QQuickScriptAction::script() const
942{
943 Q_D(const QQuickScriptAction);
944 return d->script;
945}
946
947void QQuickScriptAction::setScript(const QQmlScriptString &script)
948{
949 Q_D(QQuickScriptAction);
950 d->script = script;
951}
952
953/*!
954 \qmlproperty string QtQuick::ScriptAction::scriptName
955 This property holds the name of the StateChangeScript to run.
956
957 This property is only valid when ScriptAction is used as part of a transition.
958 If both script and scriptName are set, scriptName will be used.
959
960 \note When using scriptName in a reversible transition, the script will only
961 be run when the transition is being run forwards.
962*/
963QString QQuickScriptAction::stateChangeScriptName() const
964{
965 Q_D(const QQuickScriptAction);
966 return d->name;
967}
968
969void QQuickScriptAction::setStateChangeScriptName(const QString &name)
970{
971 Q_D(QQuickScriptAction);
972 d->name = name;
973}
974
975QAbstractAnimationAction* QQuickScriptActionPrivate::createAction()
976{
977 return new Proxy(this);
978}
979
980void QQuickScriptActionPrivate::debugAction(QDebug d, int indentLevel) const
981{
982 QQmlScriptString scriptStr = hasRunScriptScript ? runScriptScript : script;
983
984 if (!scriptStr.isEmpty()) {
985 QQmlExpression expr(scriptStr);
986
987 QByteArray ind(indentLevel, u' ');
988 QString exprStr = expr.expression();
989 int endOfFirstLine = exprStr.indexOf(c: u'\n');
990 d << "\n" << ind.constData() << QStringView{exprStr}.left(n: endOfFirstLine);
991 if (endOfFirstLine != -1 && endOfFirstLine < exprStr.size())
992 d << "...";
993 }
994}
995
996void QQuickScriptActionPrivate::execute()
997{
998 Q_Q(QQuickScriptAction);
999 if (hasRunScriptScript && reversing)
1000 return;
1001
1002 QQmlScriptString scriptStr = hasRunScriptScript ? runScriptScript : script;
1003
1004 if (!scriptStr.isEmpty()) {
1005 QQmlExpression expr(scriptStr);
1006 expr.evaluate();
1007 if (expr.hasError())
1008 qmlWarning(me: q) << expr.error();
1009 }
1010}
1011
1012QAbstractAnimationJob* QQuickScriptAction::transition(QQuickStateActions &actions,
1013 QQmlProperties &modified,
1014 TransitionDirection direction,
1015 QObject *defaultTarget)
1016{
1017 Q_D(QQuickScriptAction);
1018 Q_UNUSED(modified);
1019 Q_UNUSED(defaultTarget);
1020
1021 d->hasRunScriptScript = false;
1022 d->reversing = (direction == Backward);
1023 if (!d->name.isEmpty()) {
1024 for (int ii = 0; ii < actions.size(); ++ii) {
1025 QQuickStateAction &action = actions[ii];
1026
1027 if (action.event && action.event->type() == QQuickStateActionEvent::Script
1028 && static_cast<QQuickStateChangeScript*>(action.event)->name() == d->name) {
1029 d->runScriptScript = static_cast<QQuickStateChangeScript*>(action.event)->script();
1030 d->hasRunScriptScript = true;
1031 action.actionDone = true;
1032 break; //only match one (names should be unique)
1033 }
1034 }
1035 }
1036 return initInstance(animation: new QActionAnimation(d->createAction()));
1037}
1038
1039/*!
1040 \qmltype PropertyAction
1041 \instantiates QQuickPropertyAction
1042 \inqmlmodule QtQuick
1043 \ingroup qtquick-transitions-animations
1044 \inherits Animation
1045 \brief Specifies immediate property changes during animation.
1046
1047 PropertyAction is used to specify an immediate property change during an
1048 animation. The property change is not animated.
1049
1050 It is useful for setting non-animated property values during an animation.
1051
1052 For example, here is a SequentialAnimation that sets the image's
1053 \l {Item::}{opacity} property to \c .5, animates the width of the image,
1054 then sets \l {Item::}{opacity} back to \c 1:
1055
1056 \snippet qml/propertyaction.qml standalone
1057
1058 PropertyAction is also useful for setting the exact point at which a property
1059 change should occur during a \l Transition. For example, if PropertyChanges
1060 was used in a \l State to rotate an item around a particular
1061 \l {Item::}{transformOrigin}, it might be implemented like this:
1062
1063 \snippet qml/propertyaction.qml transition
1064
1065 However, with this code, the \c transformOrigin is not set until \e after
1066 the animation, as a \l State is taken to define the values at the \e end of
1067 a transition. The animation would rotate at the default \c transformOrigin,
1068 then jump to \c Item.BottomRight. To fix this, insert a PropertyAction
1069 before the RotationAnimation begins:
1070
1071 \snippet qml/propertyaction-sequential.qml sequential
1072
1073 This immediately sets the \c transformOrigin property to the value defined
1074 in the end state of the \l Transition (i.e. the value defined in the
1075 PropertyAction object) so that the rotation animation begins with the
1076 correct transform origin.
1077
1078 \sa {Animation and Transitions in Qt Quick}, {Qt QML}
1079*/
1080QQuickPropertyAction::QQuickPropertyAction(QObject *parent)
1081: QQuickAbstractAnimation(*(new QQuickPropertyActionPrivate), parent)
1082{
1083}
1084
1085QQuickPropertyAction::~QQuickPropertyAction()
1086{
1087}
1088
1089QObject *QQuickPropertyAction::target() const
1090{
1091 Q_D(const QQuickPropertyAction);
1092 return d->target;
1093}
1094
1095void QQuickPropertyAction::setTargetObject(QObject *o)
1096{
1097 Q_D(QQuickPropertyAction);
1098 if (d->target == o)
1099 return;
1100 d->target = o;
1101 emit targetChanged();
1102 if (d->group)
1103 d->animationGroupDirty();
1104}
1105
1106QString QQuickPropertyAction::property() const
1107{
1108 Q_D(const QQuickPropertyAction);
1109 return d->propertyName;
1110}
1111
1112void QQuickPropertyAction::setProperty(const QString &n)
1113{
1114 Q_D(QQuickPropertyAction);
1115 if (d->propertyName == n)
1116 return;
1117 d->propertyName = n;
1118 emit propertyChanged();
1119 if (d->group)
1120 d->animationGroupDirty();
1121}
1122
1123/*!
1124 \qmlproperty QtObject QtQuick::PropertyAction::target
1125 \qmlproperty list<QtObject> QtQuick::PropertyAction::targets
1126 \qmlproperty string QtQuick::PropertyAction::property
1127 \qmlproperty string QtQuick::PropertyAction::properties
1128
1129 These properties determine the items and their properties that are
1130 affected by this action.
1131
1132 The details of how these properties are interpreted in different situations
1133 is covered in the \l{PropertyAnimation::properties}{corresponding} PropertyAnimation
1134 documentation.
1135
1136 \sa exclude
1137*/
1138QString QQuickPropertyAction::properties() const
1139{
1140 Q_D(const QQuickPropertyAction);
1141 return d->properties;
1142}
1143
1144void QQuickPropertyAction::setProperties(const QString &p)
1145{
1146 Q_D(QQuickPropertyAction);
1147 if (d->properties == p)
1148 return;
1149 d->properties = p;
1150 emit propertiesChanged(p);
1151 if (d->group)
1152 d->animationGroupDirty();
1153}
1154
1155QQmlListProperty<QObject> QQuickPropertyAction::targets()
1156{
1157 Q_D(QQuickPropertyAction);
1158 return QQmlListProperty<QObject>(this, &(d->targets));
1159}
1160
1161/*!
1162 \qmlproperty list<QtObject> QtQuick::PropertyAction::exclude
1163 This property holds the objects that should not be affected by this action.
1164
1165 \sa targets
1166*/
1167QQmlListProperty<QObject> QQuickPropertyAction::exclude()
1168{
1169 Q_D(QQuickPropertyAction);
1170 return QQmlListProperty<QObject>(this, &(d->exclude));
1171}
1172
1173/*!
1174 \qmlproperty var QtQuick::PropertyAction::value
1175 This property holds the value to be set on the property.
1176
1177 If the PropertyAction is defined within a \l Transition or \l Behavior,
1178 this value defaults to the value defined in the end state of the
1179 \l Transition, or the value of the property change that triggered the
1180 \l Behavior.
1181*/
1182QVariant QQuickPropertyAction::value() const
1183{
1184 Q_D(const QQuickPropertyAction);
1185 return d->value;
1186}
1187
1188void QQuickPropertyAction::setValue(const QVariant &v)
1189{
1190 Q_D(QQuickPropertyAction);
1191 if (d->value.isNull || d->value != v) {
1192 d->value = v;
1193 emit valueChanged(v);
1194 }
1195}
1196
1197QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &actions,
1198 QQmlProperties &modified,
1199 TransitionDirection direction,
1200 QObject *defaultTarget)
1201{
1202 Q_D(QQuickPropertyAction);
1203 Q_UNUSED(direction);
1204
1205 struct QQuickSetPropertyAnimationAction : public QAbstractAnimationAction
1206 {
1207 QQuickStateActions actions;
1208 void doAction() override
1209 {
1210 for (int ii = 0; ii < actions.size(); ++ii) {
1211 const QQuickStateAction &action = actions.at(i: ii);
1212 QQmlPropertyPrivate::write(that: action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
1213 }
1214 }
1215 void debugAction(QDebug d, int indentLevel) const override {
1216 QByteArray ind(indentLevel, ' ');
1217 for (int ii = 0; ii < actions.size(); ++ii) {
1218 const QQuickStateAction &action = actions.at(i: ii);
1219 d << "\n" << ind.constData() << "target:" << action.property.object() << "property:" << action.property.name()
1220 << "value:" << action.toValue;
1221 }
1222 }
1223 };
1224
1225 QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(sep: QLatin1Char(','));
1226 for (int ii = 0; ii < props.size(); ++ii)
1227 props[ii] = props.at(i: ii).trimmed();
1228 if (!d->propertyName.isEmpty())
1229 props << d->propertyName;
1230
1231 QList<QObject*> targets = d->targets;
1232 if (d->target)
1233 targets.append(t: d->target);
1234
1235 bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty();
1236
1237 if (d->defaultProperty.isValid() && !hasSelectors) {
1238 props << d->defaultProperty.name();
1239 targets << d->defaultProperty.object();
1240 }
1241
1242 if (defaultTarget && targets.isEmpty())
1243 targets << defaultTarget;
1244
1245 QQuickSetPropertyAnimationAction *data = new QQuickSetPropertyAnimationAction;
1246
1247 bool hasExplicit = false;
1248 //an explicit animation has been specified
1249 if (d->value.isValid()) {
1250 for (int i = 0; i < props.size(); ++i) {
1251 for (int j = 0; j < targets.size(); ++j) {
1252 QQuickStateAction myAction;
1253 myAction.property = d->createProperty(obj: targets.at(i: j), str: props.at(i), infoObj: this);
1254 if (myAction.property.isValid()) {
1255 myAction.toValue = d->value;
1256 QQuickPropertyAnimationPrivate::convertVariant(variant&: myAction.toValue, type: myAction.property.propertyMetaType());
1257 data->actions << myAction;
1258 hasExplicit = true;
1259 for (int ii = 0; ii < actions.size(); ++ii) {
1260 QQuickStateAction &action = actions[ii];
1261 if (action.property.object() == myAction.property.object() &&
1262 myAction.property.name() == action.property.name()) {
1263 modified << action.property;
1264 break; //### any chance there could be multiples?
1265 }
1266 }
1267 }
1268 }
1269 }
1270 }
1271
1272 if (!hasExplicit)
1273 for (int ii = 0; ii < actions.size(); ++ii) {
1274 QQuickStateAction &action = actions[ii];
1275
1276 QObject *obj = action.property.object();
1277 QString propertyName = action.property.name();
1278 QObject *sObj = action.specifiedObject;
1279 QString sPropertyName = action.specifiedProperty;
1280 bool same = (obj == sObj);
1281
1282 if ((targets.isEmpty() || targets.contains(t: obj) || (!same && targets.contains(t: sObj))) &&
1283 (!d->exclude.contains(t: obj)) && (same || (!d->exclude.contains(t: sObj))) &&
1284 (props.contains(str: propertyName) || (!same && props.contains(str: sPropertyName)))) {
1285 QQuickStateAction myAction = action;
1286
1287 if (d->value.isValid())
1288 myAction.toValue = d->value;
1289 QQuickPropertyAnimationPrivate::convertVariant(variant&: myAction.toValue, type: myAction.property.propertyMetaType());
1290
1291 modified << action.property;
1292 data->actions << myAction;
1293 action.fromValue = myAction.toValue;
1294 }
1295 }
1296
1297 QActionAnimation *action = new QActionAnimation;
1298 if (data->actions.size()) {
1299 action->setAnimAction(data);
1300 } else {
1301 delete data;
1302 }
1303 return initInstance(animation: action);
1304}
1305
1306/*!
1307 \qmltype NumberAnimation
1308 \instantiates QQuickNumberAnimation
1309 \inqmlmodule QtQuick
1310 \ingroup qtquick-animation-properties
1311 \inherits PropertyAnimation
1312 \brief Animates changes in qreal-type values.
1313
1314 NumberAnimation is a specialized PropertyAnimation that defines an
1315 animation to be applied when a numerical value changes.
1316
1317 Here is a NumberAnimation applied to the \c x property of a \l Rectangle
1318 as a property value source. It animates the \c x value from its current
1319 value to a value of 50, over 1000 milliseconds:
1320
1321 \snippet qml/numberanimation.qml 0
1322
1323 Like any other animation type, a NumberAnimation can be applied in a
1324 number of ways, including transitions, behaviors and property value
1325 sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
1326 variety of methods for creating animations.
1327
1328 Note that NumberAnimation may not animate smoothly if there are irregular
1329 changes in the number value that it is tracking. If this is the case, use
1330 SmoothedAnimation instead.
1331
1332 \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
1333*/
1334QQuickNumberAnimation::QQuickNumberAnimation(QObject *parent)
1335: QQuickPropertyAnimation(parent)
1336{
1337 init();
1338}
1339
1340QQuickNumberAnimation::QQuickNumberAnimation(QQuickPropertyAnimationPrivate &dd, QObject *parent)
1341: QQuickPropertyAnimation(dd, parent)
1342{
1343 init();
1344}
1345
1346QQuickNumberAnimation::~QQuickNumberAnimation()
1347{
1348}
1349
1350void QQuickNumberAnimation::init()
1351{
1352 Q_D(QQuickPropertyAnimation);
1353 d->interpolatorType = QMetaType::QReal;
1354 d->interpolator = QVariantAnimationPrivate::getInterpolator(interpolationType: d->interpolatorType);
1355}
1356
1357/*!
1358 \qmlproperty real QtQuick::NumberAnimation::from
1359 This property holds the starting value for the animation.
1360
1361 For example, the following animation is not applied until the \c x value
1362 has reached 100:
1363
1364 \qml
1365 Item {
1366 states: [
1367 // ...
1368 ]
1369
1370 transitions: Transition {
1371 NumberAnimation { properties: "x"; from: 100; duration: 200 }
1372 }
1373 }
1374 \endqml
1375
1376 If the NumberAnimation is defined within a \l Transition or \l Behavior,
1377 this value defaults to the value defined in the starting state of the
1378 \l Transition, or the current value of the property at the moment the
1379 \l Behavior is triggered.
1380
1381 \sa {Animation and Transitions in Qt Quick}
1382*/
1383
1384qreal QQuickNumberAnimation::from() const
1385{
1386 Q_D(const QQuickPropertyAnimation);
1387 return d->from.toReal();
1388}
1389
1390void QQuickNumberAnimation::setFrom(qreal f)
1391{
1392 QQuickPropertyAnimation::setFrom(f);
1393}
1394
1395/*!
1396 \qmlproperty real QtQuick::NumberAnimation::to
1397 This property holds the end value for the animation.
1398
1399 If the NumberAnimation is defined within a \l Transition or \l Behavior,
1400 this value defaults to the value defined in the end state of the
1401 \l Transition, or the value of the property change that triggered the
1402 \l Behavior.
1403
1404 \sa {Animation and Transitions in Qt Quick}
1405*/
1406qreal QQuickNumberAnimation::to() const
1407{
1408 Q_D(const QQuickPropertyAnimation);
1409 return d->to.toReal();
1410}
1411
1412void QQuickNumberAnimation::setTo(qreal t)
1413{
1414 QQuickPropertyAnimation::setTo(t);
1415}
1416
1417
1418
1419/*!
1420 \qmltype Vector3dAnimation
1421 \instantiates QQuickVector3dAnimation
1422 \inqmlmodule QtQuick
1423 \ingroup qtquick-animation-properties
1424 \inherits PropertyAnimation
1425 \brief Animates changes in QVector3d values.
1426
1427 Vector3dAnimation is a specialized PropertyAnimation that defines an
1428 animation to be applied when a Vector3d value changes.
1429
1430 Like any other animation type, a Vector3dAnimation can be applied in a
1431 number of ways, including transitions, behaviors and property value
1432 sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
1433 variety of methods for creating animations.
1434
1435 \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
1436*/
1437QQuickVector3dAnimation::QQuickVector3dAnimation(QObject *parent)
1438: QQuickPropertyAnimation(parent)
1439{
1440 Q_D(QQuickPropertyAnimation);
1441 d->interpolatorType = QMetaType::QVector3D;
1442 d->defaultToInterpolatorType = true;
1443 d->interpolator = QVariantAnimationPrivate::getInterpolator(interpolationType: d->interpolatorType);
1444}
1445
1446QQuickVector3dAnimation::~QQuickVector3dAnimation()
1447{
1448}
1449
1450/*!
1451 \qmlproperty vector3d QtQuick::Vector3dAnimation::from
1452 This property holds the starting value for the animation.
1453
1454 If the Vector3dAnimation is defined within a \l Transition or \l Behavior,
1455 this value defaults to the value defined in the starting state of the
1456 \l Transition, or the current value of the property at the moment the
1457 \l Behavior is triggered.
1458
1459 \sa {Animation and Transitions in Qt Quick}
1460*/
1461QVector3D QQuickVector3dAnimation::from() const
1462{
1463 Q_D(const QQuickPropertyAnimation);
1464 return d->from.value<QVector3D>();
1465}
1466
1467void QQuickVector3dAnimation::setFrom(QVector3D f)
1468{
1469 QQuickPropertyAnimation::setFrom(f);
1470}
1471
1472/*!
1473 \qmlproperty vector3d QtQuick::Vector3dAnimation::to
1474 This property holds the end value for the animation.
1475
1476 If the Vector3dAnimation is defined within a \l Transition or \l Behavior,
1477 this value defaults to the value defined in the end state of the
1478 \l Transition, or the value of the property change that triggered the
1479 \l Behavior.
1480
1481 \sa {Animation and Transitions in Qt Quick}
1482*/
1483QVector3D QQuickVector3dAnimation::to() const
1484{
1485 Q_D(const QQuickPropertyAnimation);
1486 return d->to.value<QVector3D>();
1487}
1488
1489void QQuickVector3dAnimation::setTo(QVector3D t)
1490{
1491 QQuickPropertyAnimation::setTo(t);
1492}
1493
1494
1495
1496/*!
1497 \qmltype RotationAnimation
1498 \instantiates QQuickRotationAnimation
1499 \inqmlmodule QtQuick
1500 \ingroup qtquick-animation-properties
1501 \inherits PropertyAnimation
1502 \brief Animates changes in rotation values.
1503
1504 RotationAnimation is a specialized PropertyAnimation that gives control
1505 over the direction of rotation during an animation.
1506
1507 By default, it rotates in the direction
1508 of the numerical change; a rotation from 0 to 240 will rotate 240 degrees
1509 clockwise, while a rotation from 240 to 0 will rotate 240 degrees
1510 counterclockwise. The \l direction property can be set to specify the
1511 direction in which the rotation should occur.
1512
1513 In the following example we use RotationAnimation to animate the rotation
1514 between states via the shortest path:
1515
1516 \snippet qml/rotationanimation.qml 0
1517
1518 Notice the RotationAnimation did not need to set a \c target
1519 value. As a convenience, when used in a transition, RotationAnimation will rotate all
1520 properties named "rotation" or "angle". You can override this by providing
1521 your own properties via \l {PropertyAnimation::properties}{properties} or
1522 \l {PropertyAnimation::property}{property}.
1523
1524 Also, note the \l Rectangle will be rotated around its default
1525 \l {Item::}{transformOrigin} (which is \c Item.Center). To use a different
1526 transform origin, set the origin in the PropertyChanges object and apply
1527 the change at the start of the animation using PropertyAction. See the
1528 PropertyAction documentation for more details.
1529
1530 Like any other animation type, a RotationAnimation can be applied in a
1531 number of ways, including transitions, behaviors and property value
1532 sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
1533 variety of methods for creating animations.
1534
1535 \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
1536*/
1537QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress)
1538{
1539 qreal newt = t;
1540 qreal diff = t-f;
1541 while(diff > 180.0){
1542 newt -= 360.0;
1543 diff -= 360.0;
1544 }
1545 while(diff < -180.0){
1546 newt += 360.0;
1547 diff += 360.0;
1548 }
1549 return QVariant(f + (newt - f) * progress);
1550}
1551
1552QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress)
1553{
1554 qreal newt = t;
1555 qreal diff = t-f;
1556 while(diff < 0.0){
1557 newt += 360.0;
1558 diff += 360.0;
1559 }
1560 return QVariant(f + (newt - f) * progress);
1561}
1562
1563QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress)
1564{
1565 qreal newt = t;
1566 qreal diff = t-f;
1567 while(diff > 0.0){
1568 newt -= 360.0;
1569 diff -= 360.0;
1570 }
1571 return QVariant(f + (newt - f) * progress);
1572}
1573
1574QQuickRotationAnimation::QQuickRotationAnimation(QObject *parent)
1575: QQuickPropertyAnimation(*(new QQuickRotationAnimationPrivate), parent)
1576{
1577 Q_D(QQuickRotationAnimation);
1578 d->interpolatorType = QMetaType::QReal;
1579 d->interpolator = QVariantAnimationPrivate::getInterpolator(interpolationType: d->interpolatorType);
1580 d->defaultProperties = QLatin1String("rotation,angle");
1581}
1582
1583QQuickRotationAnimation::~QQuickRotationAnimation()
1584{
1585}
1586
1587/*!
1588 \qmlproperty real QtQuick::RotationAnimation::from
1589 This property holds the starting value for the animation.
1590
1591 For example, the following animation is not applied until the \c angle value
1592 has reached 100:
1593
1594 \qml
1595 Item {
1596 states: [
1597 // ...
1598 ]
1599
1600 transitions: Transition {
1601 RotationAnimation { properties: "angle"; from: 100; duration: 2000 }
1602 }
1603 }
1604 \endqml
1605
1606 If the RotationAnimation is defined within a \l Transition or \l Behavior,
1607 this value defaults to the value defined in the starting state of the
1608 \l Transition, or the current value of the property at the moment the
1609 \l Behavior is triggered.
1610
1611 \sa {Animation and Transitions in Qt Quick}
1612*/
1613qreal QQuickRotationAnimation::from() const
1614{
1615 Q_D(const QQuickRotationAnimation);
1616 return d->from.toReal();
1617}
1618
1619void QQuickRotationAnimation::setFrom(qreal f)
1620{
1621 QQuickPropertyAnimation::setFrom(f);
1622}
1623
1624/*!
1625 \qmlproperty real QtQuick::RotationAnimation::to
1626 This property holds the end value for the animation..
1627
1628 If the RotationAnimation is defined within a \l Transition or \l Behavior,
1629 this value defaults to the value defined in the end state of the
1630 \l Transition, or the value of the property change that triggered the
1631 \l Behavior.
1632
1633 \sa {Animation and Transitions in Qt Quick}
1634*/
1635qreal QQuickRotationAnimation::to() const
1636{
1637 Q_D(const QQuickRotationAnimation);
1638 return d->to.toReal();
1639}
1640
1641void QQuickRotationAnimation::setTo(qreal t)
1642{
1643 QQuickPropertyAnimation::setTo(t);
1644}
1645
1646/*!
1647 \qmlproperty enumeration QtQuick::RotationAnimation::direction
1648 This property holds the direction of the rotation.
1649
1650 Possible values are:
1651
1652 \value RotationAnimation.Numerical
1653 (default) Rotate by linearly interpolating between the two numbers.
1654 A rotation from \c 10 to \c 350 will rotate 340 degrees clockwise.
1655 \value RotationAnimation.Clockwise
1656 Rotate clockwise between the two values
1657 \value RotationAnimation.Counterclockwise
1658 Rotate counterclockwise between the two values
1659 \value RotationAnimation.Shortest
1660 Rotate in the direction that produces the shortest animation path.
1661 A rotation from \c 10 to \c 350 will rotate \c 20 degrees counterclockwise.
1662*/
1663QQuickRotationAnimation::RotationDirection QQuickRotationAnimation::direction() const
1664{
1665 Q_D(const QQuickRotationAnimation);
1666 return d->direction;
1667}
1668
1669void QQuickRotationAnimation::setDirection(QQuickRotationAnimation::RotationDirection direction)
1670{
1671 Q_D(QQuickRotationAnimation);
1672 if (d->direction == direction)
1673 return;
1674
1675 d->direction = direction;
1676 switch(d->direction) {
1677 case Clockwise:
1678 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&_q_interpolateClockwiseRotation));
1679 break;
1680 case Counterclockwise:
1681 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&_q_interpolateCounterclockwiseRotation));
1682 break;
1683 case Shortest:
1684 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&_q_interpolateShortestRotation));
1685 break;
1686 default:
1687 d->interpolator = QVariantAnimationPrivate::getInterpolator(interpolationType: d->interpolatorType);
1688 break;
1689 }
1690 emit directionChanged();
1691}
1692
1693
1694
1695QQuickAnimationGroup::QQuickAnimationGroup(QObject *parent)
1696: QQuickAbstractAnimation(*(new QQuickAnimationGroupPrivate), parent)
1697{
1698}
1699
1700QQuickAnimationGroup::QQuickAnimationGroup(QQuickAnimationGroupPrivate &dd, QObject *parent)
1701 : QQuickAbstractAnimation(dd, parent)
1702{
1703}
1704
1705void QQuickAnimationGroupPrivate::append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a)
1706{
1707 QQuickAnimationGroup *q = qmlobject_cast<QQuickAnimationGroup *>(object: list->object);
1708 if (q && a)
1709 a->setGroup(g: q);
1710}
1711
1712QQuickAbstractAnimation *QQuickAnimationGroupPrivate::at_animation(QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype index)
1713{
1714 if (auto q = qmlobject_cast<QQuickAnimationGroup *>(object: list->object))
1715 return q->d_func()->animations.at(i: index);
1716 return nullptr;
1717}
1718
1719qsizetype QQuickAnimationGroupPrivate::count_animation(QQmlListProperty<QQuickAbstractAnimation> *list)
1720{
1721 if (auto q = qmlobject_cast<QQuickAnimationGroup *>(object: list->object))
1722 return q->d_func()->animations.size();
1723 return 0;
1724}
1725
1726void QQuickAnimationGroupPrivate::clear_animation(QQmlListProperty<QQuickAbstractAnimation> *list)
1727{
1728 QQuickAnimationGroup *q = qobject_cast<QQuickAnimationGroup *>(object: list->object);
1729 if (q) {
1730 while (q->d_func()->animations.size()) {
1731 QQuickAbstractAnimation *firstAnim = q->d_func()->animations.at(i: 0);
1732 firstAnim->setGroup(g: nullptr);
1733 }
1734 }
1735}
1736
1737void QQuickAnimationGroupPrivate::replace_animation(QQmlListProperty<QQuickAbstractAnimation> *list,
1738 qsizetype i, QQuickAbstractAnimation *a)
1739{
1740 if (auto *q = qmlobject_cast<QQuickAnimationGroup *>(object: list->object)) {
1741 if (QQuickAbstractAnimation *anim = q->d_func()->animations.at(i))
1742 anim->setGroup(g: nullptr);
1743 if (a)
1744 a->setGroup(g: q, index: i);
1745 }
1746}
1747
1748void QQuickAnimationGroupPrivate::removeLast_animation(QQmlListProperty<QQuickAbstractAnimation> *list)
1749{
1750 if (auto *q = qobject_cast<QQuickAnimationGroup *>(object: list->object))
1751 q->d_func()->animations.last()->setGroup(g: nullptr);
1752}
1753
1754void QQuickAnimationGroupPrivate::restartFromCurrentLoop()
1755{
1756 Q_Q(QQuickAnimationGroup);
1757 if (!animationDirty)
1758 return;
1759
1760 animationDirty = false;
1761
1762 Q_ASSERT(animationInstance);
1763 const int currentLoop = animationInstance->currentLoop();
1764
1765 QSignalBlocker signalBlocker(q);
1766 q->stop();
1767 q->start();
1768
1769 Q_ASSERT(animationInstance);
1770 // Restarting adjusts animationInstance's loopCount
1771 // Since we just want to start it from this loop,
1772 // it will be restored again.
1773 if (loopCount != -1)
1774 animationInstance->setLoopCount(loopCount - currentLoop);
1775}
1776
1777void QQuickAnimationGroupPrivate::animationCurrentLoopChanged(QAbstractAnimationJob *)
1778{
1779 if (!animationDirty)
1780 return;
1781 restartFromCurrentLoop();
1782}
1783
1784QQuickAnimationGroup::~QQuickAnimationGroup()
1785{
1786 Q_D(QQuickAnimationGroup);
1787 for (int i = 0; i < d->animations.size(); ++i)
1788 d->animations.at(i)->d_func()->group = nullptr;
1789 d->animations.clear();
1790}
1791
1792QQmlListProperty<QQuickAbstractAnimation> QQuickAnimationGroup::animations()
1793{
1794 Q_D(QQuickAnimationGroup);
1795 return QQmlListProperty<QQuickAbstractAnimation>(
1796 this, &(d->animations),
1797 &QQuickAnimationGroupPrivate::append_animation,
1798 &QQuickAnimationGroupPrivate::count_animation,
1799 &QQuickAnimationGroupPrivate::at_animation,
1800 &QQuickAnimationGroupPrivate::clear_animation,
1801 &QQuickAnimationGroupPrivate::replace_animation,
1802 &QQuickAnimationGroupPrivate::removeLast_animation);
1803}
1804
1805/*!
1806 \qmltype SequentialAnimation
1807 \instantiates QQuickSequentialAnimation
1808 \inqmlmodule QtQuick
1809 \ingroup qtquick-transitions-animations
1810 \inherits Animation
1811 \brief Allows animations to be run sequentially.
1812
1813 The SequentialAnimation and ParallelAnimation types allow multiple
1814 animations to be run together. Animations defined in a SequentialAnimation
1815 are run one after the other, while animations defined in a ParallelAnimation
1816 are run at the same time.
1817
1818 The following example runs two number animations in a sequence. The \l Rectangle
1819 animates to a \c x position of 50, then to a \c y position of 50.
1820
1821 \snippet qml/sequentialanimation.qml 0
1822
1823 Animations defined within a \l Transition are automatically run in parallel,
1824 so SequentialAnimation can be used to enclose the animations in a \l Transition
1825 if this is the preferred behavior.
1826
1827 Like any other animation type, a SequentialAnimation can be applied in a
1828 number of ways, including transitions, behaviors and property value
1829 sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
1830 variety of methods for creating animations.
1831
1832 \note Once an animation has been grouped into a SequentialAnimation or
1833 ParallelAnimation, it cannot be individually started and stopped; the
1834 SequentialAnimation or ParallelAnimation must be started and stopped as a group.
1835
1836 \sa ParallelAnimation, {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
1837*/
1838
1839QQuickSequentialAnimation::QQuickSequentialAnimation(QObject *parent) :
1840 QQuickAnimationGroup(parent)
1841{
1842}
1843
1844QQuickSequentialAnimation::~QQuickSequentialAnimation()
1845{
1846}
1847
1848QQuickAbstractAnimation::ThreadingModel QQuickSequentialAnimation::threadingModel() const
1849{
1850 Q_D(const QQuickAnimationGroup);
1851
1852 ThreadingModel style = AnyThread;
1853 for (int i=0; i<d->animations.size(); ++i) {
1854 ThreadingModel ces = d->animations.at(i)->threadingModel();
1855 if (ces == GuiThread)
1856 return GuiThread;
1857 else if (ces == RenderThread)
1858 style = RenderThread;
1859 }
1860 return style;
1861}
1862
1863QAbstractAnimationJob* QQuickSequentialAnimation::transition(QQuickStateActions &actions,
1864 QQmlProperties &modified,
1865 TransitionDirection direction,
1866 QObject *defaultTarget)
1867{
1868 Q_D(QQuickAnimationGroup);
1869
1870 QSequentialAnimationGroupJob *ag = new QSequentialAnimationGroupJob;
1871
1872 int inc = 1;
1873 int from = 0;
1874 if (direction == Backward) {
1875 inc = -1;
1876 from = d->animations.size() - 1;
1877 }
1878
1879 ThreadingModel execution = threadingModel();
1880
1881 bool valid = d->defaultProperty.isValid();
1882 QAbstractAnimationJob* anim;
1883 for (int ii = from; ii < d->animations.size() && ii >= 0; ii += inc) {
1884 if (valid)
1885 d->animations.at(i: ii)->setDefaultTarget(d->defaultProperty);
1886 anim = d->animations.at(i: ii)->transition(actions, modified, direction, defaultTarget);
1887 if (anim) {
1888 if (d->animations.at(i: ii)->threadingModel() == RenderThread && execution != RenderThread)
1889 anim = new QQuickAnimatorProxyJob(anim, this);
1890 inc == -1 ? ag->prependAnimation(animation: anim) : ag->appendAnimation(animation: anim);
1891 }
1892 }
1893
1894 return initInstance(animation: ag);
1895}
1896
1897
1898
1899/*!
1900 \qmltype ParallelAnimation
1901 \instantiates QQuickParallelAnimation
1902 \inqmlmodule QtQuick
1903 \ingroup qtquick-transitions-animations
1904 \inherits Animation
1905 \brief Enables animations to be run in parallel.
1906
1907 The SequentialAnimation and ParallelAnimation types allow multiple
1908 animations to be run together. Animations defined in a SequentialAnimation
1909 are run one after the other, while animations defined in a ParallelAnimation
1910 are run at the same time.
1911
1912 The following animation runs two number animations in parallel. The \l Rectangle
1913 moves to (50,50) by animating its \c x and \c y properties at the same time.
1914
1915 \snippet qml/parallelanimation.qml 0
1916
1917 Like any other animation type, a ParallelAnimation can be applied in a
1918 number of ways, including transitions, behaviors and property value
1919 sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
1920 variety of methods for creating animations.
1921
1922 \note Once an animation has been grouped into a SequentialAnimation or
1923 ParallelAnimation, it cannot be individually started and stopped; the
1924 SequentialAnimation or ParallelAnimation must be started and stopped as a group.
1925
1926 \sa SequentialAnimation, {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
1927*/
1928QQuickParallelAnimation::QQuickParallelAnimation(QObject *parent) :
1929 QQuickAnimationGroup(parent)
1930{
1931}
1932
1933QQuickParallelAnimation::~QQuickParallelAnimation()
1934{
1935}
1936
1937QQuickAbstractAnimation::ThreadingModel QQuickParallelAnimation::threadingModel() const
1938{
1939 Q_D(const QQuickAnimationGroup);
1940
1941 ThreadingModel style = AnyThread;
1942 for (int i=0; i<d->animations.size(); ++i) {
1943 ThreadingModel ces = d->animations.at(i)->threadingModel();
1944 if (ces == GuiThread)
1945 return GuiThread;
1946 else if (ces == RenderThread)
1947 style = RenderThread;
1948 }
1949 return style;
1950}
1951
1952
1953
1954QAbstractAnimationJob* QQuickParallelAnimation::transition(QQuickStateActions &actions,
1955 QQmlProperties &modified,
1956 TransitionDirection direction,
1957 QObject *defaultTarget)
1958{
1959 Q_D(QQuickAnimationGroup);
1960 QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob;
1961
1962 ThreadingModel style = threadingModel();
1963
1964 bool valid = d->defaultProperty.isValid();
1965 QAbstractAnimationJob* anim;
1966 for (int ii = 0; ii < d->animations.size(); ++ii) {
1967 if (valid)
1968 d->animations.at(i: ii)->setDefaultTarget(d->defaultProperty);
1969 anim = d->animations.at(i: ii)->transition(actions, modified, direction, defaultTarget);
1970 if (anim) {
1971 if (d->animations.at(i: ii)->threadingModel() == RenderThread && style != RenderThread)
1972 anim = new QQuickAnimatorProxyJob(anim, this);
1973 ag->appendAnimation(animation: anim);
1974 }
1975 }
1976 return initInstance(animation: ag);
1977}
1978
1979void QQuickPropertyAnimationPrivate::animationCurrentLoopChanged(QAbstractAnimationJob *)
1980{
1981 Q_Q(QQuickPropertyAnimation);
1982 // We listen to current loop changes in order to restart the animation if e.g. from, to, etc.
1983 // are modified while the animation is running.
1984 // Restarting is a bit drastic but there is a lot of stuff that commence() (and therefore
1985 // QQuickPropertyAnimation::transition() and QQuickPropertyAnimation::createTransitionActions())
1986 // does, so we want to avoid trying to take a shortcut and just restart the whole thing.
1987 if (ourPropertiesDirty) {
1988 ourPropertiesDirty = false;
1989
1990 // We use animationInstance everywhere for simplicity - if we defined the job parameter
1991 // it would be deleted as soon as we call stop().
1992 Q_ASSERT(animationInstance);
1993 const int currentLoop = animationInstance->currentLoop();
1994
1995 QSignalBlocker signalBlocker(q);
1996 q->stop();
1997 q->start();
1998
1999 Q_ASSERT(animationInstance);
2000 // We multiply it ourselves here instead of just saving currentTime(), because otherwise
2001 // it seems to accumulate, and changing our properties while the animation is running
2002 // can result in the animation starting mid-way through a loop, which is not we want;
2003 // we want it to start from the beginning.
2004 animationInstance->setCurrentTime(currentLoop * animationInstance->duration());
2005 }
2006}
2007
2008//convert a variant from string type to another animatable type
2009void QQuickPropertyAnimationPrivate::convertVariant(QVariant &variant, QMetaType type)
2010{
2011 if (variant.userType() != QMetaType::QString) {
2012 variant.convert(type);
2013 return;
2014 }
2015
2016 switch (type.id()) {
2017 case QMetaType::QRect:
2018 case QMetaType::QRectF:
2019 case QMetaType::QPoint:
2020 case QMetaType::QPointF:
2021 case QMetaType::QSize:
2022 case QMetaType::QSizeF:
2023 case QMetaType::QColor:
2024 case QMetaType::QVector3D:
2025 {
2026 bool ok = false;
2027 variant = QQmlStringConverters::variantFromString(variant.toString(), preferredType: type, ok: &ok);
2028 }
2029 break;
2030 default:
2031 if (QQmlMetaType::isValueType(type)) {
2032 variant.convert(type: QMetaType(type));
2033 }
2034 break;
2035 }
2036}
2037
2038QQuickBulkValueAnimator::QQuickBulkValueAnimator()
2039 : QAbstractAnimationJob(), animValue(nullptr), fromIsSourced(nullptr), m_duration(250)
2040{
2041}
2042
2043QQuickBulkValueAnimator::~QQuickBulkValueAnimator()
2044{
2045 delete animValue;
2046}
2047
2048void QQuickBulkValueAnimator::setAnimValue(QQuickBulkValueUpdater *value)
2049{
2050 if (isRunning())
2051 stop();
2052 animValue = value;
2053}
2054
2055void QQuickBulkValueAnimator::updateCurrentTime(int currentTime)
2056{
2057 if (isStopped())
2058 return;
2059
2060 const qreal progress = easing.valueForProgress(progress: ((m_duration == 0) ? qreal(1) : qreal(currentTime) / qreal(m_duration)));
2061
2062 if (animValue)
2063 animValue->setValue(progress);
2064}
2065
2066void QQuickBulkValueAnimator::topLevelAnimationLoopChanged()
2067{
2068 // Check for new "from" value only when animation has one loop.
2069 // Otherwise use the initial "from" value for every iteration.
2070 if (m_loopCount == 1 && fromIsSourced)
2071 *fromIsSourced = false;
2072 QAbstractAnimationJob::topLevelAnimationLoopChanged();
2073}
2074
2075void QQuickBulkValueAnimator::debugAnimation(QDebug d) const
2076{
2077 d << "BulkValueAnimation(" << Qt::hex << (const void *) this << Qt::dec << ")" << "duration:" << duration();
2078
2079 if (animValue) {
2080 int indentLevel = 1;
2081 const QAbstractAnimationJob *job = this;
2082 while ((job = job->group()))
2083 ++indentLevel;
2084 animValue->debugUpdater(d, indentLevel);
2085 }
2086}
2087
2088/*!
2089 \qmltype PropertyAnimation
2090 \instantiates QQuickPropertyAnimation
2091 \inqmlmodule QtQuick
2092 \ingroup qtquick-animation-properties
2093 \inherits Animation
2094 \brief Animates changes in property values.
2095
2096 PropertyAnimation provides a way to animate changes to a property's value.
2097
2098 It can be used to define animations in a number of ways:
2099
2100 \list
2101 \li In a \l Transition
2102
2103 For example, to animate any objects that have changed their \c x or \c y properties
2104 as a result of a state change, using an \c InOutQuad easing curve:
2105
2106 \snippet qml/propertyanimation.qml transition
2107
2108
2109 \li In a \l Behavior
2110
2111 For example, to animate all changes to a rectangle's \c x property:
2112
2113 \snippet qml/propertyanimation.qml behavior
2114
2115
2116 \li As a property value source
2117
2118 For example, to repeatedly animate the rectangle's \c x property:
2119
2120 \snippet qml/propertyanimation.qml propertyvaluesource
2121
2122
2123 \li In a signal handler
2124
2125 For example, to fade out \c theObject when clicked:
2126 \qml
2127 MouseArea {
2128 anchors.fill: theObject
2129 onClicked: PropertyAnimation { target: theObject; property: "opacity"; to: 0 }
2130 }
2131 \endqml
2132
2133 \li Standalone
2134
2135 For example, to animate \c rect's \c width property over 500ms, from its current width to 30:
2136
2137 \snippet qml/propertyanimation.qml standalone
2138
2139 \endlist
2140
2141 Depending on how the animation is used, the set of properties normally used will be
2142 different. For more information see the individual property documentation, as well
2143 as the \l{Animation and Transitions in Qt Quick} introduction.
2144
2145 Note that PropertyAnimation inherits the abstract \l Animation type.
2146 This includes additional properties and methods for controlling the animation.
2147
2148 \section1 Modifying running animations
2149
2150 Since Qt 6.4, it is possible to set the \l from, \l to, \l duration, and
2151 \l easing properties on a top-level animation while it is running. The
2152 animation will take the changes into account on the next loop.
2153
2154 \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
2155*/
2156
2157QQuickPropertyAnimation::QQuickPropertyAnimation(QObject *parent)
2158: QQuickAbstractAnimation(*(new QQuickPropertyAnimationPrivate), parent)
2159{
2160}
2161
2162QQuickPropertyAnimation::QQuickPropertyAnimation(QQuickPropertyAnimationPrivate &dd, QObject *parent)
2163: QQuickAbstractAnimation(dd, parent)
2164{
2165}
2166
2167QQuickPropertyAnimation::~QQuickPropertyAnimation()
2168{
2169}
2170
2171/*!
2172 \qmlproperty int QtQuick::PropertyAnimation::duration
2173 This property holds the duration of the animation, in milliseconds.
2174
2175 The default value is 250.
2176*/
2177int QQuickPropertyAnimation::duration() const
2178{
2179 Q_D(const QQuickPropertyAnimation);
2180 return d->duration;
2181}
2182
2183void QQuickPropertyAnimation::setDuration(int duration)
2184{
2185 if (duration < 0) {
2186 qmlWarning(me: this) << tr(s: "Cannot set a duration of < 0");
2187 return;
2188 }
2189
2190 Q_D(QQuickPropertyAnimation);
2191 if (d->duration == duration)
2192 return;
2193 d->duration = duration;
2194 if (d->componentComplete && d->running)
2195 d->ourPropertiesDirty = true;
2196 emit durationChanged(duration);
2197 if (d->group)
2198 d->animationGroupDirty();
2199}
2200
2201/*!
2202 \qmlproperty variant QtQuick::PropertyAnimation::from
2203 This property holds the starting value for the animation.
2204
2205 If the PropertyAnimation is defined within a \l Transition or \l Behavior,
2206 this value defaults to the value defined in the starting state of the
2207 \l Transition, or the current value of the property at the moment the
2208 \l Behavior is triggered.
2209
2210 \sa {Animation and Transitions in Qt Quick}
2211*/
2212QVariant QQuickPropertyAnimation::from() const
2213{
2214 Q_D(const QQuickPropertyAnimation);
2215 return d->from;
2216}
2217
2218void QQuickPropertyAnimation::setFrom(const QVariant &f)
2219{
2220 Q_D(QQuickPropertyAnimation);
2221 if (d->fromIsDefined && f == d->from)
2222 return;
2223 d->from = f;
2224 d->fromIsDefined = f.isValid();
2225 if (d->componentComplete && d->running)
2226 d->ourPropertiesDirty = true;
2227 emit fromChanged();
2228 if (d->group)
2229 d->animationGroupDirty();
2230}
2231
2232/*!
2233 \qmlproperty variant QtQuick::PropertyAnimation::to
2234 This property holds the end value for the animation.
2235
2236 If the PropertyAnimation is defined within a \l Transition or \l Behavior,
2237 this value defaults to the value defined in the end state of the
2238 \l Transition, or the value of the property change that triggered the
2239 \l Behavior.
2240
2241 \sa {Animation and Transitions in Qt Quick}
2242*/
2243QVariant QQuickPropertyAnimation::to() const
2244{
2245 Q_D(const QQuickPropertyAnimation);
2246 return d->to;
2247}
2248
2249void QQuickPropertyAnimation::setTo(const QVariant &t)
2250{
2251 Q_D(QQuickPropertyAnimation);
2252 if (d->toIsDefined && t == d->to)
2253 return;
2254 d->to = t;
2255 d->toIsDefined = t.isValid();
2256 if (d->componentComplete && d->running)
2257 d->ourPropertiesDirty = true;
2258 emit toChanged();
2259 if (d->group)
2260 d->animationGroupDirty();
2261}
2262
2263/*!
2264 \qmlpropertygroup QtQuick::PropertyAnimation::easing
2265 \qmlproperty enumeration QtQuick::PropertyAnimation::easing.type
2266 \qmlproperty real QtQuick::PropertyAnimation::easing.amplitude
2267 \qmlproperty real QtQuick::PropertyAnimation::easing.overshoot
2268 \qmlproperty real QtQuick::PropertyAnimation::easing.period
2269 \qmlproperty list<real> QtQuick::PropertyAnimation::easing.bezierCurve
2270
2271//! propertyanimation.easing
2272 \brief Specifies the easing curve used for the animation
2273
2274 To specify an easing curve you need to specify at least the type. For some curves you can also specify
2275 amplitude, period and/or overshoot (more details provided after the table). The default easing curve is
2276 \c Easing.Linear.
2277
2278 \qml
2279 PropertyAnimation { properties: "y";
2280 easing.type: Easing.InOutElastic;
2281 easing.amplitude: 2.0;
2282 easing.period: 1.5 }
2283 \endqml
2284
2285 Available types are:
2286
2287 \table
2288 \row
2289 \li \c Easing.Linear
2290 \li Easing curve for a linear (t) function: velocity is constant.
2291 \li \inlineimage qeasingcurve-linear.png
2292 \row
2293 \li \c Easing.InQuad
2294 \li Easing curve for a quadratic (t^2) function: accelerating from zero velocity.
2295 \li \inlineimage qeasingcurve-inquad.png
2296 \row
2297 \li \c Easing.OutQuad
2298 \li Easing curve for a quadratic (t^2) function: decelerating to zero velocity.
2299 \li \inlineimage qeasingcurve-outquad.png
2300 \row
2301 \li \c Easing.InOutQuad
2302 \li Easing curve for a quadratic (t^2) function: acceleration until halfway, then deceleration.
2303 \li \inlineimage qeasingcurve-inoutquad.png
2304 \row
2305 \li \c Easing.OutInQuad
2306 \li Easing curve for a quadratic (t^2) function: deceleration until halfway, then acceleration.
2307 \li \inlineimage qeasingcurve-outinquad.png
2308 \row
2309 \li \c Easing.InCubic
2310 \li Easing curve for a cubic (t^3) function: accelerating from zero velocity.
2311 \li \inlineimage qeasingcurve-incubic.png
2312 \row
2313 \li \c Easing.OutCubic
2314 \li Easing curve for a cubic (t^3) function: decelerating to zero velocity.
2315 \li \inlineimage qeasingcurve-outcubic.png
2316 \row
2317 \li \c Easing.InOutCubic
2318 \li Easing curve for a cubic (t^3) function: acceleration until halfway, then deceleration.
2319 \li \inlineimage qeasingcurve-inoutcubic.png
2320 \row
2321 \li \c Easing.OutInCubic
2322 \li Easing curve for a cubic (t^3) function: deceleration until halfway, then acceleration.
2323 \li \inlineimage qeasingcurve-outincubic.png
2324 \row
2325 \li \c Easing.InQuart
2326 \li Easing curve for a quartic (t^4) function: accelerating from zero velocity.
2327 \li \inlineimage qeasingcurve-inquart.png
2328 \row
2329 \li \c Easing.OutQuart
2330 \li Easing curve for a quartic (t^4) function: decelerating to zero velocity.
2331 \li \inlineimage qeasingcurve-outquart.png
2332 \row
2333 \li \c Easing.InOutQuart
2334 \li Easing curve for a quartic (t^4) function: acceleration until halfway, then deceleration.
2335 \li \inlineimage qeasingcurve-inoutquart.png
2336 \row
2337 \li \c Easing.OutInQuart
2338 \li Easing curve for a quartic (t^4) function: deceleration until halfway, then acceleration.
2339 \li \inlineimage qeasingcurve-outinquart.png
2340 \row
2341 \li \c Easing.InQuint
2342 \li Easing curve for a quintic (t^5) function: accelerating from zero velocity.
2343 \li \inlineimage qeasingcurve-inquint.png
2344 \row
2345 \li \c Easing.OutQuint
2346 \li Easing curve for a quintic (t^5) function: decelerating to zero velocity.
2347 \li \inlineimage qeasingcurve-outquint.png
2348 \row
2349 \li \c Easing.InOutQuint
2350 \li Easing curve for a quintic (t^5) function: acceleration until halfway, then deceleration.
2351 \li \inlineimage qeasingcurve-inoutquint.png
2352 \row
2353 \li \c Easing.OutInQuint
2354 \li Easing curve for a quintic (t^5) function: deceleration until halfway, then acceleration.
2355 \li \inlineimage qeasingcurve-outinquint.png
2356 \row
2357 \li \c Easing.InSine
2358 \li Easing curve for a sinusoidal (sin(t)) function: accelerating from zero velocity.
2359 \li \inlineimage qeasingcurve-insine.png
2360 \row
2361 \li \c Easing.OutSine
2362 \li Easing curve for a sinusoidal (sin(t)) function: decelerating to zero velocity.
2363 \li \inlineimage qeasingcurve-outsine.png
2364 \row
2365 \li \c Easing.InOutSine
2366 \li Easing curve for a sinusoidal (sin(t)) function: acceleration until halfway, then deceleration.
2367 \li \inlineimage qeasingcurve-inoutsine.png
2368 \row
2369 \li \c Easing.OutInSine
2370 \li Easing curve for a sinusoidal (sin(t)) function: deceleration until halfway, then acceleration.
2371 \li \inlineimage qeasingcurve-outinsine.png
2372 \row
2373 \li \c Easing.InExpo
2374 \li Easing curve for an exponential (2^t) function: accelerating from zero velocity.
2375 \li \inlineimage qeasingcurve-inexpo.png
2376 \row
2377 \li \c Easing.OutExpo
2378 \li Easing curve for an exponential (2^t) function: decelerating to zero velocity.
2379 \li \inlineimage qeasingcurve-outexpo.png
2380 \row
2381 \li \c Easing.InOutExpo
2382 \li Easing curve for an exponential (2^t) function: acceleration until halfway, then deceleration.
2383 \li \inlineimage qeasingcurve-inoutexpo.png
2384 \row
2385 \li \c Easing.OutInExpo
2386 \li Easing curve for an exponential (2^t) function: deceleration until halfway, then acceleration.
2387 \li \inlineimage qeasingcurve-outinexpo.png
2388 \row
2389 \li \c Easing.InCirc
2390 \li Easing curve for a circular (sqrt(1-t^2)) function: accelerating from zero velocity.
2391 \li \inlineimage qeasingcurve-incirc.png
2392 \row
2393 \li \c Easing.OutCirc
2394 \li Easing curve for a circular (sqrt(1-t^2)) function: decelerating to zero velocity.
2395 \li \inlineimage qeasingcurve-outcirc.png
2396 \row
2397 \li \c Easing.InOutCirc
2398 \li Easing curve for a circular (sqrt(1-t^2)) function: acceleration until halfway, then deceleration.
2399 \li \inlineimage qeasingcurve-inoutcirc.png
2400 \row
2401 \li \c Easing.OutInCirc
2402 \li Easing curve for a circular (sqrt(1-t^2)) function: deceleration until halfway, then acceleration.
2403 \li \inlineimage qeasingcurve-outincirc.png
2404 \row
2405 \li \c Easing.InElastic
2406 \li Easing curve for an elastic (exponentially decaying sine wave) function: accelerating from zero velocity.
2407 \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
2408 \li \inlineimage qeasingcurve-inelastic.png
2409 \row
2410 \li \c Easing.OutElastic
2411 \li Easing curve for an elastic (exponentially decaying sine wave) function: decelerating to zero velocity.
2412 \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
2413 \li \inlineimage qeasingcurve-outelastic.png
2414 \row
2415 \li \c Easing.InOutElastic
2416 \li Easing curve for an elastic (exponentially decaying sine wave) function: acceleration until halfway, then deceleration.
2417 \li \inlineimage qeasingcurve-inoutelastic.png
2418 \row
2419 \li \c Easing.OutInElastic
2420 \li Easing curve for an elastic (exponentially decaying sine wave) function: deceleration until halfway, then acceleration.
2421 \li \inlineimage qeasingcurve-outinelastic.png
2422 \row
2423 \li \c Easing.InBack
2424 \li Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
2425 \li \inlineimage qeasingcurve-inback.png
2426 \row
2427 \li \c Easing.OutBack
2428 \li Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out: decelerating to zero velocity.
2429 \li \inlineimage qeasingcurve-outback.png
2430 \row
2431 \li \c Easing.InOutBack
2432 \li Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
2433 \li \inlineimage qeasingcurve-inoutback.png
2434 \row
2435 \li \c Easing.OutInBack
2436 \li Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
2437 \li \inlineimage qeasingcurve-outinback.png
2438 \row
2439 \li \c Easing.InBounce
2440 \li Easing curve for a bounce (exponentially decaying parabolic bounce) function: accelerating from zero velocity.
2441 \li \inlineimage qeasingcurve-inbounce.png
2442 \row
2443 \li \c Easing.OutBounce
2444 \li Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating to zero velocity.
2445 \li \inlineimage qeasingcurve-outbounce.png
2446 \row
2447 \li \c Easing.InOutBounce
2448 \li Easing curve for a bounce (exponentially decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration.
2449 \li \inlineimage qeasingcurve-inoutbounce.png
2450 \row
2451 \li \c Easing.OutInBounce
2452 \li Easing curve for a bounce (exponentially decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration.
2453 \li \inlineimage qeasingcurve-outinbounce.png
2454 \row
2455 \li \c Easing.BezierSpline
2456 \li Custom easing curve defined by the easing.bezierCurve property.
2457 \li
2458 \endtable
2459
2460 \c easing.amplitude is only applicable for bounce and elastic curves (curves of type
2461 \c Easing.InBounce, \c Easing.OutBounce, \c Easing.InOutBounce, \c Easing.OutInBounce, \c Easing.InElastic,
2462 \c Easing.OutElastic, \c Easing.InOutElastic or \c Easing.OutInElastic).
2463
2464 \c easing.overshoot is only applicable if \c easing.type is: \c Easing.InBack, \c Easing.OutBack,
2465 \c Easing.InOutBack or \c Easing.OutInBack.
2466
2467 \c easing.period is only applicable if easing.type is: \c Easing.InElastic, \c Easing.OutElastic,
2468 \c Easing.InOutElastic or \c Easing.OutInElastic.
2469
2470 \c easing.bezierCurve is only applicable if easing.type is: \c Easing.BezierSpline. This property is a list<real> containing
2471 groups of three points defining a curve from 0,0 to 1,1 - control1, control2,
2472 end point: [cx1, cy1, cx2, cy2, endx, endy, ...]. The last point must be 1,1.
2473
2474 See the \l {Qt Quick Examples - Animation#Easing Curves}{Easing Curves} for a demonstration of the different easing settings.
2475//! propertyanimation.easing
2476*/
2477QEasingCurve QQuickPropertyAnimation::easing() const
2478{
2479 Q_D(const QQuickPropertyAnimation);
2480 return d->easing;
2481}
2482
2483void QQuickPropertyAnimation::setEasing(const QEasingCurve &e)
2484{
2485 Q_D(QQuickPropertyAnimation);
2486 if (d->easing == e)
2487 return;
2488
2489 d->easing = e;
2490 if (d->componentComplete && d->running)
2491 d->ourPropertiesDirty = true;
2492 emit easingChanged(e);
2493 if (d->group)
2494 d->animationGroupDirty();
2495}
2496
2497QObject *QQuickPropertyAnimation::target() const
2498{
2499 Q_D(const QQuickPropertyAnimation);
2500 return d->target;
2501}
2502
2503void QQuickPropertyAnimation::setTargetObject(QObject *o)
2504{
2505 Q_D(QQuickPropertyAnimation);
2506 if (d->target == o)
2507 return;
2508 d->target = o;
2509 emit targetChanged();
2510 if (d->group)
2511 d->animationGroupDirty();
2512}
2513
2514QString QQuickPropertyAnimation::property() const
2515{
2516 Q_D(const QQuickPropertyAnimation);
2517 return d->propertyName;
2518}
2519
2520void QQuickPropertyAnimation::setProperty(const QString &n)
2521{
2522 Q_D(QQuickPropertyAnimation);
2523 if (d->propertyName == n)
2524 return;
2525 d->propertyName = n;
2526 emit propertyChanged();
2527 if (d->group)
2528 d->animationGroupDirty();
2529}
2530
2531QString QQuickPropertyAnimation::properties() const
2532{
2533 Q_D(const QQuickPropertyAnimation);
2534 return d->properties;
2535}
2536
2537void QQuickPropertyAnimation::setProperties(const QString &prop)
2538{
2539 Q_D(QQuickPropertyAnimation);
2540 if (d->properties == prop)
2541 return;
2542
2543 d->properties = prop;
2544 emit propertiesChanged(prop);
2545 if (d->group)
2546 d->animationGroupDirty();
2547}
2548
2549/*!
2550 \qmlproperty string QtQuick::PropertyAnimation::properties
2551 \qmlproperty list<QtObject> QtQuick::PropertyAnimation::targets
2552 \qmlproperty string QtQuick::PropertyAnimation::property
2553 \qmlproperty QtObject QtQuick::PropertyAnimation::target
2554
2555 These properties are used as a set to determine which properties should be animated.
2556 The singular and plural forms are functionally identical, e.g.
2557 \qml
2558 NumberAnimation { target: theItem; property: "x"; to: 500 }
2559 \endqml
2560 has the same meaning as
2561 \qml
2562 NumberAnimation { targets: theItem; properties: "x"; to: 500 }
2563 \endqml
2564 The singular forms are slightly optimized, so if you do have only a single target/property
2565 to animate you should try to use them.
2566
2567 The \c targets property allows multiple targets to be set. For example, this animates the
2568 \c x property of both \c itemA and \c itemB:
2569
2570 \qml
2571 NumberAnimation { targets: [itemA, itemB]; properties: "x"; to: 500 }
2572 \endqml
2573
2574 In many cases these properties do not need to be explicitly specified, as they can be
2575 inferred from the animation framework:
2576
2577 \table 80%
2578 \row
2579 \li Value Source / Behavior
2580 \li When an animation is used as a value source or in a Behavior, the default target and property
2581 name to be animated can both be inferred.
2582 \qml
2583 Rectangle {
2584 id: theRect
2585 width: 100; height: 100
2586 color: Qt.rgba(0,0,1)
2587 NumberAnimation on x { to: 500; loops: Animation.Infinite } //animate theRect's x property
2588 Behavior on y { NumberAnimation {} } //animate theRect's y property
2589 }
2590 \endqml
2591 \row
2592 \li Transition
2593 \li When used in a transition, a property animation is assumed to match \e all targets
2594 but \e no properties. In practice, that means you need to specify at least the properties
2595 in order for the animation to do anything.
2596 \qml
2597 Rectangle {
2598 id: theRect
2599 width: 100; height: 100
2600 color: Qt.rgba(0,0,1)
2601 Item { id: uselessItem }
2602 states: State {
2603 name: "state1"
2604 PropertyChanges {
2605 theRect {
2606 x: 200
2607 y: 200
2608 z: 4
2609 }
2610 uselessItem {
2611 x: 10
2612 y: 10
2613 z: 2
2614 }
2615 }
2616 }
2617 transitions: Transition {
2618 //animate both theRect's and uselessItem's x and y to their final values
2619 NumberAnimation { properties: "x,y" }
2620
2621 //animate theRect's z to its final value
2622 NumberAnimation { target: theRect; property: "z" }
2623 }
2624 }
2625 \endqml
2626 \row
2627 \li Standalone
2628 \li When an animation is used standalone, both the target and property need to be
2629 explicitly specified.
2630 \qml
2631 Rectangle {
2632 id: theRect
2633 width: 100; height: 100
2634 color: Qt.rgba(0,0,1)
2635 //need to explicitly specify target and property
2636 NumberAnimation { id: theAnim; target: theRect; property: "x"; to: 500 }
2637 MouseArea {
2638 anchors.fill: parent
2639 onClicked: theAnim.start()
2640 }
2641 }
2642 \endqml
2643 \endtable
2644
2645 As seen in the above example, properties is specified as a comma-separated string of property names to animate.
2646
2647 \sa exclude, {Animation and Transitions in Qt Quick}
2648*/
2649QQmlListProperty<QObject> QQuickPropertyAnimation::targets()
2650{
2651 Q_D(QQuickPropertyAnimation);
2652 using ListPtr = QList<QPointer<QObject>> *;
2653 using LP = QQmlListProperty<QObject>;
2654 LP::AppendFunction appendFn = [](LP *prop, QObject *value)
2655 {
2656 static_cast<ListPtr>(prop->data)->append(t: value);
2657 };
2658 LP::CountFunction countFn = [](LP *prop)
2659 {
2660 return static_cast<ListPtr>(prop->data)->size();
2661 };
2662
2663 LP::AtFunction atFn = [](LP *prop, qsizetype index) -> QObject *
2664 {
2665 return static_cast<ListPtr>(prop->data)->at(i: index);
2666 };
2667
2668 LP::ClearFunction clearFN = [](LP *prop)
2669 {
2670 return static_cast<ListPtr>(prop->data)->clear();
2671 };
2672
2673 LP::ReplaceFunction replaceFn = [](LP *prop, qsizetype index, QObject *value)
2674 {
2675 static_cast<ListPtr>(prop->data)->replace(i: index, t: value);
2676 };
2677
2678 LP::RemoveLastFunction removeLastFn = [](LP *prop)
2679 {
2680 static_cast<ListPtr>(prop->data)->removeLast();
2681 };
2682
2683 return QQmlListProperty<QObject>(this, &(d->targets), appendFn, countFn, atFn, clearFN, replaceFn, removeLastFn);
2684}
2685
2686/*!
2687 \qmlproperty list<QtObject> QtQuick::PropertyAnimation::exclude
2688 This property holds the items not to be affected by this animation.
2689 \sa PropertyAnimation::targets
2690*/
2691QQmlListProperty<QObject> QQuickPropertyAnimation::exclude()
2692{
2693 Q_D(QQuickPropertyAnimation);
2694 return QQmlListProperty<QObject>(this, &(d->exclude));
2695}
2696
2697void QQuickAnimationPropertyUpdater::setValue(qreal v)
2698{
2699 bool deleted = false;
2700 wasDeleted = &deleted;
2701 if (reverse)
2702 v = 1 - v;
2703 for (int ii = 0; ii < actions.size(); ++ii) {
2704 QQuickStateAction &action = actions[ii];
2705
2706 if (v == 1.) {
2707 QQmlPropertyPrivate::write(that: action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
2708 } else {
2709 if (!fromIsSourced && !fromIsDefined) {
2710 action.fromValue = action.property.read();
2711 if (interpolatorType) {
2712 QQuickPropertyAnimationPrivate::convertVariant(variant&: action.fromValue, type: QMetaType(interpolatorType));
2713 }
2714 }
2715 if (!interpolatorType) {
2716 int propType = action.property.propertyType();
2717 if (!prevInterpolatorType || prevInterpolatorType != propType) {
2718 prevInterpolatorType = propType;
2719 interpolator = QVariantAnimationPrivate::getInterpolator(interpolationType: prevInterpolatorType);
2720 }
2721 }
2722 if (interpolator)
2723 QQmlPropertyPrivate::write(that: action.property, interpolator(action.fromValue.constData(), action.toValue.constData(), v), QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
2724 }
2725 if (deleted)
2726 return;
2727 }
2728 wasDeleted = nullptr;
2729 fromIsSourced = true;
2730}
2731
2732void QQuickAnimationPropertyUpdater::debugUpdater(QDebug d, int indentLevel) const
2733{
2734 QByteArray ind(indentLevel, ' ');
2735 for (int i = 0; i < actions.size(); ++i) {
2736 const QQuickStateAction &action = actions.at(i);
2737 d << "\n" << ind.constData() << "target:" << action.property.object() << "property:" << action.property.name()
2738 << "from:" << action.fromValue << "to:" << action.toValue;
2739 }
2740}
2741
2742QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateActions &actions,
2743 QQmlProperties &modified,
2744 QObject *defaultTarget)
2745{
2746 Q_D(QQuickPropertyAnimation);
2747 QQuickStateActions newActions;
2748
2749 QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(sep: QLatin1Char(','));
2750 for (int ii = 0; ii < props.size(); ++ii)
2751 props[ii] = props.at(i: ii).trimmed();
2752 if (!d->propertyName.isEmpty())
2753 props << d->propertyName;
2754
2755 QList<QPointer<QObject>> targets = d->targets;
2756 if (d->target)
2757 targets.append(t: d->target);
2758
2759 bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty();
2760 bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ? true : false;
2761
2762 if (d->defaultProperty.isValid() && !hasSelectors) {
2763 props << d->defaultProperty.name();
2764 targets << d->defaultProperty.object();
2765 }
2766
2767 if (defaultTarget && targets.isEmpty())
2768 targets << defaultTarget;
2769
2770 bool usingDefaultProperties = false;
2771 if (props.isEmpty() && !d->defaultProperties.isEmpty()) {
2772 props << d->defaultProperties.split(sep: QLatin1Char(','));
2773 usingDefaultProperties = true;
2774 }
2775
2776 bool hasExplicit = false;
2777 //an explicit animation has been specified
2778 if (d->toIsDefined) {
2779 QVector<QString> errorMessages;
2780 bool successfullyCreatedDefaultProperty = false;
2781
2782 for (int i = 0; i < props.size(); ++i) {
2783 for (int j = 0; j < targets.size(); ++j) {
2784 const auto& guarded = targets.at(i: j);
2785 if (guarded.isNull())
2786 continue;
2787 QObject *target = guarded.get();
2788 QQuickStateAction myAction;
2789 QString errorMessage;
2790 const QString &propertyName = props.at(i);
2791 myAction.property = d->createProperty(obj: target, str: propertyName, infoObj: this, errorMessage: &errorMessage);
2792 if (myAction.property.isValid()) {
2793 if (usingDefaultProperties)
2794 successfullyCreatedDefaultProperty = true;
2795
2796 if (d->fromIsDefined) {
2797 myAction.fromValue = d->from;
2798 d->convertVariant(variant&: myAction.fromValue, type: d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
2799 }
2800 myAction.toValue = d->to;
2801 d->convertVariant(variant&: myAction.toValue, type: d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
2802 newActions << myAction;
2803 hasExplicit = true;
2804 for (int ii = 0; ii < actions.size(); ++ii) {
2805 QQuickStateAction &action = actions[ii];
2806 if (action.property.object() == myAction.property.object() &&
2807 myAction.property.name() == action.property.name()) {
2808 modified << action.property;
2809 break; //### any chance there could be multiples?
2810 }
2811 }
2812 } else {
2813 errorMessages.append(t: errorMessage);
2814 }
2815 }
2816 }
2817
2818 if (!successfullyCreatedDefaultProperty) {
2819 for (const QString &errorMessage : std::as_const(t&: errorMessages))
2820 qmlWarning(me: this) << errorMessage;
2821 }
2822 }
2823
2824 if (!hasExplicit)
2825 for (int ii = 0; ii < actions.size(); ++ii) {
2826 QQuickStateAction &action = actions[ii];
2827
2828 QObject *obj = action.property.object();
2829 QString propertyName = action.property.name();
2830 QObject *sObj = action.specifiedObject;
2831 QString sPropertyName = action.specifiedProperty;
2832 bool same = (obj == sObj);
2833
2834 if ((targets.isEmpty() || targets.contains(t: obj) || (!same && targets.contains(t: sObj))) &&
2835 (!d->exclude.contains(t: obj)) && (same || (!d->exclude.contains(t: sObj))) &&
2836 (props.contains(str: propertyName) || (!same && props.contains(str: sPropertyName))
2837 || (useType && action.property.propertyType() == d->interpolatorType))) {
2838 QQuickStateAction myAction = action;
2839
2840 if (d->fromIsDefined)
2841 myAction.fromValue = d->from;
2842 else
2843 myAction.fromValue = QVariant();
2844 if (d->toIsDefined)
2845 myAction.toValue = d->to;
2846
2847 d->convertVariant(variant&: myAction.fromValue, type: d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
2848 d->convertVariant(variant&: myAction.toValue, type: d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
2849
2850 modified << action.property;
2851
2852 newActions << myAction;
2853 action.fromValue = myAction.toValue;
2854 }
2855 }
2856 return newActions;
2857}
2858
2859QAbstractAnimationJob* QQuickPropertyAnimation::transition(QQuickStateActions &actions,
2860 QQmlProperties &modified,
2861 TransitionDirection direction,
2862 QObject *defaultTarget)
2863{
2864 Q_D(QQuickPropertyAnimation);
2865
2866 QQuickStateActions dataActions = createTransitionActions(actions, modified, defaultTarget);
2867
2868 QQuickBulkValueAnimator *animator = new QQuickBulkValueAnimator;
2869 animator->setDuration(d->duration);
2870 animator->setEasingCurve(d->easing);
2871
2872 if (!dataActions.isEmpty()) {
2873 QQuickAnimationPropertyUpdater *data = new QQuickAnimationPropertyUpdater;
2874 data->interpolatorType = d->interpolatorType;
2875 data->interpolator = d->interpolator;
2876 data->reverse = direction == Backward ? true : false;
2877 data->fromIsSourced = false;
2878 data->fromIsDefined = d->fromIsDefined;
2879 data->actions = dataActions;
2880 animator->setAnimValue(data);
2881 animator->setFromIsSourcedValue(&data->fromIsSourced);
2882 d->actions = &data->actions; //remove this?
2883 }
2884
2885 return initInstance(animation: animator);
2886}
2887
2888QQuickAnimationPropertyUpdater::~QQuickAnimationPropertyUpdater()
2889{
2890 if (wasDeleted) *wasDeleted = true;
2891}
2892
2893QT_END_NAMESPACE
2894
2895#include "moc_qquickanimation_p.cpp"
2896

source code of qtdeclarative/src/quick/util/qquickanimation.cpp