Preface

This document is now outdated. The QStyle API was changed in Qt 3, so if you want to write a widget style for KDE 3, this page isn’t too much use to you, except perhaps the tips at the end.

You can download a copy of this document and all related example code here:

widget_style_tutorial.tar.gz

Introduction

KDE allows two methods of customising widget appearance.

‘Code’ styles

A ‘code’ style is a shared library module, containing code which implements the virtual methods of KStyle (and QStyle.)

Advantages:

  • Can be very fast.
  • Customisation possibilities are great.

Disadvantages:

  • Must be compiled for each target platform.

Pixmap themes

A pixmap theme consists of a set of pixmaps and a configuration file, which describes how the pixmaps will be arranged on-screen.

Advantages:

  • Can be created by non-programmers.
  • More suited to complex decorations.

Disadvantages:

  • Not as flexible as ‘code’ styles.
  • Can be slower than ‘code’ styles.

This tutorial will cover ‘code’ styles only. If you are not a programmer, please look at the tutorial on mosfet.org to learn how to create a pixmap theme.

Prerequisites

  • You are sure that a pixmap theme is not better suited for your requirements.

    If you are wanting to use a lot of pixmaps, you’re probably best off with a pixmap theme, nevertheless you may need more control than afforded by pixmap themes, so you are forced to write a ‘code’ style.

    If you use pixmaps within a ‘code’ style, you will have to be careful with memory allocation, caching, etc. Good luck !

  • An environment that allows you to build KDE apps, i.e. KDE libraries and headers installed, a compiler, perl, etc.
  • The example code tarball.

Getting started

To begin the process of creating a widget style, you need to set up a build system and create some skeleton code which you can modify one piece at a time.

Fortunately for you, I’ve already done this bit. Unpack the tarball. In there you’ll find an example widget style called ‘web’, a skeleton implementation and a copy of this document.

cd skel_style
./setup MyStyle mystyle 'My style' 'A funky style'

‘setup’ does a simple search and replace, then renames some files to reflect the class name you provide.

The first parameter to setup is the name you want to use for your class.

The second parameter is the name you want to use for your library. Please use a string of lower-case letters, without punctuation, otherwise you might confuse automake.

The third parameter is the name of your style as it will be shown to the user (which will be translated later.) You can use spaces, as long as you put the text in ''.

The fourth parameter is the American English description of your style (which will be translated later.) You can use spaces, as long as you put the text in ''.

Now you should have a complete setup. Next steps:

make -f admin/Makefile.common
./configure --with-pic --enable-debug
make install

Now your style should be installed and working. You can set your style as the default for all KDE apps started in future by using:

settheme src/MyStyle.themerc

If you’re having trouble with your style, you can go back to the default style like this:

    settheme $KDEDIR/share/apps/kstyle/themes/default.themerc
  

You might notice that your style looks exactly like the low-colour default KDE style. That’s because all the method implementations simply call the KStyle:: versions.

Writing some code

This is where you start doing some work.

$EDITOR MyStyle.cpp

The plan: Replace some or all calls to KStyle in MyStyle.cpp with your own drawing code. How you paint is up to you - it’s your style !

$EDITOR WebStyle.cpp

The ‘web’ style is there for a reason. I wrote it especially to go with this tutorial. It uses simple drawing, which should give you a good base to work from, but it also uses a few tricks, so you can see how to achieve more flexibility. It has bugs, yes. I’ll try to fix them in the near future.

The last thing I can do to help those writing their first KDE widget style is to offer some tips, based on my experience.

Tips

  • The best way to see the results of your work is to use settheme to select your style for new apps and then just make install and open a new application. I use kcontrol and konqueror for most testing because they contain a good selection of KDE and Qt widgets.
  • Start simple ! Draw everything as a simple box, so that you can see what kind of area it covers, then move on to make it look pretty.
  • It’s probably a good idea to start with the more simple methods (e.g. drawKickerHandle) and work up to the harder stuff (scrollbars !) later on as you gain more understanding of how your changes affect appearance.
  • Use QPainter::save() and QPainter::restore() to avoid side-effects.
  • You can use some magic to create mouse-over effects. See the WebStyle example, method WebStyle::polish(QWidget *). The trick is to install an event filter on a widget when it it styled and use that filter to catch mouse enter/leave events.
  • Styling QFrame is difficult. There is no QStyle::drawFrame(). You have to use your ::polish(QWidget *) method and try to make a sensible decision about when to mess with the frame style. I haven’t quite got it right with WebStyle, but it’s almost ‘correct’.
  • Most methods have a QPainter passed as a parameter. In some cases the painter may already be translated for you, so you need to use (0, 0) for the top corner. drawPushButton() is an example of this.
  • Be consistent when using colours from the palette (QColorGroup). Read carefully the documentation of QColorGroup and make sure you check how your style looks with other colour schemes. I have not been entirely consistent in WebStyle and I really should fix it.
  • Read code ! WebStyle was written specifically so that there would be some simple, understandable code that you can read and use. Dig deeper (KStyle, QStyle etc) if you need more info. Yes, the docs for KStyle and QStyle are pretty poor. RTFS applies, sorry.
  • You can restart kicker (to see the effects of your style) with: dcop kicker Panel restart
  • Comment out or remove parameter names when you aren’t using them, so you can find real warnings/errors more easily. If your editor does syntax highlighting then you should be able to spot parameters you commented out later.
  • Try to keep the round-trips with the X server down to the minimum.

    Examples:

    • Draw sets of points using QPainter::drawPoints().
    • Keep pixmaps on the X server where possible, i.e. avoid QImage->QPixmap conversions.

Please mail me if you find any errors in this tutorial or can improve on the example code (that shouldn’t be too hard ;) - If you can make this tutorial better, I’ll incorporate your changes.