Jens
Qt
Styles
Posted by Jens
 in Qt, Styles
 on Friday, June 26, 2009 @ 14:08

I did some work this week on a task related to higher DPI values on Vista. The task was essentially about scaling artifacts related to checkboxes, radio buttons and menus. However after fixing up those I decided that we needed a little more to really work properly on Vista and Windows 7 and realized that there were still quite a few hard-coded pixel metrics in the current styling API that really should depend on DPI as well. So after adjusting those metrics, most Qt apps should now look a lot nicer at higher DPI values. The fixes will also directly benefit similar functionality on Mac, once this gets properly supported by Apple.

Here are some screenshots showing noticable improvements in 4.6 vs 4.5 at a moderate scale size of 1.25:

dpi1.png

With the improved DPI-scaled metrics this is what it should look like in 4.6:

dpi2.png

No radical change in this case, but it certainly looks more polished than the old one. At very high DPI scaling values (1.5 and up) Windows Vista defaults to showing applications in a compatibility friendly, but rather fuzzy scaled mode. In 4.6 we plan to make applications scale properly by default. Unfortunately existing applications are likely to have pixel-based assumptions, so the only real way to ensure that your app will look correct is to try it out.

dpi45.png

And again, this is how things should look with 4.6:

dpi46.png

AndyS
Qt
Styles
Posted by AndyS
 in Qt, Styles
 on Friday, June 05, 2009 @ 13:43

It is a fairly regular occurrence in my job in Qt Software Support that I get asked how to change the look and feel of a given widget and usually this means changing the style. If the application is going to only be released for one platform, for instance Windows XP, then this is simple because all you need to do is subclass QWindowsXPStyle and make the necessary change by reimplementing one of the functions.

However, if your application is going to be targeting more than one platform, for instance Windows and Mac, then in order to get the same change you would need to subclass QWindowsXPStyle and QMacStyle, and maybe you want to cover Windows Vista as well, and before you know it you have to maintain 7 different style subclasses just so that you can modify a tiny aspect of the look and feel for a widget!

Luckily help is at hand in the form of a proxy style, this was originally mentioned way back in Qt Quarterly 9 (all those years ago) using a class that subclasses QStyle and had a member variable which would point to the original style being used. For the curious the article can be found here.

On the face of it, this looks like it will do the trick, and it looks nice, however it is not as robust as it appears. The problem with this approach is due to the fact that inside the styles themselves they call the style functions directly. For instance in QWindowsStyle::drawControl() it will call styleHint() directly meaning it won’t call your reimplemented styleHint() function in the ProxyStyle class and its turns out to not be so useful at all anymore.

So the problem still remains, how do we make this smarter? The proxy style approach is still the one we want to go with as this will give the result we want, however its the implementation of it that we need to change to cope with the situation better. Therefore we need to somehow have subclasses of the existing styles that use the proxy style approach.

Firstly we create a ProxyStyle class that isn’t a subclass of QStyle (all will make sense later I promise :) In this example I want to change all styles to always underline shortcuts so to do this I need to reimplement styleHint() in the styles.

class ProxyStyle
{
public:
    ProxyStyle(const QString &baseStyle) { style = QStyleFactory::create(baseStyle); }
    int proxyStyleHint(QStyle::StyleHint hint, const QStyleOption *option = 0,
                             const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const
    {
        if (hint == QStyle::SH_UnderlineShortcut)
            return 1;
        return style->styleHint(hint, option, widget, returnData);
    }
private:
    QStyle *style;
};

This is similar to the approach that is given in Qt Quarterly 9 except the difference is that we don’t have a styleHint() function but we have a proxyStyleHint() function, this is delibrate due to the following:

#define ADDSTYLESUBCLASS(BaseStyleClass, BaseStyleName) 
class My##BaseStyleClass : public BaseStyleClass, public ProxyStyle 
{
public:
    My##BaseStyleClass() : BaseStyleClass(), ProxyStyle(BaseStyleName) {}
    int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const
    {
        return proxyStyleHint(hint, option, widget, returnData);
    }
};

This is where we are actually subclassing the styles themselves, it has been added as a macro because we want to make it easier to just add styles that a subclass should be provided for. So if for example a Windows 7 style was added in 4.6, it would be easy to update this relevant code. We only need to reimplement the functions that we are interested in, so in this case we add a styleHint() reimplementation that calls our proxyStyleHint() function.

So to make all styles available we just use the macro to define the classes like such (delibrately cut just for illustration purposes):

ADDSTYLESUBCLASS(QCleanlooksStyle, "cleanlooks");
ADDSTYLESUBCLASS(QPlastiqueStyle, "plastique");
ADDSTYLESUBCLASS(QMotifStyle, "motif");
ADDSTYLESUBCLASS(QWindowsStyle, "windows");
ADDSTYLESUBCLASS(QCDEStyle, "cde");

Now its possible to use MyQWindowsStyle and this will always call our proxyStyleHint() implementation even if its called from QWindowsStyle itself or directly on the style.

There is just one thing left to do to make this easy to replace any existing style either on a widget or on the application. In order to be able to determine which subclassed style should be used a function is added that utilizes qobject_cast to determine which one should be used (again cut for illustration purposes).

QStyle *returnSubclassStyleForBaseStyle(QStyle *baseStyle)
{
    if (qobject_cast<QWindowsStyle *>(baseStyle)) {
        if (qobject_cast<QCleanlooksStyle *>(baseStyle)) {
#ifdef Q_OS_X11
            if (qobject_cast<QGtkStyle *>(baseStyle))
                return new MyQGtkStyle;
#endif
            return new MyQCleanlooksStyle;
        }
    ...
    if (qobject_cast<QMotifStyle *>(baseStyle)) {
        if (qobject_cast<QCDEStyle *>(baseStyle))
            return new MyQCDEStyle;
        return new MyQMotifStyle;
    }
    return baseStyle;
}

Leaving just one line needed to set the proxy style on the application in our example:

app.setStyle(returnSubclassStyleForBaseStyle(app.style()));

And there you have it, the application still looks native with the exception of the change that has been done in the style. The way that this is implemented makes it easy to add your own changes in, as you only need to change it in one place and also makes it easy to add support for new styles too.

Unfortunately there is a problem with this approach and that is that it does not work with styles that are implemented as plugins, the approach used here needs to be able to know about the classes themselves. So for example, this will not work exactly as expected when the KDE Oxygen style is used as the code does not know about this style. However, this problem would occur too if an application developer wanted to subclass the Oxygen style to make the change directly (without using the proxy style approach). If the Oxygen style can be linked against in some way then it would be possible to utilize this approach, since all that is needed is to be done is to add an ADDSTYLESUBCLASS line and add a couple of lines to the returnSubclassStyleForBaseStyle() function.

The whole code for the proxy style approach is available here.

Jens
Uncategorized
Qt
Styles
Posted by Jens
 in Uncategorized, Qt, Styles
 on Tuesday, March 31, 2009 @ 13:31

There are a few widgets in Qt that have been treated a bit like a stepchild to other widgets. One of these widgets is the QDial. To a certain extent this has been intentional. A normal flat slider is almost always a better choice usability wise and most platforms do not have a native equivalent so it has been left looking a bit out of place everywhere. In fact the only face lift it has received since Qt 3 days is a bit of anti-aliasing. In case you haven’t seen it, here it is in all it’s glory:

old dial

However lately there has been an increased interest in touch screen devices where QDial seems to make a bit more sense usability wise. Combined with the fact that it has always been an eye-sore in our styles example I decided to finally do something about it for 4.6. So here is the new and improved QDial:

new dial 2

As you see it’s a bit more shiny. It replaces the ugly focus rect with a subtle glow and it’s designed to look more like something more out of this century. Old styles like motif and windows classic will still get the old looks because that’s what they are… old, but on all our modern styles we will use the new one. I hope you like the change.

styles example
Edit: Added a new screenshot in a few different styles also showing the increased contrast.

Jens
Qt
Styles
QGtkStyle
Posted by Jens
 in Qt, Styles, QGtkStyle
 on Wednesday, October 01, 2008 @ 08:24

One of the few remaining complaints against Qt applications using QGtkStyle on GNOME have been about the file dialog. So far it certainly looked like a GTK+ dialog, but it was not exactly the same dialog that other applications had been using. While I’m not really in a position to comment on which dialog is the better one, this is what it currently looks like with QGtkStyle:

Gtk dialog with Qt

However, the policy on other platforms such as Windows and Mac OS X has been to use the native dialogs if possible. I recently applied some patches to support this for GTK+ as well. This is what you will see if you open forms in Designer now:

Gtk dialog with Qt

Note that since the KDE file dialog provides somewhat different functionality from the Qt one, KDE applications will still use the KDE file dialog. Feel free to try it out directly from the svn on my labs page and report whatever issues you might find here.

Jens
Uncategorized
Qt
Styles
QGtkStyle
Posted by Jens
 in Uncategorized, Qt, Styles, QGtkStyle
 on Friday, September 05, 2008 @ 14:14

QGtkStyle made it’s way into the Qt snapshots this week, meaning it will become part of the Qt 4.5 release. Technical users can already compile and use it on their own desktop, but once Qt 4.5 is out it will simply replace Cleanlooks as the default application style Qt uses on GNOME desktops. While I haven’t blogged about it since the announcement back in May, a lot of fixes and improvements have gone into it since then and I’d like to thank everybody contributing bug reports, suggestions and patches to the project so far. Since the existing plugin based on Qt 4.4 seems rather popular and not everybody feel comfortable using an unstable version of Qt, I will continue to maintain it as a separate project and accept bug reports over at my google code page.

Clearlooks dialogglider theme

In other news, the nice folks over at the Qt4 Maemo garage have been adapting QGtkStyle to work nicely with the Maemo platform as was evidenced by lorn’s post last month. Samuel also blogged about using Freetype for subpixel filtering which should eventually take care of any differences in font rendering between Qt and GTK.

Jens
Uncategorized
Qt
Labs
Styles
Posted by Jens
 in Uncategorized, Qt, Labs, Styles
 on Tuesday, May 13, 2008 @ 20:28

textedit with gtkstyle

Now that 4.4 is out, I finally found the time to kick off some new development and one of my pet projects these days is QGtkStyle. We already have QCleanlooks, icon themes, standard shortcuts and dialog buttons to integrate with GNOME, but to achieve true perfection we need to use the Gtk theme engine directly just like we do on Mac and Windows. QGtkStyle does exactly this, and in addition extends and surpasses QCleanlooks in a lot of other areas as well. All group boxes are now flat style to blend better with GNOME dialogs. Icon theme support has improved, scrollbar buttons are disabled at edges and item view branches now support hover.

spreadsheet example

The style is already available right now as a Qt 4.4 plugin on Labs and given that you can accept the normal disclaimers about using unreleased and experimental code, you can start playing with it immediately.

This is how the Arora browser looks:

clearlooks style

All the above shots were taken using the “Clearlooks” engine. Here are a few alternatives:

Ubuntu Human:
mediaplayer

Mythbuntu:
mediaplayer

And of course the unforgettable Raleigh engine:
mediaplayer

kamlie
Styles
Posted by kamlie
 in Styles
 on Friday, January 11, 2008 @ 14:52

“You look at your stylesheet in awe, amazed at your own artistic power. You have just styled your widget to perfection, and it is so beautiful one could cry. Now, just to finish off with that one-pixel adjustment to the left, and…. what!? Why does it suddenly look different?”

I am sure many of you have been there when stylesheets do unexpected things. This stems from the fact that the styles were not originally meant to support stylesheets and all the adjustment capabilities that come with them. So whenever a stylesheet tries to do something that the underlying style cannot offer, it falls back onto a different style.

For this reason, we are currently aiming at trying to make stylesheets a little more consistent and predictable, and there are several approaches that can be followed. I hereby invite the readers to post some comments about what they think is important with stylesheets.

You are free to write whatever you feel, but here are some guiding questions:

  • What is your typical use of stylesheets? Giving widgets a brand new look, or just changing a color here and there?
  • Is your program used on more than one platform?
girish
Qt
Qtopia
KDE
Styles
Posted by girish
 in Qt, Qtopia, KDE, Styles
 on Tuesday, November 27, 2007 @ 16:37

This feels great. This post is an eight year old dream come true - I have always wanted to write an article titled “… for fun and profit” ever since I read the amazing phrack article :).

Qt Style Sheets makes it possible to style Qt widgets, we all know that. But, what if some user loved this Qt application and would love it even more, if only it had red push buttons (some users have strange fetishes)?

Qt 4.3’s well kept secret
In Qt 4.3, users can customize the style of any application without touching or recompiling the code. All Qt applications can take an external stylesheet using the -stylesheet command line switch. So, create a file called mystyle.qss containing “QPushButton { background: red; }”. Now start, any Qt applications as “qtapp -stylesheet mystyle.qss”. Sweeeet.

Theming Qt
So one can style widgets, but what if one wants to move things around. What if one wants the application to have a completely different layout. We have received many requests for supporting layouting in Qt Style Sheets, but did you know theming Qt applications is already possible?

So let’s see - we need a mechanism for the user to specify the layout. We can probably define our own XML format but it turns out Qt already has one and you use it all the time - .ui files. .ui file is nothing but the user interface described in XML. All we need is a mechanism to load these ui files on the fly.

Enter our hero QUiLoader. QUiLoader reads a ui file and gives you back a QWidget pointer. Ui files can be edited using Qt Designer, so you don’t need to create your own layout tool. In addition, QUiLoader::setWorkingDirectory allows creating ui files with external resources. That said, the main disadvantage is that theming this way requires you to modify your application.

I cooked up a media player that implements the above idea. You can add new themes in the themes/ folder. In addition to a layout(ui) file, the theme can also specify a style sheet. MediaPlayer can load these new themes with no recompilation.

Here’s the Classic theme that has the media controls on the bottom.
Classic Media Player

Here’s the Modern theme that has the media controls on the side.
Modern Media Player

To create a new theme,
* Unpack the source (with git history)
* qmake && make
* cp -R themes/classic themes/mytheme. At this point, mytheme and classic are identical.
* Edit file in mytheme/mediaplayer.ui using Designer
* Edit style sheet in mytheme/mediaplayer.qss using text editor
* Edit icons (play/stop/pause) under mytheme/.
* Notice how media player can support new layouts and styles with no recompilation at all.

Enjoy!

P.S: This is really a guest blog since I don’t work for Trolltech anymore :-) Please contact me at ramakrishnan dot girish at gmail, if you have any questions.

girish
Qt
KDE
Itemviews
Styles
Posted by girish
 in Qt, KDE, Itemviews, Styles
 on Thursday, November 01, 2007 @ 11:27

It all started as a small feature request - Adding style sheet support for Item views. I quickly found out that our default delegate, QItemDelegate, doesn’t use QStyle the way it is supposed to. Jens had faced the same problem when trying to provide native look and feel for Vista and ended up writing his own delegate. This is quite a limitation because currently authors of custom QStyles can customize the look of everything in Qt except item views.

So was born QStyledItemDelegate - The default delegate for Item views starting 4.4. To let that sink in - all our views now delegate painting to QStyledItemDelegate instead of QItemDelegate. QStyledItemDelegate prompty plays its part by delegating everything to QStyle :-) The cool thing is that this delegate uses the QStyle to determine the sizeHint, the layout of the text, indicators and icon. And of course, it paints everything through QStyle. Complete control to QStyle.

Jens has already incorporated this new feature into QWindowsVistaStyle. So, by default, your views will look all fancy in 4.4 like below:

vistatree2.png

We are unsure about how selection in table view must be handled. We are open to suggestions:

Chart example in vista style

On other platforms, they should exactly like before. If you had written your own delegate using QItemDelegate, it is completely unaffected by this change. If having to write a custom QStyle or a custom delegate sounds daunting, just use style sheets. Try something like this,

QTreeView::item {
    border: 1px solid #d9d9d9;
    border-top-color: transparent;
    border-bottom-color: transparent;
}

QTreeView::item:hover {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
    border: 1px solid #bfcde4;
}

QTreeView::item:selected {
    border: 1px solid #567dbc;
}

QTreeView::item:selected:active{
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);
}

QTreeView::item:selected:!active {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);
}

Here’s how it looks:

stylesheet-treeview.png

See Customizing QTreeView, Customizing QListView for more information.

We merged the new delegate into our main branch last week, so if use the latest snapshots, you already have it. If you have any specific requirements to styling of tree widgets, list views and tables in mind and are wondering if it is possible now using the new delegate, please leave behind a note!

Jens
Qt
Styles
DotNet
Posted by Jens
 in Qt, Styles, DotNet
 on Friday, July 06, 2007 @ 17:18

The style now comes in two flavors: Standard, and Office. The standard style is the one seen previously. The new Office style is presented here:

office style

I also have some good news for commercial users waiting for this. The style will be renamed QtDotNetStyle and should be released as a dual licensed Qt Solution, hopefully next week.



© 2008 Nokia Corporation and/or its subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation in Finland and/or other countries worldwide.
All other trademarks are property of their respective owners.