source: trunk/src/corelib/kernel/qtimer.cpp@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 11.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtimer.h"
43#include "qabstracteventdispatcher.h"
44#include "qcoreapplication.h"
45#include "qobject_p.h"
46
47QT_BEGIN_NAMESPACE
48
49/*!
50 \class QTimer
51 \brief The QTimer class provides repetitive and single-shot timers.
52
53 \ingroup events
54
55
56 The QTimer class provides a high-level programming interface for
57 timers. To use it, create a QTimer, connect its timeout() signal
58 to the appropriate slots, and call start(). From then on it will
59 emit the timeout() signal at constant intervals.
60
61 Example for a one second (1000 millisecond) timer (from the
62 \l{widgets/analogclock}{Analog Clock} example):
63
64 \snippet examples/widgets/analogclock/analogclock.cpp 4
65 \snippet examples/widgets/analogclock/analogclock.cpp 5
66 \snippet examples/widgets/analogclock/analogclock.cpp 6
67
68 From then on, the \c update() slot is called every second.
69
70 You can set a timer to time out only once by calling
71 setSingleShot(true). You can also use the static
72 QTimer::singleShot() function to call a slot after a specified
73 interval:
74
75 \snippet doc/src/snippets/timers/timers.cpp 3
76
77 In multithreaded applications, you can use QTimer in any thread
78 that has an event loop. To start an event loop from a non-GUI
79 thread, use QThread::exec(). Qt uses the timer's
80 \l{QObject::thread()}{thread affinity} to determine which thread
81 will emit the \l{QTimer::}{timeout()} signal. Because of this, you
82 must start and stop the timer in its thread; it is not possible to
83 start a timer from another thread.
84
85 As a special case, a QTimer with a timeout of 0 will time out as
86 soon as all the events in the window system's event queue have
87 been processed. This can be used to do heavy work while providing
88 a snappy user interface:
89
90 \snippet doc/src/snippets/timers/timers.cpp 4
91 \snippet doc/src/snippets/timers/timers.cpp 5
92 \snippet doc/src/snippets/timers/timers.cpp 6
93
94 \c processOneThing() will from then on be called repeatedly. It
95 should be written in such a way that it always returns quickly
96 (typically after processing one data item) so that Qt can deliver
97 events to widgets and stop the timer as soon as it has done all
98 its work. This is the traditional way of implementing heavy work
99 in GUI applications; multithreading is now becoming available on
100 more and more platforms, and we expect that zero-millisecond
101 QTimers will gradually be replaced by \l{QThread}s.
102
103 \section1 Accuracy and Timer Resolution
104
105 Timers will never time out earlier than the specified timeout value
106 and they are not guaranteed to time out at the exact value specified.
107 In many situations, they may time out late by a period of time that
108 depends on the accuracy of the system timers.
109
110 The accuracy of timers depends on the underlying operating system
111 and hardware. Most platforms support a resolution of 1 millisecond,
112 though the accuracy of the timer will not equal this resolution
113 in many real-world situations.
114
115 If Qt is unable to deliver the requested number of timer clicks,
116 it will silently discard some.
117
118 \section1 Alternatives to QTimer
119
120 An alternative to using QTimer is to call QObject::startTimer()
121 for your object and reimplement the QObject::timerEvent() event
122 handler in your class (which must inherit QObject). The
123 disadvantage is that timerEvent() does not support such
124 high-level features as single-shot timers or signals.
125
126 Another alternative to using QTimer is to use QBasicTimer. It is
127 typically less cumbersome than using QObject::startTimer()
128 directly. See \l{Timers} for an overview of all three approaches.
129
130 Some operating systems limit the number of timers that may be
131 used; Qt tries to work around these limitations.
132
133 \sa QBasicTimer, QTimerEvent, QObject::timerEvent(), Timers,
134 {Analog Clock Example}, {Wiggly Example}
135*/
136
137
138static const int INV_TIMER = -1; // invalid timer id
139
140/*!
141 Constructs a timer with the given \a parent.
142*/
143
144QTimer::QTimer(QObject *parent)
145 : QObject(parent), id(INV_TIMER), inter(0), del(0), single(0), nulltimer(0)
146{
147}
148
149
150#ifdef QT3_SUPPORT
151/*!
152 Constructs a timer called \a name, with a \a parent.
153*/
154
155QTimer::QTimer(QObject *parent, const char *name)
156 : QObject(parent), id(INV_TIMER), single(0), nulltimer(0)
157{
158 setObjectName(QString::fromAscii(name));
159}
160#endif
161
162/*!
163 Destroys the timer.
164*/
165
166QTimer::~QTimer()
167{
168 if (id != INV_TIMER) // stop running timer
169 stop();
170}
171
172
173/*!
174 \fn void QTimer::timeout()
175
176 This signal is emitted when the timer times out.
177
178 \sa interval, start(), stop()
179*/
180
181/*!
182 \property QTimer::active
183 \since 4.3
184
185 This boolean property is true if the timer is running; otherwise
186 false.
187*/
188
189/*!
190 \fn bool QTimer::isActive() const
191
192 Returns true if the timer is running (pending); otherwise returns
193 false.
194*/
195
196/*!
197 \fn int QTimer::timerId() const
198
199 Returns the ID of the timer if the timer is running; otherwise returns
200 -1.
201*/
202
203
204/*! \overload start()
205
206 Starts or restarts the timer with the timeout specified in \l interval.
207
208 If \l singleShot is true, the timer will be activated only once.
209*/
210void QTimer::start()
211{
212 if (id != INV_TIMER) // stop running timer
213 stop();
214 nulltimer = (!inter && single);
215 id = QObject::startTimer(inter);
216}
217
218/*!
219 Starts or restarts the timer with a timeout interval of \a msec
220 milliseconds.
221*/
222void QTimer::start(int msec)
223{
224 inter = msec;
225 start();
226}
227
228
229#ifdef QT3_SUPPORT
230/*! \overload start()
231
232 Call setSingleShot(\a sshot) and start(\a msec) instead.
233*/
234
235int QTimer::start(int msec, bool sshot)
236{
237 if (id >=0 && nulltimer && !msec && sshot)
238 return id;
239 stop();
240 setInterval(msec);
241 setSingleShot(sshot);
242 start();
243 return timerId();
244}
245#endif
246
247
248/*!
249 Stops the timer.
250
251 \sa start()
252*/
253
254void QTimer::stop()
255{
256 if (id != INV_TIMER) {
257 QObject::killTimer(id);
258 id = INV_TIMER;
259 }
260}
261
262
263/*!
264 \reimp
265*/
266void QTimer::timerEvent(QTimerEvent *e)
267{
268 if (e->timerId() == id) {
269 if (single)
270 stop();
271 emit timeout();
272 }
273}
274
275class QSingleShotTimer : public QObject
276{
277 Q_OBJECT
278 int timerId;
279public:
280 ~QSingleShotTimer();
281 QSingleShotTimer(int msec, QObject *r, const char * m);
282Q_SIGNALS:
283 void timeout();
284protected:
285 void timerEvent(QTimerEvent *);
286};
287
288QSingleShotTimer::QSingleShotTimer(int msec, QObject *receiver, const char *member)
289 : QObject(QAbstractEventDispatcher::instance())
290{
291 connect(this, SIGNAL(timeout()), receiver, member);
292 timerId = startTimer(msec);
293}
294
295QSingleShotTimer::~QSingleShotTimer()
296{
297 if (timerId > 0)
298 killTimer(timerId);
299}
300
301void QSingleShotTimer::timerEvent(QTimerEvent *)
302{
303 // need to kill the timer _before_ we emit timeout() in case the
304 // slot connected to timeout calls processEvents()
305 if (timerId > 0)
306 killTimer(timerId);
307 timerId = -1;
308 emit timeout();
309
310 // we would like to use delete later here, but it feels like a
311 // waste to post a new event to handle this event, so we just unset the flag
312 // and explicitly delete...
313 qDeleteInEventHandler(this);
314}
315
316QT_BEGIN_INCLUDE_NAMESPACE
317#include "qtimer.moc"
318QT_END_INCLUDE_NAMESPACE
319
320/*!
321 \reentrant
322 This static function calls a slot after a given time interval.
323
324 It is very convenient to use this function because you do not need
325 to bother with a \link QObject::timerEvent() timerEvent\endlink or
326 create a local QTimer object.
327
328 Example:
329 \snippet doc/src/snippets/code/src_corelib_kernel_qtimer.cpp 0
330
331 This sample program automatically terminates after 10 minutes
332 (600,000 milliseconds).
333
334 The \a receiver is the receiving object and the \a member is the
335 slot. The time interval is \a msec milliseconds.
336
337 \sa start()
338*/
339
340void QTimer::singleShot(int msec, QObject *receiver, const char *member)
341{
342 if (receiver && member) {
343 if (msec == 0) {
344 // special code shortpath for 0-timers
345 const char* bracketPosition = strchr(member, '(');
346 if (!bracketPosition || !(member[0] >= '0' && member[0] <= '3')) {
347 qWarning("QTimer::singleShot: Invalid slot specification");
348 return;
349 }
350 QByteArray methodName(member+1, bracketPosition - 1 - member); // extract method name
351 QMetaObject::invokeMethod(receiver, methodName.constData(), Qt::QueuedConnection);
352 return;
353 }
354 (void) new QSingleShotTimer(msec, receiver, member);
355 }
356}
357
358/*!
359 \property QTimer::singleShot
360 \brief whether the timer is a single-shot timer
361
362 A single-shot timer fires only once, non-single-shot timers fire
363 every \l interval milliseconds.
364
365 \sa interval, singleShot()
366*/
367
368/*!
369 \property QTimer::interval
370 \brief the timeout interval in milliseconds
371
372 The default value for this property is 0. A QTimer with a timeout
373 interval of 0 will time out as soon as all the events in the window
374 system's event queue have been processed.
375
376 Setting the interval of an active timer changes its timerId().
377
378 \sa singleShot
379*/
380void QTimer::setInterval(int msec)
381{
382 inter = msec;
383 if (id != INV_TIMER) { // create new timer
384 QObject::killTimer(id); // restart timer
385 id = QObject::startTimer(msec);
386 }
387}
388
389/*! \fn void QTimer::changeInterval(int msec)
390
391 Use setInterval(msec) or start(msec) instead.
392*/
393
394QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.