Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / doc / src / declarative / extending-tutorial.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the documentation of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:FDL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Free Documentation License
17 ** Alternatively, this file may be used under the terms of the GNU Free
18 ** Documentation License version 1.3 as published by the Free Software
19 ** Foundation and appearing in the file included in the packaging of this
20 ** file.
21 **
22 ** If you have questions regarding the use of this file, please contact
23 ** Nokia at qt-info@nokia.com.
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29 \page qml-extending-tutorial-index.html
30 \title Tutorial: Writing QML Extensions with C++
31
32 The Qt Declarative module provides a set of APIs for extending QML through
33 C++ extensions. You can write extensions to add your own QML types, extend existing
34 Qt types, or call C/C++ functions that are not accessible from ordinary QML code.
35
36 This tutorial shows how to write a QML extension using C++ that includes
37 core QML features, including properties, signals and bindings. It also shows how
38 extensions can be deployed through plugins.
39
40 You can find the source code for this tutorial in \c Qt's
41 examples/declarative/tutorials/extending directory.
42
43 Tutorial chapters:
44
45 \list 1
46 \o \l{declarative/tutorials/extending/chapter1-basics}{Creating a New Type}
47 \o \l{declarative/tutorials/extending/chapter2-methods}{Connecting to C++ Methods and Signals}
48 \o \l{declarative/tutorials/extending/chapter3-bindings}{Property Binding}
49 \o \l{declarative/tutorials/extending/chapter4-customPropertyTypes}{Using Custom Property Types}
50 \o \l{declarative/tutorials/extending/chapter5-listproperties}{Using List Property Types}
51 \o \l{declarative/tutorials/extending/chapter6-plugins}{Writing an Extension Plugin}
52 \o \l{qml-extending-tutorial7.html}{In Summary}
53 \endlist
54
55 */
56
57 /*!
58 \title Chapter 1: Creating a New Type
59
60 \example declarative/tutorials/extending/chapter1-basics
61
62 A common task when extending QML is to provide a new QML type that supports some
63  custom functionality beyond what is provided by the built-in \l {QML Elements}.
64 For example, this could be done to implement particular data models, or provide
65 elements with custom painting and drawing capabilities, or access system features
66 like network programming that are not accessible through built-in QML features.
67
68 In this tutorial, we will show how to use the C++ classes in the Qt Declarative
69 module to extend QML. The end result will be a simple Pie Chart display implemented by
70 several custom QML types connected together through QML features like bindings and
71 signals, and made available to the QML runtime through a plugin.
72
73 To begin with, let's create a new QML type called "PieChart" that has two properties: a name
74 and a color.  We will make it available in a \l {Modules}{module} called "Charts", with
75 a module version of 1.0.
76
77 We want this \c PieChart type to be usable from QML like this:
78
79 \code
80     import Charts 1.0
81
82     PieChart {
83         width: 100; height: 100
84         name: "A simple pie chart"
85         color: "red"
86     }
87 \endcode
88
89 To do this, we need a C++ class that encapsulates this \c PieChart type and its two
90 properties. Since QML makes extensive use of Qt's \l{Meta-Object System}{meta object system},
91 this new class must:
92
93 \list
94 \o Inherit from QObject
95 \o Declare its properties using the Q_PROPERTY macro
96 \endlist
97
98 Here is our \c PieChart class, defined in \c piechart.h:
99
100 \snippet declarative/tutorials/extending/chapter1-basics/piechart.h 0
101
102 The class inherits from QDeclarativeItem because we want to override
103 QDeclarativeItem::paint() in order to draw. If the class just represented some
104 data type and was not an item that actually needed to be displayed, it could simply inherit
105 from QObject. Or, if we want to extend the functionality of an existing QObject-based
106 class, it could inherit from that class instead.
107
108 The \c PieChart class defines the two properties, \c name and \c color, with the Q_PROPERTY macro,
109 and overrides QDeclarativeItem::paint(). The class implementation in \c piechart.cpp
110 simply sets and returns the \c m_name and \c m_color values as appropriate, and
111 implements \c paint() to draw a simple pie chart. It also turns off the
112 QGraphicsItem::ItemHasNoContents flag to enable painting:
113
114 \snippet declarative/tutorials/extending/chapter1-basics/piechart.cpp 0
115 \dots 0
116 \snippet declarative/tutorials/extending/chapter1-basics/piechart.cpp 1
117
118 Now that we have defined the \c PieChart type, we will use it from QML. The \c app.qml
119 file creates a \c PieChart item and display the pie chart's details
120 using a standard QML \l Text item:
121
122 \snippet declarative/tutorials/extending/chapter1-basics/app.qml 0
123
124 Notice that although the color is specified as a string in QML, it is automatically
125 converted to a QColor object for the PieChart \c color property. Automatic conversions are
126 provided for various other \l {QML Basic Types}{basic types}; for example, a string
127 like "640x480" can be automatically converted to a QSize value.
128
129 We'll also create a C++ application that uses a QDeclarativeView to run and
130 display \c app.qml. The application must register the \c PieChart type
131 using the qmlRegisterType() function, to allow it to be used from QML. If
132 you don't register the type, \c app.qml won't be able to create a \c PieChart.
133
134 Here is the application \c main.cpp:
135
136 \snippet declarative/tutorials/extending/chapter1-basics/main.cpp 0
137
138 This call to qmlRegisterType() registers the \c PieChart type as a type called "PieChart", in a module named "Charts",
139 with a module version of 1.0.
140
141 Lastly, we write a \c .pro project file that includes the files and the \c declarative library:
142
143 \quotefile declarative/tutorials/extending/chapter1-basics/chapter1-basics.pro
144
145 Now we can build and run the application:
146
147 \image extending-tutorial-chapter1.png
148
149 Try it yourself with the code in Qt's \c examples/tutorials/extending/chapter1-basics directory.
150
151 At the moment, the \c app.qml is run from within a C++ application.
152 This may seem odd if you're used to running QML files with the \l {QML Viewer}.
153 Later on, we'll show how to create a plugin so that you can run \c app.qml using the
154 \l {QML Viewer} instead.
155
156 */
157
158
159 /*!
160 \title Chapter 2: Connecting to C++ Methods and Signals
161
162 \example declarative/tutorials/extending/chapter2-methods
163
164 Suppose we want \c PieChart to have a "clearChart()" method that erases the
165 chart and then emits a "chartCleared" signal. Our \c app.qml would be able
166 to call \c clearChart() and receive \c chartCleared() signals like this:
167
168 \snippet declarative/tutorials/extending/chapter2-methods/app.qml 0
169
170 \image extending-tutorial-chapter2.png
171
172 To do this, we add a \c clearChart() method and a \c chartCleared() signal
173 to our C++ class:
174
175 \snippet declarative/tutorials/extending/chapter2-methods/piechart.h 0
176 \dots
177 \snippet declarative/tutorials/extending/chapter2-methods/piechart.h 1
178 \dots
179 \snippet declarative/tutorials/extending/chapter2-methods/piechart.h 2
180 \dots
181 \snippet declarative/tutorials/extending/chapter2-methods/piechart.h 3
182
183 The use of Q_INVOKABLE makes the \c clearChart() method available to the
184 Qt Meta-Object system, and in turn, to QML. Note that it could have
185 been declared as as a Qt slot instead of using Q_INVOKABLE, as
186 slots are also callable from QML. Both of these approaches are valid.
187
188 The \c clearChart() method simply changes the color to Qt::transparent,
189 repaints the chart, then emits the \c chartCleared() signal:
190
191 \snippet declarative/tutorials/extending/chapter2-methods/piechart.cpp 0
192
193 Now when we run the application and click the window, the pie chart
194 disappears, and the application outputs:
195
196 \code
197     The chart has been cleared
198 \endcode
199
200 Try out the example yourself with the updated code in Qt's \c examples/tutorials/extending/chapter2-methods directory.
201
202 */
203
204 /*!
205 \title Chapter 3: Adding Property Bindings
206
207 \example declarative/tutorials/extending/chapter3-bindings
208
209 Property bindings is a powerful feature of QML that allows values of different
210 elements to be synchronized automatically. It uses signals to notify and update
211 other elements' values when property values are changed.
212
213 Let's enable property bindings for the \c color property. That means
214 if we have code like this:
215
216 \snippet declarative/tutorials/extending/chapter3-bindings/app.qml 0
217
218 \image extending-tutorial-chapter3.png
219
220 The "color: chartA.color" statement binds the \c color value of
221 \c chartB to the \c color of \c chartA.
222 Whenever \c chartA's \c color value changes, \c chartB's \c color value
223 updates to the same value. When the window is clicked, the \c onClicked
224 handler in the MouseArea changes the color of \c chartA, thereby changing
225 both charts to the color blue.
226
227 It's easy to enable property binding for the \c color property.
228 We add a \l{Qt's Property System}{NOTIFY} feature to its Q_PROPERTY() declaration to indicate that a "colorChanged" signal
229 is emitted whenever the value changes.
230
231 \snippet declarative/tutorials/extending/chapter3-bindings/piechart.h 0
232 \dots
233 \snippet declarative/tutorials/extending/chapter3-bindings/piechart.h 1
234 \dots
235 \snippet declarative/tutorials/extending/chapter3-bindings/piechart.h 2
236 \dots
237 \snippet declarative/tutorials/extending/chapter3-bindings/piechart.h 3
238
239 Then, we emit this signal in \c setPieSlice():
240
241 \snippet declarative/tutorials/extending/chapter3-bindings/piechart.cpp 0
242
243 It's important for \c setColor() to check that the color value has actually changed
244 before emitting \c colorChanged(). This ensures the signal is not emitted unnecessarily and
245 also prevents loops when other elements respond to the value change.
246
247 The use of bindings is essential to QML. You should always add NOTIFY
248 signals for properties if they are able to be implemented, so that your
249 properties can be used in bindings. Properties that cannot be bound cannot be
250 automatically updated and cannot be used as flexibly in QML. Also, since
251 bindings are invoked so often and relied upon in QML usage, users of your
252 custom QML types may see unexpected behavior if bindings are not implemented.
253
254 */
255
256 /*!
257 \title Chapter 4: Using Custom Property Types
258
259 \example declarative/tutorials/extending/chapter4-customPropertyTypes
260
261 The \c PieChart type currently has a string-type property and a color-type property.
262 It could have many other types of properties. For example, it could have an
263 int-type property to store an identifier for each chart:
264
265 \code
266     // C++
267     class PieChart : public QDeclarativeItem
268     {
269         Q_PROPERTY(int chartId READ chartId WRITE setChartId NOTIFY chartIdChanged)
270         ...
271
272     public:
273         void setChartId(int chartId);
274         int chartId() const;
275         ...
276
277     signals:
278         void chartIdChanged();
279     };
280
281     // QML
282     PieChart {
283         ...
284         chartId: 100
285     }
286 \endcode
287
288 We can also use various other property types. QML has built-in support for the types
289 listed in the \l{QML Basic Types} documentation, which includes the following:
290
291 \list
292 \o bool, unsigned int, int, float, double, qreal
293 \o QString, QUrl, QColor
294 \o QDate, QTime, QDateTime
295 \o QPoint, QPointF, QSize, QSizeF, QRect, QRectF
296 \o QVariant
297 \endlist
298
299 If we want to create a property whose type is not supported by QML by default,
300 we need to register the type with QML.
301
302 For example, let's replace the use of the \c property with a type called
303 "PieSlice" that has a \c color property. Instead of assigning a color,
304 we assign an \c PieSlice value which itself contains a \c color:
305
306 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/app.qml 0
307
308 Like \c PieChart, this new \c PieSlice type inherits from QDeclarativeItem and declares
309 its properties with Q_PROPERTY():
310
311 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/pieslice.h 0
312
313 To use it in \c PieChart, we modify the \c color property declaration
314 and associated method signatures:
315
316 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h 0
317 \dots
318 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h 1
319 \dots
320 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h 2
321 \dots
322 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h 3
323
324 There is one thing to be aware of when implementing \c setPieSlice(). The \c PieSlice
325 is a visual item, so it must be set as a child of the \c PieChart using
326 QDeclarativeItem::setParentItem() so that the \c PieChart knows to paint this child
327 item when its contents are drawn:
328
329 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.cpp 0
330
331
332 Like the \c PieChart type, the \c PieSlice type has to be registered
333 using qmlRegisterType() to be used from QML. As with \c PieChart, we'll add the
334 type to the "Charts" module, version 1.0:
335
336 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/main.cpp 0
337 \dots
338 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/main.cpp 1
339 \dots
340 \snippet declarative/tutorials/extending/chapter4-customPropertyTypes/main.cpp 2
341
342 Try it out with the code in Qt's \c examples/tutorials/extending/chapter4-customPropertyTypes directory.
343
344 */
345
346
347 /*!
348 \title Chapter 5: Using List Property Types
349
350 \example declarative/tutorials/extending/chapter5-listproperties
351
352 Right now, a \c PieChart can only have one \c PieSlice. Ideally a chart would
353 have multiple slices, with different colors and sizes. To do this, we could
354 have a \c slices property that accepts a list of \c PieSlice items:
355
356 \snippet declarative/tutorials/extending/chapter5-listproperties/app.qml 0
357
358 \image extending-tutorial-chapter5.png
359
360 To do this, we replace the \c pieSlice property in \c PieChart with a \c slices property,
361 declared as a QDeclarativeListProperty type. The QDeclarativeListProperty class enables the
362 creation of list properties in QML extensions. We replace the \c pieSlice()
363 function with a \c slices() function that returns a list of slices, and add
364 an internal \c append_slice() function (discussed below). We also use a QList to
365 store the internal list of slices as \c m_slices:
366
367 \snippet declarative/tutorials/extending/chapter5-listproperties/piechart.h 0
368 \dots
369 \snippet declarative/tutorials/extending/chapter5-listproperties/piechart.h 1
370 \dots
371 \snippet declarative/tutorials/extending/chapter5-listproperties/piechart.h 2
372
373 Although the \c slices property does not have an associated \c WRITE function,
374 it is still modifiable because of the way QDeclarativeListProperty works.
375 In the \c PieChart implementation, we implement \c PieChart::slices() to
376 return a QDeclarativeListProperty value and indicate that the internal
377 \c PieChart::append_slice() function is to be called whenever a request is made from QML
378 to add items to the list:
379
380 \snippet declarative/tutorials/extending/chapter5-listproperties/piechart.cpp 0
381
382 The \c append_slice() function simply sets the parent item as before,
383 and adds the new item to the \c m_slices list. As you can see, the append function for a
384 QDeclarativeListProperty is called with two arguments: the list property, and
385 the item that is to be appended.
386
387 The \c PieSlice class has also been modified to include \c fromAngle and \c angleSpan
388 properties and to draw the slice according to these values. This is a straightforward
389 modification if you have read the previous pages in this tutorial, so the code is not shown here.
390
391 The complete code can be seen in the updated \c examples/tutorials/extending/chapter5-listproperties directory.
392
393 */
394
395
396 /*!
397 \title Chapter 6: Writing an Extension Plugin
398
399 \example declarative/tutorials/extending/chapter6-plugins
400
401 Currently the \c PieChart and \c PieSlice types are used by \c app.qml,
402 which is displayed using a QDeclarativeView in a C++ application. An alternative
403 way to use our QML extension is to create a plugin library to make it available
404 to the QML engine. This allows \c app.qml to be loaded with the \l {QML Viewer}
405 (or some other QML \l{Qt Declarative UI Runtime}{runtime} application) instead of writing a \c main.cpp file and
406 loading our own C++ application.
407
408 To create a plugin library, we need:
409
410 \list
411 \o A plugin class that registers our QML types
412 \o A project file that describes the plugin
413 \o A \l{Writing a qmldir file}{qmldir} file that tells the QML engine to load the plugin
414 \endlist
415
416 First, we create a plugin class named \c ChartsPlugin. It subclasses QDeclarativeExtensionPlugin
417 and registers our QML types in the inherited \l{QDeclarativeExtensionPlugin::}{registerTypes()} method. It also calls
418 Q_EXPORT_PLUGIN2 for Qt's \l{How to Create Qt Plugins}{plugin system}.
419
420 Here is the \c ChartsPlugin definition in \c chartsplugin.h:
421
422 \snippet declarative/tutorials/extending/chapter6-plugins/chartsplugin.h 0
423
424 And its implementation in \c chartsplugin.cpp:
425
426 \snippet declarative/tutorials/extending/chapter6-plugins/chartsplugin.cpp 0
427
428 Then, we write a \c .pro project file that defines the project as a plugin library
429 and specifies with DESTDIR that library files should be built into a "lib" subdirectory:
430
431 \quotefile declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro
432
433 Finally, we add a \l{Writing a qmldir file}{qmldir} file that is automatically parsed by the QML engine.
434 In this file, we specify that a plugin named "chapter6-plugin" (the name
435 of the example project) can be found in the "lib" subdirectory:
436
437 \quotefile declarative/tutorials/extending/chapter6-plugins/qmldir
438
439 Now we have a plugin, and instead of having a main.cpp and an executable, we can build
440 the project and then load the QML file in the \l {QML Viewer}:
441
442 \code
443     qmlviewer app.qml
444 \endcode
445
446 (On Mac OS X, you can launch the "QMLViewer" application instead.)
447
448 Notice the "import Charts 1.0" statement has disappeared from \c app.qml. This is
449 because the \c qmldir file is in the same directory as \c app.qml: this is equivalent to
450 having PieChart.qml and PieSlice.qml files inside the project directory, which could both
451 be used by \c app.qml without import statements.
452 */
453
454
455 /*!
456 \page qml-extending-tutorial7.html
457 \title Chapter 7: In Summary
458
459 In this tutorial, we've shown the basic steps for creating a QML extension:
460
461 \list
462 \o Define new QML types by subclassing QObject and registering them with qmlRegisterType()
463 \o Add callable methods using Q_INVOKABLE or Qt slots, and connect to Qt signals with an \c onSignal syntax
464 \o Add property bindings by defining \l{Qt's Property System}{NOTIFY} signals
465 \o Define custom property types if the built-in types are not sufficient
466 \o Define list property types using QDeclarativeListProperty
467 \o Create a plugin library by defining a Qt plugin and writing a \c qmldir file
468 \endlist
469
470
471 The \l {Extending QML Functionalities using C++} reference documentation shows
472 other useful features that can be added to QML extensions. For example, we
473 could use \l{Default Property}{default properties} to allow
474 slices to be added without using the \c slices property:
475
476 \code
477     PieChart {
478         PieSlice { ... }
479         PieSlice { ... }
480         PieSlice { ... }
481     }
482 \endcode
483
484 Or randomly add and remove slices from time to time using \l{Property Value Sources}{property value sources}:
485
486 \code
487     PieChart {
488         PieSliceRandomizer on slices {}
489     }
490 \endcode
491
492
493 See the \l{Extending QML Functionalities using C++} reference documentation
494 for more information.
495
496 */
497