April 8, 2011

Weekend Project: Creating Qt Interfaces with GIMP


Interface design for GUI applications is seldom easy in open source projects. There are a number of valid reasons: interface designers are scarce in comparison to developers, and usability testing isn't always possible the way it is for proprietary software shops,for example. But the tools don't always keep pace with the rest of the platform, either, which is part of why Qt's GIMP QML Exporter is so interesting. Rather than a stand-alone interface builder, it lets the developer design the interface directly in GIMP, and directly export it as usable code.


Getting Set Up: GIMP, Qt Quick and QML

GIMP QML Exporter is a GIMP script written in Python; you can download it from the Qt Gitorious repository. To install it, simply copy the qmlexporter.py file to the .gimp-2.6/plug-ins folder inside your home directory, and make sure to give the script execute permission. When you load GIMP, the script places an "Export to QML" entry in the File menu. The Gitorious tree also includes an example .XCF image file and QML (Qt Meta-object Language) output generated from it.Qt Creator Design

QML is a user interface language modeled on JavaScript and CSS that Nokia introduced with Qt 4.7. The syntax is very JavaScript-like, focusing on visual UI elements (raster images, rectangles, text labels, etc) with easily accessible properties (color, source, transparency, etc), and straightforward animations and transformations. In addition, you can interact with QML elements either through standard JavaScript or through hooks provided by Qt itself.

In order to write a QML-driven application, you will need to get the Qt Quick development kit from Qt. It includes QML documentation and examples, a run-time QML interpreter named Qt Declarative, and the latest version of the Qt Creator IDE. When you install Qt Creator, you will still need to click on a button in the main window to confirm enabling the "experimental" Qt Quick design component. After you do so, the "Design" tab on the left becomes activated, and you can use it to inspect QML layouts.


With the Qt Quick environment set up, launch GIMP and start drawing your interface. Each individual layer that you create in the XCF file will be transformed by the QML Exporter script into a separate QML "Image" object. The script will place it correctly on the coordinate grid, give it an object ID name corresponding to the layer name in the original file, and even assign the correct transparency via the opacity property. And that really does mean every layer: if you draw a button on one layer and add a drop shadow on a layer beneath it, they will both be created as Images.

QML Exporter ScriptThere are two side-effects of this script behavior. First, if you have a compound image that you want rendered as a single piece (say, a background with several image elements or effects within it), you will want to merge those layers before you call the QML Exporter script. Second, remember that GIMP doesn't force you to give convenient names to your layers. So if you build a slew of buttons and status icons into your design, but leave them all with unhelpful auto-generated names like "Layer 15" and "Layer 6 copy," you're going to end up with "Layer 15" and "Layer 6 copy" as the QML object IDs in your code, and you'll increase your own workload trying to maintain it.

Still, most of the time it is nice that QML Exporter renders each object individually, because you can control most of the object properties through QML itself. For example, if you had a way to export your button and drop shadow as a single image, you'd be forever stuck with whatever opacity you originally chose for the shadow in GIMP. On the other hand, because the button and shadow are separate objects in QML, if you decide to change the opacity from 40% to 30%, all you have to do is change opacity: 0.4 to opacity: 0.3 in Qt Creator.

You do have one option at the export stage: whether or not to convert text layers to images, or to generate QML "Text" objects. If you choose text, you can manipulate the font size, color, and other attributes via QML, but of course you lose the ability to make fancy effects.

Whenever you bring up the QML Exporter window, you can also select a name for your project and a directory in which to store the output. The exporter iterates through the file, one layer at a time, exporting full-sized images as PNG files (apparently the only output option at the moment), and creating a QML file with the project name you chose. The images themselves are placed into a subdirectory with _images appended to the name.Qt Quick Enable

Within Qt Creator, you can edit the QML code directly (which is probably what most people will do, since the syntax is so simple), but the Design tab lets you quickly make adjustments, too. You can edit text, move images, and set the most common object properties via the object navigator and standard slider and checkbox controls. You can also quickly add additional states to your project. Experienced developers might find it less precise, but it is also a decent way to teach yourself QML: make changes in the design tab, then inspect the updated source code in the Edit tab.

GUIs at the Speed of Light

GIMP QML Exporter certainly makes GUI design simple — at least for those of us that are visual thinkers. If you've ever struggled with Glade or beat your head against the wall trying to get another toolkit's padding and packing rules to cooperate, you'll no doubt appreciate both Qt Quick and the ease with which you can put together a working mockup in QML.

Nevertheless, there are a few glitches to be aware of. For one thing, QML only accepts object IDs containing letters, numbers, and underscores, and although the Exporter script is kind enough to convert spaces to underscores, it doesn't catch other reserved characters, like punctuation, and it doesn't warn you of their presence.

Also, the example file in the Gitorious tree is, to be honest, pretty bland. It's nice to control UI elements with a CSS-and-JavaScript-like syntax and all, but one of the best things about QML is that it frees you from the constraints of the default Qt widgets' look-and-feel. A better introduction to what the script can do is found in Author Jens Bache-Wiig's YouTube video, Photoshop to QML exporter, which demonstrates how to add animation effects, rotations, and other niceties to the QML output.

Finally, as the title of that YouTube video reveals, Bache-Wiig makes a Photoshop version of the script as well, and for now the GIMP edition of the exporter lacks a couple of the nicer features. In the Photoshop script, you can select an export-time option to not export any layers whose visibility is turned off. You may want to keep a few layers invisible during the design phase if you have different icons for different program states, but it's nice to control whether or not they get generated. The Photoshop edition also takes advantage of that program's ability to group layers together, so you can export a group as a single composite image — but GIMP can't support that feature, at least in the current release.

Perhaps more importantly, though, you can un-check the .QML file generation feature of the Photoshop exporter. Doing so just creates new versions of the image files. If you create the QML file then edit it in Qt Creator, perhaps adding effects or entirely new code, re-generating the QML overwrites all of those changes. Hopefully that feature will make it to the GIMP edition soon.

QML and the Qt Quick kit are targeted at developers of lightweight, mobile apps, not full-blown desktop Linux applications. Still, GIMP QML Exporter is a real find. It lets GUI design take front and center in a creative app, where layout and look-and-feel are first-rate properties, not afterthoughts. Wouldn't it be nice if all GUI toolkits were this easy to control?