diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2021-07-13 16:05:27 +0200 |
---|---|---|
committer | Andrei Golubev <andrei.golubev@qt.io> | 2021-07-19 15:48:54 +0200 |
commit | ebae5e826785304ae2b90207da3a304149792afc (patch) | |
tree | 085daa8cd7785801d381049e854a846f117ea3d0 | |
parent | b17df800dee7347e8e74089137a86dd83e6dbecc (diff) |
Make tst_qmlcompiler_manual into a QML module
Turns out not to be as easy as it might seem:
* C++ classes with QML_ELEMENT entries had to move to a separate header
* qt_add_qml_module uses URI as part of the resource path, so
"qrc:/myFile.qml" becomes "qrc:/URI/myFile.qml"
(important for the signalHandlers_qmlcachegen test)
Change-Id: I084541575c11003b07f2ef63809eeab439f2151f
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit e4eabbbb10d446ba44413f6db9abeb8115bc515f)
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | tests/auto/qml/qmlcompiler_manual/CMakeLists.txt | 16 | ||||
-rw-r--r-- | tests/auto/qml/qmlcompiler_manual/testclasses.h | 318 | ||||
-rw-r--r-- | tests/auto/qml/qmlcompiler_manual/tst_qmlcompiler_manual.cpp | 810 |
3 files changed, 620 insertions, 524 deletions
diff --git a/tests/auto/qml/qmlcompiler_manual/CMakeLists.txt b/tests/auto/qml/qmlcompiler_manual/CMakeLists.txt index 0afe49e760..ebd207e94b 100644 --- a/tests/auto/qml/qmlcompiler_manual/CMakeLists.txt +++ b/tests/auto/qml/qmlcompiler_manual/CMakeLists.txt @@ -7,23 +7,21 @@ list(APPEND test_data ${test_data_glob}) qt_internal_add_test(tst_qmlcompiler_manual SOURCES ../../shared/util.cpp ../../shared/util.h + testclasses.h tst_qmlcompiler_manual.cpp INCLUDE_DIRECTORIES ../../shared LIBRARIES Qt::CorePrivate Qt::QmlPrivate - TESTDATA ${test_data} ) -## Scopes: -##################################################################### - -qt_add_resources(tst_qmlcompiler_manual "qmlcompiler" - PREFIX - "/" - FILES - "data/signalHandlers.qml" +qt6_add_qml_module(tst_qmlcompiler_manual + VERSION 1.0 + URI "QmltcManualTests" + NO_CREATE_PLUGIN_TARGET + QML_FILES + ${test_data} ) qt_internal_extend_target(tst_qmlcompiler_manual CONDITION ANDROID OR IOS diff --git a/tests/auto/qml/qmlcompiler_manual/testclasses.h b/tests/auto/qml/qmlcompiler_manual/testclasses.h new file mode 100644 index 0000000000..a56f85460d --- /dev/null +++ b/tests/auto/qml/qmlcompiler_manual/testclasses.h @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTCLASSES_H +#define TESTCLASSES_H + +#include <QtCore/qobject.h> +#include <QtCore/qproperty.h> +#include <QtQml/qqmlregistration.h> +#include <QtQml/qqml.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQuick/qquickitem.h> + +#include <private/qqmlrefcount_p.h> +#include <private/qqmlcontextdata_p.h> + +// utility class that sets up QQmlContext for passed QObject. can be used as a +// base class to ensure that qmlEngine(object) is valid during initializer list +// evaluation +struct ContextRegistrator +{ + ContextRegistrator(QQmlEngine *engine, QObject *This); +}; + +class HelloWorld : public QObject, public ContextRegistrator +{ + Q_OBJECT + QML_NAMED_ELEMENT(HelloWorld); + Q_PROPERTY(QString hello READ getHello WRITE setHello BINDABLE bindableHello) + Q_PROPERTY(QString greeting READ getGreeting WRITE setGreeting BINDABLE bindableGreeting) + +public: + // test workaround: the url is resolved by the test base class, so use + // member variable to store the resolved url used as argument in engine + // evaluation of runtime functions + static QUrl url; + + HelloWorld(QQmlEngine *e, QObject *parent = nullptr); + virtual ~HelloWorld() { } + + QString getHello() { return hello.value(); } + QString getGreeting() { return greeting.value(); } + + void setHello(const QString &hello_) { hello.setValue(hello_); } + void setGreeting(const QString &greeting_) { greeting.setValue(greeting_); } + + QBindable<QString> bindableHello() { return QBindable<QString>(&hello); } + QBindable<QString> bindableGreeting() { return QBindable<QString>(&greeting); } + + Q_OBJECT_BINDABLE_PROPERTY(HelloWorld, QString, hello); + Q_OBJECT_BINDABLE_PROPERTY(HelloWorld, QString, greeting); +}; + +class ANON_signalHandlers : public QObject, public ContextRegistrator +{ + Q_OBJECT + QML_ANONYMOUS + Q_PROPERTY(int signal1P READ getSignal1P WRITE setSignal1P BINDABLE bindableSignal1P) + Q_PROPERTY(QString signal2P1 READ getSignal2P1 WRITE setSignal2P1 BINDABLE bindableSignal2P1) + Q_PROPERTY(int signal2P2 READ getSignal2P2 WRITE setSignal2P2 BINDABLE bindableSignal2P2) + Q_PROPERTY(QString signal2P3 READ getSignal2P3 WRITE setSignal2P3 BINDABLE bindableSignal2P3) + +public: + // test workaround: the url is resolved by the test base class, so use + // member variable to store the resolved url used as argument in engine + // evaluation of runtime functions + static QUrl url; + + ANON_signalHandlers(QQmlEngine *e, QObject *parent = nullptr); + + int getSignal1P() { return signal1P.value(); } + QString getSignal2P1() { return signal2P1.value(); } + int getSignal2P2() { return signal2P2.value(); } + QString getSignal2P3() { return signal2P3.value(); } + + void setSignal1P(const int &signal1P_) { signal1P.setValue(signal1P_); } + void setSignal2P1(const QString &signal2P1_) { signal2P1.setValue(signal2P1_); } + void setSignal2P2(const int &signal2P2_) { signal2P2.setValue(signal2P2_); } + void setSignal2P3(const QString &signal2P3_) { signal2P3.setValue(signal2P3_); } + + QBindable<int> bindableSignal1P() { return QBindable<int>(&signal1P); } + QBindable<QString> bindableSignal2P1() { return QBindable<QString>(&signal2P1); } + QBindable<int> bindableSignal2P2() { return QBindable<int>(&signal2P2); } + QBindable<QString> bindableSignal2P3() { return QBindable<QString>(&signal2P3); } + + Q_OBJECT_BINDABLE_PROPERTY(ANON_signalHandlers, int, signal1P); + Q_OBJECT_BINDABLE_PROPERTY(ANON_signalHandlers, QString, signal2P1); + Q_OBJECT_BINDABLE_PROPERTY(ANON_signalHandlers, int, signal2P2); + Q_OBJECT_BINDABLE_PROPERTY(ANON_signalHandlers, QString, signal2P3); + +Q_SIGNALS: + void signal1(); + void signal2(QString x, int y); + +public slots: + void onSignal1(); + void onSignal2(QString x, int y); + +public: + void qmlEmitSignal1(); + void qmlEmitSignal2(); + void qmlEmitSignal2WithArgs(QString x, int y); +}; + +class ANON_javaScriptFunctions : public QObject, public ContextRegistrator +{ + Q_OBJECT + QML_ANONYMOUS + Q_PROPERTY(int func1P READ getFunc1P WRITE setFunc1P) + Q_PROPERTY(QString func2P READ getFunc2P WRITE setFunc2P) + Q_PROPERTY(bool func3P READ getFunc3P WRITE setFunc3P) + +public: + // test workaround: the url is resolved by the test base class, so use + // member variable to store the resolved url used as argument in engine + // evaluation of runtime functions + static QUrl url; + + ANON_javaScriptFunctions(QQmlEngine *e, QObject *parent = nullptr); + + int getFunc1P() { return func1P.value(); } + QString getFunc2P() { return func2P.value(); } + bool getFunc3P() { return func3P.value(); } + + void setFunc1P(const int &func1P_) { func1P.setValue(func1P_); } + void setFunc2P(const QString &func2P_) { func2P.setValue(func2P_); } + void setFunc3P(const bool &func3P_) { func3P.setValue(func3P_); } + + // try if just QProperty works + QProperty<int> func1P; + QProperty<QString> func2P; + QProperty<bool> func3P; + + void func1(); + void func2(QString x); + bool func3(); +}; + +class ANON_changingBindings : public QObject, public ContextRegistrator +{ + Q_OBJECT + QML_ANONYMOUS + Q_PROPERTY(int p1 READ getP1 WRITE setP1 BINDABLE bindableP1) + Q_PROPERTY(int p2 READ getP2 WRITE setP2 BINDABLE bindableP2) + +public: + // test workaround: the url is resolved by the test base class, so use + // member variable to store the resolved url used as argument in engine + // evaluation of runtime functions + static QUrl url; + // test util to monitor binding execution + int initialBindingCallCount = 0; + // test util: allows to set C++ binding multiple times + void resetToInitialBinding(); + + ANON_changingBindings(QQmlEngine *e, QObject *parent = nullptr); + + int getP1() { return p1.value(); } + int getP2() { return p2.value(); } + + void setP1(int p1_) { p1.setValue(p1_); } + void setP2(int p2_) { p2.setValue(p2_); } + + QBindable<int> bindableP1() { return QBindable<int>(&p1); } + QBindable<int> bindableP2() { return QBindable<int>(&p2); } + + Q_OBJECT_BINDABLE_PROPERTY(ANON_changingBindings, int, p1); + Q_OBJECT_BINDABLE_PROPERTY(ANON_changingBindings, int, p2); + + void resetToConstant(); + void resetToNewBinding(); +}; + +class ANON_propertyAlias : public QObject, public ContextRegistrator +{ + Q_OBJECT + QML_ANONYMOUS + Q_PROPERTY(int dummy READ getDummy WRITE setDummy NOTIFY dummyChanged) + Q_PROPERTY(int origin READ getOrigin WRITE setOrigin BINDABLE bindableOrigin) + Q_PROPERTY(int aliasToOrigin READ getAliasToOrigin WRITE setAliasToOrigin BINDABLE + bindableAliasToOrigin) + +public: + // test workaround: the url is resolved by the test base class, so use + // member variable to store the resolved url used as argument in engine + // evaluation of runtime functions + static QUrl url; + // test util: allows to set C++ binding multiple times + void resetToInitialBinding(); + + ANON_propertyAlias(QQmlEngine *e, QObject *parent = nullptr); + + int getDummy() { return dummy.value(); } + int getOrigin() { return origin.value(); } + int getAliasToOrigin() { return getOrigin(); } + + void setDummy(int dummy_) + { + dummy.setValue(dummy_); + // emit is essential for Qt.binding() to work correctly + emit dummyChanged(); + } + void setOrigin(int origin_) { origin.setValue(origin_); } + void setAliasToOrigin(int aliasToOrigin_) { setOrigin(aliasToOrigin_); } + + QBindable<int> bindableOrigin() { return QBindable<int>(&origin); } + QBindable<int> bindableAliasToOrigin() { return bindableOrigin(); } + + QProperty<int> dummy; + QProperty<int> origin; + + void resetAliasToConstant(); + void resetOriginToConstant(); + void resetAliasToNewBinding(); + void resetOriginToNewBinding(); + int getAliasValue(); + +Q_SIGNALS: + void dummyChanged(); +}; + +class ANON_propertyChangeHandler : public QObject, public ContextRegistrator +{ + Q_OBJECT + QML_ANONYMOUS + Q_PROPERTY(int dummy READ getDummy WRITE setDummy) + Q_PROPERTY(int p READ getP WRITE setP BINDABLE bindableP) + Q_PROPERTY(int watcher READ getWatcher WRITE setWatcher) + +public: + // test workaround: the url is resolved by the test base class, so use + // member variable to store the resolved url used as argument in engine + // evaluation of runtime functions + static QUrl url; + + ANON_propertyChangeHandler(QQmlEngine *e, QObject *parent = nullptr); + + int getDummy() { return dummy.value(); } + int getP() { return p.value(); } + int getWatcher() { return watcher.value(); } + + void setDummy(int dummy_) { dummy.setValue(dummy_); } + void setP(int p_) { p.setValue(p_); } + void setWatcher(int watcher_) { watcher.setValue(watcher_); } + + QBindable<int> bindableP() { return QBindable<int>(&p); } + + QProperty<int> dummy; + QProperty<int> p; + QProperty<int> watcher; + + // property change handler: + struct ANON_propertyChangeHandler_p_changeHandler + { + ANON_propertyChangeHandler *This = nullptr; + ANON_propertyChangeHandler_p_changeHandler(ANON_propertyChangeHandler *obj); + + void operator()(); + }; + // the handler object has to be alive as long as the object + std::unique_ptr<QPropertyChangeHandler<ANON_propertyChangeHandler_p_changeHandler>> + pChangeHandler; +}; + +class ANON_propertyReturningFunction : public QObject, public ContextRegistrator +{ + Q_OBJECT + QML_ANONYMOUS + Q_PROPERTY(int counter READ getCounter WRITE setCounter) + Q_PROPERTY(QVariant f READ getF WRITE setF BINDABLE bindableF) + +public: + // test workaround: the url is resolved by the test base class, so use + // member variable to store the resolved url used as argument in engine + // evaluation of runtime functions + static QUrl url; + + ANON_propertyReturningFunction(QQmlEngine *e, QObject *parent = nullptr); + + int getCounter() { return counter.value(); } + QVariant getF() { return f.value(); } + + void setCounter(int counter_) { counter.setValue(counter_); } + void setF(QVariant f_) { f.setValue(f_); } + + QBindable<QVariant> bindableF() { return QBindable<QVariant>(&f); } + + QProperty<int> counter; + QProperty<QVariant> f; +}; + +#endif // TESTCLASSES_H diff --git a/tests/auto/qml/qmlcompiler_manual/tst_qmlcompiler_manual.cpp b/tests/auto/qml/qmlcompiler_manual/tst_qmlcompiler_manual.cpp index db1cd7132c..ae90aaa34d 100644 --- a/tests/auto/qml/qmlcompiler_manual/tst_qmlcompiler_manual.cpp +++ b/tests/auto/qml/qmlcompiler_manual/tst_qmlcompiler_manual.cpp @@ -29,6 +29,8 @@ #include <qtest.h> #include <QDebug> +#include "testclasses.h" + #include <QtCore/qscopedpointer.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> @@ -119,78 +121,46 @@ static void typeEraseArguments(std::array<void *, Size> &a, std::array<QMetaType t = { /* types */ QMetaType::fromType<std::decay_t<IOArgs>>()... }; } -// utility class that sets up QQmlContext for passed QObject. can be used as a -// base class to ensure that qmlEngine(object) is valid during initializer list -// evaluation -struct ContextRegistrator -{ - ContextRegistrator(QQmlEngine *engine, QObject *This) - { - Q_ASSERT(engine && This); - // if This object has a parent, it's not considered to be a root object, - // so it must instead have a dedicated context, but what to do when we - // reparent the root item to e.g. QQuickWindow::contentItem()? - Q_ASSERT(!This->parent() || engine->contextForObject(This->parent()) - || engine->rootContext()); - QQmlContext *context = engine->rootContext(); - if (This->parent()) { - QQmlContext *parentContext = engine->contextForObject(This->parent()); - if (parentContext) - context = new QQmlContext(parentContext, This); - } - Q_ASSERT(context); - // NB: not only sets the context, but also seeds engine into This, so - // that qmlEngine(This) works - engine->setContextForObject(This, context); - Q_ASSERT(qmlEngine(This)); - } -}; +ContextRegistrator::ContextRegistrator(QQmlEngine *engine, QObject *This) +{ + Q_ASSERT(engine && This); + if (engine->contextForObject(This)) // already set + return; + + // use simple form of the logic done in create() and set(). this code + // shouldn't actually be used in real generated classes. it just exists + // here for convenience + Q_ASSERT(!This->parent() || engine->contextForObject(This->parent()) || engine->rootContext()); + QQmlContext *parentContext = engine->contextForObject(This->parent()); + QQmlContext *context = + parentContext ? parentContext : new QQmlContext(engine->rootContext(), This); + Q_ASSERT(context); + // NB: not only sets the context, but also seeds engine into This, so + // that qmlEngine(This) works + engine->setContextForObject(This, context); + Q_ASSERT(qmlEngine(This)); +} -class HelloWorld : public QObject, public ContextRegistrator +HelloWorld::HelloWorld(QQmlEngine *e, QObject *parent) + : QObject(parent), ContextRegistrator(e, this) { - Q_OBJECT - QML_NAMED_ELEMENT(HelloWorld); - Q_PROPERTY(QString hello READ getHello WRITE setHello BINDABLE bindableHello) - Q_PROPERTY(QString greeting READ getGreeting WRITE setGreeting BINDABLE bindableGreeting) - -public: - // test workaround: the url is resolved by the test base class, so use - // member variable to store the resolved url used as argument in engine - // evaluation of runtime functions - static QUrl url; - - HelloWorld(QQmlEngine *e, QObject *parent = nullptr) - : QObject(parent), ContextRegistrator(e, this) - { - hello = QStringLiteral("Hello, World"); - QPropertyBinding<QString> HelloWorldCpp_greeting_binding( - [&]() { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::HELLO_WORLD_GREETING_BINDING; - constexpr int argc = 0; - QString ret {}; - std::array<void *, argc + 1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, ret); - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - return ret; - }, - QT_PROPERTY_DEFAULT_BINDING_LOCATION); - bindableGreeting().setBinding(HelloWorldCpp_greeting_binding); - } - - QString getHello() { return hello.value(); } - QString getGreeting() { return greeting.value(); } - - void setHello(const QString &hello_) { hello.setValue(hello_); } - void setGreeting(const QString &greeting_) { greeting.setValue(greeting_); } - - QBindable<QString> bindableHello() { return QBindable<QString>(&hello); } - QBindable<QString> bindableGreeting() { return QBindable<QString>(&greeting); } - - Q_OBJECT_BINDABLE_PROPERTY(HelloWorld, QString, hello); - Q_OBJECT_BINDABLE_PROPERTY(HelloWorld, QString, greeting); -}; + hello = QStringLiteral("Hello, World"); + QPropertyBinding<QString> HelloWorldCpp_greeting_binding( + [&]() { + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::HELLO_WORLD_GREETING_BINDING; + constexpr int argc = 0; + QString ret {}; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, ret); + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); + return ret; + }, + QT_PROPERTY_DEFAULT_BINDING_LOCATION); + bindableGreeting().setBinding(HelloWorldCpp_greeting_binding); +} + QUrl HelloWorld::url = QUrl(); // workaround void tst_qmlcompiler_manual::cppBinding() @@ -210,106 +180,63 @@ void tst_qmlcompiler_manual::cppBinding() QCOMPARE(created.getGreeting(), QStringLiteral("Hello, Qml!")); } -class ANON_signalHandlers : public QObject, public ContextRegistrator +ANON_signalHandlers::ANON_signalHandlers(QQmlEngine *e, QObject *parent) + : QObject(parent), ContextRegistrator(e, this) { - Q_OBJECT - QML_ANONYMOUS - Q_PROPERTY(int signal1P READ getSignal1P WRITE setSignal1P BINDABLE bindableSignal1P) - Q_PROPERTY(QString signal2P1 READ getSignal2P1 WRITE setSignal2P1 BINDABLE bindableSignal2P1) - Q_PROPERTY(int signal2P2 READ getSignal2P2 WRITE setSignal2P2 BINDABLE bindableSignal2P2) - Q_PROPERTY(QString signal2P3 READ getSignal2P3 WRITE setSignal2P3 BINDABLE bindableSignal2P3) - -public: - // test workaround: the url is resolved by the test base class, so use - // member variable to store the resolved url used as argument in engine - // evaluation of runtime functions - static QUrl url; - - ANON_signalHandlers(QQmlEngine *e, QObject *parent = nullptr) - : QObject(parent), ContextRegistrator(e, this) - { - signal1P = 0; - signal2P1 = QStringLiteral(""); - signal2P2 = 0; - signal2P3 = QStringLiteral(""); - - QObject::connect(this, &ANON_signalHandlers::signal1, this, - &ANON_signalHandlers::onSignal1); - QObject::connect(this, &ANON_signalHandlers::signal2, this, - &ANON_signalHandlers::onSignal2); - } - - int getSignal1P() { return signal1P.value(); } - QString getSignal2P1() { return signal2P1.value(); } - int getSignal2P2() { return signal2P2.value(); } - QString getSignal2P3() { return signal2P3.value(); } - - void setSignal1P(const int &signal1P_) { signal1P.setValue(signal1P_); } - void setSignal2P1(const QString &signal2P1_) { signal2P1.setValue(signal2P1_); } - void setSignal2P2(const int &signal2P2_) { signal2P2.setValue(signal2P2_); } - void setSignal2P3(const QString &signal2P3_) { signal2P3.setValue(signal2P3_); } - - QBindable<int> bindableSignal1P() { return QBindable<int>(&signal1P); } - QBindable<QString> bindableSignal2P1() { return QBindable<QString>(&signal2P1); } - QBindable<int> bindableSignal2P2() { return QBindable<int>(&signal2P2); } - QBindable<QString> bindableSignal2P3() { return QBindable<QString>(&signal2P3); } - - Q_OBJECT_BINDABLE_PROPERTY(ANON_signalHandlers, int, signal1P); - Q_OBJECT_BINDABLE_PROPERTY(ANON_signalHandlers, QString, signal2P1); - Q_OBJECT_BINDABLE_PROPERTY(ANON_signalHandlers, int, signal2P2); - Q_OBJECT_BINDABLE_PROPERTY(ANON_signalHandlers, QString, signal2P3); - -signals: - void signal1(); - void signal2(QString x, int y); - -public slots: - void onSignal1() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::SIGNAL_HANDLERS_ON_SIGNAL1; - e->executeRuntimeFunction(url, index, this); - } - - void onSignal2(QString x, int y) - { - constexpr int argc = 2; - std::array<void *, argc+1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, nullptr, x, y); - - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const qsizetype index = FunctionIndices::SIGNAL_HANDLERS_ON_SIGNAL2; - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - } - -public: - void qmlEmitSignal1() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::SIGNAL_HANDLERS_QML_EMIT_SIGNAL1; - e->executeRuntimeFunction(url, index, this); - } - - void qmlEmitSignal2() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::SIGNAL_HANDLERS_QML_EMIT_SIGNAL2; - e->executeRuntimeFunction(url, index, this); - } - - void qmlEmitSignal2WithArgs(QString x, int y) - { - constexpr int argc = 2; - std::array<void *, argc+1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, nullptr, x, y); - - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::SIGNAL_HANDLERS_QML_EMIT_SIGNAL2_WITH_ARGS; - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - } -}; + signal1P = 0; + signal2P1 = QStringLiteral(""); + signal2P2 = 0; + signal2P3 = QStringLiteral(""); + + QObject::connect(this, &ANON_signalHandlers::signal1, this, &ANON_signalHandlers::onSignal1); + QObject::connect(this, &ANON_signalHandlers::signal2, this, &ANON_signalHandlers::onSignal2); +} + +void ANON_signalHandlers::onSignal1() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::SIGNAL_HANDLERS_ON_SIGNAL1; + e->executeRuntimeFunction(url, index, this); +} + +void ANON_signalHandlers::onSignal2(QString x, int y) +{ + constexpr int argc = 2; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, nullptr, x, y); + + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const qsizetype index = FunctionIndices::SIGNAL_HANDLERS_ON_SIGNAL2; + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); +} + +void ANON_signalHandlers::qmlEmitSignal1() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::SIGNAL_HANDLERS_QML_EMIT_SIGNAL1; + e->executeRuntimeFunction(url, index, this); +} + +void ANON_signalHandlers::qmlEmitSignal2() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::SIGNAL_HANDLERS_QML_EMIT_SIGNAL2; + e->executeRuntimeFunction(url, index, this); +} + +void ANON_signalHandlers::qmlEmitSignal2WithArgs(QString x, int y) +{ + constexpr int argc = 2; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, nullptr, x, y); + + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::SIGNAL_HANDLERS_QML_EMIT_SIGNAL2_WITH_ARGS; + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); +} + QUrl ANON_signalHandlers::url = QUrl(); // workaround void tst_qmlcompiler_manual::signalHandlers_impl(const QUrl &url) @@ -361,76 +288,49 @@ void tst_qmlcompiler_manual::signalHandlers() void tst_qmlcompiler_manual::signalHandlers_qmlcachegen() { // use qmlcachegen's compilation unit - signalHandlers_impl(QUrl("qrc:/data/signalHandlers.qml")); + signalHandlers_impl(QUrl("qrc:/QmltcManualTests/data/signalHandlers.qml")); } -class ANON_javaScriptFunctions : public QObject, public ContextRegistrator +ANON_javaScriptFunctions::ANON_javaScriptFunctions(QQmlEngine *e, QObject *parent) + : QObject(parent), ContextRegistrator(e, this) { - Q_OBJECT - QML_ANONYMOUS - Q_PROPERTY(int func1P READ getFunc1P WRITE setFunc1P) - Q_PROPERTY(QString func2P READ getFunc2P WRITE setFunc2P) - Q_PROPERTY(bool func3P READ getFunc3P WRITE setFunc3P) - -public: - // test workaround: the url is resolved by the test base class, so use - // member variable to store the resolved url used as argument in engine - // evaluation of runtime functions - static QUrl url; - - ANON_javaScriptFunctions(QQmlEngine *e, QObject *parent = nullptr) - : QObject(parent), ContextRegistrator(e, this) - { - func1P = 0; - func2P = QStringLiteral(""); - func3P = false; - } - - int getFunc1P() { return func1P.value(); } - QString getFunc2P() { return func2P.value(); } - bool getFunc3P() { return func3P.value(); } - - void setFunc1P(const int &func1P_) { func1P.setValue(func1P_); } - void setFunc2P(const QString &func2P_) { func2P.setValue(func2P_); } - void setFunc3P(const bool &func3P_) { func3P.setValue(func3P_); } - - // try if just QProperty works - QProperty<int> func1P; - QProperty<QString> func2P; - QProperty<bool> func3P; - - void func1() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::JS_FUNCTIONS_FUNC1; - e->executeRuntimeFunction(url, index, this); - } - - void func2(QString x) - { - constexpr int argc = 1; - std::array<void *, argc+1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, nullptr, x); - - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::JS_FUNCTIONS_FUNC2; - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - } - - bool func3() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::JS_FUNCTIONS_FUNC3; - constexpr int argc = 0; - bool ret {}; - std::array<void *, argc + 1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, ret); - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - return ret; - } -}; + func1P = 0; + func2P = QStringLiteral(""); + func3P = false; +} + +void ANON_javaScriptFunctions::func1() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::JS_FUNCTIONS_FUNC1; + e->executeRuntimeFunction(url, index, this); +} + +void ANON_javaScriptFunctions::func2(QString x) +{ + constexpr int argc = 1; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, nullptr, x); + + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::JS_FUNCTIONS_FUNC2; + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); +} + +bool ANON_javaScriptFunctions::func3() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::JS_FUNCTIONS_FUNC3; + constexpr int argc = 0; + bool ret {}; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, ret); + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); + return ret; +} + QUrl ANON_javaScriptFunctions::url = QUrl(); // workaround void tst_qmlcompiler_manual::jsFunctions() @@ -450,74 +350,47 @@ void tst_qmlcompiler_manual::jsFunctions() QCOMPARE(created.func3(), true); } -class ANON_changingBindings : public QObject, public ContextRegistrator +void ANON_changingBindings::resetToInitialBinding() { - Q_OBJECT - QML_ANONYMOUS - Q_PROPERTY(int p1 READ getP1 WRITE setP1 BINDABLE bindableP1) - Q_PROPERTY(int p2 READ getP2 WRITE setP2 BINDABLE bindableP2) - -public: - // test workaround: the url is resolved by the test base class, so use - // member variable to store the resolved url used as argument in engine - // evaluation of runtime functions - static QUrl url; - // test util to monitor binding execution - int initialBindingCallCount = 0; - // test util: allows to set C++ binding multiple times - void resetToInitialBinding() - { - QPropertyBinding<int> ANON_changingBindings_p2_binding( - [&]() { - initialBindingCallCount++; - - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::CHANGING_BINDINGS_P2_BINDING; - constexpr int argc = 0; - int ret {}; - std::array<void *, argc + 1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, ret); - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - return ret; - }, - QT_PROPERTY_DEFAULT_BINDING_LOCATION); - bindableP2().setBinding(ANON_changingBindings_p2_binding); - } - - ANON_changingBindings(QQmlEngine *e, QObject *parent = nullptr) - : QObject(parent), ContextRegistrator(e, this) - { - p1 = 1; - resetToInitialBinding(); - } - - int getP1() { return p1.value(); } - int getP2() { return p2.value(); } - - void setP1(int p1_) { p1.setValue(p1_); } - void setP2(int p2_) { p2.setValue(p2_); } - - QBindable<int> bindableP1() { return QBindable<int>(&p1); } - QBindable<int> bindableP2() { return QBindable<int>(&p2); } - - Q_OBJECT_BINDABLE_PROPERTY(ANON_changingBindings, int, p1); - Q_OBJECT_BINDABLE_PROPERTY(ANON_changingBindings, int, p2); - - void resetToConstant() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::CHANGING_BINDINGS_RESET_TO_CONSTANT; - e->executeRuntimeFunction(url, index, this); - } - - void resetToNewBinding() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::CHANGING_BINDINGS_RESET_TO_NEW_BINDING; - e->executeRuntimeFunction(url, index, this); - } -}; + QPropertyBinding<int> ANON_changingBindings_p2_binding( + [&]() { + initialBindingCallCount++; + + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::CHANGING_BINDINGS_P2_BINDING; + constexpr int argc = 0; + int ret {}; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, ret); + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); + return ret; + }, + QT_PROPERTY_DEFAULT_BINDING_LOCATION); + bindableP2().setBinding(ANON_changingBindings_p2_binding); +} + +ANON_changingBindings::ANON_changingBindings(QQmlEngine *e, QObject *parent) + : QObject(parent), ContextRegistrator(e, this) +{ + p1 = 1; + resetToInitialBinding(); +} + +void ANON_changingBindings::resetToConstant() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::CHANGING_BINDINGS_RESET_TO_CONSTANT; + e->executeRuntimeFunction(url, index, this); +} + +void ANON_changingBindings::resetToNewBinding() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::CHANGING_BINDINGS_RESET_TO_NEW_BINDING; + e->executeRuntimeFunction(url, index, this); +} + QUrl ANON_changingBindings::url = QUrl(); // workaround void tst_qmlcompiler_manual::changingBindings() @@ -566,106 +439,69 @@ void tst_qmlcompiler_manual::changingBindings() QCOMPARE(created.initialBindingCallCount, 2); } -class ANON_propertyAlias : public QObject, public ContextRegistrator +void ANON_propertyAlias::resetToInitialBinding() { - Q_OBJECT - QML_ANONYMOUS - Q_PROPERTY(int dummy READ getDummy WRITE setDummy NOTIFY dummyChanged) - Q_PROPERTY(int origin READ getOrigin WRITE setOrigin BINDABLE bindableOrigin) - Q_PROPERTY(int aliasToOrigin READ getAliasToOrigin WRITE setAliasToOrigin BINDABLE - bindableAliasToOrigin) - -public: - // test workaround: the url is resolved by the test base class, so use - // member variable to store the resolved url used as argument in engine - // evaluation of runtime functions - static QUrl url; - // test util: allows to set C++ binding multiple times - void resetToInitialBinding() - { - QPropertyBinding<int> ANON_propertyAlias_origin_binding( - [&]() { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::PROPERTY_ALIAS_ORIGIN_BINDING; - constexpr int argc = 0; - int ret {}; - std::array<void *, argc + 1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, ret); - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - return ret; - }, - QT_PROPERTY_DEFAULT_BINDING_LOCATION); - bindableOrigin().setBinding(ANON_propertyAlias_origin_binding); - } - - ANON_propertyAlias(QQmlEngine *e, QObject *parent = nullptr) - : QObject(parent), ContextRegistrator(e, this) - { - dummy = 12; - resetToInitialBinding(); - } - - int getDummy() { return dummy.value(); } - int getOrigin() { return origin.value(); } - int getAliasToOrigin() { return getOrigin(); } - - void setDummy(int dummy_) - { - dummy.setValue(dummy_); - // emit is essential for Qt.binding() to work correctly - emit dummyChanged(); - } - void setOrigin(int origin_) { origin.setValue(origin_); } - void setAliasToOrigin(int aliasToOrigin_) { setOrigin(aliasToOrigin_); } - - QBindable<int> bindableOrigin() { return QBindable<int>(&origin); } - QBindable<int> bindableAliasToOrigin() { return bindableOrigin(); } - - QProperty<int> dummy; - QProperty<int> origin; - - void resetAliasToConstant() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::PROPERTY_ALIAS_RESET_ALIAS_TO_CONSTANT; - e->executeRuntimeFunction(url, index, this); - } - void resetOriginToConstant() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::PROPERTY_ALIAS_RESET_ORIGIN_TO_CONSTANT; - e->executeRuntimeFunction(url, index, this); - } - void resetAliasToNewBinding() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::PROPERTY_ALIAS_RESET_ALIAS_TO_NEW_BINDING; - e->executeRuntimeFunction(url, index, this); - } - void resetOriginToNewBinding() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::PROPERTY_ALIAS_RESET_ORIGIN_TO_NEW_BINDING; - e->executeRuntimeFunction(url, index, this); - } - - int getAliasValue() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::PROPERTY_ALIAS_GET_ALIAS_VALUE; - constexpr int argc = 0; - int ret {}; - std::array<void *, argc + 1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, ret); - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - return ret; - } - -signals: - void dummyChanged(); -}; + QPropertyBinding<int> ANON_propertyAlias_origin_binding( + [&]() { + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::PROPERTY_ALIAS_ORIGIN_BINDING; + constexpr int argc = 0; + int ret {}; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, ret); + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); + return ret; + }, + QT_PROPERTY_DEFAULT_BINDING_LOCATION); + bindableOrigin().setBinding(ANON_propertyAlias_origin_binding); +} + +ANON_propertyAlias::ANON_propertyAlias(QQmlEngine *e, QObject *parent) + : QObject(parent), ContextRegistrator(e, this) +{ + dummy = 12; + resetToInitialBinding(); +} + +void ANON_propertyAlias::resetAliasToConstant() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::PROPERTY_ALIAS_RESET_ALIAS_TO_CONSTANT; + e->executeRuntimeFunction(url, index, this); +} +void ANON_propertyAlias::resetOriginToConstant() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::PROPERTY_ALIAS_RESET_ORIGIN_TO_CONSTANT; + e->executeRuntimeFunction(url, index, this); +} +void ANON_propertyAlias::resetAliasToNewBinding() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::PROPERTY_ALIAS_RESET_ALIAS_TO_NEW_BINDING; + e->executeRuntimeFunction(url, index, this); +} +void ANON_propertyAlias::resetOriginToNewBinding() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::PROPERTY_ALIAS_RESET_ORIGIN_TO_NEW_BINDING; + e->executeRuntimeFunction(url, index, this); +} + +int ANON_propertyAlias::getAliasValue() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::PROPERTY_ALIAS_GET_ALIAS_VALUE; + constexpr int argc = 0; + int ret {}; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, ret); + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); + return ret; +} + QUrl ANON_propertyAlias::url = QUrl(); // workaround void tst_qmlcompiler_manual::propertyAlias() @@ -729,78 +565,46 @@ void tst_qmlcompiler_manual::propertyAlias() QCOMPARE(created.getAliasToOrigin(), -24); } -class ANON_propertyChangeHandler : public QObject, public ContextRegistrator +ANON_propertyChangeHandler::ANON_propertyChangeHandler(QQmlEngine *e, QObject *parent) + : QObject(parent), ContextRegistrator(e, this) { - Q_OBJECT - QML_ANONYMOUS - Q_PROPERTY(int dummy READ getDummy WRITE setDummy) - Q_PROPERTY(int p READ getP WRITE setP BINDABLE bindableP) - Q_PROPERTY(int watcher READ getWatcher WRITE setWatcher) - -public: - // test workaround: the url is resolved by the test base class, so use - // member variable to store the resolved url used as argument in engine - // evaluation of runtime functions - static QUrl url; - - ANON_propertyChangeHandler(QQmlEngine *e, QObject *parent = nullptr) - : QObject(parent), ContextRegistrator(e, this) - { - dummy = 42; - QPropertyBinding<int> ANON_propertyChangeHandler_p_binding( - [&]() { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::PROPERTY_CHANGE_HANDLER_P_BINDING; - constexpr int argc = 0; - int ret {}; - std::array<void *, argc + 1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, ret); - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - return ret; - }, - QT_PROPERTY_DEFAULT_BINDING_LOCATION); - bindableP().setBinding(ANON_propertyChangeHandler_p_binding); - watcher = 0; - - // NB: make sure property change handler appears after setBinding(). - // this prevents preliminary binding evaluation (which would fail as - // this object doesn't yet know about qmlEngine(this)) - pChangeHandler.reset(new QPropertyChangeHandler<ANON_propertyChangeHandler_p_changeHandler>( - bindableP().onValueChanged(ANON_propertyChangeHandler_p_changeHandler(this)))); - } - - int getDummy() { return dummy.value(); } - int getP() { return p.value(); } - int getWatcher() { return watcher.value(); } - - void setDummy(int dummy_) { dummy.setValue(dummy_); } - void setP(int p_) { p.setValue(p_); } - void setWatcher(int watcher_) { watcher.setValue(watcher_); } - - QBindable<int> bindableP() { return QBindable<int>(&p); } - - QProperty<int> dummy; - QProperty<int> p; - QProperty<int> watcher; - - // property change handler: - struct ANON_propertyChangeHandler_p_changeHandler - { - ANON_propertyChangeHandler *This = nullptr; - ANON_propertyChangeHandler_p_changeHandler(ANON_propertyChangeHandler *obj) : This(obj) { } - - void operator()() - { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(This)); - const auto index = FunctionIndices::PROPERTY_CHANGE_HANDLER_ON_P_CHANGED; - e->executeRuntimeFunction(This->url, index, This); - } - }; - // the handler object has to be alive as long as the object - std::unique_ptr<QPropertyChangeHandler<ANON_propertyChangeHandler_p_changeHandler>> - pChangeHandler; -}; + dummy = 42; + QPropertyBinding<int> ANON_propertyChangeHandler_p_binding( + [&]() { + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::PROPERTY_CHANGE_HANDLER_P_BINDING; + constexpr int argc = 0; + int ret {}; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, ret); + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); + return ret; + }, + QT_PROPERTY_DEFAULT_BINDING_LOCATION); + bindableP().setBinding(ANON_propertyChangeHandler_p_binding); + watcher = 0; + + // NB: make sure property change handler appears after setBinding(). + // this prevents preliminary binding evaluation (which would fail as + // this object doesn't yet know about qmlEngine(this)) + pChangeHandler.reset(new QPropertyChangeHandler<ANON_propertyChangeHandler_p_changeHandler>( + bindableP().onValueChanged(ANON_propertyChangeHandler_p_changeHandler(this)))); +} + +ANON_propertyChangeHandler::ANON_propertyChangeHandler_p_changeHandler:: + ANON_propertyChangeHandler_p_changeHandler(ANON_propertyChangeHandler *obj) + : This(obj) +{ +} + +void ANON_propertyChangeHandler::ANON_propertyChangeHandler_p_changeHandler::operator()() +{ + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(This)); + const auto index = FunctionIndices::PROPERTY_CHANGE_HANDLER_ON_P_CHANGED; + e->executeRuntimeFunction(This->url, index, This); +} + QUrl ANON_propertyChangeHandler::url = QUrl(); // workaround void tst_qmlcompiler_manual::propertyChangeHandler() @@ -832,49 +636,25 @@ void tst_qmlcompiler_manual::propertyChangeHandler() QCOMPARE(created.property("watcher").toInt(), 96); } -class ANON_propertyReturningFunction : public QObject, public ContextRegistrator +ANON_propertyReturningFunction::ANON_propertyReturningFunction(QQmlEngine *e, QObject *parent) + : QObject(parent), ContextRegistrator(e, this) { - Q_OBJECT - QML_ANONYMOUS - Q_PROPERTY(int counter READ getCounter WRITE setCounter) - Q_PROPERTY(QVariant f READ getF WRITE setF BINDABLE bindableF) - -public: - // test workaround: the url is resolved by the test base class, so use - // member variable to store the resolved url used as argument in engine - // evaluation of runtime functions - static QUrl url; - - ANON_propertyReturningFunction(QQmlEngine *e, QObject *parent = nullptr) - : QObject(parent), ContextRegistrator(e, this) - { - QPropertyBinding<QVariant> ANON_propertyReturningFunction_f_binding( - [&]() { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); - const auto index = FunctionIndices::PROPERTY_RETURNING_FUNCTION_F_BINDING; - constexpr int argc = 0; - QVariant ret {}; - std::array<void *, argc + 1> a {}; - std::array<QMetaType, argc + 1> t {}; - typeEraseArguments(a, t, ret); - e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); - return ret; - }, - QT_PROPERTY_DEFAULT_BINDING_LOCATION); - bindableF().setBinding(ANON_propertyReturningFunction_f_binding); - } - - int getCounter() { return counter.value(); } - QVariant getF() { return f.value(); } - - void setCounter(int counter_) { counter.setValue(counter_); } - void setF(QVariant f_) { f.setValue(f_); } - - QBindable<QVariant> bindableF() { return QBindable<QVariant>(&f); } - - QProperty<int> counter; - QProperty<QVariant> f; -}; + QPropertyBinding<QVariant> ANON_propertyReturningFunction_f_binding( + [&]() { + QQmlEnginePrivate *e = QQmlEnginePrivate::get(qmlEngine(this)); + const auto index = FunctionIndices::PROPERTY_RETURNING_FUNCTION_F_BINDING; + constexpr int argc = 0; + QVariant ret {}; + std::array<void *, argc + 1> a {}; + std::array<QMetaType, argc + 1> t {}; + typeEraseArguments(a, t, ret); + e->executeRuntimeFunction(url, index, this, argc, a.data(), t.data()); + return ret; + }, + QT_PROPERTY_DEFAULT_BINDING_LOCATION); + bindableF().setBinding(ANON_propertyReturningFunction_f_binding); +} + QUrl ANON_propertyReturningFunction::url = QUrl(); // workaround void tst_qmlcompiler_manual::propertyReturningFunction() |