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