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