diff options
Diffstat (limited to 'src/qml/doc/src/qmllanguageref/documents/structure.qdoc')
-rw-r--r-- | src/qml/doc/src/qmllanguageref/documents/structure.qdoc | 319 |
1 files changed, 292 insertions, 27 deletions
diff --git a/src/qml/doc/src/qmllanguageref/documents/structure.qdoc b/src/qml/doc/src/qmllanguageref/documents/structure.qdoc index 666039c73a..5a43ae2028 100644 --- a/src/qml/doc/src/qmllanguageref/documents/structure.qdoc +++ b/src/qml/doc/src/qmllanguageref/documents/structure.qdoc @@ -1,38 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \page qtqml-documents-structure.html \title Structure of a QML Document \brief Description of the structure of QML documents -A QML document is a self contained piece of QML source code that consists of two parts: +A QML document is a self contained piece of QML source code that consists of three parts: \list + \li An optional list of pragmas \li Its \e import statements \li A single root object declaration \endlist @@ -43,6 +20,294 @@ QML documents are always encoded in UTF-8 format. +\section1 Pragmas + +Pragmas are instructions to the QML engine itself that can be used to specify +certain characteristics of objects in the current file or to modify how the +engine interprets code. The following pragmas are exaplained in details below. + +\list +\li \c Singleton +\li \c ListPropertyAssignBehavior +\li \c ComponentBehavior +\li \c FunctionSignatureBehavior +\li \c NativeMethodBehavior +\li \c ValueTypeBehavior +\li \c Translator +\endlist + +\section2 Singleton + +\c{pragma Singleton} declares the component defined in the QML document as +singleton. Singletons are created only once per QML engine. In order to use +a QML-declared singleton you also have to register it with its module. See +\l{qt_target_qml_sources} for how to do this with CMake. + +\section2 ListPropertyAssignBehavior + +With this pragma you can define how assignments to list properties shall be +handled in components defined in the QML document. By default, assigning to a +list property appends to the list. You can explicitly request this behavior +using the value \c{Append}. Alternatively, you can request the contents of list +properties to always be replaced using \c{Replace}, or replaced if the property +is not the default property using \c{ReplaceIfNotDefault}. For example: + +\qml +pragma ListPropertyAssignBehavior: ReplaceIfNotDefault +\endqml + +\note The same declaration can also be given for C++-defined types, by adding +the \l{QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND}, +\l{QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE}, and +\l{QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT} macros to the +class declaration. + +\section2 ComponentBehavior + +You may have multiple components defined in the same QML file. The root +scope of the QML file is a component, and you may additionally have +elements of type \l QQmlComponent, explicitly or implicitly created +as properties, or inline components. Those components are nested. Each +of the inner components is within one specific outer component. Most of +the time, IDs defined in an outer component are accessible within all +its nested inner components. You can, however, create elements from a +component in any a different context, with different IDs available. +Doing so breaks the assumption that outer IDs are available. Therefore, +the engine and the QML tooling cannot generally know in advance what +type, if any, such IDs will resolve to at run time. + +With the ComponentBehavior pragma you can restrict all inner components +defined in a file to only create objects within their original context. +If a component is bound to its context, you can safely use IDs from +outer components in the same file within the component. QML tooling will +then assume the outer IDs with their specific types to be available. + +In order to bind the components to their context specify the \c{Bound} +argument: + +\qml +pragma ComponentBehavior: Bound +\endqml + +This implies that, in case of name clashes, IDs defined outside a bound +component override local properties of objects created from the +component. Otherwise it wouldn't actually be safe to use the IDs since +later versions of a module might add more properties to the component. +If the component is not bound, local properties override IDs defined +outside the component, but not IDs defined inside the component. + +The example below prints the \e r property of the ListView object with +the id \e color, not the \e r property of the rectangle's color. + +\qml +pragma ComponentBehavior: Bound +import QtQuick + +ListView { + id: color + property int r: 12 + model: 1 + + delegate: Rectangle { + Component.onCompleted: console.log(color.r) + } +} +\endqml + +The default value of \c ComponentBehavior is \c{Unbound}. You can also +specify it explicitly. In a future version of Qt the default will change +to \c{Bound}. + +Delegate components bound to their context don't receive their own +private contexts on instantiation. This means that model data can only +be passed via \l{Required Properties}{required properties} in this case. +Passing model data via context properties will not work. This concerns +delegates to e.g. \l{Instantiator}, \l{Repeater}, \l{ListView}, +\l{TableView}, \l{GridView}, \l{TreeView} and in general anything that +uses \l{DelegateModel} internally. + +For example, the following will \e{not} work: + +\qml +pragma ComponentBehavior: Bound +import QtQuick + +ListView { + delegate: Rectangle { + color: model.myColor + } +} +\endqml + +The \c{delegate} property of \l{ListView} is a component. Therefore, a +\l{Component} is implicitly created around the \l{Rectangle} here. That +component is bound to its context. It doesn't receive the context property +\c{model} provided by \l{ListView}. To make it work, you'd have to write +it this way: + +\qml +pragma ComponentBehavior: Bound +import QtQuick + +ListView { + delegate: Rectangle { + required property color myColor + color: myColor + } +} +\endqml + +You can nest components in a QML file. The pragma holds for all components in +the file, no matter how deeply nested. + +\section2 FunctionSignatureBehavior + +With this pragma you can change the way type annotations on functions +are handled. Since Qt 6.7 type annotations are enforced when calling +functions. Before, only the \l{QML script compiler} enforced the type +annotations. The interpreter and JIT compiler ignored them. Always +enforcing the type annotations is a behavior change in comparison to +earlier versions since you could call functions with mismatched +arguments before. + +Specifying \c{Ignored} as value makes the QML engine and the +\l{QML script compiler} ignore any type annotations and therefore +restores the pre-6.7 behavior of the interpreter and JIT. As a result +less code is compiled to C++ ahead of time, and more code has to be +interpreted or JIT-compiled. + +Specifying \c{Enforced} as value explicitly states the default: Type +annotations are always enforced. + +\sa {Type annotations and assertions} + +\section2 NativeMethodBehavior + +Calling C++ methods with \c this objects different from the one they were +retrieved from is broken, due to historical reasons. The original object is +used as \c this object. You can allow the given \c this object to be used by +setting \c {pragma NativeMethodBehavior: AcceptThisObject}. Specifying +\c RejectThisObject keeps the historical behavior. + +An example of this can be found under \l {C++ methods and the 'this' object}. + +\section2 ValueTypeBehavior + +With this pragma you can change the way value types and sequences are handled. + +Usually lower case names cannot be type names in JavaScript code. This is a +problem because value type names are lower case. You can specify \c{Addressable} +as value for this pragma to change this. If \c{Addressable} is specified a +JavaScript value can be explicitly coerced to a specific, named, value type. This is +done using the \c as operator, like you would do with object types. Furthermore, +you can also check for value types using the \c instanceof operator: + +\qml +pragma ValueTypeBehavior: Addressable +import QtQml + +QtObject { + property var a + property real b: (a as rect).x + property bool c: a instanceof rect + + property var rect // inaccessible. "rect" is a type name. +} +\endqml + +If the type does not match, casting returns \c undefined. \c instanceof +only checks for inheritance, not for all possible type coercions. So, for +example, a \l{QRect} is not a \c rect value type since \c rect is \l{QRectF} +in C++, and therefore not related by inheritance. With \c as you can cast +to any type compatible via coercion. + +Since \c rect in the above example is now a type name, it will shadow any +properties called \c{rect}. + +Explicitly casting to the desired type helps tooling. It can allow the +\l{Qt Quick Compiler} generate efficient code where it otherwise would not be +able to. You can use \l{qmllint Reference}{qmllint} to find such occurrences. + +There is also a \c{Inaddressable} value you can use to explicitly specify the +default behavior. + +Value types and sequences are generally treated as references. This means, if +you retrieve a value type instance from a property into a local value, and then +change the local value, the original property is also changed. Furthermore, +if you write the original property explicitly, the local value is also updated. +This behavior is rather unintuitive in many places, and you should not rely on +it. The \c{Copy} and \c{Reference} values for the \c{ValueTypeBehavior} pragma +are experimental options to change this behavior. You should not use them. +Specifying \c{Copy} causes all value types to be treated as actual copies. +Specifying \c{Reference} explicitly states the default behavior. + +Rather than using \c{Copy} you should explicitly re-load references to value +types and sequences any time they can have been affected by side effects. Side +effects can happen whenever you call a function or imperatively set a property. +\l qmllint provides guidance on this. For example, in the following code +the variable \c f is affected by side effects after writing \c width. This is +because there may be a binding in a derived type or in a \c Binding element +that updates \c font when \c width is changed. + +\qml +import QtQuick +Text { + function a() : real { + var f = font; + width = f.pixelSize; + return f.pointSize; + } +} +\endqml + +In order to address this, you can avoid holding \c f across the write operation +on \c width: + +\qml +import QtQuick +Text { + function a() : real { + var f = font; + width = f.pixelSize; + f = font; + return f.pointSize; + } +} +\endqml + +This, in turn can be shortened to: + +\qml +import QtQuick +Text { + function a() : real { + width = font.pixelSize; + return font.pointSize; + } +} +\endqml + +You might assume that re-retrieving the \c font property is costly, but actually +the QML engine automatically refreshes value type references each time you read +from them. So this is not more expensive than the first version, but a clearer +way to express the same operations. + +\sa {Type annotations and assertions} + +\section2 Translator + +With this pragma you can set the context for the translations in the file. + +\qml +pragma Translator: myTranslationContext +\endqml + +\qml +pragma Translator: "myTranslationContext" +\endqml + +For more information on internationalization with QML, see \l{QML: Use qsTr()}{Use qsTr}. + \section1 Imports A document must import the necessary modules or type namespaces to enable the |