summaryrefslogtreecommitdiffstats
path: root/src/corelib/animation
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2009-05-26 07:41:06 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2009-05-26 07:41:06 (GMT)
commit12ebfedc3de64e99082ca573351bdd24b1d42370 (patch)
tree0290b22723ae07fb4b11e6f5008e5bae2050a12b /src/corelib/animation
parent7ffe42d376b574239480b38b8f6430339b806daa (diff)
parentbaec0ecd314c6e9563bd56cf19571ca71d7d11cd (diff)
downloadQt-12ebfedc3de64e99082ca573351bdd24b1d42370.zip
Qt-12ebfedc3de64e99082ca573351bdd24b1d42370.tar.gz
Qt-12ebfedc3de64e99082ca573351bdd24b1d42370.tar.bz2
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Conflicts: src/corelib/kernel/qcoreevent.h src/gui/graphicsview/qgraphicsitem_p.h
Diffstat (limited to 'src/corelib/animation')
-rw-r--r--src/corelib/animation/animation.pri25
-rw-r--r--src/corelib/animation/qabstractanimation.cpp733
-rw-r--r--src/corelib/animation/qabstractanimation.h137
-rw-r--r--src/corelib/animation/qabstractanimation_p.h150
-rw-r--r--src/corelib/animation/qanimationgroup.cpp309
-rw-r--r--src/corelib/animation/qanimationgroup.h88
-rw-r--r--src/corelib/animation/qanimationgroup_p.h79
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp316
-rw-r--r--src/corelib/animation/qparallelanimationgroup.h86
-rw-r--r--src/corelib/animation/qparallelanimationgroup_p.h85
-rw-r--r--src/corelib/animation/qpauseanimation.cpp154
-rw-r--r--src/corelib/animation/qpauseanimation.h84
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp316
-rw-r--r--src/corelib/animation/qpropertyanimation.h90
-rw-r--r--src/corelib/animation/qpropertyanimation_p.h89
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.cpp594
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.h96
-rw-r--r--src/corelib/animation/qsequentialanimationgroup_p.h111
-rw-r--r--src/corelib/animation/qvariantanimation.cpp653
-rw-r--r--src/corelib/animation/qvariantanimation.h130
-rw-r--r--src/corelib/animation/qvariantanimation_p.h130
21 files changed, 4455 insertions, 0 deletions
diff --git a/src/corelib/animation/animation.pri b/src/corelib/animation/animation.pri
new file mode 100644
index 0000000..cb7850c
--- /dev/null
+++ b/src/corelib/animation/animation.pri
@@ -0,0 +1,25 @@
+# Qt core animation module
+
+HEADERS += \
+ animation/qabstractanimation.h \
+ animation/qabstractanimation_p.h \
+ animation/qvariantanimation.h \
+ animation/qvariantanimation_p.h \
+ animation/qpropertyanimation.h \
+ animation/qpropertyanimation_p.h \
+ animation/qanimationgroup.h \
+ animation/qanimationgroup_p.h \
+ animation/qsequentialanimationgroup.h \
+ animation/qsequentialanimationgroup_p.h \
+ animation/qparallelanimationgroup.h \
+ animation/qparallelanimationgroup_p.h \
+ animation/qpauseanimation.h
+
+SOURCES += \
+ animation/qabstractanimation.cpp \
+ animation/qvariantanimation.cpp \
+ animation/qpropertyanimation.cpp \
+ animation/qanimationgroup.cpp \
+ animation/qsequentialanimationgroup.cpp \
+ animation/qparallelanimationgroup.cpp \
+ animation/qpauseanimation.cpp
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
new file mode 100644
index 0000000..16307e6
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -0,0 +1,733 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAbstractAnimation
+ \ingroup animation
+ \brief The QAbstractAnimation class is the base of all animations.
+ \since 4.6
+
+ The class defines the functions for the functionality shared by
+ all animations. By inheriting this class, you can create custom
+ animations that plug into the rest of the animation framework.
+
+ The progress of an animation is given by its current time
+ (currentTime()), which is measured in milliseconds from the start
+ of the animation (0) to its end (duration()). The value is updated
+ automatically while the animation is running. It can also be set
+ directly with setCurrentTime().
+
+ At any point an animation is in one of three states:
+ \l{QAbstractAnimation::}{Running},
+ \l{QAbstractAnimation::}{Stopped}, or
+ \l{QAbstractAnimation::}{Paused}--as defined by the
+ \l{QAbstractAnimation::}{State} enum. The current state can be
+ changed by calling start(), stop(), pause(), or resume(). An
+ animation will always reset its \l{currentTime()}{current time}
+ when it is started. If paused, it will continue with the same
+ current time when resumed. When an animation is stopped, it cannot
+ be resumed, but will keep its current time (until started again).
+ QAbstractAnimation will emit stateChanged() whenever its state
+ changes.
+
+ An animation can loop any number of times by setting the loopCount
+ property. When an animation's current time reaches its duration(),
+ it will reset the current time and keep running. A loop count of 1
+ (the default value) means that the animation will run one time.
+ Note that a duration of -1 means that the animation will run until
+ stopped; the current time will increase indefinitely. When the
+ current time equals duration() and the animation is in its
+ final loop, the \l{QAbstractAnimation::}{Stopped} state is
+ entered, and the finished() signal is emitted.
+
+ QAbstractAnimation provides pure virtual functions used by
+ subclasses to track the progress of the animation: duration() and
+ updateCurrentTime(). The duration() function lets you report a
+ duration for the animation (as discussed above). The current time
+ is delivered by the animation framework through calls to
+ updateCurrentTime(). By reimplementing this function, you can
+ track the animation progress. Note that neither the interval
+ between calls nor the number of calls to this function are
+ defined; though, it will normally be 60 updates per second.
+
+ By reimplementing updateState(), you can track the animation's
+ state changes, which is particularly useful for animations that
+ are not driven by time.
+
+ \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework}
+*/
+
+/*!
+ \enum QAbstractAnimation::DeletionPolicy
+
+ \value KeepWhenStopped The animation will not be deleted when stopped.
+ \value DeleteWhenStopped The animation will be automatically deleted when
+ stopped.
+*/
+
+/*!
+ \fn QAbstractAnimation::finished()
+
+ QAbstractAnimation emits this signal after the animation has stopped and
+ has reached the end.
+
+ This signal is emitted after stateChanged().
+
+ \sa stateChanged()
+*/
+
+/*!
+ \fn QAbstractAnimation::stateChanged(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
+
+ QAbstractAnimation emits this signal whenever the state of the animation has
+ changed from \a oldState to \a newState. This signal is emitted after the virtual
+ updateState() function is called.
+
+ \sa updateState()
+*/
+
+/*!
+ \fn QAbstractAnimation::currentLoopChanged(int currentLoop)
+
+ QAbstractAnimation emits this signal whenever the current loop
+ changes. \a currentLoop is the current loop.
+
+ \sa currentLoop(), loopCount()
+*/
+
+/*!
+ \fn QAbstractAnimation::directionChanged(QAbstractAnimation::Direction newDirection);
+
+ QAbstractAnimation emits this signal whenever the direction has been
+ changed. \a newDirection is the new direction.
+
+ \sa direction
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qabstractanimation.h"
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+
+#include "qabstractanimation_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qpointer.h>
+
+#define DEFAULT_TIMER_INTERVAL 16
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer);
+
+QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), consistentTiming(false)
+{
+}
+
+QUnifiedTimer *QUnifiedTimer::instance()
+{
+ QUnifiedTimer *inst;
+ if (!unifiedTimer()->hasLocalData()) {
+ inst = new QUnifiedTimer;
+ unifiedTimer()->setLocalData(inst);
+ } else {
+ inst = unifiedTimer()->localData();
+ }
+ return inst;
+}
+
+void QUnifiedTimer::updateRecentlyStartedAnimations()
+{
+ if (animationsToStart.isEmpty())
+ return;
+
+ animations += animationsToStart;
+ updateTimer(); //we make sure we start the timer there
+
+ animationsToStart.clear();
+}
+
+void QUnifiedTimer::timerEvent(QTimerEvent *event)
+{
+ //this is simply the time we last received a tick
+ const int oldLastTick = lastTick;
+ if (time.isValid())
+ lastTick = consistentTiming ? oldLastTick + timingInterval : time.elapsed();
+
+ //we transfer the waiting animations into the "really running" state
+ updateRecentlyStartedAnimations();
+
+ if (event->timerId() == startStopAnimationTimer.timerId()) {
+ startStopAnimationTimer.stop();
+ if (animations.isEmpty()) {
+ animationTimer.stop();
+ time = QTime();
+ } else {
+ animationTimer.start(timingInterval, this);
+ lastTick = 0;
+ time.start();
+ }
+ } else if (event->timerId() == animationTimer.timerId()) {
+ const int delta = lastTick - oldLastTick;
+ for (int i = 0; i < animations.count(); ++i) {
+ QAbstractAnimation *animation = animations.at(i);
+ int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
+ + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
+ animation->setCurrentTime(elapsed);
+ }
+ }
+}
+
+void QUnifiedTimer::updateTimer()
+{
+ //we delay the call to start and stop for the animation timer so that if you
+ //stop and start animations in batch you don't stop/start the timer too often.
+ if (!startStopAnimationTimer.isActive())
+ startStopAnimationTimer.start(0, this); // we delay the actual start of the animation
+}
+
+void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation)
+{
+ if (animations.contains(animation) ||animationsToStart.contains(animation))
+ return;
+ animationsToStart << animation;
+ updateTimer();
+}
+
+void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
+{
+ animations.removeAll(animation);
+ animationsToStart.removeAll(animation);
+ updateTimer();
+}
+
+
+void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
+{
+ Q_Q(QAbstractAnimation);
+ if (state == newState)
+ return;
+
+ QAbstractAnimation::State oldState = state;
+ int oldCurrentTime = currentTime;
+ int oldCurrentLoop = currentLoop;
+ QAbstractAnimation::Direction oldDirection = direction;
+
+ state = newState;
+
+ QPointer<QAbstractAnimation> guard(q);
+
+ guard->updateState(oldState, newState);
+
+ //this is to be safe if updateState changes the state
+ if (state == oldState)
+ return;
+
+ // Notify state change
+ if (guard)
+ emit guard->stateChanged(oldState, newState);
+
+ // Enter running state.
+ switch (state)
+ {
+ case QAbstractAnimation::Paused:
+ case QAbstractAnimation::Running:
+ {
+ // Rewind
+ if (oldState == QAbstractAnimation::Stopped) {
+ if (guard) {
+ if (direction == QAbstractAnimation::Forward)
+ q->setCurrentTime(0);
+ else
+ q->setCurrentTime(loopCount == -1 ? q->duration() : q->totalDuration());
+ }
+
+ // Check if the setCurrentTime() function called stop().
+ // This can happen for a 0-duration animation
+ if (state == QAbstractAnimation::Stopped)
+ return;
+ }
+
+ // Register timer if our parent is not running.
+ if (state == QAbstractAnimation::Running && guard) {
+ if (!group || group->state() == QAbstractAnimation::Stopped) {
+ QUnifiedTimer::instance()->registerAnimation(q);
+ }
+ } else {
+ //new state is paused
+ QUnifiedTimer::instance()->unregisterAnimation(q);
+ }
+ }
+ break;
+ case QAbstractAnimation::Stopped:
+ // Leave running state.
+ int dura = q->duration();
+ if (deleteWhenStopped && guard)
+ q->deleteLater();
+
+ QUnifiedTimer::instance()->unregisterAnimation(q);
+
+ if (dura == -1 || loopCount < 0
+ || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount))
+ || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
+ if (guard)
+ emit q->finished();
+ }
+ break;
+ }
+
+}
+
+/*!
+ Constructs the QAbstractAnimation base class, and passes \a parent to
+ QObject's constructor.
+
+ \sa QVariantAnimation, QAnimationGroup
+*/
+QAbstractAnimation::QAbstractAnimation(QObject *parent)
+ : QObject(*new QAbstractAnimationPrivate, 0)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+}
+
+/*!
+ \internal
+*/
+QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
+ : QObject(dd, 0)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+}
+
+/*!
+ Stops the animation if it's running, then destroys the
+ QAbstractAnimation. If the animation is part of a QAnimationGroup, it is
+ automatically removed before it's destroyed.
+*/
+QAbstractAnimation::~QAbstractAnimation()
+{
+ Q_D(QAbstractAnimation);
+ //we can't call stop here. Otherwise we get pure virtual calls
+ if (d->state != Stopped) {
+ QAbstractAnimation::State oldState = d->state;
+ d->state = Stopped;
+ emit stateChanged(oldState, d->state);
+ QUnifiedTimer::instance()->unregisterAnimation(this);
+ }
+}
+
+/*!
+ \property QAbstractAnimation::state
+ \brief state of the animation.
+
+ This property describes the current state of the animation. When the
+ animation state changes, QAbstractAnimation emits the stateChanged()
+ signal.
+*/
+QAbstractAnimation::State QAbstractAnimation::state() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->state;
+}
+
+/*!
+ If this animation is part of a QAnimationGroup, this function returns a
+ pointer to the group; otherwise, it returns 0.
+
+ \sa QAnimationGroup::addAnimation()
+*/
+QAnimationGroup *QAbstractAnimation::group() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->group;
+}
+
+/*!
+ \enum QAbstractAnimation::State
+
+ This enum describes the state of the animation.
+
+ \value Stopped The animation is not running. This is the initial state
+ of QAbstractAnimation, and the state QAbstractAnimation reenters when finished. The current
+ time remain unchanged until either setCurrentTime() is
+ called, or the animation is started by calling start().
+
+ \value Paused The animation is paused (i.e., temporarily
+ suspended). Calling resume() will resume animation activity.
+
+ \value Running The animation is running. While control is in the event
+ loop, QAbstractAnimation will update its current time at regular intervals,
+ calling updateCurrentTime() when appropriate.
+
+ \sa state(), stateChanged()
+*/
+
+/*!
+ \enum QAbstractAnimation::Direction
+
+ This enum describes the direction of the animation when in \l Running state.
+
+ \value Forward The current time of the animation increases with time (i.e.,
+ moves from 0 and towards the end / duration).
+
+ \value Backward The current time of the animation decreases with time (i.e.,
+ moves from the end / duration and towards 0).
+
+ \sa direction
+*/
+
+/*!
+ \property QAbstractAnimation::direction
+ \brief the direction of the animation when it is in \l Running
+ state.
+
+ This direction indicates whether the time moves from 0 towards the
+ animation duration, or from the value of the duration and towards 0 after
+ start() has been called.
+
+ By default, this property is set to \l Forward.
+*/
+QAbstractAnimation::Direction QAbstractAnimation::direction() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->direction;
+}
+void QAbstractAnimation::setDirection(Direction direction)
+{
+ Q_D(QAbstractAnimation);
+ if (d->direction == direction)
+ return;
+
+ d->direction = direction;
+ if (state() == Stopped) {
+ if (direction == Backward) {
+ d->currentTime = duration();
+ d->currentLoop = d->loopCount - 1;
+ } else {
+ d->currentTime = 0;
+ d->currentLoop = 0;
+ }
+ }
+ updateDirection(direction);
+ emit directionChanged(direction);
+}
+
+/*!
+ \property QAbstractAnimation::duration
+ \brief the duration of the animation.
+
+ If the duration is -1, it means that the duration is undefined.
+ In this case, loopCount is ignored.
+*/
+
+/*!
+ \property QAbstractAnimation::loopCount
+ \brief the loop count of the animation
+
+ This property describes the loop count of the animation as an integer.
+ By default this value is 1, indicating that the animation
+ should run once only, and then stop. By changing it you can let the
+ animation loop several times. With a value of 0, the animation will not
+ run at all, and with a value of -1, the animation will loop forever
+ until stopped.
+ It is not supported to have loop on an animation that has an undefined
+ duration. It will only run once.
+*/
+int QAbstractAnimation::loopCount() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->loopCount;
+}
+void QAbstractAnimation::setLoopCount(int loopCount)
+{
+ Q_D(QAbstractAnimation);
+ d->loopCount = loopCount;
+}
+
+/*!
+ \property QAbstractAnimation::currentLoop
+ \brief the current loop of the animation
+
+ This property describes the current loop of the animation. By default,
+ the animation's loop count is 1, and so the current loop will
+ always be 0. If the loop count is 2 and the animation runs past its
+ duration, it will automatically rewind and restart at current time 0, and
+ current loop 1, and so on.
+
+ When the current loop changes, QAbstractAnimation emits the
+ currentLoopChanged() signal.
+*/
+int QAbstractAnimation::currentLoop() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->currentLoop;
+}
+
+/*!
+ \fn virtual int QAbstractAnimation::duration() const = 0
+
+ This pure virtual function returns the duration of the animation, and
+ defines for how long QAbstractAnimation should update the current
+ time. This duration is local, and does not include the loop count.
+
+ A return value of -1 indicates that the animation has no defined duration;
+ the animation should run forever until stopped. This is useful for
+ animations that are not time driven, or where you cannot easily predict
+ its duration (e.g., event driven audio playback in a game).
+
+ If the animation is a parallel QAnimationGroup, the duration will be the longest
+ duration of all its animations. If the animation is a sequential QAnimationGroup,
+ the duration will be the sum of the duration of all its animations.
+ \sa loopCount
+*/
+
+/*!
+ Returns the total and effective duration of the animation, including the
+ loop count.
+
+ \sa duration(), currentTime
+*/
+int QAbstractAnimation::totalDuration() const
+{
+ Q_D(const QAbstractAnimation);
+ if (d->loopCount < 0)
+ return -1;
+ int dura = duration();
+ if (dura == -1)
+ return -1;
+ return dura * d->loopCount;
+}
+
+/*!
+ \property QAbstractAnimation::currentTime
+ \brief the current time and progress of the animation
+
+ This property describes the animation's current time. You can change the
+ current time by calling setCurrentTime, or you can call start() and let
+ the animation run, setting the current time automatically as the animation
+ progresses.
+
+ The animation's current time starts at 0, and ends at duration(). If the
+ animation's loopCount is larger than 1, the current time will rewind and
+ start at 0 again for the consecutive loops. If the animation has a pause.
+ currentTime will also include the duration of the pause.
+
+ \sa loopCount
+ */
+int QAbstractAnimation::currentTime() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->currentTime;
+}
+void QAbstractAnimation::setCurrentTime(int msecs)
+{
+ Q_D(QAbstractAnimation);
+ msecs = qMax(msecs, 0);
+
+ // Calculate new time and loop.
+ int dura = duration();
+ int totalDura = (d->loopCount < 0 || dura == -1) ? -1 : dura * d->loopCount;
+ if (totalDura != -1)
+ msecs = qMin(totalDura, msecs);
+ d->totalCurrentTime = msecs;
+
+ // Update new values.
+ int oldLoop = d->currentLoop;
+ d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
+ if (d->currentLoop == d->loopCount) {
+ //we're at the end
+ d->currentTime = qMax(0, dura);
+ d->currentLoop = qMax(0, d->loopCount - 1);
+ } else {
+ if (d->direction == Forward) {
+ d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
+ } else {
+ d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
+ if (d->currentTime == dura)
+ --d->currentLoop;
+ }
+ }
+
+ updateCurrentTime(msecs);
+ if (d->currentLoop != oldLoop)
+ emit currentLoopChanged(d->currentLoop);
+
+ // All animations are responsible for stopping the animation when their
+ // own end state is reached; in this case the animation is time driven,
+ // and has reached the end.
+ if ((d->direction == Forward && d->totalCurrentTime == totalDura)
+ || (d->direction == Backward && d->totalCurrentTime == 0)) {
+ stop();
+ }
+}
+
+/*!
+ Starts the animation. The \a policy argument says whether or not the
+ animation should be deleted when it's done. When the animation starts, the
+ stateChanged() signal is emitted, and state() returns Running. When control
+ reaches the event loop, the animation will run by itself, periodically
+ calling updateCurrentTime() as the animation progresses.
+
+ If the animation is currently stopped or has already reached the end,
+ calling start() will rewind the animation and start again from the beginning.
+ When the animation reaches the end, the animation will either stop, or
+ if the loop level is more than 1, it will rewind and continue from the beginning.
+
+ If the animation is already running, this function does nothing.
+
+ \sa stop(), state()
+*/
+void QAbstractAnimation::start(DeletionPolicy policy)
+{
+ Q_D(QAbstractAnimation);
+ if (d->state == Running)
+ return;
+ d->setState(Running);
+ d->deleteWhenStopped = policy;
+}
+
+/*!
+ Stops the animation. When the animation is stopped, it emits the stateChanged()
+ signal, and state() returns Stopped. The current time is not changed.
+
+ If the animation stops by itself after reaching the end (i.e.,
+ currentTime() == duration() and currentLoop() > loopCount() - 1), the
+ finished() signal is emitted.
+
+ \sa start(), state()
+ */
+void QAbstractAnimation::stop()
+{
+ Q_D(QAbstractAnimation);
+
+ d->setState(Stopped);
+}
+
+/*!
+ Pauses the animation. When the animation is paused, state() returns Paused.
+ The currenttime will remain unchanged until resume() or start() is called.
+ If you want to continue from the current time, call resume().
+
+
+ \sa start(), state(), resume()
+ */
+void QAbstractAnimation::pause()
+{
+ Q_D(QAbstractAnimation);
+ if (d->state == Stopped) {
+ qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
+ return;
+ }
+
+ d->setState(Paused);
+}
+
+/*!
+ Resumes the animation after it was paused. When the animation is resumed,
+ it emits the resumed() and stateChanged() signals. The currenttime is not
+ changed.
+
+ \sa start(), pause(), state()
+ */
+void QAbstractAnimation::resume()
+{
+ Q_D(QAbstractAnimation);
+ if (d->state != Paused) {
+ qWarning("QAbstractAnimation::resume: "
+ "Cannot resume an animation that is not paused");
+ return;
+ }
+
+ d->setState(Running);
+}
+
+/*!
+ \reimp
+*/
+bool QAbstractAnimation::event(QEvent *event)
+{
+ return QObject::event(event);
+}
+
+/*!
+ \fn virtual void QAbstractAnimation::updateCurrentTime(int msecs) = 0;
+
+ This pure virtual function is called every time the animation's current
+ time changes. The \a msecs argument is the current time.
+
+ \sa updateState()
+*/
+
+/*!
+ This virtual function is called by QAbstractAnimation when the state
+ of the animation is changed from \a oldState to \a newState.
+
+ \sa start(), stop(), pause(), resume()
+*/
+void QAbstractAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_UNUSED(oldState);
+ Q_UNUSED(newState);
+}
+
+/*!
+ This virtual function is called by QAbstractAnimation when the direction
+ of the animation is changed. The \a direction argument is the new direction.
+
+ \sa setDirection(), direction()
+*/
+void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_UNUSED(direction);
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qabstractanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h
new file mode 100644
index 0000000..d6d50dc
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTANIMATION_H
+#define QABSTRACTANIMATION_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QAnimationGroup;
+class QSequentialAnimationGroup;
+
+class QAbstractAnimationPrivate;
+class Q_CORE_EXPORT QAbstractAnimation : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
+ Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime)
+ Q_PROPERTY(int currentLoop READ currentLoop NOTIFY currentLoopChanged)
+ Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged)
+ Q_PROPERTY(int duration READ duration)
+
+public:
+ enum Direction {
+ Forward,
+ Backward
+ };
+
+ enum State {
+ Stopped,
+ Paused,
+ Running
+ };
+
+ enum DeletionPolicy {
+ KeepWhenStopped = 0,
+ DeleteWhenStopped
+ };
+
+ QAbstractAnimation(QObject *parent = 0);
+ virtual ~QAbstractAnimation();
+
+ State state() const;
+
+ QAnimationGroup *group() const;
+
+ Direction direction() const;
+ void setDirection(Direction direction);
+
+ int loopCount() const;
+ void setLoopCount(int loopCount);
+ int currentLoop() const;
+
+ virtual int duration() const = 0;
+ int totalDuration() const;
+
+ int currentTime() const;
+
+Q_SIGNALS:
+ void finished();
+ void stateChanged(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void currentLoopChanged(int currentLoop);
+ void directionChanged(QAbstractAnimation::Direction);
+
+public Q_SLOTS:
+ void start(QAbstractAnimation::DeletionPolicy policy = KeepWhenStopped);
+ void pause();
+ void resume();
+ void stop();
+ void setCurrentTime(int msecs);
+
+protected:
+ QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent = 0);
+ bool event(QEvent *event);
+
+ virtual void updateCurrentTime(int msecs) = 0;
+ virtual void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ virtual void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QAbstractAnimation)
+ Q_DECLARE_PRIVATE(QAbstractAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTANIMATION_H
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
new file mode 100644
index 0000000..7a4bfcf
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTANIMATION_P_H
+#define QABSTRACTANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qbasictimer.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qtimer.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationGroup;
+class QAbstractAnimation;
+class QAbstractAnimationPrivate : public QObjectPrivate
+{
+public:
+ QAbstractAnimationPrivate()
+ : state(QAbstractAnimation::Stopped),
+ direction(QAbstractAnimation::Forward),
+ deleteWhenStopped(false),
+ totalCurrentTime(0),
+ currentTime(0),
+ loopCount(1),
+ currentLoop(0),
+ group(0)
+ {
+ }
+
+ virtual ~QAbstractAnimationPrivate() {}
+
+ static QAbstractAnimationPrivate *get(QAbstractAnimation *q)
+ {
+ return q->d_func();
+ }
+
+ QAbstractAnimation::State state;
+ QAbstractAnimation::Direction direction;
+ bool deleteWhenStopped;
+ void setState(QAbstractAnimation::State state);
+
+ int totalCurrentTime;
+ int currentTime;
+ int loopCount;
+ int currentLoop;
+
+ QAnimationGroup *group;
+
+private:
+ Q_DECLARE_PUBLIC(QAbstractAnimation)
+};
+
+
+class QUnifiedTimer : public QObject
+{
+private:
+ QUnifiedTimer();
+
+public:
+ //XXX this is needed by dui
+ static Q_CORE_EXPORT QUnifiedTimer *instance();
+
+ void registerAnimation(QAbstractAnimation *animation);
+ void unregisterAnimation(QAbstractAnimation *animation);
+
+ //defines the timing interval. Default is DEFAULT_TIMER_INTERVAL
+ void setTimingInterval(int interval)
+ {
+ timingInterval = interval;
+ if (animationTimer.isActive()) {
+ //we changed the timing interval
+ animationTimer.start(timingInterval, this);
+ }
+ }
+
+ /*
+ this allows to have a consistent timer interval at each tick from the timer
+ not taking the real time that passed into account.
+ */
+ void setConsistentTiming(bool consistent) { consistentTiming = consistent; }
+
+ int elapsedTime() const { return lastTick; }
+
+protected:
+ void timerEvent(QTimerEvent *);
+ void updateTimer();
+
+private:
+ void updateRecentlyStartedAnimations();
+
+ QBasicTimer animationTimer, startStopAnimationTimer;
+ QTime time;
+ int lastTick;
+ int timingInterval;
+ bool consistentTiming;
+ QList<QAbstractAnimation*> animations, animationsToStart;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp
new file mode 100644
index 0000000..839b522
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup.cpp
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAnimationGroup
+ \brief The QAnimationGroup class is an abstract base class for groups of animations.
+ \since 4.6
+ \ingroup animation
+
+ An animation group is a container for animations (subclasses of
+ QAbstractAnimation). A group is usually responsible for managing
+ the \l{QAbstractAnimation::State}{state} of its animations, i.e.,
+ it decides when to start, stop, resume, and pause them. Currently,
+ Qt provides two such groups: QParallelAnimationGroup and
+ QSequentialAnimationGroup. Look up their class descriptions for
+ details.
+
+ Since QAnimationGroup inherits from QAbstractAnimation, you can
+ combine groups, and easily construct complex animation graphs.
+ You can query QAbstractAnimation for the group it belongs to
+ (using the \l{QAbstractAnimation::}{group()} function).
+
+ To start a top-level animation group, you simply use the
+ \l{QAbstractAnimation::}{start()} function from
+ QAbstractAnimation. By a top-level animation group, we think of a
+ group that itself is not contained within another group. Starting
+ sub groups directly is not supported, and may lead to unexpected
+ behavior.
+
+ \omit OK, we'll put in a snippet on this here \endomit
+
+ QAnimationGroup provides methods for adding and retrieving
+ animations. Besides that, you can remove animations by calling
+ remove(), and clear the animation group by calling
+ clearAnimations(). You may keep track of changes in the group's
+ animations by listening to QEvent::ChildAdded and
+ QEvent::ChildRemoved events.
+
+ \omit OK, let's find a snippet here as well. \endomit
+
+ QAnimationGroup takes ownership of the animations it manages, and
+ ensures that they are deleted when the animation group is deleted.
+
+ You can also use a \l{The State Machine Framework}{state machine}
+ to create complex animations. The framework provides a special
+ state, QAnimationState, that plays an animation upon entry and
+ transitions to a new state when the animation has finished
+ playing. This technique can also be combined with using animation
+ groups.
+
+ \sa QAbstractAnimation, QVariantAnimation, {The Animation Framework}
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreevent.h>
+#include "qanimationgroup_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ Constructs a QAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QAnimationGroup::QAnimationGroup(QObject *parent)
+ : QAbstractAnimation(*new QAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QAnimationGroup::QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent)
+ : QAbstractAnimation(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QAnimationGroup::~QAnimationGroup()
+{
+}
+
+/*!
+ Returns a pointer to the animation at \a index in this group. This
+ function is useful when you need access to a particular animation. \a
+ index is between 0 and animationCount() - 1.
+
+ \sa animationCount(), indexOfAnimation()
+*/
+QAbstractAnimation *QAnimationGroup::animationAt(int index) const
+{
+ Q_D(const QAnimationGroup);
+
+ if (index < 0 || index >= d->animations.size()) {
+ qWarning("QAnimationGroup::animationAt: index is out of bounds");
+ return 0;
+ }
+
+ return d->animations.at(index);
+}
+
+
+/*!
+ Returns the number of animations managed by this group.
+
+ \sa indexOfAnimation(), addAnimation(), animationAt()
+*/
+int QAnimationGroup::animationCount() const
+{
+ Q_D(const QAnimationGroup);
+ return d->animations.size();
+}
+
+/*!
+ Returns the index of \a animation. The returned index can be passed
+ to the other functions that take an index as an argument.
+
+ \sa insertAnimationAt(), animationAt(), takeAnimationAt()
+*/
+int QAnimationGroup::indexOfAnimation(QAbstractAnimation *animation) const
+{
+ Q_D(const QAnimationGroup);
+ return d->animations.indexOf(animation);
+}
+
+/*!
+ Adds \a animation to this group. This will call insertAnimationAt with
+ index equals to animationCount().
+
+ \note The group takes ownership of the animation.
+
+ \sa removeAnimation()
+*/
+void QAnimationGroup::addAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+ insertAnimationAt(d->animations.count(), animation);
+}
+
+/*!
+ Inserts \a animation into this animation group at \a index.
+ If \a index is 0 the animation is inserted at the beginning.
+ If \a index is animationCount(), the animation is inserted at the end.
+
+ \note The group takes ownership of the animation.
+
+ \sa takeAnimationAt(), addAnimation(), indexOfAnimation(), removeAnimation()
+*/
+void QAnimationGroup::insertAnimationAt(int index, QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+
+ if (index < 0 || index > d->animations.size()) {
+ qWarning("QAnimationGroup::insertAnimationAt: index is out of bounds");
+ return;
+ }
+
+ if (QAnimationGroup *oldGroup = animation->group())
+ oldGroup->removeAnimation(animation);
+
+ d->animations.insert(index, animation);
+ QAbstractAnimationPrivate::get(animation)->group = this;
+ // this will make sure that ChildAdded event is sent to 'this'
+ animation->setParent(this);
+ d->animationInsertedAt(index);
+}
+
+/*!
+ Removes \a animation from this group. The ownership of \a animation is
+ transferred to the caller.
+
+ \sa takeAnimationAt(), insertAnimationAt(), addAnimation()
+*/
+void QAnimationGroup::removeAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+
+ if (!animation) {
+ qWarning("QAnimationGroup::remove: cannot remove null animation");
+ return;
+ }
+ int index = d->animations.indexOf(animation);
+ if (index == -1) {
+ qWarning("QAnimationGroup::remove: animation is not part of this group");
+ return;
+ }
+
+ takeAnimationAt(index);
+}
+
+/*!
+ Returns the animation at \a index and removes it from the animation group.
+
+ \note The ownership of the animation is transferred to the caller.
+
+ \sa removeAnimation(), addAnimation(), insertAnimationAt(), indexOfAnimation()
+*/
+QAbstractAnimation *QAnimationGroup::takeAnimationAt(int index)
+{
+ Q_D(QAnimationGroup);
+ if (index < 0 || index >= d->animations.size()) {
+ qWarning("QAnimationGroup::takeAnimationAt: no animation at index %d", index);
+ return 0;
+ }
+ QAbstractAnimation *animation = d->animations.at(index);
+ QAbstractAnimationPrivate::get(animation)->group = 0;
+ // ### removing from list before doing setParent to avoid inifinite recursion
+ // in ChildRemoved event
+ d->animations.removeAt(index);
+ animation->setParent(0);
+ d->animationRemovedAt(index);
+ return animation;
+}
+
+/*!
+ Removes and deletes all animations in this animation group, and resets the current
+ time to 0.
+
+ \sa addAnimation(), removeAnimation()
+*/
+void QAnimationGroup::clearAnimations()
+{
+ Q_D(QAnimationGroup);
+ qDeleteAll(d->animations);
+}
+
+/*!
+ \reimp
+*/
+bool QAnimationGroup::event(QEvent *event)
+{
+ Q_D(QAnimationGroup);
+ if (event->type() == QEvent::ChildAdded) {
+ QChildEvent *childEvent = static_cast<QChildEvent *>(event);
+ if (QAbstractAnimation *a = qobject_cast<QAbstractAnimation *>(childEvent->child())) {
+ if (a->group() != this)
+ addAnimation(a);
+ }
+ } else if (event->type() == QEvent::ChildRemoved) {
+ QChildEvent *childEvent = static_cast<QChildEvent *>(event);
+ QAbstractAnimation *a = static_cast<QAbstractAnimation *>(childEvent->child());
+ // You can only rely on the child being a QObject because in the QEvent::ChildRemoved
+ // case it might be called from the destructor.
+ int index = d->animations.indexOf(a);
+ if (index != -1)
+ takeAnimationAt(index);
+ }
+ return QAbstractAnimation::event(event);
+}
+
+
+void QAnimationGroupPrivate::animationRemovedAt(int index)
+{
+ Q_Q(QAnimationGroup);
+ Q_UNUSED(index);
+ if (animations.isEmpty()) {
+ currentTime = 0;
+ q->stop();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qanimationgroup.h b/src/corelib/animation/qanimationgroup.h
new file mode 100644
index 0000000..263bc38
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONGROUP_H
+#define QANIMATIONGROUP_H
+
+#include <QtCore/qabstractanimation.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QAnimationGroupPrivate;
+class Q_CORE_EXPORT QAnimationGroup : public QAbstractAnimation
+{
+ Q_OBJECT
+
+public:
+ QAnimationGroup(QObject *parent = 0);
+ ~QAnimationGroup();
+
+ QAbstractAnimation *animationAt(int index) const;
+ int animationCount() const;
+ int indexOfAnimation(QAbstractAnimation *animation) const;
+ void addAnimation(QAbstractAnimation *animation);
+ void insertAnimationAt(int index, QAbstractAnimation *animation);
+ void removeAnimation(QAbstractAnimation *animation);
+ QAbstractAnimation *takeAnimationAt(int index);
+ void clearAnimations();
+
+protected:
+ QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QAnimationGroup)
+ Q_DECLARE_PRIVATE(QAnimationGroup)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QANIMATIONGROUP_H
diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h
new file mode 100644
index 0000000..a7bd0fa
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONGROUP_P_H
+#define QANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qanimationgroup.h"
+
+#include <QtCore/qlist.h>
+
+#include "qabstractanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationGroupPrivate : public QAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QAnimationGroup)
+public:
+ QAnimationGroupPrivate()
+ { }
+
+ virtual void animationInsertedAt(int index) { Q_UNUSED(index) };
+ virtual void animationRemovedAt(int index);
+
+ QList<QAbstractAnimation *> animations;
+};
+
+QT_END_NAMESPACE
+
+#endif //QANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp
new file mode 100644
index 0000000..13f6073
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QParallelAnimationGroup
+ \brief The QParallelAnimationGroup class provides a parallel group of animations.
+ \since 4.6
+ \ingroup animation
+
+ QParallelAnimationGroup--a \l{QAnimationGroup}{container for
+ animations}--starts all its animations when it is
+ \l{QAbstractAnimation::start()}{started} itself, i.e., runs all
+ animations in parallel. The animation group finishes when the
+ longest lasting animation has finished.
+
+ You can treat QParallelAnimation as any other QAbstractAnimation,
+ e.g., pause, resume, or add it to other animation groups.
+
+ \code
+ QParallelAnimationGroup *group = new QParallelAnimationGroup;
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+
+ group->start();
+ \endcode
+
+ In this example, \c anim1 and \c anim2 are two
+ \l{QPropertyAnimation}s that have already been set up.
+
+ \sa QAnimationGroup, QPropertyAnimation, {The Animation Framework}
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qparallelanimationgroup.h"
+#include "qparallelanimationgroup_p.h"
+//#define QANIMATION_DEBUG
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a QParallelAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QParallelAnimationGroup::QParallelAnimationGroup(QObject *parent)
+ : QAnimationGroup(*new QParallelAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QParallelAnimationGroup::QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd,
+ QObject *parent)
+ : QAnimationGroup(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QParallelAnimationGroup::~QParallelAnimationGroup()
+{
+}
+
+/*!
+ \reimp
+*/
+int QParallelAnimationGroup::duration() const
+{
+ Q_D(const QParallelAnimationGroup);
+ int ret = 0;
+
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int currentDuration = animation->totalDuration();
+ if (currentDuration == -1)
+ return -1; // Undetermined length
+
+ ret = qMax(ret, currentDuration);
+ }
+
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateCurrentTime(int)
+{
+ Q_D(QParallelAnimationGroup);
+ if (d->animations.isEmpty())
+ return;
+
+ if (d->currentLoop > d->lastLoop) {
+ // simulate completion of the loop
+ int dura = duration();
+ if (dura > 0) {
+ foreach (QAbstractAnimation *animation, d->animations) {
+ animation->setCurrentTime(dura); // will stop
+ }
+ }
+ } else if (d->currentLoop < d->lastLoop) {
+ // simulate completion of the loop seeking backwards
+ foreach (QAbstractAnimation *animation, d->animations) {
+ animation->setCurrentTime(0);
+ animation->stop();
+ }
+ }
+
+ bool timeFwd = ((d->currentLoop == d->lastLoop && d->currentTime >= d->lastCurrentTime)
+ || d->currentLoop > d->lastLoop);
+#ifdef QANIMATION_DEBUG
+ qDebug("QParallellAnimationGroup %5d: setCurrentTime(%d), loop:%d, last:%d, timeFwd:%d, lastcurrent:%d, %d",
+ __LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state());
+#endif
+ // finally move into the actual time of the current loop
+ foreach (QAbstractAnimation *animation, d->animations) {
+ const int dura = animation->totalDuration();
+ if (dura == -1 && d->isUncontrolledAnimationFinished(animation))
+ continue;
+ if (dura == -1 || (d->currentTime <= dura && dura != 0)
+ || (dura == 0 && d->currentLoop != d->lastLoop)) {
+ switch (state()) {
+ case Running:
+ animation->start();
+ break;
+ case Paused:
+ animation->pause();
+ break;
+ case Stopped:
+ default:
+ break;
+ }
+ }
+
+ if (dura <= 0) {
+ if (dura == -1)
+ animation->setCurrentTime(d->currentTime);
+ continue;
+ }
+
+ if ((timeFwd && d->lastCurrentTime <= dura)
+ || (!timeFwd && d->currentTime <= dura))
+ animation->setCurrentTime(d->currentTime);
+ if (d->currentTime > dura)
+ animation->stop();
+ }
+ d->lastLoop = d->currentLoop;
+ d->lastCurrentTime = d->currentTime;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QParallelAnimationGroup);
+ QAnimationGroup::updateState(oldState, newState);
+
+ switch (newState) {
+ case Stopped:
+ foreach (QAbstractAnimation *animation, d->animations)
+ animation->stop();
+ d->disconnectUncontrolledAnimations();
+ break;
+ case Paused:
+ foreach (QAbstractAnimation *animation, d->animations)
+ animation->pause();
+ break;
+ case Running:
+ d->connectUncontrolledAnimations();
+ foreach (QAbstractAnimation *animation, d->animations) {
+ animation->stop();
+ animation->setDirection(d->direction);
+ animation->start();
+ }
+ break;
+ }
+}
+
+void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ QAbstractAnimation *animation = qobject_cast<QAbstractAnimation *>(q->sender());
+ Q_ASSERT(animation);
+
+ int uncontrolledRunningCount = 0;
+ if (animation->duration() == -1 || animation->loopCount() < 0) {
+ QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
+ while (it != uncontrolledFinishTime.end()) {
+ if (it.key() == animation) {
+ *it = animation->currentTime();
+ }
+ if (it.value() == -1)
+ ++uncontrolledRunningCount;
+ ++it;
+ }
+ }
+
+ if (uncontrolledRunningCount > 0)
+ return;
+
+ int maxDuration = 0;
+ foreach (QAbstractAnimation *a, animations)
+ maxDuration = qMax(maxDuration, a->totalDuration());
+
+ if (currentTime >= maxDuration)
+ q->stop();
+}
+
+void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
+ while (it != uncontrolledFinishTime.end()) {
+ QObject::disconnect(it.key(), SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+ ++it;
+ }
+
+ uncontrolledFinishTime.clear();
+}
+
+void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ foreach (QAbstractAnimation *animation, animations) {
+ if (animation->duration() == -1 || animation->loopCount() < 0) {
+ uncontrolledFinishTime[animation] = -1;
+ QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+ }
+ }
+}
+
+bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAnimation *anim) const
+{
+ return uncontrolledFinishTime.value(anim, -1) >= 0;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_D(QParallelAnimationGroup);
+ //we need to update the direction of the current animation
+ if (state() != Stopped) {
+ foreach(QAbstractAnimation *anim, d->animations) {
+ anim->setDirection(direction);
+ }
+ } else {
+ if (direction == Forward) {
+ d->lastLoop = 0;
+ d->lastCurrentTime = 0;
+ } else {
+ // Looping backwards with loopCount == -1 does not really work well...
+ d->lastLoop = (d->loopCount == -1 ? 0 : d->loopCount - 1);
+ d->lastCurrentTime = duration();
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QParallelAnimationGroup::event(QEvent *event)
+{
+ return QAnimationGroup::event(event);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qparallelanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qparallelanimationgroup.h b/src/corelib/animation/qparallelanimationgroup.h
new file mode 100644
index 0000000..57a8146
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPARALLELANIMATIONGROUP_H
+#define QPARALLELANIMATIONGROUP_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QParallelAnimationGroupPrivate;
+class Q_CORE_EXPORT QParallelAnimationGroup : public QAnimationGroup
+{
+ Q_OBJECT
+
+public:
+ QParallelAnimationGroup(QObject *parent = 0);
+ ~QParallelAnimationGroup();
+
+ int duration() const;
+
+protected:
+ QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QParallelAnimationGroup)
+ Q_DECLARE_PRIVATE(QParallelAnimationGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished())
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPARALLELANIMATIONGROUP
diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h
new file mode 100644
index 0000000..f36d972
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPARALLELANIMATIONGROUP_P_H
+#define QPARALLELANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qparallelanimationgroup.h"
+#include "qanimationgroup_p.h"
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QParallelAnimationGroupPrivate : public QAnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QParallelAnimationGroup)
+public:
+ QParallelAnimationGroupPrivate()
+ : lastLoop(0), lastCurrentTime(0)
+ {
+ }
+
+ QHash<QAbstractAnimation*, int> uncontrolledFinishTime;
+ int lastLoop;
+ int lastCurrentTime;
+
+ bool isUncontrolledAnimationFinished(QAbstractAnimation *anim) const;
+ void connectUncontrolledAnimations();
+ void disconnectUncontrolledAnimations();
+
+ // private slot
+ void _q_uncontrolledAnimationFinished();
+};
+
+QT_END_NAMESPACE
+
+#endif //QPARALLELANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp
new file mode 100644
index 0000000..b175f0c
--- /dev/null
+++ b/src/corelib/animation/qpauseanimation.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPauseAnimation
+ \brief The QPauseAnimation class provides a pause for QSequentialAnimationGroup.
+ \since 4.6
+ \ingroup animation
+
+ If you wish to introduce a delay between animations in a
+ QSequentialAnimationGroup, you can insert a QPauseAnimation. This
+ class does not animate anything, but does not
+ \l{QAbstractAnimation::finished()}{finish} before a specified
+ number of milliseconds have elapsed from when it was started. You
+ specify the duration of the pause in the constructor. It can also
+ be set directly with setDuration().
+
+ It is not necessary to construct a QPauseAnimation yourself.
+ QSequentialAnimationGroup provides the convenience functions
+ \l{QSequentialAnimationGroup::}{addPause()} and
+ \l{QSequentialAnimationGroup::}{insertPauseAt()}. These functions
+ simply take the number of milliseconds the pause should last.
+
+ \sa QSequentialAnimationGroup
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qpauseanimation.h"
+#include "qabstractanimation_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QPauseAnimationPrivate : public QAbstractAnimationPrivate
+{
+public:
+ QPauseAnimationPrivate() : QAbstractAnimationPrivate(), duration(0)
+ {
+ }
+
+ int duration;
+};
+
+/*!
+ Constructs a QPauseAnimation.
+ \a parent is passed to QObject's constructor.
+ The default duration is 0.
+*/
+
+QPauseAnimation::QPauseAnimation(QObject *parent) : QAbstractAnimation(*new QPauseAnimationPrivate, parent)
+{
+}
+
+/*!
+ Constructs a QPauseAnimation.
+ \a msecs is the duration of the pause.
+ \a parent is passed to QObject's constructor.
+*/
+
+QPauseAnimation::QPauseAnimation(int msecs, QObject *parent) : QAbstractAnimation(*new QPauseAnimationPrivate, parent)
+{
+ setDuration(msecs);
+}
+
+/*!
+ Destroys the pause animation.
+*/
+QPauseAnimation::~QPauseAnimation()
+{
+}
+
+/*!
+ \property QPauseAnimation::duration
+ \brief the duration of the pause.
+
+ The duration of the pause. The duration should not be negative.
+*/
+int QPauseAnimation::duration() const
+{
+ Q_D(const QPauseAnimation);
+ return d->duration;
+}
+
+void QPauseAnimation::setDuration(int msecs)
+{
+ if (msecs < 0) {
+ qWarning("QPauseAnimation::setDuration: cannot set a negative duration");
+ return;
+ }
+ Q_D(QPauseAnimation);
+ d->duration = msecs;
+}
+
+/*!
+ \reimp
+ */
+bool QPauseAnimation::event(QEvent *e)
+{
+ return QAbstractAnimation::event(e);
+}
+
+/*!
+ \reimp
+ */
+void QPauseAnimation::updateCurrentTime(int msecs)
+{
+ Q_UNUSED(msecs);
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qpauseanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qpauseanimation.h b/src/corelib/animation/qpauseanimation.h
new file mode 100644
index 0000000..cb6e041
--- /dev/null
+++ b/src/corelib/animation/qpauseanimation.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAUSEANIMATION_P_H
+#define QPAUSEANIMATION_P_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPauseAnimationPrivate;
+
+class Q_CORE_EXPORT QPauseAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(int duration READ duration WRITE setDuration)
+public:
+ QPauseAnimation(QObject *parent = 0);
+ QPauseAnimation(int msecs, QObject *parent = 0);
+ ~QPauseAnimation();
+
+ int duration() const;
+ void setDuration(int msecs);
+
+protected:
+ bool event(QEvent *e);
+ void updateCurrentTime(int msecs);
+
+private:
+ Q_DISABLE_COPY(QPauseAnimation)
+ Q_DECLARE_PRIVATE(QPauseAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPAUSEANIMATION_P_H
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
new file mode 100644
index 0000000..9a17049
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPropertyAnimation
+ \brief The QPropertyAnimation class animates Qt properties
+ \since 4.6
+ \ingroup animation
+
+ QPropertyAnimation interpolates over \l{Qt's Property System}{Qt
+ properties}. As property values are stored in \l{QVariant}s, the
+ class inherits QVariantAnimation, and supports animation of the
+ same \l{QVariant::Type}{variant types} as its super class.
+
+ A class declaring properties must be a QObject. To make it
+ possible to animate a property, it must provide a setter (so that
+ QPropertyAnimation can set the property's value). Note that this
+ makes it possible to animate many of Qt's widgets. Let's look at
+ an example:
+
+ \code
+ QPropertyAnimation animation(myWidget, "geometry");
+ animation.setDuration(10000);
+ animation.setStartValue(QRect(0, 0, 100, 30));
+ animation.setEndValue(QRect(250, 250, 100, 30));
+
+ animation.start();
+ \endcode
+
+ The property name and the QObject instance of which property
+ should be animated are passed to the constructor. You can then
+ specify the start and end value of the property. The procedure is
+ equal for properties in classes you have implemented
+ yourself--just check with QVariantAnimation that your QVariant
+ type is supported.
+
+ The QVariantAnimation class description explains how to set up the
+ animation in detail. Note, however, that if a start value is not
+ set, the property will start at the value it had when the
+ QPropertyAnimation instance was created.
+
+ QPropertyAnimation works like a charm on its own. For complex
+ animations that, for instance, contain several objects,
+ QAnimationGroup is provided. An animation group is an animation
+ that can contain other animations, and that can manage when its
+ animations are played. Look at QParallelAnimationGroup for an
+ example.
+
+ \sa QVariantAnimation, QAnimationGroup, {The Animation Framework}
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qpropertyanimation.h"
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+
+#include "qpropertyanimation_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef QPair<QObject *, QByteArray> QPropertyAnimationPair;
+typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash;
+Q_GLOBAL_STATIC(QPropertyAnimationHash, _q_runningAnimations);
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, guardHashLock, (QMutex::Recursive) )
+
+void QPropertyAnimationPrivate::updateMetaProperty()
+{
+ if (!target || propertyName.isEmpty())
+ return;
+
+ if (hasMetaProperty == 0 && !property.isValid()) {
+ const QMetaObject *mo = target->metaObject();
+ propertyIndex = mo->indexOfProperty(propertyName);
+ if (propertyIndex != -1) {
+ hasMetaProperty = 1;
+ property = mo->property(propertyIndex);
+ propertyType = property.userType();
+ } else {
+ if (!target->dynamicPropertyNames().contains(propertyName))
+ qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of your QObject", propertyName.constData());
+ hasMetaProperty = 2;
+ }
+ }
+
+ if (property.isValid())
+ convertValues(propertyType);
+}
+
+void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
+{
+ if (!target || state == QAbstractAnimation::Stopped)
+ return;
+
+ if (hasMetaProperty == 1) {
+ if (newValue.userType() == propertyType) {
+ //no conversion is needed, we directly call the QObject::qt_metacall
+ void *data = const_cast<void*>(newValue.constData());
+ target->qt_metacall(QMetaObject::WriteProperty, propertyIndex, &data);
+ } else {
+ property.write(target, newValue);
+ }
+ } else {
+ target->setProperty(propertyName.constData(), newValue);
+ }
+}
+
+void QPropertyAnimationPrivate::_q_targetDestroyed()
+{
+ Q_Q(QPropertyAnimation);
+ //we stop here so that this animation is removed from the global hash
+ q->stop();
+ target = 0;
+}
+
+/*!
+ Construct a QPropertyAnimation object. \a parent is passed to QObject's
+ constructor.
+*/
+QPropertyAnimation::QPropertyAnimation(QObject *parent)
+ : QVariantAnimation(*new QPropertyAnimationPrivate, parent)
+{
+}
+
+/*!
+ Construct a QPropertyAnimation object. \a parent is passed to QObject's
+ constructor. The animation changes the property \a propertyName on \a
+ target. The default duration is 250ms.
+
+ \sa targetObject, propertyName
+*/
+QPropertyAnimation::QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent)
+ : QVariantAnimation(*new QPropertyAnimationPrivate, parent)
+{
+ setTargetObject(target);
+ setPropertyName(propertyName);
+}
+
+/*!
+ Destroys the QPropertyAnimation instance.
+ */
+QPropertyAnimation::~QPropertyAnimation()
+{
+ stop();
+}
+
+/*!
+ \property QPropertyAnimation::targetObject
+ \brief the target QObject for this animation.
+
+ This property defines the target QObject for this animation.
+ */
+QObject *QPropertyAnimation::targetObject() const
+{
+ Q_D(const QPropertyAnimation);
+ return d->target;
+}
+
+void QPropertyAnimation::setTargetObject(QObject *target)
+{
+ Q_D(QPropertyAnimation);
+ if (d->target == target)
+ return;
+
+ if (d->state != QAbstractAnimation::Stopped) {
+ qWarning("QPropertyAnimation::setTargetObject: you can't change the target of a running animation");
+ return;
+ }
+
+ //we need to get notified when the target is destroyed
+ if (d->target)
+ disconnect(d->target, SIGNAL(destroyed()), this, SLOT(_q_targetDestroyed()));
+
+ if (target)
+ connect(target, SIGNAL(destroyed()), SLOT(_q_targetDestroyed()));
+
+ d->target = target;
+ d->hasMetaProperty = 0;
+ d->updateMetaProperty();
+}
+
+/*!
+ \property QPropertyAnimation::propertyName
+ \brief the target property name for this animation
+
+ This property defines the target property name for this animation. The
+ property name is required for the animation to operate.
+ */
+QByteArray QPropertyAnimation::propertyName() const
+{
+ Q_D(const QPropertyAnimation);
+ return d->propertyName;
+}
+
+void QPropertyAnimation::setPropertyName(const QByteArray &propertyName)
+{
+ Q_D(QPropertyAnimation);
+ if (d->state != QAbstractAnimation::Stopped) {
+ qWarning("QPropertyAnimation::setPropertyName: you can't change the property name of a running animation");
+ return;
+ }
+
+ d->propertyName = propertyName;
+ d->hasMetaProperty = 0;
+ d->updateMetaProperty();
+}
+
+
+/*!
+ \reimp
+ */
+bool QPropertyAnimation::event(QEvent *event)
+{
+ return QVariantAnimation::event(event);
+}
+
+/*!
+ This virtual function is called by QVariantAnimation whenever the current value
+ changes. \a value is the new, updated value. It updates the current value
+ of the property on the target object.
+
+ \sa currentValue, currentTime
+ */
+void QPropertyAnimation::updateCurrentValue(const QVariant &value)
+{
+ Q_D(QPropertyAnimation);
+ d->updateProperty(value);
+}
+
+/*!
+ \reimp
+
+ If the startValue is not defined when the state of the animation changes from Stopped to Running,
+ the current property value is used as the initial value for the animation.
+*/
+void QPropertyAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QPropertyAnimation);
+
+ if (!d->target) {
+ qWarning("QPropertyAnimation::updateState: Changing state of an animation without target");
+ return;
+ }
+
+ QVariantAnimation::updateState(oldState, newState);
+ QMutexLocker locker(guardHashLock());
+ QPropertyAnimationHash * hash = _q_runningAnimations();
+ QPropertyAnimationPair key(d->target, d->propertyName);
+ if (newState == Running) {
+ d->updateMetaProperty();
+ QPropertyAnimation *oldAnim = hash->value(key, 0);
+ if (oldAnim) {
+ // try to stop the top level group
+ QAbstractAnimation *current = oldAnim;
+ while (current->group() && current->state() != Stopped)
+ current = current->group();
+ current->stop();
+ }
+ hash->insert(key, this);
+
+ // update the default start value
+ if (oldState == Stopped) {
+ d->setDefaultStartValue(d->target->property(d->propertyName.constData()));
+ }
+ } else if (hash->value(key) == this) {
+ hash->remove(key);
+ }
+}
+
+#include "moc_qpropertyanimation.cpp"
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h
new file mode 100644
index 0000000..39317ba
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROPERTYANIMATION_H
+#define QPROPERTYANIMATION_H
+
+#include <QtCore/qvariantanimation.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPropertyAnimationPrivate;
+class Q_CORE_EXPORT QPropertyAnimation : public QVariantAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QByteArray propertyName READ propertyName WRITE setPropertyName)
+ Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)
+
+public:
+ QPropertyAnimation(QObject *parent = 0);
+ QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = 0);
+ ~QPropertyAnimation();
+
+ QObject *targetObject() const;
+ void setTargetObject(QObject *target);
+
+ QByteArray propertyName() const;
+ void setPropertyName(const QByteArray &propertyName);
+
+protected:
+ bool event(QEvent *event);
+ void updateCurrentValue(const QVariant &value);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+
+private:
+ Q_PRIVATE_SLOT(d_func(), void _q_targetDestroyed());
+ Q_DISABLE_COPY(QPropertyAnimation)
+ Q_DECLARE_PRIVATE(QPropertyAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPROPERTYANIMATION_H
diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h
new file mode 100644
index 0000000..b51d039
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROPERTYANIMATION_P_H
+#define QPROPERTYANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpropertyanimation.h"
+#include <QtCore/qmetaobject.h>
+
+#include "qvariantanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPropertyAnimationPrivate : public QVariantAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QPropertyAnimation)
+public:
+ QPropertyAnimationPrivate()
+ : target(0), propertyType(0), propertyIndex(0), hasMetaProperty(false)
+ {
+ }
+
+ void _q_targetDestroyed();
+
+ QObject *target;
+
+ //for the QProperty
+ QMetaProperty property;
+ int propertyType;
+ int propertyIndex;
+
+ int hasMetaProperty;
+ QByteArray propertyName;
+ void updateProperty(const QVariant &);
+ void updateMetaProperty();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp
new file mode 100644
index 0000000..14814a7
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup.cpp
@@ -0,0 +1,594 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSequentialAnimationGroup
+ \brief The QSequentialAnimationGroup class provides a sequential group of animations.
+ \since 4.6
+ \ingroup animation
+
+ QSequentialAnimationGroup is a QAnimationGroup that runs its
+ animations in sequence, i.e., it starts one animation after
+ another has finished playing. The animations are played in the
+ order they are added to the group (using
+ \l{QAnimationGroup::}{addAnimation()} or
+ \l{QAnimationGroup::}{insertAnimationAt()}). The animation group
+ finishes when its last animation has finished.
+
+ At each moment there is at most one animation that is active in
+ the group; it is returned by currentAnimation(). An empty group
+ has no current animation.
+
+ A sequential animation group can be treated as any other
+ animation, i.e., it can be started, stopped, and added to other
+ groups. You can also call addPause() or insertPauseAt() to add a
+ pause to a sequential animation group.
+
+ \code
+ QSequentialAnimationGroup group;
+
+ group.addAnimation(anim1);
+ group.addAnimation(anim2);
+
+ group.start();
+ \endcode
+
+ In this example, \c anim1 and \c anim2 are two already set up
+ \l{QPropertyAnimation}s.
+
+ \sa QAnimationGroup, QAbstractAnimation, {The Animation Framework}
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qsequentialanimationgroup.h"
+#include "qsequentialanimationgroup_p.h"
+
+#include "qpauseanimation.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+bool QSequentialAnimationGroupPrivate::atEnd() const
+{
+ // we try to detect if we're at the end of the group
+ //this is true if the following conditions are true:
+ // 1. we're in the last loop
+ // 2. the direction is forward
+ // 3. the current animation is the last one
+ // 4. the current animation has reached its end
+ const int animTotalCurrentTime = QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
+ return (currentLoop == loopCount - 1
+ && direction == QAbstractAnimation::Forward
+ && currentAnimation == animations.last()
+ && animTotalCurrentTime == animationActualTotalDuration(currentAnimationIndex));
+}
+
+int QSequentialAnimationGroupPrivate::animationActualTotalDuration(int index) const
+{
+ QAbstractAnimation *anim = animations.at(index);
+ int ret = anim->totalDuration();
+ if (ret == -1 && actualDuration.size() > index)
+ ret = actualDuration.at(index); //we can try the actual duration there
+ return ret;
+}
+
+QSequentialAnimationGroupPrivate::AnimationIndex QSequentialAnimationGroupPrivate::indexForTime(int msecs) const
+{
+ Q_Q(const QSequentialAnimationGroup);
+ Q_ASSERT(!animations.isEmpty());
+
+ AnimationIndex ret;
+ int duration = 0;
+
+ // in case duration is -1, currentLoop will always be 0
+ ret.timeOffset = currentLoop * q->duration();
+
+ for (int i = 0; i < animations.size(); ++i) {
+ duration = animationActualTotalDuration(i);
+
+ // 'animation' is the current animation if one of these reasons is true:
+ // 1. it's duration is undefined
+ // 2. it ends after msecs
+ // 3. it is the last animation (this can happen in case there is at least 1 uncontrolled animation)
+ // 4. it ends exactly in msecs and the direction is backwards
+ if (duration == -1 || msecs < (ret.timeOffset + duration)
+ || (msecs == (ret.timeOffset + duration) && direction == QAbstractAnimation::Backward)) {
+ ret.index = i;
+ return ret;
+ }
+
+ // 'animation' has a non-null defined duration and is not the one at time 'msecs'.
+ ret.timeOffset += duration;
+ }
+
+ // this can only happen when one of those conditions is true:
+ // 1. the duration of the group is undefined and we passed its actual duration
+ // 2. there are only 0-duration animations in the group
+ ret.timeOffset -= duration;
+ ret.index = animations.size() - 1;
+ return ret;
+}
+
+void QSequentialAnimationGroupPrivate::restart()
+{
+ // restarting the group by making the first/last animation the current one
+ if (direction == QAbstractAnimation::Forward) {
+ lastLoop = 0;
+ if (currentAnimationIndex == 0)
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(0);
+ } else { // direction == QAbstractAnimation::Backward
+ lastLoop = loopCount - 1;
+ int index = animations.size() - 1;
+ if (currentAnimationIndex == index)
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(index);
+ }
+}
+
+/*!
+ \internal
+ This manages advancing the execution of a group running forwards (time has gone forward),
+ which is the same behaviour for rewinding the execution of a group running backwards
+ (time has gone backward).
+*/
+void QSequentialAnimationGroupPrivate::advanceForwards(const AnimationIndex &newAnimationIndex)
+{
+ if (lastLoop < currentLoop) {
+ // we need to fast forward to the end
+ for (int i = currentAnimationIndex; i < animations.size(); ++i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(animationActualTotalDuration(i));
+ }
+ // this will make sure the current animation is reset to the beginning
+ if (animations.size() == 1)
+ // we need to force activation because setCurrentAnimation will have no effect
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(0, true);
+ }
+
+ // and now we need to fast forward from the current position to
+ for (int i = currentAnimationIndex; i < newAnimationIndex.index; ++i) { //### WRONG,
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(animationActualTotalDuration(i));
+ }
+ // setting the new current animation will happen later
+}
+
+/*!
+ \internal
+ This manages rewinding the execution of a group running forwards (time has gone forward),
+ which is the same behaviour for advancing the execution of a group running backwards
+ (time has gone backward).
+*/
+void QSequentialAnimationGroupPrivate::rewindForwards(const AnimationIndex &newAnimationIndex)
+{
+ if (lastLoop > currentLoop) {
+ // we need to fast rewind to the beginning
+ for (int i = currentAnimationIndex; i >= 0 ; --i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(0);
+ }
+ // this will make sure the current animation is reset to the end
+ if (animations.size() == 1)
+ // we need to force activation because setCurrentAnimation will have no effect
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(animations.count() - 1, true);
+ }
+
+ // and now we need to fast rewind from the current position to
+ for (int i = currentAnimationIndex; i > newAnimationIndex.index; --i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(0);
+ }
+ // setting the new current animation will happen later
+}
+
+/*!
+ \fn QSequentialAnimationGroup::currentAnimationChanged(QAbstractAnimation *current)
+
+ QSequentialAnimationGroup emits this signal when currentAnimation
+ has been changed. \a current is the current animation.
+
+ \sa currentAnimation()
+*/
+
+
+/*!
+ Constructs a QSequentialAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QSequentialAnimationGroup::QSequentialAnimationGroup(QObject *parent)
+ : QAnimationGroup(*new QSequentialAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QSequentialAnimationGroup::QSequentialAnimationGroup(QSequentialAnimationGroupPrivate &dd,
+ QObject *parent)
+ : QAnimationGroup(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QSequentialAnimationGroup::~QSequentialAnimationGroup()
+{
+}
+
+/*!
+ Adds a pause of \a msecs to this animation group.
+ The pause is considered as a special type of animation, thus count() will be
+ increased by one.
+ \sa insertPauseAt(), QAnimationGroup::addAnimation()
+*/
+QPauseAnimation *QSequentialAnimationGroup::addPause(int msecs)
+{
+ QPauseAnimation *pause = new QPauseAnimation(msecs);
+ addAnimation(pause);
+ return pause;
+}
+
+/*!
+ Inserts a pause of \a msecs milliseconds at \a index in this animation
+ group.
+
+ \sa addPause(), QAnimationGroup::insertAnimationAt()
+*/
+QPauseAnimation *QSequentialAnimationGroup::insertPauseAt(int index, int msecs)
+{
+ Q_D(const QSequentialAnimationGroup);
+
+ if (index < 0 || index > d->animations.size()) {
+ qWarning("QSequentialAnimationGroup::insertPauseAt: index is out of bounds");
+ return 0;
+ }
+
+ QPauseAnimation *pause = new QPauseAnimation(msecs);
+ insertAnimationAt(index, pause);
+ return pause;
+}
+
+
+/*!
+ \property QSequentialAnimationGroup::currentAnimation
+ Returns the animation in the current time.
+
+ \sa currentAnimationChanged()
+*/
+QAbstractAnimation *QSequentialAnimationGroup::currentAnimation() const
+{
+ Q_D(const QSequentialAnimationGroup);
+ return d->currentAnimation;
+}
+
+/*!
+ \reimp
+*/
+int QSequentialAnimationGroup::duration() const
+{
+ Q_D(const QSequentialAnimationGroup);
+ int ret = 0;
+
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int currentDuration = animation->totalDuration();
+ if (currentDuration == -1)
+ return -1; // Undetermined length
+
+ ret += currentDuration;
+ }
+
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateCurrentTime(int msecs)
+{
+ Q_D(QSequentialAnimationGroup);
+ if (!d->currentAnimation)
+ return;
+
+ const QSequentialAnimationGroupPrivate::AnimationIndex newAnimationIndex = d->indexForTime(msecs);
+
+ // remove unneeded animations from actualDuration list
+ while (newAnimationIndex.index < d->actualDuration.size())
+ d->actualDuration.removeLast();
+
+ // newAnimationIndex.index is the new current animation
+ if (d->lastLoop < d->currentLoop
+ || (d->lastLoop == d->currentLoop && d->currentAnimationIndex < newAnimationIndex.index)) {
+ // advancing with forward direction is the same as rewinding with backwards direction
+ d->advanceForwards(newAnimationIndex);
+ } else if (d->lastLoop > d->currentLoop
+ || (d->lastLoop == d->currentLoop && d->currentAnimationIndex > newAnimationIndex.index)) {
+ // rewinding with forward direction is the same as advancing with backwards direction
+ d->rewindForwards(newAnimationIndex);
+ }
+
+ d->setCurrentAnimation(newAnimationIndex.index);
+
+ const int newCurrentTime = msecs - newAnimationIndex.timeOffset;
+
+ if (d->currentAnimation) {
+ d->currentAnimation->setCurrentTime(newCurrentTime);
+ if (d->atEnd()) {
+ //we make sure that we don't exceed the duration here
+ d->currentTime += QAbstractAnimationPrivate::get(d->currentAnimation)->totalCurrentTime - newCurrentTime;
+ stop();
+ }
+ } else {
+ //the only case where currentAnimation could be null
+ //is when all animations have been removed
+ Q_ASSERT(d->animations.isEmpty());
+ d->currentTime = 0;
+ stop();
+ }
+
+ d->lastLoop = d->currentLoop;
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QSequentialAnimationGroup);
+ QAnimationGroup::updateState(oldState, newState);
+
+ if (!d->currentAnimation)
+ return;
+
+ switch (newState) {
+ case Stopped:
+ d->currentAnimation->stop();
+ break;
+ case Paused:
+ if (oldState == d->currentAnimation->state()
+ && oldState == QSequentialAnimationGroup::Running) {
+ d->currentAnimation->pause();
+ }
+ else
+ d->restart();
+ break;
+ case Running:
+ if (oldState == d->currentAnimation->state()
+ && oldState == QSequentialAnimationGroup::Paused)
+ d->currentAnimation->start();
+ else
+ d->restart();
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_D(QSequentialAnimationGroup);
+ // we need to update the direction of the current animation
+ if (state() != Stopped && d->currentAnimation)
+ d->currentAnimation->setDirection(direction);
+}
+
+/*!
+ \reimp
+*/
+bool QSequentialAnimationGroup::event(QEvent *event)
+{
+ return QAnimationGroup::event(event);
+}
+
+void QSequentialAnimationGroupPrivate::setCurrentAnimation(int index, bool intermediate)
+{
+ Q_Q(QSequentialAnimationGroup);
+
+ index = qMin(index, animations.count() - 1);
+
+ if (index == -1) {
+ Q_ASSERT(animations.isEmpty());
+ currentAnimationIndex = -1;
+ currentAnimation = 0;
+ return;
+ }
+
+ // need these two checks below because this func can be called after the current animation
+ // has been removed
+ if (index == currentAnimationIndex && animations.at(index) == currentAnimation)
+ return;
+
+ // stop the old current animation
+ if (currentAnimation)
+ currentAnimation->stop();
+
+ currentAnimation = animations.at(index);
+ currentAnimationIndex = index;
+
+ emit q->currentAnimationChanged(currentAnimation);
+
+ activateCurrentAnimation(intermediate);
+}
+
+void QSequentialAnimationGroupPrivate::activateCurrentAnimation(bool intermediate)
+{
+ Q_Q(QSequentialAnimationGroup);
+
+ if (!currentAnimation)
+ return;
+
+ if (state == QSequentialAnimationGroup::Stopped)
+ return;
+
+ currentAnimation->stop();
+
+ // we ensure the direction is consistent with the group's direction
+ currentAnimation->setDirection(direction);
+
+ // connects to the finish signal of uncontrolled animations
+ if (currentAnimation->totalDuration() == -1)
+ QObject::connect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+
+ currentAnimation->start();
+ if (!intermediate && state == QSequentialAnimationGroup::Paused)
+ currentAnimation->pause();
+}
+
+void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
+{
+ Q_Q(QSequentialAnimationGroup);
+ Q_ASSERT(qobject_cast<QAbstractAnimation *>(q->sender()) == currentAnimation);
+
+ // we trust the duration returned by the animation
+ while (actualDuration.size() < (currentAnimationIndex + 1))
+ actualDuration.append(-1);
+ actualDuration[currentAnimationIndex] = currentAnimation->currentTime();
+
+ QObject::disconnect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+
+ if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last())
+ || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) {
+ // we don't handle looping of a group with undefined duration
+ q->stop();
+ } else if (direction == QAbstractAnimation::Forward) {
+ // set the current animation to be the next one
+ setCurrentAnimation(currentAnimationIndex + 1);
+ } else {
+ // set the current animation to be the previous one
+ setCurrentAnimation(currentAnimationIndex - 1);
+ }
+}
+
+/*!
+ \internal
+ This method is called whenever an animation is added to
+ the group at index \a index.
+ Note: We only support insertion after the current animation
+*/
+void QSequentialAnimationGroupPrivate::animationInsertedAt(int index)
+{
+ if (currentAnimation == 0)
+ setCurrentAnimation(0); // initialize the current animation
+
+ if (currentAnimationIndex == index
+ && currentAnimation->currentTime() == 0 && currentAnimation->currentLoop() == 0) {
+ //in this case we simply insert an animation before the current one has actually started
+ setCurrentAnimation(index);
+ }
+
+ //we update currentAnimationIndex in case it has changed (the animation pointer is still valid)
+ currentAnimationIndex = animations.indexOf(currentAnimation);
+
+ if (index < currentAnimationIndex || currentLoop != 0) {
+ qWarning("QSequentialGroup::insertAnimationAt only supports to add animations after the current one.");
+ return; //we're not affected because it is added after the current one
+ }
+}
+
+/*!
+ \internal
+ This method is called whenever an animation is removed from
+ the group at index \a index. The animation is no more listed when this
+ method is called.
+*/
+void QSequentialAnimationGroupPrivate::animationRemovedAt(int index)
+{
+ Q_Q(QSequentialAnimationGroup);
+ QAnimationGroupPrivate::animationRemovedAt(index);
+
+ Q_ASSERT(currentAnimation); // currentAnimation should always be set
+
+ if (actualDuration.size() > index)
+ actualDuration.removeAt(index);
+
+ const int currentIndex = animations.indexOf(currentAnimation);
+ if (currentIndex == -1) {
+ //we're removing the current animation, let's update it to another one
+ if (index < animations.count())
+ setCurrentAnimation(index); //let's try to take the next one
+ else if (index > 0)
+ setCurrentAnimation(index - 1);
+ else// case all animations were removed
+ setCurrentAnimation(-1);
+ } else if (currentAnimationIndex > index) {
+ currentAnimationIndex--;
+ }
+
+ // duration of the previous animations up to the current animation
+ currentTime = 0;
+ for (int i = 0; i < currentAnimationIndex; ++i) {
+ const int current = animationActualTotalDuration(i);
+ currentTime += current;
+ }
+
+ if (currentIndex != -1) {
+ //the current animation is not the one being removed
+ //so we add its current time to the current time of this group
+ currentTime += QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
+ }
+
+ //let's also update the total current time
+ totalCurrentTime = currentTime + loopCount * q->duration();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qsequentialanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qsequentialanimationgroup.h b/src/corelib/animation/qsequentialanimationgroup.h
new file mode 100644
index 0000000..4701a76
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALANIMATIONGROUP_H
+#define QSEQUENTIALANIMATIONGROUP_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPauseAnimation;
+class QSequentialAnimationGroupPrivate;
+
+class Q_CORE_EXPORT QSequentialAnimationGroup : public QAnimationGroup
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractAnimation* currentAnimation READ currentAnimation NOTIFY currentAnimationChanged)
+
+public:
+ QSequentialAnimationGroup(QObject *parent = 0);
+ ~QSequentialAnimationGroup();
+
+ QPauseAnimation *addPause(int msecs);
+ QPauseAnimation *insertPauseAt(int index, int msecs);
+
+ QAbstractAnimation *currentAnimation() const;
+ int duration() const;
+
+Q_SIGNALS:
+ void currentAnimationChanged(QAbstractAnimation *current);
+
+protected:
+ QSequentialAnimationGroup(QSequentialAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QSequentialAnimationGroup)
+ Q_DECLARE_PRIVATE(QSequentialAnimationGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished())
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QSEQUENTIALANIMATIONGROUP_H
diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h
new file mode 100644
index 0000000..3ac90f8
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALANIMATIONGROUP_P_H
+#define QSEQUENTIALANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsequentialanimationgroup.h"
+#include "qanimationgroup_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QSequentialAnimationGroupPrivate : public QAnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QSequentialAnimationGroup)
+public:
+ QSequentialAnimationGroupPrivate()
+ : currentAnimation(0), currentAnimationIndex(-1), lastLoop(0)
+ { }
+
+
+ struct AnimationIndex
+ {
+ AnimationIndex() : index(0), timeOffset(0) {}
+ // index points to the animation at timeOffset, skipping 0 duration animations.
+ // Note that the index semantic is slightly different depending on the direction.
+ int index; // the index of the animation in timeOffset
+ int timeOffset; // time offset when the animation at index starts.
+ };
+
+ int animationActualTotalDuration(int index) const;
+ AnimationIndex indexForTime(int msecs) const;
+
+ void setCurrentAnimation(int index, bool intermediate = false);
+ void activateCurrentAnimation(bool intermediate = false);
+
+ void animationInsertedAt(int index);
+ void animationRemovedAt(int index);
+
+ bool atEnd() const;
+
+ QAbstractAnimation *currentAnimation;
+ int currentAnimationIndex;
+
+ // this is the actual duration of uncontrolled animations
+ // it helps seeking and even going forward
+ QList<int> actualDuration;
+
+ void restart();
+ int lastLoop;
+
+ // handle time changes
+ void rewindForwards(const AnimationIndex &newAnimationIndex);
+ void advanceForwards(const AnimationIndex &newAnimationIndex);
+
+ // private slot
+ void _q_uncontrolledAnimationFinished();
+};
+
+QT_END_NAMESPACE
+
+#endif //QSEQUENTIALANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
new file mode 100644
index 0000000..4542a86
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -0,0 +1,653 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qvariantanimation.h"
+#include "qvariantanimation_p.h"
+
+#include <QtCore/QRect>
+#include <QtCore/QLineF>
+#include <QtCore/QLine>
+#include <QtCore/QReadWriteLock>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVariantAnimation
+ \ingroup animation
+ \brief The QVariantAnimation class provides an abstract base class for animations.
+ \since 4.6
+
+ This class is part of \l{The Animation Framework}. It serves as a
+ base class for property and item animations, with functions for
+ shared functionality.
+
+ QVariantAnimation cannot be used directly as it is an abstract
+ class; it has a pure virtual method called updateCurrentValue().
+ The class performs interpolation over
+ \l{QVariant}s, but leaves using the interpolated values to its
+ subclasses. Currently, Qt provides QPropertyAnimation, which
+ animates Qt \l{Qt's Property System}{properties}. See the
+ QPropertyAnimation class description if you wish to animate such
+ properties.
+
+ You can then set start and end values for the property by calling
+ setStartValue() and setEndValue(), and finally call start() to
+ start the animation. QVariantAnimation will interpolate the
+ property of the target object and emit valueChanged(). To react to
+ a change in the current value you have to reimplement the
+ updateCurrentValue() virtual function.
+
+ It is also possible to set values at specified steps situated
+ between the start and end value. The interpolation will then
+ touch these points at the specified steps. Note that the start and
+ end values are defined as the key values at 0.0 and 1.0.
+
+ There are two ways to affect how QVariantAnimation interpolates
+ the values. You can set an easing curve by calling
+ setEasingCurve(), and configure the duration by calling
+ setDuration(). You can change how the QVariants are interpolated
+ by creating a subclass of QVariantAnimation, and reimplementing
+ the virtual interpolated() function.
+
+ Subclassing QVariantAnimation can be an alternative if you have
+ \l{QVariant}s that you do not wish to declare as Qt properties.
+ Note, however, that you in most cases will be better off declaring
+ your QVariant as a property.
+
+ Not all QVariant types are supported. Below is a list of currently
+ supported QVariant types:
+
+ \list
+ \o \l{QMetaType::}{Int}
+ \o \l{QMetaType::}{Double}
+ \o \l{QMetaType::}{Float}
+ \o \l{QMetaType::}{QLine}
+ \o \l{QMetaType::}{QLineF}
+ \o \l{QMetaType::}{QPoint}
+ \o \l{QMetaType::}{QSize}
+ \o \l{QMetaType::}{QSizeF}
+ \o \l{QMetaType::}{QRect}
+ \o \l{QMetaType::}{QRectF}
+ \endlist
+
+ If you need to interpolate other variant types, including custom
+ types, you have to implement interpolation for these yourself.
+ You do this by reimplementing interpolated(), which returns
+ interpolation values for the value being interpolated.
+
+ \omit We need some snippets around here. \endomit
+
+ \sa QPropertyAnimation, QAbstractAnimation, {The Animation Framework}
+*/
+
+/*!
+ \fn void QVariantAnimation::valueChanged(const QVariant &value)
+
+ QVariantAnimation emits this signal whenever the current \a value changes.
+
+ \sa currentValue, startValue, endValue
+*/
+
+/*!
+ \fn void QVariantAnimation::updateCurrentValue(const QVariant &value) = 0;
+
+ This pure virtual function is called every time the animation's current
+ value changes. The \a value argument is the new current value.
+
+ \sa currentValue
+*/
+
+
+static bool animationValueLessThan(const QVariantAnimation::KeyValue &p1, const QVariantAnimation::KeyValue &p2)
+{
+ return p1.first < p2.first;
+}
+
+template<> Q_INLINE_TEMPLATE QRect _q_interpolate(const QRect &f, const QRect &t, qreal progress)
+{
+ QRect ret;
+ ret.setCoords(_q_interpolate(f.left(), t.left(), progress),
+ _q_interpolate(f.top(), t.top(), progress),
+ _q_interpolate(f.right(), t.right(), progress),
+ _q_interpolate(f.bottom(), t.bottom(), progress));
+ return ret;
+}
+
+template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF &t, qreal progress)
+{
+ qreal x1, y1, w1, h1;
+ f.getRect(&x1, &y1, &w1, &h1);
+ qreal x2, y2, w2, h2;
+ t.getRect(&x2, &y2, &w2, &h2);
+ return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress),
+ _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress));
+}
+
+template<> Q_INLINE_TEMPLATE QLine _q_interpolate(const QLine &f, const QLine &t, qreal progress)
+{
+ return QLine( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
+}
+
+template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF &t, qreal progress)
+{
+ return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
+}
+
+void QVariantAnimationPrivate::convertValues(int t)
+{
+ //this ensures that all the keyValues are of type t
+ for (int i = 0; i < keyValues.count(); ++i) {
+ QVariantAnimation::KeyValue &pair = keyValues[i];
+ if (pair.second.userType() != t)
+ pair.second.convert(static_cast<QVariant::Type>(t));
+ }
+ interpolator = 0; // if the type changed we need to update the interpolator
+}
+
+/*!
+ \internal
+ The goal of this function is to update the currentInterval member. As a consequence, we also
+ need to update the currentValue.
+ Set \a force to true to always recalculate the interval.
+*/
+void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/)
+{
+ // can't interpolate if we have only 1 key value
+ if (keyValues.count() <= 1)
+ return;
+
+ const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration)));
+
+ if (force || progress < currentInterval.start.first || progress > currentInterval.end.first) {
+ //let's update currentInterval
+ QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(),
+ keyValues.constEnd(),
+ qMakePair(progress, QVariant()),
+ animationValueLessThan);
+ QVariantAnimation::KeyValues::const_iterator itEnd = itStart;
+
+ // If we are at the end we should continue to use the last keyValues in case of extrapolation (progress > 1.0).
+ // This is because the easing function can return a value slightly outside the range [0, 1]
+ if (itStart != keyValues.constEnd()) {
+ // this can't happen because we always prepend the default start value there
+ if (itStart == keyValues.constBegin()) {
+ ++itEnd;
+ } else {
+ --itStart;
+ }
+
+ // update all the values of the currentInterval
+ currentInterval.start = *itStart;
+ currentInterval.end = *itEnd;
+ }
+ }
+ setCurrentValueForProgress(progress);
+}
+
+void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
+{
+ Q_Q(QVariantAnimation);
+
+ const qreal startProgress = currentInterval.start.first;
+ const qreal endProgress = currentInterval.end.first;
+ const qreal localProgress = (progress - startProgress) / (endProgress - startProgress);
+
+ QVariant ret = q->interpolated(currentInterval.start.second,
+ currentInterval.end.second,
+ localProgress);
+ qSwap(currentValue, ret);
+ q->updateCurrentValue(currentValue);
+ if ((connectedSignals & changedSignalMask) && currentValue != ret) {
+ //the value has changed
+ emit q->valueChanged(currentValue);
+ }
+}
+
+QVariant QVariantAnimationPrivate::valueAt(qreal step) const
+{
+ QVariantAnimation::KeyValues::const_iterator result =
+ qBinaryFind(keyValues.begin(), keyValues.end(), qMakePair(step, QVariant()), animationValueLessThan);
+ if (result != keyValues.constEnd())
+ return result->second;
+
+ return QVariant();
+}
+
+void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value)
+{
+ if (step < qreal(0.0) || step > qreal(1.0)) {
+ qWarning("QVariantAnimation::setValueAt: invalid step = %f", step);
+ return;
+ }
+
+ QVariantAnimation::KeyValue pair(step, value);
+
+ QVariantAnimation::KeyValues::iterator result = qLowerBound(keyValues.begin(), keyValues.end(), pair, animationValueLessThan);
+ if (result == keyValues.end() || result->first != step) {
+ keyValues.insert(result, pair);
+ } else {
+ if (value.isValid())
+ result->second = value; // replaces the previous value
+ else if (step == 0 && !hasStartValue && defaultStartValue.isValid())
+ result->second = defaultStartValue; // resets to the default start value
+ else
+ keyValues.erase(result); // removes the previous value
+ }
+
+ recalculateCurrentInterval(/*force=*/true);
+}
+
+void QVariantAnimationPrivate::setDefaultStartValue(const QVariant &value)
+{
+ defaultStartValue = value;
+ if (!hasStartValue)
+ setValueAt(0, value);
+}
+
+/*!
+ Construct a QVariantAnimation object. \a parent is passed to QAbstractAnimation's
+ constructor.
+*/
+QVariantAnimation::QVariantAnimation(QObject *parent) : QAbstractAnimation(*new QVariantAnimationPrivate, parent)
+{
+ d_func()->init();
+}
+
+/*!
+ \internal
+*/
+QVariantAnimation::QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent) : QAbstractAnimation(dd, parent)
+{
+ d_func()->init();
+}
+
+/*!
+ Destroys the animation.
+*/
+QVariantAnimation::~QVariantAnimation()
+{
+}
+
+/*!
+ \property QVariantAnimation::easingCurve
+ \brief the easing curve of the animation
+
+ This property defines the easing curve of the animation. By
+ default, a linear easing curve is used, resulting in linear
+ interpolation. Other curves are provided, for instance,
+ QEasingCurve::InCirc, which provides a circular entry curve.
+ Another example is QEasingCurve::InOutElastic, which provides an
+ elastic effect on the values of the interpolated variant.
+
+ The easing curve is used with the interpolator, the interpolated()
+ virtual function, the animation's duration, and iterationCount, to
+ control how the current value changes as the animation progresses.
+*/
+QEasingCurve QVariantAnimation::easingCurve() const
+{
+ Q_D(const QVariantAnimation);
+ return d->easing;
+}
+
+void QVariantAnimation::setEasingCurve(const QEasingCurve &easing)
+{
+ Q_D(QVariantAnimation);
+ d->easing = easing;
+ d->recalculateCurrentInterval();
+}
+
+Q_GLOBAL_STATIC(QVector<QVariantAnimation::Interpolator>, registeredInterpolators)
+Q_GLOBAL_STATIC(QReadWriteLock, registeredInterpolatorsLock)
+
+/*!
+ \fn void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
+ \relates QVariantAnimation
+ \threadsafe
+
+ Registers a custom interpolator \a func for the template type \c{T}.
+ The interpolator has to be registered before the animation is constructed.
+ To unregister (and use the default interpolator) set \a func to 0.
+ */
+
+/*!
+ \internal
+ \typedef QVariantAnimation::Interpolator
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+ \code
+ QVariant myInterpolator(const QVariant &from, const QVariant &to, qreal progress);
+ \endcode
+
+*/
+
+/*! \internal
+ * Registers a custom interpolator \a func for the specific \a interpolationType.
+ * The interpolator has to be registered before the animation is constructed.
+ * To unregister (and use the default interpolator) set \a func to 0.
+ */
+void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator func, int interpolationType)
+{
+ // will override any existing interpolators
+ QWriteLocker locker(registeredInterpolatorsLock());
+ if (int(interpolationType) >= registeredInterpolators()->count())
+ registeredInterpolators()->resize(int(interpolationType) + 1);
+ registeredInterpolators()->replace(interpolationType, func);
+}
+
+
+template<typename T> static inline QVariantAnimation::Interpolator castToInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
+{
+ return reinterpret_cast<QVariantAnimation::Interpolator>(func);
+}
+
+QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType)
+{
+ QReadLocker locker(registeredInterpolatorsLock());
+ QVariantAnimation::Interpolator ret = 0;
+ if (interpolationType < registeredInterpolators()->count()) {
+ ret = registeredInterpolators()->at(interpolationType);
+ if (ret) return ret;
+ }
+
+ switch(interpolationType)
+ {
+ case QMetaType::Int:
+ return castToInterpolator(_q_interpolateVariant<int>);
+ case QMetaType::Double:
+ return castToInterpolator(_q_interpolateVariant<double>);
+ case QMetaType::Float:
+ return castToInterpolator(_q_interpolateVariant<float>);
+ case QMetaType::QLine:
+ return castToInterpolator(_q_interpolateVariant<QLine>);
+ case QMetaType::QLineF:
+ return castToInterpolator(_q_interpolateVariant<QLineF>);
+ case QMetaType::QPoint:
+ return castToInterpolator(_q_interpolateVariant<QPoint>);
+ case QMetaType::QPointF:
+ return castToInterpolator(_q_interpolateVariant<QPointF>);
+ case QMetaType::QSize:
+ return castToInterpolator(_q_interpolateVariant<QSize>);
+ case QMetaType::QSizeF:
+ return castToInterpolator(_q_interpolateVariant<QSizeF>);
+ case QMetaType::QRect:
+ return castToInterpolator(_q_interpolateVariant<QRect>);
+ case QMetaType::QRectF:
+ return castToInterpolator(_q_interpolateVariant<QRectF>);
+ default:
+ return 0; //this type is not handled
+ }
+}
+
+/*!
+ \property QVariantAnimation::duration
+ \brief the duration of the animation
+
+ This property describes the duration in milliseconds of the
+ animation. The default duration is 250 milliseconds.
+
+ \sa QAbstractAnimation::duration()
+ */
+int QVariantAnimation::duration() const
+{
+ Q_D(const QVariantAnimation);
+ return d->duration;
+}
+
+void QVariantAnimation::setDuration(int msecs)
+{
+ Q_D(QVariantAnimation);
+ if (msecs < 0) {
+ qWarning("QVariantAnimation::setDuration: cannot set a negative duration");
+ return;
+ }
+ if (d->duration == msecs)
+ return;
+ d->duration = msecs;
+ d->recalculateCurrentInterval();
+}
+
+/*!
+ \property QVariantAnimation::startValue
+ \brief the optional start value of the animation
+
+ This property describes the optional start value of the animation. If
+ omitted, or if a null QVariant is assigned as the start value, the
+ animation will use the current position of the end when the animation
+ is started.
+
+ \sa endValue
+*/
+QVariant QVariantAnimation::startValue() const
+{
+ return keyValueAt(0);
+}
+
+void QVariantAnimation::setStartValue(const QVariant &value)
+{
+ setKeyValueAt(0, value);
+}
+
+/*!
+ \property QVariantAnimation::endValue
+ \brief the end value of the animation
+
+ This property describes the end value of the animation.
+
+ \sa startValue
+ */
+QVariant QVariantAnimation::endValue() const
+{
+ return keyValueAt(1);
+}
+
+void QVariantAnimation::setEndValue(const QVariant &value)
+{
+ setKeyValueAt(1, value);
+}
+
+
+/*!
+ Returns the key frame value for the given \a step. The given \a step
+ must be in the range 0 to 1. If there is no KeyValue for \a step,
+ it returns an invalid QVariant.
+
+ \sa keyValues(), setKeyValueAt()
+*/
+QVariant QVariantAnimation::keyValueAt(qreal step) const
+{
+ Q_D(const QVariantAnimation);
+ if (step == 0 && !d->hasStartValue)
+ return QVariant(); //special case where we don't have an explicit startValue
+
+ return d->valueAt(step);
+}
+
+/*!
+ \typedef QVariantAnimation::KeyValue
+
+ This is a typedef for QPair<qreal, QVariant>.
+*/
+/*!
+ \typedef QVariantAnimation::KeyValues
+
+ This is a typedef for QVector<KeyValue>
+*/
+
+/*!
+ Creates a key frame at the given \a step with the given \a value.
+ The given \a step must be in the range 0 to 1.
+
+ \sa setKeyValues(), keyValueAt()
+*/
+void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value)
+{
+ Q_D(QVariantAnimation);
+ if (step == 0)
+ d->hasStartValue = value.isValid();
+ d->setValueAt(step, value);
+}
+
+/*!
+ Returns the key frames of this animation.
+
+ \sa keyValueAt(), setKeyValues()
+*/
+QVariantAnimation::KeyValues QVariantAnimation::keyValues() const
+{
+ Q_D(const QVariantAnimation);
+ QVariantAnimation::KeyValues ret = d->keyValues;
+ //in case we added the default start value, we remove it
+ if (!d->hasStartValue && !ret.isEmpty() && ret.at(0).first == 0)
+ ret.remove(0);
+ return ret;
+}
+
+/*!
+ Replaces the current set of key frames with the given \a keyValues.
+ the step of the key frames must be in the range 0 to 1.
+
+ \sa keyValues(), keyValueAt()
+*/
+void QVariantAnimation::setKeyValues(const KeyValues &keyValues)
+{
+ Q_D(QVariantAnimation);
+ d->keyValues = keyValues;
+ qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
+ d->hasStartValue = !d->keyValues.isEmpty() && d->keyValues.at(0).first == 0;
+ d->recalculateCurrentInterval(/*force=*/true);
+}
+
+/*!
+ \property QVariantAnimation::currentValue
+ \brief the current value of the animation.
+
+ This property describes the current value; an interpolated value
+ between the \l{startValue}{start value} and the \l{endValue}{end
+ value}, using the current time for progress. The value itself is
+ obtained from interpolated(), which is called repeatedly as the
+ animation is running.
+
+ QVariantAnimation calls the virtual updateCurrentValue() function
+ when the current value changes. This is particularly useful for
+ subclasses that need to track updates. For example,
+ QPropertyAnimation uses this function to animate Qt \l{Qt's
+ Property System}{properties}.
+
+ \sa startValue, endValue
+*/
+QVariant QVariantAnimation::currentValue() const
+{
+ Q_D(const QVariantAnimation);
+ if (!d->currentValue.isValid())
+ const_cast<QVariantAnimationPrivate*>(d)->recalculateCurrentInterval();
+ return d->currentValue;
+}
+
+/*!
+ \reimp
+ */
+bool QVariantAnimation::event(QEvent *event)
+{
+ return QAbstractAnimation::event(event);
+}
+
+/*!
+ \reimp
+*/
+void QVariantAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_UNUSED(oldState);
+ Q_UNUSED(newState);
+}
+
+/*!
+
+ This virtual function returns the linear interpolation between
+ variants \a from and \a to, at \a progress, usually a value
+ between 0 and 1. You can reimplement this function in a subclass
+ of QVariantAnimation to provide your own interpolation algorithm.
+
+ Note that in order for the interpolation to work with a
+ QEasingCurve that return a value smaller than 0 or larger than 1
+ (such as QEasingCurve::InBack) you should make sure that it can
+ extrapolate. If the semantic of the datatype does not allow
+ extrapolation this function should handle that gracefully.
+
+ You should call the QVariantAnimation implementation of this
+ function if you want your class to handle the types already
+ supported by Qt (see class QVariantAnimation description for a
+ list of supported types).
+
+ \sa QEasingCurve
+ */
+QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
+{
+ Q_D(const QVariantAnimation);
+ if (d->interpolator == 0) {
+ if (from.userType() == to.userType())
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(from.userType());
+ if (d->interpolator == 0) //no interpolator found
+ return QVariant();
+ }
+
+ return d->interpolator(from.constData(), to.constData(), progress);
+}
+
+/*!
+ \reimp
+ */
+void QVariantAnimation::updateCurrentTime(int msecs)
+{
+ Q_D(QVariantAnimation);
+ Q_UNUSED(msecs);
+ d->recalculateCurrentInterval();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qvariantanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h
new file mode 100644
index 0000000..3ae172f
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATION_H
+#define QANIMATION_H
+
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/qabstractanimation.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qpair.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QVariantAnimationPrivate;
+class Q_CORE_EXPORT QVariantAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant startValue READ startValue WRITE setStartValue)
+ Q_PROPERTY(QVariant endValue READ endValue WRITE setEndValue)
+ Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY currentValueChanged)
+ Q_PROPERTY(int duration READ duration WRITE setDuration)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
+
+public:
+ typedef QPair<qreal, QVariant> KeyValue;
+ typedef QVector<KeyValue> KeyValues;
+
+ QVariantAnimation(QObject *parent = 0);
+ ~QVariantAnimation();
+
+ QVariant startValue() const;
+ void setStartValue(const QVariant &value);
+
+ QVariant endValue() const;
+ void setEndValue(const QVariant &value);
+
+ QVariant keyValueAt(qreal step) const;
+ void setKeyValueAt(qreal step, const QVariant &value);
+
+ KeyValues keyValues() const;
+ void setKeyValues(const KeyValues &values);
+
+ QVariant currentValue() const;
+
+ int duration() const;
+ void setDuration(int msecs);
+
+ QEasingCurve easingCurve() const;
+ void setEasingCurve(const QEasingCurve &easing);
+
+ typedef QVariant (*Interpolator)(const void *from, const void *to, qreal progress);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &value);
+
+protected:
+ QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent = 0);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+
+ virtual void updateCurrentValue(const QVariant &value) = 0;
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+
+private:
+ template <typename T> friend void qRegisterAnimationInterpolator(QVariant (*func)(const T &, const T &, qreal));
+ static void registerInterpolator(Interpolator func, int interpolationType);
+
+ Q_DISABLE_COPY(QVariantAnimation)
+ Q_DECLARE_PRIVATE(QVariantAnimation)
+};
+
+template <typename T>
+void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress)) {
+ QVariantAnimation::registerInterpolator(reinterpret_cast<QVariantAnimation::Interpolator>(func), qMetaTypeId<T>());
+}
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QANIMATION_H
diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h
new file mode 100644
index 0000000..0d296db
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATION_P_H
+#define QANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qvariantanimation.h"
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qvector.h>
+
+#include "qabstractanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVariantAnimationPrivate : public QAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QVariantAnimation)
+public:
+
+ QVariantAnimationPrivate() : duration(250), hasStartValue(false)
+ {
+ }
+
+ void init()
+ {
+ //we keep the mask so that we emit valueChanged only when needed (for performance reasons)
+ changedSignalMask = (1 << q_func()->metaObject()->indexOfSignal("valueChanged(QVariant)"));
+ currentInterval.start.first = currentInterval.end.first = 2; //will force the initial refresh
+ interpolator = 0;
+ }
+
+ static QVariantAnimationPrivate *get(QVariantAnimation *q)
+ {
+ return q->d_func();
+ }
+
+ void setDefaultStartValue(const QVariant &value);
+
+ int duration;
+ QEasingCurve easing;
+
+ QVariantAnimation::KeyValues keyValues;
+ QVariant currentValue;
+ QVariant defaultStartValue;
+ bool hasStartValue;
+
+ //this is used to keep track of the KeyValue interval in which we currently are
+ struct
+ {
+ QVariantAnimation::KeyValue start, end;
+ } currentInterval;
+
+ mutable QVariantAnimation::Interpolator interpolator;
+
+ quint32 changedSignalMask;
+
+ void setCurrentValueForProgress(const qreal progress);
+ void recalculateCurrentInterval(bool force=false);
+ void setValueAt(qreal, const QVariant &);
+ QVariant valueAt(qreal step) const;
+ void convertValues(int t);
+
+ static QVariantAnimation::Interpolator getInterpolator(int interpolationType);
+};
+
+//this should make the interpolation faster
+template<typename T> inline T _q_interpolate(const T &f, const T &t, qreal progress)
+{
+ return T(f + (t - f) * progress);
+}
+
+template<typename T > inline QVariant _q_interpolateVariant(const T &from, const T &to, qreal progress)
+{
+ return _q_interpolate(from, to, progress);
+}
+
+
+QT_END_NAMESPACE
+
+#endif //QANIMATION_P_H