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