Tag Archives: qml

QtQuickControls2 and Desktop apps

GraphicsSoftware

In the screenshot below, the desktop/Breeze-looking scrollbar it’s actually a control coming from QtQuickControls2.
spectacle-c13179

Since one of the goals of Kirigami is to support also desktop applications, while working on Kirigami 2 (that is mostly porting it to be based on top of QtQuickControls2) I had the need for it to continue to integrate with desktop applications as well.
Unfortunately, desktops are not the primary target for QtQuickcontrls2, and while in Qt 5.9 some much needed desktop-related features, such as mouseover effects are getting back in, being as unrecognizable as possible with QWidget-based applications is definitely not in the roadmap.

Luckily, theming QQC2 is easy, so I’ve started a QtQuickControls2 style that integrates with desktop QStyle-based widgets (actually, based upon the QtQuickControls1 QStyle painter machinery).

If we are serious in using QtQuickControls2 in applications shipped together Plasma, we also must make sure they integrate well with the Plasma desktop’s Breeze look and feel.

I started by theming the scrollbar because I felt it was one of the hardest controls to do.
in QtQuickControls2 the scrollbars are supposed to be an attached property of flickables..
This is pretty simple for the mobile use case, turns out it’s a nightmare to create scrollbars that behave like we are used to in the desktop (unless you’re on mac, which insists to look more and more like iOS), which need to be

  • always visible
  • have optional little arrow buttons for increment/decrenent
  • be besides the flickable, not overlapping the contents, because again, they’re always visible
  • use the global desktop theme

I’ve been able to do all of the following, tough it’s necessary to reintroduce the QtQuickcontrols1 component called ScrollView (which imo was a mistake to remove in QtQuickControls2) which can correctly lay out and size the Flickable relative to its ScrollBar.
Hopefully, you’ll be soon able to build an application with QtQuickcontrols2 and Kirigami2 that feels right at home in a Plasma desktop.
What about Plasma-themed QQC2 controls for plasmoids? that will come too, of course!

Kirigami 1.1

Software

Today the first feature update of Kirigami has been released.
We have a lot of bug fixes and some cool new features:

The Menu class features some changes and fixes which give greater control over the action triggered by submenus and leaf nodes in the menu tree. Submenus now know which entry is their parent, and allow the submenu’s view to be reset when the application needs it to.
The OverlaySheet now allows to embed ListView and GridView instances in it as well.
The Drawer width now is standardized so all applications look coherent from one another and the title now elides if it doesn’t fit. We also introduced the GlobalDrawer.bannerClicked signal to let applications react to banner interaction.
SwipeListItem has been polished to make sure its contents can fit to the space they have and we introduced the Separator component.
Desktop Kirigami applications support the “quit” shortcut (such as Ctrl+Q) now.

Plasma 5.8 will depend from Kirigami 1.1, so if you are planning to write a Kirigami-based application, it will work by default and nicely integrate in the Plasma 5.8 desktop.

Plasma 5.8 also has a new big user for Kirigami 1.1, that is Discover: the application to search and install for new software, has a brand new user interface, based upon Kirigami.

plasma-5-8-discover

This is problably the last feature release based upon QtQuickControls 1, QtQuickControls 2 version is on the way at an experimental stage. The port will have way simpler code (and smaller memory footprint) but this is an entry for another day πŸ™‚

Writing QML based apps, the KDE way

Software

This is an interesting transitional period in the Qt world for desktop applications. We are in the phase where QML is becoming better and better for the use in a Desktop context, even for full fledged applications.
We noticed that there were some bits derived from the many years of experience in Plasma that can be very useful for every application developer out there, that fall pretty much in those categories:

  • where to install and how to access QML files.
  • integrating KDE pieces, such as the translation system
  • how to write an application that is 100% QML and how to distribute it
  • how to write an application that is a mix between C++ and QML
  • how to write a KCM for systemsettings that is purely based on qml (and doesn’t even link to QWidgets)

KPackage

Years ago, with the need of having plasmoids implemented with scripted language, we had also the need of having a simple way to distribute those plasmoids around. They are in the end just a bunch of files, that can beany kind of data: the actual source code of the scripts or any needed data assets such as graphics and sounds.
This brought the class Plasma::Package in libplasma, that’s the way to both install/unistall the plasmoid and access any data file or script file from plasmoids.
The problem then posed itself almost identical for things like scripting support in any generic Qt application, like any pack of addons, such as graphics or souds themes.
Same thing for applications based upon QML, that ends up being composed by two parts: purely C++ parts with the central logic and the QML files together any asset that may be needed.
One interesting feature is also that the same files (QML, assets or whatnot) can have versions specific for a particular device, for instance an application may have 99% of the same code between the normal desktop version and one optimized for touchscreen, intended at tablets. Just the few, interested QML files would be duplicated between the desktop and tablet versions.
Since Frameworks 5.6, there is a new tier 2 framework: KPackage, that offers what Plasma::Package offered in libplasma, but with less dependencies and usable by any Qt application that can use a tier 2 framework.

KDeclarative

KDeclarative is the KF5 center for all things related to extending QML.
The framework provides several qml import plugins, such as imports specific of a particular KDE Framework.
It also offers two C++ libraries: libkdeclarative and libquickaddons.
libkdeclarative focuses on KDE related functionalities of the QML engine:

  • KDeclarative: installs things in the QML engine: such as a KIO-based networkaccessmanager and the 18n() transpations functions.
  • QmlObject: A class similar to QQuickView: in which you can just set the url of a QML file or a KPackage instance and it loads it, instances the QQmlEngine etc. The difference with QQuickView is that it’s not graphics based and is not a QWindow, you’ll just have the instantiated QObject *. Useful if your project is not graphic or if you already have a view, and you just want to instantiate a new thing for reparenting it into the view you have.
  • ConfigPropertyMap: it’s a way to access KConfigXT with QML: given a KCoreConfigSkeleton instance, you’ll be abe to read and write its config keys just like it’s a JavaScript Object.

The other one is libquickaddons that focuses on utilities related to QtQuick, the actual graphical components.

  • ManagedTextureNode: it’s a QSGSimpleTextureNode that will manage its own texture, making simpler to implement your own QQuickItem.
  • ImageTexturesCache: helps to manage textures by creating images and reference counts them, use it if your QQuickItem starts from QImage.
  • KQuickAddons::ConfigModule: the base to do KControlModules based on QML, without dependencies from QWidgets, more on that later :).

QML based applications: QML only

qmlpackagelauncher is a tiny command line tool provided by KDeclarative: it’s used to launch an application that is written in QML-only (no main application executable).
The application QML is intended to be distributed in a KPackage structure, with the QML engine initialized with KDeclarative, therefore having things like the i18n() functions available.

QML based applications: mix of QML and C++

The QmlObject class of KDeclarative can now load files from a KPackage, either by setting an existing KPackage instance to it or just setting the kpackage plugin name, making very simple to load a qml file from a plasmoid-like KPackage structure installed on the disk, such as in you main:

KDeclarative::QmlObject *qmlObj = new KDeclarative::QmlObject;
qmlObj->loadPackage("org.kde.example");

For a full application is recomended to use the component ApplicationWindow from QtQuickControls, that’s its own QWindow, so it’s not even necessary to create a QQuickView or QQuickWindow, having the really needed C++ part really just those two lines.

QML based KControlModules

An important part for the ongoing redesign of the Plasma Desktop by the VDG also passes trough writing (and rewriting) modules for Systemsettings or KInfoCenter in QML, to make easy making those franly often outdated UIs beautiful.
One important thing for a mass-migration like that,
ConfigModule has the same API as the old base for kcontrol modules, KCModule, but is a pure QObject, making possible for a future QML-only Systemsettings version.
Start with your old KCModule subclass, keep all the logic in it, but start to scrape off all the QWidget based UI bits and give the class a nice property-based, QML friendly API to read and set the values that will eventually go into the config files.
The actual load and save from the config file, will be done just as in KCModule, by reimplementing ConfigModule::load() and ConfigModule::save().
The UI, QML based part will be provided by a KPackage, with the same name as the component name of the KaboutData of the ConfigModule instance. The QML part will be able to access the configModule instance as the “kcm” global object, just as “plasmoid” is accessible from within the QML code of plasmoids, as well as the ConfigModule QML attached property.

New QML components: Know thy dialogs

Software

Today part of “what to expect in 4.10 in QML components”: Dialog. The Dialog components have been introduced in plasma since sone time, and are documented in the usual page. The components that may be used to create a dialog are:

  • Dialog: unsurprising name: it creates a Plasma themed window with space for a title, a content and buttons. You have to create all of them, you’re on your own, but provides the window management and methods such as open(), close(), accepted() and rejected(). You usually don’t want to use this, unless you want some strange custom things in the titlebar area or in the buttons area.
  • CommonDialog: is a Dialog, but provides a titlebar and the buttons, you want to use this in the 90% of the cases when you want to display custom content in a dialog.
  • SelectionDialog: presents the user a list of items to chose from, useful to create menus when you want to modally ask “what of those items do you want?”
  • QueryDialog: probably the most useful: is a simple dialog with text and two buttons. Used for things like confirmation dialogs like “are you sure you want to delete this item?”. It displays a text and two buttons, that default as “Ok” and “Cancel”, but their text is customizable.

It’s a while this API exists, but in 4.10 there was an important change in its look and feel in 4.10: Now if it’s possible the dialogs looks “inline”. It will be done on the same window as the plasmoid (i.e. on the “desktop”) and if provided with a visualParent property, it will have a comic balloon tip pointing to it. As usual, an image is worth a thousand words:

Dialogs on desktop

But what about if there isn’t enough space? For instance the dialog may be displayed from a Panel, where is impossible to have an inline dialog. Fear not, in this case the dialog will become a separate window, still working everywhere:

Dialogs on panel

An “inline” behavior for dialogs is preferred because in this way questions are semantically and visually grouped with the object they belong to, and most important the desktop layer must not “interrupt” the user, it’s just background information.

The switch between an inline behavior and an external window is completely automatic, as usual, something that the plasmoid should never have to worry about.

New QML components: IconItem

Software

Last post was about a new QML component available in Plasma workspace 4.10 with an important design pattern that comes with it: Lazy loading everywhere when possible.

Next couple of posts will be about other new and old components and the UX concept behind them.

A very important thing in Plasma is to have extremely coherent elements all across the screen, both in graphics appearance and behavior. The fact that two things together in the screen are done by two different plasmoids is something that shouldn’t really matter to the user (it’s a bit of a fail the very moment they even notice, actually). I’ll go in a future blog entry on why seamlessy melting into the environment is absolutely preferable to coming out with “clever” ideas that stick out, even if it seems counter intuitive.

Today: IconItem. From 4.10 there is a new element available in org.kde.plasma.core It’s used whenever you need to represent an icon in a plasmoid (or an active application).

This describes semantically an icon: as everything in plasma you should only describe it, and not care at all how it looks (that’s the task of the component, of the themes, of the final platform and of the global settings). Also, as common in QML, it’s just a painter, doesn’t have any event management whatsoever (so you will do it in a MouseArea for instance if needed).

To use it you just have to do:

import QtQuick 1.1
import org.kde.plasma.core 0.1 as PlasmaCore

PlamaCore.IconItem {
    width: theme.iconSizes.dialog
    height: width
    source: "go-previous"
}

And that’s it. A PlasmaCore.IconItem can load:

  • It can load: freedesktop spec icon names (like “go-previous”, or konsole”). It is the preferred way
  • QIcon instances (useful when the data comes from C++, such as a QStandardItemModel)
  • QImage or QPixmap instances (again. useful pretty much only when the data arrives from a c++ part)

Some behavioral properties:

  • If the icon name has been provided, it will try to load the “best” icon it can find: it tries first a plasma themed monochrome SVG icon from the theme. If doesn’t find it, it then falls back to the classical oxygen icons.
  • For small sizes, (from 16×16 to 64×64) it renders the icon to the nearest “right” size for which there is actually a n image for it on the disk, without trying to stretch it: no more blurry-looking icons! This is also the behavior for all panel icons in 4.10, so your panel will look way sharper.
  • If you set the property enabled to false it will look grayed-out with the same effect as all the disabled icons around KDE applications.
  • If a mouseover highlight effect is needed, set the property active to true (also a property binding like active: mouseArea.containsMouse is fine). It will have the same highlight effect as all across KDE applications.
  • State changes, like enabled/disabled or active/normal or icon changes, will have a short fade animation, that is coherent with the highlight animation of the icons in the panel, like the launcher.

So you should use it always when you have to represent a simple icon in a plasmoid. It is always preferable to the QIconItem component in org.kde.qtextracomponents (the latter should be used only when you can’t really depend from plasma).

You should not use it when your icon is actually meant to be a standalone clickable button. in this case you should either Button or ToolButton from org.kde.plasma.components. For instance, if you icon is in a delegate of a ListView and is the main “decoration” for the delegate (not a small button on a side), IconItem is the way to go, regardless if the delegate itself is clickable or not.

Internally, both Button and ToolButton of org.kde.plasma.components use IconItem to load their (optional) icon, so you are ensured a consistent look and behavior.

Let’s finish with a screenshot of an example where this new IconItem component is used: the system tray.

KDE Plasma Workspace 4.10 will have a system tray completely rewritten in QML (a lot of kudos to Dmitry for this!) and looks like this:

new system tray

Don’t see any difference? yep, that’s the point πŸ˜‰ It looks exactly the same without losing any feature, it just behaves better, its layout is more reliable and the code is an order of magnitude simpler.

Btw, in this post, as well the last post by Aaron, there is also a little taste of something else… different.

Lazy loading QML

Software

What is one of the most important things while writing a QML UI? the answer is pretty easy: KISS.

There are several reasons: the first is of course a reason that is pretty valid in any UI in general: the more an interface is simple, the less visual elements there are, the less redundancy, the more elegant and easy it looks (attention: it does not mean less features, it means just better design
in their representation)

And second, of course the more objects are on the screen, the more memory is taken for their representation, sometimes a non negligible quantity.

Another thing that is very important is to actually load your interface only for the things that you are actually showing right now on the screen, anything that is hidden, or can be shown just eventually, should be instantiated only just before actually showing, otherwise you are paying in startup time and memory for some objects that may even never be actually shown to the user.

A typical example is a tabbar with maybe 10 pages, if those pages aren’t performing an important background task (like loading an html page) why bother loading them?

I’ve just added a new very simple QML component in org.kde.plasma.extras: ConditionalLoader.

It works pretty much like a standard loader: you specify a source component and it instances it, but just when a certain condition is satisfied, so for instance:

 import QtQuick 1.1
 import org.kde.plasma.components 0.1 as PlasmaComponents
 import org.kde.plasma.extras 0.1 as PlasmaExtras

 Item {
     PlasmaComponents.TabBar {
        PlasmaComponents.TabButton {
             text: "foo"
             tab: fooTab
        }
        PlasmaComponents.TabButton {
             text: "bar"
             tab: barTab
        }
        PlasmaComponents.TabButton {
             text: "baz"
             tab: bazTab
        }
    }

    PlasmaComponents.TabGroup {
        id: tabGroup
        PlasmaExtras.ConditionalLoader {
            id: fooTab
            when: tabGroup.currentTab == fooTab
            //source can be a path name as well
            source: Qt.createComponent("Foo.qml")
        }
        PlasmaExtras.ConditionalLoader {
            id: barTab
            when: tabGroup.currentTab == barTab
            source: Qt.createComponent("Bar.qml")
        }
        PlasmaExtras.ConditionalLoader {
            id: bazTab
            when: tabGroup.currentTab == bazTab
            source: Qt.createComponent("Baz.qml")
        }
    }
 }

In this example (simplified, without anchors and whatnot) the content of the tabs is in separated files, and they will get loaded only when the tab will become the current.

It may be used also to do other stuff, like in PopupApplets to load some things only when the popup gets open for the first time, or in delegates of listviews to load extra ui parts when the user clicks on an item, or whatever many other uses.

Note about QML plasmoids and dataengines

BlaBla

There is quite a lot of work going on in plasma land at the moment.

For PlasmaWorkspace 4.10 you may expect an overhauled visual appearance and an overhauled user interface on some plasmoids.

The two weather plasmoids and the pager were rewritten in QML by Luis as part of his gsoc, while others are in the works.

The Notifications and jobs plasmoid is in the works, solving many behavioural bugs that were a limit of the previous architecture (more on that later;)

A Kickoff replacement is on the works as well, and if everything goes allright another important one will arrive for 4.10.

This is made possible by the contribution of the people, I’m seeing a renewed interest in working on plasmoids, also due the new architecture that significantly decrease the learning curve.

But, there is always a but πŸ˜‰

There is a small problem I seen in some converted QML plasmoids: sometimes the needed data arrives from a Plasma dataengine. there is a nice system to map that data directly to a model usable in a QML ListView, Repeater and so forth, DataModel from org.kde.plasma.core

This is a (strong) simplification of the device notifier plasmoid:

PlasmaCore.DataSource {
    id: sdSource
    engine: "soliddevice"
    //hpSource is a datasource connected to the hotplug engine
    connectedSources: hpSource.sources
}

ListView {
    id: notifierDialog

    model: PlasmaCore.DataModel {
            dataSource: sdSource
    }
    delegate: PlasmaComponents.Label {
        text: i18nc("@info:status Free disk space", "%1 free", model["Free Space Text"])
    }
}

The keys of the dataengine are directly mapped to the ListView model, so directly accessible to the delegates via the “model” variable, or directly as their own variables.

However, due to a limitation in QML, if the dataengine doesn’t immediately do a setData() of a particular key, or a key is not always available, it won’t be mapped as a role in the delegates, if you encounter this roadblock, feear not, you can still access the data with something that in the above example would map sdSource.data[“DataengineSource”][“Free Space Text”]

When possible tough use the model mechanism, since some nice optimizations are planned for it πŸ˜‰

One of the things I wish for plasma2 is a formal specification of dataengine available data in a way that would avoid situations like that and most important nice documentation may be extracted from πŸ˜‰

Click here to lend your support to: KDE Randa Meetings and make a donation at www.pledgie.com !

Okular on touch screens

Software

Another small post about new developments in Plasma Active πŸ˜‰

An important use case for tablet is of course Ebook reading (being them pdf, epub or whatever).

KDE offers a very complete document reading application, that supports a wide variety of formats: Okular. It is of course an application optimized for desktop usage and does a very good job at that, but what is less known is that Okular has a very good separation between the logic of document parsing and rendering, managing bookmarks, annotation etc and the ui itself.

It has been revealed very easy to do a set of QML bindings that let opening all the supported documents by the desktop version of Okular and render them on a component directly usable by QML, alongside a very simple touch friendly application.

This application represents the document as a stack of sheets, in which is possible to flick them around, pich zoom and switching pages with a swipe gesture. A side panel that can be dragged in (common UI pattern in Plasma Active) contains an overview of all the pages as a thumbnail grid.

OGG version

It’s just the beginning as both the app and the reusable QML components still don’t have support or UI for more complex things like custom bookmarks and annotations, that will eventually come in future versions.

Brand new Widgets explorer

Software

The rewamp of the KDE Plasma Desktop is continuing: in the 4.8 release it got a completely new QML based device notifier (already quite improved for 4.9), now a new redesign has landed in master, scheduled for the 4.9 release of KDE Plasma Desktop.

The Plasma widget explorer and activity manager have been rewritten from scratch in QML, giving it s much smoother look and feel, new animations for free and what I love most, a way simpler code base.

By replacing the activity manager and widget explorer with the new implementation, over 4000 lines of C++ were removed (traded with around 1000 of much more readable and maintainable QML): this makes it easier to maintain, easier to spot possible problems, easier to modify and experiment new ideas.

With the rewrite of the various components of Plasma Desktop in QML I expect to slash away most of its C++ code base, making the entry level for contributors significantly lower (and being able to finally close long standing bugs πŸ˜‰

How does it look now?

QML widgets explorer

And the Activity manager: designed to look as coherent as possible with the widgets explorer:

QML activity manager

Here showing the inline ui to configure and delete an activity

The overall design is almost the same, but the layout has been redesigned to overcome a problem of the old implementation: it looked quite crowded and dirty, because elements were too cramped together, not very well aligned and sizes were quite eterogeneous. Now we paid a lot of attention about the sizes and positioning of the elements, as shown below, everything is positioned along a quite precise grid, that makes the view look less crowded that it actually is.

QML widgets explorer alignment

I a good trend can be established here, for each release of the KDE Plasma Desktop having some element not only rewritten, but its UI becoming significantly more elegant with few but important improvements in the look or in the behaviour.

QML components documentation

BlaBla

One of the priorities in Plasma (desktop and active) is to have a compelling developer story, to make easy, fun and desiderable for people to write plasmoids and actve apps.

The new QML Plasma Components are a big step in this direction, they give a common QML api across devices for a very easy development.

An important part of this is documentation: Api documentation is progressing quite well, but let’s give a little push forward πŸ˜‰

On the model of the success of the Plasma bug days, let’s have a day on IRC were all interested people can work on them to improve the documentation, have a little getting started tutorial, write wiki pages.

If you are interested on it, please let us know by filling this doodle page.