summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-03-18 15:56:17 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-03-22 17:37:28 +0100
commit855472a28675f11778a54ef1e42f6114d924b9e2 (patch)
tree08a7c30b4b65a9a467c36f09fbdb7c51d53b18e4
parentf6595345f053c43660d27fb9529baaa19ca96dcf (diff)
downloadqtactiveqt-855472a28675f11778a54ef1e42f6114d924b9e2.tar.gz
Fix QAxScriptManager::call
It takes the name of the function, not of the script name so use the scriptForFunction helper to find the QAxScript object that provides access to the function. The previous code implies that this should work for both function names and for full function prototypes, so implement that correctly and without allocating too many unnecessary temporary objects. Update the test that is now passing to cover all scenarios. Pick-to: 6.5 Change-Id: I939942cc805a56212d70b1a12b95aaa4b2f64d59 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
-rw-r--r--src/activeqt/container/qaxscript.cpp60
-rw-r--r--src/activeqt/container/qaxscript.h2
-rw-r--r--tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp7
3 files changed, 38 insertions, 31 deletions
diff --git a/src/activeqt/container/qaxscript.cpp b/src/activeqt/container/qaxscript.cpp
index ee697ba..a25c1f2 100644
--- a/src/activeqt/container/qaxscript.cpp
+++ b/src/activeqt/container/qaxscript.cpp
@@ -1112,17 +1112,8 @@ QVariant QAxScriptManager::call(const QString &function, const QVariant &var1,
const QVariant &var7,
const QVariant &var8)
{
- QAxScript *s = script(function);
- if (!s) {
-#ifdef QT_CHECK_STATE
- qWarning("QAxScriptManager::call: No script provides function %s, or this function\n"
- "\tis provided through an engine that does not support introspection",
- qPrintable(function));
-#endif
- return QVariant();
- }
-
- return s->call(function, var1, var2, var3, var4, var5, var6, var7, var8);
+ QList<QVariant> list{var1, var2, var3, var4, var5, var6, var7, var8};
+ return call(function, list);
}
/*!
@@ -1134,7 +1125,8 @@ QVariant QAxScriptManager::call(const QString &function, const QVariant &var1,
*/
QVariant QAxScriptManager::call(const QString &function, QList<QVariant> &arguments)
{
- QAxScript *s = script(function);
+ QString signature = function;
+ QAxScript *s = scriptForFunction(signature);
if (!s) {
#ifdef QT_CHECK_STATE
qWarning("QAxScriptManager::call: No script provides function %s, or this function\n"
@@ -1145,7 +1137,7 @@ QVariant QAxScriptManager::call(const QString &function, QList<QVariant> &argume
}
QVariantList args(arguments);
- return s->call(function, args);
+ return s->call(signature, args);
}
/*!
@@ -1215,30 +1207,40 @@ QString QAxScriptManager::scriptFileFilter()
*/
/*!
- \fn QAxScript *QAxScriptManager::scriptForFunction(const QString &function) const
+ \fn QAxScript *QAxScriptManager::scriptForFunction(QString &function) const
\internal
Returns a pointer to the first QAxScript that knows
- about \a function, or 0 if this function is unknown.
+ about \a function, or nullptr if this function is unknown. \a function
+ is changed to the callable signature.
*/
-QAxScript *QAxScriptManager::scriptForFunction(const QString &function) const
+QAxScript *QAxScriptManager::scriptForFunction(QString &function) const
{
- // check full prototypes if included
- if (function.contains(QLatin1Char('('))) {
- for (auto it = d->scriptDict.cbegin(), end = d->scriptDict.cend(); it != end; ++it) {
- if (it.value()->functions(QAxScript::FunctionSignatures).contains(function))
- return it.value();
+ const auto startPrototype = function.indexOf(u'(');
+
+ for (const auto &script : d->scriptDict) {
+ const QMetaObject *mo = script->scriptEngine()->metaObject();
+ for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod slot(mo->method(i));
+ if (slot.methodType() != QMetaMethod::Slot || slot.access() != QMetaMethod::Public)
+ continue;
+ const QString slotname = QString::fromLatin1(slot.methodSignature());
+ if (slotname.contains(u'_'))
+ continue;
+
+ // finding script for prototype
+ if (startPrototype != -1) {
+ if (slotname == function)
+ return script;
+ } else if (slotname.length() > function.length()
+ && slotname.at(function.length()) == u'('
+ && slotname.startsWith(function)) {
+ function = slotname;
+ return script;
+ }
}
}
- QString funcName = function;
- funcName.truncate(funcName.indexOf(QLatin1Char('(')));
- // second try, checking only names, not prototypes
- for (auto it = d->scriptDict.cbegin(), end = d->scriptDict.cend(); it != end; ++it) {
- if (it.value()->functions(QAxScript::FunctionNames).contains(funcName))
- return it.value();
- }
-
return nullptr;
}
diff --git a/src/activeqt/container/qaxscript.h b/src/activeqt/container/qaxscript.h
index 6aad2f8..e35f2dd 100644
--- a/src/activeqt/container/qaxscript.h
+++ b/src/activeqt/container/qaxscript.h
@@ -150,7 +150,7 @@ private:
QAxScriptManagerPrivate *d;
void updateScript(QAxScript*);
- QAxScript *scriptForFunction(const QString &function) const;
+ QAxScript *scriptForFunction(QString &function) const;
};
diff --git a/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp b/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp
index 7d9a36e..5c92bdf 100644
--- a/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp
+++ b/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp
@@ -172,9 +172,14 @@ void tst_QAxScriptManager::call()
QVERIFY(axScript->scriptEngine()->hasIntrospection());
}
+ // QAxScriptManager::call finds the script based on function name...
+ for (const auto &function : std::as_const(functions)) {
+ QVariant result = scriptManager.call(function);
+ QCOMPARE(result.metaType(), QMetaType::fromType<QString>());
+ }
+ // ...or fully qualified function signature
for (const auto &function : std::as_const(signatures)) {
QVariant result = scriptManager.call(function);
- QEXPECT_FAIL("", "QAxScriptManager::call is broken", Continue);
QCOMPARE(result.metaType(), QMetaType::fromType<QString>());
}
}