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