src/corelib/kernel/qobject.cpp
changeset 30 5dc02b23752f
parent 19 fcece45ef507
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    99 static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
    99 static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
   100 
   100 
   101 /** \internal
   101 /** \internal
   102  * mutex to be locked when accessing the connectionlists or the senders list
   102  * mutex to be locked when accessing the connectionlists or the senders list
   103  */
   103  */
   104 static QMutex *signalSlotLock(const QObject *o)
   104 static inline QMutex *signalSlotLock(const QObject *o)
   105 {
   105 {
   106     if (!signalSlotMutexes) {
   106     if (!signalSlotMutexes) {
   107         QMutexPool *mp = new QMutexPool;
   107         QMutexPool *mp = new QMutexPool;
   108         if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
   108         if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
   109             delete mp;
   109             delete mp;
   123         QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
   123         QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
   124         delete old;
   124         delete old;
   125     }
   125     }
   126 }
   126 }
   127 
   127 
       
   128 void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
       
   129 void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
       
   130 
   128 QObjectData::~QObjectData() {}
   131 QObjectData::~QObjectData() {}
   129 QDeclarativeData::~QDeclarativeData() {}
       
   130 
   132 
   131 QObjectPrivate::QObjectPrivate(int version)
   133 QObjectPrivate::QObjectPrivate(int version)
   132     : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
   134     : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
   133 {
   135 {
   134     if (version != QObjectPrivateVersion)
   136     if (version != QObjectPrivateVersion)
   135         qFatal("Cannot mix incompatible Qt libraries");
   137         qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
       
   138                 version, QObjectPrivateVersion);
   136 
   139 
   137     // QObjectData initialization
   140     // QObjectData initialization
   138     q_ptr = 0;
   141     q_ptr = 0;
   139     parent = 0;                                 // no parent yet. It is set by setParent()
   142     parent = 0;                                 // no parent yet. It is set by setParent()
   140     isWidget = false;                           // assume not a widget object
   143     isWidget = false;                           // assume not a widget object
   388         }
   391         }
   389         connectionLists->dirty = false;
   392         connectionLists->dirty = false;
   390     }
   393     }
   391 }
   394 }
   392 
   395 
   393 QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
       
   394                                                          Sender *sender)
       
   395 {
       
   396     Sender *previousSender = receiver->d_func()->currentSender;
       
   397     receiver->d_func()->currentSender = sender;
       
   398     return previousSender;
       
   399 }
       
   400 
       
   401 void QObjectPrivate::resetCurrentSender(QObject *receiver,
       
   402                                         Sender *currentSender,
       
   403                                         Sender *previousSender)
       
   404 {
       
   405     // ref is set to zero when this object is deleted during the metacall
       
   406     if (currentSender->ref == 1)
       
   407         receiver->d_func()->currentSender = previousSender;
       
   408     // if we've recursed, we need to tell the caller about the objects deletion
       
   409     if (previousSender)
       
   410         previousSender->ref = currentSender->ref;
       
   411 }
       
   412 
       
   413 
       
   414 typedef QMultiHash<QObject *, QObject **> GuardHash;
   396 typedef QMultiHash<QObject *, QObject **> GuardHash;
   415 Q_GLOBAL_STATIC(GuardHash, guardHash)
   397 Q_GLOBAL_STATIC(GuardHash, guardHash)
   416 Q_GLOBAL_STATIC(QMutex, guardHashLock)
   398 Q_GLOBAL_STATIC(QMutex, guardHashLock)
   417 
   399 
   418 /*!\internal
   400 /*!\internal
   493 /*! \internal
   475 /*! \internal
   494  */
   476  */
   495 void QObjectPrivate::clearGuards(QObject *object)
   477 void QObjectPrivate::clearGuards(QObject *object)
   496 {
   478 {
   497     QObjectPrivate *priv = QObjectPrivate::get(object);
   479     QObjectPrivate *priv = QObjectPrivate::get(object);
   498     QGuard<QObject> *guard = priv->extraData ? priv->extraData->objectGuards : 0;
       
   499     while (guard) {
       
   500         QGuard<QObject> *g = guard;
       
   501         guard = guard->next;
       
   502         g->o = 0;
       
   503         g->prev = 0;
       
   504         g->next = 0;
       
   505         g->objectDestroyed(object);
       
   506     }
       
   507 
   480 
   508     if (!priv->hasGuards)
   481     if (!priv->hasGuards)
   509         return;
   482         return;
   510 
   483 
   511     GuardHash *hash = 0;
   484     GuardHash *hash = 0;
   567 
   540 
   568     \ingroup objectmodel
   541     \ingroup objectmodel
   569 
   542 
   570     \reentrant
   543     \reentrant
   571 
   544 
   572     QObject is the heart of the \l{Qt object model}. The central
   545     QObject is the heart of the Qt \l{Object Model}. The central
   573     feature in this model is a very powerful mechanism for seamless
   546     feature in this model is a very powerful mechanism for seamless
   574     object communication called \l{signals and slots}. You can
   547     object communication called \l{signals and slots}. You can
   575     connect a signal to a slot with connect() and destroy the
   548     connect a signal to a slot with connect() and destroy the
   576     connection with disconnect(). To avoid never ending notification
   549     connection with disconnect(). To avoid never ending notification
   577     loops you can temporarily block signals with blockSignals(). The
   550     loops you can temporarily block signals with blockSignals(). The
   578     protected functions connectNotify() and disconnectNotify() make
   551     protected functions connectNotify() and disconnectNotify() make
   579     it possible to track connections.
   552     it possible to track connections.
   580 
   553 
   581     QObjects organize themselves in \l {Object Trees and Object
   554     QObjects organize themselves in \l {Object Trees & Ownership}
   582     Ownership} {object trees}. When you create a QObject with another
   555     {object trees}. When you create a QObject with another object as
   583     object as parent, the object will automatically add itself to the
   556     parent, the object will automatically add itself to the parent's
   584     parent's children() list. The parent takes ownership of the
   557     children() list. The parent takes ownership of the object; i.e.,
   585     object; i.e., it will automatically delete its children in its
   558     it will automatically delete its children in its destructor. You
   586     destructor. You can look for an object by name and optionally type
   559     can look for an object by name and optionally type using
   587     using findChild() or findChildren().
   560     findChild() or findChildren().
   588 
   561 
   589     Every object has an objectName() and its class name can be found
   562     Every object has an objectName() and its class name can be found
   590     via the corresponding metaObject() (see QMetaObject::className()).
   563     via the corresponding metaObject() (see QMetaObject::className()).
   591     You can determine whether the object's class inherits another
   564     You can determine whether the object's class inherits another
   592     class in the QObject inheritance hierarchy by using the
   565     class in the QObject inheritance hierarchy by using the
   634     This is by design. Actually, they are declared, but in a
   607     This is by design. Actually, they are declared, but in a
   635     \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
   608     \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
   636     Qt classes derived from QObject (direct or indirect) use this
   609     Qt classes derived from QObject (direct or indirect) use this
   637     macro to declare their copy constructor and assignment operator to
   610     macro to declare their copy constructor and assignment operator to
   638     be private. The reasoning is found in the discussion on
   611     be private. The reasoning is found in the discussion on
   639     \l{Identity vs Value} {Identity vs Value} on the \l{Qt Object
   612     \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
   640     Model} page.
   613     Model} page.
   641 
   614 
   642     The main consequence is that you should use pointers to QObject
   615     The main consequence is that you should use pointers to QObject
   643     (or to your QObject subclass) where you might otherwise be tempted
   616     (or to your QObject subclass) where you might otherwise be tempted
   644     to use your QObject subclass as a value. For example, without a
   617     to use your QObject subclass as a value. For example, without a
   681     To make user-visible text translatable, it must be wrapped in calls to
   654     To make user-visible text translatable, it must be wrapped in calls to
   682     the tr() function. This is explained in detail in the
   655     the tr() function. This is explained in detail in the
   683     \l{Writing Source Code for Translation} document.
   656     \l{Writing Source Code for Translation} document.
   684 
   657 
   685     \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
   658     \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
   686     \sa {Object Trees and Object Ownership}
   659     \sa {Object Trees & Ownership}
   687 */
   660 */
   688 
   661 
   689 /*!
   662 /*!
   690     \relates QObject
   663     \relates QObject
   691 
   664 
   869         emit destroyed(this);
   842         emit destroyed(this);
   870     } QT_CATCH(...) {
   843     } QT_CATCH(...) {
   871         // all the signal/slots connections are still in place - if we don't
   844         // all the signal/slots connections are still in place - if we don't
   872         // quit now, we will crash pretty soon.
   845         // quit now, we will crash pretty soon.
   873         qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");
   846         qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");
   874 #if defined(Q_AUTOTEST_EXPORT) && !defined(QT_NO_EXCEPTIONS)
   847 #if defined(Q_BUILD_INTERNAL) && !defined(QT_NO_EXCEPTIONS)
   875         struct AutotestException : public std::exception
   848         struct AutotestException : public std::exception
   876         {
   849         {
   877             const char *what() const throw() { return "autotest swallow"; }
   850             const char *what() const throw() { return "autotest swallow"; }
   878         } autotestException;
   851         } autotestException;
   879         // throw autotestException;
   852         // throw autotestException;
   882         QT_RETHROW;
   855         QT_RETHROW;
   883 #endif
   856 #endif
   884     }
   857     }
   885 
   858 
   886     if (d->declarativeData)
   859     if (d->declarativeData)
   887         d->declarativeData->destroyed(this);
   860         QAbstractDeclarativeData::destroyed(d->declarativeData, this);
   888 
   861 
   889     {
   862     // set ref to zero to indicate that this object has been deleted
   890         QMutex *signalSlotMutex = 0;
   863     if (d->currentSender != 0)
   891         QT_TRY {
   864         d->currentSender->ref = 0;
   892             signalSlotMutex = signalSlotLock(this);
   865     d->currentSender = 0;
   893         } QT_CATCH(const std::bad_alloc &) {
   866 
   894             // out of memory - swallow to prevent a crash
   867     if (d->connectionLists || d->senders) {
   895         }
   868         QMutex *signalSlotMutex = signalSlotLock(this);
   896         QMutexLocker locker(signalSlotMutex);
   869         QMutexLocker locker(signalSlotMutex);
   897 
       
   898         // set ref to zero to indicate that this object has been deleted
       
   899         if (d->currentSender != 0)
       
   900             d->currentSender->ref = 0;
       
   901         d->currentSender = 0;
       
   902 
   870 
   903         // disconnect all receivers
   871         // disconnect all receivers
   904         if (d->connectionLists) {
   872         if (d->connectionLists) {
   905             ++d->connectionLists->inUse;
   873             ++d->connectionLists->inUse;
   906             for (int signal = -1; signal < d->connectionLists->count(); ++signal) {
   874             int connectionListsCount = d->connectionLists->count();
       
   875             for (int signal = -1; signal < connectionListsCount; ++signal) {
   907                 QObjectPrivate::ConnectionList &connectionList =
   876                 QObjectPrivate::ConnectionList &connectionList =
   908                     (*d->connectionLists)[signal];
   877                     (*d->connectionLists)[signal];
   909 
   878 
   910                 while (QObjectPrivate::Connection *c = connectionList.first) {
   879                 while (QObjectPrivate::Connection *c = connectionList.first) {
   911                     if (!c->receiver) {
   880                     if (!c->receiver) {
   913                         delete c;
   882                         delete c;
   914                         continue;
   883                         continue;
   915                     }
   884                     }
   916 
   885 
   917                     QMutex *m = signalSlotLock(c->receiver);
   886                     QMutex *m = signalSlotLock(c->receiver);
   918                     bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
   887                     bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
   919 
   888 
   920                     if (c->receiver) {
   889                     if (c->receiver) {
   921                         *c->prev = c->next;
   890                         *c->prev = c->next;
   922                         if (c->next) c->next->prev = c->prev;
   891                         if (c->next) c->next->prev = c->prev;
   923                     }
   892                     }
   938         }
   907         }
   939 
   908 
   940         // disconnect all senders
   909         // disconnect all senders
   941         QObjectPrivate::Connection *node = d->senders;
   910         QObjectPrivate::Connection *node = d->senders;
   942         while (node) {
   911         while (node) {
   943             QMutex *m = signalSlotLock(node->sender);
   912             QObject *sender = node->sender;
       
   913             QMutex *m = signalSlotLock(sender);
   944             node->prev = &node;
   914             node->prev = &node;
   945             bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
   915             bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
   946             //the node has maybe been removed while the mutex was unlocked in relock?
   916             //the node has maybe been removed while the mutex was unlocked in relock?
   947             if (!node || signalSlotLock(node->sender) != m) {
   917             if (!node || node->sender != sender) {
   948                 m->unlock();
   918                 m->unlock();
   949                 continue;
   919                 continue;
   950             }
   920             }
   951             node->receiver = 0;
   921             node->receiver = 0;
   952             QObjectConnectionListVector *senderLists = node->sender->d_func()->connectionLists;
   922             QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists;
   953             if (senderLists)
   923             if (senderLists)
   954                 senderLists->dirty = true;
   924                 senderLists->dirty = true;
   955 
   925 
   956             node = node->next;
   926             node = node->next;
   957             if (needToUnlock)
   927             if (needToUnlock)
   974     if (!d->children.isEmpty())
   944     if (!d->children.isEmpty())
   975         d->deleteChildren();
   945         d->deleteChildren();
   976 
   946 
   977     qt_removeObject(this);
   947     qt_removeObject(this);
   978 
   948 
   979     QCoreApplication::removePostedEvents(this);
   949     if (d->postedEvents)
       
   950         QCoreApplication::removePostedEvents(this, 0);
   980 
   951 
   981     if (d->parent)        // remove it from parent object
   952     if (d->parent)        // remove it from parent object
   982         d->setParent_helper(0);
   953         d->setParent_helper(0);
   983 
   954 
   984     d->threadData->deref();
   955     d->threadData->deref();
  1474         // one exception to the rule: we allow moving objects with no thread affinity to the current thread
  1445         // one exception to the rule: we allow moving objects with no thread affinity to the current thread
  1475         currentData = d->threadData;
  1446         currentData = d->threadData;
  1476     } else if (d->threadData != currentData) {
  1447     } else if (d->threadData != currentData) {
  1477         qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
  1448         qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
  1478                  "Cannot move to target thread (%p)\n",
  1449                  "Cannot move to target thread (%p)\n",
  1479                  d->threadData->thread, currentData->thread, targetData->thread);
  1450                  currentData->thread, d->threadData->thread, targetData->thread);
  1480 
  1451 
  1481 #ifdef Q_WS_MAC
  1452 #ifdef Q_WS_MAC
  1482         qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. "
  1453         qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. "
  1483                  "Check that all plugins are compiled against the right Qt binaries. Export "
  1454                  "Check that all plugins are compiled against the right Qt binaries. Export "
  1484                  "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
  1455                  "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
  2028                 parent->d_func()->pendingChildInsertedEvents.append(q);
  1999                 parent->d_func()->pendingChildInsertedEvents.append(q);
  2029 #endif
  2000 #endif
  2030             }
  2001             }
  2031         }
  2002         }
  2032     }
  2003     }
       
  2004     if (!wasDeleted && declarativeData)
       
  2005         QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
  2033 }
  2006 }
  2034 
  2007 
  2035 /*!
  2008 /*!
  2036     \fn void QObject::installEventFilter(QObject *filterObj)
  2009     \fn void QObject::installEventFilter(QObject *filterObj)
  2037 
  2010 
  2508     if (!check_signal_macro(sender, signal, "connect", "bind"))
  2481     if (!check_signal_macro(sender, signal, "connect", "bind"))
  2509         return false;
  2482         return false;
  2510     const QMetaObject *smeta = sender->metaObject();
  2483     const QMetaObject *smeta = sender->metaObject();
  2511     const char *signal_arg = signal;
  2484     const char *signal_arg = signal;
  2512     ++signal; //skip code
  2485     ++signal; //skip code
  2513     int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal);
  2486     int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
  2514     if (signal_index < 0) {
  2487     if (signal_index < 0) {
  2515         // check for normalized signatures
  2488         // check for normalized signatures
  2516         tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
  2489         tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
  2517         signal = tmp_signal_name.constData() + 1;
  2490         signal = tmp_signal_name.constData() + 1;
  2518 
  2491 
  2519         smeta = sender->metaObject();
  2492         smeta = sender->metaObject();
  2520         signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal);
  2493         signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
  2521 
  2494     }
  2522         if (signal_index < 0) {
  2495     if (signal_index < 0) {
  2523             err_method_notfound(sender, signal_arg, "connect");
  2496         // re-use tmp_signal_name and signal from above
  2524             err_info_about_objects("connect", sender, receiver);
  2497 
  2525             return false;
  2498         smeta = sender->metaObject();
  2526         }
  2499         signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
       
  2500     }
       
  2501     if (signal_index < 0) {
       
  2502         err_method_notfound(sender, signal_arg, "connect");
       
  2503         err_info_about_objects("connect", sender, receiver);
       
  2504         return false;
  2527     }
  2505     }
  2528     signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
  2506     signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
  2529     int signalOffset, methodOffset;
  2507     int signalOffset, methodOffset;
  2530     computeOffsets(smeta, &signalOffset, &methodOffset);
  2508     computeOffsets(smeta, &signalOffset, &methodOffset);
  2531     int signal_absolute_index = signal_index + methodOffset;
  2509     int signal_absolute_index = signal_index + methodOffset;
  2541 
  2519 
  2542     const QMetaObject *rmeta = receiver->metaObject();
  2520     const QMetaObject *rmeta = receiver->metaObject();
  2543     int method_index = -1;
  2521     int method_index = -1;
  2544     switch (membcode) {
  2522     switch (membcode) {
  2545     case QSLOT_CODE:
  2523     case QSLOT_CODE:
  2546         method_index = rmeta->indexOfSlot(method);
  2524         method_index = QMetaObjectPrivate::indexOfSlot(rmeta, method, false);
  2547         break;
  2525         break;
  2548     case QSIGNAL_CODE:
  2526     case QSIGNAL_CODE:
  2549         method_index = rmeta->indexOfSignal(method);
  2527         method_index = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
       
  2528         if (method_index >= 0)
       
  2529             method_index += rmeta->methodOffset();
  2550         break;
  2530         break;
  2551     }
  2531     }
  2552     if (method_index < 0) {
  2532     if (method_index < 0) {
  2553         // check for normalized methods
  2533         // check for normalized methods
  2554         tmp_method_name = QMetaObject::normalizedSignature(method);
  2534         tmp_method_name = QMetaObject::normalizedSignature(method);
  2555         method = tmp_method_name.constData();
  2535         method = tmp_method_name.constData();
       
  2536 
       
  2537         // rmeta may have been modified above
       
  2538         rmeta = receiver->metaObject();
  2556         switch (membcode) {
  2539         switch (membcode) {
  2557         case QSLOT_CODE:
  2540         case QSLOT_CODE:
  2558             method_index = rmeta->indexOfSlot(method);
  2541             method_index = rmeta->indexOfSlot(method);
  2559             break;
  2542             break;
  2560         case QSIGNAL_CODE:
  2543         case QSIGNAL_CODE:
  2738     bool res = false;
  2721     bool res = false;
  2739     const QMetaObject *smeta = sender->metaObject();
  2722     const QMetaObject *smeta = sender->metaObject();
  2740     do {
  2723     do {
  2741         int signal_index = -1;
  2724         int signal_index = -1;
  2742         if (signal) {
  2725         if (signal) {
  2743             signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal);
  2726             signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
       
  2727             if (signal_index < 0)
       
  2728                 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
  2744             if (signal_index < 0)
  2729             if (signal_index < 0)
  2745                 break;
  2730                 break;
  2746             signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
  2731             signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
  2747             int signalOffset, methodOffset;
  2732             int signalOffset, methodOffset;
  2748             computeOffsets(smeta, &signalOffset, &methodOffset);
  2733             computeOffsets(smeta, &signalOffset, &methodOffset);
  3219     if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
  3204     if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
  3220         qt_signal_spy_callback_set.signal_begin_callback(sender, signal_absolute_index,
  3205         qt_signal_spy_callback_set.signal_begin_callback(sender, signal_absolute_index,
  3221                                                          argv ? argv : empty_argv);
  3206                                                          argv ? argv : empty_argv);
  3222     }
  3207     }
  3223 
  3208 
       
  3209     QThreadData *currentThreadData = QThreadData::current();
       
  3210 
  3224     QMutexLocker locker(signalSlotLock(sender));
  3211     QMutexLocker locker(signalSlotLock(sender));
  3225     QThreadData *currentThreadData = QThreadData::current();
       
  3226 
       
  3227     QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
  3212     QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
  3228     if (!connectionLists) {
  3213     if (!connectionLists) {
  3229         locker.unlock();
  3214         locker.unlock();
  3230         if (qt_signal_spy_callback_set.signal_end_callback != 0)
  3215         if (qt_signal_spy_callback_set.signal_end_callback != 0)
  3231             qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
  3216             qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
  3317     --connectionLists->inUse;
  3302     --connectionLists->inUse;
  3318     Q_ASSERT(connectionLists->inUse >= 0);
  3303     Q_ASSERT(connectionLists->inUse >= 0);
  3319     if (connectionLists->orphaned) {
  3304     if (connectionLists->orphaned) {
  3320         if (!connectionLists->inUse)
  3305         if (!connectionLists->inUse)
  3321             delete connectionLists;
  3306             delete connectionLists;
  3322     } else {
  3307     } else if (connectionLists->dirty) {
  3323         sender->d_func()->cleanConnectionLists();
  3308         sender->d_func()->cleanConnectionLists();
  3324     }
  3309     }
  3325 
  3310 
  3326     locker.unlock();
  3311     locker.unlock();
  3327 
  3312 
  3361 */
  3346 */
  3362 int QObjectPrivate::signalIndex(const char *signalName) const
  3347 int QObjectPrivate::signalIndex(const char *signalName) const
  3363 {
  3348 {
  3364     Q_Q(const QObject);
  3349     Q_Q(const QObject);
  3365     const QMetaObject *base = q->metaObject();
  3350     const QMetaObject *base = q->metaObject();
  3366     int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName);
  3351     int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false);
       
  3352     if (relative_index < 0)
       
  3353         relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true);
  3367     if (relative_index < 0)
  3354     if (relative_index < 0)
  3368         return relative_index;
  3355         return relative_index;
  3369     relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
  3356     relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
  3370     int signalOffset, methodOffset;
  3357     int signalOffset, methodOffset;
  3371     computeOffsets(base, &signalOffset, &methodOffset);
  3358     computeOffsets(base, &signalOffset, &methodOffset);