aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-11-02 10:57:59 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-11-02 14:00:23 +0100
commite826636a0bebd0d73e6c17038b24ee2a42d92ead (patch)
tree0a2ea355eb83af6ac636bec0e5fb0028b81ffbe2 /src/qml/qml
parent6f968781c4c8a278a7743b0904fb2bdf4c6ddf1a (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.h64
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>