From 0d7e9fd357bbcf5f6d638b114d715b28d2c71df4 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 10 Oct 2023 17:25:10 +0200 Subject: Document how to expose value types with enumerations Fixes: QTBUG-108883 Change-Id: I7d3de174cff6a04af4996375500b7dc18e21ef2c Reviewed-by: Fabian Kosmale Reviewed-by: Pierre-Yves Siret Reviewed-by: Sami Shalayel (cherry picked from commit 6c4f44773d9844ccf69cb209aa44698712b5be4c) (cherry picked from commit facd6c685bbf4238e54e940dfcce7761befbae07) Reviewed-by: Qt Cherry-pick Bot --- src/qml/doc/src/cppintegration/definetypes.qdoc | 54 ++++++++++++++++++++++ .../src/qmllanguageref/typesystem/namespaces.qdoc | 16 +++++++ 2 files changed, 70 insertions(+) create mode 100644 src/qml/doc/src/qmllanguageref/typesystem/namespaces.qdoc diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index 34c8bce1c8..1701d2766d 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -206,6 +206,60 @@ There are some further limitations on what you can do with value types: and subject to future changes. \endlist +\section2 Value Types with Enumerations + +Exposing enumerations from a value type to QML requires some extra steps. + +Value types have lower case names in QML and types with lower case +names are generally not addressable in JavaScript code (unless you specify +\l{ValueTypeBehavior}{pragma ValueTypeBehavior: Addressable}). If you have +a value type in C++ with an enumeration you want to expose to QML, you +need to expose the enumeration separately. + +This can be solved by using \l{QML_FOREIGN_NAMESPACE}. First, derive from +your value type to create a separate C++ type: + +\code +class Person +{ + Q_GADGET + Q_PROPERTY(QString firstName READ firstName WRITE setFirstName) + Q_PROPERTY(QString lastName READ lastName WRITE setLastName) + QML_VALUE_TYPE(person) +public: + enum TheEnum { A, B, C }; + Q_ENUM(TheEnum) + //... +}; + +class PersonDerived: public Person +{ + Q_GADGET +}; +\endcode + +Then expose the derived type as a foreign namespace: + +\code +namespace PersonDerivedForeign +{ + Q_NAMESPACE + QML_NAMED_ELEMENT(Person) + QML_FOREIGN_NAMESPACE(PersonDerived) +} +\endcode + +This produces a \l{qtqml-typesystem-namespaces.html}{QML Namespace} +called \c Person (upper case) with an enumeration called \c TheEnum and +values \c{A}, \c{B}, and \c{C}. Then you can write the following in QML: + +\qml + someProperty: Person.A +\endqml + +At the same time you can still use your value type called \c person +(lower case) exactly as before. + \section2 Registering Non-Instantiable Types Sometimes a QObject-derived class may need to be registered with the QML type diff --git a/src/qml/doc/src/qmllanguageref/typesystem/namespaces.qdoc b/src/qml/doc/src/qmllanguageref/typesystem/namespaces.qdoc new file mode 100644 index 0000000000..0635dbd026 --- /dev/null +++ b/src/qml/doc/src/qmllanguageref/typesystem/namespaces.qdoc @@ -0,0 +1,16 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only +/*! +\page qtqml-typesystem-namespaces.html +\title QML Namespaces +\brief Description of QML Namespaces + +A QML Namespace is a special kind of type that only exposes enumerations and cannot +be instantiated. A namespace can only be declared in C++, using the \l QML_ELEMENT or +\l QML_NAMED_ELEMENT macro inside a C++ namespace marked with \l{Q_NAMESPACE}. + +QML namespaces can be used to +\l{qtqml-cppintegration-definetypes.html#value-types-with-enumerations}{extract enumerations} +from other types. + +*/ -- cgit v1.2.3