Dev Week -- From idea to app in no time with QML -- oSoMoN -- Thu, Jul 14th, 2011

   1 [16:00] <oSoMoN> let's get this rolling…
   2 [16:01] <oSoMoN> Hi everyone!
   3 [16:01] <oSoMoN> In this session I'm gonna show you how to write a cool application in QML in no time (in Ubuntu of course!)
   4 [16:01] <oSoMoN> I'll first start with a super quick introduction to QML and pointers to documentation for complete beginners, and then I'll move on to writing an actual application step by step.
   5 [16:01] <oSoMoN> If you have contextual questions don't hesitate to ask, myself and others (I hope) will be happy to answer as best as we can.
   6 [16:01] <oSoMoN> If a question is too general, keep it for the end of the session so as not to disrupt the flow too much, we'll save some time at the end to answer them, and eventually if we go overflow the allocated time we can take the discussions offline.
   7 [16:01] <oSoMoN> So, on to the topic!
   8 [16:01] <oSoMoN> There's a very good introduction of what QML is at http://doc.qt.nokia.com/qdeclarativeintroduction.html.
   9 [16:01] <oSoMoN> There's also very good documentation, it's one of the strong points of Qt in general.
  10 [16:02] <oSoMoN> There are official tutorials as well as plenty of unofficial ones on the interwebs.
  11 [16:02] <oSoMoN> Basic tutorial: http://doc.qt.nokia.com/qml-tutorial.html
  12 [16:02] <oSoMoN> Advanced tutorial: http://doc.qt.nokia.com/qml-advtutorial.html
  13 === Hutley_ is now known as Hutley
  14 [16:02] <oSoMoN> Here is a non exhaustive list of advantages that make it a great language to develop applications for Ubuntu:
  15 [16:02] <oSoMoN> very good documentation
  16 [16:02] <oSoMoN> implicit animations
  17 [16:02] <oSoMoN> property bindings
  18 [16:02] <oSoMoN> states
  19 [16:02] <oSoMoN> extensible in C++ or Python (using PySide)
  20 [16:02] <oSoMoN> supports touch input (e.g. kinetic scrolling for lists)
  21 [16:03] <oSoMoN> First let's install the packages we're going to need: `sudo apt-get install qtcreator qt4-qmlviewer libqtwebkit-qmlwebkitplugin`
  22 [16:03] <oSoMoN> My purpose with this session is not to teach you QML from the very beginning, there's plenty of great documentation out there for that.
  23 [16:03] <oSoMoN> The idea is more to show you how to use it to write a real application for Ubuntu, not the typical and useless Hello World.
  24 [16:04] <oSoMoN> For years I've been using liferea, a gnome feed reader, to aggregate and read RSS feeds. It does the job, but it's been getting incredibly slow, to the point it takes more than a minute to start and display its main window, and that's not even checking for new feeds. Not acceptable, let's see if we can write a replacement in QML.
  25 [16:04] <oSoMoN> For the sake of the example it's going to aggregate all feeds from Planet Ubuntu (http://planet.ubuntu.com/).
  26 [16:04] <oSoMoN> The desired layout is basic: a list of all recents entries in a left pane, and a view of the currently selected entry in a right pane.
  27 [16:04] <oSoMoN> I'll guide you through the code step by step, you can find it in the following bzr branch: lp:~osomon/+junk/qml-feedreader.
  28 [16:05] <oSoMoN> Each revision in the branch corresponds to a step. For convenience, you can browse the revisions and see the diffs between each revision at http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/changes.
  29 [16:05] <oSoMoN> Let's fire up Qt Creator, and click on "Create Project".
  30 [16:05] <oSoMoN> Select "Qt Quick Project" > "Qt Quick UI".
  31 [16:05] <oSoMoN> Let's call it "feedreader" and create it in e.g. "~/dev/qml". Then click "Next" and then "Finish".
  32 [16:05] <oSoMoN> (if I'm pasting too fast, someone please tell me and I'll slow down)
  33 [16:06] <oSoMoN> Qt Creator created a skeleton application, which we can already run.
  34 [16:06] <oSoMoN> We will replace this code incrementally to implement the functionality of our feed reader.
  35 [16:06] <oSoMoN> Let's get started.
  36 [16:06] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/1
  37 [16:06] <oSoMoN> We're starting by adding to the root element an XmlListModel that will be responsible for fetching the data from the RSS feed and exposing this data in the form of properties for each item in the model, using XPath queries to extract the relevant data.
  38 [16:07] <oSoMoN> Then we're adding a ListView to display the data from the list model. The delegate is the component responsible for displaying one item in the list, it is automatically instantiated and positioned correctly by the list view.
  39 [16:07] <oSoMoN> At this point we can already run this code, and tada! We get a list of the latest entries for the RSS feed.
  40 [16:07] <oSoMoN> As you can see, you can use the mouse wheel and do kinetic scrolling on the list. All of this comes for free with the ListView element.
  41 [16:07] <oSoMoN> It's rather ugly and not very readable as no layout is applied to the delegates. We are going to remedy this in the next step.
  42 [16:08] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/2
  43 [16:08] <oSoMoN> Instead of a simple Text element, we make the delegate a Rectangle containing two rows of text.
  44 [16:08] <oSoMoN> The first line displays the title of the entry, and the second line the publication date. We tweak the font size, add an ellipsis, margins and spacing.
  45 [16:09] <oSoMoN> It is much better already, but we can improve it visually by adding alternating colors to the rows.
  46 [16:10] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/3
  47 [16:11] <oSoMoN> The SystemPalette element exposes a palette of colors for the current theme, which allows us to give a consistent look'n'feel to our application.
  48 [16:11] <oSoMoN> As you can see, an interesting feature of QML is that we can assign an anonymous function to the value of a property, for non-trivial computations. This of course preserves property binding, meaning that whenever the value of a property used inside the body of this function changes, the property is updated in a transparent manner.
  49 [16:13] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/4
  50 [16:13] <oSoMoN> QML items are not mouse-aware by default, but it is very easy to fix this: we just add an invisible MouseArea that covers the area of the item, and we can now connect to the various signals it emits when it receives mouse events.
  51 [16:14] <oSoMoN> In this case, clicking an item in the list will make it the current item. It will be highlighted with a different color for visual feedback.
  52 [16:15] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/5
  53 [16:15] <oSoMoN> We now want to display the contents of the current entry in a pane to the right of the list.
  54 [16:16] <oSoMoN> The contents are stored in the 'description' attribute, so we need to add it to the XmlListModel.
  55 [16:17] <oSoMoN> The contents are HTML, so we are going to display them in a WebView, which is basically a component embedding webkit to render a web page or arbitrary HTML. This requires an extra import.
  56 [16:17] <oSoMoN> As you can see here, property binding is a very powerful feature: unlike in imperative programming, I do not have to set the value of the 'html' property to the contents whenever I change the current entry in the list. All I need to do is bind it, and done!
  57 [16:17] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/6
  58 [16:18] <oSoMoN> You may have noticed that the web view cannot be scrolled. This can be annoying if the contents don't fit in the frame. Putting the WebView inside a Flickable element fixes this.
  59 [16:18] <oSoMoN> The contents can now be scrolled vertically by clicking and dragging them. Note that a limitation of the Flickable element it that unfortunately it currently doesn't handle mouse wheel events (this could be overcome by writing a custom Flickable element in C++, but is not the point of today's session).
  60 [16:19] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/7
  61 [16:20] <oSoMoN> We now add a one-pixel separator between the list view and the webview.
  62 [16:20] <oSoMoN> Note how QML stacks sibling elements: the last on top of the others. Which is why we add the separator at the end, after the listview and the flickable.
  63 [16:21] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/8
  64 [16:21] <oSoMoN> To handle keyboard focus properly, we make the top-level element a focus scope, meaning that when it gets the focus it transfers it to one and only one of its children (in our case, the listview).
  65 [16:22] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/9
  66 [16:22] <oSoMoN> We now add a fancy animation on the opacity of the webview whenever we click an entry in the list: the web view fades out, then the index is actually changed, then the webview fades in again.
  67 [16:23] <oSoMoN> This is achieved with a sequential animation; by default animations in QML are run in parallel.
  68 [16:24] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/10
  69 [16:25] <oSoMoN> Our webview can be scrolled, that's nice, but we don't have any visual indicator of the position within the document.
  70 [16:25] <oSoMoN> Let's add a simple scrollbar that will act as a visual clue (it won't be clickable to actually change the position).
  71 [16:26] <oSoMoN> The scrollbar is made up of two rectangles: the first one is a semi-transparent background, and the second one is the handle of the scrollbar.
  72 [16:26] <oSoMoN> The scrollbar defines custom properties for the position and the pageSize, those are bound the usual way, so whenever the position of the contents inside the flickable is updated, the properties of the scrollbar are updated accordingly.
  73 [16:27] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/11
  74 [16:28] <oSoMoN> This scrollbar is very nice, how about we extract it to a separate file so as to make it a reusable component?
  75 [16:28] <oSoMoN> QML files representing components in the same directory as the main one are discovered automatically, no need to import anything else.
  76 [16:28] <oSoMoN> We name the file "ScrollBar.qml", and the component can be used under the name 'ScrollBar'. Easy, heh?
  77 [16:29] <oSoMoN> In the external component, we remove all references to the flickable. The properties of the scrollbar will be set wherever it is instantiated. This ensures our component is truly reusable and doesn't rely on the implicit presence of other components.
  78 [16:30] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/12
  79 [16:30] <oSoMoN> Now that we've done that, it is trivial to add a scrollbar to the listview as well. Almost too easy :)
  80 === a is now known as Guest32986
  81 [16:31] <oSoMoN> http://bazaar.launchpad.net/~osomon/+junk/qml-feedreader/revision/13
  82 [16:32] <oSoMoN> For the final touch, let's add a header to the right pane, displaying two lines: one with the title of the current entry, and the second one with a link to the original blog entry.
  83 [16:33] <oSoMoN> As a bonus, we can very easily make the link clickable by using a MouseArea and invoking the handy helper function "Qt.openUrlExternally()".
  84 [16:34] <oSoMoN> That's it for the code folks!
  85 [16:34] <oSoMoN> We have written a full-fledged real-word application in about half an hour and under 200 lines of code (158 lines if we exclude copyright and license headers and blank lines).
  86 [16:35] <oSoMoN> real-world
  87 [16:35] <oSoMoN> Here is a screenshot of the application running: http://tilloy.net/olivier/qml/qml-feedreader.png, for those who haven't tested it.
  88 [16:35] <oSoMoN> This is only a quick example of what QML can help you build, it's by no means a complete overview of how rich the framework is.
  89 [16:36] <oSoMoN> The following page has lots of very interesting pointers to resources and documentation to take in on from here, including extending QML components with C++: http://doc.qt.nokia.com/qtquick.html
  90 [16:37] <oSoMoN> It looks like I went really fast (maybe too fast?), let's open the floor for questions
  91 [16:37] <oSoMoN> !q
  92 [16:38] <oSoMoN> any questions? should I go back to one of the steps and explain in more details?
  93 [16:43] <ClassBot> abhinav_singh asked: can you please give some links for including QML components with python
  94 [16:44] <ClassBot> shadeslayer asked: what is the ideal way of communicating with DBus using QML ?
  95 [16:44] <nerochiaro> shadeslayer: normally you create c++ classes that implement the DBUS interface and then you expose them to QML. to expose them you have two possibilities
  96 [16:45] <nerochiaro> shadeslayer: one is to use QDeclarativeContext::setContextProperty (assuming you're not using qmlviewer)
  97 [16:46] <nerochiaro> shadeslayer: the other is to create a plugin which exposes them, and then use the import directive in QML to import that plugin. after that you can use the classes exported by the plugin in QML. there's some good docs for that, let me find them
  98 [16:47] <nerochiaro> shadeslayer: http://doc.qt.nokia.com/4.7-snapshot/qml-extending.html
  99 [16:47] <oSoMoN> one could also probably write a generic DBus QML component that allows connecting to whatever object/interface on a given bus, but that may be overkill for most use-cases
 100 [16:48] <nerochiaro> shadeslayer: QtCreator has also some templates to create these plugins easil
 101 [16:48] <nerochiaro> y
 102 [16:49] <oSoMoN> if we're done with questions, I'd like to mention two cools projects that use QML
 103 [16:49] <oSoMoN> the first one is unity-2d
 104 [16:50] <oSoMoN> the UI is almost entirely written in QML, and it makes it super easy and fun to prototype new ideas
 105 [16:50] <ClassBot> There are 10 minutes remaining in the current session.
 106 [16:51] <oSoMoN> and the second one is an experiment of mine, a limited clone of the Ubuntu Software Center, written in QML and Python
 107 [16:51] <oSoMoN> this one is more like a playground at the moment
 108 [16:52] <oSoMoN> but you can already get the code form S-C's trunk (lp:software-center) and play with it by running ./software-center-qml
 109 [16:52] <oSoMoN> that's all I got for you today, we have 10 minutes left, more questions maybe?
 110 [16:54] <ClassBot> tsimpson asked: have there been any comparisons of the speed of native (C++) apps compared to QML apps?
 111 [16:55] <oSoMoN> tsimpson: I recall reading a blog post about it, let me see if I can find the link for you
 112 [16:55] <ClassBot> There are 5 minutes remaining in the current session.
 113 [16:56] <oSoMoN> tsimpson: http://labs.qt.nokia.com/2011/05/31/qml-scene-graph-in-master/ has some clues about performance, but apparently not compared with native C++ apps
 114 [16:58] <oSoMoN> tsimpson: look at the numbers at the end of the article
 115 [16:59] <oSoMoN> looks like it's time to wrap up, thanks everyone for following and the interesting questions

MeetingLogs/devweek1107/QMLHacking (last edited 2011-07-15 08:03:48 by dholbach)