Change copyrights from Nokia to Digia
[profile/ivi/qtdeclarative.git] / src / quick / util / qquicktimer.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtQml 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 "qquicktimer_p.h"
43
44 #include <QtCore/qcoreapplication.h>
45 #include "private/qpauseanimationjob_p.h"
46 #include <qdebug.h>
47
48 #include <private/qobject_p.h>
49
50 QT_BEGIN_NAMESPACE
51
52
53
54 class QQuickTimerPrivate : public QObjectPrivate, public QAnimationJobChangeListener
55 {
56     Q_DECLARE_PUBLIC(QQuickTimer)
57 public:
58     QQuickTimerPrivate()
59         : interval(1000), running(false), repeating(false), triggeredOnStart(false)
60         , classBegun(false), componentComplete(false), firstTick(true) {}
61
62     virtual void animationFinished(QAbstractAnimationJob *);
63     virtual void animationCurrentLoopChanged(QAbstractAnimationJob *)  { Q_Q(QQuickTimer); q->ticked(); }
64
65     int interval;
66     QPauseAnimationJob pause;
67     bool running : 1;
68     bool repeating : 1;
69     bool triggeredOnStart : 1;
70     bool classBegun : 1;
71     bool componentComplete : 1;
72     bool firstTick : 1;
73 };
74
75 /*!
76     \qmltype Timer
77     \instantiates QQuickTimer
78     \inqmlmodule QtQuick 2
79     \ingroup qtquick-interceptors
80     \brief Triggers a handler at a specified interval
81
82     A Timer can be used to trigger an action either once, or repeatedly
83     at a given interval.
84
85     Here is a Timer that shows the current date and time, and updates
86     the text every 500 milliseconds. It uses the JavaScript \c Date
87     object to access the current time.
88
89     \qml
90     import QtQuick 2.0
91
92     Item {
93         Timer {
94             interval: 500; running: true; repeat: true
95             onTriggered: time.text = Date().toString()
96         }
97
98         Text { id: time }
99     }
100     \endqml
101
102     The Timer type is synchronized with the animation timer.  Since the animation
103     timer is usually set to 60fps, the resolution of Timer will be
104     at best 16ms.
105
106     If the Timer is running and one of its properties is changed, the
107     elapsed time will be reset.  For example, if a Timer with interval of
108     1000ms has its \e repeat property changed 500ms after starting, the
109     elapsed time will be reset to 0, and the Timer will be triggered
110     1000ms later.
111
112     \sa {declarative/toys/clocks}{Clocks example}
113 */
114
115 QQuickTimer::QQuickTimer(QObject *parent)
116     : QObject(*(new QQuickTimerPrivate), parent)
117 {
118     Q_D(QQuickTimer);
119     d->pause.addAnimationChangeListener(d, QAbstractAnimationJob::Completion | QAbstractAnimationJob::CurrentLoop);
120     d->pause.setLoopCount(1);
121     d->pause.setDuration(d->interval);
122 }
123
124 /*!
125     \qmlproperty int QtQuick2::Timer::interval
126
127     Sets the \a interval between triggers, in milliseconds.
128
129     The default interval is 1000 milliseconds.
130 */
131 void QQuickTimer::setInterval(int interval)
132 {
133     Q_D(QQuickTimer);
134     if (interval != d->interval) {
135         d->interval = interval;
136         update();
137         emit intervalChanged();
138     }
139 }
140
141 int QQuickTimer::interval() const
142 {
143     Q_D(const QQuickTimer);
144     return d->interval;
145 }
146
147 /*!
148     \qmlproperty bool QtQuick2::Timer::running
149
150     If set to true, starts the timer; otherwise stops the timer.
151     For a non-repeating timer, \a running is set to false after the
152     timer has been triggered.
153
154     \a running defaults to false.
155
156     \sa repeat
157 */
158 bool QQuickTimer::isRunning() const
159 {
160     Q_D(const QQuickTimer);
161     return d->running;
162 }
163
164 void QQuickTimer::setRunning(bool running)
165 {
166     Q_D(QQuickTimer);
167     if (d->running != running) {
168         d->running = running;
169         d->firstTick = true;
170         emit runningChanged();
171         update();
172     }
173 }
174
175 /*!
176     \qmlproperty bool QtQuick2::Timer::repeat
177
178     If \a repeat is true the timer is triggered repeatedly at the
179     specified interval; otherwise, the timer will trigger once at the
180     specified interval and then stop (i.e. running will be set to false).
181
182     \a repeat defaults to false.
183
184     \sa running
185 */
186 bool QQuickTimer::isRepeating() const
187 {
188     Q_D(const QQuickTimer);
189     return d->repeating;
190 }
191
192 void QQuickTimer::setRepeating(bool repeating)
193 {
194     Q_D(QQuickTimer);
195     if (repeating != d->repeating) {
196         d->repeating = repeating;
197         update();
198         emit repeatChanged();
199     }
200 }
201
202 /*!
203     \qmlproperty bool QtQuick2::Timer::triggeredOnStart
204
205     When a timer is started, the first trigger is usually after the specified
206     interval has elapsed.  It is sometimes desirable to trigger immediately
207     when the timer is started; for example, to establish an initial
208     state.
209
210     If \a triggeredOnStart is true, the timer is triggered immediately
211     when started, and subsequently at the specified interval. Note that if
212     \e repeat is set to false, the timer is triggered twice; once on start,
213     and again at the interval.
214
215     \a triggeredOnStart defaults to false.
216
217     \sa running
218 */
219 bool QQuickTimer::triggeredOnStart() const
220 {
221     Q_D(const QQuickTimer);
222     return d->triggeredOnStart;
223 }
224
225 void QQuickTimer::setTriggeredOnStart(bool triggeredOnStart)
226 {
227     Q_D(QQuickTimer);
228     if (d->triggeredOnStart != triggeredOnStart) {
229         d->triggeredOnStart = triggeredOnStart;
230         update();
231         emit triggeredOnStartChanged();
232     }
233 }
234
235 /*!
236     \qmlmethod QtQuick2::Timer::start()
237     \brief Starts the timer
238
239     If the timer is already running, calling this method has no effect.  The
240     \c running property will be true following a call to \c start().
241 */
242 void QQuickTimer::start()
243 {
244     setRunning(true);
245 }
246
247 /*!
248     \qmlmethod QtQuick2::Timer::stop()
249     \brief Stops the timer
250
251     If the timer is not running, calling this method has no effect.  The
252     \c running property will be false following a call to \c stop().
253 */
254 void QQuickTimer::stop()
255 {
256     setRunning(false);
257 }
258
259 /*!
260     \qmlmethod QtQuick2::Timer::restart()
261     \brief Restarts the timer
262
263     If the Timer is not running it will be started, otherwise it will be
264     stopped, reset to initial state and started.  The \c running property
265     will be true following a call to \c restart().
266 */
267 void QQuickTimer::restart()
268 {
269     setRunning(false);
270     setRunning(true);
271 }
272
273 void QQuickTimer::update()
274 {
275     Q_D(QQuickTimer);
276     if (d->classBegun && !d->componentComplete)
277         return;
278     d->pause.stop();
279     if (d->running) {
280         d->pause.setCurrentTime(0);
281         d->pause.setLoopCount(d->repeating ? -1 : 1);
282         d->pause.setDuration(d->interval);
283         d->pause.start();
284         if (d->triggeredOnStart && d->firstTick) {
285             QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
286             QMetaObject::invokeMethod(this, "ticked", Qt::QueuedConnection);
287         }
288     }
289 }
290
291 void QQuickTimer::classBegin()
292 {
293     Q_D(QQuickTimer);
294     d->classBegun = true;
295 }
296
297 void QQuickTimer::componentComplete()
298 {
299     Q_D(QQuickTimer);
300     d->componentComplete = true;
301     update();
302 }
303
304 /*!
305     \qmlsignal QtQuick2::Timer::onTriggered()
306
307     This handler is called when the Timer is triggered.
308 */
309 void QQuickTimer::ticked()
310 {
311     Q_D(QQuickTimer);
312     if (d->running && (d->pause.currentTime() > 0 || (d->triggeredOnStart && d->firstTick)))
313         emit triggered();
314     d->firstTick = false;
315 }
316
317 void QQuickTimerPrivate::animationFinished(QAbstractAnimationJob *)
318 {
319     Q_Q(QQuickTimer);
320     if (repeating || !running)
321         return;
322     running = false;
323     firstTick = false;
324     emit q->triggered();
325     emit q->runningChanged();
326 }
327
328 QT_END_NAMESPACE