aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/doc/src/cppintegration/data.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/doc/src/cppintegration/data.qdoc')
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc235
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