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>
This commit is contained in:
parent
56d4d97852
commit
dac23b9a57
@ -133,4 +133,8 @@ method.invoke(obj,
|
||||
Q_ARG(double, 9.7));
|
||||
//! [8]
|
||||
|
||||
//! [9]
|
||||
QMetaMethod destroyedSignal = QMetaMethod::fromSignal(&QObject::destroyed);
|
||||
//! [9]
|
||||
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user