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