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
definetypes.qdoc
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3/*!
4\page qtqml-cppintegration-definetypes.html
5\title Defining QML Types from C++
6\brief Description of ways to define QML object types from C++ code
7
8When extending QML with C++ code, a C++ class can be registered with the QML
9type system to enable the class to be used as a data type within QML code.
10While the properties, methods and signals of any QObject-derived class are
11accessible from QML, as discussed in \l{qtqml-cppintegration-exposecppattributes.html}
12{Exposing Attributes of C++ Types to QML}, such a class cannot be used as a
13data type from QML until it is registered with the type system. Additionally
14registration can provide other features, such as allowing a class to be used
15as an instantiable \l{qtqml-typesystem-objecttypes.html}{QML object type} from
16QML, or enabling a singleton instance of the class to be imported and used
17from QML.
18
19Additionally, the \l {Qt Qml} module provides mechanisms for implementing QML-specific
20features such as \e{attached properties} and \e{default properties} in C++.
21
22(Note that a number of the important concepts covered in this document are
23demonstrated in the \l{Writing QML Extensions with C++} tutorial.)
24
25\b{NOTE:} All headers that declare QML types need to be accessible without any prefix from the project's include path.
26
27For more information about C++ and the different QML integration methods,
28see the
29\l {Overview - QML and C++ Integration} {C++ and QML integration overview} page.
30
31\section1 Registering C++ Types with the QML Type System
32
33A QObject-derived class can be registered with the QML type system to enable the
34type to be used as a data type from within QML code.
35
36The engine allows the registration of both instantiable and non-instantiable
37types. Registering an instantiable type enables a C++ class to be used as the
38definition of a QML object type, allowing it to be used in object declarations
39from QML code to create objects of this type. Registration also provides
40the engine with additional type metadata, enabling the type (and any enums
41declared by the class) to be used as a data type for property values, method
42parameters and return values, and signal parameters that are exchanged between
43QML and C++.
44
45Registering a non-instantiable type also registers the class as a data type in
46this manner, but the type cannot be used instantiated as a QML object type
47from QML. This is useful, for example, if a type has enums that should be
48exposed to QML but the type itself should not be instantiable.
49
50For a quick guide to choosing the correct approach to expose C++ types to QML,
51see \l {Choosing the Correct Integration Method Between C++ and QML}.
52
53\section2 Preconditions
54
55All the macros mentioned below are available from the \l qqmlintegration.h
56header file from the QtQmlIntegration module.
57
58You need to add the following code to the files using them in order to
59make the macros available:
60
61\code
62#include <QtQmlIntegration/qqmlintegration.h>
63\endcode
64
65If you are already linking to the QtQml module, you can instead use the \c
66qqmlregistration.h header file, which will include \l qqmlintegration.h, as
67follows:
68
69\code
70#include <QtQml/qqmlregistration.h>
71\endcode
72
73Furthermore, your class declarations have to live in headers reachable via your
74project's include path. The declarations are used to generate registration code
75at compile time, and the registration code needs to include the headers that
76contain the declarations.
77
78\section2 Registering an Instantiable Object Type
79
80\b{Any QObject-derived C++ class can be registered as the definition of a
81\l{qtqml-typesystem-objecttypes.html}{QML object type}}. Once a
82class is registered with the QML type system, the class can be declared and
83instantiated like any other object type from QML code. Once created, a
84class instance can be manipulated from QML; as
85\l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++
86Types to QML} explains, the properties, methods and signals of any
87QObject-derived class are accessible from QML code.
88
89To register a QObject-derived class as an instantiable QML object type, add
90\c QML_ELEMENT or \c QML_NAMED_ELEMENT(<name>) to the class declaration. You
91also need to make adjustments in the build system. For qmake, add
92\c {CONFIG += qmltypes}, a \c {QML_IMPORT_NAME}, and a
93\c QML_IMPORT_MAJOR_VERSION to your project file. For CMake, the file containing
94the class should be part of a target set-up with
95\l{qt_add_qml_module}{qt_add_qml_module()}.
96This will register the class into the type namespace under the given major version,
97using either the class name or an explicitly given name as QML type name. The
98minor version(s) will be derived from any revisions attached to properties,
99methods, or signals. The default minor version is \c 0. You can explicitly
100restrict the type to be available only from specific minor versions by adding
101the \c QML_ADDED_IN_VERSION() macro to the class declaration. Clients can
102import suitable versions of the namespace in order to use the type.
103
104For example, suppose there is a \c Message class with \c author and
105\c creationDate properties:
106
107\code
108class Message : public QObject
109{
110 Q_OBJECT
111 Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
112 Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
113 QML_ELEMENT
114public:
115 // ...
116};
117\endcode
118
119This type can be registered by adding an appropriate type namespace and version
120number to the project file. For example, to make the type available in the
121\c com.mycompany.messaging namespace with version 1.0:
122
123\if defined(onlinedocs)
124 \tab {build-qt-app}{tab-cmake}{CMake}{checked}
125 \tab {build-qt-app}{tab-qmake}{qmake}{}
126 \tabcontent {tab-cmake}
127\else
128 \section3 Using CMake
129\endif
130 \badcode
131 qt_add_qml_module(messaging
132 URI com.mycompany.messaging
133 VERSION 1.0
134 SOURCES
135 message.cpp message.h
136 )
137 \endcode
138\if defined(onlinedocs)
139 \endtabcontent
140 \tabcontent {tab-qmake}
141\else
142 \section3 Using QMake
143\endif
144 \badcode
145 CONFIG += qmltypes
146 QML_IMPORT_NAME = com.mycompany.messaging
147 QML_IMPORT_MAJOR_VERSION = 1
148 \endcode
149
150 If the header the class is declared in is not accessible from your project's
151 include path, you may have to amend the include path so that the generated
152 registration code can be compiled.
153
154 \badcode
155 INCLUDEPATH += com/mycompany/messaging
156 \endcode
157\if defined(onlinedocs)
158 \endtabcontent
159\endif
160
161
162
163The type can be used in an \l{qtqml-syntax-basics.html#object-declarations}
164{object declaration} from QML, and its properties can be read and written to,
165as per the example below:
166
167\qml
168import com.mycompany.messaging
169
170Message {
171 author: "Amelie"
172 creationDate: new Date()
173}
174\endqml
175
176\section2 Registering Value Types
177
178Any type with a \l{Q_GADGET} macro can the registered as a
179\l{qtqml-typesystem-valuetypes.html}{QML value type}. Once such a type is
180registered with the QML type system it can be used as property type in QML
181code. Such an instance can be manipulated from QML; as
182\l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++
183Types to QML} explains, the properties and methods of any value type are
184accessible from QML code.
185
186In contrast to object types, value types require \b{lower case} names. The
187preferred way to register them is using the \l{QML_VALUE_TYPE} or
188\l{QML_ANONYMOUS} macros. There is no equivalent to \l{QML_ELEMENT} as your
189C++ classes are typically going to have upper case names. Otherwise the
190registration is very similar to the registration of object types.
191
192For example, suppose you want to register a value type \c{person} that consists
193of two strings for first and last name:
194
195\code
196class Person
197{
198 Q_GADGET
199 Q_PROPERTY(QString firstName READ firstName WRITE setFirstName)
200 Q_PROPERTY(QString lastName READ lastName WRITE setLastName)
201 QML_VALUE_TYPE(person)
202public:
203 // ...
204};
205\endcode
206
207There are some further limitations on what you can do with value types:
208\list
209\li Value types cannot be singletons.
210\li Value types need to be default-constructible and copy-constructible.
211\li Using QProperty as a member of a value type is problematic. Value types get
212 copied, and you would need to decide what to do with any bindings on the
213 QProperty at that point. You should not use QProperty in value types.
214\li Value types cannot provide attached properties.
215\li The API to define extensions to value types (\l{QML_EXTENDED}) is not public
216 and subject to future changes.
217\endlist
218
219\section2 Value Types with Enumerations
220
221Exposing enumerations from a value type to QML requires some extra steps.
222
223Value types have lower case names in QML and types with lower case
224names are generally not addressable in JavaScript code (unless you specify
225\l{ValueTypeBehavior}{pragma ValueTypeBehavior: Addressable}). If you have
226a value type in C++ with an enumeration you want to expose to QML, you
227need to expose the enumeration separately.
228
229This can be solved by using \l{QML_FOREIGN_NAMESPACE}. First, derive from
230your value type to create a separate C++ type:
231
232\code
233class Person
234{
235 Q_GADGET
236 Q_PROPERTY(QString firstName READ firstName WRITE setFirstName)
237 Q_PROPERTY(QString lastName READ lastName WRITE setLastName)
238 QML_VALUE_TYPE(person)
239public:
240 enum TheEnum { A, B, C };
241 Q_ENUM(TheEnum)
242 //...
243};
244
245class PersonDerived: public Person
246{
247 Q_GADGET
248};
249\endcode
250
251Then expose the derived type as a foreign namespace:
252
253\code
254namespace PersonDerivedForeign
255{
256 Q_NAMESPACE
257 QML_NAMED_ELEMENT(Person)
258 QML_FOREIGN_NAMESPACE(PersonDerived)
259}
260\endcode
261
262This produces a \l{qtqml-typesystem-namespaces.html}{QML Namespace}
263called \c Person (upper case) with an enumeration called \c TheEnum and
264values \c{A}, \c{B}, and \c{C}. Then you can write the following in QML:
265
266\qml
267 someProperty: Person.A
268\endqml
269
270At the same time you can still use your value type called \c person
271(lower case) exactly as before.
272
273\section2 Registering Non-Instantiable Types
274
275Sometimes a QObject-derived class may need to be registered with the QML type
276system but not as an instantiable type. For example, this is the case if a C++
277class:
278
279\list
280\li is an interface type that should not be instantiable
281\li is a base class type that does not need to be exposed to QML
282\li declares some enum that should be accessible from QML, but otherwise should
283not be instantiable
284\li is a type that should be provided to QML through a singleton instance, and
285should not be instantiable from QML
286\endlist
287
288The \l {Qt Qml} module provides several macros for registering non-instantiable
289types:
290
291\list
292\li QML_ANONYMOUS registers a C++ type that is not instantiable and cannot be
293referred to from QML. This enables the engine to coerce any inherited types that
294are instantiable from QML.
295\li QML_INTERFACE registers an existing Qt interface type. The type is
296not instantiable from QML, and you cannot declare QML properties with it. Using
297C++ properties of this type from QML will do the expected interface casts,
298though.
299\li QML_UNCREATABLE(reason) combined with with QML_ELEMENT or QML_NAMED_ELEMENT
300registers a named C++ type that is not instantiable but should be identifiable
301as a type to the QML type system. This is useful if a type's enums or attached
302properties should be accessible from QML but the type itself should not be
303instantiable. The parameter should be an error message to be emitted if an
304attempt at creating an instance of the type is detected.
305\li QML_SINGLETON combined with QML_ELEMENT or QML_NAMED_ELEMENT registers a
306singleton type that can be imported from QML, as discussed below.
307\endlist
308
309Note that all C++ types registered with the QML type system must be
310QObject-derived, even if they are non-instantiable.
311
312
313\section3 Registering Singleton Objects with a Singleton Type
314
315A singleton type enables properties, signals and methods to be exposed in
316a namespace without requiring the client to manually instantiate an
317object instance. QObject singleton types in particular are an efficient and
318convenient way to provide functionality or global property values.
319
320Note that singleton types do not have an associated QQmlContext as they are
321shared across all contexts in an engine. QObject singleton type instances
322are constructed and owned by the QQmlEngine, and will be destroyed when
323the engine is destroyed.
324
325A QObject singleton type can be interacted with in a manner similar to any
326other QObject or instantiated type, except that only one (engine constructed
327and owned) instance will exist, and it must be referenced by type name rather
328than id. Q_PROPERTYs of QObject singleton types may be bound to, and Q_INVOKABLE
329functions of QObject module APIs may be used in signal handler expressions.
330This makes singleton types an ideal way to implement styling or theming, and
331they can also be used instead of ".pragma library" script imports to store global
332state or to provide global functionality.
333
334Once registered, a QObject singleton type may be imported and used like any
335other QObject instance exposed to QML. The following example assumes that
336a QObject singleton type was registered into the "MyThemeModule" namespace
337with version 1.0, where that QObject has a QColor "color" Q_PROPERTY:
338
339\qml
340import MyThemeModule 1.0 as Theme
341
342Rectangle {
343 color: Theme.color // binding.
344}
345\endqml
346
347A QJSValue may also be exposed as a singleton type, however clients should
348be aware that properties of such a singleton type cannot be bound to.
349
350See \l{QML_SINGLETON} for more information on how implement and
351register a new singleton type, and how to use an existing singleton type.
352See \l{Singletons in QML} for more in-depth information about singletons.
353
354\note Enum values for registered types in QML should start with a capital.
355
356\section2 Final properties
357
358Properties declared final using the \c FINAL modifier to \l Q_PROPERTY cannot
359be overridden. This means that any properties or functions of the same name,
360declared either in QML or in C++ on derived types, are ignored by the QML
361engine. You should declare properties \c FINAL when possible, in order to avoid
362accidental overrides. An override of a property is visible not only in
363derived classes, but also to QML code executing the context of the base class.
364Such QML code, typically expects the original property, though. This is a
365frequent source of mistakes.
366
367Properties declared \c FINAL can also not be overridden by functions in QML, or
368by \l Q_INVOKABLE methods in C++.
369
370\section2 Type Revisions and Versions
371
372Many of the type registration functions require versions to be specified
373for the registered type. Type revisions and versions allow new properties
374or methods to exist in the new version while remaining compatible with
375previous versions.
376
377Consider these two QML files:
378\code
379// main.qml
380import QtQuick 1.0
381
382Item {
383 id: root
384 MyType {}
385}
386\endcode
387
388\code
389// MyType.qml
390import MyTypes 1.0
391
392CppType {
393 value: root.x
394}
395\endcode
396
397where \c CppType maps to the C++ class \c CppType.
398
399If the author of CppType adds a \c root property to CppType in a new
400version of their type definition, \c root.x now resolves to a different value
401because \c root is also the \c id of the top level component. The author could
402specify that the new \c root property is available from a specific minor
403version. This permits new properties and features to be added to existing
404types without breaking existing programs.
405
406The REVISION tag is used to mark the \c root property as added in revision 1
407of the type. Methods such as Q_INVOKABLE's, signals and slots can also be
408tagged for a revision using the \l Q_REVISION macro:
409
410\code
411class CppType : public BaseType
412{
413 Q_OBJECT
414 Q_PROPERTY(int root READ root WRITE setRoot NOTIFY rootChanged REVISION(1, 0))
415 QML_ELEMENT
416
417signals:
418 Q_REVISION(1, 0) void rootChanged();
419};
420\endcode
421
422The revisions given this way are automatically interpreted as minor versions to
423the major version given in the project file. In this case, \c root is only
424available when \c MyTypes version 1.1 or higher is imported. Imports of
425\c MyTypes version 1.0 remain unaffected.
426
427For the same reason, new types introduced in later versions should be tagged
428with the QML_ADDED_IN_VERSION macro.
429
430This feature of the language allows for behavioural changes to be made
431without breaking existing applications. Consequently QML module authors
432should always remember to document what changed between minor versions, and
433QML module users should check that their application still runs correctly
434before deploying an updated import statement.
435
436Revisions of a base class that your type depends upon are automatically
437registered when registering the type itself. This is useful when deriving
438from base classes provided by other authors, e.g. when extending classes from
439the Qt Quick module.
440
441\note The QML engine does not support revisions for properties or signals of
442grouped and attached property objects.
443
444\section2 Registering Extension Objects
445
446When integrating existing classes and technology into QML, APIs will
447often need tweaking to fit better into the declarative environment.
448Although the best results are usually obtained by modifying the original
449classes directly, if this is either not possible or is complicated by some
450other concerns, extension objects allow limited extension possibilities
451without direct modifications.
452
453\e{Extension objects} add additional properties to an existing type. An extended
454type definition allows the programmer to supply an additional type, known as the
455\e{extension type}, when registering the class. Its members are transparently
456merged with the original target class when used from within QML. For example:
457
458\qml
459QLineEdit {
460 leftMargin: 20
461}
462\endqml
463
464The \c leftMargin property is a new property added to an existing C++ type, \l
465QLineEdit, without modifying its source code.
466
467The QML_EXTENDED(extension) macro is for registering extended types. The
468argument is the name of another class to be used as extension.
469
470You can also use QML_EXTENDED_NAMESPACE(namespace) to register a namespace, and
471especially the enumerations declared within, as an extension to a type. If the
472type you are extending is itself a namespace, you need to use
473QML_NAMESPACE_EXTENDED(namespace) instead.
474
475An extension class is a regular QObject, with a constructor that takes a QObject
476pointer. However, the extension class creation is delayed until the first
477extended property is accessed. The extension class is created and the target
478object is passed in as the parent. When the property on the original is
479accessed, the corresponding property on the extension object is used instead.
480
481\section2 Registering Foreign Types
482
483There may be C++ types that cannot be modified to hold the above mentioned
484macros. Those may be types from 3rdparty libraries, or types that need to
485fulfill some contract that contradicts the presence of those macros. You can
486still expose those types to QML, though, using the QML_FOREIGN macro. In order
487to do this, create a separate struct that consists entirely of the registration
488macros, like this:
489
490\code
491// Contains class Immutable3rdParty
492#include <3rdpartyheader.h>
493
494struct Foreign
495{
496 Q_GADGET
497 QML_FOREIGN(Immutable3rdParty)
498 QML_NAMED_ELEMENT(Accessible3rdParty)
499 QML_ADDED_IN_VERSION(2, 4)
500 // QML_EXTENDED, QML_SINGLETON ...
501};
502\endcode
503
504From this code, you get a QML type with the methods and properties of
505Immutable3rdParty, and the QML traits (e.g.: singleton, extended) specified in
506Foreign.
507
508\section1 Defining QML-Specific Types and Attributes
509
510\section2 Providing Attached Properties
511\keyword Integrating QML and C++ - Attached Properties
512
513In the QML language syntax, there is a notion of \l{Attached properties and
514attached signal handlers}{\e {attached properties} and \e {attached signal
515handlers}}, which are additional attributes that are attached to an object.
516Essentially, such attributes are implemented and provided by an \e {attaching
517type}, and these attributes may be \e attached to an object of another type.
518This contrasts with ordinary object properties which are provided by the object
519type itself (or the object's inherited type).
520
521For example, the \l Item below uses attached properties and attached handlers:
522
523\qml
524import QtQuick 2.0
525
526Item {
527 width: 100; height: 100
528
529 focus: true
530 Keys.enabled: false
531 Keys.onReturnPressed: console.log("Return key was pressed")
532}
533\endqml
534
535Here, the \l Item object is able to access and set the values of \c Keys.enabled
536and \c Keys.onReturnPressed. This allows the \l Item object to access these
537extra attributes as an extension to its own existing attributes.
538
539\section3 Steps for Implementing Attached Objects
540
541When considering the above example, there are several parties involved:
542
543\list
544\li There is an instance of an anonymous \e {attached object type}, with
545an \c enabled property and a \c returnPressed signal, that has been attached to
546the \l Item object to enable it to access and set these attributes.
547\li The \l Item object is the \e {attachee}, to which the instance of the \e
548{attached object type} has been attached.
549\li \l Keys is the \e {attaching type}, which provides the \e {attachee} with a
550named qualifier, "Keys", through which it may access the attributes of the
551\e {attached object type}.
552\endlist
553
554When the QML engine processes this code, it creates a single instance of the
555\e {attached object type} and attaches this instance to the \l Item object,
556thereby providing it with access to the \c enabled and \c returnPressed
557attributes of the instance.
558
559The mechanisms for providing attached objects can be implemented from C++ by
560providing classes for the \e {attached object type} and \e {attaching type}.
561For the \e{attached object type}, provide a QObject-derived class that defines
562the attributes to be made accessible to \e attachee objects. For the
563\e {attaching type}, provide a QObject-derived class that:
564
565\list
566\li implements a static qmlAttachedProperties() with the following signature:
567 \code
568 static <AttachedPropertiesType> *qmlAttachedProperties(QObject *object);
569 \endcode
570
571 This method should return an instance of the \e{attached object type}.
572
573 The QML engine invokes this method in order to attach an instance of
574 the attached object type to the \e attachee specified by the \c object
575 parameter. It is customary, though not strictly required, for this method
576 implementation to parent the returned instance to \c object in order
577 to prevent memory leaks.
578
579 This method is called at most once by the engine for each attachee object
580 instance, as the engine caches the returned instance pointer for subsequent
581 attached property accesses. Consequently the attachment object may not be
582 deleted until the attachee \c object is destroyed.
583
584\li is declared as an attaching type, by adding the QML_ATTACHED(attached) macro
585 to the class declaration. The argument is the name of the
586 \e{attached object type}
587\endlist
588
589
590\section3 Implementing Attached Objects: An Example
591
592For example, take the \c Message type described in an \l{Registering an
593Instantiable Object Type}{earlier example}:
594
595\code
596class Message : public QObject
597{
598 Q_OBJECT
599 Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
600 Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
601 QML_ELEMENT
602public:
603 // ...
604};
605\endcode
606
607Suppose it is necessary to trigger a signal on a \c Message when it is
608published to a message board, and also track when the message has expired on
609the message board. Since it doesn't make sense to add these attributes
610directly to a \c Message, as the attributes are more relevant to the message
611board context, they could be implemented as \e attached attributes on a
612\c Message object that are provided through a "MessageBoard" qualifier. In
613terms of the concepts described earlier, the parties involved here are:
614
615\list
616\li An instance of an anonymous \e{attached object type}, which provides a
617 \c published signal and an \c expired property. This type is implemented by
618 \c MessageBoardAttachedType below
619\li A \c Message object, which will be the \e attachee
620\li The \c MessageBoard type, which will be the \e {attaching type} that is
621 used by \c Message objects to access the attached attributes
622\endlist
623
624Following is an example implementation. First, there needs to be an
625\e {attached object type} with the necessary properties and signals that
626will be accessible to the \e attachee:
627
628\code
629class MessageBoardAttachedType : public QObject
630{
631 Q_OBJECT
632 Q_PROPERTY(bool expired READ expired WRITE setExpired NOTIFY expiredChanged)
633 QML_ANONYMOUS
634public:
635 MessageBoardAttachedType(QObject *parent);
636 bool expired() const;
637 void setExpired(bool expired);
638signals:
639 void published();
640 void expiredChanged();
641};
642\endcode
643
644Then the \e {attaching type}, \c MessageBoard, must declare a \c
645qmlAttachedProperties() method that returns an instance of the
646\e {attached object type} as implemented by MessageBoardAttachedType.
647Additionally, \c MessageBoard must be declared as an attaching type
648via the QML_ATTACHED() macro:
649
650\code
651class MessageBoard : public QObject
652{
653 Q_OBJECT
654 QML_ATTACHED(MessageBoardAttachedType)
655 QML_ELEMENT
656public:
657 static MessageBoardAttachedType *qmlAttachedProperties(QObject *object)
658 {
659 return new MessageBoardAttachedType(object);
660 }
661};
662\endcode
663
664Now, a \c Message type can access the properties and signals of the attached
665object type:
666
667\qml
668Message {
669 author: "Amelie"
670 creationDate: new Date()
671
672 MessageBoard.expired: creationDate < new Date("January 01, 2015 10:45:00")
673 MessageBoard.onPublished: console.log("Message by", author, "has been
674published!")
675}
676\endqml
677
678Additionally, the C++ implementation may access the attached object instance
679that has been attached to any object by calling the
680qmlAttachedPropertiesObject() function.
681
682For example:
683
684\code
685Message *msg = someMessageInstance();
686MessageBoardAttachedType *attached =
687 qobject_cast<MessageBoardAttachedType*>(qmlAttachedPropertiesObject<MessageBoard>(msg));
688
689qDebug() << "Value of MessageBoard.expired:" << attached->expired();
690\endcode
691
692
693\section3 Propagating Attached Properties
694
695\l QQuickAttachedPropertyPropagator can be subclassed to propagate attached properties
696from a parent object to its children, similar to \l {Control::}{font} and
697\l {Item::}{palette} propagation. It supports propagation through
698\l {Item}{items}, \l {Popup}{popups}, and \l {Window}{windows}.
699
700
701\section2 Property Modifier Types
702
703A property modifier type is a special kind of QML object type. A property
704modifier type instance affects a property (of a QML object instance) which it
705is applied to. There are two different kinds of property modifier types:
706\list
707\li property value write interceptors
708\li property value sources
709\endlist
710
711A property value write interceptor can be used to filter or modify values as
712they are written to properties. Currently, the only supported property
713value write interceptor is the \l Behavior type provided by the \c QtQuick
714import.
715
716A property value source can be used to automatically update the value of a
717property over time. Clients can define their own property value source types.
718The various \l{qtquick-statesanimations-animations.html}{property animation}
719types provided by the \c QtQuick import are examples of property value
720sources.
721
722Property modifier type instances can be created and applied to a property of
723a QML object through the "<ModifierType> on <propertyName>" syntax, as the
724following example shows:
725
726\qml
727import QtQuick 2.0
728
729Item {
730 width: 400
731 height: 50
732
733 Rectangle {
734 width: 50
735 height: 50
736 color: "red"
737
738 NumberAnimation on x {
739 from: 0
740 to: 350
741 loops: Animation.Infinite
742 duration: 2000
743 }
744 }
745}
746\endqml
747
748This is commonly referred to as "on" syntax.
749
750Clients can register their own property value source types, but currently not
751property value write interceptors.
752
753\section3 Property Value Sources
754
755\e {Property value sources} are QML types that can automatically update the
756value of a property over time, using the
757\c {<PropertyValueSource> on <property>} syntax. For example, the various
758\l{qtquick-statesanimations-animations.html}{property animation} types
759provided by the \c QtQuick module are examples of property value sources.
760
761A property value source can be implemented in C++ by subclassing
762QQmlPropertyValueSource and providing an implementation that writes different
763values to a property over time. When the property value source is applied to a
764property using the \c {<PropertyValueSource> on <property>} syntax in QML, it
765is given a reference to this property by the engine so that the property value
766can be updated.
767
768For example, suppose there is a \c RandomNumberGenerator class to be made
769available as a property value source, so that when applied to a QML property,
770it will update the property value to a different random number every 500
771milliseconds. Additionally, a maxValue can be provided to this random number
772generator. This class can be implemented as follows:
773
774\code
775class RandomNumberGenerator : public QObject, public QQmlPropertyValueSource
776{
777 Q_OBJECT
778 Q_INTERFACES(QQmlPropertyValueSource)
779 Q_PROPERTY(int maxValue READ maxValue WRITE setMaxValue NOTIFY maxValueChanged);
780 QML_ELEMENT
781public:
782 RandomNumberGenerator(QObject *parent)
783 : QObject(parent), m_maxValue(100)
784 {
785 QObject::connect(&m_timer, SIGNAL(timeout()), SLOT(updateProperty()));
786 m_timer.start(500);
787 }
788
789 int maxValue() const;
790 void setMaxValue(int maxValue);
791
792 virtual void setTarget(const QQmlProperty &prop) { m_targetProperty = prop; }
793
794signals:
795 void maxValueChanged();
796
797private slots:
798 void updateProperty() {
799 m_targetProperty.write(QRandomGenerator::global()->bounded(m_maxValue));
800 }
801
802private:
803 QQmlProperty m_targetProperty;
804 QTimer m_timer;
805 int m_maxValue;
806};
807\endcode
808
809When the QML engine encounters a use of \c RandomNumberGenerator as a property
810value source, it invokes \c RandomNumberGenerator::setTarget() to provide the
811type with the property to which the value source has been applied. When the
812internal timer in \c RandomNumberGenerator triggers every 500 milliseconds,
813it will write a new number value to that specified property.
814
815Once the \c RandomNumberGenerator class has been registered with the QML type
816system, it can be used from QML as a property value source. Below, it is used
817to change the width of a \l Rectangle every 500 milliseconds:
818
819\qml
820import QtQuick 2.0
821
822Item {
823 width: 300; height: 300
824
825 Rectangle {
826 RandomNumberGenerator on width { maxValue: 300 }
827
828 height: 100
829 color: "red"
830 }
831}
832\endqml
833
834In all other respects, property value sources are regular QML types that can
835have properties, signals methods and so on, but with the added capability that
836they can be used to change property values using the
837\c {<PropertyValueSource> on <property>} syntax.
838
839When a property value source object is assigned to a property, QML first tries
840to assign it normally, as though it were a regular QML type. Only if this
841assignment fails does the engine call the \l
842{QQmlPropertyValueSource::}{setTarget()} method. This allows
843the type to also be used in contexts other than just as a value source.
844
845
846\section2 Specifying Default and Parent Properties for QML Object Types
847
848Any QObject-derived type that is registered as an instantiable QML object type
849can optionally specify a \e {default property} for the type. A default
850property is the property to which an object's children are automatically
851assigned if they are not assigned to any specific property.
852
853The default property can be set by calling the Q_CLASSINFO() macro for a class
854with a specific "DefaultProperty" value. For example, the \c MessageBoard
855class below specifies its \c messages property as the default property for the
856class:
857
858\code
859class MessageBoard : public QObject
860{
861 Q_OBJECT
862 Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
863 Q_CLASSINFO("DefaultProperty", "messages")
864 QML_ELEMENT
865public:
866 QQmlListProperty<Message> messages();
867
868private:
869 QList<Message *> m_messages;
870};
871\endcode
872
873This enables children of a \c MessageBoard object to be automatically assigned
874to its \c messages property if they are not assigned to a specific property. For
875example:
876
877\qml
878MessageBoard {
879 Message { author: "Naomi" }
880 Message { author: "Clancy" }
881}
882\endqml
883
884If \c messages was not set as the default property, then any \c Message objects
885would have to be explicitly assigned to the \c messages property instead, as
886follows:
887
888\qml
889MessageBoard {
890 messages: [
891 Message { author: "Naomi" },
892 Message { author: "Clancy" }
893 ]
894}
895\endqml
896
897(Incidentally, the \l Item::data property is its default property. Any \l Item
898objects added to this \c data property are also added to the list of
899\l Item::children, so the use of the default property enables visual children
900to be declared for an item without explicitly assigning them to the
901\l{Item::}{children} property.)
902
903Additionally, you can declare a "ParentProperty" Q_CLASSINFO() to inform the QML
904engine which property should denote the parent object in the QML hierarchy. For
905example, the Message type might be declared as follows:
906
907\code
908class Message : public QObject
909{
910 Q_OBJECT
911 Q_PROPERTY(QObject* board READ board BINDABLE boardBindable)
912 Q_PROPERTY(QString author READ author BINDABLE authorBindable)
913 Q_CLASSINFO("ParentProperty", "board")
914 QML_ELEMENT
915
916public:
917 Message(QObject *parent = nullptr) : QObject(parent) { m_board = parent; }
918
919 QObject *board() const { return m_board.value(); }
920 QBindable<QObject *> boardBindable() { return QBindable<QObject *>(&m_board); }
921
922 QString author() const { return m_author.value(); }
923 QBindable<QString> authorBindable() { return QBindable<QString>(&m_author); }
924
925private:
926 QProperty<QObject *> m_board;
927 QProperty<QString> m_author;
928};
929\endcode
930
931Defining the parent property affords \l{qmllint} and other tools better insight
932into the intention of your code and avoids false positive warnings on some
933property accesses.
934
935\section2 Defining Visual Items with the Qt Quick Module
936
937When building user interfaces with the \l {Qt Quick} module, all QML objects that are
938to be visually rendered must derive from the \l Item type, as it is the base
939type for all visual objects in \l {Qt Quick}. This \l Item type is
940implemented by the QQuickItem C++ class, which is provided by the
941\l {Qt Quick} module. Therefore, this class should be subclassed when it is
942necessary to implement a visual type in C++ that can be integrated into a
943QML-based user interface.
944
945See the QQuickItem documentation for more information. Additionally, the
946\l{Writing QML Extensions with C++} tutorial demonstrates how a QQuickItem-based
947visual item can be implemented in C++ and integrated into a Qt Quick-based user
948interface.
949
950
951\section1 Receiving Notifications for Object Initialization
952
953For some custom QML object types, it may be beneficial to delay the
954initialization of particular data until the object has been created and all of
955its properties have been set. For example, this may be the case if the
956initialization is costly, or if the initialization should not be performed until
957all property values have been initialized.
958
959The \l {Qt Qml} module provides the QQmlParserStatus to be subclassed for these
960purposes. It defines a number of virtual methods that are invoked at
961various stages during component instantiation. To receive these notifications, a
962C++ class should inherit QQmlParserStatus and also notify the Qt meta system
963using the Q_INTERFACES() macro.
964
965For example:
966
967\code
968class MyQmlType : public QObject, public QQmlParserStatus
969{
970 Q_OBJECT
971 Q_INTERFACES(QQmlParserStatus)
972 QML_ELEMENT
973public:
974 virtual void componentComplete()
975 {
976 // Perform some initialization here now that the object is fully created
977 }
978};
979\endcode
980
981*/