diff options
Diffstat (limited to 'src/corelib/kernel/qtimer.cpp')
| -rw-r--r-- | src/corelib/kernel/qtimer.cpp | 394 | 
1 files changed, 394 insertions, 0 deletions
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp new file mode 100644 index 0000000000..3efeda229d --- /dev/null +++ b/src/corelib/kernel/qtimer.cpp @@ -0,0 +1,394 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file.  Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights.  These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtimer.h" +#include "qabstracteventdispatcher.h" +#include "qcoreapplication.h" +#include "qobject_p.h" + +QT_BEGIN_NAMESPACE + +/*! +    \class QTimer +    \brief The QTimer class provides repetitive and single-shot timers. + +    \ingroup events + + +    The QTimer class provides a high-level programming interface for +    timers. To use it, create a QTimer, connect its timeout() signal +    to the appropriate slots, and call start(). From then on it will +    emit the timeout() signal at constant intervals. + +    Example for a one second (1000 millisecond) timer (from the +    \l{widgets/analogclock}{Analog Clock} example): + +    \snippet examples/widgets/analogclock/analogclock.cpp 4 +    \snippet examples/widgets/analogclock/analogclock.cpp 5 +    \snippet examples/widgets/analogclock/analogclock.cpp 6 + +    From then on, the \c update() slot is called every second. + +    You can set a timer to time out only once by calling +    setSingleShot(true). You can also use the static +    QTimer::singleShot() function to call a slot after a specified +    interval: + +    \snippet doc/src/snippets/timers/timers.cpp 3 + +    In multithreaded applications, you can use QTimer in any thread +    that has an event loop. To start an event loop from a non-GUI +    thread, use QThread::exec(). Qt uses the timer's +    \l{QObject::thread()}{thread affinity} to determine which thread +    will emit the \l{QTimer::}{timeout()} signal. Because of this, you +    must start and stop the timer in its thread; it is not possible to +    start a timer from another thread. + +    As a special case, a QTimer with a timeout of 0 will time out as +    soon as all the events in the window system's event queue have +    been processed. This can be used to do heavy work while providing +    a snappy user interface: + +    \snippet doc/src/snippets/timers/timers.cpp 4 +    \snippet doc/src/snippets/timers/timers.cpp 5 +    \snippet doc/src/snippets/timers/timers.cpp 6 + +    \c processOneThing() will from then on be called repeatedly. It +    should be written in such a way that it always returns quickly +    (typically after processing one data item) so that Qt can deliver +    events to widgets and stop the timer as soon as it has done all +    its work. This is the traditional way of implementing heavy work +    in GUI applications; multithreading is now becoming available on +    more and more platforms, and we expect that zero-millisecond +    QTimers will gradually be replaced by \l{QThread}s. + +    \section1 Accuracy and Timer Resolution + +    Timers will never time out earlier than the specified timeout value +    and they are not guaranteed to time out at the exact value specified. +    In many situations, they may time out late by a period of time that +    depends on the accuracy of the system timers. + +    The accuracy of timers depends on the underlying operating system +    and hardware. Most platforms support a resolution of 1 millisecond, +    though the accuracy of the timer will not equal this resolution +    in many real-world situations. + +    If Qt is unable to deliver the requested number of timer clicks, +    it will silently discard some. + +    \section1 Alternatives to QTimer + +    An alternative to using QTimer is to call QObject::startTimer() +    for your object and reimplement the QObject::timerEvent() event +    handler in your class (which must inherit QObject). The +    disadvantage is that timerEvent() does not support such +    high-level features as single-shot timers or signals. + +    Another alternative to using QTimer is to use QBasicTimer. It is +    typically less cumbersome than using QObject::startTimer() +    directly. See \l{Timers} for an overview of all three approaches. + +    Some operating systems limit the number of timers that may be +    used; Qt tries to work around these limitations. + +    \sa QBasicTimer, QTimerEvent, QObject::timerEvent(), Timers, +        {Analog Clock Example}, {Wiggly Example} +*/ + + +static const int INV_TIMER = -1;                // invalid timer id + +/*! +    Constructs a timer with the given \a parent. +*/ + +QTimer::QTimer(QObject *parent) +    : QObject(parent), id(INV_TIMER), inter(0), del(0), single(0), nulltimer(0) +{ +} + + +#ifdef QT3_SUPPORT +/*! +    Constructs a timer called \a name, with a \a parent. +*/ + +QTimer::QTimer(QObject *parent, const char *name) +    : QObject(parent), id(INV_TIMER), single(0), nulltimer(0) +{ +    setObjectName(QString::fromAscii(name)); +} +#endif + +/*! +    Destroys the timer. +*/ + +QTimer::~QTimer() +{ +    if (id != INV_TIMER)                        // stop running timer +        stop(); +} + + +/*! +    \fn void QTimer::timeout() + +    This signal is emitted when the timer times out. + +    \sa interval, start(), stop() +*/ + +/*! +    \property QTimer::active +    \since 4.3 + +    This boolean property is true if the timer is running; otherwise +    false. +*/ + +/*! +    \fn bool QTimer::isActive() const + +    Returns true if the timer is running (pending); otherwise returns +    false. +*/ + +/*! +    \fn int QTimer::timerId() const + +    Returns the ID of the timer if the timer is running; otherwise returns +    -1. +*/ + + +/*! \overload start() + +    Starts or restarts the timer with the timeout specified in \l interval. + +    If \l singleShot is true, the timer will be activated only once. +*/ +void QTimer::start() +{ +    if (id != INV_TIMER)                        // stop running timer +        stop(); +    nulltimer = (!inter && single); +    id = QObject::startTimer(inter); +} + +/*! +    Starts or restarts the timer with a timeout interval of \a msec +    milliseconds. +*/ +void QTimer::start(int msec) +{ +    inter = msec; +    start(); +} + + +#ifdef QT3_SUPPORT +/*! \overload start() + +  Call setSingleShot(\a sshot) and start(\a msec) instead. +*/ + +int QTimer::start(int msec, bool sshot) +{ +    if (id >=0 && nulltimer && !msec && sshot) +        return id; +    stop(); +    setInterval(msec); +    setSingleShot(sshot); +    start(); +    return timerId(); +} +#endif + + +/*! +    Stops the timer. + +    \sa start() +*/ + +void QTimer::stop() +{ +    if (id != INV_TIMER) { +        QObject::killTimer(id); +        id = INV_TIMER; +    } +} + + +/*! +  \reimp +*/ +void QTimer::timerEvent(QTimerEvent *e) +{ +    if (e->timerId() == id) { +        if (single) +            stop(); +        emit timeout(); +    } +} + +class QSingleShotTimer : public QObject +{ +    Q_OBJECT +    int timerId; +public: +    ~QSingleShotTimer(); +    QSingleShotTimer(int msec, QObject *r, const char * m); +Q_SIGNALS: +    void timeout(); +protected: +    void timerEvent(QTimerEvent *); +}; + +QSingleShotTimer::QSingleShotTimer(int msec, QObject *receiver, const char *member) +    : QObject(QAbstractEventDispatcher::instance()) +{ +    connect(this, SIGNAL(timeout()), receiver, member); +    timerId = startTimer(msec); +} + +QSingleShotTimer::~QSingleShotTimer() +{ +    if (timerId > 0) +        killTimer(timerId); +} + +void QSingleShotTimer::timerEvent(QTimerEvent *) +{ +    // need to kill the timer _before_ we emit timeout() in case the +    // slot connected to timeout calls processEvents() +    if (timerId > 0) +        killTimer(timerId); +    timerId = -1; +    emit timeout(); + +    // we would like to use delete later here, but it feels like a +    // waste to post a new event to handle this event, so we just unset the flag +    // and explicitly delete... +    qDeleteInEventHandler(this); +} + +QT_BEGIN_INCLUDE_NAMESPACE +#include "qtimer.moc" +QT_END_INCLUDE_NAMESPACE + +/*! +    \reentrant +    This static function calls a slot after a given time interval. + +    It is very convenient to use this function because you do not need +    to bother with a \link QObject::timerEvent() timerEvent\endlink or +    create a local QTimer object. + +    Example: +    \snippet doc/src/snippets/code/src_corelib_kernel_qtimer.cpp 0 + +    This sample program automatically terminates after 10 minutes +    (600,000 milliseconds). + +    The \a receiver is the receiving object and the \a member is the +    slot. The time interval is \a msec milliseconds. + +    \sa start() +*/ + +void QTimer::singleShot(int msec, QObject *receiver, const char *member) +{ +    if (receiver && member) { +        if (msec == 0) { +            // special code shortpath for 0-timers +            const char* bracketPosition = strchr(member, '('); +            if (!bracketPosition || !(member[0] >= '0' && member[0] <= '3')) { +                qWarning("QTimer::singleShot: Invalid slot specification"); +                return; +            } +            QByteArray methodName(member+1, bracketPosition - 1 - member); // extract method name +            QMetaObject::invokeMethod(receiver, methodName.constData(), Qt::QueuedConnection); +            return; +        } +        (void) new QSingleShotTimer(msec, receiver, member); +    } +} + +/*! +    \property QTimer::singleShot +    \brief whether the timer is a single-shot timer + +    A single-shot timer fires only once, non-single-shot timers fire +    every \l interval milliseconds. + +    \sa interval, singleShot() +*/ + +/*! +    \property QTimer::interval +    \brief the timeout interval in milliseconds + +    The default value for this property is 0.  A QTimer with a timeout +    interval of 0 will time out as soon as all the events in the window +    system's event queue have been processed. + +    Setting the interval of an active timer changes its timerId(). + +    \sa singleShot +*/ +void QTimer::setInterval(int msec) +{ +    inter = msec; +    if (id != INV_TIMER) {                        // create new timer +        QObject::killTimer(id);                        // restart timer +        id = QObject::startTimer(msec); +    } +} + +/*! \fn void QTimer::changeInterval(int msec) + +   Use setInterval(msec) or start(msec) instead. +*/ + +QT_END_NAMESPACE  | 
