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