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