Make Q_INVOKABLE work on Q_GADGET
Methods can be invoked with QMetaMethod::invokeOnGadget Change-Id: Id734868bb530b02587daf0f62bce01798ade2ac2 Reviewed-by: Lars Knoll <lars.knoll@digia.com> Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>bb10
parent
d9e8571f4d
commit
8c77a7f77a
|
|
@ -2298,6 +2298,112 @@ bool QMetaMethod::invoke(QObject *object,
|
|||
connection type Qt::AutoConnection and ignores return values.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 5.5
|
||||
|
||||
Invokes this method on a Q_GADGET. Returns \c true if the member could be invoked.
|
||||
Returns \c false if there is no such member or the parameters did not match.
|
||||
|
||||
The pointer \a gadget must point to an instance of the gadget class.
|
||||
|
||||
The invocation is always synchronous.
|
||||
|
||||
The return value of this method call is placed in \a
|
||||
returnValue. You can pass up to ten arguments (\a val0, \a val1,
|
||||
\a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
|
||||
and \a val9) to this method call.
|
||||
|
||||
\warning this method will not test the validity of the arguments: \a gadget
|
||||
must be an instance of the class of the QMetaObject of which this QMetaMethod
|
||||
has been constructed with. The arguments must have the same type as the ones
|
||||
expected by the method, else, the behavior is undefined.
|
||||
|
||||
\sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
|
||||
*/
|
||||
bool QMetaMethod::invokeOnGadget(void* gadget, QGenericReturnArgument returnValue, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9) const
|
||||
{
|
||||
if (!gadget || !mobj)
|
||||
return false;
|
||||
|
||||
// check return type
|
||||
if (returnValue.data()) {
|
||||
const char *retType = typeName();
|
||||
if (qstrcmp(returnValue.name(), retType) != 0) {
|
||||
// normalize the return value as well
|
||||
QByteArray normalized = QMetaObject::normalizedType(returnValue.name());
|
||||
if (qstrcmp(normalized.constData(), retType) != 0) {
|
||||
// String comparison failed, try compare the metatype.
|
||||
int t = returnType();
|
||||
if (t == QMetaType::UnknownType || t != QMetaType::type(normalized))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check argument count (we don't allow invoking a method if given too few arguments)
|
||||
const char *typeNames[] = {
|
||||
returnValue.name(),
|
||||
val0.name(),
|
||||
val1.name(),
|
||||
val2.name(),
|
||||
val3.name(),
|
||||
val4.name(),
|
||||
val5.name(),
|
||||
val6.name(),
|
||||
val7.name(),
|
||||
val8.name(),
|
||||
val9.name()
|
||||
};
|
||||
int paramCount;
|
||||
for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
|
||||
if (qstrlen(typeNames[paramCount]) <= 0)
|
||||
break;
|
||||
}
|
||||
if (paramCount <= QMetaMethodPrivate::get(this)->parameterCount())
|
||||
return false;
|
||||
|
||||
// invoke!
|
||||
void *param[] = {
|
||||
returnValue.data(),
|
||||
val0.data(),
|
||||
val1.data(),
|
||||
val2.data(),
|
||||
val3.data(),
|
||||
val4.data(),
|
||||
val5.data(),
|
||||
val6.data(),
|
||||
val7.data(),
|
||||
val8.data(),
|
||||
val9.data()
|
||||
};
|
||||
int idx_relative = QMetaMethodPrivate::get(this)->ownMethodIndex();
|
||||
Q_ASSERT(QMetaObjectPrivate::get(mobj)->revision >= 6);
|
||||
QObjectPrivate::StaticMetaCallFunction callFunction = mobj->d.static_metacall;
|
||||
if (!callFunction)
|
||||
return false;
|
||||
callFunction(reinterpret_cast<QObject*>(gadget), QMetaObject::InvokeMetaMethod, idx_relative, param);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool QMetaMethod::invokeOnGadget(void *gadget,
|
||||
QGenericArgument val0 = QGenericArgument(0),
|
||||
QGenericArgument val1 = QGenericArgument(),
|
||||
QGenericArgument val2 = QGenericArgument(),
|
||||
QGenericArgument val3 = QGenericArgument(),
|
||||
QGenericArgument val4 = QGenericArgument(),
|
||||
QGenericArgument val5 = QGenericArgument(),
|
||||
QGenericArgument val6 = QGenericArgument(),
|
||||
QGenericArgument val7 = QGenericArgument(),
|
||||
QGenericArgument val8 = QGenericArgument(),
|
||||
QGenericArgument val9 = QGenericArgument()) const
|
||||
|
||||
\overload
|
||||
\since 5.5
|
||||
|
||||
This overload invokes this method for a \a gadget and ignores return values.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QMetaEnum
|
||||
\inmodule QtCore
|
||||
|
|
|
|||
|
|
@ -132,6 +132,34 @@ public:
|
|||
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
|
||||
}
|
||||
|
||||
bool invokeOnGadget(void *gadget,
|
||||
QGenericReturnArgument returnValue,
|
||||
QGenericArgument val0 = QGenericArgument(0),
|
||||
QGenericArgument val1 = QGenericArgument(),
|
||||
QGenericArgument val2 = QGenericArgument(),
|
||||
QGenericArgument val3 = QGenericArgument(),
|
||||
QGenericArgument val4 = QGenericArgument(),
|
||||
QGenericArgument val5 = QGenericArgument(),
|
||||
QGenericArgument val6 = QGenericArgument(),
|
||||
QGenericArgument val7 = QGenericArgument(),
|
||||
QGenericArgument val8 = QGenericArgument(),
|
||||
QGenericArgument val9 = QGenericArgument()) const;
|
||||
inline bool invokeOnGadget(void *gadget,
|
||||
QGenericArgument val0 = QGenericArgument(0),
|
||||
QGenericArgument val1 = QGenericArgument(),
|
||||
QGenericArgument val2 = QGenericArgument(),
|
||||
QGenericArgument val3 = QGenericArgument(),
|
||||
QGenericArgument val4 = QGenericArgument(),
|
||||
QGenericArgument val5 = QGenericArgument(),
|
||||
QGenericArgument val6 = QGenericArgument(),
|
||||
QGenericArgument val7 = QGenericArgument(),
|
||||
QGenericArgument val8 = QGenericArgument(),
|
||||
QGenericArgument val9 = QGenericArgument()) const
|
||||
{
|
||||
return invokeOnGadget(gadget, QGenericReturnArgument(),
|
||||
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
|
||||
}
|
||||
|
||||
inline bool isValid() const { return mobj != 0; }
|
||||
|
||||
#ifdef Q_QDOC
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
|
|
@ -50,6 +51,8 @@ private slots:
|
|||
void comparisonOperators();
|
||||
|
||||
void fromSignal();
|
||||
|
||||
void gadget();
|
||||
};
|
||||
|
||||
struct CustomType { };
|
||||
|
|
@ -727,5 +730,51 @@ void tst_QMetaMethod::fromSignal()
|
|||
#undef FROMSIGNAL_HELPER
|
||||
}
|
||||
|
||||
class MyGadget {
|
||||
Q_GADGET
|
||||
public:
|
||||
QString m_value;
|
||||
Q_INVOKABLE void setValue(const QString &value) { m_value = value; }
|
||||
Q_INVOKABLE QString getValue() { return m_value; }
|
||||
};
|
||||
|
||||
void tst_QMetaMethod::gadget()
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = MyGadget::staticMetaObject.indexOfMethod("setValue(QString)");
|
||||
QVERIFY(idx >= 0);
|
||||
QMetaMethod setValueMethod = MyGadget::staticMetaObject.method(idx);
|
||||
QVERIFY(setValueMethod.isValid());
|
||||
|
||||
idx = MyGadget::staticMetaObject.indexOfMethod("getValue()");
|
||||
QVERIFY(idx >= 0);
|
||||
QMetaMethod getValueMethod = MyGadget::staticMetaObject.method(idx);
|
||||
QVERIFY(getValueMethod.isValid());
|
||||
|
||||
{
|
||||
MyGadget gadget;
|
||||
QString string;
|
||||
|
||||
QVERIFY(getValueMethod.invokeOnGadget(&gadget, Q_RETURN_ARG(QString, string)));
|
||||
QCOMPARE(string, gadget.m_value);
|
||||
|
||||
QVERIFY(setValueMethod.invokeOnGadget(&gadget, Q_ARG(QString, QLatin1String("hello"))));
|
||||
QCOMPARE(gadget.m_value, QLatin1String("hello"));
|
||||
|
||||
QVERIFY(getValueMethod.invokeOnGadget(&gadget, Q_RETURN_ARG(QString, string)));
|
||||
QCOMPARE(string, gadget.m_value);
|
||||
}
|
||||
|
||||
{
|
||||
// Call with null should not crash
|
||||
MyGadget *gadget = Q_NULLPTR;
|
||||
QString string;
|
||||
QVERIFY(!setValueMethod.invokeOnGadget(gadget, Q_ARG(QString, QLatin1String("hi"))));
|
||||
QVERIFY(!getValueMethod.invokeOnGadget(gadget, Q_RETURN_ARG(QString, string)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN(tst_QMetaMethod)
|
||||
#include "tst_qmetamethod.moc"
|
||||
|
|
|
|||
Loading…
Reference in New Issue