diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-11-02 10:57:59 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-11-02 14:00:23 +0100 |
commit | e826636a0bebd0d73e6c17038b24ee2a42d92ead (patch) | |
tree | 0a2ea355eb83af6ac636bec0e5fb0028b81ffbe2 /src/qml/qml | |
parent | 6f968781c4c8a278a7743b0904fb2bdf4c6ddf1a (diff) |
QML: Allow singletons to be created with a factory function
This is in line with what we do on qmlRegisterSingletonType(), and it
allows us to return singleton objects created independently of the
instantiation mechanism.
Change-Id: Ia6a077f5d22241593acd8cc87b3f65ae20f95667
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 64 |
1 files changed, 56 insertions, 8 deletions
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 2beeacd20f..4fcfd65c09 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -145,17 +145,57 @@ namespace QQmlPrivate } }; + enum class ConstructionMode + { + None, + Constructor, + Factory + }; + + template<typename T, typename = std::void_t<>> + struct HasSingletonFactory + { + static constexpr bool value = false; + }; + template<typename T> - constexpr bool isConstructible() + struct HasSingletonFactory<T, std::void_t<decltype(T::create( + static_cast<QQmlEngine *>(nullptr), + static_cast<QJSEngine *>(nullptr)))>> { - return std::is_default_constructible<T>::value && std::is_base_of<QObject, T>::value; + static constexpr bool value = std::is_same_v< + decltype(T::create(static_cast<QQmlEngine *>(nullptr), + static_cast<QJSEngine *>(nullptr))), T *>; + }; + + template<typename T> + constexpr ConstructionMode constructionMode() + { + if constexpr (!std::is_base_of<QObject, T>::value) + return ConstructionMode::None; + if constexpr (std::is_default_constructible<T>::value) + return ConstructionMode::Constructor; + if constexpr (HasSingletonFactory<T>::value) + return ConstructionMode::Factory; + + return ConstructionMode::None; } template<typename T> void createInto(void *memory, void *) { new (memory) QQmlElement<T>; } - template<typename T> - QObject *createSingletonInstance(QQmlEngine *, QJSEngine *) { return new T; } + template<typename T, ConstructionMode Mode> + QObject *createSingletonInstance(QQmlEngine *q, QJSEngine *j) + { + Q_UNUSED(q); + Q_UNUSED(j); + if constexpr (Mode == ConstructionMode::Constructor) + return new T; + else if constexpr (Mode == ConstructionMode::Factory) + return T::create(q, j); + else + return nullptr; + } template<typename T> QObject *createParent(QObject *p) { return new T(p); } @@ -165,25 +205,33 @@ namespace QQmlPrivate using CreateParentFunction = QObject *(*)(QObject *); using CreateValueTypeFunction = QVariant (*)(const QJSValue &); - template<typename T, bool Constructible = isConstructible<T>()> + template<typename T, ConstructionMode Mode = constructionMode<T>()> struct Constructors; template<typename T> - struct Constructors<T, true> + struct Constructors<T, ConstructionMode::Constructor> { static constexpr CreateIntoFunction createInto = QQmlPrivate::createInto<T>; static constexpr CreateSingletonFunction createSingletonInstance - = QQmlPrivate::createSingletonInstance<T>; + = QQmlPrivate::createSingletonInstance<T, ConstructionMode::Constructor>; }; template<typename T> - struct Constructors<T, false> + struct Constructors<T, ConstructionMode::None> { static constexpr CreateIntoFunction createInto = nullptr; static constexpr CreateSingletonFunction createSingletonInstance = nullptr; }; + template<typename T> + struct Constructors<T, ConstructionMode::Factory> + { + static constexpr CreateIntoFunction createInto = nullptr; + static constexpr CreateSingletonFunction createSingletonInstance + = QQmlPrivate::createSingletonInstance<T, ConstructionMode::Factory>; + }; + template<typename T, bool IsObject = std::is_base_of<QObject, T>::value, bool IsGadget = QtPrivate::IsGadgetHelper<T>::IsRealGadget> |