Qt Quick hates me

August 17, 2012

I haven’t blogged since a while, because I do not do much KDE hacking lately, but today I’ve got around to playing with QML again.

The goal was to build something like a breadcrumb navigation widget, where the current directory is indicated by its name being written in a larger font. Here’s what I arrived at after a few minutes:

import QtQuick 1.1

Rectangle {
    width: 800
    height: 100
    color: "black"

    Row {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: parent.top
        spacing: 10

        Repeater {
            id: repeater
            property int currentIndex: 4
            model: ["/home", "/username", "/some", "/pseudo", "/path"]

            Text {
                text: modelData
                font.pixelSize: index == repeater.currentIndex ? 40 : 20
                color: "white"
            }
        }
    }
}

Close enough. Just adjust that alignment:

...
Text {
    ...
    height: 60
    verticalAlignment: Text.AlignBottom
}
...

Gah! Can you see it? The baselines are misaligned. Usually, you lay out text such that all letters “sit” on an even line (the baseline).

The documentation does not mention any type baseline alignment in a Row element (or any type of vertical alignment in a Row element, for that matter).

I then tried to hack around this problem by dropping the Row element and laying out the Text elements manually, but the elements in the repeater won’t anchor to each other. That’s probably a problem with the elements not being fully initialized when the anchor property is evaluated, but at this point I give up.

This has been my second experience with Quick. When I tried it for the first time, my goal was a Quick version of the Planarity game. I got stuck when I noticed that Qt Quick 1 does not have any kind of line or ellipse primitive (only rectangles and images). Really?!?

So, while I understand very well and appreciate the idea behind Qt Quick, I have come to the conclusion that Qt Quick hates me. Or I have a talent of hitting a roadblock within ten minutes, regardless of the general direction.

P. S. Turns out the WordPress WYSIWYG editor hates me, too. (Well, either me or the combination of <pre> and images.)

Another inquiry post. I’m thinking about removing the custom mouse interaction code in Palapeli. The situation is that whereas most applications hardcode what certain mouse buttons do (e.g. left button = click, right button = context menu), Palapeli allows the user to configure which mouse button (or wheel) does what. For reference, this is the default configuration:

Problem is that the code behind these mouse button associations is awkwardly complex.¹ I plan to remove this mess and replace it with a sane default configuration because I feel it’s just adding clutter without providing much added value.

So if you want me to keep this code, please write back. Besides that, I also accept recommendations for a better default configuration.

¹ In numbers: 1127 LOC where the whole application is about 6000 LOC.

Any users of libkdegames?

January 31, 2012

Since we’re thinking about updating libkdegames, I was just wondering if any developer outside kdegames uses libkdegames. If you are or know such a developer, please write a comment.

While I was on my quest of reducing the memory footprint of a freshly launched KDE session, I found that the process which uses most memory just after startup is Amarok, which contributes over 80 MiB to 300 MiB total RAM usage. Now of course, Amarok has its reasons for a high memory usage: For example, its collection is backed by a MySQL/Embedded database. This memory footprint is justified by the plethora of features Amarok offers. But still, 80 MiB RAM usage is quite a lot when all I want to do (99% of the time) is to listen to some music files on the local disk. (My collection has 818 tracks at this very moment.)

Can we improve on that?

Looking at my desktop, I see the “Now Playing” applet. It shows the current track from Amarok, and has the basic media player controls (pause/stop/previous/next + seek slider + volume slider). Again, this is about all I need for an user interface while my playlist is filled. I remember that the nowplaying applet communicates with Amarok via DBus using the MPRIS (Media Player Remote Interface Specification) standard.

With all these impressions in mind, my target is clear: I want a headless media player which runs in the background and offers an MPRIS-compliant control interface on DBus. Something with a smaller memory footprint.

Intensive searches on the internet did not turn up anything of interest. Of course there are command-line music players (e.g. MPlayer), but those expect to be connected to a terminal for control. They cannot be run in the background, and there’s no nice GUI for them (like with the nowplaying applet). It looks like I need to do it myself yet again.

So here is the Raven Music Server (called ravend for short, as it is a daemon), which is now publicly available at git://anongit.kde.org/scratch/majewsky/raven. It currently implements the basic interfaces mandated by MPRIS version 2 (unfortunately the “Now Playing” applet supports MPRIS 1 only). The biggest missing piece is support for editing the track list, so at the moment you need to restart the process to change the playlist.

I have been productively using ravend for two weeks now, since one day after its inception, and I’m quite satisfied with it. And now that it is in a public Git repo, you can, too! Provided that you find pleasure in controlling your mediaplayer with commands like

qdbus org.mpris.MediaPlayer2.ravend /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause

Convenient user interfaces will become available, eventually. Even then, the Raven Music Server will probably not be interesting for end users. Power users may find this project interesting if they like to keep an eye on their system’s memory footprint, or want to have their playback continue even when the X server is terminated, or want to run a full-fledged media player on a headless system.

I have some systems where I don’t use Kontact or anything else that makes use of Akonadi, so my Akonadi database is empty. Still I find the Akonadi server and its numerous agents running when I have just started my session.

The Akonadi server is only started when some application needs it. So who wants to communicate with Akonadi? After some search, I found that the clock applet on the Plasma panel is the culprit. It has a feature to display events from the Akonadi calendar which is enabled by default (and I don’t want to oppose this choice; it’s a very nice integration feature for people using KOrganizer).

So if you want to prevent the Akonadi server from starting on systems where you don’t use Akonadi, or just want to speed up the startup of your KDE session by delaying Akonadi’s startup until it’s actually needed, do the following: Go to the configuration of the clock applet, and disable “Display Events” in the “Calendar” section.

To check whether Akonadi is running, open the “System Activity” monitor with Ctrl+Esc (or by clicking on the second icon from the left in KRunner). Look for a process called “akonadiserver”. (There will also be multiple processes with names like “akonadi_agent_launcher” or “akonadi_whatever_resource”.) You can also manually start and stop Akonadi with the commands “akonadictl start” and “akonadictl stop” (from either the command line or KRunner).

What you see here is the very first steps towards systemd integration in Qt. I’ve started to build a libqsystemd, which wraps systemd’s DBus API into something which can be used by Qt applications. The screenshot shows a simple QML-based Plasma applet reading information about available systemd units from a simple dataengine.

At the moment, the library can only list available units, providing about 60% of the info which you would get from `systemctl list-units`. But adding more functions should be trivial now that the foundations are laid.

The only interesting point left is how different privilege levels will be handled. For example, only root may activate and deactivate units, initiate system shutdown etc. Most properties are even read-protected from normal users.

Of course, providing a library interface is only the first step for systemd integration with KDE. The second step is to actually use it. For example, systemd provides standard interfaces for setting the hostname, timezone, etc. in a desktop-independent manner. systemd can in the future also be used to coordinate the startup of a KDE session, and thus replace parts of startkde and kdeinit.

The fact that KDiamond is included by default in Plasma Active’s default set of “Favorite applications” (among rekonq-active, calligra-active, and friends) finally made me hack a bit on kdegames stuff again. The main problem I see with KDiamond on a mobile form factor is that menubar and toolbar waste quite some vertical space. Also, the menubar is awful to use on a touchscreen; the toolbar is much better in this regard.

Can we combine these observations into an interface that saves space, yet is as approachable as a simple toolbar? We can.

In the back is the normal menubar/toolbar chrome. In the front is my first draft of an “Active” version of it. The menus “Game” and “Move” are completely gone, all contained actions are now on this first level of the toolbar. The “Settings” and “Help” menus have turned into toolbar buttons. Upon pressing one of these, the toolbar descends into that subcategory:

After selecting something from a subcategory, the toolbar automatically returns to the default category. For example, if you click on “Settings”, then on “Configure KDiamond”, the theme selection dialog comes up. When you’re done with that, you come back to the main window and find the default toolbar with the relevant New/Pause/Hint actions again.

What do you think? A first step in a good direction? Something you would even want on the desktop? Or just plain awful? Please let me know. BTW the source is available on ReviewBoard.

P.S. To get that straight: This is only for games with a small set of menu actions (about 28 of 40 KDE games, according to my counting). Apps like KGoldRunner or KTuberling just don’t fit the idea behind this proposal and will therefore not be affected.

P.P.S. I’m aware that vertical space is still wasted. I’m going to experiment with moving the toolbar to the side for displays which are wider than tall.

Now on Twitter

April 2, 2011

My last post was quite big, so I’ve split out the news part to ensure that it gets some attention. I’m now on Twitter as @stefanmajewsky. Follow me for updates on my KDE development, esp. Palapeli and Tagaro. My blog posts should also be syndicated there automatically; this post is the test balloon.

The Blue Wonder Meeting last week was an excellent opportunity to do some work on Palapeli. One thing that I wanted to do for at least a year was to rewrite the multithreading code around the (fairly central) Palapeli::Puzzle class. The new class has an aspect-oriented design, where single components of the puzzle (like the metadata or the contents) are always made available by worker threads, by casting existing components. For example, a puzzle file can be casted into metadata by reading the latter from the puzzle file. The possible casting paths are actually so convoluted that I documented them in an image inside the source code directory:

Yet there are still areas where Palapeli’s concurrency needs to improve. Much of the puzzle loading is done in the GUI thread, which causes the loading animation to freeze frequently. But that’s for another day. Moving back from what I should do to what I actually did, I noticed that Palapeli’s memory usage is awful. During the sprint, I wanted to demo Palapeli’s performance with big piece counts, and created a puzzle with the maximum of 2000 pieces from a 5000×5000 px image. It actually rendered fluently, but only because I upgraded my notebook’s RAM to 2 GB last year. Palapeli used an enormous 1.6 gigabytes of memory.

I figured that’s a bit much, and looked yesterday evening into how this can be optimized. I was testing with a 30 pieces puzzle from a 4000x4000px image. After having started Palapeli and having loaded the puzzle, the application used about 800 MB memory. The first, and simple, optimization was to remove some intermediary images which are only used while loading the image. That saved something like 100 MB of memory. But wait! Shouldn’t a 4000×4000 pixel image need only 61 MB (four bytes per pixel)? Yes, that’s true, but actually we’re not talking about one big image, but about 30 images, one for each piece. While pieces might have an arbitrary shape, their image must internally be rectangular all the time, even if big parts (e.g. around the plugs) are fully transparent. This means that the memory usage for the 30 pieces is bigger than what one might expect from the complete image.

A randomly chosen piece was 855×1098 pixels big, so by a rough approximation, all 30 pieces take 30*855*1098*4 bytes = 107 MB in memory. That still does not explain why the process still occupies 700 MB. But what’s that?

There’s a shadow around the pieces! This shadow is not added by the slicer when the puzzle is created, but by the engine when the puzzle is loaded. And because we need to control how shadows cover other pieces, we cannot render the shadows into the piece image, but must store them as separate images! And to make matters even worse, we need different shadow images for selected and unselected pieces (note the difference between blue and black shadows). The shadow size for the test image is 0.15 * (width + height) = 300 pixels on each side. Putting everything together, the memory usage of piece images + normal shadows + selected shadows is about 700 MB, i.e. everything can be explained by the pure size of the displayed images. The second optimization therefore was to restrict the shadow size to 50 pixels. This reduces the memory consumption to 380 MB, and allows to play even 5000×5000 px (i.e. 25 megapixel) images with below 1 GB of RAM.

More sophisticated optimizations are certainly possible, but let’s stop at this 50% improvement for now. There’s another thing I want to show: Palapeli’s mainwindow has been cleaned up. I really liked the old tab interface. It had its time and justification, but I want to move forward and need a cleaner, more standard interface for that. So now Palapeli has only a menubar and toolbar, just like all the other apps:

This change was possible after I realized that all toolbar actions for the collection also make sense on the puzzle table: Delete and Export work on the current puzzle. Newly created or imported puzzled will be loaded into the puzzle table afterwards. The “Back to collection” button replaces the “My collection” and “Puzzle table” tabs.

No time to blog yesterday! The Gluon guys were at my flat and we spent the evening cooking some tasty vegetarian meals. (No idea where the photos from this ground-breaking event ended up, though.)

Of course, we had some productive sprint session before that, which Josef covered yesterday already. The only missing part for now is the obligatory group photo below, which is (along with other photos) available from the git repository at kde:scratch/majewsky/blue-wonder-meeting.

From left to right: Josef, Laszlo, Felix, Shantanu, Arjen, Dan, me, Friedrich, Julian and Jeffrey.