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#include <QtCore/qanimationgroup.h>
31#include <QtCore/qsequentialanimationgroup.h>
32
33Q_DECLARE_METATYPE(QAbstractAnimation::State)
34
35class tst_QSequentialAnimationGroup : public QObject
36{
37 Q_OBJECT
38public Q_SLOTS:
39 void initTestCase();
40
41private slots:
42 void construction();
43 void setCurrentTime();
44 void setCurrentTimeWithUncontrolledAnimation();
45 void seekingForwards();
46 void seekingBackwards();
47 void pauseAndResume();
48 void restart();
49 void looping();
50 void startDelay();
51 void clearGroup();
52 void groupWithZeroDurationAnimations();
53 void propagateGroupUpdateToChildren();
54 void updateChildrenWithRunningGroup();
55 void deleteChildrenWithRunningGroup();
56 void startChildrenWithStoppedGroup();
57 void stopGroupWithRunningChild();
58 void startGroupWithRunningChild();
59 void zeroDurationAnimation();
60 void stopUncontrolledAnimations();
61 void finishWithUncontrolledAnimation();
62 void addRemoveAnimation();
63 void currentAnimation();
64 void currentAnimationWithZeroDuration();
65 void insertAnimation();
66 void clear();
67 void pauseResume();
68};
69
70void tst_QSequentialAnimationGroup::initTestCase()
71{
72 qRegisterMetaType<QAbstractAnimation::State>(typeName: "QAbstractAnimation::State");
73}
74
75void tst_QSequentialAnimationGroup::construction()
76{
77 QSequentialAnimationGroup animationgroup;
78}
79
80class AnimationObject : public QObject
81{
82 Q_OBJECT
83 Q_PROPERTY(int value READ value WRITE setValue)
84public:
85 AnimationObject(int startValue = 0)
86 : v(startValue)
87 { }
88
89 int value() const { return v; }
90 void setValue(int value) { v = value; }
91
92 int v;
93};
94
95class TestAnimation : public QVariantAnimation
96{
97 Q_OBJECT
98public:
99 virtual void updateCurrentValue(const QVariant &value) { Q_UNUSED(value)};
100 virtual void updateState(QAbstractAnimation::State newState,
101 QAbstractAnimation::State oldState)
102 {
103 Q_UNUSED(oldState)
104 Q_UNUSED(newState)
105 };
106};
107
108class DummyPropertyAnimation : public QPropertyAnimation
109{
110public:
111 DummyPropertyAnimation(QObject *parent = 0) : QPropertyAnimation(parent)
112 {
113 setTargetObject(&o);
114 this->setPropertyName("value");
115 setEndValue(0);
116 }
117
118 AnimationObject o;
119};
120
121class UncontrolledAnimation : public QPropertyAnimation
122{
123 Q_OBJECT
124public:
125 UncontrolledAnimation(QObject *target, QObject *parent = 0)
126 : QPropertyAnimation(target, "value", parent)
127 {
128 setDuration(250);
129 setEndValue(0);
130 }
131
132 int duration() const { return -1; /* not time driven */ }
133
134protected:
135 void updateCurrentTime(int currentTime)
136 {
137 QPropertyAnimation::updateCurrentTime(currentTime);
138 if (currentTime >= QPropertyAnimation::duration())
139 stop();
140 }
141};
142
143void tst_QSequentialAnimationGroup::setCurrentTime()
144{
145 // sequence operating on same object/property
146 QAnimationGroup *sequence = new QSequentialAnimationGroup();
147 QVariantAnimation *a1_s_o1 = new DummyPropertyAnimation;
148 QVariantAnimation *a2_s_o1 = new DummyPropertyAnimation;
149 QVariantAnimation *a3_s_o1 = new DummyPropertyAnimation;
150 a2_s_o1->setLoopCount(3);
151 sequence->addAnimation(animation: a1_s_o1);
152 sequence->addAnimation(animation: a2_s_o1);
153 sequence->addAnimation(animation: a3_s_o1);
154
155 // sequence operating on different object/properties
156 QAnimationGroup *sequence2 = new QSequentialAnimationGroup();
157 QVariantAnimation *a1_s_o2 = new DummyPropertyAnimation;
158 QVariantAnimation *a1_s_o3 = new DummyPropertyAnimation;
159 sequence2->addAnimation(animation: a1_s_o2);
160 sequence2->addAnimation(animation: a1_s_o3);
161
162 QSequentialAnimationGroup group;
163 group.addAnimation(animation: sequence);
164 group.addAnimation(animation: sequence2);
165
166 // Current time = 1
167 group.setCurrentTime(1);
168 QCOMPARE(group.state(), QAnimationGroup::Stopped);
169 QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
170 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
171 QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
172 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
173
174 QCOMPARE(group.currentLoopTime(), 1);
175 QCOMPARE(sequence->currentLoopTime(), 1);
176 QCOMPARE(a1_s_o1->currentLoopTime(), 1);
177 QCOMPARE(a2_s_o1->currentLoopTime(), 0);
178 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
179 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
180 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
181
182 // Current time = 250
183 group.setCurrentTime(250);
184 QCOMPARE(group.currentLoopTime(), 250);
185 QCOMPARE(sequence->currentLoopTime(), 250);
186 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
187 QCOMPARE(a2_s_o1->currentLoopTime(), 0);
188 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
189 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
190 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
191
192 // Current time = 251
193 group.setCurrentTime(251);
194 QCOMPARE(group.currentLoopTime(), 251);
195 QCOMPARE(sequence->currentLoopTime(), 251);
196 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
197 QCOMPARE(a2_s_o1->currentLoopTime(), 1);
198 QCOMPARE(a2_s_o1->currentLoop(), 0);
199 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
200 QCOMPARE(sequence2->currentLoopTime(), 0);
201 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
202 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
203
204 // Current time = 750
205 group.setCurrentTime(750);
206 QCOMPARE(group.currentLoopTime(), 750);
207 QCOMPARE(sequence->currentLoopTime(), 750);
208 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
209 QCOMPARE(a2_s_o1->currentLoopTime(), 0);
210 QCOMPARE(a2_s_o1->currentLoop(), 2);
211 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
212 QCOMPARE(sequence2->currentLoopTime(), 0);
213 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
214 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
215
216 // Current time = 1000
217 group.setCurrentTime(1000);
218 QCOMPARE(group.currentLoopTime(), 1000);
219 QCOMPARE(sequence->currentLoopTime(), 1000);
220 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
221 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
222 QCOMPARE(a2_s_o1->currentLoop(), 2);
223 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
224 QCOMPARE(sequence2->currentLoopTime(), 0);
225 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
226 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
227
228 // Current time = 1010
229 group.setCurrentTime(1010);
230 QCOMPARE(group.currentLoopTime(), 1010);
231 QCOMPARE(sequence->currentLoopTime(), 1010);
232 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
233 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
234 QCOMPARE(a2_s_o1->currentLoop(), 2);
235 QCOMPARE(a3_s_o1->currentLoopTime(), 10);
236 QCOMPARE(sequence2->currentLoopTime(), 0);
237 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
238 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
239
240 // Current time = 1250
241 group.setCurrentTime(1250);
242 QCOMPARE(group.currentLoopTime(), 1250);
243 QCOMPARE(sequence->currentLoopTime(), 1250);
244 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
245 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
246 QCOMPARE(a2_s_o1->currentLoop(), 2);
247 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
248 QCOMPARE(sequence2->currentLoopTime(), 0);
249 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
250 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
251
252 // Current time = 1500
253 group.setCurrentTime(1500);
254 QCOMPARE(group.currentLoopTime(), 1500);
255 QCOMPARE(sequence->currentLoopTime(), 1250);
256 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
257 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
258 QCOMPARE(a2_s_o1->currentLoop(), 2);
259 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
260 QCOMPARE(sequence2->currentLoopTime(), 250);
261 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
262 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
263
264 // Current time = 1750
265 group.setCurrentTime(1750);
266 QCOMPARE(group.currentLoopTime(), 1750);
267 QCOMPARE(sequence->currentLoopTime(), 1250);
268 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
269 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
270 QCOMPARE(a2_s_o1->currentLoop(), 2);
271 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
272 QCOMPARE(sequence2->currentLoopTime(), 500);
273 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
274 QCOMPARE(a1_s_o3->currentLoopTime(), 250);
275
276 // Current time = 2000
277 group.setCurrentTime(2000);
278 QCOMPARE(group.currentLoopTime(), 1750);
279 QCOMPARE(sequence->currentLoopTime(), 1250);
280 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
281 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
282 QCOMPARE(a2_s_o1->currentLoop(), 2);
283 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
284 QCOMPARE(sequence2->currentLoopTime(), 500);
285 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
286 QCOMPARE(a1_s_o3->currentLoopTime(), 250);
287}
288
289void tst_QSequentialAnimationGroup::setCurrentTimeWithUncontrolledAnimation()
290{
291 AnimationObject t_o1;
292
293 // sequence operating on different object/properties
294 QAnimationGroup *sequence = new QSequentialAnimationGroup();
295 QPropertyAnimation *a1_s_o1 = new DummyPropertyAnimation;
296 QPropertyAnimation *a1_s_o2 = new DummyPropertyAnimation;
297 sequence->addAnimation(animation: a1_s_o1);
298 sequence->addAnimation(animation: a1_s_o2);
299
300 QPropertyAnimation *notTimeDriven = new UncontrolledAnimation(&t_o1);
301 QCOMPARE(notTimeDriven->totalDuration(), -1);
302
303 QAbstractAnimation *loopsForever = new DummyPropertyAnimation;
304 loopsForever->setLoopCount(-1);
305 QCOMPARE(loopsForever->totalDuration(), -1);
306
307 QSequentialAnimationGroup group;
308 group.addAnimation(animation: sequence);
309 group.addAnimation(animation: notTimeDriven);
310 group.addAnimation(animation: loopsForever);
311 group.start();
312 group.pause(); // this allows the group to listen for the finish signal of its children
313
314 // Current time = 1
315 group.setCurrentTime(1);
316 QCOMPARE(group.state(), QAnimationGroup::Paused);
317 QCOMPARE(sequence->state(), QAnimationGroup::Paused);
318 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Paused);
319 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
320 QCOMPARE(notTimeDriven->state(), QAnimationGroup::Stopped);
321 QCOMPARE(loopsForever->state(), QAnimationGroup::Stopped);
322
323 QCOMPARE(group.currentLoopTime(), 1);
324 QCOMPARE(sequence->currentLoopTime(), 1);
325 QCOMPARE(a1_s_o1->currentLoopTime(), 1);
326 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
327 QCOMPARE(notTimeDriven->currentLoopTime(), 0);
328 QCOMPARE(loopsForever->currentLoopTime(), 0);
329
330 // Current time = 250
331 group.setCurrentTime(250);
332 QCOMPARE(group.currentLoopTime(), 250);
333 QCOMPARE(sequence->currentLoopTime(), 250);
334 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
335 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
336 QCOMPARE(notTimeDriven->currentLoopTime(), 0);
337 QCOMPARE(loopsForever->currentLoopTime(), 0);
338
339 // Current time = 500
340 group.setCurrentTime(500);
341 QCOMPARE(group.currentLoopTime(), 500);
342 QCOMPARE(sequence->currentLoopTime(), 500);
343 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
344 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
345 QCOMPARE(notTimeDriven->currentLoopTime(), 0);
346 QCOMPARE(loopsForever->currentLoopTime(), 0);
347 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation *>(notTimeDriven));
348
349 // Current time = 505
350 group.setCurrentTime(505);
351 QCOMPARE(group.currentLoopTime(), 505);
352 QCOMPARE(sequence->currentLoopTime(), 500);
353 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
354 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
355 QCOMPARE(notTimeDriven->currentLoopTime(), 5);
356 QCOMPARE(loopsForever->currentLoopTime(), 0);
357 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation *>(notTimeDriven));
358 QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
359 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
360 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
361 QCOMPARE(notTimeDriven->state(), QAnimationGroup::Paused);
362 QCOMPARE(loopsForever->state(), QAnimationGroup::Stopped);
363
364 // Current time = 750 (end of notTimeDriven animation)
365 group.setCurrentTime(750);
366 QCOMPARE(group.currentLoopTime(), 750);
367 QCOMPARE(sequence->currentLoopTime(), 500);
368 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
369 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
370 QCOMPARE(notTimeDriven->currentLoopTime(), 250);
371 QCOMPARE(loopsForever->currentLoopTime(), 0);
372 QCOMPARE(group.currentAnimation(), loopsForever);
373 QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
374 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
375 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
376 QCOMPARE(notTimeDriven->state(), QAnimationGroup::Stopped);
377 QCOMPARE(loopsForever->state(), QAnimationGroup::Paused);
378
379 // Current time = 800 (as notTimeDriven was finished at 750, loopsforever should still run)
380 group.setCurrentTime(800);
381 QCOMPARE(group.currentLoopTime(), 800);
382 QCOMPARE(group.currentAnimation(), loopsForever);
383 QCOMPARE(sequence->currentLoopTime(), 500);
384 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
385 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
386 QCOMPARE(notTimeDriven->currentLoopTime(), 250);
387 QCOMPARE(loopsForever->currentLoopTime(), 50);
388
389 loopsForever->stop(); // this should stop the group
390
391 QCOMPARE(group.state(), QAnimationGroup::Stopped);
392 QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
393 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
394 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
395 QCOMPARE(notTimeDriven->state(), QAnimationGroup::Stopped);
396 QCOMPARE(loopsForever->state(), QAnimationGroup::Stopped);
397}
398
399void tst_QSequentialAnimationGroup::seekingForwards()
400{
401
402 // sequence operating on same object/property
403 QAnimationGroup *sequence = new QSequentialAnimationGroup;
404 QVariantAnimation *a1_s_o1 = new DummyPropertyAnimation;
405 QVariantAnimation *a2_s_o1 = new DummyPropertyAnimation;
406 QVariantAnimation *a3_s_o1 = new DummyPropertyAnimation;
407 a2_s_o1->setLoopCount(3);
408 sequence->addAnimation(animation: a1_s_o1);
409 sequence->addAnimation(animation: a2_s_o1);
410 sequence->addAnimation(animation: a3_s_o1);
411
412 // sequence operating on different object/properties
413 QAnimationGroup *sequence2 = new QSequentialAnimationGroup;
414 QVariantAnimation *a1_s_o2 = new DummyPropertyAnimation;
415 QVariantAnimation *a1_s_o3 = new DummyPropertyAnimation;
416 sequence2->addAnimation(animation: a1_s_o2);
417 sequence2->addAnimation(animation: a1_s_o3);
418
419 QSequentialAnimationGroup group;
420 group.addAnimation(animation: sequence);
421 group.addAnimation(animation: sequence2);
422
423 // Current time = 1
424 group.setCurrentTime(1);
425 QCOMPARE(group.state(), QAnimationGroup::Stopped);
426 QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
427 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
428 QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
429 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
430 QCOMPARE(a1_s_o3->state(), QAnimationGroup::Stopped);
431
432 QCOMPARE(group.currentLoopTime(), 1);
433 QCOMPARE(sequence->currentLoopTime(), 1);
434 QCOMPARE(a1_s_o1->currentLoopTime(), 1);
435 QCOMPARE(a2_s_o1->currentLoopTime(), 0);
436 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
437 QCOMPARE(sequence2->currentLoopTime(), 0);
438 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
439 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
440
441 // Current time = 1500
442 group.setCurrentTime(1500);
443 QCOMPARE(group.currentLoopTime(), 1500);
444 QCOMPARE(sequence->currentLoopTime(), 1250);
445 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
446 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
447 QCOMPARE(a2_s_o1->currentLoop(), 2);
448 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
449 QCOMPARE(sequence2->currentLoopTime(), 250);
450 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
451 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
452
453 // this will restart the group
454 group.start();
455 group.pause();
456 QCOMPARE(group.state(), QAnimationGroup::Paused);
457 QCOMPARE(sequence->state(), QAnimationGroup::Paused);
458 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Paused);
459 QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
460 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
461 QCOMPARE(a1_s_o3->state(), QAnimationGroup::Stopped);
462
463 // Current time = 1750
464 group.setCurrentTime(1750);
465 QCOMPARE(group.currentLoopTime(), 1750);
466 QCOMPARE(sequence->currentLoopTime(), 1250);
467 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
468 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
469 QCOMPARE(a2_s_o1->currentLoop(), 2);
470 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
471 QCOMPARE(sequence2->currentLoopTime(), 500);
472 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
473 QCOMPARE(a1_s_o3->currentLoopTime(), 250);
474}
475
476void tst_QSequentialAnimationGroup::seekingBackwards()
477{
478 // sequence operating on same object/property
479 QAnimationGroup *sequence = new QSequentialAnimationGroup();
480 QVariantAnimation *a1_s_o1 = new DummyPropertyAnimation;
481 QVariantAnimation *a2_s_o1 = new DummyPropertyAnimation;
482 QVariantAnimation *a3_s_o1 = new DummyPropertyAnimation;
483 a2_s_o1->setLoopCount(3);
484 sequence->addAnimation(animation: a1_s_o1);
485 sequence->addAnimation(animation: a2_s_o1);
486 sequence->addAnimation(animation: a3_s_o1);
487
488 // sequence operating on different object/properties
489 QAnimationGroup *sequence2 = new QSequentialAnimationGroup();
490 QVariantAnimation *a1_s_o2 = new DummyPropertyAnimation;
491 QVariantAnimation *a1_s_o3 = new DummyPropertyAnimation;
492 sequence2->addAnimation(animation: a1_s_o2);
493 sequence2->addAnimation(animation: a1_s_o3);
494
495 QSequentialAnimationGroup group;
496 group.addAnimation(animation: sequence);
497 group.addAnimation(animation: sequence2);
498
499 group.start();
500
501 // Current time = 1600
502 group.setCurrentTime(1600);
503 QCOMPARE(group.currentLoopTime(), 1600);
504 QCOMPARE(sequence->currentLoopTime(), 1250);
505 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
506 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
507 QCOMPARE(a2_s_o1->currentLoop(), 2);
508 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
509 QCOMPARE(sequence2->currentLoopTime(), 350);
510 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
511 QCOMPARE(a1_s_o3->currentLoopTime(), 100);
512
513 QCOMPARE(group.state(), QAnimationGroup::Running);
514 QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
515 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
516 QCOMPARE(sequence2->state(), QAnimationGroup::Running);
517 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
518 QCOMPARE(a1_s_o3->state(), QAnimationGroup::Running);
519
520 // Seeking backwards, current time = 1
521 group.setCurrentTime(1);
522 QCOMPARE(group.currentLoopTime(), 1);
523 QCOMPARE(sequence->currentLoopTime(), 1);
524 QCOMPARE(a1_s_o1->currentLoopTime(), 1);
525
526 QEXPECT_FAIL("", "rewinding in nested groups is considered as a restart from the children,"
527 "hence they don't reset from their current animation", Continue);
528 QCOMPARE(a2_s_o1->currentLoopTime(), 0);
529 QEXPECT_FAIL("", "rewinding in nested groups is considered as a restart from the children,"
530 "hence they don't reset from their current animation", Continue);
531 QCOMPARE(a2_s_o1->currentLoop(), 0);
532 QEXPECT_FAIL("", "rewinding in nested groups is considered as a restart from the children,"
533 "hence they don't reset from their current animation", Continue);
534 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
535 QCOMPARE(sequence2->currentLoopTime(), 0);
536 QCOMPARE(a1_s_o2->currentLoopTime(), 0);
537 QCOMPARE(a1_s_o3->currentLoopTime(), 0);
538
539 QCOMPARE(group.state(), QAnimationGroup::Running);
540 QCOMPARE(sequence->state(), QAnimationGroup::Running);
541 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Running);
542 QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
543 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
544 QCOMPARE(a1_s_o3->state(), QAnimationGroup::Stopped);
545
546 // Current time = 2000
547 group.setCurrentTime(2000);
548 QCOMPARE(group.currentLoopTime(), 1750);
549 QCOMPARE(sequence->currentLoopTime(), 1250);
550 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
551 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
552 QCOMPARE(a2_s_o1->currentLoop(), 2);
553 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
554 QCOMPARE(sequence2->currentLoopTime(), 500);
555 QCOMPARE(a1_s_o2->currentLoopTime(), 250);
556 QCOMPARE(a1_s_o3->currentLoopTime(), 250);
557
558 QCOMPARE(group.state(), QAnimationGroup::Stopped);
559 QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
560 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
561 QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
562 QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
563 QCOMPARE(a1_s_o3->state(), QAnimationGroup::Stopped);
564}
565
566typedef QVector<QAbstractAnimation::State> StateList;
567
568static bool compareStates(const QSignalSpy& spy, const StateList &expectedStates)
569{
570 bool equals = true;
571 for (int i = 0; i < qMax(a: expectedStates.count(), b: spy.count()); ++i) {
572 if (i >= spy.count() || i >= expectedStates.count()) {
573 equals = false;
574 break;
575 }
576 QList<QVariant> args = spy.at(i);
577 QAbstractAnimation::State st = expectedStates.at(i);
578 QAbstractAnimation::State actual = qvariant_cast<QAbstractAnimation::State>(v: args.first());
579 if (equals && actual != st) {
580 equals = false;
581 break;
582 }
583 }
584 if (!equals) {
585 const char *stateStrings[] = {"Stopped", "Paused", "Running"};
586 QString e,a;
587 for (int i = 0; i < qMax(a: expectedStates.count(), b: spy.count()); ++i) {
588 if (i < expectedStates.count()) {
589 int exp = int(expectedStates.at(i));
590 if (!e.isEmpty())
591 e += QLatin1String(", ");
592 e += QLatin1String(stateStrings[exp]);
593 }
594 if (i < spy.count()) {
595 QList<QVariant> args = spy.at(i);
596 QAbstractAnimation::State actual = qvariant_cast<QAbstractAnimation::State>(v: args.value(i: 1));
597 if (!a.isEmpty())
598 a += QLatin1String(", ");
599 if (int(actual) >= 0 && int(actual) <= 2) {
600 a += QLatin1String(stateStrings[int(actual)]);
601 } else {
602 a += QLatin1String("NaN");
603 }
604 }
605
606 }
607 qDebug(msg: "\n"
608 "expected (count == %d): %s\n"
609 "actual (count == %d): %s\n", expectedStates.count(), qPrintable(e), spy.count(), qPrintable(a));
610 }
611 return equals;
612}
613
614void tst_QSequentialAnimationGroup::pauseAndResume()
615{
616 // sequence operating on same object/property
617 QAnimationGroup *sequence = new QSequentialAnimationGroup();
618 QVariantAnimation *a1_s_o1 = new DummyPropertyAnimation;
619 QVariantAnimation *a2_s_o1 = new DummyPropertyAnimation;
620 QVariantAnimation *a3_s_o1 = new DummyPropertyAnimation;
621 a2_s_o1->setLoopCount(2);
622 sequence->addAnimation(animation: a1_s_o1);
623 sequence->addAnimation(animation: a2_s_o1);
624 sequence->addAnimation(animation: a3_s_o1);
625 sequence->setLoopCount(2);
626
627 QSignalSpy a1StateChangedSpy(a1_s_o1, &QVariantAnimation::stateChanged);
628 QSignalSpy seqStateChangedSpy(sequence, &QAnimationGroup::stateChanged);
629
630 QVERIFY(a1StateChangedSpy.isValid());
631 QVERIFY(seqStateChangedSpy.isValid());
632
633 QSequentialAnimationGroup group;
634 group.addAnimation(animation: sequence);
635
636 group.start();
637 group.pause();
638
639 // Current time = 1751
640 group.setCurrentTime(1751);
641 QCOMPARE(group.currentLoopTime(), 1751);
642 QCOMPARE(sequence->currentLoopTime(), 751);
643 QCOMPARE(sequence->currentLoop(), 1);
644 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
645 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
646 QCOMPARE(a2_s_o1->currentLoop(), 1);
647 QCOMPARE(a3_s_o1->currentLoop(), 0);
648 QCOMPARE(a3_s_o1->currentLoopTime(), 1);
649
650 QCOMPARE(group.state(), QAnimationGroup::Paused);
651 QCOMPARE(sequence->state(), QAnimationGroup::Paused);
652 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
653 QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
654 QCOMPARE(a3_s_o1->state(), QAnimationGroup::Paused);
655
656 QCOMPARE(a1StateChangedSpy.count(), 5); // Running,Paused,Stopped,Running,Stopped
657 QCOMPARE(seqStateChangedSpy.count(), 2); // Running,Paused
658
659 QVERIFY(compareStates(a1StateChangedSpy, (StateList() << QAbstractAnimation::Running
660 << QAbstractAnimation::Paused
661 << QAbstractAnimation::Stopped
662 << QAbstractAnimation::Running
663 << QAbstractAnimation::Stopped)));
664
665 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(a1StateChangedSpy.at(0).first()),
666 QAnimationGroup::Running);
667 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(a1StateChangedSpy.at(1).first()),
668 QAnimationGroup::Paused);
669 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(a1StateChangedSpy.at(2).first()),
670 QAnimationGroup::Stopped);
671 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(a1StateChangedSpy.at(3).first()),
672 QAnimationGroup::Running);
673 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(a1StateChangedSpy.at(4).first()),
674 QAnimationGroup::Stopped);
675
676 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(seqStateChangedSpy.at(0).first()),
677 QAnimationGroup::Running);
678 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(seqStateChangedSpy.at(1).first()),
679 QAnimationGroup::Paused);
680
681 group.resume();
682
683 QCOMPARE(group.state(), QAnimationGroup::Running);
684 QCOMPARE(sequence->state(), QAnimationGroup::Running);
685 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
686 QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
687 QCOMPARE(a3_s_o1->state(), QAnimationGroup::Running);
688
689 QVERIFY(group.currentLoopTime() >= 1751);
690 QVERIFY(sequence->currentLoopTime() >= 751);
691 QCOMPARE(sequence->currentLoop(), 1);
692 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
693 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
694 QCOMPARE(a2_s_o1->currentLoop(), 1);
695 QCOMPARE(a3_s_o1->currentLoop(), 0);
696 QVERIFY(a3_s_o1->currentLoopTime() >= 1);
697
698 QCOMPARE(seqStateChangedSpy.count(), 3); // Running,Paused,Running
699 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(seqStateChangedSpy.at(2).first()),
700 QAnimationGroup::Running);
701
702 group.pause();
703
704 QCOMPARE(group.state(), QAnimationGroup::Paused);
705 QCOMPARE(sequence->state(), QAnimationGroup::Paused);
706 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
707 QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
708 QCOMPARE(a3_s_o1->state(), QAnimationGroup::Paused);
709
710 QVERIFY(group.currentLoopTime() >= 1751);
711 QVERIFY(sequence->currentLoopTime() >= 751);
712 QCOMPARE(sequence->currentLoop(), 1);
713 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
714 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
715 QCOMPARE(a2_s_o1->currentLoop(), 1);
716 QCOMPARE(a3_s_o1->currentLoop(), 0);
717 QVERIFY(a3_s_o1->currentLoopTime() >= 1);
718
719 QCOMPARE(seqStateChangedSpy.count(), 4); // Running,Paused,Running,Paused
720 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(seqStateChangedSpy.at(3).first()),
721 QAnimationGroup::Paused);
722
723 group.stop();
724
725 QCOMPARE(seqStateChangedSpy.count(), 5); // Running,Paused,Running,Paused,Stopped
726 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(seqStateChangedSpy.at(4).first()),
727 QAnimationGroup::Stopped);
728}
729
730void tst_QSequentialAnimationGroup::restart()
731{
732 // sequence operating on same object/property
733 QAnimationGroup *sequence = new QSequentialAnimationGroup();
734 QSignalSpy seqCurrentAnimChangedSpy(static_cast<QSequentialAnimationGroup*>(sequence), &QSequentialAnimationGroup::currentAnimationChanged);
735 QSignalSpy seqStateChangedSpy(sequence, &QAnimationGroup::stateChanged);
736
737 QVERIFY(seqCurrentAnimChangedSpy.isValid());
738 QVERIFY(seqStateChangedSpy.isValid());
739
740 QVariantAnimation *anims[3];
741 QSignalSpy *animsStateChanged[3];
742
743 for (int i = 0; i < 3; i++) {
744 anims[i] = new DummyPropertyAnimation;
745 anims[i]->setDuration(100);
746 animsStateChanged[i] = new QSignalSpy(anims[i], &QVariantAnimation::stateChanged);
747 QVERIFY(animsStateChanged[i]->isValid());
748 }
749
750 anims[1]->setLoopCount(2);
751 sequence->addAnimation(animation: anims[0]);
752 sequence->addAnimation(animation: anims[1]);
753 sequence->addAnimation(animation: anims[2]);
754 sequence->setLoopCount(2);
755
756 QSequentialAnimationGroup group;
757 group.addAnimation(animation: sequence);
758
759 group.start();
760
761 QTest::qWait(ms: 500);
762
763 QCOMPARE(group.state(), QAnimationGroup::Running);
764
765 QTest::qWait(ms: 300);
766 QTRY_COMPARE(group.state(), QAnimationGroup::Stopped);
767
768 for (int i = 0; i < 3; i++) {
769 QCOMPARE(animsStateChanged[i]->count(), 4);
770 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(animsStateChanged[i]->at(0).first()),
771 QAnimationGroup::Running);
772 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(animsStateChanged[i]->at(1).first()),
773 QAnimationGroup::Stopped);
774 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(animsStateChanged[i]->at(2).first()),
775 QAnimationGroup::Running);
776 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(animsStateChanged[i]->at(3).first()),
777 QAnimationGroup::Stopped);
778 }
779
780 QCOMPARE(seqStateChangedSpy.count(), 2);
781 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(seqStateChangedSpy.at(0).first()),
782 QAnimationGroup::Running);
783 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(seqStateChangedSpy.at(1).first()),
784 QAnimationGroup::Stopped);
785
786 QCOMPARE(seqCurrentAnimChangedSpy.count(), 6);
787 for(int i=0; i<seqCurrentAnimChangedSpy.count(); i++)
788 QCOMPARE(static_cast<QAbstractAnimation*>(anims[i%3]), qvariant_cast<QAbstractAnimation*>(seqCurrentAnimChangedSpy.at(i).at(0)));
789
790 group.start();
791
792 QCOMPARE(animsStateChanged[0]->count(), 5);
793 QCOMPARE(animsStateChanged[1]->count(), 4);
794 QCOMPARE(animsStateChanged[2]->count(), 4);
795 QCOMPARE(seqStateChangedSpy.count(), 3);
796}
797
798void tst_QSequentialAnimationGroup::looping()
799{
800 // sequence operating on same object/property
801 QSequentialAnimationGroup *sequence = new QSequentialAnimationGroup();
802 QAbstractAnimation *a1_s_o1 = new DummyPropertyAnimation;
803 QAbstractAnimation *a2_s_o1 = new DummyPropertyAnimation;
804 QAbstractAnimation *a3_s_o1 = new DummyPropertyAnimation;
805
806 QSignalSpy a1Spy(a1_s_o1, &QAbstractAnimation::stateChanged);
807 QSignalSpy a2Spy(a2_s_o1, &QAbstractAnimation::stateChanged);
808 QSignalSpy a3Spy(a3_s_o1, &QAbstractAnimation::stateChanged);
809 QSignalSpy seqSpy(sequence, &QSequentialAnimationGroup::stateChanged);
810
811 QVERIFY(a1Spy.isValid());
812 QVERIFY(a2Spy.isValid());
813 QVERIFY(a3Spy.isValid());
814 QVERIFY(seqSpy.isValid());
815
816 a2_s_o1->setLoopCount(2);
817 sequence->addAnimation(animation: a1_s_o1);
818 sequence->addAnimation(animation: a2_s_o1);
819 sequence->addAnimation(animation: a3_s_o1);
820 sequence->setLoopCount(2);
821
822 QSequentialAnimationGroup group;
823 QSignalSpy groupSpy(&group, &QSequentialAnimationGroup::stateChanged);
824 QVERIFY(groupSpy.isValid());
825
826 group.addAnimation(animation: sequence);
827 group.setLoopCount(2);
828
829 group.start();
830 group.pause();
831
832 // Current time = 1750
833 group.setCurrentTime(1750);
834 QCOMPARE(group.currentLoopTime(), 1750);
835 QCOMPARE(sequence->currentLoopTime(), 750);
836 QCOMPARE(sequence->currentLoop(), 1);
837 QCOMPARE(a1_s_o1->currentLoopTime(), 250);
838 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
839 QCOMPARE(a2_s_o1->currentLoop(), 1);
840 // this animation is at the beginning because it is the current one inside sequence
841 QCOMPARE(a3_s_o1->currentLoop(), 0);
842 QCOMPARE(a3_s_o1->currentLoopTime(), 0);
843 QCOMPARE(sequence->currentAnimation(), a3_s_o1);
844
845 QCOMPARE(group.state(), QAnimationGroup::Paused);
846 QCOMPARE(sequence->state(), QAnimationGroup::Paused);
847 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
848 QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
849 QCOMPARE(a3_s_o1->state(), QAnimationGroup::Paused);
850
851 QCOMPARE(a1Spy.count(), 5); // Running,Paused,Stopped,Running,Stopped
852 QVERIFY(compareStates(a1Spy, (StateList() << QAbstractAnimation::Running
853 << QAbstractAnimation::Paused
854 << QAbstractAnimation::Stopped
855 << QAbstractAnimation::Running
856 << QAbstractAnimation::Stopped)));
857
858 QCOMPARE(a2Spy.count(), 4); // Running,Stopped,Running,Stopped
859 QVERIFY(compareStates(a3Spy, (StateList() << QAbstractAnimation::Running
860 << QAbstractAnimation::Stopped
861 << QAbstractAnimation::Running
862 << QAbstractAnimation::Paused)));
863
864 QCOMPARE(seqSpy.count(), 2); // Running,Paused
865 QCOMPARE(groupSpy.count(), 2); // Running,Paused
866
867 // Looping, current time = duration + 1
868 group.setCurrentTime(group.duration() + 1);
869 QCOMPARE(group.currentLoopTime(), 1);
870 QCOMPARE(group.currentLoop(), 1);
871 QCOMPARE(sequence->currentLoopTime(), 1);
872 QCOMPARE(sequence->currentLoop(), 0);
873 QCOMPARE(a1_s_o1->currentLoopTime(), 1);
874 QCOMPARE(a2_s_o1->currentLoopTime(), 250);
875 QCOMPARE(a2_s_o1->currentLoop(), 1);
876 // this animation is at the end because it was run on the previous loop
877 QCOMPARE(a3_s_o1->currentLoop(), 0);
878 QCOMPARE(a3_s_o1->currentLoopTime(), 250);
879
880 QCOMPARE(group.state(), QAnimationGroup::Paused);
881 QCOMPARE(sequence->state(), QAnimationGroup::Paused);
882 QCOMPARE(a1_s_o1->state(), QAnimationGroup::Paused);
883 QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
884 QCOMPARE(a3_s_o1->state(), QAnimationGroup::Stopped);
885
886 QCOMPARE(a1Spy.count(), 7); // Running,Paused,Stopped,Running,Stopped,Running,Stopped
887 QCOMPARE(a2Spy.count(), 4); // Running, Stopped, Running, Stopped
888 QVERIFY(compareStates(a3Spy, (StateList() << QAbstractAnimation::Running
889 << QAbstractAnimation::Stopped
890 << QAbstractAnimation::Running
891 << QAbstractAnimation::Paused
892 << QAbstractAnimation::Stopped)));
893 QVERIFY(compareStates(seqSpy, (StateList() << QAbstractAnimation::Running
894 << QAbstractAnimation::Paused
895 << QAbstractAnimation::Stopped
896 << QAbstractAnimation::Running
897 << QAbstractAnimation::Paused)));
898 QCOMPARE(groupSpy.count(), 2);
899}
900
901void tst_QSequentialAnimationGroup::startDelay()
902{
903 QSequentialAnimationGroup group;
904 group.addPause(msecs: 250);
905 group.addPause(msecs: 125);
906 QCOMPARE(group.totalDuration(), 375);
907
908 group.start();
909 QCOMPARE(group.state(), QAnimationGroup::Running);
910
911 QTest::qWait(ms: 500);
912
913 QTRY_COMPARE(group.state(), QAnimationGroup::Stopped);
914 QCOMPARE(group.currentLoopTime(), 375);
915}
916
917void tst_QSequentialAnimationGroup::clearGroup()
918{
919 QSequentialAnimationGroup group;
920
921 static const int animationCount = 20;
922
923 for (int i = 0; i < animationCount/2; ++i) {
924 QSequentialAnimationGroup *subGroup = new QSequentialAnimationGroup(&group);
925 group.addPause(msecs: 100);
926 subGroup->addPause(msecs: 10);
927 }
928
929 QCOMPARE(group.animationCount(), animationCount);
930
931 QPointer<QAbstractAnimation> children[animationCount];
932 for (int i = 0; i < animationCount; ++i) {
933 QVERIFY(group.animationAt(i) != 0);
934 children[i] = group.animationAt(index: i);
935 }
936
937 group.clear();
938 QCOMPARE(group.animationCount(), 0);
939 QCOMPARE(group.currentLoopTime(), 0);
940 for (int i = 0; i < animationCount; ++i)
941 QVERIFY(children[i].isNull());
942}
943
944void tst_QSequentialAnimationGroup::groupWithZeroDurationAnimations()
945{
946 QObject o;
947 QObject o2;
948
949 o.setProperty(name: "myProperty", value: 42);
950 o.setProperty(name: "myOtherProperty", value: 13);
951 o2.setProperty(name: "myProperty", value: 42);
952 o2.setProperty(name: "myOtherProperty", value: 13);
953
954 QSequentialAnimationGroup group;
955
956 QVariantAnimation *a1 = new QPropertyAnimation(&o, "myProperty");
957 a1->setDuration(0);
958 a1->setEndValue(43);
959 group.addAnimation(animation: a1);
960
961 //this should just run fine and change nothing
962 group.setCurrentTime(0);
963 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(a1));
964
965 QVariantAnimation *a2 = new QPropertyAnimation(&o2, "myOtherProperty");
966 a2->setDuration(500);
967 a2->setEndValue(31);
968 group.addAnimation(animation: a2);
969
970 QVariantAnimation *a3 = new QPropertyAnimation(&o, "myProperty");
971 a3->setDuration(0);
972 a3->setEndValue(44);
973 group.addAnimation(animation: a3);
974
975 QVariantAnimation *a4 = new QPropertyAnimation(&o, "myOtherProperty");
976 a4->setDuration(250);
977 a4->setEndValue(75);
978 group.addAnimation(animation: a4);
979
980 QVariantAnimation *a5 = new QPropertyAnimation(&o2, "myProperty");
981 a5->setDuration(0);
982 a5->setEndValue(12);
983 group.addAnimation(animation: a5);
984
985 QCOMPARE(o.property("myProperty").toInt(), 42);
986 QCOMPARE(o.property("myOtherProperty").toInt(), 13);
987 QCOMPARE(o2.property("myProperty").toInt(), 42);
988 QCOMPARE(o2.property("myOtherProperty").toInt(), 13);
989
990
991 group.start();
992
993 QCOMPARE(o.property("myProperty").toInt(), 43);
994 QCOMPARE(o.property("myOtherProperty").toInt(), 13);
995 QCOMPARE(o2.property("myProperty").toInt(), 42);
996 QCOMPARE(o2.property("myOtherProperty").toInt(), 13);
997
998 QTest::qWait(ms: 100);
999
1000 int o2val = o2.property(name: "myOtherProperty").toInt();
1001 QVERIFY(o2val > 13);
1002 QVERIFY(o2val < 31);
1003 QCOMPARE(o.property("myProperty").toInt(), 43);
1004 QCOMPARE(o.property("myOtherProperty").toInt(), 13);
1005
1006 QTest::qWait(ms: 500);
1007
1008 QTRY_COMPARE(o.property("myProperty").toInt(), 44);
1009 QCOMPARE(o2.property("myProperty").toInt(), 42);
1010 QCOMPARE(o2.property("myOtherProperty").toInt(), 31);
1011 QCOMPARE(a1->state(), QAnimationGroup::Stopped);
1012 QCOMPARE(a2->state(), QAnimationGroup::Stopped);
1013 QCOMPARE(a3->state(), QAnimationGroup::Stopped);
1014 QCOMPARE(a4->state(), QAnimationGroup::Running);
1015 QCOMPARE(a5->state(), QAnimationGroup::Stopped);
1016 QCOMPARE(group.state(), QAnimationGroup::Running);
1017 QTest::qWait(ms: 500);
1018
1019 QTRY_COMPARE(group.state(), QAnimationGroup::Stopped);
1020 QCOMPARE(o.property("myProperty").toInt(), 44);
1021 QCOMPARE(o.property("myOtherProperty").toInt(), 75);
1022 QCOMPARE(o2.property("myProperty").toInt(), 12);
1023 QCOMPARE(o2.property("myOtherProperty").toInt(), 31);
1024 QCOMPARE(a1->state(), QAnimationGroup::Stopped);
1025 QCOMPARE(a2->state(), QAnimationGroup::Stopped);
1026 QCOMPARE(a3->state(), QAnimationGroup::Stopped);
1027 QCOMPARE(a4->state(), QAnimationGroup::Stopped);
1028 QCOMPARE(a5->state(), QAnimationGroup::Stopped);
1029}
1030
1031void tst_QSequentialAnimationGroup::propagateGroupUpdateToChildren()
1032{
1033 // this test verifies if group state changes are updating its children correctly
1034 QSequentialAnimationGroup group;
1035
1036 QObject o;
1037 o.setProperty(name: "ole", value: 42);
1038 QCOMPARE(o.property("ole").toInt(), 42);
1039
1040 QPropertyAnimation anim1(&o, "ole");
1041 anim1.setEndValue(43);
1042 anim1.setDuration(100);
1043 QVERIFY(!anim1.currentValue().isValid());
1044 QCOMPARE(anim1.currentValue().toInt(), 0);
1045 QCOMPARE(o.property("ole").toInt(), 42);
1046
1047 TestAnimation anim2;
1048 anim2.setStartValue(0);
1049 anim2.setEndValue(100);
1050 anim2.setDuration(200);
1051
1052 QVERIFY(anim2.currentValue().isValid());
1053 QCOMPARE(anim2.currentValue().toInt(), 0);
1054
1055 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1056 QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
1057 QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
1058
1059 group.addAnimation(animation: &anim1);
1060 group.addAnimation(animation: &anim2);
1061
1062 group.start();
1063
1064 QCOMPARE(group.state(), QAnimationGroup::Running);
1065 QCOMPARE(anim1.state(), QAnimationGroup::Running);
1066 QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
1067
1068 group.pause();
1069
1070 QCOMPARE(group.state(), QAnimationGroup::Paused);
1071 QCOMPARE(anim1.state(), QAnimationGroup::Paused);
1072 QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
1073
1074 group.stop();
1075
1076 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1077 QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
1078 QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
1079}
1080
1081void tst_QSequentialAnimationGroup::updateChildrenWithRunningGroup()
1082{
1083 // assert that its possible to modify a child's state directly while their group is running
1084 QSequentialAnimationGroup group;
1085
1086 TestAnimation anim;
1087 anim.setStartValue(0);
1088 anim.setEndValue(100);
1089 anim.setDuration(200);
1090
1091 QSignalSpy groupStateChangedSpy(&group, &QSequentialAnimationGroup::stateChanged);
1092 QSignalSpy childStateChangedSpy(&anim, &TestAnimation::stateChanged);
1093
1094 QVERIFY(groupStateChangedSpy.isValid());
1095 QVERIFY(childStateChangedSpy.isValid());
1096
1097 QCOMPARE(groupStateChangedSpy.count(), 0);
1098 QCOMPARE(childStateChangedSpy.count(), 0);
1099 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1100 QCOMPARE(anim.state(), QAnimationGroup::Stopped);
1101
1102 group.addAnimation(animation: &anim);
1103
1104 group.start();
1105
1106 QCOMPARE(group.state(), QAnimationGroup::Running);
1107 QCOMPARE(anim.state(), QAnimationGroup::Running);
1108
1109 QCOMPARE(groupStateChangedSpy.count(), 1);
1110 QCOMPARE(childStateChangedSpy.count(), 1);
1111
1112 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(groupStateChangedSpy.at(0).first()),
1113 QAnimationGroup::Running);
1114 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(childStateChangedSpy.at(0).first()),
1115 QAnimationGroup::Running);
1116
1117 // starting directly a running child will not have any effect
1118 anim.start();
1119
1120 QCOMPARE(groupStateChangedSpy.count(), 1);
1121 QCOMPARE(childStateChangedSpy.count(), 1);
1122
1123 anim.pause();
1124
1125 QCOMPARE(group.state(), QAnimationGroup::Running);
1126 QCOMPARE(anim.state(), QAnimationGroup::Paused);
1127
1128 // in the animation stops directly, the group will still be running
1129 anim.stop();
1130
1131 QCOMPARE(group.state(), QAnimationGroup::Running);
1132 QCOMPARE(anim.state(), QAnimationGroup::Stopped);
1133}
1134
1135void tst_QSequentialAnimationGroup::deleteChildrenWithRunningGroup()
1136{
1137 // test if children can be activated when their group is stopped
1138 QSequentialAnimationGroup group;
1139
1140 QVariantAnimation *anim1 = new TestAnimation;
1141 anim1->setStartValue(0);
1142 anim1->setEndValue(100);
1143 anim1->setDuration(200);
1144 group.addAnimation(animation: anim1);
1145
1146 QCOMPARE(group.duration(), anim1->duration());
1147
1148 group.start();
1149 QCOMPARE(group.state(), QAnimationGroup::Running);
1150 QCOMPARE(anim1->state(), QAnimationGroup::Running);
1151
1152 QTest::qWait(ms: 100);
1153 QTRY_VERIFY(group.currentLoopTime() > 0);
1154
1155 delete anim1;
1156 QCOMPARE(group.animationCount(), 0);
1157 QCOMPARE(group.duration(), 0);
1158 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1159 QCOMPARE(group.currentLoopTime(), 0); //that's the invariant
1160}
1161
1162void tst_QSequentialAnimationGroup::startChildrenWithStoppedGroup()
1163{
1164 // test if children can be activated when their group is stopped
1165 QSequentialAnimationGroup group;
1166
1167 TestAnimation anim1;
1168 anim1.setStartValue(0);
1169 anim1.setEndValue(100);
1170 anim1.setDuration(200);
1171
1172 TestAnimation anim2;
1173 anim2.setStartValue(0);
1174 anim2.setEndValue(100);
1175 anim2.setDuration(200);
1176
1177 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1178 QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
1179 QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
1180
1181 group.addAnimation(animation: &anim1);
1182 group.addAnimation(animation: &anim2);
1183
1184 group.stop();
1185
1186 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1187 QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
1188 QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
1189
1190 anim1.start();
1191 anim2.start();
1192 anim2.pause();
1193
1194 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1195 QCOMPARE(anim1.state(), QAnimationGroup::Running);
1196 QCOMPARE(anim2.state(), QAnimationGroup::Paused);
1197}
1198
1199void tst_QSequentialAnimationGroup::stopGroupWithRunningChild()
1200{
1201 // children that started independently will not be affected by a group stop
1202 QSequentialAnimationGroup group;
1203
1204 TestAnimation anim1;
1205 anim1.setStartValue(0);
1206 anim1.setEndValue(100);
1207 anim1.setDuration(200);
1208
1209 TestAnimation anim2;
1210 anim2.setStartValue(0);
1211 anim2.setEndValue(100);
1212 anim2.setDuration(200);
1213
1214 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1215 QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
1216 QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
1217
1218 group.addAnimation(animation: &anim1);
1219 group.addAnimation(animation: &anim2);
1220
1221 anim1.start();
1222 anim2.start();
1223 anim2.pause();
1224
1225 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1226 QCOMPARE(anim1.state(), QAnimationGroup::Running);
1227 QCOMPARE(anim2.state(), QAnimationGroup::Paused);
1228
1229 group.stop();
1230
1231 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1232 QCOMPARE(anim1.state(), QAnimationGroup::Running);
1233 QCOMPARE(anim2.state(), QAnimationGroup::Paused);
1234
1235 anim1.stop();
1236 anim2.stop();
1237
1238 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1239 QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
1240 QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
1241}
1242
1243void tst_QSequentialAnimationGroup::startGroupWithRunningChild()
1244{
1245 // as the group has precedence over its children, starting a group will restart all the children
1246 QSequentialAnimationGroup group;
1247
1248 TestAnimation *anim1 = new TestAnimation();
1249 anim1->setStartValue(0);
1250 anim1->setEndValue(100);
1251 anim1->setDuration(200);
1252
1253 TestAnimation *anim2 = new TestAnimation();
1254 anim2->setStartValue(0);
1255 anim2->setEndValue(100);
1256 anim2->setDuration(200);
1257
1258 QSignalSpy stateChangedSpy1(anim1, &TestAnimation::stateChanged);
1259 QSignalSpy stateChangedSpy2(anim2, &TestAnimation::stateChanged);
1260
1261 QVERIFY(stateChangedSpy1.isValid());
1262 QVERIFY(stateChangedSpy2.isValid());
1263
1264 QCOMPARE(stateChangedSpy1.count(), 0);
1265 QCOMPARE(stateChangedSpy2.count(), 0);
1266 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1267 QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
1268 QCOMPARE(anim2->state(), QAnimationGroup::Stopped);
1269
1270 group.addAnimation(animation: anim1);
1271 group.addAnimation(animation: anim2);
1272
1273 anim1->start();
1274 anim2->start();
1275 anim2->pause();
1276
1277 QVERIFY(compareStates(stateChangedSpy1, (StateList() << QAbstractAnimation::Running)));
1278
1279 QVERIFY(compareStates(stateChangedSpy2, (StateList() << QAbstractAnimation::Running
1280 << QAbstractAnimation::Paused)));
1281
1282 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1283 QCOMPARE(anim1->state(), QAnimationGroup::Running);
1284 QCOMPARE(anim2->state(), QAnimationGroup::Paused);
1285
1286 group.start();
1287
1288 QVERIFY(compareStates(stateChangedSpy1, (StateList() << QAbstractAnimation::Running
1289 << QAbstractAnimation::Stopped
1290 << QAbstractAnimation::Running)));
1291 QVERIFY(compareStates(stateChangedSpy2, (StateList() << QAbstractAnimation::Running
1292 << QAbstractAnimation::Paused)));
1293
1294 QCOMPARE(group.state(), QAnimationGroup::Running);
1295 QCOMPARE(anim1->state(), QAnimationGroup::Running);
1296 QCOMPARE(anim2->state(), QAnimationGroup::Paused);
1297
1298 // Wait until anim1 finishes (anim2 should be still running)
1299 QTRY_COMPARE(anim1->state(), QAnimationGroup::Stopped);
1300 QCOMPARE(group.state(), QAnimationGroup::Running);
1301 QCOMPARE(anim2->state(), QAnimationGroup::Running);
1302
1303 QCOMPARE(stateChangedSpy2.count(), 4);
1304 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(stateChangedSpy2.at(2).first()),
1305 QAnimationGroup::Stopped);
1306 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(stateChangedSpy2.at(3).first()),
1307 QAnimationGroup::Running);
1308
1309 group.stop();
1310
1311 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1312 QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
1313 QCOMPARE(anim2->state(), QAnimationGroup::Stopped);
1314}
1315
1316void tst_QSequentialAnimationGroup::zeroDurationAnimation()
1317{
1318 QSequentialAnimationGroup group;
1319
1320 TestAnimation *anim1 = new TestAnimation();
1321 anim1->setStartValue(0);
1322 anim1->setEndValue(100);
1323 anim1->setDuration(0);
1324
1325 TestAnimation *anim2 = new TestAnimation();
1326 anim2->setStartValue(0);
1327 anim2->setEndValue(100);
1328 anim2->setDuration(100);
1329
1330 DummyPropertyAnimation *anim3 = new DummyPropertyAnimation;
1331 anim3->setEndValue(100);
1332 anim3->setDuration(0);
1333
1334 QSignalSpy stateChangedSpy(anim1, &TestAnimation::stateChanged);
1335 QVERIFY(stateChangedSpy.isValid());
1336
1337 group.addAnimation(animation: anim1);
1338 group.addAnimation(animation: anim2);
1339 group.addAnimation(animation: anim3);
1340 group.setLoopCount(2);
1341 group.start();
1342
1343 QCOMPARE(stateChangedSpy.count(), 2);
1344 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(stateChangedSpy.at(0).first()),
1345 QAnimationGroup::Running);
1346 QCOMPARE(qvariant_cast<QAbstractAnimation::State>(stateChangedSpy.at(1).first()),
1347 QAnimationGroup::Stopped);
1348
1349 QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
1350 QCOMPARE(anim2->state(), QAnimationGroup::Running);
1351 QCOMPARE(group.state(), QAnimationGroup::Running);
1352
1353 //now let's try to seek to the next loop
1354 group.setCurrentTime(group.duration() + 1);
1355 QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
1356 QCOMPARE(anim2->state(), QAnimationGroup::Running);
1357 QCOMPARE(anim3->state(), QAnimationGroup::Stopped);
1358 QCOMPARE(group.state(), QAnimationGroup::Running);
1359 QCOMPARE(anim3->o.value(), 100); //anim3 should have been run
1360}
1361
1362void tst_QSequentialAnimationGroup::stopUncontrolledAnimations()
1363{
1364 QSequentialAnimationGroup group;
1365
1366 AnimationObject o1;
1367 UncontrolledAnimation notTimeDriven(&o1);
1368 QCOMPARE(notTimeDriven.totalDuration(), -1);
1369
1370 TestAnimation loopsForever;
1371 loopsForever.setStartValue(0);
1372 loopsForever.setEndValue(100);
1373 loopsForever.setDuration(100);
1374 loopsForever.setLoopCount(-1);
1375
1376 group.addAnimation(animation: &notTimeDriven);
1377 group.addAnimation(animation: &loopsForever);
1378
1379 group.start();
1380
1381 QCOMPARE(group.state(), QAnimationGroup::Running);
1382 QCOMPARE(notTimeDriven.state(), QAnimationGroup::Running);
1383 QCOMPARE(loopsForever.state(), QAnimationGroup::Stopped);
1384
1385 notTimeDriven.stop();
1386
1387 QCOMPARE(group.state(), QAnimationGroup::Running);
1388 QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
1389 QCOMPARE(loopsForever.state(), QAnimationGroup::Running);
1390
1391 loopsForever.stop();
1392
1393 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1394 QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
1395 QCOMPARE(loopsForever.state(), QAnimationGroup::Stopped);
1396}
1397
1398void tst_QSequentialAnimationGroup::finishWithUncontrolledAnimation()
1399{
1400 AnimationObject o1;
1401
1402 //1st case:
1403 //first we test a group with one uncontrolled animation
1404 QSequentialAnimationGroup group;
1405 UncontrolledAnimation notTimeDriven(&o1, &group);
1406 QSignalSpy spy(&group, &QSequentialAnimationGroup::finished);
1407 QVERIFY(spy.isValid());
1408
1409 group.start();
1410 QCOMPARE(group.state(), QAnimationGroup::Running);
1411 QCOMPARE(notTimeDriven.state(), QAnimationGroup::Running);
1412 QCOMPARE(group.currentLoopTime(), 0);
1413 QCOMPARE(notTimeDriven.currentLoopTime(), 0);
1414
1415 QTest::qWait(ms: 300); //wait for the end of notTimeDriven
1416 QTRY_COMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
1417 const int actualDuration = notTimeDriven.currentLoopTime();
1418 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1419 QCOMPARE(group.currentLoopTime(), actualDuration);
1420 QCOMPARE(spy.count(), 1);
1421
1422 //2nd case:
1423 // lets make sure the seeking will work again
1424 spy.clear();
1425 DummyPropertyAnimation anim(&group);
1426 QSignalSpy animStateChangedSpy(&anim, &DummyPropertyAnimation::stateChanged);
1427 QVERIFY(animStateChangedSpy.isValid());
1428
1429 group.setCurrentTime(300);
1430 QCOMPARE(group.state(), QAnimationGroup::Stopped);
1431 QCOMPARE(notTimeDriven.currentLoopTime(), actualDuration);
1432 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(&anim));
1433
1434 //3rd case:
1435 //now let's add a perfectly defined animation at the end
1436 QCOMPARE(animStateChangedSpy.count(), 0);
1437 group.start();
1438 QCOMPARE(group.state(), QAnimationGroup::Running);
1439 QCOMPARE(notTimeDriven.state(), QAnimationGroup::Running);
1440 QCOMPARE(group.currentLoopTime(), 0);
1441 QCOMPARE(notTimeDriven.currentLoopTime(), 0);
1442
1443 QCOMPARE(animStateChangedSpy.count(), 0);
1444
1445 QTest::qWait(ms: 300); //wait for the end of notTimeDriven
1446 QTRY_COMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
1447 QCOMPARE(group.state(), QAnimationGroup::Running);
1448 QCOMPARE(anim.state(), QAnimationGroup::Running);
1449 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(&anim));
1450 QCOMPARE(animStateChangedSpy.count(), 1);
1451 QTest::qWait(ms: 300); //wait for the end of anim
1452
1453 QTRY_COMPARE(anim.state(), QAnimationGroup::Stopped);
1454 QCOMPARE(anim.currentLoopTime(), anim.duration());
1455
1456 //we should simply be at the end
1457 QCOMPARE(spy.count(), 1);
1458 QCOMPARE(animStateChangedSpy.count(), 2);
1459 QCOMPARE(group.currentLoopTime(), notTimeDriven.currentLoopTime() + anim.currentLoopTime());
1460}
1461
1462void tst_QSequentialAnimationGroup::addRemoveAnimation()
1463{
1464 //this test is specific to the sequential animation group
1465 QSequentialAnimationGroup group;
1466
1467 QCOMPARE(group.duration(), 0);
1468 QCOMPARE(group.currentLoopTime(), 0);
1469 QAbstractAnimation *anim1 = new QPropertyAnimation;
1470 group.addAnimation(animation: anim1);
1471 QCOMPARE(group.duration(), 250);
1472 QCOMPARE(group.currentLoopTime(), 0);
1473 QCOMPARE(group.currentAnimation(), anim1);
1474
1475 //let's append an animation
1476 QAbstractAnimation *anim2 = new QPropertyAnimation;
1477 group.addAnimation(animation: anim2);
1478 QCOMPARE(group.duration(), 500);
1479 QCOMPARE(group.currentLoopTime(), 0);
1480 QCOMPARE(group.currentAnimation(), anim1);
1481
1482 //let's prepend an animation
1483 QAbstractAnimation *anim0 = new QPropertyAnimation;
1484 group.insertAnimation(index: 0, animation: anim0);
1485 QCOMPARE(group.duration(), 750);
1486 QCOMPARE(group.currentLoopTime(), 0);
1487 QCOMPARE(group.currentAnimation(), anim0); //anim0 has become the new currentAnimation
1488
1489 group.setCurrentTime(300); //anim0 | anim1 | anim2
1490 QCOMPARE(group.currentLoopTime(), 300);
1491 QCOMPARE(group.currentAnimation(), anim1);
1492 QCOMPARE(anim1->currentLoopTime(), 50);
1493
1494 group.removeAnimation(animation: anim0); //anim1 | anim2
1495 QCOMPARE(group.currentLoopTime(), 50);
1496 QCOMPARE(group.currentAnimation(), anim1);
1497 QCOMPARE(anim1->currentLoopTime(), 50);
1498
1499 group.setCurrentTime(0);
1500 group.insertAnimation(index: 0, animation: anim0); //anim0 | anim1 | anim2
1501 group.setCurrentTime(300);
1502 QCOMPARE(group.currentLoopTime(), 300);
1503 QCOMPARE(group.currentAnimation(), anim1);
1504 QCOMPARE(anim1->currentLoopTime(), 50);
1505
1506 group.removeAnimation(animation: anim1); //anim0 | anim2
1507 QCOMPARE(group.currentLoopTime(), 250);
1508 QCOMPARE(group.currentAnimation(), anim2);
1509 QCOMPARE(anim0->currentLoopTime(), 250);
1510}
1511
1512void tst_QSequentialAnimationGroup::currentAnimation()
1513{
1514 QSequentialAnimationGroup group;
1515 QVERIFY(!group.currentAnimation());
1516
1517 QPropertyAnimation anim;
1518 anim.setDuration(0);
1519 group.addAnimation(animation: &anim);
1520 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(&anim));
1521}
1522
1523void tst_QSequentialAnimationGroup::currentAnimationWithZeroDuration()
1524{
1525 QSequentialAnimationGroup group;
1526 QVERIFY(!group.currentAnimation());
1527
1528 QPropertyAnimation zero1;
1529 zero1.setDuration(0);
1530 QPropertyAnimation zero2;
1531 zero2.setDuration(0);
1532
1533 QPropertyAnimation anim;
1534
1535 QPropertyAnimation zero3;
1536 zero3.setDuration(0);
1537 QPropertyAnimation zero4;
1538 zero4.setDuration(0);
1539
1540
1541 group.addAnimation(animation: &zero1);
1542 group.addAnimation(animation: &zero2);
1543 group.addAnimation(animation: &anim);
1544 group.addAnimation(animation: &zero3);
1545 group.addAnimation(animation: &zero4);
1546
1547 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(&zero1));
1548
1549 group.setCurrentTime(0);
1550 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(&anim));
1551
1552 group.setCurrentTime(group.duration());
1553 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(&zero4));
1554
1555 group.setDirection(QAbstractAnimation::Backward);
1556
1557 group.setCurrentTime(0);
1558 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(&zero1));
1559
1560 group.setCurrentTime(group.duration());
1561 QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimation*>(&anim));
1562}
1563
1564void tst_QSequentialAnimationGroup::insertAnimation()
1565{
1566 QSequentialAnimationGroup group;
1567 group.setLoopCount(2);
1568 QPropertyAnimation *anim = new DummyPropertyAnimation(&group);
1569 QCOMPARE(group.duration(), anim->duration());
1570 group.setCurrentTime(300);
1571 QCOMPARE(group.currentLoop(), 1);
1572
1573 //this will crash if the sequential group calls duration on the created animation
1574 new QPropertyAnimation(&group);
1575}
1576
1577
1578class SequentialAnimationGroup : public QSequentialAnimationGroup
1579{
1580 Q_OBJECT
1581public slots:
1582 void clear()
1583 {
1584 QSequentialAnimationGroup::clear();
1585 }
1586
1587 void refill()
1588 {
1589 stop();
1590 clear();
1591 new DummyPropertyAnimation(this);
1592 start();
1593 }
1594
1595};
1596
1597
1598void tst_QSequentialAnimationGroup::clear()
1599{
1600 SequentialAnimationGroup group;
1601 QPointer<QAbstractAnimation> anim1 = new DummyPropertyAnimation(&group);
1602 group.connect(asender: anim1, SIGNAL(finished()), SLOT(clear()));
1603 new DummyPropertyAnimation(&group);
1604 QCOMPARE(group.animationCount(), 2);
1605
1606 group.start();
1607 QTest::qWait(ms: anim1->duration() + 100);
1608 QTRY_COMPARE(group.animationCount(), 0);
1609 QCOMPARE(group.state(), QAbstractAnimation::Stopped);
1610 QCOMPARE(group.currentLoopTime(), 0);
1611
1612 anim1 = new DummyPropertyAnimation(&group);
1613 group.connect(asender: anim1, SIGNAL(finished()), SLOT(refill()));
1614 group.start();
1615 QTest::qWait(ms: anim1->duration() + 100);
1616 QTRY_COMPARE(group.state(), QAbstractAnimation::Running);
1617 QTRY_COMPARE(anim1, nullptr); // anim1 should have been deleted
1618}
1619
1620void tst_QSequentialAnimationGroup::pauseResume()
1621{
1622 QObject dummy;
1623 dummy.setProperty(name: "foo", value: 0);
1624 QParallelAnimationGroup group;
1625 QPropertyAnimation *anim = new QPropertyAnimation(&dummy, "foo", &group);
1626 anim->setDuration(250);
1627 anim->setEndValue(250);
1628 QSignalSpy spy(anim, &QPropertyAnimation::stateChanged);
1629 QVERIFY(spy.isValid());
1630 QCOMPARE(group.duration(), 250);
1631 group.start();
1632 QTest::qWait(ms: 100);
1633 QTRY_COMPARE(group.state(), QAnimationGroup::Running);
1634 QCOMPARE(anim->state(), QAnimationGroup::Running);
1635 QCOMPARE(spy.count(), 1);
1636 spy.clear();
1637 const int currentTime = group.currentLoopTime();
1638 QCOMPARE(anim->currentLoopTime(), currentTime);
1639
1640 group.pause();
1641 QCOMPARE(group.state(), QAnimationGroup::Paused);
1642 QCOMPARE(group.currentLoopTime(), currentTime);
1643 QCOMPARE(anim->state(), QAnimationGroup::Paused);
1644 QCOMPARE(anim->currentLoopTime(), currentTime);
1645 QCOMPARE(spy.count(), 1);
1646 spy.clear();
1647
1648 group.resume();
1649 QCOMPARE(group.state(), QAnimationGroup::Running);
1650 QCOMPARE(group.currentLoopTime(), currentTime);
1651 QCOMPARE(anim->state(), QAnimationGroup::Running);
1652 QCOMPARE(anim->currentLoopTime(), currentTime);
1653 QCOMPARE(spy.count(), 1);
1654}
1655
1656QTEST_MAIN(tst_QSequentialAnimationGroup)
1657#include "tst_qsequentialanimationgroup.moc"
1658

source code of qtbase/tests/auto/corelib/animation/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp