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
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
|
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Free Documentation License
** 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page qml-extending.html
\title Extending QML in C++
The QML syntax declaratively describes how to construct an in-memory object
tree. In Qt, QML is mainly used to describe a visual scene graph, but it is
not conceptually limited to this: the QML format is an abstract description of
any object tree. All the QML element types included in Qt are implemented using
the C++ extension mechanisms describe on this page. Programmers can use these
APIs to add new types that interact with the existing Qt types, or to repurpose
QML for their own independent use.
\tableofcontents
\section1 Adding Types
\target adding-types
\snippet examples/declarative/cppextensions/referenceexamples/adding/example.qml 0
The QML snippet shown above instantiates one \c Person instance and sets
the \c name and \c shoeSize properties on it. Everything in QML ultimately comes down
to either instantiating an object instance, or assigning a property a value.
QML relies heavily on Qt's meta object system and can only instantiate classes
that derive from QObject. For visual element types, this will usually mean a subclass
of QDeclarativeItem; for models used with the view elements, a subclass of QAbstractItemModel;
and for abitrary objects with properties, a direct subclass of QObject.
The QML engine has no intrinsic knowledge of any class types. Instead the
programmer must register the C++ types with their corresponding QML names.
Custom C++ types are registered using a template function:
\quotation
\code
template<typename T>
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
\endcode
Calling qmlRegisterType() registers the C++ type \a T with the QML
system, and makes it available in QML under the name \a qmlName in
library \a uri version \a versionMajor.versionMinor. The \a qmlName
can be the same as the C++ type name.
Type \a T must be a concrete type that inherits QObject and has a default
constructor.
\endquotation
#include <QtDeclarative> to use qmlRegisterType().
Types can be registered by libraries, application code, or by plugins
(see QDeclarativeExtensionPlugin).
Once registered, all \l {Qt's Property System}{properties} of the
supported types are available in QML. QML has intrinsic support for
properties of the types listed in the \l{Adding Properties}
document, which includes the following:
\list
\o bool, unsigned int, int, float, double, qreal
\o QString, QUrl, QColor
\o QDate, QTime, QDateTime
\o QPoint, QPointF, QSize, QSizeF, QRect, QRectF
\o QVariant
\endlist
When a property of a supported type is added to a C++ class, in a QML
element based on the C++ class, a \e{value-changed} signal handler
will be available. See \l{Signal Support} below.
QML is typesafe. Attempting to assign an invalid value to a property
will generate an error. For example, assuming the \e{name} property
of the \c Person element had a type of QString, this would cause an
error:
\code
Person {
// Will NOT work
name: 12
}
\endcode
\l {Extending QML - Adding Types Example} shows the complete code used to create
the \c Person type.
\section1 Object and List Property Types
\snippet examples/declarative/cppextensions/referenceexamples/properties/example.qml 0
The QML snippet shown above assigns a \c Person object to the \c BirthdayParty's
\c host property, and assigns three \c Person objects to the guests property.
QML can set properties of types that are more complex than basic intrinsics like
integers and strings. Properties can also be object pointers, Qt interface
pointers, lists of object points, and lists of Qt interface pointers. As QML
is typesafe it ensures that only valid types are assigned to these properties,
just like it does for primitive types.
Properties that are pointers to objects or Qt interfaces are declared with the
Q_PROPERTY() macro, just like other properties. The \c host property
declaration looks like this:
\snippet examples/declarative/cppextensions/referenceexamples/properties/birthdayparty.h 1
As long as the property type, in this case \c Person, is registered with QML the
property can be assigned.
QML also supports assigning Qt interfaces. To assign to a property whose type
is a Qt interface pointer, the interface must also be registered with QML. As
they cannot be instantiated directly, registering a Qt interface is different
from registering a new QML type. The following function is used instead:
\quotation
\code
template<typename T>
int qmlRegisterInterface(const char *typeName)
\endcode
This registers the C++ interface \a T with the QML system as \a typeName.
Following registration, QML can coerce objects that implement this interface
for assignment to appropriately typed properties.
\endquotation
The \c guests property is a list of \c Person objects. Properties that are lists
of objects or Qt interfaces are also declared with the Q_PROPERTY() macro, just
like other properties. List properties must have the type \c {QDeclarativeListProperty<T>}.
As with object properties, the type \a T must be registered with QML.
The \c guest property declaration looks like this:
\snippet examples/declarative/cppextensions/referenceexamples/properties/birthdayparty.h 2
\l {Extending QML - Object and List Property Types Example} shows the complete
code used to create the \c BirthdayParty type.
\section1 Inheritance and Coercion
\snippet examples/declarative/cppextensions/referenceexamples/coercion/example.qml 0
The QML snippet shown above assigns a \c Boy object to the \c BirthdayParty's
\c host property, and assigns three other objects to the \c guests property.
QML supports C++ inheritance hierarchies and can freely coerce between known,
valid object types. This enables the creation of common base classes that allow
the assignment of specialized classes to object or list properties. In the
snippet shown, both the \c host and the \c guests properties retain the \c Person
type used in the previous section, but the assignment is valid as both the \c Boy
and \c Girl objects inherit from \c Person.
To assign to a property, the property's type must have been registered with QML.
Both the qmlRegisterType() and qmlRegisterInterface() template functions already
shown can be used to register a type with QML. Additionally, if a type that acts purely
as a base class that cannot be instantiated from QML needs to be
registered, the following function can be used:
\quotation
\code
template<typename T>
int qmlRegisterType()
\endcode
This registers the C++ type \a T with the QML system. The parameterless call to the template
function qmlRegisterType() does not define a mapping between the
C++ class and a QML element name, so the type is not instantiable from QML, but
it is available for type coercion.
Type \a T must inherit QObject, but there are no restrictions on whether it is
concrete or the signature of its constructor.
\endquotation
QML will automatically coerce C++ types when assigning to either an object
property, or to a list property. Only if coercion fails does an assignment
error occur.
\l {Extending QML - Inheritance and Coercion Example} shows the complete
code used to create the \c Boy and \c Girl types.
\section1 Default Property
\snippet examples/declarative/cppextensions/referenceexamples/default/example.qml 0
The QML snippet shown above assigns a collection of objects to the
\c BirthdayParty's default property.
The \e {default property} is a syntactic convenience that allows a type designer to
specify a single property as the type's default. The default property is
assigned to whenever no explicit property is specified. As a convenience, it is
behaviorally identical to assigning to the default property explicitly by name.
From C++, type designers mark the default property using a Q_CLASSINFO()
annotation:
\quotation
\code
Q_CLASSINFO("DefaultProperty", "property")
\endcode
This marks \a property as the class's default property. \a property must be either
an object property, or a list property.
A default property is optional. A derived class inherits its base class's
default property, but may override it in its own declaration. \a property can
refer to a property declared in the class itself, or a property inherited from a
base class.
\endquotation
\l {Extending QML - Default Property Example} shows the complete code used to
specify a default property.
\section1 Grouped Properties
\snippet examples/declarative/cppextensions/referenceexamples/grouped/example.qml 1
The QML snippet shown above assigns a number of properties to the \c Boy object,
including four properties using the grouped property syntax.
Grouped properties collect similar properties together into a single named
block. Grouped properties can be used to present a nicer API to developers, and
may also simplify the implementation of common property collections across
different types through implementation reuse.
A grouped property block is implemented as a read-only object property. The
\c shoe property shown is declared like this:
\snippet examples/declarative/cppextensions/referenceexamples/grouped/person.h 1
The \c ShoeDescription type declares the properties available to the grouped
property block - in this case the \c size, \c color, \c brand and \c price properties.
Grouped property blocks may declared and accessed be recusively.
\l {Extending QML - Grouped Properties Example} shows the complete code used to
implement the \c shoe property grouping.
\section1 Attached Properties
\snippet examples/declarative/cppextensions/referenceexamples/attached/example.qml 1
The QML snippet shown above assigns a date to the \c rsvp property using the attached
property syntax.
Attached properties allow unrelated types to annotate other types with some
additional properties, generally for their own use. Attached properties are
identified through the use of the attacher type name, in the case shown
\c BirthdayParty, as a prefix to the property name.
In the example shown, \c BirthdayParty is called the attaching type, and the
\c Boy instance the attachee object instance.
For the attaching type, an attached property block is implemented as a new
QObject derived type, called the attachment object. The properties on the
attachment object are those that become available for use as the attached
property block.
Any QML type can become an attaching type by declaring the
\c qmlAttachedProperties() public function and declaring that the class has
QML_HAS_ATTACHED_PROPERTIES:
\quotation
\code
class MyType : public QObject {
Q_OBJECT
public:
...
static AttachedPropertiesType *qmlAttachedProperties(QObject *object);
};
QML_DECLARE_TYPEINFO(MyType, QML_HAS_ATTACHED_PROPERTIES)
\endcode
This returns an attachment object, of type \a AttachedPropertiesType, for the
attachee \a object instance. It is customary, though not strictly required, for
the attachment object to be parented to \a object to prevent memory leaks.
\a AttachedPropertiesType must be a QObject derived type. The properties on
this type will be accessible through the attached properties syntax.
This method will be called at most once for each attachee object instance. The
QML engine will cache the returned instance pointer for subsequent attached
property accesses. Consequently the attachment object may not be deleted until
\a object is destroyed.
\endquotation
Conceptually, attached properties are a \e type exporting a set of additional
properties that can be set on \e any other object instance. Attached properties
cannot be limited to only attaching to a sub-set of object instances, although
their effect may be so limited.
For example, a common usage scenario is for a type to enhance the properties
available to its children in order to gather instance specific data. Here we
add a \c rsvp field to all the guests coming to a birthday party:
\code
BirthdayParty {
Boy { BirthdayParty.rsvp: "2009-06-01" }
}
\endcode
However, as a type cannot limit the instances to which the attachment object
must attach, the following is also allowed, even though adding a birthday party
rsvp in this context will have no effect.
\code
GraduationParty {
Boy { BirthdayParty.rsvp: "2009-06-01" }
}
\endcode
From C++, including the attaching type implementation, the attachment object for
an instance can be accessed using the following method:
\quotation
\code
template<typename T>
QObject *qmlAttachedPropertiesObject<T>(QObject *attachee, bool create = true);
\endcode
This returns the attachment object attached to \a attachee by the attaching type
\a T. If type \a T is not a valid attaching type, this method always returns 0.
If \a create is true, a valid attachment object will always be returned,
creating it if it does not already exist. If \a create is false, the attachment
object will only be returned if it has previously been created.
\endquotation
\l {Extending QML - Attached Properties Example} shows the complete code used to
implement the rsvp attached property.
\section1 Memory Management and QVariant types
It is an element's responsibility to ensure that it does not access or return
pointers to invalid objects. QML makes the following guarentees:
\list
\o An object assigned to a QObject (or QObject-derived) pointer property will be
valid at the time of assignment.
Following assignment, it is the responsibility of the class to subsequently guard
this pointer, either through a class specific method or the generic QPointer class.
\o An object assigned to a QVariant will be valid at the time of assignment.
When assigning an object to a QVariant property, QML will always use a QMetaType::QObjectStar
typed QVariant. It is the responsibility of the class to guard the pointer. A
general rule when writing a class that uses QVariant properties is to check the
type of the QVariant when it is set and if the type is not handled by your class,
reset it to an invalid variant.
\o An object assigned to a QObject (or QObject-derived) list property will be
valid at the time of assignment.
Following assignment, it is the responsibility of the class to subsequently guard
this pointer, either through a class specific method or the generic QPointer class.
\endlist
Elements should assume that any QML assigned object can be deleted at any time, and
respond accordingly. If documented as such an element need not continue to work in
this situation, but it must not crash.
\section1 Signal Support
\snippet examples/declarative/cppextensions/referenceexamples/signal/example.qml 0
\snippet examples/declarative/cppextensions/referenceexamples/signal/example.qml 1
The QML snippet shown above associates the evaluation of a JavaScript expression
with the emission of a Qt signal.
All Qt signals on a registered class become available as special "signal
properties" within QML to which the user can assign a single JavaScript
expression. The signal property's name is a transformed version of the Qt
signal name: "on" is prepended, and the first letter of the signal name upper
cased. For example, the signal used in the example above has the following
C++ signature:
\snippet examples/declarative/cppextensions/referenceexamples/signal/birthdayparty.h 0
In classes with multiple signals with the same name, only the final signal
is accessible as a signal property. Note that signals with the same name
but different parameters cannot be distinguished.
Signal parameters become accessible by name to the assigned script. An
unnamed parameter cannot be accessed, so care should be taken to name all the
signal parameters in the C++ class declaration. The intrinsic types
listed in \l {Adding Types}, as well registered object types are permitted as
signal parameter types. Using other types is not an error, but the parameter
value will not be accessible from script.
\l {Extending QML - Signal Support Example} shows the complete code used to
implement the onPartyStarted signal property.
If you want to use signals from items not created in QML, you can access their
signals with the \l {Connections} element.
Additionally, if a property is added to a C++ class, all QML elements
based on that C++ class will have a \e{value-changed} signal handler
for that property. The name of the signal handler is
\e{on<Property-name>Changed}, with the first letter of the property
name being upper case.
\note The QML signal handler will always be named
on<Property-name>Changed, regardless of the name used for the NOTIFY
signal in C++. We recommend using <property-name>Changed() for the
NOTIFY signal in C++.
See also \l {Writing QML Components: Properties, Methods and Signals}
\section1 Methods
Slots and methods marked Q_INVOKABLE may be called as functions in QML.
\snippet examples/declarative/cppextensions/referenceexamples/methods/example.qml 0
In this example an invitation is added via an \c {invite()} invokable method of
the BirthdayParty element. This function is available in QML by marking the \c {invite()}
method with Q_INVOKABLE in the BirthdayParty class:
\snippet examples/declarative/cppextensions/referenceexamples/methods/birthdayparty.h 0
\l {Extending QML - Methods Example} shows the complete code used to
implement the invite() method.
The \c {invite()} method is similarly available if it is declared as a slot.
\section1 Property Value Sources
\snippet examples/declarative/cppextensions/referenceexamples/valuesource/example.qml 0
\snippet examples/declarative/cppextensions/referenceexamples/valuesource/example.qml 1
The QML snippet shown above applies a property value source to the \c announcment property.
A property value source generates a value for a property that changes over time.
Property value sources are most commonly used to do animation. Rather than
constructing an animation object and manually setting the animation's "target"
property, a property value source can be assigned directly to a property of any
type and automatically set up this association.
The example shown here is rather contrived: the \c announcement property of the
\c BirthdayParty object is a string that is printed every time it is assigned and
the \c HappyBirthdaySong value source generates the lyrics of the song
"Happy Birthday".
\snippet examples/declarative/cppextensions/referenceexamples/valuesource/birthdayparty.h 0
Normally, assigning an object to a string property would not be allowed. In
the case of a property value source, rather than assigning the object instance
itself, the QML engine sets up an association between the value source and
the property.
Property value sources are special types that derive from the
QDeclarativePropertyValueSource base class. This base class contains a single method,
QDeclarativePropertyValueSource::setTarget(), that the QML engine invokes when
associating the property value source with a property. The relevant part of
the \c HappyBirthdaySong type declaration looks like this:
\snippet examples/declarative/cppextensions/referenceexamples/valuesource/happybirthdaysong.h 0
\snippet examples/declarative/cppextensions/referenceexamples/valuesource/happybirthdaysong.h 1
\snippet examples/declarative/cppextensions/referenceexamples/valuesource/happybirthdaysong.h 2
In all other respects, property value sources are regular QML types. They must
be registered with the QML engine using the same macros as other types, and can
contain properties, signals and methods just like other types.
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 {QDeclarativePropertyValueSource::}{setTarget()} method. This allows
the type to also be used in contexts other than just as a value source.
\l {Extending QML - Property Value Source Example} shows the complete code used
implement the \c HappyBirthdaySong property value source.
\section1 Property Binding
\snippet examples/declarative/cppextensions/referenceexamples/binding/example.qml 0
\snippet examples/declarative/cppextensions/referenceexamples/binding/example.qml 1
The QML snippet shown above uses a property binding to ensure the
\c HappyBirthdaySong's \c name property remains up to date with the \c host.
Property binding is a core feature of QML. In addition to assigning literal
values, property bindings allow the developer to assign an arbitrarily complex
JavaScript expression that may include dependencies on other property values.
Whenever the expression's result changes - through a change in one of its
constituent values - the expression is automatically reevaluated and
the new result assigned to the property.
All properties on custom types automatically support property binding. However,
for binding to work correctly, QML must be able to reliably determine when a
property has changed so that it knows to reevaluate any bindings that depend on
the property's value. QML relies on the presence of a
\l {Qt's Property System}{NOTIFY signal} for this determination.
Here is the \c host property declaration:
\snippet examples/declarative/cppextensions/referenceexamples/binding/birthdayparty.h 0
The NOTIFY attribute is followed by a signal name. It is the responsibility of
the class implementer to ensure that whenever the property's value changes, the
NOTIFY signal is emitted. The signature of the NOTIFY signal is not important to QML.
To prevent loops or excessive evaluation, developers should ensure that the
signal is only emitted whenever the property's value is actually changed. If
a property, or group of properties, is infrequently used it is permitted to use
the same NOTIFY signal for several properties. This should be done with care to
ensure that performance doesn't suffer.
To keep QML reliable, if a property does not have a NOTIFY signal, it cannot be
used in a binding expression. However, the property can still be assigned
a binding as QML does not need to monitor the property for change in that
scenario.
Consider a custom type, \c TestElement, that has two properties, "a" and "b".
Property "a" does not have a NOTIFY signal, and property "b" does have a NOTIFY
signal.
\code
TestElement {
// This is OK
a: b
}
TestElement {
// Will NOT work
b: a
}
\endcode
The presence of a NOTIFY signal does incur a small overhead. There are cases
where a property's value is set at object construction time, and does not
subsequently change. The most common case of this is when a type uses
\l {Grouped Properties}, and the grouped property object is allocated once, and
only freed when the object is deleted. In these cases, the CONSTANT attribute
may be added to the property declaration instead of a NOTIFY signal.
\snippet examples/declarative/cppextensions/referenceexamples/binding/person.h 0
Extreme care must be taken here or applications using your type may misbehave.
The CONSTANT attribute should only be used for properties whose value is set,
and finalized, only in the class constructor. All other properties that want
to be used in bindings should have a NOTIFY signal instead.
\l {Extending QML - Binding Example} shows the BirthdayParty example updated to
include NOTIFY signals for use in binding.
\section1 Extension Objects
\snippet examples/declarative/cppextensions/referenceexamples/extended/example.qml 0
The QML snippet shown above adds a new property to an existing C++ type without
modifying its source code.
When integrating existing classes and technology into QML, their APIs will often
need to be tweaked 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.
Extension objects are used to 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
extension type - when registering the target class whose properties are
transparently merged with the original target class when used from within QML.
An extension class is a regular QObject, with a constructor that takes a QObject
pointer. When needed (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 an extended property on the original is accessed,
the appropriate property on the extension object is used instead.
When an extended type is installed, one of the
\code
template<typename T, typename ExtendedT>
int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
template<typename T, typename ExtendedT>
int qmlRegisterExtendedType()
\endcode
functions should be used instead of the regular \c qmlRegisterType() variations.
The arguments are identical to the corresponding non-extension registration functions,
except for the ExtendedT parameter which is the type
of the extension object.
\section1 Optimization
Often to develop high performance elements it is helpful to know more about the
status of the QML engine. For example, it might be beneficial to delay
initializing some costly data structures until after all the properties have been
set.
The QML engine defines an interface class called QDeclarativeParserStatus, which contains a
number of virtual methods that are invoked at various stages during component
instantiation. To receive these notifications, an element implementation inherits
QDeclarativeParserStatus and notifies the Qt meta system using the Q_INTERFACES() macro.
For example,
\code
class Example : public QObject, public QDeclarativeParserStatus
{
Q_OBJECT
Q_INTERFACES(QDeclarativeParserStatus)
public:
virtual void componentComplete()
{
qDebug() << "Woohoo! Now to do my costly initialization";
}
};
\endcode
*/
/*!
\page qml-extending-types.html
\title Writing QML Components: Properties, Methods and Signals
One of the key concepts in QML is the ability to define your own QML components that suit
the purposes of your application. The standard \l {QML Elements} provide the essential components
for creating a QML application; beyond these, you can write your own custom components that can
be created and reused, without the use of C++.
Components are the building blocks of a QML project. When writing a QML application, whether
large or small, it is best to separate QML code into smaller components that perform specific
sets of operations, instead of creating mammoth QML files with large, combined functionality
that is more difficult to manage and may contain duplicated code.
\section1 Defining New Components
A component is a reusable type with a well-defined interface, built entirely in QML.
Any snippet of QML code can become a component, by placing the code in a file "<Name>.qml" where
<Name> is the new component name, beginning with an uppercase letter. These QML files automatically
become available as new QML element types to other QML components and applications in the same directory.
For example, one of the simplest and most common components you can build in QML is a
button-type component. Below, we implement this component as a \l Rectangle with a clickable
\l MouseArea, in a file named \c Button.qml:
\snippet doc/src/snippets/declarative/qml-extending-types/components/Button.qml 0
Now this component can be reused by another file within the same directory. Since the file is
named \c Button.qml, the component is referred to as \c Button:
\table
\row
\o \snippet doc/src/snippets/declarative/qml-extending-types/components/application.qml 0
\o \image qml-extending-types.png
\endtable
The root object in \c Button.qml defines the attributes that are available to users of the
\c Button component. In this case, the root object is a \l Rectangle, so any properties, methods
and signals of \l Rectangle are made available, allowing \c application.qml to
customize the \c width, \c height, \c radius and \c color properties of \c Button objects.
If \c Button.qml was not in the same directory, \c application.qml would need to load it as a
\l {Modules}{module} from a specific filesystem path or \l{QDeclarativeExtensionPlugin}{plugin}.
Also, note the letter case of the component file name is significant on some (notably UNIX)
filesystems. It is recommended the file name case matches the case of the QML component name
exactly - for example, \c Box.qml and not \c BoX.qml - regardless of the platform to which the
QML component will be deployed.
To write a useful component, it is generally necessary to provide it with custom attributes that store and
communicate specific data. This is achieved by adding the following attributes to your components:
\list
\o \bold Properties that can be accessed externally to modify an object (for example, \l Item has
\l {Item::}{width} and \l {Item::}{height} properties) and used in \l {Property Binding}
\o \bold Methods of JavaScript code can be invoked internally or externally (for example,
\l Animation has a \l {Animation::}{start()} method)
\o \bold Signals to notify other objects when an event has occurred (for example, MouseArea has a
\c clicked signal)
\endlist
The following sections show how these attributes can be added to QML components.
\section1 Adding Properties
A property is a value of a QML component that can be read and modified by other objects. For
example, a \l Rectangle component has \l {Item::}{width}, \l {Item::}{height} and \l
{Rectangle::}{color} properties. Significantly, properties be used with \l {Property Binding}, where
a property value is automatically updated using the value of another property.
The syntax for defining a new property is:
\code
[default] property <type> <name>[: defaultValue]
\endcode
A \c property declaration can appear anywhere within a QML component definition, but it is customary
to place it at the top. A component cannot declare more than one property with the same name. (It is
possible to have a property name that is the same as an existing property in a type, but this is not
recommended as the existing property becomes hidden and inaccessible.)
Below is an example. The \c ImageViewer component has defined a \c string type property named
\c currentImage, and its initial value is "default-image.png". This property is used to set the image
displayed in the child \l Image object. Another file, \c application.qml, can create
an \c ImageViewer object and read or modify the \c currentImage value:
\table
\row
\o \snippet doc/src/snippets/declarative/qml-extending-types/properties/ImageViewer.qml 0
\o \snippet doc/src/snippets/declarative/qml-extending-types/properties/application.qml 0
\endtable
It is optional for a property to have a default value. The default value is a convenient shortcut, and is
behaviorally identical to doing it in two steps, like this:
\qml
// Use default value
property int myProperty: 10
// Longer, but behaviorally identical
property int myProperty
myProperty: 10
\endqml
\section2 Supported property types
All QML properties are typed. The examples above show properties with \c int and \c string types;
notice that the type of the property must be declared. The type is used to determine the property
behavior, and how the property is defined in C++.
A number of property types are supported by default. These are listed in the table below,
with their default values and the corresponding C++ type:
\table
\header \o QML Type Name \o Default value \o C++ Type Name
\row \o int \o 0 \o int
\row \o bool \o \c false \o bool
\row \o double \o 0.0 \o double
\row \o real \o 0.0 \o double
\row \o string \o "" (empty string) \o QString
\row \o url \o "" (empty url) \o QUrl
\row \o color \o #000000 (black) \o QColor
\row \o date \o \c undefined \o QDateTime
\row \o variant \o \c undefined \o QVariant
\endtable
QML object types can also be used as property types. This includes
\l {Defining new QML elements}{custom QML types} implemented in C++. Such properties are
defined like this:
\qml
property Item itemProperty
property QtObject objectProperty
property MyCustomType customProperty
\endqml
Such object-type properties default to an \c undefined value.
\l{list}{List properties} are created with the \c list<Type> syntax, and default to an empty
list:
\qml
property list<Item> listOfItems
\endqml
Note that list properties cannot be modified like ordinary JavaScript
arrays. See the \l {list}{list type documentation} for details.
For details about accessing and manipulating QML properties from C++, see \l {Using QML with C++}.
\section2 Property change signals
Adding a \c property to an item automatically adds a \e {value changed}
signal handler to the item. To connect to this signal, use a \l {Signal Handlers}{signal handler}
named with the \c on<Property>Changed syntax, using upper case for the first letter of the
property name.
For example, the following \c onMyNumberChanged signal handler is automatically called whenever the
\c myNumber property changes:
\snippet doc/src/snippets/declarative/qml-extending-types/properties/property-signals.qml 0
\section2 Default properties
The optional \c default attribute for a property marks it as the \e {default property}
for a type. This allows other items to specify the default property's value
as child elements. For example, the \l Item element's default property is its
\l{Item::children}{children} property. This allows the children of an \l Item
to be set like this:
\qml
Item {
Rectangle {}
Rectangle {}
}
\endqml
If the \l{Item::children}{children} property was not the default property for
\l Item, its value would have to be set like this instead:
\qml
Item {
children: [
Rectangle {}
Rectangle {}
]
}
\endqml
See the \l{declarative/ui-components/tabwidget}{TabWidget} example for a
demonstration of using default properties.
Specifying a default property overrides any existing default property (for
example, any default property inherited from a parent item). Using the
\c default attribute twice in the same type block is an error.
\section2 Property aliases
Property aliases are a more advanced form of property declaration. Unlike a
property definition, which allocates a new, unique storage space for the
property, a property alias connects the newly declared property (called the
aliasing property) as a direct reference to an existing property (the aliased property). Read
operations on the aliasing property act as read operations on the aliased
property, and write operations on the aliasing property as write operations on
the aliased property.
A property alias declaration looks a lot like an ordinary property definition:
\code
[default] property alias <name>: <alias reference>
\endcode
As the aliasing property has the same type as the aliased property, an explicit
type is omitted, and the special "alias" keyword is used. Instead of a default
value, a property alias includes a compulsory alias reference. The alias
reference is used to locate the aliased property. While similar to a property
binding, the alias reference syntax is highly restricted.
An alias reference takes one of the following forms:
\code
<id>.<property>
<id>
\endcode
where <id> must refer to an object id within the same component as the type
declaring the alias, and, optionally, <property> refers to a property on that object.
For example, below is a \c Button.qml component with a \c buttonText aliased property which is
connected to the child Text object's \c text property:
\snippet doc/src/snippets/declarative/qml-extending-types/properties/alias.qml 0
The following code would create a \c Button with a defined text string for the
child \l Text object:
\qml
Button { buttonText: "This is a button" }
\endqml
Here, modifying \c buttonText directly modifies the \c textItem.text value; it does not
change some other value that then updates \c textItem.text.
In this case, the use of aliased properties is essential. If \c buttonText was not an alias,
changing its value would not actually change the displayed text at all, as
\l {Property Binding}{property bindings} are not bi-directional: the \c buttonText value would
change when \c textItem.text changes, but not the other way around.
Aliased properties are also useful for allowing external objects to directly modify and
access child objects in a component. For example, here is a modified version of the \c ImageViewer
component shown \l {Adding Properties}{earlier} on this page. The \c currentImage property has
been changed to an alias to the child \l Image object:
\table
\row
\o \snippet doc/src/snippets/declarative/qml-extending-types/properties/alias/ImageViewer.qml 0
\o \snippet doc/src/snippets/declarative/qml-extending-types/properties/alias/application.qml 0
\endtable
Instead of being limited to setting the \l Image source, \c application.qml can now directly
access and modify the child \l Image object and its properties.
Obviously, exposing child objects in this manner should be done with care, as it allows external
objects to modify them freely. However, this use of aliased properties can be quite useful in
particular situations, such as for the \l {declarative/ui-components/tabwidget}{TabWidget}
example, where new tab items are actually parented to a child object that displays the current tab.
\section3 Considerations for property aliases
Aliases are only activated once the component specifying them is completed. The
most obvious consequence of this is that the component itself cannot generally
use the aliased property directly during creation. For example, this will not work:
\code
// Does NOT work
property alias buttonText: textItem.text
buttonText: "Some text" // buttonText is not yet defined when this value is set
\endcode
A second, much less significant, consequence of the delayed activation of
aliases is that an alias reference cannot refer to another aliasing property
declared within the same component. This will not work:
\code
// Does NOT work
id: root
property alias buttonText: textItem.text
property alias buttonText2: root.buttonText
\endcode
At the time the component is created, the \c buttonText value has not yet been assigned,
so \c root.buttonText would refer to an undefined value. (From outside the component,
however, aliasing properties appear as regular Qt properties and consequently can be
used in alias references.)
It is possible for an aliased property to have the same name as an existing property. For example,
the following component has a \c color alias property, named the same as the built-in
\l {Rectangle::color} property:
\snippet doc/src/snippets/declarative/qml-extending-types/properties/alias-override.qml 0
Any objects that use this component and refer to its \c color property will be
referring to the alias rather than the ordinary \l {Rectangle::color} property. Internally,
however, the rectangle can correctly set this property to "red" and refer to the actual defined
property rather than the alias.
\section1 Adding Methods
A QML component can define methods of JavaScript code. These methods can be invoked
either internally or by other objects.
The syntax for defining a method is:
\code
function <name>([<parameter name>[, ...]]) { <body> }
\endcode
This declaration may appear anywhere within a type body, but it is customary to
include it at the top. Attempting to declare two methods or signals with the
same name in the same type block is an error. However, a new method may reuse
the name of an existing method on the type. (This should be done with caution,
as the existing method may be hidden and become inaccessible.)
Unlike \l{Adding Signals}{signals}, method parameter types do not have to be declared as they
default to the \c variant type. The body of the method is written in JavaScript and may access
the parameters by name.
Here is an example of a component with a \c say() method that accepts a single \c text argument:
\snippet doc/src/snippets/declarative/qml-extending-types/methods/app.qml 0
A method can be connected to a signal so that it is automatically invoked whenever the signal
is emitted. See \l {Connecting signals to methods and other signals} below.
Also see \l {Integrating JavaScript} for more information on using JavaScript with QML.
\section1 Adding Signals
Signals provide a way to notify other objects when an event has occurred. For example, the MouseArea
\c clicked signal notifies other objects that the mouse has been clicked within the area.
The syntax for defining a new signal is:
\code
signal <name>[([<type> <parameter name>[, ...]])]
\endcode
This declaration may appear anywhere within a type body, but it is customary to
include it at the top. Attempting to declare two signals or methods with the
same name in the same type block is an error. However, a new signal may reuse
the name of an existing signal on the type. (This should be done with caution,
as the existing signal may be hidden and become inaccessible.)
Here are three examples of signal declarations:
\code
Item {
signal clicked
signal hovered()
signal performAction(string action, variant actionArgument)
}
\endcode
If the signal has no parameters, the "()" brackets are optional. If parameters are used, the
parameter types must be declared, as for the \c string and \c variant arguments for the \c
performAction signal above; the allowed parameter types are the same as those listed in the \l
{Adding Properties} section on this page.
Adding a signal to an item automatically adds a \l {Signal Handlers}{signal handler} as well.
The signal hander is named \c on<SignalName>, with the first letter of the signal being upper
cased. The above example item would now have the following signal handlers:
\list
\o onClicked
\o onHovered
\o onPerformAction
\endlist
To emit a signal, simply invoke it in the same way as a method. Below left, when the \l MouseArea is
clicked, it emits the parent \c buttonClicked signal by invoking \c rect.buttonClicked(). The
signal is received by \c application.qml through an \c onButtonClicked signal handler:
\table
\row
\o \snippet doc/src/snippets/declarative/qml-extending-types/signals/basic.qml 0
\o \snippet doc/src/snippets/declarative/qml-extending-types/signals/no-parameters.qml 0
\endtable
If the signal has parameters, they are accessible by parameter name in the signal handler.
In the example below, \c buttonClicked is emitted with \c xPos and \c yPos parameters instead:
\table
\row
\o \snippet doc/src/snippets/declarative/qml-extending-types/signals/Button.qml 0
\o \snippet doc/src/snippets/declarative/qml-extending-types/signals/parameters.qml 0
\endtable
\section2 Connecting signals to methods and other signals
Signal objects have a \c connect() method that can be used to a connect a signal to a method or
another signal. When a signal is connected to a method, the method is automatically invoked
whenever the signal is emitted. (In Qt terminology, the method is a \e slot that is connected
to the \e signal; all methods defined in QML are created as Qt slots.) This enables a signal
to be received by a method instead of a \l {Signal Handlers}{signal handler}.
For example, the \c application.qml above could be rewritten as:
\snippet doc/src/snippets/declarative/qml-extending-types/signals/connectslots.qml 0
The \c myMethod() method will be called whenever the \c buttonClicked signal is received.
In many cases it is sufficient to receive signals through signal handlers rather than using
the \c connect() function; the above example does not provide any improvements over using a
simple \c onButtonClicked handler. However, if you are \l{Dynamic Object Management in QML}{creating objects dynamically},
or \l {Integrating JavaScript}{integrating JavaScript code}, then you will find the
\c connect() method useful. For example, the component below creates three \c Button
objects dynamically, and connects the \c buttonClicked signal of each object to the
\c myMethod() function:
\snippet doc/src/snippets/declarative/qml-extending-types/signals/connectdynamic.qml 0
In the same way, you could connect a signal to methods defined in a dynamically
created object, or \l {Receiving QML Signals in JavaScript}{connect a signal to a JavaScript method}.
There is also a corresponding \c disconnect() method for removing connected signals. The following
code removes the connection created in \c application.qml above:
\qml
// application.qml
Item {
...
function removeSignal() {
button.clicked.disconnect(item.myMethod)
}
}
\endqml
\section3 Forwarding signals
The \c connect() method can also connect a signal to other signals. This has the effect
of "forwarding" a signal: it is automatically emitted whenever the relevant signal is emitted. For
example, the MouseArea \c onClicked handler in \c Button.qml above could have been replaced with
a call to \c connect():
\qml
MouseArea {
anchors.fill: parent
Component.onCompleted: clicked.connect(item.buttonClicked)
}
\endqml
Whenever the \l MouseArea \c clicked signal is emitted, the \c rect.buttonClicked signal will
automatically be emitted as well.
*/
|