diff options
-rw-r--r-- | src/qml/doc/src/qmlfunctions.qdoc | 8 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 25 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p.h | 4 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 19 |
6 files changed, 62 insertions, 7 deletions
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index 3c80f16c8f..ab54b5fd1d 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -564,6 +564,14 @@ \sa {Choosing the Correct Integration Method Between C++ and QML} */ + +/*! + \fn int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, std::function<QObject*(QQmlEngine *, QJSEngine *)> callback) + \relates QQmlEngine + + \overload qmlRegisterSingletonType +*/ + /*! \fn int qmlRegisterSingletonType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName) \relates QQmlEngine diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index f84a1b2109..4f3bfb76b0 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -624,13 +624,13 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi uri, versionMajor, versionMinor, typeName, - callback, nullptr, nullptr, 0, 0 + callback, nullptr, nullptr, 0, 0, {} }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); } -enum { QmlCurrentSingletonTypeRegistrationVersion = 2 }; +enum { QmlCurrentSingletonTypeRegistrationVersion = 3 }; template <typename T> inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject *(*callback)(QQmlEngine *, QJSEngine *)) @@ -642,7 +642,26 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi uri, versionMajor, versionMinor, typeName, - nullptr, callback, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0 + nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, callback + }; + + return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); +} + +template <typename T, typename F, typename std::enable_if<std::is_convertible<F, std::function<QObject *(QQmlEngine *, QJSEngine *)>>::value + && !std::is_convertible<F, QObject *(*)(QQmlEngine *, QJSEngine *)>::value, void>::type* = nullptr> +inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, + F&& callback) +{ + + QML_GETTYPENAMES + + QQmlPrivate::RegisterSingletonType api = { + QmlCurrentSingletonTypeRegistrationVersion, + + uri, versionMajor, versionMinor, typeName, + + nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, callback }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index c6858780a1..a2c2ae47af 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -107,7 +107,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el d->version_maj = type.versionMajor; d->version_min = type.versionMinor; - if (type.qobjectApi) { + if (type.qobjectApi || (type.version >= 3 && type.generalizedQobjectApi)) { if (type.version >= 1) // static metaobject added in version 1 d->baseMetaObject = type.instanceMetaObject; if (type.version >= 2) // typeId added in version 2 @@ -118,10 +118,14 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi; - d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi; + if (type.version >= 3) { + d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.generalizedQobjectApi; + } else { + d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi; + } d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); d->extraData.sd->singletonInstanceInfo->instanceMetaObject - = (type.qobjectApi && type.version >= 1) ? type.instanceMetaObject : nullptr; + = ((type.qobjectApi || (type.version >= 3 && type.generalizedQobjectApi) ) && type.version >= 1) ? type.instanceMetaObject : nullptr; return d; } diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index ae84803648..a07736c6fc 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -51,6 +51,8 @@ // We mean it. // +#include <functional> + #include <QtQml/qtqmlglobal.h> #include <QtCore/qglobal.h> @@ -276,6 +278,7 @@ namespace QQmlPrivate const QMetaObject *instanceMetaObject; // new in version 1 int typeId; // new in version 2 int revision; // new in version 2 + std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3 // If this is extended ensure "version" is bumped!!! }; diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h index 1d65a08c8f..158fefad2c 100644 --- a/src/qml/qml/qqmltype_p.h +++ b/src/qml/qml/qqmltype_p.h @@ -51,6 +51,8 @@ // We mean it. // +#include <functional> + #include <private/qtqmlglobal_p.h> #include <private/qqmlrefcount_p.h> @@ -145,7 +147,7 @@ public: struct Q_QML_PRIVATE_EXPORT SingletonInstanceInfo { QJSValue (*scriptCallback)(QQmlEngine *, QJSEngine *) = nullptr; - QObject *(*qobjectCallback)(QQmlEngine *, QJSEngine *) = nullptr; + std::function<QObject *(QQmlEngine *, QJSEngine *)> qobjectCallback = {}; const QMetaObject *instanceMetaObject = nullptr; QString typeName; QUrl url; // used by composite singletons diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 0cb6753020..8d0106b92c 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -1015,6 +1015,25 @@ void tst_qqmlengine::singletonInstance() } { + int data = 30; + auto id = qmlRegisterSingletonType<CppSingleton>("Qt.test",1,0,"CapturingLambda",[data](QQmlEngine*, QJSEngine*){ // register qobject singleton with capturing lambda + auto o = new CppSingleton; + o->setProperty("data", data); + return o; + }); + QJSValue value = engine.singletonInstance<QJSValue>(id); + QVERIFY(!value.isUndefined()); + QVERIFY(value.isQObject()); + QObject *instance = value.toQObject(); + QVERIFY(instance); + QCOMPARE(instance->metaObject()->className(), "CppSingleton"); + QCOMPARE(instance->property("data"), data); + } + { + qmlRegisterSingletonType<CppSingleton>("Qt.test",1,0,"NotAmbiguous", [](QQmlEngine* qeng, QJSEngine* jeng) -> QObject* {return CppSingleton::create(qeng, jeng);}); // test that overloads for qmlRegisterSingleton are not ambiguous + } + + { // Invalid types QJSValue value; value = engine.singletonInstance<QJSValue>(-4711); |