1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#ifndef QOBJECT_H
42#define QOBJECT_H
43
44#ifndef QT_NO_QOBJECT
45
46#include <QtCore/qobjectdefs.h>
47#include <QtCore/qstring.h>
48#include <QtCore/qbytearray.h>
49#include <QtCore/qlist.h>
50#ifdef QT_INCLUDE_COMPAT
51#include <QtCore/qcoreevent.h>
52#endif
53#include <QtCore/qscopedpointer.h>
54#include <QtCore/qmetatype.h>
55
56#include <QtCore/qobject_impl.h>
57
58#if QT_HAS_INCLUDE(<chrono>)
59# include <chrono>
60#endif
61
62QT_BEGIN_NAMESPACE
63
64
65class QEvent;
66class QTimerEvent;
67class QChildEvent;
68struct QMetaObject;
69class QVariant;
70class QObjectPrivate;
71class QObject;
72class QThread;
73class QWidget;
74#ifndef QT_NO_REGEXP
75class QRegExp;
76#endif
77#ifndef QT_NO_REGULAREXPRESSION
78class QRegularExpression;
79#endif
80#ifndef QT_NO_USERDATA
81class QObjectUserData;
82#endif
83struct QDynamicMetaObjectData;
84
85typedef QList<QObject*> QObjectList;
86
87Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name,
88 const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
89Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegExp &re,
90 const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
91Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
92 const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
93Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options);
94
95class Q_CORE_EXPORT QObjectData {
96public:
97 virtual ~QObjectData() = 0;
98 QObject *q_ptr;
99 QObject *parent;
100 QObjectList children;
101
102 uint isWidget : 1;
103 uint blockSig : 1;
104 uint wasDeleted : 1;
105 uint isDeletingChildren : 1;
106 uint sendChildEvents : 1;
107 uint receiveChildEvents : 1;
108 uint isWindow : 1; //for QWindow
109 uint unused : 25;
110 int postedEvents;
111 QDynamicMetaObjectData *metaObject;
112 QMetaObject *dynamicMetaObject() const;
113};
114
115
116class Q_CORE_EXPORT QObject
117{
118 Q_OBJECT
119 Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)
120 Q_DECLARE_PRIVATE(QObject)
121
122public:
123 Q_INVOKABLE explicit QObject(QObject *parent=nullptr);
124 virtual ~QObject();
125
126 virtual bool event(QEvent *event);
127 virtual bool eventFilter(QObject *watched, QEvent *event);
128
129#ifdef Q_QDOC
130 static QString tr(const char *sourceText, const char *comment = nullptr, int n = -1);
131 static QString trUtf8(const char *sourceText, const char *comment = nullptr, int n = -1);
132 virtual const QMetaObject *metaObject() const;
133 static const QMetaObject staticMetaObject;
134#endif
135#ifdef QT_NO_TRANSLATION
136 static QString tr(const char *sourceText, const char * = nullptr, int = -1)
137 { return QString::fromUtf8(sourceText); }
138#if QT_DEPRECATED_SINCE(5, 0)
139 QT_DEPRECATED static QString trUtf8(const char *sourceText, const char * = nullptr, int = -1)
140 { return QString::fromUtf8(sourceText); }
141#endif
142#endif //QT_NO_TRANSLATION
143
144 QString objectName() const;
145 void setObjectName(const QString &name);
146
147 inline bool isWidgetType() const { return d_ptr->isWidget; }
148 inline bool isWindowType() const { return d_ptr->isWindow; }
149
150 inline bool signalsBlocked() const Q_DECL_NOTHROW { return d_ptr->blockSig; }
151 bool blockSignals(bool b) Q_DECL_NOTHROW;
152
153 QThread *thread() const;
154 void moveToThread(QThread *thread);
155
156 int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);
157#if QT_HAS_INCLUDE(<chrono>) || defined(Q_QDOC)
158 Q_ALWAYS_INLINE
159 int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer)
160 {
161 return startTimer(int(time.count()), timerType);
162 }
163#endif
164 void killTimer(int id);
165
166 template<typename T>
167 inline T findChild(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
168 {
169 typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
170 return static_cast<T>(qt_qFindChild_helper(this, aName, ObjType::staticMetaObject, options));
171 }
172
173 template<typename T>
174 inline QList<T> findChildren(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
175 {
176 typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
177 QList<T> list;
178 qt_qFindChildren_helper(this, aName, ObjType::staticMetaObject,
179 reinterpret_cast<QList<void *> *>(&list), options);
180 return list;
181 }
182
183#ifndef QT_NO_REGEXP
184 template<typename T>
185 inline QList<T> findChildren(const QRegExp &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
186 {
187 typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
188 QList<T> list;
189 qt_qFindChildren_helper(this, re, ObjType::staticMetaObject,
190 reinterpret_cast<QList<void *> *>(&list), options);
191 return list;
192 }
193#endif
194
195#ifndef QT_NO_REGULAREXPRESSION
196 template<typename T>
197 inline QList<T> findChildren(const QRegularExpression &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
198 {
199 typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
200 QList<T> list;
201 qt_qFindChildren_helper(this, re, ObjType::staticMetaObject,
202 reinterpret_cast<QList<void *> *>(&list), options);
203 return list;
204 }
205#endif
206
207 inline const QObjectList &children() const { return d_ptr->children; }
208
209 void setParent(QObject *parent);
210 void installEventFilter(QObject *filterObj);
211 void removeEventFilter(QObject *obj);
212
213 static QMetaObject::Connection connect(const QObject *sender, const char *signal,
214 const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);
215
216 static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
217 const QObject *receiver, const QMetaMethod &method,
218 Qt::ConnectionType type = Qt::AutoConnection);
219
220 inline QMetaObject::Connection connect(const QObject *sender, const char *signal,
221 const char *member, Qt::ConnectionType type = Qt::AutoConnection) const;
222
223#ifdef Q_QDOC
224 template<typename PointerToMemberFunction>
225 static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection);
226 template<typename PointerToMemberFunction, typename Functor>
227 static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor);
228 template<typename PointerToMemberFunction, typename Functor>
229 static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection);
230#else
231 //Connect a signal to a pointer to qobject member function
232 template <typename Func1, typename Func2>
233 static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
234 const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
235 Qt::ConnectionType type = Qt::AutoConnection)
236 {
237 typedef QtPrivate::FunctionPointer<Func1> SignalType;
238 typedef QtPrivate::FunctionPointer<Func2> SlotType;
239
240 Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
241 "No Q_OBJECT in the class with the signal");
242
243 //compilation error if the arguments does not match.
244 Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
245 "The slot requires more arguments than the signal provides.");
246 Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
247 "Signal and slot arguments are not compatible.");
248 Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
249 "Return type of the slot is not compatible with the return type of the signal.");
250
251 const int *types = nullptr;
252 if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
253 types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
254
255 return connectImpl(sender, reinterpret_cast<void **>(&signal),
256 receiver, reinterpret_cast<void **>(&slot),
257 new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
258 typename SignalType::ReturnType>(slot),
259 type, types, &SignalType::Object::staticMetaObject);
260 }
261
262 //connect to a function pointer (not a member)
263 template <typename Func1, typename Func2>
264 static inline typename std::enable_if<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0, QMetaObject::Connection>::type
265 connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
266 {
267 return connect(sender, signal, sender, slot, Qt::DirectConnection);
268 }
269
270 //connect to a function pointer (not a member)
271 template <typename Func1, typename Func2>
272 static inline typename std::enable_if<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0 &&
273 !QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction, QMetaObject::Connection>::type
274 connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
275 Qt::ConnectionType type = Qt::AutoConnection)
276 {
277 typedef QtPrivate::FunctionPointer<Func1> SignalType;
278 typedef QtPrivate::FunctionPointer<Func2> SlotType;
279
280 Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
281 "No Q_OBJECT in the class with the signal");
282
283 //compilation error if the arguments does not match.
284 Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
285 "The slot requires more arguments than the signal provides.");
286 Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
287 "Signal and slot arguments are not compatible.");
288 Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
289 "Return type of the slot is not compatible with the return type of the signal.");
290
291 const int *types = nullptr;
292 if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
293 types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
294
295 return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
296 new QtPrivate::QStaticSlotObject<Func2,
297 typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
298 typename SignalType::ReturnType>(slot),
299 type, types, &SignalType::Object::staticMetaObject);
300 }
301
302 //connect to a functor
303 template <typename Func1, typename Func2>
304 static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type
305 connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
306 {
307 return connect(sender, signal, sender, std::move(slot), Qt::DirectConnection);
308 }
309
310 //connect to a functor, with a "context" object defining in which event loop is going to be executed
311 template <typename Func1, typename Func2>
312 static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type
313 connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
314 Qt::ConnectionType type = Qt::AutoConnection)
315 {
316 typedef QtPrivate::FunctionPointer<Func1> SignalType;
317 const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value;
318
319 Q_STATIC_ASSERT_X((FunctorArgumentCount >= 0),
320 "Signal and slot arguments are not compatible.");
321 const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
322 typedef typename QtPrivate::FunctorReturnType<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType;
323
324 Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<SlotReturnType, typename SignalType::ReturnType>::value),
325 "Return type of the slot is not compatible with the return type of the signal.");
326
327 Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
328 "No Q_OBJECT in the class with the signal");
329
330 const int *types = nullptr;
331 if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
332 types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
333
334 return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
335 new QtPrivate::QFunctorSlotObject<Func2, SlotArgumentCount,
336 typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value,
337 typename SignalType::ReturnType>(std::move(slot)),
338 type, types, &SignalType::Object::staticMetaObject);
339 }
340#endif //Q_QDOC
341
342 static bool disconnect(const QObject *sender, const char *signal,
343 const QObject *receiver, const char *member);
344 static bool disconnect(const QObject *sender, const QMetaMethod &signal,
345 const QObject *receiver, const QMetaMethod &member);
346 inline bool disconnect(const char *signal = nullptr,
347 const QObject *receiver = nullptr, const char *member = nullptr) const
348 { return disconnect(this, signal, receiver, member); }
349 inline bool disconnect(const QObject *receiver, const char *member = nullptr) const
350 { return disconnect(this, nullptr, receiver, member); }
351 static bool disconnect(const QMetaObject::Connection &);
352
353#ifdef Q_QDOC
354 template<typename PointerToMemberFunction>
355 static bool disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method);
356#else
357 template <typename Func1, typename Func2>
358 static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
359 const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot)
360 {
361 typedef QtPrivate::FunctionPointer<Func1> SignalType;
362 typedef QtPrivate::FunctionPointer<Func2> SlotType;
363
364 Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
365 "No Q_OBJECT in the class with the signal");
366
367 //compilation error if the arguments does not match.
368 Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
369 "Signal and slot arguments are not compatible.");
370
371 return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, reinterpret_cast<void **>(&slot),
372 &SignalType::Object::staticMetaObject);
373 }
374 template <typename Func1>
375 static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
376 const QObject *receiver, void **zero)
377 {
378 // This is the overload for when one wish to disconnect a signal from any slot. (slot=nullptr)
379 // Since the function template parameter cannot be deduced from '0', we use a
380 // dummy void ** parameter that must be equal to 0
381 Q_ASSERT(!zero);
382 typedef QtPrivate::FunctionPointer<Func1> SignalType;
383 return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, zero,
384 &SignalType::Object::staticMetaObject);
385 }
386#endif //Q_QDOC
387
388
389#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
390 void dumpObjectTree(); // ### Qt 6: remove
391 void dumpObjectInfo(); // ### Qt 6: remove
392#endif
393 void dumpObjectTree() const;
394 void dumpObjectInfo() const;
395
396#ifndef QT_NO_PROPERTIES
397 bool setProperty(const char *name, const QVariant &value);
398 QVariant property(const char *name) const;
399 QList<QByteArray> dynamicPropertyNames() const;
400#endif // QT_NO_PROPERTIES
401
402#ifndef QT_NO_USERDATA
403 static uint registerUserData();
404 void setUserData(uint id, QObjectUserData* data);
405 QObjectUserData* userData(uint id) const;
406#endif // QT_NO_USERDATA
407
408Q_SIGNALS:
409 void destroyed(QObject * = nullptr);
410 void objectNameChanged(const QString &objectName, QPrivateSignal);
411
412public:
413 inline QObject *parent() const { return d_ptr->parent; }
414
415 inline bool inherits(const char *classname) const
416 { return const_cast<QObject *>(this)->qt_metacast(classname) != nullptr; }
417
418public Q_SLOTS:
419 void deleteLater();
420
421protected:
422 QObject *sender() const;
423 int senderSignalIndex() const;
424 int receivers(const char* signal) const;
425 bool isSignalConnected(const QMetaMethod &signal) const;
426
427 virtual void timerEvent(QTimerEvent *event);
428 virtual void childEvent(QChildEvent *event);
429 virtual void customEvent(QEvent *event);
430
431 virtual void connectNotify(const QMetaMethod &signal);
432 virtual void disconnectNotify(const QMetaMethod &signal);
433
434protected:
435 QObject(QObjectPrivate &dd, QObject *parent = nullptr);
436
437protected:
438 QScopedPointer<QObjectData> d_ptr;
439
440 static const QMetaObject staticQtMetaObject;
441 friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT;
442
443 friend struct QMetaObject;
444 friend struct QMetaObjectPrivate;
445 friend class QMetaCallEvent;
446 friend class QApplication;
447 friend class QApplicationPrivate;
448 friend class QCoreApplication;
449 friend class QCoreApplicationPrivate;
450 friend class QWidget;
451 friend class QThreadData;
452
453private:
454 Q_DISABLE_COPY(QObject)
455 Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
456
457private:
458 static QMetaObject::Connection connectImpl(const QObject *sender, void **signal,
459 const QObject *receiver, void **slotPtr,
460 QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type,
461 const int *types, const QMetaObject *senderMetaObject);
462
463 static bool disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot,
464 const QMetaObject *senderMetaObject);
465
466};
467
468inline QMetaObject::Connection QObject::connect(const QObject *asender, const char *asignal,
469 const char *amember, Qt::ConnectionType atype) const
470{ return connect(asender, asignal, this, amember, atype); }
471
472inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT
473{ return &QObject::staticQtMetaObject; }
474
475#ifndef QT_NO_USERDATA
476class Q_CORE_EXPORT QObjectUserData {
477public:
478 virtual ~QObjectUserData();
479};
480#endif
481
482#ifdef Q_QDOC
483T qFindChild(const QObject *o, const QString &name = QString());
484QList<T> qFindChildren(const QObject *oobj, const QString &name = QString());
485QList<T> qFindChildren(const QObject *o, const QRegExp &re);
486#endif
487#if QT_DEPRECATED_SINCE(5, 0)
488template<typename T>
489inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString())
490{ return o->findChild<T>(name); }
491
492template<typename T>
493inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QString &name = QString())
494{
495 return o->findChildren<T>(name);
496}
497
498#ifndef QT_NO_REGEXP
499template<typename T>
500inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QRegExp &re)
501{
502 return o->findChildren<T>(re);
503}
504#endif
505
506#endif //QT_DEPRECATED
507
508template <class T>
509inline T qobject_cast(QObject *object)
510{
511 typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
512 Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
513 "qobject_cast requires the type to have a Q_OBJECT macro");
514 return static_cast<T>(ObjType::staticMetaObject.cast(object));
515}
516
517template <class T>
518inline T qobject_cast(const QObject *object)
519{
520 typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
521 Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
522 "qobject_cast requires the type to have a Q_OBJECT macro");
523 return static_cast<T>(ObjType::staticMetaObject.cast(object));
524}
525
526
527template <class T> inline const char * qobject_interface_iid()
528{ return nullptr; }
529
530#ifndef Q_MOC_RUN
531# define Q_DECLARE_INTERFACE(IFace, IId) \
532 template <> inline const char *qobject_interface_iid<IFace *>() \
533 { return IId; } \
534 template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
535 { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : nullptr)); } \
536 template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
537 { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : nullptr)); }
538#endif // Q_MOC_RUN
539
540#ifndef QT_NO_DEBUG_STREAM
541Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
542#endif
543
544class QSignalBlocker
545{
546public:
547 inline explicit QSignalBlocker(QObject *o) Q_DECL_NOTHROW;
548 inline explicit QSignalBlocker(QObject &o) Q_DECL_NOTHROW;
549 inline ~QSignalBlocker();
550
551#ifdef Q_COMPILER_RVALUE_REFS
552 inline QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW;
553 inline QSignalBlocker &operator=(QSignalBlocker &&other) Q_DECL_NOTHROW;
554#endif
555
556 inline void reblock() Q_DECL_NOTHROW;
557 inline void unblock() Q_DECL_NOTHROW;
558private:
559 Q_DISABLE_COPY(QSignalBlocker)
560 QObject * m_o;
561 bool m_blocked;
562 bool m_inhibited;
563};
564
565QSignalBlocker::QSignalBlocker(QObject *o) Q_DECL_NOTHROW
566 : m_o(o),
567 m_blocked(o && o->blockSignals(true)),
568 m_inhibited(false)
569{}
570
571QSignalBlocker::QSignalBlocker(QObject &o) Q_DECL_NOTHROW
572 : m_o(&o),
573 m_blocked(o.blockSignals(true)),
574 m_inhibited(false)
575{}
576
577#ifdef Q_COMPILER_RVALUE_REFS
578QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW
579 : m_o(other.m_o),
580 m_blocked(other.m_blocked),
581 m_inhibited(other.m_inhibited)
582{
583 other.m_o = nullptr;
584}
585
586QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW
587{
588 if (this != &other) {
589 // if both *this and other block the same object's signals:
590 // unblock *this iff our dtor would unblock, but other's wouldn't
591 if (m_o != other.m_o || (!m_inhibited && other.m_inhibited))
592 unblock();
593 m_o = other.m_o;
594 m_blocked = other.m_blocked;
595 m_inhibited = other.m_inhibited;
596 // disable other:
597 other.m_o = nullptr;
598 }
599 return *this;
600}
601#endif
602
603QSignalBlocker::~QSignalBlocker()
604{
605 if (m_o && !m_inhibited)
606 m_o->blockSignals(m_blocked);
607}
608
609void QSignalBlocker::reblock() Q_DECL_NOTHROW
610{
611 if (m_o) m_o->blockSignals(true);
612 m_inhibited = false;
613}
614
615void QSignalBlocker::unblock() Q_DECL_NOTHROW
616{
617 if (m_o) m_o->blockSignals(m_blocked);
618 m_inhibited = true;
619}
620
621namespace QtPrivate {
622 inline QObject & deref_for_methodcall(QObject &o) { return o; }
623 inline QObject & deref_for_methodcall(QObject *o) { return *o; }
624}
625#define Q_SET_OBJECT_NAME(obj) QT_PREPEND_NAMESPACE(QtPrivate)::deref_for_methodcall(obj).setObjectName(QLatin1String(#obj))
626
627QT_END_NAMESPACE
628
629#endif
630
631#endif // QOBJECT_H
632