source: vendor/trolltech/current/src/kernel/qtimer.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 8.9 KB
Line 
1/****************************************************************************
2** $Id: qtimer.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QTimer class
5**
6** Created : 931111
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qtimer.h"
39#include "qsignal.h"
40#include "qobjectlist.h"
41
42/*!
43 \class QTimer qtimer.h
44 \brief The QTimer class provides timer signals and single-shot timers.
45
46 \ingroup time
47 \ingroup events
48 \mainclass
49
50 It uses \link QTimerEvent timer events\endlink internally to
51 provide a more versatile timer. QTimer is very easy to use:
52 create a QTimer, call start() to start it and connect its
53 timeout() to the appropriate slots. When the time is up it will
54 emit the timeout() signal.
55
56 Note that a QTimer object is destroyed automatically when its
57 parent object is destroyed.
58
59 Example:
60 \code
61 QTimer *timer = new QTimer( myObject );
62 connect( timer, SIGNAL(timeout()), myObject, SLOT(timerDone()) );
63 timer->start( 2000, TRUE ); // 2 seconds single-shot timer
64 \endcode
65
66 You can also use the static singleShot() function to create a
67 single shot timer.
68
69 As a special case, a QTimer with timeout 0 times out as soon as
70 all the events in the window system's event queue have been
71 processed.
72
73 This can be used to do heavy work while providing a snappy
74 user interface:
75 \code
76 QTimer *t = new QTimer( myObject );
77 connect( t, SIGNAL(timeout()), SLOT(processOneThing()) );
78 t->start( 0, FALSE );
79 \endcode
80
81 myObject->processOneThing() will be called repeatedly and should
82 return quickly (typically after processing one data item) so that
83 Qt can deliver events to widgets and stop the timer as soon as it
84 has done all its work. This is the traditional way of
85 implementing heavy work in GUI applications; multi-threading is
86 now becoming available on more and more platforms, and we expect
87 that null events will eventually be replaced by threading.
88
89 Note that QTimer's accuracy depends on the underlying operating
90 system and hardware. Most platforms support an accuracy of 20ms;
91 some provide more. If Qt is unable to deliver the requested
92 number of timer clicks, it will silently discard some.
93
94 An alternative to using QTimer is to call QObject::startTimer()
95 for your object and reimplement the QObject::timerEvent() event
96 handler in your class (which must, of course, inherit QObject).
97 The disadvantage is that timerEvent() does not support such
98 high-level features as single-shot timers or signals.
99
100 Some operating systems limit the number of timers that may be
101 used; Qt tries to work around these limitations.
102*/
103
104
105static const int INV_TIMER = -1; // invalid timer id
106
107
108/*!
109 Constructs a timer called \a name, with the parent \a parent.
110
111 Note that the parent object's destructor will destroy this timer
112 object.
113*/
114
115QTimer::QTimer( QObject *parent, const char *name )
116 : QObject( parent, name ), id(INV_TIMER), single(0), nulltimer(0)
117{
118}
119
120/*!
121 Destroys the timer.
122*/
123
124QTimer::~QTimer()
125{
126 if ( id != INV_TIMER ) // stop running timer
127 stop();
128}
129
130
131/*!
132 \fn void QTimer::timeout()
133
134 This signal is emitted when the timer is activated.
135*/
136
137/*!
138 \fn bool QTimer::isActive() const
139
140 Returns TRUE if the timer is running (pending); otherwise returns
141 FALSE.
142*/
143
144/*!
145 \fn int QTimer::timerId() const
146
147 Returns the ID of the timer if the timer is running; otherwise returns
148 -1.
149*/
150
151
152/*!
153 Starts the timer with a \a msec milliseconds timeout, and returns
154 the ID of the timer, or zero when starting the timer failed.
155
156 If \a sshot is TRUE, the timer will be activated only once;
157 otherwise it will continue until it is stopped.
158
159 Any pending timer will be stopped.
160
161 \sa singleShot() stop(), changeInterval(), isActive()
162*/
163
164int QTimer::start( int msec, bool sshot )
165{
166 if ( id >=0 && nulltimer && !msec && sshot )
167 return id;
168 if ( id != INV_TIMER ) // stop running timer
169 stop();
170 single = sshot;
171 nulltimer = ( !msec && sshot );
172 return id = startTimer( msec );
173}
174
175
176/*!
177 Changes the timeout interval to \a msec milliseconds.
178
179 If the timer signal is pending, it will be stopped and restarted;
180 otherwise it will be started.
181
182 \sa start(), isActive()
183*/
184
185void QTimer::changeInterval( int msec )
186{
187 if ( id == INV_TIMER ) { // create new timer
188 start( msec );
189 } else {
190 killTimer( id ); // restart timer
191 id = startTimer( msec );
192 }
193}
194
195/*!
196 Stops the timer.
197
198 \sa start()
199*/
200
201void QTimer::stop()
202{
203 if ( id != INV_TIMER ) {
204 killTimer( id );
205 id = INV_TIMER;
206 }
207}
208
209
210/*!
211 \reimp
212*/
213bool QTimer::event( QEvent *e )
214{
215 if ( e->type() != QEvent::Timer ) // ignore all other events
216 return FALSE;
217 if ( single ) // stop single shot timer
218 stop();
219 emit timeout(); // emit timeout signal
220 return TRUE;
221}
222
223
224/*
225 The QSingleShotTimer class is an internal class for implementing
226 QTimer::singleShot(). It starts a timer and emits the signal
227 and kills itself when it gets the timeout.
228*/
229
230static QObjectList *sst_list = 0; // list of single shot timers
231
232static void sst_cleanup()
233{
234 if ( sst_list ) {
235 sst_list->setAutoDelete( TRUE );
236 delete sst_list;
237 sst_list = 0;
238 }
239}
240
241static void sst_init()
242{
243 if ( !sst_list ) {
244 sst_list = new QObjectList;
245 Q_CHECK_PTR( sst_list );
246 qAddPostRoutine( sst_cleanup );
247 }
248}
249
250
251class QSingleShotTimer : public QObject
252{
253public:
254 bool start( int msec, QObject *r, const char * m );
255 bool isActive() const { return timerId > 0; }
256protected:
257 bool event( QEvent * );
258private:
259 QSignal signal;
260 int timerId;
261};
262
263extern int qStartTimer( int interval, QObject *obj ); // implemented in qapp_xxx.cpp
264extern bool qKillTimer( int id );
265
266bool QSingleShotTimer::start( int msec, QObject *r, const char *m )
267{
268 timerId = 0;
269 if ( signal.connect(r, m) )
270 timerId = qStartTimer( msec, (QObject *)this );
271 return timerId != 0;
272}
273
274bool QSingleShotTimer::event( QEvent * )
275{
276 qKillTimer( timerId ); // no more timeouts
277 signal.activate(); // emit the signal
278 signal.disconnect( 0, 0 );
279 timerId = 0; // mark as inactive
280 return TRUE;
281}
282
283
284/*!
285 This static function calls a slot after a given time interval.
286
287 It is very convenient to use this function because you do not need
288 to bother with a \link QObject::timerEvent() timerEvent\endlink or
289 to create a local QTimer object.
290
291 Example:
292 \code
293 #include <qapplication.h>
294 #include <qtimer.h>
295
296 int main( int argc, char **argv )
297 {
298 QApplication a( argc, argv );
299 QTimer::singleShot( 10*60*1000, &a, SLOT(quit()) );
300 ... // create and show your widgets
301 return a.exec();
302 }
303 \endcode
304
305 This sample program automatically terminates after 10 minutes (i.e.
306 600000 milliseconds).
307
308 The \a receiver is the receiving object and the \a member is the
309 slot. The time interval is \a msec.
310*/
311
312void QTimer::singleShot( int msec, QObject *receiver, const char *member )
313{
314 if ( !sst_list )
315 sst_init();
316 // search the list for a free ss timer we could reuse
317 QSingleShotTimer *sst = (QSingleShotTimer*)sst_list->first();
318 while ( sst && sst->isActive() )
319 sst = (QSingleShotTimer*)sst_list->next();
320 // create a new one if not successful
321 if ( !sst ) {
322 sst = new QSingleShotTimer;
323 sst_list->append( sst );
324 }
325 sst->start(msec, receiver, member);
326}
Note: See TracBrowser for help on using the repository browser.