diff options
Diffstat (limited to 'src/qml/doc/src/cppintegration/data.qdoc')
-rw-r--r-- | src/qml/doc/src/cppintegration/data.qdoc | 235 |
1 files changed, 117 insertions, 118 deletions
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index 9dfb7837e5..2822f4acee 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -1,29 +1,5 @@ -/**************************************************************************** -** -** 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) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \page qtqml-cppintegration-data.html \title Data Type Conversion Between QML and C++ @@ -38,6 +14,10 @@ The QML engine provides built-in support for a large number of Qt C++ data types. Additionally, custom C++ types may be registered with the QML type system to make them available to the engine. +For more information about C++ and the different QML integration methods, +see the +\l {Overview - QML and C++ Integration} {C++ and QML integration overview} page. + This page discusses the data types supported by the QML engine and how they are converted between QML and C++. @@ -59,13 +39,13 @@ has a parent. \section1 Basic Qt Data Types By default, QML recognizes the following Qt data types, which are -automatically converted to a corresponding \l {QML Basic Types}{QML basic type} +automatically converted to a corresponding \l {QML Value Types}{QML value type} when passed from C++ to QML and vice-versa: \table \row \li Qt Type - \li QML Basic Type + \li QML Value Type \row \li bool \li \l bool @@ -112,7 +92,7 @@ when passed from C++ to QML and vice-versa: \li QVector2D, QVector3D, QVector4D \li \l vector2d, \l vector3d, \l vector4d \row - \li Enums declared with Q_ENUM() or Q_ENUMS() + \li Enums declared with Q_ENUM() \li \l enumeration \endtable @@ -133,7 +113,7 @@ Item { } \endqml -See documentation for each individual type under \l {QML Basic Types} for more +See documentation for each individual type under \l {QML Value Types} for more information. @@ -266,6 +246,51 @@ Similarly, if a C++ type uses a QDateTime for a property type or method parameter, the value can be created as a JavaScript \c Date object in QML, and is automatically converted to a QDateTime value when it is passed to C++. +\note Watch out for the difference in month numbering: JavaScript numbers +January as 0 through 11 for December, off by one from Qt's numbering +of January as 1 through 12 for December. + +\note When using a string in JavaScript as the value of a \c Date object, +note that a string with no time fields (so a simple date) is +interpreted as the UTC start of the relevant day, in contrast +to \c{new Date(y, m, d)} which uses the local time start of the day. +Most other ways of constructing a \c Date object in JavaScript produce +a local time, unless methods with UTC in their names are used. If your +program is run in a zone behind UTC (nominally west of The Prime +Meridian), use of a date-only string will lead to a \c Date object +whose \c getDate() is one less than the day-number in your string; it +will typically have a large value for \c getHours(). The UTC variants +of these methods, \c getUTCDate() and \c getUTCHours(), will give the +results you expect for such a \c Date objects. See also the next +section. + +\section2 QDate and JavaScript Date + +The QML engine converts automatically between \l QDate and the +JavaScript \c Date type by representing the date by the UTC start of +its day. A date is mapped back to QDate via QDateTime, selecting +its \l {QDateTime::}{date()} method, using the local time form of the +date unless the UTC form of it coincides with the start of the next +day, in which case the UTC form is used. + +This slighly eccentric arrangement is a work-around for the fact that +JavaScript's construction of a \c Date object from a date-only string +uses the UTC start of the day, but \c{new Date(y, m, d)} uses the +local time start of the indicated date, as discussed in a note at the +end of the previous section. + +As a result, where a QDate property or parameter is exposed to QML, +care should be taken in reading its value: the \c +Date.getUTCFullYear(), \c Date.getUTCMonth() and \c Date.getUTCDate() +methods are more likely to deliver the results users expect than the +corresponding methods without UTC in their names. + +It is thus commonly more robust to use a \l QDateTime property. This +makes it possible to take control, on the QDateTime side, of whether +the date (and time) is specified in terms of UTC or local time; as +long as the JavaScript code is written to work with the same standard, +it should be possible to avoid trouble. + //! Target adds an anchor, so renaming the section won't break incoming links. \target QTime to JavaScript Date \section2 QTime and JavaScript Date @@ -275,103 +300,21 @@ JavaScript \c Date objects. As QTime values do not contain a date component, one is created for the conversion only. Thus, you should not rely on the date component of the resulting Date object. -Under the hood, conversion from a JavaScript \c Date object to QTime is done by -converting to a QDateTime object and calling its \l {QDateTime::}{time()} -method. +Under the hood, conversion from a JavaScript \c Date object to QTime +is done by converting to a QDateTime object (using local time) and +calling its \l {QDateTime::}{time()} method. \section2 Sequence Type to JavaScript Array -Certain C++ sequence types are supported transparently in QML to behave like -JavaScript \c Array types. - -In particular, QML currently supports: -\list - \li \c {QList<int>} - \li \c {QList<qreal>} - \li \c {QList<bool>} - \li \c {QList<QString>} and \c{QStringList} - \li \c {QVector<QString>} - \li \c {std::vector<QString>} - \li \c {QList<QUrl>} - \li \c {QVector<QUrl>} - \li \c {std::vector<QUrl>} - \li \c {QVector<int>} - \li \c {QVector<qreal>} - \li \c {QVector<bool>} - \li \c {std::vector<int>} - \li \c {std::vector<qreal>} - \li \c {std::vector<bool>} -\endlist - -and all registered QList, QVector, QQueue, QStack, QSet, std::list, -std::vector that contain a type marked with \l Q_DECLARE_METATYPE. - -These sequence types are implemented directly in terms of the underlying C++ -sequence. There are two ways in which such sequences can be exposed to QML: -as a Q_PROPERTY of the given sequence type; or as the return type of a -Q_INVOKABLE method. There are some differences in the way these are -implemented, which are important to note. - -If the sequence is exposed as a Q_PROPERTY, accessing any value in the -sequence by index will cause the sequence data to be read from the QObject's -property, then a read to occur. Similarly, modifying any value in the -sequence will cause the sequence data to be read, and then the modification -will be performed and the modified sequence will be written back to the -QObject's property. - -If the sequence is returned from a Q_INVOKABLE function, access and mutation -is much cheaper, as no QObject property read or write occurs; instead, the -C++ sequence data is accessed and modified directly. - -In both the Q_PROPERTY and return from Q_INVOKABLE cases, the elements -of a std::vector are copied. This copying may be an expensive operation, -so std::vector should be used judiciously. +See \l{QML Sequence Types} for a general description of sequence types. The +\l{Qt QML QML Types}{QtQml module} contains a few sequence types +you may want to use. You can also create a list-like data structure by constructing a QJSValue using QJSEngine::newArray(). Such a JavaScript array does not need any conversion when passing it between QML and C++. See \l{QJSValue#Working With Arrays} for details on how to manipulate JavaScript arrays from C++. -Other sequence types are not supported transparently, and instead an -instance of any other sequence type will be passed between QML and C++ as an -opaque QVariantList. - -\b {Important Note:} There are some minor differences between the -semantics of such sequence Array types and default JavaScript Array types -which result from the use of a C++ storage type in the implementation. In -particular, deleting an element from an Array will result in a -default-constructed value replacing that element, rather than an Undefined -value. Similarly, setting the length property of the Array to a value larger -than its current value will result in the Array being padded out to the -specified length with default-constructed elements rather than Undefined -elements. Finally, the Qt container classes support signed (rather than -unsigned) integer indexes; thus, attempting to access any index greater -than INT_MAX will fail. - -The default-constructed values for each sequence type are as follows: -\table -\row \li QList<int> \li integer value 0 -\row \li QList<qreal> \li real value 0.0 -\row \li QList<bool> \li boolean value \c {false} -\row \li QList<QString> and QStringList \li empty QString -\row \li QVector<QString> \li empty QString -\row \li std::vector<QString> \li empty QString -\row \li QList<QUrl> \li empty QUrl -\row \li QVector<QUrl> \li empty QUrl -\row \li std::vector<QUrl> \li empty QUrl -\row \li QVector<int> \li integer value 0 -\row \li QVector<qreal> \li real value 0.0 -\row \li QVector<bool> \li boolean value \c {false} -\row \li std::vector<int> \li integer value 0 -\row \li std::vector<qreal> \li real value 0.0 -\row \li std::vector<bool> \li boolean value \c {false} -\endtable - -If you wish to remove elements from a sequence rather than simply replace -them with default constructed values, do not use the indexed delete operator -("delete sequence[i]") but instead use the \c {splice} function -("sequence.splice(startIndex, deleteCount)"). - \section2 QByteArray to JavaScript ArrayBuffer The QML engine provides automatic type conversion between QByteArray values and @@ -497,6 +440,62 @@ class Message : public QObject }; \endcode +Enums from related types are usually registered in the scope of the relating +type. For example any enum from a different type used in a \l{Q_PROPERTY} +declaration causes all enums from that type to be made available in QML. This +is usually more of a liability than a feature. In order to prevent it from +happening, annotate your class with a special \l{Q_CLASSINFO} macro. +Use the name \c RegisterEnumsFromRelatedTypes with the value \c false to prevent +enums from related types from being registered in this type. + +You should explicitly register the enclosing types of any enums you want to use +in QML, using \l{QML_ELEMENT} or \l{QML_NAMED_ELEMENT}, rather than rely on +their enums to be injected into other types. + +\code +class OtherType : public QObject +{ + Q_OBJECT + QML_ELEMENT + +public: + enum SomeEnum { A, B, C }; + Q_ENUM(SomeEnum) + + enum AnotherEnum { D, E, F }; + Q_ENUM(AnotherEnum) +}; + +class Message : public QObject +{ + Q_OBJECT + QML_ELEMENT + + // This would usually cause all enums from OtherType to be registered + // as members of Message ... + Q_PROPERTY(OtherType::SomeEnum someEnum READ someEnum CONSTANT) + + // ... but this way it doesn't. + Q_CLASSINFO("RegisterEnumsFromRelatedTypes", "false") + +public: + OtherType::SomeEnum someEnum() const { return OtherType::B; } +}; +\endcode + +The important difference is the scope for the enums in QML. If an enum from a +related class is automatically registered, the scope is the type it is +imported into. In the above case, without the extra \l{Q_CLASSINFO}, you would +use \c {Message.A}, for example. If C++ type holding the enums is explicitly +registered, and the registration of enums from related types is suppressed, the +QML type for the C++ type holding the enums is the scope for all of its enums. +You would use \c {OtherType.A} instead of \c {Message.A} in QML. + +Mind that you can use \l QML_FOREIGN to register a type you cannot modify. You +can also use \l QML_FOREIGN_NAMESPACE to register the enumerators of a C++ type +into a QML namespace of any upper-case name, even if the same C++ type is +also registered as a QML value type. + \section2 Enumeration Types as Signal and Method Parameters C++ signals and methods with enumeration-type parameters can be used from QML |