1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include "qobject_p.h"
44 #include "qmetaobject_p.h"
46 #include "qabstracteventdispatcher.h"
47 #include "qabstracteventdispatcher_p.h"
48 #include "qcoreapplication.h"
49 #include "qcoreapplication_p.h"
51 #include "qmetaobject.h"
53 #include <qregularexpression.h>
55 #include <private/qthread_p.h>
59 #include <qvarlengtharray.h>
61 #include <qsemaphore.h>
62 #include <qsharedpointer.h>
64 #include <private/qorderedmutexlocker_p.h>
73 struct QObjectPrivate::ExtraData
76 #ifndef QT_NO_USERDATA
77 QVector<QObjectUserData *> userData;
79 QList<QByteArray> propertyNames;
80 QList<QVariant> propertyValues;
83 static int DIRECT_CONNECTION_ONLY = 0;
85 static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
87 int *types = new int [typeNames.count() + 1];
89 for (int i = 0; i < typeNames.count(); ++i) {
90 const QByteArray typeName = typeNames.at(i);
91 if (typeName.endsWith('*'))
92 types[i] = QMetaType::VoidStar;
94 types[i] = QMetaType::type(typeName);
97 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
98 "(Make sure '%s' is registered using qRegisterMetaType().)",
99 typeName.constData(), typeName.constData());
104 types[typeNames.count()] = 0;
109 static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
111 QScopedArrayPointer<int> types(new int [argc + 1]);
112 for (int i = 0; i < argc; ++i) {
113 const QArgumentType &type = argumentTypes[i];
115 types[i] = type.type();
116 else if (type.name().endsWith('*'))
117 types[i] = QMetaType::VoidStar;
119 types[i] = QMetaType::type(type.name());
122 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
123 "(Make sure '%s' is registered using qRegisterMetaType().)",
124 type.name().constData(), type.name().constData());
133 static QBasicMutex _q_ObjectMutexPool[131];
136 * mutex to be locked when accessing the connectionlists or the senders list
138 static inline QMutex *signalSlotLock(const QObject *o)
140 return static_cast<QMutex *>(&_q_ObjectMutexPool[
141 uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]);
144 extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
147 extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
150 struct QConnectionSenderSwitcher {
152 QObjectPrivate::Sender *previousSender;
153 QObjectPrivate::Sender currentSender;
156 inline QConnectionSenderSwitcher() : switched(false) {}
158 inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id)
160 switchSender(receiver, sender, signal_absolute_id);
163 inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id)
165 this->receiver = receiver;
166 currentSender.sender = sender;
167 currentSender.signal = signal_absolute_id;
168 currentSender.ref = 1;
169 previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender);
173 inline ~QConnectionSenderSwitcher()
176 QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender);
179 Q_DISABLE_COPY(QConnectionSenderSwitcher)
183 void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
184 void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
185 void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0;
186 void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = 0;
188 QObjectData::~QObjectData() {}
190 QObjectPrivate::QObjectPrivate(int version)
191 : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
193 if (version != QObjectPrivateVersion)
194 qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
195 version, QObjectPrivateVersion);
197 // QObjectData initialization
199 parent = 0; // no parent yet. It is set by setParent()
200 isWidget = false; // assume not a widget object
201 blockSig = false; // not blocking signals
202 wasDeleted = false; // double-delete catcher
203 isDeletingChildren = false; // set by deleteChildren()
204 sendChildEvents = true; // if we should send ChildInsert and ChildRemove events to parent
205 receiveChildEvents = true;
208 connectedSignals[0] = connectedSignals[1] = 0;
213 QObjectPrivate::~QObjectPrivate()
215 if (!runningTimers.isEmpty()) {
216 // unregister pending timers
217 if (threadData->eventDispatcher)
218 threadData->eventDispatcher->unregisterTimers(q_ptr);
220 // release the timer ids back to the pool
221 for (int i = 0; i < runningTimers.size(); ++i)
222 QAbstractEventDispatcherPrivate::releaseTimerId(runningTimers.at(i));
226 QCoreApplication::removePostedEvents(q_ptr, 0);
230 delete static_cast<QAbstractDynamicMetaObject*>(metaObject);
231 #ifndef QT_NO_USERDATA
233 qDeleteAll(extraData->userData);
239 For a given metaobject, compute the signal offset, and the method offset (including signals)
241 static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
243 *signalOffset = *methodOffset = 0;
244 const QMetaObject *m = metaobject->d.superdata;
246 const QMetaObjectPrivate *d = QMetaObjectPrivate::get(m);
247 *methodOffset += d->methodCount;
248 Q_ASSERT(d->revision >= 4);
249 *signalOffset += d->signalCount;
255 This vector contains the all connections from an object.
257 Each object may have one vector containing the lists of
258 connections for a given signal. The index in the vector correspond
259 to the signal index. The signal index is the one returned by
260 QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal).
261 Negative index means connections to all signals.
263 This vector is protected by the object mutex (signalSlotMutexes())
265 Each Connection is also part of a 'senders' linked list. The mutex
266 of the receiver must be locked when touching the pointers of this
269 class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList>
272 bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse
273 bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet
274 int inUse; //number of functions that are currently accessing this object or its connections
275 QObjectPrivate::ConnectionList allsignals;
277 QObjectConnectionListVector()
278 : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
281 QObjectPrivate::ConnectionList &operator[](int at)
285 return QVector<QObjectPrivate::ConnectionList>::operator[](at);
289 // Used by QAccessibleWidget
290 bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
293 int signal_index = signalIndex(signal);
294 if (signal_index < 0)
296 QMutexLocker locker(signalSlotLock(q));
297 if (connectionLists) {
298 if (signal_index < connectionLists->count()) {
299 const QObjectPrivate::Connection *c =
300 connectionLists->at(signal_index).first;
303 if (c->receiver == receiver)
305 c = c->nextConnectionList;
312 // Used by QAccessibleWidget
313 QObjectList QObjectPrivate::receiverList(const char *signal) const
316 QObjectList returnValue;
317 int signal_index = signalIndex(signal);
318 if (signal_index < 0)
320 QMutexLocker locker(signalSlotLock(q));
321 if (connectionLists) {
322 if (signal_index < connectionLists->count()) {
323 const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
327 returnValue << c->receiver;
328 c = c->nextConnectionList;
335 // Used by QAccessibleWidget
336 QObjectList QObjectPrivate::senderList() const
338 QObjectList returnValue;
339 QMutexLocker locker(signalSlotLock(q_func()));
340 for (Connection *c = senders; c; c = c->next)
341 returnValue << c->sender;
346 Add the connection \a c to to the list of connections of the sender's object
347 for the specified \a signal
349 The signalSlotLock() of the sender and receiver must be locked while calling
352 Will also add the connection in the sender's list of the receiver.
354 void QObjectPrivate::addConnection(int signal, Connection *c)
356 Q_ASSERT(c->sender == q_ptr);
357 if (!connectionLists)
358 connectionLists = new QObjectConnectionListVector();
359 if (signal >= connectionLists->count())
360 connectionLists->resize(signal + 1);
362 ConnectionList &connectionList = (*connectionLists)[signal];
363 if (connectionList.last) {
364 connectionList.last->nextConnectionList = c;
366 connectionList.first = c;
368 connectionList.last = c;
370 cleanConnectionLists();
372 c->prev = &(QObjectPrivate::get(c->receiver)->senders);
376 c->next->prev = &c->next;
379 connectedSignals[0] = connectedSignals[1] = ~0;
380 } else if (signal < (int)sizeof(connectedSignals) * 8) {
381 connectedSignals[signal >> 5] |= (1 << (signal & 0x1f));
385 void QObjectPrivate::cleanConnectionLists()
387 if (connectionLists->dirty && !connectionLists->inUse) {
388 // remove broken connections
389 for (int signal = -1; signal < connectionLists->count(); ++signal) {
390 QObjectPrivate::ConnectionList &connectionList =
391 (*connectionLists)[signal];
393 // Set to the last entry in the connection list that was *not*
394 // deleted. This is needed to update the list's last pointer
395 // at the end of the cleanup.
396 QObjectPrivate::Connection *last = 0;
398 QObjectPrivate::Connection **prev = &connectionList.first;
399 QObjectPrivate::Connection *c = *prev;
403 prev = &c->nextConnectionList;
406 QObjectPrivate::Connection *next = c->nextConnectionList;
413 // Correct the connection list's last pointer.
414 // As conectionList.last could equal last, this could be a noop
415 connectionList.last = last;
417 connectionLists->dirty = false;
423 QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
424 const QObject *sender, int signalId,
425 int nargs, int *types, void **args, QSemaphore *semaphore)
426 : QEvent(MetaCall), slotObj_(0), sender_(sender), signalId_(signalId),
427 nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
428 callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
433 QMetaCallEvent::QMetaCallEvent(QObject::QSlotObjectBase *slotO, const QObject *sender, int signalId,
434 int nargs, int *types, void **args, QSemaphore *semaphore)
435 : QEvent(MetaCall), slotObj_(slotO), sender_(sender), signalId_(signalId),
436 nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
437 callFunction_(0), method_offset_(0), method_relative_(-1)
445 QMetaCallEvent::~QMetaCallEvent()
448 for (int i = 0; i < nargs_; ++i) {
449 if (types_[i] && args_[i])
450 QMetaType::destroy(types_[i], args_[i]);
457 semaphore_->release();
459 if (slotObj_ && !slotObj_->ref.deref())
465 void QMetaCallEvent::placeMetaCall(QObject *object)
468 slotObj_->call(object, args_);
469 } else if (callFunction_ && method_offset_ <= object->metaObject()->methodOffset()) {
470 callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
472 QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
478 \brief The QObject class is the base class of all Qt objects.
484 QObject is the heart of the Qt \l{Object Model}. The central
485 feature in this model is a very powerful mechanism for seamless
486 object communication called \l{signals and slots}. You can
487 connect a signal to a slot with connect() and destroy the
488 connection with disconnect(). To avoid never ending notification
489 loops you can temporarily block signals with blockSignals(). The
490 protected functions connectNotify() and disconnectNotify() make
491 it possible to track connections.
493 QObjects organize themselves in \l {Object Trees & Ownership}
494 {object trees}. When you create a QObject with another object as
495 parent, the object will automatically add itself to the parent's
496 children() list. The parent takes ownership of the object; i.e.,
497 it will automatically delete its children in its destructor. You
498 can look for an object by name and optionally type using
499 findChild() or findChildren().
501 Every object has an objectName() and its class name can be found
502 via the corresponding metaObject() (see QMetaObject::className()).
503 You can determine whether the object's class inherits another
504 class in the QObject inheritance hierarchy by using the
507 When an object is deleted, it emits a destroyed() signal. You can
508 catch this signal to avoid dangling references to QObjects.
510 QObjects can receive events through event() and filter the events
511 of other objects. See installEventFilter() and eventFilter() for
512 details. A convenience handler, childEvent(), can be reimplemented
513 to catch child events.
515 Events are delivered in the thread in which the object was
516 created; see \l{Thread Support in Qt} and thread() for details.
517 Note that event processing is not done at all for QObjects with no
518 thread affinity (thread() returns zero). Use the moveToThread()
519 function to change the thread affinity for an object and its
520 children (the object cannot be moved if it has a parent).
522 Last but not least, QObject provides the basic timer support in
523 Qt; see QTimer for high-level support for timers.
525 Notice that the Q_OBJECT macro is mandatory for any object that
526 implements signals, slots or properties. You also need to run the
527 \l{moc}{Meta Object Compiler} on the source file. We strongly
528 recommend the use of this macro in all subclasses of QObject
529 regardless of whether or not they actually use signals, slots and
530 properties, since failure to do so may lead certain functions to
531 exhibit strange behavior.
533 All Qt widgets inherit QObject. The convenience function
534 isWidgetType() returns whether an object is actually a widget. It
536 \l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
537 \e{obj}->\l{inherits()}{inherits}("QWidget").
539 Some QObject functions, e.g. children(), return a QObjectList.
540 QObjectList is a typedef for QList<QObject *>.
542 \target No copy constructor
543 \section1 No copy constructor or assignment operator
545 QObject has neither a copy constructor nor an assignment operator.
546 This is by design. Actually, they are declared, but in a
547 \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
548 Qt classes derived from QObject (direct or indirect) use this
549 macro to declare their copy constructor and assignment operator to
550 be private. The reasoning is found in the discussion on
551 \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
554 The main consequence is that you should use pointers to QObject
555 (or to your QObject subclass) where you might otherwise be tempted
556 to use your QObject subclass as a value. For example, without a
557 copy constructor, you can't use a subclass of QObject as the value
558 to be stored in one of the container classes. You must store
561 \section1 Auto-Connection
563 Qt's meta-object system provides a mechanism to automatically connect
564 signals and slots between QObject subclasses and their children. As long
565 as objects are defined with suitable object names, and slots follow a
566 simple naming convention, this connection can be performed at run-time
567 by the QMetaObject::connectSlotsByName() function.
569 \l uic generates code that invokes this function to enable
570 auto-connection to be performed between widgets on forms created
571 with \e{Qt Designer}. More information about using auto-connection with \e{Qt Designer} is
572 given in the \l{Using a Designer UI File in Your Application} section of
573 the \e{Qt Designer} manual.
575 \section1 Dynamic Properties
577 From Qt 4.2, dynamic properties can be added to and removed from QObject
578 instances at run-time. Dynamic properties do not need to be declared at
579 compile-time, yet they provide the same advantages as static properties
580 and are manipulated using the same API - using property() to read them
581 and setProperty() to write them.
583 From Qt 4.3, dynamic properties are supported by
584 \l{Qt Designer's Widget Editing Mode#The Property Editor}{Qt Designer},
585 and both standard Qt widgets and user-created forms can be given dynamic
588 \section1 Internationalization (i18n)
590 All QObject subclasses support Qt's translation features, making it possible
591 to translate an application's user interface into different languages.
593 To make user-visible text translatable, it must be wrapped in calls to
594 the tr() function. This is explained in detail in the
595 \l{Writing Source Code for Translation} document.
597 \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
598 \sa {Object Trees & Ownership}
604 Returns a pointer to the object named \a name that inherits \a
605 type and with a given \a parent.
607 Returns 0 if there is no such child.
609 \snippet code/src_corelib_kernel_qobject.cpp 0
612 void *qt_find_obj_child(QObject *parent, const char *type, const QString &name)
614 QObjectList list = parent->children();
615 if (list.size() == 0) return 0;
616 for (int i = 0; i < list.size(); ++i) {
617 QObject *obj = list.at(i);
618 if (name == obj->objectName() && obj->inherits(type))
625 /*****************************************************************************
626 QObject member functions
627 *****************************************************************************/
629 // check the constructor's parent thread argument
630 static bool check_parent_thread(QObject *parent,
631 QThreadData *parentThreadData,
632 QThreadData *currentThreadData)
634 if (parent && parentThreadData != currentThreadData) {
635 QThread *parentThread = parentThreadData->thread;
636 QThread *currentThread = currentThreadData->thread;
637 qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
638 "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
639 parent->metaObject()->className(),
641 parentThread ? parentThread->metaObject()->className() : "QThread",
643 currentThread ? currentThread->metaObject()->className() : "QThread",
651 Constructs an object with parent object \a parent.
653 The parent of an object may be viewed as the object's owner. For
654 instance, a \l{QDialog}{dialog box} is the parent of the \uicontrol{OK}
655 and \uicontrol{Cancel} buttons it contains.
657 The destructor of a parent object destroys all child objects.
659 Setting \a parent to 0 constructs an object with no parent. If the
660 object is a widget, it will become a top-level window.
662 \sa parent(), findChild(), findChildren()
665 QObject::QObject(QObject *parent)
666 : d_ptr(new QObjectPrivate)
670 d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
671 d->threadData->ref();
674 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
678 d->threadData->deref();
687 QObject::QObject(QObjectPrivate &dd, QObject *parent)
692 d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
693 d->threadData->ref();
696 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
701 d->parent->d_func()->children.append(this);
703 // no events sent here, this is done at the end of the QWidget constructor
708 d->threadData->deref();
716 Destroys the object, deleting all its child objects.
718 All signals to and from the object are automatically disconnected, and
719 any pending posted events for the object are removed from the event
720 queue. However, it is often safer to use deleteLater() rather than
721 deleting a QObject subclass directly.
723 \warning All child objects are deleted. If any of these objects
724 are on the stack or global, sooner or later your program will
725 crash. We do not recommend holding pointers to child objects from
726 outside the parent. If you still do, the destroyed() signal gives
727 you an opportunity to detect when an object is destroyed.
729 \warning Deleting a QObject while pending events are waiting to
730 be delivered can cause a crash. You must not delete the QObject
731 directly if it exists in a different thread than the one currently
732 executing. Use deleteLater() instead, which will cause the event
733 loop to delete the object after all pending events have been
742 d->wasDeleted = true;
743 d->blockSig = 0; // unblock signals so we always emit destroyed()
745 QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.load();
746 if (sharedRefcount) {
747 if (sharedRefcount->strongref.load() > 0) {
748 qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
749 // but continue deleting, it's too late to stop anyway
752 // indicate to all QWeakPointers that this QObject has now been deleted
753 sharedRefcount->strongref.store(0);
754 if (!sharedRefcount->weakref.deref())
755 delete sharedRefcount;
758 if (d->isSignalConnected(0)) {
760 emit destroyed(this);
762 // all the signal/slots connections are still in place - if we don't
763 // quit now, we will crash pretty soon.
764 qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");
769 if (d->declarativeData)
770 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
772 // set ref to zero to indicate that this object has been deleted
773 if (d->currentSender != 0)
774 d->currentSender->ref = 0;
775 d->currentSender = 0;
777 if (d->connectionLists || d->senders) {
778 QMutex *signalSlotMutex = signalSlotLock(this);
779 QMutexLocker locker(signalSlotMutex);
781 // disconnect all receivers
782 if (d->connectionLists) {
783 ++d->connectionLists->inUse;
784 int connectionListsCount = d->connectionLists->count();
785 for (int signal = -1; signal < connectionListsCount; ++signal) {
786 QObjectPrivate::ConnectionList &connectionList =
787 (*d->connectionLists)[signal];
789 while (QObjectPrivate::Connection *c = connectionList.first) {
791 connectionList.first = c->nextConnectionList;
796 QMutex *m = signalSlotLock(c->receiver);
797 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
801 if (c->next) c->next->prev = c->prev;
807 connectionList.first = c->nextConnectionList;
812 if (!--d->connectionLists->inUse) {
813 delete d->connectionLists;
815 d->connectionLists->orphaned = true;
817 d->connectionLists = 0;
820 // disconnect all senders
821 QObjectPrivate::Connection *node = d->senders;
823 QObject *sender = node->sender;
824 QMutex *m = signalSlotLock(sender);
826 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
827 //the node has maybe been removed while the mutex was unlocked in relock?
828 if (!node || node->sender != sender) {
833 QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists;
835 senderLists->dirty = true;
843 if (!d->children.isEmpty())
846 qt_removeObject(this);
848 if (d->parent) // remove it from parent object
849 d->setParent_helper(0);
852 QObjectPrivate::Connection::~Connection()
854 if (ownArgumentTypes) {
855 const int *v = argumentTypes.load();
856 if (v != &DIRECT_CONNECTION_ONLY)
859 if (isSlotObject && !slotObj->ref.deref())
865 \fn QMetaObject *QObject::metaObject() const
867 Returns a pointer to the meta-object of this object.
869 A meta-object contains information about a class that inherits
870 QObject, e.g. class name, superclass name, properties, signals and
871 slots. Every QObject subclass that contains the Q_OBJECT macro will have a
874 The meta-object information is required by the signal/slot
875 connection mechanism and the property system. The inherits()
876 function also makes use of the meta-object.
878 If you have no pointer to an actual object instance but still
879 want to access the meta-object of a class, you can use \l
884 \snippet code/src_corelib_kernel_qobject.cpp 1
890 \variable QObject::staticMetaObject
892 This variable stores the meta-object for the class.
894 A meta-object contains information about a class that inherits
895 QObject, e.g. class name, superclass name, properties, signals and
896 slots. Every class that contains the Q_OBJECT macro will also have
899 The meta-object information is required by the signal/slot
900 connection mechanism and the property system. The inherits()
901 function also makes use of the meta-object.
903 If you have a pointer to an object, you can use metaObject() to
904 retrieve the meta-object associated with that object.
908 \snippet code/src_corelib_kernel_qobject.cpp 2
913 /*! \fn T *qobject_cast<T *>(QObject *object)
916 Returns the given \a object cast to type T if the object is of type
917 T (or of a subclass); otherwise returns 0. If \a object is 0 then
918 it will also return 0.
920 The class T must inherit (directly or indirectly) QObject and be
921 declared with the \l Q_OBJECT macro.
923 A class is considered to inherit itself.
927 \snippet code/src_corelib_kernel_qobject.cpp 3
929 The qobject_cast() function behaves similarly to the standard C++
930 \c dynamic_cast(), with the advantages that it doesn't require
931 RTTI support and it works across dynamic library boundaries.
933 qobject_cast() can also be used in conjunction with interfaces;
934 see the \l{tools/plugandpaint}{Plug & Paint} example for details.
936 \warning If T isn't declared with the Q_OBJECT macro, this
937 function's return value is undefined.
939 \sa QObject::inherits()
943 \fn bool QObject::inherits(const char *className) const
945 Returns true if this object is an instance of a class that
946 inherits \a className or a QObject subclass that inherits \a
947 className; otherwise returns false.
949 A class is considered to inherit itself.
953 \snippet code/src_corelib_kernel_qobject.cpp 4
955 If you need to determine whether an object is an instance of a particular
956 class for the purpose of casting it, consider using qobject_cast<Type *>(object)
959 \sa metaObject(), qobject_cast()
963 \property QObject::objectName
965 \brief the name of this object
967 You can find an object by name (and type) using findChild().
968 You can find a set of objects with findChildren().
970 \snippet code/src_corelib_kernel_qobject.cpp 5
972 By default, this property contains an empty string.
974 \sa metaObject(), QMetaObject::className()
977 QString QObject::objectName() const
980 return d->objectName;
984 Sets the object's name to \a name.
986 void QObject::setObjectName(const QString &name)
989 if (d->objectName != name) {
990 d->objectName = name;
991 if (d->declarativeData)
992 d->declarativeData->objectNameChanged(d->declarativeData, this);
993 emit objectNameChanged(d->objectName);
997 /*! \fn void QObject::objectNameChanged(const QString &objectName)
999 This signal is emitted after the object's name has been changed. The new object name is passed as \a objectName.
1001 \sa QObject::objectName
1005 \fn bool QObject::isWidgetType() const
1007 Returns true if the object is a widget; otherwise returns false.
1009 Calling this function is equivalent to calling
1010 inherits("QWidget"), except that it is much faster.
1015 This virtual function receives events to an object and should
1016 return true if the event \a e was recognized and processed.
1018 The event() function can be reimplemented to customize the
1019 behavior of an object.
1021 \sa installEventFilter(), timerEvent(), QApplication::sendEvent(),
1022 QApplication::postEvent(), QWidget::event()
1025 bool QObject::event(QEvent *e)
1027 switch (e->type()) {
1029 timerEvent((QTimerEvent*)e);
1032 case QEvent::ChildAdded:
1033 case QEvent::ChildPolished:
1034 case QEvent::ChildRemoved:
1035 childEvent((QChildEvent*)e);
1038 case QEvent::DeferredDelete:
1039 qDeleteInEventHandler(this);
1042 case QEvent::MetaCall:
1044 QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
1046 QConnectionSenderSwitcher sw(this, const_cast<QObject*>(mce->sender()), mce->signalId());
1048 mce->placeMetaCall(this);
1052 case QEvent::ThreadChange: {
1054 QThreadData *threadData = d->threadData;
1055 QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
1056 if (eventDispatcher) {
1057 QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
1058 if (!timers.isEmpty()) {
1059 // do not to release our timer ids back to the pool (since the timer ids are moving to a new thread).
1060 eventDispatcher->unregisterTimers(this);
1061 QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
1062 Q_ARG(void*, (new QList<QAbstractEventDispatcher::TimerInfo>(timers))));
1069 if (e->type() >= QEvent::User) {
1079 \fn void QObject::timerEvent(QTimerEvent *event)
1081 This event handler can be reimplemented in a subclass to receive
1082 timer events for the object.
1084 QTimer provides a higher-level interface to the timer
1085 functionality, and also more general information about timers. The
1086 timer event is passed in the \a event parameter.
1088 \sa startTimer(), killTimer(), event()
1091 void QObject::timerEvent(QTimerEvent *)
1097 This event handler can be reimplemented in a subclass to receive
1098 child events. The event is passed in the \a event parameter.
1100 QEvent::ChildAdded and QEvent::ChildRemoved events are sent to
1101 objects when children are added or removed. In both cases you can
1102 only rely on the child being a QObject, or if isWidgetType()
1103 returns true, a QWidget. (This is because, in the
1104 \l{QEvent::ChildAdded}{ChildAdded} case, the child is not yet
1105 fully constructed, and in the \l{QEvent::ChildRemoved}{ChildRemoved}
1106 case it might have been destructed already).
1108 QEvent::ChildPolished events are sent to widgets when children
1109 are polished, or when polished children are added. If you receive
1110 a child polished event, the child's construction is usually
1111 completed. However, this is not guaranteed, and multiple polish
1112 events may be delivered during the execution of a widget's
1115 For every child widget, you receive one
1116 \l{QEvent::ChildAdded}{ChildAdded} event, zero or more
1117 \l{QEvent::ChildPolished}{ChildPolished} events, and one
1118 \l{QEvent::ChildRemoved}{ChildRemoved} event.
1120 The \l{QEvent::ChildPolished}{ChildPolished} event is omitted if
1121 a child is removed immediately after it is added. If a child is
1122 polished several times during construction and destruction, you
1123 may receive several child polished events for the same child,
1124 each time with a different virtual table.
1129 void QObject::childEvent(QChildEvent * /* event */)
1135 This event handler can be reimplemented in a subclass to receive
1136 custom events. Custom events are user-defined events with a type
1137 value at least as large as the QEvent::User item of the
1138 QEvent::Type enum, and is typically a QEvent subclass. The event
1139 is passed in the \a event parameter.
1143 void QObject::customEvent(QEvent * /* event */)
1150 Filters events if this object has been installed as an event
1151 filter for the \a watched object.
1153 In your reimplementation of this function, if you want to filter
1154 the \a event out, i.e. stop it being handled further, return
1155 true; otherwise return false.
1158 \snippet code/src_corelib_kernel_qobject.cpp 6
1160 Notice in the example above that unhandled events are passed to
1161 the base class's eventFilter() function, since the base class
1162 might have reimplemented eventFilter() for its own internal
1165 \warning If you delete the receiver object in this function, be
1166 sure to return true. Otherwise, Qt will forward the event to the
1167 deleted object and the program might crash.
1169 \sa installEventFilter()
1172 bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
1178 \fn bool QObject::signalsBlocked() const
1180 Returns true if signals are blocked; otherwise returns false.
1182 Signals are not blocked by default.
1188 If \a block is true, signals emitted by this object are blocked
1189 (i.e., emitting a signal will not invoke anything connected to it).
1190 If \a block is false, no such blocking will occur.
1192 The return value is the previous value of signalsBlocked().
1194 Note that the destroyed() signal will be emitted even if the signals
1195 for this object have been blocked.
1197 \sa signalsBlocked()
1200 bool QObject::blockSignals(bool block)
1203 bool previous = d->blockSig;
1204 d->blockSig = block;
1209 Returns the thread in which the object lives.
1213 QThread *QObject::thread() const
1215 return d_func()->threadData->thread;
1219 Changes the thread affinity for this object and its children. The
1220 object cannot be moved if it has a parent. Event processing will
1221 continue in the \a targetThread.
1223 To move an object to the main thread, use QApplication::instance()
1224 to retrieve a pointer to the current application, and then use
1225 QApplication::thread() to retrieve the thread in which the
1226 application lives. For example:
1228 \snippet code/src_corelib_kernel_qobject.cpp 7
1230 If \a targetThread is zero, all event processing for this object
1231 and its children stops.
1233 Note that all active timers for the object will be reset. The
1234 timers are first stopped in the current thread and restarted (with
1235 the same interval) in the \a targetThread. As a result, constantly
1236 moving an object between threads can postpone timer events
1239 A QEvent::ThreadChange event is sent to this object just before
1240 the thread affinity is changed. You can handle this event to
1241 perform any special processing. Note that any new events that are
1242 posted to this object will be handled in the \a targetThread.
1244 \warning This function is \e not thread-safe; the current thread
1245 must be same as the current thread affinity. In other words, this
1246 function can only "push" an object from the current thread to
1247 another thread, it cannot "pull" an object from any arbitrary
1248 thread to the current thread.
1252 void QObject::moveToThread(QThread *targetThread)
1256 if (d->threadData->thread == targetThread) {
1257 // object is already in this thread
1261 if (d->parent != 0) {
1262 qWarning("QObject::moveToThread: Cannot move objects with a parent");
1266 qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
1270 QThreadData *currentData = QThreadData::current();
1271 QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : new QThreadData(0);
1272 if (d->threadData->thread == 0 && currentData == targetData) {
1273 // one exception to the rule: we allow moving objects with no thread affinity to the current thread
1274 currentData = d->threadData;
1275 } else if (d->threadData != currentData) {
1276 qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
1277 "Cannot move to target thread (%p)\n",
1278 currentData->thread, d->threadData->thread, targetData->thread);
1281 qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. "
1282 "Check that all plugins are compiled against the right Qt binaries. Export "
1283 "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
1290 d->moveToThread_helper();
1292 QOrderedMutexLocker locker(¤tData->postEventList.mutex,
1293 &targetData->postEventList.mutex);
1295 // keep currentData alive (since we've got it locked)
1299 d_func()->setThreadData_helper(currentData, targetData);
1303 // now currentData can commit suicide if it wants to
1304 currentData->deref();
1307 void QObjectPrivate::moveToThread_helper()
1310 QEvent e(QEvent::ThreadChange);
1311 QCoreApplication::sendEvent(q, &e);
1312 for (int i = 0; i < children.size(); ++i) {
1313 QObject *child = children.at(i);
1314 child->d_func()->moveToThread_helper();
1318 void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
1322 // move posted events
1323 int eventsMoved = 0;
1324 for (int i = 0; i < currentData->postEventList.size(); ++i) {
1325 const QPostEvent &pe = currentData->postEventList.at(i);
1328 if (pe.receiver == q) {
1329 // move this post event to the targetList
1330 targetData->postEventList.addEvent(pe);
1331 const_cast<QPostEvent &>(pe).event = 0;
1335 if (eventsMoved > 0 && targetData->eventDispatcher) {
1336 targetData->canWait = false;
1337 targetData->eventDispatcher->wakeUp();
1340 // the current emitting thread shouldn't restore currentSender after calling moveToThread()
1342 currentSender->ref = 0;
1345 // set new thread data
1347 threadData->deref();
1348 threadData = targetData;
1350 for (int i = 0; i < children.size(); ++i) {
1351 QObject *child = children.at(i);
1352 child->d_func()->setThreadData_helper(currentData, targetData);
1356 void QObjectPrivate::_q_reregisterTimers(void *pointer)
1359 QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
1360 QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
1361 for (int i = 0; i < timerList->size(); ++i) {
1362 const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
1363 eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q);
1370 // The timer flag hasTimer is set when startTimer is called.
1371 // It is not reset when killing the timer because more than
1372 // one timer might be active.
1376 Starts a timer and returns a timer identifier, or returns zero if
1377 it could not start a timer.
1379 A timer event will occur every \a interval milliseconds until
1380 killTimer() is called. If \a interval is 0, then the timer event
1381 occurs once every time there are no more window system events to
1384 The virtual timerEvent() function is called with the QTimerEvent
1385 event parameter class when a timer event occurs. Reimplement this
1386 function to get timer events.
1388 If multiple timers are running, the QTimerEvent::timerId() can be
1389 used to find out which timer was activated.
1393 \snippet code/src_corelib_kernel_qobject.cpp 8
1395 Note that QTimer's accuracy depends on the underlying operating system and
1396 hardware. The \a timerType argument allows you to customize the accuracy of
1397 the timer. See Qt::TimerType for information on the different timer types.
1398 Most platforms support an accuracy of 20 milliseconds; some provide more.
1399 If Qt is unable to deliver the requested number of timer events, it will
1400 silently discard some.
1402 The QTimer class provides a high-level programming interface with
1403 single-shot timers and timer signals instead of events. There is
1404 also a QBasicTimer class that is more lightweight than QTimer and
1405 less clumsy than using timer IDs directly.
1407 \sa timerEvent(), killTimer(), QTimer::singleShot()
1410 int QObject::startTimer(int interval, Qt::TimerType timerType)
1415 qWarning("QObject::startTimer: QTimer cannot have a negative interval");
1419 if (!d->threadData->eventDispatcher) {
1420 qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread");
1423 int timerId = d->threadData->eventDispatcher->registerTimer(interval, timerType, this);
1424 d->runningTimers.append(timerId);
1429 Kills the timer with timer identifier, \a id.
1431 The timer identifier is returned by startTimer() when a timer
1434 \sa timerEvent(), startTimer()
1437 void QObject::killTimer(int id)
1441 int at = d->runningTimers.indexOf(id);
1443 // timer isn't owned by this object
1444 qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s), timer has not been killed",
1447 qPrintable(objectName()));
1451 if (d->threadData->eventDispatcher)
1452 d->threadData->eventDispatcher->unregisterTimer(id);
1454 d->runningTimers.remove(at);
1455 QAbstractEventDispatcherPrivate::releaseTimerId(id);
1461 \fn QObject *QObject::parent() const
1463 Returns a pointer to the parent object.
1469 \fn const QObjectList &QObject::children() const
1471 Returns a list of child objects.
1472 The QObjectList class is defined in the \c{<QObject>} header
1473 file as the following:
1475 \quotefromfile kernel/qobject.h
1476 \skipto /typedef .*QObjectList/
1477 \printuntil QObjectList
1479 The first child added is the \l{QList::first()}{first} object in
1480 the list and the last child added is the \l{QList::last()}{last}
1481 object in the list, i.e. new children are appended at the end.
1483 Note that the list order changes when QWidget children are
1484 \l{QWidget::raise()}{raised} or \l{QWidget::lower()}{lowered}. A
1485 widget that is raised becomes the last object in the list, and a
1486 widget that is lowered becomes the first object in the list.
1488 \sa findChild(), findChildren(), parent(), setParent()
1493 \fn T *QObject::findChild(const QString &name, Qt::FindChildOptions options) const
1495 Returns the child of this object that can be cast into type T and
1496 that is called \a name, or 0 if there is no such object.
1497 Omitting the \a name argument causes all object names to be matched.
1498 The search is performed recursively, unless \a options specifies the
1499 option FindDirectChildrenOnly.
1501 If there is more than one child matching the search, the most
1502 direct ancestor is returned. If there are several direct
1503 ancestors, it is undefined which one will be returned. In that
1504 case, findChildren() should be used.
1506 This example returns a child \l{QPushButton} of \c{parentWidget}
1507 named \c{"button1"}, even if the button isn't a direct child of
1510 \snippet code/src_corelib_kernel_qobject.cpp 10
1512 This example returns a \l{QListWidget} child of \c{parentWidget}:
1514 \snippet code/src_corelib_kernel_qobject.cpp 11
1516 This example returns a child \l{QPushButton} of \c{parentWidget}
1517 (its direct parent) named \c{"button1"}:
1519 \snippet code/src_corelib_kernel_qobject.cpp 41
1521 This example returns a \l{QListWidget} child of \c{parentWidget},
1524 \snippet code/src_corelib_kernel_qobject.cpp 42
1530 \fn QList<T> QObject::findChildren(const QString &name, Qt::FindChildOptions options) const
1532 Returns all children of this object with the given \a name that can be
1533 cast to type T, or an empty list if there are no such objects.
1534 Omitting the \a name argument causes all object names to be matched.
1535 The search is performed recursively, unless \a options specifies the
1536 option FindDirectChildrenOnly.
1538 The following example shows how to find a list of child \l{QWidget}s of
1539 the specified \c{parentWidget} named \c{widgetname}:
1541 \snippet code/src_corelib_kernel_qobject.cpp 12
1543 This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
1545 \snippet code/src_corelib_kernel_qobject.cpp 13
1547 This example returns all \c{QPushButton}s that are immediate children of \c{parentWidget}:
1549 \snippet code/src_corelib_kernel_qobject.cpp 43
1555 \fn QList<T> QObject::findChildren(const QRegExp ®Exp, Qt::FindChildOptions options) const
1556 \overload findChildren()
1558 Returns the children of this object that can be cast to type T
1559 and that have names matching the regular expression \a regExp,
1560 or an empty list if there are no such objects.
1561 The search is performed recursively, unless \a options specifies the
1562 option FindDirectChildrenOnly.
1566 \fn QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options) const
1567 \overload findChildren()
1571 Returns the children of this object that can be cast to type T
1572 and that have names matching the regular expression \a re,
1573 or an empty list if there are no such objects.
1574 The search is performed recursively, unless \a options specifies the
1575 option FindDirectChildrenOnly.
1579 \fn T qFindChild(const QObject *obj, const QString &name)
1581 \overload qFindChildren()
1584 This function is equivalent to
1585 \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
1587 \note This function was provided as a workaround for MSVC 6
1588 which did not support member template functions. It is advised
1589 to use the other form in new code.
1591 \sa QObject::findChild()
1595 \fn QList<T> qFindChildren(const QObject *obj, const QString &name)
1597 \overload qFindChildren()
1600 This function is equivalent to
1601 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
1603 \note This function was provided as a workaround for MSVC 6
1604 which did not support member template functions. It is advised
1605 to use the other form in new code.
1607 \sa QObject::findChildren()
1611 \fn QList<T> qFindChildren(const QObject *obj, const QRegExp ®Exp)
1613 \overload qFindChildren()
1615 This function is equivalent to
1616 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp).
1618 \note This function was provided as a workaround for MSVC 6
1619 which did not support member template functions. It is advised
1620 to use the other form in new code.
1622 \sa QObject::findChildren()
1628 void qt_qFindChildren_helper(const QObject *parent, const QString &name,
1629 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
1631 if (!parent || !list)
1633 const QObjectList &children = parent->children();
1635 for (int i = 0; i < children.size(); ++i) {
1636 obj = children.at(i);
1638 if (name.isNull() || obj->objectName() == name)
1641 if (options & Qt::FindChildrenRecursively)
1642 qt_qFindChildren_helper(obj, name, mo, list, options);
1646 #ifndef QT_NO_REGEXP
1650 void qt_qFindChildren_helper(const QObject *parent, const QRegExp &re,
1651 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
1653 if (!parent || !list)
1655 const QObjectList &children = parent->children();
1657 for (int i = 0; i < children.size(); ++i) {
1658 obj = children.at(i);
1659 if (mo.cast(obj) && re.indexIn(obj->objectName()) != -1)
1662 if (options & Qt::FindChildrenRecursively)
1663 qt_qFindChildren_helper(obj, re, mo, list, options);
1666 #endif // QT_NO_REGEXP
1668 #ifndef QT_NO_REGEXP
1672 void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
1673 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
1675 if (!parent || !list)
1677 const QObjectList &children = parent->children();
1679 for (int i = 0; i < children.size(); ++i) {
1680 obj = children.at(i);
1682 QRegularExpressionMatch m = re.match(obj->objectName());
1686 if (options & Qt::FindChildrenRecursively)
1687 qt_qFindChildren_helper(obj, re, mo, list, options);
1690 #endif // QT_NO_REGEXP
1694 QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options)
1698 const QObjectList &children = parent->children();
1701 for (i = 0; i < children.size(); ++i) {
1702 obj = children.at(i);
1703 if (mo.cast(obj) && (name.isNull() || obj->objectName() == name))
1706 if (options & Qt::FindChildrenRecursively) {
1707 for (i = 0; i < children.size(); ++i) {
1708 obj = qt_qFindChild_helper(children.at(i), name, mo, options);
1717 Makes the object a child of \a parent.
1719 \sa QWidget::setParent()
1722 void QObject::setParent(QObject *parent)
1725 Q_ASSERT(!d->isWidget);
1726 d->setParent_helper(parent);
1729 void QObjectPrivate::deleteChildren()
1731 Q_ASSERT_X(!isDeletingChildren, "QObjectPrivate::deleteChildren()", "isDeletingChildren already set, did this function recurse?");
1732 isDeletingChildren = true;
1733 // delete children objects
1734 // don't use qDeleteAll as the destructor of the child might
1736 for (int i = 0; i < children.count(); ++i) {
1737 currentChildBeingDeleted = children.at(i);
1739 delete currentChildBeingDeleted;
1742 currentChildBeingDeleted = 0;
1743 isDeletingChildren = false;
1746 void QObjectPrivate::setParent_helper(QObject *o)
1752 QObjectPrivate *parentD = parent->d_func();
1753 if (parentD->isDeletingChildren && wasDeleted
1754 && parentD->currentChildBeingDeleted == q) {
1755 // don't do anything since QObjectPrivate::deleteChildren() already
1756 // cleared our entry in parentD->children.
1758 const int index = parentD->children.indexOf(q);
1759 if (parentD->isDeletingChildren) {
1760 parentD->children[index] = 0;
1762 parentD->children.removeAt(index);
1763 if (sendChildEvents && parentD->receiveChildEvents) {
1764 QChildEvent e(QEvent::ChildRemoved, q);
1765 QCoreApplication::sendEvent(parent, &e);
1772 // object hierarchies are constrained to a single thread
1773 if (threadData != parent->d_func()->threadData) {
1774 qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
1778 parent->d_func()->children.append(q);
1779 if(sendChildEvents && parent->d_func()->receiveChildEvents) {
1781 QChildEvent e(QEvent::ChildAdded, q);
1782 QCoreApplication::sendEvent(parent, &e);
1786 if (!isDeletingChildren && declarativeData)
1787 QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
1791 \fn void QObject::installEventFilter(QObject *filterObj)
1793 Installs an event filter \a filterObj on this object. For example:
1794 \snippet code/src_corelib_kernel_qobject.cpp 14
1796 An event filter is an object that receives all events that are
1797 sent to this object. The filter can either stop the event or
1798 forward it to this object. The event filter \a filterObj receives
1799 events via its eventFilter() function. The eventFilter() function
1800 must return true if the event should be filtered, (i.e. stopped);
1801 otherwise it must return false.
1803 If multiple event filters are installed on a single object, the
1804 filter that was installed last is activated first.
1806 Here's a \c KeyPressEater class that eats the key presses of its
1809 \snippet code/src_corelib_kernel_qobject.cpp 15
1811 And here's how to install it on two widgets:
1813 \snippet code/src_corelib_kernel_qobject.cpp 16
1815 The QShortcut class, for example, uses this technique to intercept
1816 shortcut key presses.
1818 \warning If you delete the receiver object in your eventFilter()
1819 function, be sure to return true. If you return false, Qt sends
1820 the event to the deleted object and the program will crash.
1822 Note that the filtering object must be in the same thread as this
1823 object. If \a filterObj is in a different thread, this function does
1824 nothing. If either \a filterObj or this object are moved to a different
1825 thread after calling this function, the event filter will not be
1826 called until both objects have the same thread affinity again (it
1829 \sa removeEventFilter(), eventFilter(), event()
1832 void QObject::installEventFilter(QObject *obj)
1837 if (d->threadData != obj->d_func()->threadData) {
1838 qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
1842 // clean up unused items in the list
1843 d->eventFilters.removeAll((QObject*)0);
1844 d->eventFilters.removeAll(obj);
1845 d->eventFilters.prepend(obj);
1849 Removes an event filter object \a obj from this object. The
1850 request is ignored if such an event filter has not been installed.
1852 All event filters for this object are automatically removed when
1853 this object is destroyed.
1855 It is always safe to remove an event filter, even during event
1856 filter activation (i.e. from the eventFilter() function).
1858 \sa installEventFilter(), eventFilter(), event()
1861 void QObject::removeEventFilter(QObject *obj)
1864 for (int i = 0; i < d->eventFilters.count(); ++i) {
1865 if (d->eventFilters.at(i) == obj)
1866 d->eventFilters[i] = 0;
1872 \fn QObject::destroyed(QObject *obj)
1874 This signal is emitted immediately before the object \a obj is
1875 destroyed, and can not be blocked.
1877 All the objects's children are destroyed immediately after this
1880 \sa deleteLater(), QPointer
1884 Schedules this object for deletion.
1886 The object will be deleted when control returns to the event
1887 loop. If the event loop is not running when this function is
1888 called (e.g. deleteLater() is called on an object before
1889 QCoreApplication::exec()), the object will be deleted once the
1890 event loop is started.
1892 Note that entering and leaving a new event loop (e.g., by opening a modal
1893 dialog) will \e not perform the deferred deletion; for the object to be
1894 deleted, the control must return to the event loop from which
1895 deleteLater() was called.
1897 \b{Note:} It is safe to call this function more than once; when the
1898 first deferred deletion event is delivered, any pending events for the
1899 object are removed from the event queue.
1901 \sa destroyed(), QPointer
1903 void QObject::deleteLater()
1905 QCoreApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
1909 \fn QString QObject::tr(const char *sourceText, const char *disambiguation, int n)
1912 Returns a translated version of \a sourceText, optionally based on a
1913 \a disambiguation string and value of \a n for strings containing plurals;
1914 otherwise returns \a sourceText itself if no appropriate translated string
1918 \snippet mainwindows/sdi/mainwindow.cpp implicit tr context
1921 If the same \a sourceText is used in different roles within the
1922 same context, an additional identifying string may be passed in
1923 \a disambiguation (0 by default). In Qt 4.4 and earlier, this was
1924 the preferred way to pass comments to translators.
1928 \snippet code/src_corelib_kernel_qobject.cpp 17
1931 See \l{Writing Source Code for Translation} for a detailed description of
1932 Qt's translation mechanisms in general, and the
1933 \l{Writing Source Code for Translation#Disambiguation}{Disambiguation}
1934 section for information on disambiguation.
1936 \warning This method is reentrant only if all translators are
1937 installed \e before calling this method. Installing or removing
1938 translators while performing translations is not supported. Doing
1939 so will probably result in crashes or other undesirable behavior.
1941 \sa trUtf8(), QApplication::translate(), {Internationalization with Qt}
1945 \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
1948 Returns a translated version of \a sourceText, or
1949 QString::fromUtf8(\a sourceText) if there is no appropriate
1950 version. It is otherwise identical to tr(\a sourceText, \a
1951 disambiguation, \a n).
1953 \warning This method is reentrant only if all translators are
1954 installed \e before calling this method. Installing or removing
1955 translators while performing translations is not supported. Doing
1956 so will probably result in crashes or other undesirable behavior.
1958 \warning For portability reasons, we recommend that you use
1959 escape sequences for specifying non-ASCII characters in string
1960 literals to trUtf8(). For example:
1962 \snippet code/src_corelib_kernel_qobject.cpp 20
1964 \sa tr(), QApplication::translate(), {Internationalization with Qt}
1970 /*****************************************************************************
1972 *****************************************************************************/
1975 const int flagged_locations_count = 2;
1976 static const char* flagged_locations[flagged_locations_count] = {0};
1978 const char *qFlagLocation(const char *method)
1981 flagged_locations[idx] = method;
1982 idx = (idx+1) % flagged_locations_count;
1986 static int extract_code(const char *member)
1988 // extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
1989 return (((int)(*member) - '0') & 0x3);
1992 static const char * extract_location(const char *member)
1994 for (int i = 0; i < flagged_locations_count; ++i) {
1995 if (member == flagged_locations[i]) {
1996 // signature includes location information after the first null-terminator
1997 const char *location = member + qstrlen(member) + 1;
1998 if (*location != '\0')
2006 static bool check_signal_macro(const QObject *sender, const char *signal,
2007 const char *func, const char *op)
2009 int sigcode = extract_code(signal);
2010 if (sigcode != QSIGNAL_CODE) {
2011 if (sigcode == QSLOT_CODE)
2012 qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
2013 func, op, sender->metaObject()->className(), signal+1);
2015 qWarning("QObject::%s: Use the SIGNAL macro to %s %s::%s",
2016 func, op, sender->metaObject()->className(), signal);
2022 static bool check_method_code(int code, const QObject *object,
2023 const char *method, const char *func)
2025 if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
2026 qWarning("QObject::%s: Use the SLOT or SIGNAL macro to "
2027 "%s %s::%s", func, func, object->metaObject()->className(), method);
2033 static void err_method_notfound(const QObject *object,
2034 const char *method, const char *func)
2036 const char *type = "method";
2037 switch (extract_code(method)) {
2038 case QSLOT_CODE: type = "slot"; break;
2039 case QSIGNAL_CODE: type = "signal"; break;
2041 const char *loc = extract_location(method);
2042 if (strchr(method,')') == 0) // common typing mistake
2043 qWarning("QObject::%s: Parentheses expected, %s %s::%s%s%s",
2044 func, type, object->metaObject()->className(), method+1,
2045 loc ? " in ": "", loc ? loc : "");
2047 qWarning("QObject::%s: No such %s %s::%s%s%s",
2048 func, type, object->metaObject()->className(), method+1,
2049 loc ? " in ": "", loc ? loc : "");
2054 static void err_info_about_objects(const char * func,
2055 const QObject * sender,
2056 const QObject * receiver)
2058 QString a = sender ? sender->objectName() : QString();
2059 QString b = receiver ? receiver->objectName() : QString();
2061 qWarning("QObject::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
2063 qWarning("QObject::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
2067 Returns a pointer to the object that sent the signal, if called in
2068 a slot activated by a signal; otherwise it returns 0. The pointer
2069 is valid only during the execution of the slot that calls this
2070 function from this object's thread context.
2072 The pointer returned by this function becomes invalid if the
2073 sender is destroyed, or if the slot is disconnected from the
2076 \warning This function violates the object-oriented principle of
2077 modularity. However, getting access to the sender might be useful
2078 when many signals are connected to a single slot.
2080 \warning As mentioned above, the return value of this function is
2081 not valid when the slot is called via a Qt::DirectConnection from
2082 a thread different from this object's thread. Do not use this
2083 function in this type of scenario.
2085 \sa senderSignalIndex(), QSignalMapper
2088 QObject *QObject::sender() const
2092 QMutexLocker locker(signalSlotLock(this));
2093 if (!d->currentSender)
2096 for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
2097 if (c->sender == d->currentSender->sender)
2098 return d->currentSender->sender;
2107 Returns the meta-method index of the signal that called the currently
2108 executing slot, which is a member of the class returned by sender().
2109 If called outside of a slot activated by a signal, -1 is returned.
2111 For signals with default parameters, this function will always return
2112 the index with all parameters, regardless of which was used with
2113 connect(). For example, the signal \c {destroyed(QObject *obj = 0)}
2114 will have two different indexes (with and without the parameter), but
2115 this function will always return the index with a parameter. This does
2116 not apply when overloading signals with different parameters.
2118 \warning This function violates the object-oriented principle of
2119 modularity. However, getting access to the signal index might be useful
2120 when many signals are connected to a single slot.
2122 \warning The return value of this function is not valid when the slot
2123 is called via a Qt::DirectConnection from a thread different from this
2124 object's thread. Do not use this function in this type of scenario.
2126 \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method()
2129 int QObject::senderSignalIndex() const
2133 QMutexLocker locker(signalSlotLock(this));
2134 if (!d->currentSender)
2137 for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
2138 if (c->sender == d->currentSender->sender)
2139 return d->currentSender->signal;
2146 Returns the number of receivers connected to the \a signal.
2148 Since both slots and signals can be used as receivers for signals,
2149 and the same connections can be made many times, the number of
2150 receivers is the same as the number of connections made from this
2153 When calling this function, you can use the \c SIGNAL() macro to
2154 pass a specific signal:
2156 \snippet code/src_corelib_kernel_qobject.cpp 21
2158 As the code snippet above illustrates, you can use this function
2159 to avoid emitting a signal that nobody listens to.
2161 \warning This function violates the object-oriented principle of
2162 modularity. However, it might be useful when you need to perform
2163 expensive initialization only if something is connected to a
2167 int QObject::receivers(const char *signal) const
2172 QByteArray signal_name = QMetaObject::normalizedSignature(signal);
2173 signal = signal_name;
2175 if (!check_signal_macro(this, signal, "receivers", "bind"))
2178 signal++; // skip code
2179 int signal_index = d->signalIndex(signal);
2180 if (signal_index < 0) {
2182 err_method_notfound(this, signal-1, "receivers");
2188 QMutexLocker locker(signalSlotLock(this));
2189 if (d->connectionLists) {
2190 if (signal_index < d->connectionLists->count()) {
2191 const QObjectPrivate::Connection *c =
2192 d->connectionLists->at(signal_index).first;
2194 receivers += c->receiver ? 1 : 0;
2195 c = c->nextConnectionList;
2206 This helper function calculates signal and method index for the given
2207 member in the specified class.
2210 \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1.
2212 \li If specified member is not a member of obj instance class (or one of
2213 its parent classes) then both signalIndex and methodIndex are set to -1.
2216 This function is used by QObject::connect and QObject::disconnect which
2217 are working with QMetaMethod.
2219 \a signalIndex is set to the signal index of member. If the member
2220 specified is not signal this variable is set to -1.
2222 \a methodIndex is set to the method index of the member. If the
2223 member is not a method of the object specified by the \a obj argument this
2224 variable is set to -1.
2226 void QMetaObjectPrivate::memberIndexes(const QObject *obj,
2227 const QMetaMethod &member,
2228 int *signalIndex, int *methodIndex)
2232 if (!obj || !member.mobj)
2234 const QMetaObject *m = obj->metaObject();
2235 // Check that member is member of obj class
2236 while (m != 0 && m != member.mobj)
2240 *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5;
2244 computeOffsets(m, &signalOffset, &methodOffset);
2246 *methodIndex += methodOffset;
2247 if (member.methodType() == QMetaMethod::Signal) {
2248 *signalIndex = originalClone(m, *signalIndex);
2249 *signalIndex += signalOffset;
2255 static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal,
2256 const QMetaObject *receiver, const QMetaMethod &method)
2258 if (signal.attributes() & QMetaMethod::Compatibility) {
2259 if (!(method.attributes() & QMetaMethod::Compatibility))
2260 qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
2261 sender->className(), signal.methodSignature().constData());
2262 } else if ((method.attributes() & QMetaMethod::Compatibility) &&
2263 method.methodType() == QMetaMethod::Signal) {
2264 qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
2265 sender->className(), signal.methodSignature().constData(),
2266 receiver->className(), method.methodSignature().constData());
2273 Creates a connection of the given \a type from the \a signal in
2274 the \a sender object to the \a method in the \a receiver object.
2275 Returns a handle to the connection that can be used to disconnect
2278 You must use the \c SIGNAL() and \c SLOT() macros when specifying
2279 the \a signal and the \a method, for example:
2281 \snippet code/src_corelib_kernel_qobject.cpp 22
2283 This example ensures that the label always displays the current
2284 scroll bar value. Note that the signal and slots parameters must not
2285 contain any variable names, only the type. E.g. the following would
2286 not work and return false:
2288 \snippet code/src_corelib_kernel_qobject.cpp 23
2290 A signal can also be connected to another signal:
2292 \snippet code/src_corelib_kernel_qobject.cpp 24
2294 In this example, the \c MyWidget constructor relays a signal from
2295 a private member variable, and makes it available under a name
2296 that relates to \c MyWidget.
2298 A signal can be connected to many slots and signals. Many signals
2299 can be connected to one slot.
2301 If a signal is connected to several slots, the slots are activated
2302 in the same order as the order the connection was made, when the
2305 The function returns a handle to a connection if it successfully
2306 connects the signal to the slot. The Connection handle will be invalid
2307 if it cannot create the connection, for example, if QObject is unable
2308 to verify the existence of either \a signal or \a method, or if their
2309 signatures aren't compatible.
2310 You can check if the QMetaObject::Connection is valid by casting it to a bool.
2312 By default, a signal is emitted for every connection you make;
2313 two signals are emitted for duplicate connections. You can break
2314 all of these connections with a single disconnect() call.
2315 If you pass the Qt::UniqueConnection \a type, the connection will only
2316 be made if it is not a duplicate. If there is already a duplicate
2317 (exact same signal to the exact same slot on the same objects),
2318 the connection will fail and connect will return an invalid QMetaObject::Connection.
2320 The optional \a type parameter describes the type of connection
2321 to establish. In particular, it determines whether a particular
2322 signal is delivered to a slot immediately or queued for delivery
2323 at a later time. If the signal is queued, the parameters must be
2324 of types that are known to Qt's meta-object system, because Qt
2325 needs to copy the arguments to store them in an event behind the
2326 scenes. If you try to use a queued connection and get the error
2329 \snippet code/src_corelib_kernel_qobject.cpp 25
2331 call qRegisterMetaType() to register the data type before you
2332 establish the connection.
2334 \sa disconnect(), sender(), qRegisterMetaType(), Q_DECLARE_METATYPE()
2336 QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
2337 const QObject *receiver, const char *method,
2338 Qt::ConnectionType type)
2340 if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {
2341 qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2342 sender ? sender->metaObject()->className() : "(null)",
2343 (signal && *signal) ? signal+1 : "(null)",
2344 receiver ? receiver->metaObject()->className() : "(null)",
2345 (method && *method) ? method+1 : "(null)");
2346 return QMetaObject::Connection(0);
2348 QByteArray tmp_signal_name;
2350 if (!check_signal_macro(sender, signal, "connect", "bind"))
2351 return QMetaObject::Connection(0);
2352 const QMetaObject *smeta = sender->metaObject();
2353 const char *signal_arg = signal;
2354 ++signal; //skip code
2355 QArgumentTypeArray signalTypes;
2356 Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
2357 QByteArray signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
2358 int signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2359 &smeta, signalName, signalTypes.size(), signalTypes.constData());
2360 if (signal_index < 0) {
2361 // check for normalized signatures
2362 tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
2363 signal = tmp_signal_name.constData() + 1;
2365 signalTypes.clear();
2366 signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
2367 smeta = sender->metaObject();
2368 signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2369 &smeta, signalName, signalTypes.size(), signalTypes.constData());
2371 if (signal_index < 0) {
2372 err_method_notfound(sender, signal_arg, "connect");
2373 err_info_about_objects("connect", sender, receiver);
2374 return QMetaObject::Connection(0);
2376 signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
2377 int signalOffset, methodOffset;
2378 computeOffsets(smeta, &signalOffset, &methodOffset);
2379 int signal_absolute_index = signal_index + methodOffset;
2380 signal_index += signalOffset;
2382 QByteArray tmp_method_name;
2383 int membcode = extract_code(method);
2385 if (!check_method_code(membcode, receiver, method, "connect"))
2386 return QMetaObject::Connection(0);
2387 const char *method_arg = method;
2388 ++method; // skip code
2390 QByteArray methodName;
2391 QArgumentTypeArray methodTypes;
2392 const QMetaObject *rmeta = receiver->metaObject();
2393 int method_index_relative = -1;
2394 Q_ASSERT(QMetaObjectPrivate::get(rmeta)->revision >= 7);
2397 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
2398 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2401 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
2402 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2405 if (method_index_relative < 0) {
2406 // check for normalized methods
2407 tmp_method_name = QMetaObject::normalizedSignature(method);
2408 method = tmp_method_name.constData();
2410 methodTypes.clear();
2411 methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
2412 // rmeta may have been modified above
2413 rmeta = receiver->metaObject();
2416 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
2417 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2420 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
2421 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2426 if (method_index_relative < 0) {
2427 err_method_notfound(receiver, method_arg, "connect");
2428 err_info_about_objects("connect", sender, receiver);
2429 return QMetaObject::Connection(0);
2432 if (!QMetaObjectPrivate::checkConnectArgs(signalTypes.size(), signalTypes.constData(),
2433 methodTypes.size(), methodTypes.constData())) {
2434 qWarning("QObject::connect: Incompatible sender/receiver arguments"
2435 "\n %s::%s --> %s::%s",
2436 sender->metaObject()->className(), signal,
2437 receiver->metaObject()->className(), method);
2438 return QMetaObject::Connection(0);
2442 if ((type == Qt::QueuedConnection)
2443 && !(types = queuedConnectionTypes(signalTypes.constData(), signalTypes.size()))) {
2444 return QMetaObject::Connection(0);
2448 QMetaMethod smethod = smeta->method(signal_absolute_index);
2449 QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
2450 check_and_warn_compat(smeta, smethod, rmeta, rmethod);
2452 QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
2453 sender, signal_index, receiver, method_index_relative, rmeta ,type, types));
2455 const_cast<QObject*>(sender)->connectNotify(signal - 1);
2462 Creates a connection of the given \a type from the \a signal in
2463 the \a sender object to the \a method in the \a receiver object.
2464 Returns a handle to the connection that can be used to disconnect
2467 The Connection handle will be invalid if it cannot create the
2468 connection, for example, the parameters were invalid.
2469 You can check if the QMetaObject::Connection is valid by casting it to a bool.
2471 This function works in the same way as
2472 connect(const QObject *sender, const char *signal,
2473 const QObject *receiver, const char *method,
2474 Qt::ConnectionType type)
2475 but it uses QMetaMethod to specify signal and method.
2477 \sa connect(const QObject *sender, const char *signal,
2478 const QObject *receiver, const char *method,
2479 Qt::ConnectionType type)
2481 QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal,
2482 const QObject *receiver, const QMetaMethod &method,
2483 Qt::ConnectionType type)
2487 || signal.methodType() != QMetaMethod::Signal
2488 || method.methodType() == QMetaMethod::Constructor) {
2489 qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2490 sender ? sender->metaObject()->className() : "(null)",
2491 signal.methodSignature().constData(),
2492 receiver ? receiver->metaObject()->className() : "(null)",
2493 method.methodSignature().constData() );
2494 return QMetaObject::Connection(0);
2497 // Reconstructing SIGNAL() macro result for signal.methodSignature() string
2498 QByteArray signalSignature;
2499 signalSignature.reserve(signal.methodSignature().size()+1);
2500 signalSignature.append((char)(QSIGNAL_CODE + '0'));
2501 signalSignature.append(signal.methodSignature());
2507 QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
2508 QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
2511 const QMetaObject *smeta = sender->metaObject();
2512 const QMetaObject *rmeta = receiver->metaObject();
2513 if (signal_index == -1) {
2514 qWarning("QObject::connect: Can't find signal %s on instance of class %s",
2515 signal.methodSignature().constData(), smeta->className());
2516 return QMetaObject::Connection(0);
2518 if (method_index == -1) {
2519 qWarning("QObject::connect: Can't find method %s on instance of class %s",
2520 method.methodSignature().constData(), rmeta->className());
2521 return QMetaObject::Connection(0);
2524 if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) {
2525 qWarning("QObject::connect: Incompatible sender/receiver arguments"
2526 "\n %s::%s --> %s::%s",
2527 smeta->className(), signal.methodSignature().constData(),
2528 rmeta->className(), method.methodSignature().constData());
2529 return QMetaObject::Connection(0);
2533 if ((type == Qt::QueuedConnection)
2534 && !(types = queuedConnectionTypes(signal.parameterTypes())))
2535 return QMetaObject::Connection(0);
2538 check_and_warn_compat(smeta, signal, rmeta, method);
2540 QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
2541 sender, signal_index, receiver, method_index, 0, type, types));
2543 const_cast<QObject*>(sender)->connectNotify(signalSignature.constData());
2548 \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
2552 Connects \a signal from the \a sender object to this object's \a
2555 Equivalent to connect(\a sender, \a signal, \c this, \a method, \a type).
2557 Every connection you make emits a signal, so duplicate connections emit
2558 two signals. You can break a connection using disconnect().
2566 Disconnects \a signal in object \a sender from \a method in object
2567 \a receiver. Returns true if the connection is successfully broken;
2568 otherwise returns false.
2570 A signal-slot connection is removed when either of the objects
2571 involved are destroyed.
2573 disconnect() is typically used in three ways, as the following
2574 examples demonstrate.
2576 \li Disconnect everything connected to an object's signals:
2578 \snippet code/src_corelib_kernel_qobject.cpp 26
2580 equivalent to the non-static overloaded function
2582 \snippet code/src_corelib_kernel_qobject.cpp 27
2584 \li Disconnect everything connected to a specific signal:
2586 \snippet code/src_corelib_kernel_qobject.cpp 28
2588 equivalent to the non-static overloaded function
2590 \snippet code/src_corelib_kernel_qobject.cpp 29
2592 \li Disconnect a specific receiver:
2594 \snippet code/src_corelib_kernel_qobject.cpp 30
2596 equivalent to the non-static overloaded function
2598 \snippet code/src_corelib_kernel_qobject.cpp 31
2602 0 may be used as a wildcard, meaning "any signal", "any receiving
2603 object", or "any slot in the receiving object", respectively.
2605 The \a sender may never be 0. (You cannot disconnect signals from
2606 more than one object in a single call.)
2608 If \a signal is 0, it disconnects \a receiver and \a method from
2609 any signal. If not, only the specified signal is disconnected.
2611 If \a receiver is 0, it disconnects anything connected to \a
2612 signal. If not, slots in objects other than \a receiver are not
2615 If \a method is 0, it disconnects anything that is connected to \a
2616 receiver. If not, only slots named \a method will be disconnected,
2617 and all other slots are left alone. The \a method must be 0 if \a
2618 receiver is left out, so you cannot disconnect a
2619 specifically-named slot on all objects.
2623 bool QObject::disconnect(const QObject *sender, const char *signal,
2624 const QObject *receiver, const char *method)
2626 if (sender == 0 || (receiver == 0 && method != 0)) {
2627 qWarning("QObject::disconnect: Unexpected null parameter");
2631 const char *signal_arg = signal;
2632 QByteArray signal_name;
2633 bool signal_found = false;
2636 signal_name = QMetaObject::normalizedSignature(signal);
2637 signal = signal_name.constData();
2638 } QT_CATCH (const std::bad_alloc &) {
2639 // if the signal is already normalized, we can continue.
2640 if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
2644 if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
2646 signal++; // skip code
2649 QByteArray method_name;
2650 const char *method_arg = method;
2652 bool method_found = false;
2655 method_name = QMetaObject::normalizedSignature(method);
2656 method = method_name.constData();
2657 } QT_CATCH(const std::bad_alloc &) {
2658 // if the method is already normalized, we can continue.
2659 if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
2663 membcode = extract_code(method);
2664 if (!check_method_code(membcode, receiver, method, "disconnect"))
2666 method++; // skip code
2669 /* We now iterate through all the sender's and receiver's meta
2670 * objects in order to also disconnect possibly shadowed signals
2671 * and slots with the same signature.
2674 const QMetaObject *smeta = sender->metaObject();
2675 QByteArray signalName;
2676 QArgumentTypeArray signalTypes;
2677 Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
2679 signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
2680 QByteArray methodName;
2681 QArgumentTypeArray methodTypes;
2682 Q_ASSERT(!receiver || QMetaObjectPrivate::get(receiver->metaObject())->revision >= 7);
2684 methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
2686 int signal_index = -1;
2688 signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2689 &smeta, signalName, signalTypes.size(), signalTypes.constData());
2690 if (signal_index < 0)
2692 signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
2693 int signalOffset, methodOffset;
2694 computeOffsets(smeta, &signalOffset, &methodOffset);
2695 signal_index += signalOffset;
2696 signal_found = true;
2700 res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1, 0);
2702 const QMetaObject *rmeta = receiver->metaObject();
2704 int method_index = QMetaObjectPrivate::indexOfMethod(
2705 rmeta, methodName, methodTypes.size(), methodTypes.constData());
2706 if (method_index >= 0)
2707 while (method_index < rmeta->methodOffset())
2708 rmeta = rmeta->superClass();
2709 if (method_index < 0)
2711 res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index, 0);
2712 method_found = true;
2713 } while ((rmeta = rmeta->superClass()));
2715 } while (signal && (smeta = smeta->superClass()));
2717 if (signal && !signal_found) {
2718 err_method_notfound(sender, signal_arg, "disconnect");
2719 err_info_about_objects("disconnect", sender, receiver);
2720 } else if (method && !method_found) {
2721 err_method_notfound(receiver, method_arg, "disconnect");
2722 err_info_about_objects("disconnect", sender, receiver);
2725 const_cast<QObject*>(sender)->disconnectNotify(signal ? (signal - 1) : 0);
2732 Disconnects \a signal in object \a sender from \a method in object
2733 \a receiver. Returns true if the connection is successfully broken;
2734 otherwise returns false.
2736 This function provides the same possibilities like
2737 disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
2738 but uses QMetaMethod to represent the signal and the method to be disconnected.
2740 Additionally this function returnsfalse and no signals and slots disconnected
2744 \li \a signal is not a member of sender class or one of its parent classes.
2746 \li \a method is not a member of receiver class or one of its parent classes.
2748 \li \a signal instance represents not a signal.
2752 QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object".
2753 In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case
2754 method should also be QMetaMethod(). \a sender parameter should be never 0.
2756 \sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
2758 bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
2759 const QObject *receiver, const QMetaMethod &method)
2761 if (sender == 0 || (receiver == 0 && method.mobj != 0)) {
2762 qWarning("QObject::disconnect: Unexpected null parameter");
2766 if(signal.methodType() != QMetaMethod::Signal) {
2767 qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
2768 "disconnect","unbind",
2769 sender->metaObject()->className(), signal.methodSignature().constData());
2774 if(method.methodType() == QMetaMethod::Constructor) {
2775 qWarning("QObject::disconect: cannot use constructor as argument %s::%s",
2776 receiver->metaObject()->className(), method.methodSignature().constData());
2781 // Reconstructing SIGNAL() macro result for signal.methodSignature() string
2782 QByteArray signalSignature;
2784 signalSignature.reserve(signal.methodSignature().size()+1);
2785 signalSignature.append((char)(QSIGNAL_CODE + '0'));
2786 signalSignature.append(signal.methodSignature());
2793 QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
2794 QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
2796 // If we are here sender is not null. If signal is not null while signal_index
2797 // is -1 then this signal is not a member of sender.
2798 if (signal.mobj && signal_index == -1) {
2799 qWarning("QObject::disconect: signal %s not found on class %s",
2800 signal.methodSignature().constData(), sender->metaObject()->className());
2803 // If this condition is true then method is not a member of receeiver.
2804 if (receiver && method.mobj && method_index == -1) {
2805 qWarning("QObject::disconect: method %s not found on class %s",
2806 method.methodSignature().constData(), receiver->metaObject()->className());
2810 if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index, 0))
2813 const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0);
2820 \fn bool QObject::disconnect(const char *signal, const QObject *receiver, const char *method) const
2821 \overload disconnect()
2823 Disconnects \a signal from \a method of \a receiver.
2825 A signal-slot connection is removed when either of the objects
2826 involved are destroyed.
2830 \fn bool QObject::disconnect(const QObject *receiver, const char *method) const
2831 \overload disconnect()
2833 Disconnects all signals in this object from \a receiver's \a
2836 A signal-slot connection is removed when either of the objects
2837 involved are destroyed.
2842 \fn void QObject::connectNotify(const char *signal)
2844 This virtual function is called when something has been connected
2845 to \a signal in this object.
2847 If you want to compare \a signal with a specific signal, use
2848 QLatin1String and the \c SIGNAL() macro as follows:
2850 \snippet code/src_corelib_kernel_qobject.cpp 32
2852 If the signal contains multiple parameters or parameters that
2853 contain spaces, call QMetaObject::normalizedSignature() on
2854 the result of the \c SIGNAL() macro.
2856 \warning This function violates the object-oriented principle of
2857 modularity. However, it might be useful when you need to perform
2858 expensive initialization only if something is connected to a
2861 \sa connect(), disconnectNotify()
2864 void QObject::connectNotify(const char *)
2869 \fn void QObject::disconnectNotify(const char *signal)
2871 This virtual function is called when something has been
2872 disconnected from \a signal in this object.
2874 See connectNotify() for an example of how to compare
2875 \a signal with a specific signal.
2877 \warning This function violates the object-oriented principle of
2878 modularity. However, it might be useful for optimizing access to
2879 expensive resources.
2881 \sa disconnect(), connectNotify()
2884 void QObject::disconnectNotify(const char *)
2889 convert a signal index from the method range to the signal range
2891 static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_index)
2893 if (signal_index < 0)
2894 return signal_index;
2895 while (metaObject && metaObject->methodOffset() > signal_index)
2896 metaObject = metaObject->superClass();
2899 int signalOffset, methodOffset;
2900 computeOffsets(metaObject, &signalOffset, &methodOffset);
2901 if (signal_index < metaObject->methodCount())
2902 signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
2904 signal_index = signal_index - methodOffset + signalOffset;
2906 return signal_index;
2910 \a types is a 0-terminated vector of meta types for queued
2913 if \a signal_index is -1, then we effectively connect *all* signals
2914 from the sender to the receiver's slot
2916 QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_index,
2917 const QObject *receiver, int method_index, int type, int *types)
2919 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
2920 return Connection(QMetaObjectPrivate::connect(sender, signal_index,
2921 receiver, method_index,
2922 0, //FIXME, we could speed this connection up by computing the relative index
2927 Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
2929 method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index
2931 the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection
2933 QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
2934 const QObject *receiver, int method_index,
2935 const QMetaObject *rmeta, int type, int *types)
2937 QObject *s = const_cast<QObject *>(sender);
2938 QObject *r = const_cast<QObject *>(receiver);
2940 int method_offset = rmeta ? rmeta->methodOffset() : 0;
2941 Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6);
2942 QObjectPrivate::StaticMetaCallFunction callFunction =
2943 (rmeta && rmeta->d.extradata)
2944 ? reinterpret_cast<const QMetaObjectExtraData *>(rmeta->d.extradata)->static_metacall : 0;
2946 QOrderedMutexLocker locker(signalSlotLock(sender),
2947 signalSlotLock(receiver));
2949 if (type & Qt::UniqueConnection) {
2950 QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
2951 if (connectionLists && connectionLists->count() > signal_index) {
2952 const QObjectPrivate::Connection *c2 =
2953 (*connectionLists)[signal_index].first;
2955 int method_index_absolute = method_index + method_offset;
2958 if (c2->receiver == receiver && c2->method() == method_index_absolute)
2960 c2 = c2->nextConnectionList;
2963 type &= Qt::UniqueConnection - 1;
2966 QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
2969 c->method_relative = method_index;
2970 c->method_offset = method_offset;
2971 c->connectionType = type;
2972 c->isSlotObject = false;
2973 c->argumentTypes.store(types);
2974 c->nextConnectionList = 0;
2975 c->callFunction = callFunction;
2977 QObjectPrivate::get(s)->addConnection(signal_index, c.data());
2983 bool QMetaObject::disconnect(const QObject *sender, int signal_index,
2984 const QObject *receiver, int method_index)
2986 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
2987 return QMetaObjectPrivate::disconnect(sender, signal_index,
2988 receiver, method_index, 0);
2993 Disconnect a single signal connection. If QMetaObject::connect() has been called
2994 multiple times for the same sender, signal_index, receiver and method_index only
2995 one of these connections will be removed.
2997 bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
2998 const QObject *receiver, int method_index)
3000 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
3001 return QMetaObjectPrivate::disconnect(sender, signal_index,
3002 receiver, method_index, 0,
3003 QMetaObjectPrivate::DisconnectOne);
3007 Helper function to remove the connection from the senders list and setting the receivers to 0
3009 bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
3010 const QObject *receiver, int method_index, void **slot,
3011 QMutex *senderMutex, DisconnectType disconnectType)
3013 bool success = false;
3016 && (receiver == 0 || (c->receiver == receiver
3017 && (method_index < 0 || c->method() == method_index)
3018 && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) {
3019 bool needToUnlock = false;
3020 QMutex *receiverMutex = 0;
3022 receiverMutex = signalSlotLock(c->receiver);
3023 // need to relock this receiver and sender in the correct order
3024 needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
3029 c->next->prev = c->prev;
3033 receiverMutex->unlock();
3039 if (disconnectType == DisconnectOne)
3042 c = c->nextConnectionList;
3048 Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3050 bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
3051 const QObject *receiver, int method_index, void **slot,
3052 DisconnectType disconnectType)
3057 QObject *s = const_cast<QObject *>(sender);
3059 QMutex *senderMutex = signalSlotLock(sender);
3060 QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
3061 QOrderedMutexLocker locker(senderMutex, receiverMutex);
3063 QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
3064 if (!connectionLists)
3067 // prevent incoming connections changing the connectionLists while unlocked
3068 ++connectionLists->inUse;
3070 bool success = false;
3071 if (signal_index < 0) {
3072 // remove from all connection lists
3073 for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
3074 QObjectPrivate::Connection *c =
3075 (*connectionLists)[signal_index].first;
3076 if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
3078 connectionLists->dirty = true;
3081 } else if (signal_index < connectionLists->count()) {
3082 QObjectPrivate::Connection *c =
3083 (*connectionLists)[signal_index].first;
3084 if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
3086 connectionLists->dirty = true;
3090 --connectionLists->inUse;
3091 Q_ASSERT(connectionLists->inUse >= 0);
3092 if (connectionLists->orphaned && !connectionLists->inUse)
3093 delete connectionLists;
3099 \fn void QMetaObject::connectSlotsByName(QObject *object)
3101 Searches recursively for all child objects of the given \a object, and connects
3102 matching signals from them to slots of \a object that follow the following form:
3104 \snippet code/src_corelib_kernel_qobject.cpp 33
3106 Let's assume our object has a child object of type QPushButton with
3107 the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
3108 button's \c{clicked()} signal would be:
3110 \snippet code/src_corelib_kernel_qobject.cpp 34
3112 \sa QObject::setObjectName()
3114 void QMetaObject::connectSlotsByName(QObject *o)
3118 const QMetaObject *mo = o->metaObject();
3120 const QObjectList list = o->findChildren<QObject *>(QString());
3121 for (int i = 0; i < mo->methodCount(); ++i) {
3122 QByteArray slotSignature = mo->method(i).methodSignature();
3123 const char *slot = slotSignature.constData();
3125 if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
3127 bool foundIt = false;
3128 for(int j = 0; j < list.count(); ++j) {
3129 const QObject *co = list.at(j);
3130 QByteArray objName = co->objectName().toAscii();
3131 int len = objName.length();
3132 if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')
3134 int sigIndex = co->d_func()->signalIndex(slot + len + 4);
3135 if (sigIndex < 0) { // search for compatible signals
3136 const QMetaObject *smo = co->metaObject();
3137 int slotlen = qstrlen(slot + len + 4) - 1;
3138 for (int k = 0; k < co->metaObject()->methodCount(); ++k) {
3139 QMetaMethod method = smo->method(k);
3140 if (method.methodType() != QMetaMethod::Signal)
3143 if (!qstrncmp(method.methodSignature().constData(), slot + len + 4, slotlen)) {
3144 int signalOffset, methodOffset;
3145 computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
3146 sigIndex = k + - methodOffset + signalOffset;
3153 if (Connection(QMetaObjectPrivate::connect(co, sigIndex, o, i))) {
3159 // we found our slot, now skip all overloads
3160 while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
3162 } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
3163 qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
3168 static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
3170 const int *argumentTypes = c->argumentTypes.load();
3171 if (!argumentTypes && argumentTypes != &DIRECT_CONNECTION_ONLY) {
3172 QMetaMethod m = sender->metaObject()->method(signal);
3173 argumentTypes = queuedConnectionTypes(m.parameterTypes());
3174 if (!argumentTypes) // cannot queue arguments
3175 argumentTypes = &DIRECT_CONNECTION_ONLY;
3176 if (!c->argumentTypes.testAndSetOrdered(0, argumentTypes)) {
3177 if (argumentTypes != &DIRECT_CONNECTION_ONLY)
3178 delete [] argumentTypes;
3179 argumentTypes = c->argumentTypes.load();
3182 if (argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
3184 int nargs = 1; // include return type
3185 while (argumentTypes[nargs-1])
3187 int *types = (int *) malloc(nargs*sizeof(int));
3189 void **args = (void **) malloc(nargs*sizeof(void *));
3191 types[0] = 0; // return type
3192 args[0] = 0; // return value
3193 for (int n = 1; n < nargs; ++n)
3194 args[n] = QMetaType::create((types[n] = argumentTypes[n-1]), argv[n]);
3195 QMetaCallEvent *ev = c->isSlotObject ?
3196 new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) :
3197 new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args);
3198 QCoreApplication::postEvent(c->receiver, ev);
3203 void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
3208 computeOffsets(m, &signalOffset, &methodOffset);
3210 int signal_index = signalOffset + local_signal_index;
3212 if (sender->d_func()->declarativeData && QAbstractDeclarativeData::signalEmitted)
3213 QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender,
3214 methodOffset + local_signal_index, argv);
3216 if (!sender->d_func()->isSignalConnected(signal_index))
3217 return; // nothing connected to these signals, and no spy
3219 if (sender->d_func()->blockSig)
3222 int signal_absolute_index = methodOffset + local_signal_index;
3224 void *empty_argv[] = { 0 };
3225 if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
3226 qt_signal_spy_callback_set.signal_begin_callback(sender, signal_absolute_index,
3227 argv ? argv : empty_argv);
3230 Qt::HANDLE currentThreadId = QThread::currentThreadId();
3233 QMutexLocker locker(signalSlotLock(sender));
3234 struct ConnectionListsRef {
3235 QObjectConnectionListVector *connectionLists;
3236 ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists)
3238 if (connectionLists)
3239 ++connectionLists->inUse;
3241 ~ConnectionListsRef()
3243 if (!connectionLists)
3246 --connectionLists->inUse;
3247 Q_ASSERT(connectionLists->inUse >= 0);
3248 if (connectionLists->orphaned) {
3249 if (!connectionLists->inUse)
3250 delete connectionLists;
3254 QObjectConnectionListVector *operator->() const { return connectionLists; }
3256 ConnectionListsRef connectionLists = sender->d_func()->connectionLists;
3257 if (!connectionLists.connectionLists) {
3259 if (qt_signal_spy_callback_set.signal_end_callback != 0)
3260 qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
3264 const QObjectPrivate::ConnectionList *list;
3265 if (signal_index < connectionLists->count())
3266 list = &connectionLists->at(signal_index);
3268 list = &connectionLists->allsignals;
3271 QObjectPrivate::Connection *c = list->first;
3273 // We need to check against last here to ensure that signals added
3274 // during the signal emission are not emitted in this emission.
3275 QObjectPrivate::Connection *last = list->last;
3281 QObject * const receiver = c->receiver;
3282 const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId;
3284 // determine if this connection should be sent immediately or
3285 // put into the event queue
3286 if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
3287 || (c->connectionType == Qt::QueuedConnection)) {
3288 queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
3290 #ifndef QT_NO_THREAD
3291 } else if (c->connectionType == Qt::BlockingQueuedConnection) {
3293 if (receiverInSameThread) {
3294 qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
3295 "Sender is %s(%p), receiver is %s(%p)",
3296 sender->metaObject()->className(), sender,
3297 receiver->metaObject()->className(), receiver);
3299 QSemaphore semaphore;
3300 QMetaCallEvent *ev = c->isSlotObject ?
3301 new QMetaCallEvent(c->slotObj, sender, signal_absolute_index, 0, 0, argv ? argv : empty_argv, &semaphore) :
3302 new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_absolute_index, 0, 0, argv ? argv : empty_argv, &semaphore);
3303 QCoreApplication::postEvent(receiver, ev);
3304 semaphore.acquire();
3310 QConnectionSenderSwitcher sw;
3312 if (receiverInSameThread) {
3313 sw.switchSender(receiver, sender, signal_absolute_index);
3315 const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
3316 const int method_relative = c->method_relative;
3317 if (c->isSlotObject) {
3318 QExplicitlySharedDataPointer<QObject::QSlotObjectBase> obj(c->slotObj);
3320 obj->call(receiver, argv ? argv : empty_argv);
3322 } else if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
3323 //we compare the vtable to make sure we are not in the destructor of the object.
3325 if (qt_signal_spy_callback_set.slot_begin_callback != 0)
3326 qt_signal_spy_callback_set.slot_begin_callback(receiver, c->method(), argv ? argv : empty_argv);
3328 callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
3330 if (qt_signal_spy_callback_set.slot_end_callback != 0)
3331 qt_signal_spy_callback_set.slot_end_callback(receiver, c->method());
3334 const int method = method_relative + c->method_offset;
3337 if (qt_signal_spy_callback_set.slot_begin_callback != 0) {
3338 qt_signal_spy_callback_set.slot_begin_callback(receiver,
3340 argv ? argv : empty_argv);
3343 metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
3345 if (qt_signal_spy_callback_set.slot_end_callback != 0)
3346 qt_signal_spy_callback_set.slot_end_callback(receiver, method);
3351 if (connectionLists->orphaned)
3353 } while (c != last && (c = c->nextConnectionList) != 0);
3355 if (connectionLists->orphaned)
3357 } while (list != &connectionLists->allsignals &&
3358 //start over for all signals;
3359 ((list = &connectionLists->allsignals), true));
3363 if (qt_signal_spy_callback_set.signal_end_callback != 0)
3364 qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
3369 signal_index comes from indexOfMethod()
3371 void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
3373 const QMetaObject *mo = sender->metaObject();
3374 while (mo->methodOffset() > signal_index)
3375 mo = mo->superClass();
3376 activate(sender, mo, signal_index - mo->methodOffset(), argv);
3380 Returns the signal index used in the internal connectionLists vector.
3382 It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
3383 while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
3385 int QObjectPrivate::signalIndex(const char *signalName) const
3388 const QMetaObject *base = q->metaObject();
3389 Q_ASSERT(QMetaObjectPrivate::get(base)->revision >= 7);
3390 QArgumentTypeArray types;
3391 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signalName, types);
3392 int relative_index = QMetaObjectPrivate::indexOfSignalRelative(
3393 &base, name, types.size(), types.constData());
3394 if (relative_index < 0)
3395 return relative_index;
3396 relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
3397 int signalOffset, methodOffset;
3398 computeOffsets(base, &signalOffset, &methodOffset);
3399 return relative_index + signalOffset;
3402 /*****************************************************************************
3404 *****************************************************************************/
3406 #ifndef QT_NO_PROPERTIES
3409 Sets the value of the object's \a name property to \a value.
3411 If the property is defined in the class using Q_PROPERTY then
3412 true is returned on success and false otherwise. If the property
3413 is not defined using Q_PROPERTY, and therefore not listed in the
3414 meta-object, it is added as a dynamic property and false is returned.
3416 Information about all available properties is provided through the
3417 metaObject() and dynamicPropertyNames().
3419 Dynamic properties can be queried again using property() and can be
3420 removed by setting the property value to an invalid QVariant.
3421 Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent
3422 to be sent to the object.
3424 \b{Note:} Dynamic properties starting with "_q_" are reserved for internal
3427 \sa property(), metaObject(), dynamicPropertyNames()
3429 bool QObject::setProperty(const char *name, const QVariant &value)
3432 const QMetaObject* meta = metaObject();
3436 int id = meta->indexOfProperty(name);
3439 d->extraData = new QObjectPrivate::ExtraData;
3441 const int idx = d->extraData->propertyNames.indexOf(name);
3443 if (!value.isValid()) {
3446 d->extraData->propertyNames.removeAt(idx);
3447 d->extraData->propertyValues.removeAt(idx);
3450 d->extraData->propertyNames.append(name);
3451 d->extraData->propertyValues.append(value);
3453 d->extraData->propertyValues[idx] = value;
3457 QDynamicPropertyChangeEvent ev(name);
3458 QCoreApplication::sendEvent(this, &ev);
3462 QMetaProperty p = meta->property(id);
3464 if (!p.isWritable())
3465 qWarning("%s::setProperty: Property \"%s\" invalid,"
3466 " read-only or does not exist", metaObject()->className(), name);
3468 return p.write(this, value);
3472 Returns the value of the object's \a name property.
3474 If no such property exists, the returned variant is invalid.
3476 Information about all available properties is provided through the
3477 metaObject() and dynamicPropertyNames().
3479 \sa setProperty(), QVariant::isValid(), metaObject(), dynamicPropertyNames()
3481 QVariant QObject::property(const char *name) const
3484 const QMetaObject* meta = metaObject();
3488 int id = meta->indexOfProperty(name);
3492 const int i = d->extraData->propertyNames.indexOf(name);
3493 return d->extraData->propertyValues.value(i);
3495 QMetaProperty p = meta->property(id);
3497 if (!p.isReadable())
3498 qWarning("%s::property: Property \"%s\" invalid or does not exist",
3499 metaObject()->className(), name);
3501 return p.read(this);
3507 Returns the names of all properties that were dynamically added to
3508 the object using setProperty().
3510 QList<QByteArray> QObject::dynamicPropertyNames() const
3514 return d->extraData->propertyNames;
3515 return QList<QByteArray>();
3518 #endif // QT_NO_PROPERTIES
3521 /*****************************************************************************
3522 QObject debugging output routines.
3523 *****************************************************************************/
3525 static void dumpRecursive(int level, QObject *object)
3527 #if defined(QT_DEBUG)
3530 buf.fill(' ', level / 2 * 8);
3533 QString name = object->objectName();
3534 QString flags = QLatin1String("");
3536 if (qApp->focusWidget() == object)
3538 if (object->isWidgetType()) {
3539 QWidget * w = (QWidget *)object;
3540 if (w->isVisible()) {
3541 QString t("<%1,%2,%3,%4>");
3542 flags += t.arg(w->x()).arg(w->y()).arg(w->width()).arg(w->height());
3548 qDebug("%s%s::%s %s", (const char*)buf, object->metaObject()->className(), name.toLocal8Bit().data(),
3549 flags.toLatin1().data());
3550 QObjectList children = object->children();
3551 if (!children.isEmpty()) {
3552 for (int i = 0; i < children.size(); ++i)
3553 dumpRecursive(level+1, children.at(i));
3563 Dumps a tree of children to the debug output.
3565 This function is useful for debugging, but does nothing if the
3566 library has been compiled in release mode (i.e. without debugging
3569 \sa dumpObjectInfo()
3572 void QObject::dumpObjectTree()
3574 dumpRecursive(0, this);
3578 Dumps information about signal connections, etc. for this object
3579 to the debug output.
3581 This function is useful for debugging, but does nothing if the
3582 library has been compiled in release mode (i.e. without debugging
3585 \sa dumpObjectTree()
3588 void QObject::dumpObjectInfo()
3590 #if defined(QT_DEBUG)
3591 qDebug("OBJECT %s::%s", metaObject()->className(),
3592 objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
3595 QMutexLocker locker(signalSlotLock(this));
3597 // first, look for connections where this object is the sender
3598 qDebug(" SIGNALS OUT");
3600 if (d->connectionLists) {
3602 int offsetToNextMetaObject = 0;
3603 for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) {
3604 if (signal_index >= offsetToNextMetaObject) {
3605 const QMetaObject *mo = metaObject();
3606 int signalOffset, methodOffset;
3607 computeOffsets(mo, &signalOffset, &methodOffset);
3608 while (signalOffset > signal_index) {
3609 mo = mo->superClass();
3610 offsetToNextMetaObject = signalOffset;
3611 computeOffsets(mo, &signalOffset, &methodOffset);
3613 offset = methodOffset - signalOffset;
3615 const QMetaMethod signal = metaObject()->method(signal_index + offset);
3616 qDebug(" signal: %s", signal.methodSignature().constData());
3619 const QObjectPrivate::Connection *c =
3620 d->connectionLists->at(signal_index).first;
3623 qDebug(" <Disconnected receiver>");
3624 c = c->nextConnectionList;
3627 const QMetaObject *receiverMetaObject = c->receiver->metaObject();
3628 const QMetaMethod method = receiverMetaObject->method(c->method());
3629 qDebug(" --> %s::%s %s",
3630 receiverMetaObject->className(),
3631 c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
3632 method.methodSignature().constData());
3633 c = c->nextConnectionList;
3637 qDebug( " <None>" );
3640 // now look for connections where this object is the receiver
3641 qDebug(" SIGNALS IN");
3644 for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) {
3645 const QMetaMethod slot = metaObject()->method(s->method());
3646 qDebug(" <-- %s::%s %s",
3647 s->sender->metaObject()->className(),
3648 s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
3649 slot.methodSignature().constData());
3657 #ifndef QT_NO_USERDATA
3660 uint QObject::registerUserData()
3662 static int user_data_registration = 0;
3663 return user_data_registration++;
3668 QObjectUserData::~QObjectUserData()
3674 void QObject::setUserData(uint id, QObjectUserData* data)
3678 d->extraData = new QObjectPrivate::ExtraData;
3680 if (d->extraData->userData.size() <= (int) id)
3681 d->extraData->userData.resize((int) id + 1);
3682 d->extraData->userData[id] = data;
3687 QObjectUserData* QObject::userData(uint id) const
3692 if ((int)id < d->extraData->userData.size())
3693 return d->extraData->userData.at(id);
3697 #endif // QT_NO_USERDATA
3700 #ifndef QT_NO_DEBUG_STREAM
3701 QDebug operator<<(QDebug dbg, const QObject *o) {
3703 return dbg << "QObject(0x0) ";
3704 dbg.nospace() << o->metaObject()->className() << '(' << (void *)o;
3705 if (!o->objectName().isEmpty())
3706 dbg << ", name = " << o->objectName();
3713 \macro Q_CLASSINFO(Name, Value)
3716 This macro associates extra information to the class, which is
3717 available using QObject::metaObject(). Except for the ActiveQt
3718 extension, Qt doesn't use this information.
3720 The extra information takes the form of a \a Name string and a \a
3721 Value literal string.
3725 \snippet code/src_corelib_kernel_qobject.cpp 35
3727 \sa QMetaObject::classInfo()
3731 \macro Q_INTERFACES(...)
3734 This macro tells Qt which interfaces the class implements. This
3735 is used when implementing plugins.
3739 \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.h 1
3741 \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.h 3
3743 See the \l{tools/plugandpaintplugins/basictools}{Plug & Paint
3744 Basic Tools} example for details.
3746 \sa Q_DECLARE_INTERFACE(), Q_EXPORT_PLUGIN2(), {How to Create Qt Plugins}
3750 \macro Q_PROPERTY(...)
3753 This macro is used for declaring properties in classes that
3754 inherit QObject. Properties behave like class data members, but
3755 they have additional features accessible through the \l
3756 {Meta-Object System}.
3758 \snippet code/src_corelib_kernel_qobject.cpp 36
3760 The property name and type and the \c READ function are required.
3761 The type can be any type supported by QVariant, or it can be a
3762 user-defined type. The other items are optional, but a \c WRITE
3763 function is common. The attributes default to true except \c USER,
3764 which defaults to false.
3768 \snippet code/src_corelib_kernel_qobject.cpp 37
3770 For more details about how to use this macro, and a more detailed
3771 example of its use, see the discussion on \l {Qt's Property System}.
3773 \sa {Qt's Property System}
3780 This macro registers one or several enum types to the meta-object
3785 \snippet code/src_corelib_kernel_qobject.cpp 38
3787 If you want to register an enum that is declared in another class,
3788 the enum must be fully qualified with the name of the class
3789 defining it. In addition, the class \e defining the enum has to
3790 inherit QObject as well as declare the enum using Q_ENUMS().
3792 \sa {Qt's Property System}
3799 This macro registers one or several \l{QFlags}{flags types} to the
3800 meta-object system. It is typically used in a class definition to declare
3801 that values of a given enum can be used as flags and combined using the
3802 bitwise OR operator.
3804 For example, in QLibrary, the \l{QLibrary::LoadHints}{LoadHints} flag is
3805 declared in the following way:
3807 \snippet code/src_corelib_kernel_qobject.cpp 39a
3809 The declaration of the flags themselves is performed in the public section
3810 of the QLibrary class itself, using the \l Q_DECLARE_FLAGS() macro:
3812 \snippet code/src_corelib_kernel_qobject.cpp 39b
3814 \note This macro takes care of registering individual flag values
3815 with the meta-object system, so it is unnecessary to use Q_ENUMS()
3816 in addition to this macro.
3818 \sa {Qt's Property System}
3825 The Q_OBJECT macro must appear in the private section of a class
3826 definition that declares its own signals and slots or that uses
3827 other services provided by Qt's meta-object system.
3831 \snippet signalsandslots/signalsandslots.h 1
3833 \snippet signalsandslots/signalsandslots.h 2
3834 \snippet signalsandslots/signalsandslots.h 3
3836 \note This macro requires the class to be a subclass of QObject. Use
3837 Q_GADGET instead of Q_OBJECT to enable the meta object system's support
3838 for enums in a class that is not a QObject subclass. Q_GADGET makes a
3839 class member, \c{staticMetaObject}, available.
3840 \c{staticMetaObject} is of type QMetaObject and provides access to the
3841 enums declared with Q_ENUMS.
3842 Q_GADGET is provided only for C++.
3844 \sa {Meta-Object System}, {Signals and Slots}, {Qt's Property System}
3851 Use this macro to replace the \c signals keyword in class
3852 declarations, when you want to use Qt Signals and Slots with a
3853 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
3855 The macro is normally used when \c no_keywords is specified with
3856 the \c CONFIG variable in the \c .pro file, but it can be used
3857 even when \c no_keywords is \e not specified.
3864 This is an additional macro that allows you to mark a single
3865 function as a signal. It can be quite useful, especially when you
3866 use a 3rd-party source code parser which doesn't understand a \c
3867 signals or \c Q_SIGNALS groups.
3869 Use this macro to replace the \c signals keyword in class
3870 declarations, when you want to use Qt Signals and Slots with a
3871 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
3873 The macro is normally used when \c no_keywords is specified with
3874 the \c CONFIG variable in the \c .pro file, but it can be used
3875 even when \c no_keywords is \e not specified.
3882 Use this macro to replace the \c slots keyword in class
3883 declarations, when you want to use Qt Signals and Slots with a
3884 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
3886 The macro is normally used when \c no_keywords is specified with
3887 the \c CONFIG variable in the \c .pro file, but it can be used
3888 even when \c no_keywords is \e not specified.
3895 This is an additional macro that allows you to mark a single
3896 function as a slot. It can be quite useful, especially when you
3897 use a 3rd-party source code parser which doesn't understand a \c
3898 slots or \c Q_SLOTS groups.
3900 Use this macro to replace the \c slots keyword in class
3901 declarations, when you want to use Qt Signals and Slots with a
3902 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
3904 The macro is normally used when \c no_keywords is specified with
3905 the \c CONFIG variable in the \c .pro file, but it can be used
3906 even when \c no_keywords is \e not specified.
3913 Use this macro to replace the \c emit keyword for emitting
3914 signals, when you want to use Qt Signals and Slots with a
3915 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
3917 The macro is normally used when \c no_keywords is specified with
3918 the \c CONFIG variable in the \c .pro file, but it can be used
3919 even when \c no_keywords is \e not specified.
3926 Apply this macro to definitions of member functions to allow them to
3927 be invoked via the meta-object system. The macro is written before
3928 the return type, as shown in the following example:
3930 \snippet qmetaobject-invokable/window.h Window class with invokable method
3932 The \c invokableMethod() function is marked up using Q_INVOKABLE, causing
3933 it to be registered with the meta-object system and enabling it to be
3934 invoked using QMetaObject::invokeMethod().
3935 Since \c normalMethod() function is not registered in this way, it cannot
3936 be invoked using QMetaObject::invokeMethod().
3940 \typedef QObjectList
3943 Synonym for QList<QObject *>.
3946 void qDeleteInEventHandler(QObject *o)
3952 \fn QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type)
3956 Creates a connection of the given \a type from the \a signal in
3957 the \a sender object to the \a method in the \a receiver object.
3958 Returns a handle to the connection that can be used to disconnect
3961 The signal must be a function declared as a signal in the header.
3962 The slot function can be any member function that can be connected
3964 A slot can be connected to a given signal if the signal has at
3965 least as many arguments as the slot, and there is an implicit
3966 conversion between the types of the corresponding arguments in the
3967 signal and the slot.
3971 \snippet code/src_corelib_kernel_qobject.cpp 44
3973 This example ensures that the label always displays the current
3976 A signal can be connected to many slots and signals. Many signals
3977 can be connected to one slot.
3979 If a signal is connected to several slots, the slots are activated
3980 in the same order as the order the connection was made, when the
3983 The function returns an handle to a connection if it successfully
3984 connects the signal to the slot. The Connection handle will be invalid
3985 if it cannot create the connection, for example, if QObject is unable
3986 to verify the existence of \a signal (if it was not declared as a signal)
3987 You can check if the QMetaObject::Connection is valid by casting it to a bool.
3989 By default, a signal is emitted for every connection you make;
3990 two signals are emitted for duplicate connections. You can break
3991 all of these connections with a single disconnect() call.
3992 If you pass the Qt::UniqueConnection \a type, the connection will only
3993 be made if it is not a duplicate. If there is already a duplicate
3994 (exact same signal to the exact same slot on the same objects),
3995 the connection will fail and connect will return an invalid QMetaObject::Connection.
3997 The optional \a type parameter describes the type of connection
3998 to establish. In particular, it determines whether a particular
3999 signal is delivered to a slot immediately or queued for delivery
4000 at a later time. If the signal is queued, the parameters must be
4001 of types that are known to Qt's meta-object system, because Qt
4002 needs to copy the arguments to store them in an event behind the
4003 scenes. If you try to use a queued connection and get the error
4006 \snippet code/src_corelib_kernel_qobject.cpp 25
4008 make sure to declare the argument type with Q_DECLARE_METATYPE
4013 \fn QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
4018 Creates a connection of the given \a type from the \a signal in
4019 the \a sender object to the \a functor and returns a handle to the connection
4021 The signal must be a function declared as a signal in the header.
4022 The slot function can be any function or functor that can be connected
4024 A function can be connected to a given signal if the signal as at
4025 least as many argument as the slot. A functor can be connected to a signal
4026 if they have exactly the same number of arguments. There must exist implicit
4027 conversion between the types of the corresponding arguments in the
4028 signal and the slot.
4032 \snippet code/src_corelib_kernel_qobject.cpp 45
4034 If your compiler support C++11 lambda expressions, you can use them:
4036 \snippet code/src_corelib_kernel_qobject.cpp 46
4038 The connection will automatically disconnect if the sender is destroyed.
4043 Implementation of the template version of connect
4045 \a sender is the sender object
4046 \a signal is a pointer to a pointer to a member signal of the sender
4047 \a receiver is the receiver object, may not be null, will be equal to sender when
4048 connecting to a static function or a functor
4049 \a slot a pointer only used when using Qt::UniqueConnection
4050 \a type the Qt::ConnctionType passed as argument to connect
4051 \a types an array of integer with the metatype id of the parametter of the signal
4052 to be used with queued connection
4053 must stay valid at least for the whole time of the connection, this function
4054 do not take ownership. typically static data.
4055 If null, then the types will be computed when the signal is emit in a queued
4056 connection from the types from the signature.
4057 \a senderMetaObject is the metaobject used to lookup the signal, the signal must be in
4060 QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
4061 const QObject *receiver, void **slot,
4062 QObject::QSlotObjectBase *slotObj, Qt::ConnectionType type,
4063 const int *types, const QMetaObject *senderMetaObject)
4065 if (!sender || !signal || !slotObj || !senderMetaObject) {
4066 qWarning("QObject::connect: invalid null parametter");
4067 if (slotObj && !slotObj->ref.deref())
4069 return QMetaObject::Connection();
4071 int signal_index = -1;
4072 void *args[] = { &signal_index, signal };
4073 senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
4074 if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) {
4075 qWarning("QObject::connect: signal not found in %s", senderMetaObject->className());
4076 if (!slotObj->ref.deref())
4078 return QMetaObject::Connection(0);
4080 int signalOffset, methodOffset;
4081 computeOffsets(senderMetaObject, &signalOffset, &methodOffset);
4082 signal_index += signalOffset;
4084 QObject *s = const_cast<QObject *>(sender);
4085 QObject *r = const_cast<QObject *>(receiver);
4087 QOrderedMutexLocker locker(signalSlotLock(sender),
4088 signalSlotLock(receiver));
4090 if (type & Qt::UniqueConnection) {
4091 QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
4092 if (connectionLists && connectionLists->count() > signal_index) {
4093 const QObjectPrivate::Connection *c2 =
4094 (*connectionLists)[signal_index].first;
4097 if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
4098 if (!slotObj->ref.deref())
4100 return QMetaObject::Connection();
4102 c2 = c2->nextConnectionList;
4105 type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
4108 QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
4111 c->slotObj = slotObj;
4112 c->connectionType = type;
4113 c->isSlotObject = true;
4115 c->argumentTypes.store(types);
4116 c->ownArgumentTypes = false;
4119 QObjectPrivate::get(s)->addConnection(signal_index, c.data());
4120 QMetaObject::Connection ret(c.take());
4123 // reconstruct the signature to call connectNotify
4125 QByteArray tmp_sig = senderMetaObject->method(signal_index - signalOffset + methodOffset).methodSignature();
4126 sig = tmp_sig.constData();
4127 QVarLengthArray<char> signalSignature(qstrlen(sig) + 2);
4128 signalSignature.data()[0] = char(QSIGNAL_CODE + '0');
4129 strcpy(signalSignature.data() + 1 , sig);
4130 s->connectNotify(signalSignature.data());
4136 Disconnect a connection.
4138 If the \a connection is invalid or has already been disconnected, do nothing
4143 bool QObject::disconnect(const QMetaObject::Connection &connection)
4145 QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr);
4147 if (!c || !c->receiver)
4150 QMutex *senderMutex = signalSlotLock(c->sender);
4151 QMutex *receiverMutex = signalSlotLock(c->receiver);
4152 QOrderedMutexLocker locker(senderMutex, receiverMutex);
4154 QObjectConnectionListVector *connectionLists = QObjectPrivate::get(c->sender)->connectionLists;
4155 Q_ASSERT(connectionLists);
4156 connectionLists->dirty = true;
4160 c->next->prev = c->prev;
4165 /*! \fn bool QObject::disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)
4166 \overload diconnect()
4169 Disconnects \a signal in object \a sender from \a method in object
4170 \a receiver. Returns true if the connection is successfully broken;
4171 otherwise returns false.
4173 A signal-slot connection is removed when either of the objects
4174 involved are destroyed.
4176 disconnect() is typically used in three ways, as the following
4177 examples demonstrate.
4179 \li Disconnect everything connected to an object's signals:
4181 \snippet code/src_corelib_kernel_qobject.cpp 26
4183 \li Disconnect everything connected to a specific signal:
4185 \snippet code/src_corelib_kernel_qobject.cpp 47
4187 \li Disconnect a specific receiver:
4189 \snippet code/src_corelib_kernel_qobject.cpp 30
4191 \li Disconnect a connection from one specific signal to a specific slot:
4193 \snippet code/src_corelib_kernel_qobject.cpp 48
4198 0 may be used as a wildcard, meaning "any signal", "any receiving
4199 object", or "any slot in the receiving object", respectively.
4201 The \a sender may never be 0. (You cannot disconnect signals from
4202 more than one object in a single call.)
4204 If \a signal is 0, it disconnects \a receiver and \a method from
4205 any signal. If not, only the specified signal is disconnected.
4207 If \a receiver is 0, it disconnects anything connected to \a
4208 signal. If not, slots in objects other than \a receiver are not
4211 If \a method is 0, it disconnects anything that is connected to \a
4212 receiver. If not, only slots named \a method will be disconnected,
4213 and all other slots are left alone. The \a method must be 0 if \a
4214 receiver is left out, so you cannot disconnect a
4215 specifically-named slot on all objects.
4217 \note It is not possible to use this overload to diconnect signals
4218 connected to functors or lambda expressions. That is because it is not
4219 possible to compare them. Instead, use the olverload that take a
4220 QMetaObject::Connection
4225 bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, const QMetaObject *senderMetaObject)
4227 if (sender == 0 || (receiver == 0 && slot != 0)) {
4228 qWarning("QObject::disconnect: Unexpected null parameter");
4232 int signal_index = -1;
4234 void *args[] = { &signal_index, signal };
4235 senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
4236 if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) {
4237 qWarning("QObject::disconnect: signal not found in %s", senderMetaObject->className());
4240 int signalOffset, methodOffset;
4241 computeOffsets(senderMetaObject, &signalOffset, &methodOffset);
4242 signal_index += signalOffset;
4245 return QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1, slot);
4248 /*! \class QMetaObject::Connection
4249 Represents a handle to a signal-slot connection.
4250 It can be used to disconnect that connection, or check if
4251 the connection was successful
4253 \sa QObject::disconnect
4257 Create a copy of the handle to the connection
4259 QMetaObject::Connection::Connection(const QMetaObject::Connection &other) : d_ptr(other.d_ptr)
4262 static_cast<QObjectPrivate::Connection *>(d_ptr)->ref();
4265 QMetaObject::Connection& QMetaObject::Connection::operator=(const QMetaObject::Connection& other)
4267 if (other.d_ptr != d_ptr) {
4269 static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
4270 d_ptr = other.d_ptr;
4272 static_cast<QObjectPrivate::Connection *>(other.d_ptr)->ref();
4277 QMetaObject::Connection::Connection() : d_ptr(0) {}
4279 QMetaObject::Connection::~Connection()
4282 static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
4286 \fn QMetaObject::Connection::operator bool() const
4288 Returns true if the connection is valid.
4290 The connection is valid if the call to QObject::connect succeeded.
4291 The connection is invalid if QObject::connect was not able to find
4292 the signal or the slot, or if the arguments do not match.
4295 QObject::QSlotObjectBase::~QSlotObjectBase()
4299 bool QObject::QSlotObjectBase::compare(void** )
4307 #include "moc_qobject.cpp"