65bool QSequentialAnimationGroupPrivate::atEnd()
const
73 const int animTotalCurrentTime = QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
74 return (currentLoop == loopCount - 1
75 && direction == QAbstractAnimation::Forward
76 && currentAnimation == animations.last()
77 && animTotalCurrentTime == animationActualTotalDuration(currentAnimationIndex));
80int QSequentialAnimationGroupPrivate::animationActualTotalDuration(
int index)
const
82 QAbstractAnimation *anim = animations.at(index);
83 int ret = anim->totalDuration();
84 if (ret == -1 && actualDuration.size() > index)
85 ret = actualDuration.at(index);
89QSequentialAnimationGroupPrivate::AnimationIndex QSequentialAnimationGroupPrivate::indexForCurrentTime()
const
91 Q_ASSERT(!animations.isEmpty());
96 for (
int i = 0; i < animations.size(); ++i) {
97 duration = animationActualTotalDuration(i);
104 const int offsetPlusDuration = addSaturating(ret.timeOffset, duration);
105 if (duration == -1 || currentTime < offsetPlusDuration
106 || (currentTime == offsetPlusDuration && direction == QAbstractAnimation::Backward)) {
112 ret.timeOffset = offsetPlusDuration;
118 ret.timeOffset -= duration;
119 ret.index = animations.size() - 1;
123void QSequentialAnimationGroupPrivate::restart()
126 if (direction == QAbstractAnimation::Forward) {
128 if (currentAnimationIndex == 0)
129 activateCurrentAnimation();
131 setCurrentAnimation(0);
133 lastLoop = loopCount - 1;
134 int index = animations.size() - 1;
135 if (currentAnimationIndex == index)
136 activateCurrentAnimation();
138 setCurrentAnimation(index);
148void QSequentialAnimationGroupPrivate::advanceForwards(
const AnimationIndex &newAnimationIndex)
150 if (lastLoop < currentLoop) {
152 for (
int i = currentAnimationIndex; i < animations.size(); ++i) {
153 QAbstractAnimation *anim = animations.at(i);
154 setCurrentAnimation(i,
true);
155 anim->setCurrentTime(animationActualTotalDuration(i));
158 if (animations.size() == 1)
160 activateCurrentAnimation();
162 setCurrentAnimation(0,
true);
166 for (
int i = currentAnimationIndex; i < newAnimationIndex.index; ++i) {
167 QAbstractAnimation *anim = animations.at(i);
168 setCurrentAnimation(i,
true);
169 anim->setCurrentTime(animationActualTotalDuration(i));
180void QSequentialAnimationGroupPrivate::rewindForwards(
const AnimationIndex &newAnimationIndex)
182 if (lastLoop > currentLoop) {
184 for (
int i = currentAnimationIndex; i >= 0 ; --i) {
185 QAbstractAnimation *anim = animations.at(i);
186 setCurrentAnimation(i,
true);
187 anim->setCurrentTime(0);
190 if (animations.size() == 1)
192 activateCurrentAnimation();
194 setCurrentAnimation(animations.size() - 1,
true);
198 for (
int i = currentAnimationIndex; i > newAnimationIndex.index; --i) {
199 QAbstractAnimation *anim = animations.at(i);
200 setCurrentAnimation(i,
true);
201 anim->setCurrentTime(0);
262QPauseAnimation *QSequentialAnimationGroup::insertPause(
int index,
int msecs)
264 Q_D(
const QSequentialAnimationGroup);
266 if (index < 0 || index > d->animations.size()) {
267 qWarning(
"QSequentialAnimationGroup::insertPause: index is out of bounds");
271 QPauseAnimation *pause =
new QPauseAnimation(msecs);
272 insertAnimation(index, pause);
295int QSequentialAnimationGroup::duration()
const
297 Q_D(
const QSequentialAnimationGroup);
300 for (AnimationListConstIt it = d->animations.constBegin(), cend = d->animations.constEnd(); it != cend; ++it) {
301 const int currentDuration = (*it)->totalDuration();
302 if (currentDuration == -1)
305 if (qAddOverflow(ret, currentDuration, &ret))
306 return std::numeric_limits<
int>::max();
315void QSequentialAnimationGroup::updateCurrentTime(
int currentTime)
317 Q_D(QSequentialAnimationGroup);
318 if (!d->currentAnimation)
321 const QSequentialAnimationGroupPrivate::AnimationIndex newAnimationIndex = d->indexForCurrentTime();
324 while (newAnimationIndex.index < d->actualDuration.size())
325 d->actualDuration.removeLast();
328 if (d->lastLoop < d->currentLoop
329 || (d->lastLoop == d->currentLoop && d->currentAnimationIndex < newAnimationIndex.index)) {
331 d->advanceForwards(newAnimationIndex);
332 }
else if (d->lastLoop > d->currentLoop
333 || (d->lastLoop == d->currentLoop && d->currentAnimationIndex > newAnimationIndex.index)) {
335 d->rewindForwards(newAnimationIndex);
338 d->setCurrentAnimation(newAnimationIndex.index);
340 const int newCurrentTime = currentTime - newAnimationIndex.timeOffset;
342 if (d->currentAnimation) {
343 d->currentAnimation->setCurrentTime(newCurrentTime);
347 QAbstractAnimationPrivate::get(d->currentAnimation)->totalCurrentTime - newCurrentTime;
348 d->currentTime = addSaturating(d->currentTime, diff);
354 Q_ASSERT(d->animations.isEmpty());
359 d->lastLoop = d->currentLoop;
365void QSequentialAnimationGroup::updateState(QAbstractAnimation::State newState,
366 QAbstractAnimation::State oldState)
368 Q_D(QSequentialAnimationGroup);
369 QAnimationGroup::updateState(newState, oldState);
371 if (!d->currentAnimation)
376 d->currentAnimation->stop();
379 if (oldState == d->currentAnimation->state()
380 && oldState == QSequentialAnimationGroup::Running) {
381 d->currentAnimation->pause();
387 if (oldState == d->currentAnimation->state()
388 && oldState == QSequentialAnimationGroup::Paused)
389 d->currentAnimation->start();
415void QSequentialAnimationGroupPrivate::setCurrentAnimation(
int index,
bool intermediate)
417 Q_Q(QSequentialAnimationGroup);
421 index = qMin(index, animations.size() - 1);
424 Q_ASSERT(animations.isEmpty());
425 currentAnimationIndex = -1;
426 currentAnimation =
nullptr;
432 if (index == currentAnimationIndex && animations.at(index) == currentAnimation)
436 if (currentAnimation)
437 currentAnimation->stop();
439 currentAnimationIndex = index;
440 currentAnimation = animations.at(index);
442 emit q->currentAnimationChanged(currentAnimation);
444 activateCurrentAnimation(intermediate);
447void QSequentialAnimationGroupPrivate::activateCurrentAnimation(
bool intermediate)
449 if (!currentAnimation || state == QSequentialAnimationGroup::Stopped)
452 currentAnimation->stop();
455 currentAnimation->setDirection(direction);
458 if (currentAnimation->totalDuration() == -1)
459 connectUncontrolledAnimation(currentAnimation);
461 currentAnimation->start();
462 if (!intermediate && state == QSequentialAnimationGroup::Paused)
463 currentAnimation->pause();
466void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
468 Q_Q(QSequentialAnimationGroup);
469 Q_ASSERT(qobject_cast<QAbstractAnimation *>(q->sender()) == currentAnimation);
472 while (actualDuration.size() < (currentAnimationIndex + 1))
473 actualDuration.append(-1);
474 actualDuration[currentAnimationIndex] = currentAnimation->currentTime();
476 disconnectUncontrolledAnimation(currentAnimation);
478 if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last())
479 || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) {
482 }
else if (direction == QAbstractAnimation::Forward) {
484 setCurrentAnimation(currentAnimationIndex + 1);
487 setCurrentAnimation(currentAnimationIndex - 1);
497void QSequentialAnimationGroupPrivate::animationInsertedAt(qsizetype index)
499 if (currentAnimation ==
nullptr) {
500 setCurrentAnimation(0);
501 Q_ASSERT(currentAnimation);
504 if (currentAnimationIndex == index
505 && currentAnimation->currentTime() == 0 && currentAnimation->currentLoop() == 0) {
507 setCurrentAnimation(index);
511 currentAnimationIndex = animations.indexOf(currentAnimation);
513 if (index < currentAnimationIndex || currentLoop != 0) {
514 qWarning(
"QSequentialGroup::insertAnimation only supports to add animations after the current one.");
525void QSequentialAnimationGroupPrivate::animationRemoved(qsizetype index, QAbstractAnimation *anim)
527 Q_Q(QSequentialAnimationGroup);
528 QAnimationGroupPrivate::animationRemoved(index, anim);
530 if (!currentAnimation)
533 if (actualDuration.size() > index)
534 actualDuration.removeAt(index);
536 const qsizetype currentIndex = animations.indexOf(currentAnimation);
537 if (currentIndex == -1) {
540 disconnectUncontrolledAnimation(currentAnimation);
542 if (index < animations.size())
543 setCurrentAnimation(index);
545 setCurrentAnimation(index - 1);
547 setCurrentAnimation(-1);
548 }
else if (currentAnimationIndex > index) {
549 currentAnimationIndex--;
554 for (qsizetype i = 0; i < currentAnimationIndex; ++i) {
555 const int current = animationActualTotalDuration(i);
556 currentTime = addSaturating(currentTime, current);
559 if (currentIndex != -1) {
562 const int currAnimTotalTime =
563 QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
564 currentTime = addSaturating(currentTime, currAnimTotalTime);
568 totalCurrentTime = addSaturating(currentTime, q->totalDuration());