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