src/corelib/kernel/qtimer.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    47 QT_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 
       
   138 static const int INV_TIMER = -1;                // invalid timer id
       
   139 
       
   140 /*!
       
   141     Constructs a timer with the given \a parent.
       
   142 */
       
   143 
       
   144 QTimer::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 
       
   155 QTimer::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 
       
   166 QTimer::~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 */
       
   210 void 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 */
       
   222 void 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 
       
   235 int 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 
       
   254 void QTimer::stop()
       
   255 {
       
   256     if (id != INV_TIMER) {
       
   257         QObject::killTimer(id);
       
   258         id = INV_TIMER;
       
   259     }
       
   260 }
       
   261 
       
   262 
       
   263 /*!
       
   264   \reimp
       
   265 */
       
   266 void QTimer::timerEvent(QTimerEvent *e)
       
   267 {
       
   268     if (e->timerId() == id) {
       
   269         if (single)
       
   270             stop();
       
   271         emit timeout();
       
   272     }
       
   273 }
       
   274 
       
   275 class QSingleShotTimer : public QObject
       
   276 {
       
   277     Q_OBJECT
       
   278     int timerId;
       
   279 public:
       
   280     ~QSingleShotTimer();
       
   281     QSingleShotTimer(int msec, QObject *r, const char * m);
       
   282 Q_SIGNALS:
       
   283     void timeout();
       
   284 protected:
       
   285     void timerEvent(QTimerEvent *);
       
   286 };
       
   287 
       
   288 QSingleShotTimer::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 
       
   295 QSingleShotTimer::~QSingleShotTimer()
       
   296 {
       
   297     if (timerId > 0)
       
   298         killTimer(timerId);
       
   299 }
       
   300 
       
   301 void 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 
       
   316 QT_BEGIN_INCLUDE_NAMESPACE
       
   317 #include "qtimer.moc"
       
   318 QT_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 
       
   340 void QTimer::singleShot(int msec, QObject *receiver, const char *member)
       
   341 {
       
   342     if (receiver && member)
       
   343         (void) new QSingleShotTimer(msec, receiver, member);
       
   344 }
       
   345 
       
   346 /*!
       
   347     \property QTimer::singleShot
       
   348     \brief whether the timer is a single-shot timer
       
   349 
       
   350     A single-shot timer fires only once, non-single-shot timers fire
       
   351     every \l interval milliseconds.
       
   352 
       
   353     \sa interval, singleShot()
       
   354 */
       
   355 
       
   356 /*!
       
   357     \property QTimer::interval
       
   358     \brief the timeout interval in milliseconds
       
   359 
       
   360     The default value for this property is 0.  A QTimer with a timeout
       
   361     interval of 0 will time out as soon as all the events in the window
       
   362     system's event queue have been processed.
       
   363 
       
   364     Setting the interval of an active timer changes its timerId().
       
   365 
       
   366     \sa singleShot
       
   367 */
       
   368 void QTimer::setInterval(int msec)
       
   369 {
       
   370     inter = msec;
       
   371     if (id != INV_TIMER) {                        // create new timer
       
   372         QObject::killTimer(id);                        // restart timer
       
   373         id = QObject::startTimer(msec);
       
   374     }
       
   375 }
       
   376 
       
   377 /*! \fn void QTimer::changeInterval(int msec)
       
   378 
       
   379    Use setInterval(msec) or start(msec) instead.
       
   380 */
       
   381 
       
   382 QT_END_NAMESPACE