diff options
Diffstat (limited to 'src/corelib/animation/qabstractanimation.cpp')
-rw-r--r-- | src/corelib/animation/qabstractanimation.cpp | 142 |
1 files changed, 59 insertions, 83 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index ce9cb70565..9687af0987 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /*! \class QAbstractAnimation @@ -149,7 +113,6 @@ #include "qabstractanimation_p.h" #include <QtCore/qmath.h> -#include <QtCore/qthreadstorage.h> #include <QtCore/qcoreevent.h> #include <QtCore/qpointer.h> #include <QtCore/qscopedvaluerollback.h> @@ -214,8 +177,6 @@ typedef QList<QAbstractAnimation*>::ConstIterator AnimationListConstIt; QUnifiedTimer drives animations indirectly, via QAbstractAnimationTimer. */ -Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer) - QUnifiedTimer::QUnifiedTimer() : QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), currentAnimationIdx(0), insideTick(false), insideRestart(false), consistentTiming(false), slowMode(false), @@ -233,11 +194,12 @@ QUnifiedTimer::~QUnifiedTimer() QUnifiedTimer *QUnifiedTimer::instance(bool create) { QUnifiedTimer *inst; - if (create && !unifiedTimer()->hasLocalData()) { + static thread_local std::unique_ptr<QUnifiedTimer> unifiedTimer; + if (create && !unifiedTimer) { inst = new QUnifiedTimer; - unifiedTimer()->setLocalData(inst); + unifiedTimer.reset(inst); } else { - inst = unifiedTimer() ? unifiedTimer()->localData() : nullptr; + inst = unifiedTimer.get(); } return inst; } @@ -321,7 +283,7 @@ void QUnifiedTimer::updateAnimationTimers() QScopedValueRollback<bool> guard(insideTick, true); if (profilerCallback) profilerCallback(delta); - for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.count(); ++currentAnimationIdx) { + for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.size(); ++currentAnimationIdx) { QAbstractAnimationTimer *animation = animationTimers.at(currentAnimationIdx); animation->updateAnimationsTime(delta); } @@ -332,7 +294,7 @@ void QUnifiedTimer::updateAnimationTimers() int QUnifiedTimer::runningAnimationCount() { int count = 0; - for (int i = 0; i < animationTimers.count(); ++i) + for (int i = 0; i < animationTimers.size(); ++i) count += animationTimers.at(i)->runningAnimationCount(); return count; } @@ -347,7 +309,7 @@ void QUnifiedTimer::localRestart() if (insideRestart) return; - if (!pausedAnimationTimers.isEmpty() && (animationTimers.count() + animationTimersToStart.count() == pausedAnimationTimers.count())) { + if (!pausedAnimationTimers.isEmpty() && (animationTimers.size() + animationTimersToStart.size() == pausedAnimationTimers.size())) { driver->stop(); int closestTimeToFinish = closestPausedAnimationTimerTimeToFinish(); // use a precise timer if the pause will be short @@ -365,7 +327,7 @@ void QUnifiedTimer::restart() { { QScopedValueRollback<bool> guard(insideRestart, true); - for (int i = 0; i < animationTimers.count(); ++i) + for (int i = 0; i < animationTimers.size(); ++i) animationTimers.at(i)->restartAnimationTimer(); } @@ -550,10 +512,6 @@ bool QUnifiedTimer::canUninstallAnimationDriver(QAnimationDriver *d) return d == driver && driver != &defaultDriver; } -#if QT_CONFIG(thread) -Q_GLOBAL_STATIC(QThreadStorage<QAnimationTimer *>, animationTimer) -#endif - QAnimationTimer::QAnimationTimer() : QAbstractAnimationTimer(), lastTick(0), currentAnimationIdx(0), insideTick(false), @@ -569,11 +527,12 @@ QAnimationTimer *QAnimationTimer::instance(bool create) { QAnimationTimer *inst; #if QT_CONFIG(thread) - if (create && !animationTimer()->hasLocalData()) { + static thread_local std::unique_ptr<QAnimationTimer> animationTimer; + if (create && !animationTimer) { inst = new QAnimationTimer; - animationTimer()->setLocalData(inst); + animationTimer.reset(inst); } else { - inst = animationTimer() ? animationTimer()->localData() : nullptr; + inst = animationTimer.get(); } #else Q_UNUSED(create); @@ -609,7 +568,7 @@ void QAnimationTimer::updateAnimationsTime(qint64 delta) //when the CPU load is high if (delta) { QScopedValueRollback<bool> guard(insideTick, true); - for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) { + for (currentAnimationIdx = 0; currentAnimationIdx < animations.size(); ++currentAnimationIdx) { QAbstractAnimation *animation = animations.at(currentAnimationIdx); int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta); @@ -897,12 +856,15 @@ qint64 QAnimationDriver::elapsed() const QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer) : QAnimationDriver(nullptr), m_unified_timer(timer) { - connect(this, SIGNAL(started()), this, SLOT(startTimer())); - connect(this, SIGNAL(stopped()), this, SLOT(stopTimer())); + connect(this, &QAnimationDriver::started, this, &QDefaultAnimationDriver::startTimer); + connect(this, &QAnimationDriver::stopped, this, &QDefaultAnimationDriver::stopTimer); } QDefaultAnimationDriver::~QDefaultAnimationDriver() - = default; +{ + disconnect(this, &QAnimationDriver::started, this, &QDefaultAnimationDriver::startTimer); + disconnect(this, &QAnimationDriver::stopped, this, &QDefaultAnimationDriver::stopTimer); +} void QDefaultAnimationDriver::timerEvent(QTimerEvent *e) { @@ -942,13 +904,13 @@ QAbstractAnimationPrivate::~QAbstractAnimationPrivate() { } void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) { Q_Q(QAbstractAnimation); - if (state == newState) + const QAbstractAnimation::State oldState = state.valueBypassingBindings(); + if (oldState == newState) return; if (loopCount == 0) return; - QAbstractAnimation::State oldState = state; int oldCurrentTime = currentTime; int oldCurrentLoop = currentLoop; QAbstractAnimation::Direction oldDirection = direction; @@ -982,13 +944,15 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) } q->updateState(newState, oldState); - if (!guard || newState != state) //this is to be safe if updateState changes the state + //this is to be safe if updateState changes the state + if (!guard || newState != state.valueBypassingBindings()) return; // Notify state change state.notify(); emit q->stateChanged(newState, oldState); - if (!guard || newState != state) //this is to be safe if updateState changes the state + //this is to be safe if updateState changes the state + if (!guard || newState != state.valueBypassingBindings()) return; switch (state) { @@ -1162,7 +1126,7 @@ void QAbstractAnimation::setDirection(Direction direction) return; } - Qt::beginPropertyUpdateGroup(); + const QScopedPropertyUpdateGroup guard; const int oldCurrentLoop = d->currentLoop; if (state() == Stopped) { if (direction == Backward) { @@ -1189,7 +1153,6 @@ void QAbstractAnimation::setDirection(Direction direction) if (d->currentLoop != oldCurrentLoop) d->currentLoop.notify(); d->direction.notify(); - Qt::endPropertyUpdateGroup(); } QBindable<QAbstractAnimation::Direction> QAbstractAnimation::bindableDirection() @@ -1343,46 +1306,59 @@ void QAbstractAnimation::setCurrentTime(int msecs) msecs = qMax(msecs, 0); // Calculate new time and loop. - int dura = duration(); - int totalDura = dura <= 0 ? dura : ((d->loopCount < 0) ? -1 : dura * d->loopCount); + const int dura = duration(); + const int totalLoopCount = d->loopCount; + const int totalDura = dura <= 0 ? dura : ((totalLoopCount < 0) ? -1 : dura * totalLoopCount); if (totalDura != -1) msecs = qMin(totalDura, msecs); - const int oldCurrentTime = d->totalCurrentTime; - d->totalCurrentTime = msecs; + d->totalCurrentTime.removeBindingUnlessInWrapper(); + + const int oldCurrentTime = d->totalCurrentTime.valueBypassingBindings(); + d->totalCurrentTime.setValueBypassingBindings(msecs); + + QAbstractAnimation::Direction currentDirection = d->direction; // Update new values. - int oldLoop = d->currentLoop; - d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura)); - if (d->currentLoop == d->loopCount) { + const int oldLoop = d->currentLoop.valueBypassingBindings(); + int newCurrentLoop = (dura <= 0) ? 0 : (msecs / dura); + if (newCurrentLoop == totalLoopCount) { //we're at the end d->currentTime = qMax(0, dura); - d->currentLoop = qMax(0, d->loopCount - 1); + newCurrentLoop = qMax(0, totalLoopCount - 1); } else { - if (d->direction == Forward) { + if (currentDirection == Forward) { d->currentTime = (dura <= 0) ? msecs : (msecs % dura); } else { d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1; if (d->currentTime == dura) - d->currentLoop = d->currentLoop - 1; + newCurrentLoop = newCurrentLoop - 1; } } + d->currentLoop.setValueBypassingBindings(newCurrentLoop); + // this is a virtual function, so it can update the properties as well updateCurrentTime(d->currentTime); - if (d->currentLoop != oldLoop) + + // read the property values again + newCurrentLoop = d->currentLoop.valueBypassingBindings(); + currentDirection = d->direction; + const int newTotalCurrentTime = d->totalCurrentTime.valueBypassingBindings(); + + if (newCurrentLoop != oldLoop) d->currentLoop.notify(); /* Notify before calling stop: As seen in tst_QSequentialAnimationGroup::clear * we might delete the animation when stop is called. Thus after stop no member * of the object must be used anymore. */ - if (oldCurrentTime != d->totalCurrentTime) + if (oldCurrentTime != newTotalCurrentTime) d->totalCurrentTime.notify(); // 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)) { + if ((currentDirection == Forward && newTotalCurrentTime == totalDura) + || (currentDirection == Backward && newTotalCurrentTime == 0)) { stop(); } } @@ -1406,7 +1382,7 @@ void QAbstractAnimation::setCurrentTime(int msecs) void QAbstractAnimation::start(DeletionPolicy policy) { Q_D(QAbstractAnimation); - if (d->state == Running) + if (d->state.valueBypassingBindings() == Running) return; d->deleteWhenStopped = policy; d->setState(Running); @@ -1426,7 +1402,7 @@ void QAbstractAnimation::stop() { Q_D(QAbstractAnimation); - if (d->state == Stopped) + if (d->state.valueBypassingBindings() == Stopped) return; d->setState(Stopped); @@ -1442,7 +1418,7 @@ void QAbstractAnimation::stop() void QAbstractAnimation::pause() { Q_D(QAbstractAnimation); - if (d->state == Stopped) { + if (d->state.valueBypassingBindings() == Stopped) { qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation"); return; } @@ -1460,7 +1436,7 @@ void QAbstractAnimation::pause() void QAbstractAnimation::resume() { Q_D(QAbstractAnimation); - if (d->state != Paused) { + if (d->state.valueBypassingBindings() != Paused) { qWarning("QAbstractAnimation::resume: " "Cannot resume an animation that is not paused"); return; |