summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2012-04-22 22:44:58 +0200
committerQt by Nokia <qt-info@nokia.com>2012-04-27 10:37:02 +0200
commitdac23b9a5700d3736cfb1aa2dccb1643f1122827 (patch)
tree82f00219fe8681a78b06bfb8c0d9fc077014a43e
parent56d4d97852b37d9d1ca73d5b7f85e3865912f3db (diff)
Add QMetaMethod::fromSignal() function
Given a member function that's a signal, returns the corresponding QMetaMethod. Inspired by the implementation of the template-based QObject::connect(). The primary use case for this function is to have an effective and exact (not subject to shadowing) way of checking whether a known signal was connected to in reimplementations of QObject::connectNotify(QMetaMethod), avoiding string comparisons. Example: void MyObject::connectNotify(const QMetaMethod &signal) { if (signal == QMetaMethod::fromSignal(&MyObject::mySignal)) { // Someone connected to mySignal ... } } Change-Id: I5e4de434275fe543c004d569dcaa9ceda3442f03 Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp4
-rw-r--r--src/corelib/kernel/qmetaobject.cpp35
-rw-r--r--src/corelib/kernel/qmetaobject.h15
-rw-r--r--tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp27
4 files changed, 81 insertions, 0 deletions
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 7c0c2c2122..528fdbd329 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 4414393d37..45667ae378 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -1857,6 +1857,41 @@ QMetaMethod::MethodType QMetaMethod::methodType() const
}
/*!
+ \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 5204f04ca3..1c49506926 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 <typename Func>
+ static inline QMetaMethod fromSignal(Func signal)
+ {
+ typedef QtPrivate::FunctionPointer<Func> SignalType;
+ reinterpret_cast<typename SignalType::Object *>(0)->qt_check_for_QOBJECT_macro(
+ *reinterpret_cast<typename SignalType::Object *>(0));
+ return fromSignalImpl(&SignalType::Object::staticMetaObject,
+ reinterpret_cast<void **>(&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 b5ab61443c..2858bf64eb 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"