summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qmetaobject.cpp106
-rw-r--r--src/corelib/kernel/qmetaobject.h28
-rw-r--r--tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp49
3 files changed, 183 insertions, 0 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 7f37a1ce9a..1b7ced8dc8 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -2299,6 +2299,112 @@ bool QMetaMethod::invoke(QObject *object,
*/
/*!
+ \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
\brief The QMetaEnum class provides meta-data about an enumerator.
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index dca920d7ac..e68b899280 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -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
diff --git a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
index 1d39280afb..18de761e2a 100644
--- a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
+++ b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
@@ -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"