diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-02-03 14:24:14 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-02-05 15:20:02 +0100 |
commit | 4938984f9a779192264757a06e6ca555fc8f5e91 (patch) | |
tree | d4d1684298c889a3775f5dd19added3a23e24371 /src/qml/animations | |
parent | 680f28b08f65ad38c8d5498b5738231b2a2779a3 (diff) |
Use a QDoubleEndedList for the children of animation group jobs
This way it's fundamentally impossible to add the same animation job to
two different group jobs. The pointers are not exposed anymore and no
one can re-order the jobs.
Task-number: QTBUG-90401
Change-Id: Iebff4b64960c853915dd32714acd144fc5cdc00d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/animations')
-rw-r--r-- | src/qml/animations/qabstractanimationjob.cpp | 2 | ||||
-rw-r--r-- | src/qml/animations/qabstractanimationjob_p.h | 7 | ||||
-rw-r--r-- | src/qml/animations/qanimationgroupjob.cpp | 58 | ||||
-rw-r--r-- | src/qml/animations/qanimationgroupjob_p.h | 19 | ||||
-rw-r--r-- | src/qml/animations/qcontinuinganimationgroupjob.cpp | 18 | ||||
-rw-r--r-- | src/qml/animations/qparallelanimationgroupjob.cpp | 24 | ||||
-rw-r--r-- | src/qml/animations/qsequentialanimationgroupjob.cpp | 73 | ||||
-rw-r--r-- | src/qml/animations/qsequentialanimationgroupjob_p.h | 6 |
8 files changed, 92 insertions, 115 deletions
diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp index a04b8b6e9b..9e82b63771 100644 --- a/src/qml/animations/qabstractanimationjob.cpp +++ b/src/qml/animations/qabstractanimationjob.cpp @@ -259,8 +259,6 @@ QAbstractAnimationJob::QAbstractAnimationJob() , m_currentLoop(0) , m_uncontrolledFinishTime(-1) , m_currentLoopStartTime(0) - , m_nextSibling(nullptr) - , m_previousSibling(nullptr) , m_hasRegisteredTimer(false) , m_isPause(false) , m_isGroup(false) diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h index 9490070246..c7514f4583 100644 --- a/src/qml/animations/qabstractanimationjob_p.h +++ b/src/qml/animations/qabstractanimationjob_p.h @@ -53,6 +53,7 @@ #include <private/qtqmlglobal_p.h> #include <private/qanimationjobutil_p.h> +#include <private/qdoubleendedlist_p.h> #include <QtCore/QObject> #include <QtCore/private/qabstractanimation_p.h> #include <vector> @@ -65,7 +66,7 @@ class QAnimationGroupJob; class QAnimationJobChangeListener; class QQmlAnimationTimer; -class Q_QML_PRIVATE_EXPORT QAbstractAnimationJob +class Q_QML_PRIVATE_EXPORT QAbstractAnimationJob : public QInheritedListNode { Q_DISABLE_COPY(QAbstractAnimationJob) public: @@ -124,8 +125,6 @@ public: void addAnimationChangeListener(QAnimationJobChangeListener *listener, QAbstractAnimationJob::ChangeTypes); void removeAnimationChangeListener(QAnimationJobChangeListener *listener, QAbstractAnimationJob::ChangeTypes); - QAbstractAnimationJob *nextSibling() const { return m_nextSibling; } - QAbstractAnimationJob *previousSibling() const { return m_previousSibling; } bool isGroup() const { return m_isGroup; } bool isRenderThreadJob() const { return m_isRenderThreadJob; } @@ -173,8 +172,6 @@ protected: }; std::vector<ChangeListener> changeListeners; - QAbstractAnimationJob *m_nextSibling; - QAbstractAnimationJob *m_previousSibling; QQmlAnimationTimer *m_timer = nullptr; bool m_hasRegisteredTimer:1; diff --git a/src/qml/animations/qanimationgroupjob.cpp b/src/qml/animations/qanimationgroupjob.cpp index 60b3003d0a..3b6c9123bf 100644 --- a/src/qml/animations/qanimationgroupjob.cpp +++ b/src/qml/animations/qanimationgroupjob.cpp @@ -42,7 +42,6 @@ QT_BEGIN_NAMESPACE QAnimationGroupJob::QAnimationGroupJob() - : QAbstractAnimationJob(), m_firstChild(nullptr), m_lastChild(nullptr) { m_isGroup = true; } @@ -51,29 +50,14 @@ void QAnimationGroupJob::ungroupChild(QAbstractAnimationJob *animation) { Q_ASSERT(animation); Q_ASSERT(animation->m_group == this); - QAbstractAnimationJob *prev = animation->previousSibling(); - QAbstractAnimationJob *next = animation->nextSibling(); - - if (prev) - prev->m_nextSibling = next; - else - m_firstChild = next; - - if (next) - next->m_previousSibling = prev; - else - m_lastChild = prev; - - animation->m_previousSibling = nullptr; - animation->m_nextSibling = nullptr; - + m_children.remove(animation); animation->m_group = nullptr; } void QAnimationGroupJob::handleAnimationRemoved(QAbstractAnimationJob *animation) { resetUncontrolledAnimationFinishTime(animation); - if (!firstChild()) { + if (m_children.isEmpty()) { m_currentTime = 0; stop(); } @@ -81,7 +65,7 @@ void QAnimationGroupJob::handleAnimationRemoved(QAbstractAnimationJob *animation QAnimationGroupJob::~QAnimationGroupJob() { - while (QAbstractAnimationJob *animation = firstChild()) { + while (QAbstractAnimationJob *animation = m_children.first()) { ungroupChild(animation); handleAnimationRemoved(animation); delete animation; @@ -90,7 +74,7 @@ QAnimationGroupJob::~QAnimationGroupJob() void QAnimationGroupJob::topLevelAnimationLoopChanged() { - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) + for (QAbstractAnimationJob *animation : m_children) animation->fireTopLevelAnimationLoopChanged(); } @@ -99,15 +83,9 @@ void QAnimationGroupJob::appendAnimation(QAbstractAnimationJob *animation) if (QAnimationGroupJob *oldGroup = animation->m_group) oldGroup->removeAnimation(animation); - Q_ASSERT(!animation->previousSibling() && !animation->nextSibling()); - - if (m_lastChild) - m_lastChild->m_nextSibling = animation; - else - m_firstChild = animation; - animation->m_previousSibling = m_lastChild; - m_lastChild = animation; + Q_ASSERT(!animation->isInList()); + m_children.append(animation); animation->m_group = this; animationInserted(animation); } @@ -117,40 +95,34 @@ void QAnimationGroupJob::prependAnimation(QAbstractAnimationJob *animation) if (QAnimationGroupJob *oldGroup = animation->m_group) oldGroup->removeAnimation(animation); - Q_ASSERT(!previousSibling() && !nextSibling()); - - if (m_firstChild) - m_firstChild->m_previousSibling = animation; - else - m_lastChild = animation; - animation->m_nextSibling = m_firstChild; - m_firstChild = animation; + Q_ASSERT(!animation->isInList()); + m_children.prepend(animation); animation->m_group = this; animationInserted(animation); } void QAnimationGroupJob::removeAnimation(QAbstractAnimationJob *animation) { - QAbstractAnimationJob *prev = animation->previousSibling(); - QAbstractAnimationJob *next = animation->nextSibling(); + QAbstractAnimationJob *prev = m_children.prev(animation); + QAbstractAnimationJob *next = m_children.next(animation); ungroupChild(animation); animationRemoved(animation, prev, next); } void QAnimationGroupJob::clear() { - while (QAbstractAnimationJob *child = firstChild()) { + while (QAbstractAnimationJob *child = m_children.first()) { removeAnimation(child); delete child; } - m_firstChild = nullptr; - m_lastChild = nullptr; + + Q_ASSERT(m_children.isEmpty()); } void QAnimationGroupJob::resetUncontrolledAnimationsFinishTime() { - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) { if (animation->duration() == -1 || animation->loopCount() < 0) { resetUncontrolledAnimationFinishTime(animation); } @@ -185,7 +157,7 @@ void QAnimationGroupJob::debugChildren(QDebug d) const ++indentLevel; QByteArray ind(indentLevel, ' '); - for (QAbstractAnimationJob *child = firstChild(); child; child = child->nextSibling()) + for (const QAbstractAnimationJob *child : m_children) d << "\n" << ind.constData() << child; } diff --git a/src/qml/animations/qanimationgroupjob_p.h b/src/qml/animations/qanimationgroupjob_p.h index 6a0941db65..3733fc6b8a 100644 --- a/src/qml/animations/qanimationgroupjob_p.h +++ b/src/qml/animations/qanimationgroupjob_p.h @@ -51,7 +51,8 @@ // We mean it. // -#include "private/qabstractanimationjob_p.h" +#include <QtQml/private/qabstractanimationjob_p.h> +#include <QtQml/private/qdoubleendedlist_p.h> #include <QtCore/qdebug.h> QT_REQUIRE_CONFIG(qml_animation); @@ -62,6 +63,8 @@ class Q_QML_PRIVATE_EXPORT QAnimationGroupJob : public QAbstractAnimationJob { Q_DISABLE_COPY(QAnimationGroupJob) public: + using Children = QDoubleEndedList<QAbstractAnimationJob>; + QAnimationGroupJob(); ~QAnimationGroupJob() override; @@ -69,8 +72,8 @@ public: void prependAnimation(QAbstractAnimationJob *animation); void removeAnimation(QAbstractAnimationJob *animation); - QAbstractAnimationJob *firstChild() const { return m_firstChild; } - QAbstractAnimationJob *lastChild() const { return m_lastChild; } + Children *children() { return &m_children; } + const Children *children() const { return &m_children; } virtual void clear(); @@ -85,18 +88,18 @@ protected: //TODO: confirm location of these (should any be moved into QAbstractAnimationJob?) void resetUncontrolledAnimationsFinishTime(); void resetUncontrolledAnimationFinishTime(QAbstractAnimationJob *anim); - int uncontrolledAnimationFinishTime(QAbstractAnimationJob *anim) const { return anim->m_uncontrolledFinishTime; } + int uncontrolledAnimationFinishTime(const QAbstractAnimationJob *anim) const + { + return anim->m_uncontrolledFinishTime; + } void setUncontrolledAnimationFinishTime(QAbstractAnimationJob *anim, int time); void debugChildren(QDebug d) const; -private: void ungroupChild(QAbstractAnimationJob *animation); void handleAnimationRemoved(QAbstractAnimationJob *animation); - //definition - QAbstractAnimationJob *m_firstChild = nullptr; - QAbstractAnimationJob *m_lastChild = nullptr; + Children m_children; }; QT_END_NAMESPACE diff --git a/src/qml/animations/qcontinuinganimationgroupjob.cpp b/src/qml/animations/qcontinuinganimationgroupjob.cpp index 88c0e9e60e..7d24d8ce55 100644 --- a/src/qml/animations/qcontinuinganimationgroupjob.cpp +++ b/src/qml/animations/qcontinuinganimationgroupjob.cpp @@ -52,9 +52,8 @@ QContinuingAnimationGroupJob::~QContinuingAnimationGroupJob() void QContinuingAnimationGroupJob::updateCurrentTime(int /*currentTime*/) { - Q_ASSERT(firstChild()); - - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + Q_ASSERT(!m_children.isEmpty()); + for (QAbstractAnimationJob *animation : m_children) { if (animation->state() == state()) { RETURN_IF_DELETED(animation->setCurrentTime(m_currentTime)); } @@ -68,20 +67,20 @@ void QContinuingAnimationGroupJob::updateState(QAbstractAnimationJob::State newS switch (newState) { case Stopped: - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) + for (QAbstractAnimationJob *animation : m_children) animation->stop(); break; case Paused: - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) + for (QAbstractAnimationJob *animation : m_children) if (animation->isRunning()) animation->pause(); break; case Running: - if (!firstChild()) { + if (m_children.isEmpty()) { stop(); return; } - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) { resetUncontrolledAnimationFinishTime(animation); animation->setDirection(m_direction); animation->start(); @@ -93,9 +92,8 @@ void QContinuingAnimationGroupJob::updateState(QAbstractAnimationJob::State newS void QContinuingAnimationGroupJob::updateDirection(QAbstractAnimationJob::Direction direction) { if (!isStopped()) { - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) animation->setDirection(direction); - } } } @@ -104,7 +102,7 @@ void QContinuingAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimat Q_ASSERT(animation && (animation->duration() == -1)); int uncontrolledRunningCount = 0; - for (QAbstractAnimationJob *child = firstChild(); child; child = child->nextSibling()) { + for (QAbstractAnimationJob *child : m_children) { if (child == animation) setUncontrolledAnimationFinishTime(animation, animation->currentTime()); else if (uncontrolledAnimationFinishTime(child) == -1) diff --git a/src/qml/animations/qparallelanimationgroupjob.cpp b/src/qml/animations/qparallelanimationgroupjob.cpp index 420a934ba2..4da4a06af2 100644 --- a/src/qml/animations/qparallelanimationgroupjob.cpp +++ b/src/qml/animations/qparallelanimationgroupjob.cpp @@ -57,7 +57,7 @@ int QParallelAnimationGroupJob::duration() const { int ret = 0; - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (const QAbstractAnimationJob *animation : m_children) { int currentDuration = animation->totalDuration(); if (currentDuration == -1) return -1; // Undetermined length @@ -69,7 +69,7 @@ int QParallelAnimationGroupJob::duration() const void QParallelAnimationGroupJob::updateCurrentTime(int /*currentTime*/) { - if (!firstChild()) + if (m_children.isEmpty()) return; if (m_currentLoop > m_previousLoop) { @@ -79,21 +79,21 @@ void QParallelAnimationGroupJob::updateCurrentTime(int /*currentTime*/) // For an uncontrolled parallel group, we need to simulate the end of running animations. // As uncontrolled animation finish time is already reset for this next loop, we pick the // longest of the known stop times. - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) { int currentDuration = animation->totalDuration(); if (currentDuration >= 0) dura = qMax(dura, currentDuration); } } if (dura > 0) { - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) { if (!animation->isStopped()) RETURN_IF_DELETED(animation->setCurrentTime(dura)); // will stop } } } else if (m_currentLoop < m_previousLoop) { // simulate completion of the loop seeking backwards - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) { //we need to make sure the animation is in the right state //and then rewind it applyGroupState(animation); @@ -103,7 +103,7 @@ void QParallelAnimationGroupJob::updateCurrentTime(int /*currentTime*/) } // finally move into the actual time of the current loop - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) { const int dura = animation->totalDuration(); //if the loopcount is bigger we should always start all animations if (m_currentLoop > m_previousLoop @@ -130,16 +130,16 @@ void QParallelAnimationGroupJob::updateState(QAbstractAnimationJob::State newSta switch (newState) { case Stopped: - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) + for (QAbstractAnimationJob *animation : m_children) animation->stop(); break; case Paused: - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) + for (QAbstractAnimationJob *animation : m_children) if (animation->isRunning()) animation->pause(); break; case Running: - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) { if (oldState == Stopped) { animation->stop(); m_previousLoop = m_direction == Forward ? 0 : m_loopCount - 1; @@ -188,7 +188,7 @@ void QParallelAnimationGroupJob::updateDirection(QAbstractAnimationJob::Directio { //we need to update the direction of the current animation if (!isStopped()) { - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { + for (QAbstractAnimationJob *animation : m_children) { animation->setDirection(direction); } } else { @@ -208,7 +208,7 @@ void QParallelAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimatio Q_ASSERT(animation && (animation->duration() == -1 || animation->loopCount() < 0)); int uncontrolledRunningCount = 0; - for (QAbstractAnimationJob *child = firstChild(); child; child = child->nextSibling()) { + for (QAbstractAnimationJob *child : m_children) { if (child == animation) { setUncontrolledAnimationFinishTime(animation, animation->currentTime()); } else if (child->duration() == -1 || child->loopCount() < 0) { @@ -222,7 +222,7 @@ void QParallelAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimatio int maxDuration = 0; bool running = false; - for (QAbstractAnimationJob *job = firstChild(); job; job = job->nextSibling()) { + for (QAbstractAnimationJob *job : m_children) { if (job->state() == Running) running = true; maxDuration = qMax(maxDuration, job->totalDuration()); diff --git a/src/qml/animations/qsequentialanimationgroupjob.cpp b/src/qml/animations/qsequentialanimationgroupjob.cpp index 1d19bbf79d..2da6c79e29 100644 --- a/src/qml/animations/qsequentialanimationgroupjob.cpp +++ b/src/qml/animations/qsequentialanimationgroupjob.cpp @@ -66,11 +66,12 @@ bool QSequentialAnimationGroupJob::atEnd() const const int animTotalCurrentTime = m_currentAnimation->currentTime(); return (m_currentLoop == m_loopCount - 1 && m_direction == Forward - && !m_currentAnimation->nextSibling() + && !m_children.next(m_currentAnimation) && animTotalCurrentTime == animationActualTotalDuration(m_currentAnimation)); } -int QSequentialAnimationGroupJob::animationActualTotalDuration(QAbstractAnimationJob *anim) const +int QSequentialAnimationGroupJob::animationActualTotalDuration( + const QAbstractAnimationJob *anim) const { int ret = anim->totalDuration(); if (ret == -1) { @@ -84,13 +85,12 @@ int QSequentialAnimationGroupJob::animationActualTotalDuration(QAbstractAnimatio QSequentialAnimationGroupJob::AnimationIndex QSequentialAnimationGroupJob::indexForCurrentTime() const { - Q_ASSERT(firstChild()); + Q_ASSERT(!m_children.isEmpty()); AnimationIndex ret; - QAbstractAnimationJob *anim = nullptr; int duration = 0; - for (anim = firstChild(); anim; anim = anim->nextSibling()) { + for (const QAbstractAnimationJob *anim : m_children) { duration = animationActualTotalDuration(anim); // 'animation' is the current animation if one of these reasons is true: @@ -116,7 +116,7 @@ QSequentialAnimationGroupJob::AnimationIndex QSequentialAnimationGroupJob::index // 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(); + ret.animation = m_children.last(); return ret; } @@ -125,17 +125,17 @@ void QSequentialAnimationGroupJob::restart() // restarting the group by making the first/last animation the current one if (m_direction == Forward) { m_previousLoop = 0; - if (m_currentAnimation == firstChild()) + if (m_currentAnimation == m_children.first()) activateCurrentAnimation(); else - setCurrentAnimation(firstChild()); + setCurrentAnimation(m_children.first()); } else { // direction == Backward m_previousLoop = m_loopCount - 1; - if (m_currentAnimation == lastChild()) + if (m_currentAnimation == m_children.last()) activateCurrentAnimation(); else - setCurrentAnimation(lastChild()); + setCurrentAnimation(m_children.last()); } } @@ -143,21 +143,22 @@ void QSequentialAnimationGroupJob::advanceForwards(const AnimationIndex &newAnim { if (m_previousLoop < m_currentLoop) { // we need to fast forward to the end - for (QAbstractAnimationJob *anim = m_currentAnimation; anim; anim = anim->nextSibling()) { + for (QAbstractAnimationJob *anim = m_currentAnimation; anim; anim = m_children.next(anim)) { RETURN_IF_DELETED(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 + if (m_children.count() == 1) { // we need to force activation because setCurrentAnimation will have no effect RETURN_IF_DELETED(activateCurrentAnimation()); } else { - RETURN_IF_DELETED(setCurrentAnimation(firstChild(), true)); + RETURN_IF_DELETED(setCurrentAnimation(m_children.first(), 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, + for (QAbstractAnimationJob *anim = m_currentAnimation; + anim && anim != newAnimationIndex.animation; anim = m_children.next(anim)) { //### WRONG, RETURN_IF_DELETED(setCurrentAnimation(anim, true)); RETURN_IF_DELETED(anim->setCurrentTime(animationActualTotalDuration(anim))); } @@ -168,21 +169,23 @@ void QSequentialAnimationGroupJob::rewindForwards(const AnimationIndex &newAnima { if (m_previousLoop > m_currentLoop) { // we need to fast rewind to the beginning - for (QAbstractAnimationJob *anim = m_currentAnimation; anim; anim = anim->previousSibling()) { + for (QAbstractAnimationJob *anim = m_currentAnimation; anim; + anim = m_children.prev(anim)) { RETURN_IF_DELETED(setCurrentAnimation(anim, true)); RETURN_IF_DELETED(anim->setCurrentTime(0)); } // this will make sure the current animation is reset to the end - if (lastChild() && !lastChild()->previousSibling()) { //count == 1 + if (m_children.count() == 1) { //count == 1 // we need to force activation because setCurrentAnimation will have no effect RETURN_IF_DELETED(activateCurrentAnimation()); } else { - RETURN_IF_DELETED(setCurrentAnimation(lastChild(), true)); + RETURN_IF_DELETED(setCurrentAnimation(m_children.last(), true)); } } // and now we need to fast rewind from the current position to - for (QAbstractAnimationJob *anim = m_currentAnimation; anim && anim != newAnimationIndex.animation; anim = anim->previousSibling()) { + for (QAbstractAnimationJob *anim = m_currentAnimation; + anim && anim != newAnimationIndex.animation; anim = m_children.prev(anim)) { RETURN_IF_DELETED(setCurrentAnimation(anim, true)); RETURN_IF_DELETED(anim->setCurrentTime(0)); } @@ -193,7 +196,7 @@ int QSequentialAnimationGroupJob::duration() const { int ret = 0; - for (QAbstractAnimationJob *anim = firstChild(); anim; anim = anim->nextSibling()) { + for (const QAbstractAnimationJob *anim : m_children) { const int currentDuration = anim->totalDuration(); if (currentDuration == -1) return -1; // Undetermined length @@ -246,7 +249,7 @@ void QSequentialAnimationGroupJob::updateCurrentTime(int currentTime) } else { //the only case where currentAnimation could be null //is when all animations have been removed - Q_ASSERT(!firstChild()); + Q_ASSERT(m_children.isEmpty()); m_currentTime = 0; RETURN_IF_DELETED(stop()); } @@ -288,10 +291,11 @@ void QSequentialAnimationGroupJob::updateDirection(QAbstractAnimationJob::Direct m_currentAnimation->setDirection(direction); } -void QSequentialAnimationGroupJob::setCurrentAnimation(QAbstractAnimationJob *anim, bool intermediate) +void QSequentialAnimationGroupJob::setCurrentAnimation( + const QAbstractAnimationJob *anim, bool intermediate) { if (!anim) { - Q_ASSERT(!firstChild()); + Q_ASSERT(m_children.isEmpty()); m_currentAnimation = nullptr; return; } @@ -303,7 +307,12 @@ void QSequentialAnimationGroupJob::setCurrentAnimation(QAbstractAnimationJob *an if (m_currentAnimation) m_currentAnimation->stop(); - m_currentAnimation = anim; + // Assert that the animation passed as argument is actually part of this group ... + Q_ASSERT(m_children.contains(anim)); + + // ... as then this const_cast is just a shortcut for looking up the non-const + // pointer in the linked list of jobs. + m_currentAnimation = const_cast<QAbstractAnimationJob *>(anim); activateCurrentAnimation(intermediate); } @@ -337,10 +346,10 @@ void QSequentialAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimat int totalTime = currentTime(); if (m_direction == Forward) { // set the current animation to be the next one - if (m_currentAnimation->nextSibling()) - RETURN_IF_DELETED(setCurrentAnimation(m_currentAnimation->nextSibling())); + if (auto *anim = m_children.next(m_currentAnimation)) + RETURN_IF_DELETED(setCurrentAnimation(anim)); - for (QAbstractAnimationJob *a = animation->nextSibling(); a; a = a->nextSibling()) { + for (QAbstractAnimationJob *a = m_children.next(animation); a; a = m_children.next(a)) { int dur = a->duration(); if (dur == -1) { totalTime = -1; @@ -352,10 +361,10 @@ void QSequentialAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimat } else { // set the current animation to be the previous one - if (m_currentAnimation->previousSibling()) - RETURN_IF_DELETED(setCurrentAnimation(m_currentAnimation->previousSibling())); + if (auto *anim = m_children.prev(m_currentAnimation)) + RETURN_IF_DELETED(setCurrentAnimation(anim)); - for (QAbstractAnimationJob *a = animation->previousSibling(); a; a = a->previousSibling()) { + for (QAbstractAnimationJob *a = m_children.prev(animation); a; a = m_children.prev(a)) { int dur = a->duration(); if (dur == -1) { totalTime = -1; @@ -374,9 +383,9 @@ void QSequentialAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimat void QSequentialAnimationGroupJob::animationInserted(QAbstractAnimationJob *anim) { if (m_currentAnimation == nullptr) - RETURN_IF_DELETED(setCurrentAnimation(firstChild())); // initialize the current animation + RETURN_IF_DELETED(setCurrentAnimation(m_children.first())); // initialize the current animation - if (m_currentAnimation == anim->nextSibling() + if (m_currentAnimation == m_children.next(anim) && m_currentAnimation->currentTime() == 0 && m_currentAnimation->currentLoop() == 0) { //in this case we simply insert the animation before the current one has actually started RETURN_IF_DELETED(setCurrentAnimation(anim)); @@ -407,7 +416,7 @@ void QSequentialAnimationGroupJob::animationRemoved(QAbstractAnimationJob *anim, // duration of the previous animations up to the current animation m_currentTime = 0; - for (QAbstractAnimationJob *job = firstChild(); job; job = job->nextSibling()) { + for (QAbstractAnimationJob *job : m_children) { if (job == m_currentAnimation) break; m_currentTime += animationActualTotalDuration(job); diff --git a/src/qml/animations/qsequentialanimationgroupjob_p.h b/src/qml/animations/qsequentialanimationgroupjob_p.h index 34e8fe1e08..8c58862a50 100644 --- a/src/qml/animations/qsequentialanimationgroupjob_p.h +++ b/src/qml/animations/qsequentialanimationgroupjob_p.h @@ -85,13 +85,13 @@ private: // Note that the index semantic is slightly different depending on the direction. bool afterCurrent = false; //whether animation is before or after m_currentAnimation //TODO: make enum Before/After/Same int timeOffset = 0; // time offset when the animation at index starts. - QAbstractAnimationJob *animation = nullptr; //points to the animation at timeOffset + const QAbstractAnimationJob *animation = nullptr; //points to the animation at timeOffset }; - int animationActualTotalDuration(QAbstractAnimationJob *anim) const; + int animationActualTotalDuration(const QAbstractAnimationJob *anim) const; AnimationIndex indexForCurrentTime() const; - void setCurrentAnimation(QAbstractAnimationJob *anim, bool intermediate = false); + void setCurrentAnimation(const QAbstractAnimationJob *anim, bool intermediate = false); void activateCurrentAnimation(bool intermediate = false); void animationInserted(QAbstractAnimationJob *anim) override; |