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