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