diff options
Diffstat (limited to 'src/corelib/tools/qtimeline.cpp')
-rw-r--r-- | src/corelib/tools/qtimeline.cpp | 198 |
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() |