Posts tagged ‘pixmap’

Trolltech / Nokia Qt – Styles Could Be More … Stylish

One of the great things about Trolltech’s hard work into Qt has been the ability to use styles.  It’s a great concept, not only that you can tailor your application to a native look and feel at the drop of a hat simply by switching the style used, but that you can even derive your own style from QStyle (or any style based on QStyle) to create your own look and feel.

It’s absolutely great!

…Except for when it doesn’t work.

I won’t even begin to go into a long rant on just exactly why the native-OS styles don’t have “emulation” to execute on non-native platforms (the very point of using Qt), even if it is at a performance loss.  No, that Epic Fail  is blatantly obvious and doesn’t need a whole blog entry just on its own.

No, what I’m going to talk about today is where styles are broken.

Take, for example, the great ability to use a brush instead of a color in a palette.  In this way you can, most obviously, turn a background into not just a solitary color, but a pixmap, or even a gradient.  You can do all sorts of funky things with brushes.  It’s a wonderful concept in Qt.  … Except for when it doesn’t work.

Now I don’t know just how many styles this affects, but I do know that while basing a custom style on QCleanlooksStyle I found a number of bugs, and while walking through some of them through the debugger they step back through QCleanlooksStyle into QWindowsStyle and even QCommonStyle.  Now I get how some of these have been around for so long that maybe somehow someone just forgot that they needed upgrading.

Maybe.

Even if the ability to use a background pixmap has been around since Qt 3…

Or maybe there were just some serious bugs in Qt4.7.0.  (When will Nokia get around to actually releasing the 4.7.3 SDK instead of a “release candidate”?  And why didn’t they release a 4.7.1 or 4.7.2 SDK?  For professional developers who don’t work off of anything “official” this is a grievous oversight.)  But suffice it to say, turn on QCleanlooksStyle and then set your palette’s Window brush to, say, a gradient, and BAM! Bugs.

I think one of my favorite, one of the perfect examples, happens to reside right in QCleanlooksStyle itself.  One of the nice things about Qt is that you can look at the code.  And right there in drawControl, is little old QStyle::CE_Splitter.  Now I love that the Linux world has taken things like splitters and sliders and made them more … visible.  Lines and circles and dashes and all sorts of visual cues that this is something you want to touch.  In other styles things like splitters can be darned hard to realize are movable objects.

But, one of the epic fails in the Cleanlooks implementation of the splitter is … the failure to properly support the brush of the palette.  As soon as you un-colorify your palette, you’re asking for trouble.  Because plenty of things in styles, like splitter, like frames for that matter, just assume that you want to fill in an area of space with a color.  And be it a bug or by intent, at least in version 4.7.0, once you set a palette to use a brush it nukes the color.  So if you ask for the color specifically, you just get black.  And so all of those nicely colored areas are suddenly filled with black.  Black splitters.  To say it doesn’t look right is an understatement.  And all because they try to fill a rect with a palette’s Window color.

Now, of course the easy solution would be to use the frigging brush! Obviously.

But the thing is, they’re trying to be fancy, to say, highlight a selected splitter by lightening up the color.  Which works if your palette is only drawing with colors.  But works not at all if your palette is brush-happy.

And yet, there’s an easy better fix.  Instead of filling a rect with a 5% lighter color, why not use the awesome power of Qt to do something even better?  Set the painter’s opacity to 5% and paint a white rect instead.  Because that works just great with both color and brush.

Is it really too much to ask that the Trolls do a simple validation of their styles by setting a simple QLinearGradient Window brush to test the drawing of each and every style?

I can only hope that in future versions of Qt (heck, hopefully in the 7.4.3 SDK if it ever gets past beta into actual release) all of these style bugs can be fixed so that the beauty of Qt can truly shine.

Programming Rant – Annoyed With Qt – Pixel Metric Failure

Here’s an odd one. Today was the first time that I can ever say I was truly annoyed by something in Qt.

Well, okay, maybe not exactly the first time. I mean there are still some niggling bugs that get on my nerves, like how resize events called between constructor and the first show can result in incorrect sizing thanks to the optimizations being done. (Fortunately once you resize after that initial cluster-FUBAR things work fine, so you can work around it by sending a single-shot timer event to force a resize to the same size and all is fixed.)

And I have to say that there are times even in Qt4 when I have to wonder if the Trolls got their own memo about cleaning up the architecture from Qt3 by doing everything the “right” way, like all drawn objects inherit from QWidget so that there are no longer any strange custom drawing widgets without proper QWidget architecture. I mean I get why for performance it was done that way in earlier versions, and I guess still is done on (rare) occasion, but it’d be nice if we could have a clean simple architecture.

(By the way, can anyone explain why QGraphicsViewItems don’t inherit from QObject?  Talk about missing the memo!)

And, well, that whole private class internal architecture thing, that gets annoying too sometimes. It would be awfully more convenient if everything were accessible when you inherit from something. Not to mention be nice if the sourcecode were a lot more straight forward and readable.  (But then I guess that’s where their licensing starts making them money.  If you need to fix something that low level, you either pay for a commercial license, or you’re forced to make your changes available to the world at large.)

But these are all things that I can overlook, because I love Qt. They generally can be worked with or worked around in a way that in the end really isn’t a big deal.

Today, however, I ran into one that’s really making me scratch my head. I’m working on a touchscreen application and wanted to do something that I thought would be simple: create a custom GUI style based on the Windows Vista style. Inheriting from QWindowsVistaStyle was easy. That part was no worry. As was reimplementing the pixelMetric method so that I could return larger values for things like checkbox and scroll bars sizing. The idea was to keep the Windows 7 look-and-feel, only to make things larger targets for finger pressing. (It’s amazing how many tablet-style devices exist and yet this notion isn’t taken a lot more seriously.)

Well, as I said, in theory it was as easy as you’d expect from Qt.

In practice however … epic fail.

I don’t know if it’s the Trolls to blame, or if it’s Microsoft. But whichever the case may be, it turns out that checkboxes aren’t sized according to their pixel metrics. Meh? Say what?! Yeah!

Go fig!

So you can increase the pixel metrics all you want, but it does you no good. The GUI style does not draw according to its own pixel metrics!

I don’t know how many of the GUI styles are affected. Nor how many other of the primitives ignore their corresponding pixel metrics.  I do know for certain that the Windows-based ones all do ignore the checkbox pixel metrics to one extent or another. At first the QWindowsVistaStyle and QWindowsXPStyle both altogether ignore PM_IndicatorWidth and PM_IndicatorHeight when drawing checkboxes, but if you go back far enough to the basic QWindowsStyle you’ll find that the box will draw larger, like it should, but the checkmark inside of the box does not. Eh?  It’s a truly “special” look.

I wonder what other GUI styles perform similar bloopers.

I don’t know… Call me crazy, but I really expected better from the Trolls. Even if it was something kernel-based and not their own code, per se, I can’t imagine why they wouldn’t have implemented a workaround of some kind.  It seems like an awful cop-out to me to just say, “Well that’s the way Windows does it.”  Not that the Trolls have said that, because to my knowledge they haven’t said anything on this bug, but I really don’t see how you could intentionally implement the pixel metric system in a way so that you can easily adjust the pixel metric values and then not have tested it and found this bug.

Presently my workaround is to also reimplement drawPrimitive so that I can create a pixmap buffer to draw the undersized checkbox to using the bugged sizing, and then scale it up to the correct size. It works. It looks like crap because checkboxes are tiny, so pixelate badly when enlarged. But it works.

In the longer run however, it’s not a good enough solution.  Obviously.  It’s a kludge of the worst kind. So what I’m going to have to do (assuming that the Trolls don’t fix this blunder) is to manually draw these controls myself. I really don’t look forward to that, because there are a lot of shading effects in Windows 7 to duplicate. I may end up cheating and inserting a few XPM images into the code to scale down from. Or possibly even sit down and work on some vector graphics…

But in any event, the point is, who the heck would have expected that one of the main points of styles is in fact moot? That the pixel metrics are ignored when drawing the style primitives? And for the first time, there is no odd architectural quick to just get used to, or easy workaround to solve the problem. It’s going to take some serious effort to overcome this issue. Talk about being a waste of my time! For the first time in years I am actually annoyed with Qt and unimpressed by the Trolls that this somehow hasn’t been already addressed.

And speaking of GUI styles, I also get why certain GUI styles are only available on their target platform. Well … kind of. I mean I get why using the underlying kernel code may be necessary to get the native look and feel … without performance penalties. What I don’t get however is why no one bothered to write kernel-independent workarounds for the non-native platforms. Wouldn’t it have made sense to do that so that you can use these styles on any platform, just with some performance penalties? The whole purpose of Qt is that it’s a highly flexible multiplatform GUI solution. Except … apparently … it isn’t completely.  You can’t have your Mac look and feel port to every other platform.  Nor your Windows 7.  Etc.

Nerf!