summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qtimeline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qtimeline.cpp')
-rw-r--r--src/corelib/tools/qtimeline.cpp198
1 files changed, 109 insertions, 89 deletions
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index 4609b258fc..5512da867f 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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) 2020 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
#include "qtimeline.h"
+#include <private/qproperty_p.h>
#include <private/qobject_p.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qmath.h>
@@ -50,31 +15,29 @@ class QTimeLinePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTimeLine)
public:
- inline QTimeLinePrivate()
- : easingCurve(QEasingCurve::InOutSine),
- startTime(0), duration(1000), startFrame(0), endFrame(0),
- updateInterval(1000 / 25),
- totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0),
- direction(QTimeLine::Forward),
- state(QTimeLine::NotRunning)
- { }
-
QElapsedTimer timer;
- QEasingCurve easingCurve;
-
- int startTime;
- int duration;
- int startFrame;
- int endFrame;
- int updateInterval;
- int totalLoopCount;
- int currentLoopCount;
-
- int currentTime;
- int timerId;
-
- QTimeLine::Direction direction;
- QTimeLine::State state;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, QEasingCurve, easingCurve,
+ QEasingCurve::InOutSine)
+
+ int startTime = 0;
+ void setDuration(int duration) { q_func()->setDuration(duration); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, duration,
+ &QTimeLinePrivate::setDuration, 1000)
+ int startFrame = 0;
+ int endFrame = 0;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, updateInterval, 1000 / 25)
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, loopCount, 1)
+ int currentLoopCount = 0;
+
+ void setCurrentTimeForwardToQ(int time) { q_func()->setCurrentTime(time); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, currentTime,
+ &QTimeLinePrivate::setCurrentTimeForwardToQ, 0)
+ int timerId = 0;
+
+ void setDirection(QTimeLine::Direction direction) { q_func()->setDirection(direction); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, QTimeLine::Direction, direction,
+ &QTimeLinePrivate::setDirection, QTimeLine::Forward)
+ QTimeLine::State state = QTimeLine::NotRunning;
inline void setState(QTimeLine::State newState)
{
Q_Q(QTimeLine);
@@ -91,42 +54,45 @@ public:
void QTimeLinePrivate::setCurrentTime(int msecs)
{
Q_Q(QTimeLine);
+ currentTime.removeBindingUnlessInWrapper();
+ const auto previousCurrentTime = currentTime.valueBypassingBindings();
- qreal lastValue = q->currentValue();
- int lastFrame = q->currentFrame();
+ const qreal lastValue = q->valueForTime(previousCurrentTime);
+ const int lastFrame = q->frameForTime(previousCurrentTime);
// Determine if we are looping.
- int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
- int loopCount = elapsed / duration;
+ const int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
+ const int loopCountNow = elapsed / duration;
- bool looping = (loopCount != currentLoopCount);
+ const bool looping = (loopCountNow != currentLoopCount);
#ifdef QTIMELINE_DEBUG
- qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCount" << loopCount
- << "currentLoopCount" << currentLoopCount
- << "looping" << looping;
+ qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCountNow"
+ << loopCountNow << "currentLoopCount" << currentLoopCount << "looping" << looping;
#endif
if (looping)
- currentLoopCount = loopCount;
+ currentLoopCount = loopCountNow;
// Normalize msecs to be between 0 and duration, inclusive.
- currentTime = elapsed % duration;
- if (direction == QTimeLine::Backward)
- currentTime = duration - currentTime;
+ currentTime.setValueBypassingBindings(elapsed % duration);
+ if (direction.value() == QTimeLine::Backward)
+ currentTime.setValueBypassingBindings(duration - currentTime.valueBypassingBindings());
// Check if we have reached the end of loopcount.
bool finished = false;
- if (totalLoopCount && currentLoopCount >= totalLoopCount) {
+ if (loopCount && currentLoopCount >= loopCount) {
finished = true;
- currentTime = (direction == QTimeLine::Backward) ? 0 : duration;
- currentLoopCount = totalLoopCount - 1;
+ currentTime.setValueBypassingBindings((direction == QTimeLine::Backward) ? 0 : duration);
+ currentLoopCount = loopCount - 1;
}
- int currentFrame = q->frameForTime(currentTime);
+ const int currentFrame = q->frameForTime(currentTime.valueBypassingBindings());
#ifdef QTIMELINE_DEBUG
- qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime" << currentTime << currentFrame;
+ qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime"
+ << currentTime.valueBypassingBindings() << currentFrame;
#endif
- if (!qFuzzyCompare(lastValue, q->currentValue()))
- emit q->valueChanged(q->currentValue(), QTimeLine::QPrivateSignal());
+ const qreal currentValue = q->valueForTime(currentTime.valueBypassingBindings());
+ if (!qFuzzyCompare(lastValue, currentValue))
+ emit q->valueChanged(currentValue, QTimeLine::QPrivateSignal());
if (lastFrame != currentFrame) {
const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame);
if (looping && !finished && transitionframe != currentFrame) {
@@ -159,6 +125,13 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
q->stop();
emit q->finished(QTimeLine::QPrivateSignal());
}
+ if (currentTime.valueBypassingBindings() != previousCurrentTime)
+ currentTime.notify();
+}
+QBindable<int> QTimeLine::bindableCurrentTime()
+{
+ Q_D(QTimeLine);
+ return &d->currentTime;
}
/*!
@@ -319,19 +292,26 @@ QTimeLine::State QTimeLine::state() const
\property QTimeLine::loopCount
\brief the number of times the timeline should loop before it's finished.
- A loop count of of 0 means that the timeline will loop forever.
+ A loop count of 0 means that the timeline will loop forever.
By default, this property contains a value of 1.
*/
int QTimeLine::loopCount() const
{
Q_D(const QTimeLine);
- return d->totalLoopCount;
+ return d->loopCount;
}
+
void QTimeLine::setLoopCount(int count)
{
Q_D(QTimeLine);
- d->totalLoopCount = count;
+ d->loopCount = count;
+}
+
+QBindable<int> QTimeLine::bindableLoopCount()
+{
+ Q_D(QTimeLine);
+ return &d->loopCount;
}
/*!
@@ -343,6 +323,9 @@ void QTimeLine::setLoopCount(int count)
timeline duration, or from the value of the duration and towards 0 after
start() has been called.
+ Any binding of direction will be removed not only by setDirection(),
+ but also by toggleDirection().
+
By default, this property is set to \l Forward.
*/
QTimeLine::Direction QTimeLine::direction() const
@@ -353,9 +336,19 @@ QTimeLine::Direction QTimeLine::direction() const
void QTimeLine::setDirection(Direction direction)
{
Q_D(QTimeLine);
- d->direction = direction;
+ d->direction.removeBindingUnlessInWrapper();
+ const auto previousDirection = d->direction.valueBypassingBindings();
+ d->direction.setValueBypassingBindings(direction);
d->startTime = d->currentTime;
d->timer.start();
+ if (previousDirection != d->direction.valueBypassingBindings())
+ d->direction.notify();
+}
+
+QBindable<QTimeLine::Direction> QTimeLine::bindableDirection()
+{
+ Q_D(QTimeLine);
+ return &d->direction;
}
/*!
@@ -382,7 +375,17 @@ void QTimeLine::setDuration(int duration)
qWarning("QTimeLine::setDuration: cannot set duration <= 0");
return;
}
- d->duration = duration;
+ d->duration.removeBindingUnlessInWrapper();
+ if (duration != d->duration.valueBypassingBindings()) {
+ d->duration.setValueBypassingBindings(duration);
+ d->duration.notify();
+ }
+}
+
+QBindable<int> QTimeLine::bindableDuration()
+{
+ Q_D(QTimeLine);
+ return &d->duration;
}
/*!
@@ -472,6 +475,11 @@ void QTimeLine::setUpdateInterval(int interval)
Q_D(QTimeLine);
d->updateInterval = interval;
}
+QBindable<int> QTimeLine::bindableUpdateInterval()
+{
+ Q_D(QTimeLine);
+ return &d->updateInterval;
+}
/*!
\property QTimeLine::easingCurve
@@ -496,6 +504,12 @@ void QTimeLine::setEasingCurve(const QEasingCurve &curve)
d->easingCurve = curve;
}
+QBindable<QEasingCurve> QTimeLine::bindableEasingCurve()
+{
+ Q_D(QTimeLine);
+ return &d->easingCurve;
+}
+
/*!
\property QTimeLine::currentTime
\brief the current time of the time line.
@@ -505,6 +519,10 @@ void QTimeLine::setEasingCurve(const QEasingCurve &curve)
value that was current when stop() was called last, or the value set by
setCurrentTime().
+ \note You can bind other properties to currentTime, but it is not
+ recommended setting bindings to it. As animation progresses, the currentTime
+ is updated automatically, which cancels its bindings.
+
By default, this property contains a value of 0.
*/
int QTimeLine::currentTime() const
@@ -571,10 +589,10 @@ int QTimeLine::frameForTime(int msec) const
qreal QTimeLine::valueForTime(int msec) const
{
Q_D(const QTimeLine);
- msec = qMin(qMax(msec, 0), d->duration);
+ msec = qBound(0, msec, d->duration.value());
- qreal value = msec / qreal(d->duration);
- return d->easingCurve.valueForProgress(value);
+ qreal value = msec / qreal(d->duration.value());
+ return d->easingCurve.value().valueForProgress(value);
}
/*!
@@ -678,6 +696,8 @@ void QTimeLine::setPaused(bool paused)
Toggles the direction of the timeline. If the direction was Forward, it
becomes Backward, and vice verca.
+ Existing bindings of \l direction are removed.
+
\sa setDirection()
*/
void QTimeLine::toggleDirection()