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));
|
Q_ARG(double, 9.7));
|
||||||
//! [8]
|
//! [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);
|
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.
|
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.
|
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; }
|
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:
|
private:
|
||||||
#if QT_DEPRECATED_SINCE(5,0)
|
#if QT_DEPRECATED_SINCE(5,0)
|
||||||
// signature() has been renamed to methodSignature() in Qt 5.
|
// signature() has been renamed to methodSignature() in Qt 5.
|
||||||
@ -148,6 +162,7 @@ private:
|
|||||||
// you convert to char*.
|
// you convert to char*.
|
||||||
char *signature(struct renamedInQt5_warning_checkTheLifeTime * = 0) Q_DECL_EQ_DELETE;
|
char *signature(struct renamedInQt5_warning_checkTheLifeTime * = 0) Q_DECL_EQ_DELETE;
|
||||||
#endif
|
#endif
|
||||||
|
static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
|
||||||
|
|
||||||
const QMetaObject *mobj;
|
const QMetaObject *mobj;
|
||||||
uint handle;
|
uint handle;
|
||||||
|
@ -56,6 +56,8 @@ private slots:
|
|||||||
void invalidMethod();
|
void invalidMethod();
|
||||||
|
|
||||||
void comparisonOperators();
|
void comparisonOperators();
|
||||||
|
|
||||||
|
void fromSignal();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CustomType { };
|
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)
|
QTEST_MAIN(tst_QMetaMethod)
|
||||||
#include "tst_qmetamethod.moc"
|
#include "tst_qmetamethod.moc"
|
||||||
|
Loading…
Reference in New Issue
Block a user