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 Q_D(const QObject);
4152 if (d->extraData)
4153 return d->extraData->propertyNames;
4154 return QList<QByteArray>();
4155}
4156
4157#endif // QT_NO_PROPERTIES
4158
4159
4160/*****************************************************************************
4161 QObject debugging output routines.
4162 *****************************************************************************/
4163
4164static void dumpRecursive(int level, const QObject *object)
4165{
4166 if (object) {
4167 QByteArray buf;
4168 buf.fill(c: ' ', size: level / 2 * 8);
4169 if (level % 2)
4170 buf += " ";
4171 QString name = object->objectName();
4172 QString flags = QLatin1String("");
4173#if 0
4174 if (qApp->focusWidget() == object)
4175 flags += 'F';
4176 if (object->isWidgetType()) {
4177 QWidget * w = (QWidget *)object;
4178 if (w->isVisible()) {
4179 QString t("<%1,%2,%3,%4>");
4180 flags += t.arg(w->x()).arg(w->y()).arg(w->width()).arg(w->height());
4181 } else {
4182 flags += 'I';
4183 }
4184 }
4185#endif
4186 qDebug(msg: "%s%s::%s %s", (const char*)buf, object->metaObject()->className(), name.toLocal8Bit().data(),
4187 flags.toLatin1().data());
4188 QObjectList children = object->children();
4189 if (!children.isEmpty()) {
4190 for (int i = 0; i < children.size(); ++i)
4191 dumpRecursive(level: level+1, object: children.at(i));
4192 }
4193 }
4194}
4195
4196#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4197/*!
4198 \overload
4199 \obsolete
4200
4201 Dumps a tree of children to the debug output.
4202
4203 \sa dumpObjectInfo()
4204*/
4205
4206void QObject::dumpObjectTree()
4207{
4208 const_cast<const QObject *>(this)->dumpObjectTree();
4209}
4210#endif
4211
4212/*!
4213 Dumps a tree of children to the debug output.
4214
4215 \note Before Qt 5.9, this function was not const.
4216
4217 \sa dumpObjectInfo()
4218*/
4219
4220void QObject::dumpObjectTree() const
4221{
4222 dumpRecursive(level: 0, object: this);
4223}
4224
4225#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4226/*!
4227 \overload
4228 \obsolete
4229
4230 Dumps information about signal connections, etc. for this object
4231 to the debug output.
4232
4233 \sa dumpObjectTree()
4234*/
4235
4236void QObject::dumpObjectInfo()
4237{
4238 const_cast<const QObject *>(this)->dumpObjectInfo();
4239}
4240#endif
4241
4242/*!
4243 Dumps information about signal connections, etc. for this object
4244 to the debug output.
4245
4246 \note Before Qt 5.9, this function was not const.
4247
4248 \sa dumpObjectTree()
4249*/
4250
4251void QObject::dumpObjectInfo() const
4252{
4253 qDebug(msg: "OBJECT %s::%s", metaObject()->className(),
4254 objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
4255
4256 Q_D(const QObject);
4257 QBasicMutexLocker locker(signalSlotLock(o: this));
4258
4259 // first, look for connections where this object is the sender
4260 qDebug(msg: " SIGNALS OUT");
4261
4262 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
4263 if (cd && cd->signalVectorCount() > 0) {
4264 QObjectPrivate::SignalVector *signalVector = cd->signalVector.loadRelaxed();
4265 for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) {
4266 const QObjectPrivate::Connection *c = signalVector->at(i: signal_index).first.loadRelaxed();
4267 if (!c)
4268 continue;
4269 const QMetaMethod signal = QMetaObjectPrivate::signal(m: metaObject(), signal_index);
4270 qDebug(msg: " signal: %s", signal.methodSignature().constData());
4271
4272 // receivers
4273 while (c) {
4274 if (!c->receiver.loadRelaxed()) {
4275 qDebug(msg: " <Disconnected receiver>");
4276 c = c->nextConnectionList.loadRelaxed();
4277 continue;
4278 }
4279 if (c->isSlotObject) {
4280 qDebug(msg: " <functor or function pointer>");
4281 c = c->nextConnectionList.loadRelaxed();
4282 continue;
4283 }
4284 const QMetaObject *receiverMetaObject = c->receiver.loadRelaxed()->metaObject();
4285 const QMetaMethod method = receiverMetaObject->method(index: c->method());
4286 qDebug(msg: " --> %s::%s %s",
4287 receiverMetaObject->className(),
4288 c->receiver.loadRelaxed()->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver.loadRelaxed()->objectName()),
4289 method.methodSignature().constData());
4290 c = c->nextConnectionList.loadRelaxed();
4291 }
4292 }
4293 } else {
4294 qDebug( msg: " <None>" );
4295 }
4296
4297 // now look for connections where this object is the receiver
4298 qDebug(msg: " SIGNALS IN");
4299
4300 if (cd && cd->senders) {
4301 for (QObjectPrivate::Connection *s = cd->senders; s; s = s->next) {
4302 QByteArray slotName = QByteArrayLiteral("<unknown>");
4303 if (!s->isSlotObject) {
4304 const QMetaMethod slot = metaObject()->method(index: s->method());
4305 slotName = slot.methodSignature();
4306 }
4307 qDebug(msg: " <-- %s::%s %s",
4308 s->sender->metaObject()->className(),
4309 s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
4310 slotName.constData());
4311 }
4312 } else {
4313 qDebug(msg: " <None>");
4314 }
4315}
4316
4317#ifndef QT_NO_USERDATA
4318static QBasicAtomicInteger<uint> user_data_registration = Q_BASIC_ATOMIC_INITIALIZER(0);
4319
4320/*!
4321 \internal
4322 */
4323uint QObject::registerUserData()
4324{
4325 return user_data_registration.fetchAndAddRelaxed(valueToAdd: 1);
4326}
4327
4328/*!
4329 \fn QObjectUserData::QObjectUserData()
4330 \internal
4331 */
4332
4333/*!
4334 \internal
4335 */
4336QObjectUserData::~QObjectUserData()
4337{
4338}
4339
4340/*!
4341 \internal
4342 */
4343void QObject::setUserData(uint id, QObjectUserData* data)
4344{
4345 Q_D(QObject);
4346 if (!d->extraData)
4347 d->extraData = new QObjectPrivate::ExtraData;
4348
4349 if (d->extraData->userData.size() <= (int) id)
4350 d->extraData->userData.resize(asize: (int) id + 1);
4351 d->extraData->userData[id] = data;
4352}
4353
4354/*!
4355 \internal
4356 */
4357QObjectUserData* QObject::userData(uint id) const
4358{
4359 Q_D(const QObject);
4360 if (!d->extraData)
4361 return nullptr;
4362 if ((int)id < d->extraData->userData.size())
4363 return d->extraData->userData.at(i: id);
4364 return nullptr;
4365}
4366
4367#endif // QT_NO_USERDATA
4368
4369
4370#ifndef QT_NO_DEBUG_STREAM
4371QDebug operator<<(QDebug dbg, const QObject *o)
4372{
4373 QDebugStateSaver saver(dbg);
4374 if (!o)
4375 return dbg << "QObject(0x0)";
4376 dbg.nospace() << o->metaObject()->className() << '(' << (const void *)o;
4377 if (!o->objectName().isEmpty())
4378 dbg << ", name = " << o->objectName();
4379 dbg << ')';
4380 return dbg;
4381}
4382#endif
4383
4384/*!
4385 \macro Q_CLASSINFO(Name, Value)
4386 \relates QObject
4387
4388 This macro associates extra information to the class, which is available
4389 using QObject::metaObject(). Qt makes only limited use of this feature, in
4390 the \l{Active Qt}, \l{Qt D-Bus} and \l{Qt QML module}{Qt QML}.
4391
4392 The extra information takes the form of a \a Name string and a \a Value
4393 literal string.
4394
4395 Example:
4396
4397 \snippet code/src_corelib_kernel_qobject.cpp 35
4398
4399 \sa QMetaObject::classInfo()
4400 \sa QAxFactory
4401 \sa {Using Qt D-Bus Adaptors}
4402 \sa {Extending QML}
4403*/
4404
4405/*!
4406 \macro Q_INTERFACES(...)
4407 \relates QObject
4408
4409 This macro tells Qt which interfaces the class implements. This
4410 is used when implementing plugins.
4411
4412 Example:
4413
4414 \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 1
4415 \dots
4416 \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 3
4417
4418 See the \l{tools/plugandpaint/plugins/basictools}{Plug & Paint
4419 Basic Tools} example for details.
4420
4421 \sa Q_DECLARE_INTERFACE(), Q_PLUGIN_METADATA(), {How to Create Qt Plugins}
4422*/
4423
4424/*!
4425 \macro Q_PROPERTY(...)
4426 \relates QObject
4427
4428 This macro is used for declaring properties in classes that
4429 inherit QObject. Properties behave like class data members, but
4430 they have additional features accessible through the \l
4431 {Meta-Object System}.
4432
4433 \snippet code/doc_src_properties.cpp 0
4434
4435 The property name and type and the \c READ function are required.
4436 The type can be any type supported by QVariant, or it can be a
4437 user-defined type. The other items are optional, but a \c WRITE
4438 function is common. The attributes default to true except \c USER,
4439 which defaults to false.
4440
4441 For example:
4442
4443 \snippet code/src_corelib_kernel_qobject.cpp 37
4444
4445 For more details about how to use this macro, and a more detailed
4446 example of its use, see the discussion on \l {Qt's Property System}.
4447
4448 \sa {Qt's Property System}
4449*/
4450
4451/*!
4452 \macro Q_ENUMS(...)
4453 \relates QObject
4454 \obsolete
4455
4456 In new code, you should prefer the use of the Q_ENUM() macro, which makes the
4457 type available also to the meta type system.
4458 For instance, QMetaEnum::fromType() will not work with types declared with Q_ENUMS().
4459
4460 This macro registers one or several enum types to the meta-object
4461 system.
4462
4463 If you want to register an enum that is declared in another class,
4464 the enum must be fully qualified with the name of the class
4465 defining it. In addition, the class \e defining the enum has to
4466 inherit QObject as well as declare the enum using Q_ENUMS().
4467
4468 \sa {Qt's Property System}
4469*/
4470
4471/*!
4472 \macro Q_FLAGS(...)
4473 \relates QObject
4474 \obsolete
4475
4476 This macro registers one or several \l{QFlags}{flags types} with the
4477 meta-object system. It is typically used in a class definition to declare
4478 that values of a given enum can be used as flags and combined using the
4479 bitwise OR operator.
4480
4481 \note This macro takes care of registering individual flag values
4482 with the meta-object system, so it is unnecessary to use Q_ENUMS()
4483 in addition to this macro.
4484
4485 In new code, you should prefer the use of the Q_FLAG() macro, which makes the
4486 type available also to the meta type system.
4487
4488 \sa {Qt's Property System}
4489*/
4490
4491/*!
4492 \macro Q_ENUM(...)
4493 \relates QObject
4494 \since 5.5
4495
4496 This macro registers an enum type with the meta-object system.
4497 It must be placed after the enum declaration in a class that has the Q_OBJECT or the
4498 Q_GADGET macro. For namespaces use \l Q_ENUM_NS() instead.
4499
4500 For example:
4501
4502 \snippet code/src_corelib_kernel_qobject.cpp 38
4503
4504 Enumerations that are declared with Q_ENUM have their QMetaEnum registered in the
4505 enclosing QMetaObject. You can also use QMetaEnum::fromType() to get the QMetaEnum.
4506
4507 Registered enumerations are automatically registered also to the Qt meta
4508 type system, making them known to QMetaType without the need to use
4509 Q_DECLARE_METATYPE(). This will enable useful features; for example, if used
4510 in a QVariant, you can convert them to strings. Likewise, passing them to
4511 QDebug will print out their names.
4512
4513 Mind that the enum values are stored as signed \c int in the meta object system.
4514 Registering enumerations with values outside the range of values valid for \c int
4515 will lead to overflows and potentially undefined behavior when accessing them through
4516 the meta object system. QML, for example, does access registered enumerations through
4517 the meta object system.
4518
4519 \sa {Qt's Property System}
4520*/
4521
4522
4523/*!
4524 \macro Q_FLAG(...)
4525 \relates QObject
4526 \since 5.5
4527
4528 This macro registers a single \l{QFlags}{flags type} with the
4529 meta-object system. It is typically used in a class definition to declare
4530 that values of a given enum can be used as flags and combined using the
4531 bitwise OR operator. For namespaces use \l Q_FLAG_NS() instead.
4532
4533 The macro must be placed after the enum declaration. The declaration of
4534 the flags type is done using the \l Q_DECLARE_FLAGS() macro.
4535
4536 For example, in QItemSelectionModel, the
4537 \l{QItemSelectionModel::SelectionFlags}{SelectionFlags} flag is
4538 declared in the following way:
4539
4540 \snippet code/src_corelib_kernel_qobject.cpp 39
4541
4542 \note The Q_FLAG macro takes care of registering individual flag values
4543 with the meta-object system, so it is unnecessary to use Q_ENUM()
4544 in addition to this macro.
4545
4546 \sa {Qt's Property System}
4547*/
4548
4549/*!
4550 \macro Q_ENUM_NS(...)
4551 \relates QObject
4552 \since 5.8
4553
4554 This macro registers an enum type with the meta-object system.
4555 It must be placed after the enum declaration in a namespace that
4556 has the Q_NAMESPACE macro. It is the same as \l Q_ENUM but in a
4557 namespace.
4558
4559 Enumerations that are declared with Q_ENUM_NS have their QMetaEnum
4560 registered in the enclosing QMetaObject. You can also use
4561 QMetaEnum::fromType() to get the QMetaEnum.
4562
4563 Registered enumerations are automatically registered also to the Qt meta
4564 type system, making them known to QMetaType without the need to use
4565 Q_DECLARE_METATYPE(). This will enable useful features; for example, if
4566 used in a QVariant, you can convert them to strings. Likewise, passing them
4567 to QDebug will print out their names.
4568
4569 Mind that the enum values are stored as signed \c int in the meta object system.
4570 Registering enumerations with values outside the range of values valid for \c int
4571 will lead to overflows and potentially undefined behavior when accessing them through
4572 the meta object system. QML, for example, does access registered enumerations through
4573 the meta object system.
4574
4575 \sa {Qt's Property System}
4576*/
4577
4578
4579/*!
4580 \macro Q_FLAG_NS(...)
4581 \relates QObject
4582 \since 5.8
4583
4584 This macro registers a single \l{QFlags}{flags type} with the
4585 meta-object system. It is used in a namespace that has the
4586 Q_NAMESPACE macro, to declare that values of a given enum can be
4587 used as flags and combined using the bitwise OR operator.
4588 It is the same as \l Q_FLAG but in a namespace.
4589
4590 The macro must be placed after the enum declaration.
4591
4592 \note The Q_FLAG_NS macro takes care of registering individual flag
4593 values with the meta-object system, so it is unnecessary to use
4594 Q_ENUM_NS() in addition to this macro.
4595
4596 \sa {Qt's Property System}
4597*/
4598
4599
4600/*!
4601 \macro Q_OBJECT
4602 \relates QObject
4603
4604 The Q_OBJECT macro must appear in the private section of a class
4605 definition that declares its own signals and slots or that uses
4606 other services provided by Qt's meta-object system.
4607
4608 For example:
4609
4610 \snippet signalsandslots/signalsandslots.h 1
4611 \codeline
4612 \snippet signalsandslots/signalsandslots.h 2
4613 \snippet signalsandslots/signalsandslots.h 3
4614
4615 \note This macro requires the class to be a subclass of QObject. Use
4616 Q_GADGET instead of Q_OBJECT to enable the meta object system's support
4617 for enums in a class that is not a QObject subclass.
4618
4619 \sa {Meta-Object System}, {Signals and Slots}, {Qt's Property System}
4620*/
4621
4622/*!
4623 \macro Q_GADGET
4624 \relates QObject
4625
4626 The Q_GADGET macro is a lighter version of the Q_OBJECT macro for classes
4627 that do not inherit from QObject but still want to use some of the
4628 reflection capabilities offered by QMetaObject. Just like the Q_OBJECT
4629 macro, it must appear in the private section of a class definition.
4630
4631 Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have
4632 signals or slots.
4633
4634 Q_GADGET makes a class member, \c{staticMetaObject}, available.
4635 \c{staticMetaObject} is of type QMetaObject and provides access to the
4636 enums declared with Q_ENUMS.
4637*/
4638
4639/*!
4640 \macro Q_NAMESPACE
4641 \relates QObject
4642 \since 5.8
4643
4644 The Q_NAMESPACE macro can be used to add QMetaObject capabilities
4645 to a namespace.
4646
4647 Q_NAMESPACEs can have Q_CLASSINFO, Q_ENUM_NS, Q_FLAG_NS, but they
4648 cannot have Q_ENUM, Q_FLAG, Q_PROPERTY, Q_INVOKABLE, signals nor slots.
4649
4650 Q_NAMESPACE makes an external variable, \c{staticMetaObject}, available.
4651 \c{staticMetaObject} is of type QMetaObject and provides access to the
4652 enums declared with Q_ENUM_NS/Q_FLAG_NS.
4653
4654 For example:
4655
4656 \code
4657 namespace test {
4658 Q_NAMESPACE
4659 ...
4660 \endcode
4661
4662 \sa Q_NAMESPACE_EXPORT
4663*/
4664
4665/*!
4666 \macro Q_NAMESPACE_EXPORT(EXPORT_MACRO)
4667 \relates QObject
4668 \since 5.14
4669
4670 The Q_NAMESPACE_EXPORT macro can be used to add QMetaObject capabilities
4671 to a namespace.
4672
4673 It works exactly like the Q_NAMESPACE macro. However, the external
4674 \c{staticMetaObject} variable that gets defined in the namespace
4675 is declared with the supplied \a EXPORT_MACRO qualifier. This is
4676 useful if the object needs to be exported from a dynamic library.
4677
4678 For example:
4679
4680 \code
4681 namespace test {
4682 Q_NAMESPACE_EXPORT(EXPORT_MACRO)
4683 ...
4684 \endcode
4685
4686 \sa Q_NAMESPACE, {Creating Shared Libraries}
4687*/
4688
4689/*!
4690 \macro Q_SIGNALS
4691 \relates QObject
4692
4693 Use this macro to replace the \c signals keyword in class
4694 declarations, when you want to use Qt Signals and Slots with a
4695 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4696
4697 The macro is normally used when \c no_keywords is specified with
4698 the \c CONFIG variable in the \c .pro file, but it can be used
4699 even when \c no_keywords is \e not specified.
4700*/
4701
4702/*!
4703 \macro Q_SIGNAL
4704 \relates QObject
4705
4706 This is an additional macro that allows you to mark a single
4707 function as a signal. It can be quite useful, especially when you
4708 use a 3rd-party source code parser which doesn't understand a \c
4709 signals or \c Q_SIGNALS groups.
4710
4711 Use this macro to replace the \c signals keyword in class
4712 declarations, when you want to use Qt Signals and Slots with a
4713 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4714
4715 The macro is normally used when \c no_keywords is specified with
4716 the \c CONFIG variable in the \c .pro file, but it can be used
4717 even when \c no_keywords is \e not specified.
4718*/
4719
4720/*!
4721 \macro Q_SLOTS
4722 \relates QObject
4723
4724 Use this macro to replace the \c slots keyword in class
4725 declarations, when you want to use Qt Signals and Slots with a
4726 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4727
4728 The macro is normally used when \c no_keywords is specified with
4729 the \c CONFIG variable in the \c .pro file, but it can be used
4730 even when \c no_keywords is \e not specified.
4731*/
4732
4733/*!
4734 \macro Q_SLOT
4735 \relates QObject
4736
4737 This is an additional macro that allows you to mark a single
4738 function as a slot. It can be quite useful, especially when you
4739 use a 3rd-party source code parser which doesn't understand a \c
4740 slots or \c Q_SLOTS groups.
4741
4742 Use this macro to replace the \c slots keyword in class
4743 declarations, when you want to use Qt Signals and Slots with a
4744 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4745
4746 The macro is normally used when \c no_keywords is specified with
4747 the \c CONFIG variable in the \c .pro file, but it can be used
4748 even when \c no_keywords is \e not specified.
4749*/
4750
4751/*!
4752 \macro Q_EMIT
4753 \relates QObject
4754
4755 Use this macro to replace the \c emit keyword for emitting
4756 signals, when you want to use Qt Signals and Slots with a
4757 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4758
4759 The macro is normally used when \c no_keywords is specified with
4760 the \c CONFIG variable in the \c .pro file, but it can be used
4761 even when \c no_keywords is \e not specified.
4762*/
4763
4764/*!
4765 \macro Q_INVOKABLE
4766 \relates QObject
4767
4768 Apply this macro to declarations of member functions to allow them to
4769 be invoked via the meta-object system. The macro is written before
4770 the return type, as shown in the following example:
4771
4772 \snippet qmetaobject-invokable/window.h Window class with invokable method
4773
4774 The \c invokableMethod() function is marked up using Q_INVOKABLE, causing
4775 it to be registered with the meta-object system and enabling it to be
4776 invoked using QMetaObject::invokeMethod().
4777 Since \c normalMethod() function is not registered in this way, it cannot
4778 be invoked using QMetaObject::invokeMethod().
4779
4780 If an invokable member function returns a pointer to a QObject or a
4781 subclass of QObject and it is invoked from QML, special ownership rules
4782 apply. See \l{qtqml-cppintegration-data.html}{Data Type Conversion Between QML and C++}
4783 for more information.
4784*/
4785
4786/*!
4787 \macro Q_REVISION
4788 \relates QObject
4789
4790 Apply this macro to declarations of member functions to tag them with a
4791 revision number in the meta-object system. The macro is written before
4792 the return type, as shown in the following example:
4793
4794 \snippet qmetaobject-revision/window.h Window class with revision
4795
4796 This is useful when using the meta-object system to dynamically expose
4797 objects to another API, as you can match the version expected by multiple
4798 versions of the other API. Consider the following simplified example:
4799
4800 \snippet qmetaobject-revision/main.cpp Window class using revision
4801
4802 Using the same Window class as the previous example, the newProperty and
4803 newMethod would only be exposed in this code when the expected version is
4804 1 or greater.
4805
4806 Since all methods are considered to be in revision 0 if untagged, a tag
4807 of Q_REVISION(0) is invalid and ignored.
4808
4809 This tag is not used by the meta-object system itself. Currently this is only
4810 used by the QtQml module.
4811
4812 For a more generic string tag, see \l QMetaMethod::tag()
4813
4814 \sa QMetaMethod::revision()
4815*/
4816
4817/*!
4818 \macro Q_SET_OBJECT_NAME(Object)
4819 \relates QObject
4820 \since 5.0
4821
4822 This macro assigns \a Object the objectName "Object".
4823
4824 It doesn't matter whether \a Object is a pointer or not, the
4825 macro figures that out by itself.
4826
4827 \sa QObject::objectName()
4828*/
4829
4830/*!
4831 \macro QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
4832 \relates QObject
4833 \since 5.8
4834
4835 Defining this macro will disable narrowing and floating-point-to-integral
4836 conversions between the arguments carried by a signal and the arguments
4837 accepted by a slot, when the signal and the slot are connected using the
4838 PMF-based syntax.
4839
4840 \sa QObject::connect
4841*/
4842
4843/*!
4844 \typedef QObjectList
4845 \relates QObject
4846
4847 Synonym for QList<QObject *>.
4848*/
4849
4850void qDeleteInEventHandler(QObject *o)
4851{
4852 delete o;
4853}
4854
4855/*!
4856 \fn template<typename PointerToMemberFunction> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type)
4857 \overload connect()
4858 \threadsafe
4859
4860 Creates a connection of the given \a type from the \a signal in
4861 the \a sender object to the \a method in the \a receiver object.
4862 Returns a handle to the connection that can be used to disconnect
4863 it later.
4864
4865 The signal must be a function declared as a signal in the header.
4866 The slot function can be any member function that can be connected
4867 to the signal.
4868 A slot can be connected to a given signal if the signal has at
4869 least as many arguments as the slot, and there is an implicit
4870 conversion between the types of the corresponding arguments in the
4871 signal and the slot.
4872
4873 Example:
4874
4875 \snippet code/src_corelib_kernel_qobject.cpp 44
4876
4877 This example ensures that the label always displays the current
4878 line edit text.
4879
4880 A signal can be connected to many slots and signals. Many signals
4881 can be connected to one slot.
4882
4883 If a signal is connected to several slots, the slots are activated
4884 in the same order as the order the connection was made, when the
4885 signal is emitted
4886
4887 The function returns an handle to a connection if it successfully
4888 connects the signal to the slot. The Connection handle will be invalid
4889 if it cannot create the connection, for example, if QObject is unable
4890 to verify the existence of \a signal (if it was not declared as a signal)
4891 You can check if the QMetaObject::Connection is valid by casting it to a bool.
4892
4893 By default, a signal is emitted for every connection you make;
4894 two signals are emitted for duplicate connections. You can break
4895 all of these connections with a single disconnect() call.
4896 If you pass the Qt::UniqueConnection \a type, the connection will only
4897 be made if it is not a duplicate. If there is already a duplicate
4898 (exact same signal to the exact same slot on the same objects),
4899 the connection will fail and connect will return an invalid QMetaObject::Connection.
4900
4901 The optional \a type parameter describes the type of connection
4902 to establish. In particular, it determines whether a particular
4903 signal is delivered to a slot immediately or queued for delivery
4904 at a later time. If the signal is queued, the parameters must be
4905 of types that are known to Qt's meta-object system, because Qt
4906 needs to copy the arguments to store them in an event behind the
4907 scenes. If you try to use a queued connection and get the error
4908 message
4909
4910 \snippet code/src_corelib_kernel_qobject.cpp 25
4911
4912 make sure to declare the argument type with Q_DECLARE_METATYPE
4913
4914 Overloaded functions can be resolved with help of \l qOverload.
4915
4916 \sa {Differences between String-Based and Functor-Based Connections}
4917 */
4918
4919/*!
4920 \fn template<typename PointerToMemberFunction, typename Functor> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
4921
4922 \threadsafe
4923 \overload connect()
4924
4925 Creates a connection from \a signal in
4926 \a sender object to \a functor, and returns a handle to the connection
4927
4928 The signal must be a function declared as a signal in the header.
4929 The slot function can be any function or functor that can be connected
4930 to the signal.
4931 A function can be connected to a given signal if the signal has at
4932 least as many argument as the slot. A functor can be connected to a signal
4933 if they have exactly the same number of arguments. There must exist implicit
4934 conversion between the types of the corresponding arguments in the
4935 signal and the slot.
4936
4937 Example:
4938
4939 \snippet code/src_corelib_kernel_qobject.cpp 45
4940
4941 Lambda expressions can also be used:
4942
4943 \snippet code/src_corelib_kernel_qobject.cpp 46
4944
4945 The connection will automatically disconnect if the sender is destroyed.
4946 However, you should take care that any objects used within the functor
4947 are still alive when the signal is emitted.
4948
4949 Overloaded functions can be resolved with help of \l qOverload.
4950
4951 */
4952
4953/*!
4954 \fn template<typename PointerToMemberFunction, typename Functor> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type)
4955
4956 \threadsafe
4957 \overload connect()
4958
4959 \since 5.2
4960
4961 Creates a connection of a given \a type from \a signal in
4962 \a sender object to \a functor to be placed in a specific event
4963 loop of \a context, and returns a handle to the connection.
4964
4965 \note Qt::UniqueConnections do not work for lambdas, non-member functions
4966 and functors; they only apply to connecting to member functions.
4967
4968 The signal must be a function declared as a signal in the header.
4969 The slot function can be any function or functor that can be connected
4970 to the signal.
4971 A function can be connected to a given signal if the signal has at
4972 least as many argument as the slot. A functor can be connected to a signal
4973 if they have exactly the same number of arguments. There must exist implicit
4974 conversion between the types of the corresponding arguments in the
4975 signal and the slot.
4976
4977 Example:
4978
4979 \snippet code/src_corelib_kernel_qobject.cpp 50
4980
4981 Lambda expressions can also be used:
4982
4983 \snippet code/src_corelib_kernel_qobject.cpp 51
4984
4985 The connection will automatically disconnect if the sender or the context
4986 is destroyed.
4987 However, you should take care that any objects used within the functor
4988 are still alive when the signal is emitted.
4989
4990 Overloaded functions can be resolved with help of \l qOverload.
4991 */
4992
4993/*!
4994 \internal
4995
4996 Implementation of the template version of connect
4997
4998 \a sender is the sender object
4999 \a signal is a pointer to a pointer to a member signal of the sender
5000 \a receiver is the receiver object, may not be \nullptr, will be equal to sender when
5001 connecting to a static function or a functor
5002 \a slot a pointer only used when using Qt::UniqueConnection
5003 \a type the Qt::ConnectionType passed as argument to connect
5004 \a types an array of integer with the metatype id of the parameter of the signal
5005 to be used with queued connection
5006 must stay valid at least for the whole time of the connection, this function
5007 do not take ownership. typically static data.
5008 If \nullptr, then the types will be computed when the signal is emit in a queued
5009 connection from the types from the signature.
5010 \a senderMetaObject is the metaobject used to lookup the signal, the signal must be in
5011 this metaobject
5012 */
5013QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
5014 const QObject *receiver, void **slot,
5015 QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
5016 const int *types, const QMetaObject *senderMetaObject)
5017{
5018 if (!signal) {
5019 qWarning(msg: "QObject::connect: invalid nullptr parameter");
5020 if (slotObj)
5021 slotObj->destroyIfLastRef();
5022 return QMetaObject::Connection();
5023 }
5024
5025 int signal_index = -1;
5026 void *args[] = { &signal_index, signal };
5027 for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
5028 senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
5029 if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(metaobject: senderMetaObject)->signalCount)
5030 break;
5031 }
5032 if (!senderMetaObject) {
5033 qWarning(msg: "QObject::connect: signal not found in %s", sender->metaObject()->className());
5034 slotObj->destroyIfLastRef();
5035 return QMetaObject::Connection(nullptr);
5036 }
5037 signal_index += QMetaObjectPrivate::signalOffset(m: senderMetaObject);
5038 return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
5039}
5040
5041/*!
5042 \internal
5043
5044 Internal version of connect used by the template version of QObject::connect (called via connectImpl) and
5045 also used by the QObjectPrivate::connect version used by QML. The signal_index is expected to be relative
5046 to the number of signals.
5047 */
5048QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int signal_index,
5049 const QObject *receiver, void **slot,
5050 QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
5051 const int *types, const QMetaObject *senderMetaObject)
5052{
5053 if (!sender || !receiver || !slotObj || !senderMetaObject) {
5054 const char *senderString = sender ? sender->metaObject()->className()
5055 : senderMetaObject ? senderMetaObject->className()
5056 : "Unknown";
5057 const char *receiverString = receiver ? receiver->metaObject()->className()
5058 : "Unknown";
5059 qWarning(msg: "QObject::connect(%s, %s): invalid nullptr parameter", senderString, receiverString);
5060 if (slotObj)
5061 slotObj->destroyIfLastRef();
5062 return QMetaObject::Connection();
5063 }
5064
5065 QObject *s = const_cast<QObject *>(sender);
5066 QObject *r = const_cast<QObject *>(receiver);
5067
5068 QOrderedMutexLocker locker(signalSlotLock(o: sender),
5069 signalSlotLock(o: receiver));
5070
5071 if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(o: s)->connections.loadRelaxed()) {
5072 QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(o: s)->connections.loadRelaxed();
5073 if (connections->signalVectorCount() > signal_index) {
5074 const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(i: signal_index).first.loadRelaxed();
5075
5076 while (c2) {
5077 if (c2->receiver.loadRelaxed() == receiver && c2->isSlotObject && c2->slotObj->compare(a: slot)) {
5078 slotObj->destroyIfLastRef();
5079 return QMetaObject::Connection();
5080 }
5081 c2 = c2->nextConnectionList.loadRelaxed();
5082 }
5083 }
5084 type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
5085 }
5086
5087 std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
5088 c->sender = s;
5089 c->signal_index = signal_index;
5090 QThreadData *td = r->d_func()->threadData;
5091 td->ref();
5092 c->receiverThreadData.storeRelaxed(newValue: td);
5093 c->receiver.storeRelaxed(newValue: r);
5094 c->slotObj = slotObj;
5095 c->connectionType = type;
5096 c->isSlotObject = true;
5097 if (types) {
5098 c->argumentTypes.storeRelaxed(newValue: types);
5099 c->ownArgumentTypes = false;
5100 }
5101
5102 QObjectPrivate::get(o: s)->addConnection(signal: signal_index, c: c.get());
5103 QMetaObject::Connection ret(c.release());
5104 locker.unlock();
5105
5106 QMetaMethod method = QMetaObjectPrivate::signal(m: senderMetaObject, signal_index);
5107 Q_ASSERT(method.isValid());
5108 s->connectNotify(signal: method);
5109
5110 return ret;
5111}
5112
5113/*!
5114 Disconnect a connection.
5115
5116 If the \a connection is invalid or has already been disconnected, do nothing
5117 and return false.
5118
5119 \sa connect()
5120 */
5121bool QObject::disconnect(const QMetaObject::Connection &connection)
5122{
5123 QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr);
5124
5125 if (!c)
5126 return false;
5127 QObject *receiver = c->receiver.loadRelaxed();
5128 if (!receiver)
5129 return false;
5130
5131 QBasicMutex *senderMutex = signalSlotLock(o: c->sender);
5132 QBasicMutex *receiverMutex = signalSlotLock(o: receiver);
5133
5134 QObjectPrivate::ConnectionData *connections;
5135 {
5136 QOrderedMutexLocker locker(senderMutex, receiverMutex);
5137
5138 // load receiver once again and recheck to ensure nobody else has removed the connection in the meantime
5139 receiver = c->receiver.loadRelaxed();
5140 if (!receiver)
5141 return false;
5142
5143 connections = QObjectPrivate::get(o: c->sender)->connections.loadRelaxed();
5144 Q_ASSERT(connections);
5145 connections->removeConnection(c);
5146
5147 c->sender->disconnectNotify(signal: QMetaObjectPrivate::signal(m: c->sender->metaObject(), signal_index: c->signal_index));
5148 // We must not hold the receiver mutex, else we risk dead-locking; we also only need the sender mutex
5149 // It is however vital to hold the senderMutex before calling cleanOrphanedConnections, as otherwise
5150 // another thread might modify/delete the connection
5151 if (receiverMutex != senderMutex) {
5152 receiverMutex->unlock();
5153 }
5154 connections->cleanOrphanedConnections(sender: c->sender, lockPolicy: QObjectPrivate::ConnectionData::AlreadyLockedAndTemporarilyReleasingLock);
5155 senderMutex->unlock(); // now both sender and receiver mutex have been manually unlocked
5156 locker.dismiss(); // so we dismiss the QOrderedMutexLocker
5157 }
5158
5159 const_cast<QMetaObject::Connection &>(connection).d_ptr = nullptr;
5160 c->deref(); // has been removed from the QMetaObject::Connection object
5161
5162 return true;
5163}
5164
5165/*! \fn template<typename PointerToMemberFunction> bool QObject::disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)
5166 \overload disconnect()
5167 \threadsafe
5168
5169 Disconnects \a signal in object \a sender from \a method in object
5170 \a receiver. Returns \c true if the connection is successfully broken;
5171 otherwise returns \c false.
5172
5173 A signal-slot connection is removed when either of the objects
5174 involved are destroyed.
5175
5176 disconnect() is typically used in three ways, as the following
5177 examples demonstrate.
5178 \list 1
5179 \li Disconnect everything connected to an object's signals:
5180
5181 \snippet code/src_corelib_kernel_qobject.cpp 26
5182
5183 \li Disconnect everything connected to a specific signal:
5184
5185 \snippet code/src_corelib_kernel_qobject.cpp 47
5186
5187 \li Disconnect a specific receiver:
5188
5189 \snippet code/src_corelib_kernel_qobject.cpp 30
5190
5191 \li Disconnect a connection from one specific signal to a specific slot:
5192
5193 \snippet code/src_corelib_kernel_qobject.cpp 48
5194
5195
5196 \endlist
5197
5198 \nullptr may be used as a wildcard, meaning "any signal", "any receiving
5199 object", or "any slot in the receiving object", respectively.
5200
5201 The \a sender may never be \nullptr. (You cannot disconnect signals
5202 from more than one object in a single call.)
5203
5204 If \a signal is \nullptr, it disconnects \a receiver and \a method from
5205 any signal. If not, only the specified signal is disconnected.
5206
5207 If \a receiver is \nullptr, it disconnects anything connected to \a
5208 signal. If not, slots in objects other than \a receiver are not
5209 disconnected.
5210
5211 If \a method is \nullptr, it disconnects anything that is connected to \a
5212 receiver. If not, only slots named \a method will be disconnected,
5213 and all other slots are left alone. The \a method must be \nullptr
5214 if \a receiver is left out, so you cannot disconnect a
5215 specifically-named slot on all objects.
5216
5217 \note It is not possible to use this overload to disconnect signals
5218 connected to functors or lambda expressions. That is because it is not
5219 possible to compare them. Instead, use the overload that takes a
5220 QMetaObject::Connection
5221
5222 \sa connect()
5223*/
5224
5225bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, const QMetaObject *senderMetaObject)
5226{
5227 if (sender == nullptr || (receiver == nullptr && slot != nullptr)) {
5228 qWarning(msg: "QObject::disconnect: Unexpected nullptr parameter");
5229 return false;
5230 }
5231
5232 int signal_index = -1;
5233 if (signal) {
5234 void *args[] = { &signal_index, signal };
5235 for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
5236 senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
5237 if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(metaobject: senderMetaObject)->signalCount)
5238 break;
5239 }
5240 if (!senderMetaObject) {
5241 qWarning(msg: "QObject::disconnect: signal not found in %s", sender->metaObject()->className());
5242 return false;
5243 }
5244 signal_index += QMetaObjectPrivate::signalOffset(m: senderMetaObject);
5245 }
5246
5247 return QMetaObjectPrivate::disconnect(sender, signal_index, smeta: senderMetaObject, receiver, method_index: -1, slot);
5248}
5249
5250/*!
5251 \internal
5252 Used by QML to connect a signal by index to a slot implemented in JavaScript
5253 (wrapped in a custom QSlotObjectBase subclass).
5254
5255 This version of connect assumes that sender and receiver are the same object.
5256
5257 The signal_index is an index relative to the number of methods.
5258 */
5259QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type)
5260{
5261 return QObjectPrivate::connect(sender, signal_index, receiver: sender, slotObj, type);
5262}
5263
5264/*!
5265 \internal
5266 Used by QML to connect a signal by index to a slot implemented in JavaScript
5267 (wrapped in a custom QSlotObjectBase subclass).
5268
5269 This is an overload that should be used when \a sender and \a receiver are
5270 different objects.
5271
5272 The signal_index is an index relative to the number of methods.
5273 */
5274QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index,
5275 const QObject *receiver,
5276 QtPrivate::QSlotObjectBase *slotObj,
5277 Qt::ConnectionType type)
5278{
5279 if (!sender) {
5280 qWarning(msg: "QObject::connect: invalid nullptr parameter");
5281 if (slotObj)
5282 slotObj->destroyIfLastRef();
5283 return QMetaObject::Connection();
5284 }
5285 const QMetaObject *senderMetaObject = sender->metaObject();
5286 signal_index = methodIndexToSignalIndex(base: &senderMetaObject, signal_index);
5287
5288 return QObjectPrivate::connectImpl(sender, signal_index, receiver, /*slot*/ nullptr, slotObj,
5289 type, /*types*/ nullptr, senderMetaObject);
5290}
5291
5292/*!
5293 \internal
5294 Used by QML to disconnect a signal by index that's connected to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass)
5295 In the QML case the slot is not a pointer to a pointer to the function to disconnect, but instead it is a pointer to an array of internal values
5296 required for the disconnect.
5297
5298 This version of disconnect assumes that sender and receiver are the same object.
5299 */
5300bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void **slot)
5301{
5302 return QObjectPrivate::disconnect(sender, signal_index, receiver: sender, slot);
5303}
5304
5305/*!
5306 \internal
5307
5308 Used by QML to disconnect a signal by index that's connected to a slot
5309 implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass) In the
5310 QML case the slot is not a pointer to a pointer to the function to disconnect,
5311 but instead it is a pointer to an array of internal values required for the
5312 disconnect.
5313
5314 This is an overload that should be used when \a sender and \a receiver are
5315 different objects.
5316 */
5317bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, const QObject *receiver,
5318 void **slot)
5319{
5320 const QMetaObject *senderMetaObject = sender->metaObject();
5321 signal_index = methodIndexToSignalIndex(base: &senderMetaObject, signal_index);
5322
5323 return QMetaObjectPrivate::disconnect(sender, signal_index, smeta: senderMetaObject, receiver, method_index: -1,
5324 slot);
5325}
5326
5327/*! \class QMetaObject::Connection
5328 \inmodule QtCore
5329 Represents a handle to a signal-slot (or signal-functor) connection.
5330
5331 It can be used to check if the connection is valid and to disconnect it using
5332 QObject::disconnect(). For a signal-functor connection without a context object,
5333 it is the only way to selectively disconnect that connection.
5334
5335 As Connection is just a handle, the underlying signal-slot connection is unaffected
5336 when Connection is destroyed or reassigned.
5337 */
5338
5339/*!
5340 Create a copy of the handle to the \a other connection
5341 */
5342QMetaObject::Connection::Connection(const QMetaObject::Connection &other) : d_ptr(other.d_ptr)
5343{
5344 if (d_ptr)
5345 static_cast<QObjectPrivate::Connection *>(d_ptr)->ref();
5346}
5347
5348/*!
5349 Assigns \a other to this connection and returns a reference to this connection.
5350*/
5351QMetaObject::Connection& QMetaObject::Connection::operator=(const QMetaObject::Connection& other)
5352{
5353 if (other.d_ptr != d_ptr) {
5354 if (d_ptr)
5355 static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
5356 d_ptr = other.d_ptr;
5357 if (other.d_ptr)
5358 static_cast<QObjectPrivate::Connection *>(other.d_ptr)->ref();
5359 }
5360 return *this;
5361}
5362
5363/*!
5364 Creates a Connection instance.
5365*/
5366
5367QMetaObject::Connection::Connection() : d_ptr(nullptr) {}
5368
5369/*!
5370 Destructor for QMetaObject::Connection.
5371*/
5372QMetaObject::Connection::~Connection()
5373{
5374 if (d_ptr)
5375 static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
5376}
5377
5378/*! \internal Returns true if the object is still connected */
5379bool QMetaObject::Connection::isConnected_helper() const
5380{
5381 Q_ASSERT(d_ptr); // we're only called from operator RestrictedBool() const
5382 QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(d_ptr);
5383
5384 return c->receiver.loadRelaxed();
5385}
5386
5387
5388/*!
5389 \fn QMetaObject::Connection::operator bool() const
5390
5391 Returns \c true if the connection is valid.
5392
5393 The connection is valid if the call to QObject::connect succeeded.
5394 The connection is invalid if QObject::connect was not able to find
5395 the signal or the slot, or if the arguments do not match.
5396 */
5397
5398QT_END_NAMESPACE
5399
5400#include "moc_qnamespace.cpp"
5401#include "moc_qobject.cpp"
5402

source code of qtbase/src/corelib/kernel/qobject.cpp