source: trunk/src/corelib/animation/qabstractanimation.cpp@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 28.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*!
43 \class QAbstractAnimation
44 \ingroup animation
45 \brief The QAbstractAnimation class is the base of all animations.
46 \since 4.6
47
48 The class defines the functions for the functionality shared by
49 all animations. By inheriting this class, you can create custom
50 animations that plug into the rest of the animation framework.
51
52 The progress of an animation is given by its current time
53 (currentLoopTime()), which is measured in milliseconds from the start
54 of the animation (0) to its end (duration()). The value is updated
55 automatically while the animation is running. It can also be set
56 directly with setCurrentTime().
57
58 At any point an animation is in one of three states:
59 \l{QAbstractAnimation::}{Running},
60 \l{QAbstractAnimation::}{Stopped}, or
61 \l{QAbstractAnimation::}{Paused}--as defined by the
62 \l{QAbstractAnimation::}{State} enum. The current state can be
63 changed by calling start(), stop(), pause(), or resume(). An
64 animation will always reset its \l{currentTime()}{current time}
65 when it is started. If paused, it will continue with the same
66 current time when resumed. When an animation is stopped, it cannot
67 be resumed, but will keep its current time (until started again).
68 QAbstractAnimation will emit stateChanged() whenever its state
69 changes.
70
71 An animation can loop any number of times by setting the loopCount
72 property. When an animation's current time reaches its duration(),
73 it will reset the current time and keep running. A loop count of 1
74 (the default value) means that the animation will run one time.
75 Note that a duration of -1 means that the animation will run until
76 stopped; the current time will increase indefinitely. When the
77 current time equals duration() and the animation is in its
78 final loop, the \l{QAbstractAnimation::}{Stopped} state is
79 entered, and the finished() signal is emitted.
80
81 QAbstractAnimation provides pure virtual functions used by
82 subclasses to track the progress of the animation: duration() and
83 updateCurrentTime(). The duration() function lets you report a
84 duration for the animation (as discussed above). The animation
85 framework calls updateCurrentTime() when current time has changed.
86 By reimplementing this function, you can track the animation
87 progress. Note that neither the interval between calls nor the
88 number of calls to this function are defined; though, it will
89 normally be 60 updates per second.
90
91 By reimplementing updateState(), you can track the animation's
92 state changes, which is particularly useful for animations that
93 are not driven by time.
94
95 \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework}
96*/
97
98/*!
99 \enum QAbstractAnimation::DeletionPolicy
100
101 \value KeepWhenStopped The animation will not be deleted when stopped.
102 \value DeleteWhenStopped The animation will be automatically deleted when
103 stopped.
104*/
105
106/*!
107 \fn QAbstractAnimation::finished()
108
109 QAbstractAnimation emits this signal after the animation has stopped and
110 has reached the end.
111
112 This signal is emitted after stateChanged().
113
114 \sa stateChanged()
115*/
116
117/*!
118 \fn QAbstractAnimation::stateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
119
120 QAbstractAnimation emits this signal whenever the state of the animation has
121 changed from \a oldState to \a newState. This signal is emitted after the virtual
122 updateState() function is called.
123
124 \sa updateState()
125*/
126
127/*!
128 \fn QAbstractAnimation::currentLoopChanged(int currentLoop)
129
130 QAbstractAnimation emits this signal whenever the current loop
131 changes. \a currentLoop is the current loop.
132
133 \sa currentLoop(), loopCount()
134*/
135
136/*!
137 \fn QAbstractAnimation::directionChanged(QAbstractAnimation::Direction newDirection);
138
139 QAbstractAnimation emits this signal whenever the direction has been
140 changed. \a newDirection is the new direction.
141
142 \sa direction
143*/
144
145#include "qabstractanimation.h"
146#include "qanimationgroup.h"
147
148#include <QtCore/qdebug.h>
149
150#include "qabstractanimation_p.h"
151
152#include <QtCore/qmath.h>
153#include <QtCore/qthreadstorage.h>
154#include <QtCore/qcoreevent.h>
155#include <QtCore/qpointer.h>
156
157#ifndef QT_NO_ANIMATION
158
159#define DEFAULT_TIMER_INTERVAL 16
160#define STARTSTOP_TIMER_DELAY 0
161
162QT_BEGIN_NAMESPACE
163
164#ifndef QT_NO_THREAD
165Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
166#endif
167
168QUnifiedTimer::QUnifiedTimer() :
169 QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
170 currentAnimationIdx(0), consistentTiming(false), slowMode(false),
171 slowdownFactor(5.0f), isPauseTimerActive(false), runningLeafAnimations(0)
172{
173 time.invalidate();
174}
175
176
177QUnifiedTimer *QUnifiedTimer::instance(bool create)
178{
179 QUnifiedTimer *inst;
180#ifndef QT_NO_THREAD
181 if (create && !unifiedTimer()->hasLocalData()) {
182 inst = new QUnifiedTimer;
183 unifiedTimer()->setLocalData(inst);
184 } else {
185 inst = unifiedTimer()->localData();
186 }
187#else
188 static QUnifiedTimer unifiedTimer;
189 inst = &unifiedTimer;
190#endif
191 return inst;
192}
193
194QUnifiedTimer *QUnifiedTimer::instance()
195{
196 return instance(true);
197}
198
199void QUnifiedTimer::ensureTimerUpdate()
200{
201 QUnifiedTimer *inst = QUnifiedTimer::instance(false);
202 if (inst && inst->isPauseTimerActive)
203 inst->updateAnimationsTime();
204}
205
206void QUnifiedTimer::updateAnimationsTime()
207{
208 qint64 totalElapsed = time.elapsed();
209 // ignore consistentTiming in case the pause timer is active
210 int delta = (consistentTiming && !isPauseTimerActive) ?
211 timingInterval : totalElapsed - lastTick;
212 if (slowMode) {
213 if (slowdownFactor > 0)
214 delta = qRound(delta / slowdownFactor);
215 else
216 delta = 0;
217 }
218
219 lastTick = totalElapsed;
220
221 //we make sure we only call update time if the time has actually changed
222 //it might happen in some cases that the time doesn't change because events are delayed
223 //when the CPU load is high
224 if (delta) {
225 for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
226 QAbstractAnimation *animation = animations.at(currentAnimationIdx);
227 int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
228 + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
229 animation->setCurrentTime(elapsed);
230 }
231 currentAnimationIdx = 0;
232 }
233}
234
235void QUnifiedTimer::updateAnimationTimer()
236{
237 QUnifiedTimer *inst = QUnifiedTimer::instance(false);
238 if (inst)
239 inst->restartAnimationTimer();
240}
241
242void QUnifiedTimer::restartAnimationTimer()
243{
244 if (runningLeafAnimations == 0 && !runningPauseAnimations.isEmpty()) {
245 int closestTimeToFinish = closestPauseAnimationTimeToFinish();
246 if (closestTimeToFinish < 0) {
247 qDebug() << runningPauseAnimations;
248 qDebug() << closestPauseAnimationTimeToFinish();
249 }
250 animationTimer.start(closestTimeToFinish, this);
251 isPauseTimerActive = true;
252 } else if (!animationTimer.isActive() || isPauseTimerActive) {
253 animationTimer.start(timingInterval, this);
254 isPauseTimerActive = false;
255 }
256}
257
258void QUnifiedTimer::timerEvent(QTimerEvent *event)
259{
260 //in the case of consistent timing we make sure the orders in which events come is always the same
261 //for that purpose we do as if the startstoptimer would always fire before the animation timer
262 if ((consistentTiming && startStopAnimationTimer.isActive()) ||
263 event->timerId() == startStopAnimationTimer.timerId()) {
264 startStopAnimationTimer.stop();
265
266 //we transfer the waiting animations into the "really running" state
267 animations += animationsToStart;
268 animationsToStart.clear();
269 if (animations.isEmpty()) {
270 animationTimer.stop();
271 isPauseTimerActive = false;
272 // invalidate the start reference time
273 time.invalidate();
274 } else {
275 restartAnimationTimer();
276 if (!time.isValid()) {
277 lastTick = 0;
278 time.start();
279 }
280 }
281 }
282
283 if (event->timerId() == animationTimer.timerId()) {
284 // update current time on all top level animations
285 updateAnimationsTime();
286 restartAnimationTimer();
287 }
288}
289
290void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation, bool isTopLevel)
291{
292 QUnifiedTimer *inst = instance(true); //we create the instance if needed
293 inst->registerRunningAnimation(animation);
294 if (isTopLevel) {
295 Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer);
296 QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true;
297 inst->animationsToStart << animation;
298 if (!inst->startStopAnimationTimer.isActive())
299 inst->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, inst);
300 }
301}
302
303void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
304{
305 QUnifiedTimer *inst = QUnifiedTimer::instance(false);
306 if (inst) {
307 //at this point the unified timer should have been created
308 //but it might also have been already destroyed in case the application is shutting down
309
310 inst->unregisterRunningAnimation(animation);
311
312 if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer)
313 return;
314
315 int idx = inst->animations.indexOf(animation);
316 if (idx != -1) {
317 inst->animations.removeAt(idx);
318 // this is needed if we unregister an animation while its running
319 if (idx <= inst->currentAnimationIdx)
320 --inst->currentAnimationIdx;
321
322 if (inst->animations.isEmpty() && !inst->startStopAnimationTimer.isActive())
323 inst->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, inst);
324 } else {
325 inst->animationsToStart.removeOne(animation);
326 }
327 }
328 QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false;
329}
330
331void QUnifiedTimer::registerRunningAnimation(QAbstractAnimation *animation)
332{
333 if (QAbstractAnimationPrivate::get(animation)->isGroup)
334 return;
335
336 if (QAbstractAnimationPrivate::get(animation)->isPause) {
337 runningPauseAnimations << animation;
338 } else
339 runningLeafAnimations++;
340}
341
342void QUnifiedTimer::unregisterRunningAnimation(QAbstractAnimation *animation)
343{
344 if (QAbstractAnimationPrivate::get(animation)->isGroup)
345 return;
346
347 if (QAbstractAnimationPrivate::get(animation)->isPause)
348 runningPauseAnimations.removeOne(animation);
349 else
350 runningLeafAnimations--;
351 Q_ASSERT(runningLeafAnimations >= 0);
352}
353
354int QUnifiedTimer::closestPauseAnimationTimeToFinish()
355{
356 int closestTimeToFinish = INT_MAX;
357 for (int i = 0; i < runningPauseAnimations.size(); ++i) {
358 QAbstractAnimation *animation = runningPauseAnimations.at(i);
359 int timeToFinish;
360
361 if (animation->direction() == QAbstractAnimation::Forward)
362 timeToFinish = animation->duration() - animation->currentLoopTime();
363 else
364 timeToFinish = animation->currentLoopTime();
365
366 if (timeToFinish < closestTimeToFinish)
367 closestTimeToFinish = timeToFinish;
368 }
369 return closestTimeToFinish;
370}
371
372void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
373{
374 Q_Q(QAbstractAnimation);
375 if (state == newState)
376 return;
377
378 if (loopCount == 0)
379 return;
380
381 QAbstractAnimation::State oldState = state;
382 int oldCurrentTime = currentTime;
383 int oldCurrentLoop = currentLoop;
384 QAbstractAnimation::Direction oldDirection = direction;
385
386 // check if we should Rewind
387 if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running)
388 && oldState == QAbstractAnimation::Stopped) {
389 //here we reset the time if needed
390 //we don't call setCurrentTime because this might change the way the animation
391 //behaves: changing the state or changing the current value
392 totalCurrentTime = currentTime = (direction == QAbstractAnimation::Forward) ?
393 0 : (loopCount == -1 ? q->duration() : q->totalDuration());
394 }
395
396 state = newState;
397 QWeakPointer<QAbstractAnimation> guard(q);
398
399 //(un)registration of the animation must always happen before calls to
400 //virtual function (updateState) to ensure a correct state of the timer
401 bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped;
402 if (oldState == QAbstractAnimation::Running) {
403 if (newState == QAbstractAnimation::Paused && hasRegisteredTimer)
404 QUnifiedTimer::ensureTimerUpdate();
405 //the animation, is not running any more
406 QUnifiedTimer::unregisterAnimation(q);
407 } else if (newState == QAbstractAnimation::Running) {
408 QUnifiedTimer::registerAnimation(q, isTopLevel);
409 }
410
411 q->updateState(newState, oldState);
412 if (!guard || newState != state) //this is to be safe if updateState changes the state
413 return;
414
415 // Notify state change
416 emit q->stateChanged(newState, oldState);
417 if (!guard || newState != state) //this is to be safe if updateState changes the state
418 return;
419
420 switch (state) {
421 case QAbstractAnimation::Paused:
422 break;
423 case QAbstractAnimation::Running:
424 {
425
426 // this ensures that the value is updated now that the animation is running
427 if (oldState == QAbstractAnimation::Stopped) {
428 if (isTopLevel) {
429 // currentTime needs to be updated if pauseTimer is active
430 QUnifiedTimer::ensureTimerUpdate();
431 q->setCurrentTime(totalCurrentTime);
432 }
433 }
434 }
435 break;
436 case QAbstractAnimation::Stopped:
437 // Leave running state.
438 int dura = q->duration();
439
440 if (deleteWhenStopped)
441 q->deleteLater();
442
443 if (dura == -1 || loopCount < 0
444 || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount))
445 || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
446 emit q->finished();
447 }
448 break;
449 }
450}
451
452/*!
453 Constructs the QAbstractAnimation base class, and passes \a parent to
454 QObject's constructor.
455
456 \sa QVariantAnimation, QAnimationGroup
457*/
458QAbstractAnimation::QAbstractAnimation(QObject *parent)
459 : QObject(*new QAbstractAnimationPrivate, 0)
460{
461 // Allow auto-add on reparent
462 setParent(parent);
463}
464
465/*!
466 \internal
467*/
468QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
469 : QObject(dd, 0)
470{
471 // Allow auto-add on reparent
472 setParent(parent);
473}
474
475/*!
476 Stops the animation if it's running, then destroys the
477 QAbstractAnimation. If the animation is part of a QAnimationGroup, it is
478 automatically removed before it's destroyed.
479*/
480QAbstractAnimation::~QAbstractAnimation()
481{
482 Q_D(QAbstractAnimation);
483 //we can't call stop here. Otherwise we get pure virtual calls
484 if (d->state != Stopped) {
485 QAbstractAnimation::State oldState = d->state;
486 d->state = Stopped;
487 emit stateChanged(oldState, d->state);
488 if (oldState == QAbstractAnimation::Running)
489 QUnifiedTimer::unregisterAnimation(this);
490 }
491}
492
493/*!
494 \property QAbstractAnimation::state
495 \brief state of the animation.
496
497 This property describes the current state of the animation. When the
498 animation state changes, QAbstractAnimation emits the stateChanged()
499 signal.
500*/
501QAbstractAnimation::State QAbstractAnimation::state() const
502{
503 Q_D(const QAbstractAnimation);
504 return d->state;
505}
506
507/*!
508 If this animation is part of a QAnimationGroup, this function returns a
509 pointer to the group; otherwise, it returns 0.
510
511 \sa QAnimationGroup::addAnimation()
512*/
513QAnimationGroup *QAbstractAnimation::group() const
514{
515 Q_D(const QAbstractAnimation);
516 return d->group;
517}
518
519/*!
520 \enum QAbstractAnimation::State
521
522 This enum describes the state of the animation.
523
524 \value Stopped The animation is not running. This is the initial state
525 of QAbstractAnimation, and the state QAbstractAnimation reenters when finished. The current
526 time remain unchanged until either setCurrentTime() is
527 called, or the animation is started by calling start().
528
529 \value Paused The animation is paused (i.e., temporarily
530 suspended). Calling resume() will resume animation activity.
531
532 \value Running The animation is running. While control is in the event
533 loop, QAbstractAnimation will update its current time at regular intervals,
534 calling updateCurrentTime() when appropriate.
535
536 \sa state(), stateChanged()
537*/
538
539/*!
540 \enum QAbstractAnimation::Direction
541
542 This enum describes the direction of the animation when in \l Running state.
543
544 \value Forward The current time of the animation increases with time (i.e.,
545 moves from 0 and towards the end / duration).
546
547 \value Backward The current time of the animation decreases with time (i.e.,
548 moves from the end / duration and towards 0).
549
550 \sa direction
551*/
552
553/*!
554 \property QAbstractAnimation::direction
555 \brief the direction of the animation when it is in \l Running
556 state.
557
558 This direction indicates whether the time moves from 0 towards the
559 animation duration, or from the value of the duration and towards 0 after
560 start() has been called.
561
562 By default, this property is set to \l Forward.
563*/
564QAbstractAnimation::Direction QAbstractAnimation::direction() const
565{
566 Q_D(const QAbstractAnimation);
567 return d->direction;
568}
569void QAbstractAnimation::setDirection(Direction direction)
570{
571 Q_D(QAbstractAnimation);
572 if (d->direction == direction)
573 return;
574
575 if (state() == Stopped) {
576 if (direction == Backward) {
577 d->currentTime = duration();
578 d->currentLoop = d->loopCount - 1;
579 } else {
580 d->currentTime = 0;
581 d->currentLoop = 0;
582 }
583 }
584
585 // the commands order below is important: first we need to setCurrentTime with the old direction,
586 // then update the direction on this and all children and finally restart the pauseTimer if needed
587 if (d->hasRegisteredTimer)
588 QUnifiedTimer::ensureTimerUpdate();
589
590 d->direction = direction;
591 updateDirection(direction);
592
593 if (d->hasRegisteredTimer)
594 // needed to update the timer interval in case of a pause animation
595 QUnifiedTimer::updateAnimationTimer();
596
597 emit directionChanged(direction);
598}
599
600/*!
601 \property QAbstractAnimation::duration
602 \brief the duration of the animation.
603
604 If the duration is -1, it means that the duration is undefined.
605 In this case, loopCount is ignored.
606*/
607
608/*!
609 \property QAbstractAnimation::loopCount
610 \brief the loop count of the animation
611
612 This property describes the loop count of the animation as an integer.
613 By default this value is 1, indicating that the animation
614 should run once only, and then stop. By changing it you can let the
615 animation loop several times. With a value of 0, the animation will not
616 run at all, and with a value of -1, the animation will loop forever
617 until stopped.
618 It is not supported to have loop on an animation that has an undefined
619 duration. It will only run once.
620*/
621int QAbstractAnimation::loopCount() const
622{
623 Q_D(const QAbstractAnimation);
624 return d->loopCount;
625}
626void QAbstractAnimation::setLoopCount(int loopCount)
627{
628 Q_D(QAbstractAnimation);
629 d->loopCount = loopCount;
630}
631
632/*!
633 \property QAbstractAnimation::currentLoop
634 \brief the current loop of the animation
635
636 This property describes the current loop of the animation. By default,
637 the animation's loop count is 1, and so the current loop will
638 always be 0. If the loop count is 2 and the animation runs past its
639 duration, it will automatically rewind and restart at current time 0, and
640 current loop 1, and so on.
641
642 When the current loop changes, QAbstractAnimation emits the
643 currentLoopChanged() signal.
644*/
645int QAbstractAnimation::currentLoop() const
646{
647 Q_D(const QAbstractAnimation);
648 return d->currentLoop;
649}
650
651/*!
652 \fn virtual int QAbstractAnimation::duration() const = 0
653
654 This pure virtual function returns the duration of the animation, and
655 defines for how long QAbstractAnimation should update the current
656 time. This duration is local, and does not include the loop count.
657
658 A return value of -1 indicates that the animation has no defined duration;
659 the animation should run forever until stopped. This is useful for
660 animations that are not time driven, or where you cannot easily predict
661 its duration (e.g., event driven audio playback in a game).
662
663 If the animation is a parallel QAnimationGroup, the duration will be the longest
664 duration of all its animations. If the animation is a sequential QAnimationGroup,
665 the duration will be the sum of the duration of all its animations.
666 \sa loopCount
667*/
668
669/*!
670 Returns the total and effective duration of the animation, including the
671 loop count.
672
673 \sa duration(), currentTime
674*/
675int QAbstractAnimation::totalDuration() const
676{
677 int dura = duration();
678 if (dura <= 0)
679 return dura;
680 int loopcount = loopCount();
681 if (loopcount < 0)
682 return -1;
683 return dura * loopcount;
684}
685
686/*!
687 Returns the current time inside the current loop. It can go from 0 to duration().
688
689 \sa duration(), currentTime
690*/
691
692int QAbstractAnimation::currentLoopTime() const
693{
694 Q_D(const QAbstractAnimation);
695 return d->currentTime;
696}
697
698/*!
699 \property QAbstractAnimation::currentTime
700 \brief the current time and progress of the animation
701
702 This property describes the animation's current time. You can change the
703 current time by calling setCurrentTime, or you can call start() and let
704 the animation run, setting the current time automatically as the animation
705 progresses.
706
707 The animation's current time starts at 0, and ends at totalDuration().
708
709 \sa loopCount, currentLoopTime()
710 */
711int QAbstractAnimation::currentTime() const
712{
713 Q_D(const QAbstractAnimation);
714 return d->totalCurrentTime;
715}
716void QAbstractAnimation::setCurrentTime(int msecs)
717{
718 Q_D(QAbstractAnimation);
719 msecs = qMax(msecs, 0);
720
721 // Calculate new time and loop.
722 int dura = duration();
723 int totalDura = dura <= 0 ? dura : ((d->loopCount < 0) ? -1 : dura * d->loopCount);
724 if (totalDura != -1)
725 msecs = qMin(totalDura, msecs);
726 d->totalCurrentTime = msecs;
727
728 // Update new values.
729 int oldLoop = d->currentLoop;
730 d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
731 if (d->currentLoop == d->loopCount) {
732 //we're at the end
733 d->currentTime = qMax(0, dura);
734 d->currentLoop = qMax(0, d->loopCount - 1);
735 } else {
736 if (d->direction == Forward) {
737 d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
738 } else {
739 d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
740 if (d->currentTime == dura)
741 --d->currentLoop;
742 }
743 }
744
745 updateCurrentTime(d->currentTime);
746 if (d->currentLoop != oldLoop)
747 emit currentLoopChanged(d->currentLoop);
748
749 // All animations are responsible for stopping the animation when their
750 // own end state is reached; in this case the animation is time driven,
751 // and has reached the end.
752 if ((d->direction == Forward && d->totalCurrentTime == totalDura)
753 || (d->direction == Backward && d->totalCurrentTime == 0)) {
754 stop();
755 }
756}
757
758/*!
759 Starts the animation. The \a policy argument says whether or not the
760 animation should be deleted when it's done. When the animation starts, the
761 stateChanged() signal is emitted, and state() returns Running. When control
762 reaches the event loop, the animation will run by itself, periodically
763 calling updateCurrentTime() as the animation progresses.
764
765 If the animation is currently stopped or has already reached the end,
766 calling start() will rewind the animation and start again from the beginning.
767 When the animation reaches the end, the animation will either stop, or
768 if the loop level is more than 1, it will rewind and continue from the beginning.
769
770 If the animation is already running, this function does nothing.
771
772 \sa stop(), state()
773*/
774void QAbstractAnimation::start(DeletionPolicy policy)
775{
776 Q_D(QAbstractAnimation);
777 if (d->state == Running)
778 return;
779 d->deleteWhenStopped = policy;
780 d->setState(Running);
781}
782
783/*!
784 Stops the animation. When the animation is stopped, it emits the stateChanged()
785 signal, and state() returns Stopped. The current time is not changed.
786
787 If the animation stops by itself after reaching the end (i.e.,
788 currentLoopTime() == duration() and currentLoop() > loopCount() - 1), the
789 finished() signal is emitted.
790
791 \sa start(), state()
792 */
793void QAbstractAnimation::stop()
794{
795 Q_D(QAbstractAnimation);
796
797 d->setState(Stopped);
798}
799
800/*!
801 Pauses the animation. When the animation is paused, state() returns Paused.
802 The value of currentTime will remain unchanged until resume() or start()
803 is called. If you want to continue from the current time, call resume().
804
805 \sa start(), state(), resume()
806 */
807void QAbstractAnimation::pause()
808{
809 Q_D(QAbstractAnimation);
810 if (d->state == Stopped) {
811 qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
812 return;
813 }
814
815 d->setState(Paused);
816}
817
818/*!
819 Resumes the animation after it was paused. When the animation is resumed,
820 it emits the resumed() and stateChanged() signals. The currenttime is not
821 changed.
822
823 \sa start(), pause(), state()
824 */
825void QAbstractAnimation::resume()
826{
827 Q_D(QAbstractAnimation);
828 if (d->state != Paused) {
829 qWarning("QAbstractAnimation::resume: "
830 "Cannot resume an animation that is not paused");
831 return;
832 }
833
834 d->setState(Running);
835}
836
837/*!
838 If \a paused is true, the animation is paused.
839 If \a paused is false, the animation is resumed.
840
841 \sa state(), pause(), resume()
842*/
843void QAbstractAnimation::setPaused(bool paused)
844{
845 if (paused)
846 pause();
847 else
848 resume();
849}
850
851
852/*!
853 \reimp
854*/
855bool QAbstractAnimation::event(QEvent *event)
856{
857 return QObject::event(event);
858}
859
860/*!
861 \fn virtual void QAbstractAnimation::updateCurrentTime(int currentTime) = 0;
862
863 This pure virtual function is called every time the animation's
864 \a currentTime changes.
865
866 \sa updateState()
867*/
868
869/*!
870 This virtual function is called by QAbstractAnimation when the state
871 of the animation is changed from \a oldState to \a newState.
872
873 \sa start(), stop(), pause(), resume()
874*/
875void QAbstractAnimation::updateState(QAbstractAnimation::State newState,
876 QAbstractAnimation::State oldState)
877{
878 Q_UNUSED(oldState);
879 Q_UNUSED(newState);
880}
881
882/*!
883 This virtual function is called by QAbstractAnimation when the direction
884 of the animation is changed. The \a direction argument is the new direction.
885
886 \sa setDirection(), direction()
887*/
888void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
889{
890 Q_UNUSED(direction);
891}
892
893
894QT_END_NAMESPACE
895
896#include "moc_qabstractanimation.cpp"
897
898#endif //QT_NO_ANIMATION
Note: See TracBrowser for help on using the repository browser.