Qt 4.8
qtimeline.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qtimeline.h"
43 
44 #include <private/qobject_p.h>
45 #include <QtCore/qcoreevent.h>
46 #include <QtCore/qmath.h>
47 #include <QtCore/qelapsedtimer.h>
48 
50 
52 {
54 public:
56  : startTime(0), duration(1000), startFrame(0), endFrame(0),
57  updateInterval(1000 / 25),
59  direction(QTimeLine::Forward), easingCurve(QEasingCurve::InOutSine),
60  state(QTimeLine::NotRunning)
61  { }
62 
63  int startTime;
64  int duration;
66  int endFrame;
70 
72  int timerId;
74 
78  inline void setState(QTimeLine::State newState)
79  {
80  Q_Q(QTimeLine);
81  if (newState != state)
82  emit q->stateChanged(state = newState);
83  }
84 
85  void setCurrentTime(int msecs);
86 };
87 
92 {
93  Q_Q(QTimeLine);
94 
95  qreal lastValue = q->currentValue();
96  int lastFrame = q->currentFrame();
97 
98  // Determine if we are looping.
99  int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
100  int loopCount = elapsed / duration;
101 
102  bool looping = (loopCount != currentLoopCount);
103 #ifdef QTIMELINE_DEBUG
104  qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCount" << loopCount
105  << "currentLoopCount" << currentLoopCount
106  << "looping" << looping;
107 #endif
108  if (looping)
109  currentLoopCount = loopCount;
110 
111  // Normalize msecs to be between 0 and duration, inclusive.
112  currentTime = elapsed % duration;
115 
116  // Check if we have reached the end of loopcount.
117  bool finished = false;
119  finished = true;
120  currentTime = (direction == QTimeLine::Backward) ? 0 : duration;
122  }
123 
124  int currentFrame = q->frameForTime(currentTime);
125 #ifdef QTIMELINE_DEBUG
126  qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime" << currentTime << currentFrame;
127 #endif
128  if (!qFuzzyCompare(lastValue, q->currentValue()))
129  emit q->valueChanged(q->currentValue());
130  if (lastFrame != currentFrame) {
131  const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame);
132  if (looping && !finished && transitionframe != currentFrame) {
133 #ifdef QTIMELINE_DEBUG
134  qDebug() << "QTimeLinePrivate::setCurrentTime: transitionframe";
135 #endif
136  emit q->frameChanged(transitionframe);
137  }
138 #ifdef QTIMELINE_DEBUG
139  else {
140  QByteArray reason;
141  if (!looping)
142  reason += " not looping";
143  if (finished) {
144  if (!reason.isEmpty())
145  reason += " and";
146  reason += " finished";
147  }
148  if (transitionframe == currentFrame) {
149  if (!reason.isEmpty())
150  reason += " and";
151  reason += " transitionframe is equal to currentFrame: " + QByteArray::number(currentFrame);
152  }
153  qDebug("QTimeLinePrivate::setCurrentTime: not transitionframe because %s", reason.constData());
154  }
155 #endif
156  emit q->frameChanged(currentFrame);
157  }
158  if (finished && state == QTimeLine::Running) {
159  q->stop();
160  emit q->finished();
161  }
162 }
163 
338  : QObject(*new QTimeLinePrivate, parent)
339 {
340  setDuration(duration);
341 }
342 
347 {
348  Q_D(QTimeLine);
349 
350  if (d->state == Running)
351  stop();
352 }
353 
360 {
361  Q_D(const QTimeLine);
362  return d->state;
363 }
364 
376 int QTimeLine::loopCount() const
377 {
378  Q_D(const QTimeLine);
379  return d->totalLoopCount;
380 }
381 void QTimeLine::setLoopCount(int count)
382 {
383  Q_D(QTimeLine);
384  d->totalLoopCount = count;
385 }
386 
402 {
403  Q_D(const QTimeLine);
404  return d->direction;
405 }
407 {
408  Q_D(QTimeLine);
409  d->direction = direction;
410  d->startTime = d->currentTime;
411  d->timer.start();
412 }
413 
429 int QTimeLine::duration() const
430 {
431  Q_D(const QTimeLine);
432  return d->duration;
433 }
435 {
436  Q_D(QTimeLine);
437  if (duration <= 0) {
438  qWarning("QTimeLine::setDuration: cannot set duration <= 0");
439  return;
440  }
441  d->duration = duration;
442 }
443 
451 {
452  Q_D(const QTimeLine);
453  return d->startFrame;
454 }
455 
463 {
464  Q_D(QTimeLine);
465  d->startFrame = frame;
466 }
467 
475 {
476  Q_D(const QTimeLine);
477  return d->endFrame;
478 }
479 
486 void QTimeLine::setEndFrame(int frame)
487 {
488  Q_D(QTimeLine);
489  d->endFrame = frame;
490 }
491 
504 {
505  Q_D(QTimeLine);
506  d->startFrame = startFrame;
507  d->endFrame = endFrame;
508 }
509 
524 int QTimeLine::updateInterval() const
525 {
526  Q_D(const QTimeLine);
527  return d->updateInterval;
528 }
530 {
531  Q_D(QTimeLine);
532  d->updateInterval = interval;
533 }
534 
552 {
553  Q_D(const QTimeLine);
554  switch (d->easingCurve.type()) {
555  default:
557  return EaseInOutCurve;
559  return EaseInCurve;
561  return EaseOutCurve;
563  return LinearCurve;
565  return SineCurve;
567  return CosineCurve;
568  }
569  return EaseInOutCurve;
570 }
571 
573 {
574  switch (shape) {
575  default:
576  case EaseInOutCurve:
578  break;
579  case EaseInCurve:
581  break;
582  case EaseOutCurve:
584  break;
585  case LinearCurve:
587  break;
588  case SineCurve:
590  break;
591  case CosineCurve:
593  break;
594  }
595 }
596 
612 {
613  Q_D(const QTimeLine);
614  return d->easingCurve;
615 }
616 
618 {
619  Q_D(QTimeLine);
620  d->easingCurve = curve;
621 }
622 
637 int QTimeLine::currentTime() const
638 {
639  Q_D(const QTimeLine);
640  return d->currentTime;
641 }
643 {
644  Q_D(QTimeLine);
645  d->startTime = 0;
646  d->currentLoopCount = 0;
647  d->timer.restart();
648  d->setCurrentTime(msec);
649 }
650 
657 {
658  Q_D(const QTimeLine);
659  return frameForTime(d->currentTime);
660 }
661 
668 {
669  Q_D(const QTimeLine);
670  return valueForTime(d->currentTime);
671 }
672 
680 int QTimeLine::frameForTime(int msec) const
681 {
682  Q_D(const QTimeLine);
683  if (d->direction == Forward)
684  return d->startFrame + int((d->endFrame - d->startFrame) * valueForTime(msec));
685  return d->startFrame + qCeil((d->endFrame - d->startFrame) * valueForTime(msec));
686 }
687 
699 {
700  Q_D(const QTimeLine);
701  msec = qMin(qMax(msec, 0), d->duration);
702 
703  qreal value = msec / qreal(d->duration);
704  return d->easingCurve.valueForProgress(value);
705 }
706 
721 {
722  Q_D(QTimeLine);
723  if (d->timerId) {
724  qWarning("QTimeLine::start: already running");
725  return;
726  }
727  int curTime = 0;
728  if (d->direction == Backward)
729  curTime = d->duration;
730  d->timerId = startTimer(d->updateInterval);
731  d->startTime = curTime;
732  d->currentLoopCount = 0;
733  d->timer.start();
734  d->setState(Running);
735  d->setCurrentTime(curTime);
736 }
737 
749 {
750  Q_D(QTimeLine);
751  if (d->timerId) {
752  qWarning("QTimeLine::resume: already running");
753  return;
754  }
755  d->timerId = startTimer(d->updateInterval);
756  d->startTime = d->currentTime;
757  d->timer.start();
758  d->setState(Running);
759 }
760 
767 {
768  Q_D(QTimeLine);
769  if (d->timerId)
770  killTimer(d->timerId);
771  d->setState(NotRunning);
772  d->timerId = 0;
773 }
774 
783 void QTimeLine::setPaused(bool paused)
784 {
785  Q_D(QTimeLine);
786  if (d->state == NotRunning) {
787  qWarning("QTimeLine::setPaused: Not running");
788  return;
789  }
790  if (paused && d->state != Paused) {
791  d->startTime = d->currentTime;
792  killTimer(d->timerId);
793  d->timerId = 0;
794  d->setState(Paused);
795  } else if (!paused && d->state == Paused) {
796  // Same as resume()
797  d->timerId = startTimer(d->updateInterval);
798  d->startTime = d->currentTime;
799  d->timer.start();
800  d->setState(Running);
801  }
802 }
803 
811 {
812  Q_D(QTimeLine);
813  setDirection(d->direction == Forward ? Backward : Forward);
814 }
815 
820 {
821  Q_D(QTimeLine);
822  if (event->timerId() != d->timerId) {
823  event->ignore();
824  return;
825  }
826  event->accept();
827 
828  if (d->direction == Forward) {
829  d->setCurrentTime(d->startTime + d->timer.elapsed());
830  } else {
831  d->setCurrentTime(d->startTime - d->timer.elapsed());
832  }
833 }
834 
int startTimer(int interval)
Starts a timer and returns a timer identifier, or returns zero if it could not start a timer...
Definition: qobject.cpp:1623
QTimeLine::State state
Definition: qtimeline.cpp:77
double d
Definition: qnumeric_p.h:62
void start()
Starts the timeline.
Definition: qtimeline.cpp:720
double qreal
Definition: qglobal.h:1193
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
static double elapsed(qint64 after, qint64 before)
void setCurrentTime(int msec)
Definition: qtimeline.cpp:642
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QEasingCurve class provides easing curves for controlling animation.
Definition: qeasingcurve.h:55
int qCeil(qreal v)
Definition: qmath.h:63
void setFrameRange(int startFrame, int endFrame)
Sets the timeline&#39;s frame counter to start at startFrame, and end and endFrame.
Definition: qtimeline.cpp:503
CurveShape
This enum describes the default shape of QTimeLine&#39;s value curve.
Definition: qtimeline.h:75
void setPaused(bool paused)
If paused is true, the timeline is paused, causing QTimeLine to enter Paused state.
Definition: qtimeline.cpp:783
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void setDirection(Direction direction)
Definition: qtimeline.cpp:406
void timerEvent(QTimerEvent *event)
Reimplemented Function
Definition: qtimeline.cpp:819
void setEndFrame(int frame)
Sets the end frame, which is the frame corresponding to the end of the timeline (i.e., the frame for which the current value is 1), to frame.
Definition: qtimeline.cpp:486
void stop()
Stops the timeline, causing QTimeLine to enter NotRunning state.
Definition: qtimeline.cpp:766
State state() const
Returns the state of the timeline.
Definition: qtimeline.cpp:359
static Q_DECL_CONSTEXPR bool qFuzzyCompare(double p1, double p2)
Definition: qglobal.h:2030
State
This enum describes the state of the timeline.
Definition: qtimeline.h:66
int currentFrame() const
Returns the frame corresponding to the current time.
Definition: qtimeline.cpp:656
CurveShape curveShape() const
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
virtual bool event(QEvent *)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition: qobject.cpp:1200
#define Q_D(Class)
Definition: qglobal.h:2482
The QElapsedTimer class provides a fast way to calculate elapsed times.
Definition: qelapsedtimer.h:53
virtual ~QTimeLine()
Destroys the timeline.
Definition: qtimeline.cpp:346
Direction direction() const
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
#define Q_Q(Class)
Definition: qglobal.h:2483
The QTimeLine class provides a timeline for controlling animations.
Definition: qtimeline.h:55
Q_CORE_EXPORT void qDebug(const char *,...)
int frameForTime(int msec) const
Returns the frame corresponding to the time msec.
Definition: qtimeline.cpp:680
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void setEasingCurve(const QEasingCurve &curve)
Definition: qtimeline.cpp:617
int loopCount() const
QTimeLine::Direction direction
Definition: qtimeline.cpp:75
#define emit
Definition: qobjectdefs.h:76
Q_CORE_EXPORT void qWarning(const char *,...)
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition: qcoreevent.h:346
void setCurrentTime(int msecs)
Definition: qtimeline.cpp:91
void setUpdateInterval(int interval)
Definition: qtimeline.cpp:529
Direction
This enum describes the direction of the timeline when in Running state.
Definition: qtimeline.h:71
void setLoopCount(int count)
Definition: qtimeline.cpp:381
int currentTime() const
void setDuration(int duration)
Definition: qtimeline.cpp:434
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
void toggleDirection()
Toggles the direction of the timeline.
Definition: qtimeline.cpp:810
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
QEasingCurve easingCurve
Definition: qtimeline.cpp:76
int endFrame() const
Returns the end frame, which is the frame corresponding to the end of the timeline (i...
Definition: qtimeline.cpp:474
QElapsedTimer timer
Definition: qtimeline.cpp:73
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:341
virtual qreal valueForTime(int msec) const
Returns the timeline value for the time msec.
Definition: qtimeline.cpp:698
qreal currentValue() const
Returns the value corresponding to the current time.
Definition: qtimeline.cpp:667
QEasingCurve easingCurve() const
QObject * parent
Definition: qobject.h:92
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QTimeLine(int duration=1000, QObject *parent=0)
Constructs a timeline with a duration of duration milliseconds.
Definition: qtimeline.cpp:337
int updateInterval() const
void resume()
Resumes the timeline from the current time.
Definition: qtimeline.cpp:748
void setState(QTimeLine::State newState)
Definition: qtimeline.cpp:78
void setCurveShape(CurveShape shape)
Definition: qtimeline.cpp:572
int startFrame() const
Returns the start frame, which is the frame corresponding to the start of the timeline (i...
Definition: qtimeline.cpp:450
static QByteArray number(int, int base=10)
Returns a byte array containing the string equivalent of the number n to base base (10 by default)...
int duration() const
void setStartFrame(int frame)
Sets the start frame, which is the frame corresponding to the start of the timeline (i...
Definition: qtimeline.cpp:462
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition: qobject.cpp:1650