1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
4\page qtqml-cppintegration-data.html
5\title Data Type Conversion Between QML and C++
6\brief Description of how data types are exchanged between QML and C++
8When data values are exchanged between QML and C++, they are converted by the
9QML engine to have the correct data types as appropriate for use in QML or
10C++. This requires the exchanged data to be of a type that is recognizable by
13The QML engine provides built-in support for a large number of Qt C++ data
14types. Additionally, custom C++ types may be registered with the QML type
15system to make them available to the engine.
17For more information about C++ and the different QML integration methods,
19\l {Overview - QML and C++ Integration} {C++ and QML integration overview} page.
21This page discusses the data types supported by the QML engine and how
22they are converted between QML and C++.
25\section1 Data Ownership
27When data is transferred from C++ to QML, the ownership of the data always
28remains with C++. The exception to this rule is when a QObject is returned from
29an explicit C++ method call: in this case, the QML engine assumes ownership of
30the object, unless the ownership of the object has explicitly been set to
31remain with C++ by invoking QQmlEngine::setObjectOwnership() with
32QQmlEngine::CppOwnership specified.
34Additionally, the QML engine respects the normal QObject parent ownership
35semantics of Qt C++ objects, and will never delete a QObject instance which
39\section1 Basic Qt Data Types
41By default, QML recognizes the following Qt data types, which are
42automatically converted to a corresponding \l {QML Value Types}{QML value type}
43when passed from C++ to QML and vice-versa:
92 \li QVector2D, QVector3D, QVector4D
93 \li \l vector2d, \l vector3d, \l vector4d
95 \li Enums declared with Q_ENUM()
99\note Classes provided by the \l {Qt GUI} module, such as QColor, QFont,
100QQuaternion and QMatrix4x4, are only available from QML when the \l {Qt Quick}
103As a convenience, many of these types can be specified in QML by string values,
104or by a related method provided by the \l {QtQml::Qt} object. For example, the \l
105{Image::sourceSize} property is of type \l size (which automatically translates
106to the QSize type) and can be specified by a string value formatted as
107"width\c{x}height", or by the Qt.size() function:
111 Image { sourceSize: "100x200" }
112 Image { sourceSize: Qt.size(100, 200) }
116See documentation for each individual type under \l {QML Value Types} for more
120\section1 QObject-derived Types
122Any QObject-derived class may be used as a type for the exchange of data between
123QML and C++, providing the class has been registered with the QML type system.
125The engine allows the registration of both instantiable and non-instantiable
126types. Once a class is registered as a QML type, it can be used as a data type
127for exchanging data between QML and C++. See
128\l{qtqml-cppintegration-definetypes.html#registering-c++-types-with-the-qml-type-system}{Registering C++ types with the QML type system} for further details on type registration.
131\section1 Conversion Between Qt and JavaScript Types
133The QML engine has built-in support for converting a number of Qt types to
134related JavaScript types, and vice-versa, when transferring data between QML
135and C++. This makes it possible to use these types and receive them in C++ or
136JavaScript without needing to implement custom types that provide access to
137the data values and their attributes.
139(Note that the JavaScript environment in QML modifies native JavaScript object
140prototypes, including those of \c String, \c Date and \c Number, to provide
141additional features. See the \l {qtqml-javascript-hostenvironment.html}
142{JavaScript Host Environment} for further details.)
145\section2 QVariantList and QVariantMap to JavaScript Array and Object
147The QML engine provides automatic type conversion between QVariantList and
148JavaScript arrays, and between QVariantMap and JavaScript objects.
150For example, the function defined in QML below expects two arguments, an
151array and an object, and prints their contents using the standard JavaScript
152syntax for array and object item access. The C++ code below calls this
153function, passing a QVariantList and a QVariantMap, which are automatically
154converted to JavaScript array and object values, repectively:
159\li \snippet qml/qtbinding/variantlistmap/MyItem.qml 0
162\li \snippet qml/qtbinding/variantlistmap/main.cpp 0
165This produces output like:
171Object item: language = QML
172Object item: released = Tue Sep 21 2010 00:00:00 GMT+1000 (EST)
175Similarly, if a C++ type uses a QVariantList or QVariantMap type for a property
176type or method parameter, the value can be created as a JavaScript array or
177object in QML, and is automatically converted to a QVariantList or QVariantMap
178when it is passed to C++.
180Mind that QVariantList and QVariantMap properties of C++ types are stored as
181values and cannot be changed in place by QML code. You can only replace the
182whole map or list, but not manipulate its contents. The following code does
183not work if the property \c l is a QVariantList:
188 Component.onCompleted: l[0] = 10
192The following code does work:
196 Component.onCompleted: l = [10, 2, 3]
200\section2 QDateTime to JavaScript Date
202The QML engine provides automatic type conversion between QDateTime values and
203JavaScript \c Date objects.
205For example, the function defined in QML below expects a JavaScript
206\c Date object, and also returns a new \c Date object with the current date and
207time. The C++ code below calls this function, passing a QDateTime value
208that is automatically converted by the engine into a \c Date object when it is
209passed to the \c readDate() function. In turn, the readDate() function returns
210a \c Date object that is automatically converted into a QDateTime value when it
220 function readDate(dt) {
221 console.log("The given date is:", dt.toUTCString());
231QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
233QDateTime dateTime = QDateTime::currentDateTime();
236QMetaObject::invokeMethod(view.rootObject(), "readDate",
237 Q_RETURN_ARG(QVariant, retValue),
238 Q_ARG(QVariant, QVariant::fromValue(dateTime)));
240qDebug() << "Value returned from readDate():" << retValue;
245Similarly, if a C++ type uses a QDateTime for a property type or method
246parameter, the value can be created as a JavaScript \c Date object in QML, and
247is automatically converted to a QDateTime value when it is passed to C++.
249\note Watch out for the difference in month numbering: JavaScript numbers
250January as 0 through 11 for December, off by one from Qt's numbering
251of January as 1 through 12 for December.
253\note When using a string in JavaScript as the value of a \c Date object,
254note that a string with no time fields (so a simple date) is
255interpreted as the UTC start of the relevant day, in contrast
256to \c{new Date(y, m, d)} which uses the local time start of the day.
257Most other ways of constructing a \c Date object in JavaScript produce
258a local time, unless methods with UTC in their names are used. If your
259program is run in a zone behind UTC (nominally west of The Prime
260Meridian), use of a date-only string will lead to a \c Date object
261whose \c getDate() is one less than the day-number in your string; it
262will typically have a large value for \c getHours(). The UTC variants
263of these methods, \c getUTCDate() and \c getUTCHours(), will give the
264results you expect for such a \c Date objects. See also the next
267\section2 QDate and JavaScript Date
269The QML engine converts automatically between \l QDate and the
270JavaScript \c Date type by representing the date by the UTC start of
271its day. A date is mapped back to QDate via QDateTime, selecting
272its \l {QDateTime::}{date()} method, using the local time form of the
273date unless the UTC form of it coincides with the start of the next
274day, in which case the UTC form is used.
276This slighly eccentric arrangement is a work-around for the fact that
277JavaScript's construction of a \c Date object from a date-only string
278uses the UTC start of the day, but \c{new Date(y, m, d)} uses the
279local time start of the indicated date, as discussed in a note at the
280end of the previous section.
282As a result, where a QDate property or parameter is exposed to QML,
283care should be taken in reading its value: the \c
284Date.getUTCFullYear(), \c Date.getUTCMonth() and \c Date.getUTCDate()
285methods are more likely to deliver the results users expect than the
286corresponding methods without UTC in their names.
288It is thus commonly more robust to use a \l QDateTime property. This
289makes it possible to take control, on the QDateTime side, of whether
290the date (and time) is specified in terms of UTC or local time; as
291long as the JavaScript code is written to work with the same standard,
292it should be possible to avoid trouble.
294//! Target adds an anchor, so renaming the section won't break incoming links.
295\target QTime to JavaScript Date
296\section2 QTime and JavaScript Date
298The QML engine provides automatic type conversion from QTime values to
299JavaScript \c Date objects. As QTime values do not contain a date component,
300one is created for the conversion only. Thus, you should not rely on the date
301component of the resulting Date object.
303Under the hood, conversion from a JavaScript \c Date object to QTime
304is done by converting to a QDateTime object (using local time) and
305calling its \l {QDateTime::}{time()} method.
307\section2 Sequence Type to JavaScript Array
309Certain C++ sequence types are supported transparently in QML to behave like
310JavaScript \c Array types.
312In particular, QML currently supports:
315 \li \c {QList<qreal>}
317 \li \c {QList<QString>} and \c{QStringList}
318 \li \c {QVector<QString>}
319 \li \c {std::vector<QString>}
321 \li \c {QVector<QUrl>}
322 \li \c {std::vector<QUrl>}
323 \li \c {QVector<int>}
324 \li \c {QVector<qreal>}
325 \li \c {QVector<bool>}
326 \li \c {std::vector<int>}
327 \li \c {std::vector<qreal>}
328 \li \c {std::vector<bool>}
331and all registered QList, QVector, QQueue, QStack, QSet, std::list,
332std::vector that contain a type marked with \l Q_DECLARE_METATYPE.
334These sequence types are implemented directly in terms of the underlying C++
335sequence. There are two ways in which such sequences can be exposed to QML:
336as a Q_PROPERTY of the given sequence type; or as the return type of a
337Q_INVOKABLE method. There are some differences in the way these are
338implemented, which are important to note.
340If the sequence is exposed as a Q_PROPERTY, accessing any value in the
341sequence by index will cause the sequence data to be read from the QObject's
342property, then a read to occur. Similarly, modifying any value in the
343sequence will cause the sequence data to be read, and then the modification
344will be performed and the modified sequence will be written back to the
347If the sequence is returned from a Q_INVOKABLE function, access and mutation
348is much cheaper, as no QObject property read or write occurs; instead, the
349C++ sequence data is accessed and modified directly.
351In both the Q_PROPERTY and return from Q_INVOKABLE cases, the elements
352of a std::vector are copied. This copying may be an expensive operation,
353so std::vector should be used judiciously.
355You can also create a list-like data structure by constructing a QJSValue using
356QJSEngine::newArray(). Such a JavaScript array does not need any conversion
357when passing it between QML and C++. See \l{QJSValue#Working With Arrays} for
358details on how to manipulate JavaScript arrays from C++.
360Other sequence types are not supported transparently, and instead an
361instance of any other sequence type will be passed between QML and C++ as an
364\b {Important Note:} There are some minor differences between the
365semantics of such sequence Array types and default JavaScript Array types
366which result from the use of a C++ storage type in the implementation. In
367particular, deleting an element from an Array will result in a
368default-constructed value replacing that element, rather than an Undefined
369value. Similarly, setting the length property of the Array to a value larger
370than its current value will result in the Array being padded out to the
371specified length with default-constructed elements rather than Undefined
372elements. Finally, the Qt container classes support signed (rather than
373unsigned) integer indexes; thus, attempting to access any index greater
374than INT_MAX will fail.
376The default-constructed values for each sequence type are as follows:
378\row \li QList<int> \li integer value 0
379\row \li QList<qreal> \li real value 0.0
380\row \li QList<bool> \li boolean value \c {false}
381\row \li QList<QString> and QStringList \li empty QString
382\row \li QVector<QString> \li empty QString
383\row \li std::vector<QString> \li empty QString
384\row \li QList<QUrl> \li empty QUrl
385\row \li QVector<QUrl> \li empty QUrl
386\row \li std::vector<QUrl> \li empty QUrl
387\row \li QVector<int> \li integer value 0
388\row \li QVector<qreal> \li real value 0.0
389\row \li QVector<bool> \li boolean value \c {false}
390\row \li std::vector<int> \li integer value 0
391\row \li std::vector<qreal> \li real value 0.0
392\row \li std::vector<bool> \li boolean value \c {false}
395If you wish to remove elements from a sequence rather than simply replace
396them with default constructed values, do not use the indexed delete operator
397("delete sequence[i]") but instead use the \c {splice} function
398("sequence.splice(startIndex, deleteCount)").
400\section2 QByteArray to JavaScript ArrayBuffer
402The QML engine provides automatic type conversion between QByteArray values and
403JavaScript \c ArrayBuffer objects.
407Some value types in Qt such as QPoint are represented in JavaScript as objects
408that have the same properties and functions like in the C++ API. The same
409representation is possible with custom C++ value types. To enable a custom
410value type with the QML engine, the class declaration needs to be annotated
411with \c{Q_GADGET}. Properties that are intended to be visible in the JavaScript
412representation need to be declared with \c Q_PROPERTY. Similarly functions need
413to be marked with \c Q_INVOKABLE. This is the same with QObject based C++ APIs.
414For example, the \c Actor class below is annotated as gadget and has
421 Q_PROPERTY(QString name READ name WRITE setName)
423 QString name() const { return m_name; }
424 void setName(const QString &name) { m_name = name; }
430 Q_DECLARE_METATYPE(Actor)
433The usual pattern is to use a gadget class as the type of a property, or to
434emit a gadget as a signal argument. In such cases, the gadget instance is
435passed by value between C++ and QML (because it's a value type). If QML code
436changes a property of a gadget property, the entire gadget is re-created and
437passed back to the C++ property setter. In Qt 5, gadget types cannot be
438instantiated by direct declaration in QML. In contrast, a QObject instance can
439be declared; and QObject instances are always passed by pointer from C++ to QML.
441\section1 Enumeration Types
443To use a custom enumeration as a data type, its class must be registered and
444the enumeration must also be declared with Q_ENUM() to register it with Qt's
445meta object system. For example, the \c Message class below has a \c Status
449 class Message : public QObject
452 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
460 Status status() const;
462 void statusChanged();
466Providing the \c Message class has been
467\l{qtqml-cppintegration-definetypes.html#registering-c++-types-with-the-qml-type-system}{registered} with the QML type system, its \c Status enum can be used from QML:
472 if (status == Message.Ready)
473 console.log("Message is loaded!")
478To use an enum as a \l {QFlags}{flags} type in QML, see \l Q_FLAG().
480\note The names of enum values must begin with a capital letter in order to
481be accessible from QML.
494Enum classes are registered in QML as scoped and unscoped properties.
495The \c Ready value will be registered at \c Message.Status.Ready and \c Message.Ready .
497When using enum classes, there can be multiple enums using the same identifiers.
498The unscoped registration will be overwriten by the last registered enum. For classes
499that contain such name conficts it is possible to disable the unscoped registration by
500annotating your class with a special Q_CLASSINFO macro.
501Use the name \c RegisterEnumClassesUnscoped with the value \c false to prevent scoped
502enums from being merged into the same name space.
505class Message : public QObject
508 Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
513 enum class ScopedEnum {
518 enum class OtherValue {
525Enums from related types are usually registered in the scope of the relating
526type. For example any enum from a different type used in a \l{Q_PROPERTY}
527declaration causes all enums from that type to be made available in QML. This
528is usually more of a liability than a feature. In order to prevent it from
529happening, annotate your class with a special \l{Q_CLASSINFO} macro.
530Use the name \c RegisterEnumsFromRelatedTypes with the value \c false to prevent
531enums from related types from being registered in this type.
533You should explicitly register the enclosing types of any enums you want to use
534in QML, using \l{QML_ELEMENT} or \l{QML_NAMED_ELEMENT}, rather than rely on
535their enums to be injected into other types.
538class OtherType : public QObject
544 enum SomeEnum { A, B, C };
547 enum AnotherEnum { D, E, F };
551class Message : public QObject
556 // This would usually cause all enums from OtherType to be registered
557 // as members of Message ...
558 Q_PROPERTY(OtherType::SomeEnum someEnum READ someEnum CONSTANT)
560 // ... but this way it doesn't.
561 Q_CLASSINFO("RegisterEnumsFromRelatedTypes", "false")
564 OtherType::SomeEnum someEnum() const { return OtherType::B; }
568The important difference is the scope for the enums in QML. If an enum from a
569related class is automatically registered, the scope is the type it is
570imported into. In the above case, without the extra \l{Q_CLASSINFO}, you would
571use \c {Message.A}, for example. If C++ type holding the enums is explicitly
572registered, and the registration of enums from related types is suppressed, the
573QML type for the C++ type holding the enums is the scope for all of its enums.
574You would use \c {OtherType.A} instead of \c {Message.A} in QML.
576Mind that you can use \l QML_FOREIGN to register a type you cannot modify. You
577can also use \l QML_FOREIGN_NAMESPACE to register the enumerators of a C++ type
578into a QML namespace of any upper-case name, even if the same C++ type is
579also registered as a QML value type.
581\section2 Enumeration Types as Signal and Method Parameters
583C++ signals and methods with enumeration-type parameters can be used from QML
584provided that the enumeration and the signal or method are both declared
585within the same class, or that the enumeration value is one of those declared
586in the \l {Qt}{Qt Namespace}.
588Additionally, if a C++ signal with an enum parameter should be connectable to a
589QML function using the \l{qtqml-syntax-signals.html#connecting-signals-to-methods-and-signals}
590{connect()} function, the enum type must be registered
591using qRegisterMetaType().
593For QML signals, enum values may be passed as signal parameters using the \c int
598 signal someOtherSignal(int statusValue)
600 Component.onCompleted: {
601 someOtherSignal(Message.Loading)