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