1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QTIMER_H
41 #define QTIMER_H
42 
43 #include <QtCore/qglobal.h>
44 
45 #ifndef QT_NO_QOBJECT
46 
47 #include <QtCore/qbasictimer.h> // conceptual inheritance
48 #include <QtCore/qobject.h>
49 
50 #if __has_include(<chrono>)
51 #  include <chrono>
52 #endif
53 
54 QT_BEGIN_NAMESPACE
55 
56 
57 class Q_CORE_EXPORT QTimer : public QObject
58 {
59     Q_OBJECT
60     Q_PROPERTY(bool singleShot READ isSingleShot WRITE setSingleShot)
61     Q_PROPERTY(int interval READ interval WRITE setInterval)
62     Q_PROPERTY(int remainingTime READ remainingTime)
63     Q_PROPERTY(Qt::TimerType timerType READ timerType WRITE setTimerType)
64     Q_PROPERTY(bool active READ isActive)
65 public:
66     explicit QTimer(QObject *parent = nullptr);
67     ~QTimer();
68 
isActive()69     inline bool isActive() const { return id >= 0; }
timerId()70     int timerId() const { return id; }
71 
72     void setInterval(int msec);
interval()73     int interval() const { return inter; }
74 
75     int remainingTime() const;
76 
setTimerType(Qt::TimerType atype)77     void setTimerType(Qt::TimerType atype) { this->type = atype; }
timerType()78     Qt::TimerType timerType() const { return Qt::TimerType(type); }
79 
80     inline void setSingleShot(bool singleShot);
isSingleShot()81     inline bool isSingleShot() const { return single; }
82 
83     static void singleShot(int msec, const QObject *receiver, const char *member);
84     static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member);
85 
86 #ifdef Q_CLANG_QDOC
87     template<typename PointerToMemberFunction>
88     static void singleShot(int msec, const QObject *receiver, PointerToMemberFunction method);
89     template<typename PointerToMemberFunction>
90     static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method);
91     template<typename Functor>
92     static void singleShot(int msec, Functor functor);
93     template<typename Functor>
94     static void singleShot(int msec, Qt::TimerType timerType, Functor functor);
95     template<typename Functor, int>
96     static void singleShot(int msec, const QObject *context, Functor functor);
97     template<typename Functor, int>
98     static void singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor);
99     template <typename Functor>
100     QMetaObject::Connection callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
101     template <typename Functor>
102     QMetaObject::Connection callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
103     template <typename MemberFunction>
104     QMetaObject::Connection callOnTimeout(const QObject *receiver, MemberFunction *slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
105 #else
106     // singleShot to a QObject slot
107     template <typename Duration, typename Func1>
singleShot(Duration interval,const typename QtPrivate::FunctionPointer<Func1>::Object * receiver,Func1 slot)108     static inline void singleShot(Duration interval, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot)
109     {
110         singleShot(interval, defaultTypeFor(interval), receiver, slot);
111     }
112     template <typename Duration, typename Func1>
singleShot(Duration interval,Qt::TimerType timerType,const typename QtPrivate::FunctionPointer<Func1>::Object * receiver,Func1 slot)113     static inline void singleShot(Duration interval, Qt::TimerType timerType, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver,
114                                   Func1 slot)
115     {
116         typedef QtPrivate::FunctionPointer<Func1> SlotType;
117 
118         //compilation error if the slot has arguments.
119         Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) == 0,
120                           "The slot must not have any arguments.");
121 
122         singleShotImpl(interval, timerType, receiver,
123                        new QtPrivate::QSlotObject<Func1, typename SlotType::Arguments, void>(slot));
124     }
125     // singleShot to a functor or function pointer (without context)
126     template <typename Duration, typename Func1>
127     static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
128                                           !std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval,Func1 slot)129             singleShot(Duration interval, Func1 slot)
130     {
131         singleShot(interval, defaultTypeFor(interval), nullptr, std::move(slot));
132     }
133     template <typename Duration, typename Func1>
134     static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
135                                           !std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval,Qt::TimerType timerType,Func1 slot)136             singleShot(Duration interval, Qt::TimerType timerType, Func1 slot)
137     {
138         singleShot(interval, timerType, nullptr, std::move(slot));
139     }
140     // singleShot to a functor or function pointer (with context)
141     template <typename Duration, typename Func1>
142     static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
143                                           !std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval,const QObject * context,Func1 slot)144             singleShot(Duration interval, const QObject *context, Func1 slot)
145     {
146         singleShot(interval, defaultTypeFor(interval), context, std::move(slot));
147     }
148     template <typename Duration, typename Func1>
149     static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
150                                           !std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval,Qt::TimerType timerType,const QObject * context,Func1 slot)151             singleShot(Duration interval, Qt::TimerType timerType, const QObject *context, Func1 slot)
152     {
153         //compilation error if the slot has arguments.
154         typedef QtPrivate::FunctionPointer<Func1> SlotType;
155         Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) <= 0,  "The slot must not have any arguments.");
156 
157         singleShotImpl(interval, timerType, context,
158                        new QtPrivate::QFunctorSlotObject<Func1, 0,
159                             typename QtPrivate::List_Left<void, 0>::Value, void>(std::move(slot)));
160     }
161 
162     template <typename ... Args>
callOnTimeout(Args &&...args)163     QMetaObject::Connection callOnTimeout(Args && ...args)
164     {
165         return QObject::connect(this, &QTimer::timeout, std::forward<Args>(args)... );
166     }
167 
168 #endif
169 
170 public Q_SLOTS:
171     void start(int msec);
172 
173     void start();
174     void stop();
175 
176 Q_SIGNALS:
177     void timeout(QPrivateSignal);
178 
179 public:
180 #if __has_include(<chrono>) || defined(Q_QDOC)
setInterval(std::chrono::milliseconds value)181     void setInterval(std::chrono::milliseconds value)
182     {
183         setInterval(int(value.count()));
184     }
185 
intervalAsDuration()186     std::chrono::milliseconds intervalAsDuration() const
187     {
188         return std::chrono::milliseconds(interval());
189     }
190 
remainingTimeAsDuration()191     std::chrono::milliseconds remainingTimeAsDuration() const
192     {
193         return std::chrono::milliseconds(remainingTime());
194     }
195 
singleShot(std::chrono::milliseconds value,const QObject * receiver,const char * member)196     static void singleShot(std::chrono::milliseconds value, const QObject *receiver, const char *member)
197     {
198         singleShot(int(value.count()), receiver, member);
199     }
200 
singleShot(std::chrono::milliseconds value,Qt::TimerType timerType,const QObject * receiver,const char * member)201     static void singleShot(std::chrono::milliseconds value, Qt::TimerType timerType, const QObject *receiver, const char *member)
202     {
203         singleShot(int(value.count()), timerType, receiver, member);
204     }
205 
start(std::chrono::milliseconds value)206     void start(std::chrono::milliseconds value)
207     {
208         start(int(value.count()));
209     }
210 #endif
211 
212 protected:
213     void timerEvent(QTimerEvent *) override;
214 
215 private:
Q_DISABLE_COPY(QTimer)216     Q_DISABLE_COPY(QTimer)
217 
218     inline int startTimer(int){ return -1;}
killTimer(int)219     inline void killTimer(int){}
220 
defaultTypeFor(int msecs)221     static Q_DECL_CONSTEXPR Qt::TimerType defaultTypeFor(int msecs) noexcept
222     { return msecs >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer; }
223     static void singleShotImpl(int msec, Qt::TimerType timerType,
224                                const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
225 
226 #if __has_include(<chrono>)
defaultTypeFor(std::chrono::milliseconds interval)227     static Qt::TimerType defaultTypeFor(std::chrono::milliseconds interval)
228     { return defaultTypeFor(int(interval.count())); }
229 
singleShotImpl(std::chrono::milliseconds interval,Qt::TimerType timerType,const QObject * receiver,QtPrivate::QSlotObjectBase * slotObj)230     static void singleShotImpl(std::chrono::milliseconds interval, Qt::TimerType timerType,
231                                const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj)
232     {
233         singleShotImpl(int(interval.count()),
234                        timerType, receiver, slotObj);
235     }
236 #endif
237 
238     int id, inter, del;
239     uint single : 1;
240     uint nulltimer : 1;
241     uint type : 2;
242     // reserved : 28
243 };
244 
setSingleShot(bool asingleShot)245 inline void QTimer::setSingleShot(bool asingleShot) { single = asingleShot; }
246 
247 QT_END_NAMESPACE
248 
249 #endif // QT_NO_QOBJECT
250 
251 #endif // QTIMER_H
252