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