1 /****************************************************************************
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
43 #include "qobject_p.h"
44 #include "qmetaobject_p.h"
46 #include "qabstracteventdispatcher.h"
47 #include "qcoreapplication.h"
48 #include "qcoreapplication_p.h"
50 #include "qmetaobject.h"
53 #include <private/qthread_p.h>
58 #include <qsemaphore.h>
59 #include <qsharedpointer.h>
61 #include <private/qorderedmutexlocker_p.h>
62 #include <private/qmutexpool_p.h>
71 static int DIRECT_CONNECTION_ONLY = 0;
73 static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
75 int *types = new int [typeNames.count() + 1];
77 for (int i = 0; i < typeNames.count(); ++i) {
78 const QByteArray typeName = typeNames.at(i);
79 if (typeName.endsWith('*'))
80 types[i] = QMetaType::VoidStar;
82 types[i] = QMetaType::type(typeName);
85 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
86 "(Make sure '%s' is registered using qRegisterMetaType().)",
87 typeName.constData(), typeName.constData());
92 types[typeNames.count()] = 0;
97 static QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
98 static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
101 * mutex to be locked when accessing the connectionlists or the senders list
103 static inline QMutex *signalSlotLock(const QObject *o)
105 if (!signalSlotMutexes) {
106 QMutexPool *mp = new QMutexPool;
107 if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
111 return signalSlotMutexes->get(o);
114 extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
119 extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
121 if(!objectCount.deref()) {
122 QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
127 void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
128 void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
129 void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0;
131 QObjectData::~QObjectData() {}
133 QObjectPrivate::QObjectPrivate(int version)
134 : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
136 if (version != QObjectPrivateVersion)
137 qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
138 version, QObjectPrivateVersion);
140 // QObjectData initialization
142 parent = 0; // no parent yet. It is set by setParent()
143 isWidget = false; // assume not a widget object
144 pendTimer = false; // no timers yet
145 blockSig = false; // not blocking signals
146 wasDeleted = false; // double-delete catcher
147 sendChildEvents = true; // if we should send ChildInsert and ChildRemove events to parent
148 receiveChildEvents = true;
151 connectedSignals[0] = connectedSignals[1] = 0;
152 inThreadChangeEvent = false;
153 #ifdef QT_JAMBI_BUILD
154 inEventHandler = false;
161 QObjectPrivate::~QObjectPrivate()
164 // unregister pending timers
165 if (threadData && threadData->eventDispatcher)
166 threadData->eventDispatcher->unregisterTimers(q_ptr);
170 QCoreApplication::removePostedEvents(q_ptr, 0);
175 delete static_cast<QAbstractDynamicMetaObject*>(metaObject);
176 #ifdef QT_JAMBI_BUILD
180 #ifndef QT_NO_USERDATA
182 qDeleteAll(extraData->userData);
188 #ifdef QT_JAMBI_BUILD
189 int *QObjectPrivate::setDeleteWatch(QObjectPrivate *d, int *w) {
190 int *old = d->deleteWatch;
196 void QObjectPrivate::resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch) {
198 d->deleteWatch = oldWatch;
201 *oldWatch = deleteWatch;
206 void QObjectPrivate::sendPendingChildInsertedEvents()
209 for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) {
210 QObject *c = pendingChildInsertedEvents.at(i).data();
211 if (!c || c->parent() != q)
213 QChildEvent childEvent(QEvent::ChildInserted, c);
214 QCoreApplication::sendEvent(q, &childEvent);
216 pendingChildInsertedEvents.clear();
223 For a given metaobject, compute the signal offset, and the method offset (including signals)
225 static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
227 *signalOffset = *methodOffset = 0;
228 const QMetaObject *m = metaobject->d.superdata;
230 const QMetaObjectPrivate *d = QMetaObjectPrivate::get(m);
231 *methodOffset += d->methodCount;
232 *signalOffset += (d->revision >= 4) ? d->signalCount : d->methodCount;
233 /*Before Qt 4.6 (revision 4), the signalCount information was not generated by moc.
234 so for compatibility we consider all the method as slot for old moc output*/
240 This vector contains the all connections from an object.
242 Each object may have one vector containing the lists of
243 connections for a given signal. The index in the vector correspond
244 to the signal index. The signal index is the one returned by
245 QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal).
246 Negative index means connections to all signals.
248 This vector is protected by the object mutex (signalSlotMutexes())
250 Each Connection is also part of a 'senders' linked list. The mutex
251 of the receiver must be locked when touching the pointers of this
254 class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList>
257 bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse
258 bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet
259 int inUse; //number of functions that are currently accessing this object or its connections
260 QObjectPrivate::ConnectionList allsignals;
262 QObjectConnectionListVector()
263 : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
266 QObjectPrivate::ConnectionList &operator[](int at)
270 return QVector<QObjectPrivate::ConnectionList>::operator[](at);
274 // Used by QAccessibleWidget
275 bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
278 int signal_index = signalIndex(signal);
279 if (signal_index < 0)
281 QMutexLocker locker(signalSlotLock(q));
282 if (connectionLists) {
283 if (signal_index < connectionLists->count()) {
284 const QObjectPrivate::Connection *c =
285 connectionLists->at(signal_index).first;
288 if (c->receiver == receiver)
290 c = c->nextConnectionList;
297 // Used by QAccessibleWidget
298 QObjectList QObjectPrivate::receiverList(const char *signal) const
301 QObjectList returnValue;
302 int signal_index = signalIndex(signal);
303 if (signal_index < 0)
305 QMutexLocker locker(signalSlotLock(q));
306 if (connectionLists) {
307 if (signal_index < connectionLists->count()) {
308 const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
312 returnValue << c->receiver;
313 c = c->nextConnectionList;
320 // Used by QAccessibleWidget
321 QObjectList QObjectPrivate::senderList() const
323 QObjectList returnValue;
324 QMutexLocker locker(signalSlotLock(q_func()));
325 for (Connection *c = senders; c; c = c->next)
326 returnValue << c->sender;
330 void QObjectPrivate::addConnection(int signal, Connection *c)
332 if (!connectionLists)
333 connectionLists = new QObjectConnectionListVector();
334 if (signal >= connectionLists->count())
335 connectionLists->resize(signal + 1);
337 ConnectionList &connectionList = (*connectionLists)[signal];
338 if (connectionList.last) {
339 connectionList.last->nextConnectionList = c;
341 connectionList.first = c;
343 connectionList.last = c;
345 cleanConnectionLists();
348 void QObjectPrivate::cleanConnectionLists()
350 if (connectionLists->dirty && !connectionLists->inUse) {
351 // remove broken connections
352 for (int signal = -1; signal < connectionLists->count(); ++signal) {
353 QObjectPrivate::ConnectionList &connectionList =
354 (*connectionLists)[signal];
356 // Set to the last entry in the connection list that was *not*
357 // deleted. This is needed to update the list's last pointer
358 // at the end of the cleanup.
359 QObjectPrivate::Connection *last = 0;
361 QObjectPrivate::Connection **prev = &connectionList.first;
362 QObjectPrivate::Connection *c = *prev;
366 prev = &c->nextConnectionList;
369 QObjectPrivate::Connection *next = c->nextConnectionList;
376 // Correct the connection list's last pointer.
377 // As conectionList.last could equal last, this could be a noop
378 connectionList.last = last;
380 connectionLists->dirty = false;
384 typedef QMultiHash<QObject *, QObject **> GuardHash;
385 Q_GLOBAL_STATIC(GuardHash, guardHash)
386 Q_GLOBAL_STATIC(QMutex, guardHashLock)
390 void QMetaObject::addGuard(QObject **ptr)
394 GuardHash *hash = guardHash();
399 QMutexLocker locker(guardHashLock());
400 QObjectPrivate::get(*ptr)->hasGuards = true;
401 hash->insert(*ptr, ptr);
406 void QMetaObject::removeGuard(QObject **ptr)
410 GuardHash *hash = guardHash();
411 /* check that the hash is empty - otherwise we might detach
412 the shared_null hash, which will alloc, which is not nice */
413 if (!hash || hash->isEmpty())
415 QMutexLocker locker(guardHashLock());
416 if (!*ptr) //check again, under the lock
418 GuardHash::iterator it = hash->find(*ptr);
419 const GuardHash::iterator end = hash->end();
420 bool more = false; //if the QObject has more pointer attached to it.
421 for (; it.key() == *ptr && it != end; ++it) {
422 if (it.value() == ptr) {
423 it = hash->erase(it);
424 if (!more) more = (it != end && it.key() == *ptr);
430 QObjectPrivate::get(*ptr)->hasGuards = false;
435 void QMetaObject::changeGuard(QObject **ptr, QObject *o)
437 GuardHash *hash = guardHash();
442 QMutexLocker locker(guardHashLock());
444 hash->insert(o, ptr);
445 QObjectPrivate::get(o)->hasGuards = true;
448 bool more = false; //if the QObject has more pointer attached to it.
449 GuardHash::iterator it = hash->find(*ptr);
450 const GuardHash::iterator end = hash->end();
451 for (; it.key() == *ptr && it != end; ++it) {
452 if (it.value() == ptr) {
453 it = hash->erase(it);
454 if (!more) more = (it != end && it.key() == *ptr);
460 QObjectPrivate::get(*ptr)->hasGuards = false;
467 void QObjectPrivate::clearGuards(QObject *object)
473 mutex = guardHashLock();
474 } QT_CATCH(const std::bad_alloc &) {
475 // do nothing in case of OOM - code below is safe
478 /* check that the hash is empty - otherwise we might detach
479 the shared_null hash, which will alloc, which is not nice */
480 if (hash && !hash->isEmpty()) {
481 QMutexLocker locker(mutex);
482 GuardHash::iterator it = hash->find(object);
483 const GuardHash::iterator end = hash->end();
484 while (it.key() == object && it != end) {
486 it = hash->erase(it);
493 QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
494 const QObject *sender, int signalId,
495 int nargs, int *types, void **args, QSemaphore *semaphore)
496 : QEvent(MetaCall), sender_(sender), signalId_(signalId),
497 nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
498 callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
503 QMetaCallEvent::~QMetaCallEvent()
506 for (int i = 0; i < nargs_; ++i) {
507 if (types_[i] && args_[i])
508 QMetaType::destroy(types_[i], args_[i]);
515 semaphore_->release();
521 void QMetaCallEvent::placeMetaCall(QObject *object)
524 callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
526 QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
532 \brief The QObject class is the base class of all Qt objects.
538 QObject is the heart of the Qt \l{Object Model}. The central
539 feature in this model is a very powerful mechanism for seamless
540 object communication called \l{signals and slots}. You can
541 connect a signal to a slot with connect() and destroy the
542 connection with disconnect(). To avoid never ending notification
543 loops you can temporarily block signals with blockSignals(). The
544 protected functions connectNotify() and disconnectNotify() make
545 it possible to track connections.
547 QObjects organize themselves in \l {Object Trees & Ownership}
548 {object trees}. When you create a QObject with another object as
549 parent, the object will automatically add itself to the parent's
550 children() list. The parent takes ownership of the object; i.e.,
551 it will automatically delete its children in its destructor. You
552 can look for an object by name and optionally type using
553 findChild() or findChildren().
555 Every object has an objectName() and its class name can be found
556 via the corresponding metaObject() (see QMetaObject::className()).
557 You can determine whether the object's class inherits another
558 class in the QObject inheritance hierarchy by using the
561 When an object is deleted, it emits a destroyed() signal. You can
562 catch this signal to avoid dangling references to QObjects.
564 QObjects can receive events through event() and filter the events
565 of other objects. See installEventFilter() and eventFilter() for
566 details. A convenience handler, childEvent(), can be reimplemented
567 to catch child events.
569 Last but not least, QObject provides the basic timer support in
570 Qt; see QTimer for high-level support for timers.
572 Notice that the Q_OBJECT macro is mandatory for any object that
573 implements signals, slots or properties. You also need to run the
574 \l{moc}{Meta Object Compiler} on the source file. We strongly
575 recommend the use of this macro in all subclasses of QObject
576 regardless of whether or not they actually use signals, slots and
577 properties, since failure to do so may lead certain functions to
578 exhibit strange behavior.
580 All Qt widgets inherit QObject. The convenience function
581 isWidgetType() returns whether an object is actually a widget. It
583 \l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
584 \e{obj}->\l{inherits()}{inherits}("QWidget").
586 Some QObject functions, e.g. children(), return a QObjectList.
587 QObjectList is a typedef for QList<QObject *>.
589 \section1 Thread Affinity
591 A QObject instance is said to have a \e{thread affinity}, or that
592 it \e{lives} in a certain thread. When a QObject receives a
593 \l{Qt::QueuedConnection}{queued signal} or a \l{The Event
594 System#Sending Events}{posted event}, the slot or event handler
595 will run in the thread that the object lives in.
597 \note If a QObject has no thread affinity (that is, if thread()
598 returns zero), or if it lives in a thread that has no running event
599 loop, then it cannot receive queued signals or posted events.
601 By default, a QObject lives in the thread in which it is created.
602 An object's thread affinity can be queried using thread() and
603 changed using moveToThread().
605 All QObjects must live in the same thread as their parent. Consequently:
608 \li setParent() will fail if the two QObjects involved live in
610 \li When a QObject is moved to another thread, all its children
611 will be automatically moved too.
612 \li moveToThread() will fail if the QObject has a parent.
613 \li If \l{QObject}s are created within QThread::run(), they cannot
614 become children of the QThread object because the QThread does
615 not live in the thread that calls QThread::run().
618 \note A QObject's member variables \e{do not} automatically become
619 its children. The parent-child relationship must be set by either
620 passing a pointer to the child's \l{QObject()}{constructor}, or by
621 calling setParent(). Without this step, the object's member variables
622 will remain in the old thread when moveToThread() is called.
624 \target No copy constructor
625 \section1 No copy constructor or assignment operator
627 QObject has neither a copy constructor nor an assignment operator.
628 This is by design. Actually, they are declared, but in a
629 \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
630 Qt classes derived from QObject (direct or indirect) use this
631 macro to declare their copy constructor and assignment operator to
632 be private. The reasoning is found in the discussion on
633 \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
636 The main consequence is that you should use pointers to QObject
637 (or to your QObject subclass) where you might otherwise be tempted
638 to use your QObject subclass as a value. For example, without a
639 copy constructor, you can't use a subclass of QObject as the value
640 to be stored in one of the container classes. You must store
643 \section1 Auto-Connection
645 Qt's meta-object system provides a mechanism to automatically connect
646 signals and slots between QObject subclasses and their children. As long
647 as objects are defined with suitable object names, and slots follow a
648 simple naming convention, this connection can be performed at run-time
649 by the QMetaObject::connectSlotsByName() function.
651 \l uic generates code that invokes this function to enable
652 auto-connection to be performed between widgets on forms created
653 with \QD. More information about using auto-connection with \QD is
654 given in the \l{Using a Designer UI File in Your Application} section of
657 \section1 Dynamic Properties
659 From Qt 4.2, dynamic properties can be added to and removed from QObject
660 instances at run-time. Dynamic properties do not need to be declared at
661 compile-time, yet they provide the same advantages as static properties
662 and are manipulated using the same API - using property() to read them
663 and setProperty() to write them.
665 From Qt 4.3, dynamic properties are supported by
666 \l{Qt Designer's Widget Editing Mode#The Property Editor}{Qt Designer},
667 and both standard Qt widgets and user-created forms can be given dynamic
670 \section1 Internationalization (i18n)
672 All QObject subclasses support Qt's translation features, making it possible
673 to translate an application's user interface into different languages.
675 To make user-visible text translatable, it must be wrapped in calls to
676 the tr() function. This is explained in detail in the
677 \l{Writing Source Code for Translation} document.
679 \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
680 \sa {Object Trees & Ownership}
686 Returns a pointer to the object named \a name that inherits \a
687 type and with a given \a parent.
689 Returns 0 if there is no such child.
691 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 0
694 void *qt_find_obj_child(QObject *parent, const char *type, const QString &name)
696 QObjectList list = parent->children();
697 if (list.size() == 0) return 0;
698 for (int i = 0; i < list.size(); ++i) {
699 QObject *obj = list.at(i);
700 if (name == obj->objectName() && obj->inherits(type))
707 /*****************************************************************************
708 QObject member functions
709 *****************************************************************************/
711 // check the constructor's parent thread argument
712 static bool check_parent_thread(QObject *parent,
713 QThreadData *parentThreadData,
714 QThreadData *currentThreadData)
716 if (parent && parentThreadData != currentThreadData) {
717 QThread *parentThread = parentThreadData->thread;
718 QThread *currentThread = currentThreadData->thread;
719 qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
720 "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
721 parent->metaObject()->className(),
723 parentThread ? parentThread->metaObject()->className() : "QThread",
725 currentThread ? currentThread->metaObject()->className() : "QThread",
733 Constructs an object with parent object \a parent.
735 The parent of an object may be viewed as the object's owner. For
736 instance, a \l{QDialog}{dialog box} is the parent of the \gui OK
737 and \gui Cancel buttons it contains.
739 The destructor of a parent object destroys all child objects.
741 Setting \a parent to 0 constructs an object with no parent. If the
742 object is a widget, it will become a top-level window.
744 \sa parent(), findChild(), findChildren()
747 QObject::QObject(QObject *parent)
748 : d_ptr(new QObjectPrivate)
752 d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
753 d->threadData->ref();
756 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
760 d->threadData->deref();
772 Creates a new QObject with the given \a parent and object \a name.
774 QObject::QObject(QObject *parent, const char *name)
775 : d_ptr(new QObjectPrivate)
778 qt_addObject(d_ptr->q_ptr = this);
779 d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
780 d->threadData->ref();
782 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
786 setObjectName(QString::fromAscii(name));
792 QObject::QObject(QObjectPrivate &dd, QObject *parent)
797 d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
798 d->threadData->ref();
801 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
806 d->parent->d_func()->children.append(this);
808 // no events sent here, this is done at the end of the QWidget constructor
813 d->threadData->deref();
821 Destroys the object, deleting all its child objects.
823 All signals to and from the object are automatically disconnected, and
824 any pending posted events for the object are removed from the event
825 queue. However, it is often safer to use deleteLater() rather than
826 deleting a QObject subclass directly.
828 \warning All child objects are deleted. If any of these objects
829 are on the stack or global, sooner or later your program will
830 crash. We do not recommend holding pointers to child objects from
831 outside the parent. If you still do, the destroyed() signal gives
832 you an opportunity to detect when an object is destroyed.
834 \warning Deleting a QObject while pending events are waiting to
835 be delivered can cause a crash. You must not delete the QObject
836 directly if it exists in a different thread than the one currently
837 executing. Use deleteLater() instead, which will cause the event
838 loop to delete the object after all pending events have been
847 d->wasDeleted = true;
848 d->blockSig = 0; // unblock signals so we always emit destroyed()
850 if (d->hasGuards && !d->isWidget) {
851 // set all QPointers for this object to zero - note that
852 // ~QWidget() does this for us, so we don't have to do it twice
853 QObjectPrivate::clearGuards(this);
856 if (d->sharedRefcount) {
857 if (d->sharedRefcount->strongref > 0) {
858 qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
859 // but continue deleting, it's too late to stop anyway
862 // indicate to all QWeakPointers that this QObject has now been deleted
863 d->sharedRefcount->strongref = 0;
864 if (!d->sharedRefcount->weakref.deref())
865 delete d->sharedRefcount;
869 if (d->isSignalConnected(0)) {
871 emit destroyed(this);
873 // all the signal/slots connections are still in place - if we don't
874 // quit now, we will crash pretty soon.
875 qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");
880 if (d->declarativeData)
881 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
883 // set ref to zero to indicate that this object has been deleted
884 if (d->currentSender != 0)
885 d->currentSender->ref = 0;
886 d->currentSender = 0;
888 if (d->connectionLists || d->senders) {
889 QMutex *signalSlotMutex = signalSlotLock(this);
890 QMutexLocker locker(signalSlotMutex);
892 // disconnect all receivers
893 if (d->connectionLists) {
894 ++d->connectionLists->inUse;
895 int connectionListsCount = d->connectionLists->count();
896 for (int signal = -1; signal < connectionListsCount; ++signal) {
897 QObjectPrivate::ConnectionList &connectionList =
898 (*d->connectionLists)[signal];
900 while (QObjectPrivate::Connection *c = connectionList.first) {
902 connectionList.first = c->nextConnectionList;
907 QMutex *m = signalSlotLock(c->receiver);
908 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
912 if (c->next) c->next->prev = c->prev;
917 connectionList.first = c->nextConnectionList;
922 if (!--d->connectionLists->inUse) {
923 delete d->connectionLists;
925 d->connectionLists->orphaned = true;
927 d->connectionLists = 0;
930 // disconnect all senders
931 QObjectPrivate::Connection *node = d->senders;
933 QObject *sender = node->sender;
934 QMutex *m = signalSlotLock(sender);
936 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
937 //the node has maybe been removed while the mutex was unlocked in relock?
938 if (!node || node->sender != sender) {
943 QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists;
945 senderLists->dirty = true;
953 if (!d->children.isEmpty())
956 qt_removeObject(this);
958 if (d->parent) // remove it from parent object
959 d->setParent_helper(0);
961 #ifdef QT_JAMBI_BUILD
962 if (d->inEventHandler) {
963 qWarning("QObject: Do not delete object, '%s', during its event handler!",
964 objectName().isNull() ? "unnamed" : qPrintable(objectName()));
969 QObjectPrivate::Connection::~Connection()
971 if (argumentTypes != &DIRECT_CONNECTION_ONLY)
972 delete [] static_cast<int *>(argumentTypes);
977 \fn QMetaObject *QObject::metaObject() const
979 Returns a pointer to the meta-object of this object.
981 A meta-object contains information about a class that inherits
982 QObject, e.g. class name, superclass name, properties, signals and
983 slots. Every QObject subclass that contains the Q_OBJECT macro will have a
986 The meta-object information is required by the signal/slot
987 connection mechanism and the property system. The inherits()
988 function also makes use of the meta-object.
990 If you have no pointer to an actual object instance but still
991 want to access the meta-object of a class, you can use \l
996 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 1
1002 \variable QObject::staticMetaObject
1004 This variable stores the meta-object for the class.
1006 A meta-object contains information about a class that inherits
1007 QObject, e.g. class name, superclass name, properties, signals and
1008 slots. Every class that contains the Q_OBJECT macro will also have
1011 The meta-object information is required by the signal/slot
1012 connection mechanism and the property system. The inherits()
1013 function also makes use of the meta-object.
1015 If you have a pointer to an object, you can use metaObject() to
1016 retrieve the meta-object associated with that object.
1020 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 2
1025 /*! \fn T *qobject_cast<T *>(QObject *object)
1028 Returns the given \a object cast to type T if the object is of type
1029 T (or of a subclass); otherwise returns 0. If \a object is 0 then
1030 it will also return 0.
1032 The class T must inherit (directly or indirectly) QObject and be
1033 declared with the \l Q_OBJECT macro.
1035 A class is considered to inherit itself.
1039 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 3
1041 The qobject_cast() function behaves similarly to the standard C++
1042 \c dynamic_cast(), with the advantages that it doesn't require
1043 RTTI support and it works across dynamic library boundaries.
1045 qobject_cast() can also be used in conjunction with interfaces;
1046 see the \l{tools/plugandpaint}{Plug & Paint} example for details.
1048 \warning If T isn't declared with the Q_OBJECT macro, this
1049 function's return value is undefined.
1051 \sa QObject::inherits()
1055 \fn bool QObject::inherits(const char *className) const
1057 Returns true if this object is an instance of a class that
1058 inherits \a className or a QObject subclass that inherits \a
1059 className; otherwise returns false.
1061 A class is considered to inherit itself.
1065 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 4
1067 If you need to determine whether an object is an instance of a particular
1068 class for the purpose of casting it, consider using qobject_cast<Type *>(object)
1071 \sa metaObject(), qobject_cast()
1075 \property QObject::objectName
1077 \brief the name of this object
1079 You can find an object by name (and type) using findChild(). You can
1080 find a set of objects with findChildren().
1082 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 5
1084 By default, this property contains an empty string.
1086 \sa metaObject(), QMetaObject::className()
1089 QString QObject::objectName() const
1092 return d->objectName;
1096 Sets the object's name to \a name.
1098 void QObject::setObjectName(const QString &name)
1101 bool objectNameChanged = d->declarativeData && d->objectName != name;
1103 d->objectName = name;
1105 if (objectNameChanged)
1106 d->declarativeData->objectNameChanged(d->declarativeData, this);
1112 QObject::child is compat but needs to call itself recursively,
1113 that's why we need this helper.
1115 static QObject *qChildHelper(const char *objName, const char *inheritsClass,
1116 bool recursiveSearch, const QObjectList &children)
1118 if (children.isEmpty())
1121 bool onlyWidgets = (inheritsClass && qstrcmp(inheritsClass, "QWidget") == 0);
1122 const QLatin1String oName(objName);
1123 for (int i = 0; i < children.size(); ++i) {
1124 QObject *obj = children.at(i);
1126 if (obj->isWidgetType() && (!objName || obj->objectName() == oName))
1128 } else if ((!inheritsClass || obj->inherits(inheritsClass))
1129 && (!objName || obj->objectName() == oName))
1131 if (recursiveSearch && (obj = qChildHelper(objName, inheritsClass,
1132 recursiveSearch, obj->children())))
1140 Searches the children and optionally grandchildren of this object,
1141 and returns a child that is called \a objName that inherits \a
1142 inheritsClass. If \a inheritsClass is 0 (the default), any class
1145 If \a recursiveSearch is true (the default), child() performs a
1146 depth-first search of the object's children.
1148 If there is no such object, this function returns 0. If there are
1149 more than one, the first one found is returned.
1151 QObject* QObject::child(const char *objName, const char *inheritsClass,
1152 bool recursiveSearch) const
1155 return qChildHelper(objName, inheritsClass, recursiveSearch, d->children);
1160 \fn bool QObject::isWidgetType() const
1162 Returns true if the object is a widget; otherwise returns false.
1164 Calling this function is equivalent to calling
1165 inherits("QWidget"), except that it is much faster.
1170 This virtual function receives events to an object and should
1171 return true if the event \a e was recognized and processed.
1173 The event() function can be reimplemented to customize the
1174 behavior of an object.
1176 \sa installEventFilter(), timerEvent(), QApplication::sendEvent(),
1177 QApplication::postEvent(), QWidget::event()
1180 bool QObject::event(QEvent *e)
1182 switch (e->type()) {
1184 timerEvent((QTimerEvent*)e);
1188 case QEvent::ChildInsertedRequest:
1189 d_func()->sendPendingChildInsertedEvents();
1193 case QEvent::ChildAdded:
1194 case QEvent::ChildPolished:
1196 case QEvent::ChildInserted:
1198 case QEvent::ChildRemoved:
1199 childEvent((QChildEvent*)e);
1202 case QEvent::DeferredDelete:
1203 qDeleteInEventHandler(this);
1206 case QEvent::MetaCall:
1208 #ifdef QT_JAMBI_BUILD
1209 d_func()->inEventHandler = false;
1211 QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
1212 QObjectPrivate::Sender currentSender;
1213 currentSender.sender = const_cast<QObject*>(mce->sender());
1214 currentSender.signal = mce->signalId();
1215 currentSender.ref = 1;
1216 QObjectPrivate::Sender * const previousSender =
1217 QObjectPrivate::setCurrentSender(this, ¤tSender);
1218 #if defined(QT_NO_EXCEPTIONS)
1219 mce->placeMetaCall(this);
1222 mce->placeMetaCall(this);
1224 QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender);
1228 QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender);
1232 case QEvent::ThreadChange: {
1234 QThreadData *threadData = d->threadData;
1235 QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
1236 if (eventDispatcher) {
1237 QList<QPair<int, int> > timers = eventDispatcher->registeredTimers(this);
1238 if (!timers.isEmpty()) {
1239 // set inThreadChangeEvent to true to tell the dispatcher not to release out timer ids
1240 // back to the pool (since the timer ids are moving to a new thread).
1241 d->inThreadChangeEvent = true;
1242 eventDispatcher->unregisterTimers(this);
1243 d->inThreadChangeEvent = false;
1244 QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
1245 Q_ARG(void*, (new QList<QPair<int, int> >(timers))));
1252 if (e->type() >= QEvent::User) {
1262 \fn void QObject::timerEvent(QTimerEvent *event)
1264 This event handler can be reimplemented in a subclass to receive
1265 timer events for the object.
1267 QTimer provides a higher-level interface to the timer
1268 functionality, and also more general information about timers. The
1269 timer event is passed in the \a event parameter.
1271 \sa startTimer(), killTimer(), event()
1274 void QObject::timerEvent(QTimerEvent *)
1280 This event handler can be reimplemented in a subclass to receive
1281 child events. The event is passed in the \a event parameter.
1283 QEvent::ChildAdded and QEvent::ChildRemoved events are sent to
1284 objects when children are added or removed. In both cases you can
1285 only rely on the child being a QObject, or if isWidgetType()
1286 returns true, a QWidget. (This is because, in the
1287 \l{QEvent::ChildAdded}{ChildAdded} case, the child is not yet
1288 fully constructed, and in the \l{QEvent::ChildRemoved}{ChildRemoved}
1289 case it might have been destructed already).
1291 QEvent::ChildPolished events are sent to widgets when children
1292 are polished, or when polished children are added. If you receive
1293 a child polished event, the child's construction is usually
1294 completed. However, this is not guaranteed, and multiple polish
1295 events may be delivered during the execution of a widget's
1298 For every child widget, you receive one
1299 \l{QEvent::ChildAdded}{ChildAdded} event, zero or more
1300 \l{QEvent::ChildPolished}{ChildPolished} events, and one
1301 \l{QEvent::ChildRemoved}{ChildRemoved} event.
1303 The \l{QEvent::ChildPolished}{ChildPolished} event is omitted if
1304 a child is removed immediately after it is added. If a child is
1305 polished several times during construction and destruction, you
1306 may receive several child polished events for the same child,
1307 each time with a different virtual table.
1312 void QObject::childEvent(QChildEvent * /* event */)
1318 This event handler can be reimplemented in a subclass to receive
1319 custom events. Custom events are user-defined events with a type
1320 value at least as large as the QEvent::User item of the
1321 QEvent::Type enum, and is typically a QEvent subclass. The event
1322 is passed in the \a event parameter.
1326 void QObject::customEvent(QEvent * /* event */)
1333 Filters events if this object has been installed as an event
1334 filter for the \a watched object.
1336 In your reimplementation of this function, if you want to filter
1337 the \a event out, i.e. stop it being handled further, return
1338 true; otherwise return false.
1341 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 6
1343 Notice in the example above that unhandled events are passed to
1344 the base class's eventFilter() function, since the base class
1345 might have reimplemented eventFilter() for its own internal
1348 \warning If you delete the receiver object in this function, be
1349 sure to return true. Otherwise, Qt will forward the event to the
1350 deleted object and the program might crash.
1352 \sa installEventFilter()
1355 bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
1361 \fn bool QObject::signalsBlocked() const
1363 Returns true if signals are blocked; otherwise returns false.
1365 Signals are not blocked by default.
1371 If \a block is true, signals emitted by this object are blocked
1372 (i.e., emitting a signal will not invoke anything connected to it).
1373 If \a block is false, no such blocking will occur.
1375 The return value is the previous value of signalsBlocked().
1377 Note that the destroyed() signal will be emitted even if the signals
1378 for this object have been blocked.
1380 \sa signalsBlocked()
1383 bool QObject::blockSignals(bool block)
1386 bool previous = d->blockSig;
1387 d->blockSig = block;
1392 Returns the thread in which the object lives.
1396 QThread *QObject::thread() const
1398 return d_func()->threadData->thread;
1402 Changes the thread affinity for this object and its children. The
1403 object cannot be moved if it has a parent. Event processing will
1404 continue in the \a targetThread.
1406 To move an object to the main thread, use QApplication::instance()
1407 to retrieve a pointer to the current application, and then use
1408 QApplication::thread() to retrieve the thread in which the
1409 application lives. For example:
1411 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 7
1413 If \a targetThread is zero, all event processing for this object
1414 and its children stops.
1416 Note that all active timers for the object will be reset. The
1417 timers are first stopped in the current thread and restarted (with
1418 the same interval) in the \a targetThread. As a result, constantly
1419 moving an object between threads can postpone timer events
1422 A QEvent::ThreadChange event is sent to this object just before
1423 the thread affinity is changed. You can handle this event to
1424 perform any special processing. Note that any new events that are
1425 posted to this object will be handled in the \a targetThread.
1427 \warning This function is \e not thread-safe; the current thread
1428 must be same as the current thread affinity. In other words, this
1429 function can only "push" an object from the current thread to
1430 another thread, it cannot "pull" an object from any arbitrary
1431 thread to the current thread.
1435 void QObject::moveToThread(QThread *targetThread)
1439 if (d->threadData->thread == targetThread) {
1440 // object is already in this thread
1444 if (d->parent != 0) {
1445 qWarning("QObject::moveToThread: Cannot move objects with a parent");
1449 qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
1453 QThreadData *currentData = QThreadData::current();
1454 QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : new QThreadData(0);
1455 if (d->threadData->thread == 0 && currentData == targetData) {
1456 // one exception to the rule: we allow moving objects with no thread affinity to the current thread
1457 currentData = d->threadData;
1458 } else if (d->threadData != currentData) {
1459 qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
1460 "Cannot move to target thread (%p)\n",
1461 currentData->thread, d->threadData->thread, targetData->thread);
1464 qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. "
1465 "Check that all plugins are compiled against the right Qt binaries. Export "
1466 "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
1473 d->moveToThread_helper();
1475 QOrderedMutexLocker locker(¤tData->postEventList.mutex,
1476 &targetData->postEventList.mutex);
1478 // keep currentData alive (since we've got it locked)
1482 d_func()->setThreadData_helper(currentData, targetData);
1486 // now currentData can commit suicide if it wants to
1487 currentData->deref();
1490 void QObjectPrivate::moveToThread_helper()
1493 QEvent e(QEvent::ThreadChange);
1494 QCoreApplication::sendEvent(q, &e);
1495 for (int i = 0; i < children.size(); ++i) {
1496 QObject *child = children.at(i);
1497 child->d_func()->moveToThread_helper();
1501 void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
1505 // move posted events
1506 int eventsMoved = 0;
1507 for (int i = 0; i < currentData->postEventList.size(); ++i) {
1508 const QPostEvent &pe = currentData->postEventList.at(i);
1511 if (pe.receiver == q) {
1512 // move this post event to the targetList
1513 targetData->postEventList.addEvent(pe);
1514 const_cast<QPostEvent &>(pe).event = 0;
1518 if (eventsMoved > 0 && targetData->eventDispatcher) {
1519 targetData->canWait = false;
1520 targetData->eventDispatcher->wakeUp();
1523 // the current emitting thread shouldn't restore currentSender after calling moveToThread()
1525 currentSender->ref = 0;
1528 #ifdef QT_JAMBI_BUILD
1529 // the current event thread also shouldn't restore the delete watch
1530 inEventHandler = false;
1537 // set new thread data
1539 threadData->deref();
1540 threadData = targetData;
1542 for (int i = 0; i < children.size(); ++i) {
1543 QObject *child = children.at(i);
1544 child->d_func()->setThreadData_helper(currentData, targetData);
1548 void QObjectPrivate::_q_reregisterTimers(void *pointer)
1551 QList<QPair<int, int> > *timerList = reinterpret_cast<QList<QPair<int, int> > *>(pointer);
1552 QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
1553 for (int i = 0; i < timerList->size(); ++i) {
1554 const QPair<int, int> &pair = timerList->at(i);
1555 eventDispatcher->registerTimer(pair.first, pair.second, q);
1562 // The timer flag hasTimer is set when startTimer is called.
1563 // It is not reset when killing the timer because more than
1564 // one timer might be active.
1568 Starts a timer and returns a timer identifier, or returns zero if
1569 it could not start a timer.
1571 A timer event will occur every \a interval milliseconds until
1572 killTimer() is called. If \a interval is 0, then the timer event
1573 occurs once every time there are no more window system events to
1576 The virtual timerEvent() function is called with the QTimerEvent
1577 event parameter class when a timer event occurs. Reimplement this
1578 function to get timer events.
1580 If multiple timers are running, the QTimerEvent::timerId() can be
1581 used to find out which timer was activated.
1585 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 8
1587 Note that QTimer's accuracy depends on the underlying operating
1588 system and hardware. Most platforms support an accuracy of 20
1589 milliseconds; some provide more. If Qt is unable to deliver the
1590 requested number of timer events, it will silently discard some.
1592 The QTimer class provides a high-level programming interface with
1593 single-shot timers and timer signals instead of events. There is
1594 also a QBasicTimer class that is more lightweight than QTimer and
1595 less clumsy than using timer IDs directly.
1597 \sa timerEvent(), killTimer(), QTimer::singleShot()
1600 int QObject::startTimer(int interval)
1605 qWarning("QObject::startTimer: QTimer cannot have a negative interval");
1609 d->pendTimer = true; // set timer flag
1611 if (!d->threadData->eventDispatcher) {
1612 qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread");
1615 return d->threadData->eventDispatcher->registerTimer(interval, this);
1619 Kills the timer with timer identifier, \a id.
1621 The timer identifier is returned by startTimer() when a timer
1624 \sa timerEvent(), startTimer()
1627 void QObject::killTimer(int id)
1630 if (d->threadData->eventDispatcher)
1631 d->threadData->eventDispatcher->unregisterTimer(id);
1636 \fn QObject *QObject::parent() const
1638 Returns a pointer to the parent object.
1644 \fn const QObjectList &QObject::children() const
1646 Returns a list of child objects.
1647 The QObjectList class is defined in the \c{<QObject>} header
1648 file as the following:
1650 \quotefromfile src/corelib/kernel/qobject.h
1651 \skipto /typedef .*QObjectList/
1652 \printuntil QObjectList
1654 The first child added is the \l{QList::first()}{first} object in
1655 the list and the last child added is the \l{QList::last()}{last}
1656 object in the list, i.e. new children are appended at the end.
1658 Note that the list order changes when QWidget children are
1659 \l{QWidget::raise()}{raised} or \l{QWidget::lower()}{lowered}. A
1660 widget that is raised becomes the last object in the list, and a
1661 widget that is lowered becomes the first object in the list.
1663 \sa findChild(), findChildren(), parent(), setParent()
1667 static void objSearch(QObjectList &result,
1668 const QObjectList &list,
1669 const char *inheritsClass,
1671 const char *objName,
1675 for (int i = 0; i < list.size(); ++i) {
1676 QObject *obj = list.at(i);
1681 ok = obj->isWidgetType();
1682 else if (inheritsClass && !obj->inherits(inheritsClass))
1686 ok = (obj->objectName() == QLatin1String(objName));
1687 #ifndef QT_NO_REGEXP
1689 ok = (rx->indexIn(obj->objectName()) != -1);
1695 QObjectList clist = obj->children();
1696 if (!clist.isEmpty())
1697 objSearch(result, clist, inheritsClass,
1698 onlyWidgets, objName, rx, recurse);
1706 Searches the children and optionally grandchildren of this object,
1707 and returns a list of those objects that are named or that match
1708 \a objName and inherit \a inheritsClass. If \a inheritsClass is 0
1709 (the default), all classes match. If \a objName is 0 (the
1710 default), all object names match.
1712 If \a regexpMatch is true (the default), \a objName is a regular
1713 expression that the objects's names must match. The syntax is that
1714 of a QRegExp. If \a regexpMatch is false, \a objName is a string
1715 and object names must match it exactly.
1717 Note that \a inheritsClass uses single inheritance from QObject,
1718 the way inherits() does. According to inherits(), QWidget
1719 inherits QObject but not QPaintDevice. This does not quite match
1720 reality, but is the best that can be done on the wide variety of
1721 compilers Qt supports.
1723 Finally, if \a recursiveSearch is true (the default), queryList()
1724 searches \e{n}th-generation as well as first-generation children.
1726 If all this seems a bit complex for your needs, the simpler
1727 child() function may be what you want.
1729 This somewhat contrived example disables all the buttons in this
1732 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 9
1734 \warning Delete the list as soon you have finished using it. The
1735 list contains pointers that may become invalid at almost any time
1736 without notice (as soon as the user closes a window you may have
1737 dangling pointers, for example).
1739 \sa child() children(), parent(), inherits(), objectName(), QRegExp
1742 QObjectList QObject::queryList(const char *inheritsClass,
1743 const char *objName,
1745 bool recursiveSearch) const
1749 bool onlyWidgets = (inheritsClass && qstrcmp(inheritsClass, "QWidget") == 0);
1750 #ifndef QT_NO_REGEXP
1751 if (regexpMatch && objName) { // regexp matching
1752 QRegExp rx(QString::fromLatin1(objName));
1753 objSearch(list, d->children, inheritsClass, onlyWidgets, 0, &rx, recursiveSearch);
1757 objSearch(list, d->children, inheritsClass, onlyWidgets, objName, 0, recursiveSearch);
1764 \fn T *QObject::findChild(const QString &name) const
1766 Returns the child of this object that can be cast into type T and
1767 that is called \a name, or 0 if there is no such object.
1768 Omitting the \a name argument causes all object names to be matched.
1769 The search is performed recursively.
1771 If there is more than one child matching the search, the most
1772 direct ancestor is returned. If there are several direct
1773 ancestors, it is undefined which one will be returned. In that
1774 case, findChildren() should be used.
1776 This example returns a child \l{QPushButton} of \c{parentWidget}
1777 named \c{"button1"}:
1779 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 10
1781 This example returns a \l{QListWidget} child of \c{parentWidget}:
1783 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 11
1789 \fn QList<T> QObject::findChildren(const QString &name) const
1791 Returns all children of this object with the given \a name that can be
1792 cast to type T, or an empty list if there are no such objects.
1793 Omitting the \a name argument causes all object names to be matched.
1794 The search is performed recursively.
1796 The following example shows how to find a list of child \l{QWidget}s of
1797 the specified \c{parentWidget} named \c{widgetname}:
1799 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 12
1801 This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
1803 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 13
1809 \fn QList<T> QObject::findChildren(const QRegExp ®Exp) const
1810 \overload findChildren()
1812 Returns the children of this object that can be cast to type T
1813 and that have names matching the regular expression \a regExp,
1814 or an empty list if there are no such objects.
1815 The search is performed recursively.
1819 \fn T qFindChild(const QObject *obj, const QString &name)
1821 \overload qFindChildren()
1824 This function is equivalent to
1825 \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
1827 \note This function was provided as a workaround for MSVC 6
1828 which did not support member template functions. It is advised
1829 to use the other form in new code.
1831 \sa QObject::findChild()
1835 \fn QList<T> qFindChildren(const QObject *obj, const QString &name)
1837 \overload qFindChildren()
1840 This function is equivalent to
1841 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
1843 \note This function was provided as a workaround for MSVC 6
1844 which did not support member template functions. It is advised
1845 to use the other form in new code.
1847 \sa QObject::findChildren()
1851 \fn QList<T> qFindChildren(const QObject *obj, const QRegExp ®Exp)
1853 \overload qFindChildren()
1855 This function is equivalent to
1856 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp).
1858 \note This function was provided as a workaround for MSVC 6
1859 which did not support member template functions. It is advised
1860 to use the other form in new code.
1862 \sa QObject::findChildren()
1868 void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re,
1869 const QMetaObject &mo, QList<void*> *list)
1871 if (!parent || !list)
1873 const QObjectList &children = parent->children();
1875 for (int i = 0; i < children.size(); ++i) {
1876 obj = children.at(i);
1879 if (re->indexIn(obj->objectName()) != -1)
1882 if (name.isNull() || obj->objectName() == name)
1886 qt_qFindChildren_helper(obj, name, re, mo, list);
1892 QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo)
1896 const QObjectList &children = parent->children();
1899 for (i = 0; i < children.size(); ++i) {
1900 obj = children.at(i);
1901 if (mo.cast(obj) && (name.isNull() || obj->objectName() == name))
1904 for (i = 0; i < children.size(); ++i) {
1905 obj = qt_qFindChild_helper(children.at(i), name, mo);
1913 Makes the object a child of \a parent.
1915 \sa QWidget::setParent()
1918 void QObject::setParent(QObject *parent)
1921 Q_ASSERT(!d->isWidget);
1922 d->setParent_helper(parent);
1925 void QObjectPrivate::deleteChildren()
1927 const bool reallyWasDeleted = wasDeleted;
1929 // delete children objects
1930 // don't use qDeleteAll as the destructor of the child might
1932 for (int i = 0; i < children.count(); ++i) {
1933 currentChildBeingDeleted = children.at(i);
1935 delete currentChildBeingDeleted;
1938 currentChildBeingDeleted = 0;
1939 wasDeleted = reallyWasDeleted;
1942 void QObjectPrivate::setParent_helper(QObject *o)
1948 QObjectPrivate *parentD = parent->d_func();
1949 if (parentD->wasDeleted && wasDeleted
1950 && parentD->currentChildBeingDeleted == q) {
1951 // don't do anything since QObjectPrivate::deleteChildren() already
1952 // cleared our entry in parentD->children.
1954 const int index = parentD->children.indexOf(q);
1955 if (parentD->wasDeleted) {
1956 parentD->children[index] = 0;
1958 parentD->children.removeAt(index);
1959 if (sendChildEvents && parentD->receiveChildEvents) {
1960 QChildEvent e(QEvent::ChildRemoved, q);
1961 QCoreApplication::sendEvent(parent, &e);
1968 // object hierarchies are constrained to a single thread
1969 if (threadData != parent->d_func()->threadData) {
1970 qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
1974 parent->d_func()->children.append(q);
1975 if(sendChildEvents && parent->d_func()->receiveChildEvents) {
1977 QChildEvent e(QEvent::ChildAdded, q);
1978 QCoreApplication::sendEvent(parent, &e);
1980 if (QCoreApplicationPrivate::useQt3Support) {
1981 if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) {
1982 QCoreApplication::postEvent(parent,
1983 new QEvent(QEvent::ChildInsertedRequest),
1984 Qt::HighEventPriority);
1986 parent->d_func()->pendingChildInsertedEvents.append(q);
1992 if (!wasDeleted && declarativeData)
1993 QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
1997 \fn void QObject::installEventFilter(QObject *filterObj)
1999 Installs an event filter \a filterObj on this object. For example:
2000 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 14
2002 An event filter is an object that receives all events that are
2003 sent to this object. The filter can either stop the event or
2004 forward it to this object. The event filter \a filterObj receives
2005 events via its eventFilter() function. The eventFilter() function
2006 must return true if the event should be filtered, (i.e. stopped);
2007 otherwise it must return false.
2009 If multiple event filters are installed on a single object, the
2010 filter that was installed last is activated first.
2012 Here's a \c KeyPressEater class that eats the key presses of its
2015 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 15
2017 And here's how to install it on two widgets:
2019 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 16
2021 The QShortcut class, for example, uses this technique to intercept
2022 shortcut key presses.
2024 \warning If you delete the receiver object in your eventFilter()
2025 function, be sure to return true. If you return false, Qt sends
2026 the event to the deleted object and the program will crash.
2028 Note that the filtering object must be in the same thread as this
2029 object. If \a filterObj is in a different thread, this function does
2030 nothing. If either \a filterObj or this object are moved to a different
2031 thread after calling this function, the event filter will not be
2032 called until both objects have the same thread affinity again (it
2035 \sa removeEventFilter(), eventFilter(), event()
2038 void QObject::installEventFilter(QObject *obj)
2043 if (d->threadData != obj->d_func()->threadData) {
2044 qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
2048 // clean up unused items in the list
2049 d->eventFilters.removeAll((QObject*)0);
2050 d->eventFilters.removeAll(obj);
2051 d->eventFilters.prepend(obj);
2055 Removes an event filter object \a obj from this object. The
2056 request is ignored if such an event filter has not been installed.
2058 All event filters for this object are automatically removed when
2059 this object is destroyed.
2061 It is always safe to remove an event filter, even during event
2062 filter activation (i.e. from the eventFilter() function).
2064 \sa installEventFilter(), eventFilter(), event()
2067 void QObject::removeEventFilter(QObject *obj)
2070 for (int i = 0; i < d->eventFilters.count(); ++i) {
2071 if (d->eventFilters.at(i) == obj)
2072 d->eventFilters[i] = 0;
2078 \fn QObject::destroyed(QObject *obj)
2080 This signal is emitted immediately before the object \a obj is
2081 destroyed, and can not be blocked.
2083 All the objects's children are destroyed immediately after this
2086 \sa deleteLater(), QPointer
2090 Schedules this object for deletion.
2092 The object will be deleted when control returns to the event
2093 loop. If the event loop is not running when this function is
2094 called (e.g. deleteLater() is called on an object before
2095 QCoreApplication::exec()), the object will be deleted once the
2096 event loop is started. If deleteLater() is called after the main event loop
2097 has stopped, the object will not be deleted.
2098 Since Qt 4.8, if deleteLater() is called on an object that lives in a
2099 thread with no running event loop, the object will be destroyed when the
2102 Note that entering and leaving a new event loop (e.g., by opening a modal
2103 dialog) will \e not perform the deferred deletion; for the object to be
2104 deleted, the control must return to the event loop from which
2105 deleteLater() was called.
2107 \bold{Note:} It is safe to call this function more than once; when the
2108 first deferred deletion event is delivered, any pending events for the
2109 object are removed from the event queue.
2111 \sa destroyed(), QPointer
2113 void QObject::deleteLater()
2115 QCoreApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
2119 \fn QString QObject::tr(const char *sourceText, const char *disambiguation, int n)
2122 Returns a translated version of \a sourceText, optionally based on a
2123 \a disambiguation string and value of \a n for strings containing plurals;
2124 otherwise returns \a sourceText itself if no appropriate translated string
2128 \snippet mainwindows/sdi/mainwindow.cpp implicit tr context
2131 If the same \a sourceText is used in different roles within the
2132 same context, an additional identifying string may be passed in
2133 \a disambiguation (0 by default). In Qt 4.4 and earlier, this was
2134 the preferred way to pass comments to translators.
2138 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 17
2141 See \l{Writing Source Code for Translation} for a detailed description of
2142 Qt's translation mechanisms in general, and the
2143 \l{Writing Source Code for Translation#Disambiguation}{Disambiguation}
2144 section for information on disambiguation.
2146 \warning This method is reentrant only if all translators are
2147 installed \e before calling this method. Installing or removing
2148 translators while performing translations is not supported. Doing
2149 so will probably result in crashes or other undesirable behavior.
2151 \sa trUtf8(), QApplication::translate(), QTextCodec::setCodecForTr(), {Internationalization with Qt}
2155 \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
2158 Returns a translated version of \a sourceText, or
2159 QString::fromUtf8(\a sourceText) if there is no appropriate
2160 version. It is otherwise identical to tr(\a sourceText, \a
2161 disambiguation, \a n).
2163 Note that using the Utf8 variants of the translation functions
2164 is not required if \c CODECFORTR is already set to UTF-8 in the
2165 qmake project file and QTextCodec::setCodecForTr("UTF-8") is
2168 \warning This method is reentrant only if all translators are
2169 installed \e before calling this method. Installing or removing
2170 translators while performing translations is not supported. Doing
2171 so will probably result in crashes or other undesirable behavior.
2173 \warning For portability reasons, we recommend that you use
2174 escape sequences for specifying non-ASCII characters in string
2175 literals to trUtf8(). For example:
2177 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 20
2179 \sa tr(), QApplication::translate(), {Internationalization with Qt}
2185 /*****************************************************************************
2187 *****************************************************************************/
2190 const char *qFlagLocation(const char *method)
2192 QThreadData::current()->flaggedSignatures.store(method);
2196 static int extract_code(const char *member)
2198 // extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
2199 return (((int)(*member) - '0') & 0x3);
2202 static const char * extract_location(const char *member)
2204 if (QThreadData::current()->flaggedSignatures.contains(member)) {
2205 // signature includes location information after the first null-terminator
2206 const char *location = member + qstrlen(member) + 1;
2207 if (*location != '\0')
2213 static bool check_signal_macro(const QObject *sender, const char *signal,
2214 const char *func, const char *op)
2216 int sigcode = extract_code(signal);
2217 if (sigcode != QSIGNAL_CODE) {
2218 if (sigcode == QSLOT_CODE)
2219 qWarning("Object::%s: Attempt to %s non-signal %s::%s",
2220 func, op, sender->metaObject()->className(), signal+1);
2222 qWarning("Object::%s: Use the SIGNAL macro to %s %s::%s",
2223 func, op, sender->metaObject()->className(), signal);
2229 static bool check_method_code(int code, const QObject *object,
2230 const char *method, const char *func)
2232 if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
2233 qWarning("Object::%s: Use the SLOT or SIGNAL macro to "
2234 "%s %s::%s", func, func, object->metaObject()->className(), method);
2240 static void err_method_notfound(const QObject *object,
2241 const char *method, const char *func)
2243 const char *type = "method";
2244 switch (extract_code(method)) {
2245 case QSLOT_CODE: type = "slot"; break;
2246 case QSIGNAL_CODE: type = "signal"; break;
2248 const char *loc = extract_location(method);
2249 if (strchr(method,')') == 0) // common typing mistake
2250 qWarning("Object::%s: Parentheses expected, %s %s::%s%s%s",
2251 func, type, object->metaObject()->className(), method+1,
2252 loc ? " in ": "", loc ? loc : "");
2254 qWarning("Object::%s: No such %s %s::%s%s%s",
2255 func, type, object->metaObject()->className(), method+1,
2256 loc ? " in ": "", loc ? loc : "");
2261 static void err_info_about_objects(const char * func,
2262 const QObject * sender,
2263 const QObject * receiver)
2265 QString a = sender ? sender->objectName() : QString();
2266 QString b = receiver ? receiver->objectName() : QString();
2268 qWarning("Object::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
2270 qWarning("Object::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
2274 Returns a pointer to the object that sent the signal, if called in
2275 a slot activated by a signal; otherwise it returns 0. The pointer
2276 is valid only during the execution of the slot that calls this
2277 function from this object's thread context.
2279 The pointer returned by this function becomes invalid if the
2280 sender is destroyed, or if the slot is disconnected from the
2283 \warning This function violates the object-oriented principle of
2284 modularity. However, getting access to the sender might be useful
2285 when many signals are connected to a single slot.
2287 \warning As mentioned above, the return value of this function is
2288 not valid when the slot is called via a Qt::DirectConnection from
2289 a thread different from this object's thread. Do not use this
2290 function in this type of scenario.
2292 \sa senderSignalIndex(), QSignalMapper
2295 QObject *QObject::sender() const
2299 QMutexLocker locker(signalSlotLock(this));
2300 if (!d->currentSender)
2303 for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
2304 if (c->sender == d->currentSender->sender)
2305 return d->currentSender->sender;
2314 Returns the meta-method index of the signal that called the currently
2315 executing slot, which is a member of the class returned by sender().
2316 If called outside of a slot activated by a signal, -1 is returned.
2318 For signals with default parameters, this function will always return
2319 the index with all parameters, regardless of which was used with
2320 connect(). For example, the signal \c {destroyed(QObject *obj = 0)}
2321 will have two different indexes (with and without the parameter), but
2322 this function will always return the index with a parameter. This does
2323 not apply when overloading signals with different parameters.
2325 \warning This function violates the object-oriented principle of
2326 modularity. However, getting access to the signal index might be useful
2327 when many signals are connected to a single slot.
2329 \warning The return value of this function is not valid when the slot
2330 is called via a Qt::DirectConnection from a thread different from this
2331 object's thread. Do not use this function in this type of scenario.
2333 \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method()
2336 int QObject::senderSignalIndex() const
2340 QMutexLocker locker(signalSlotLock(this));
2341 if (!d->currentSender)
2344 for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
2345 if (c->sender == d->currentSender->sender)
2346 return d->currentSender->signal;
2353 Returns the number of receivers connected to the \a signal.
2355 Since both slots and signals can be used as receivers for signals,
2356 and the same connections can be made many times, the number of
2357 receivers is the same as the number of connections made from this
2360 When calling this function, you can use the \c SIGNAL() macro to
2361 pass a specific signal:
2363 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 21
2365 As the code snippet above illustrates, you can use this function
2366 to avoid emitting a signal that nobody listens to.
2368 \warning This function violates the object-oriented principle of
2369 modularity. However, it might be useful when you need to perform
2370 expensive initialization only if something is connected to a
2374 int QObject::receivers(const char *signal) const
2379 QByteArray signal_name = QMetaObject::normalizedSignature(signal);
2380 signal = signal_name;
2382 if (!check_signal_macro(this, signal, "receivers", "bind"))
2385 signal++; // skip code
2386 int signal_index = d->signalIndex(signal);
2387 if (signal_index < 0) {
2389 err_method_notfound(this, signal-1, "receivers");
2395 QMutexLocker locker(signalSlotLock(this));
2396 if (d->connectionLists) {
2397 if (signal_index < d->connectionLists->count()) {
2398 const QObjectPrivate::Connection *c =
2399 d->connectionLists->at(signal_index).first;
2401 receivers += c->receiver ? 1 : 0;
2402 c = c->nextConnectionList;
2413 This helper function calculates signal and method index for the given
2414 member in the specified class.
2417 \o If member.mobj is 0 then both signalIndex and methodIndex are set to -1.
2419 \o If specified member is not a member of obj instance class (or one of
2420 its parent classes) then both signalIndex and methodIndex are set to -1.
2423 This function is used by QObject::connect and QObject::disconnect which
2424 are working with QMetaMethod.
2426 \a signalIndex is set to the signal index of member. If the member
2427 specified is not signal this variable is set to -1.
2429 \a methodIndex is set to the method index of the member. If the
2430 member is not a method of the object specified by the \a obj argument this
2431 variable is set to -1.
2433 void QMetaObjectPrivate::memberIndexes(const QObject *obj,
2434 const QMetaMethod &member,
2435 int *signalIndex, int *methodIndex)
2439 if (!obj || !member.mobj)
2441 const QMetaObject *m = obj->metaObject();
2442 // Check that member is member of obj class
2443 while (m != 0 && m != member.mobj)
2447 *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5;
2451 computeOffsets(m, &signalOffset, &methodOffset);
2453 *methodIndex += methodOffset;
2454 if (member.methodType() == QMetaMethod::Signal) {
2455 *signalIndex = originalClone(m, *signalIndex);
2456 *signalIndex += signalOffset;
2462 static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal,
2463 const QMetaObject *receiver, const QMetaMethod &method)
2465 if (signal.attributes() & QMetaMethod::Compatibility) {
2466 if (!(method.attributes() & QMetaMethod::Compatibility))
2467 qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
2468 sender->className(), signal.signature());
2469 } else if ((method.attributes() & QMetaMethod::Compatibility) &&
2470 method.methodType() == QMetaMethod::Signal) {
2471 qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
2472 sender->className(), signal.signature(),
2473 receiver->className(), method.signature());
2480 Creates a connection of the given \a type from the \a signal in
2481 the \a sender object to the \a method in the \a receiver object.
2482 Returns true if the connection succeeds; otherwise returns false.
2484 You must use the \c SIGNAL() and \c SLOT() macros when specifying
2485 the \a signal and the \a method, for example:
2487 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 22
2489 This example ensures that the label always displays the current
2490 scroll bar value. Note that the signal and slots parameters must not
2491 contain any variable names, only the type. E.g. the following would
2492 not work and return false:
2494 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 23
2496 A signal can also be connected to another signal:
2498 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 24
2500 In this example, the \c MyWidget constructor relays a signal from
2501 a private member variable, and makes it available under a name
2502 that relates to \c MyWidget.
2504 A signal can be connected to many slots and signals. Many signals
2505 can be connected to one slot.
2507 If a signal is connected to several slots, the slots are activated
2508 in the same order as the order the connection was made, when the
2511 The function returns true if it successfully connects the signal
2512 to the slot. It will return false if it cannot create the
2513 connection, for example, if QObject is unable to verify the
2514 existence of either \a signal or \a method, or if their signatures
2517 By default, a signal is emitted for every connection you make;
2518 two signals are emitted for duplicate connections. You can break
2519 all of these connections with a single disconnect() call.
2520 If you pass the Qt::UniqueConnection \a type, the connection will only
2521 be made if it is not a duplicate. If there is already a duplicate
2522 (exact same signal to the exact same slot on the same objects),
2523 the connection will fail and connect will return false.
2525 The optional \a type parameter describes the type of connection
2526 to establish. In particular, it determines whether a particular
2527 signal is delivered to a slot immediately or queued for delivery
2528 at a later time. If the signal is queued, the parameters must be
2529 of types that are known to Qt's meta-object system, because Qt
2530 needs to copy the arguments to store them in an event behind the
2531 scenes. If you try to use a queued connection and get the error
2534 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 25
2536 call qRegisterMetaType() to register the data type before you
2537 establish the connection.
2539 \sa disconnect(), sender(), qRegisterMetaType(), Q_DECLARE_METATYPE()
2542 bool QObject::connect(const QObject *sender, const char *signal,
2543 const QObject *receiver, const char *method,
2544 Qt::ConnectionType type)
2547 const void *cbdata[] = { sender, signal, receiver, method, &type };
2548 if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
2553 bool warnCompat = true;
2555 if (type == Qt::AutoCompatConnection) {
2556 type = Qt::AutoConnection;
2562 if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {
2563 qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2564 sender ? sender->metaObject()->className() : "(null)",
2565 (signal && *signal) ? signal+1 : "(null)",
2566 receiver ? receiver->metaObject()->className() : "(null)",
2567 (method && *method) ? method+1 : "(null)");
2570 QByteArray tmp_signal_name;
2572 if (!check_signal_macro(sender, signal, "connect", "bind"))
2574 const QMetaObject *smeta = sender->metaObject();
2575 const char *signal_arg = signal;
2576 ++signal; //skip code
2577 int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
2578 if (signal_index < 0) {
2579 // check for normalized signatures
2580 tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
2581 signal = tmp_signal_name.constData() + 1;
2583 smeta = sender->metaObject();
2584 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
2586 if (signal_index < 0) {
2587 // re-use tmp_signal_name and signal from above
2589 smeta = sender->metaObject();
2590 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
2592 if (signal_index < 0) {
2593 err_method_notfound(sender, signal_arg, "connect");
2594 err_info_about_objects("connect", sender, receiver);
2597 signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
2598 int signalOffset, methodOffset;
2599 computeOffsets(smeta, &signalOffset, &methodOffset);
2600 int signal_absolute_index = signal_index + methodOffset;
2601 signal_index += signalOffset;
2603 QByteArray tmp_method_name;
2604 int membcode = extract_code(method);
2606 if (!check_method_code(membcode, receiver, method, "connect"))
2608 const char *method_arg = method;
2609 ++method; // skip code
2611 const QMetaObject *rmeta = receiver->metaObject();
2612 int method_index_relative = -1;
2615 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
2618 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
2622 if (method_index_relative < 0) {
2623 // check for normalized methods
2624 tmp_method_name = QMetaObject::normalizedSignature(method);
2625 method = tmp_method_name.constData();
2627 // rmeta may have been modified above
2628 rmeta = receiver->metaObject();
2631 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
2632 if (method_index_relative < 0)
2633 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, true);
2636 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
2637 if (method_index_relative < 0)
2638 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, true);
2643 if (method_index_relative < 0) {
2644 err_method_notfound(receiver, method_arg, "connect");
2645 err_info_about_objects("connect", sender, receiver);
2649 if (!QMetaObject::checkConnectArgs(signal, method)) {
2650 qWarning("QObject::connect: Incompatible sender/receiver arguments"
2651 "\n %s::%s --> %s::%s",
2652 sender->metaObject()->className(), signal,
2653 receiver->metaObject()->className(), method);
2658 if ((type == Qt::QueuedConnection)
2659 && !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))
2664 QMetaMethod smethod = smeta->method(signal_absolute_index);
2665 QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
2666 check_and_warn_compat(smeta, smethod, rmeta, rmethod);
2669 if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index_relative, rmeta ,type, types))
2671 const_cast<QObject*>(sender)->connectNotify(signal - 1);
2678 Creates a connection of the given \a type from the \a signal in
2679 the \a sender object to the \a method in the \a receiver object.
2680 Returns true if the connection succeeds; otherwise returns false.
2682 This function works in the same way as
2683 connect(const QObject *sender, const char *signal,
2684 const QObject *receiver, const char *method,
2685 Qt::ConnectionType type)
2686 but it uses QMetaMethod to specify signal and method.
2688 \sa connect(const QObject *sender, const char *signal,
2689 const QObject *receiver, const char *method,
2690 Qt::ConnectionType type)
2692 bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
2693 const QObject *receiver, const QMetaMethod &method,
2694 Qt::ConnectionType type)
2697 bool warnCompat = true;
2699 if (type == Qt::AutoCompatConnection) {
2700 type = Qt::AutoConnection;
2708 || signal.methodType() != QMetaMethod::Signal
2709 || method.methodType() == QMetaMethod::Constructor) {
2710 qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2711 sender ? sender->metaObject()->className() : "(null)",
2713 receiver ? receiver->metaObject()->className() : "(null)",
2714 method.signature() );
2718 QVarLengthArray<char> signalSignature;
2719 QObjectPrivate::signalSignature(signal, &signalSignature);
2722 QByteArray methodSignature;
2723 methodSignature.reserve(qstrlen(method.signature())+1);
2724 methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
2725 : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
2726 methodSignature.append(method.signature());
2727 const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type };
2728 if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
2737 QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
2738 QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
2741 const QMetaObject *smeta = sender->metaObject();
2742 const QMetaObject *rmeta = receiver->metaObject();
2743 if (signal_index == -1) {
2744 qWarning("QObject::connect: Can't find signal %s on instance of class %s",
2745 signal.signature(), smeta->className());
2748 if (method_index == -1) {
2749 qWarning("QObject::connect: Can't find method %s on instance of class %s",
2750 method.signature(), rmeta->className());
2754 if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) {
2755 qWarning("QObject::connect: Incompatible sender/receiver arguments"
2756 "\n %s::%s --> %s::%s",
2757 smeta->className(), signal.signature(),
2758 rmeta->className(), method.signature());
2763 if ((type == Qt::QueuedConnection)
2764 && !(types = queuedConnectionTypes(signal.parameterTypes())))
2769 check_and_warn_compat(smeta, signal, rmeta, method);
2771 if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, 0, type, types))
2774 const_cast<QObject*>(sender)->connectNotify(signalSignature.constData());
2779 \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
2783 Connects \a signal from the \a sender object to this object's \a
2786 Equivalent to connect(\a sender, \a signal, \c this, \a method, \a type).
2788 Every connection you make emits a signal, so duplicate connections emit
2789 two signals. You can break a connection using disconnect().
2797 Disconnects \a signal in object \a sender from \a method in object
2798 \a receiver. Returns true if the connection is successfully broken;
2799 otherwise returns false.
2801 A signal-slot connection is removed when either of the objects
2802 involved are destroyed.
2804 disconnect() is typically used in three ways, as the following
2805 examples demonstrate.
2807 \i Disconnect everything connected to an object's signals:
2809 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26
2811 equivalent to the non-static overloaded function
2813 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 27
2815 \i Disconnect everything connected to a specific signal:
2817 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 28
2819 equivalent to the non-static overloaded function
2821 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 29
2823 \i Disconnect a specific receiver:
2825 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30
2827 equivalent to the non-static overloaded function
2829 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 31
2833 0 may be used as a wildcard, meaning "any signal", "any receiving
2834 object", or "any slot in the receiving object", respectively.
2836 The \a sender may never be 0. (You cannot disconnect signals from
2837 more than one object in a single call.)
2839 If \a signal is 0, it disconnects \a receiver and \a method from
2840 any signal. If not, only the specified signal is disconnected.
2842 If \a receiver is 0, it disconnects anything connected to \a
2843 signal. If not, slots in objects other than \a receiver are not
2846 If \a method is 0, it disconnects anything that is connected to \a
2847 receiver. If not, only slots named \a method will be disconnected,
2848 and all other slots are left alone. The \a method must be 0 if \a
2849 receiver is left out, so you cannot disconnect a
2850 specifically-named slot on all objects.
2854 bool QObject::disconnect(const QObject *sender, const char *signal,
2855 const QObject *receiver, const char *method)
2857 if (sender == 0 || (receiver == 0 && method != 0)) {
2858 qWarning("Object::disconnect: Unexpected null parameter");
2863 const void *cbdata[] = { sender, signal, receiver, method };
2864 if (QInternal::activateCallbacks(QInternal::DisconnectCallback, (void **) cbdata))
2868 const char *signal_arg = signal;
2869 QByteArray signal_name;
2870 bool signal_found = false;
2873 signal_name = QMetaObject::normalizedSignature(signal);
2874 signal = signal_name.constData();
2875 } QT_CATCH (const std::bad_alloc &) {
2876 // if the signal is already normalized, we can continue.
2877 if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
2881 if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
2883 signal++; // skip code
2886 QByteArray method_name;
2887 const char *method_arg = method;
2889 bool method_found = false;
2892 method_name = QMetaObject::normalizedSignature(method);
2893 method = method_name.constData();
2894 } QT_CATCH(const std::bad_alloc &) {
2895 // if the method is already normalized, we can continue.
2896 if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
2900 membcode = extract_code(method);
2901 if (!check_method_code(membcode, receiver, method, "disconnect"))
2903 method++; // skip code
2906 /* We now iterate through all the sender's and receiver's meta
2907 * objects in order to also disconnect possibly shadowed signals
2908 * and slots with the same signature.
2911 const QMetaObject *smeta = sender->metaObject();
2913 int signal_index = -1;
2915 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
2916 if (signal_index < 0)
2917 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
2918 if (signal_index < 0)
2920 signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
2921 int signalOffset, methodOffset;
2922 computeOffsets(smeta, &signalOffset, &methodOffset);
2923 signal_index += signalOffset;
2924 signal_found = true;
2928 res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1);
2930 const QMetaObject *rmeta = receiver->metaObject();
2932 int method_index = rmeta->indexOfMethod(method);
2933 if (method_index >= 0)
2934 while (method_index < rmeta->methodOffset())
2935 rmeta = rmeta->superClass();
2936 if (method_index < 0)
2938 res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index);
2939 method_found = true;
2940 } while ((rmeta = rmeta->superClass()));
2942 } while (signal && (smeta = smeta->superClass()));
2944 if (signal && !signal_found) {
2945 err_method_notfound(sender, signal_arg, "disconnect");
2946 err_info_about_objects("disconnect", sender, receiver);
2947 } else if (method && !method_found) {
2948 err_method_notfound(receiver, method_arg, "disconnect");
2949 err_info_about_objects("disconnect", sender, receiver);
2952 const_cast<QObject*>(sender)->disconnectNotify(signal ? (signal - 1) : 0);
2959 Disconnects \a signal in object \a sender from \a method in object
2960 \a receiver. Returns true if the connection is successfully broken;
2961 otherwise returns false.
2963 This function provides the same possibilities like
2964 disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
2965 but uses QMetaMethod to represent the signal and the method to be disconnected.
2967 Additionally this function returnsfalse and no signals and slots disconnected
2971 \i \a signal is not a member of sender class or one of its parent classes.
2973 \i \a method is not a member of receiver class or one of its parent classes.
2975 \i \a signal instance represents not a signal.
2979 QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object".
2980 In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case
2981 method should also be QMetaMethod(). \a sender parameter should be never 0.
2983 \sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
2985 bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
2986 const QObject *receiver, const QMetaMethod &method)
2988 if (sender == 0 || (receiver == 0 && method.mobj != 0)) {
2989 qWarning("Object::disconnect: Unexpected null parameter");
2993 if(signal.methodType() != QMetaMethod::Signal) {
2994 qWarning("Object::%s: Attempt to %s non-signal %s::%s",
2995 "disconnect","unbind",
2996 sender->metaObject()->className(), signal.signature());
3001 if(method.methodType() == QMetaMethod::Constructor) {
3002 qWarning("QObject::disconect: cannot use constructor as argument %s::%s",
3003 receiver->metaObject()->className(), method.signature());
3008 QVarLengthArray<char> signalSignature;
3010 QObjectPrivate::signalSignature(signal, &signalSignature);
3013 QByteArray methodSignature;
3015 methodSignature.reserve(qstrlen(method.signature())+1);
3016 methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
3017 : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
3018 methodSignature.append(method.signature());
3020 const void *cbdata[] = { sender, signal.mobj ? signalSignature.constData() : 0,
3021 receiver, method.mobj ? methodSignature.constData() : 0 };
3022 if (QInternal::activateCallbacks(QInternal::DisconnectCallback, (void **) cbdata))
3030 QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
3031 QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
3033 // If we are here sender is not null. If signal is not null while signal_index
3034 // is -1 then this signal is not a member of sender.
3035 if (signal.mobj && signal_index == -1) {
3036 qWarning("QObject::disconect: signal %s not found on class %s",
3037 signal.signature(), sender->metaObject()->className());
3040 // If this condition is true then method is not a member of receeiver.
3041 if (receiver && method.mobj && method_index == -1) {
3042 qWarning("QObject::disconect: method %s not found on class %s",
3043 method.signature(), receiver->metaObject()->className());
3047 if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index))
3050 const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0);
3057 \fn bool QObject::disconnect(const char *signal, const QObject *receiver, const char *method)
3058 \overload disconnect()
3060 Disconnects \a signal from \a method of \a receiver.
3062 A signal-slot connection is removed when either of the objects
3063 involved are destroyed.
3067 \fn bool QObject::disconnect(const QObject *receiver, const char *method)
3068 \overload disconnect()
3070 Disconnects all signals in this object from \a receiver's \a
3073 A signal-slot connection is removed when either of the objects
3074 involved are destroyed.
3079 \fn void QObject::connectNotify(const char *signal)
3081 This virtual function is called when something has been connected
3082 to \a signal in this object.
3084 If you want to compare \a signal with a specific signal, use
3085 QLatin1String and the \c SIGNAL() macro as follows:
3087 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 32
3089 If the signal contains multiple parameters or parameters that
3090 contain spaces, call QMetaObject::normalizedSignature() on
3091 the result of the \c SIGNAL() macro.
3093 \warning This function violates the object-oriented principle of
3094 modularity. However, it might be useful when you need to perform
3095 expensive initialization only if something is connected to a
3098 \sa connect(), disconnectNotify()
3101 void QObject::connectNotify(const char *)
3106 \fn void QObject::disconnectNotify(const char *signal)
3108 This virtual function is called when something has been
3109 disconnected from \a signal in this object.
3111 See connectNotify() for an example of how to compare
3112 \a signal with a specific signal.
3114 \warning This function violates the object-oriented principle of
3115 modularity. However, it might be useful for optimizing access to
3116 expensive resources.
3118 \sa disconnect(), connectNotify()
3121 void QObject::disconnectNotify(const char *)
3126 convert a signal index from the method range to the signal range
3128 static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_index)
3130 if (signal_index < 0)
3131 return signal_index;
3132 while (metaObject && metaObject->methodOffset() > signal_index)
3133 metaObject = metaObject->superClass();
3136 int signalOffset, methodOffset;
3137 computeOffsets(metaObject, &signalOffset, &methodOffset);
3138 if (signal_index < metaObject->methodCount())
3139 signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
3141 signal_index = signal_index - methodOffset + signalOffset;
3143 return signal_index;
3147 \a types is a 0-terminated vector of meta types for queued
3150 if \a signal_index is -1, then we effectively connect *all* signals
3151 from the sender to the receiver's slot
3153 bool QMetaObject::connect(const QObject *sender, int signal_index,
3154 const QObject *receiver, int method_index, int type, int *types)
3156 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
3157 return QMetaObjectPrivate::connect(sender, signal_index,
3158 receiver, method_index,
3159 0, //FIXME, we could speed this connection up by computing the relative index
3164 Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3166 method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index
3168 bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
3169 const QObject *receiver, int method_index,
3170 const QMetaObject *rmeta, int type, int *types)
3172 QObject *s = const_cast<QObject *>(sender);
3173 QObject *r = const_cast<QObject *>(receiver);
3175 int method_offset = rmeta ? rmeta->methodOffset() : 0;
3176 QObjectPrivate::StaticMetaCallFunction callFunction =
3177 (rmeta && QMetaObjectPrivate::get(rmeta)->revision >= 6 && rmeta->d.extradata)
3178 ? reinterpret_cast<const QMetaObjectExtraData *>(rmeta->d.extradata)->static_metacall : 0;
3180 QOrderedMutexLocker locker(signalSlotLock(sender),
3181 signalSlotLock(receiver));
3183 if (type & Qt::UniqueConnection) {
3184 QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
3185 if (connectionLists && connectionLists->count() > signal_index) {
3186 const QObjectPrivate::Connection *c2 =
3187 (*connectionLists)[signal_index].first;
3189 int method_index_absolute = method_index + method_offset;
3192 if (c2->receiver == receiver && c2->method() == method_index_absolute)
3194 c2 = c2->nextConnectionList;
3197 type &= Qt::UniqueConnection - 1;
3200 QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
3203 c->method_relative = method_index;
3204 c->method_offset = method_offset;
3205 c->connectionType = type;
3206 c->argumentTypes = types;
3207 c->nextConnectionList = 0;
3208 c->callFunction = callFunction;
3211 QObjectPrivate::get(s)->addConnection(signal_index, c);
3217 c->prev = &(QObjectPrivate::get(r)->senders);
3221 c->next->prev = &c->next;
3223 QObjectPrivate *const sender_d = QObjectPrivate::get(s);
3224 if (signal_index < 0) {
3225 sender_d->connectedSignals[0] = sender_d->connectedSignals[1] = ~0;
3226 } else if (signal_index < (int)sizeof(sender_d->connectedSignals) * 8) {
3227 sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f));
3235 bool QMetaObject::disconnect(const QObject *sender, int signal_index,
3236 const QObject *receiver, int method_index)
3238 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
3239 return QMetaObjectPrivate::disconnect(sender, signal_index,
3240 receiver, method_index);
3245 Disconnect a single signal connection. If QMetaObject::connect() has been called
3246 multiple times for the same sender, signal_index, receiver and method_index only
3247 one of these connections will be removed.
3249 bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
3250 const QObject *receiver, int method_index)
3252 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
3253 return QMetaObjectPrivate::disconnect(sender, signal_index,
3254 receiver, method_index,
3255 QMetaObjectPrivate::DisconnectOne);
3259 Helper function to remove the connection from the senders list and setting the receivers to 0
3261 bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
3262 const QObject *receiver, int method_index,
3263 QMutex *senderMutex, DisconnectType disconnectType)
3265 bool success = false;
3268 && (receiver == 0 || (c->receiver == receiver
3269 && (method_index < 0 || c->method() == method_index)))) {
3270 bool needToUnlock = false;
3271 QMutex *receiverMutex = 0;
3273 receiverMutex = signalSlotLock(c->receiver);
3274 // need to relock this receiver and sender in the correct order
3275 needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
3280 c->next->prev = c->prev;
3284 receiverMutex->unlockInline();
3290 if (disconnectType == DisconnectOne)
3293 c = c->nextConnectionList;
3299 Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3301 bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
3302 const QObject *receiver, int method_index,
3303 DisconnectType disconnectType)
3308 QObject *s = const_cast<QObject *>(sender);
3310 QMutex *senderMutex = signalSlotLock(sender);
3311 QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
3312 QOrderedMutexLocker locker(senderMutex, receiverMutex);
3314 QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
3315 if (!connectionLists)
3318 // prevent incoming connections changing the connectionLists while unlocked
3319 ++connectionLists->inUse;
3321 bool success = false;
3322 if (signal_index < 0) {
3323 // remove from all connection lists
3324 for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
3325 QObjectPrivate::Connection *c =
3326 (*connectionLists)[signal_index].first;
3327 if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
3329 connectionLists->dirty = true;
3332 } else if (signal_index < connectionLists->count()) {
3333 QObjectPrivate::Connection *c =
3334 (*connectionLists)[signal_index].first;
3335 if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
3337 connectionLists->dirty = true;
3341 --connectionLists->inUse;
3342 Q_ASSERT(connectionLists->inUse >= 0);
3343 if (connectionLists->orphaned && !connectionLists->inUse)
3344 delete connectionLists;
3350 \fn void QMetaObject::connectSlotsByName(QObject *object)
3352 Searches recursively for all child objects of the given \a object, and connects
3353 matching signals from them to slots of \a object that follow the following form:
3355 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 33
3357 Let's assume our object has a child object of type QPushButton with
3358 the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
3359 button's \c{clicked()} signal would be:
3361 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 34
3363 \sa QObject::setObjectName()
3365 void QMetaObject::connectSlotsByName(QObject *o)
3369 const QMetaObject *mo = o->metaObject();
3371 const QObjectList list = o->findChildren<QObject *>(QString());
3372 for (int i = 0; i < mo->methodCount(); ++i) {
3373 const char *slot = mo->method(i).signature();
3375 if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
3377 bool foundIt = false;
3378 for(int j = 0; j < list.count(); ++j) {
3379 const QObject *co = list.at(j);
3380 QByteArray objName = co->objectName().toAscii();
3381 int len = objName.length();
3382 if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')
3384 int sigIndex = co->d_func()->signalIndex(slot + len + 4);
3385 if (sigIndex < 0) { // search for compatible signals
3386 const QMetaObject *smo = co->metaObject();
3387 int slotlen = qstrlen(slot + len + 4) - 1;
3388 for (int k = 0; k < co->metaObject()->methodCount(); ++k) {
3389 QMetaMethod method = smo->method(k);
3390 if (method.methodType() != QMetaMethod::Signal)
3393 if (!qstrncmp(method.signature(), slot + len + 4, slotlen)) {
3394 int signalOffset, methodOffset;
3395 computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
3396 sigIndex = k + - methodOffset + signalOffset;
3403 if (QMetaObjectPrivate::connect(co, sigIndex, o, i)) {
3409 // we found our slot, now skip all overloads
3410 while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
3412 } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
3413 qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
3418 static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
3420 if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
3421 QMetaMethod m = sender->metaObject()->method(signal);
3422 int *tmp = queuedConnectionTypes(m.parameterTypes());
3423 if (!tmp) // cannot queue arguments
3424 tmp = &DIRECT_CONNECTION_ONLY;
3425 if (!c->argumentTypes.testAndSetOrdered(0, tmp)) {
3426 if (tmp != &DIRECT_CONNECTION_ONLY)
3430 if (c->argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
3432 int nargs = 1; // include return type
3433 while (c->argumentTypes[nargs-1])
3435 int *types = (int *) qMalloc(nargs*sizeof(int));
3437 void **args = (void **) qMalloc(nargs*sizeof(void *));
3439 types[0] = 0; // return type
3440 args[0] = 0; // return value
3441 for (int n = 1; n < nargs; ++n)
3442 args[n] = QMetaType::construct((types[n] = c->argumentTypes[n-1]), argv[n]);
3443 QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method_offset,
3446 sender, signal, nargs,
3453 Used to be called from QMetaObject::activate(QObject *, QMetaObject *, int, int, void **) before Qt 4.6
3455 void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)
3457 Q_UNUSED(to_signal_index);
3458 activate(sender, from_signal_index, argv);
3463 void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
3468 computeOffsets(m, &signalOffset, &methodOffset);
3470 int signal_index = signalOffset + local_signal_index;
3472 if (!sender->d_func()->isSignalConnected(signal_index))
3473 return; // nothing connected to these signals, and no spy
3475 if (sender->d_func()->blockSig)
3478 int signal_absolute_index = methodOffset + local_signal_index;
3480 void *empty_argv[] = { 0 };
3481 if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
3482 qt_signal_spy_callback_set.signal_begin_callback(sender, signal_absolute_index,
3483 argv ? argv : empty_argv);
3486 Qt::HANDLE currentThreadId = QThread::currentThreadId();
3488 QMutexLocker locker(signalSlotLock(sender));
3489 QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
3490 if (!connectionLists) {
3492 if (qt_signal_spy_callback_set.signal_end_callback != 0)
3493 qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
3496 ++connectionLists->inUse;
3499 const QObjectPrivate::ConnectionList *list;
3500 if (signal_index < connectionLists->count())
3501 list = &connectionLists->at(signal_index);
3503 list = &connectionLists->allsignals;
3506 QObjectPrivate::Connection *c = list->first;
3508 // We need to check against last here to ensure that signals added
3509 // during the signal emission are not emitted in this emission.
3510 QObjectPrivate::Connection *last = list->last;
3516 QObject * const receiver = c->receiver;
3517 const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId;
3519 // determine if this connection should be sent immediately or
3520 // put into the event queue
3521 if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
3522 || (c->connectionType == Qt::QueuedConnection)) {
3523 queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
3525 #ifndef QT_NO_THREAD
3526 } else if (c->connectionType == Qt::BlockingQueuedConnection) {
3528 if (receiverInSameThread) {
3529 qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "