Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
data.qdoc
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3/*!
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++
7
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
11the engine.
12
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.
16
17For more information about C++ and the different QML integration methods,
18see the
19\l {Overview - QML and C++ Integration} {C++ and QML integration overview} page.
20
21This page discusses the data types supported by the QML engine and how
22they are converted between QML and C++.
23
24
25\section1 Data Ownership
26
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.
33
34Additionally, the QML engine respects the normal QObject parent ownership
35semantics of Qt C++ objects, and will never delete a QObject instance which
36has a parent.
37
38
39\section1 Basic Qt Data Types
40
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:
44
45\table
46 \row
47 \li Qt Type
48 \li QML Value Type
49 \row
50 \li bool
51 \li \l bool
52 \row
53 \li unsigned int, int
54 \li \l int
55 \row
56 \li double
57 \li \l double
58 \row
59 \li float, qreal
60 \li \l real
61 \row
62 \li QString
63 \li \l string
64 \row
65 \li QUrl
66 \li \l url
67 \row
68 \li QColor
69 \li \l color
70 \row
71 \li QFont
72 \li \l font
73 \row
74 \li QDateTime
75 \li \l date
76 \row
77 \li QPoint, QPointF
78 \li \l point
79 \row
80 \li QSize, QSizeF
81 \li \l size
82 \row
83 \li QRect, QRectF
84 \li \l rect
85 \row
86 \li QMatrix4x4
87 \li \l matrix4x4
88 \row
89 \li QQuaternion
90 \li \l quaternion
91 \row
92 \li QVector2D, QVector3D, QVector4D
93 \li \l vector2d, \l vector3d, \l vector4d
94\endtable
95
96\note Classes provided by the \l {Qt GUI} module, such as QColor, QFont,
97QQuaternion and QMatrix4x4, are only available from QML when the \l {Qt Quick}
98module is included.
99
100As a convenience, many of these types can be specified in QML by string values,
101or by a related method provided by the \l {QtQml::Qt} object. For example, the \l
102{Image::sourceSize} property is of type \l size (which automatically translates
103to the QSize type) and can be specified by a string value formatted as
104"width\c{x}height", or by the Qt.size() function:
105
106\qml
107Item {
108 Image { sourceSize: "100x200" }
109 Image { sourceSize: Qt.size(100, 200) }
110}
111\endqml
112
113See documentation for each individual type under \l {QML Value Types} for more
114information.
115
116
117\section1 QObject-derived Types
118
119Any QObject-derived class may be used as a type for the exchange of data between
120QML and C++, providing the class has been registered with the QML type system.
121
122The engine allows the registration of both instantiable and non-instantiable
123types. Once a class is registered as a QML type, it can be used as a data type
124for exchanging data between QML and C++. See
125\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.
126
127
128\section1 Conversion Between Qt and JavaScript Types
129
130The QML engine has built-in support for converting a number of Qt types to
131related JavaScript types, and vice-versa, when transferring data between QML
132and C++. This makes it possible to use these types and receive them in C++ or
133JavaScript without needing to implement custom types that provide access to
134the data values and their attributes.
135
136(Note that the JavaScript environment in QML modifies native JavaScript object
137prototypes, including those of \c String, \c Date and \c Number, to provide
138additional features. See the \l {qtqml-javascript-hostenvironment.html}
139{JavaScript Host Environment} for further details.)
140
141
142\section2 QVariantList and QVariantMap to JavaScript Array-like and Object
143
144The QML engine provides automatic type conversion between QVariantList and
145JavaScript array-likes, and between QVariantMap and JavaScript objects.
146
147An \e{array-like}, in ECMAScript terms, is an object used like an array. The
148array-likes produced by conversion from QVariantList (and other C++ sequential
149containers) are not only that but also offer the common array methods
150and automatically synchronize the \e length property. They can be used just
151like JavaScript Arrays for any practical purposes. The \e{Array.isArray()}
152method still returns false for them, though.
153
154For example, the function defined in QML below expects two arguments, an
155array and an object, and prints their contents using the standard JavaScript
156syntax for array and object item access. The C++ code below calls this
157function, passing a QVariantList and a QVariantMap, which are automatically
158converted to JavaScript array-like and object values, respectively:
159
160\table
161\row
162\li QML
163\li \snippet qml/qtbinding/variantlistmap/MyItem.qml 0
164\row
165\li C++
166\li \snippet qml/qtbinding/variantlistmap/main.cpp 0
167\endtable
168
169This produces output like:
170
171\code
172Array item: 10
173Array item: #00ff00
174Array item: bottles
175Object item: language = QML
176Object item: released = Tue Sep 21 2010 00:00:00 GMT+1000 (EST)
177\endcode
178
179Similarly, if a C++ type uses a QVariantList or QVariantMap type for a property
180type or method parameter, the value can be created as a JavaScript array or
181object in QML, and is automatically converted to a QVariantList or QVariantMap
182when it is passed to C++.
183
184Since Qt 6.5, QVariantList properties of C++ types can be changed in place by
185QML code. Since Qt 6.9, QVariantMap properties of C++ types can be changed in
186place by QML code.
187
188\section2 QDateTime to JavaScript Date
189
190The QML engine provides automatic type conversion between QDateTime values and
191JavaScript \c Date objects.
192
193For example, the function defined in QML below expects a JavaScript
194\c Date object, and also returns a new \c Date object with the current date and
195time. The C++ code below calls this function, passing a QDateTime value
196that is automatically converted by the engine into a \c Date object when it is
197passed to the \c readDate() function. In turn, the readDate() function returns
198a \c Date object that is automatically converted into a QDateTime value when it
199is received in C++:
200
201\table
202\row
203\li QML
204\li
205\qml
206// MyItem.qml
207Item {
208 function readDate(dt) {
209 console.log("The given date is:", dt.toUTCString());
210 return new Date();
211 }
212}
213\endqml
214\row
215\li C++
216\li
217\code
218// C++
219QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
220
221QDateTime dateTime = QDateTime::currentDateTime();
222QDateTime retValue;
223
224QMetaObject::invokeMethod(view.rootObject(), "readDate",
225 Q_RETURN_ARG(QVariant, retValue),
226 Q_ARG(QVariant, QVariant::fromValue(dateTime)));
227
228qDebug() << "Value returned from readDate():" << retValue;
229\endcode
230
231\endtable
232
233Similarly, if a C++ type uses a QDateTime for a property type or method
234parameter, the value can be created as a JavaScript \c Date object in QML, and
235is automatically converted to a QDateTime value when it is passed to C++.
236
237\note Watch out for the difference in month numbering: JavaScript numbers
238January as 0 through 11 for December, off by one from Qt's numbering
239of January as 1 through 12 for December.
240
241\note When using a string in JavaScript as the value of a \c Date object,
242note that a string with no time fields (so a simple date) is
243interpreted as the UTC start of the relevant day, in contrast
244to \c{new Date(y, m, d)} which uses the local time start of the day.
245Most other ways of constructing a \c Date object in JavaScript produce
246a local time, unless methods with UTC in their names are used. If your
247program is run in a zone behind UTC (nominally west of The Prime
248Meridian), use of a date-only string will lead to a \c Date object
249whose \c getDate() is one less than the day-number in your string; it
250will typically have a large value for \c getHours(). The UTC variants
251of these methods, \c getUTCDate() and \c getUTCHours(), will give the
252results you expect for such a \c Date objects. See also the next
253section.
254
255\section2 QDate and JavaScript Date
256
257The QML engine converts automatically between \l QDate and the
258JavaScript \c Date type by representing the date by the UTC start of
259its day. A date is mapped back to QDate via QDateTime, selecting
260its \l {QDateTime::}{date()} method, using the local time form of the
261date unless the UTC form of it coincides with the start of the next
262day, in which case the UTC form is used.
263
264This slighly eccentric arrangement is a work-around for the fact that
265JavaScript's construction of a \c Date object from a date-only string
266uses the UTC start of the day, but \c{new Date(y, m, d)} uses the
267local time start of the indicated date, as discussed in a note at the
268end of the previous section.
269
270As a result, where a QDate property or parameter is exposed to QML,
271care should be taken in reading its value: the \c
272Date.getUTCFullYear(), \c Date.getUTCMonth() and \c Date.getUTCDate()
273methods are more likely to deliver the results users expect than the
274corresponding methods without UTC in their names.
275
276It is thus commonly more robust to use a \l QDateTime property. This
277makes it possible to take control, on the QDateTime side, of whether
278the date (and time) is specified in terms of UTC or local time; as
279long as the JavaScript code is written to work with the same standard,
280it should be possible to avoid trouble.
281
282//! Target adds an anchor, so renaming the section won't break incoming links.
283\target QTime to JavaScript Date
284\section2 QTime and JavaScript Date
285
286The QML engine provides automatic type conversion from QTime values to
287JavaScript \c Date objects. As QTime values do not contain a date component,
288one is created for the conversion only. Thus, you should not rely on the date
289component of the resulting Date object.
290
291Under the hood, conversion from a JavaScript \c Date object to QTime
292is done by converting to a QDateTime object (using local time) and
293calling its \l {QDateTime::}{time()} method.
294
295\section2 Sequence Type to JavaScript Array
296
297See \l{QML Sequence Types} for a general description of sequence types. The
298\l{Qt Qml QML Types}{QtQml module} contains a few sequence types
299you may want to use.
300
301You can also create a list-like data structure by constructing a QJSValue using
302QJSEngine::newArray(). Such a JavaScript array does not need any conversion
303when passing it between QML and C++. See \l{QJSValue#Working With Arrays} for
304details on how to manipulate JavaScript arrays from C++.
305
306\section2 QByteArray to JavaScript ArrayBuffer
307
308The QML engine provides automatic type conversion between QByteArray values and
309JavaScript \c ArrayBuffer objects.
310
311\section2 Value Types
312
313Some value types in Qt such as QPoint are represented in JavaScript as objects
314that have the same properties and functions like in the C++ API. The same
315representation is possible with custom C++ value types. To enable a custom
316value type with the QML engine, the class declaration needs to be annotated
317with \c{Q_GADGET}. Properties that are intended to be visible in the JavaScript
318representation need to be declared with \c Q_PROPERTY. Similarly functions need
319to be marked with \c Q_INVOKABLE. This is the same with QObject based C++ APIs.
320For example, the \c Actor class below is annotated as gadget and has
321properties:
322
323\code
324 class Actor
325 {
326 Q_GADGET
327 Q_PROPERTY(QString name READ name WRITE setName)
328 public:
329 QString name() const { return m_name; }
330 void setName(const QString &name) { m_name = name; }
331
332 private:
333 QString m_name;
334 };
335
336 Q_DECLARE_METATYPE(Actor)
337\endcode
338
339The usual pattern is to use a gadget class as the type of a property, or to
340emit a gadget as a signal argument. In such cases, the gadget instance is
341passed by value between C++ and QML (because it's a value type). If QML code
342changes a property of a gadget property, the entire gadget is re-created and
343passed back to the C++ property setter. In Qt 5, gadget types cannot be
344instantiated by direct declaration in QML. In contrast, a QObject instance can
345be declared; and QObject instances are always passed by pointer from C++ to QML.
346
347\section1 Enumeration Types
348
349To use a custom enumeration as a data type, its class must be registered and
350the enumeration must also be declared with Q_ENUM() to register it with Qt's
351meta object system. For example, the \c Message class below has a \c Status
352enum:
353
354\code
355 class Message : public QObject
356 {
357 Q_OBJECT
358 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
359 public:
360 enum Status {
361 Ready,
362 Loading,
363 Error
364 };
365 Q_ENUM(Status)
366 Status status() const;
367 signals:
368 void statusChanged();
369 };
370\endcode
371
372Providing the \c Message class has been
373\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:
374
375\qml
376Message {
377 onStatusChanged: {
378 if (status == Message.Ready)
379 console.log("Message is loaded!")
380 }
381 }
382\endqml
383
384To use an enum as a \l {QFlags}{flags} type in QML, see \l Q_FLAG().
385
386\note The names of enum values must begin with a capital letter in order to
387be accessible from QML.
388
389\code
390...
391enum class Status {
392 Ready,
393 Loading,
394 Error
395}
396Q_ENUM(Status)
397...
398\endcode
399
400Enum classes are registered in QML as scoped and unscoped properties.
401The \c Ready value will be registered as \c Message.Status.Ready and \c Message.Ready .
402
403When using enum classes, there can be multiple enums using the same identifiers.
404The unscoped registration will be overwriten by the last registered enum. For classes
405that contain such name conficts it is possible to disable the unscoped registration by
406annotating your class with a special Q_CLASSINFO macro.
407Use the name \c RegisterEnumClassesUnscoped with the value \c false to prevent scoped
408enums from being merged into the same name space.
409
410\code
411class Message : public QObject
412 {
413 Q_OBJECT
414 Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
415 Q_ENUM(ScopedEnum)
416 Q_ENUM(OtherValue)
417
418 public:
419 enum class ScopedEnum {
420 Value1,
421 Value2,
422 OtherValue
423 };
424 enum class OtherValue {
425 Value1,
426 Value2
427 };
428 };
429\endcode
430
431Enums from related types are usually registered in the scope of the relating
432type. For example any enum from a different type used in a \l{Q_PROPERTY}
433declaration causes all enums from that type to be made available in QML. This
434is usually more of a liability than a feature. In order to prevent it from
435happening, annotate your class with a special \l{Q_CLASSINFO} macro.
436Use the name \c RegisterEnumsFromRelatedTypes with the value \c false to prevent
437enums from related types from being registered in this type.
438
439You should explicitly register the enclosing types of any enums you want to use
440in QML, using \l{QML_ELEMENT} or \l{QML_NAMED_ELEMENT}, rather than rely on
441their enums to be injected into other types.
442
443\code
444class OtherType : public QObject
445{
446 Q_OBJECT
447 QML_ELEMENT
448
449public:
450 enum SomeEnum { A, B, C };
451 Q_ENUM(SomeEnum)
452
453 enum AnotherEnum { D, E, F };
454 Q_ENUM(AnotherEnum)
455};
456
457class Message : public QObject
458{
459 Q_OBJECT
460 QML_ELEMENT
461
462 // This would usually cause all enums from OtherType to be registered
463 // as members of Message ...
464 Q_PROPERTY(OtherType::SomeEnum someEnum READ someEnum CONSTANT)
465
466 // ... but this way it doesn't.
467 Q_CLASSINFO("RegisterEnumsFromRelatedTypes", "false")
468
469public:
470 OtherType::SomeEnum someEnum() const { return OtherType::B; }
471};
472\endcode
473
474The important difference is the scope for the enums in QML. If an enum from a
475related class is automatically registered, the scope is the type it is
476imported into. In the above case, without the extra \l{Q_CLASSINFO}, you would
477use \c {Message.A}, for example. If C++ type holding the enums is explicitly
478registered, and the registration of enums from related types is suppressed, the
479QML type for the C++ type holding the enums is the scope for all of its enums.
480You would use \c {OtherType.A} instead of \c {Message.A} in QML.
481
482Mind that you can use \l QML_FOREIGN to register a type you cannot modify. You
483can also use \l QML_FOREIGN_NAMESPACE to register the enumerators of a C++ type
484into a QML namespace of any upper-case name, even if the same C++ type is
485also registered as a QML value type.
486
487\section2 Enumeration Types as Signal and Method Parameters
488
489C++ signals and methods with enumeration-type parameters can be used from QML
490provided that the enumeration and the signal or method are both declared
491within the same class, or that the enumeration value is one of those declared
492in the \l {Qt}{Qt Namespace}.
493
494Additionally, if a C++ signal with an enum parameter should be connectable to a
495QML function using the \l{qtqml-syntax-signals.html#connecting-signals-to-methods-and-signals}
496{connect()} function, the enum type must be registered
497using qRegisterMetaType().
498
499For QML signals, enum values may be passed as signal parameters using the \c int
500type:
501
502\qml
503 Message {
504 signal someOtherSignal(int statusValue)
505
506 Component.onCompleted: {
507 someOtherSignal(Message.Loading)
508 }
509 }
510\endqml
511
512*/