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