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 test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30
31#include <QtQml/private/qanimationgroupjob_p.h>
32#include <QtQml/private/qsequentialanimationgroupjob_p.h>
33#include <QtQml/private/qparallelanimationgroupjob_p.h>
34
35Q_DECLARE_METATYPE(QAbstractAnimationJob::State)
36
37class tst_QAnimationGroupJob : public QObject
38{
39 Q_OBJECT
40public Q_SLOTS:
41 void initTestCase();
42
43private slots:
44 void construction();
45 void emptyGroup();
46 void setCurrentTime();
47 void addChildTwice();
48};
49
50void tst_QAnimationGroupJob::initTestCase()
51{
52 qRegisterMetaType<QAbstractAnimationJob::State>(typeName: "QAbstractAnimationJob::State");
53}
54
55void tst_QAnimationGroupJob::construction()
56{
57 QSequentialAnimationGroupJob animationgroup;
58}
59
60class TestableGenericAnimation : public QAbstractAnimationJob
61{
62public:
63 TestableGenericAnimation(int duration = 250) : m_duration(duration) {}
64 int duration() const { return m_duration; }
65
66private:
67 int m_duration;
68};
69
70class UncontrolledAnimation : public QObject, public QAbstractAnimationJob
71{
72 Q_OBJECT
73public:
74 UncontrolledAnimation() { }
75
76 int duration() const { return -1; /* not time driven */ }
77
78protected:
79 void timerEvent(QTimerEvent *event)
80 {
81 if (event->timerId() == id)
82 stop();
83 }
84
85 void updateRunning(bool running)
86 {
87 if (running) {
88 id = startTimer(interval: 500);
89 } else {
90 killTimer(id);
91 id = 0;
92 }
93 }
94
95private:
96 int id = 0;
97};
98
99class StateChangeListener: public QAnimationJobChangeListener
100{
101public:
102 virtual void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
103 {
104 states << newState;
105 }
106
107 int count()
108 {
109 return states.count();
110 }
111
112 QList<QAbstractAnimationJob::State> states;
113};
114
115void tst_QAnimationGroupJob::emptyGroup()
116{
117 QSequentialAnimationGroupJob group;
118 StateChangeListener groupStateChangedSpy;
119 group.addAnimationChangeListener(listener: &groupStateChangedSpy, QAbstractAnimationJob::StateChange);
120
121 QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
122 group.start();
123
124 QCOMPARE(groupStateChangedSpy.count(), 2);
125
126 QCOMPARE(groupStateChangedSpy.states.at(0), QAnimationGroupJob::Running);
127 QCOMPARE(groupStateChangedSpy.states.at(1), QAnimationGroupJob::Stopped);
128
129 QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
130
131 QTest::ignoreMessage(type: QtWarningMsg, message: "QAbstractAnimationJob::pause: Cannot pause a stopped animation");
132 group.pause();
133
134 QCOMPARE(groupStateChangedSpy.count(), 2);
135 QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
136
137 group.start();
138
139 QCOMPARE(groupStateChangedSpy.states.at(2),
140 QAnimationGroupJob::Running);
141 QCOMPARE(groupStateChangedSpy.states.at(3),
142 QAnimationGroupJob::Stopped);
143
144 QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
145
146 group.stop();
147
148 QCOMPARE(groupStateChangedSpy.count(), 4);
149 QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
150}
151
152void tst_QAnimationGroupJob::setCurrentTime()
153{
154 // was originally sequence operating on same object/property
155 QSequentialAnimationGroupJob *sequence = new QSequentialAnimationGroupJob();
156 QAbstractAnimationJob *a1_s_o1 = new TestableGenericAnimation;
157 QAbstractAnimationJob *a2_s_o1 = new TestableGenericAnimation;
158 QAbstractAnimationJob *a3_s_o1 = new TestableGenericAnimation;
159 a2_s_o1->setLoopCount(3);
160 sequence->appendAnimation(animation: a1_s_o1);
161 sequence->appendAnimation(animation: a2_s_o1);
162 sequence->appendAnimation(animation: a3_s_o1);
163
164 // was originally sequence operating on different object/properties
165 QAnimationGroupJob *sequence2 = new QSequentialAnimationGroupJob();
166 QAbstractAnimationJob *a1_s_o2 = new TestableGenericAnimation;
167 QAbstractAnimationJob *a1_s_o3 = new TestableGenericAnimation;
168 sequence2->appendAnimation(animation: a1_s_o2);
169 sequence2->appendAnimation(animation: a1_s_o3);
170
171 // was originally parallel operating on different object/properties
172 QAnimationGroupJob *parallel = new QParallelAnimationGroupJob();
173 QAbstractAnimationJob *a1_p_o1 = new TestableGenericAnimation;
174 QAbstractAnimationJob *a1_p_o2 = new TestableGenericAnimation;
175 QAbstractAnimationJob *a1_p_o3 = new TestableGenericAnimation;
176 a1_p_o2->setLoopCount(3);
177 parallel->appendAnimation(animation: a1_p_o1);
178 parallel->appendAnimation(animation: a1_p_o2);
179 parallel->appendAnimation(animation: a1_p_o3);
180
181 QAbstractAnimationJob *notTimeDriven = new UncontrolledAnimation;
182 QCOMPARE(notTimeDriven->totalDuration(), -1);
183
184 QAbstractAnimationJob *loopsForever = new TestableGenericAnimation;
185 loopsForever->setLoopCount(-1);
186 QCOMPARE(loopsForever->totalDuration(), -1);
187
188 QParallelAnimationGroupJob group;
189 group.appendAnimation(animation: sequence);
190 group.appendAnimation(animation: sequence2);
191 group.appendAnimation(animation: parallel);
192 group.appendAnimation(animation: notTimeDriven);
193 group.appendAnimation(animation: loopsForever);
194
195 // Current time = 1
196 group.setCurrentTime(1);
197 QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
198 QCOMPARE(sequence->state(), QAnimationGroupJob::Stopped);
199 QCOMPARE(a1_s_o1->state(), QAnimationGroupJob::Stopped);
200 QCOMPARE(sequence2->state(), QAnimationGroupJob::Stopped);
201 QCOMPARE(a1_s_o2->state(), QAnimationGroupJob::Stopped);
202 QCOMPARE(parallel->state(), QAnimationGroupJob::Stopped);
203 QCOMPARE(a1_p_o1->state(), QAnimationGroupJob::Stopped);
204 QCOMPARE(a1_p_o2->state(), QAnimationGroupJob::Stopped);
205 QCOMPARE(a1_p_o3->state(), QAnimationGroupJob::Stopped);
206 QCOMPARE(notTimeDriven->state(), QAnimationGroupJob::Stopped);
207 QCOMPARE(loopsForever->state(), QAnimationGroupJob::Stopped);
208
209 QCOMPARE(group.currentLoopTime(), 1);
210 QCOMPARE(sequence->currentLoopTime(), 1);
211 QCOMPARE(a1_s_o1->currentLoopTime(), 1);
212 QCOMPARE(a2_s_o1->currentLoopTime(), 0);
213 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
214 QCOMPARE(a1_s_o2->currentLoopTime(), 1);
215 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
216 QCOMPARE(a1_p_o1->currentLoopTime(), 1);
217 QCOMPARE(a1_p_o2->currentLoopTime(), 1);
218 QCOMPARE(a1_p_o3->currentLoopTime(), 1);
219 QCOMPARE(notTimeDriven->currentLoopTime(), 1);
220 QCOMPARE(loopsForever->currentLoopTime(), 1);
221
222 // Current time = 250
223 group.setCurrentTime(250);
224 QCOMPARE(group.currentLoopTime(), 250);
225 QCOMPARE(sequence->currentLoopTime(), 250);
226 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
227 QCOMPARE(a2_s_o1->currentLoopTime(), 0);
228 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
229 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
230 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
231 QCOMPARE(a1_p_o1->currentLoopTime(), 250);
232 QCOMPARE(a1_p_o2->currentLoopTime(), 0);
233 QCOMPARE(a1_p_o2->currentLoop(), 1);
234 QCOMPARE(a1_p_o3->currentLoopTime(), 250);
235 QCOMPARE(notTimeDriven->currentLoopTime(), 250);
236 QCOMPARE(loopsForever->currentLoopTime(), 0);
237 QCOMPARE(loopsForever->currentLoop(), 1);
238 QCOMPARE(sequence->currentAnimation(), a2_s_o1);
239
240 // Current time = 251
241 group.setCurrentTime(251);
242 QCOMPARE(group.currentLoopTime(), 251);
243 QCOMPARE(sequence->currentLoopTime(), 251);
244 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
245 QCOMPARE(a2_s_o1->currentLoopTime(), 1);
246 QCOMPARE(a2_s_o1->currentLoop(), 0);
247 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
248 QCOMPARE(sequence2->currentLoopTime(), 251);
249 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
250 QCOMPARE(a1_s_o3->currentLoopTime(), 1);
251 QCOMPARE(a1_p_o1->currentLoopTime(), 250);
252 QCOMPARE(a1_p_o2->currentLoopTime(), 1);
253 QCOMPARE(a1_p_o2->currentLoop(), 1);
254 QCOMPARE(a1_p_o3->currentLoopTime(), 250);
255 QCOMPARE(notTimeDriven->currentLoopTime(), 251);
256 QCOMPARE(loopsForever->currentLoopTime(), 1);
257 QCOMPARE(sequence->currentAnimation(), a2_s_o1);
258}
259
260void tst_QAnimationGroupJob::addChildTwice()
261{
262 QAbstractAnimationJob *subGroup;
263 QAbstractAnimationJob *subGroup2;
264 auto *parent = new QSequentialAnimationGroupJob();
265
266 subGroup = new QAbstractAnimationJob;
267 parent->appendAnimation(animation: subGroup);
268 parent->appendAnimation(animation: subGroup);
269 QVERIFY(parent->firstChild());
270 QVERIFY(!parent->firstChild()->nextSibling());
271 QVERIFY(!parent->firstChild()->previousSibling());
272
273 parent->clear();
274
275 QCOMPARE(parent->currentAnimation(), nullptr);
276 QVERIFY(!parent->firstChild());
277
278 // adding the same item twice to a group will remove the item from its current position
279 // and append it to the end
280 subGroup = new QAbstractAnimationJob;
281 parent->appendAnimation(animation: subGroup);
282 subGroup2 = new QAbstractAnimationJob;
283 parent->appendAnimation(animation: subGroup2);
284
285 QCOMPARE(parent->firstChild(), subGroup);
286 QCOMPARE(parent->lastChild(), subGroup2);
287
288 parent->appendAnimation(animation: subGroup);
289
290 QCOMPARE(parent->firstChild(), subGroup2);
291 QCOMPARE(parent->lastChild(), subGroup);
292
293 delete parent;
294}
295
296QTEST_MAIN(tst_QAnimationGroupJob)
297#include "tst_qanimationgroupjob.moc"
298

source code of qtdeclarative/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp