aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc')
-rw-r--r--src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc88
1 files changed, 85 insertions, 3 deletions
diff --git a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc b/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc
index 0a824bb5b5..6277b01af3 100644
--- a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc
+++ b/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc
@@ -105,6 +105,88 @@ You can also connect to any signals or call methods defined in the component
using QMetaObject::invokeMethod() and QObject::connect(). See \l {Invoking QML Methods}
and \l {Connecting to QML Signals} below for further details.
+\section1 Accessing QML Objects via well-defined C++ Interfaces
+
+The best way of interacting with QML from C++ is to define an interface for
+doing so in C++ and accessing it in QML itself. With other methods, refactoring
+your QML code can easily lead to your QML / C++ interaction breaking. It also
+helps to reason about the interaction of QML and C++ code, as having it driven
+via QML can be more easily reasoned about by both users and tooling such as
+qmllint. Accessing QML from C++ will lead to QML code that cannot be understood
+without manually verifying that no outside C++ code is modifying a given QML
+component, and even then the extent of the access might change over time, making
+continued use of this strategy a maintenance burden.
+
+To let QML drive the interaction, first you need to define a C++ interface:
+
+\code
+class CppInterface : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ // ...
+};
+\endcode
+
+Using a QML-driven approach, this interface can be interacted with in two ways:
+
+\section2 Singletons
+
+One option is to register the interface as a singleton by adding the \l
+QML_SINGLETON macro to the interface, exposing it to all components. Following
+that, the interface becomes available via a simple import statement:
+
+\code
+import my.company.module
+
+Item {
+ Component.onCompleted: {
+ CppInterface.foo();
+ }
+}
+\endcode
+
+Use this approach if you need your interface in more places than the root component, as
+simply passing down an object would require explicitly passing it on to other
+components via a property or utilizing the slow and not recommended method of
+using \l {Unqualified access}{unqualified access}.
+
+\section2 Initial properties
+
+Another option is to mark the interface as uncreatable via \l QML_UNCREATABLE
+and supplying it to the root QML Component by using \l
+QQmlComponent::createWithInitialProperties() and a \l {Required
+Properties}{required property} on the QML end.
+
+Your root component may look something like this:
+
+\code
+import QtQuick
+
+Item {
+ required property CppInterface interface
+ Component.onCompleted: {
+ interface.foo();
+ }
+}
+\endcode
+
+Marking the property as required here protects the component against being
+created without the interface property being set.
+
+You can then initialize your component in the same way as outlined in \l
+{Loading QML Objects from C++} except using \c {createWithInitialProperties()}:
+
+\code
+ component.createWithInitialProperties(QVariantMap{{u"interface"_qs, QVariant::fromValue<CppInterface *>(new CppInterface)}});
+\endcode
+
+This method is to be preferred if you know that your interface only needs to be
+available to the root component. It also allows for connecting to signals and
+slots of the interface more easily on the C++ side.
+
+If neither of these methods suit your needs you may want to investigate the usage of
+\l {Using C++ Models with Qt Quick Views}{C++ models} instead.
\section1 Accessing Loaded QML Objects by Object Name
@@ -189,9 +271,9 @@ Notice the parameter and return type specified after the colon. You can use \l
{QML Basic Types}{basic types} and \l {QML Object Types}{object types} as type
names.
-If the type is omitted in QML, then you must specify QVariant as type with
-Q_RETURN_ARG() and Q_ARG() when calling QMetaObject::invokeMethod.
-
+If the type is omitted or specified as \c var in QML, then you must pass
+QVariant as type with Q_RETURN_ARG() and Q_ARG() when calling
+QMetaObject::invokeMethod.
\section2 Connecting to QML Signals