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

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