/*! \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 }
void QSequentialAnimationGroupJob::animationRemoved(QAbstractAnimationJob *anim, QAbstractAnimationJob *prev, QAbstractAnimationJob *next) { QAnimationGroupJob::animationRemoved(anim, prev, next); Q_ASSERT(m_currentAnimation); // currentAnimation should always be set bool removingCurrent = anim == m_currentAnimation; if (removingCurrent) { if (next) setCurrentAnimation(next); //let's try to take the next one else if (prev) setCurrentAnimation(prev); else// case all animations were removed setCurrentAnimation(0); } // duration of the previous animations up to the current animation m_currentTime = 0; for (QAbstractAnimationJob *job = firstChild(); job; job = job->nextSibling()) { if (job == m_currentAnimation) break; m_currentTime += animationActualTotalDuration(job); } if (!removingCurrent) { //the current animation is not the one being removed //so we add its current time to the current time of this group m_currentTime += m_currentAnimation->currentTime(); } //let's also update the total current time m_totalCurrentTime = m_currentTime + m_loopCount * duration(); }
QSequentialAnimationGroupPrivate::AnimationIndex QSequentialAnimationGroupPrivate::indexForCurrentTime() const { Q_ASSERT(!animations.isEmpty()); AnimationIndex ret; int duration = 0; 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 || currentTime < (ret.timeOffset + duration) || (currentTime == (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; }
bool QSequentialAnimationGroupJob::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 = m_currentAnimation->currentTime(); return (m_currentLoop == m_loopCount - 1 && m_direction == Forward && !m_currentAnimation->nextSibling() && animTotalCurrentTime == animationActualTotalDuration(m_currentAnimation)); }
void QSequentialAnimationGroupJob::advanceForwards(const AnimationIndex &newAnimationIndex) { if (m_previousLoop < m_currentLoop) { // we need to fast forward to the end for (QAbstractAnimationJob *anim = m_currentAnimation; anim; anim = anim->nextSibling()) { setCurrentAnimation(anim, true); RETURN_IF_DELETED(anim->setCurrentTime(animationActualTotalDuration(anim))); } // this will make sure the current animation is reset to the beginning if (firstChild() && !firstChild()->nextSibling()) //count == 1 // we need to force activation because setCurrentAnimation will have no effect activateCurrentAnimation(); else setCurrentAnimation(firstChild(), true); } // and now we need to fast forward from the current position to for (QAbstractAnimationJob *anim = m_currentAnimation; anim && anim != newAnimationIndex.animation; anim = anim->nextSibling()) { //### WRONG, setCurrentAnimation(anim, true); RETURN_IF_DELETED(anim->setCurrentTime(animationActualTotalDuration(anim))); } // setting the new current animation will happen later }
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)); }
/*! \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::animationRemoved(int index, QAbstractAnimation *anim) { Q_Q(QSequentialAnimationGroup); QAnimationGroupPrivate::animationRemoved(index, anim); 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 disconnectUncontrolledAnimation(currentAnimation); 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(); }
QSequentialAnimationGroupJob::AnimationIndex QSequentialAnimationGroupJob::indexForCurrentTime() const { Q_ASSERT(firstChild()); AnimationIndex ret; QAbstractAnimationJob *anim = 0; int duration = 0; for (anim = firstChild(); anim; anim = anim->nextSibling()) { duration = animationActualTotalDuration(anim); // '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 || m_currentTime < (ret.timeOffset + duration) || (m_currentTime == (ret.timeOffset + duration) && m_direction == QAbstractAnimationJob::Backward)) { ret.animation = anim; return ret; } if (anim == m_currentAnimation) { ret.afterCurrent = true; } // '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.animation = lastChild(); return ret; }