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