1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QTIMER_H
5#define QTIMER_H
6
7#include <QtCore/qglobal.h>
8
9#ifndef QT_NO_QOBJECT
10
11#include <QtCore/qbasictimer.h> // conceptual inheritance
12#include <QtCore/qobject.h>
13
14#include <chrono>
15
16QT_BEGIN_NAMESPACE
17
18class QTimerPrivate;
19class Q_CORE_EXPORT QTimer : public QObject
20{
21 Q_OBJECT
22 Q_PROPERTY(bool singleShot READ isSingleShot WRITE setSingleShot BINDABLE bindableSingleShot)
23 Q_PROPERTY(int interval READ interval WRITE setInterval BINDABLE bindableInterval)
24 Q_PROPERTY(int remainingTime READ remainingTime)
25 Q_PROPERTY(Qt::TimerType timerType READ timerType WRITE setTimerType BINDABLE bindableTimerType)
26 Q_PROPERTY(bool active READ isActive STORED false BINDABLE bindableActive)
27public:
28 explicit QTimer(QObject *parent = nullptr);
29 ~QTimer();
30
31 bool isActive() const;
32 QBindable<bool> bindableActive();
33 int timerId() const;
34
35 void setInterval(int msec);
36 int interval() const;
37 QBindable<int> bindableInterval();
38
39 int remainingTime() const;
40
41 void setTimerType(Qt::TimerType atype);
42 Qt::TimerType timerType() const;
43 QBindable<Qt::TimerType> bindableTimerType();
44
45 void setSingleShot(bool singleShot);
46 bool isSingleShot() const;
47 QBindable<bool> bindableSingleShot();
48
49 static void singleShot(int msec, const QObject *receiver, const char *member);
50 static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member);
51
52 // singleShot with context
53#ifdef Q_QDOC
54 template <typename Duration, typename Functor>
55 static inline void singleShot(Duration interval, const QObject *receiver, Functor &&slot);
56 template <typename Duration, typename Functor>
57 static inline void singleShot(Duration interval, Qt::TimerType timerType,
58 const QObject *receiver, Functor &&slot);
59#else
60 template <typename Duration, typename Functor>
61 static inline void singleShot(Duration interval,
62 const typename QtPrivate::ContextTypeForFunctor<Functor>::ContextType *receiver,
63 Functor &&slot)
64 {
65 singleShot(interval, defaultTypeFor(interval), receiver, std::forward<Functor>(slot));
66 }
67 template <typename Duration, typename Functor>
68 static inline void singleShot(Duration interval, Qt::TimerType timerType,
69 const typename QtPrivate::ContextTypeForFunctor<Functor>::ContextType *receiver,
70 Functor &&slot)
71 {
72 using Prototype = void(*)();
73 singleShotImpl(interval, timerType, receiver,
74 QtPrivate::makeCallableObject<Prototype>(std::forward<Functor>(slot)));
75 }
76#endif
77
78 // singleShot without context
79 template <typename Duration, typename Functor>
80 static inline void singleShot(Duration interval, Functor &&slot)
81 {
82 singleShot(interval, defaultTypeFor(interval), nullptr, std::forward<Functor>(slot));
83 }
84 template <typename Duration, typename Functor>
85 static inline void singleShot(Duration interval, Qt::TimerType timerType, Functor &&slot)
86 {
87 singleShot(interval, timerType, nullptr, std::forward<Functor>(slot));
88 }
89
90#ifdef Q_QDOC
91 template <typename Functor>
92 QMetaObject::Connection callOnTimeout(Functor &&slot);
93 template <typename Functor>
94 QMetaObject::Connection callOnTimeout(const QObject *context, Functor &&slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
95#else
96 template <typename ... Args>
97 QMetaObject::Connection callOnTimeout(Args && ...args)
98 {
99 return QObject::connect(this, &QTimer::timeout, std::forward<Args>(args)... );
100 }
101
102#endif
103
104public Q_SLOTS:
105 void start(int msec);
106
107 void start();
108 void stop();
109
110Q_SIGNALS:
111 void timeout(QPrivateSignal);
112
113public:
114 void setInterval(std::chrono::milliseconds value)
115 {
116 setInterval(int(value.count()));
117 }
118
119 std::chrono::milliseconds intervalAsDuration() const
120 {
121 return std::chrono::milliseconds(interval());
122 }
123
124 std::chrono::milliseconds remainingTimeAsDuration() const
125 {
126 return std::chrono::milliseconds(remainingTime());
127 }
128
129 static void singleShot(std::chrono::milliseconds value, const QObject *receiver, const char *member)
130 {
131 singleShot(msec: int(value.count()), receiver, member);
132 }
133
134 static void singleShot(std::chrono::milliseconds value, Qt::TimerType timerType, const QObject *receiver, const char *member)
135 {
136 singleShot(msec: int(value.count()), timerType, receiver, member);
137 }
138
139 void start(std::chrono::milliseconds value)
140 {
141 start(msec: int(value.count()));
142 }
143
144protected:
145 void timerEvent(QTimerEvent *) override;
146
147private:
148 Q_DISABLE_COPY(QTimer)
149 Q_DECLARE_PRIVATE(QTimer)
150
151 inline int startTimer(int){ return -1;}
152 inline void killTimer(int){}
153
154 static constexpr Qt::TimerType defaultTypeFor(int msecs) noexcept
155 { return defaultTypeFor(interval: std::chrono::milliseconds{msecs}); }
156
157 static constexpr Qt::TimerType defaultTypeFor(std::chrono::milliseconds interval) noexcept
158 {
159 // coarse timers are worst in their first firing
160 // so we prefer a high precision timer for something that happens only once
161 // unless the timeout is too big, in which case we go for coarse anyway
162 using namespace std::chrono_literals;
163 return interval >= 2s ? Qt::CoarseTimer : Qt::PreciseTimer;
164 }
165
166 static void singleShotImpl(int msec, Qt::TimerType timerType,
167 const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
168
169 static void singleShotImpl(std::chrono::milliseconds interval, Qt::TimerType timerType,
170 const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj)
171 {
172 singleShotImpl(msec: int(interval.count()),
173 timerType, receiver, slotObj);
174 }
175};
176
177QT_END_NAMESPACE
178
179#endif // QT_NO_QOBJECT
180
181#endif // QTIMER_H
182