diff options
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 49 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 6 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 28 |
3 files changed, 80 insertions, 3 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 68082910dc..3eda1b384e 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -5062,12 +5062,33 @@ bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject /*! \internal - Used by QML to connect a signal by index to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass). + Used by QML to connect a signal by index to a slot implemented in JavaScript + (wrapped in a custom QSlotObjectBase subclass). + + This version of connect assumes that sender and receiver are the same object. The signal_index is an index relative to the number of methods. */ QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type) { + return QObjectPrivate::connect(sender, signal_index, sender, slotObj, type); +} + +/*! + \internal + Used by QML to connect a signal by index to a slot implemented in JavaScript + (wrapped in a custom QSlotObjectBase subclass). + + This is an overload that should be used when \a sender and \a receiver are + different objects. + + The signal_index is an index relative to the number of methods. + */ +QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index, + const QObject *receiver, + QtPrivate::QSlotObjectBase *slotObj, + Qt::ConnectionType type) +{ if (!sender) { qCWarning(lcConnect, "QObject::connect: invalid nullptr parameter"); if (slotObj) @@ -5077,7 +5098,8 @@ QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signa const QMetaObject *senderMetaObject = sender->metaObject(); signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index); - return QObjectPrivate::connectImpl(sender, signal_index, sender, /*slot*/nullptr, slotObj, type, /*types*/nullptr, senderMetaObject); + return QObjectPrivate::connectImpl(sender, signal_index, receiver, /*slot*/ nullptr, slotObj, + type, /*types*/ nullptr, senderMetaObject); } /*! @@ -5085,13 +5107,34 @@ QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signa Used by QML to disconnect a signal by index that's connected to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass) In the QML case the slot is not a pointer to a pointer to the function to disconnect, but instead it is a pointer to an array of internal values required for the disconnect. + + This version of disconnect assumes that sender and receiver are the same object. */ bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void **slot) { + return QObjectPrivate::disconnect(sender, signal_index, sender, slot); +} + +/*! + \internal + + Used by QML to disconnect a signal by index that's connected to a slot + implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass) In the + QML case the slot is not a pointer to a pointer to the function to disconnect, + but instead it is a pointer to an array of internal values required for the + disconnect. + + This is an overload that should be used when \a sender and \a receiver are + different objects. + */ +bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, const QObject *receiver, + void **slot) +{ const QMetaObject *senderMetaObject = sender->metaObject(); signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index); - return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, sender, -1, slot); + return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, receiver, -1, + slot); } /*! diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index a9626a8ab0..4483e2b6ce 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -353,7 +353,13 @@ public: QtPrivate::QSlotObjectBase *slotObj, int type, const int *types, const QMetaObject *senderMetaObject); static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type); + static QMetaObject::Connection connect(const QObject *sender, int signal_index, + const QObject *receiver, + QtPrivate::QSlotObjectBase *slotObj, + Qt::ConnectionType type); static bool disconnect(const QObject *sender, int signal_index, void **slot); + static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver, + void **slot); static bool disconnect(Connection *c); void ensureConnectionData() diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 5cf1f0e50f..68d90987e1 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -149,6 +149,7 @@ private slots: void connectBase(); void connectWarnings(); void qmlConnect(); + void qmlConnectToQObjectReceiver(); void exceptions(); void noDeclarativeParentChangedOnDestruction(); void deleteLaterInAboutToBlockHandler(); @@ -6787,6 +6788,33 @@ void tst_QObject::qmlConnect() #endif } +void tst_QObject::qmlConnectToQObjectReceiver() +{ +#ifdef QT_BUILD_INTERNAL + SenderObject sender; + QScopedPointer<QObject> receiver(new QObject); + QmlReceiver *slotObject = new QmlReceiver; + slotObject->magic = slotObject; + slotObject->ref(); // extra ref so that slot object is not implicitly deleted + + QVERIFY(QObjectPrivate::connect(&sender, sender.metaObject()->indexOfSignal("signal1()"), + receiver.get(), slotObject, Qt::AutoConnection)); + + QCOMPARE(slotObject->callCount, 0); + sender.emitSignal1(); + QCOMPARE(slotObject->callCount, 1); + + receiver.reset(); // this should disconnect the slotObject + + sender.emitSignal1(); + QCOMPARE(slotObject->callCount, 1); + + slotObject->destroyIfLastRef(); +#else + QSKIP("Needs QT_BUILD_INTERNAL"); +#endif +} + #ifndef QT_NO_EXCEPTIONS class ObjectException : public std::exception { }; |