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

Last change on this file since 420 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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