~mhall119/developer-ubuntu-com/currency_tutorial

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
[caption id="attachment_646" align="alignnone" width="36"]<img class="aligncenter size-full wp-image-2183" title="David Planella" src="http://developer.ubuntu.com/wp-content/uploads/2012/12/dpm-36px1.jpg" alt="Thumbnail picture of David Planella" width="36" height="36" /> By David Planella (code by the SDK Team)[/caption]

In this recipe you will learn how to write a currency converter app for Ubuntu on the phone. You will be using several components from the Ubuntu QML toolkit: <em>i18n</em>, <em>units</em>, <em>ItemStyle</em> for theming, <em>Label</em>, <em>ActivityIndicator</em>, <em>Popover</em>, <em>Button</em>, <em>TextField</em>, <em>ListItems.Header</em> and <em>ListItems.Standard</em>

The application will show you how to use the QML declarative language to create a functional user interface and its logic, and to communicate through the network and fetch data from a remote source on the Internet.

In practical terms, you will be writing an application that performs currency conversion between two selected currencies. The rates are fetched using the European Central Bank’s API. Currencies can be changed by pressing the buttons and selecting the currency required from the list.
<h2 id="requirements">Requirements</h2>
<ul>
	<li>Ubuntu 12.04 or later – <a href="http://releases.ubuntu.com/12.10/">get Ubuntu ›</a></li>
	<li>Qt 5 and the Ubuntu QML toolkit – <a href="http://developer.ubuntu.com/get-started/gomobile/#step-get-toolkit">get Qt5 and the Ubuntu toolkit ›</a></li>
	<li>Code editor (Qt Creator recommended) – <a href="apt://qtcreator">install Qt Creator ›</a></li>
</ul>
<h2 id="the-tools">The tools</h2>
The focus of this tutorial will be on the Ubuntu UI toolkit preview and its components, rather than on the tools. However, it is worth mentioning and giving an overview of the tools you will be using:
<h3 id="development-host">Development host</h3>
<strong>Ubuntu 12.04</strong> (or later) will be used as the host machine for development. At the end of this recipe you will have created a platform-agnostic QML app that can be run on the development host machine. Subjects such as cross-compiling for a different architecture and installation on a phone are more advanced topics that will be covered at a later date when the full Ubuntu SDK is released.

<h3 id="text-editor">Integrated Development Environment (IDE)</h3>
We will be writing declarative QML code, which does not need to be compiled to be executed, so <strong>you can use your favourite text editor</strong> to write the actual code, which will consist of a single QML file.

For this tutorial, <strong>we recommend using Qt Creator</strong>. Qt Creator is a powerful IDE to develop applications based on the Qt framework.

<h3 id="qml-viewer">QML viewer</h3>
To start QML applications, either during the prototyping or final stages, we will use <strong>Qt Creator</strong> and the <kbd>Ctrl</kbd>+<kbd>R</kbd> shortcut.

However, as an alternative for quick app viewing with QML Scene, it is worth noting that you can also use <strong>QML Scene</strong> without Qt Creator. QML Scene is a command-line application that interprets and runs QML code.

To run a QML application with QML Scene, open up a terminal with the <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>T</kbd> key combination, and execute the qmlscene command, followed by the path to the application:

<code>$ qmlscene /path/to/application.qml</code>

<a href="http://qt-project.org/doc/qt-5.0/qtquick/qtquick-qmlscene.html">Learn more about QML Scene ›</a>

<h2 id="getting-started">Getting started</h2>
To start Qt creator, simply open the <strong>Dash</strong>, start typing “<strong>qt creator</strong>”, and click on the Qt Creator icon that appears on the search results.

<img class="aligncenter size-full wp-image-3735" title="Qt Creator" src="http://developer.ubuntu.com/wp-content/uploads/2012/12/Qt-Creator.png" alt="" width="324" height="264" />
<p id="the-rectangle">Next stop: putting our developer hat on.</p>

<h3>The main view</h3>
We’ll start off with a minimum QML canvas with our first Ubuntu component: a label inside the main view.
 
<ol>
	<li>In Qt Creator, press <strong>Ctrl+N</strong> to create a new project</li>
	<li>Select the<strong> Projects &gt; Ubuntu &gt; Ubuntu UI - Simple</strong> template and click <strong>Choose...</strong></li>
	<li>Give the project <strong>CurrencyConverter</strong> as a <strong>Name</strong>. You can leave the <strong>Create in:</strong> field as the default and then click <strong>Next</strong>.</li>
	<li>You can optionally set up a revision control system such as Bazaar in the final step, but that’s outside the scope of this tutorial. Click on <strong>Finish</strong>.</li>
	<li>Replace the <strong>Column</strong> component and all of it's chidren, and replace them with the <strong>Page</strong> as shown below, and then <strong>save</strong> it with <strong>Ctrl+S</strong>:</li>
</ol>
[sourcecode language="javascript"]
import QtQuick 2.0
import Ubuntu.Components 0.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"
    applicationName: "CurrencyConverter"

    width: units.gu(100)
    height: units.gu(75)
    
    Page {
        anchors.fill: parent
        title: i18n.tr("Currency Converter")

        property real margins: units.gu(2)
        property real buttonWidth: units.gu(9)
    }
}
[/sourcecode]

Try to run it now to see the results:
<ol>
	<li>Inside Qt Creator, press the <kbd>Ctrl</kbd>+<kbd>R</kbd> key combination. It is a shortcut to the <strong>Build &gt; Run</strong> menu entry</li>
</ol>
Or alternatively, from the terminal:
<ol>
	<li>Open a terminal with <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>T</kbd></li>
	<li>Run the following command:</li>
</ol>
<code>qmlscene ~/CurrencyConverter/CurrencyConverter.qml</code>

<img class="aligncenter size-full wp-image-3736" title="Currency Converter MainView" src="currency_header.png" alt="" width="482" />

Hooray! Your first Ubuntu app for the phone is up and running. Nothing very exciting yet, but notice how simple it was to bootstrap it. You can close your app for now.

Now starting from the top of the file, let’s go through the code.

[sourcecode language="javascript"]
import QtQuick 2.0
import Ubuntu.Components 0.1
[/sourcecode]

Every QML document consists of two parts: an imports section and an object declaration section. First of all we import the QML types and components that we need, specifying the namespace and its version. In our case, we import the built-in QML and Ubuntu types and components.

We now move on to declaring our objects. In QML, a user interface is specified as a tree of objects with properties. JavaScript can be embedded as a scripting language in QML as well, but we’ll see this later on.

[sourcecode language="javascript" firstline="8"]
MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"
    applicationName: "CurrencyConverter"

    width: units.gu(100)
    height: units.gu(75)
    
    Page {
        anchors.fill: parent
        title: i18n.tr("Currency Converter")

        property real margins: units.gu(2)
        property real buttonWidth: units.gu(9)
    }
}
[/sourcecode]

Secondly, we create a <a href="http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/qml-ubuntu-components0-mainview.html">MainView</a>, the most essential SDK component, which acts as the root container for our application. It also provides the standard <a href="http://design.ubuntu.com/apps/building-blocks/toolbar">Toolbar</a> and <a href="http://design.ubuntu.com/apps/building-blocks/header">Header</a>.

With a syntax similar to JSON, we define its <a href="http://qt-project.org/doc/qt-4.8/propertybinding.html#properties">properties</a> by giving it an id we can refer it to (<em>root</em>), and then we define some visual properties (<em>width</em>, <em>height</em>, <em>color</em>). Notice how in QML properties are bound to values with the ‘<em>property: value</em>’ syntax. We also define a custom property called <em>margins</em>, of <a href="http://qt-project.org/doc/qt-5.0/qtqml/qtqml-typesystem-basictypes.html">type</a> <a href="http://qt-project.org/doc/qt-5.0/qtqml/qml-real.html">real</a> (a number with decimal point). Don’t worry about the <em>buttonWidth</em> property for now, we’ll use it later on. The rest of the properties available in the MainView we leave at their default values by not declaring them.

Notice how we specify units as <em>units.gu</em>. These are <strong>grid units</strong>, which we are going to talk about in a minute. For now, you can consider them as a form-factor-agnostic way to specify measurements. They return a pixel value that’s dependent on the device the application is running on.

Inside our main view, we add a child Ubuntu <a href="http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/qml-ubuntu-components0-page.html">Page</a>, which will contain the rest of our components as well as provide an Ubuntu title.  We title text to the page, ensuring it is enclosed with the <em>i18n.tr()</em> function, which will make it translatable.

<div class="clearfix"></div>
<h3 id="resolution-independence">Resolution independence</h3>
A key feature of the Ubuntu user interface toolkit is the ability to scale to all form factors in a world defined by users with multiple devices. The approach taken has been to define a new unit type, the grid unit (gu in short). Grid units translate to a pixel value depending on the type of screen and device the application is running on. Here are some examples:
<table style="width: 100%; margin-top: 20px; margin-bottom: 20px;">
<tbody>
<tr style="border-top: 1px solid #CCCCCC;">
<td style="padding: 5px 10px;"><strong>Device</strong></td>
<td style="padding: 5px 10px;"><strong>Conversion</strong></td>
</tr>
<tr style="border-top: 1px solid #CCCCCC;">
<td style="padding: 5px 10px;">Most laptops</td>
<td style="padding: 5px 10px;">1 gu = 8 px</td>
</tr>
<tr style="border-top: 1px solid #CCCCCC;">
<td style="padding: 5px 10px;">Retina laptops</td>
<td style="padding: 5px 10px;">1 gu = 16 px</td>
</tr>
<tr style="border-top: 1px solid #CCCCCC;">
<td style="padding: 5px 10px;">Smart phones</td>
<td style="padding: 5px 10px;">1 gu = 18 px</td>
</tr>
</tbody>
</table>
<a href="http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/resolution-independence.html">Learn more about resolution independence ›</a>
<h3 id="internationalization">Internationalization</h3>
As part of the Ubuntu philosophy, internationalization and native language support is a key feature of the Ubuntu toolkit. We’ve chosen <em>gettext</em> as the most ubiquitous Free Software internationalization technology, which we’ve implemented in QML through the family of <em>i18n.tr()</em> functions.

<strong>Up next:</strong> Fetching and converting currencies

<!--nextpage-->
<h2 id="fetching-and-converting-currencies">Fetching and converting currencies</h2>
Now we will start adding the logic to our app, which will mean getting the currency and rates data and doing the actual conversion.

Start by adding the following code around line 30 <strong>before the last closing brace</strong>. We will mostly be appending code in all subsequent steps, but any snippet will be contained inside our root MainView. So when you append code, make sure it is still before the MainView’s closing brace at the end of the file.

[sourcecode language="javascript" firstline="30"]
    ListModel {
        id: currencies
        ListElement {
            currency: "EUR"
            rate: 1.0
        }

        function getCurrency(idx) {
            return (idx >= 0 && idx < count) ? get(idx).currency: ""
        }

        function getRate(idx) {
            return (idx >= 0 && idx < count) ? get(idx).rate: 0.0
        }
    }
[/sourcecode]

What we are doing here is to use <em>currencies</em> as a <a href="http://doc.qt.digia.com/qt/qml-listmodel.html">ListModel</a> object that will contain a list of items consisting of <em>currency</em> and <em>rate</em> pairs. The <em>currencies</em> ListModel will be used as a source for the view elements that will display the data. We will be fetching the actual data from the Euro foreign exchange reference rates from the European Central Bank. As such, the Euro itself is not defined there, so we’ll pre-populate our list with the EUR currency, with a reference rate of 1.0.

The function statements in currencies illustrate another powerful feature of QML: integration with JavaScript. The two JavaScript functions are used as glue code to retrieve a currency or rate from an index. They are required as currencies may not be loaded when component property bindings use them for the first time. But do not worry much about their function. For now it’s just important to remember that you can transparently <a href="http://qt-project.org/doc/qt-5.0/qtqml/qtqml-javascript-expressions.htm">integrate JavaScript code in your QML objects</a>.

Now we’ll fetch the actual data with a QtQuick object to load XML data into a model: the <a href="http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-xmllistmodel2-xmllistmodel.html">XmlListModel</a>. To use it, we add an additional import statement at the top of the file, so that it looks like:

[sourcecode language="javascript"]
import QtQuick 2.0
import QtQuick.XmlListModel 2.0
import Ubuntu.Components 0.1
[/sourcecode]

And then around line 47, add the actual rate exchange fetcher code:

[sourcecode language="javascript" firstline="47"]
    XmlListModel {
        id: ratesFetcher
        source: "http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml"
        namespaceDeclarations: "declare namespace gesmes='http://www.gesmes.org/xml/2002-08-01';"
                               +"declare default element namespace 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref';"
        query: "/gesmes:Envelope/Cube/Cube/Cube"

        onStatusChanged: {
            if (status === XmlListModel.Ready) {
                for (var i = 0; i < count; i++)
                    currencies.append({"currency": get(i).currency, "rate": parseFloat(get(i).rate)})
            }
        }

        XmlRole { name: "currency"; query: "@currency/string()" }
        XmlRole { name: "rate"; query: "@rate/string()" }
    }
[/sourcecode]

The relevant properties are <em>source</em>, to indicate the URL where the data will be fetched from; <em>query</em>, to specify an absolute <a href="https://developer.mozilla.org/en-US/docs/XPath">XPath</a> query to use as the base query for creating model items from the <em>XmlRoles</em> below; and <em>namespaceDeclarations</em> as the namespace declarations to be used in the XPath queries.

The <em>onStatusChanged</em> <strong>signal handler</strong> demonstrates another combination of versatile features: the signal and handler system together with JavaScript. Each QML property has got a <em>&lt;property&gt;Changed</em> signal and its corresponding on<em>&lt;property&gt;Changed</em> signal handler. In this case, the <em>StatusChanged</em> signal will be emitted to notify of any changes of the status property, and we define a handler to append all the currency/rate items to the <em>currencies</em> ListModel once <em>ratesFetcher</em> has finished loading the data.

In summary, <em>ratesFetcher</em> will be populated with currency/rate items, which will then be appended to <em>currencies</em>.

It is worth mentioning that in most cases we’d be able to use a single XmlListModel as the data source, but in our case we use it as an intermediate container. We need to modify the data to add the EUR currency, and we put the result in the <em>currencies</em> ListModel.

Notice how network access happens transparently so that you as a developer don’t have to even think about it!

Around line 65, let’s add an Ubuntu <a href="http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/qml-ubuntu-components0-activityindicator.html">ActivityIndicator</a> component to show activity while the rates are being fetched:

[sourcecode language="javascript" firstline="65"]
    ActivityIndicator {
        anchors.right: parent.right
        running: ratesFetcher.status === XmlListModel.Loading
    }
[/sourcecode]

We anchor it to the right of its parent (<em>root</em>) and it will show activity until the rates data has been fetched.

And finally, around line 70, we add the <em>convert</em> JavaScript function that will perform the actual currency conversions:

[sourcecode language="javascript" firstline="70"]
    function convert(from, fromRateIndex, toRateIndex) {
        var fromRate = currencies.getRate(fromRateIndex);
        if (from.length <= 0 || fromRate <= 0.0)
            return "";
        return currencies.getRate(toRateIndex) * (parseFloat(from) / fromRate);
    }
[/sourcecode]
<h2 id="choosing-currencies">Choosing currencies</h2>
At this point we’ve added all the backend code and we move on to user interaction. We’ll start off with creating a new <a href="http://qt-project.org/doc/qt-5.0/qtqml/qtqml-typereference-topic.html#component">Component</a>, a reusable block that is created by combining other components and objects.

Let’s first append two import statements at the top of the file:

[sourcecode language="javascript" firstline="4"]
import Ubuntu.Components.ListItems 0.1
import Ubuntu.Components.Popups 0.1
[/sourcecode]

And then add the following code around line 79:

[sourcecode language="javascript" firstline="79"]
    Component {
        id: currencySelector
        Popover {
            Column {
                anchors {
                    top: parent.top
                    left: parent.left
                    right: parent.right
                }
                height: pageLayout.height
                Header {
                    id: header
                    text: i18n.tr("Select currency")
                }
                ListView {
                    clip: true
                    width: parent.width
                    height: parent.height - header.height
                    model: currencies
                    delegate: Standard {
                        text: currency
                        onClicked: {
                            caller.currencyIndex = index
                            caller.input.update()
                            hide()
                        }
                    }
                }
            }
        }
    }
[/sourcecode]

At this point, if you run the app, you will not yet see any visible changes, so don't worry if all you see if an empty rectangle.

What we’ve done is to create the currency selector, based on an Ubuntu <a href="http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/qml-ubuntu-components-popups0-popover.html">Popover</a> and a standard Qt Quick <a href="http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick2-listview.html">ListView</a>. The ListView will display the data from the <em>currencies</em> ListMode. Notice how the Column object wraps the Ubuntu <a href="http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/qml-ubuntu-components-listitems0-header.html">Header</a> and the list view to arrange them vertically, and how each item in the list view will be a <a href="http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/qml-ubuntu-components-listitems0-standard.html">Standard</a> list item component.

The popover will show the selection of currencies. Upon selection, the popover will be hidden (see <em>onClicked</em> signal) and the caller’s data is updated. We assume that the caller has <em>currencyIndex</em> and <em>input</em> properties, and that <em>input</em> is an item with an <em>update()</em> function.

<strong>Up next:</strong> Arranging the UI

<!--nextpage-->
<h2 id="arranging-the-ui">Arranging the UI</h2>
Up until now we’ve been setting up the backend and building blocks for our currency converter app. Let’s move on to the final step and the fun bit, putting it all together and seeing the result!

Add the final snippet of code around line 111:

[sourcecode language="javascript" firstline="111"]
    Column {
        id: pageLayout

        anchors {
            fill: parent
            margins: root.margins
            topMargin: title.height
        }
        spacing: units.gu(1)

        Row {
            spacing: units.gu(1)

            Button {
                id: selectorFrom
                property int currencyIndex: 0
                property TextField input: inputFrom
                text: currencies.getCurrency(currencyIndex)
                onClicked: PopupUtils.open(currencySelector, selectorFrom)
            }

            TextField {
                id: inputFrom
                errorHighlight: false
                validator: DoubleValidator {notation: DoubleValidator.StandardNotation}
                width: pageLayout.width - 2 * root.margins - root.buttonWidth
                height: units.gu(4)
                font.pixelSize: FontUtils.sizeToPixels("medium")
                text: '0.0'
                onTextChanged: {
                    if (activeFocus) {
                        inputTo.text = convert(inputFrom.text, selectorFrom.currencyIndex, selectorTo.currencyIndex)
                    }
                }
                function update() {
                    text = convert(inputTo.text, selectorTo.currencyIndex, selectorFrom.currencyIndex)
                }
            }
        }

        Row {
            spacing: units.gu(1)
            Button {
                id: selectorTo
                property int currencyIndex: 1
                property TextField input: inputTo
                text: currencies.getCurrency(currencyIndex)
                onClicked: PopupUtils.open(currencySelector, selectorTo)
            }

            TextField {
                id: inputTo
                errorHighlight: false
                validator: DoubleValidator {notation: DoubleValidator.StandardNotation}
                width: pageLayout.width - 2 * root.margins - root.buttonWidth
                height: units.gu(4)
                font.pixelSize: FontUtils.sizeToPixels("medium")
                text: '0.0'
                onTextChanged: {
                    if (activeFocus) {
                        inputFrom.text = convert(inputTo.text, selectorTo.currencyIndex, selectorFrom.currencyIndex)
                    }
                }
                function update() {
                    text = convert(inputFrom.text, selectorFrom.currencyIndex, selectorTo.currencyIndex)
                }
            }
        }

        Button {
            text: i18n.tr("Clear")
            width: units.gu(12)
            onClicked: {
                inputTo.text = '0.0';
                inputFrom.text = '0.0';
            }
        }
    }
[/sourcecode]

It’s a piece of code that’s longer than previous snippets, but it is pretty simple and there is not much new in terms of syntax. What we’re doing is arranging the visual components to provide user interaction within the <em>root</em> area and defining signal handlers.

Notice how we use the <em>onClicked</em> signal handlers to define what will happen when the user clicks on the currency selectors (i.e. the pop ups are opened), the <em>onTextChanged</em> handler to call the <em>convert</em>() function defined earlier to do conversions as we type, and we define the <em>update()</em> function the list view items from the <em>currencySelector</em> component defined earlier expect.

We are using a Column and two Rows to set up the layout, and each row contains a currency selector button and a text field to display or input the currency conversion values. We’ve also added a button below them to clear both text fields at once. Here’s a mockup to illustrate the layout:

<img class="aligncenter size-full wp-image-3781" title="Page Layout" src="http://developer.ubuntu.com/wp-content/uploads/2012/12/PageLayout_2.png" alt="" width="491" height="318" />
<div class="clearfix"></div>
<strong>Up next:</strong> Lo and behold

<!--nextpage-->
<h2 id="lo-and-behold">Lo and behold</h2>
So that’s it! Now we can lay back and enjoy our creation. Just press the <kbd>Ctrl</kbd>+<kbd>R</kbd> shortcut within Qt Creator, and behold the fully functional and slick currency converter you’ve just written with a few lines of code.

<img src="http://developer.ubuntu.com/wp-content/uploads/2012/12/Currency-Converter-plain.png" alt="" title="Currency Converter" width="482" height="214" class="aligncenter size-full wp-image-4094" />

<img src="http://developer.ubuntu.com/wp-content/uploads/2012/12/Currency-Converter-popover.png" alt="" title="Currency Converter popover" width="482" height="225" class="aligncenter size-full wp-image-4095" />

<div class="clearfix"></div>
<h2 id="conclusion">Conclusion</h2>
You’ve just learned how to write a form-factor-independent Ubuntu application for the phone. In doing that, you’ve been exercising and combining the power of technologies such as QML, Javascript and a variety of Ubuntu components, to produce an app with a cohesive, crisp and clean Ubuntu look.

You’ll surely have noticed the vast array of possibilities these technologies open up, so it’s now up to you: help us testing the toolkit preview, write your own apps and give us your feedback to make Ubuntu be in the next billion phones!
<h2 id="learn-more">Learn more</h2>
If this tutorial has started whetting your appetite, you should definitely check out the <strong>Component Showcase</strong> app that comes with the Ubuntu QML toolkit preview. With it, you'll be able to see all of the Ubuntu components in action and look at their code to learn how to use it in your apps.

<img class="aligncenter size-full wp-image-3754" title="Component Showcase" src="http://developer.ubuntu.com/wp-content/uploads/2012/12/ComponentShowcase.png" alt="" width="700" height="339" />
<div class="clearfix"></div>

If you want to study the Component Showcase code:
<ol>
	<li><strong>Start Qt Creator</strong> by pressing the Ubuntu button in the Launcher. That will bring up the <strong>Dash</strong>.</li>
	<li>Start typing <em>qt creator</em> and click on the Qt Creator icon.</li>
	<li>In Qt Creator, then press the <kbd>Ctrl</kbd>+<kbd>O</kbd> key combination to open the file selection dialog.</li>
	<li><strong>Select</strong> the file <em>/usr/lib/ubuntu-ui-toolkit/demos/ComponentShowcase.qml</em> and click on <strong>Open</strong>.</li>
	<li>To run the code, you can select the Tools > External > Qt Quick > Qt Quick 2 Preview (qmlscene) menu entry.</a></li>
</ol>
Alternatively, if you only want to run the Component Showcase:
<ol>
	<li>Open a <strong>terminal</strong> with the <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>T</kbd> key combination</li>
	<li><strong>Type the command below</strong>, followed by <kbd>Enter</kbd><code>qmlscene /usr/lib/ubuntu-ui-toolkit/demos/ComponentShowcase.qml</code></li>
</ol>
<h3>Reference</h3>
<ul>
	<li><a href="https://bazaar.launchpad.net/~dpm/+junk/CurrencyConverterUpdated/files/8">Code for this tutorial</a></li>
	<li><a href="http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/overview-ubuntu-sdk.html">Ubuntu QML toolkit API documentation</a></li>
	<li><a href="http://qt-project.org/doc/qt-5.0/qtquick/qtquick-index.html">Qt Quick documentation</a></li>
	<li><a href="http://qt-project.org/doc/qt-5.0/qtdoc/gettingstartedqml.html">Getting Started Programming with Qt Quick</a></li>
	<li><a href="http://qt-project.org/doc/qt-5.0/qtquick/qtquick-applicationdevelopers.html">QtQuick for Application Developers</a></li>
	<li><a href="http://qt-project.org/doc/qt-5.0/qtqml/qtqml-index.html#syntax-of-the-qml-language">Syntax of the QML language</a></li>
	<li><a href="http://qt-project.org/doc/qt-5.0/qtquick/qtquick-usecase-integratingjs.html">Integrating JavaScript and QML</a></li>
</ul>
<h2 id="questions">Questions?</h2>
If you’ve got any questions on this tutorial, or on the technologies that it uses, just <a href="http://askubuntu.com/questions/ask?tags=application-development">ask on Ask Ubuntu!</a>