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