Update copyright headers
[qt:qt.git] / doc / src / getting-started / gettingstartedqml.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the documentation of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Free Documentation License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Free
19 ** Documentation License version 1.3 as published by the Free Software
20 ** Foundation and appearing in the file included in the packaging of
21 ** this file.  Please review the following information to ensure
22 ** the GNU Free Documentation License version 1.3 requirements
23 ** will be met: http://www.gnu.org/copyleft/fdl.html.
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29     \page gettingstartedqml.html
30     \title Getting Started Programming with QML
31     \ingroup gettingStarted
32
33     Welcome to the world of QML, the declarative UI language. In this Getting
34     Started guide, we will create a simple text editor application using QML.
35     After reading this guide, you should be ready to develop your own applications
36     using QML and Qt C++.
37
38     \section1 Installation
39
40     First, we would need to install the latest version of Qt that includes \l{Qt
41     Quick}, which is Qt 4.7. The \l{Installation} {installation} guide contains
42     installation instructions and requirements for different platforms.
43
44     Qt Quick includes a declarative language called
45     \l{Introduction to the QML language}{QML}, the \l{Qt Declarative Module}, and
46     \l{QML Viewer}.
47
48     \section1 QML to Build User Interfaces
49
50     The application we are building is a simple text editor that will load, save,
51     and perform some text manipulation. This guide will consist of two parts. The
52     first part will involve designing the application layout and behaviors using
53     declarative language in QML. For the second part, file loading and saving will
54     be implemented using Qt C++. Using
55     \l {The Meta-Object System}{Qt's Meta-Object System}, we can expose C++ functions
56     as properties that QML elements can use. Utilizing QML and Qt C++, we can
57     efficiently decouple the interface logic from the application logic.
58
59     \image qml-texteditor5_editmenu.png
60
61     The final source code is in the \c{examples/tutorials/gettingStarted/gsQml}
62     directory. You may need to compile the C++ plugin in the
63     \c{examples/tutorials/gettingStarted/gsQml/} first. This will put the
64     C++ plugin in a directory where the QML files may find it.
65
66     To launch the text editor, merely provide the included \l{QML Viewer}{qmlviewer}
67     tool with the QML file as the argument. The C++ portion of this tutorial assumes
68     that the reader possesses basic knowledge of Qt's compilation procedures.
69
70     Tutorial chapters:
71     \list 1
72         \o \l {Defining a Button and a Menu}{Defining a Button and a Menu}
73         \o \l {Implementing a Menu Bar}{Implementing a Menu Bar}
74         \o \l {Building a Text Editor}{Building a Text Editor}
75         \o \l {Decorating the Text Editor}{Decorating the Text Editor}
76         \o \l {Extending QML using Qt C++}{Extending QML using Qt C++}
77     \endlist
78
79     \section1 Defining a Button and a Menu
80
81     \section2 Basic Component - a Button
82
83     We start our text editor by building a button. Functionally, a button has a mouse
84     sensitive area and a label. Buttons perform actions when a user presses the button.
85
86     In QML, the basic visual item is the \l {Rectangle}{Rectangle} element. The
87     \c Rectangle element has properties to control the element's appearance and location.
88
89     \snippet examples/tutorials/gettingStarted/gsQml/parts/part0/Button.qml document
90
91     First, the \c { import QtQuick 1.0 } allows the qmlviewer tool to import the QML elements
92     we will later use. This line must exist for every QML file. Notice that the version
93     of Qt modules is included in the import statement.
94
95     This simple rectangle has a unique identifier, \c simplebutton, which is bound to the
96     id property. The \c Rectangle element's properties are bound to values by listing the
97     property, followed by a colon, then the value. In the code sample, the color \c grey
98     is bound to the the Rectangle's \c color property. Similarly, we bind the \c width
99     and \c height of the Rectangle.
100
101     The \l {Text}{Text} element is a non-editable text field. We name this \c Text element
102     \c buttonLabel. To set the string content of the Text field, we bind a value to the
103     \c text property. The label is contained within the Rectangle and in order to center
104     it in the middle, we assign the \c anchors of the Text element to its parent, which
105     is called \c simplebutton. Anchors may bind to other items' anchors, allowing layout
106     assignments simpler.
107
108     We shall save this code as \c SimpleButton.qml. Running qmlviewer with the file as the
109     argument will display the grey rectangle with a text label.
110
111     \image qml-texteditor1_simplebutton.png
112
113     To implement the button click functionality, we can use QML's event handling. QML's event
114     handling is very similar to \l {Signals & Slots}{Qt's signal and slot} mechanism. Signals
115     are emitted and the connected slot is called.
116
117     \code
118         Rectangle{
119             id:simplebutton
120             ...
121
122             MouseArea{
123                 id: buttonMouseArea
124
125                 anchors.fill: parent //anchor all sides of the mouse area to the rectangle's anchors
126                         //onClicked handles valid mouse button clicks
127                 onClicked: console.log(buttonLabel.text + " clicked" )
128             }
129         }
130     \endcode
131
132     We include a \l{MouseArea} element in our simplebutton. \c MouseArea elements describe
133     the interactive area where mouse movements are detected. For our button, we anchor the
134     whole MouseArea to its parent, which is \c simplebutton. The \c anchors.fill syntax is
135     one way of accessing a specific property called \c fill inside a group of properties
136     called \c anchors. QML uses \l {Anchor-Based Layout in QML}{anchor-based layouts} where
137     items can anchor to another item, creating robust layouts.
138
139     The \c MouseArea has many signal handlers that are called during mouse movements within
140     the specified \c MouseArea boundaries. One of them is \c onClicked and it is called
141     whenever the acceptable mouse button is clicked, the left click being the default. We
142     can bind actions to the onClicked handler. In our example, \c console.log() outputs text
143     whenever the mouse area is clicked. The function \c console.log() is a useful tool for
144     debugging purposes and for outputting text.
145
146     The code in \c SimpleButton.qml is sufficient to display a button on the screen and
147     output text whenever it is clicked with a mouse.
148
149     \code
150         Rectangle {
151             id: button
152             ...
153
154             property color buttonColor: "lightblue"
155             property color onHoverColor: "gold"
156             property color borderColor: "white"
157
158             signal buttonClick()
159             onButtonClick: {
160                 console.log(buttonLabel.text + " clicked" )
161             }
162
163             MouseArea{
164                 onClicked: buttonClick()
165                 hoverEnabled: true
166                 onEntered: parent.border.color = onHoverColor
167                 onExited:  parent.border.color = borderColor
168             }
169
170             //determines the color of the button by using the conditional operator
171             color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor
172         }
173     \endcode
174
175     A fully functioning button is in \c Button.qml. The code snippets in this article
176     have some code omitted, denoted by ellipses because they were either introduced
177     earlier in the previous sections or irrelevant to the current code discussion.
178
179     Custom properties are declared using the \c {property type name} syntax. In the
180     code, the property \c buttonColor, of type \c color, is declared and bound to
181     the value \c{"lightblue"}. The \c buttonColor is later used in a conditional
182     operation to determine the buttons's fill color. Note that property value
183     assignment is possible using the \c= equals sign, in addition to value binding
184     using the \c : colon character. Custom properties allow internal items to be
185     accessible outside of the Rectangle's scope. There are basic
186     \l{QML Basic Types}{QML types} such as \c int, \c string, \c real, as well as
187     a type called \c variant.
188
189     By binding the \c onEntered and \c onExited signal handlers to colors, the
190     button's border will turn yellow when the mouse hovers above the button and
191     reverts the color when the mouse exits the mouse area.
192
193     A \c buttonClick() signal is declared in \c Button.qml by placing the \c signal
194     keyword in front of the signal name. All signals have their handlers automatically
195     created, their names starting with \c on. As a result, the \c onButtonClick is
196     \c buttonClick's handler. The \c onButtonClick is then assigned an action to
197     perform. In our button example, the \c onClicked mouse handler will simply call
198     \c onButtonClick, which displays a text. The \c onButtonClick enables outside
199     objects to access the \c {Button}'s mouse area easily. For example, items may
200     have more than one \c MouseArea declarations and a \c buttonClick signal can
201     make the distinction between the several \c MouseArea signal handlers better.
202
203     We now have the basic knowledge to implement items in QML that can handle
204     basic mouse movements. We created a \c Text label inside a \c Rectangle,
205     customized its properties, and implemented behaviors that respond to mouse
206     movements. This idea of creating elements within elements is repeated
207     throughout the text editor application.
208
209     This button is not useful unless used as a component to perform an action.
210     In the next section, we will soon create a menu containing several of these
211     buttons.
212
213     \image qml-texteditor1_button.png
214
215     \section2 Creating a Menu Page
216
217     Up to this stage, we covered how to create elements and assign behaviors inside
218     a single QML file. In this section, we will cover how to import QML elements and how
219     to reuse some of the created components to build other components.
220
221     Menus display the contents of a list, each item having the ability to perform an action.
222     In QML, we can create a menu in several ways. First, we will create a menu containing
223     buttons which will eventually perform different actions. The menu code is in
224     \c FileMenu.qml.
225
226     \code
227         import QtQuick 1.0                \\import the main Qt QML module
228         import "folderName"            \\import the contents of the folder
229         import "script.js" as Script        \\import a Javascript file and name it as Script
230     \endcode
231
232     The syntax shown above shows how to use the \c import keyword. This is required to
233     use JavaScript files, or QML files that are not within the same directory. Since
234     \c Button.qml is in the same directory as \c FileMenu.qml, we do not need to import
235     the \c Button.qml file to use it. We can directly create a \c Button element by declaring
236     \c Button{}, similar to a \c Rectangle{} declaration.
237
238     \code
239     In FileMenu.qml:
240
241         Row{
242             anchors.centerIn: parent
243             spacing: parent.width/6
244
245             Button{
246                 id: loadButton
247                 buttonColor: "lightgrey"
248                 label: "Load"
249             }
250             Button{
251                 buttonColor: "grey"
252                 id: saveButton
253                 label: "Save"
254             }
255             Button{
256                 id: exitButton
257                 label: "Exit"
258                 buttonColor: "darkgrey"
259
260                 onButtonClick: Qt.quit()
261             }
262         }
263     \endcode
264
265     In \c FileMenu.qml, we declare three \c Button elements. They are declared
266     inside a \l {Row}{Row} element, a positioner that will position its children
267     along a vertical row. The \c Button declaration resides in Button.qml,
268     which is the same as the \c Button.qml we used in the previous section.
269     New property bindings can be declared within the newly created buttons,
270     effectively overwriting the properties set in \c Button.qml. The button
271     called \c exitButton will quit and close the window when it is clicked.
272     Note that the signal handler \c onButtonClick in \c Button.qml will be
273     called in addition to the \c onButtonClick handler in \c exitButton.
274
275     \image qml-texteditor1_filemenu.png
276
277     The \c Row declaration is declared in a \c Rectangle, creating a rectangle
278     container for the row of buttons. This additional rectangle creates an indirect
279     way of organizing the row of buttons inside a menu.
280
281     The declaration of the edit menu is very similar at this stage. The menu has
282     buttons that have the labels: \c Copy, \c Paste, and \c {Select All}.
283
284     \image qml-texteditor1_editmenu.png
285
286     Armed with our knowledge of importing and customizing previously made
287     components, we may now combine these menu pages to create a menu bar,
288     consisting of buttons to select the menu, and look at how we may structure
289     data using QML.
290
291     \section1 Implementing a Menu Bar
292
293     Our text editor application will need a way to display menus using a menu bar.
294     The menu bar will switch the different menus and the user can choose which menu
295     to display. Menu switching implies that the menus need more structure than
296     merely displaying them in a row. QML uses models and views to structure data
297     and display the structured data.
298
299     \section2  Using Data Models and Views
300
301     QML has different \l{QML Data Models}{data views} that display
302     \l{QML Data Models}{data models}. Our menu bar will display the menus in a list,
303     with a header that displays a row of menu names. The list of menus are declared
304     inside a \c VisualItemModel. The \l{VisualItemModel}{\c VisualItemModel}
305     element contains items that already have views such as \c Rectangle elements
306     and imported UI elements. Other model types such as the \l{ListModel}{\c ListModel}
307     element need a delegate to display their data.
308
309     We declare two visual items in the \c menuListModel, the \c FileMenu and the
310     \c EditMenu. We customize the two menus and display them using a
311     \l {ListView}{ListView}. The \c MenuBar.qml file contains the QML declarations
312     and a simple edit menu is defined in \c EditMenu.qml.
313
314     \code
315         VisualItemModel{
316             id: menuListModel
317             FileMenu{
318                 width: menuListView.width
319                 height: menuBar.height
320                 color: fileColor
321             }
322             EditMenu{
323                 color: editColor
324                 width:  menuListView.width
325                 height: menuBar.height
326             }
327         }
328     \endcode
329
330     The \l {ListView}{ListView} element will display a model according to a delegate.
331     The delegate may declare the model items to display in a \c Row element or display
332     the items in a grid. Our \c menuListModel already has visible items, therefore,
333     we do not need to declare a delegate.
334
335     \code
336         ListView{
337             id: menuListView
338
339             //Anchors are set to react to window anchors
340             anchors.fill:parent
341             anchors.bottom: parent.bottom
342             width:parent.width
343             height: parent.height
344
345             //the model contains the data
346             model: menuListModel
347
348             //control the movement of the menu switching
349             snapMode: ListView.SnapOneItem
350             orientation: ListView.Horizontal
351             boundsBehavior: Flickable.StopAtBounds
352             flickDeceleration: 5000
353             highlightFollowsCurrentItem: true
354             highlightMoveDuration:240
355             highlightRangeMode: ListView.StrictlyEnforceRange
356         }
357     \endcode
358
359     Additionally, \c ListView inherits from \l{Flickable}{\c Flickable}, making
360     the list respond to mouse drags and other gestures. The last portion of the
361     code above sets \c Flickable properties to create the desired flicking movement
362     to our view. In particular,the property \c highlightMoveDuration changes the
363     duration of the flick transition. A higher \c highlightMoveDuration value
364     results in slower menu switching.
365
366     The \c ListView maintains the model items through an \c index and each visual
367     item in the model is accessible through the \c index, in the order of the
368     declaration. Changing the \c currentIndex effectively changes the highlighted
369     item in the \c ListView. The header of our menu bar exemplify this effect.
370     There are two buttons in a row, both changing the current menu when clicked.
371     The \c fileButton changes the current menu to the file menu when clicked,
372     the \c index being \c 0 because \c FileMenu is declared first in the
373     \c menuListModel. Similarly, the \c editButton will change the current
374     menu to the \c EditMenu when clicked.
375
376     The \c labelList rectangle has \c z value of \c 1, denoting that it is displayed
377     at the front of the menu bar. Items with higher \c z values are displayed in front
378     of items with lower \c z values. The default \c z value is \c 0.
379
380     \code
381         Rectangle{
382             id: labelList
383             ...
384             z: 1
385             Row{
386                 anchors.centerIn: parent
387                 spacing:40
388                 Button{
389                     label: "File"
390                     id: fileButton
391                     ...
392                     onButtonClick: menuListView.currentIndex = 0
393                 }
394                 Button{
395                     id: editButton
396                     label: "Edit"
397                     ...
398                     onButtonClick:    menuListView.currentIndex = 1
399                 }
400             }
401         }
402     \endcode
403
404     The menu bar we just created can be flicked to access the menus or by clicking
405     on the menu names at the top. Switching menu screens feel intuitive and responsive.
406
407     \image qml-texteditor2_menubar.png
408
409     \section1 Building a Text Editor
410
411     \section2 Declaring a TextArea
412
413     Our text editor is not a text editor if it didn't contain an editable text area.
414     QML's \l {TextEdit}{TextEdit} element allows the declaration of a multi-line
415     editable text area. \l {TextEdit}{TextEdit} is different from a \l {Text}{Text}
416     element, which doesn't allow the user to directly edit the text.
417
418     \code
419         TextEdit{
420             id: textEditor
421             anchors.fill:parent
422             width:parent.width; height:parent.height
423             color:"midnightblue"
424             focus: true
425
426             wrapMode: TextEdit.Wrap
427
428             onCursorRectangleChanged: flickArea.ensureVisible(cursorRectangle)
429         }
430     \endcode
431
432     The editor has its font color property set and set to wrap the text. The
433     \c TextEdit area is inside a flickable area that will scroll the text if the
434     text cursor is outside the visible area. The function \c ensureVisible() will
435     check if the cursor rectangle is outside the visible boundaries and move the
436     text area accordingly. QML uses Javascript syntax for its scripts, and as previously
437     mentioned, Javascript files can be imported and used within a QML file.
438
439     \code
440         function ensureVisible(r){
441             if (contentX >= r.x)
442                 contentX = r.x;
443             else if (contentX+width <= r.x+r.width)
444                 contentX = r.x+r.width-width;
445             if (contentY >= r.y)
446                 contentY = r.y;
447             else if (contentY+height <= r.y+r.height)
448                 contentY = r.y+r.height-height;
449         }
450     \endcode
451
452     \section2 Combining Components for the Text Editor
453
454     We are now ready to create the layout of our text editor using QML. The text
455     editor has two components, the menu bar we created and the text area. QML allows
456     us to reuse components, therefore making our code simpler, by importing components
457     and customizing when necessary. Our text editor splits the window into two;
458     one-third of the screen is dedicated to the menu bar and two-thirds of the screen
459     displays the text area. The menu bar is displayed in front of any other elements.
460
461     \code
462         Rectangle{
463
464             id: screen
465             width: 1000; height: 1000
466
467             //the screen is partitioned into the MenuBar and TextArea. 1/3 of the screen is assigned to the MenuBar
468             property int partition: height/3
469
470             MenuBar{
471                 id:menuBar
472                 height: partition
473                 width:parent.width
474                 z: 1
475             }
476
477             TextArea{
478                 id:textArea
479                 anchors.bottom:parent.bottom
480                 y: partition
481                 color: "white"
482                 height: partition*2
483                 width:parent.width
484             }
485         }
486     \endcode
487
488     By importing reusable components, our \c TextEditor code looks much simpler.
489     We can then customize the main application, without worrying about properties
490     that already have defined behaviors. Using this approach, application layouts
491     and UI components can be created easily.
492
493     \image qml-texteditor3_texteditor.png
494
495     \section1 Decorating the Text Editor
496     \section2 Implementing a Drawer Interface
497
498     Our text editor looks simple and we need to decorate it. Using QML, we can declare
499     transitions and animate our text editor. Our menu bar is occupying one-third of the
500     screen and it would be nice to have it only appear when we want it.
501
502     We can add a drawer interface, that will contract or expand the menu bar when clicked.
503     In our implementation, we have a thin rectangle that responds to mouse clicks. The
504     \c drawer, as well as the application, has two sates: the "drawer is open" state and
505     the "drawer is closed" state. The \c drawer item is a strip of rectangle with a small
506     height. There is a nested \l {Image}{Image} element declaring that an arrow icon will
507     be centered inside the drawer. The drawer assigns a state to the whole application,
508     with the identifier \c screen, whenever a user clicks the mouse area.
509
510     \code
511         Rectangle{
512             id:drawer
513             height:15
514
515             Image{
516                 id: arrowIcon
517                 source: "images/arrow.png"
518                 anchors.horizontalCenter: parent.horizontalCenter
519             }
520
521             MouseArea{
522                 id: drawerMouseArea
523                 anchors.fill:parent
524                 onClicked:{
525                     if (screen.state == "DRAWER_CLOSED"){
526                         screen.state = "DRAWER_OPEN"
527                     }
528                     else if (screen.state == "DRAWER_OPEN"){
529                         screen.state = "DRAWER_CLOSED"
530                     }
531                 }
532                 ...
533             }
534         }
535     \endcode
536
537     A state is simply a collection of configurations and it is declared in a
538     \l{State}{State} element. A list of states can be listed and bound to the
539     \c states property. In our application, the two states are called
540     \c DRAWER_CLOSED and \c DRAWER_OPEN. Item configurations are declared in
541     \l {PropertyChanges}{PropertyChanges} elements. In the \c DRAWER_OPEN state,
542     there are four items that will receive property changes. The first target,
543     \c menuBar, will change its \c y property to \c 0. Similarly, the \c textArea
544     will lower to a new position when the state is \c DRAWER_OPEN. The \c textArea,
545     the \c drawer, and the drawer's icon will undergo property changes to meet the
546     current state.
547
548     \snippet examples/tutorials/gettingStarted/gsQml/texteditor.qml states
549
550     State changes are abrupt and needs smoother transitions. Transitions between states
551     are defined using the \l {Transition}{Transition} element, which can then bind to
552     the item's \c transitions property. Our text editor has a state transition whenever
553     the state changes to either \c DRAWER_OPEN or \c DRAWER_CLOSED. Importantly, the
554     transition needs a \c from and a \c to state but for our transitions, we can use
555     the wild card \c * symbol to denote that the transition applies to all state changes.
556
557     During transitions, we can assign animations to the property changes. Our
558     \c menuBar switches position from \c {y:0} to \c {y:-partition} and we can animate
559     this transition using the \l {NumberAnimation}{NumberAnimation} element. We declare
560     that the targets' properties will animate for a certain duration of time and using
561     a certain easing curve. An easing curve controls the animation rates and
562     interpolation behavior during state transitions. The easing curve we chose is
563     \l{PropertyAnimation::easing.type}{Easing.OutQuint}, which slows the movement near
564     the end of the animation. Please read \l {qdeclarativeanimation.html}{QML's Animation}
565     article.
566
567     \snippet examples/tutorials/gettingStarted/gsQml/texteditor.qml transitions
568
569     Another way of animating property changes is by declaring a \l {Behavior}{Behavior}
570     element. A transition only works during state changes and \c Behavior can set an
571     animation for a general property change. In the text editor, the arrow has a
572     \c NumberAnimation animating its \c rotation property whenever the property changes.
573
574     \code
575     In TextEditor.qml:
576
577         Behavior{
578             NumberAnimation{property: "rotation";easing.type: Easing.OutExpo }
579         }
580     \endcode
581
582     Going back to our components with knowledge of states and animations, we can improve
583     the appearances of the components. In \c Button.qml, we can add \c color and \c scale
584     property changes when the button is clicked. Color types are animated using
585     \l {ColorAnimation}{ColorAnimation} and numbers are animated using
586     \l {NumberAnimation}{NumberAnimation}. The \c {on propertyName} syntax displayed below
587     is helpful when targeting a single property.
588
589     \code
590     In Button.qml:
591         ...
592
593         color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor
594         Behavior on color { ColorAnimation{ duration: 55} }
595
596         scale: buttonMouseArea.pressed ? 1.1 : 1.00
597         Behavior on scale { NumberAnimation{ duration: 55} }
598     \endcode
599
600     Additionally, we can enhance the appearances of our QML components by adding color
601     effects such as gradients and opacity effects. Declaring a \l {Gradient}{Gradient}
602     element will override the \c color property of the element. You may declare a color
603     in the gradient using the \l {GradientStop}{GradientStop} element. The gradient is
604     positioned using a scale, between \c 0.0 and \c 1.0.
605
606     \code
607     In MenuBar.qml
608         gradient: Gradient {
609             GradientStop { position: 0.0; color: "#8C8F8C" }
610             GradientStop { position: 0.17; color: "#6A6D6A" }
611             GradientStop { position: 0.98;color: "#3F3F3F" }
612             GradientStop { position: 1.0; color: "#0e1B20" }
613         }
614     \endcode
615
616     This gradient is used by the menu bar to display a gradient simulating depth.
617     The first color starts at \c 0.0 and the last color is at \c 1.0.
618
619
620     \section3 Where to Go from Here
621
622         We are finished building the user interface of a very simple text editor.
623         Going forward, the user interface is complete, and we can implement the
624         application logic using regular Qt and C++. QML works nicely as a prototyping
625         tool, separating the application logic away from the UI design.
626
627     \image qml-texteditor4_texteditor.png
628
629     \section2 Extending QML using Qt C++
630
631     Now that we have our text editor layout, we may now implement the text editor
632     functionalities in C++. Using QML with C++ enables us to create our application
633     logic using Qt. We can create a QML context in a C++ application using the
634     \l {Using QML Bindings in C++ Applications}{Qt's Declarative} classes and display the QML
635     elements using a Graphics Scene. Alternatively, we can export our C++ code into
636     a plugin that the \l {QML Viewer}{qmlviewer} tool can read. For our application,
637     we shall implement the load and save functions in C++ and export it as a plugin.
638     This way, we only need to load the QML file directly instead of running an executable.
639
640     \section3 Exposing C++ Classes to QML
641
642     We will be implementing file loading and saving using Qt and C++. C++ classes
643     and functions can be used in QML by registering them. The class also needs to be
644     compiled as a Qt plugin and the QML file will need to know where the plugin is located.
645
646     For our application, we need to create the following items:
647     \list 1
648     \o \c Directory class that will handle directory related operations
649     \o \c File class which is a QObject, simulating the list of files in a directory
650     \o plugin class that will register the class to the QML context
651     \o Qt project file that will compile the plugin
652     \o A \c qmldir file telling the qmlviewer tool where to find the plugin
653     \endlist
654
655     \section3 Building a Qt Plugin
656
657         To build a plugin, we need to set the following in a Qt project file. First,
658         the necessary sources, headers, and Qt modules need to be added into our
659         project file. All the C++ code and project files are in the \c filedialog
660         directory.
661
662     \code
663     In filedialog.pro:
664
665         TEMPLATE = lib
666         CONFIG += qt plugin
667         QT += declarative
668
669         DESTDIR +=  ../plugins
670         OBJECTS_DIR = tmp
671         MOC_DIR = tmp
672
673         TARGET = FileDialog
674
675         HEADERS +=     directory.h \
676                 file.h \
677                 dialogPlugin.h
678
679         SOURCES +=    directory.cpp \
680                 file.cpp \
681                 dialogPlugin.cpp
682     \endcode
683
684     In particular, we compile Qt with the \c declarative module and configure it as a
685     \c plugin, needing a \c lib template. We shall put the compiled plugin into the
686     parent's \c plugins directory.
687
688
689     \section3 Registering a Class into QML
690
691     \code
692     In dialogPlugin.h:
693
694         #include <QtDeclarative/QDeclarativeExtensionPlugin>
695
696         class DialogPlugin : public QDeclarativeExtensionPlugin
697         {
698             Q_OBJECT
699
700             public:
701             void registerTypes(const char *uri);
702
703         };
704
705     \endcode
706
707     Our plugin class, \c DialogPlugin is a subclass of \l{QDeclarativeExtensionPlugin}.
708     We need to implement the inherited function, \l {QDeclarativeExtensionPlugin::}{registerTypes()}.
709     The \c dialogPlugin.cpp file looks like this:
710
711     \code
712     DialogPlugin.cpp:
713
714         #include "dialogPlugin.h"
715         #include "directory.h"
716         #include "file.h"
717         #include <QtDeclarative/qdeclarative.h>
718
719         void DialogPlugin::registerTypes(const char *uri){
720
721             qmlRegisterType<Directory>(uri, 1, 0, "Directory");
722             qmlRegisterType<File>(uri, 1, 0,"File");
723         }
724
725         Q_EXPORT_PLUGIN2(FileDialog, DialogPlugin);
726     \endcode
727
728     The \l{QDeclarativeExtensionPlugin::}{registerTypes()} function registers
729     our File and Directory classes into QML. This function needs the class name
730     for its template, a major version number, a minor version number, and a name
731     for our classes.
732
733     We need to export the plugin using the \l {Q_EXPORT_PLUGIN2}{Q_EXPORT_PLUGIN2}
734     macro. Note that in our \c dialogPlugin.h file, we have the \l {Q_OBJECT}{Q_OBJECT}
735     macro at the top of our class. As well, we need to run \c qmake on the project
736     file to generate the necessary meta-object code.
737
738
739     \section3 Creating QML Properties in a C++ class
740
741         We can create QML elements and properties using C++ and
742         \l {The Meta-Object System}{Qt's Meta-Object System}. We can implement
743         properties using slots and signals, making Qt aware of these properties.
744         These properties can then be used in QML.
745
746     For the text editor, we need to be able to load and save files. Typically,
747     these features are contained in a file dialog. Fortunately, we can use
748     \l {QDir}{QDir}, \l {QFile}{QFile}, and \l {QTextStream}{QTextStream} to
749     implement directory reading and input/output streams.
750
751     \code
752         class Directory : public QObject{
753
754             Q_OBJECT
755
756             Q_PROPERTY(int filesCount READ filesCount CONSTANT)
757             Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)
758             Q_PROPERTY(QString fileContent READ fileContent WRITE setFileContent NOTIFY fileContentChanged)
759             Q_PROPERTY(QDeclarativeListProperty<File> files READ files CONSTANT )
760
761             ...
762     \endcode
763
764     The \c Directory class uses Qt's Meta-Object System to register properties it
765     needs to accomplish file handling. The \c Directory class is exported as a plugin
766     and is useable in QML as the \c Directory element. Each of the listed properties
767     using the \l {Q_PROPERTY()}{Q_PROPERTY} macro is a QML property.
768
769     The \l {Q_PROPERTY()} {Q_PROPERTY} declares a property as well as its read and
770     write functions into Qt's Meta-Object System. For example, the \c filename
771     property, of type \l {QString}{QString}, is readable using the \c filename()
772     function and writable using the function \c setFilename(). Additionally, there
773     is a signal associated to the filename property called \c filenameChanged(),
774     which is emitted whenever the property changes. The read and write functions
775     are declared as \c public in the header file.
776
777     Similarly, we have the other properties declared according to their uses. The
778     \c filesCount property indicates the number of files in a directory. The filename
779     property is set to the currently selected file's name and the loaded/saved file
780     content is stored in \c fileContent property.
781
782     \code
783         Q_PROPERTY(QDeclarativeListProperty<File> files READ files CONSTANT )
784     \endcode
785
786     The \c files list property is a list of all the filtered files in a directory.
787     The \c Directory class is implemented to filter out invalid text files; only
788     files with a \c .txt extension are valid. Further, \l{QList}s can be
789     used in QML files by declaring them as a QDeclarativeListProperty in C++.
790     The templated object needs to inherit from a QObject, therefore,
791     the \c File class must also inherit from QObject. In the \c Directory class,
792     the list of \c File objects is stored in a QList called \c m_fileList.
793
794     \code
795         class File : public QObject{
796
797             Q_OBJECT
798             Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
799
800             ...
801         };
802     \endcode
803
804     The properties can then be used in QML as part of the \c Directory element's
805     properties. Note that we do not have to create an identifier \c id property
806     in our C++ code.
807
808     \code
809         Directory{
810             id: directory
811
812             filesCount
813             filename
814             fileContent
815             files
816
817             files[0].name
818         }
819
820     \endcode
821
822     Because QML uses Javascript's syntax and structure, we can iterate through
823     the list of files and retrieve its properties. To retrieve the first file's
824     name property, we can call \c { files[0].name }.
825
826     Regular C++ functions are also accessible from QML. The file loading and saving
827     functions are implemented in C++ and declared using the
828     \l {Q_INVOKABLE}{Q_INVOKABLE} macro. Alternatively, we can declare the functions
829     as a \c slot and the functions will be accessible from QML.
830
831     \code
832     In Directory.h:
833
834         Q_INVOKABLE void saveFile();
835         Q_INVOKABLE void loadFile();
836     \endcode
837
838     The \c Directory class also has to notify other objects whenever the directory
839     contents change. This feature is performed using a \c signal. As previously
840     mentioned, QML signals have a corresponding handler with their names prepended
841     with \c on. The signal is called \c directoryChanged and it is emitted whenever
842     there is a directory refresh. The refresh simply reloads the directory contents
843     and updates the list of valid files in the directory. QML items can then be
844     notified by attaching an action to the \c onDirectoryChanged signal handler.
845
846     The \c list properties need to be explored further. This is because list
847     properties use callbacks to access and modify the list contents. The list
848     property is of type \c QDeclarativeListProperty<File>. Whenever the list
849     is accessed, the accessor function needs to return a
850     \c QDeclarativeListProperty<File>. The template type, \c File, needs to be a
851     \c QObject derivative. Further, to create the
852     \l {QDeclarativeListProperty}{QDeclarativeListProperty}, the list's accessor
853     and modifiers need to be passed to the constructor as function pointers. The list,
854     a \c QList in our case,  also needs to be a list of \c File pointers.
855
856     The constructor of \l {QDeclarativeListProperty}{QDeclarativeListProperty}
857     constructor and the \c Directory implementation:
858     \code
859         QDeclarativeListProperty  ( QObject * object, void * data, AppendFunction append, CountFunction count = 0, AtFunction at = 0, ClearFunction clear = 0 )
860         QDeclarativeListProperty<File>( this, &m_fileList, &appendFiles, &filesSize, &fileAt,  &clearFilesPtr );
861     \endcode
862
863     The constructor passes pointers to functions that will append the list, count
864     the list, retrieve the item using an index, and empty the list. Only the append
865     function is mandatory. Note that the function pointers must match the definition
866     of \l {QDeclarativeListProperty::AppendFunction}{AppendFunction},
867     \l {QDeclarativeListProperty::CountFunction}{CountFunction},
868     \l {QDeclarativeListProperty::AtFunction}{AtFunction}, or
869     \l {QDeclarativeListProperty::ClearFunction}{ClearFunction}.
870
871     \code
872         void appendFiles(QDeclarativeListProperty<File> * property, File * file)
873         File* fileAt(QDeclarativeListProperty<File> * property, int index)
874         int filesSize(QDeclarativeListProperty<File> * property)
875         void clearFilesPtr(QDeclarativeListProperty<File> *property)
876     \endcode
877
878     To simplify our file dialog, the \c Directory class filters out invalid text
879     files, which are files that do not have a \c .txt extension. If a file name
880     doesn't have the \c .txt extension, then it won't be seen in our file dialog.
881     Also, the implementation makes sure that saved files have a \c .txt extension in
882     the file name. \c Directory uses \l {QTextStream}{QTextStream} to read the file
883     and to output the file contents to a file.
884
885     With our \c Directory element, we can retrieve the files as a list, know how many
886     text files is in the application directory, get the file's name and content as a
887     string, and be notified whenever there are changes in the directory contents.
888
889     To build the plugin, run \c qmake on the \c filedialog.pro project file, then run
890     \c make to build and transfer the plugin to the \c plugins directory.
891
892
893     \section3 Importing a Plugin in QML
894
895         The qmlviewer tool imports files that are in the same directory as the
896         application. We can also create a \c qmldir file containing the locations of
897         QML files we wish to import. The \c qmldir file can also store locations of
898         plugins and other resources.
899
900     \code
901     In qmldir:
902
903         Button ./Button.qml
904         FileDialog ./FileDialog.qml
905         TextArea ./TextArea.qml
906         TextEditor ./TextEditor.qml
907         EditMenu ./EditMenu.qml
908
909         plugin FileDialog plugins
910     \endcode
911
912     The plugin we just created is called \c FileDialog, as indicated by the
913     \c TARGET field in the project file. The compiled plugin is in the \c plugins directory.
914
915
916     \section3 Integrating a File Dialog into the File Menu
917
918         Our \c FileMenu needs to display the \c FileDialog element, containing a list of
919         the text files in a directory thus allowing the user to select the file by
920         clicking on the list. We also need to assign the save, load, and new buttons
921         to their respective actions. The FileMenu contains an editable text input to
922         allow the user to type a file name using the keyboard.
923
924     The \c Directory element is used in the \c FileMenu.qml file and it notifies the
925     \c FileDialog element that the directory refreshed its contents. This notification
926     is performed in the signal handler, \c onDirectoryChanged.
927
928     \code
929     In FileMenu.qml:
930
931         Directory{
932             id:directory
933             filename: textInput.text
934             onDirectoryChanged: fileDialog.notifyRefresh()
935         }
936     \endcode
937
938     Keeping with the simplicity of our application, the file dialog will always be
939     visible and will not display invalid text files, which do not have a \c .txt
940     extension to their filenames.
941
942     \code
943     In FileDialog.qml:
944
945         signal notifyRefresh()
946         onNotifyRefresh: dirView.model = directory.files
947     \endcode
948
949     The \c FileDialog element will display the contents of a directory by reading its
950     list property called \c files. The files are used as the model of a
951     \l {GridView}{GridView} element, which displays data items in a grid according
952     to a delegate. The delegate handles the appearance of the model and our file
953     dialog will simply create a grid with text centered in the middle. Clicking on
954     the file name will result in the appearance of a rectangle to highlight the file
955     name. The \c FileDialog is notified whenever the \c notifyRefresh signal is emitted,
956     reloading the files in the directory.
957
958     \code
959     In FileMenu.qml:
960
961         Button{
962             id: newButton
963             label: "New"
964             onButtonClick:{
965                 textArea.textContent = ""
966             }
967         }
968         Button{
969             id: loadButton
970             label: "Load"
971             onButtonClick:{
972                 directory.filename = textInput.text
973                 directory.loadFile()
974                 textArea.textContent = directory.fileContent
975             }
976         }
977         Button{
978             id: saveButton
979             label: "Save"
980             onButtonClick:{
981                 directory.fileContent = textArea.textContent
982                 directory.filename = textInput.text
983                 directory.saveFile()
984             }
985         }
986         Button{
987             id: exitButton
988             label: "Exit"
989             onButtonClick:{
990                 Qt.quit()
991             }
992         }
993     \endcode
994
995     Our \c FileMenu can now connect to their respective actions. The \c saveButton
996     will transfer the text from the \c TextEdit onto the directory's \c fileContent
997     property, then copy its file name from the editable text input. Finally, the button
998     calls the \c saveFile() function, saving the file. The \c loadButton has a similar
999     execution. Also, the \c New action will empty the contents of the \c TextEdit.
1000
1001     Further, the \c EditMenu buttons are connected to the \c TextEdit functions to copy,
1002     paste, and select all the text in the text editor.
1003
1004     \image qml-texteditor5_filemenu.png
1005
1006     \section2 Text Editor Completion
1007
1008     \image qml-texteditor5_newfile.png
1009
1010     The application can function as a simple text editor, able to accept text
1011     and save the text into a file. The text editor can also load from a file and
1012     perform text manipulation.
1013
1014     \section1 Running the Text Editor
1015
1016     We need to compile the file dialog C++ plugin before the text editor can run.
1017     To compile, enter the \c gsQml directory, then run \c qmake and compile
1018     using \c make or \c nmake, depending on your platform. To run, launch
1019     qmlviewer and open the \c texteditor.qml file.
1020
1021     The source code is in the \c{examples/tutorials/gettingStarted/gsQml}
1022     directory.
1023 */