1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
6 ** Contact: https://www.qt.io/licensing/
7 **
8 ** This file is part of the QtCore module of the Qt Toolkit.
9 **
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** Commercial License Usage
12 ** Licensees holding valid commercial Qt licenses may use this file in
13 ** accordance with the commercial license agreement provided with the
14 ** Software or, alternatively, in accordance with the terms contained in
15 ** a written agreement between you and The Qt Company. For licensing terms
16 ** and conditions see https://www.qt.io/terms-conditions. For further
17 ** information use the contact form at https://www.qt.io/contact-us.
18 **
19 ** GNU Lesser General Public License Usage
20 ** Alternatively, this file may be used under the terms of the GNU Lesser
21 ** General Public License version 3 as published by the Free Software
22 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
23 ** packaging of this file. Please review the following information to
24 ** ensure the GNU Lesser General Public License version 3 requirements
25 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26 **
27 ** GNU General Public License Usage
28 ** Alternatively, this file may be used under the terms of the GNU
29 ** General Public License version 2.0 or (at your option) the GNU General
30 ** Public license version 3 or any later version approved by the KDE Free
31 ** Qt Foundation. The licenses are as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33 ** included in the packaging of this file. Please review the following
34 ** information to ensure the GNU General Public License requirements will
35 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36 ** https://www.gnu.org/licenses/gpl-3.0.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qobject.h"
43 #include "qobject_p.h"
44 #include "qmetaobject_p.h"
45 
46 #include "qabstracteventdispatcher.h"
47 #include "qabstracteventdispatcher_p.h"
48 #include "qcoreapplication.h"
49 #include "qcoreapplication_p.h"
50 #include "qloggingcategory.h"
51 #include "qvariant.h"
52 #include "qmetaobject.h"
53 #include <qregexp.h>
54 #if QT_CONFIG(regularexpression)
55 #  include <qregularexpression.h>
56 #endif
57 #include <qthread.h>
58 #include <private/qthread_p.h>
59 #include <qdebug.h>
60 #include <qpair.h>
61 #include <qvarlengtharray.h>
62 #include <qscopeguard.h>
63 #include <qset.h>
64 #if QT_CONFIG(thread)
65 #include <qsemaphore.h>
66 #endif
67 #include <qsharedpointer.h>
68 
69 #include <private/qorderedmutexlocker_p.h>
70 #include <private/qhooks_p.h>
71 #include <qtcore_tracepoints_p.h>
72 
73 #include <new>
74 
75 #include <ctype.h>
76 #include <limits.h>
77 
78 QT_BEGIN_NAMESPACE
79 
80 static int DIRECT_CONNECTION_ONLY = 0;
81 
82 Q_LOGGING_CATEGORY(lcConnections, "qt.core.qmetaobject.connectslotsbyname")
83 
84 Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
85 
qt_register_signal_spy_callbacks(QSignalSpyCallbackSet * callback_set)86 void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set)
87 {
88     qt_signal_spy_callback_set.storeRelease(callback_set);
89 }
90 
~QDynamicMetaObjectData()91 QDynamicMetaObjectData::~QDynamicMetaObjectData()
92 {
93 }
94 
~QAbstractDynamicMetaObject()95 QAbstractDynamicMetaObject::~QAbstractDynamicMetaObject()
96 {
97 }
98 
queuedConnectionTypes(const QList<QByteArray> & typeNames)99 static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
100 {
101     int *types = new int [typeNames.count() + 1];
102     Q_CHECK_PTR(types);
103     for (int i = 0; i < typeNames.count(); ++i) {
104         const QByteArray typeName = typeNames.at(i);
105         if (typeName.endsWith('*'))
106             types[i] = QMetaType::VoidStar;
107         else
108             types[i] = QMetaType::type(typeName);
109 
110         if (!types[i]) {
111             qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
112                      "(Make sure '%s' is registered using qRegisterMetaType().)",
113                      typeName.constData(), typeName.constData());
114             delete [] types;
115             return nullptr;
116         }
117     }
118     types[typeNames.count()] = 0;
119 
120     return types;
121 }
122 
queuedConnectionTypes(const QArgumentType * argumentTypes,int argc)123 static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
124 {
125     QScopedArrayPointer<int> types(new int [argc + 1]);
126     for (int i = 0; i < argc; ++i) {
127         const QArgumentType &type = argumentTypes[i];
128         if (type.type())
129             types[i] = type.type();
130         else if (type.name().endsWith('*'))
131             types[i] = QMetaType::VoidStar;
132         else
133             types[i] = QMetaType::type(type.name());
134 
135         if (!types[i]) {
136             qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
137                      "(Make sure '%s' is registered using qRegisterMetaType().)",
138                      type.name().constData(), type.name().constData());
139             return nullptr;
140         }
141     }
142     types[argc] = 0;
143 
144     return types.take();
145 }
146 
147 static QBasicMutex _q_ObjectMutexPool[131];
148 
149 /**
150  * \internal
151  * mutex to be locked when accessing the connection lists or the senders list
152  */
signalSlotLock(const QObject * o)153 static inline QBasicMutex *signalSlotLock(const QObject *o)
154 {
155     return &_q_ObjectMutexPool[uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)];
156 }
157 
158 #if QT_VERSION < 0x60000
qt_addObject(QObject *)159 extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
160 {}
161 
qt_removeObject(QObject *)162 extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
163 {}
164 #endif
165 
166 void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = nullptr;
167 void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = nullptr;
168 void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = nullptr;
169 void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = nullptr;
170 int  (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
171 bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
172 void (*QAbstractDeclarativeData::setWidgetParent)(QObject *, QObject *) = nullptr;
173 
174 /*!
175     \fn QObjectData::QObjectData()
176     \internal
177  */
178 
179 
~QObjectData()180 QObjectData::~QObjectData() {}
181 
dynamicMetaObject() const182 QMetaObject *QObjectData::dynamicMetaObject() const
183 {
184     return metaObject->toDynamicMetaObject(q_ptr);
185 }
186 
QObjectPrivate(int version)187 QObjectPrivate::QObjectPrivate(int version)
188     : threadData(nullptr), currentChildBeingDeleted(nullptr)
189 {
190     checkForIncompatibleLibraryVersion(version);
191 
192     // QObjectData initialization
193     q_ptr = nullptr;
194     parent = nullptr;                           // no parent yet. It is set by setParent()
195     isWidget = false;                           // assume not a widget object
196     blockSig = false;                           // not blocking signals
197     wasDeleted = false;                         // double-delete catcher
198     isDeletingChildren = false;                 // set by deleteChildren()
199     sendChildEvents = true;                     // if we should send ChildAdded and ChildRemoved events to parent
200     receiveChildEvents = true;
201     postedEvents = 0;
202     extraData = nullptr;
203     metaObject = nullptr;
204     isWindow = false;
205     deleteLaterCalled = false;
206 }
207 
~QObjectPrivate()208 QObjectPrivate::~QObjectPrivate()
209 {
210     auto thisThreadData = threadData.loadRelaxed();
211     if (extraData && !extraData->runningTimers.isEmpty()) {
212         if (Q_LIKELY(thisThreadData->thread.loadAcquire() == QThread::currentThread())) {
213             // unregister pending timers
214             if (thisThreadData->hasEventDispatcher())
215                 thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr);
216 
217             // release the timer ids back to the pool
218             for (int i = 0; i < extraData->runningTimers.size(); ++i)
219                 QAbstractEventDispatcherPrivate::releaseTimerId(extraData->runningTimers.at(i));
220         } else {
221             qWarning("QObject::~QObject: Timers cannot be stopped from another thread");
222         }
223     }
224 
225     if (postedEvents)
226         QCoreApplication::removePostedEvents(q_ptr, 0);
227 
228     thisThreadData->deref();
229 
230     if (metaObject) metaObject->objectDestroyed(q_ptr);
231 
232 #ifndef QT_NO_USERDATA
233     if (extraData)
234         qDeleteAll(extraData->userData);
235 #endif
236     delete extraData;
237 }
238 
239 /*!
240   \internal
241   For a given metaobject, compute the signal offset, and the method offset (including signals)
242 */
computeOffsets(const QMetaObject * metaobject,int * signalOffset,int * methodOffset)243 static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
244 {
245     *signalOffset = *methodOffset = 0;
246     const QMetaObject *m = metaobject->d.superdata;
247     while (m) {
248         const QMetaObjectPrivate *d = QMetaObjectPrivate::get(m);
249         *methodOffset += d->methodCount;
250         Q_ASSERT(d->revision >= 4);
251         *signalOffset += d->signalCount;
252         m = m->d.superdata;
253     }
254 }
255 
256 // Used by QAccessibleWidget
isSender(const QObject * receiver,const char * signal) const257 bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
258 {
259     Q_Q(const QObject);
260     int signal_index = signalIndex(signal);
261     ConnectionData *cd = connections.loadRelaxed();
262     if (signal_index < 0 || !cd)
263         return false;
264     QBasicMutexLocker locker(signalSlotLock(q));
265     if (signal_index < cd->signalVectorCount()) {
266         const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
267 
268         while (c) {
269             if (c->receiver.loadRelaxed() == receiver)
270                 return true;
271             c = c->nextConnectionList.loadRelaxed();
272         }
273     }
274     return false;
275 }
276 
277 // Used by QAccessibleWidget
receiverList(const char * signal) const278 QObjectList QObjectPrivate::receiverList(const char *signal) const
279 {
280     QObjectList returnValue;
281     int signal_index = signalIndex(signal);
282     ConnectionData *cd = connections.loadRelaxed();
283     if (signal_index < 0 || !cd)
284         return returnValue;
285     if (signal_index < cd->signalVectorCount()) {
286         const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
287 
288         while (c) {
289             QObject *r = c->receiver.loadRelaxed();
290             if (r)
291                 returnValue << r;
292             c = c->nextConnectionList.loadRelaxed();
293         }
294     }
295     return returnValue;
296 }
297 
298 // Used by QAccessibleWidget
senderList() const299 QObjectList QObjectPrivate::senderList() const
300 {
301     QObjectList returnValue;
302     ConnectionData *cd = connections.loadRelaxed();
303     if (cd) {
304         QBasicMutexLocker locker(signalSlotLock(q_func()));
305         for (Connection *c = cd->senders; c; c = c->next)
306             returnValue << c->sender;
307     }
308     return returnValue;
309 }
310 
311 /*!
312   \internal
313   Add the connection \a c to the list of connections of the sender's object
314   for the specified \a signal
315 
316   The signalSlotLock() of the sender and receiver must be locked while calling
317   this function
318 
319   Will also add the connection in the sender's list of the receiver.
320  */
addConnection(int signal,Connection * c)321 void QObjectPrivate::addConnection(int signal, Connection *c)
322 {
323     Q_ASSERT(c->sender == q_ptr);
324     ensureConnectionData();
325     ConnectionData *cd = connections.loadRelaxed();
326     cd->resizeSignalVector(signal + 1);
327 
328     ConnectionList &connectionList = cd->connectionsForSignal(signal);
329     if (connectionList.last.loadRelaxed()) {
330         Q_ASSERT(connectionList.last.loadRelaxed()->receiver.loadRelaxed());
331         connectionList.last.loadRelaxed()->nextConnectionList.storeRelaxed(c);
332     } else {
333         connectionList.first.storeRelaxed(c);
334     }
335     c->id = ++cd->currentConnectionId;
336     c->prevConnectionList = connectionList.last.loadRelaxed();
337     connectionList.last.storeRelaxed(c);
338 
339     QObjectPrivate *rd = QObjectPrivate::get(c->receiver.loadRelaxed());
340     rd->ensureConnectionData();
341 
342     c->prev = &(rd->connections.loadRelaxed()->senders);
343     c->next = *c->prev;
344     *c->prev = c;
345     if (c->next)
346         c->next->prev = &c->next;
347 }
348 
removeConnection(QObjectPrivate::Connection * c)349 void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection *c)
350 {
351     Q_ASSERT(c->receiver.loadRelaxed());
352     ConnectionList &connections = signalVector.loadRelaxed()->at(c->signal_index);
353     c->receiver.storeRelaxed(nullptr);
354     QThreadData *td = c->receiverThreadData.loadRelaxed();
355     if (td)
356         td->deref();
357     c->receiverThreadData.storeRelaxed(nullptr);
358 
359 #ifndef QT_NO_DEBUG
360     bool found = false;
361     for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
362         if (cc == c) {
363             found = true;
364             break;
365         }
366     }
367     Q_ASSERT(found);
368 #endif
369 
370     // remove from the senders linked list
371     *c->prev = c->next;
372     if (c->next)
373         c->next->prev = c->prev;
374     c->prev = nullptr;
375 
376     if (connections.first.loadRelaxed() == c)
377         connections.first.storeRelaxed(c->nextConnectionList.loadRelaxed());
378     if (connections.last.loadRelaxed() == c)
379         connections.last.storeRelaxed(c->prevConnectionList);
380     Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).first.loadRelaxed() != c);
381     Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).last.loadRelaxed() != c);
382 
383     // keep c->nextConnectionList intact, as it might still get accessed by activate
384     Connection *n = c->nextConnectionList.loadRelaxed();
385     if (n)
386         n->prevConnectionList = c->prevConnectionList;
387     if (c->prevConnectionList)
388         c->prevConnectionList->nextConnectionList.storeRelaxed(n);
389     c->prevConnectionList = nullptr;
390 
391     Q_ASSERT(c != orphaned.loadRelaxed());
392     // add c to orphanedConnections
393     c->nextInOrphanList = orphaned.loadRelaxed();
394     orphaned.storeRelaxed(c);
395 
396 #ifndef QT_NO_DEBUG
397     found = false;
398     for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
399         if (cc == c) {
400             found = true;
401             break;
402         }
403     }
404     Q_ASSERT(!found);
405 #endif
406 
407 }
408 
cleanOrphanedConnectionsImpl(QObject * sender)409 void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender)
410 {
411     ConnectionOrSignalVector *c = nullptr;
412     {
413         QBasicMutexLocker l(signalSlotLock(sender));
414         if (ref.loadAcquire() > 1)
415             return;
416 
417         // Since ref == 1, no activate() is in process since we locked the mutex. That implies,
418         // that nothing can reference the orphaned connection objects anymore and they can
419         // be safely deleted
420         c = orphaned.loadRelaxed();
421         orphaned.storeRelaxed(nullptr);
422     }
423     deleteOrphaned(c);
424 }
425 
deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector * o)426 void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o)
427 {
428     while (o) {
429         QObjectPrivate::ConnectionOrSignalVector *next = nullptr;
430         if (SignalVector *v = ConnectionOrSignalVector::asSignalVector(o)) {
431             next = v->nextInOrphanList;
432             free(v);
433         } else {
434             QObjectPrivate::Connection *c = static_cast<Connection *>(o);
435             next = c->nextInOrphanList;
436             Q_ASSERT(!c->receiver.loadRelaxed());
437             Q_ASSERT(!c->prev);
438             c->freeSlotObject();
439             c->deref();
440         }
441         o = next;
442     }
443 }
444 
445 /*! \internal
446 
447   Returns \c true if the signal with index \a signal_index from object \a sender is connected.
448 
449   \a signal_index must be the index returned by QObjectPrivate::signalIndex;
450 */
isSignalConnected(uint signalIndex,bool checkDeclarative) const451 bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) const
452 {
453     if (checkDeclarative && isDeclarativeSignalConnected(signalIndex))
454         return true;
455 
456     ConnectionData *cd = connections.loadRelaxed();
457     if (!cd)
458         return false;
459     SignalVector *signalVector = cd->signalVector.loadRelaxed();
460     if (!signalVector)
461         return false;
462 
463     if (signalVector->at(-1).first.loadRelaxed())
464         return true;
465 
466     if (signalIndex < uint(cd->signalVectorCount())) {
467         const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.loadRelaxed();
468         while (c) {
469             if (c->receiver.loadRelaxed())
470                 return true;
471             c = c->nextConnectionList.loadRelaxed();
472         }
473     }
474     return false;
475 }
476 
maybeSignalConnected(uint signalIndex) const477 bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
478 {
479     ConnectionData *cd = connections.loadRelaxed();
480     if (!cd)
481         return false;
482     SignalVector *signalVector = cd->signalVector.loadRelaxed();
483     if (!signalVector)
484         return false;
485 
486     if (signalVector->at(-1).first.loadAcquire())
487         return true;
488 
489     if (signalIndex < uint(cd->signalVectorCount())) {
490         const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.loadAcquire();
491         return c != nullptr;
492     }
493     return false;
494 }
495 
496 /*!
497     \internal
498  */
~QAbstractMetaCallEvent()499 QAbstractMetaCallEvent::~QAbstractMetaCallEvent()
500 {
501 #if QT_CONFIG(thread)
502     if (semaphore_)
503         semaphore_->release();
504 #endif
505 }
506 
507 /*!
508     \internal
509  */
allocArgs()510 inline void QMetaCallEvent::allocArgs()
511 {
512     if (!d.nargs_)
513         return;
514 
515     constexpr size_t each = sizeof(void*) + sizeof(int);
516     void *const memory = d.nargs_ * each > sizeof(prealloc_) ?
517         calloc(d.nargs_, each) : prealloc_;
518 
519     Q_CHECK_PTR(memory);
520     d.args_ = static_cast<void **>(memory);
521 }
522 
523 /*!
524     \internal
525 
526     Used for blocking queued connections, just passes \a args through without
527     allocating any memory.
528  */
QMetaCallEvent(ushort method_offset,ushort method_relative,QObjectPrivate::StaticMetaCallFunction callFunction,const QObject * sender,int signalId,void ** args,QSemaphore * semaphore)529 QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
530                                QObjectPrivate::StaticMetaCallFunction callFunction,
531                                const QObject *sender, int signalId,
532                                void **args, QSemaphore *semaphore)
533     : QAbstractMetaCallEvent(sender, signalId, semaphore),
534       d({nullptr, args, callFunction, 0, method_offset, method_relative}),
535       prealloc_()
536 {
537 }
538 
539 /*!
540     \internal
541 
542     Used for blocking queued connections, just passes \a args through without
543     allocating any memory.
544  */
QMetaCallEvent(QtPrivate::QSlotObjectBase * slotO,const QObject * sender,int signalId,void ** args,QSemaphore * semaphore)545 QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
546                                const QObject *sender, int signalId,
547                                void **args, QSemaphore *semaphore)
548     : QAbstractMetaCallEvent(sender, signalId, semaphore),
549       d({slotO, args, nullptr, 0, 0, ushort(-1)}),
550       prealloc_()
551 {
552     if (d.slotObj_)
553         d.slotObj_->ref();
554 }
555 
556 /*!
557     \internal
558 
559     Allocates memory for \a nargs; code creating an event needs to initialize
560     the void* and int arrays by accessing \a args() and \a types(), respectively.
561  */
QMetaCallEvent(ushort method_offset,ushort method_relative,QObjectPrivate::StaticMetaCallFunction callFunction,const QObject * sender,int signalId,int nargs)562 QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
563                                QObjectPrivate::StaticMetaCallFunction callFunction,
564                                const QObject *sender, int signalId,
565                                int nargs)
566     : QAbstractMetaCallEvent(sender, signalId),
567       d({nullptr, nullptr, callFunction, nargs, method_offset, method_relative}),
568       prealloc_()
569 {
570     allocArgs();
571 }
572 
573 /*!
574     \internal
575 
576     Allocates memory for \a nargs; code creating an event needs to initialize
577     the void* and int arrays by accessing \a args() and \a types(), respectively.
578  */
QMetaCallEvent(QtPrivate::QSlotObjectBase * slotO,const QObject * sender,int signalId,int nargs)579 QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
580                                const QObject *sender, int signalId,
581                                int nargs)
582     : QAbstractMetaCallEvent(sender, signalId),
583       d({slotO, nullptr, nullptr, nargs, 0, ushort(-1)}),
584       prealloc_()
585 {
586     if (d.slotObj_)
587         d.slotObj_->ref();
588     allocArgs();
589 }
590 
591 /*!
592     \internal
593  */
~QMetaCallEvent()594 QMetaCallEvent::~QMetaCallEvent()
595 {
596     if (d.nargs_) {
597         int *typeIDs = types();
598         for (int i = 0; i < d.nargs_; ++i) {
599             if (typeIDs[i] && d.args_[i])
600                 QMetaType::destroy(typeIDs[i], d.args_[i]);
601         }
602         if (reinterpret_cast<void*>(d.args_) != reinterpret_cast<void*>(prealloc_))
603             free(d.args_);
604     }
605     if (d.slotObj_)
606         d.slotObj_->destroyIfLastRef();
607 }
608 
609 /*!
610     \internal
611  */
placeMetaCall(QObject * object)612 void QMetaCallEvent::placeMetaCall(QObject *object)
613 {
614     if (d.slotObj_) {
615         d.slotObj_->call(object, d.args_);
616     } else if (d.callFunction_ && d.method_offset_ <= object->metaObject()->methodOffset()) {
617         d.callFunction_(object, QMetaObject::InvokeMetaMethod, d.method_relative_, d.args_);
618     } else {
619         QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod,
620                               d.method_offset_ + d.method_relative_, d.args_);
621     }
622 }
623 
624 /*!
625     \class QSignalBlocker
626     \brief Exception-safe wrapper around QObject::blockSignals().
627     \since 5.3
628     \ingroup objectmodel
629     \inmodule QtCore
630 
631     \reentrant
632 
633     QSignalBlocker can be used wherever you would otherwise use a
634     pair of calls to blockSignals(). It blocks signals in its
635     constructor and in the destructor it resets the state to what
636     it was before the constructor ran.
637 
638     \snippet code/src_corelib_kernel_qobject.cpp 53
639     is thus equivalent to
640     \snippet code/src_corelib_kernel_qobject.cpp 54
641 
642     except the code using QSignalBlocker is safe in the face of
643     exceptions.
644 
645     \sa QMutexLocker, QEventLoopLocker
646 */
647 
648 /*!
649     \fn QSignalBlocker::QSignalBlocker(QObject *object)
650 
651     Constructor. Calls \a{object}->blockSignals(true).
652 */
653 
654 /*!
655     \fn QSignalBlocker::QSignalBlocker(QObject &object)
656     \overload
657 
658     Calls \a{object}.blockSignals(true).
659 */
660 
661 /*!
662     \fn QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
663 
664     Move-constructs a signal blocker from \a other. \a other will have
665     a no-op destructor, while responsibility for restoring the
666     QObject::signalsBlocked() state is transferred to the new object.
667 */
668 
669 /*!
670     \fn QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other)
671 
672     Move-assigns this signal blocker from \a other. \a other will have
673     a no-op destructor, while responsibility for restoring the
674     QObject::signalsBlocked() state is transferred to this object.
675 
676     The object's signals this signal blocker was blocking prior to
677     being moved to, if any, are unblocked \e except in the case where
678     both instances block the same object's signals and \c *this is
679     unblocked while \a other is not, at the time of the move.
680 */
681 
682 /*!
683     \fn QSignalBlocker::~QSignalBlocker()
684 
685     Destructor. Restores the QObject::signalsBlocked() state to what it
686     was before the constructor ran, unless unblock() has been called
687     without a following reblock(), in which case it does nothing.
688 */
689 
690 /*!
691     \fn void QSignalBlocker::reblock()
692 
693     Re-blocks signals after a previous unblock().
694 
695     The numbers of reblock() and unblock() calls are not counted, so
696     every reblock() undoes any number of unblock() calls.
697 */
698 
699 /*!
700     \fn void QSignalBlocker::unblock()
701 
702     Temporarily restores the QObject::signalsBlocked() state to what
703     it was before this QSignalBlocker's constructor ran. To undo, use
704     reblock().
705 
706     The numbers of reblock() and unblock() calls are not counted, so
707     every unblock() undoes any number of reblock() calls.
708 */
709 
710 /*!
711     \class QObject
712     \inmodule QtCore
713     \brief The QObject class is the base class of all Qt objects.
714 
715     \ingroup objectmodel
716 
717     \reentrant
718 
719     QObject is the heart of the Qt \l{Object Model}. The central
720     feature in this model is a very powerful mechanism for seamless
721     object communication called \l{signals and slots}. You can
722     connect a signal to a slot with connect() and destroy the
723     connection with disconnect(). To avoid never ending notification
724     loops you can temporarily block signals with blockSignals(). The
725     protected functions connectNotify() and disconnectNotify() make
726     it possible to track connections.
727 
728     QObjects organize themselves in \l {Object Trees & Ownership}
729     {object trees}. When you create a QObject with another object as
730     parent, the object will automatically add itself to the parent's
731     children() list. The parent takes ownership of the object; i.e.,
732     it will automatically delete its children in its destructor. You
733     can look for an object by name and optionally type using
734     findChild() or findChildren().
735 
736     Every object has an objectName() and its class name can be found
737     via the corresponding metaObject() (see QMetaObject::className()).
738     You can determine whether the object's class inherits another
739     class in the QObject inheritance hierarchy by using the
740     inherits() function.
741 
742     When an object is deleted, it emits a destroyed() signal. You can
743     catch this signal to avoid dangling references to QObjects.
744 
745     QObjects can receive events through event() and filter the events
746     of other objects. See installEventFilter() and eventFilter() for
747     details. A convenience handler, childEvent(), can be reimplemented
748     to catch child events.
749 
750     Last but not least, QObject provides the basic timer support in
751     Qt; see QTimer for high-level support for timers.
752 
753     Notice that the Q_OBJECT macro is mandatory for any object that
754     implements signals, slots or properties. You also need to run the
755     \l{moc}{Meta Object Compiler} on the source file. We strongly
756     recommend the use of this macro in all subclasses of QObject
757     regardless of whether or not they actually use signals, slots and
758     properties, since failure to do so may lead certain functions to
759     exhibit strange behavior.
760 
761     All Qt widgets inherit QObject. The convenience function
762     isWidgetType() returns whether an object is actually a widget. It
763     is much faster than
764     \l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
765     \e{obj}->\l{inherits()}{inherits}("QWidget").
766 
767     Some QObject functions, e.g. children(), return a QObjectList.
768     QObjectList is a typedef for QList<QObject *>.
769 
770     \section1 Thread Affinity
771 
772     A QObject instance is said to have a \e{thread affinity}, or that
773     it \e{lives} in a certain thread. When a QObject receives a
774     \l{Qt::QueuedConnection}{queued signal} or a \l{The Event
775     System#Sending Events}{posted event}, the slot or event handler
776     will run in the thread that the object lives in.
777 
778     \note If a QObject has no thread affinity (that is, if thread()
779     returns zero), or if it lives in a thread that has no running event
780     loop, then it cannot receive queued signals or posted events.
781 
782     By default, a QObject lives in the thread in which it is created.
783     An object's thread affinity can be queried using thread() and
784     changed using moveToThread().
785 
786     All QObjects must live in the same thread as their parent. Consequently:
787 
788     \list
789     \li setParent() will fail if the two QObjects involved live in
790         different threads.
791     \li When a QObject is moved to another thread, all its children
792         will be automatically moved too.
793     \li moveToThread() will fail if the QObject has a parent.
794     \li If QObjects are created within QThread::run(), they cannot
795         become children of the QThread object because the QThread does
796         not live in the thread that calls QThread::run().
797     \endlist
798 
799     \note A QObject's member variables \e{do not} automatically become
800     its children. The parent-child relationship must be set by either
801     passing a pointer to the child's \l{QObject()}{constructor}, or by
802     calling setParent(). Without this step, the object's member variables
803     will remain in the old thread when moveToThread() is called.
804 
805     \target No copy constructor
806     \section1 No Copy Constructor or Assignment Operator
807 
808     QObject has neither a copy constructor nor an assignment operator.
809     This is by design. Actually, they are declared, but in a
810     \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
811     Qt classes derived from QObject (direct or indirect) use this
812     macro to declare their copy constructor and assignment operator to
813     be private. The reasoning is found in the discussion on
814     \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
815     Model} page.
816 
817     The main consequence is that you should use pointers to QObject
818     (or to your QObject subclass) where you might otherwise be tempted
819     to use your QObject subclass as a value. For example, without a
820     copy constructor, you can't use a subclass of QObject as the value
821     to be stored in one of the container classes. You must store
822     pointers.
823 
824     \section1 Auto-Connection
825 
826     Qt's meta-object system provides a mechanism to automatically connect
827     signals and slots between QObject subclasses and their children. As long
828     as objects are defined with suitable object names, and slots follow a
829     simple naming convention, this connection can be performed at run-time
830     by the QMetaObject::connectSlotsByName() function.
831 
832     \l uic generates code that invokes this function to enable
833     auto-connection to be performed between widgets on forms created
834     with \e{Qt Designer}. More information about using auto-connection with \e{Qt Designer} is
835     given in the \l{Using a Designer UI File in Your C++ Application} section of
836     the \e{Qt Designer} manual.
837 
838     \section1 Dynamic Properties
839 
840     From Qt 4.2, dynamic properties can be added to and removed from QObject
841     instances at run-time. Dynamic properties do not need to be declared at
842     compile-time, yet they provide the same advantages as static properties
843     and are manipulated using the same API - using property() to read them
844     and setProperty() to write them.
845 
846     From Qt 4.3, dynamic properties are supported by
847     \l{Qt Designer's Widget Editing Mode#The Property Editor}{Qt Designer},
848     and both standard Qt widgets and user-created forms can be given dynamic
849     properties.
850 
851     \section1 Internationalization (I18n)
852 
853     All QObject subclasses support Qt's translation features, making it possible
854     to translate an application's user interface into different languages.
855 
856     To make user-visible text translatable, it must be wrapped in calls to
857     the tr() function. This is explained in detail in the
858     \l{Writing Source Code for Translation} document.
859 
860     \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
861     \sa {Object Trees & Ownership}
862 */
863 
864 /*****************************************************************************
865   QObject member functions
866  *****************************************************************************/
867 
868 // check the constructor's parent thread argument
check_parent_thread(QObject * parent,QThreadData * parentThreadData,QThreadData * currentThreadData)869 static bool check_parent_thread(QObject *parent,
870                                 QThreadData *parentThreadData,
871                                 QThreadData *currentThreadData)
872 {
873     if (parent && parentThreadData != currentThreadData) {
874         QThread *parentThread = parentThreadData->thread.loadAcquire();
875         QThread *currentThread = currentThreadData->thread.loadAcquire();
876         qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
877                  "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
878                  parent->metaObject()->className(),
879                  parent,
880                  parentThread ? parentThread->metaObject()->className() : "QThread",
881                  parentThread,
882                  currentThread ? currentThread->metaObject()->className() : "QThread",
883                  currentThread);
884         return false;
885     }
886     return true;
887 }
888 
889 /*!
890     Constructs an object with parent object \a parent.
891 
892     The parent of an object may be viewed as the object's owner. For
893     instance, a \l{QDialog}{dialog box} is the parent of the \uicontrol{OK}
894     and \uicontrol{Cancel} buttons it contains.
895 
896     The destructor of a parent object destroys all child objects.
897 
898     Setting \a parent to \nullptr constructs an object with no parent. If the
899     object is a widget, it will become a top-level window.
900 
901     \sa parent(), findChild(), findChildren()
902 */
903 
QObject(QObject * parent)904 QObject::QObject(QObject *parent)
905     : QObject(*new QObjectPrivate, parent)
906 {
907 }
908 
909 /*!
910     \internal
911  */
QObject(QObjectPrivate & dd,QObject * parent)912 QObject::QObject(QObjectPrivate &dd, QObject *parent)
913     : d_ptr(&dd)
914 {
915     Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QObject to itself");
916 
917     Q_D(QObject);
918     d_ptr->q_ptr = this;
919     auto threadData = (parent && !parent->thread()) ? parent->d_func()->threadData.loadRelaxed() : QThreadData::current();
920     threadData->ref();
921     d->threadData.storeRelaxed(threadData);
922     if (parent) {
923         QT_TRY {
924             if (!check_parent_thread(parent, parent ? parent->d_func()->threadData.loadRelaxed() : nullptr, threadData))
925                 parent = nullptr;
926             if (d->isWidget) {
927                 if (parent) {
928                     d->parent = parent;
929                     d->parent->d_func()->children.append(this);
930                 }
931                 // no events sent here, this is done at the end of the QWidget constructor
932             } else {
933                 setParent(parent);
934             }
935         } QT_CATCH(...) {
936             threadData->deref();
937             QT_RETHROW;
938         }
939     }
940 #if QT_VERSION < 0x60000
941     qt_addObject(this);
942 #endif
943     if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
944         reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
945     Q_TRACE(QObject_ctor, this);
946 }
947 
948 /*!
949     Destroys the object, deleting all its child objects.
950 
951     All signals to and from the object are automatically disconnected, and
952     any pending posted events for the object are removed from the event
953     queue. However, it is often safer to use deleteLater() rather than
954     deleting a QObject subclass directly.
955 
956     \warning All child objects are deleted. If any of these objects
957     are on the stack or global, sooner or later your program will
958     crash. We do not recommend holding pointers to child objects from
959     outside the parent. If you still do, the destroyed() signal gives
960     you an opportunity to detect when an object is destroyed.
961 
962     \warning Deleting a QObject while pending events are waiting to
963     be delivered can cause a crash. You must not delete the QObject
964     directly if it exists in a different thread than the one currently
965     executing. Use deleteLater() instead, which will cause the event
966     loop to delete the object after all pending events have been
967     delivered to it.
968 
969     \sa deleteLater()
970 */
971 
~QObject()972 QObject::~QObject()
973 {
974     Q_D(QObject);
975     d->wasDeleted = true;
976     d->blockSig = 0; // unblock signals so we always emit destroyed()
977 
978     QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.loadRelaxed();
979     if (sharedRefcount) {
980         if (sharedRefcount->strongref.loadRelaxed() > 0) {
981             qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
982             // but continue deleting, it's too late to stop anyway
983         }
984 
985         // indicate to all QWeakPointers that this QObject has now been deleted
986         sharedRefcount->strongref.storeRelaxed(0);
987         if (!sharedRefcount->weakref.deref())
988             delete sharedRefcount;
989     }
990 
991     if (!d->isWidget && d->isSignalConnected(0)) {
992         emit destroyed(this);
993     }
994 
995     if (d->declarativeData) {
996         if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
997             if (QAbstractDeclarativeData::destroyed_qml1)
998                 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
999         } else {
1000             if (QAbstractDeclarativeData::destroyed)
1001                 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1002         }
1003     }
1004 
1005     QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
1006     if (cd) {
1007         if (cd->currentSender) {
1008             cd->currentSender->receiverDeleted();
1009             cd->currentSender = nullptr;
1010         }
1011 
1012         QBasicMutex *signalSlotMutex = signalSlotLock(this);
1013         QBasicMutexLocker locker(signalSlotMutex);
1014 
1015         // disconnect all receivers
1016         int receiverCount = cd->signalVectorCount();
1017         for (int signal = -1; signal < receiverCount; ++signal) {
1018             QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal);
1019 
1020             while (QObjectPrivate::Connection *c = connectionList.first.loadRelaxed()) {
1021                 Q_ASSERT(c->receiver.loadAcquire());
1022 
1023                 QBasicMutex *m = signalSlotLock(c->receiver.loadRelaxed());
1024                 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
1025                 if (c->receiver.loadAcquire()) {
1026                     cd->removeConnection(c);
1027                     Q_ASSERT(connectionList.first.loadRelaxed() != c);
1028                 }
1029                 if (needToUnlock)
1030                     m->unlock();
1031             }
1032         }
1033 
1034         /* Disconnect all senders:
1035          */
1036         while (QObjectPrivate::Connection *node = cd->senders) {
1037             Q_ASSERT(node->receiver.loadAcquire());
1038             QObject *sender = node->sender;
1039             // Send disconnectNotify before removing the connection from sender's connection list.
1040             // This ensures any eventual destructor of sender will block on getting receiver's lock
1041             // and not finish until we release it.
1042             sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index));
1043             QBasicMutex *m = signalSlotLock(sender);
1044             bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
1045             //the node has maybe been removed while the mutex was unlocked in relock?
1046             if (node != cd->senders) {
1047                 // We hold the wrong mutex
1048                 Q_ASSERT(needToUnlock);
1049                 m->unlock();
1050                 continue;
1051             }
1052 
1053             QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.loadRelaxed();
1054             Q_ASSERT(senderData);
1055 
1056             QtPrivate::QSlotObjectBase *slotObj = nullptr;
1057             if (node->isSlotObject) {
1058                 slotObj = node->slotObj;
1059                 node->isSlotObject = false;
1060             }
1061 
1062             senderData->removeConnection(node);
1063             if (needToUnlock)
1064                 m->unlock();
1065 
1066             if (slotObj) {
1067                 locker.unlock();
1068                 slotObj->destroyIfLastRef();
1069                 locker.relock();
1070             }
1071         }
1072 
1073         // invalidate all connections on the object and make sure
1074         // activate() will skip them
1075         cd->currentConnectionId.storeRelaxed(0);
1076     }
1077     if (cd && !cd->ref.deref())
1078         delete cd;
1079     d->connections.storeRelaxed(nullptr);
1080 
1081     if (!d->children.isEmpty())
1082         d->deleteChildren();
1083 
1084 #if QT_VERSION < 0x60000
1085     qt_removeObject(this);
1086 #endif
1087     if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
1088         reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
1089 
1090     Q_TRACE(QObject_dtor, this);
1091 
1092     if (d->parent)        // remove it from parent object
1093         d->setParent_helper(nullptr);
1094 }
1095 
~Connection()1096 QObjectPrivate::Connection::~Connection()
1097 {
1098     if (ownArgumentTypes) {
1099         const int *v = argumentTypes.loadRelaxed();
1100         if (v != &DIRECT_CONNECTION_ONLY)
1101             delete [] v;
1102     }
1103     if (isSlotObject)
1104         slotObj->destroyIfLastRef();
1105 }
1106 
1107 
1108 /*!
1109     \fn const QMetaObject *QObject::metaObject() const
1110 
1111     Returns a pointer to the meta-object of this object.
1112 
1113     A meta-object contains information about a class that inherits
1114     QObject, e.g. class name, superclass name, properties, signals and
1115     slots. Every QObject subclass that contains the Q_OBJECT macro will have a
1116     meta-object.
1117 
1118     The meta-object information is required by the signal/slot
1119     connection mechanism and the property system. The inherits()
1120     function also makes use of the meta-object.
1121 
1122     If you have no pointer to an actual object instance but still
1123     want to access the meta-object of a class, you can use \l
1124     staticMetaObject.
1125 
1126     Example:
1127 
1128     \snippet code/src_corelib_kernel_qobject.cpp 1
1129 
1130     \sa staticMetaObject
1131 */
1132 
1133 /*!
1134     \variable QObject::staticMetaObject
1135 
1136     This variable stores the meta-object for the class.
1137 
1138     A meta-object contains information about a class that inherits
1139     QObject, e.g. class name, superclass name, properties, signals and
1140     slots. Every class that contains the Q_OBJECT macro will also have
1141     a meta-object.
1142 
1143     The meta-object information is required by the signal/slot
1144     connection mechanism and the property system. The inherits()
1145     function also makes use of the meta-object.
1146 
1147     If you have a pointer to an object, you can use metaObject() to
1148     retrieve the meta-object associated with that object.
1149 
1150     Example:
1151 
1152     \snippet code/src_corelib_kernel_qobject.cpp 2
1153 
1154     \sa metaObject()
1155 */
1156 
1157 /*!
1158     \fn template <class T> T qobject_cast(QObject *object)
1159     \fn template <class T> T qobject_cast(const QObject *object)
1160     \relates QObject
1161 
1162     Returns the given \a object cast to type T if the object is of type
1163     T (or of a subclass); otherwise returns \nullptr. If \a object is
1164     \nullptr then it will also return \nullptr.
1165 
1166     The class T must inherit (directly or indirectly) QObject and be
1167     declared with the \l Q_OBJECT macro.
1168 
1169     A class is considered to inherit itself.
1170 
1171     Example:
1172 
1173     \snippet code/src_corelib_kernel_qobject.cpp 3
1174 
1175     The qobject_cast() function behaves similarly to the standard C++
1176     \c dynamic_cast(), with the advantages that it doesn't require
1177     RTTI support and it works across dynamic library boundaries.
1178 
1179     qobject_cast() can also be used in conjunction with interfaces;
1180     see the \l{tools/plugandpaint/app}{Plug & Paint} example for details.
1181 
1182     \warning If T isn't declared with the Q_OBJECT macro, this
1183     function's return value is undefined.
1184 
1185     \sa QObject::inherits()
1186 */
1187 
1188 /*!
1189     \fn bool QObject::inherits(const char *className) const
1190 
1191     Returns \c true if this object is an instance of a class that
1192     inherits \a className or a QObject subclass that inherits \a
1193     className; otherwise returns \c false.
1194 
1195     A class is considered to inherit itself.
1196 
1197     Example:
1198 
1199     \snippet code/src_corelib_kernel_qobject.cpp 4
1200 
1201     If you need to determine whether an object is an instance of a particular
1202     class for the purpose of casting it, consider using qobject_cast<Type *>(object)
1203     instead.
1204 
1205     \sa metaObject(), qobject_cast()
1206 */
1207 
1208 /*!
1209     \property QObject::objectName
1210 
1211     \brief the name of this object
1212 
1213     You can find an object by name (and type) using findChild().
1214     You can find a set of objects with findChildren().
1215 
1216     \snippet code/src_corelib_kernel_qobject.cpp 5
1217 
1218     By default, this property contains an empty string.
1219 
1220     \sa metaObject(), QMetaObject::className()
1221 */
1222 
objectName() const1223 QString QObject::objectName() const
1224 {
1225     Q_D(const QObject);
1226     return d->extraData ? d->extraData->objectName : QString();
1227 }
1228 
1229 /*
1230     Sets the object's name to \a name.
1231 */
setObjectName(const QString & name)1232 void QObject::setObjectName(const QString &name)
1233 {
1234     Q_D(QObject);
1235     if (!d->extraData)
1236         d->extraData = new QObjectPrivate::ExtraData;
1237 
1238     if (d->extraData->objectName != name) {
1239         d->extraData->objectName = name;
1240         emit objectNameChanged(d->extraData->objectName, QPrivateSignal());
1241     }
1242 }
1243 
1244 /*! \fn void QObject::objectNameChanged(const QString &objectName)
1245 
1246     This signal is emitted after the object's name has been changed. The new object name is passed as \a objectName.
1247 
1248     \sa QObject::objectName
1249 */
1250 
1251 /*!
1252     \fn bool QObject::isWidgetType() const
1253 
1254     Returns \c true if the object is a widget; otherwise returns \c false.
1255 
1256     Calling this function is equivalent to calling
1257     \c{inherits("QWidget")}, except that it is much faster.
1258 */
1259 
1260 /*!
1261     \fn bool QObject::isWindowType() const
1262 
1263     Returns \c true if the object is a window; otherwise returns \c false.
1264 
1265     Calling this function is equivalent to calling
1266     \c{inherits("QWindow")}, except that it is much faster.
1267 */
1268 
1269 /*!
1270     This virtual function receives events to an object and should
1271     return true if the event \a e was recognized and processed.
1272 
1273     The event() function can be reimplemented to customize the
1274     behavior of an object.
1275 
1276     Make sure you call the parent event class implementation
1277     for all the events you did not handle.
1278 
1279     Example:
1280 
1281     \snippet code/src_corelib_kernel_qobject.cpp 52
1282 
1283     \sa installEventFilter(), timerEvent(), QCoreApplication::sendEvent(),
1284     QCoreApplication::postEvent()
1285 */
1286 
event(QEvent * e)1287 bool QObject::event(QEvent *e)
1288 {
1289     switch (e->type()) {
1290     case QEvent::Timer:
1291         timerEvent((QTimerEvent*)e);
1292         break;
1293 
1294     case QEvent::ChildAdded:
1295     case QEvent::ChildPolished:
1296     case QEvent::ChildRemoved:
1297         childEvent((QChildEvent*)e);
1298         break;
1299 
1300     case QEvent::DeferredDelete:
1301         qDeleteInEventHandler(this);
1302         break;
1303 
1304     case QEvent::MetaCall:
1305         {
1306             QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e);
1307 
1308             if (!d_func()->connections.loadRelaxed()) {
1309                 QBasicMutexLocker locker(signalSlotLock(this));
1310                 d_func()->ensureConnectionData();
1311             }
1312             QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId());
1313 
1314             mce->placeMetaCall(this);
1315             break;
1316         }
1317 
1318     case QEvent::ThreadChange: {
1319         Q_D(QObject);
1320         QThreadData *threadData = d->threadData.loadRelaxed();
1321         QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
1322         if (eventDispatcher) {
1323             QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
1324             if (!timers.isEmpty()) {
1325                 // do not to release our timer ids back to the pool (since the timer ids are moving to a new thread).
1326                 eventDispatcher->unregisterTimers(this);
1327                 QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
1328                                           Q_ARG(void*, (new QList<QAbstractEventDispatcher::TimerInfo>(timers))));
1329             }
1330         }
1331         break;
1332     }
1333 
1334     default:
1335         if (e->type() >= QEvent::User) {
1336             customEvent(e);
1337             break;
1338         }
1339         return false;
1340     }
1341     return true;
1342 }
1343 
1344 /*!
1345     \fn void QObject::timerEvent(QTimerEvent *event)
1346 
1347     This event handler can be reimplemented in a subclass to receive
1348     timer events for the object.
1349 
1350     QTimer provides a higher-level interface to the timer
1351     functionality, and also more general information about timers. The
1352     timer event is passed in the \a event parameter.
1353 
1354     \sa startTimer(), killTimer(), event()
1355 */
1356 
timerEvent(QTimerEvent *)1357 void QObject::timerEvent(QTimerEvent *)
1358 {
1359 }
1360 
1361 
1362 /*!
1363     This event handler can be reimplemented in a subclass to receive
1364     child events. The event is passed in the \a event parameter.
1365 
1366     QEvent::ChildAdded and QEvent::ChildRemoved events are sent to
1367     objects when children are added or removed. In both cases you can
1368     only rely on the child being a QObject, or if isWidgetType()
1369     returns \c true, a QWidget. (This is because, in the
1370     \l{QEvent::ChildAdded}{ChildAdded} case, the child is not yet
1371     fully constructed, and in the \l{QEvent::ChildRemoved}{ChildRemoved}
1372     case it might have been destructed already).
1373 
1374     QEvent::ChildPolished events are sent to widgets when children
1375     are polished, or when polished children are added. If you receive
1376     a child polished event, the child's construction is usually
1377     completed. However, this is not guaranteed, and multiple polish
1378     events may be delivered during the execution of a widget's
1379     constructor.
1380 
1381     For every child widget, you receive one
1382     \l{QEvent::ChildAdded}{ChildAdded} event, zero or more
1383     \l{QEvent::ChildPolished}{ChildPolished} events, and one
1384     \l{QEvent::ChildRemoved}{ChildRemoved} event.
1385 
1386     The \l{QEvent::ChildPolished}{ChildPolished} event is omitted if
1387     a child is removed immediately after it is added. If a child is
1388     polished several times during construction and destruction, you
1389     may receive several child polished events for the same child,
1390     each time with a different virtual table.
1391 
1392     \sa event()
1393 */
1394 
childEvent(QChildEvent *)1395 void QObject::childEvent(QChildEvent * /* event */)
1396 {
1397 }
1398 
1399 
1400 /*!
1401     This event handler can be reimplemented in a subclass to receive
1402     custom events. Custom events are user-defined events with a type
1403     value at least as large as the QEvent::User item of the
1404     QEvent::Type enum, and is typically a QEvent subclass. The event
1405     is passed in the \a event parameter.
1406 
1407     \sa event(), QEvent
1408 */
customEvent(QEvent *)1409 void QObject::customEvent(QEvent * /* event */)
1410 {
1411 }
1412 
1413 
1414 
1415 /*!
1416     Filters events if this object has been installed as an event
1417     filter for the \a watched object.
1418 
1419     In your reimplementation of this function, if you want to filter
1420     the \a event out, i.e. stop it being handled further, return
1421     true; otherwise return false.
1422 
1423     Example:
1424     \snippet code/src_corelib_kernel_qobject.cpp 6
1425 
1426     Notice in the example above that unhandled events are passed to
1427     the base class's eventFilter() function, since the base class
1428     might have reimplemented eventFilter() for its own internal
1429     purposes.
1430 
1431     Some events, such as \l QEvent::ShortcutOverride must be explicitly
1432     accepted (by calling \l {QEvent::}{accept()} on them) in order to prevent
1433     propagation.
1434 
1435     \warning If you delete the receiver object in this function, be
1436     sure to return true. Otherwise, Qt will forward the event to the
1437     deleted object and the program might crash.
1438 
1439     \sa installEventFilter()
1440 */
1441 
eventFilter(QObject *,QEvent *)1442 bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
1443 {
1444     return false;
1445 }
1446 
1447 /*!
1448     \fn bool QObject::signalsBlocked() const
1449 
1450     Returns \c true if signals are blocked; otherwise returns \c false.
1451 
1452     Signals are not blocked by default.
1453 
1454     \sa blockSignals(), QSignalBlocker
1455 */
1456 
1457 /*!
1458     If \a block is true, signals emitted by this object are blocked
1459     (i.e., emitting a signal will not invoke anything connected to it).
1460     If \a block is false, no such blocking will occur.
1461 
1462     The return value is the previous value of signalsBlocked().
1463 
1464     Note that the destroyed() signal will be emitted even if the signals
1465     for this object have been blocked.
1466 
1467     Signals emitted while being blocked are not buffered.
1468 
1469     \sa signalsBlocked(), QSignalBlocker
1470 */
1471 
blockSignals(bool block)1472 bool QObject::blockSignals(bool block) noexcept
1473 {
1474     Q_D(QObject);
1475     bool previous = d->blockSig;
1476     d->blockSig = block;
1477     return previous;
1478 }
1479 
1480 /*!
1481     Returns the thread in which the object lives.
1482 
1483     \sa moveToThread()
1484 */
thread() const1485 QThread *QObject::thread() const
1486 {
1487     return d_func()->threadData.loadRelaxed()->thread.loadAcquire();
1488 }
1489 
1490 /*!
1491     Changes the thread affinity for this object and its children. The
1492     object cannot be moved if it has a parent. Event processing will
1493     continue in the \a targetThread.
1494 
1495     To move an object to the main thread, use QApplication::instance()
1496     to retrieve a pointer to the current application, and then use
1497     QApplication::thread() to retrieve the thread in which the
1498     application lives. For example:
1499 
1500     \snippet code/src_corelib_kernel_qobject.cpp 7
1501 
1502     If \a targetThread is \nullptr, all event processing for this object
1503     and its children stops, as they are no longer associated with any
1504     thread.
1505 
1506     Note that all active timers for the object will be reset. The
1507     timers are first stopped in the current thread and restarted (with
1508     the same interval) in the \a targetThread. As a result, constantly
1509     moving an object between threads can postpone timer events
1510     indefinitely.
1511 
1512     A QEvent::ThreadChange event is sent to this object just before
1513     the thread affinity is changed. You can handle this event to
1514     perform any special processing. Note that any new events that are
1515     posted to this object will be handled in the \a targetThread,
1516     provided it is not \nullptr: when it is \nullptr, no event processing
1517     for this object or its children can happen, as they are no longer
1518     associated with any thread.
1519 
1520     \warning This function is \e not thread-safe; the current thread
1521     must be same as the current thread affinity. In other words, this
1522     function can only "push" an object from the current thread to
1523     another thread, it cannot "pull" an object from any arbitrary
1524     thread to the current thread. There is one exception to this rule
1525     however: objects with no thread affinity can be "pulled" to the
1526     current thread.
1527 
1528     \sa thread()
1529  */
moveToThread(QThread * targetThread)1530 void QObject::moveToThread(QThread *targetThread)
1531 {
1532     Q_D(QObject);
1533 
1534     if (d->threadData.loadRelaxed()->thread.loadAcquire() == targetThread) {
1535         // object is already in this thread
1536         return;
1537     }
1538 
1539     if (d->parent != nullptr) {
1540         qWarning("QObject::moveToThread: Cannot move objects with a parent");
1541         return;
1542     }
1543     if (d->isWidget) {
1544         qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
1545         return;
1546     }
1547 
1548     QThreadData *currentData = QThreadData::current();
1549     QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr;
1550     QThreadData *thisThreadData = d->threadData.loadRelaxed();
1551     if (!thisThreadData->thread.loadAcquire() && currentData == targetData) {
1552         // one exception to the rule: we allow moving objects with no thread affinity to the current thread
1553         currentData = d->threadData;
1554     } else if (thisThreadData != currentData) {
1555         qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
1556                  "Cannot move to target thread (%p)\n",
1557                  currentData->thread.loadRelaxed(), thisThreadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr);
1558 
1559 #ifdef Q_OS_MAC
1560         qWarning("You might be loading two sets of Qt binaries into the same process. "
1561                  "Check that all plugins are compiled against the right Qt binaries. Export "
1562                  "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
1563 #endif
1564 
1565         return;
1566     }
1567 
1568     // prepare to move
1569     d->moveToThread_helper();
1570 
1571     if (!targetData)
1572         targetData = new QThreadData(0);
1573 
1574     // make sure nobody adds/removes connections to this object while we're moving it
1575     QMutexLocker l(signalSlotLock(this));
1576 
1577     QOrderedMutexLocker locker(&currentData->postEventList.mutex,
1578                                &targetData->postEventList.mutex);
1579 
1580     // keep currentData alive (since we've got it locked)
1581     currentData->ref();
1582 
1583     // move the object
1584     d_func()->setThreadData_helper(currentData, targetData);
1585 
1586     locker.unlock();
1587 
1588     // now currentData can commit suicide if it wants to
1589     currentData->deref();
1590 }
1591 
moveToThread_helper()1592 void QObjectPrivate::moveToThread_helper()
1593 {
1594     Q_Q(QObject);
1595     QEvent e(QEvent::ThreadChange);
1596     QCoreApplication::sendEvent(q, &e);
1597     for (int i = 0; i < children.size(); ++i) {
1598         QObject *child = children.at(i);
1599         child->d_func()->moveToThread_helper();
1600     }
1601 }
1602 
setThreadData_helper(QThreadData * currentData,QThreadData * targetData)1603 void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
1604 {
1605     Q_Q(QObject);
1606 
1607     // move posted events
1608     int eventsMoved = 0;
1609     for (int i = 0; i < currentData->postEventList.size(); ++i) {
1610         const QPostEvent &pe = currentData->postEventList.at(i);
1611         if (!pe.event)
1612             continue;
1613         if (pe.receiver == q) {
1614             // move this post event to the targetList
1615             targetData->postEventList.addEvent(pe);
1616             const_cast<QPostEvent &>(pe).event = nullptr;
1617             ++eventsMoved;
1618         }
1619     }
1620     if (eventsMoved > 0 && targetData->hasEventDispatcher()) {
1621         targetData->canWait = false;
1622         targetData->eventDispatcher.loadRelaxed()->wakeUp();
1623     }
1624 
1625     // the current emitting thread shouldn't restore currentSender after calling moveToThread()
1626     ConnectionData *cd = connections.loadRelaxed();
1627     if (cd) {
1628         if (cd->currentSender) {
1629             cd->currentSender->receiverDeleted();
1630             cd->currentSender = nullptr;
1631         }
1632 
1633         // adjust the receiverThreadId values in the Connections
1634         if (cd) {
1635             auto *c = cd->senders;
1636             while (c) {
1637                 QObject *r = c->receiver.loadRelaxed();
1638                 if (r) {
1639                     Q_ASSERT(r == q);
1640                     targetData->ref();
1641                     QThreadData *old = c->receiverThreadData.loadRelaxed();
1642                     if (old)
1643                         old->deref();
1644                     c->receiverThreadData.storeRelaxed(targetData);
1645                 }
1646                 c = c->next;
1647             }
1648         }
1649 
1650     }
1651 
1652     // set new thread data
1653     targetData->ref();
1654     threadData.loadRelaxed()->deref();
1655 
1656     // synchronizes with loadAcquire e.g. in QCoreApplication::postEvent
1657     threadData.storeRelease(targetData);
1658 
1659     for (int i = 0; i < children.size(); ++i) {
1660         QObject *child = children.at(i);
1661         child->d_func()->setThreadData_helper(currentData, targetData);
1662     }
1663 }
1664 
_q_reregisterTimers(void * pointer)1665 void QObjectPrivate::_q_reregisterTimers(void *pointer)
1666 {
1667     Q_Q(QObject);
1668     QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
1669     QAbstractEventDispatcher *eventDispatcher = threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
1670     for (int i = 0; i < timerList->size(); ++i) {
1671         const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
1672         eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q);
1673     }
1674     delete timerList;
1675 }
1676 
1677 
1678 //
1679 // The timer flag hasTimer is set when startTimer is called.
1680 // It is not reset when killing the timer because more than
1681 // one timer might be active.
1682 //
1683 
1684 /*!
1685     Starts a timer and returns a timer identifier, or returns zero if
1686     it could not start a timer.
1687 
1688     A timer event will occur every \a interval milliseconds until
1689     killTimer() is called. If \a interval is 0, then the timer event
1690     occurs once every time there are no more window system events to
1691     process.
1692 
1693     The virtual timerEvent() function is called with the QTimerEvent
1694     event parameter class when a timer event occurs. Reimplement this
1695     function to get timer events.
1696 
1697     If multiple timers are running, the QTimerEvent::timerId() can be
1698     used to find out which timer was activated.
1699 
1700     Example:
1701 
1702     \snippet code/src_corelib_kernel_qobject.cpp 8
1703 
1704     Note that QTimer's accuracy depends on the underlying operating system and
1705     hardware. The \a timerType argument allows you to customize the accuracy of
1706     the timer. See Qt::TimerType for information on the different timer types.
1707     Most platforms support an accuracy of 20 milliseconds; some provide more.
1708     If Qt is unable to deliver the requested number of timer events, it will
1709     silently discard some.
1710 
1711     The QTimer class provides a high-level programming interface with
1712     single-shot timers and timer signals instead of events. There is
1713     also a QBasicTimer class that is more lightweight than QTimer and
1714     less clumsy than using timer IDs directly.
1715 
1716     \sa timerEvent(), killTimer(), QTimer::singleShot()
1717 */
1718 
startTimer(int interval,Qt::TimerType timerType)1719 int QObject::startTimer(int interval, Qt::TimerType timerType)
1720 {
1721     Q_D(QObject);
1722 
1723     if (Q_UNLIKELY(interval < 0)) {
1724         qWarning("QObject::startTimer: Timers cannot have negative intervals");
1725         return 0;
1726     }
1727 
1728     auto thisThreadData = d->threadData.loadRelaxed();
1729     if (Q_UNLIKELY(!thisThreadData->hasEventDispatcher())) {
1730         qWarning("QObject::startTimer: Timers can only be used with threads started with QThread");
1731         return 0;
1732     }
1733     if (Q_UNLIKELY(thread() != QThread::currentThread())) {
1734         qWarning("QObject::startTimer: Timers cannot be started from another thread");
1735         return 0;
1736     }
1737     int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this);
1738     if (!d->extraData)
1739         d->extraData = new QObjectPrivate::ExtraData;
1740     d->extraData->runningTimers.append(timerId);
1741     return timerId;
1742 }
1743 
1744 /*!
1745     \since 5.9
1746     \overload
1747     \fn int QObject::startTimer(std::chrono::milliseconds time, Qt::TimerType timerType)
1748 
1749     Starts a timer and returns a timer identifier, or returns zero if
1750     it could not start a timer.
1751 
1752     A timer event will occur every \a time interval until killTimer()
1753     is called. If \a time is equal to \c{std::chrono::duration::zero()},
1754     then the timer event occurs once every time there are no more window
1755     system events to process.
1756 
1757     The virtual timerEvent() function is called with the QTimerEvent
1758     event parameter class when a timer event occurs. Reimplement this
1759     function to get timer events.
1760 
1761     If multiple timers are running, the QTimerEvent::timerId() can be
1762     used to find out which timer was activated.
1763 
1764     Example:
1765 
1766     \snippet code/src_corelib_kernel_qobject.cpp 8
1767 
1768     Note that QTimer's accuracy depends on the underlying operating system and
1769     hardware. The \a timerType argument allows you to customize the accuracy of
1770     the timer. See Qt::TimerType for information on the different timer types.
1771     Most platforms support an accuracy of 20 milliseconds; some provide more.
1772     If Qt is unable to deliver the requested number of timer events, it will
1773     silently discard some.
1774 
1775     The QTimer class provides a high-level programming interface with
1776     single-shot timers and timer signals instead of events. There is
1777     also a QBasicTimer class that is more lightweight than QTimer and
1778     less clumsy than using timer IDs directly.
1779 
1780     \sa timerEvent(), killTimer(), QTimer::singleShot()
1781 */
1782 
1783 /*!
1784     Kills the timer with timer identifier, \a id.
1785 
1786     The timer identifier is returned by startTimer() when a timer
1787     event is started.
1788 
1789     \sa timerEvent(), startTimer()
1790 */
1791 
killTimer(int id)1792 void QObject::killTimer(int id)
1793 {
1794     Q_D(QObject);
1795     if (Q_UNLIKELY(thread() != QThread::currentThread())) {
1796         qWarning("QObject::killTimer: Timers cannot be stopped from another thread");
1797         return;
1798     }
1799     if (id) {
1800         int at = d->extraData ? d->extraData->runningTimers.indexOf(id) : -1;
1801         if (at == -1) {
1802             // timer isn't owned by this object
1803             qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %ls), timer has not been killed",
1804                      id,
1805                      this,
1806                      metaObject()->className(),
1807                      qUtf16Printable(objectName()));
1808             return;
1809         }
1810 
1811         auto thisThreadData = d->threadData.loadRelaxed();
1812         if (thisThreadData->hasEventDispatcher())
1813             thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimer(id);
1814 
1815         d->extraData->runningTimers.remove(at);
1816         QAbstractEventDispatcherPrivate::releaseTimerId(id);
1817     }
1818 }
1819 
1820 
1821 /*!
1822     \fn QObject *QObject::parent() const
1823 
1824     Returns a pointer to the parent object.
1825 
1826     \sa children()
1827 */
1828 
1829 /*!
1830     \fn const QObjectList &QObject::children() const
1831 
1832     Returns a list of child objects.
1833     The QObjectList class is defined in the \c{<QObject>} header
1834     file as the following:
1835 
1836     \quotefromfile kernel/qobject.h
1837     \skipto /typedef .*QObjectList/
1838     \printuntil QObjectList
1839 
1840     The first child added is the \l{QList::first()}{first} object in
1841     the list and the last child added is the \l{QList::last()}{last}
1842     object in the list, i.e. new children are appended at the end.
1843 
1844     Note that the list order changes when QWidget children are
1845     \l{QWidget::raise()}{raised} or \l{QWidget::lower()}{lowered}. A
1846     widget that is raised becomes the last object in the list, and a
1847     widget that is lowered becomes the first object in the list.
1848 
1849     \sa findChild(), findChildren(), parent(), setParent()
1850 */
1851 
1852 
1853 /*!
1854     \fn template<typename T> T *QObject::findChild(const QString &name, Qt::FindChildOptions options) const
1855 
1856     Returns the child of this object that can be cast into type T and
1857     that is called \a name, or \nullptr if there is no such object.
1858     Omitting the \a name argument causes all object names to be matched.
1859     The search is performed recursively, unless \a options specifies the
1860     option FindDirectChildrenOnly.
1861 
1862     If there is more than one child matching the search, the most
1863     direct ancestor is returned. If there are several direct
1864     ancestors, it is undefined which one will be returned. In that
1865     case, findChildren() should be used.
1866 
1867     This example returns a child \c{QPushButton} of \c{parentWidget}
1868     named \c{"button1"}, even if the button isn't a direct child of
1869     the parent:
1870 
1871     \snippet code/src_corelib_kernel_qobject.cpp 10
1872 
1873     This example returns a \c{QListWidget} child of \c{parentWidget}:
1874 
1875     \snippet code/src_corelib_kernel_qobject.cpp 11
1876 
1877     This example returns a child \c{QPushButton} of \c{parentWidget}
1878     (its direct parent) named \c{"button1"}:
1879 
1880     \snippet code/src_corelib_kernel_qobject.cpp 41
1881 
1882     This example returns a \c{QListWidget} child of \c{parentWidget},
1883     its direct parent:
1884 
1885     \snippet code/src_corelib_kernel_qobject.cpp 42
1886 
1887     \sa findChildren()
1888 */
1889 
1890 /*!
1891     \fn template<typename T> QList<T> QObject::findChildren(const QString &name, Qt::FindChildOptions options) const
1892 
1893     Returns all children of this object with the given \a name that can be
1894     cast to type T, or an empty list if there are no such objects.
1895     Omitting the \a name argument causes all object names to be matched.
1896     The search is performed recursively, unless \a options specifies the
1897     option FindDirectChildrenOnly.
1898 
1899     The following example shows how to find a list of child \c{QWidget}s of
1900     the specified \c{parentWidget} named \c{widgetname}:
1901 
1902     \snippet code/src_corelib_kernel_qobject.cpp 12
1903 
1904     This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
1905 
1906     \snippet code/src_corelib_kernel_qobject.cpp 13
1907 
1908     This example returns all \c{QPushButton}s that are immediate children of \c{parentWidget}:
1909 
1910     \snippet code/src_corelib_kernel_qobject.cpp 43
1911 
1912     \sa findChild()
1913 */
1914 
1915 /*!
1916     \fn template<typename T> QList<T> QObject::findChildren(const QRegExp &regExp, Qt::FindChildOptions options) const
1917     \overload findChildren()
1918     \obsolete
1919 
1920     Returns the children of this object that can be cast to type T
1921     and that have names matching the regular expression \a regExp,
1922     or an empty list if there are no such objects.
1923     The search is performed recursively, unless \a options specifies the
1924     option FindDirectChildrenOnly.
1925 
1926     Use the findChildren overload taking a QRegularExpression instead.
1927 */
1928 
1929 /*!
1930     \fn QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options) const
1931     \overload findChildren()
1932 
1933     \since 5.0
1934 
1935     Returns the children of this object that can be cast to type T
1936     and that have names matching the regular expression \a re,
1937     or an empty list if there are no such objects.
1938     The search is performed recursively, unless \a options specifies the
1939     option FindDirectChildrenOnly.
1940 */
1941 
1942 /*!
1943     \fn template<typename T> T qFindChild(const QObject *obj, const QString &name)
1944     \relates QObject
1945     \overload qFindChildren()
1946     \obsolete
1947 
1948     This function is equivalent to
1949     \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
1950 
1951     \note This function was provided as a workaround for MSVC 6
1952     which did not support member template functions. It is advised
1953     to use the other form in new code.
1954 
1955     \sa QObject::findChild()
1956 */
1957 
1958 /*!
1959     \fn template<typename T> QList<T> qFindChildren(const QObject *obj, const QString &name)
1960     \relates QObject
1961     \overload qFindChildren()
1962     \obsolete
1963 
1964     This function is equivalent to
1965     \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
1966 
1967     \note This function was provided as a workaround for MSVC 6
1968     which did not support member template functions. It is advised
1969     to use the other form in new code.
1970 
1971     \sa QObject::findChildren()
1972 */
1973 
1974 /*!
1975     \fn template<typename T> QList<T> qFindChildren(const QObject *obj, const QRegExp &regExp)
1976     \relates QObject
1977     \overload qFindChildren()
1978 
1979     This function is equivalent to
1980     \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp).
1981 
1982     \note This function was provided as a workaround for MSVC 6
1983     which did not support member template functions. It is advised
1984     to use the other form in new code.
1985 
1986     \sa QObject::findChildren()
1987 */
1988 
1989 /*!
1990     \internal
1991 */
qt_qFindChildren_helper(const QObject * parent,const QString & name,const QMetaObject & mo,QList<void * > * list,Qt::FindChildOptions options)1992 void qt_qFindChildren_helper(const QObject *parent, const QString &name,
1993                              const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
1994 {
1995     if (!parent || !list)
1996         return;
1997     const QObjectList &children = parent->children();
1998     QObject *obj;
1999     for (int i = 0; i < children.size(); ++i) {
2000         obj = children.at(i);
2001         if (mo.cast(obj)) {
2002             if (name.isNull() || obj->objectName() == name)
2003                 list->append(obj);
2004         }
2005         if (options & Qt::FindChildrenRecursively)
2006             qt_qFindChildren_helper(obj, name, mo, list, options);
2007     }
2008 }
2009 
2010 #ifndef QT_NO_REGEXP
2011 /*!
2012     \internal
2013 */
qt_qFindChildren_helper(const QObject * parent,const QRegExp & re,const QMetaObject & mo,QList<void * > * list,Qt::FindChildOptions options)2014 void qt_qFindChildren_helper(const QObject *parent, const QRegExp &re,
2015                              const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
2016 {
2017     if (!parent || !list)
2018         return;
2019     const QObjectList &children = parent->children();
2020     QRegExp reCopy = re;
2021     QObject *obj;
2022     for (int i = 0; i < children.size(); ++i) {
2023         obj = children.at(i);
2024         if (mo.cast(obj) && reCopy.indexIn(obj->objectName()) != -1)
2025             list->append(obj);
2026 
2027         if (options & Qt::FindChildrenRecursively)
2028             qt_qFindChildren_helper(obj, re, mo, list, options);
2029     }
2030 }
2031 #endif // QT_NO_REGEXP
2032 
2033 #if QT_CONFIG(regularexpression)
2034 /*!
2035     \internal
2036 */
qt_qFindChildren_helper(const QObject * parent,const QRegularExpression & re,const QMetaObject & mo,QList<void * > * list,Qt::FindChildOptions options)2037 void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
2038                              const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
2039 {
2040     if (!parent || !list)
2041         return;
2042     const QObjectList &children = parent->children();
2043     QObject *obj;
2044     for (int i = 0; i < children.size(); ++i) {
2045         obj = children.at(i);
2046         if (mo.cast(obj)) {
2047             QRegularExpressionMatch m = re.match(obj->objectName());
2048             if (m.hasMatch())
2049                 list->append(obj);
2050         }
2051         if (options & Qt::FindChildrenRecursively)
2052             qt_qFindChildren_helper(obj, re, mo, list, options);
2053     }
2054 }
2055 #endif // QT_CONFIG(regularexpression)
2056 
2057 /*!
2058     \internal
2059  */
qt_qFindChild_helper(const QObject * parent,const QString & name,const QMetaObject & mo,Qt::FindChildOptions options)2060 QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options)
2061 {
2062     if (!parent)
2063         return nullptr;
2064     const QObjectList &children = parent->children();
2065     QObject *obj;
2066     int i;
2067     for (i = 0; i < children.size(); ++i) {
2068         obj = children.at(i);
2069         if (mo.cast(obj) && (name.isNull() || obj->objectName() == name))
2070             return obj;
2071     }
2072     if (options & Qt::FindChildrenRecursively) {
2073         for (i = 0; i < children.size(); ++i) {
2074             obj = qt_qFindChild_helper(children.at(i), name, mo, options);
2075             if (obj)
2076                 return obj;
2077         }
2078     }
2079     return nullptr;
2080 }
2081 
2082 /*!
2083     Makes the object a child of \a parent.
2084 
2085     \sa parent(), children()
2086 */
setParent(QObject * parent)2087 void QObject::setParent(QObject *parent)
2088 {
2089     Q_D(QObject);
2090     Q_ASSERT(!d->isWidget);
2091     d->setParent_helper(parent);
2092 }
2093 
deleteChildren()2094 void QObjectPrivate::deleteChildren()
2095 {
2096     Q_ASSERT_X(!isDeletingChildren, "QObjectPrivate::deleteChildren()", "isDeletingChildren already set, did this function recurse?");
2097     isDeletingChildren = true;
2098     // delete children objects
2099     // don't use qDeleteAll as the destructor of the child might
2100     // delete siblings
2101     for (int i = 0; i < children.count(); ++i) {
2102         currentChildBeingDeleted = children.at(i);
2103         children[i] = 0;
2104         delete currentChildBeingDeleted;
2105     }
2106     children.clear();
2107     currentChildBeingDeleted = nullptr;
2108     isDeletingChildren = false;
2109 }
2110 
setParent_helper(QObject * o)2111 void QObjectPrivate::setParent_helper(QObject *o)
2112 {
2113     Q_Q(QObject);
2114     Q_ASSERT_X(q != o, Q_FUNC_INFO, "Cannot parent a QObject to itself");
2115 #ifdef QT_DEBUG
2116     const auto checkForParentChildLoops = qScopeGuard([&](){
2117         int depth = 0;
2118         auto p = parent;
2119         while (p) {
2120             if (++depth == CheckForParentChildLoopsWarnDepth) {
2121                 qWarning("QObject %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
2122                          "this is undefined behavior",
2123                          q, q->metaObject()->className(), qPrintable(q->objectName()));
2124             }
2125             p = p->parent();
2126         }
2127     });
2128 #endif
2129 
2130     if (o == parent)
2131         return;
2132 
2133     if (parent) {
2134         QObjectPrivate *parentD = parent->d_func();
2135         if (parentD->isDeletingChildren && wasDeleted
2136             && parentD->currentChildBeingDeleted == q) {
2137             // don't do anything since QObjectPrivate::deleteChildren() already
2138             // cleared our entry in parentD->children.
2139         } else {
2140             const int index = parentD->children.indexOf(q);
2141             if (index < 0) {
2142                 // we're probably recursing into setParent() from a ChildRemoved event, don't do anything
2143             } else if (parentD->isDeletingChildren) {
2144                 parentD->children[index] = 0;
2145             } else {
2146                 parentD->children.removeAt(index);
2147                 if (sendChildEvents && parentD->receiveChildEvents) {
2148                     QChildEvent e(QEvent::ChildRemoved, q);
2149                     QCoreApplication::sendEvent(parent, &e);
2150                 }
2151             }
2152         }
2153     }
2154     parent = o;
2155     if (parent) {
2156         // object hierarchies are constrained to a single thread
2157         if (threadData != parent->d_func()->threadData) {
2158             qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
2159             parent = nullptr;
2160             return;
2161         }
2162         parent->d_func()->children.append(q);
2163         if(sendChildEvents && parent->d_func()->receiveChildEvents) {
2164             if (!isWidget) {
2165                 QChildEvent e(QEvent::ChildAdded, q);
2166                 QCoreApplication::sendEvent(parent, &e);
2167             }
2168         }
2169     }
2170     if (!wasDeleted && !isDeletingChildren && declarativeData && QAbstractDeclarativeData::parentChanged)
2171         QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
2172 }
2173 
2174 /*!
2175     \fn void QObject::installEventFilter(QObject *filterObj)
2176 
2177     Installs an event filter \a filterObj on this object. For example:
2178     \snippet code/src_corelib_kernel_qobject.cpp 14
2179 
2180     An event filter is an object that receives all events that are
2181     sent to this object. The filter can either stop the event or
2182     forward it to this object. The event filter \a filterObj receives
2183     events via its eventFilter() function. The eventFilter() function
2184     must return true if the event should be filtered, (i.e. stopped);
2185     otherwise it must return false.
2186 
2187     If multiple event filters are installed on a single object, the
2188     filter that was installed last is activated first.
2189 
2190     Here's a \c KeyPressEater class that eats the key presses of its
2191     monitored objects:
2192 
2193     \snippet code/src_corelib_kernel_qobject.cpp 15
2194 
2195     And here's how to install it on two widgets:
2196 
2197     \snippet code/src_corelib_kernel_qobject.cpp 16
2198 
2199     The QShortcut class, for example, uses this technique to intercept
2200     shortcut key presses.
2201 
2202     \warning If you delete the receiver object in your eventFilter()
2203     function, be sure to return true. If you return false, Qt sends
2204     the event to the deleted object and the program will crash.
2205 
2206     Note that the filtering object must be in the same thread as this
2207     object. If \a filterObj is in a different thread, this function does
2208     nothing. If either \a filterObj or this object are moved to a different
2209     thread after calling this function, the event filter will not be
2210     called until both objects have the same thread affinity again (it
2211     is \e not removed).
2212 
2213     \sa removeEventFilter(), eventFilter(), event()
2214 */
2215 
installEventFilter(QObject * obj)2216 void QObject::installEventFilter(QObject *obj)
2217 {
2218     Q_D(QObject);
2219     if (!obj)
2220         return;
2221     if (d->threadData != obj->d_func()->threadData) {
2222         qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
2223         return;
2224     }
2225 
2226     if (!d->extraData)
2227         d->extraData = new QObjectPrivate::ExtraData;
2228 
2229     // clean up unused items in the list
2230     d->extraData->eventFilters.removeAll((QObject*)nullptr);
2231     d->extraData->eventFilters.removeAll(obj);
2232     d->extraData->eventFilters.prepend(obj);
2233 }
2234 
2235 /*!
2236     Removes an event filter object \a obj from this object. The
2237     request is ignored if such an event filter has not been installed.
2238 
2239     All event filters for this object are automatically removed when
2240     this object is destroyed.
2241 
2242     It is always safe to remove an event filter, even during event
2243     filter activation (i.e. from the eventFilter() function).
2244 
2245     \sa installEventFilter(), eventFilter(), event()
2246 */
2247 
removeEventFilter(QObject * obj)2248 void QObject::removeEventFilter(QObject *obj)
2249 {
2250     Q_D(QObject);
2251     if (d->extraData) {
2252         for (int i = 0; i < d->extraData->eventFilters.count(); ++i) {
2253             if (d->extraData->eventFilters.at(i) == obj)
2254                 d->extraData->eventFilters[i] = nullptr;
2255         }
2256     }
2257 }
2258 
2259 
2260 /*!
2261     \fn void QObject::destroyed(QObject *obj)
2262 
2263     This signal is emitted immediately before the object \a obj is
2264     destroyed, after any instances of QPointer have been notified,
2265     and cannot be blocked.
2266 
2267     All the objects's children are destroyed immediately after this
2268     signal is emitted.
2269 
2270     \sa deleteLater(), QPointer
2271 */
2272 
2273 /*!
2274     \threadsafe
2275 
2276     Schedules this object for deletion.
2277 
2278     The object will be deleted when control returns to the event
2279     loop. If the event loop is not running when this function is
2280     called (e.g. deleteLater() is called on an object before
2281     QCoreApplication::exec()), the object will be deleted once the
2282     event loop is started. If deleteLater() is called after the main event loop
2283     has stopped, the object will not be deleted.
2284     Since Qt 4.8, if deleteLater() is called on an object that lives in a
2285     thread with no running event loop, the object will be destroyed when the
2286     thread finishes.
2287 
2288     Note that entering and leaving a new event loop (e.g., by opening a modal
2289     dialog) will \e not perform the deferred deletion; for the object to be
2290     deleted, the control must return to the event loop from which deleteLater()
2291     was called. This does not apply to objects deleted while a previous, nested
2292     event loop was still running: the Qt event loop will delete those objects
2293     as soon as the new nested event loop starts.
2294 
2295     \b{Note:} It is safe to call this function more than once; when the
2296     first deferred deletion event is delivered, any pending events for the
2297     object are removed from the event queue.
2298 
2299     \sa destroyed(), QPointer
2300 */
deleteLater()2301 void QObject::deleteLater()
2302 {
2303     QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
2304 }
2305 
2306 /*!
2307     \fn QString QObject::tr(const char *sourceText, const char *disambiguation, int n)
2308     \reentrant
2309 
2310     Returns a translated version of \a sourceText, optionally based on a
2311     \a disambiguation string and value of \a n for strings containing plurals;
2312     otherwise returns QString::fromUtf8(\a sourceText) if no appropriate
2313     translated string is available.
2314 
2315     Example:
2316     \snippet ../widgets/mainwindows/sdi/mainwindow.cpp implicit tr context
2317     \dots
2318 
2319     If the same \a sourceText is used in different roles within the
2320     same context, an additional identifying string may be passed in
2321     \a disambiguation (\nullptr by default). In Qt 4.4 and earlier, this was
2322     the preferred way to pass comments to translators.
2323 
2324     Example:
2325 
2326     \snippet code/src_corelib_kernel_qobject.cpp 17
2327     \dots
2328 
2329     See \l{Writing Source Code for Translation} for a detailed description of
2330     Qt's translation mechanisms in general, and the
2331     \l{Writing Source Code for Translation#Disambiguation}{Disambiguation}
2332     section for information on disambiguation.
2333 
2334     \warning This method is reentrant only if all translators are
2335     installed \e before calling this method. Installing or removing
2336     translators while performing translations is not supported. Doing
2337     so will probably result in crashes or other undesirable behavior.
2338 
2339     \sa QCoreApplication::translate(), {Internationalization with Qt}
2340 */
2341 
2342 /*!
2343     \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
2344     \reentrant
2345     \obsolete
2346 
2347     Returns a translated version of \a sourceText, or
2348     QString::fromUtf8(\a sourceText) if there is no appropriate
2349     version. It is otherwise identical to tr(\a sourceText, \a
2350     disambiguation, \a n).
2351 
2352     \warning This method is reentrant only if all translators are
2353     installed \e before calling this method. Installing or removing
2354     translators while performing translations is not supported. Doing
2355     so will probably result in crashes or other undesirable behavior.
2356 
2357     \warning For portability reasons, we recommend that you use
2358     escape sequences for specifying non-ASCII characters in string
2359     literals to trUtf8(). For example:
2360 
2361     \snippet code/src_corelib_kernel_qobject.cpp 20
2362 
2363     \sa tr(), QCoreApplication::translate(), {Internationalization with Qt}
2364 */
2365 
2366 
2367 
2368 
2369 /*****************************************************************************
2370   Signals and slots
2371  *****************************************************************************/
2372 
2373 
qFlagLocation(const char * method)2374 const char *qFlagLocation(const char *method)
2375 {
2376     QThreadData *currentThreadData = QThreadData::current(false);
2377     if (currentThreadData != nullptr)
2378         currentThreadData->flaggedSignatures.store(method);
2379     return method;
2380 }
2381 
extract_code(const char * member)2382 static int extract_code(const char *member)
2383 {
2384     // extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
2385     return (((int)(*member) - '0') & 0x3);
2386 }
2387 
extract_location(const char * member)2388 static const char * extract_location(const char *member)
2389 {
2390     if (QThreadData::current()->flaggedSignatures.contains(member)) {
2391         // signature includes location information after the first null-terminator
2392         const char *location = member + qstrlen(member) + 1;
2393         if (*location != '\0')
2394             return location;
2395     }
2396     return nullptr;
2397 }
2398 
check_signal_macro(const QObject * sender,const char * signal,const char * func,const char * op)2399 static bool check_signal_macro(const QObject *sender, const char *signal,
2400                                 const char *func, const char *op)
2401 {
2402     int sigcode = extract_code(signal);
2403     if (sigcode != QSIGNAL_CODE) {
2404         if (sigcode == QSLOT_CODE)
2405             qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
2406                      func, op, sender->metaObject()->className(), signal+1);
2407         else
2408             qWarning("QObject::%s: Use the SIGNAL macro to %s %s::%s",
2409                      func, op, sender->metaObject()->className(), signal);
2410         return false;
2411     }
2412     return true;
2413 }
2414 
check_method_code(int code,const QObject * object,const char * method,const char * func)2415 static bool check_method_code(int code, const QObject *object,
2416                                const char *method, const char *func)
2417 {
2418     if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
2419         qWarning("QObject::%s: Use the SLOT or SIGNAL macro to "
2420                  "%s %s::%s", func, func, object->metaObject()->className(), method);
2421         return false;
2422     }
2423     return true;
2424 }
2425 
err_method_notfound(const QObject * object,const char * method,const char * func)2426 static void err_method_notfound(const QObject *object,
2427                                 const char *method, const char *func)
2428 {
2429     const char *type = "method";
2430     switch (extract_code(method)) {
2431         case QSLOT_CODE:   type = "slot";   break;
2432         case QSIGNAL_CODE: type = "signal"; break;
2433     }
2434     const char *loc = extract_location(method);
2435     if (strchr(method,')') == nullptr)                // common typing mistake
2436         qWarning("QObject::%s: Parentheses expected, %s %s::%s%s%s",
2437                  func, type, object->metaObject()->className(), method+1,
2438                  loc ? " in ": "", loc ? loc : "");
2439     else
2440         qWarning("QObject::%s: No such %s %s::%s%s%s",
2441                  func, type, object->metaObject()->className(), method+1,
2442                  loc ? " in ": "", loc ? loc : "");
2443 
2444 }
2445 
2446 
err_info_about_objects(const char * func,const QObject * sender,const QObject * receiver)2447 static void err_info_about_objects(const char * func,
2448                                     const QObject * sender,
2449                                     const QObject * receiver)
2450 {
2451     QString a = sender ? sender->objectName() : QString();
2452     QString b = receiver ? receiver->objectName() : QString();
2453     if (!a.isEmpty())
2454         qWarning("QObject::%s:  (sender name:   '%s')", func, a.toLocal8Bit().data());
2455     if (!b.isEmpty())
2456         qWarning("QObject::%s:  (receiver name: '%s')", func, b.toLocal8Bit().data());
2457 }
2458 
2459 /*!
2460     Returns a pointer to the object that sent the signal, if called in
2461     a slot activated by a signal; otherwise it returns \nullptr. The pointer
2462     is valid only during the execution of the slot that calls this
2463     function from this object's thread context.
2464 
2465     The pointer returned by this function becomes invalid if the
2466     sender is destroyed, or if the slot is disconnected from the
2467     sender's signal.
2468 
2469     \warning This function violates the object-oriented principle of
2470     modularity. However, getting access to the sender might be useful
2471     when many signals are connected to a single slot.
2472 
2473     \warning As mentioned above, the return value of this function is
2474     not valid when the slot is called via a Qt::DirectConnection from
2475     a thread different from this object's thread. Do not use this
2476     function in this type of scenario.
2477 
2478     \sa senderSignalIndex()
2479 */
2480 
sender() const2481 QObject *QObject::sender() const
2482 {
2483     Q_D(const QObject);
2484 
2485     QBasicMutexLocker locker(signalSlotLock(this));
2486     QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2487     if (!cd || !cd->currentSender)
2488         return nullptr;
2489 
2490     for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) {
2491         if (c->sender == cd->currentSender->sender)
2492             return cd->currentSender->sender;
2493     }
2494 
2495     return nullptr;
2496 }
2497 
2498 /*!
2499     \since 4.8
2500 
2501     Returns the meta-method index of the signal that called the currently
2502     executing slot, which is a member of the class returned by sender().
2503     If called outside of a slot activated by a signal, -1 is returned.
2504 
2505     For signals with default parameters, this function will always return
2506     the index with all parameters, regardless of which was used with
2507     connect(). For example, the signal \c {destroyed(QObject *obj = \nullptr)}
2508     will have two different indexes (with and without the parameter), but
2509     this function will always return the index with a parameter. This does
2510     not apply when overloading signals with different parameters.
2511 
2512     \warning This function violates the object-oriented principle of
2513     modularity. However, getting access to the signal index might be useful
2514     when many signals are connected to a single slot.
2515 
2516     \warning The return value of this function is not valid when the slot
2517     is called via a Qt::DirectConnection from a thread different from this
2518     object's thread. Do not use this function in this type of scenario.
2519 
2520     \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method()
2521 */
2522 
senderSignalIndex() const2523 int QObject::senderSignalIndex() const
2524 {
2525     Q_D(const QObject);
2526 
2527     QBasicMutexLocker locker(signalSlotLock(this));
2528     QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2529     if (!cd || !cd->currentSender)
2530         return -1;
2531 
2532     for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) {
2533         if (c->sender == cd->currentSender->sender) {
2534             // Convert from signal range to method range
2535             return QMetaObjectPrivate::signal(c->sender->metaObject(), cd->currentSender->signal).methodIndex();
2536         }
2537     }
2538 
2539     return -1;
2540 }
2541 
2542 /*!
2543     Returns the number of receivers connected to the \a signal.
2544 
2545     Since both slots and signals can be used as receivers for signals,
2546     and the same connections can be made many times, the number of
2547     receivers is the same as the number of connections made from this
2548     signal.
2549 
2550     When calling this function, you can use the \c SIGNAL() macro to
2551     pass a specific signal:
2552 
2553     \snippet code/src_corelib_kernel_qobject.cpp 21
2554 
2555     \warning This function violates the object-oriented principle of
2556     modularity. However, it might be useful when you need to perform
2557     expensive initialization only if something is connected to a
2558     signal.
2559 
2560     \sa isSignalConnected()
2561 */
2562 
receivers(const char * signal) const2563 int QObject::receivers(const char *signal) const
2564 {
2565     Q_D(const QObject);
2566     int receivers = 0;
2567     if (signal) {
2568         QByteArray signal_name = QMetaObject::normalizedSignature(signal);
2569         signal = signal_name;
2570 #ifndef QT_NO_DEBUG
2571         if (!check_signal_macro(this, signal, "receivers", "bind"))
2572             return 0;
2573 #endif
2574         signal++; // skip code
2575         int signal_index = d->signalIndex(signal);
2576         if (signal_index < 0) {
2577 #ifndef QT_NO_DEBUG
2578             err_method_notfound(this, signal-1, "receivers");
2579 #endif
2580             return 0;
2581         }
2582 
2583         if (!d->isSignalConnected(signal_index))
2584             return receivers;
2585 
2586         if (d->declarativeData && QAbstractDeclarativeData::receivers) {
2587             receivers += QAbstractDeclarativeData::receivers(d->declarativeData, this,
2588                                                              signal_index);
2589         }
2590 
2591         QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2592         QBasicMutexLocker locker(signalSlotLock(this));
2593         if (cd && signal_index < cd->signalVectorCount()) {
2594             const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
2595             while (c) {
2596                 receivers += c->receiver.loadRelaxed() ? 1 : 0;
2597                 c = c->nextConnectionList.loadRelaxed();
2598             }
2599         }
2600     }
2601     return receivers;
2602 }
2603 
2604 /*!
2605     \since 5.0
2606     Returns \c true if the \a signal is connected to at least one receiver,
2607     otherwise returns \c false.
2608 
2609     \a signal must be a signal member of this object, otherwise the behaviour
2610     is undefined.
2611 
2612     \snippet code/src_corelib_kernel_qobject.cpp 49
2613 
2614     As the code snippet above illustrates, you can use this function
2615     to avoid emitting a signal that nobody listens to.
2616 
2617     \warning This function violates the object-oriented principle of
2618     modularity. However, it might be useful when you need to perform
2619     expensive initialization only if something is connected to a
2620     signal.
2621 */
isSignalConnected(const QMetaMethod & signal) const2622 bool QObject::isSignalConnected(const QMetaMethod &signal) const
2623 {
2624     Q_D(const QObject);
2625     if (!signal.mobj)
2626         return false;
2627 
2628     Q_ASSERT_X(signal.mobj->cast(this) && signal.methodType() == QMetaMethod::Signal,
2629                "QObject::isSignalConnected" , "the parameter must be a signal member of the object");
2630     uint signalIndex = (signal.handle - QMetaObjectPrivate::get(signal.mobj)->methodData)/5;
2631 
2632     if (signal.mobj->d.data[signal.handle + 4] & MethodCloned)
2633         signalIndex = QMetaObjectPrivate::originalClone(signal.mobj, signalIndex);
2634 
2635     signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj);
2636 
2637     QBasicMutexLocker locker(signalSlotLock(this));
2638     return d->isSignalConnected(signalIndex, true);
2639 }
2640 
2641 /*!
2642     \internal
2643 
2644     This helper function calculates signal and method index for the given
2645     member in the specified class.
2646 
2647     \list
2648     \li If member.mobj is \nullptr then both signalIndex and methodIndex are set to -1.
2649 
2650     \li If specified member is not a member of obj instance class (or one of
2651     its parent classes) then both signalIndex and methodIndex are set to -1.
2652     \endlist
2653 
2654     This function is used by QObject::connect and QObject::disconnect which
2655     are working with QMetaMethod.
2656 
2657     \a signalIndex is set to the signal index of member. If the member
2658     specified is not signal this variable is set to -1.
2659 
2660     \a methodIndex is set to the method index of the member. If the
2661     member is not a method of the object specified by the \a obj argument this
2662     variable is set to -1.
2663 */
memberIndexes(const QObject * obj,const QMetaMethod & member,int * signalIndex,int * methodIndex)2664 void QMetaObjectPrivate::memberIndexes(const QObject *obj,
2665                                        const QMetaMethod &member,
2666                                        int *signalIndex, int *methodIndex)
2667 {
2668     *signalIndex = -1;
2669     *methodIndex = -1;
2670     if (!obj || !member.mobj)
2671         return;
2672     const QMetaObject *m = obj->metaObject();
2673     // Check that member is member of obj class
2674     while (m != nullptr && m != member.mobj)
2675         m = m->d.superdata;
2676     if (!m)
2677         return;
2678     *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5;
2679 
2680     int signalOffset;
2681     int methodOffset;
2682     computeOffsets(m, &signalOffset, &methodOffset);
2683 
2684     *methodIndex += methodOffset;
2685     if (member.methodType() == QMetaMethod::Signal) {
2686         *signalIndex = originalClone(m, *signalIndex);
2687         *signalIndex += signalOffset;
2688     } else {
2689         *signalIndex = -1;
2690     }
2691 }
2692 
2693 #ifndef QT_NO_DEBUG
check_and_warn_compat(const QMetaObject * sender,const QMetaMethod & signal,const QMetaObject * receiver,const QMetaMethod & method)2694 static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal,
2695                                          const QMetaObject *receiver, const QMetaMethod &method)
2696 {
2697     if (signal.attributes() & QMetaMethod::Compatibility) {
2698         if (!(method.attributes() & QMetaMethod::Compatibility))
2699             qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
2700                      sender->className(), signal.methodSignature().constData());
2701     } else if ((method.attributes() & QMetaMethod::Compatibility) &&
2702                method.methodType() == QMetaMethod::Signal) {
2703         qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
2704                  sender->className(), signal.methodSignature().constData(),
2705                  receiver->className(), method.methodSignature().constData());
2706     }
2707 }
2708 #endif
2709 
2710 /*!
2711     \threadsafe
2712 
2713     Creates a connection of the given \a type from the \a signal in
2714     the \a sender object to the \a method in the \a receiver object.
2715     Returns a handle to the connection that can be used to disconnect
2716     it later.
2717 
2718     You must use the \c SIGNAL() and \c SLOT() macros when specifying
2719     the \a signal and the \a method, for example:
2720 
2721     \snippet code/src_corelib_kernel_qobject.cpp 22
2722 
2723     This example ensures that the label always displays the current
2724     scroll bar value. Note that the signal and slots parameters must not
2725     contain any variable names, only the type. E.g. the following would
2726     not work and return false:
2727 
2728     \snippet code/src_corelib_kernel_qobject.cpp 23
2729 
2730     A signal can also be connected to another signal:
2731 
2732     \snippet code/src_corelib_kernel_qobject.cpp 24
2733 
2734     In this example, the \c MyWidget constructor relays a signal from
2735     a private member variable, and makes it available under a name
2736     that relates to \c MyWidget.
2737 
2738     A signal can be connected to many slots and signals. Many signals
2739     can be connected to one slot.
2740 
2741     If a signal is connected to several slots, the slots are activated
2742     in the same order in which the connections were made, when the
2743     signal is emitted.
2744 
2745     The function returns a QMetaObject::Connection that represents
2746     a handle to a connection if it successfully
2747     connects the signal to the slot. The connection handle will be invalid
2748     if it cannot create the connection, for example, if QObject is unable
2749     to verify the existence of either \a signal or \a method, or if their
2750     signatures aren't compatible.
2751     You can check if the handle is valid by casting it to a bool.
2752 
2753     By default, a signal is emitted for every connection you make;
2754     two signals are emitted for duplicate connections. You can break
2755     all of these connections with a single disconnect() call.
2756     If you pass the Qt::UniqueConnection \a type, the connection will only
2757     be made if it is not a duplicate. If there is already a duplicate
2758     (exact same signal to the exact same slot on the same objects),
2759     the connection will fail and connect will return an invalid QMetaObject::Connection.
2760 
2761     \note Qt::UniqueConnections do not work for lambdas, non-member functions
2762     and functors; they only apply to connecting to member functions.
2763 
2764     The optional \a type parameter describes the type of connection
2765     to establish. In particular, it determines whether a particular
2766     signal is delivered to a slot immediately or queued for delivery
2767     at a later time. If the signal is queued, the parameters must be
2768     of types that are known to Qt's meta-object system, because Qt
2769     needs to copy the arguments to store them in an event behind the
2770     scenes. If you try to use a queued connection and get the error
2771     message
2772 
2773     \snippet code/src_corelib_kernel_qobject.cpp 25
2774 
2775     call qRegisterMetaType() to register the data type before you
2776     establish the connection.
2777 
2778     \sa disconnect(), sender(), qRegisterMetaType(), Q_DECLARE_METATYPE(),
2779     {Differences between String-Based and Functor-Based Connections}
2780 */
connect(const QObject * sender,const char * signal,const QObject * receiver,const char * method,Qt::ConnectionType type)2781 QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
2782                                      const QObject *receiver, const char *method,
2783                                      Qt::ConnectionType type)
2784 {
2785     if (sender == nullptr || receiver == nullptr || signal == nullptr || method == nullptr) {
2786         qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2787                  sender ? sender->metaObject()->className() : "(nullptr)",
2788                  (signal && *signal) ? signal+1 : "(nullptr)",
2789                  receiver ? receiver->metaObject()->className() : "(nullptr)",
2790                  (method && *method) ? method+1 : "(nullptr)");
2791         return QMetaObject::Connection(nullptr);
2792     }
2793     QByteArray tmp_signal_name;
2794 
2795     if (!check_signal_macro(sender, signal, "connect", "bind"))
2796         return QMetaObject::Connection(nullptr);
2797     const QMetaObject *smeta = sender->metaObject();
2798     const char *signal_arg = signal;
2799     ++signal; //skip code
2800     QArgumentTypeArray signalTypes;
2801     Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
2802     QByteArray signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
2803     int signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2804             &smeta, signalName, signalTypes.size(), signalTypes.constData());
2805     if (signal_index < 0) {
2806         // check for normalized signatures
2807         tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
2808         signal = tmp_signal_name.constData() + 1;
2809 
2810         signalTypes.clear();
2811         signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
2812         smeta = sender->metaObject();
2813         signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2814                 &smeta, signalName, signalTypes.size(), signalTypes.constData());
2815     }
2816     if (signal_index < 0) {
2817         err_method_notfound(sender, signal_arg, "connect");
2818         err_info_about_objects("connect", sender, receiver);
2819         return QMetaObject::Connection(nullptr);
2820     }
2821     signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
2822     signal_index += QMetaObjectPrivate::signalOffset(smeta);
2823 
2824     QByteArray tmp_method_name;
2825     int membcode = extract_code(method);
2826 
2827     if (!check_method_code(membcode, receiver, method, "connect"))
2828         return QMetaObject::Connection(nullptr);
2829     const char *method_arg = method;
2830     ++method; // skip code
2831 
2832     QArgumentTypeArray methodTypes;
2833     QByteArray methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
2834     const QMetaObject *rmeta = receiver->metaObject();
2835     int method_index_relative = -1;
2836     Q_ASSERT(QMetaObjectPrivate::get(rmeta)->revision >= 7);
2837     switch (membcode) {
2838     case QSLOT_CODE:
2839         method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
2840                 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2841         break;
2842     case QSIGNAL_CODE:
2843         method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
2844                 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2845         break;
2846     }
2847     if (method_index_relative < 0) {
2848         // check for normalized methods
2849         tmp_method_name = QMetaObject::normalizedSignature(method);
2850         method = tmp_method_name.constData();
2851 
2852         methodTypes.clear();
2853         methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
2854         // rmeta may have been modified above
2855         rmeta = receiver->metaObject();
2856         switch (membcode) {
2857         case QSLOT_CODE:
2858             method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
2859                     &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2860             break;
2861         case QSIGNAL_CODE:
2862             method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
2863                     &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2864             break;
2865         }
2866     }
2867 
2868     if (method_index_relative < 0) {
2869         err_method_notfound(receiver, method_arg, "connect");
2870         err_info_about_objects("connect", sender, receiver);
2871         return QMetaObject::Connection(nullptr);
2872     }
2873 
2874     if (!QMetaObjectPrivate::checkConnectArgs(signalTypes.size(), signalTypes.constData(),
2875                                               methodTypes.size(), methodTypes.constData())) {
2876         qWarning("QObject::connect: Incompatible sender/receiver arguments"
2877                  "\n        %s::%s --> %s::%s",
2878                  sender->metaObject()->className(), signal,
2879                  receiver->metaObject()->className(), method);
2880         return QMetaObject::Connection(nullptr);
2881     }
2882 
2883     int *types = nullptr;
2884     if ((type == Qt::QueuedConnection)
2885             && !(types = queuedConnectionTypes(signalTypes.constData(), signalTypes.size()))) {
2886         return QMetaObject::Connection(nullptr);
2887     }
2888 
2889 #ifndef QT_NO_DEBUG
2890     QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
2891     QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
2892     check_and_warn_compat(smeta, smethod, rmeta, rmethod);
2893 #endif
2894     QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
2895         sender, signal_index, smeta, receiver, method_index_relative, rmeta ,type, types));
2896     return handle;
2897 }
2898 
2899 /*!
2900     \since 4.8
2901 
2902     Creates a connection of the given \a type from the \a signal in
2903     the \a sender object to the \a method in the \a receiver object.
2904     Returns a handle to the connection that can be used to disconnect
2905     it later.
2906 
2907     The Connection handle will be invalid  if it cannot create the
2908     connection, for example, the parameters were invalid.
2909     You can check if the QMetaObject::Connection is valid by casting it to a bool.
2910 
2911     This function works in the same way as
2912     \c {connect(const QObject *sender, const char *signal,
2913             const QObject *receiver, const char *method,
2914             Qt::ConnectionType type)}
2915     but it uses QMetaMethod to specify signal and method.
2916 
2917     \sa connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
2918  */
connect(const QObject * sender,const QMetaMethod & signal,const QObject * receiver,const QMetaMethod & method,Qt::ConnectionType type)2919 QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal,
2920                                      const QObject *receiver, const QMetaMethod &method,
2921                                      Qt::ConnectionType type)
2922 {
2923     if (sender == nullptr
2924             || receiver == nullptr
2925             || signal.methodType() != QMetaMethod::Signal
2926             || method.methodType() == QMetaMethod::Constructor) {
2927         qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2928                  sender ? sender->metaObject()->className() : "(nullptr)",
2929                  signal.methodSignature().constData(),
2930                  receiver ? receiver->metaObject()->className() : "(nullptr)",
2931                  method.methodSignature().constData() );
2932         return QMetaObject::Connection(nullptr);
2933     }
2934 
2935     int signal_index;
2936     int method_index;
2937     {
2938         int dummy;
2939         QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
2940         QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
2941     }
2942 
2943     const QMetaObject *smeta = sender->metaObject();
2944     const QMetaObject *rmeta = receiver->metaObject();
2945     if (signal_index == -1) {
2946         qWarning("QObject::connect: Can't find signal %s on instance of class %s",
2947                  signal.methodSignature().constData(), smeta->className());
2948         return QMetaObject::Connection(nullptr);
2949     }
2950     if (method_index == -1) {
2951         qWarning("QObject::connect: Can't find method %s on instance of class %s",
2952                  method.methodSignature().constData(), rmeta->className());
2953         return QMetaObject::Connection(nullptr);
2954     }
2955 
2956     if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) {
2957         qWarning("QObject::connect: Incompatible sender/receiver arguments"
2958                  "\n        %s::%s --> %s::%s",
2959                  smeta->className(), signal.methodSignature().constData(),
2960                  rmeta->className(), method.methodSignature().constData());
2961         return QMetaObject::Connection(nullptr);
2962     }
2963 
2964     int *types = nullptr;
2965     if ((type == Qt::QueuedConnection)
2966             && !(types = queuedConnectionTypes(signal.parameterTypes())))
2967         return QMetaObject::Connection(nullptr);
2968 
2969 #ifndef QT_NO_DEBUG
2970     check_and_warn_compat(smeta, signal, rmeta, method);
2971 #endif
2972     QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
2973         sender, signal_index, signal.enclosingMetaObject(), receiver, method_index, nullptr, type, types));
2974     return handle;
2975 }
2976 
2977 /*!
2978     \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
2979     \overload connect()
2980     \threadsafe
2981 
2982     Connects \a signal from the \a sender object to this object's \a
2983     method.
2984 
2985     Equivalent to connect(\a sender, \a signal, \c this, \a method, \a type).
2986 
2987     Every connection you make emits a signal, so duplicate connections emit
2988     two signals. You can break a connection using disconnect().
2989 
2990     \sa disconnect()
2991 */
2992 
2993 /*!
2994     \threadsafe
2995 
2996     Disconnects \a signal in object \a sender from \a method in object
2997     \a receiver. Returns \c true if the connection is successfully broken;
2998     otherwise returns \c false.
2999 
3000     A signal-slot connection is removed when either of the objects
3001     involved are destroyed.
3002 
3003     disconnect() is typically used in three ways, as the following
3004     examples demonstrate.
3005     \list 1
3006     \li Disconnect everything connected to an object's signals:
3007 
3008        \snippet code/src_corelib_kernel_qobject.cpp 26
3009 
3010        equivalent to the non-static overloaded function
3011 
3012        \snippet code/src_corelib_kernel_qobject.cpp 27
3013 
3014     \li Disconnect everything connected to a specific signal:
3015 
3016        \snippet code/src_corelib_kernel_qobject.cpp 28
3017 
3018        equivalent to the non-static overloaded function
3019 
3020        \snippet code/src_corelib_kernel_qobject.cpp 29
3021 
3022     \li Disconnect a specific receiver:
3023 
3024        \snippet code/src_corelib_kernel_qobject.cpp 30
3025 
3026        equivalent to the non-static overloaded function
3027 
3028        \snippet code/src_corelib_kernel_qobject.cpp 31
3029 
3030     \endlist
3031 
3032     \nullptr may be used as a wildcard, meaning "any signal", "any receiving
3033     object", or "any slot in the receiving object", respectively.
3034 
3035     The \a sender may never be \nullptr. (You cannot disconnect signals
3036     from more than one object in a single call.)
3037 
3038     If \a signal is \nullptr, it disconnects \a receiver and \a method from
3039     any signal. If not, only the specified signal is disconnected.
3040 
3041     If \a receiver is \nullptr, it disconnects anything connected to \a
3042     signal. If not, slots in objects other than \a receiver are not
3043     disconnected.
3044 
3045     If \a method is \nullptr, it disconnects anything that is connected to \a
3046     receiver. If not, only slots named \a method will be disconnected,
3047     and all other slots are left alone. The \a method must be \nullptr
3048     if \a receiver is left out, so you cannot disconnect a
3049     specifically-named slot on all objects.
3050 
3051     \sa connect()
3052 */
disconnect(const QObject * sender,const char * signal,const QObject * receiver,const char * method)3053 bool QObject::disconnect(const QObject *sender, const char *signal,
3054                          const QObject *receiver, const char *method)
3055 {
3056     if (sender == nullptr || (receiver == nullptr && method != nullptr)) {
3057         qWarning("QObject::disconnect: Unexpected nullptr parameter");
3058         return false;
3059     }
3060 
3061     const char *signal_arg = signal;
3062     QByteArray signal_name;
3063     bool signal_found = false;
3064     if (signal) {
3065         QT_TRY {
3066             signal_name = QMetaObject::normalizedSignature(signal);
3067             signal = signal_name.constData();
3068         } QT_CATCH (const std::bad_alloc &) {
3069             // if the signal is already normalized, we can continue.
3070             if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
3071                 QT_RETHROW;
3072         }
3073 
3074         if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
3075             return false;
3076         signal++; // skip code
3077     }
3078 
3079     QByteArray method_name;
3080     const char *method_arg = method;
3081     int membcode = -1;
3082     bool method_found = false;
3083     if (method) {
3084         QT_TRY {
3085             method_name = QMetaObject::normalizedSignature(method);
3086             method = method_name.constData();
3087         } QT_CATCH(const std::bad_alloc &) {
3088             // if the method is already normalized, we can continue.
3089             if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
3090                 QT_RETHROW;
3091         }
3092 
3093         membcode = extract_code(method);
3094         if (!check_method_code(membcode, receiver, method, "disconnect"))
3095             return false;
3096         method++; // skip code
3097     }
3098 
3099     /* We now iterate through all the sender's and receiver's meta
3100      * objects in order to also disconnect possibly shadowed signals
3101      * and slots with the same signature.
3102     */
3103     bool res = false;
3104     const QMetaObject *smeta = sender->metaObject();
3105     QByteArray signalName;
3106     QArgumentTypeArray signalTypes;
3107     Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
3108     if (signal)
3109         signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
3110     QByteArray methodName;
3111     QArgumentTypeArray methodTypes;
3112     Q_ASSERT(!receiver || QMetaObjectPrivate::get(receiver->metaObject())->revision >= 7);
3113     if (method)
3114         methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
3115     do {
3116         int signal_index = -1;
3117         if (signal) {
3118             signal_index = QMetaObjectPrivate::indexOfSignalRelative(
3119                         &smeta, signalName, signalTypes.size(), signalTypes.constData());
3120             if (signal_index < 0)
3121                 break;
3122             signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
3123             signal_index += QMetaObjectPrivate::signalOffset(smeta);
3124             signal_found = true;
3125         }
3126 
3127         if (!method) {
3128             res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, -1, nullptr);
3129         } else {
3130             const QMetaObject *rmeta = receiver->metaObject();
3131             do {
3132                 int method_index = QMetaObjectPrivate::indexOfMethod(
3133                             rmeta, methodName, methodTypes.size(), methodTypes.constData());
3134                 if (method_index >= 0)
3135                     while (method_index < rmeta->methodOffset())
3136                             rmeta = rmeta->superClass();
3137                 if (method_index < 0)
3138                     break;
3139                 res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, method_index, nullptr);
3140                 method_found = true;
3141             } while ((rmeta = rmeta->superClass()));
3142         }
3143     } while (signal && (smeta = smeta->superClass()));
3144 
3145     if (signal && !signal_found) {
3146         err_method_notfound(sender, signal_arg, "disconnect");
3147         err_info_about_objects("disconnect", sender, receiver);
3148     } else if (method && !method_found) {
3149         err_method_notfound(receiver, method_arg, "disconnect");
3150         err_info_about_objects("disconnect", sender, receiver);
3151     }
3152     if (res) {
3153         if (!signal)
3154             const_cast<QObject*>(sender)->disconnectNotify(QMetaMethod());
3155     }
3156     return res;
3157 }
3158 
3159 /*!
3160     \since 4.8
3161 
3162     Disconnects \a signal in object \a sender from \a method in object
3163     \a receiver. Returns \c true if the connection is successfully broken;
3164     otherwise returns \c false.
3165 
3166     This function provides the same possibilities like
3167     \c {disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) }
3168     but uses QMetaMethod to represent the signal and the method to be disconnected.
3169 
3170     Additionally this function returns false and no signals and slots disconnected
3171     if:
3172     \list 1
3173 
3174         \li \a signal is not a member of sender class or one of its parent classes.
3175 
3176         \li \a method is not a member of receiver class or one of its parent classes.
3177 
3178         \li \a signal instance represents not a signal.
3179 
3180     \endlist
3181 
3182     QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object".
3183     In the same way \nullptr can be used for \a receiver in the meaning "any receiving object".
3184     In this case method should also be QMetaMethod(). \a sender parameter should be never \nullptr.
3185 
3186     \sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
3187  */
disconnect(const QObject * sender,const QMetaMethod & signal,const QObject * receiver,const QMetaMethod & method)3188 bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
3189                          const QObject *receiver, const QMetaMethod &method)
3190 {
3191     if (sender == nullptr || (receiver == nullptr && method.mobj != nullptr)) {
3192         qWarning("QObject::disconnect: Unexpected nullptr parameter");
3193         return false;
3194     }
3195     if (signal.mobj) {
3196         if(signal.methodType() != QMetaMethod::Signal) {
3197             qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
3198                      "disconnect","unbind",
3199                      sender->metaObject()->className(), signal.methodSignature().constData());
3200             return false;
3201         }
3202     }
3203     if (method.mobj) {
3204         if(method.methodType() == QMetaMethod::Constructor) {
3205             qWarning("QObject::disconnect: cannot use constructor as argument %s::%s",
3206                      receiver->metaObject()->className(), method.methodSignature().constData());
3207             return false;
3208         }
3209     }
3210 
3211     // Reconstructing SIGNAL() macro result for signal.methodSignature() string
3212     QByteArray signalSignature;
3213     if (signal.mobj) {
3214         signalSignature.reserve(signal.methodSignature().size()+1);
3215         signalSignature.append((char)(QSIGNAL_CODE + '0'));
3216         signalSignature.append(signal.methodSignature());
3217     }
3218 
3219     int signal_index;
3220     int method_index;
3221     {
3222         int dummy;
3223         QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
3224         QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
3225     }
3226     // If we are here sender is not nullptr. If signal is not nullptr while signal_index
3227     // is -1 then this signal is not a member of sender.
3228     if (signal.mobj && signal_index == -1) {
3229         qWarning("QObject::disconnect: signal %s not found on class %s",
3230                  signal.methodSignature().constData(), sender->metaObject()->className());
3231         return false;
3232     }
3233     // If this condition is true then method is not a member of receiver.
3234     if (receiver && method.mobj && method_index == -1) {
3235         qWarning("QObject::disconnect: method %s not found on class %s",
3236                  method.methodSignature().constData(), receiver->metaObject()->className());
3237         return false;
3238     }
3239 
3240     if (!QMetaObjectPrivate::disconnect(sender, signal_index, signal.mobj, receiver, method_index, nullptr))
3241         return false;
3242 
3243     if (!signal.isValid()) {
3244         // The signal is a wildcard, meaning all signals were disconnected.
3245         // QMetaObjectPrivate::disconnect() doesn't call disconnectNotify()
3246         // per connection in this case. Call it once now, with an invalid
3247         // QMetaMethod as argument, as documented.
3248         const_cast<QObject*>(sender)->disconnectNotify(signal);
3249     }
3250     return true;
3251 }
3252 
3253 /*!
3254     \threadsafe
3255 
3256     \fn bool QObject::disconnect(const char *signal, const QObject *receiver, const char *method) const
3257     \overload disconnect()
3258 
3259     Disconnects \a signal from \a method of \a receiver.
3260 
3261     A signal-slot connection is removed when either of the objects
3262     involved are destroyed.
3263 */
3264 
3265 /*!
3266     \fn bool QObject::disconnect(const QObject *receiver, const char *method) const
3267     \overload disconnect()
3268 
3269     Disconnects all signals in this object from \a receiver's \a
3270     method.
3271 
3272     A signal-slot connection is removed when either of the objects
3273     involved are destroyed.
3274 */
3275 
3276 
3277 /*!
3278     \since 5.0
3279 
3280     This virtual function is called when something has been connected
3281     to \a signal in this object.
3282 
3283     If you want to compare \a signal with a specific signal, you can
3284     use QMetaMethod::fromSignal() as follows:
3285 
3286     \snippet code/src_corelib_kernel_qobject.cpp 32
3287 
3288     \warning This function violates the object-oriented principle of
3289     modularity. However, it might be useful when you need to perform
3290     expensive initialization only if something is connected to a
3291     signal.
3292 
3293     \warning This function is called from the thread which performs the
3294     connection, which may be a different thread from the thread in
3295     which this object lives.
3296 
3297     \sa connect(), disconnectNotify()
3298 */
3299 
connectNotify(const QMetaMethod & signal)3300 void QObject::connectNotify(const QMetaMethod &signal)
3301 {
3302     Q_UNUSED(signal);
3303 }
3304 
3305 /*!
3306     \since 5.0
3307 
3308     This virtual function is called when something has been
3309     disconnected from \a signal in this object.
3310 
3311     See connectNotify() for an example of how to compare
3312     \a signal with a specific signal.
3313 
3314     If all signals were disconnected from this object (e.g., the
3315     signal argument to disconnect() was \nullptr), disconnectNotify()
3316     is only called once, and the \a signal will be an invalid
3317     QMetaMethod (QMetaMethod::isValid() returns \c false).
3318 
3319     \warning This function violates the object-oriented principle of
3320     modularity. However, it might be useful for optimizing access to
3321     expensive resources.
3322 
3323     \warning This function is called from the thread which performs the
3324     disconnection, which may be a different thread from the thread in
3325     which this object lives. This function may also be called with a QObject
3326     internal mutex locked. It is therefore not allowed to re-enter any
3327     of any QObject functions from your reimplementation and if you lock
3328     a mutex in your reimplementation, make sure that you don't call QObject
3329     functions with that mutex held in other places or it will result in
3330     a deadlock.
3331 
3332     \sa disconnect(), connectNotify()
3333 */
3334 
disconnectNotify(const QMetaMethod & signal)3335 void QObject::disconnectNotify(const QMetaMethod &signal)
3336 {
3337     Q_UNUSED(signal);
3338 }
3339 
3340 /*
3341     \internal
3342     convert a signal index from the method range to the signal range
3343  */
methodIndexToSignalIndex(const QMetaObject ** base,int signal_index)3344 static int methodIndexToSignalIndex(const QMetaObject **base, int signal_index)
3345 {
3346     if (signal_index < 0)
3347         return signal_index;
3348     const QMetaObject *metaObject = *base;
3349     while (metaObject && metaObject->methodOffset() > signal_index)
3350         metaObject = metaObject->superClass();
3351 
3352     if (metaObject) {
3353         int signalOffset, methodOffset;
3354         computeOffsets(metaObject, &signalOffset, &methodOffset);
3355         if (signal_index < metaObject->methodCount())
3356             signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
3357         else
3358             signal_index = signal_index - methodOffset + signalOffset;
3359         *base = metaObject;
3360     }
3361     return signal_index;
3362 }
3363 
3364 /*!
3365    \internal
3366    \a types is a 0-terminated vector of meta types for queued
3367    connections.
3368 
3369    if \a signal_index is -1, then we effectively connect *all* signals
3370    from the sender to the receiver's slot
3371  */
connect(const QObject * sender,int signal_index,const QObject * receiver,int method_index,int type,int * types)3372 QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_index,
3373                                           const QObject *receiver, int method_index, int type, int *types)
3374 {
3375     const QMetaObject *smeta = sender->metaObject();
3376     signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3377     return Connection(QMetaObjectPrivate::connect(sender, signal_index, smeta,
3378                                        receiver, method_index,
3379                                        nullptr, //FIXME, we could speed this connection up by computing the relative index
3380                                        type, types));
3381 }
3382 
3383 /*!
3384     \internal
3385    Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3386 
3387     method_index is relative to the rmeta metaobject, if rmeta is \nullptr, then it is absolute index
3388 
3389     the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection
3390  */
connect(const QObject * sender,int signal_index,const QMetaObject * smeta,const QObject * receiver,int method_index,const QMetaObject * rmeta,int type,int * types)3391 QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
3392                                  int signal_index, const QMetaObject *smeta,
3393                                  const QObject *receiver, int method_index,
3394                                  const QMetaObject *rmeta, int type, int *types)
3395 {
3396     QObject *s = const_cast<QObject *>(sender);
3397     QObject *r = const_cast<QObject *>(receiver);
3398 
3399     int method_offset = rmeta ? rmeta->methodOffset() : 0;
3400     Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6);
3401     QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : nullptr;
3402 
3403     QOrderedMutexLocker locker(signalSlotLock(sender),
3404                                signalSlotLock(receiver));
3405 
3406     QObjectPrivate::ConnectionData *scd  = QObjectPrivate::get(s)->connections.loadRelaxed();
3407     if (type & Qt::UniqueConnection && scd) {
3408         if (scd->signalVectorCount() > signal_index) {
3409             const QObjectPrivate::Connection *c2 = scd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
3410 
3411             int method_index_absolute = method_index + method_offset;
3412 
3413             while (c2) {
3414                 if (!c2->isSlotObject && c2->receiver.loadRelaxed() == receiver && c2->method() == method_index_absolute)
3415                     return nullptr;
3416                 c2 = c2->nextConnectionList.loadRelaxed();
3417             }
3418         }
3419         type &= Qt::UniqueConnection - 1;
3420     }
3421 
3422     std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
3423     c->sender = s;
3424     c->signal_index = signal_index;
3425     c->receiver.storeRelaxed(r);
3426     QThreadData *td = r->d_func()->threadData;
3427     td->ref();
3428     c->receiverThreadData.storeRelaxed(td);
3429     c->method_relative = method_index;
3430     c->method_offset = method_offset;
3431     c->connectionType = type;
3432     c->isSlotObject = false;
3433     c->argumentTypes.storeRelaxed(types);
3434     c->callFunction = callFunction;
3435 
3436     QObjectPrivate::get(s)->addConnection(signal_index, c.get());
3437 
3438     locker.unlock();
3439     QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
3440     if (smethod.isValid())
3441         s->connectNotify(smethod);
3442 
3443     return c.release();
3444 }
3445 
3446 /*!
3447     \internal
3448  */
disconnect(const QObject * sender,int signal_index,const QObject * receiver,int method_index)3449 bool QMetaObject::disconnect(const QObject *sender, int signal_index,
3450                              const QObject *receiver, int method_index)
3451 {
3452     const QMetaObject *smeta = sender->metaObject();
3453     signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3454     return QMetaObjectPrivate::disconnect(sender, signal_index, smeta,
3455                                           receiver, method_index, nullptr);
3456 }
3457 
3458 /*!
3459     \internal
3460 
3461 Disconnect a single signal connection.  If QMetaObject::connect() has been called
3462 multiple times for the same sender, signal_index, receiver and method_index only
3463 one of these connections will be removed.
3464  */
disconnectOne(const QObject * sender,int signal_index,const QObject * receiver,int method_index)3465 bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
3466                                 const QObject *receiver, int method_index)
3467 {
3468     const QMetaObject *smeta = sender->metaObject();
3469     signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3470     return QMetaObjectPrivate::disconnect(sender, signal_index, smeta,
3471                                           receiver, method_index, nullptr,
3472                                           QMetaObjectPrivate::DisconnectOne);
3473 }
3474 
3475 /*!
3476     \internal
3477     Helper function to remove the connection from the senders list and set the receivers to \nullptr
3478  */
disconnectHelper(QObjectPrivate::ConnectionData * connections,int signalIndex,const QObject * receiver,int method_index,void ** slot,QBasicMutex * senderMutex,DisconnectType disconnectType)3479 bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex,
3480                                           const QObject *receiver, int method_index, void **slot,
3481                                           QBasicMutex *senderMutex, DisconnectType disconnectType)
3482 {
3483     bool success = false;
3484 
3485     auto &connectionList = connections->connectionsForSignal(signalIndex);
3486     auto *c = connectionList.first.loadRelaxed();
3487     while (c) {
3488         QObject *r = c->receiver.loadRelaxed();
3489         if (r && (receiver == nullptr || (r == receiver
3490                            && (method_index < 0 || (!c->isSlotObject && c->method() == method_index))
3491                            && (slot == nullptr || (c->isSlotObject && c->slotObj->compare(slot)))))) {
3492             bool needToUnlock = false;
3493             QBasicMutex *receiverMutex = nullptr;
3494             if (r) {
3495                 receiverMutex = signalSlotLock(r);
3496                 // need to relock this receiver and sender in the correct order
3497                 needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
3498             }
3499             if (c->receiver.loadRelaxed())
3500                 connections->removeConnection(c);
3501 
3502             if (needToUnlock)
3503                 receiverMutex->unlock();
3504 
3505             success = true;
3506 
3507             if (disconnectType == DisconnectOne)
3508                 return success;
3509         }
3510         c = c->nextConnectionList.loadRelaxed();
3511     }
3512     return success;
3513 }
3514 
3515 /*!
3516     \internal
3517     Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3518  */
disconnect(const QObject * sender,int signal_index,const QMetaObject * smeta,const QObject * receiver,int method_index,void ** slot,DisconnectType disconnectType)3519 bool QMetaObjectPrivate::disconnect(const QObject *sender,
3520                                     int signal_index, const QMetaObject *smeta,
3521                                     const QObject *receiver, int method_index, void **slot,
3522                                     DisconnectType disconnectType)
3523 {
3524     if (!sender)
3525         return false;
3526 
3527     QObject *s = const_cast<QObject *>(sender);
3528 
3529     QBasicMutex *senderMutex = signalSlotLock(sender);
3530     QBasicMutexLocker locker(senderMutex);
3531 
3532     QObjectPrivate::ConnectionData *scd  = QObjectPrivate::get(s)->connections.loadRelaxed();
3533     if (!scd)
3534         return false;
3535 
3536     bool success = false;
3537     {
3538         // prevent incoming connections changing the connections->receivers while unlocked
3539         QObjectPrivate::ConnectionDataPointer connections(scd);
3540 
3541         if (signal_index < 0) {
3542             // remove from all connection lists
3543             for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) {
3544                 if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType))
3545                     success = true;
3546             }
3547         } else if (signal_index < scd->signalVectorCount()) {
3548             if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType))
3549                 success = true;
3550         }
3551     }
3552 
3553     locker.unlock();
3554     if (success) {
3555         scd->cleanOrphanedConnections(s);
3556 
3557         QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
3558         if (smethod.isValid())
3559             s->disconnectNotify(smethod);
3560     }
3561 
3562     return success;
3563 }
3564 
3565 // Helpers for formatting the connect statements of connectSlotsByName()'s debug mode
formatConnectionSignature(const char * className,const QMetaMethod & method)3566 static QByteArray formatConnectionSignature(const char *className, const QMetaMethod &method)
3567 {
3568     const auto signature = method.methodSignature();
3569     Q_ASSERT(signature.endsWith(')'));
3570     const int openParen = signature.indexOf('(');
3571     const bool hasParameters = openParen >= 0 && openParen < signature.size() - 2;
3572     QByteArray result;
3573     if (hasParameters) {
3574         result += "qOverload<"
3575             + signature.mid(openParen + 1, signature.size() - openParen - 2) + ">(";
3576     }
3577     result += '&';
3578     result += className + QByteArrayLiteral("::") + method.name();
3579     if (hasParameters)
3580         result += ')';
3581     return result;
3582 }
3583 
msgConnect(const QMetaObject * senderMo,const QByteArray & senderName,const QMetaMethod & signal,const QObject * receiver,int receiverIndex)3584 static QByteArray msgConnect(const QMetaObject *senderMo, const QByteArray &senderName,
3585                              const QMetaMethod &signal, const QObject *receiver, int receiverIndex)
3586 {
3587     const auto receiverMo = receiver->metaObject();
3588     const auto slot = receiverMo->method(receiverIndex);
3589     QByteArray message = QByteArrayLiteral("QObject::connect(")
3590         + senderName + ", " + formatConnectionSignature(senderMo->className(), signal)
3591         + ", " + receiver->objectName().toLatin1() + ", "
3592         + formatConnectionSignature(receiverMo->className(), slot) + ");";
3593     return message;
3594 }
3595 
3596 /*!
3597     \fn void QMetaObject::connectSlotsByName(QObject *object)
3598 
3599     Searches recursively for all child objects of the given \a object, and connects
3600     matching signals from them to slots of \a object that follow the following form:
3601 
3602     \snippet code/src_corelib_kernel_qobject.cpp 33
3603 
3604     Let's assume our object has a child object of type \c{QPushButton} with
3605     the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
3606     button's \c{clicked()} signal would be:
3607 
3608     \snippet code/src_corelib_kernel_qobject.cpp 34
3609 
3610     If \a object itself has a properly set object name, its own signals are also
3611     connected to its respective slots.
3612 
3613     \sa QObject::setObjectName()
3614  */
connectSlotsByName(QObject * o)3615 void QMetaObject::connectSlotsByName(QObject *o)
3616 {
3617     if (!o)
3618         return;
3619     const QMetaObject *mo = o->metaObject();
3620     Q_ASSERT(mo);
3621     const QObjectList list = // list of all objects to look for matching signals including...
3622             o->findChildren<QObject *>(QString()) // all children of 'o'...
3623             << o; // and the object 'o' itself
3624 
3625     // for each method/slot of o ...
3626     for (int i = 0; i < mo->methodCount(); ++i) {
3627         const QByteArray slotSignature = mo->method(i).methodSignature();
3628         const char *slot = slotSignature.constData();
3629         Q_ASSERT(slot);
3630 
3631         // ...that starts with "on_", ...
3632         if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
3633             continue;
3634 
3635         // ...we check each object in our list, ...
3636         bool foundIt = false;
3637         for(int j = 0; j < list.count(); ++j) {
3638             const QObject *co = list.at(j);
3639             const QByteArray coName = co->objectName().toLatin1();
3640 
3641             // ...discarding those whose objectName is not fitting the pattern "on_<objectName>_...", ...
3642             if (coName.isEmpty() || qstrncmp(slot + 3, coName.constData(), coName.size()) || slot[coName.size()+3] != '_')
3643                 continue;
3644 
3645             const char *signal = slot + coName.size() + 4; // the 'signal' part of the slot name
3646 
3647             // ...for the presence of a matching signal "on_<objectName>_<signal>".
3648             const QMetaObject *smeta;
3649             int sigIndex = co->d_func()->signalIndex(signal, &smeta);
3650             if (sigIndex < 0) {
3651                 // if no exactly fitting signal (name + complete parameter type list) could be found
3652                 // look for just any signal with the correct name and at least the slot's parameter list.
3653                 // Note: if more than one of those signals exist, the one that gets connected is
3654                 // chosen 'at random' (order of declaration in source file)
3655                 QList<QByteArray> compatibleSignals;
3656                 const QMetaObject *smo = co->metaObject();
3657                 int sigLen = qstrlen(signal) - 1; // ignore the trailing ')'
3658                 for (int k = QMetaObjectPrivate::absoluteSignalCount(smo)-1; k >= 0; --k) {
3659                     const QMetaMethod method = QMetaObjectPrivate::signal(smo, k);
3660                     if (!qstrncmp(method.methodSignature().constData(), signal, sigLen)) {
3661                         smeta = method.enclosingMetaObject();
3662                         sigIndex = k;
3663                         compatibleSignals.prepend(method.methodSignature());
3664                     }
3665                 }
3666                 if (compatibleSignals.size() > 1)
3667                     qWarning() << "QMetaObject::connectSlotsByName: Connecting slot" << slot
3668                                << "with the first of the following compatible signals:" << compatibleSignals;
3669             }
3670 
3671             if (sigIndex < 0)
3672                 continue;
3673 
3674             // we connect it...
3675             if (Connection(QMetaObjectPrivate::connect(co, sigIndex, smeta, o, i))) {
3676                 foundIt = true;
3677                 qCDebug(lcConnections, "%s",
3678                         msgConnect(smeta, coName, QMetaObjectPrivate::signal(smeta, sigIndex), o,  i).constData());
3679                 // ...and stop looking for further objects with the same name.
3680                 // Note: the Designer will make sure each object name is unique in the above
3681                 // 'list' but other code may create two child objects with the same name. In
3682                 // this case one is chosen 'at random'.
3683                 break;
3684             }
3685         }
3686         if (foundIt) {
3687             // we found our slot, now skip all overloads
3688             while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
3689                   ++i;
3690         } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
3691             // check if the slot has the following signature: "on_..._...(..."
3692             int iParen = slotSignature.indexOf('(');
3693             int iLastUnderscore = slotSignature.lastIndexOf('_', iParen-1);
3694             if (iLastUnderscore > 3)
3695                 qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
3696         }
3697     }
3698 }
3699 
3700 /*!
3701     \internal
3702 
3703     \a signal must be in the signal index range (see QObjectPrivate::signalIndex()).
3704 */
queued_activate(QObject * sender,int signal,QObjectPrivate::Connection * c,void ** argv)3705 static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
3706 {
3707     const int *argumentTypes = c->argumentTypes.loadRelaxed();
3708     if (!argumentTypes) {
3709         QMetaMethod m = QMetaObjectPrivate::signal(sender->metaObject(), signal);
3710         argumentTypes = queuedConnectionTypes(m.parameterTypes());
3711         if (!argumentTypes) // cannot queue arguments
3712             argumentTypes = &DIRECT_CONNECTION_ONLY;
3713         if (!c->argumentTypes.testAndSetOrdered(nullptr, argumentTypes)) {
3714             if (argumentTypes != &DIRECT_CONNECTION_ONLY)
3715                 delete [] argumentTypes;
3716             argumentTypes = c->argumentTypes.loadRelaxed();
3717         }
3718     }
3719     if (argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
3720         return;
3721     int nargs = 1; // include return type
3722     while (argumentTypes[nargs-1])
3723         ++nargs;
3724 
3725     QBasicMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed()));
3726     if (!c->receiver.loadRelaxed()) {
3727         // the connection has been disconnected before we got the lock
3728         return;
3729     }
3730     if (c->isSlotObject)
3731         c->slotObj->ref();
3732     locker.unlock();
3733 
3734     QMetaCallEvent *ev = c->isSlotObject ?
3735         new QMetaCallEvent(c->slotObj, sender, signal, nargs) :
3736         new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs);
3737 
3738     void **args = ev->args();
3739     int *types = ev->types();
3740 
3741     types[0] = 0; // return type
3742     args[0] = nullptr; // return value
3743 
3744     if (nargs > 1) {
3745         for (int n = 1; n < nargs; ++n)
3746             types[n] = argumentTypes[n-1];
3747 
3748         for (int n = 1; n < nargs; ++n)
3749             args[n] = QMetaType::create(types[n], argv[n]);
3750     }
3751 
3752     locker.relock();
3753     if (c->isSlotObject)
3754         c->slotObj->destroyIfLastRef();
3755     if (!c->receiver.loadRelaxed()) {
3756         // the connection has been disconnected while we were unlocked
3757         locker.unlock();
3758         delete ev;
3759         return;
3760     }
3761 
3762     QCoreApplication::postEvent(c->receiver.loadRelaxed(), ev);
3763 }
3764 
3765 template <bool callbacks_enabled>
doActivate(QObject * sender,int signal_index,void ** argv)3766 void doActivate(QObject *sender, int signal_index, void **argv)
3767 {
3768     QObjectPrivate *sp = QObjectPrivate::get(sender);
3769 
3770     if (sp->blockSig)
3771         return;
3772 
3773     Q_TRACE_SCOPE(QMetaObject_activate, sender, signal_index);
3774 
3775     if (sp->isDeclarativeSignalConnected(signal_index)
3776             && QAbstractDeclarativeData::signalEmitted) {
3777         Q_TRACE_SCOPE(QMetaObject_activate_declarative_signal, sender, signal_index);
3778         QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender,
3779                                                 signal_index, argv);
3780     }
3781 
3782     const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.loadAcquire() : nullptr;
3783 
3784     void *empty_argv[] = { nullptr };
3785     if (!argv)
3786         argv = empty_argv;
3787 
3788     if (!sp->maybeSignalConnected(signal_index)) {
3789         // The possible declarative connection is done, and nothing else is connected
3790         if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
3791             signal_spy_set->signal_begin_callback(sender, signal_index, argv);
3792         if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
3793             signal_spy_set->signal_end_callback(sender, signal_index);
3794         return;
3795     }
3796 
3797     if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
3798         signal_spy_set->signal_begin_callback(sender, signal_index, argv);
3799 
3800     bool senderDeleted = false;
3801     {
3802     Q_ASSERT(sp->connections.loadAcquire());
3803     QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed());
3804     QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed();
3805 
3806     const QObjectPrivate::ConnectionList *list;
3807     if (signal_index < signalVector->count())
3808         list = &signalVector->at(signal_index);
3809     else
3810         list = &signalVector->at(-1);
3811 
3812     Qt::HANDLE currentThreadId = QThread::currentThreadId();
3813     bool inSenderThread = currentThreadId == QObjectPrivate::get(sender)->threadData.loadRelaxed()->threadId.loadRelaxed();
3814 
3815     // We need to check against the highest connection id to ensure that signals added
3816     // during the signal emission are not emitted in this emission.
3817     uint highestConnectionId = connections->currentConnectionId.loadRelaxed();
3818     do {
3819         QObjectPrivate::Connection *c = list->first.loadRelaxed();
3820         if (!c)
3821             continue;
3822 
3823         do {
3824             QObject * const receiver = c->receiver.loadRelaxed();
3825             if (!receiver)
3826                 continue;
3827 
3828             QThreadData *td = c->receiverThreadData.loadRelaxed();
3829             if (!td)
3830                 continue;
3831 
3832             bool receiverInSameThread;
3833             if (inSenderThread) {
3834                 receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
3835             } else {
3836                 // need to lock before reading the threadId, because moveToThread() could interfere
3837                 QMutexLocker lock(signalSlotLock(receiver));
3838                 receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
3839             }
3840 
3841 
3842             // determine if this connection should be sent immediately or
3843             // put into the event queue
3844             if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
3845                 || (c->connectionType == Qt::QueuedConnection)) {
3846                 queued_activate(sender, signal_index, c, argv);
3847                 continue;
3848 #if QT_CONFIG(thread)
3849             } else if (c->connectionType == Qt::BlockingQueuedConnection) {
3850                 if (receiverInSameThread) {
3851                     qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
3852                     "Sender is %s(%p), receiver is %s(%p)",
3853                     sender->metaObject()->className(), sender,
3854                     receiver->metaObject()->className(), receiver);
3855                 }
3856                 QSemaphore semaphore;
3857                 {
3858                     QBasicMutexLocker locker(signalSlotLock(sender));
3859                     if (!c->receiver.loadAcquire())
3860                         continue;
3861                     QMetaCallEvent *ev = c->isSlotObject ?
3862                         new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) :
3863                         new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction,
3864                                            sender, signal_index, argv, &semaphore);
3865                     QCoreApplication::postEvent(receiver, ev);
3866                 }
3867                 semaphore.acquire();
3868                 continue;
3869 #endif
3870             }
3871 
3872             QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index);
3873 
3874             if (c->isSlotObject) {
3875                 c->slotObj->ref();
3876 
3877                 struct Deleter {
3878                     void operator()(QtPrivate::QSlotObjectBase *slot) const {
3879                         if (slot) slot->destroyIfLastRef();
3880                     }
3881                 };
3882                 const std::unique_ptr<QtPrivate::QSlotObjectBase, Deleter> obj{c->slotObj};
3883 
3884                 {
3885                     Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.get());
3886                     obj->call(receiver, argv);
3887                 }
3888             } else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
3889                 //we compare the vtable to make sure we are not in the destructor of the object.
3890                 const int method_relative = c->method_relative;
3891                 const auto callFunction = c->callFunction;
3892                 const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0;
3893                 if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr)
3894                     signal_spy_set->slot_begin_callback(receiver, methodIndex, argv);
3895 
3896                 {
3897                     Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, methodIndex);
3898                     callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv);
3899                 }
3900 
3901                 if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
3902                     signal_spy_set->slot_end_callback(receiver, methodIndex);
3903             } else {
3904                 const int method = c->method_relative + c->method_offset;
3905 
3906                 if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) {
3907                     signal_spy_set->slot_begin_callback(receiver, method, argv);
3908                 }
3909 
3910                 {
3911                     Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, method);
3912                     QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);
3913                 }
3914 
3915                 if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
3916                     signal_spy_set->slot_end_callback(receiver, method);
3917             }
3918         } while ((c = c->nextConnectionList.loadRelaxed()) != nullptr && c->id <= highestConnectionId);
3919 
3920     } while (list != &signalVector->at(-1) &&
3921         //start over for all signals;
3922         ((list = &signalVector->at(-1)), true));
3923 
3924         if (connections->currentConnectionId.loadRelaxed() == 0)
3925             senderDeleted = true;
3926     }
3927     if (!senderDeleted) {
3928         sp->connections.loadRelaxed()->cleanOrphanedConnections(sender);
3929 
3930         if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
3931             signal_spy_set->signal_end_callback(sender, signal_index);
3932     }
3933 }
3934 
3935 /*!
3936     \internal
3937  */
activate(QObject * sender,const QMetaObject * m,int local_signal_index,void ** argv)3938 void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
3939                            void **argv)
3940 {
3941     int signal_index = local_signal_index + QMetaObjectPrivate::signalOffset(m);
3942 
3943     if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
3944         doActivate<true>(sender, signal_index, argv);
3945     else
3946         doActivate<false>(sender, signal_index, argv);
3947 }
3948 
3949 /*!
3950     \internal
3951  */
activate(QObject * sender,int signalOffset,int local_signal_index,void ** argv)3952 void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
3953 {
3954     int signal_index = signalOffset + local_signal_index;
3955 
3956     if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
3957         doActivate<true>(sender, signal_index, argv);
3958     else
3959         doActivate<false>(sender, signal_index, argv);
3960  }
3961 
3962 /*!
3963     \internal
3964    signal_index comes from indexOfMethod()
3965 */
activate(QObject * sender,int signal_index,void ** argv)3966 void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
3967 {
3968     const QMetaObject *mo = sender->metaObject();
3969     while (mo->methodOffset() > signal_index)
3970         mo = mo->superClass();
3971     activate(sender, mo, signal_index - mo->methodOffset(), argv);
3972 }
3973 
3974 /*!
3975     \internal
3976     Returns the signal index used in the internal connections->receivers vector.
3977 
3978     It is different from QMetaObject::indexOfSignal():  indexOfSignal is the same as indexOfMethod
3979     while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
3980 
3981     If \a meta is not \nullptr, it is set to the meta-object where the signal was found.
3982 */
signalIndex(const char * signalName,const QMetaObject ** meta) const3983 int QObjectPrivate::signalIndex(const char *signalName,
3984                                 const QMetaObject **meta) const
3985 {
3986     Q_Q(const QObject);
3987     const QMetaObject *base = q->metaObject();
3988     Q_ASSERT(QMetaObjectPrivate::get(base)->revision >= 7);
3989     QArgumentTypeArray types;
3990     QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signalName, types);
3991     int relative_index = QMetaObjectPrivate::indexOfSignalRelative(
3992             &base, name, types.size(), types.constData());
3993     if (relative_index < 0)
3994         return relative_index;
3995     relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
3996     if (meta)
3997         *meta = base;
3998     return relative_index + QMetaObjectPrivate::signalOffset(base);
3999 }
4000 
4001 /*****************************************************************************
4002   Properties
4003  *****************************************************************************/
4004 
4005 #ifndef QT_NO_PROPERTIES
4006 
4007 /*!
4008   Sets the value of the object's \a name property to \a value.
4009 
4010   If the property is defined in the class using Q_PROPERTY then
4011   true is returned on success and false otherwise. If the property
4012   is not defined using Q_PROPERTY, and therefore not listed in the
4013   meta-object, it is added as a dynamic property and false is returned.
4014 
4015   Information about all available properties is provided through the
4016   metaObject() and dynamicPropertyNames().
4017 
4018   Dynamic properties can be queried again using property() and can be
4019   removed by setting the property value to an invalid QVariant.
4020   Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent
4021   to be sent to the object.
4022 
4023   \b{Note:} Dynamic properties starting with "_q_" are reserved for internal
4024   purposes.
4025 
4026   \sa property(), metaObject(), dynamicPropertyNames(), QMetaProperty::write()
4027 */
setProperty(const char * name,const QVariant & value)4028 bool QObject::setProperty(const char *name, const QVariant &value)
4029 {
4030     Q_D(QObject);
4031     const QMetaObject* meta = metaObject();
4032     if (!name || !meta)
4033         return false;
4034 
4035     int id = meta->indexOfProperty(name);
4036     if (id < 0) {
4037         if (!d->extraData)
4038             d->extraData = new QObjectPrivate::ExtraData;
4039 
4040         const int idx = d->extraData->propertyNames.indexOf(name);
4041 
4042         if (!value.isValid()) {
4043             if (idx == -1)
4044                 return false;
4045             d->extraData->propertyNames.removeAt(idx);
4046             d->extraData->propertyValues.removeAt(idx);
4047         } else {
4048             if (idx == -1) {
4049                 d->extraData->propertyNames.append(name);
4050                 d->extraData->propertyValues.append(value);
4051             } else {
4052                 if (value.userType() == d->extraData->propertyValues.at(idx).userType()
4053                         && value == d->extraData->propertyValues.at(idx))
4054                     return false;
4055                 d->extraData->propertyValues[idx] = value;
4056             }
4057         }
4058 
4059         QDynamicPropertyChangeEvent ev(name);
4060         QCoreApplication::sendEvent(this, &ev);
4061 
4062         return false;
4063     }
4064     QMetaProperty p = meta->property(id);
4065 #ifndef QT_NO_DEBUG
4066     if (!p.isWritable())
4067         qWarning("%s::setProperty: Property \"%s\" invalid,"
4068                  " read-only or does not exist", metaObject()->className(), name);
4069 #endif
4070     return p.write(this, value);
4071 }
4072 
4073 /*!
4074   Returns the value of the object's \a name property.
4075 
4076   If no such property exists, the returned variant is invalid.
4077 
4078   Information about all available properties is provided through the
4079   metaObject() and dynamicPropertyNames().
4080 
4081   \sa setProperty(), QVariant::isValid(), metaObject(), dynamicPropertyNames()
4082 */
property(const char * name) const4083 QVariant QObject::property(const char *name) const
4084 {
4085     Q_D(const QObject);
4086     const QMetaObject* meta = metaObject();
4087     if (!name || !meta)
4088         return QVariant();
4089 
4090     int id = meta->indexOfProperty(name);
4091     if (id < 0) {
4092         if (!d->extraData)
4093             return QVariant();
4094         const int i = d->extraData->propertyNames.indexOf(name);
4095         return d->extraData->propertyValues.value(i);
4096     }
4097     QMetaProperty p = meta->property(id);
4098 #ifndef QT_NO_DEBUG
4099     if (!p.isReadable())
4100         qWarning("%s::property: Property \"%s\" invalid or does not exist",
4101                  metaObject()->className(), name);
4102 #endif
4103     return p.read(this);
4104 }
4105 
4106 /*!
4107     \since 4.2
4108 
4109     Returns the names of all properties that were dynamically added to
4110     the object using setProperty().
4111 */
dynamicPropertyNames() const4112 QList<QByteArray> QObject::dynamicPropertyNames() const
4113 {
4114     Q_D(const QObject);
4115     if (d->extraData)
4116         return d->extraData->propertyNames;
4117     return QList<QByteArray>();
4118 }
4119 
4120 #endif // QT_NO_PROPERTIES
4121 
4122 
4123 /*****************************************************************************
4124   QObject debugging output routines.
4125  *****************************************************************************/
4126 
dumpRecursive(int level,const QObject * object)4127 static void dumpRecursive(int level, const QObject *object)
4128 {
4129     if (object) {
4130         QByteArray buf;
4131         buf.fill(' ', level / 2 * 8);
4132         if (level % 2)
4133             buf += "    ";
4134         QString name = object->objectName();
4135         QString flags = QLatin1String("");
4136 #if 0
4137         if (qApp->focusWidget() == object)
4138             flags += 'F';
4139         if (object->isWidgetType()) {
4140             QWidget * w = (QWidget *)object;
4141             if (w->isVisible()) {
4142                 QString t("<%1,%2,%3,%4>");
4143                 flags += t.arg(w->x()).arg(w->y()).arg(w->width()).arg(w->height());
4144             } else {
4145                 flags += 'I';
4146             }
4147         }
4148 #endif
4149         qDebug("%s%s::%s %s", (const char*)buf, object->metaObject()->className(), name.toLocal8Bit().data(),
4150                flags.toLatin1().data());
4151         QObjectList children = object->children();
4152         if (!children.isEmpty()) {
4153             for (int i = 0; i < children.size(); ++i)
4154                 dumpRecursive(level+1, children.at(i));
4155         }
4156     }
4157 }
4158 
4159 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4160 /*!
4161     \overload
4162     \obsolete
4163 
4164     Dumps a tree of children to the debug output.
4165 
4166     \sa dumpObjectInfo()
4167 */
4168 
dumpObjectTree()4169 void QObject::dumpObjectTree()
4170 {
4171     const_cast<const QObject *>(this)->dumpObjectTree();
4172 }
4173 #endif
4174 
4175 /*!
4176     Dumps a tree of children to the debug output.
4177 
4178     \note before Qt 5.9, this function was not const.
4179 
4180     \sa dumpObjectInfo()
4181 */
4182 
dumpObjectTree() const4183 void QObject::dumpObjectTree() const
4184 {
4185     dumpRecursive(0, this);
4186 }
4187 
4188 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4189 /*!
4190     \overload
4191     \obsolete
4192 
4193     Dumps information about signal connections, etc. for this object
4194     to the debug output.
4195 
4196     \sa dumpObjectTree()
4197 */
4198 
dumpObjectInfo()4199 void QObject::dumpObjectInfo()
4200 {
4201     const_cast<const QObject *>(this)->dumpObjectInfo();
4202 }
4203 #endif
4204 
4205 /*!
4206     Dumps information about signal connections, etc. for this object
4207     to the debug output.
4208 
4209     \note before Qt 5.9, this function was not const.
4210 
4211     \sa dumpObjectTree()
4212 */
4213 
dumpObjectInfo() const4214 void QObject::dumpObjectInfo() const
4215 {
4216     qDebug("OBJECT %s::%s", metaObject()->className(),
4217            objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
4218 
4219     Q_D(const QObject);
4220     QBasicMutexLocker locker(signalSlotLock(this));
4221 
4222     // first, look for connections where this object is the sender
4223     qDebug("  SIGNALS OUT");
4224 
4225     QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
4226     if (cd && cd->signalVectorCount()) {
4227         QObjectPrivate::SignalVector *signalVector = cd->signalVector.loadRelaxed();
4228         for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) {
4229             const QObjectPrivate::Connection *c = signalVector->at(signal_index).first.loadRelaxed();
4230             if (!c)
4231                 continue;
4232             const QMetaMethod signal = QMetaObjectPrivate::signal(metaObject(), signal_index);
4233             qDebug("        signal: %s", signal.methodSignature().constData());
4234 
4235             // receivers
4236             while (c) {
4237                 if (!c->receiver.loadRelaxed()) {
4238                     qDebug("          <Disconnected receiver>");
4239                     c = c->nextConnectionList.loadRelaxed();
4240                     continue;
4241                 }
4242                 if (c->isSlotObject) {
4243                     qDebug("          <functor or function pointer>");
4244                     c = c->nextConnectionList.loadRelaxed();
4245                     continue;
4246                 }
4247                 const QMetaObject *receiverMetaObject = c->receiver.loadRelaxed()->metaObject();
4248                 const QMetaMethod method = receiverMetaObject->method(c->method());
4249                 qDebug("          --> %s::%s %s",
4250                        receiverMetaObject->className(),
4251                        c->receiver.loadRelaxed()->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver.loadRelaxed()->objectName()),
4252                        method.methodSignature().constData());
4253                 c = c->nextConnectionList.loadRelaxed();
4254             }
4255         }
4256     } else {
4257         qDebug( "        <None>" );
4258     }
4259 
4260     // now look for connections where this object is the receiver
4261     qDebug("  SIGNALS IN");
4262 
4263     if (cd && cd->senders) {
4264         for (QObjectPrivate::Connection *s = cd->senders; s; s = s->next) {
4265             QByteArray slotName = QByteArrayLiteral("<unknown>");
4266             if (!s->isSlotObject) {
4267                 const QMetaMethod slot = metaObject()->method(s->method());
4268                 slotName = slot.methodSignature();
4269             }
4270             qDebug("          <-- %s::%s %s",
4271                    s->sender->metaObject()->className(),
4272                    s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
4273                    slotName.constData());
4274         }
4275     } else {
4276         qDebug("        <None>");
4277     }
4278 }
4279 
4280 #ifndef QT_NO_USERDATA
4281 static QBasicAtomicInteger<uint> user_data_registration = Q_BASIC_ATOMIC_INITIALIZER(0);
4282 
4283 /*!
4284     \internal
4285  */
registerUserData()4286 uint QObject::registerUserData()
4287 {
4288     return user_data_registration.fetchAndAddRelaxed(1);
4289 }
4290 
4291 /*!
4292     \fn QObjectUserData::QObjectUserData()
4293     \internal
4294  */
4295 
4296 /*!
4297     \internal
4298  */
~QObjectUserData()4299 QObjectUserData::~QObjectUserData()
4300 {
4301 }
4302 
4303 /*!
4304     \internal
4305  */
setUserData(uint id,QObjectUserData * data)4306 void QObject::setUserData(uint id, QObjectUserData* data)
4307 {
4308     Q_D(QObject);
4309     if (!d->extraData)
4310         d->extraData = new QObjectPrivate::ExtraData;
4311 
4312     if (d->extraData->userData.size() <= (int) id)
4313         d->extraData->userData.resize((int) id + 1);
4314     d->extraData->userData[id] = data;
4315 }
4316 
4317 /*!
4318     \internal
4319  */
userData(uint id) const4320 QObjectUserData* QObject::userData(uint id) const
4321 {
4322     Q_D(const QObject);
4323     if (!d->extraData)
4324         return nullptr;
4325     if ((int)id < d->extraData->userData.size())
4326         return d->extraData->userData.at(id);
4327     return nullptr;
4328 }
4329 
4330 #endif // QT_NO_USERDATA
4331 
4332 
4333 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug dbg,const QObject * o)4334 QDebug operator<<(QDebug dbg, const QObject *o)
4335 {
4336     QDebugStateSaver saver(dbg);
4337     if (!o)
4338         return dbg << "QObject(0x0)";
4339     dbg.nospace() << o->metaObject()->className() << '(' << (const void *)o;
4340     if (!o->objectName().isEmpty())
4341         dbg << ", name = " << o->objectName();
4342     dbg << ')';
4343     return dbg;
4344 }
4345 #endif
4346 
4347 /*!
4348     \macro Q_CLASSINFO(Name, Value)
4349     \relates QObject
4350 
4351     This macro associates extra information to the class, which is available
4352     using QObject::metaObject(). Qt makes only limited use of this feature, in
4353     the \l{Active Qt}, \l{Qt D-Bus} and \l{Qt QML module}{Qt QML}.
4354 
4355     The extra information takes the form of a \a Name string and a \a Value
4356     literal string.
4357 
4358     Example:
4359 
4360     \snippet code/src_corelib_kernel_qobject.cpp 35
4361 
4362     \sa QMetaObject::classInfo()
4363     \sa QAxFactory
4364     \sa {Using Qt D-Bus Adaptors}
4365     \sa {Extending QML}
4366 */
4367 
4368 /*!
4369     \macro Q_INTERFACES(...)
4370     \relates QObject
4371 
4372     This macro tells Qt which interfaces the class implements. This
4373     is used when implementing plugins.
4374 
4375     Example:
4376 
4377     \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 1
4378     \dots
4379     \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 3
4380 
4381     See the \l{tools/plugandpaint/plugins/basictools}{Plug & Paint
4382     Basic Tools} example for details.
4383 
4384     \sa Q_DECLARE_INTERFACE(), Q_PLUGIN_METADATA(), {How to Create Qt Plugins}
4385 */
4386 
4387 /*!
4388     \macro Q_PROPERTY(...)
4389     \relates QObject
4390 
4391     This macro is used for declaring properties in classes that
4392     inherit QObject. Properties behave like class data members, but
4393     they have additional features accessible through the \l
4394     {Meta-Object System}.
4395 
4396     \snippet code/doc_src_properties.cpp 0
4397 
4398     The property name and type and the \c READ function are required.
4399     The type can be any type supported by QVariant, or it can be a
4400     user-defined type.  The other items are optional, but a \c WRITE
4401     function is common.  The attributes default to true except \c USER,
4402     which defaults to false.
4403 
4404     For example:
4405 
4406     \snippet code/src_corelib_kernel_qobject.cpp 37
4407 
4408     For more details about how to use this macro, and a more detailed
4409     example of its use, see the discussion on \l {Qt's Property System}.
4410 
4411     \sa {Qt's Property System}
4412 */
4413 
4414 /*!
4415     \macro Q_ENUMS(...)
4416     \relates QObject
4417     \obsolete
4418 
4419     In new code, you should prefer the use of the Q_ENUM() macro, which makes the
4420     type available also to the meta type system.
4421     For instance, QMetaEnum::fromType() will not work with types declared with Q_ENUMS().
4422 
4423     This macro registers one or several enum types to the meta-object
4424     system.
4425 
4426     If you want to register an enum that is declared in another class,
4427     the enum must be fully qualified with the name of the class
4428     defining it. In addition, the class \e defining the enum has to
4429     inherit QObject as well as declare the enum using Q_ENUMS().
4430 
4431     \sa {Qt's Property System}
4432 */
4433 
4434 /*!
4435     \macro Q_FLAGS(...)
4436     \relates QObject
4437     \obsolete
4438 
4439     This macro registers one or several \l{QFlags}{flags types} with the
4440     meta-object system. It is typically used in a class definition to declare
4441     that values of a given enum can be used as flags and combined using the
4442     bitwise OR operator.
4443 
4444     \note This macro takes care of registering individual flag values
4445     with the meta-object system, so it is unnecessary to use Q_ENUMS()
4446     in addition to this macro.
4447 
4448     In new code, you should prefer the use of the Q_FLAG() macro, which makes the
4449     type available also to the meta type system.
4450 
4451     \sa {Qt's Property System}
4452 */
4453 
4454 /*!
4455     \macro Q_ENUM(...)
4456     \relates QObject
4457     \since 5.5
4458 
4459     This macro registers an enum type with the meta-object system.
4460     It must be placed after the enum declaration in a class that has the Q_OBJECT or the
4461     Q_GADGET macro. For namespaces use \l Q_ENUM_NS() instead.
4462 
4463     For example:
4464 
4465     \snippet code/src_corelib_kernel_qobject.cpp 38
4466 
4467     Enumerations that are declared with Q_ENUM have their QMetaEnum registered in the
4468     enclosing QMetaObject. You can also use QMetaEnum::fromType() to get the QMetaEnum.
4469 
4470     Registered enumerations are automatically registered also to the Qt meta
4471     type system, making them known to QMetaType without the need to use
4472     Q_DECLARE_METATYPE(). This will enable useful features; for example, if used
4473     in a QVariant, you can convert them to strings. Likewise, passing them to
4474     QDebug will print out their names.
4475 
4476     Mind that the enum values are stored as signed \c int in the meta object system.
4477     Registering enumerations with values outside the range of values valid for \c int
4478     will lead to overflows and potentially undefined behavior when accessing them through
4479     the meta object system. QML, for example, does access registered enumerations through
4480     the meta object system.
4481 
4482     \sa {Qt's Property System}
4483 */
4484 
4485 
4486 /*!
4487     \macro Q_FLAG(...)
4488     \relates QObject
4489     \since 5.5
4490 
4491     This macro registers a single \l{QFlags}{flags type} with the
4492     meta-object system. It is typically used in a class definition to declare
4493     that values of a given enum can be used as flags and combined using the
4494     bitwise OR operator. For namespaces use \l Q_FLAG_NS() instead.
4495 
4496     The macro must be placed after the enum declaration. The declaration of
4497     the flags type is done using the \l Q_DECLARE_FLAGS() macro.
4498 
4499     For example, in QItemSelectionModel, the
4500     \l{QItemSelectionModel::SelectionFlags}{SelectionFlags} flag is
4501     declared in the following way:
4502 
4503     \snippet code/src_corelib_kernel_qobject.cpp 39
4504 
4505     \note The Q_FLAG macro takes care of registering individual flag values
4506     with the meta-object system, so it is unnecessary to use Q_ENUM()
4507     in addition to this macro.
4508 
4509     \sa {Qt's Property System}
4510 */
4511 
4512 /*!
4513     \macro Q_ENUM_NS(...)
4514     \relates QObject
4515     \since 5.8
4516 
4517     This macro registers an enum type with the meta-object system.
4518     It must be placed after the enum declaration in a namespace that
4519     has the Q_NAMESPACE macro. It is the same as \l Q_ENUM but in a
4520     namespace.
4521 
4522     Enumerations that are declared with Q_ENUM_NS have their QMetaEnum
4523     registered in the enclosing QMetaObject. You can also use
4524     QMetaEnum::fromType() to get the QMetaEnum.
4525 
4526     Registered enumerations are automatically registered also to the Qt meta
4527     type system, making them known to QMetaType without the need to use
4528     Q_DECLARE_METATYPE(). This will enable useful features; for example, if
4529     used in a QVariant, you can convert them to strings. Likewise, passing them
4530     to QDebug will print out their names.
4531 
4532     Mind that the enum values are stored as signed \c int in the meta object system.
4533     Registering enumerations with values outside the range of values valid for \c int
4534     will lead to overflows and potentially undefined behavior when accessing them through
4535     the meta object system. QML, for example, does access registered enumerations through
4536     the meta object system.
4537 
4538     \sa {Qt's Property System}
4539 */
4540 
4541 
4542 /*!
4543     \macro Q_FLAG_NS(...)
4544     \relates QObject
4545     \since 5.8
4546 
4547     This macro registers a single \l{QFlags}{flags type} with the
4548     meta-object system. It is used in a namespace that has the
4549     Q_NAMESPACE macro, to declare that values of a given enum can be
4550     used as flags and combined using the bitwise OR operator.
4551     It is the same as \l Q_FLAG but in a namespace.
4552 
4553     The macro must be placed after the enum declaration.
4554 
4555     \note The Q_FLAG_NS macro takes care of registering individual flag
4556     values with the meta-object system, so it is unnecessary to use
4557     Q_ENUM_NS() in addition to this macro.
4558 
4559     \sa {Qt's Property System}
4560 */
4561 
4562 
4563 /*!
4564     \macro Q_OBJECT
4565     \relates QObject
4566 
4567     The Q_OBJECT macro must appear in the private section of a class
4568     definition that declares its own signals and slots or that uses
4569     other services provided by Qt's meta-object system.
4570 
4571     For example:
4572 
4573     \snippet signalsandslots/signalsandslots.h 1
4574     \codeline
4575     \snippet signalsandslots/signalsandslots.h 2
4576     \snippet signalsandslots/signalsandslots.h 3
4577 
4578     \note This macro requires the class to be a subclass of QObject. Use
4579     Q_GADGET instead of Q_OBJECT to enable the meta object system's support
4580     for enums in a class that is not a QObject subclass.
4581 
4582     \sa {Meta-Object System}, {Signals and Slots}, {Qt's Property System}
4583 */
4584 
4585 /*!
4586     \macro Q_GADGET
4587     \relates QObject
4588 
4589     The Q_GADGET macro is a lighter version of the Q_OBJECT macro for classes
4590     that do not inherit from QObject but still want to use some of the
4591     reflection capabilities offered by QMetaObject. Just like the Q_OBJECT
4592     macro, it must appear in the private section of a class definition.
4593 
4594     Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have
4595     signals or slots.
4596 
4597     Q_GADGET makes a class member, \c{staticMetaObject}, available.
4598     \c{staticMetaObject} is of type QMetaObject and provides access to the
4599     enums declared with Q_ENUMS.
4600 */
4601 
4602 /*!
4603     \macro Q_NAMESPACE
4604     \relates QObject
4605     \since 5.8
4606 
4607     The Q_NAMESPACE macro can be used to add QMetaObject capabilities
4608     to a namespace.
4609 
4610     Q_NAMESPACEs can have Q_CLASSINFO, Q_ENUM_NS, Q_FLAG_NS, but they
4611     cannot have Q_ENUM, Q_FLAG, Q_PROPERTY, Q_INVOKABLE, signals nor slots.
4612 
4613     Q_NAMESPACE makes an external variable, \c{staticMetaObject}, available.
4614     \c{staticMetaObject} is of type QMetaObject and provides access to the
4615     enums declared with Q_ENUM_NS/Q_FLAG_NS.
4616 
4617     For example:
4618 
4619     \code
4620     namespace test {
4621     Q_NAMESPACE
4622     ...
4623     \endcode
4624 
4625     \sa Q_NAMESPACE_EXPORT
4626 */
4627 
4628 /*!
4629     \macro Q_NAMESPACE_EXPORT(EXPORT_MACRO)
4630     \relates QObject
4631     \since 5.14
4632 
4633     The Q_NAMESPACE_EXPORT macro can be used to add QMetaObject capabilities
4634     to a namespace.
4635 
4636     It works exactly like the Q_NAMESPACE macro. However, the external
4637     \c{staticMetaObject} variable that gets defined in the namespace
4638     is declared with the supplied \a EXPORT_MACRO qualifier. This is
4639     useful if the object needs to be exported from a dynamic library.
4640 
4641     For example:
4642 
4643     \code
4644     namespace test {
4645     Q_NAMESPACE_EXPORT(EXPORT_MACRO)
4646     ...
4647     \endcode
4648 
4649     \sa Q_NAMESPACE, {Creating Shared Libraries}
4650 */
4651 
4652 /*!
4653     \macro Q_SIGNALS
4654     \relates QObject
4655 
4656     Use this macro to replace the \c signals keyword in class
4657     declarations, when you want to use Qt Signals and Slots with a
4658     \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4659 
4660     The macro is normally used when \c no_keywords is specified with
4661     the \c CONFIG variable in the \c .pro file, but it can be used
4662     even when \c no_keywords is \e not specified.
4663 */
4664 
4665 /*!
4666     \macro Q_SIGNAL
4667     \relates QObject
4668 
4669     This is an additional macro that allows you to mark a single
4670     function as a signal. It can be quite useful, especially when you
4671     use a 3rd-party source code parser which doesn't understand a \c
4672     signals or \c Q_SIGNALS groups.
4673 
4674     Use this macro to replace the \c signals keyword in class
4675     declarations, when you want to use Qt Signals and Slots with a
4676     \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4677 
4678     The macro is normally used when \c no_keywords is specified with
4679     the \c CONFIG variable in the \c .pro file, but it can be used
4680     even when \c no_keywords is \e not specified.
4681 */
4682 
4683 /*!
4684     \macro Q_SLOTS
4685     \relates QObject
4686 
4687     Use this macro to replace the \c slots keyword in class
4688     declarations, when you want to use Qt Signals and Slots with a
4689     \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4690 
4691     The macro is normally used when \c no_keywords is specified with
4692     the \c CONFIG variable in the \c .pro file, but it can be used
4693     even when \c no_keywords is \e not specified.
4694 */
4695 
4696 /*!
4697     \macro Q_SLOT
4698     \relates QObject
4699 
4700     This is an additional macro that allows you to mark a single
4701     function as a slot. It can be quite useful, especially when you
4702     use a 3rd-party source code parser which doesn't understand a \c
4703     slots or \c Q_SLOTS groups.
4704 
4705     Use this macro to replace the \c slots keyword in class
4706     declarations, when you want to use Qt Signals and Slots with a
4707     \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4708 
4709     The macro is normally used when \c no_keywords is specified with
4710     the \c CONFIG variable in the \c .pro file, but it can be used
4711     even when \c no_keywords is \e not specified.
4712 */
4713 
4714 /*!
4715     \macro Q_EMIT
4716     \relates QObject
4717 
4718     Use this macro to replace the \c emit keyword for emitting
4719     signals, when you want to use Qt Signals and Slots with a
4720     \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4721 
4722     The macro is normally used when \c no_keywords is specified with
4723     the \c CONFIG variable in the \c .pro file, but it can be used
4724     even when \c no_keywords is \e not specified.
4725 */
4726 
4727 /*!
4728     \macro Q_INVOKABLE
4729     \relates QObject
4730 
4731     Apply this macro to declarations of member functions to allow them to
4732     be invoked via the meta-object system. The macro is written before
4733     the return type, as shown in the following example:
4734 
4735     \snippet qmetaobject-invokable/window.h Window class with invokable method
4736 
4737     The \c invokableMethod() function is marked up using Q_INVOKABLE, causing
4738     it to be registered with the meta-object system and enabling it to be
4739     invoked using QMetaObject::invokeMethod().
4740     Since \c normalMethod() function is not registered in this way, it cannot
4741     be invoked using QMetaObject::invokeMethod().
4742 
4743     If an invokable member function returns a pointer to a QObject or a
4744     subclass of QObject and it is invoked from QML, special ownership rules
4745     apply. See \l{qtqml-cppintegration-data.html}{Data Type Conversion Between QML and C++}
4746     for more information.
4747 */
4748 
4749 /*!
4750     \macro Q_REVISION
4751     \relates QObject
4752 
4753     Apply this macro to declarations of member functions to tag them with a
4754     revision number in the meta-object system. The macro is written before
4755     the return type, as shown in the following example:
4756 
4757     \snippet qmetaobject-revision/window.h Window class with revision
4758 
4759     This is useful when using the meta-object system to dynamically expose
4760     objects to another API, as you can match the version expected by multiple
4761     versions of the other API. Consider the following simplified example:
4762 
4763     \snippet qmetaobject-revision/main.cpp Window class using revision
4764 
4765     Using the same Window class as the previous example, the newProperty and
4766     newMethod would only be exposed in this code when the expected version is
4767     1 or greater.
4768 
4769     Since all methods are considered to be in revision 0 if untagged, a tag
4770     of Q_REVISION(0) is invalid and ignored.
4771 
4772     This tag is not used by the meta-object system itself. Currently this is only
4773     used by the QtQml module.
4774 
4775     For a more generic string tag, see \l QMetaMethod::tag()
4776 
4777     \sa QMetaMethod::revision()
4778 */
4779 
4780 /*!
4781     \macro Q_SET_OBJECT_NAME(Object)
4782     \relates QObject
4783     \since 5.0
4784 
4785     This macro assigns \a Object the objectName "Object".
4786 
4787     It doesn't matter whether \a Object is a pointer or not, the
4788     macro figures that out by itself.
4789 
4790     \sa QObject::objectName()
4791 */
4792 
4793 /*!
4794     \macro QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
4795     \relates QObject
4796     \since 5.8
4797 
4798     Defining this macro will disable narrowing and floating-point-to-integral
4799     conversions between the arguments carried by a signal and the arguments
4800     accepted by a slot, when the signal and the slot are connected using the
4801     PMF-based syntax.
4802 
4803     \sa QObject::connect
4804 */
4805 
4806 /*!
4807     \typedef QObjectList
4808     \relates QObject
4809 
4810     Synonym for QList<QObject *>.
4811 */
4812 
qDeleteInEventHandler(QObject * o)4813 void qDeleteInEventHandler(QObject *o)
4814 {
4815     delete o;
4816 }
4817 
4818 /*!
4819     \fn template<typename PointerToMemberFunction> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type)
4820     \overload connect()
4821     \threadsafe
4822 
4823     Creates a connection of the given \a type from the \a signal in
4824     the \a sender object to the \a method in the \a receiver object.
4825     Returns a handle to the connection that can be used to disconnect
4826     it later.
4827 
4828     The signal must be a function declared as a signal in the header.
4829     The slot function can be any member function that can be connected
4830     to the signal.
4831     A slot can be connected to a given signal if the signal has at
4832     least as many arguments as the slot, and there is an implicit
4833     conversion between the types of the corresponding arguments in the
4834     signal and the slot.
4835 
4836     Example:
4837 
4838     \snippet code/src_corelib_kernel_qobject.cpp 44
4839 
4840     This example ensures that the label always displays the current
4841     line edit text.
4842 
4843     A signal can be connected to many slots and signals. Many signals
4844     can be connected to one slot.
4845 
4846     If a signal is connected to several slots, the slots are activated
4847     in the same order as the order the connection was made, when the
4848     signal is emitted
4849 
4850     The function returns an handle to a connection if it successfully
4851     connects the signal to the slot. The Connection handle will be invalid
4852     if it cannot create the connection, for example, if QObject is unable
4853     to verify the existence of \a signal (if it was not declared as a signal)
4854     You can check if the QMetaObject::Connection is valid by casting it to a bool.
4855 
4856     By default, a signal is emitted for every connection you make;
4857     two signals are emitted for duplicate connections. You can break
4858     all of these connections with a single disconnect() call.
4859     If you pass the Qt::UniqueConnection \a type, the connection will only
4860     be made if it is not a duplicate. If there is already a duplicate
4861     (exact same signal to the exact same slot on the same objects),
4862     the connection will fail and connect will return an invalid QMetaObject::Connection.
4863 
4864     The optional \a type parameter describes the type of connection
4865     to establish. In particular, it determines whether a particular
4866     signal is delivered to a slot immediately or queued for delivery
4867     at a later time. If the signal is queued, the parameters must be
4868     of types that are known to Qt's meta-object system, because Qt
4869     needs to copy the arguments to store them in an event behind the
4870     scenes. If you try to use a queued connection and get the error
4871     message
4872 
4873     \snippet code/src_corelib_kernel_qobject.cpp 25
4874 
4875     make sure to declare the argument type with Q_DECLARE_METATYPE
4876 
4877     Overloaded functions can be resolved with help of \l qOverload.
4878 
4879     \sa {Differences between String-Based and Functor-Based Connections}
4880  */
4881 
4882 /*!
4883     \fn template<typename PointerToMemberFunction, typename Functor> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
4884 
4885     \threadsafe
4886     \overload connect()
4887 
4888     Creates a connection from \a signal in
4889     \a sender object to \a functor, and returns a handle to the connection
4890 
4891     The signal must be a function declared as a signal in the header.
4892     The slot function can be any function or functor that can be connected
4893     to the signal.
4894     A function can be connected to a given signal if the signal has at
4895     least as many argument as the slot. A functor can be connected to a signal
4896     if they have exactly the same number of arguments. There must exist implicit
4897     conversion between the types of the corresponding arguments in the
4898     signal and the slot.
4899 
4900     Example:
4901 
4902     \snippet code/src_corelib_kernel_qobject.cpp 45
4903 
4904     Lambda expressions can also be used:
4905 
4906     \snippet code/src_corelib_kernel_qobject.cpp 46
4907 
4908     The connection will automatically disconnect if the sender is destroyed.
4909     However, you should take care that any objects used within the functor
4910     are still alive when the signal is emitted.
4911 
4912     Overloaded functions can be resolved with help of \l qOverload.
4913 
4914  */
4915 
4916 /*!
4917     \fn template<typename PointerToMemberFunction, typename Functor> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type)
4918 
4919     \threadsafe
4920     \overload connect()
4921 
4922     \since 5.2
4923 
4924     Creates a connection of a given \a type from \a signal in
4925     \a sender object to \a functor to be placed in a specific event
4926     loop of \a context, and returns a handle to the connection.
4927 
4928     \note Qt::UniqueConnections do not work for lambdas, non-member functions
4929     and functors; they only apply to connecting to member functions.
4930 
4931     The signal must be a function declared as a signal in the header.
4932     The slot function can be any function or functor that can be connected
4933     to the signal.
4934     A function can be connected to a given signal if the signal has at
4935     least as many argument as the slot. A functor can be connected to a signal
4936     if they have exactly the same number of arguments. There must exist implicit
4937     conversion between the types of the corresponding arguments in the
4938     signal and the slot.
4939 
4940     Example:
4941 
4942     \snippet code/src_corelib_kernel_qobject.cpp 50
4943 
4944     Lambda expressions can also be used:
4945 
4946     \snippet code/src_corelib_kernel_qobject.cpp 51
4947 
4948     The connection will automatically disconnect if the sender or the context
4949     is destroyed.
4950     However, you should take care that any objects used within the functor
4951     are still alive when the signal is emitted.
4952 
4953     Overloaded functions can be resolved with help of \l qOverload.
4954  */
4955 
4956 /*!
4957     \internal
4958 
4959     Implementation of the template version of connect
4960 
4961     \a sender is the sender object
4962     \a signal is a pointer to a pointer to a member signal of the sender
4963     \a receiver is the receiver object, may not be \nullptr, will be equal to sender when
4964                 connecting to a static function or a functor
4965     \a slot a pointer only used when using Qt::UniqueConnection
4966     \a type the Qt::ConnectionType passed as argument to connect
4967     \a types an array of integer with the metatype id of the parameter of the signal
4968              to be used with queued connection
4969              must stay valid at least for the whole time of the connection, this function
4970              do not take ownership. typically static data.
4971              If \nullptr, then the types will be computed when the signal is emit in a queued
4972              connection from the types from the signature.
4973     \a senderMetaObject is the metaobject used to lookup the signal, the signal must be in
4974                         this metaobject
4975  */
connectImpl(const QObject * sender,void ** signal,const QObject * receiver,void ** slot,QtPrivate::QSlotObjectBase * slotObj,Qt::ConnectionType type,const int * types,const QMetaObject * senderMetaObject)4976 QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
4977                                              const QObject *receiver, void **slot,
4978                                              QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
4979                                              const int *types, const QMetaObject *senderMetaObject)
4980 {
4981     if (!signal) {
4982         qWarning("QObject::connect: invalid nullptr parameter");
4983         if (slotObj)
4984             slotObj->destroyIfLastRef();
4985         return QMetaObject::Connection();
4986     }
4987 
4988     int signal_index = -1;
4989     void *args[] = { &signal_index, signal };
4990     for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
4991         senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
4992         if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(senderMetaObject)->signalCount)
4993             break;
4994     }
4995     if (!senderMetaObject) {
4996         qWarning("QObject::connect: signal not found in %s", sender->metaObject()->className());
4997         slotObj->destroyIfLastRef();
4998         return QMetaObject::Connection(nullptr);
4999     }
5000     signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
5001     return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
5002 }
5003 
5004 /*!
5005     \internal
5006 
5007     Internal version of connect used by the template version of QObject::connect (called via connectImpl) and
5008     also used by the QObjectPrivate::connect version used by QML. The signal_index is expected to be relative
5009     to the number of signals.
5010  */
connectImpl(const QObject * sender,int signal_index,const QObject * receiver,void ** slot,QtPrivate::QSlotObjectBase * slotObj,Qt::ConnectionType type,const int * types,const QMetaObject * senderMetaObject)5011 QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int signal_index,
5012                                              const QObject *receiver, void **slot,
5013                                              QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
5014                                              const int *types, const QMetaObject *senderMetaObject)
5015 {
5016     if (!sender || !receiver || !slotObj || !senderMetaObject) {
5017         const char *senderString = sender ? sender->metaObject()->className()
5018                                           : senderMetaObject ? senderMetaObject->className()
5019                                           : "Unknown";
5020         const char *receiverString = receiver ? receiver->metaObject()->className()
5021                                               : "Unknown";
5022         qWarning("QObject::connect(%s, %s): invalid nullptr parameter", senderString, receiverString);
5023         if (slotObj)
5024             slotObj->destroyIfLastRef();
5025         return QMetaObject::Connection();
5026     }
5027 
5028     QObject *s = const_cast<QObject *>(sender);
5029     QObject *r = const_cast<QObject *>(receiver);
5030 
5031     QOrderedMutexLocker locker(signalSlotLock(sender),
5032                                signalSlotLock(receiver));
5033 
5034     if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.loadRelaxed()) {
5035         QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed();
5036         if (connections->signalVectorCount() > signal_index) {
5037             const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
5038 
5039             while (c2) {
5040                 if (c2->receiver.loadRelaxed() == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
5041                     slotObj->destroyIfLastRef();
5042                     return QMetaObject::Connection();
5043                 }
5044                 c2 = c2->nextConnectionList.loadRelaxed();
5045             }
5046         }
5047         type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
5048     }
5049 
5050     std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
5051     c->sender = s;
5052     c->signal_index = signal_index;
5053     QThreadData *td = r->d_func()->threadData;
5054     td->ref();
5055     c->receiverThreadData.storeRelaxed(td);
5056     c->receiver.storeRelaxed(r);
5057     c->slotObj = slotObj;
5058     c->connectionType = type;
5059     c->isSlotObject = true;
5060     if (types) {
5061         c->argumentTypes.storeRelaxed(types);
5062         c->ownArgumentTypes = false;
5063     }
5064 
5065     QObjectPrivate::get(s)->addConnection(signal_index, c.get());
5066     QMetaObject::Connection ret(c.release());
5067     locker.unlock();
5068 
5069     QMetaMethod method = QMetaObjectPrivate::signal(senderMetaObject, signal_index);
5070     Q_ASSERT(method.isValid());
5071     s->connectNotify(method);
5072 
5073     return ret;
5074 }
5075 
5076 /*!
5077     Disconnect a connection.
5078 
5079     If the \a connection is invalid or has already been disconnected, do nothing
5080     and return false.
5081 
5082    \sa connect()
5083  */
disconnect(const QMetaObject::Connection & connection)5084 bool QObject::disconnect(const QMetaObject::Connection &connection)
5085 {
5086     QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr);
5087 
5088     if (!c)
5089         return false;
5090     QObject *receiver = c->receiver.loadRelaxed();
5091     if (!receiver)
5092         return false;
5093 
5094     QBasicMutex *senderMutex = signalSlotLock(c->sender);
5095     QBasicMutex *receiverMutex = signalSlotLock(receiver);
5096 
5097     QObjectPrivate::ConnectionData *connections;
5098     {
5099         QOrderedMutexLocker locker(senderMutex, receiverMutex);
5100 
5101         // load receiver once again and recheck to ensure nobody else has removed the connection in the meantime
5102         receiver = c->receiver.loadRelaxed();
5103         if (!receiver)
5104             return false;
5105 
5106         connections = QObjectPrivate::get(c->sender)->connections.loadRelaxed();
5107         Q_ASSERT(connections);
5108         connections->removeConnection(c);
5109     }
5110 
5111     connections->cleanOrphanedConnections(c->sender);
5112 
5113     c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(),
5114                                                            c->signal_index));
5115 
5116     const_cast<QMetaObject::Connection &>(connection).d_ptr = nullptr;
5117     c->deref(); // has been removed from the QMetaObject::Connection object
5118 
5119     return true;
5120 }
5121 
5122 /*! \fn template<typename PointerToMemberFunction> bool QObject::disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)
5123     \overload disconnect()
5124     \threadsafe
5125 
5126     Disconnects \a signal in object \a sender from \a method in object
5127     \a receiver. Returns \c true if the connection is successfully broken;
5128     otherwise returns \c false.
5129 
5130     A signal-slot connection is removed when either of the objects
5131     involved are destroyed.
5132 
5133     disconnect() is typically used in three ways, as the following
5134     examples demonstrate.
5135     \list 1
5136     \li Disconnect everything connected to an object's signals:
5137 
5138        \snippet code/src_corelib_kernel_qobject.cpp 26
5139 
5140     \li Disconnect everything connected to a specific signal:
5141 
5142        \snippet code/src_corelib_kernel_qobject.cpp 47
5143 
5144     \li Disconnect a specific receiver:
5145 
5146        \snippet code/src_corelib_kernel_qobject.cpp 30
5147 
5148     \li Disconnect a connection from one specific signal to a specific slot:
5149 
5150        \snippet code/src_corelib_kernel_qobject.cpp 48
5151 
5152 
5153     \endlist
5154 
5155     \nullptr may be used as a wildcard, meaning "any signal", "any receiving
5156     object", or "any slot in the receiving object", respectively.
5157 
5158     The \a sender may never be \nullptr. (You cannot disconnect signals
5159     from more than one object in a single call.)
5160 
5161     If \a signal is \nullptr, it disconnects \a receiver and \a method from
5162     any signal. If not, only the specified signal is disconnected.
5163 
5164     If \a receiver is \nullptr, it disconnects anything connected to \a
5165     signal. If not, slots in objects other than \a receiver are not
5166     disconnected.
5167 
5168     If \a method is \nullptr, it disconnects anything that is connected to \a
5169     receiver. If not, only slots named \a method will be disconnected,
5170     and all other slots are left alone. The \a method must be \nullptr
5171     if \a receiver is left out, so you cannot disconnect a
5172     specifically-named slot on all objects.
5173 
5174     \note It is not possible to use this overload to disconnect signals
5175     connected to functors or lambda expressions. That is because it is not
5176     possible to compare them. Instead, use the overload that takes a
5177     QMetaObject::Connection
5178 
5179     \sa connect()
5180 */
5181 
disconnectImpl(const QObject * sender,void ** signal,const QObject * receiver,void ** slot,const QMetaObject * senderMetaObject)5182 bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, const QMetaObject *senderMetaObject)
5183 {
5184     if (sender == nullptr || (receiver == nullptr && slot != nullptr)) {
5185         qWarning("QObject::disconnect: Unexpected nullptr parameter");
5186         return false;
5187     }
5188 
5189     int signal_index = -1;
5190     if (signal) {
5191         void *args[] = { &signal_index, signal };
5192         for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
5193             senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
5194             if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(senderMetaObject)->signalCount)
5195                 break;
5196         }
5197         if (!senderMetaObject) {
5198             qWarning("QObject::disconnect: signal not found in %s", sender->metaObject()->className());
5199             return false;
5200         }
5201         signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
5202     }
5203 
5204     return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, receiver, -1, slot);
5205 }
5206 
5207 /*!
5208  \internal
5209  Used by QML to connect a signal by index to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass).
5210 
5211  The signal_index is an index relative to the number of methods.
5212  */
connect(const QObject * sender,int signal_index,QtPrivate::QSlotObjectBase * slotObj,Qt::ConnectionType type)5213 QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type)
5214 {
5215     if (!sender) {
5216         qWarning("QObject::connect: invalid nullptr parameter");
5217         if (slotObj)
5218             slotObj->destroyIfLastRef();
5219         return QMetaObject::Connection();
5220     }
5221     const QMetaObject *senderMetaObject = sender->metaObject();
5222     signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
5223 
5224     return QObjectPrivate::connectImpl(sender, signal_index, sender, /*slot*/nullptr, slotObj, type, /*types*/nullptr, senderMetaObject);
5225 }
5226 
5227 /*!
5228  \internal
5229  Used by QML to disconnect a signal by index that's connected to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass)
5230  In the QML case the slot is not a pointer to a pointer to the function to disconnect, but instead it is a pointer to an array of internal values
5231  required for the disconnect.
5232  */
disconnect(const QObject * sender,int signal_index,void ** slot)5233 bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void **slot)
5234 {
5235     const QMetaObject *senderMetaObject = sender->metaObject();
5236     signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
5237 
5238     return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, sender, -1, slot);
5239 }
5240 
5241 /*! \class QMetaObject::Connection
5242     \inmodule QtCore
5243      Represents a handle to a signal-slot (or signal-functor) connection.
5244 
5245      It can be used to check if the connection is valid and to disconnect it using
5246      QObject::disconnect(). For a signal-functor connection without a context object,
5247      it is the only way to selectively disconnect that connection.
5248 
5249      As Connection is just a handle, the underlying signal-slot connection is unaffected
5250      when Connection is destroyed or reassigned.
5251  */
5252 
5253 /*!
5254     Create a copy of the handle to the \a other connection
5255  */
Connection(const QMetaObject::Connection & other)5256 QMetaObject::Connection::Connection(const QMetaObject::Connection &other) : d_ptr(other.d_ptr)
5257 {
5258     if (d_ptr)
5259         static_cast<QObjectPrivate::Connection *>(d_ptr)->ref();
5260 }
5261 
5262 /*!
5263     Assigns \a other to this connection and returns a reference to this connection.
5264 */
operator =(const QMetaObject::Connection & other)5265 QMetaObject::Connection& QMetaObject::Connection::operator=(const QMetaObject::Connection& other)
5266 {
5267     if (other.d_ptr != d_ptr) {
5268         if (d_ptr)
5269             static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
5270         d_ptr = other.d_ptr;
5271         if (other.d_ptr)
5272             static_cast<QObjectPrivate::Connection *>(other.d_ptr)->ref();
5273     }
5274     return *this;
5275 }
5276 
5277 /*!
5278     Creates a Connection instance.
5279 */
5280 
Connection()5281 QMetaObject::Connection::Connection() : d_ptr(nullptr) {}
5282 
5283 /*!
5284     Destructor for QMetaObject::Connection.
5285 */
~Connection()5286 QMetaObject::Connection::~Connection()
5287 {
5288     if (d_ptr)
5289         static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
5290 }
5291 
5292 /*! \internal Returns true if the object is still connected */
isConnected_helper() const5293 bool QMetaObject::Connection::isConnected_helper() const
5294 {
5295     Q_ASSERT(d_ptr);    // we're only called from operator RestrictedBool() const
5296     QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(d_ptr);
5297 
5298     return c->receiver.loadRelaxed();
5299 }
5300 
5301 
5302 /*!
5303     \fn QMetaObject::Connection::operator bool() const
5304 
5305     Returns \c true if the connection is valid.
5306 
5307     The connection is valid if the call to QObject::connect succeeded.
5308     The connection is invalid if QObject::connect was not able to find
5309     the signal or the slot, or if the arguments do not match.
5310  */
5311 
5312 QT_END_NAMESPACE
5313 
5314 #include "moc_qnamespace.cpp"
5315 #include "moc_qobject.cpp"
5316