/*!
    \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
}
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;
    for (int i = 0; i < animations.size(); ++i)
        maxDuration = qMax(maxDuration, animations.at(i)->totalDuration());

    if (currentTime >= maxDuration)
        q->stop();
}
/*!
    \reimp
*/
void QParallelAnimationGroup::updateState(QAbstractAnimation::State newState,
                                          QAbstractAnimation::State oldState)
{
    Q_D(QParallelAnimationGroup);
    QAnimationGroup::updateState(newState, oldState);

    switch (newState) {
    case Stopped:
        for (int i = 0; i < d->animations.size(); ++i)
            d->animations.at(i)->stop();
        d->disconnectUncontrolledAnimations();
        break;
    case Paused:
        for (int i = 0; i < d->animations.size(); ++i)
            if (d->animations.at(i)->state() == Running)
                d->animations.at(i)->pause();
        break;
    case Running:
        d->connectUncontrolledAnimations();
        for (int i = 0; i < d->animations.size(); ++i) {
            QAbstractAnimation *animation = d->animations.at(i);
            if (oldState == Stopped)
                animation->stop();
            animation->setDirection(d->direction);
            if (d->shouldAnimationStart(animation, oldState == Stopped))
                animation->start();
        }
        break;
    }
}
Beispiel #5
0
void QUnifiedTimer::updateAnimationsTime()
{
    //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations
    if(insideTick)
        return;

    qint64 totalElapsed = time.elapsed();
    // ignore consistentTiming in case the pause timer is active
    int delta = (consistentTiming && !isPauseTimerActive) ?
                timingInterval : totalElapsed - lastTick;
    if (slowMode) {
        if (slowdownFactor > 0)
            delta = qRound(delta / slowdownFactor);
        else
            delta = 0;
    }

    lastTick = totalElapsed;

    //we make sure we only call update time if the time has actually changed
    //it might happen in some cases that the time doesn't change because events are delayed
    //when the CPU load is high
    if (delta) {
        insideTick = true;
        for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
            QAbstractAnimation *animation = animations.at(currentAnimationIdx);
            int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
                          + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
            animation->setCurrentTime(elapsed);
        }
        insideTick = false;
        currentAnimationIdx = 0;
    }
}
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;
}
void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
{
    for (int i = 0; i < animations.size(); ++i) {
        QAbstractAnimation *animation = animations.at(i);
        if (animation->duration() == -1 || animation->loopCount() < 0) {
            uncontrolledFinishTime[animation] = -1;
            connectUncontrolledAnimation(animation);
        }
    }
}
/*!
    \reimp
*/
void QParallelAnimationGroup::updateCurrentTime(int currentTime)
{
    Q_D(QParallelAnimationGroup);
    if (d->animations.isEmpty())
        return;

    if (d->currentLoop > d->lastLoop) {
        // simulate completion of the loop
        int dura = duration();
        if (dura > 0) {
            for (int i = 0; i < d->animations.size(); ++i) {
                QAbstractAnimation *animation = d->animations.at(i);
                if (animation->state() != QAbstractAnimation::Stopped)
                    d->animations.at(i)->setCurrentTime(dura);   // will stop
            }
        }
    } else if (d->currentLoop < d->lastLoop) {
        // simulate completion of the loop seeking backwards
        for (int i = 0; i < d->animations.size(); ++i) {
            QAbstractAnimation *animation = d->animations.at(i);
            //we need to make sure the animation is in the right state
            //and then rewind it
            d->applyGroupState(animation);
            animation->setCurrentTime(0);
            animation->stop();
        }
    }

#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
    for (int i = 0; i < d->animations.size(); ++i) {
        QAbstractAnimation *animation = d->animations.at(i);
        const int dura = animation->totalDuration();
        //if the loopcount is bigger we should always start all animations
        if (d->currentLoop > d->lastLoop
            //if we're at the end of the animation, we need to start it if it wasn't already started in this loop
            //this happens in Backward direction where not all animations are started at the same time
            || d->shouldAnimationStart(animation, d->lastCurrentTime > dura /*startIfAtEnd*/)) {
            d->applyGroupState(animation);
        }

        if (animation->state() == state()) {
            animation->setCurrentTime(currentTime);
            if (dura > 0 && currentTime > dura)
                animation->stop();
        }
    }
    d->lastLoop = d->currentLoop;
    d->lastCurrentTime = currentTime;
}
void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
{
    Q_Q(QParallelAnimationGroup);

    for (int i = 0; i < animations.size(); ++i) {
        QAbstractAnimation *animation = animations.at(i);
        if (animation->duration() == -1 || animation->loopCount() < 0) {
            uncontrolledFinishTime[animation] = -1;
            QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
        }
    }
}
/*!
    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(), insertAnimation(), indexOfAnimation()
*/
QAbstractAnimation *QAnimationGroup::takeAnimation(int index)
{
    Q_D(QAnimationGroup);
    if (index < 0 || index >= d->animations.size()) {
        qWarning("QAnimationGroup::takeAnimation: 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->animationRemoved(index, animation);
    return animation;
}
/*!
    \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;
}
Beispiel #12
0
int QAnimationTimer::closestPauseAnimationTimeToFinish()
{
    int closestTimeToFinish = INT_MAX;
    for (int i = 0; i < runningPauseAnimations.size(); ++i) {
        QAbstractAnimation *animation = runningPauseAnimations.at(i);
        int timeToFinish;

        if (animation->direction() == QAbstractAnimation::Forward)
            timeToFinish = animation->duration() - animation->currentLoopTime();
        else
            timeToFinish = animation->currentLoopTime();

        if (timeToFinish < closestTimeToFinish)
            closestTimeToFinish = timeToFinish;
    }
    return closestTimeToFinish;
}
/*!
    \reimp
*/
void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
{
    Q_D(QParallelAnimationGroup);
    //we need to update the direction of the current animation
    if (state() != Stopped) {
        for (int i = 0; i < d->animations.size(); ++i) {
            QAbstractAnimation *animation = d->animations.at(i);
            animation->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();
        }
    }
}
void QUnifiedTimer::updateAnimationsTime()
{
    // ignore consistentTiming in case the pause timer is active
    int delta = (consistentTiming && !isPauseTimerActive) ?
                        timingInterval : time.elapsed() - lastTick;
    if (slowMode)
        delta /= 5;
    lastTick = time.elapsed();

    //we make sure we only call update time if the time has actually changed
    //it might happen in some cases that the time doesn't change because events are delayed
    //when the CPU load is high
    if (delta) {
        for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
            QAbstractAnimation *animation = animations.at(currentAnimationIdx);
            int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
                          + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
            animation->setCurrentTime(elapsed);
        }
        currentAnimationIdx = 0;
    }
}
Beispiel #15
0
void QAnimationTimer::updateAnimationsTime(qint64 delta)
{
    //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations
    if (insideTick)
        return;

    lastTick += delta;

    //we make sure we only call update time if the time has actually changed
    //it might happen in some cases that the time doesn't change because events are delayed
    //when the CPU load is high
    if (delta) {
        insideTick = true;
        for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
            QAbstractAnimation *animation = animations.at(currentAnimationIdx);
            int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
                          + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
            animation->setCurrentTime(elapsed);
        }
        insideTick = false;
        currentAnimationIdx = 0;
    }
}