Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 \row
95 \li Enums declared with Q_ENUM()
96 \li \l enumeration
97\endtable
98
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}
101module is included.
102
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:
108
109\qml
110Item {
111 Image { sourceSize: "100x200" }
112 Image { sourceSize: Qt.size(100, 200) }
113}
114\endqml
115
116See documentation for each individual type under \l {QML Value Types} for more
117information.
118
119
120\section1 QObject-derived Types
121
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.
124
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.
129
130
131\section1 Conversion Between Qt and JavaScript Types
132
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.
138
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.)
143
144
145\section2 QVariantList and QVariantMap to JavaScript Array and Object
146
147The QML engine provides automatic type conversion between QVariantList and
148JavaScript arrays, and between QVariantMap and JavaScript objects.
149
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:
155
156\table
157\row
158\li QML
159\li \snippet qml/qtbinding/variantlistmap/MyItem.qml 0
160\row
161\li C++
162\li \snippet qml/qtbinding/variantlistmap/main.cpp 0
163\endtable
164
165This produces output like:
166
167\code
168Array item: 10
169Array item: #00ff00
170Array item: bottles
171Object item: language = QML
172Object item: released = Tue Sep 21 2010 00:00:00 GMT+1000 (EST)
173\endcode
174
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++.
179
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:
184
185\code
186MyListExposingItem {
187 l: [1, 2, 3]
188 Component.onCompleted: l[0] = 10
189}
190\endcode
191
192The following code does work:
193\code
194MyListExposingItem {
195 l: [1, 2, 3]
196 Component.onCompleted: l = [10, 2, 3]
197}
198\endcode
199
200\section2 QDateTime to JavaScript Date
201
202The QML engine provides automatic type conversion between QDateTime values and
203JavaScript \c Date objects.
204
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
211is received in C++:
212
213\table
214\row
215\li QML
216\li
217\qml
218// MyItem.qml
219Item {
220 function readDate(dt) {
221 console.log("The given date is:", dt.toUTCString());
222 return new Date();
223 }
224}
225\endqml
226\row
227\li C++
228\li
229\code
230// C++
231QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
232
233QDateTime dateTime = QDateTime::currentDateTime();
234QDateTime retValue;
235
236QMetaObject::invokeMethod(view.rootObject(), "readDate",
237 Q_RETURN_ARG(QVariant, retValue),
238 Q_ARG(QVariant, QVariant::fromValue(dateTime)));
239
240qDebug() << "Value returned from readDate():" << retValue;
241\endcode
242
243\endtable
244
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++.
248
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.
252
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
265section.
266
267\section2 QDate and JavaScript Date
268
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.
275
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.
281
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.
287
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.
293
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
297
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.
302
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.
306
307\section2 Sequence Type to JavaScript Array
308
309See \l{QML Sequence Types} for a general description of sequence types. The
310\l{Qt QML QML Types}{QtQml module} contains a few sequence types
311you may want to use.
312
313You can also create a list-like data structure by constructing a QJSValue using
314QJSEngine::newArray(). Such a JavaScript array does not need any conversion
315when passing it between QML and C++. See \l{QJSValue#Working With Arrays} for
316details on how to manipulate JavaScript arrays from C++.
317
318\section2 QByteArray to JavaScript ArrayBuffer
319
320The QML engine provides automatic type conversion between QByteArray values and
321JavaScript \c ArrayBuffer objects.
322
323\section2 Value Types
324
325Some value types in Qt such as QPoint are represented in JavaScript as objects
326that have the same properties and functions like in the C++ API. The same
327representation is possible with custom C++ value types. To enable a custom
328value type with the QML engine, the class declaration needs to be annotated
329with \c{Q_GADGET}. Properties that are intended to be visible in the JavaScript
330representation need to be declared with \c Q_PROPERTY. Similarly functions need
331to be marked with \c Q_INVOKABLE. This is the same with QObject based C++ APIs.
332For example, the \c Actor class below is annotated as gadget and has
333properties:
334
335\code
336 class Actor
337 {
338 Q_GADGET
339 Q_PROPERTY(QString name READ name WRITE setName)
340 public:
341 QString name() const { return m_name; }
342 void setName(const QString &name) { m_name = name; }
343
344 private:
345 QString m_name;
346 };
347
348 Q_DECLARE_METATYPE(Actor)
349\endcode
350
351The usual pattern is to use a gadget class as the type of a property, or to
352emit a gadget as a signal argument. In such cases, the gadget instance is
353passed by value between C++ and QML (because it's a value type). If QML code
354changes a property of a gadget property, the entire gadget is re-created and
355passed back to the C++ property setter. In Qt 5, gadget types cannot be
356instantiated by direct declaration in QML. In contrast, a QObject instance can
357be declared; and QObject instances are always passed by pointer from C++ to QML.
358
359\section1 Enumeration Types
360
361To use a custom enumeration as a data type, its class must be registered and
362the enumeration must also be declared with Q_ENUM() to register it with Qt's
363meta object system. For example, the \c Message class below has a \c Status
364enum:
365
366\code
367 class Message : public QObject
368 {
369 Q_OBJECT
370 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
371 public:
372 enum Status {
373 Ready,
374 Loading,
375 Error
376 };
377 Q_ENUM(Status)
378 Status status() const;
379 signals:
380 void statusChanged();
381 };
382\endcode
383
384Providing the \c Message class has been
385\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:
386
387\qml
388Message {
389 onStatusChanged: {
390 if (status == Message.Ready)
391 console.log("Message is loaded!")
392 }
393 }
394\endqml
395
396To use an enum as a \l {QFlags}{flags} type in QML, see \l Q_FLAG().
397
398\note The names of enum values must begin with a capital letter in order to
399be accessible from QML.
400
401\code
402...
403enum class Status {
404 Ready,
405 Loading,
406 Error
407}
408Q_ENUM(Status)
409...
410\endcode
411
412Enum classes are registered in QML as scoped and unscoped properties.
413The \c Ready value will be registered at \c Message.Status.Ready and \c Message.Ready .
414
415When using enum classes, there can be multiple enums using the same identifiers.
416The unscoped registration will be overwriten by the last registered enum. For classes
417that contain such name conficts it is possible to disable the unscoped registration by
418annotating your class with a special Q_CLASSINFO macro.
419Use the name \c RegisterEnumClassesUnscoped with the value \c false to prevent scoped
420enums from being merged into the same name space.
421
422\code
423class Message : public QObject
424 {
425 Q_OBJECT
426 Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
427 Q_ENUM(ScopedEnum)
428 Q_ENUM(OtherValue)
429
430 public:
431 enum class ScopedEnum {
432 Value1,
433 Value2,
434 OtherValue
435 };
436 enum class OtherValue {
437 Value1,
438 Value2
439 };
440 };
441\endcode
442
443Enums from related types are usually registered in the scope of the relating
444type. For example any enum from a different type used in a \l{Q_PROPERTY}
445declaration causes all enums from that type to be made available in QML. This
446is usually more of a liability than a feature. In order to prevent it from
447happening, annotate your class with a special \l{Q_CLASSINFO} macro.
448Use the name \c RegisterEnumsFromRelatedTypes with the value \c false to prevent
449enums from related types from being registered in this type.
450
451You should explicitly register the enclosing types of any enums you want to use
452in QML, using \l{QML_ELEMENT} or \l{QML_NAMED_ELEMENT}, rather than rely on
453their enums to be injected into other types.
454
455\code
456class OtherType : public QObject
457{
458 Q_OBJECT
459 QML_ELEMENT
460
461public:
462 enum SomeEnum { A, B, C };
463 Q_ENUM(SomeEnum)
464
465 enum AnotherEnum { D, E, F };
466 Q_ENUM(AnotherEnum)
467};
468
469class Message : public QObject
470{
471 Q_OBJECT
472 QML_ELEMENT
473
474 // This would usually cause all enums from OtherType to be registered
475 // as members of Message ...
476 Q_PROPERTY(OtherType::SomeEnum someEnum READ someEnum CONSTANT)
477
478 // ... but this way it doesn't.
479 Q_CLASSINFO("RegisterEnumsFromRelatedTypes", "false")
480
481public:
482 OtherType::SomeEnum someEnum() const { return OtherType::B; }
483};
484\endcode
485
486The important difference is the scope for the enums in QML. If an enum from a
487related class is automatically registered, the scope is the type it is
488imported into. In the above case, without the extra \l{Q_CLASSINFO}, you would
489use \c {Message.A}, for example. If C++ type holding the enums is explicitly
490registered, and the registration of enums from related types is suppressed, the
491QML type for the C++ type holding the enums is the scope for all of its enums.
492You would use \c {OtherType.A} instead of \c {Message.A} in QML.
493
494Mind that you can use \l QML_FOREIGN to register a type you cannot modify. You
495can also use \l QML_FOREIGN_NAMESPACE to register the enumerators of a C++ type
496into a QML namespace of any upper-case name, even if the same C++ type is
497also registered as a QML value type.
498
499\section2 Enumeration Types as Signal and Method Parameters
500
501C++ signals and methods with enumeration-type parameters can be used from QML
502provided that the enumeration and the signal or method are both declared
503within the same class, or that the enumeration value is one of those declared
504in the \l {Qt}{Qt Namespace}.
505
506Additionally, if a C++ signal with an enum parameter should be connectable to a
507QML function using the \l{qtqml-syntax-signals.html#connecting-signals-to-methods-and-signals}
508{connect()} function, the enum type must be registered
509using qRegisterMetaType().
510
511For QML signals, enum values may be passed as signal parameters using the \c int
512type:
513
514\qml
515 Message {
516 signal someOtherSignal(int statusValue)
517
518 Component.onCompleted: {
519 someOtherSignal(Message.Loading)
520 }
521 }
522\endqml
523
524*/