diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp index 7c0c2c21221..528fdbd329b 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp @@ -133,4 +133,8 @@ method.invoke(obj, Q_ARG(double, 9.7)); //! [8] +//! [9] +QMetaMethod destroyedSignal = QMetaMethod::fromSignal(&QObject::destroyed); +//! [9] + } diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 4414393d37b..45667ae3780 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1856,6 +1856,41 @@ QMetaMethod::MethodType QMetaMethod::methodType() const return (QMetaMethod::MethodType)((mobj->d.data[handle + 4] & MethodTypeMask)>>2); } +/*! + \fn QMetaMethod QMetaMethod::fromSignal(PointerToMemberFunction signal) + \since 5.0 + + Returns the meta-method that corresponds to the given \a signal, or an + invalid QMetaMethod if \a signal is not a signal of the class. + + Example: + + \snippet code/src_corelib_kernel_qmetaobject.cpp 9 +*/ + +/*! \internal + + Implementation of the fromSignal() function. + + \a metaObject is the class's meta-object + \a signal is a pointer to a pointer to a member signal of the class +*/ +QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **signal) +{ + int i = -1; + void *args[] = { &i, signal }; + QMetaMethod result; + for (const QMetaObject *m = metaObject; m; m = m->d.superdata) { + m->static_metacall(QMetaObject::IndexOfMethod, 0, args); + if (i >= 0) { + result.mobj = m; + result.handle = priv(m->d.data)->methodData + 5*i; + break; + } + } + return result; +} + /*! Invokes this method on the object \a object. Returns true if the member could be invoked. Returns false if there is no such member or the parameters did not match. diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 5204f04ca31..1c49506926e 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -141,6 +141,20 @@ public: inline bool isValid() const { return mobj != 0; } +#ifdef Q_QDOC + static QMetaMethod fromSignal(PointerToMemberFunction signal); +#else + template + static inline QMetaMethod fromSignal(Func signal) + { + typedef QtPrivate::FunctionPointer SignalType; + reinterpret_cast(0)->qt_check_for_QOBJECT_macro( + *reinterpret_cast(0)); + return fromSignalImpl(&SignalType::Object::staticMetaObject, + reinterpret_cast(&signal)); + } +#endif + private: #if QT_DEPRECATED_SINCE(5,0) // signature() has been renamed to methodSignature() in Qt 5. @@ -148,6 +162,7 @@ private: // you convert to char*. char *signature(struct renamedInQt5_warning_checkTheLifeTime * = 0) Q_DECL_EQ_DELETE; #endif + static QMetaMethod fromSignalImpl(const QMetaObject *, void **); const QMetaObject *mobj; uint handle; diff --git a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp index b5ab61443c6..2858bf64ebd 100644 --- a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp +++ b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp @@ -56,6 +56,8 @@ private slots: void invalidMethod(); void comparisonOperators(); + + void fromSignal(); }; struct CustomType { }; @@ -709,5 +711,30 @@ void tst_QMetaMethod::comparisonOperators() } } +void tst_QMetaMethod::fromSignal() +{ +#define FROMSIGNAL_HELPER(ObjectType, Name, Arguments) { \ + void (ObjectType::*signal)Arguments = &ObjectType::Name; \ + const QMetaObject *signalMeta = &ObjectType::staticMetaObject; \ + QCOMPARE(QMetaMethod::fromSignal(signal), \ + signalMeta->method(signalMeta->indexOfSignal(QMetaObject::normalizedSignature(#Name #Arguments)))); \ + } + + FROMSIGNAL_HELPER(MethodTestObject, voidSignal, ()) + FROMSIGNAL_HELPER(MethodTestObject, voidSignalQString, (const QString&)) + FROMSIGNAL_HELPER(QObject, destroyed, (QObject*)) + FROMSIGNAL_HELPER(QObject, objectNameChanged, (const QString &)) + + // Inherited from QObject + FROMSIGNAL_HELPER(MethodTestObject, destroyed, (QObject*)) + FROMSIGNAL_HELPER(MethodTestObject, objectNameChanged, (const QString &)) + + // Methods that are not signals; fromSignal should return invalid method + FROMSIGNAL_HELPER(MethodTestObject, voidSlot, ()) + FROMSIGNAL_HELPER(QObject, deleteLater, ()) + +#undef FROMSIGNAL_HELPER +} + QTEST_MAIN(tst_QMetaMethod) #include "tst_qmetamethod.moc"