aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/doc/src/cppintegration/definetypes.qdoc
blob: 2fdd6edded306f6df39b6845daac3eac34750a44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page qtqml-cppintegration-definetypes.html
\title Defining QML Types from C++
\brief Description of ways to define QML object types from C++ code

When extending QML with C++ code, a C++ class can be registered with the QML
type system to enable the class to be used as a data type within QML code.
While the properties, methods and signals of any QObject-derived class are
accessible from QML, as discussed in \l{qtqml-cppintegration-exposecppattributes.html}
{Exposing Attributes of C++ Types to QML}, such a class cannot be used as a
data type from QML until it is registered with the type system. Additionally
registration can provide other features, such as allowing a class to be used
as an instantiable \l{qtqml-typesystem-objecttypes.html}{QML object type} from
QML, or enabling a singleton instance of the class to be imported and used
from QML.

Additionally, the \l {Qt QML} module provides mechanisms for implementing QML-specific
features such as \e{attached properties} and \e{default properties} in C++.

(Note that a number of the important concepts covered in this document are
demonstrated in the \l{Writing QML Extensions with C++} tutorial.)

\b{NOTE:} All headers that declare QML types need to be accessible without any prefix from the project's include path.

\section1 Registering C++ Types with the QML Type System

A QObject-derived class can be registered with the QML type system to enable the
type to be used as a data type from within QML code.

The engine allows the registration of both instantiable and non-instantiable
types. Registering an instantiable type enables a C++ class to be used as the
definition of a QML object type, allowing it to be used in object declarations
from QML code to create objects of this type. Registration also provides
the engine with additional type metadata, enabling the type (and any enums
declared by the class) to be used as a data type for property values, method
parameters and return values, and signal parameters that are exchanged between
QML and C++.

Registering a non-instantiable type also registers the class as a data type in
this manner, but the type cannot be used instantiated as a QML object type
from QML. This is useful, for example, if a type has enums that should be
exposed to QML but the type itself should not be instantiable.

For a quick guide to choosing the correct approach to expose C++ types to QML,
see \l {Choosing the Correct Integration Method Between C++ and QML}.

\section2 Registering an Instantiable Object Type

\b{Any QObject-derived C++ class can be registered as the definition of a
\l{qtqml-typesystem-objecttypes.html}{QML object type}}. Once a
class is registered with the QML type system, the class can be declared and
instantiated like any other object type from QML code. Once created, a
class instance can be manipulated from QML; as
\l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++
Types to QML} explains, the properties, methods and signals of any
QObject-derived class are accessible from QML code.

To register a QObject-derived class as an instantiable QML object type, add
\c QML_ELEMENT or \c QML_NAMED_ELEMENT(<name>) to the class declaration and
\c {CONFIG += qmltypes}, a \c {QML_IMPORT_NAME}, and a
\c QML_IMPORT_MAJOR_VERSION to your project file. This will register the class
into the type namespace under the given major version, using either the class
name or an explicitly given name as QML type name. The minor version(s) will
be derived from any revisions attached to properties, methods, or signals. The
default minor version is \c 0. You can explicitly restrict the type to be
available only from specific minor versions by adding the
\c QML_ADDED_IN_MINOR_VERSION() macro to the class declaration. Clients can
import suitable versions of the namespace in order to use the type.

For example, suppose there is a \c Message class with \c author and
\c creationDate properties:

\code
class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
    Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
    QML_ELEMENT
public:
    // ...
};
\endcode

This type can be registered by adding an appropriate type namespace and version
number to the project file. For example, to make the type available in the
\c com.mycompany.messaging namespace with version 1.0:

\code
CONFIG += qmltypes
QML_IMPORT_NAME = com.mycompany.messaging
QML_IMPORT_MAJOR_VERSION = 1
\endcode

If the header the class is declared in is not accessible from your project's
include path, you may have to amend the include path so that the generated
registration code can be compiled:

\code
INCLUDEPATH += com/mycompany/messaging
\endcode

The type can be used in an \l{qtqml-syntax-basics.html#object-declarations}
{object declaration} from QML, and its properties can be read and written to,
as per the example below:

\qml
import com.mycompany.messaging 1.0

Message {
    author: "Amelie"
    creationDate: new Date()
}
\endqml


\section2 Registering Non-Instantiable Types

Sometimes a QObject-derived class may need to be registered with the QML type
system but not as an instantiable type. For example, this is the case if a C++
class:

\list
\li is an interface type that should not be instantiable
\li is a base class type that does not need to be exposed to QML
\li declares some enum that should be accessible from QML, but otherwise should
not be instantiable
\li is a type that should be provided to QML through a singleton instance, and
should not be instantiable from QML
\endlist

The \l {Qt QML} module provides several macros for registering non-instantiable
types:

\list
\li QML_ANONYMOUS registers a C++ type that is not instantiable and cannot be
referred to from QML. This enables the engine to coerce any inherited types that
are instantiable from QML.
\li QML_INTERFACE registers an existing Qt interface type. The type is
not instantiable from QML, and you cannot declare QML properties with it. Using
C++ properties of this type from QML will do the expected interface casts,
though.
\li QML_UNCREATABLE(reason) combined with with QML_ELEMENT or QML_NAMED_ELEMENT
registers a named C++ type that is not instantiable but should be identifiable
as a type to the QML type system. This is useful if a type's enums or attached
properties should be accessible from QML but the type itself should not be
instantiable. The parameter should be an error message to be emitted if an
attempt at creating an instance of the type is detected.
\li QML_SINGLETON combined with QML_ELEMENT or QML_NAMED_ELEMENT registers a
singleton type that can be imported from QML, as discussed below.
\endlist

Note that all C++ types registered with the QML type system must be
QObject-derived, even if they are non-instantiable.


\section3 Registering Singleton Objects with a Singleton Type

A singleton type enables properties, signals and methods to be exposed in
a namespace without requiring the client to manually instantiate an
object instance. QObject singleton types in particular are an efficient and
convenient way to provide functionality or global property values.

Note that singleton types do not have an associated QQmlContext as they are
shared across all contexts in an engine.  QObject singleton type instances
are constructed and owned by the QQmlEngine, and will be destroyed when
the engine is destroyed.

A QObject singleton type can be interacted with in a manner similar to any
other QObject or instantiated type, except that only one (engine constructed
and owned) instance will exist, and it must be referenced by type name rather
than id.  Q_PROPERTYs of QObject singleton types may be bound to, and Q_INVOKABLE
functions of QObject module APIs may be used in signal handler expressions.
This makes singleton types an ideal way to implement styling or theming, and
they can also be used instead of ".pragma library" script imports to store global
state or to provide global functionality.

Once registered, a QObject singleton type may be imported and used like any
other QObject instance exposed to QML.  The following example assumes that
a QObject singleton type was registered into the "MyThemeModule" namespace
with version 1.0, where that QObject has a QColor "color" Q_PROPERTY:

\qml
import MyThemeModule 1.0 as Theme

Rectangle {
    color: Theme.color // binding.
}
\endqml

A QJSValue may also be exposed as a singleton type, however clients should
be aware that properties of such a singleton type cannot be bound to.

See \l{QML_SINGLETON} for more information on how implement and
register a new singleton type, and how to use an existing singleton type.

\note Enum values for registered types in QML should start with a capital.

\section2 Type Revisions and Versions

Many of the type registration functions require versions to be specified
for the registered type. Type revisions and versions allow new properties
or methods to exist in the new version while remaining compatible with
previous versions.

Consider these two QML files:
\code
// main.qml
import QtQuick 1.0

Item {
    id: root
    MyType {}
}
\endcode

\code
// MyType.qml
import MyTypes 1.0

CppType {
    value: root.x
}
\endcode

where \c CppType maps to the C++ class \c CppType.

If the author of CppType adds a \c root property to CppType in a new
version of their type definition, \c root.x now resolves to a different value
because \c root is also the \c id of the top level component. The author could
specify that the new \c root property is available from a specific minor
version. This permits new properties and features to be added to existing
types without breaking existing programs.

The REVISION tag is used to mark the \c root property as added in revision 1
of the type. Methods such as Q_INVOKABLE's, signals and slots can also be
tagged for a revision using the \c Q_REVISION(x) macro:

\code
class CppType : public BaseType
{
    Q_OBJECT
    Q_PROPERTY(int root READ root WRITE setRoot NOTIFY rootChanged REVISION 1)
    QML_ELEMENT

signals:
    Q_REVISION(1) void rootChanged();
};
\endcode

The revisions given this way are automatically interpreted as minor versions to
the major version given in the project file. In this case, \c root is only
available when \c MyTypes version 1.1 or higher is imported. Imports of
\c MyTypes version 1.0 remain unaffected.

For the same reason, new types introduced in later versions should be tagged
with the QML_ADDED_IN_MINOR_VERSION macro.

This feature of the language allows for behavioural changes to be made
without breaking existing applications. Consequently QML module authors
should always remember to document what changed between minor versions, and
QML module users should check that their application still runs correctly
before deploying an updated import statement.

Revisions of a base class that your type depends upon are automatically
registered when registering the type itself. This is useful when deriving
from base classes provided by other authors, e.g. when extending classes from
the Qt Quick module.

\note The QML engine does not support revisions for properties or signals of
grouped and attached property objects.

\section2 Registering Extension Objects

When integrating existing classes and technology into QML, APIs will
often need tweaking to fit better into the declarative environment.
Although the best results are usually obtained by modifying the original
classes directly, if this is either not possible or is complicated by some
other concerns, extension objects allow limited extension possibilities
without direct modifications.

\e{Extension objects} add additional properties to an existing type. Extension
objects can only add properties, not signals or methods. An extended type
definition allows the programmer to supply an additional type, known as the
\e{extension type}, when registering the class. The properties are transparently
merged with the original target class when used from within QML. For example:

\snippet referenceexamples/extended/example.qml 0

The \c leftMargin property is a new property added to an existing C++ type, \l
QLineEdit, without modifying its source code.

The QML_EXTENDED(extended) macro is for registering extended types. The
argument is the name of another class to be used as extension.

You can also use QML_EXTENDED_NAMESPACE(namespace) to register a namespace, and
especially the enumerations declared within, as an extension to a type.

An extension class is a regular QObject, with a constructor that takes a QObject
pointer. However, the extension class creation is delayed until the first
extended property is accessed. The extension class is created and the target
object is passed in as the parent. When the property on the original is
accessed, the corresponding property on the extension object is used instead.

The \l{Extending QML - Extension Objects Example}{Extension Objects Example}
demonstrates a usage of extension objects.

\section2 Registering Foreign Types

There may be C++ types that cannot be modified to hold the above mentioned
macros. Those may be types from 3rdparty libraries, or types that need to
fulfill some contract that contradicts the presence of those macros. You can
still expose those types to QML, though, using the QML_FOREIGN macro. In order
to do this, create a separate struct that consists entirely of the registration
macros, like this:

\code
// Contains class Immutable3rdParty
#include <3rdpartyheader.h>

struct Foreign
{
    Q_GADGET
    QML_FOREIGN(Immutable3rdParty)
    QML_NAMED_ELEMENT(Accessible3rdParty)
    QML_ADDED_IN_VERSION(2, 4)
    // QML_EXTENDED, QML_SINGLETON ...
};
\endcode

From this code, you get a QML type with the methods and properties of
Immutable3rdParty, and the QML traits (e.g.: singleton, extended) specified in
Foreign.

\section1 Defining QML-Specific Types and Attributes

\section2 Providing Attached Properties
\keyword Integrating QML and C++ - Attached Properties

In the QML language syntax, there is a notion of \l{Attached properties and
attached signal handlers}{\e {attached properties} and \e {attached signal
handlers}}, which are additional attributes that are attached to an object.
Essentially, such attributes are implemented and provided by an \e {attaching
type}, and these attributes may be \e attached to an object of another type.
This contrasts with ordinary object properties which are provided by the object
type itself (or the object's inherited type).

For example, the \l Item below uses attached properties and attached handlers:

\qml
import QtQuick 2.0

Item {
    width: 100; height: 100

    focus: true
    Keys.enabled: false
    Keys.onReturnPressed: console.log("Return key was pressed")
}
\endqml

Here, the \l Item object is able to access and set the values of \c Keys.enabled
and \c Keys.onReturnPressed. This allows the \l Item object to access these
extra attributes as an extension to its own existing attributes.

\section3 Steps for Implementing Attached Objects

When considering the above example, there are several parties involved:

\list
\li There is an instance of an anonymous \e {attached object type}, with
an \c enabled and a \c returnPressed signal, that has been attached to the
\l Item object to enable it to access and set these attributes.
\li The \l Item object is the \e {attachee}, to which the instance of the \e
{attached object type} has been attached.
\li \l Keys is the \e {attaching type}, which provides the \e {attachee} with a
named qualifier, "Keys", through which it may access the attributes of the
\e {attached object type}.
\endlist

When the QML engine processes this code, it creates a single instance of the
\e {attached object type} and attaches this instance to the \l Item object,
thereby providing it with access to the \c enabled and \c returnPressed
attributes of the instance.

The mechanisms for providing attached objects can be implemented from C++ by
providing classes for the \e {attached object type} and \e {attaching type}.
For the \e{attached object type}, provide a QObject-derived class that defines
the attributes to be made accessible to \e attachee objects. For the
\e {attaching type}, provide a QObject-derived class that:

\list
\li implements a static qmlAttachedProperties() with the following signature:
    \code
    static <AttachedPropertiesType> *qmlAttachedProperties(QObject *object);
    \endcode

    This method should return an instance of the \e{attached object type}.

    The QML engine invokes this method in order to attach an instance of
    the attached object type to the \e attachee specified by the \c object
    parameter.  It is customary, though not strictly required, for this method
    implementation to parent the returned instance to \c object in order
    to prevent memory leaks.

    This method is called at most once by the engine for each attachee object
    instance, as the engine caches the returned instance pointer for subsequent
    attached property accesses. Consequently the attachment object may not be
    deleted until the attachee \c object is destroyed.

\li is declared as an attaching type, by adding the QML_ATTACHED(attached) macro
    to the class declaration. The argument is the name of the
    \e{attached object type}
\endlist


\section3 Implementing Attached Objects: An Example

For example, take the \c Message type described in an \l{Registering an
Instantiable Object Type}{earlier example}:

\code
class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
    Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
    QML_ELEMENT
public:
    // ...
};
\endcode

Suppose it is necessary to trigger a signal on a \c Message when it is
published to a message board, and also track when the message has expired on
the message board. Since it doesn't make sense to add these attributes
directly to a \c Message, as the attributes are more relevant to the message
board context, they could be implemented as \e attached attributes on a
\c Message object that are provided through a "MessageBoard" qualifier. In
terms of the concepts described earlier, the parties involved here are:

\list
\li An instance of an anonymous \e{attached object type}, which provides a
    \c published signal and an expired property. This type is implemented by
    \c MessageBoardAttachedType below
\li A \c Message object, which will be the \e attachee
\li The \c MessageBoard type, which will be the \e {attaching type} that is
    used by \c Message objects to access the attached attributes
\endlist

Following is an example implementation. First, there needs to be an
\e {attached object type} with the necessary properties and signals that
will be accessible to the \e attachee:

\code
class MessageBoardAttachedType : public QObject
{
    Q_OBJECT
    Q_PROPERTY(bool expired READ expired WRITE setExpired NOTIFY expiredChanged)
    QML_ANONYMOUS
public:
    MessageBoardAttachedType(QObject *parent);
    bool expired() const;
    void setExpired(bool expired);
signals:
    void published();
    void expiredChanged();
};
\endcode

Then the \e {attaching type}, \c MessageBoard, must declare a \c
qmlAttachedProperties() method that returns an instance of the
\e {attached object type} as implemented by MessageBoardAttachedType.
Additionally, \c MessageBoard must be declared as an attaching type
via the QML_ATTACHED() macro:

\code
class MessageBoard : public QObject
{
    Q_OBJECT
    QML_ATTACHED(MessageBoardAttachedType)
    QML_ELEMENT
public:
    static MessageBoardAttachedType *qmlAttachedProperties(QObject *object)
    {
        return new MessageBoardAttachedType(object);
    }
};
\endcode

Now, a \c Message type can access the properties and signals of the attached
object type:

\qml
Message {
    author: "Amelie"
    creationDate: new Date()

    MessageBoard.expired: creationDate < new Date("January 01, 2015 10:45:00")
    MessageBoard.onPublished: console.log("Message by", author, "has been
published!")
}
\endqml

Additionally, the C++ implementation may access the attached object instance
that has been attached to any object by calling the
qmlAttachedPropertiesObject() function.

For example:

\code
Message *msg = someMessageInstance();
MessageBoardAttachedType *attached =
        qobject_cast<MessageBoardAttachedType*>(qmlAttachedPropertiesObject<MessageBoard>(msg));

qDebug() << "Value of MessageBoard.expired:" << attached->expired();
\endcode


\section2 Property Modifier Types

A property modifier type is a special kind of QML object type.  A property
modifier type instance affects a property (of a QML object instance) which it
is applied to.  There are two different kinds of property modifier types:
\list
\li property value write interceptors
\li property value sources
\endlist

A property value write interceptor can be used to filter or modify values as
they are written to properties.  Currently, the only supported property
value write interceptor is the \l Behavior type provided by the \c QtQuick
import.

A property value source can be used to automatically update the value of a
property over time.  Clients can define their own property value source types.
The various \l{qtquick-statesanimations-animations.html}{property animation}
types provided by the \c QtQuick import are examples of property value
sources.

Property modifier type instances can be created and applied to a property of
a QML object through the "<ModifierType> on <propertyName>" syntax, as the
following example shows:

\qml
import QtQuick 2.0

Item {
    width: 400
    height: 50

    Rectangle {
        width: 50
        height: 50
        color: "red"

        NumberAnimation on x {
            from: 0
            to: 350
            loops: Animation.Infinite
            duration: 2000
        }
    }
}
\endqml

Clients can register their own property value source types, but currently not
property value write interceptors.

\section3 Property Value Sources

\e {Property value sources} are QML types that can automatically update the
value of a property over time, using the
\c {<PropertyValueSource> on <property>} syntax. For example, the various
\l{qtquick-statesanimations-animations.html}{property animation} types
provided by the \c QtQuick module are examples of property value sources.

A property value source can be implemented in C++ by subclassing
QQmlPropertyValueSource and providing an implementation that writes different
values to a property over time. When the property value source is applied to a
property using the \c {<PropertyValueSource> on <property>} syntax in QML, it
is given a reference to this property by the engine so that the property value
can be updated.

For example, suppose there is a \c RandomNumberGenerator class to be made
available as a property value source, so that when applied to a QML property,
it will update the property value to a different random number every 500
milliseconds. Additionally, a maxValue can be provided to this random number
generator. This class can be implemented as follows:

\code
class RandomNumberGenerator : public QObject, public QQmlPropertyValueSource
{
    Q_OBJECT
    Q_INTERFACES(QQmlPropertyValueSource)
    Q_PROPERTY(int maxValue READ maxValue WRITE setMaxValue NOTIFY maxValueChanged);
    QML_ELEMENT
public:
    RandomNumberGenerator(QObject *parent)
        : QObject(parent), m_maxValue(100)
    {
        QObject::connect(&m_timer, SIGNAL(timeout()), SLOT(updateProperty()));
        m_timer.start(500);
    }

    int maxValue() const;
    void setMaxValue(int maxValue);

    virtual void setTarget(const QQmlProperty &prop) { m_targetProperty = prop; }

signals:
    void maxValueChanged();

private slots:
    void updateProperty() {
        m_targetProperty.write(QRandomGenerator::global()->bounded(m_maxValue));
    }

private:
    QQmlProperty m_targetProperty;
    QTimer m_timer;
    int m_maxValue;
};
\endcode

When the QML engine encounters a use of \c RandomNumberGenerator as a property
value source, it invokes \c RandomNumberGenerator::setTarget() to provide the
type with the property to which the value source has been applied. When the
internal timer in \c RandomNumberGenerator triggers every 500 milliseconds,
it will write a new number value to that specified property.

Once the \c RandomNumberGenerator class has been registered with the QML type
system, it can be used from QML as a property value source. Below, it is used
to change the width of a \l Rectangle every 500 milliseconds:

\qml
import QtQuick 2.0

Item {
    width: 300; height: 300

    Rectangle {
        RandomNumberGenerator on width { maxValue: 300 }

        height: 100
        color: "red"
    }
}
\endqml

In all other respects, property value sources are regular QML types that can
have properties, signals methods and so on, but with the added capability that
they can be used to change property values using the
\c {<PropertyValueSource> on <property>} syntax.

When a property value source object is assigned to a property, QML first tries
to assign it normally, as though it were a regular QML type.  Only if this
assignment fails does the engine call the \l
{QQmlPropertyValueSource::}{setTarget()} method.  This allows
the type to also be used in contexts other than just as a value source.


\section2 Specifying Default Properties for QML Object Types

Any QObject-derived type that is registered as an instantiable QML object type
can optionally specify a \e {default property} for the type. A default
property is the property to which an object's children are automatically
assigned if they are not assigned to any specific property.

The default property can be set by calling the Q_CLASSINFO() macro for a class
with a specific "DefaultProperty" value. For example, the \c MessageBoard
class below specifies its \c messages property as the default property for the
class:

\code
class MessageBoard : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
    Q_CLASSINFO("DefaultProperty", "messages")
    QML_ELEMENT
public:
    QQmlListProperty<Message> messages();

private:
    QList<Message *> m_messages;
};
\endcode

This enables children of a \c MessageBoard object to be automatically assigned
to its \c messages property if they are not assigned to a specific property. For
example:

\qml
MessageBoard {
    Message { author: "Naomi" }
    Message { author: "Clancy" }
}
\endqml

If \c messages was not set as the default property, then any \c Message objects
would have to be explicitly assigned to the \c messages property instead, as
follows:

\qml
MessageBoard {
    messages: [
        Message { author: "Naomi" },
        Message { author: "Clancy" }
    ]
}
\endqml

(Incidentally, the \l Item::data property is its default property. Any \l Item
objects added to this \c data property are also added to the list of
\l Item::children, so the use of the default property enables visual children
to be declared for an item without explicitly assigning them to the
\l{Item::}{children} property.)


\section2 Defining Visual Items with the Qt Quick Module

When building user interfaces with the \l {Qt Quick} module, all QML objects that are
to be visually rendered must derive from the \l Item type, as it is the base
type for all visual objects in \l {Qt Quick}. This \l Item type is
implemented by the QQuickItem C++ class, which is provided by the
\l {Qt Quick} module. Therefore, this class should be subclassed when it is
necessary to implement a visual type in C++ that can be integrated into a
QML-based user interface.

See the QQuickItem documentation for more information. Additionally, the
\l{Writing QML Extensions with C++} tutorial demonstrates how a QQuickItem-based
visual item can be implemented in C++ and integrated into a Qt Quick-based user
interface.


\section1 Receiving Notifications for Object Initialization

For some custom QML object types, it may be beneficial to delay the
initialization of particular data until the object has been created and all of
its properties have been set. For example, this may be the case if the
initialization is costly, or if the initialization should not be performed until
all property values have been initialized.

The \l {Qt QML} module provides the QQmlParserStatus to be subclassed for these
purposes. It defines a number of virtual methods that are invoked at
various stages during component instantiation. To receive these notifications, a
C++ class should inherit QQmlParserStatus and also notify the Qt meta system
using the Q_INTERFACES() macro.

For example:

\code
class MyQmlType : public QObject, public QQmlParserStatus
{
    Q_OBJECT
    Q_INTERFACES(QQmlParserStatus)
    QML_ELEMENT
public:
    virtual void componentComplete()
    {
        // Perform some initialization here now that the object is fully created
    }
};
\endcode

*/