Mart

a cute little home a cute little boy a cute little cow: mooo!

Tale of a little pixel

a cute little girl

A Declaration of Plasma Love

Declarative RSS reader The image on the left is a new (example) plasmoid that marks an important change... this is going to be a quite massive blog post, with pretty technical details about what I think is going to be a feature of an higly important strategic relevance on the road towards Plasma as a mature and powerful platform.

The Plasma declarative bindings have landed into kdebase! This means it will be possible to use the new QML language part on Qt 4.7.

As Aaron noted some days ago, QML in conjunction with now in heavy development technologies like QtComponents (and in the future Qt cene-graph) will play a key role in the creation of user interfaces in the future, and gives us a very important puzzle piece we were still sorta missing.

So we deceided to be (as usual ;) erly adopters of the technology and with the KDE Plasma workspace 4.6 the first pieces will be in place for the roadmap that will lead us basically to this path:

  • Separate the implementation of the logic from the user interface
  • Avoid C++ (and well, any imperative language) as much as possible for the UI
  • Be flexible, an application should be able to jump between different devices as easily as possible
  • do applications that can chose the proper ui amond different choiced depending on the device used, the screen size, the input methods and what not
  • With QtComponents, use what will be the native set of widgets/components for the given platform: on a MeeGo phone, use its own widgets, theme and UI paradigms, but a different interface somewhere else
  • Performance, perforance, performance, enter Qt scene graph

So, what will have the KDE Plasma platform 4.6 of all of this?

Use QML from C++ Plasma widgets

The first pass (needed to do the following one) is to have a way to easily load a QML file into a normal C++ plasmoid. Now, loading a QML file into a QGraphicsScene (and making it well behave inside the QGraphicsLayout based Plasma widgets) is a quite simple operation, however it is a bit long and repetitive amount of boilerplate code... enter Plasma::DeclarativeWidget.

This is a normal QGraphicsWidget just like the other Plasma widgets, all you have to do is to add it in the QGraphicsLayout of the applet, set the path of a QML file in it et voilą, that's it, you will be able to use about any QML based ui in this way, even if as we will see, if you write a QML/JavaScript only plasmoid there is a richer API available.

Plasma related goodies in QML

QML has a system of exensions called imports: Plasma offers 3 of them, that will be usable by any KDE application that wants to do a bit of QML UI:

  • org.kde.plasma.graphicswidgets : bindings for all our old widgets, in a QML file you just have to write something like PlasmaWidgets.PushButton{text:"foo"; onClicked:doSomething()} to have a working Plasma pushbutton for instance. Those will be gradually replaced with QtComponents as they become ready.
  • org.kde.plasma.graphicslayouts : bindings for qgraphicslinearlayout and qgraphicsgridlayout. In QML use their anchor based layouts where possible, but it's still nice to have qgraphicslayouts in there for the qgraphicswidgets based Plsma widgets
  • org.kde.plasma.core : some core functionality of Pasma, actually the most important things offered here. A DataSource class, to connect to dataengines in a declarative way, alongside classes for the Plasma Theme and our SVG painting and manipulation routines.

Pure QML Plasma widgets

This is where it gets interesting. Since some releases of the KDE Plasma platform, is possible to write plasmoids using just JavaScript.

And not only Plasma Widgets, but DataEngines, Services and Runners too.

We are very happy of those bindings, because they bring a great ease of use in a sandboxed environment, while retaining the possibility to extend them to do more system level operations.

Something that is really important as well is the possibility to add extra functionality to them, in a plugin-based fashion, so it's possible to dynamically add/remove functionality, or update the extra addons plugins.

A place where it's used is the Pastebin Dataengine/Service, where each pastebin-like site has its own addon, simple to add and update.

Another place is in the Plasma Mediacenter project. we have a JavaScript based dataengine used to query various media-related sites (like, YouTube, flickr, you name it). Each backend is a different addon, adding or updating the support for a new site is very simple (and will be possible to do so with Get hot new stuff)

So all of this is very nice, the only part that we weren't so happy was the definition of the user interface of the Plasma widget itself. While significantly easier than C++, it was still an imperative based approach, with manual layout manipulation in the code, like:

  layout = new LinearLayout(plasmoid);
  layout.orientation = QtVertical;

  label = new Label();
  layout.addItem(label);

That for instnce makes impossible to have a graphical designer for the layout, like the good old Qt Designer for QWidget based user interfaces.

QML solves the problem, since is a declarative based language to define user interfaces that even comes with a nice graphical designer in the latest version of the QtCreator IDE, besides making significantly easier to do completely animated user interfaces.

Given the amount of nice features we had in our JavaScript bindings, it was really "mandatory" to not lose any of this, what we really want is the full power of our current JS bindings, with easy access to dataengines, services, exensions, packages, addons and what not; all of this while using the new way to define user interfaces.

This is exactly what landed in trunk (kdebase/runtime) yesterday: a variant of the Plasma JS bindings that shares 90% of the code with its "imperative" brother, so let's see an example of a plasmoid written with this new beast.

Read some news

This example plasmoid is a simple RSS feed reader, right now only a prototype but when will be progressed enough could be a good candidate for the progressive replacement of the components of the default Plasma Desktop towards QML and QtComponents.

First, let's see how it's behaving: videos are always fun ;)

OGG version

As you can see, while it's still missing some touches to be a new default, it's already quite more powerful and pretty compared to the curret C++ one, while it has a fraction of the code.

Now, that the candy is done, let's go to the scary part: the code, but as ou can see it's not as scary as it usually is ;)

there are some interesting things in that code that need to be outlined:

Import of the Plasma related modules:

  import Qt 4.7
  import org.kde.plasma.graphicswidgets 0.1 as PlasmaWidgets
  import org.kde.plasma.core 0.1 as PlasmaCore
  import org.kde.plasma.graphicslayouts 4.7 as GraphicsLayouts

As soon as the loading is completed, as in JS bindings, you can register JS functions defined in the QML component itself as "listeners" for events, in this case the change of the configuration file: note that you have a global object called "plasmoid" just as in the JS bindings, with exactly the same API.

    Component.onCompleted: {
        plasmoid.addEventListener('ConfigChanged', configChanged);
    }

    function configChanged()
    {
        var url = plasmoid.readConfig("feeds")
        print("Configuration changed: " + url);
        dataSource.source = url
    }

Connecting to a DataEngine is very easy:

    PlasmaCore.DataSource {
        id: dataSource
        engine: "rss"
        interval: 50000
    }

If the dataengine results provide a list of items, in this case the list of recent posts of the RSS feed, is really easy to visualize them in a ListView.

ListView {
    id: list
    anchors.fill: listContainer
    signal itemClicked;
    spacing: 5;
    snapMode: ListView.SnapToItem

    clip: true
    /*dataSource.data contains the result of the dataengine,
      dataSource.data['items'] the list of the posts of the RSS feed*/
    model: dataSource.data['items']
    delegate: simpleText
}

Then we want to visualize individual items of the list: enter delegates (here just a little part for clarity).

resources: [
    Component {
        id: simpleText

   [snip]

            Text {
                color: theme.textColor
                textFormat: Text.RichText
                //model.modelData.title is the title of the post
                //represented by the delegate instance
                text: model.modelData.title
            }

   [snip]

This was a not exactly trivial example, but as you can see the code is still not so long and quite clear and understandable. in subversion there are quite a lot of examples that cover the usage of services, addons, extesions and what not.

In conclusion...

All of this is quite a milestone for Plasma, since will allow us to develop new features (and good looking ones!) in a very small amount of time and in a safer way than a pure C++ based approach.

Needless to say, all of this is still quite experimental, and prior to the release of the KDE platform 4.6 any part of it can still change quite a lot.

So in the end to recap, what QML and QtComponents can offer to Plasma? A very easy to use, build and interchangeable user interface.

But, (and here is what i'm interested more ;) what Plasma has to offer to QML?

  • A very easy way to package and deploy simple QML based applications
  • A bridge to use a good portion of the KDE platform API from them
  • A coherent workspace environment to load and display said tiny applications (Plasma Desktop, Netbook, Mobile, or the "standalone application" loader Plasma-Windowed)
  • An easy way to distribute, search, upload and download them (Get Hot New Stuff)
  • API wise, powerful and coherent plugin based systems to query data from local or remote sources, with the ability to use C++, Javascript or any other language we have bindings for (DataEngines, Services, Addons, Extensions)
  • An uniform (and pretty) way to style any graphical element with a powerful (but still pretty efficient) theme engine completely based upon SVG (this part will be stressed even more with the introduction of QtComponents)


Submit comment



Article: