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#include <mutex>
75
76#include <ctype.h>
77#include <limits.h>
78
79QT_BEGIN_NAMESPACE
80
81static int DIRECT_CONNECTION_ONLY = 0;
82
83Q_LOGGING_CATEGORY(lcConnections, "qt.core.qmetaobject.connectslotsbyname")
84
85Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
86
87void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set)
88{
89 qt_signal_spy_callback_set.storeRelease(newValue: callback_set);
90}
91
92QDynamicMetaObjectData::~QDynamicMetaObjectData()
93{
94}
95
96QAbstractDynamicMetaObject::~QAbstractDynamicMetaObject()
97{
98}
99
100static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
101{
102 int *types = new int [typeNames.count() + 1];
103 Q_CHECK_PTR(types);
104 for (int i = 0; i < typeNames.count(); ++i) {
105 const QByteArray typeName = typeNames.at(i);
106 if (typeName.endsWith(c: '*'))
107 types[i] = QMetaType::VoidStar;
108 else
109 types[i] = QMetaType::type(typeName);
110
111 if (!types[i]) {
112 qWarning(msg: "QObject::connect: Cannot queue arguments of type '%s'\n"
113 "(Make sure '%s' is registered using qRegisterMetaType().)",
114 typeName.constData(), typeName.constData());
115 delete [] types;
116 return nullptr;
117 }
118 }
119 types[typeNames.count()] = 0;
120
121 return types;
122}
123
124static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
125{
126 QScopedArrayPointer<int> types(new int [argc + 1]);
127 for (int i = 0; i < argc; ++i) {
128 const QArgumentType &type = argumentTypes[i];
129 if (type.type())
130 types[i] = type.type();
131 else if (type.name().endsWith(c: '*'))
132 types[i] = QMetaType::VoidStar;
133 else
134 types[i] = QMetaType::type(typeName: type.name());
135
136 if (!types[i]) {
137 qWarning(msg: "QObject::connect: Cannot queue arguments of type '%s'\n"
138 "(Make sure '%s' is registered using qRegisterMetaType().)",
139 type.name().constData(), type.name().constData());
140 return nullptr;
141 }
142 }
143 types[argc] = 0;
144
145 return types.take();
146}
147
148static QBasicMutex _q_ObjectMutexPool[131];
149
150/**
151 * \internal
152 * mutex to be locked when accessing the connection lists or the senders list
153 */
154static inline QBasicMutex *signalSlotLock(const QObject *o)
155{
156 return &_q_ObjectMutexPool[uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)];
157}
158
159#if QT_VERSION < 0x60000
160extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
161{}
162
163extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
164{}
165#endif
166
167void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = nullptr;
168void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = nullptr;
169void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = nullptr;
170void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = nullptr;
171int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
172bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
173void (*QAbstractDeclarativeData::setWidgetParent)(QObject *, QObject *) = nullptr;
174
175/*!
176 \fn QObjectData::QObjectData()
177 \internal
178 */
179
180
181QObjectData::~QObjectData() {}
182
183QMetaObject *QObjectData::dynamicMetaObject() const
184{
185 return metaObject->toDynamicMetaObject(q_ptr);
186}
187
188QObjectPrivate::QObjectPrivate(int version)
189 : threadData(nullptr), currentChildBeingDeleted(nullptr)
190{
191 checkForIncompatibleLibraryVersion(version);
192
193 // QObjectData initialization
194 q_ptr = nullptr;
195 parent = nullptr; // no parent yet. It is set by setParent()
196 isWidget = false; // assume not a widget object
197 blockSig = false; // not blocking signals
198 wasDeleted = false; // double-delete catcher
199 isDeletingChildren = false; // set by deleteChildren()
200 sendChildEvents = true; // if we should send ChildAdded and ChildRemoved events to parent
201 receiveChildEvents = true;
202 postedEvents = 0;
203 extraData = nullptr;
204 metaObject = nullptr;
205 isWindow = false;
206 deleteLaterCalled = false;
207}
208
209QObjectPrivate::~QObjectPrivate()
210{
211 auto thisThreadData = threadData.loadRelaxed();
212 if (extraData && !extraData->runningTimers.isEmpty()) {
213 if (Q_LIKELY(thisThreadData->thread.loadAcquire() == QThread::currentThread())) {
214 // unregister pending timers
215 if (thisThreadData->hasEventDispatcher())
216 thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimers(object: q_ptr);
217
218 // release the timer ids back to the pool
219 for (int i = 0; i < extraData->runningTimers.size(); ++i)
220 QAbstractEventDispatcherPrivate::releaseTimerId(id: extraData->runningTimers.at(i));
221 } else {
222 qWarning(msg: "QObject::~QObject: Timers cannot be stopped from another thread");
223 }
224 }
225
226 if (postedEvents)
227 QCoreApplication::removePostedEvents(receiver: q_ptr, eventType: 0);
228
229 thisThreadData->deref();
230
231 if (metaObject) metaObject->objectDestroyed(q_ptr);
232
233#ifndef QT_NO_USERDATA
234 if (extraData)
235 qDeleteAll(c: extraData->userData);
236#endif
237 delete extraData;
238}
239
240/*!
241 \internal
242 For a given metaobject, compute the signal offset, and the method offset (including signals)
243*/
244static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
245{
246 *signalOffset = *methodOffset = 0;
247 const QMetaObject *m = metaobject->d.superdata;
248 while (m) {
249 const QMetaObjectPrivate *d = QMetaObjectPrivate::get(metaobject: m);
250 *methodOffset += d->methodCount;
251 Q_ASSERT(d->revision >= 4);
252 *signalOffset += d->signalCount;
253 m = m->d.superdata;
254 }
255}
256
257// Used by QAccessibleWidget
258bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
259{
260 Q_Q(const QObject);
261 int signal_index = signalIndex(signalName: signal);
262 ConnectionData *cd = connections.loadRelaxed();
263 if (signal_index < 0 || !cd)
264 return false;
265 QBasicMutexLocker locker(signalSlotLock(o: q));
266 if (signal_index < cd->signalVectorCount()) {
267 const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(i: signal_index).first.loadRelaxed();
268
269 while (c) {
270 if (c->receiver.loadRelaxed() == receiver)
271 return true;
272 c = c->nextConnectionList.loadRelaxed();
273 }
274 }
275 return false;
276}
277
278// Used by QAccessibleWidget
279QObjectList QObjectPrivate::receiverList(const char *signal) const
280{
281 QObjectList returnValue;
282 int signal_index = signalIndex(signalName: signal);
283 ConnectionData *cd = connections.loadRelaxed();
284 if (signal_index < 0 || !cd)
285 return returnValue;
286 if (signal_index < cd->signalVectorCount()) {
287 const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(i: signal_index).first.loadRelaxed();
288
289 while (c) {
290 QObject *r = c->receiver.loadRelaxed();
291 if (r)
292 returnValue << r;
293 c = c->nextConnectionList.loadRelaxed();
294 }
295 }
296 return returnValue;
297}
298
299// Used by QAccessibleWidget
300QObjectList QObjectPrivate::senderList() const
301{
302 QObjectList returnValue;
303 ConnectionData *cd = connections.loadRelaxed();
304 if (cd) {
305 QBasicMutexLocker locker(signalSlotLock(o: q_func()));
306 for (Connection *c = cd->senders; c; c = c->next)
307 returnValue << c->sender;
308 }
309 return returnValue;
310}
311
312/*!
313 \internal
314 Add the connection \a c to the list of connections of the sender's object
315 for the specified \a signal
316
317 The signalSlotLock() of the sender and receiver must be locked while calling
318 this function
319
320 Will also add the connection in the sender's list of the receiver.
321 */
322void QObjectPrivate::addConnection(int signal, Connection *c)
323{
324 Q_ASSERT(c->sender == q_ptr);
325 ensureConnectionData();
326 ConnectionData *cd = connections.loadRelaxed();
327 cd->resizeSignalVector(size: signal + 1);
328
329 ConnectionList &connectionList = cd->connectionsForSignal(signal);
330 if (connectionList.last.loadRelaxed()) {
331 Q_ASSERT(connectionList.last.loadRelaxed()->receiver.loadRelaxed());
332 connectionList.last.loadRelaxed()->nextConnectionList.storeRelaxed(newValue: c);
333 } else {
334 connectionList.first.storeRelaxed(newValue: c);
335 }
336 c->id = ++cd->currentConnectionId;
337 c->prevConnectionList = connectionList.last.loadRelaxed();
338 connectionList.last.storeRelaxed(newValue: c);
339
340 QObjectPrivate *rd = QObjectPrivate::get(o: c->receiver.loadRelaxed());
341 rd->ensureConnectionData();
342
343 c->prev = &(rd->connections.loadRelaxed()->senders);
344 c->next = *c->prev;
345 *c->prev = c;
346 if (c->next)
347 c->next->prev = &c->next;
348}
349
350void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection *c)
351{
352 Q_ASSERT(c->receiver.loadRelaxed());
353 ConnectionList &connections = signalVector.loadRelaxed()->at(i: c->signal_index);
354 c->receiver.storeRelaxed(newValue: nullptr);
355 QThreadData *td = c->receiverThreadData.loadRelaxed();
356 if (td)
357 td->deref();
358 c->receiverThreadData.storeRelaxed(newValue: nullptr);
359
360#ifndef QT_NO_DEBUG
361 bool found = false;
362 for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
363 if (cc == c) {
364 found = true;
365 break;
366 }
367 }
368 Q_ASSERT(found);
369#endif
370
371 // remove from the senders linked list
372 *c->prev = c->next;
373 if (c->next)
374 c->next->prev = c->prev;
375 c->prev = nullptr;
376
377 if (connections.first.loadRelaxed() == c)
378 connections.first.storeRelaxed(newValue: c->nextConnectionList.loadRelaxed());
379 if (connections.last.loadRelaxed() == c)
380 connections.last.storeRelaxed(newValue: c->prevConnectionList);
381 Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).first.loadRelaxed() != c);
382 Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).last.loadRelaxed() != c);
383
384 // keep c->nextConnectionList intact, as it might still get accessed by activate
385 Connection *n = c->nextConnectionList.loadRelaxed();
386 if (n)
387 n->prevConnectionList = c->prevConnectionList;
388 if (c->prevConnectionList)
389 c->prevConnectionList->nextConnectionList.storeRelaxed(newValue: n);
390 c->prevConnectionList = nullptr;
391
392 Q_ASSERT(c != orphaned.loadRelaxed());
393 // add c to orphanedConnections
394 Connection *o = nullptr;
395 /* No ABA issue here: When adding a node, we only care about the list head, it doesn't
396 * matter if the tail changes.
397 */
398 do {
399 o = orphaned.loadRelaxed();
400 c->nextInOrphanList = o;
401 } while (!orphaned.testAndSetRelease(expectedValue: o, newValue: c));
402
403#ifndef QT_NO_DEBUG
404 found = false;
405 for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
406 if (cc == c) {
407 found = true;
408 break;
409 }
410 }
411 Q_ASSERT(!found);
412#endif
413
414}
415
416void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy)
417{
418 QBasicMutex *senderMutex = signalSlotLock(o: sender);
419 ConnectionOrSignalVector *c = nullptr;
420 {
421 std::unique_lock<QBasicMutex> lock(*senderMutex, std::defer_lock_t{});
422 if (lockPolicy == NeedToLock)
423 lock.lock();
424 if (ref.loadAcquire() > 1)
425 return;
426
427 // Since ref == 1, no activate() is in process since we locked the mutex. That implies,
428 // that nothing can reference the orphaned connection objects anymore and they can
429 // be safely deleted
430 c = orphaned.fetchAndStoreRelaxed(newValue: nullptr);
431 }
432 if (c) {
433 // Deleting c might run arbitrary user code, so we must not hold the lock
434 if (lockPolicy == AlreadyLockedAndTemporarilyReleasingLock) {
435 senderMutex->unlock();
436 deleteOrphaned(c);
437 senderMutex->lock();
438 } else {
439 deleteOrphaned(c);
440 }
441 }
442}
443
444void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o)
445{
446 while (o) {
447 QObjectPrivate::ConnectionOrSignalVector *next = nullptr;
448 if (SignalVector *v = ConnectionOrSignalVector::asSignalVector(c: o)) {
449 next = v->nextInOrphanList;
450 free(ptr: v);
451 } else {
452 QObjectPrivate::Connection *c = static_cast<Connection *>(o);
453 next = c->nextInOrphanList;
454 Q_ASSERT(!c->receiver.loadRelaxed());
455 Q_ASSERT(!c->prev);
456 c->freeSlotObject();
457 c->deref();
458 }
459 o = next;
460 }
461}
462
463/*! \internal
464
465 Returns \c true if the signal with index \a signal_index from object \a sender is connected.
466
467 \a signal_index must be the index returned by QObjectPrivate::signalIndex;
468*/
469bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) const
470{
471 if (checkDeclarative && isDeclarativeSignalConnected(signal_index: signalIndex))
472 return true;
473
474 ConnectionData *cd = connections.loadRelaxed();
475 if (!cd)
476 return false;
477 SignalVector *signalVector = cd->signalVector.loadRelaxed();
478 if (!signalVector)
479 return false;
480
481 if (signalVector->at(i: -1).first.loadRelaxed())
482 return true;
483
484 if (signalIndex < uint(cd->signalVectorCount())) {
485 const QObjectPrivate::Connection *c = signalVector->at(i: signalIndex).first.loadRelaxed();
486 while (c) {
487 if (c->receiver.loadRelaxed())
488 return true;
489 c = c->nextConnectionList.loadRelaxed();
490 }
491 }
492 return false;
493}
494
495bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
496{
497 ConnectionData *cd = connections.loadRelaxed();
498 if (!cd)
499 return false;
500 SignalVector *signalVector = cd->signalVector.loadRelaxed();
501 if (!signalVector)
502 return false;
503
504 if (signalVector->at(i: -1).first.loadAcquire())
505 return true;
506
507 if (signalIndex < uint(cd->signalVectorCount())) {
508 const QObjectPrivate::Connection *c = signalVector->at(i: signalIndex).first.loadAcquire();
509 return c != nullptr;
510 }
511 return false;
512}
513
514/*!
515 \internal
516 */
517QAbstractMetaCallEvent::~QAbstractMetaCallEvent()
518{
519#if QT_CONFIG(thread)
520 if (semaphore_)
521 semaphore_->release();
522#endif
523}
524
525/*!
526 \internal
527 */
528inline void QMetaCallEvent::allocArgs()
529{
530 if (!d.nargs_)
531 return;
532
533 constexpr size_t each = sizeof(void*) + sizeof(int);
534 void *const memory = d.nargs_ * each > sizeof(prealloc_) ?
535 calloc(nmemb: d.nargs_, size: each) : prealloc_;
536
537 Q_CHECK_PTR(memory);
538 d.args_ = static_cast<void **>(memory);
539}
540
541/*!
542 \internal
543
544 Used for blocking queued connections, just passes \a args through without
545 allocating any memory.
546 */
547QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
548 QObjectPrivate::StaticMetaCallFunction callFunction,
549 const QObject *sender, int signalId,
550 void **args, QSemaphore *semaphore)
551 : QAbstractMetaCallEvent(sender, signalId, semaphore),
552 d({.slotObj_: nullptr, .args_: args, .callFunction_: callFunction, .nargs_: 0, .method_offset_: method_offset, .method_relative_: method_relative}),
553 prealloc_()
554{
555}
556
557/*!
558 \internal
559
560 Used for blocking queued connections, just passes \a args through without
561 allocating any memory.
562 */
563QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
564 const QObject *sender, int signalId,
565 void **args, QSemaphore *semaphore)
566 : QAbstractMetaCallEvent(sender, signalId, semaphore),
567 d({.slotObj_: slotO, .args_: args, .callFunction_: nullptr, .nargs_: 0, .method_offset_: 0, .method_relative_: ushort(-1)}),
568 prealloc_()
569{
570 if (d.slotObj_)
571 d.slotObj_->ref();
572}
573
574/*!
575 \internal
576
577 Allocates memory for \a nargs; code creating an event needs to initialize
578 the void* and int arrays by accessing \a args() and \a types(), respectively.
579 */
580QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
581 QObjectPrivate::StaticMetaCallFunction callFunction,
582 const QObject *sender, int signalId,
583 int nargs)
584 : QAbstractMetaCallEvent(sender, signalId),
585 d({.slotObj_: nullptr, .args_: nullptr, .callFunction_: callFunction, .nargs_: nargs, .method_offset_: method_offset, .method_relative_: method_relative}),
586 prealloc_()
587{
588 allocArgs();
589}
590
591/*!
592 \internal
593
594 Allocates memory for \a nargs; code creating an event needs to initialize
595 the void* and int arrays by accessing \a args() and \a types(), respectively.
596 */
597QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
598 const QObject *sender, int signalId,
599 int nargs)
600 : QAbstractMetaCallEvent(sender, signalId),
601 d({.slotObj_: slotO, .args_: nullptr, .callFunction_: nullptr, .nargs_: nargs, .method_offset_: 0, .method_relative_: ushort(-1)}),
602 prealloc_()
603{
604 if (d.slotObj_)
605 d.slotObj_->ref();
606 allocArgs();
607}
608
609/*!
610 \internal
611 */
612QMetaCallEvent::~QMetaCallEvent()
613{
614 if (d.nargs_) {
615 int *typeIDs = types();
616 for (int i = 0; i < d.nargs_; ++i) {
617 if (typeIDs[i] && d.args_[i])
618 QMetaType::destroy(type: typeIDs[i], data: d.args_[i]);
619 }
620 if (reinterpret_cast<void*>(d.args_) != reinterpret_cast<void*>(prealloc_))
621 free(ptr: d.args_);
622 }
623 if (d.slotObj_)
624 d.slotObj_->destroyIfLastRef();
625}
626
627/*!
628 \internal
629 */
630void QMetaCallEvent::placeMetaCall(QObject *object)
631{
632 if (d.slotObj_) {
633 d.slotObj_->call(r: object, a: d.args_);
634 } else if (d.callFunction_ && d.method_offset_ <= object->metaObject()->methodOffset()) {
635 d.callFunction_(object, QMetaObject::InvokeMetaMethod, d.method_relative_, d.args_);
636 } else {
637 QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod,
638 d.method_offset_ + d.method_relative_, d.args_);
639 }
640}
641
642/*!
643 \class QSignalBlocker
644 \brief Exception-safe wrapper around QObject::blockSignals().
645 \since 5.3
646 \ingroup objectmodel
647 \inmodule QtCore
648
649 \reentrant
650
651 QSignalBlocker can be used wherever you would otherwise use a
652 pair of calls to blockSignals(). It blocks signals in its
653 constructor and in the destructor it resets the state to what
654 it was before the constructor ran.
655
656 \snippet code/src_corelib_kernel_qobject.cpp 53
657 is thus equivalent to
658 \snippet code/src_corelib_kernel_qobject.cpp 54
659
660 except the code using QSignalBlocker is safe in the face of
661 exceptions.
662
663 \sa QMutexLocker, QEventLoopLocker
664*/
665
666/*!
667 \fn QSignalBlocker::QSignalBlocker(QObject *object)
668
669 Constructor. Calls \a{object}->blockSignals(true).
670*/
671
672/*!
673 \fn QSignalBlocker::QSignalBlocker(QObject &object)
674 \overload
675
676 Calls \a{object}.blockSignals(true).
677*/
678
679/*!
680 \fn QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
681
682 Move-constructs a signal blocker from \a other. \a other will have
683 a no-op destructor, while responsibility for restoring the
684 QObject::signalsBlocked() state is transferred to the new object.
685*/
686
687/*!
688 \fn QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other)
689
690 Move-assigns this signal blocker from \a other. \a other will have
691 a no-op destructor, while responsibility for restoring the
692 QObject::signalsBlocked() state is transferred to this object.
693
694 The object's signals this signal blocker was blocking prior to
695 being moved to, if any, are unblocked \e except in the case where
696 both instances block the same object's signals and \c *this is
697 unblocked while \a other is not, at the time of the move.
698*/
699
700/*!
701 \fn QSignalBlocker::~QSignalBlocker()
702
703 Destructor. Restores the QObject::signalsBlocked() state to what it
704 was before the constructor ran, unless unblock() has been called
705 without a following reblock(), in which case it does nothing.
706*/
707
708/*!
709 \fn void QSignalBlocker::reblock()
710
711 Re-blocks signals after a previous unblock().
712
713 The numbers of reblock() and unblock() calls are not counted, so
714 every reblock() undoes any number of unblock() calls.
715*/
716
717/*!
718 \fn void QSignalBlocker::unblock()
719
720 Temporarily restores the QObject::signalsBlocked() state to what
721 it was before this QSignalBlocker's constructor ran. To undo, use
722 reblock().
723
724 The numbers of reblock() and unblock() calls are not counted, so
725 every unblock() undoes any number of reblock() calls.
726*/
727
728/*!
729 \class QObject
730 \inmodule QtCore
731 \brief The QObject class is the base class of all Qt objects.
732
733 \ingroup objectmodel
734
735 \reentrant
736
737 QObject is the heart of the Qt \l{Object Model}. The central
738 feature in this model is a very powerful mechanism for seamless
739 object communication called \l{signals and slots}. You can
740 connect a signal to a slot with connect() and destroy the
741 connection with disconnect(). To avoid never ending notification
742 loops you can temporarily block signals with blockSignals(). The
743 protected functions connectNotify() and disconnectNotify() make
744 it possible to track connections.
745
746 QObjects organize themselves in \l {Object Trees & Ownership}
747 {object trees}. When you create a QObject with another object as
748 parent, the object will automatically add itself to the parent's
749 children() list. The parent takes ownership of the object; i.e.,
750 it will automatically delete its children in its destructor. You
751 can look for an object by name and optionally type using
752 findChild() or findChildren().
753
754 Every object has an objectName() and its class name can be found
755 via the corresponding metaObject() (see QMetaObject::className()).
756 You can determine whether the object's class inherits another
757 class in the QObject inheritance hierarchy by using the
758 inherits() function.
759
760 When an object is deleted, it emits a destroyed() signal. You can
761 catch this signal to avoid dangling references to QObjects.
762
763 QObjects can receive events through event() and filter the events
764 of other objects. See installEventFilter() and eventFilter() for
765 details. A convenience handler, childEvent(), can be reimplemented
766 to catch child events.
767
768 Last but not least, QObject provides the basic timer support in
769 Qt; see QTimer for high-level support for timers.
770
771 Notice that the Q_OBJECT macro is mandatory for any object that
772 implements signals, slots or properties. You also need to run the
773 \l{moc}{Meta Object Compiler} on the source file. We strongly
774 recommend the use of this macro in all subclasses of QObject
775 regardless of whether or not they actually use signals, slots and
776 properties, since failure to do so may lead certain functions to
777 exhibit strange behavior.
778
779 All Qt widgets inherit QObject. The convenience function
780 isWidgetType() returns whether an object is actually a widget. It
781 is much faster than
782 \l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
783 \e{obj}->\l{inherits()}{inherits}("QWidget").
784
785 Some QObject functions, e.g. children(), return a QObjectList.
786 QObjectList is a typedef for QList<QObject *>.
787
788 \section1 Thread Affinity
789
790 A QObject instance is said to have a \e{thread affinity}, or that
791 it \e{lives} in a certain thread. When a QObject receives a
792 \l{Qt::QueuedConnection}{queued signal} or a \l{The Event
793 System#Sending Events}{posted event}, the slot or event handler
794 will run in the thread that the object lives in.
795
796 \note If a QObject has no thread affinity (that is, if thread()
797 returns zero), or if it lives in a thread that has no running event
798 loop, then it cannot receive queued signals or posted events.
799
800 By default, a QObject lives in the thread in which it is created.
801 An object's thread affinity can be queried using thread() and
802 changed using moveToThread().
803
804 All QObjects must live in the same thread as their parent. Consequently:
805
806 \list
807 \li setParent() will fail if the two QObjects involved live in
808 different threads.
809 \li When a QObject is moved to another thread, all its children
810 will be automatically moved too.
811 \li moveToThread() will fail if the QObject has a parent.
812 \li If QObjects are created within QThread::run(), they cannot
813 become children of the QThread object because the QThread does
814 not live in the thread that calls QThread::run().
815 \endlist
816
817 \note A QObject's member variables \e{do not} automatically become
818 its children. The parent-child relationship must be set by either
819 passing a pointer to the child's \l{QObject()}{constructor}, or by
820 calling setParent(). Without this step, the object's member variables
821 will remain in the old thread when moveToThread() is called.
822
823 \target No copy constructor
824 \section1 No Copy Constructor or Assignment Operator
825
826 QObject has neither a copy constructor nor an assignment operator.
827 This is by design. Actually, they are declared, but in a
828 \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
829 Qt classes derived from QObject (direct or indirect) use this
830 macro to declare their copy constructor and assignment operator to
831 be private. The reasoning is found in the discussion on
832 \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
833 Model} page.
834
835 The main consequence is that you should use pointers to QObject
836 (or to your QObject subclass) where you might otherwise be tempted
837 to use your QObject subclass as a value. For example, without a
838 copy constructor, you can't use a subclass of QObject as the value
839 to be stored in one of the container classes. You must store
840 pointers.
841
842 \section1 Auto-Connection
843
844 Qt's meta-object system provides a mechanism to automatically connect
845 signals and slots between QObject subclasses and their children. As long
846 as objects are defined with suitable object names, and slots follow a
847 simple naming convention, this connection can be performed at run-time
848 by the QMetaObject::connectSlotsByName() function.
849
850 \l uic generates code that invokes this function to enable
851 auto-connection to be performed between widgets on forms created
852 with \e{Qt Designer}. More information about using auto-connection with \e{Qt Designer} is
853 given in the \l{Using a Designer UI File in Your C++ Application} section of
854 the \e{Qt Designer} manual.
855
856 \section1 Dynamic Properties
857
858 From Qt 4.2, dynamic properties can be added to and removed from QObject
859 instances at run-time. Dynamic properties do not need to be declared at
860 compile-time, yet they provide the same advantages as static properties
861 and are manipulated using the same API - using property() to read them
862 and setProperty() to write them.
863
864 From Qt 4.3, dynamic properties are supported by
865 \l{Qt Designer's Widget Editing Mode#The Property Editor}{Qt Designer},
866 and both standard Qt widgets and user-created forms can be given dynamic
867 properties.
868
869 \section1 Internationalization (I18n)
870
871 All QObject subclasses support Qt's translation features, making it possible
872 to translate an application's user interface into different languages.
873
874 To make user-visible text translatable, it must be wrapped in calls to
875 the tr() function. This is explained in detail in the
876 \l{Writing Source Code for Translation} document.
877
878 \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
879 \sa {Object Trees & Ownership}
880*/
881
882/*****************************************************************************
883 QObject member functions
884 *****************************************************************************/
885
886// check the constructor's parent thread argument
887static bool check_parent_thread(QObject *parent,
888 QThreadData *parentThreadData,
889 QThreadData *currentThreadData)
890{
891 if (parent && parentThreadData != currentThreadData) {
892 QThread *parentThread = parentThreadData->thread.loadAcquire();
893 QThread *currentThread = currentThreadData->thread.loadAcquire();
894 qWarning(msg: "QObject: Cannot create children for a parent that is in a different thread.\n"
895 "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
896 parent->metaObject()->className(),
897 parent,
898 parentThread ? parentThread->metaObject()->className() : "QThread",
899 parentThread,
900 currentThread ? currentThread->metaObject()->className() : "QThread",
901 currentThread);
902 return false;
903 }
904 return true;
905}
906
907/*!
908 Constructs an object with parent object \a parent.
909
910 The parent of an object may be viewed as the object's owner. For
911 instance, a \l{QDialog}{dialog box} is the parent of the \uicontrol{OK}
912 and \uicontrol{Cancel} buttons it contains.
913
914 The destructor of a parent object destroys all child objects.
915
916 Setting \a parent to \nullptr constructs an object with no parent. If the
917 object is a widget, it will become a top-level window.
918
919 \sa parent(), findChild(), findChildren()
920*/
921
922QObject::QObject(QObject *parent)
923 : QObject(*new QObjectPrivate, parent)
924{
925}
926
927/*!
928 \internal
929 */
930QObject::QObject(QObjectPrivate &dd, QObject *parent)
931 : d_ptr(&dd)
932{
933 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QObject to itself");
934
935 Q_D(QObject);
936 d_ptr->q_ptr = this;
937 auto threadData = (parent && !parent->thread()) ? parent->d_func()->threadData.loadRelaxed() : QThreadData::current();
938 threadData->ref();
939 d->threadData.storeRelaxed(newValue: threadData);
940 if (parent) {
941 QT_TRY {
942 if (!check_parent_thread(parent, parentThreadData: parent ? parent->d_func()->threadData.loadRelaxed() : nullptr, currentThreadData: threadData))
943 parent = nullptr;
944 if (d->isWidget) {
945 if (parent) {
946 d->parent = parent;
947 d->parent->d_func()->children.append(t: this);
948 }
949 // no events sent here, this is done at the end of the QWidget constructor
950 } else {
951 setParent(parent);
952 }
953 } QT_CATCH(...) {
954 threadData->deref();
955 QT_RETHROW;
956 }
957 }
958#if QT_VERSION < 0x60000
959 qt_addObject(this);
960#endif
961 if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
962 reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
963 Q_TRACE(QObject_ctor, this);
964}
965
966/*!
967 Destroys the object, deleting all its child objects.
968
969 All signals to and from the object are automatically disconnected, and
970 any pending posted events for the object are removed from the event
971 queue. However, it is often safer to use deleteLater() rather than
972 deleting a QObject subclass directly.
973
974 \warning All child objects are deleted. If any of these objects
975 are on the stack or global, sooner or later your program will
976 crash. We do not recommend holding pointers to child objects from
977 outside the parent. If you still do, the destroyed() signal gives
978 you an opportunity to detect when an object is destroyed.
979
980 \warning Deleting a QObject while pending events are waiting to
981 be delivered can cause a crash. You must not delete the QObject
982 directly if it exists in a different thread than the one currently
983 executing. Use deleteLater() instead, which will cause the event
984 loop to delete the object after all pending events have been
985 delivered to it.
986
987 \sa deleteLater()
988*/
989
990QObject::~QObject()
991{
992 Q_D(QObject);
993 d->wasDeleted = true;
994 d->blockSig = 0; // unblock signals so we always emit destroyed()
995
996 QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.loadRelaxed();
997 if (sharedRefcount) {
998 if (sharedRefcount->strongref.loadRelaxed() > 0) {
999 qWarning(msg: "QObject: shared QObject was deleted directly. The program is malformed and may crash.");
1000 // but continue deleting, it's too late to stop anyway
1001 }
1002
1003 // indicate to all QWeakPointers that this QObject has now been deleted
1004 sharedRefcount->strongref.storeRelaxed(newValue: 0);
1005 if (!sharedRefcount->weakref.deref())
1006 delete sharedRefcount;
1007 }
1008
1009 if (!d->isWidget && d->isSignalConnected(signalIndex: 0)) {
1010 emit destroyed(this);
1011 }
1012
1013 if (d->declarativeData) {
1014 if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
1015 if (QAbstractDeclarativeData::destroyed_qml1)
1016 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
1017 } else {
1018 if (QAbstractDeclarativeData::destroyed)
1019 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1020 }
1021 }
1022
1023 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
1024 if (cd) {
1025 if (cd->currentSender) {
1026 cd->currentSender->receiverDeleted();
1027 cd->currentSender = nullptr;
1028 }
1029
1030 QBasicMutex *signalSlotMutex = signalSlotLock(o: this);
1031 QBasicMutexLocker locker(signalSlotMutex);
1032
1033 // disconnect all receivers
1034 int receiverCount = cd->signalVectorCount();
1035 for (int signal = -1; signal < receiverCount; ++signal) {
1036 QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal);
1037
1038 while (QObjectPrivate::Connection *c = connectionList.first.loadRelaxed()) {
1039 Q_ASSERT(c->receiver.loadAcquire());
1040
1041 QBasicMutex *m = signalSlotLock(o: c->receiver.loadRelaxed());
1042 bool needToUnlock = QOrderedMutexLocker::relock(mtx1: signalSlotMutex, mtx2: m);
1043 if (c == connectionList.first.loadAcquire() && c->receiver.loadAcquire()) {
1044 cd->removeConnection(c);
1045 Q_ASSERT(connectionList.first.loadRelaxed() != c);
1046 }
1047 if (needToUnlock)
1048 m->unlock();
1049 }
1050 }
1051
1052 /* Disconnect all senders:
1053 */
1054 while (QObjectPrivate::Connection *node = cd->senders) {
1055 Q_ASSERT(node->receiver.loadAcquire());
1056 QObject *sender = node->sender;
1057 // Send disconnectNotify before removing the connection from sender's connection list.
1058 // This ensures any eventual destructor of sender will block on getting receiver's lock
1059 // and not finish until we release it.
1060 sender->disconnectNotify(signal: QMetaObjectPrivate::signal(m: sender->metaObject(), signal_index: node->signal_index));
1061 QBasicMutex *m = signalSlotLock(o: sender);
1062 bool needToUnlock = QOrderedMutexLocker::relock(mtx1: signalSlotMutex, mtx2: m);
1063 //the node has maybe been removed while the mutex was unlocked in relock?
1064 if (node != cd->senders) {
1065 // We hold the wrong mutex
1066 Q_ASSERT(needToUnlock);
1067 m->unlock();
1068 continue;
1069 }
1070
1071 QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.loadRelaxed();
1072 Q_ASSERT(senderData);
1073
1074 QtPrivate::QSlotObjectBase *slotObj = nullptr;
1075 if (node->isSlotObject) {
1076 slotObj = node->slotObj;
1077 node->isSlotObject = false;
1078 }
1079
1080 senderData->removeConnection(c: node);
1081 /*
1082 When we unlock, another thread has the chance to delete/modify sender data.
1083 Thus we need to call cleanOrphanedConnections before unlocking. We use the
1084 variant of the function which assumes that the lock is already held to avoid
1085 a deadlock.
1086 We need to hold m, the sender lock. Considering that we might execute arbitrary user
1087 code, we should already release the signalSlotMutex here – unless they are the same.
1088 */
1089 const bool locksAreTheSame = signalSlotMutex == m;
1090 if (!locksAreTheSame)
1091 locker.unlock();
1092 senderData->cleanOrphanedConnections(
1093 sender,
1094 lockPolicy: QObjectPrivate::ConnectionData::AlreadyLockedAndTemporarilyReleasingLock
1095 );
1096 if (needToUnlock)
1097 m->unlock();
1098
1099 if (locksAreTheSame) // otherwise already unlocked
1100 locker.unlock();
1101 if (slotObj)
1102 slotObj->destroyIfLastRef();
1103 locker.relock();
1104 }
1105
1106 // invalidate all connections on the object and make sure
1107 // activate() will skip them
1108 cd->currentConnectionId.storeRelaxed(newValue: 0);
1109 }
1110 if (cd && !cd->ref.deref())
1111 delete cd;
1112 d->connections.storeRelaxed(newValue: nullptr);
1113
1114 if (!d->children.isEmpty())
1115 d->deleteChildren();
1116
1117#if QT_VERSION < 0x60000
1118 qt_removeObject(this);
1119#endif
1120 if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
1121 reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
1122
1123 Q_TRACE(QObject_dtor, this);
1124
1125 if (d->parent) // remove it from parent object
1126 d->setParent_helper(nullptr);
1127}
1128
1129QObjectPrivate::Connection::~Connection()
1130{
1131 if (ownArgumentTypes) {
1132 const int *v = argumentTypes.loadRelaxed();
1133 if (v != &DIRECT_CONNECTION_ONLY)
1134 delete [] v;
1135 }
1136 if (isSlotObject)
1137 slotObj->destroyIfLastRef();
1138}
1139
1140
1141/*!
1142 \fn const QMetaObject *QObject::metaObject() const
1143
1144 Returns a pointer to the meta-object of this object.
1145
1146 A meta-object contains information about a class that inherits
1147 QObject, e.g. class name, superclass name, properties, signals and
1148 slots. Every QObject subclass that contains the Q_OBJECT macro will have a
1149 meta-object.
1150
1151 The meta-object information is required by the signal/slot
1152 connection mechanism and the property system. The inherits()
1153 function also makes use of the meta-object.
1154
1155 If you have no pointer to an actual object instance but still
1156 want to access the meta-object of a class, you can use \l
1157 staticMetaObject.
1158
1159 Example:
1160
1161 \snippet code/src_corelib_kernel_qobject.cpp 1
1162
1163 \sa staticMetaObject
1164*/
1165
1166/*!
1167 \variable QObject::staticMetaObject
1168
1169 This variable stores the meta-object for the class.
1170
1171 A meta-object contains information about a class that inherits
1172 QObject, e.g. class name, superclass name, properties, signals and
1173 slots. Every class that contains the Q_OBJECT macro will also have
1174 a meta-object.
1175
1176 The meta-object information is required by the signal/slot
1177 connection mechanism and the property system. The inherits()
1178 function also makes use of the meta-object.
1179
1180 If you have a pointer to an object, you can use metaObject() to
1181 retrieve the meta-object associated with that object.
1182
1183 Example:
1184
1185 \snippet code/src_corelib_kernel_qobject.cpp 2
1186
1187 \sa metaObject()
1188*/
1189
1190/*!
1191 \fn template <class T> T qobject_cast(QObject *object)
1192 \fn template <class T> T qobject_cast(const QObject *object)
1193 \relates QObject
1194
1195 Returns the given \a object cast to type T if the object is of type
1196 T (or of a subclass); otherwise returns \nullptr. If \a object is
1197 \nullptr then it will also return \nullptr.
1198
1199 The class T must inherit (directly or indirectly) QObject and be
1200 declared with the \l Q_OBJECT macro.
1201
1202 A class is considered to inherit itself.
1203
1204 Example:
1205
1206 \snippet code/src_corelib_kernel_qobject.cpp 3
1207
1208 The qobject_cast() function behaves similarly to the standard C++
1209 \c dynamic_cast(), with the advantages that it doesn't require
1210 RTTI support and it works across dynamic library boundaries.
1211
1212 qobject_cast() can also be used in conjunction with interfaces;
1213 see the \l{tools/plugandpaint/app}{Plug & Paint} example for details.
1214
1215 \warning If T isn't declared with the Q_OBJECT macro, this
1216 function's return value is undefined.
1217
1218 \sa QObject::inherits()
1219*/
1220
1221/*!
1222 \fn bool QObject::inherits(const char *className) const
1223
1224 Returns \c true if this object is an instance of a class that
1225 inherits \a className or a QObject subclass that inherits \a
1226 className; otherwise returns \c false.
1227
1228 A class is considered to inherit itself.
1229
1230 Example:
1231
1232 \snippet code/src_corelib_kernel_qobject.cpp 4
1233
1234 If you need to determine whether an object is an instance of a particular
1235 class for the purpose of casting it, consider using qobject_cast<Type *>(object)
1236 instead.
1237
1238 \sa metaObject(), qobject_cast()
1239*/
1240
1241/*!
1242 \property QObject::objectName
1243
1244 \brief the name of this object
1245
1246 You can find an object by name (and type) using findChild().
1247 You can find a set of objects with findChildren().
1248
1249 \snippet code/src_corelib_kernel_qobject.cpp 5
1250
1251 By default, this property contains an empty string.
1252
1253 \sa metaObject(), QMetaObject::className()
1254*/
1255
1256QString QObject::objectName() const
1257{
1258 Q_D(const QObject);
1259 return d->extraData ? d->extraData->objectName : QString();
1260}
1261
1262/*
1263 Sets the object's name to \a name.
1264*/
1265void QObject::setObjectName(const QString &name)
1266{
1267 Q_D(QObject);
1268 if (!d->extraData)
1269 d->extraData = new QObjectPrivate::ExtraData;
1270
1271 if (d->extraData->objectName != name) {
1272 d->extraData->objectName = name;
1273 emit objectNameChanged(objectName: d->extraData->objectName, QPrivateSignal());
1274 }
1275}
1276
1277/*! \fn void QObject::objectNameChanged(const QString &objectName)
1278
1279 This signal is emitted after the object's name has been changed. The new object name is passed as \a objectName.
1280
1281 \sa QObject::objectName
1282*/
1283
1284/*!
1285 \fn bool QObject::isWidgetType() const
1286
1287 Returns \c true if the object is a widget; otherwise returns \c false.
1288
1289 Calling this function is equivalent to calling
1290 \c{inherits("QWidget")}, except that it is much faster.
1291*/
1292
1293/*!
1294 \fn bool QObject::isWindowType() const
1295
1296 Returns \c true if the object is a window; otherwise returns \c false.
1297
1298 Calling this function is equivalent to calling
1299 \c{inherits("QWindow")}, except that it is much faster.
1300*/
1301
1302/*!
1303 This virtual function receives events to an object and should
1304 return true if the event \a e was recognized and processed.
1305
1306 The event() function can be reimplemented to customize the
1307 behavior of an object.
1308
1309 Make sure you call the parent event class implementation
1310 for all the events you did not handle.
1311
1312 Example:
1313
1314 \snippet code/src_corelib_kernel_qobject.cpp 52
1315
1316 \sa installEventFilter(), timerEvent(), QCoreApplication::sendEvent(),
1317 QCoreApplication::postEvent()
1318*/
1319
1320bool QObject::event(QEvent *e)
1321{
1322 switch (e->type()) {
1323 case QEvent::Timer:
1324 timerEvent(event: (QTimerEvent*)e);
1325 break;
1326
1327 case QEvent::ChildAdded:
1328 case QEvent::ChildPolished:
1329 case QEvent::ChildRemoved:
1330 childEvent(event: (QChildEvent*)e);
1331 break;
1332
1333 case QEvent::DeferredDelete:
1334 qDeleteInEventHandler(o: this);
1335 break;
1336
1337 case QEvent::MetaCall:
1338 {
1339 QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e);
1340
1341 if (!d_func()->connections.loadRelaxed()) {
1342 QBasicMutexLocker locker(signalSlotLock(o: this));
1343 d_func()->ensureConnectionData();
1344 }
1345 QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId());
1346
1347 mce->placeMetaCall(object: this);
1348 break;
1349 }
1350
1351 case QEvent::ThreadChange: {
1352 Q_D(QObject);
1353 QThreadData *threadData = d->threadData.loadRelaxed();
1354 QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
1355 if (eventDispatcher) {
1356 QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(object: this);
1357 if (!timers.isEmpty()) {
1358 // do not to release our timer ids back to the pool (since the timer ids are moving to a new thread).
1359 eventDispatcher->unregisterTimers(object: this);
1360 QMetaObject::invokeMethod(obj: this, member: "_q_reregisterTimers", type: Qt::QueuedConnection,
1361 Q_ARG(void*, (new QList<QAbstractEventDispatcher::TimerInfo>(timers))));
1362 }
1363 }
1364 break;
1365 }
1366
1367 default:
1368 if (e->type() >= QEvent::User) {
1369 customEvent(event: e);
1370 break;
1371 }
1372 return false;
1373 }
1374 return true;
1375}
1376
1377/*!
1378 \fn void QObject::timerEvent(QTimerEvent *event)
1379
1380 This event handler can be reimplemented in a subclass to receive
1381 timer events for the object.
1382
1383 QTimer provides a higher-level interface to the timer
1384 functionality, and also more general information about timers. The
1385 timer event is passed in the \a event parameter.
1386
1387 \sa startTimer(), killTimer(), event()
1388*/
1389
1390void QObject::timerEvent(QTimerEvent *)
1391{
1392}
1393
1394
1395/*!
1396 This event handler can be reimplemented in a subclass to receive
1397 child events. The event is passed in the \a event parameter.
1398
1399 QEvent::ChildAdded and QEvent::ChildRemoved events are sent to
1400 objects when children are added or removed. In both cases you can
1401 only rely on the child being a QObject, or if isWidgetType()
1402 returns \c true, a QWidget. (This is because, in the
1403 \l{QEvent::ChildAdded}{ChildAdded} case, the child is not yet
1404 fully constructed, and in the \l{QEvent::ChildRemoved}{ChildRemoved}
1405 case it might have been destructed already).
1406
1407 QEvent::ChildPolished events are sent to widgets when children
1408 are polished, or when polished children are added. If you receive
1409 a child polished event, the child's construction is usually
1410 completed. However, this is not guaranteed, and multiple polish
1411 events may be delivered during the execution of a widget's
1412 constructor.
1413
1414 For every child widget, you receive one
1415 \l{QEvent::ChildAdded}{ChildAdded} event, zero or more
1416 \l{QEvent::ChildPolished}{ChildPolished} events, and one
1417 \l{QEvent::ChildRemoved}{ChildRemoved} event.
1418
1419 The \l{QEvent::ChildPolished}{ChildPolished} event is omitted if
1420 a child is removed immediately after it is added. If a child is
1421 polished several times during construction and destruction, you
1422 may receive several child polished events for the same child,
1423 each time with a different virtual table.
1424
1425 \sa event()
1426*/
1427
1428void QObject::childEvent(QChildEvent * /* event */)
1429{
1430}
1431
1432
1433/*!
1434 This event handler can be reimplemented in a subclass to receive
1435 custom events. Custom events are user-defined events with a type
1436 value at least as large as the QEvent::User item of the
1437 QEvent::Type enum, and is typically a QEvent subclass. The event
1438 is passed in the \a event parameter.
1439
1440 \sa event(), QEvent
1441*/
1442void QObject::customEvent(QEvent * /* event */)
1443{
1444}
1445
1446
1447
1448/*!
1449 Filters events if this object has been installed as an event
1450 filter for the \a watched object.
1451
1452 In your reimplementation of this function, if you want to filter
1453 the \a event out, i.e. stop it being handled further, return
1454 true; otherwise return false.
1455
1456 Example:
1457 \snippet code/src_corelib_kernel_qobject.cpp 6
1458
1459 Notice in the example above that unhandled events are passed to
1460 the base class's eventFilter() function, since the base class
1461 might have reimplemented eventFilter() for its own internal
1462 purposes.
1463
1464 Some events, such as \l QEvent::ShortcutOverride must be explicitly
1465 accepted (by calling \l {QEvent::}{accept()} on them) in order to prevent
1466 propagation.
1467
1468 \warning If you delete the receiver object in this function, be
1469 sure to return true. Otherwise, Qt will forward the event to the
1470 deleted object and the program might crash.
1471
1472 \sa installEventFilter()
1473*/
1474
1475bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
1476{
1477 return false;
1478}
1479
1480/*!
1481 \fn bool QObject::signalsBlocked() const
1482
1483 Returns \c true if signals are blocked; otherwise returns \c false.
1484
1485 Signals are not blocked by default.
1486
1487 \sa blockSignals(), QSignalBlocker
1488*/
1489
1490/*!
1491 If \a block is true, signals emitted by this object are blocked
1492 (i.e., emitting a signal will not invoke anything connected to it).
1493 If \a block is false, no such blocking will occur.
1494
1495 The return value is the previous value of signalsBlocked().
1496
1497 Note that the destroyed() signal will be emitted even if the signals
1498 for this object have been blocked.
1499
1500 Signals emitted while being blocked are not buffered.
1501
1502 \sa signalsBlocked(), QSignalBlocker
1503*/
1504
1505bool QObject::blockSignals(bool block) noexcept
1506{
1507 Q_D(QObject);
1508 bool previous = d->blockSig;
1509 d->blockSig = block;
1510 return previous;
1511}
1512
1513/*!
1514 Returns the thread in which the object lives.
1515
1516 \sa moveToThread()
1517*/
1518QThread *QObject::thread() const
1519{
1520 return d_func()->threadData.loadRelaxed()->thread.loadAcquire();
1521}
1522
1523/*!
1524 Changes the thread affinity for this object and its children. The
1525 object cannot be moved if it has a parent. Event processing will
1526 continue in the \a targetThread.
1527
1528 To move an object to the main thread, use QApplication::instance()
1529 to retrieve a pointer to the current application, and then use
1530 QApplication::thread() to retrieve the thread in which the
1531 application lives. For example:
1532
1533 \snippet code/src_corelib_kernel_qobject.cpp 7
1534
1535 If \a targetThread is \nullptr, all event processing for this object
1536 and its children stops, as they are no longer associated with any
1537 thread.
1538
1539 Note that all active timers for the object will be reset. The
1540 timers are first stopped in the current thread and restarted (with
1541 the same interval) in the \a targetThread. As a result, constantly
1542 moving an object between threads can postpone timer events
1543 indefinitely.
1544
1545 A QEvent::ThreadChange event is sent to this object just before
1546 the thread affinity is changed. You can handle this event to
1547 perform any special processing. Note that any new events that are
1548 posted to this object will be handled in the \a targetThread,
1549 provided it is not \nullptr: when it is \nullptr, no event processing
1550 for this object or its children can happen, as they are no longer
1551 associated with any thread.
1552
1553 \warning This function is \e not thread-safe; the current thread
1554 must be same as the current thread affinity. In other words, this
1555 function can only "push" an object from the current thread to
1556 another thread, it cannot "pull" an object from any arbitrary
1557 thread to the current thread. There is one exception to this rule
1558 however: objects with no thread affinity can be "pulled" to the
1559 current thread.
1560
1561 \sa thread()
1562 */
1563void QObject::moveToThread(QThread *targetThread)
1564{
1565 Q_D(QObject);
1566
1567 if (d->threadData.loadRelaxed()->thread.loadAcquire() == targetThread) {
1568 // object is already in this thread
1569 return;
1570 }
1571
1572 if (d->parent != nullptr) {
1573 qWarning(msg: "QObject::moveToThread: Cannot move objects with a parent");
1574 return;
1575 }
1576 if (d->isWidget) {
1577 qWarning(msg: "QObject::moveToThread: Widgets cannot be moved to a new thread");
1578 return;
1579 }
1580
1581 QThreadData *currentData = QThreadData::current();
1582 QThreadData *targetData = targetThread ? QThreadData::get2(thread: targetThread) : nullptr;
1583 QThreadData *thisThreadData = d->threadData.loadRelaxed();
1584 if (!thisThreadData->thread.loadAcquire() && currentData == targetData) {
1585 // one exception to the rule: we allow moving objects with no thread affinity to the current thread
1586 currentData = d->threadData;
1587 } else if (thisThreadData != currentData) {
1588 qWarning(msg: "QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
1589 "Cannot move to target thread (%p)\n",
1590 currentData->thread.loadRelaxed(), thisThreadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr);
1591
1592#ifdef Q_OS_MAC
1593 qWarning("You might be loading two sets of Qt binaries into the same process. "
1594 "Check that all plugins are compiled against the right Qt binaries. Export "
1595 "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
1596#endif
1597
1598 return;
1599 }
1600
1601 // prepare to move
1602 d->moveToThread_helper();
1603
1604 if (!targetData)
1605 targetData = new QThreadData(0);
1606
1607 // make sure nobody adds/removes connections to this object while we're moving it
1608 QMutexLocker l(signalSlotLock(o: this));
1609
1610 QOrderedMutexLocker locker(&currentData->postEventList.mutex,
1611 &targetData->postEventList.mutex);
1612
1613 // keep currentData alive (since we've got it locked)
1614 currentData->ref();
1615
1616 // move the object
1617 d_func()->setThreadData_helper(currentData, targetData);
1618
1619 locker.unlock();
1620
1621 // now currentData can commit suicide if it wants to
1622 currentData->deref();
1623}
1624
1625void QObjectPrivate::moveToThread_helper()
1626{
1627 Q_Q(QObject);
1628 QEvent e(QEvent::ThreadChange);
1629 QCoreApplication::sendEvent(receiver: q, event: &e);
1630 for (int i = 0; i < children.size(); ++i) {
1631 QObject *child = children.at(i);
1632 child->d_func()->moveToThread_helper();
1633 }
1634}
1635
1636void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
1637{
1638 Q_Q(QObject);
1639
1640 // move posted events
1641 int eventsMoved = 0;
1642 for (int i = 0; i < currentData->postEventList.size(); ++i) {
1643 const QPostEvent &pe = currentData->postEventList.at(i);
1644 if (!pe.event)
1645 continue;
1646 if (pe.receiver == q) {
1647 // move this post event to the targetList
1648 targetData->postEventList.addEvent(ev: pe);
1649 const_cast<QPostEvent &>(pe).event = nullptr;
1650 ++eventsMoved;
1651 }
1652 }
1653 if (eventsMoved > 0 && targetData->hasEventDispatcher()) {
1654 targetData->canWait = false;
1655 targetData->eventDispatcher.loadRelaxed()->wakeUp();
1656 }
1657
1658 // the current emitting thread shouldn't restore currentSender after calling moveToThread()
1659 ConnectionData *cd = connections.loadRelaxed();
1660 if (cd) {
1661 if (cd->currentSender) {
1662 cd->currentSender->receiverDeleted();
1663 cd->currentSender = nullptr;
1664 }
1665
1666 // adjust the receiverThreadId values in the Connections
1667 if (cd) {
1668 auto *c = cd->senders;
1669 while (c) {
1670 QObject *r = c->receiver.loadRelaxed();
1671 if (r) {
1672 Q_ASSERT(r == q);
1673 targetData->ref();
1674 QThreadData *old = c->receiverThreadData.loadRelaxed();
1675 if (old)
1676 old->deref();
1677 c->receiverThreadData.storeRelaxed(newValue: targetData);
1678 }
1679 c = c->next;
1680 }
1681 }
1682
1683 }
1684
1685 // set new thread data
1686 targetData->ref();
1687 threadData.loadRelaxed()->deref();
1688
1689 // synchronizes with loadAcquire e.g. in QCoreApplication::postEvent
1690 threadData.storeRelease(newValue: targetData);
1691
1692 for (int i = 0; i < children.size(); ++i) {
1693 QObject *child = children.at(i);
1694 child->d_func()->setThreadData_helper(currentData, targetData);
1695 }
1696}
1697
1698void QObjectPrivate::_q_reregisterTimers(void *pointer)
1699{
1700 Q_Q(QObject);
1701 QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
1702 QAbstractEventDispatcher *eventDispatcher = threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
1703 for (int i = 0; i < timerList->size(); ++i) {
1704 const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
1705 eventDispatcher->registerTimer(timerId: ti.timerId, interval: ti.interval, timerType: ti.timerType, object: q);
1706 }
1707 delete timerList;
1708}
1709
1710
1711//
1712// The timer flag hasTimer is set when startTimer is called.
1713// It is not reset when killing the timer because more than
1714// one timer might be active.
1715//
1716
1717/*!
1718 Starts a timer and returns a timer identifier, or returns zero if
1719 it could not start a timer.
1720
1721 A timer event will occur every \a interval milliseconds until
1722 killTimer() is called. If \a interval is 0, then the timer event
1723 occurs once every time there are no more window system events to
1724 process.
1725
1726 The virtual timerEvent() function is called with the QTimerEvent
1727 event parameter class when a timer event occurs. Reimplement this
1728 function to get timer events.
1729
1730 If multiple timers are running, the QTimerEvent::timerId() can be
1731 used to find out which timer was activated.
1732
1733 Example:
1734
1735 \snippet code/src_corelib_kernel_qobject.cpp 8
1736
1737 Note that QTimer's accuracy depends on the underlying operating system and
1738 hardware. The \a timerType argument allows you to customize the accuracy of
1739 the timer. See Qt::TimerType for information on the different timer types.
1740 Most platforms support an accuracy of 20 milliseconds; some provide more.
1741 If Qt is unable to deliver the requested number of timer events, it will
1742 silently discard some.
1743
1744 The QTimer class provides a high-level programming interface with
1745 single-shot timers and timer signals instead of events. There is
1746 also a QBasicTimer class that is more lightweight than QTimer and
1747 less clumsy than using timer IDs directly.
1748
1749 \sa timerEvent(), killTimer(), QTimer::singleShot()
1750*/
1751
1752int QObject::startTimer(int interval, Qt::TimerType timerType)
1753{
1754 Q_D(QObject);
1755
1756 if (Q_UNLIKELY(interval < 0)) {
1757 qWarning(msg: "QObject::startTimer: Timers cannot have negative intervals");
1758 return 0;
1759 }
1760
1761 auto thisThreadData = d->threadData.loadRelaxed();
1762 if (Q_UNLIKELY(!thisThreadData->hasEventDispatcher())) {
1763 qWarning(msg: "QObject::startTimer: Timers can only be used with threads started with QThread");
1764 return 0;
1765 }
1766 if (Q_UNLIKELY(thread() != QThread::currentThread())) {
1767 qWarning(msg: "QObject::startTimer: Timers cannot be started from another thread");
1768 return 0;
1769 }
1770 int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, object: this);
1771 if (!d->extraData)
1772 d->extraData = new QObjectPrivate::ExtraData;
1773 d->extraData->runningTimers.append(t: timerId);
1774 return timerId;
1775}
1776
1777/*!
1778 \since 5.9
1779 \overload
1780 \fn int QObject::startTimer(std::chrono::milliseconds time, Qt::TimerType timerType)
1781
1782 Starts a timer and returns a timer identifier, or returns zero if
1783 it could not start a timer.
1784
1785 A timer event will occur every \a time interval until killTimer()
1786 is called. If \a time is equal to \c{std::chrono::duration::zero()},
1787 then the timer event occurs once every time there are no more window
1788 system events to process.
1789
1790 The virtual timerEvent() function is called with the QTimerEvent
1791 event parameter class when a timer event occurs. Reimplement this
1792 function to get timer events.
1793
1794 If multiple timers are running, the QTimerEvent::timerId() can be
1795 used to find out which timer was activated.
1796
1797 Example:
1798
1799 \snippet code/src_corelib_kernel_qobject.cpp 8
1800
1801 Note that QTimer's accuracy depends on the underlying operating system and
1802 hardware. The \a timerType argument allows you to customize the accuracy of
1803 the timer. See Qt::TimerType for information on the different timer types.
1804 Most platforms support an accuracy of 20 milliseconds; some provide more.
1805 If Qt is unable to deliver the requested number of timer events, it will
1806 silently discard some.
1807
1808 The QTimer class provides a high-level programming interface with
1809 single-shot timers and timer signals instead of events. There is
1810 also a QBasicTimer class that is more lightweight than QTimer and
1811 less clumsy than using timer IDs directly.
1812
1813 \sa timerEvent(), killTimer(), QTimer::singleShot()
1814*/
1815
1816/*!
1817 Kills the timer with timer identifier, \a id.
1818
1819 The timer identifier is returned by startTimer() when a timer
1820 event is started.
1821
1822 \sa timerEvent(), startTimer()
1823*/
1824
1825void QObject::killTimer(int id)
1826{
1827 Q_D(QObject);
1828 if (Q_UNLIKELY(thread() != QThread::currentThread())) {
1829 qWarning(msg: "QObject::killTimer: Timers cannot be stopped from another thread");
1830 return;
1831 }
1832 if (id) {
1833 int at = d->extraData ? d->extraData->runningTimers.indexOf(t: id) : -1;
1834 if (at == -1) {
1835 // timer isn't owned by this object
1836 qWarning(msg: "QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %ls), timer has not been killed",
1837 id,
1838 this,
1839 metaObject()->className(),
1840 qUtf16Printable(objectName()));
1841 return;
1842 }
1843
1844 auto thisThreadData = d->threadData.loadRelaxed();
1845 if (thisThreadData->hasEventDispatcher())
1846 thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimer(timerId: id);
1847
1848 d->extraData->runningTimers.remove(i: at);
1849 QAbstractEventDispatcherPrivate::releaseTimerId(id);
1850 }
1851}
1852
1853
1854/*!
1855 \fn QObject *QObject::parent() const
1856
1857 Returns a pointer to the parent object.
1858
1859 \sa children()
1860*/
1861
1862/*!
1863 \fn const QObjectList &QObject::children() const
1864
1865 Returns a list of child objects.
1866 The QObjectList class is defined in the \c{<QObject>} header
1867 file as the following:
1868
1869 \quotefromfile kernel/qobject.h
1870 \skipto /typedef .*QObjectList/
1871 \printuntil QObjectList
1872
1873 The first child added is the \l{QList::first()}{first} object in
1874 the list and the last child added is the \l{QList::last()}{last}
1875 object in the list, i.e. new children are appended at the end.
1876
1877 Note that the list order changes when QWidget children are
1878 \l{QWidget::raise()}{raised} or \l{QWidget::lower()}{lowered}. A
1879 widget that is raised becomes the last object in the list, and a
1880 widget that is lowered becomes the first object in the list.
1881
1882 \sa findChild(), findChildren(), parent(), setParent()
1883*/
1884
1885
1886/*!
1887 \fn template<typename T> T *QObject::findChild(const QString &name, Qt::FindChildOptions options) const
1888
1889 Returns the child of this object that can be cast into type T and
1890 that is called \a name, or \nullptr if there is no such object.
1891 Omitting the \a name argument causes all object names to be matched.
1892 The search is performed recursively, unless \a options specifies the
1893 option FindDirectChildrenOnly.
1894
1895 If there is more than one child matching the search, the most
1896 direct ancestor is returned. If there are several direct
1897 ancestors, it is undefined which one will be returned. In that
1898 case, findChildren() should be used.
1899
1900 This example returns a child \c{QPushButton} of \c{parentWidget}
1901 named \c{"button1"}, even if the button isn't a direct child of
1902 the parent:
1903
1904 \snippet code/src_corelib_kernel_qobject.cpp 10
1905
1906 This example returns a \c{QListWidget} child of \c{parentWidget}:
1907
1908 \snippet code/src_corelib_kernel_qobject.cpp 11
1909
1910 This example returns a child \c{QPushButton} of \c{parentWidget}
1911 (its direct parent) named \c{"button1"}:
1912
1913 \snippet code/src_corelib_kernel_qobject.cpp 41
1914
1915 This example returns a \c{QListWidget} child of \c{parentWidget},
1916 its direct parent:
1917
1918 \snippet code/src_corelib_kernel_qobject.cpp 42
1919
1920 \sa findChildren()
1921*/
1922
1923/*!
1924 \fn template<typename T> QList<T> QObject::findChildren(const QString &name, Qt::FindChildOptions options) const
1925
1926 Returns all children of this object with the given \a name that can be
1927 cast to type T, or an empty list if there are no such objects.
1928 Omitting the \a name argument causes all object names to be matched.
1929 The search is performed recursively, unless \a options specifies the
1930 option FindDirectChildrenOnly.
1931
1932 The following example shows how to find a list of child \c{QWidget}s of
1933 the specified \c{parentWidget} named \c{widgetname}:
1934
1935 \snippet code/src_corelib_kernel_qobject.cpp 12
1936
1937 This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
1938
1939 \snippet code/src_corelib_kernel_qobject.cpp 13
1940
1941 This example returns all \c{QPushButton}s that are immediate children of \c{parentWidget}:
1942
1943 \snippet code/src_corelib_kernel_qobject.cpp 43
1944
1945 \sa findChild()
1946*/
1947
1948/*!
1949 \fn template<typename T> QList<T> QObject::findChildren(const QRegExp &regExp, Qt::FindChildOptions options) const
1950 \overload findChildren()
1951 \obsolete
1952
1953 Returns the children of this object that can be cast to type T
1954 and that have names matching the regular expression \a regExp,
1955 or an empty list if there are no such objects.
1956 The search is performed recursively, unless \a options specifies the
1957 option FindDirectChildrenOnly.
1958
1959 Use the findChildren overload taking a QRegularExpression instead.
1960*/
1961
1962/*!
1963 \fn QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options) const
1964 \overload findChildren()
1965
1966 \since 5.0
1967
1968 Returns the children of this object that can be cast to type T
1969 and that have names matching the regular expression \a re,
1970 or an empty list if there are no such objects.
1971 The search is performed recursively, unless \a options specifies the
1972 option FindDirectChildrenOnly.
1973*/
1974
1975/*!
1976 \fn template<typename T> T qFindChild(const QObject *obj, const QString &name)
1977 \relates QObject
1978 \overload qFindChildren()
1979 \obsolete
1980
1981 This function is equivalent to
1982 \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
1983
1984 \note This function was provided as a workaround for MSVC 6
1985 which did not support member template functions. It is advised
1986 to use the other form in new code.
1987
1988 \sa QObject::findChild()
1989*/
1990
1991/*!
1992 \fn template<typename T> QList<T> qFindChildren(const QObject *obj, const QString &name)
1993 \relates QObject
1994 \overload qFindChildren()
1995 \obsolete
1996
1997 This function is equivalent to
1998 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
1999
2000 \note This function was provided as a workaround for MSVC 6
2001 which did not support member template functions. It is advised
2002 to use the other form in new code.
2003
2004 \sa QObject::findChildren()
2005*/
2006
2007/*!
2008 \fn template<typename T> QList<T> qFindChildren(const QObject *obj, const QRegExp &regExp)
2009 \relates QObject
2010 \overload qFindChildren()
2011
2012 This function is equivalent to
2013 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp).
2014
2015 \note This function was provided as a workaround for MSVC 6
2016 which did not support member template functions. It is advised
2017 to use the other form in new code.
2018
2019 \sa QObject::findChildren()
2020*/
2021
2022/*!
2023 \internal
2024*/
2025void qt_qFindChildren_helper(const QObject *parent, const QString &name,
2026 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
2027{
2028 if (!parent || !list)
2029 return;
2030 const QObjectList &children = parent->children();
2031 QObject *obj;
2032 for (int i = 0; i < children.size(); ++i) {
2033 obj = children.at(i);
2034 if (mo.cast(obj)) {
2035 if (name.isNull() || obj->objectName() == name)
2036 list->append(t: obj);
2037 }
2038 if (options & Qt::FindChildrenRecursively)
2039 qt_qFindChildren_helper(parent: obj, name, mo, list, options);
2040 }
2041}
2042
2043#ifndef QT_NO_REGEXP
2044/*!
2045 \internal
2046*/
2047void qt_qFindChildren_helper(const QObject *parent, const QRegExp &re,
2048 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
2049{
2050 if (!parent || !list)
2051 return;
2052 const QObjectList &children = parent->children();
2053 QRegExp reCopy = re;
2054 QObject *obj;
2055 for (int i = 0; i < children.size(); ++i) {
2056 obj = children.at(i);
2057 if (mo.cast(obj) && reCopy.indexIn(str: obj->objectName()) != -1)
2058 list->append(t: obj);
2059
2060 if (options & Qt::FindChildrenRecursively)
2061 qt_qFindChildren_helper(parent: obj, re, mo, list, options);
2062 }
2063}
2064#endif // QT_NO_REGEXP
2065
2066#if QT_CONFIG(regularexpression)
2067/*!
2068 \internal
2069*/
2070void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
2071 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
2072{
2073 if (!parent || !list)
2074 return;
2075 const QObjectList &children = parent->children();
2076 QObject *obj;
2077 for (int i = 0; i < children.size(); ++i) {
2078 obj = children.at(i);
2079 if (mo.cast(obj)) {
2080 QRegularExpressionMatch m = re.match(subject: obj->objectName());
2081 if (m.hasMatch())
2082 list->append(t: obj);
2083 }
2084 if (options & Qt::FindChildrenRecursively)
2085 qt_qFindChildren_helper(parent: obj, re, mo, list, options);
2086 }
2087}
2088#endif // QT_CONFIG(regularexpression)
2089
2090/*!
2091 \internal
2092 */
2093QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options)
2094{
2095 if (!parent)
2096 return nullptr;
2097 const QObjectList &children = parent->children();
2098 QObject *obj;
2099 int i;
2100 for (i = 0; i < children.size(); ++i) {
2101 obj = children.at(i);
2102 if (mo.cast(obj) && (name.isNull() || obj->objectName() == name))
2103 return obj;
2104 }
2105 if (options & Qt::FindChildrenRecursively) {
2106 for (i = 0; i < children.size(); ++i) {
2107 obj = qt_qFindChild_helper(parent: children.at(i), name, mo, options);
2108 if (obj)
2109 return obj;
2110 }
2111 }
2112 return nullptr;
2113}
2114
2115/*!
2116 Makes the object a child of \a parent.
2117
2118 \sa parent(), children()
2119*/
2120void QObject::setParent(QObject *parent)
2121{
2122 Q_D(QObject);
2123 Q_ASSERT(!d->isWidget);
2124 d->setParent_helper(parent);
2125}
2126
2127void QObjectPrivate::deleteChildren()
2128{
2129 Q_ASSERT_X(!isDeletingChildren, "QObjectPrivate::deleteChildren()", "isDeletingChildren already set, did this function recurse?");
2130 isDeletingChildren = true;
2131 // delete children objects
2132 // don't use qDeleteAll as the destructor of the child might
2133 // delete siblings
2134 for (int i = 0; i < children.count(); ++i) {
2135 currentChildBeingDeleted = children.at(i);
2136 children[i] = 0;
2137 delete currentChildBeingDeleted;
2138 }
2139 children.clear();
2140 currentChildBeingDeleted = nullptr;
2141 isDeletingChildren = false;
2142}
2143
2144void QObjectPrivate::setParent_helper(QObject *o)
2145{
2146 Q_Q(QObject);
2147 Q_ASSERT_X(q != o, Q_FUNC_INFO, "Cannot parent a QObject to itself");
2148#ifdef QT_DEBUG
2149 const auto checkForParentChildLoops = qScopeGuard(f: [&](){
2150 int depth = 0;
2151 auto p = parent;
2152 while (p) {
2153 if (++depth == CheckForParentChildLoopsWarnDepth) {
2154 qWarning(msg: "QObject %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
2155 "this is undefined behavior",
2156 q, q->metaObject()->className(), qPrintable(q->objectName()));
2157 }
2158 p = p->parent();
2159 }
2160 });
2161#endif
2162
2163 if (o == parent)
2164 return;
2165
2166 if (parent) {
2167 QObjectPrivate *parentD = parent->d_func();
2168 if (parentD->isDeletingChildren && wasDeleted
2169 && parentD->currentChildBeingDeleted == q) {
2170 // don't do anything since QObjectPrivate::deleteChildren() already
2171 // cleared our entry in parentD->children.
2172 } else {
2173 const int index = parentD->children.indexOf(t: q);
2174 if (index < 0) {
2175 // we're probably recursing into setParent() from a ChildRemoved event, don't do anything
2176 } else if (parentD->isDeletingChildren) {
2177 parentD->children[index] = 0;
2178 } else {
2179 parentD->children.removeAt(i: index);
2180 if (sendChildEvents && parentD->receiveChildEvents) {
2181 QChildEvent e(QEvent::ChildRemoved, q);
2182 QCoreApplication::sendEvent(receiver: parent, event: &e);
2183 }
2184 }
2185 }
2186 }
2187 parent = o;
2188 if (parent) {
2189 // object hierarchies are constrained to a single thread
2190 if (threadData != parent->d_func()->threadData) {
2191 qWarning(msg: "QObject::setParent: Cannot set parent, new parent is in a different thread");
2192 parent = nullptr;
2193 return;
2194 }
2195 parent->d_func()->children.append(t: q);
2196 if(sendChildEvents && parent->d_func()->receiveChildEvents) {
2197 if (!isWidget) {
2198 QChildEvent e(QEvent::ChildAdded, q);
2199 QCoreApplication::sendEvent(receiver: parent, event: &e);
2200 }
2201 }
2202 }
2203 if (!wasDeleted && !isDeletingChildren && declarativeData && QAbstractDeclarativeData::parentChanged)
2204 QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
2205}
2206
2207/*!
2208 \fn void QObject::installEventFilter(QObject *filterObj)
2209
2210 Installs an event filter \a filterObj on this object. For example:
2211 \snippet code/src_corelib_kernel_qobject.cpp 14
2212
2213 An event filter is an object that receives all events that are
2214 sent to this object. The filter can either stop the event or
2215 forward it to this object. The event filter \a filterObj receives
2216 events via its eventFilter() function. The eventFilter() function
2217 must return true if the event should be filtered, (i.e. stopped);
2218 otherwise it must return false.
2219
2220 If multiple event filters are installed on a single object, the
2221 filter that was installed last is activated first.
2222
2223 Here's a \c KeyPressEater class that eats the key presses of its
2224 monitored objects:
2225
2226 \snippet code/src_corelib_kernel_qobject.cpp 15
2227
2228 And here's how to install it on two widgets:
2229
2230 \snippet code/src_corelib_kernel_qobject.cpp 16
2231
2232 The QShortcut class, for example, uses this technique to intercept
2233 shortcut key presses.
2234
2235 \warning If you delete the receiver object in your eventFilter()
2236 function, be sure to return true. If you return false, Qt sends
2237 the event to the deleted object and the program will crash.
2238
2239 Note that the filtering object must be in the same thread as this
2240 object. If \a filterObj is in a different thread, this function does
2241 nothing. If either \a filterObj or this object are moved to a different
2242 thread after calling this function, the event filter will not be
2243 called until both objects have the same thread affinity again (it
2244 is \e not removed).
2245
2246 \sa removeEventFilter(), eventFilter(), event()
2247*/
2248
2249void QObject::installEventFilter(QObject *obj)
2250{
2251 Q_D(QObject);
2252 if (!obj)
2253 return;
2254 if (d->threadData != obj->d_func()->threadData) {
2255 qWarning(msg: "QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
2256 return;
2257 }
2258
2259 if (!d->extraData)
2260 d->extraData = new QObjectPrivate::ExtraData;
2261
2262 // clean up unused items in the list
2263 d->extraData->eventFilters.removeAll(t: (QObject*)nullptr);
2264 d->extraData->eventFilters.removeAll(t: obj);
2265 d->extraData->eventFilters.prepend(t: obj);
2266}
2267
2268/*!
2269 Removes an event filter object \a obj from this object. The
2270 request is ignored if such an event filter has not been installed.
2271
2272 All event filters for this object are automatically removed when
2273 this object is destroyed.
2274
2275 It is always safe to remove an event filter, even during event
2276 filter activation (i.e. from the eventFilter() function).
2277
2278 \sa installEventFilter(), eventFilter(), event()
2279*/
2280
2281void QObject::removeEventFilter(QObject *obj)
2282{
2283 Q_D(QObject);
2284 if (d->extraData) {
2285 for (int i = 0; i < d->extraData->eventFilters.count(); ++i) {
2286 if (d->extraData->eventFilters.at(i) == obj)
2287 d->extraData->eventFilters[i] = nullptr;
2288 }
2289 }
2290}
2291
2292
2293/*!
2294 \fn void QObject::destroyed(QObject *obj)
2295
2296 This signal is emitted immediately before the object \a obj is
2297 destroyed, after any instances of QPointer have been notified,
2298 and cannot be blocked.
2299
2300 All the objects's children are destroyed immediately after this
2301 signal is emitted.
2302
2303 \sa deleteLater(), QPointer
2304*/
2305
2306/*!
2307 \threadsafe
2308
2309 Schedules this object for deletion.
2310
2311 The object will be deleted when control returns to the event
2312 loop. If the event loop is not running when this function is
2313 called (e.g. deleteLater() is called on an object before
2314 QCoreApplication::exec()), the object will be deleted once the
2315 event loop is started. If deleteLater() is called after the main event loop
2316 has stopped, the object will not be deleted.
2317 Since Qt 4.8, if deleteLater() is called on an object that lives in a
2318 thread with no running event loop, the object will be destroyed when the
2319 thread finishes.
2320
2321 Note that entering and leaving a new event loop (e.g., by opening a modal
2322 dialog) will \e not perform the deferred deletion; for the object to be
2323 deleted, the control must return to the event loop from which deleteLater()
2324 was called. This does not apply to objects deleted while a previous, nested
2325 event loop was still running: the Qt event loop will delete those objects
2326 as soon as the new nested event loop starts.
2327
2328 \note It is safe to call this function more than once; when the
2329 first deferred deletion event is delivered, any pending events for the
2330 object are removed from the event queue.
2331
2332 \sa destroyed(), QPointer
2333*/
2334void QObject::deleteLater()
2335{
2336#ifdef QT_DEBUG
2337 if (qApp == this)
2338 qWarning(msg: "You are deferring the delete of QCoreApplication, this may not work as expected.");
2339#endif
2340 QCoreApplication::postEvent(receiver: this, event: new QDeferredDeleteEvent());
2341}
2342
2343/*!
2344 \fn QString QObject::tr(const char *sourceText, const char *disambiguation, int n)
2345 \reentrant
2346
2347 Returns a translated version of \a sourceText, optionally based on a
2348 \a disambiguation string and value of \a n for strings containing plurals;
2349 otherwise returns QString::fromUtf8(\a sourceText) if no appropriate
2350 translated string is available.
2351
2352 Example:
2353 \snippet ../widgets/mainwindows/sdi/mainwindow.cpp implicit tr context
2354 \dots
2355
2356 If the same \a sourceText is used in different roles within the
2357 same context, an additional identifying string may be passed in
2358 \a disambiguation (\nullptr by default). In Qt 4.4 and earlier, this was
2359 the preferred way to pass comments to translators.
2360
2361 Example:
2362
2363 \snippet code/src_corelib_kernel_qobject.cpp 17
2364 \dots
2365
2366 See \l{Writing Source Code for Translation} for a detailed description of
2367 Qt's translation mechanisms in general, and the
2368 \l{Writing Source Code for Translation#Disambiguation}{Disambiguation}
2369 section for information on disambiguation.
2370
2371 \warning This method is reentrant only if all translators are
2372 installed \e before calling this method. Installing or removing
2373 translators while performing translations is not supported. Doing
2374 so will probably result in crashes or other undesirable behavior.
2375
2376 \sa QCoreApplication::translate(), {Internationalization with Qt}
2377*/
2378
2379/*!
2380 \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
2381 \reentrant
2382 \obsolete
2383
2384 Returns a translated version of \a sourceText, or
2385 QString::fromUtf8(\a sourceText) if there is no appropriate
2386 version. It is otherwise identical to tr(\a sourceText, \a
2387 disambiguation, \a n).
2388
2389 \warning This method is reentrant only if all translators are
2390 installed \e before calling this method. Installing or removing
2391 translators while performing translations is not supported. Doing
2392 so will probably result in crashes or other undesirable behavior.
2393
2394 \warning For portability reasons, we recommend that you use
2395 escape sequences for specifying non-ASCII characters in string
2396 literals to trUtf8(). For example:
2397
2398 \snippet code/src_corelib_kernel_qobject.cpp 20
2399
2400 \sa tr(), QCoreApplication::translate(), {Internationalization with Qt}
2401*/
2402
2403
2404
2405
2406/*****************************************************************************
2407 Signals and slots
2408 *****************************************************************************/
2409
2410
2411const char *qFlagLocation(const char *method)
2412{
2413 QThreadData *currentThreadData = QThreadData::current(createIfNecessary: false);
2414 if (currentThreadData != nullptr)
2415 currentThreadData->flaggedSignatures.store(method);
2416 return method;
2417}
2418
2419static int extract_code(const char *member)
2420{
2421 // extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
2422 return (((int)(*member) - '0') & 0x3);
2423}
2424
2425static const char * extract_location(const char *member)
2426{
2427 if (QThreadData::current()->flaggedSignatures.contains(method: member)) {
2428 // signature includes location information after the first null-terminator
2429 const char *location = member + qstrlen(str: member) + 1;
2430 if (*location != '\0')
2431 return location;
2432 }
2433 return nullptr;
2434}
2435
2436static bool check_signal_macro(const QObject *sender, const char *signal,
2437 const char *func, const char *op)
2438{
2439 int sigcode = extract_code(member: signal);
2440 if (sigcode != QSIGNAL_CODE) {
2441 if (sigcode == QSLOT_CODE)
2442 qWarning(msg: "QObject::%s: Attempt to %s non-signal %s::%s",
2443 func, op, sender->metaObject()->className(), signal+1);
2444 else
2445 qWarning(msg: "QObject::%s: Use the SIGNAL macro to %s %s::%s",
2446 func, op, sender->metaObject()->className(), signal);
2447 return false;
2448 }
2449 return true;
2450}
2451
2452static bool check_method_code(int code, const QObject *object,
2453 const char *method, const char *func)
2454{
2455 if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
2456 qWarning(msg: "QObject::%s: Use the SLOT or SIGNAL macro to "
2457 "%s %s::%s", func, func, object->metaObject()->className(), method);
2458 return false;
2459 }
2460 return true;
2461}
2462
2463static void err_method_notfound(const QObject *object,
2464 const char *method, const char *func)
2465{
2466 const char *type = "method";
2467 switch (extract_code(member: method)) {
2468 case QSLOT_CODE: type = "slot"; break;
2469 case QSIGNAL_CODE: type = "signal"; break;
2470 }
2471 const char *loc = extract_location(member: method);
2472 if (strchr(s: method,c: ')') == nullptr) // common typing mistake
2473 qWarning(msg: "QObject::%s: Parentheses expected, %s %s::%s%s%s",
2474 func, type, object->metaObject()->className(), method+1,
2475 loc ? " in ": "", loc ? loc : "");
2476 else
2477 qWarning(msg: "QObject::%s: No such %s %s::%s%s%s",
2478 func, type, object->metaObject()->className(), method+1,
2479 loc ? " in ": "", loc ? loc : "");
2480
2481}
2482
2483
2484static void err_info_about_objects(const char * func,
2485 const QObject * sender,
2486 const QObject * receiver)
2487{
2488 QString a = sender ? sender->objectName() : QString();
2489 QString b = receiver ? receiver->objectName() : QString();
2490 if (!a.isEmpty())
2491 qWarning(msg: "QObject::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
2492 if (!b.isEmpty())
2493 qWarning(msg: "QObject::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
2494}
2495
2496/*!
2497 Returns a pointer to the object that sent the signal, if called in
2498 a slot activated by a signal; otherwise it returns \nullptr. The pointer
2499 is valid only during the execution of the slot that calls this
2500 function from this object's thread context.
2501
2502 The pointer returned by this function becomes invalid if the
2503 sender is destroyed, or if the slot is disconnected from the
2504 sender's signal.
2505
2506 \warning This function violates the object-oriented principle of
2507 modularity. However, getting access to the sender might be useful
2508 when many signals are connected to a single slot.
2509
2510 \warning As mentioned above, the return value of this function is
2511 not valid when the slot is called via a Qt::DirectConnection from
2512 a thread different from this object's thread. Do not use this
2513 function in this type of scenario.
2514
2515 \sa senderSignalIndex()
2516*/
2517
2518QObject *QObject::sender() const
2519{
2520 Q_D(const QObject);
2521
2522 QBasicMutexLocker locker(signalSlotLock(o: this));
2523 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2524 if (!cd || !cd->currentSender)
2525 return nullptr;
2526
2527 for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) {
2528 if (c->sender == cd->currentSender->sender)
2529 return cd->currentSender->sender;
2530 }
2531
2532 return nullptr;
2533}
2534
2535/*!
2536 \since 4.8
2537
2538 Returns the meta-method index of the signal that called the currently
2539 executing slot, which is a member of the class returned by sender().
2540 If called outside of a slot activated by a signal, -1 is returned.
2541
2542 For signals with default parameters, this function will always return
2543 the index with all parameters, regardless of which was used with
2544 connect(). For example, the signal \c {destroyed(QObject *obj = \nullptr)}
2545 will have two different indexes (with and without the parameter), but
2546 this function will always return the index with a parameter. This does
2547 not apply when overloading signals with different parameters.
2548
2549 \warning This function violates the object-oriented principle of
2550 modularity. However, getting access to the signal index might be useful
2551 when many signals are connected to a single slot.
2552
2553 \warning The return value of this function is not valid when the slot
2554 is called via a Qt::DirectConnection from a thread different from this
2555 object's thread. Do not use this function in this type of scenario.
2556
2557 \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method()
2558*/
2559
2560int QObject::senderSignalIndex() const
2561{
2562 Q_D(const QObject);
2563
2564 QBasicMutexLocker locker(signalSlotLock(o: this));
2565 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2566 if (!cd || !cd->currentSender)
2567 return -1;
2568
2569 for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) {
2570 if (c->sender == cd->currentSender->sender) {
2571 // Convert from signal range to method range
2572 return QMetaObjectPrivate::signal(m: c->sender->metaObject(), signal_index: cd->currentSender->signal).methodIndex();
2573 }
2574 }
2575
2576 return -1;
2577}
2578
2579/*!
2580 Returns the number of receivers connected to the \a signal.
2581
2582 Since both slots and signals can be used as receivers for signals,
2583 and the same connections can be made many times, the number of
2584 receivers is the same as the number of connections made from this
2585 signal.
2586
2587 When calling this function, you can use the \c SIGNAL() macro to
2588 pass a specific signal:
2589
2590 \snippet code/src_corelib_kernel_qobject.cpp 21
2591
2592 \warning This function violates the object-oriented principle of
2593 modularity. However, it might be useful when you need to perform
2594 expensive initialization only if something is connected to a
2595 signal.
2596
2597 \sa isSignalConnected()
2598*/
2599
2600int QObject::receivers(const char *signal) const
2601{
2602 Q_D(const QObject);
2603 int receivers = 0;
2604 if (signal) {
2605 QByteArray signal_name = QMetaObject::normalizedSignature(method: signal);
2606 signal = signal_name;
2607#ifndef QT_NO_DEBUG
2608 if (!check_signal_macro(sender: this, signal, func: "receivers", op: "bind"))
2609 return 0;
2610#endif
2611 signal++; // skip code
2612 int signal_index = d->signalIndex(signalName: signal);
2613 if (signal_index < 0) {
2614#ifndef QT_NO_DEBUG
2615 err_method_notfound(object: this, method: signal-1, func: "receivers");
2616#endif
2617 return 0;
2618 }
2619
2620 if (!d->isSignalConnected(signalIndex: signal_index))
2621 return receivers;
2622
2623 if (d->declarativeData && QAbstractDeclarativeData::receivers) {
2624 receivers += QAbstractDeclarativeData::receivers(d->declarativeData, this,
2625 signal_index);
2626 }
2627
2628 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2629 QBasicMutexLocker locker(signalSlotLock(o: this));
2630 if (cd && signal_index < cd->signalVectorCount()) {
2631 const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(i: signal_index).first.loadRelaxed();
2632 while (c) {
2633 receivers += c->receiver.loadRelaxed() ? 1 : 0;
2634 c = c->nextConnectionList.loadRelaxed();
2635 }
2636 }
2637 }
2638 return receivers;
2639}
2640
2641/*!
2642 \since 5.0
2643 Returns \c true if the \a signal is connected to at least one receiver,
2644 otherwise returns \c false.
2645
2646 \a signal must be a signal member of this object, otherwise the behaviour
2647 is undefined.
2648
2649 \snippet code/src_corelib_kernel_qobject.cpp 49
2650
2651 As the code snippet above illustrates, you can use this function
2652 to avoid emitting a signal that nobody listens to.
2653
2654 \warning This function violates the object-oriented principle of
2655 modularity. However, it might be useful when you need to perform
2656 expensive initialization only if something is connected to a
2657 signal.
2658*/
2659bool QObject::isSignalConnected(const QMetaMethod &signal) const
2660{
2661 Q_D(const QObject);
2662 if (!signal.mobj)
2663 return false;
2664
2665 Q_ASSERT_X(signal.mobj->cast(this) && signal.methodType() == QMetaMethod::Signal,
2666 "QObject::isSignalConnected" , "the parameter must be a signal member of the object");
2667 uint signalIndex = (signal.handle - QMetaObjectPrivate::get(metaobject: signal.mobj)->methodData)/5;
2668
2669 if (signal.mobj->d.data[signal.handle + 4] & MethodCloned)
2670 signalIndex = QMetaObjectPrivate::originalClone(obj: signal.mobj, local_method_index: signalIndex);
2671
2672 signalIndex += QMetaObjectPrivate::signalOffset(m: signal.mobj);
2673
2674 QBasicMutexLocker locker(signalSlotLock(o: this));
2675 return d->isSignalConnected(signalIndex, checkDeclarative: true);
2676}
2677
2678/*!
2679 \internal
2680
2681 This helper function calculates signal and method index for the given
2682 member in the specified class.
2683
2684 \list
2685 \li If member.mobj is \nullptr then both signalIndex and methodIndex are set to -1.
2686
2687 \li If specified member is not a member of obj instance class (or one of
2688 its parent classes) then both signalIndex and methodIndex are set to -1.
2689 \endlist
2690
2691 This function is used by QObject::connect and QObject::disconnect which
2692 are working with QMetaMethod.
2693
2694 \a signalIndex is set to the signal index of member. If the member
2695 specified is not signal this variable is set to -1.
2696
2697 \a methodIndex is set to the method index of the member. If the
2698 member is not a method of the object specified by the \a obj argument this
2699 variable is set to -1.
2700*/
2701void QMetaObjectPrivate::memberIndexes(const QObject *obj,
2702 const QMetaMethod &member,
2703 int *signalIndex, int *methodIndex)
2704{
2705 *signalIndex = -1;
2706 *methodIndex = -1;
2707 if (!obj || !member.mobj)
2708 return;
2709 const QMetaObject *m = obj->metaObject();
2710 // Check that member is member of obj class
2711 while (m != nullptr && m != member.mobj)
2712 m = m->d.superdata;
2713 if (!m)
2714 return;
2715 *signalIndex = *methodIndex = (member.handle - get(metaobject: member.mobj)->methodData)/5;
2716
2717 int signalOffset;
2718 int methodOffset;
2719 computeOffsets(metaobject: m, signalOffset: &signalOffset, methodOffset: &methodOffset);
2720
2721 *methodIndex += methodOffset;
2722 if (member.methodType() == QMetaMethod::Signal) {
2723 *signalIndex = originalClone(obj: m, local_method_index: *signalIndex);
2724 *signalIndex += signalOffset;
2725 } else {
2726 *signalIndex = -1;
2727 }
2728}
2729
2730#ifndef QT_NO_DEBUG
2731static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal,
2732 const QMetaObject *receiver, const QMetaMethod &method)
2733{
2734 if (signal.attributes() & QMetaMethod::Compatibility) {
2735 if (!(method.attributes() & QMetaMethod::Compatibility))
2736 qWarning(msg: "QObject::connect: Connecting from COMPAT signal (%s::%s)",
2737 sender->className(), signal.methodSignature().constData());
2738 } else if ((method.attributes() & QMetaMethod::Compatibility) &&
2739 method.methodType() == QMetaMethod::Signal) {
2740 qWarning(msg: "QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
2741 sender->className(), signal.methodSignature().constData(),
2742 receiver->className(), method.methodSignature().constData());
2743 }
2744}
2745#endif
2746
2747/*!
2748 \threadsafe
2749
2750 Creates a connection of the given \a type from the \a signal in
2751 the \a sender object to the \a method in the \a receiver object.
2752 Returns a handle to the connection that can be used to disconnect
2753 it later.
2754
2755 You must use the \c SIGNAL() and \c SLOT() macros when specifying
2756 the \a signal and the \a method, for example:
2757
2758 \snippet code/src_corelib_kernel_qobject.cpp 22
2759
2760 This example ensures that the label always displays the current
2761 scroll bar value. Note that the signal and slots parameters must not
2762 contain any variable names, only the type. E.g. the following would
2763 not work and return false:
2764
2765 \snippet code/src_corelib_kernel_qobject.cpp 23
2766
2767 A signal can also be connected to another signal:
2768
2769 \snippet code/src_corelib_kernel_qobject.cpp 24
2770
2771 In this example, the \c MyWidget constructor relays a signal from
2772 a private member variable, and makes it available under a name
2773 that relates to \c MyWidget.
2774
2775 A signal can be connected to many slots and signals. Many signals
2776 can be connected to one slot.
2777
2778 If a signal is connected to several slots, the slots are activated
2779 in the same order in which the connections were made, when the
2780 signal is emitted.
2781
2782 The function returns a QMetaObject::Connection that represents
2783 a handle to a connection if it successfully
2784 connects the signal to the slot. The connection handle will be invalid
2785 if it cannot create the connection, for example, if QObject is unable
2786 to verify the existence of either \a signal or \a method, or if their
2787 signatures aren't compatible.
2788 You can check if the handle is valid by casting it to a bool.
2789
2790 By default, a signal is emitted for every connection you make;
2791 two signals are emitted for duplicate connections. You can break
2792 all of these connections with a single disconnect() call.
2793 If you pass the Qt::UniqueConnection \a type, the connection will only
2794 be made if it is not a duplicate. If there is already a duplicate
2795 (exact same signal to the exact same slot on the same objects),
2796 the connection will fail and connect will return an invalid QMetaObject::Connection.
2797
2798 \note Qt::UniqueConnections do not work for lambdas, non-member functions
2799 and functors; they only apply to connecting to member functions.
2800
2801 The optional \a type parameter describes the type of connection
2802 to establish. In particular, it determines whether a particular
2803 signal is delivered to a slot immediately or queued for delivery
2804 at a later time. If the signal is queued, the parameters must be
2805 of types that are known to Qt's meta-object system, because Qt
2806 needs to copy the arguments to store them in an event behind the
2807 scenes. If you try to use a queued connection and get the error
2808 message
2809
2810 \snippet code/src_corelib_kernel_qobject.cpp 25
2811
2812 call qRegisterMetaType() to register the data type before you
2813 establish the connection.
2814
2815 \sa disconnect(), sender(), qRegisterMetaType(), Q_DECLARE_METATYPE(),
2816 {Differences between String-Based and Functor-Based Connections}
2817*/
2818QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
2819 const QObject *receiver, const char *method,
2820 Qt::ConnectionType type)
2821{
2822 if (sender == nullptr || receiver == nullptr || signal == nullptr || method == nullptr) {
2823 qWarning(msg: "QObject::connect: Cannot connect %s::%s to %s::%s",
2824 sender ? sender->metaObject()->className() : "(nullptr)",
2825 (signal && *signal) ? signal+1 : "(nullptr)",
2826 receiver ? receiver->metaObject()->className() : "(nullptr)",
2827 (method && *method) ? method+1 : "(nullptr)");
2828 return QMetaObject::Connection(nullptr);
2829 }
2830 QByteArray tmp_signal_name;
2831
2832 if (!check_signal_macro(sender, signal, func: "connect", op: "bind"))
2833 return QMetaObject::Connection(nullptr);
2834 const QMetaObject *smeta = sender->metaObject();
2835 const char *signal_arg = signal;
2836 ++signal; //skip code
2837 QArgumentTypeArray signalTypes;
2838 Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
2839 QByteArray signalName = QMetaObjectPrivate::decodeMethodSignature(signature: signal, types&: signalTypes);
2840 int signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2841 baseObject: &smeta, name: signalName, argc: signalTypes.size(), types: signalTypes.constData());
2842 if (signal_index < 0) {
2843 // check for normalized signatures
2844 tmp_signal_name = QMetaObject::normalizedSignature(method: signal - 1);
2845 signal = tmp_signal_name.constData() + 1;
2846
2847 signalTypes.clear();
2848 signalName = QMetaObjectPrivate::decodeMethodSignature(signature: signal, types&: signalTypes);
2849 smeta = sender->metaObject();
2850 signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2851 baseObject: &smeta, name: signalName, argc: signalTypes.size(), types: signalTypes.constData());
2852 }
2853 if (signal_index < 0) {
2854 err_method_notfound(object: sender, method: signal_arg, func: "connect");
2855 err_info_about_objects(func: "connect", sender, receiver);
2856 return QMetaObject::Connection(nullptr);
2857 }
2858 signal_index = QMetaObjectPrivate::originalClone(obj: smeta, local_method_index: signal_index);
2859 signal_index += QMetaObjectPrivate::signalOffset(m: smeta);
2860
2861 QByteArray tmp_method_name;
2862 int membcode = extract_code(member: method);
2863
2864 if (!check_method_code(code: membcode, object: receiver, method, func: "connect"))
2865 return QMetaObject::Connection(nullptr);
2866 const char *method_arg = method;
2867 ++method; // skip code
2868
2869 QArgumentTypeArray methodTypes;
2870 QByteArray methodName = QMetaObjectPrivate::decodeMethodSignature(signature: method, types&: methodTypes);
2871 const QMetaObject *rmeta = receiver->metaObject();
2872 int method_index_relative = -1;
2873 Q_ASSERT(QMetaObjectPrivate::get(rmeta)->revision >= 7);
2874 switch (membcode) {
2875 case QSLOT_CODE:
2876 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
2877 m: &rmeta, name: methodName, argc: methodTypes.size(), types: methodTypes.constData());
2878 break;
2879 case QSIGNAL_CODE:
2880 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
2881 baseObject: &rmeta, name: methodName, argc: methodTypes.size(), types: methodTypes.constData());
2882 break;
2883 }
2884 if (method_index_relative < 0) {
2885 // check for normalized methods
2886 tmp_method_name = QMetaObject::normalizedSignature(method);
2887 method = tmp_method_name.constData();
2888
2889 methodTypes.clear();
2890 methodName = QMetaObjectPrivate::decodeMethodSignature(signature: method, types&: methodTypes);
2891 // rmeta may have been modified above
2892 rmeta = receiver->metaObject();
2893 switch (membcode) {
2894 case QSLOT_CODE:
2895 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
2896 m: &rmeta, name: methodName, argc: methodTypes.size(), types: methodTypes.constData());
2897 break;
2898 case QSIGNAL_CODE:
2899 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
2900 baseObject: &rmeta, name: methodName, argc: methodTypes.size(), types: methodTypes.constData());
2901 break;
2902 }
2903 }
2904
2905 if (method_index_relative < 0) {
2906 err_method_notfound(object: receiver, method: method_arg, func: "connect");
2907 err_info_about_objects(func: "connect", sender, receiver);
2908 return QMetaObject::Connection(nullptr);
2909 }
2910
2911 if (!QMetaObjectPrivate::checkConnectArgs(signalArgc: signalTypes.size(), signalTypes: signalTypes.constData(),
2912 methodArgc: methodTypes.size(), methodTypes: methodTypes.constData())) {
2913 qWarning(msg: "QObject::connect: Incompatible sender/receiver arguments"
2914 "\n %s::%s --> %s::%s",
2915 sender->metaObject()->className(), signal,
2916 receiver->metaObject()->className(), method);
2917 return QMetaObject::Connection(nullptr);
2918 }
2919
2920 int *types = nullptr;
2921 if ((type == Qt::QueuedConnection)
2922 && !(types = queuedConnectionTypes(argumentTypes: signalTypes.constData(), argc: signalTypes.size()))) {
2923 return QMetaObject::Connection(nullptr);
2924 }
2925
2926#ifndef QT_NO_DEBUG
2927 QMetaMethod smethod = QMetaObjectPrivate::signal(m: smeta, signal_index);
2928 QMetaMethod rmethod = rmeta->method(index: method_index_relative + rmeta->methodOffset());
2929 check_and_warn_compat(sender: smeta, signal: smethod, receiver: rmeta, method: rmethod);
2930#endif
2931 QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
2932 sender, signal_index, smeta, receiver, method_index_relative, rmeta ,type, types));
2933 return handle;
2934}
2935
2936/*!
2937 \since 4.8
2938
2939 Creates a connection of the given \a type from the \a signal in
2940 the \a sender object to the \a method in the \a receiver object.
2941 Returns a handle to the connection that can be used to disconnect
2942 it later.
2943
2944 The Connection handle will be invalid if it cannot create the
2945 connection, for example, the parameters were invalid.
2946 You can check if the QMetaObject::Connection is valid by casting it to a bool.
2947
2948 This function works in the same way as
2949 \c {connect(const QObject *sender, const char *signal,
2950 const QObject *receiver, const char *method,
2951 Qt::ConnectionType type)}
2952 but it uses QMetaMethod to specify signal and method.
2953
2954 \sa connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
2955 */
2956QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal,
2957 const QObject *receiver, const QMetaMethod &method,
2958 Qt::ConnectionType type)
2959{
2960 if (sender == nullptr
2961 || receiver == nullptr
2962 || signal.methodType() != QMetaMethod::Signal
2963 || method.methodType() == QMetaMethod::Constructor) {
2964 qWarning(msg: "QObject::connect: Cannot connect %s::%s to %s::%s",
2965 sender ? sender->metaObject()->className() : "(nullptr)",
2966 signal.methodSignature().constData(),
2967 receiver ? receiver->metaObject()->className() : "(nullptr)",
2968 method.methodSignature().constData() );
2969 return QMetaObject::Connection(nullptr);
2970 }
2971
2972 int signal_index;
2973 int method_index;
2974 {
2975 int dummy;
2976 QMetaObjectPrivate::memberIndexes(obj: sender, member: signal, signalIndex: &signal_index, methodIndex: &dummy);
2977 QMetaObjectPrivate::memberIndexes(obj: receiver, member: method, signalIndex: &dummy, methodIndex: &method_index);
2978 }
2979
2980 const QMetaObject *smeta = sender->metaObject();
2981 const QMetaObject *rmeta = receiver->metaObject();
2982 if (signal_index == -1) {
2983 qWarning(msg: "QObject::connect: Can't find signal %s on instance of class %s",
2984 signal.methodSignature().constData(), smeta->className());
2985 return QMetaObject::Connection(nullptr);
2986 }
2987 if (method_index == -1) {
2988 qWarning(msg: "QObject::connect: Can't find method %s on instance of class %s",
2989 method.methodSignature().constData(), rmeta->className());
2990 return QMetaObject::Connection(nullptr);
2991 }
2992
2993 if (!QMetaObject::checkConnectArgs(signal: signal.methodSignature().constData(), method: method.methodSignature().constData())) {
2994 qWarning(msg: "QObject::connect: Incompatible sender/receiver arguments"
2995 "\n %s::%s --> %s::%s",
2996 smeta->className(), signal.methodSignature().constData(),
2997 rmeta->className(), method.methodSignature().constData());
2998 return QMetaObject::Connection(nullptr);
2999 }
3000
3001 int *types = nullptr;
3002 if ((type == Qt::QueuedConnection)
3003 && !(types = queuedConnectionTypes(typeNames: signal.parameterTypes())))
3004 return QMetaObject::Connection(nullptr);
3005
3006#ifndef QT_NO_DEBUG
3007 check_and_warn_compat(sender: smeta, signal, receiver: rmeta, method);
3008#endif
3009 QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
3010 sender, signal_index, smeta: signal.enclosingMetaObject(), receiver, method_index_relative: method_index, rmeta: nullptr, type, types));
3011 return handle;
3012}
3013
3014/*!
3015 \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
3016 \overload connect()
3017 \threadsafe
3018
3019 Connects \a signal from the \a sender object to this object's \a
3020 method.
3021
3022 Equivalent to connect(\a sender, \a signal, \c this, \a method, \a type).
3023
3024 Every connection you make emits a signal, so duplicate connections emit
3025 two signals. You can break a connection using disconnect().
3026
3027 \sa disconnect()
3028*/
3029
3030/*!
3031 \threadsafe
3032
3033 Disconnects \a signal in object \a sender from \a method in object
3034 \a receiver. Returns \c true if the connection is successfully broken;
3035 otherwise returns \c false.
3036
3037 A signal-slot connection is removed when either of the objects
3038 involved are destroyed.
3039
3040 disconnect() is typically used in three ways, as the following
3041 examples demonstrate.
3042 \list 1
3043 \li Disconnect everything connected to an object's signals:
3044
3045 \snippet code/src_corelib_kernel_qobject.cpp 26
3046
3047 equivalent to the non-static overloaded function
3048
3049 \snippet code/src_corelib_kernel_qobject.cpp 27
3050
3051 \li Disconnect everything connected to a specific signal:
3052
3053 \snippet code/src_corelib_kernel_qobject.cpp 28
3054
3055 equivalent to the non-static overloaded function
3056
3057 \snippet code/src_corelib_kernel_qobject.cpp 29
3058
3059 \li Disconnect a specific receiver:
3060
3061 \snippet code/src_corelib_kernel_qobject.cpp 30
3062
3063 equivalent to the non-static overloaded function
3064
3065 \snippet code/src_corelib_kernel_qobject.cpp 31
3066
3067 \endlist
3068
3069 \nullptr may be used as a wildcard, meaning "any signal", "any receiving
3070 object", or "any slot in the receiving object", respectively.
3071
3072 The \a sender may never be \nullptr. (You cannot disconnect signals
3073 from more than one object in a single call.)
3074
3075 If \a signal is \nullptr, it disconnects \a receiver and \a method from
3076 any signal. If not, only the specified signal is disconnected.
3077
3078 If \a receiver is \nullptr, it disconnects anything connected to \a
3079 signal. If not, slots in objects other than \a receiver are not
3080 disconnected.
3081
3082 If \a method is \nullptr, it disconnects anything that is connected to \a
3083 receiver. If not, only slots named \a method will be disconnected,
3084 and all other slots are left alone. The \a method must be \nullptr
3085 if \a receiver is left out, so you cannot disconnect a
3086 specifically-named slot on all objects.
3087
3088 \sa connect()
3089*/
3090bool QObject::disconnect(const QObject *sender, const char *signal,
3091 const QObject *receiver, const char *method)
3092{
3093 if (sender == nullptr || (receiver == nullptr && method != nullptr)) {
3094 qWarning(msg: "QObject::disconnect: Unexpected nullptr parameter");
3095 return false;
3096 }
3097
3098 const char *signal_arg = signal;
3099 QByteArray signal_name;
3100 bool signal_found = false;
3101 if (signal) {
3102 QT_TRY {
3103 signal_name = QMetaObject::normalizedSignature(method: signal);
3104 signal = signal_name.constData();
3105 } QT_CATCH (const std::bad_alloc &) {
3106 // if the signal is already normalized, we can continue.
3107 if (sender->metaObject()->indexOfSignal(signal: signal + 1) == -1)
3108 QT_RETHROW;
3109 }
3110
3111 if (!check_signal_macro(sender, signal, func: "disconnect", op: "unbind"))
3112 return false;
3113 signal++; // skip code
3114 }
3115
3116 QByteArray method_name;
3117 const char *method_arg = method;
3118 int membcode = -1;
3119 bool method_found = false;
3120 if (method) {
3121 QT_TRY {
3122 method_name = QMetaObject::normalizedSignature(method);
3123 method = method_name.constData();
3124 } QT_CATCH(const std::bad_alloc &) {
3125 // if the method is already normalized, we can continue.
3126 if (receiver->metaObject()->indexOfMethod(method: method + 1) == -1)
3127 QT_RETHROW;
3128 }
3129
3130 membcode = extract_code(member: method);
3131 if (!check_method_code(code: membcode, object: receiver, method, func: "disconnect"))
3132 return false;
3133 method++; // skip code
3134 }
3135
3136 /* We now iterate through all the sender's and receiver's meta
3137 * objects in order to also disconnect possibly shadowed signals
3138 * and slots with the same signature.
3139 */
3140 bool res = false;
3141 const QMetaObject *smeta = sender->metaObject();
3142 QByteArray signalName;
3143 QArgumentTypeArray signalTypes;
3144 Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
3145 if (signal)
3146 signalName = QMetaObjectPrivate::decodeMethodSignature(signature: signal, types&: signalTypes);
3147 QByteArray methodName;
3148 QArgumentTypeArray methodTypes;
3149 Q_ASSERT(!receiver || QMetaObjectPrivate::get(receiver->metaObject())->revision >= 7);
3150 if (method)
3151 methodName = QMetaObjectPrivate::decodeMethodSignature(signature: method, types&: methodTypes);
3152 do {
3153 int signal_index = -1;
3154 if (signal) {
3155 signal_index = QMetaObjectPrivate::indexOfSignalRelative(
3156 baseObject: &smeta, name: signalName, argc: signalTypes.size(), types: signalTypes.constData());
3157 if (signal_index < 0)
3158 break;
3159 signal_index = QMetaObjectPrivate::originalClone(obj: smeta, local_method_index: signal_index);
3160 signal_index += QMetaObjectPrivate::signalOffset(m: smeta);
3161 signal_found = true;
3162 }
3163
3164 if (!method) {
3165 res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, method_index: -1, slot: nullptr);
3166 } else {
3167 const QMetaObject *rmeta = receiver->metaObject();
3168 do {
3169 int method_index = QMetaObjectPrivate::indexOfMethod(
3170 m: rmeta, name: methodName, argc: methodTypes.size(), types: methodTypes.constData());
3171 if (method_index >= 0)
3172 while (method_index < rmeta->methodOffset())
3173 rmeta = rmeta->superClass();
3174 if (method_index < 0)
3175 break;
3176 res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, method_index, slot: nullptr);
3177 method_found = true;
3178 } while ((rmeta = rmeta->superClass()));
3179 }
3180 } while (signal && (smeta = smeta->superClass()));
3181
3182 if (signal && !signal_found) {
3183 err_method_notfound(object: sender, method: signal_arg, func: "disconnect");
3184 err_info_about_objects(func: "disconnect", sender, receiver);
3185 } else if (method && !method_found) {
3186 err_method_notfound(object: receiver, method: method_arg, func: "disconnect");
3187 err_info_about_objects(func: "disconnect", sender, receiver);
3188 }
3189 if (res) {
3190 if (!signal)
3191 const_cast<QObject*>(sender)->disconnectNotify(signal: QMetaMethod());
3192 }
3193 return res;
3194}
3195
3196/*!
3197 \since 4.8
3198
3199 Disconnects \a signal in object \a sender from \a method in object
3200 \a receiver. Returns \c true if the connection is successfully broken;
3201 otherwise returns \c false.
3202
3203 This function provides the same possibilities like
3204 \c {disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) }
3205 but uses QMetaMethod to represent the signal and the method to be disconnected.
3206
3207 Additionally this function returns false and no signals and slots disconnected
3208 if:
3209 \list 1
3210
3211 \li \a signal is not a member of sender class or one of its parent classes.
3212
3213 \li \a method is not a member of receiver class or one of its parent classes.
3214
3215 \li \a signal instance represents not a signal.
3216
3217 \endlist
3218
3219 QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object".
3220 In the same way \nullptr can be used for \a receiver in the meaning "any receiving object".
3221 In this case method should also be QMetaMethod(). \a sender parameter should be never \nullptr.
3222
3223 \sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
3224 */
3225bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
3226 const QObject *receiver, const QMetaMethod &method)
3227{
3228 if (sender == nullptr || (receiver == nullptr && method.mobj != nullptr)) {
3229 qWarning(msg: "QObject::disconnect: Unexpected nullptr parameter");
3230 return false;
3231 }
3232 if (signal.mobj) {
3233 if(signal.methodType() != QMetaMethod::Signal) {
3234 qWarning(msg: "QObject::%s: Attempt to %s non-signal %s::%s",
3235 "disconnect","unbind",
3236 sender->metaObject()->className(), signal.methodSignature().constData());
3237 return false;
3238 }
3239 }
3240 if (method.mobj) {
3241 if(method.methodType() == QMetaMethod::Constructor) {
3242 qWarning(msg: "QObject::disconnect: cannot use constructor as argument %s::%s",
3243 receiver->metaObject()->className(), method.methodSignature().constData());
3244 return false;
3245 }
3246 }
3247
3248 // Reconstructing SIGNAL() macro result for signal.methodSignature() string
3249 QByteArray signalSignature;
3250 if (signal.mobj) {
3251 signalSignature.reserve(asize: signal.methodSignature().size()+1);
3252 signalSignature.append(c: (char)(QSIGNAL_CODE + '0'));
3253 signalSignature.append(a: signal.methodSignature());
3254 }
3255
3256 int signal_index;
3257 int method_index;
3258 {
3259 int dummy;
3260 QMetaObjectPrivate::memberIndexes(obj: sender, member: signal, signalIndex: &signal_index, methodIndex: &dummy);
3261 QMetaObjectPrivate::memberIndexes(obj: receiver, member: method, signalIndex: &dummy, methodIndex: &method_index);
3262 }
3263 // If we are here sender is not nullptr. If signal is not nullptr while signal_index
3264 // is -1 then this signal is not a member of sender.
3265 if (signal.mobj && signal_index == -1) {
3266 qWarning(msg: "QObject::disconnect: signal %s not found on class %s",
3267 signal.methodSignature().constData(), sender->metaObject()->className());
3268 return false;
3269 }
3270 // If this condition is true then method is not a member of receiver.
3271 if (receiver && method.mobj && method_index == -1) {
3272 qWarning(msg: "QObject::disconnect: method %s not found on class %s",
3273 method.methodSignature().constData(), receiver->metaObject()->className());
3274 return false;
3275 }
3276
3277 if (!QMetaObjectPrivate::disconnect(sender, signal_index, smeta: signal.mobj, receiver, method_index, slot: nullptr))
3278 return false;
3279
3280 if (!signal.isValid()) {
3281 // The signal is a wildcard, meaning all signals were disconnected.
3282 // QMetaObjectPrivate::disconnect() doesn't call disconnectNotify()
3283 // per connection in this case. Call it once now, with an invalid
3284 // QMetaMethod as argument, as documented.
3285 const_cast<QObject*>(sender)->disconnectNotify(signal);
3286 }
3287 return true;
3288}
3289
3290/*!
3291 \threadsafe
3292
3293 \fn bool QObject::disconnect(const char *signal, const QObject *receiver, const char *method) const
3294 \overload disconnect()
3295
3296 Disconnects \a signal from \a method of \a receiver.
3297
3298 A signal-slot connection is removed when either of the objects
3299 involved are destroyed.
3300*/
3301
3302/*!
3303 \fn bool QObject::disconnect(const QObject *receiver, const char *method) const
3304 \overload disconnect()
3305
3306 Disconnects all signals in this object from \a receiver's \a
3307 method.
3308
3309 A signal-slot connection is removed when either of the objects
3310 involved are destroyed.
3311*/
3312
3313
3314/*!
3315 \since 5.0
3316
3317 This virtual function is called when something has been connected
3318 to \a signal in this object.
3319
3320 If you want to compare \a signal with a specific signal, you can
3321 use QMetaMethod::fromSignal() as follows:
3322
3323 \snippet code/src_corelib_kernel_qobject.cpp 32
3324
3325 \warning This function violates the object-oriented principle of
3326 modularity. However, it might be useful when you need to perform
3327 expensive initialization only if something is connected to a
3328 signal.
3329
3330 \warning This function is called from the thread which performs the
3331 connection, which may be a different thread from the thread in
3332 which this object lives.
3333
3334 \sa connect(), disconnectNotify()
3335*/
3336
3337void QObject::connectNotify(const QMetaMethod &signal)
3338{
3339 Q_UNUSED(signal);
3340}
3341
3342/*!
3343 \since 5.0
3344
3345 This virtual function is called when something has been
3346 disconnected from \a signal in this object.
3347
3348 See connectNotify() for an example of how to compare
3349 \a signal with a specific signal.
3350
3351 If all signals were disconnected from this object (e.g., the
3352 signal argument to disconnect() was \nullptr), disconnectNotify()
3353 is only called once, and the \a signal will be an invalid
3354 QMetaMethod (QMetaMethod::isValid() returns \c false).
3355
3356 \warning This function violates the object-oriented principle of
3357 modularity. However, it might be useful for optimizing access to
3358 expensive resources.
3359
3360 \warning This function is called from the thread which performs the
3361 disconnection, which may be a different thread from the thread in
3362 which this object lives. This function may also be called with a QObject
3363 internal mutex locked. It is therefore not allowed to re-enter any
3364 of any QObject functions from your reimplementation and if you lock
3365 a mutex in your reimplementation, make sure that you don't call QObject
3366 functions with that mutex held in other places or it will result in
3367 a deadlock.
3368
3369 \sa disconnect(), connectNotify()
3370*/
3371
3372void QObject::disconnectNotify(const QMetaMethod &signal)
3373{
3374 Q_UNUSED(signal);
3375}
3376
3377/*
3378 \internal
3379 convert a signal index from the method range to the signal range
3380 */
3381static int methodIndexToSignalIndex(const QMetaObject **base, int signal_index)
3382{
3383 if (signal_index < 0)
3384 return signal_index;
3385 const QMetaObject *metaObject = *base;
3386 while (metaObject && metaObject->methodOffset() > signal_index)
3387 metaObject = metaObject->superClass();
3388
3389 if (metaObject) {
3390 int signalOffset, methodOffset;
3391 computeOffsets(metaobject: metaObject, signalOffset: &signalOffset, methodOffset: &methodOffset);
3392 if (signal_index < metaObject->methodCount())
3393 signal_index = QMetaObjectPrivate::originalClone(obj: metaObject, local_method_index: signal_index - methodOffset) + signalOffset;
3394 else
3395 signal_index = signal_index - methodOffset + signalOffset;
3396 *base = metaObject;
3397 }
3398 return signal_index;
3399}
3400
3401/*!
3402 \internal
3403 \a types is a 0-terminated vector of meta types for queued
3404 connections.
3405
3406 if \a signal_index is -1, then we effectively connect *all* signals
3407 from the sender to the receiver's slot
3408 */
3409QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_index,
3410 const QObject *receiver, int method_index, int type, int *types)
3411{
3412 const QMetaObject *smeta = sender->metaObject();
3413 signal_index = methodIndexToSignalIndex(base: &smeta, signal_index);
3414 return Connection(QMetaObjectPrivate::connect(sender, signal_index, smeta,
3415 receiver, method_index_relative: method_index,
3416 rmeta: nullptr, //FIXME, we could speed this connection up by computing the relative index
3417 type, types));
3418}
3419
3420/*!
3421 \internal
3422 Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3423
3424 method_index is relative to the rmeta metaobject, if rmeta is \nullptr, then it is absolute index
3425
3426 the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection
3427 */
3428QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
3429 int signal_index, const QMetaObject *smeta,
3430 const QObject *receiver, int method_index,
3431 const QMetaObject *rmeta, int type, int *types)
3432{
3433 QObject *s = const_cast<QObject *>(sender);
3434 QObject *r = const_cast<QObject *>(receiver);
3435
3436 int method_offset = rmeta ? rmeta->methodOffset() : 0;
3437 Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6);
3438 QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : nullptr;
3439
3440 QOrderedMutexLocker locker(signalSlotLock(o: sender),
3441 signalSlotLock(o: receiver));
3442
3443 QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(o: s)->connections.loadRelaxed();
3444 if (type & Qt::UniqueConnection && scd) {
3445 if (scd->signalVectorCount() > signal_index) {
3446 const QObjectPrivate::Connection *c2 = scd->signalVector.loadRelaxed()->at(i: signal_index).first.loadRelaxed();
3447
3448 int method_index_absolute = method_index + method_offset;
3449
3450 while (c2) {
3451 if (!c2->isSlotObject && c2->receiver.loadRelaxed() == receiver && c2->method() == method_index_absolute)
3452 return nullptr;
3453 c2 = c2->nextConnectionList.loadRelaxed();
3454 }
3455 }
3456 type &= Qt::UniqueConnection - 1;
3457 }
3458
3459 std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
3460 c->sender = s;
3461 c->signal_index = signal_index;
3462 c->receiver.storeRelaxed(newValue: r);
3463 QThreadData *td = r->d_func()->threadData;
3464 td->ref();
3465 c->receiverThreadData.storeRelaxed(newValue: td);
3466 c->method_relative = method_index;
3467 c->method_offset = method_offset;
3468 c->connectionType = type;
3469 c->isSlotObject = false;
3470 c->argumentTypes.storeRelaxed(newValue: types);
3471 c->callFunction = callFunction;
3472
3473 QObjectPrivate::get(o: s)->addConnection(signal: signal_index, c: c.get());
3474
3475 locker.unlock();
3476 QMetaMethod smethod = QMetaObjectPrivate::signal(m: smeta, signal_index);
3477 if (smethod.isValid())
3478 s->connectNotify(signal: smethod);
3479
3480 return c.release();
3481}
3482
3483/*!
3484 \internal
3485 */
3486bool QMetaObject::disconnect(const QObject *sender, int signal_index,
3487 const QObject *receiver, int method_index)
3488{
3489 const QMetaObject *smeta = sender->metaObject();
3490 signal_index = methodIndexToSignalIndex(base: &smeta, signal_index);
3491 return QMetaObjectPrivate::disconnect(sender, signal_index, smeta,
3492 receiver, method_index, slot: nullptr);
3493}
3494
3495/*!
3496 \internal
3497
3498Disconnect a single signal connection. If QMetaObject::connect() has been called
3499multiple times for the same sender, signal_index, receiver and method_index only
3500one of these connections will be removed.
3501 */
3502bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
3503 const QObject *receiver, int method_index)
3504{
3505 const QMetaObject *smeta = sender->metaObject();
3506 signal_index = methodIndexToSignalIndex(base: &smeta, signal_index);
3507 return QMetaObjectPrivate::disconnect(sender, signal_index, smeta,
3508 receiver, method_index, slot: nullptr,
3509 QMetaObjectPrivate::DisconnectOne);
3510}
3511
3512/*!
3513 \internal
3514 Helper function to remove the connection from the senders list and set the receivers to \nullptr
3515 */
3516bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex,
3517 const QObject *receiver, int method_index, void **slot,
3518 QBasicMutex *senderMutex, DisconnectType disconnectType)
3519{
3520 bool success = false;
3521
3522 auto &connectionList = connections->connectionsForSignal(signal: signalIndex);
3523 auto *c = connectionList.first.loadRelaxed();
3524 while (c) {
3525 QObject *r = c->receiver.loadRelaxed();
3526 if (r && (receiver == nullptr || (r == receiver
3527 && (method_index < 0 || (!c->isSlotObject && c->method() == method_index))
3528 && (slot == nullptr || (c->isSlotObject && c->slotObj->compare(a: slot)))))) {
3529 bool needToUnlock = false;
3530 QBasicMutex *receiverMutex = nullptr;
3531 if (r) {
3532 receiverMutex = signalSlotLock(o: r);
3533 // need to relock this receiver and sender in the correct order
3534 needToUnlock = QOrderedMutexLocker::relock(mtx1: senderMutex, mtx2: receiverMutex);
3535 }
3536 if (c->receiver.loadRelaxed())
3537 connections->removeConnection(c);
3538
3539 if (needToUnlock)
3540 receiverMutex->unlock();
3541
3542 success = true;
3543
3544 if (disconnectType == DisconnectOne)
3545 return success;
3546 }
3547 c = c->nextConnectionList.loadRelaxed();
3548 }
3549 return success;
3550}
3551
3552/*!
3553 \internal
3554 Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3555 */
3556bool QMetaObjectPrivate::disconnect(const QObject *sender,
3557 int signal_index, const QMetaObject *smeta,
3558 const QObject *receiver, int method_index, void **slot,
3559 DisconnectType disconnectType)
3560{
3561 if (!sender)
3562 return false;
3563
3564 QObject *s = const_cast<QObject *>(sender);
3565
3566 QBasicMutex *senderMutex = signalSlotLock(o: sender);
3567 QBasicMutexLocker locker(senderMutex);
3568
3569 QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(o: s)->connections.loadRelaxed();
3570 if (!scd)
3571 return false;
3572
3573 bool success = false;
3574 {
3575 // prevent incoming connections changing the connections->receivers while unlocked
3576 QObjectPrivate::ConnectionDataPointer connections(scd);
3577
3578 if (signal_index < 0) {
3579 // remove from all connection lists
3580 for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) {
3581 if (disconnectHelper(connections: connections.data(), signalIndex: sig_index, receiver, method_index, slot, senderMutex, disconnectType))
3582 success = true;
3583 }
3584 } else if (signal_index < scd->signalVectorCount()) {
3585 if (disconnectHelper(connections: connections.data(), signalIndex: signal_index, receiver, method_index, slot, senderMutex, disconnectType))
3586 success = true;
3587 }
3588 }
3589
3590 locker.unlock();
3591 if (success) {
3592 scd->cleanOrphanedConnections(sender: s);
3593
3594 QMetaMethod smethod = QMetaObjectPrivate::signal(m: smeta, signal_index);
3595 if (smethod.isValid())
3596 s->disconnectNotify(signal: smethod);
3597 }
3598
3599 return success;
3600}
3601
3602// Helpers for formatting the connect statements of connectSlotsByName()'s debug mode
3603static QByteArray formatConnectionSignature(const char *className, const QMetaMethod &method)
3604{
3605 const auto signature = method.methodSignature();
3606 Q_ASSERT(signature.endsWith(')'));
3607 const int openParen = signature.indexOf(c: '(');
3608 const bool hasParameters = openParen >= 0 && openParen < signature.size() - 2;
3609 QByteArray result;
3610 if (hasParameters) {
3611 result += "qOverload<"
3612 + signature.mid(index: openParen + 1, len: signature.size() - openParen - 2) + ">(";
3613 }
3614 result += '&';
3615 result += className + QByteArrayLiteral("::") + method.name();
3616 if (hasParameters)
3617 result += ')';
3618 return result;
3619}
3620
3621static QByteArray msgConnect(const QMetaObject *senderMo, const QByteArray &senderName,
3622 const QMetaMethod &signal, const QObject *receiver, int receiverIndex)
3623{
3624 const auto receiverMo = receiver->metaObject();
3625 const auto slot = receiverMo->method(index: receiverIndex);
3626 QByteArray message = QByteArrayLiteral("QObject::connect(")
3627 + senderName + ", " + formatConnectionSignature(className: senderMo->className(), method: signal)
3628 + ", " + receiver->objectName().toLatin1() + ", "
3629 + formatConnectionSignature(className: receiverMo->className(), method: slot) + ");";
3630 return message;
3631}
3632
3633/*!
3634 \fn void QMetaObject::connectSlotsByName(QObject *object)
3635
3636 Searches recursively for all child objects of the given \a object, and connects
3637 matching signals from them to slots of \a object that follow the following form:
3638
3639 \snippet code/src_corelib_kernel_qobject.cpp 33
3640
3641 Let's assume our object has a child object of type \c{QPushButton} with
3642 the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
3643 button's \c{clicked()} signal would be:
3644
3645 \snippet code/src_corelib_kernel_qobject.cpp 34
3646
3647 If \a object itself has a properly set object name, its own signals are also
3648 connected to its respective slots.
3649
3650 \sa QObject::setObjectName()
3651 */
3652void QMetaObject::connectSlotsByName(QObject *o)
3653{
3654 if (!o)
3655 return;
3656 const QMetaObject *mo = o->metaObject();
3657 Q_ASSERT(mo);
3658 const QObjectList list = // list of all objects to look for matching signals including...
3659 o->findChildren<QObject *>(aName: QString()) // all children of 'o'...
3660 << o; // and the object 'o' itself
3661
3662 // for each method/slot of o ...
3663 for (int i = 0; i < mo->methodCount(); ++i) {
3664 const QByteArray slotSignature = mo->method(index: i).methodSignature();
3665 const char *slot = slotSignature.constData();
3666 Q_ASSERT(slot);
3667
3668 // ...that starts with "on_", ...
3669 if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
3670 continue;
3671
3672 // ...we check each object in our list, ...
3673 bool foundIt = false;
3674 for(int j = 0; j < list.count(); ++j) {
3675 const QObject *co = list.at(i: j);
3676 const QByteArray coName = co->objectName().toLatin1();
3677
3678 // ...discarding those whose objectName is not fitting the pattern "on_<objectName>_...", ...
3679 if (coName.isEmpty() || qstrncmp(str1: slot + 3, str2: coName.constData(), len: coName.size()) || slot[coName.size()+3] != '_')
3680 continue;
3681
3682 const char *signal = slot + coName.size() + 4; // the 'signal' part of the slot name
3683
3684 // ...for the presence of a matching signal "on_<objectName>_<signal>".
3685 const QMetaObject *smeta;
3686 int sigIndex = co->d_func()->signalIndex(signalName: signal, meta: &smeta);
3687 if (sigIndex < 0) {
3688 // if no exactly fitting signal (name + complete parameter type list) could be found
3689 // look for just any signal with the correct name and at least the slot's parameter list.
3690 // Note: if more than one of those signals exist, the one that gets connected is
3691 // chosen 'at random' (order of declaration in source file)
3692 QList<QByteArray> compatibleSignals;
3693 const QMetaObject *smo = co->metaObject();
3694 int sigLen = qstrlen(str: signal) - 1; // ignore the trailing ')'
3695 for (int k = QMetaObjectPrivate::absoluteSignalCount(m: smo)-1; k >= 0; --k) {
3696 const QMetaMethod method = QMetaObjectPrivate::signal(m: smo, signal_index: k);
3697 if (!qstrncmp(str1: method.methodSignature().constData(), str2: signal, len: sigLen)) {
3698 smeta = method.enclosingMetaObject();
3699 sigIndex = k;
3700 compatibleSignals.prepend(t: method.methodSignature());
3701 }
3702 }
3703 if (compatibleSignals.size() > 1)
3704 qWarning() << "QMetaObject::connectSlotsByName: Connecting slot" << slot
3705 << "with the first of the following compatible signals:" << compatibleSignals;
3706 }
3707
3708 if (sigIndex < 0)
3709 continue;
3710
3711 // we connect it...
3712 if (Connection(QMetaObjectPrivate::connect(sender: co, signal_index: sigIndex, smeta, receiver: o, method_index: i))) {
3713 foundIt = true;
3714 qCDebug(lcConnections, "%s",
3715 msgConnect(smeta, coName, QMetaObjectPrivate::signal(smeta, sigIndex), o, i).constData());
3716 // ...and stop looking for further objects with the same name.
3717 // Note: the Designer will make sure each object name is unique in the above
3718 // 'list' but other code may create two child objects with the same name. In
3719 // this case one is chosen 'at random'.
3720 break;
3721 }
3722 }
3723 if (foundIt) {
3724 // we found our slot, now skip all overloads
3725 while (mo->method(index: i + 1).attributes() & QMetaMethod::Cloned)
3726 ++i;
3727 } else if (!(mo->method(index: i).attributes() & QMetaMethod::Cloned)) {
3728 // check if the slot has the following signature: "on_..._...(..."
3729 int iParen = slotSignature.indexOf(c: '(');
3730 int iLastUnderscore = slotSignature.lastIndexOf(c: '_', from: iParen-1);
3731 if (iLastUnderscore > 3)
3732 qWarning(msg: "QMetaObject::connectSlotsByName: No matching signal for %s", slot);
3733 }
3734 }
3735}
3736
3737/*!
3738 \internal
3739
3740 \a signal must be in the signal index range (see QObjectPrivate::signalIndex()).
3741*/
3742static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
3743{
3744 const int *argumentTypes = c->argumentTypes.loadRelaxed();
3745 if (!argumentTypes) {
3746 QMetaMethod m = QMetaObjectPrivate::signal(m: sender->metaObject(), signal_index: signal);
3747 argumentTypes = queuedConnectionTypes(typeNames: m.parameterTypes());
3748 if (!argumentTypes) // cannot queue arguments
3749 argumentTypes = &DIRECT_CONNECTION_ONLY;
3750 if (!c->argumentTypes.testAndSetOrdered(expectedValue: nullptr, newValue: argumentTypes)) {
3751 if (argumentTypes != &DIRECT_CONNECTION_ONLY)
3752 delete [] argumentTypes;
3753 argumentTypes = c->argumentTypes.loadRelaxed();
3754 }
3755 }
3756 if (argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
3757 return;
3758 int nargs = 1; // include return type
3759 while (argumentTypes[nargs-1])
3760 ++nargs;
3761
3762 QBasicMutexLocker locker(signalSlotLock(o: c->receiver.loadRelaxed()));
3763 if (!c->receiver.loadRelaxed()) {
3764 // the connection has been disconnected before we got the lock
3765 return;
3766 }
3767 if (c->isSlotObject)
3768 c->slotObj->ref();
3769 locker.unlock();
3770
3771 QMetaCallEvent *ev = c->isSlotObject ?
3772 new QMetaCallEvent(c->slotObj, sender, signal, nargs) :
3773 new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs);
3774
3775 void **args = ev->args();
3776 int *types = ev->types();
3777
3778 types[0] = 0; // return type
3779 args[0] = nullptr; // return value
3780
3781 if (nargs > 1) {
3782 for (int n = 1; n < nargs; ++n)
3783 types[n] = argumentTypes[n-1];
3784
3785 for (int n = 1; n < nargs; ++n)
3786 args[n] = QMetaType::create(type: types[n], copy: argv[n]);
3787 }
3788
3789 locker.relock();
3790 if (c->isSlotObject)
3791 c->slotObj->destroyIfLastRef();
3792 if (!c->receiver.loadRelaxed()) {
3793 // the connection has been disconnected while we were unlocked
3794 locker.unlock();
3795 delete ev;
3796 return;
3797 }
3798
3799 QCoreApplication::postEvent(receiver: c->receiver.loadRelaxed(), event: ev);
3800}
3801
3802template <bool callbacks_enabled>
3803void doActivate(QObject *sender, int signal_index, void **argv)
3804{
3805 QObjectPrivate *sp = QObjectPrivate::get(o: sender);
3806
3807 if (sp->blockSig)
3808 return;
3809
3810 Q_TRACE_SCOPE(QMetaObject_activate, sender, signal_index);
3811
3812 if (sp->isDeclarativeSignalConnected(signal_index)
3813 && QAbstractDeclarativeData::signalEmitted) {
3814 Q_TRACE_SCOPE(QMetaObject_activate_declarative_signal, sender, signal_index);
3815 QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender,
3816 signal_index, argv);
3817 }
3818
3819 const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.loadAcquire() : nullptr;
3820
3821 void *empty_argv[] = { nullptr };
3822 if (!argv)
3823 argv = empty_argv;
3824
3825 if (!sp->maybeSignalConnected(signalIndex: signal_index)) {
3826 // The possible declarative connection is done, and nothing else is connected
3827 if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
3828 signal_spy_set->signal_begin_callback(sender, signal_index, argv);
3829 if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
3830 signal_spy_set->signal_end_callback(sender, signal_index);
3831 return;
3832 }
3833
3834 if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
3835 signal_spy_set->signal_begin_callback(sender, signal_index, argv);
3836
3837 bool senderDeleted = false;
3838 {
3839 Q_ASSERT(sp->connections.loadAcquire());
3840 QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed());
3841 QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed();
3842
3843 const QObjectPrivate::ConnectionList *list;
3844 if (signal_index < signalVector->count())
3845 list = &signalVector->at(i: signal_index);
3846 else
3847 list = &signalVector->at(i: -1);
3848
3849 Qt::HANDLE currentThreadId = QThread::currentThreadId();
3850 bool inSenderThread = currentThreadId == QObjectPrivate::get(o: sender)->threadData.loadRelaxed()->threadId.loadRelaxed();
3851
3852 // We need to check against the highest connection id to ensure that signals added
3853 // during the signal emission are not emitted in this emission.
3854 uint highestConnectionId = connections->currentConnectionId.loadRelaxed();
3855 do {
3856 QObjectPrivate::Connection *c = list->first.loadRelaxed();
3857 if (!c)
3858 continue;
3859
3860 do {
3861 QObject * const receiver = c->receiver.loadRelaxed();
3862 if (!receiver)
3863 continue;
3864
3865 QThreadData *td = c->receiverThreadData.loadRelaxed();
3866 if (!td)
3867 continue;
3868
3869 bool receiverInSameThread;
3870 if (inSenderThread) {
3871 receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
3872 } else {
3873 // need to lock before reading the threadId, because moveToThread() could interfere
3874 QMutexLocker lock(signalSlotLock(o: receiver));
3875 receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
3876 }
3877
3878
3879 // determine if this connection should be sent immediately or
3880 // put into the event queue
3881 if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
3882 || (c->connectionType == Qt::QueuedConnection)) {
3883 queued_activate(sender, signal: signal_index, c, argv);
3884 continue;
3885#if QT_CONFIG(thread)
3886 } else if (c->connectionType == Qt::BlockingQueuedConnection) {
3887 if (receiverInSameThread) {
3888 qWarning(msg: "Qt: Dead lock detected while activating a BlockingQueuedConnection: "
3889 "Sender is %s(%p), receiver is %s(%p)",
3890 sender->metaObject()->className(), sender,
3891 receiver->metaObject()->className(), receiver);
3892 }
3893 QSemaphore semaphore;
3894 {
3895 QBasicMutexLocker locker(signalSlotLock(o: sender));
3896 if (!c->receiver.loadAcquire())
3897 continue;
3898 QMetaCallEvent *ev = c->isSlotObject ?
3899 new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) :
3900 new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction,
3901 sender, signal_index, argv, &semaphore);
3902 QCoreApplication::postEvent(receiver, event: ev);
3903 }
3904 semaphore.acquire();
3905 continue;
3906#endif
3907 }
3908
3909 QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index);
3910
3911 if (c->isSlotObject) {
3912 c->slotObj->ref();
3913
3914 struct Deleter {
3915 void operator()(QtPrivate::QSlotObjectBase *slot) const {
3916 if (slot) slot->destroyIfLastRef();
3917 }
3918 };
3919 const std::unique_ptr<QtPrivate::QSlotObjectBase, Deleter> obj{c->slotObj};
3920
3921 {
3922 Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.get());
3923 obj->call(receiver, argv);
3924 }
3925 } else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
3926 //we compare the vtable to make sure we are not in the destructor of the object.
3927 const int method_relative = c->method_relative;
3928 const auto callFunction = c->callFunction;
3929 const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0;
3930 if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr)
3931 signal_spy_set->slot_begin_callback(receiver, methodIndex, argv);
3932
3933 {
3934 Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, methodIndex);
3935 callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv);
3936 }
3937
3938 if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
3939 signal_spy_set->slot_end_callback(receiver, methodIndex);
3940 } else {
3941 const int method = c->method_relative + c->method_offset;
3942
3943 if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) {
3944 signal_spy_set->slot_begin_callback(receiver, method, argv);
3945 }
3946
3947 {
3948 Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, method);
3949 QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);
3950 }
3951
3952 if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
3953 signal_spy_set->slot_end_callback(receiver, method);
3954 }
3955 } while ((c = c->nextConnectionList.loadRelaxed()) != nullptr && c->id <= highestConnectionId);
3956
3957 } while (list != &signalVector->at(i: -1) &&
3958 //start over for all signals;
3959 ((list = &signalVector->at(i: -1)), true));
3960
3961 if (connections->currentConnectionId.loadRelaxed() == 0)
3962 senderDeleted = true;
3963 }
3964 if (!senderDeleted) {
3965 sp->connections.loadRelaxed()->cleanOrphanedConnections(sender);
3966
3967 if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
3968 signal_spy_set->signal_end_callback(sender, signal_index);
3969 }
3970}
3971
3972/*!
3973 \internal
3974 */
3975void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
3976 void **argv)
3977{
3978 int signal_index = local_signal_index + QMetaObjectPrivate::signalOffset(m);
3979
3980 if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
3981 doActivate<true>(sender, signal_index, argv);
3982 else
3983 doActivate<false>(sender, signal_index, argv);
3984}
3985
3986/*!
3987 \internal
3988 */
3989void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
3990{
3991 int signal_index = signalOffset + local_signal_index;
3992
3993 if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
3994 doActivate<true>(sender, signal_index, argv);
3995 else
3996 doActivate<false>(sender, signal_index, argv);
3997 }
3998
3999/*!
4000 \internal
4001 signal_index comes from indexOfMethod()
4002*/
4003void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
4004{
4005 const QMetaObject *mo = sender->metaObject();
4006 while (mo->methodOffset() > signal_index)
4007 mo = mo->superClass();
4008 activate(sender, m: mo, local_signal_index: signal_index - mo->methodOffset(), argv);
4009}
4010
4011/*!
4012 \internal
4013 Returns the signal index used in the internal connections->receivers vector.
4014
4015 It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
4016 while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
4017
4018 If \a meta is not \nullptr, it is set to the meta-object where the signal was found.
4019*/
4020int QObjectPrivate::signalIndex(const char *signalName,
4021 const QMetaObject **meta) const
4022{
4023 Q_Q(const QObject);
4024 const QMetaObject *base = q->metaObject();
4025 Q_ASSERT(QMetaObjectPrivate::get(base)->revision >= 7);
4026 QArgumentTypeArray types;
4027 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signature: signalName, types);
4028 int relative_index = QMetaObjectPrivate::indexOfSignalRelative(
4029 baseObject: &base, name, argc: types.size(), types: types.constData());
4030 if (relative_index < 0)
4031 return relative_index;
4032 relative_index = QMetaObjectPrivate::originalClone(obj: base, local_method_index: relative_index);
4033 if (meta)
4034 *meta = base;
4035 return relative_index + QMetaObjectPrivate::signalOffset(m: base);
4036}
4037
4038/*****************************************************************************
4039 Properties
4040 *****************************************************************************/
4041
4042#ifndef QT_NO_PROPERTIES
4043
4044/*!
4045 Sets the value of the object's \a name property to \a value.
4046
4047 If the property is defined in the class using Q_PROPERTY then
4048 true is returned on success and false otherwise. If the property
4049 is not defined using Q_PROPERTY, and therefore not listed in the
4050 meta-object, it is added as a dynamic property and false is returned.
4051
4052 Information about all available properties is provided through the
4053 metaObject() and dynamicPropertyNames().
4054
4055 Dynamic properties can be queried again using property() and can be
4056 removed by setting the property value to an invalid QVariant.
4057 Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent
4058 to be sent to the object.
4059
4060 \b{Note:} Dynamic properties starting with "_q_" are reserved for internal
4061 purposes.
4062
4063 \sa property(), metaObject(), dynamicPropertyNames(), QMetaProperty::write()
4064*/
4065bool QObject::setProperty(const char *name, const QVariant &value)
4066{
4067 Q_D(QObject);
4068 const QMetaObject* meta = metaObject();
4069 if (!name || !meta)
4070 return false;
4071
4072 int id = meta->indexOfProperty(name);
4073 if (id < 0) {
4074 if (!d->extraData)
4075 d->extraData = new QObjectPrivate::ExtraData;
4076
4077 const int idx = d->extraData->propertyNames.indexOf(t: name);
4078
4079 if (!value.isValid()) {
4080 if (idx == -1)
4081 return false;
4082 d->extraData->propertyNames.removeAt(i: idx);
4083 d->extraData->propertyValues.removeAt(i: idx);
4084 } else {
4085 if (idx == -1) {
4086 d->extraData->propertyNames.append(t: name);
4087 d->extraData->propertyValues.append(t: value);
4088 } else {
4089 if (value.userType() == d->extraData->propertyValues.at(i: idx).userType()
4090 && value == d->extraData->propertyValues.at(i: idx))
4091 return false;
4092 d->extraData->propertyValues[idx] = value;
4093 }
4094 }
4095
4096 QDynamicPropertyChangeEvent ev(name);
4097 QCoreApplication::sendEvent(receiver: this, event: &ev);
4098
4099 return false;
4100 }
4101 QMetaProperty p = meta->property(index: id);
4102#ifndef QT_NO_DEBUG
4103 if (!p.isWritable())
4104 qWarning(msg: "%s::setProperty: Property \"%s\" invalid,"
4105 " read-only or does not exist", metaObject()->className(), name);
4106#endif
4107 return p.write(obj: this, value);
4108}
4109
4110/*!
4111 Returns the value of the object's \a name property.
4112
4113 If no such property exists, the returned variant is invalid.
4114
4115 Information about all available properties is provided through the
4116 metaObject() and dynamicPropertyNames().
4117
4118 \sa setProperty(), QVariant::isValid(), metaObject(), dynamicPropertyNames()
4119*/
4120QVariant QObject::property(const char *name) const
4121{
4122 Q_D(const QObject);
4123 const QMetaObject* meta = metaObject();
4124 if (!name || !meta)
4125 return QVariant();
4126
4127 int id = meta->indexOfProperty(name);
4128 if (id < 0) {
4129 if (!d->extraData)
4130 return QVariant();
4131 const int i = d->extraData->propertyNames.indexOf(t: name);
4132 return d->extraData->propertyValues.value(i);
4133 }
4134 QMetaProperty p = meta->property(index: id);
4135#ifndef QT_NO_DEBUG
4136 if (!p.isReadable())
4137 qWarning(msg: "%s::property: Property \"%s\" invalid or does not exist",
4138 metaObject()->className(), name);
4139#endif
4140 return p.read(obj: this);
4141}
4142
4143/*!
4144 \since 4.2
4145
4146 Returns the names of all properties that were dynamically added to
4147 the object using setProperty().
4148*/
4149QList<QByteArray> QObject::dynamicPropertyNames() const
4150{
4151