» tagged pages
» logout

sorted by: recent | see : popular
Content Tagged with KDE + graphics

KDE 4: Creating a Plasma Theme in 7 Easy Steps

Tutorial: How to create a Plasma desktop theme for KDE 4 by using vector SVG graphic elements.

opensource: del.icio.us tag/opensource

Decoration items, light and shadow effects

I’m studying how we can add light and shadow to widgets and items. I want to hear what you think :-). So I’ll just throw out my ideas and see what happens.

Light and shadow are special effects that follow and decorate items, and affect how they are rendered, at the same time as they’re a bit different from regular items / subitems, or subwidgets. For both light and shadow effects, there’s sometimes a need to render outside the item’s boundaries and blend into surroundings. For widgets, we then need to do something to break out of the box model… to make that happen. For inside-widget light effects, we’re limited to what we can do inside paintEvent() or inside the paint() function. I don’t know about you, but I think both light and shadow effects should be primary citizens of the scene graph, which essentially means they are also items. Stack-above / always-on-top (overlays) or stack-below / always-below items (underlays?).

Here’s a flash video showing a sample of what I’m working on. This is based on Graphics View.

The scene consists of 150 elliptoid items with shadows, and one light source that’s flying over it. It’s a bit psychedelic; anyone who loves colliding mice will love this. ;-) Haha.

Let’s start with shadows. In 2D, shadows can be pretty simple. Shadows can be thought of as transformed filled outlines of an object with a dark semitransparent fill and possibly fuzzy/blurred edges, stacked below the object itself. It has an offset, and/or an angle. The offset can be fixed for all items, or relative to one or more light sources. Ideally two shadows on top of each other don’t make a darker shadow, rather they blend with each other along the edges. Exact shadows are expensive to do accurately, and in many cases they’re completely pointless because they’re hard to see in the first place; at least the types of shadows we foresee being used in 2D / 2.5D UIs… Extreme shadows are cool but useless, subtle shadows, however, to me, are/can be beautiful. There seems to be a “market” for simple stupid fast shadows (e.g., bounding rect / bounding region based), pretty good medium-speed shadows (e.g., shape based), and custom shadows. And possibly perfect shadows (e.g., based on paint()) but I don’t really think that market is very big :-)).

As for how shadows are stacked, the easiest way is to just say that an item with a shadow always renders the shadow before itself. This works fine for most cases. But as soon as sibling items come close, and one’s shadow renders on top of the other, it starts looking wrong.

Sibling Shadows 1 Sibling Shadows 2
Take 1: Sibling shadow overlaps Take 2: Sibling shadows behind both

It would be nice if I could set a shadow on our favorite “Drag And Drop Robot” without having lower leg shadows cast on the upper legs, or a shadow from the left leg draw on top of the right leg. I can see the need for both, but what would the API look like? And how would the items be stacked? My solution right now is to add a special flag to QGraphicsItem called QGraphicsItem::ItemStacksBehindParent (the child and its children are behind the parent), which is certainly one step on the way.

The other thing is how the shadow is placed. I don’t know about you, but I hate it how some presentation tools rotate the shadow relative to the item when you rotate and item that has a shadow on it. A picture says more than a thousand words:

Shadow follows item transform Shadow transform relative to scene
No -( Shadow follows item. Yes! Shadow follows scene :-)).

It’s a bit complicated though because you want the shadow to follow the item, but you wants its offset to be done scene-relative. Turns out it’s just that the item’s local transform is prepended to instead of appended to the parent item’s scene transform. So I added a flag for that: QGraphicsItem::ItemBeforeSceneTransform. Btw this is just research, it’s not in Qt snapshots or anything.

Now light effects come in many different shapes and colors. Light can affect shadows, or it can just add a glow to an item. Light is typically represented by an abstract member of the scene, to which you can calculate distance and angle and apply a suitable effect to your item, or the background, and so on. In styling, we usually fake light big-time by just applying light and dark effects to our button bevels, or use pixmaps that look shiny and sparkly. Which, of course, is in many cases much faster than doing “correct lighting”. I recall once Zack Rusin and I were talking crap, I don’t know who brought it up but if the whole UI was a complex detailed 3D scene graph, lighting could come by itself (I think the discussion started with why buttons in RTL mode don’t have shadows cast as if the sun shine from the upper right).

For blend effects it’s also necessary to apply aftereffects that combine the source and destination. That can be done in two ways - either just via an offscreen buffer, or directly onto the destination device / framebuffer / or so. If we want blend effects I think we need some type of shader integration. Let’s not digress though.

So, ball in your court. What are your thoughts about light and shadow?

Trolltech: Trolltech Labs Blogs

QWidget vs. Graphics View (ding-ding-ding!)

I’ve always had a dream that Qt’s widget system would be based on a powerful 2D, or possibly even 3D, graphics engine, reaping all the benefits and optimizations that make games run fast. The reason is, coming from a 3D graphics background originally (alright, I was 16 at the time), I’ve always been puzzled by how poor application UIs perform, and how constrained they are, compared to the most basic 2D and 3D graphics engines out there. I think there are many reason for why graphics toolkits provide limited capabilities, and performance, and I’ve been studying this, hoping to help find ways for Qt to be better than the rest. If you ask me why oh why, be warned, I will talk all night. ;-)

I think I could get shot for saying this, but IMO widgets are monolithic beasts. Input, painting, clipping, geometry, events and all are almost always packed into just one class. And that class plugs into a framework that works in only one way. It’s hard to change the way a widget clips without introducing rendering artifacts (draw outside and try to update with the rendered region - oops, the dirty region is autoclipped to the widget rect). It’s impossible to know what a widget looks like without calling paintEvent(), which is a virtual function that might do something different every time it’s called. Multithreaded painting is extremely hard. It’s hard to make the widget paint outside paintEvent() in general. Couldn’t the widget just say what it looks like instead?

The main reason it’s like this, I think, is that UI toolkits’ graphics capabilities are just a hurdle in the path to the ultimate goal, which is to pull together UIs with a nice tool, perhaps targeting your favorite language, and with a cool style and the perfect widget ;-). IOW modeled vertically, after the concrete problem to be solved (which is generally speaking a good approach), and perhaps constrained by the capabilities of the primary target platform. I still think we can learn a lot from looking at UIs as a specialization of a 2D graphics scene API, rather than 2D graphics being an extension to a UI toolkit. We need to model our graphics the way that graphics works (both software and hardware), and not cling so much to a particular problem space. Make sense?

Qt provides both a high-level widget API, a low-level graphics API, and a “mid-level” canvas API called Graphics View. Graphics View is an example of loosening up the constraints of the high-level API, without exposing too many low-level problems such as geometry and dirty region handling. In a way it’s more a 2D graphics engine than anything else. It manages surfaces in 2D (or 2.5D, quasi-3D) space. Originally, we meant for it to be different from QWidget. Obviously, it’s a framework that’s meant for something completely different than widgets (vector graphics, charts, maps, IC design, large scrollable scenes, and so on). What we’ve learned, however, is that the two aren’t really that different. Why can’t I have 1000 widgets in a QScrollArea, for example.

So looking back a few years, you’ll see that we’ve made changes to improve QWidget. Without breaking compatibility of course (which is amazing in itself, shows how Qt’s architecture allows for significant internal changes).

Before Graphics View came out, in Qt 4.1, we loosened up one constraint in QWidget by enabling automatic background propagation. Now, widgets no longer had any default background (remember this change? how about QWidget::autoFillBackground oh, OK now you remember ;-)), and we were one step out of the box-model that widgets traditionally represent (btw when I use the term “box-model” I refer to a widget representing an independent rectangular region of actual screen real estate). Then, in Qt 4.2, we introduced delayed widget creation (DWC), which allows a widget to be constructed without an actual window handle. As part of the DWC work Paul, Matthias and a few others did for 4.2, they had to ensure that widgets had enough local state to independently represent what it otherwise had with a window handle, as without. Well, this had a ripple-effect. During the Qt 4.2 and 4.3 maintenance cycles, we discussed the fact that the only widget that really needs a window handle, is the top-level. With Qt 4.4, Bjørn Erik did some tough refactoring work (which some of us, me included, thought wouldn’t really be feasible), and gave birth to what we call Alien Widgets, the invisible behind-the-scenes beauty. Because of this, in Qt 4.4, a window and a widget are different, despite being the same class, in that the window signs a “contract” with the windowing system to register some screen real estate. This is the same now on all platforms.

Still, after this, you could see some strings that pull QWidget down. Painting outside paint event - using QWidget for screen shot captures, for example, required painter redirection. Each widget still constructed its own QPainter inside paintEvent(), and with it a separate paint engine, despite how all painting ended up in the same paint device: the QPixmap backingstore, which was associated with the same top-level window. Now in Qt 4.4, QWidget has a render-function, much like QGraphicsItem has a paint-function, and the window is, for a subtree of QWidgets, essentially the same as a QGraphicsView is for a scene. Puh.

Background propagation. DWC. Alien Widgets. Shared Painter. You see what’s happening? We’re on a mission. -) We’re closing the gap between QWidget and Graphics View. And we’re not done, there’s still more to come. -) There are some things that we cannot easily change, like QWidget’s clipping model for one (it’s opposite from Graphics View) [*]. And that Graphics View can’t make windows like QWidget (arguably, this is solvable though). Plus all our widgets are QWidget-based. Embedding the QWidget-based widgets into Graphics View using WoC is cool, but it’s just not good enough for full-blown exploitation…

Feature by feature, I must say the situation today looks surprisingly good. I’m looking forward to the day when I can simply assign a QGLWidget viewport as QWidget’s window. Or when I can load UIs from Qt Designer into Graphics View. Or in Qt 5, maybe the two are the same thing (the latter is usually only mentioned between some specially interested devs in Trolltech social events after consuming large amounts of beer).

That’s enough blabber for one blog post. I just felt like sharing what’s on my mind these days. This is btw all part of the research we’re doing in Development / Trolltech to support next generation UIs.

[*] QWidget is by default clipped to the intersect of its rect() and the localized exposed region before paintEvent() is called. QScrollArea has no explicit clipping features. Because most widgets don’t draw outside their bounds, item-imposed clipping should have been off by default (obviously expose-clipping is unavoidable for viewports that allow partial updates). And scroll areas should instead explicitly clip the widgets that intersect its edges (widgets outside shouldn’t be drawn, you don’t need clipping for that) (most 2D and 3D graphics APIs use subdivision instead, essentially real-time retesselation of the intersecting primitives to avoid clipping altogether). It’s extremely hard to change this in QWidget today without breaking compatibility. QGraphicsItem has the preferred model in place. But all our standard widgets are written using QWidget, not QGraphicsItem/QGraphicsWidget.

Trolltech: Trolltech Labs Blogs

Four countries in two days

I’m preparing for an interesting trip… Finishing up Qt 4.4.0, as Thiago blogged about yesterday, I’m spending my time planning activites for 4.5 and 4.6. Input from everybody is crucial these days and months ahead; we want to hear first hand from you all what we should focus on. So I’m going on a trip to meet our fellows and users face to face :-). It goes something like this:

Oslo - Prague - Milan - Helsinki - Frankfurt - Sao Paolo - Porto Alegre - Sao Paolo - Frankfurt - Oslo

Thiago pointed out that I’ll be in four countries in just two days. One is a connection, so it doesn’t really count ;-). But I’m not used to traveling, and I prefer economy over business [*] ;-). I enjoy airtime, so it’ll be fine.

I’ll be in Milan for the April Plasma sprint. Hoping for quality time with some of KDE’s Plasma developers. I’m there to look and listen, hopefully I can help out with something. I’ll share some ideas we have for improvements to Graphics View and Qt in general, we’ll see what comes from that. Looking forward to beer in the evenings too of course ;-). Unfortunately (a slight communication error or lack of attention from my side) I’ll be there a day late, arriving the evening of the 11th, and I have to leave the evening of the 13th, so I’ll only be there for two whole days. Still, I’m very much looking forward to this event :-). Got my laptop, prepared to eat chips, drink coffee and coke, and just help out.

After that I’m heading to Helsinki to co-present some of our plans for Qt for a group of representatives of our future benefactors. -) At first I was intimidated by the upcoming acquisition. Now I’ve learned that there are some really cool people working for Nokia, they’re down-to-earth, they respect the work that we’re doing, and also the methodology and development culture that Trolltech is known for. Arriving at 00:55 that day (ugh!).

Then I’m going to Sao Paolo (Thiago’s home town!), having some pizza, staying over one night and then going to Porto Alegre to attend the FISL (9° Fórum Internacional Software Livre) to present how Qt is evolving to match tomorrow’s UI requirements across all platforms.

Oh and btw, our plans point in the direction of improving stability, quality, and performance of Qt as a whole. My sketchboard is also covered with ideas on how we can evolve the UI (thinking about styling, benefits and limitations our widget model, animation support, and more).

If you have small or large features you’d like to see in Qt, go ahead and open the threads on qt-interest, QtCentre.org and other forums. Get your ideas out, get feedback for them, and let us know about it.

[*] I’ve never flown business class ever before, and I’m proud of it!

Trolltech: Trolltech Labs Blogs

Open Source embedded development: My Gumstix Story

I recently got a new embedded Linux device to decorate my desk. This is like my childhood dream. :-)) I’m incredibly happy to have the opportunity to work with such a range of awesome stuff at Trolltech. And working on embedded devices is like bringing me back to the days when I was hacking graphics demos on a home made 386 SX 33MHz with a CGA screen ;-) (INF). Here’s my new baby:

My Gumstix

It’s running a simple Graphics View demo app. I’m hereby dedicating my Creative Fridays to play around with this device, it’s actually great fun to see how fast you can make it go. And I must say, speaking as an open source developer, it pleases me to know how easy it is for anyone to get hooked up with one of these babies.

First, Brad and I went onto the Gumstix web site and ordered two LCD packs. This is a decent piece of embedded hardware: you get a 600MHz XScale CPU, with a 10/100MBit ethernet plug, USB and serial connectors, and a nice big 4.3″ touchscreen 18bit display, at around $450. Delivery was swift. Now Brad got his device up in no-time, but me being completely new to this game, I needed some help with getting the screws into the right spot. It took us 15 minutes (now that Brad had figured out how to connect the LCD ;-)).

My Gumstix 2

After assembling the device, we booted it up. It gave us the Linux console prompt out-of-the box, and immediately hooked onto the network/DHCP, so I had ssh access right away. Following the instructions on http://docwiki.gumstix.org/Buildroot I quickly got the basic setup for running cross compilation, and I installed some of the basic tools I need to have a decent console (e.g., bash). I installed my build root under ~/gumstix-buildroot, and added the bin dir of the cross compiler to my PATH:

export PATH=$HOME/gumstix-buildroot/build_arm_nofpu/staging_dir/bin:$PATH

Then I configured Qt 4.4 for Embedded Linux (ftp://ftp.trolltech.com/qt/snapshots gives you the free edition, Qtopia Core source packages). Turned out to be pretty straight forward. I created a qt-4.4 directory on my device in my user’s home dir, and configured Qt like this:

$ ./configure -release -embedded arm -no-webkit 
        -prefix /home/ahanssen/qt-4.4 -hostprefix   
        && make

Notice how I skipped webkit, you probably want to skip all the modules you aren’t planning to deploy on the device. Space counts :-).

After this, I copied the lib files onto the device, and copied an example over, and ran it on the host like this:

$ ./collidingmice -qws

That’s it! For Linux developers, working on a Gumstix device like this is really really fun. I strongly encourage more people to throw themselves into this game. These devices also come in boxed versions, with Wifi and GPS expansion boards, audio chipsets, and more.

Next step: I’m planning to get KDE4 and Plasma to run on this device. Oh yes. ;-)

Trolltech: Trolltech Labs Blogs

Qt 4.4 and painting performance

Although the Nokia acquisition has sucked away some time from development and made it somewhat difficult to stay focused, it doesn’t mean we are halted. Our coffee machine is still up and running so there should be no need to worry.

I’ve been working on improving the painting performance lately, and I can tell you we’ve found nasty stuff. Resizing top-level windows has always been quite frankly horrible. With Qt3 it was snappy, but looking at it almost felt like staring at a strobe emitting a series of flashes. I’m pretty sure it was a useful feature at the discos back in the days. With Qt 4.1.4 and the backing store, we closed down that business and started focusing on usability and managed to get rid of most of the flicker at the cost of performance. We have continuously worked on improving the performance in the 4.2 and 4.3 series, but up until the alien technology, we struggled with flicker. With flicker-free child widgets in place, the only problem left was the sluggish top-level flicker, and that’s what I’ve been working on recently. Tests showed that in worst-case an application could easily repaint itself three times per resize. So, with 100 resize events you could actually get 300 repaint events, which is 200 more than needed! Now imagine how this appears with an application having lots of complex widgets with expensive paint events. It’s ridiculous!

This has now been fixed and reduced down to one repaint per resize, but the story doesn’t end here. Another nasty thing I found was useless QPainter redirection operating on a global list involving several mutex locks and for loop iterations. More precisely (per paint event); 2 + X mutex locks and 1 + X for-loops, where X is the number of painters created during the paint event.

In addition, Jens found out how we could easily get rid of the black background fill appearing on resize on Windows Vista, and it really makes things look much better!

Aah, yes, and there’s one more thing I’d like to mention. If we go few months back in time when the Widgets on The Canvas project was integrated, you can see how we were able to draw widgets directly onto the canvas with resolution independence. You might wonder how on earth we were able to do that. Well, there is an easy answer: The new QWidget::render overload taking an arbitrary QPainter -) I really had to wrap my brain around lots of pain in order to achieve that. As you probably know, creating a QPainter on a widget boils down to initializing the paint engine using the backing store as the paint device. It just means we’re doing exactly the same over and over again, which in turn means it’s possible to use a shared painter! Yes! Easy, then we simply pass the shared painter in QPaintEvent and everything is fine. Or wait… Damn, then we would have to change every single paintEvent in Qt and customers code. Bad idea! So what we ended up doing instead was to hijack sub-sequent QPainter constructions/initializations and set the d-pointer of the newly created QPainter to the shared painter’s d-pointer and push/pop the state accordingly. Everything happens behind the scene without requiring changes to existing code. When it comes to performance it means we don’t have to initialize the paint engine (which is an expensive operation) each time we construct a QPainter. Great, isn’t it?

Unfortunately, I don’t have any demo to show you this time, but I hope it encourages you to download the latest snapshot and try it with your application. If you’re brave, you could also run it against 4.1, 4.2 and 4.3 and see how we gradually become better and better. It clearly shows we’re going in the right direction.

Performance is really important and needs serious attention, so you can expect to see more action on this topic in upcoming releases of Qt.

Happy hacking!

Trolltech: Trolltech Labs Blogs

Accurate update regions for thin QGraphicsItems

We’ve gotten reports about how Graphics View’s performance drops in one special (yet quite common) case. It’s the case when the item is fairly thin, flat, non-square, or simply sparse, where QGraphicsItem’s bounding rect generates something close to worst-case updates that cause repaints of areas that really haven’t changed. A very helpful customer showed me a simple testcase that illustrates this problem, which is quite hard to work around, which again effectively makes it a bug. Start the portedcanvas example, and clear the canvas (CTRL-E). Add a few meshes (ALT-M). Now click a node in the top left corner and drag it down towards the bottom right corner.

portedcanvas screenshot

Performance degrades steadily as you get closer and closer to the bottom-right corner, until the example almost grinds to a halt. The example is very busy doing something close to nothing, at least it seems so. It’s redrawing the bounding rectangle of the edges to the node you’re dragging.

The yellow thing you get in debug mode by setting/exporting QT_FLUSH_PAINT=1 reveals what’s going on.

portedcanvas screenshot using bounding rect updates

To finally hammer this bug down, we’ve added an opt-in feature, QGraphicsItem::boundingRegion(), and a configurable granularity. You can tune the granularity of the bounding region of your line / edge / connector items, and with the wave of a wand, QGraphicsView will magically generate an optimal update region for that item.

So with 4.4, you’ll instead get something like this:

portedcanvas screenshot using granular region updates

What you’re seeing is that each of the two connector lines updates itself using a region consisting of 20-30 rectangles, a tunable granularity.

Should be in tonight’s 4.4 snapshots.

Trolltech: Trolltech Labs Blogs

davigno

One of the graphic designers that bring gorgeous artwork to KDE.

opensource: del.icio.us tag/opensource

davigno

One of the graphic designers that bring gorgeous artwork to KDE.

open-source: del.icio.us tag/open-source

Popups are a can of worms

Hm, that title sounds funny with no associated context.

We’re implementing popup support in Graphics View. This is the result of an outstanding bug, or rather essential missing functionality, in the Widgets on Canvas project: support for embedded popups. I.e., popups that pop out of widgets that are embedded into a QGraphicsScene. Such as the QComboBox popup list, the QMenus of a QMenuBar, the context menu in QLineEdit. I could go on. Popups are everywhere! (AAaaarggh….) The bug is easy to see. Add a combobox to a scene, then click on it. As of a few days ago, the popup will show up at the right spot. But you’ll soon uncover the problem. It’s not a popup. It’s just a widget. And uh, plain widgets aren’t half way as cool at being a popup as popups are.

#include <qtgui>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

    QComboBox *box = new QComboBox;
    box->addItem("Mandag"); box->addItem("Tirsdag"); box->addItem("Onsdag");
    box->addItem("Torsdag"); box->addItem("Fredag"); box->addItem("Lørdag");
    box->addItem("Søndag");

    QGraphicsScene scene;
    scene.addWidget(box)->show();

    QGraphicsView view(&scene);
    view.show();

    return app.exec();
}

This is crazy, when you think of it. First we thought QGraphicsWidget would be fine. From a framework POV, it made perfect sense. We add support for layouts and widget-like properties, and you can write your own widgets to put inside a scene. Then some bright fellow said “what about widgets people already spent time writing, do they have to _port_ them to QGraphicsWidget?”. We all knew the answer, which was an undisputable “yes and no”. Yes, you can, and that should be quite easy, but no, you shouldn’t have to. Making basic things easy, and advanced stuff possible, is a central design philosophy that swirls around in our minds more often than what’s good for us. Then some sucker ends up saying what everyone was thinking, (but couldn’t quite grasp so they chose not to say at risk of being held responsible for some major mistake later on,) which sounded something like “….a proxy widget?”.

Embedded popups - strike 1

Why on earth does the popup show up there? Wait, windows use global coordinates… and the popup adjusts to the current screen’s available geometry….

Yeah, a proxy widget. You know, just “plug it in!”. Ehem. Everybody nods and goes “that makes perfect sense, but,…” and then you see everybody thinking like crazy, before one of our brightest people suddenly breaks and tilts his head to the side, a spring popping out of his ear. Everyone wants to say something, everyone knows a proxy is a can of worms, but some silly person goes “hey, how hard can it be?”. And you know what, we really just can’t get enough of those people. ;-) Sometimes I like to think that many of mandkind’s greatest achievements come from people with a sudden unexplained lack-of-insight, inability to foresee the future, and just plain stupid. It’s like building a house. Everyone knows building a house is crazy, it’ll take way too long, cost more than you have, mess up your relationship, but still some people go “Look sweetheart, it’s just €175000 for the house and another €150000 for the lot!”. And hey, you get a house. Which is great ;-). And have more kids, and you know.

So the project starts, and when it reaches its successful end, everyone, (including the stupid entrepreneur,) wonders how on earth this project could succeed.

Hah! Anyway. Popups! Yes.

What’s the big deal with popups? Popups imply explicit and implicit mouse grabbing, event replays, nesting popups (i.e., nesting grabs), grab-on-show, release-on-hide. Window positioning (converting QWidget global screen coordinates to QGraphicsWidget local parent coordinates). Delete/hide/remove/deactivate/unfocus/disable while grabbing? Implicitly? Explicitly? What if you grab while grabbing? Ungrab without grabbing? You grab the mouse and some other widget does the same, then the other releases the grab. Or better yet, releases _your_ grab. Should the scene propagate the grab to the view? [*] It’s one hell of a state machine! I’m losing sleep thinking about cases where somebody’d explicitly release a grab that some other widget has implicitly gained from a simple mouse press. That’s a silly reason to lose sleep ;-).

Of course, it’ll work, that’s almost the annoying part. When it’s done it’ll work just fine. No bells ‘n’ whistles, just a darn popup. It’s just such a can of worms.

Embedded popups

Now that’s more like it!

[*] No, it probably shouldn’t ;-)

Update 2007-12-20: Here’s a patch that implements popup and mouse grab support. It’s a bit broken, but the basic functionality is there.

Trolltech: Trolltech Labs Blogs

Widgets On The Canvas Integrated

The day has finally arrived. We are proud to announce that we have now integrated our development branch for the Widgets On The Canvas project into Qt/main, or what will become Qt 4.4. You have already seen a random selection of screenshots and feature rundowns in previous blogs, but now it’s all in your hands to try and enjoy. It should appear in tonight’s snapshots.

I’d like to thank Jan-Arve, Bjørn Erik, Jo, Benjamin, Jasmin, Girish, Lars, and everyone else who has helped us with rowing this boat ashore. It was a beast, but we seem to have managed to tame it. Now, we’d all like for you to play around with this API, and let us know what you think.

Graphics View now provides a brand new layout and widget API. It’s similar to the way QWidget works, and should be familiar for most of you right away. The purpose of this API is mainly so you can write layout-aware items, but it also means you now have a richer base class for your items. Because QGraphicsWidget inherits from QObject, it allows declaring signals and slots and manages event delivery just like any widget in Qt. Like QWidget it also provides a palette, a font, layout directions and a style.

Graphics View doesn’t provide its own widgets like QLineEdit and QComboBox - instead, you can embed existing widgets (indeed, any custom widget that you have written yourself) into the scene by calling QGraphicsScene::addWidget(). If you also pass the Qt::Window flag, your widgets will even get window decorations similar to QMdiSubWindow. You can move, resize, rotate and scale your widgets, or combine widgets and items to generate fancy overlay or transition effects.

There are still a few remaining issues to solve. For one, Graphics View automatically embeds popups of embedded widgets. So if you embed a combobox, its popup will also appear as an embedded popup inside the scene. And QMenuBar’s menus also also embedded. We aim to make this feature work 100% for 4.4, but currently it doesn’t work properly (in particular, modality and mouse grabs are missing). Also, there’s the well-known Mac OS X styling problem. We still haven’t found a perfect solution for this, so for now, if you use Mac style for Graphics View, embedded widgets will look a bit chunky when transformed. And finally, because this is all brand new API, we expect some bugs to appear in this pre-alpha phase, and hope to iron them out based on your feedback. But hey - Widgets on Graphics View! How about it??? ;-)

PS: The members of the WOC project are all present and listening on qt4-preview-feedback@trolltech.com (also available through nntp.trolltech.com). Now is the time that you can help hone Widgets on Canvas to be just as great as we all want it to be. So enjoy! We’re eagerly awaiting your feedback.

Trolltech: Trolltech Labs Blogs

KDE and Gnome Comparison

Gnome, on the other hand, opts for simplicity and often hides certain configurations in order to achieve that simplicity. Fans of Gnome think the simplicity of Gnome offers a cleanliness that allows the user to get stuff done. Critics of Gnome think it ju

Kubuntu: del.icio.us/tag/kubuntu

Demo screenshot: “embedded dialogs”

This is just a sneak-peek of one of the demos for Widgets on Graphics View.

Embedded Dialogs - small

-D

And yes - those are real QDialogs btw.

Trolltech: Trolltech Labs Blogs

KDE Pinheiro: More apps, more mimetypes.

More apps, more mimetypes. This is a quick post just t show some of the latest developments in oxygen first , krita icon and krita mimetype Second Kchart withe his mimetype alongside.

opensource: del.icio.us tag/opensource

Noises from the crypt… (Widgets on Graphics View update)

Feature freeze for 4.4 is closing in. The offices in the dev department are awfully quiet. A bit… too quiet. The snippety-snapping sound of brilliant minds tapping in code, merging changes, polishing APIs, writing tests, reviewing patches. An incredible atmosphere, you would have to just be there to sense it. This is the period of Qt development when most of the building blocks are assembled, and awesome features and improvements emerge like glowing fresh steel from the furnace. This is the most busy, the most stressful, and by far the most fascinating phase.

Today in particular, I almost felt emotional. Together with Jan-Arve, Jo, Bjørn Erik, Benjamin, Girish, all brilliant developers, and everyone else who has participated in the Widgets on Graphics View project, I had the sensation that things were fitting so well together that you’d almost think we hadn’t invented these APIs, but rather uncovered ancient APIs from a past civilization. ;-) The pieces of the Widgets on Graphics View project are coming together. In very few weeks, they will be in your hands to test.

Early on, I was worried about many things. Prior to 4.2, I was almost convinced that adding embedded widget support to Graphics View would be an insane operation. Undoable. I think I was right. I’ll just list some of the problems we foresaw then, here:

  • QWidget cannot render itself onto an arbitrary painter like QGraphicsItem can… :-((
  • QPen is cosmetic by default. Will all styled widgets look strange when transformed?
  • Will the styles’ implicit pixmap caching slow everything down to the state of it being useless?
  • How does scroll optimization (QWidget::scroll) work for a transformed widget?
  • Qt already has widgets, do we have to clone all the APIs into separate Graphics Widgets with a duplicated implementation?
  • How can graphics items be part of the tab focus chain when they aren’t based on QWidget? (QWidget::setTabOrder…)
  • Do we need support for window flags? How about window activation? When is a Graphics Window activated?
  • Is there a concept of top-level window decorations in Graphics View, similar to QMdiSubArea?
  • How can we fool a QWidget into embedding itself into QGraphicsScene without it interfering with other widgets as if it wasn’t embedded? (Think about QuitOnLastWindowClosed, and so on…)

Sigh. Looking back, I don’t quite understand how we’ve made it. After numerous discussions with the guys directly involved in the project, and Lars, Brad (thanks for those long discussions in the car!), Paul, Jasmin, and many many other trolls, we’ve found solutions to almost every single problem that we foresaw. And we even uncovered more problems. And solved those too. And what we got, what we have, and what we’re honing, stabilizing, testing and reviewing these days, makes me emotional.

#include "mainwindow.h"
#include <QtGui>

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QGraphicsScene scene;
    scene.addWidget(new MainWindow); // embed the whole thing

    QGraphicsView view(&scene);
    view.show();

    return app.exec();
}

I can’t wait to merge our stuff into Qt/main. When we do, it’ll be in the Qt/main snapshots. And then, you can all have a go. Give it a try. Embed your entire QMainWindow based app, with a QMdiArea central widget that embeds a QGraphicsView inside a QMdiSubWindow, and see it fly. When you do, you’ll get emotional too. I swear.

Trolltech: Trolltech Labs Blogs

Thoughts about graphics performance

Ah, performance. Today we had yet another discussion about how to make Qt even faster, preferably all over the place. Generally, we feel that resources spent on hunting down performance problems are resources well spent. But we’re (surprisingly?) not a huge lot of people working on Qt’s 1000000 lines of code, and many of us feel that we’re spread thin trying to juggle major and minor feature development, maintenance and innovation, and so on. So how do you spend your effort? I personally feel strongest about graphics.

Qt is, of course, a kick-ass toolkit written by a bunch of hard-core (yet wonderfully pleasant!) developers, and sometimes we try to make everything as fast as possible, other times we’re forced to make a trade of API quality versus performance. Before he left us, former Troll Zack(r) held a seminar where he stressed how truly high-performant graphics, (and we’re talking the tens-of-thousands-of-polygons full-screen with tons of impressive effects at 75fps,) needs tailoring, and is typically written very close to the actual hardware, in order to run as fast as possible. Convenient APIs can still perform well if they are sufficiently high-level (”I know exactly what you want to do!”), or sufficiently low-level (”I don’t know squat about why you want to draw these trigons but I swear I’ll do it real fast!”). Qt is in the middle. You can’t ask Qt to mock together Black & White III (you would naturally use OpenGL for that!), but you can’t ask Qt to upload a subroutine to the graphics card’s pixel shaders either. It does that for you in the background, but it doesn’t provide that API. Qt can render vector graphics for you. It does it incredibly fast, and beautifully, but pixel perfect vector graphics is not always what you want. Otoh, Qt doesn’t know that. -) Gah!

Now Arthur’s rendering model does give you many options to write beautiful and fast graphics. The default paint engines and QPainter provide a mid-level intuitive API for drawing vector graphics, implemented with the best effort approach (speed + quality). Depending on the platform and complexity of your shapes, Arthur picks the best approach giving you high-quality output at high speed. Through QImage, you can also access pixels directly and work all your magic “by hand”. With Qtopia Core you also have QDirectPainter, which lets you touch pixels directly on the frame buffer. QGLWidget provides two things: Both the QPainter API, which I consider to be truly unique, basically the exact same operations you use with QWidget are translated to OpenGL calls. And, of course, you can use OpenGL directly (the context is set up by default in QGLWidget::paintEvent(), just fire away those GL calls!).

But QPainter, the heart of our graphics API, works on a non-compositional model. QPainter doesn’t know enough about how you want to blend your stuff together; it has to rely on you to do the smart stuff. For example, if you ask QPainter to draw a complex path, say a QPainterPath representation of a text document, and then ask it to do it again, and again, and again, QPainter has a pretty tough time figuring out that it would be nice to cache that path. Even if it could, it doesn’t necessarily know how to make it also look good in your case! It cannot know what’s best for you; to a certain degree it must rely on you knowing what you’re doing. You, on the other hand, do know what you’re doing. You know perfectly well what could make it faster, but maybe you don’t know how to make Qt do what you want. Somewhere between QPainter and you, there’s some smart stuff flying around, I’ve just been feeling that there’s got to be an API in there somewhere ;-). The trick is to pull it out of the hat somehow.

People tend to prefer quality high-level APIs over low-level ones. By that I mean APIs that are easy to understand and use, empowering you and allowing you to quickly transform your brain vibes into shapes on the screen. Now how can you do that with a really addictive, efficient and intuitive API, while still keeping it blindingly fast? The hard problem lies in finding the right level of abstraction. Our closest thing so far to an abstraction over Arthur is the Graphics View API. I’ve spent some time with QGV to bring my ideas into the API somehow. Does QGV “know” enough about what you’re doing, to do it more efficiently?

QGraphicsItem knows that everything going on inside of paint() is basically drawn on one surface using a single homogenous transform, and it can render the item off-screen into a texture in logical coordinates to avoid asking QPainter to redraw and redraw and redraw and redraw. That texture could then be stored in graphics memory, like QPixmap already works with QGLWidget, and you could transform and translate the item without ever “redrawing” it. Your paint() functions wouldn’t even get called at all. I just think it could do miracles for lots of graphics apps that spend a lot of time redrawing. So when the item is exposed, or even transformed, instead of retesselating, rescaling and rerendering the thing, we just blit the texture. Whenever the item needs to redraw parts of itself, it could call QGraphicsItem::invalidate(QRectF), as opposed to update(QRectF), which just reblits the texture. The following screenshot shows an app I wrote to measure just how fast or slow a straight-forward application for Qtopia Core would run. It’s a phone keypad navigator:

Padnavigator-example

Here’s the source code, download and unpack:

The Pad Navigator Source Code

And my patch to Qt 4.3.x, download and unpack:

My Patch to Qt 4.3.x

Now, it goes like this: Download your favorite open source edition of Qt (I prefer the all-package for simplicity), preferably 4.3.1. Unpack, apply the above patch to src/gui/graphicsview - it should apply cleanly with no conflicts. Build Qt, and build the padnavigator example. Now run the example. Play around with the key pad, press enter, bla bla. Resize it, it’s resolution independent. Now, if you hit space, the whole example enables logical caching for all its items. Notice how the quality level goes down, but speed just goes sky-rocketing. OK - I think I’m onto something here, now back to the drawing board.

PS: Try without OpenGL and compare the performance by removing the setViewport() call in main.cpp.

Disclaimer: If you don’t really notice any other difference than image quality degradation, you probably have state-of-the-art hardware and a modern graphics card. Don’t blame me for Qt being fast without any tricks! ;-) Try running padnavigator over a remote X connection on Linux, or run it through a heavy profiler like valgrind, just to “emulate” slow hardware.

Trolltech: Trolltech Labs Blogs

shadows

a fellow named daniel commented in my last blog entry:


here's to hoping that the shadow in the future will actually be drawn by plasma or compositor, instead of being part of the packground pngs. Roll-your-own shadow was an annoying visual problem in SK, and I really hope Plasma moves forward on that one.


being tired (it's 01:00) and not really feeling up to any serious hacking, i took stackblur in hand and came up with this:



the shadow there is done based on the shape of the item (generically, not specifically for that shape). the png's shadow is on top of it (i didn't both lopping that off; this was a "i'm tired, let's do something quick and fun" hack remember ;) and if you look closely you'll see that the shadow seem sto be cut off at the bottom a pixel or so prematurely. performance wise it's quite fast, but could be faster yet if i bothered to do a few smart things with it.

in any case, i'm not going to commit this to svn (well, i am, but #if 0'd out for future reference only) because i know we (or rather zack, frederik, etc) can do even better with a little effort.

but you can see it's possible and pretty trivial with stackblur in hand (9 lines of code, to be exact).

KDE: aseigo - trials of a KDE hacker

Dialogs on the Canvas

With 4.3.0 released, it’s finally time to get back to maintenance and research again. It’s been both an exciting and exhausting release, and mostly we’re all very happy with the way things have gone. There’s certainly something special about features you spent so much time working on, popping up as topics in forums here and there, and seeing diverse screenshots in magazines showing off how someone made perfect use of something that you busted your pyjamas implementing. But, nothing beats laying out plans for what to do next.

So what happens next? I’ve got two major projects planned for making life easier for all you canvas-lovers out there. The initial research is starting to bear fruit, and all I can say is that 4.4 will (also!) have a lot of good stuff in it. And Graphics View is just a part of it, but it will certainly be a spectacular part of it.

woc-small.jpg

The screenshot seems to be showing QMdiArea with several QMdiSubWindows, with a texture background. But it’s not. It’s actually Graphics View, and this particular demo is running 250 dialogs with 5 buttons in a gridlayout. This is Widgets On The Canvas, one large enhancement we’ll be doing to Graphics View. We’re planning on implementing support for several widgets, but initially we’ll spend most of the time available making sure that the corner stones, the widget and layout classes, reach rock solid Qt 4 quality. You know, the kind that makes you go mmmmmmmmm.

The sweetest thing about these widgets are that they seem to run faster than regular widgets; at least when there’s no transformation. They’re perfectly stylable (the scene provides the font, palette, style, etc, defaulting to QApplication’s defaults); it even works well and fast, and looks good, on Windows XP.

woc_xp-small.jpg

It’s fast. On Windows XP, running fullscreen with full colors on a 1600×1200 display, it’s just as fast to scroll this thing as the chip demo. If you scale or rotate it, it becomes really slow. But that just shows that we’re on thef right track (I mean - if it was all blindingly fast, you just know something must be very wrong, right?).

As much as I’d love to provide the source code, it’s in a miserable state right now (since we’re basically throwing around ideas and prototyping, the source code looks like crap, and I’d like to spare you from the ugliness). But you can try it on Windows with
this executable. Hope to provide source code later on.

Trolltech: Trolltech Labs Blogs

Help Krita - a free and open source painting program

Donate to Krita so they can buy some Wacom tablets to help them improve the application even further.

open-source: del.icio.us tag/open-source

Page 1 | Next >>