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