Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtimer.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qtimer.h"
6#include "qtimer_p.h"
8
10#include "qcoreapplication.h"
11#include "qcoreapplication_p.h"
12#include "qdeadlinetimer.h"
13#include "qmetaobject_p.h"
14#include "qobject_p.h"
15#include "qproperty_p.h"
16#include "qthread.h"
17
18using namespace std::chrono_literals;
19
21
128 : QObject(*new QTimerPrivate(this), parent)
129{
130 Q_ASSERT(d_func()->isQTimer);
131}
132
133
139{
140 if (d_func()->isActive()) // stop running timer
141 stop();
142}
143
144
168{
169 return d_func()->isActiveData.value();
170}
171
172QBindable<bool> QTimer::bindableActive()
173{
174 return QBindable<bool>(&d_func()->isActiveData);
175}
176
184{
185 auto v = qToUnderlying(id());
186 return v == 0 ? -1 : v;
187}
188
197{
198 return d_func()->id;
199}
200
211{
212 Q_D(QTimer);
213 if (d->isActive()) // stop running timer
214 stop();
215
216 Qt::TimerId newId{ QObject::startTimer(d->inter * 1ms, d->type) }; // overflow impossible
217 if (newId > Qt::TimerId::Invalid) {
218 d->id = newId;
219 d->isActiveData.notify();
220 }
221}
222
241void QTimer::start(int msec)
242{
243 start(msec * 1ms);
244}
245
246void QTimer::start(std::chrono::milliseconds interval)
247{
248 Q_D(QTimer);
249 // This could be narrowing as the interval is stored in an `int` QProperty,
250 // and the type can't be changed in Qt6.
251 const int msec = interval.count();
252 const bool intervalChanged = msec != d->inter;
253 d->inter.setValue(msec);
254 start();
255 if (intervalChanged)
256 d->inter.notify();
257}
258
259
260
268{
269 Q_D(QTimer);
270 if (d->isActive()) {
273 d->isActiveData.notify();
274 }
275}
276
277
282{
283 Q_D(QTimer);
284 if (Qt::TimerId{e->timerId()} == d->id) {
285 if (d->single)
286 stop();
287 emit timeout(QPrivateSignal());
288 }
289}
290
302void QTimer::singleShotImpl(std::chrono::milliseconds msec, Qt::TimerType timerType,
303 const QObject *receiver,
305{
306 if (msec == 0ms) {
307 bool deleteReceiver = false;
308 // Optimize: set a receiver context when none is given, such that we can use
309 // QMetaObject::invokeMethod which is more efficient than going through a timer.
310 // We need a QObject living in the current thread. But the QThread itself lives
311 // in a different thread - with the exception of the main QThread which lives in
312 // itself. And QThread::currentThread() is among the few QObjects we know that will
313 // most certainly be there. Note that one can actually call singleShot before the
314 // QApplication is created!
316 // reuse main thread as context object
317 receiver = QThread::currentThread();
318 } else if (!receiver) {
319 // Create a receiver context object on-demand. According to the benchmarks,
320 // this is still more efficient than going through a timer.
321 receiver = new QObject;
322 deleteReceiver = true;
323 }
324
326 QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj,
327 Qt::QueuedConnection, h.parameterCount(), h.parameters.data(), h.typeNames.data(),
328 h.metaTypes.data());
329
330 if (deleteReceiver)
331 const_cast<QObject *>(receiver)->deleteLater();
332 return;
333 }
334
335 new QSingleShotTimer(QSingleShotTimer::fromMsecs(msec), timerType, receiver, slotObj);
336}
337
378void QTimer::singleShot(std::chrono::milliseconds msec, Qt::TimerType timerType,
379 const QObject *receiver, const char *member)
380{
381 if (Q_UNLIKELY(msec < 0ms)) {
382 qWarning("QTimer::singleShot: Timers cannot have negative timeouts");
383 return;
384 }
385 if (receiver && member) {
386 if (msec == 0ms) {
387 // special code shortpath for 0-timers
388 const char* bracketPosition = strchr(member, '(');
389 if (!bracketPosition || !(member[0] >= '0' && member[0] <= '2')) {
390 qWarning("QTimer::singleShot: Invalid slot specification");
391 return;
392 }
393 const auto methodName = QByteArrayView(member + 1, // extract method name
394 bracketPosition - 1 - member).trimmed();
395 QMetaObject::invokeMethod(const_cast<QObject *>(receiver), methodName.toByteArray().constData(),
397 return;
398 }
399 (void) new QSingleShotTimer(QSingleShotTimer::fromMsecs(msec), timerType, receiver, member);
400 }
401}
402
552void QTimer::setSingleShot(bool singleShot)
553{
554 d_func()->single = singleShot;
555}
556
558{
559 return d_func()->single;
560}
561
563{
564 return QBindable<bool>(&d_func()->single);
565}
566
580{
581 setInterval(std::chrono::milliseconds{msec});
582}
583
584void QTimer::setInterval(std::chrono::milliseconds interval)
585{
586 Q_D(QTimer);
587 // This could be narrowing as the interval is stored in an `int` QProperty,
588 // and the type can't be changed in Qt6.
589 const int msec = interval.count();
590 d->inter.removeBindingUnlessInWrapper();
591 const bool intervalChanged = msec != d->inter.valueBypassingBindings();
592 d->inter.setValueBypassingBindings(msec);
593 if (d->isActive()) { // create new timer
594 QObject::killTimer(d->id); // restart timer
595 Qt::TimerId newId{ QObject::startTimer(msec * 1ms, d->type) }; // overflow impossible
596 if (newId > Qt::TimerId::Invalid) {
597 // Restarted successfully. No need to update the active state.
598 d->id = newId;
599 } else {
600 // Failed to start the timer.
601 // Need to notify about active state change.
603 d->isActiveData.notify();
604 }
605 }
606 if (intervalChanged)
607 d->inter.notify();
608}
609
611{
612 return d_func()->inter;
613}
614
616{
617 return QBindable<int>(&d_func()->inter);
618}
619
632{
633 Q_D(const QTimer);
634 if (d->isActive()) {
635 using namespace std::chrono;
636 auto remaining = QAbstractEventDispatcher::instance()->remainingTime(d->id);
637 return ceil<milliseconds>(remaining).count();
638 }
639
640 return -1;
641}
642
652{
653 d_func()->type = atype;
654}
655
657{
658 return d_func()->type;
659}
660
661QBindable<Qt::TimerType> QTimer::bindableTimerType()
662{
663 return QBindable<Qt::TimerType>(&d_func()->type);
664}
665
667
668#include "moc_qtimer.cpp"
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
QByteArrayView trimmed() const noexcept
static QThread * mainThread()
\inmodule QtCore
Definition qobject.h:103
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
Definition qobject.cpp:1817
Q_INVOKABLE QObject(QObject *parent=nullptr)
Constructs an object with parent object parent.
Definition qobject.cpp:936
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1912
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
static Duration fromMsecs(std::chrono::milliseconds ms)
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
Definition qcoreevent.h:366
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition qcoreevent.h:370
\inmodule QtCore
Definition qtimer.h:20
QTimer(QObject *parent=nullptr)
Constructs a timer with the given parent.
Definition qtimer.cpp:127
void setSingleShot(bool singleShot)
Definition qtimer.cpp:552
void timerEvent(QTimerEvent *) override
\reimp
Definition qtimer.cpp:281
bool isSingleShot() const
Definition qtimer.cpp:557
int interval
the timeout interval in milliseconds
Definition qtimer.h:23
int remainingTime
the remaining time in milliseconds
Definition qtimer.h:24
Qt::TimerId id() const
Definition qtimer.cpp:196
Qt::TimerType timerType
controls the accuracy of the timer
Definition qtimer.h:25
void setInterval(int msec)
Definition qtimer.cpp:579
QBindable< Qt::TimerType > bindableTimerType()
Definition qtimer.cpp:661
int timerId() const
Returns the ID of the timer if the timer is running; otherwise returns -1.
Definition qtimer.cpp:183
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
Definition qtimer.cpp:167
bool singleShot
whether the timer is a single-shot timer
Definition qtimer.h:22
QBindable< int > bindableInterval()
Definition qtimer.cpp:615
void start()
Definition qtimer.cpp:210
QBindable< bool > bindableActive()
Definition qtimer.cpp:172
void stop()
Stops the timer.
Definition qtimer.cpp:267
QBindable< bool > bindableSingleShot()
Definition qtimer.cpp:562
~QTimer()
Destroys the timer.
Definition qtimer.cpp:138
void setTimerType(Qt::TimerType atype)
Definition qtimer.cpp:651
#define this
Definition dialogs.cpp:9
Combined button and popup list for selecting options.
auto invokeMethodHelper(QMetaMethodReturnArgument r, const Args &... arguments)
TimerType
@ QueuedConnection
#define Q_UNLIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
static QString methodName(const QDBusIntrospection::Method &method)
#define qWarning
Definition qlogging.h:166
GLsizei const GLfloat * v
[13]
GLbitfield GLuint64 timeout
[4]
GLenum type
GLfloat GLfloat GLfloat GLfloat h
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
QT_BEGIN_NAMESPACE constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...