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