aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-05-14 12:53:13 +0200
committerUlf Hermann <ulf.hermann@qt.io>2021-05-17 10:24:12 +0200
commitf4f1e348c01f8301cbebde870a5cef098baaa0b8 (patch)
treeb449b30200a7be15c4fa990aad3a88c1e2ac9d3d
parent42afb8249cfcf8cec66aac9e55d13ac508699ec8 (diff)
Doc: Expand documentation on QML_SINGLETON
Give concrete examples on how to cover common use cases of qmlRegisterSingletonType and qmlRegisterSingletonInstance. Change-Id: I06084336b789afaa6a7833803a0fa6eb55b45f10 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc126
1 files changed, 125 insertions, 1 deletions
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index 92d9bdec49..7fc1f15c69 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -187,7 +187,131 @@
\c{T *create(QQmlEngine *, QJSEngine *)} when the type is first accessed.
If both do exist and are accessible, the default constructor is preferred.
If there is no default constructor and no factory function the singleton is
- initially inaccessible.
+ inaccessible.
+
+ In order to declare a default-constructible class as singleton, all you have
+ to do is add \l QML_SINGLETON:
+
+ \code
+ class MySingleton : public QObject
+ {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ // Q_PROPERTY( ... )
+ public:
+ // members, Q_INVOKABLE functions, etc.
+ };
+ \endcode
+
+ If the singleton class is not default-constructible, but you can modify it,
+ you can add a factory function to it, in order to make it accessible:
+
+ \code
+ class MySingleton : public QObject
+ {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ // Q_PROPERTY( ... )
+
+ public:
+ static MySingleton *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
+ {
+ MySingleton *result = nullptr;
+ // Create the object using some custom constructor or factory.
+ // The QML engine will assume ownership and delete it, eventually.
+ return result;
+ }
+
+ // members, Q_INVOKABLE functions, etc
+ };
+ \endcode
+
+ If you cannot modify the class and it does not have a default constructor or a
+ suitable factory function, you can provide a \l QML_FOREIGN wrapper to define
+ the factory function:
+
+ \code
+ struct SingletonForeign
+ {
+ Q_GADGET
+ QML_FOREIGN(MySingleton)
+ QML_SINGLETON
+ QML_NAMED_ELEMENT(MySingleton)
+ public:
+
+ static MySingleton *create(QQmlEngine *, QJSEngine *engine)
+ {
+ MySingleton *result = nullptr;
+ // Create the instance using some custom constructor or factory.
+ // The QML engine will assume ownership and delete it, eventually.
+ return result;
+ }
+ };
+ \endcode
+
+ Finally, if you want to provide one specific singleton object, the creation of
+ which you cannot control, you can return that from a factory function. This is
+ a replacement for the \l qmlRegisterSingletonInstance function.
+ If you were calling
+
+ \code
+ qmlRegisterSingletonInstance("MyModule", 1, 0, "MySingleton", myObject);
+ \endcode
+
+ with myObject being of type \c{MySingleton *}, you can do the following
+ instead:
+
+ \code
+ struct SingletonForeign
+ {
+ Q_GADGET
+ QML_FOREIGN(MySingleton)
+ QML_SINGLETON
+ QML_NAMED_ELEMENT(MySingleton)
+ public:
+
+ // Initialize this using myObject where you would previously
+ // call qmlRegisterSingletonInstance().
+ static MySingleton *s_singletonInstance = nullptr;
+
+ static MySingleton *create(QQmlEngine *, QJSEngine *engine)
+ {
+ // The instance has to exist before it is used. We cannot replace it.
+ Q_ASSERT(s_singletonInstance);
+
+ // The engine has to have the same thread affinity as the singleton.
+ Q_ASSERT(engine->thread() == s_singletonInstance->thread());
+
+ // There can only be one engine accessing the singleton.
+ if (s_engine)
+ Q_ASSERT(engine == s_engine);
+ else
+ s_engine = engine;
+
+ // Explicitly specify C++ ownership so that the engine doesn't delete
+ // the instance.
+ QJSEngine::setObjectOwnership(s_singletonInstance,
+ QJSEngine::CppOwnership);
+ return s_singletonInstance;
+ }
+
+ private:
+ static QJSEngine *s_engine = nullptr;
+ };
+ \endcode
+
+ This way, the pre-existing class \c MySingleton is declared to be a QML
+ singleton, called \c MySingleton. You can specify an instance for it any time
+ before it is used by setting the \c s_singletonInstance member. None of this
+ requires modification of \c MySingleton itself.
+
+ \note This pattern doesn't work if either the singleton is accessed by
+ multiple QML engines, or if the QML engine accessing it has a different thread
+ affinity than the singleton object itself. As shown above, you can check the
+ parameters to the \c create() method for identity and thread affinity of the
+ engine in order to assert on that.
\sa QML_ELEMENT, QML_NAMED_ELEMENT(), qmlRegisterSingletonInstance().
*/