summaryrefslogtreecommitdiffstats
path: root/src/corelib/animation/qabstractanimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/animation/qabstractanimation.cpp')
-rw-r--r--src/corelib/animation/qabstractanimation.cpp156
1 files changed, 76 insertions, 80 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 1e887bfb54..e9845b0e17 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),
@@ -227,15 +188,18 @@ QUnifiedTimer::QUnifiedTimer() :
driver = &defaultDriver;
}
+QUnifiedTimer::~QUnifiedTimer()
+ = default;
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;
}
@@ -319,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);
}
@@ -330,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;
}
@@ -345,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
@@ -363,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();
}
@@ -548,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),
@@ -560,15 +520,19 @@ QAnimationTimer::QAnimationTimer() :
{
}
+QAnimationTimer::~QAnimationTimer()
+ = default;
+
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);
@@ -604,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);
@@ -896,6 +860,9 @@ QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer)
connect(this, SIGNAL(stopped()), this, SLOT(stopTimer()));
}
+QDefaultAnimationDriver::~QDefaultAnimationDriver()
+ = default;
+
void QDefaultAnimationDriver::timerEvent(QTimerEvent *e)
{
Q_ASSERT(e->timerId() == m_timer.timerId());
@@ -914,18 +881,33 @@ void QDefaultAnimationDriver::stopTimer()
m_timer.stop();
}
+QAnimationDriverPrivate::QAnimationDriverPrivate()
+ = default;
+
+QAnimationDriverPrivate::~QAnimationDriverPrivate()
+ = default;
+
+QAbstractAnimationTimer::QAbstractAnimationTimer()
+ = default;
+
+QAbstractAnimationTimer::~QAbstractAnimationTimer()
+ = default;
+
+QAbstractAnimationPrivate::QAbstractAnimationPrivate()
+ = default;
+
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;
@@ -959,13 +941,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) {
@@ -1139,7 +1123,7 @@ void QAbstractAnimation::setDirection(Direction direction)
return;
}
- Qt::beginPropertyUpdateGroup();
+ const QScopedPropertyUpdateGroup guard;
const int oldCurrentLoop = d->currentLoop;
if (state() == Stopped) {
if (direction == Backward) {
@@ -1166,7 +1150,6 @@ void QAbstractAnimation::setDirection(Direction direction)
if (d->currentLoop != oldCurrentLoop)
d->currentLoop.notify();
d->direction.notify();
- Qt::endPropertyUpdateGroup();
}
QBindable<QAbstractAnimation::Direction> QAbstractAnimation::bindableDirection()
@@ -1320,46 +1303,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();
}
}
@@ -1383,7 +1379,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);
@@ -1403,7 +1399,7 @@ void QAbstractAnimation::stop()
{
Q_D(QAbstractAnimation);
- if (d->state == Stopped)
+ if (d->state.valueBypassingBindings() == Stopped)
return;
d->setState(Stopped);
@@ -1419,7 +1415,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;
}
@@ -1437,7 +1433,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;