Andreas
Qt
Labs
Graphics View
Graphics Items
Posted by Andreas
 in Qt, Labs, Graphics View, Graphics Items
 on Thursday, November 30, 2006 @ 14:01

Have you seen flash-interfaces with controls that grow and twist when you move your mouse over them? Here’s how to do that in Graphics View. I was so surprised at how easy it was that I thought I’d share it. Here’s a screenshot, just so you know what I’m talking about:


I’ll do this in the good old all-in-one-file style that we all love to hate. So, main.cpp:

#include 

class ImageZoomItem : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
public:
    ImageZoomItem(const QPixmap &pixmap, QGraphicsScene *scene = 0);
protected:
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
private slots:
    void setFrame(int frame);
private:
    QTimeLine timeLine;
};

An image item that cross-inherits from QObject and QGraphicsPixmapItem? Isn’t that considered inherently evil by the API purists we are? In fact, no. We designed QGraphicsItem specificly so you could do this. So you can easily have signals and slots and all that fun stuff, in addition to the events. Graphics items aren’t QObjects by default, because QObject requires memory. Event support, however, is free. So now you know. If you want slots, bring in QObject. So let’s move on.

ImageZoomItem::ImageZoomItem(const QPixmap &pixmap, QGraphicsScene *scene)
    : QGraphicsPixmapItem(pixmap, 0, scene)
{
    setAcceptsHoverEvents(true);

    timeLine.setDuration(100);
    timeLine.setFrameRange(0, 100);
    connect(&timeLine, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int)));
}

The image zoom item starts by enabling hover events. You need those to track the mouse entering and leaving your item. Then, we set up a QTimeLine (beautiful class, that is ;-)), with a 100 millisecond duration, starting at frame 0 and ending at 100. We’ll use the timeline to control our animation as the item zooms in and out. Finally, we connect the timeline to a slot in this class.

void ImageZoomItem::hoverEnterEvent(QGraphicsSceneHoverEvent *)
{
    timeLine.setDirection(QTimeLine::Forward);
    if (timeLine.state() == QTimeLine::NotRunning)
        timeLine.start();
}

The hoverEnterEvent() implementation is called when the mouse enters the item’s area. For semi-transparent images like the one in the screenshot above, this means when the mouse enters the opaque part of the bulb itself. So we start by setting the timeline direction, then start the timeline if necessary. With QTimeLine::Forward, this will make QTimeLine call the slot below 25 times per second over a period of 100 milliseconds, increasing the frame step from 0 to 100 with even steps.

The leave event is almost the same:

void ImageZoomItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
{
    timeLine.setDirection(QTimeLine::Backward);
    if (timeLine.state() == QTimeLine::NotRunning)
        timeLine.start();
}

Just set the timeline direction to QTimeLine::Backward when the mouse leaves the item. The cool thing is that this seamlessly supports moving the mouse over a bunch of items like crazy. Once the mouse moves in, the item will start growing, and as soon as you leave the item it’ll switch back to shrinking again. OK now for the slot:

void ImageZoomItem::setFrame(int frame)
{
    QPointF center = boundingRect().center();
    resetMatrix();

    translate(center.x(), center.y());
    scale(1 + frame / 150.0, 1 + frame / 150.0);
    rotate(frame / 8.0);
    translate(-center.x(), -center.y());
}

Reset the matrix, translate the item by half its height and width to ensure the items doesn’t visually move while zooming, scale it a bit, rotate a bit, and translate back again. And make note that the scale and rotate operations are not accumulative, but rather a function of the frame number. That means we can play the animation forwards and backwards or skip around randomly.

That leaves us with the main function itself:

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

    QPixmap pix("light.png");
    QGraphicsScene scene;

    for (int i = 0; i setPos(qrand() % 1000, qrand() % 1000);
        scene.addItem(item);
    }

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

    return app.exec();
}

#include "main.moc"

Scatter a hundred bulb items around the scene. Create and show a view for the scene. Done.

Download the sources here.

harald
Qt
Qtopia
KDE
Posted by harald
 in Qt, Qtopia, KDE
 on Friday, November 24, 2006 @ 16:16

I’ve put up a new version of qdasher (qdasher-20061124.tar.gz), the Qt4 port of Dasher. I’ve managed to get it down to about 20% CPU usage when running in fullscreen on my standard Pentium IV machine. It runs nice and smooth on our embedded hardware. If dasher is paused, no CPU cycles will be wasted (unless you move the mouse around).

If you have an LSB compliant i386 system (with the LSB Qt4 module installed), grab the binary and try it out. I also created a package for the Greenphone (QDasher_1.0.0-1_arm.ipk).

zack
Aggregated
Posted by zack
 in Aggregated
 on Wednesday, November 22, 2006 @ 13:50

Jakub Steiner wrote an interesting blog about woes of creating resolution independent icons. It’s a problem I’ve been thinking about during the last few days, one that has been solved, at least to some extend, already.

It was solved for fonts. Grid-fitting (aka. “font hinting”) is a crucial step on the way to produce legible output at small sizes for any font. Hinting can be manual (e.g TrueType has a stack-based language for it, each glyph in the font contains its own little hint program and as a result of running that program control points for the outlines can be adjusted in any way the creator of the hints desired) or automatic (as used by FreeType). An interesting medium is described in “Example-Based Hinting of TrueType Fonts” paper, in which a method of reusing hints from one font for another are described. All in all it’s a very common problem for fonts.

The iSlayer blog that Jakub mentioned makes it very clear we need it fast. His example showing how much worse his logo looks in the vector form than the as bitmap looks almost precisely like the “example of hinting” image that can be found on Wikipedia:
(The upper sample in each case is unhinted)
When talking about fonts we’re just dealing with a subset of our exact problem.

In Qt, Gunnar just implemented support for non-scaling stroke, which is great. Now we need to figure out a way of doing automatic hinting for vector shapes and we’ll be set.

I’ve always been all for manual adjustment of icons on a pixel-by-pixel basis, simply because they looked a lot better, but during the last few days I’ve became convinced that we can, in fact, create resolution independent icons. Or let me rephrase, not “resolution independent icons” but “icons that preserve their good looks across resolutions”. We have the former, we need the latter.

I’m taking a week off and that’s exactly what I’ll work now.

I think manual hinting is too cumbersome and we’d need a new container format for icons to make it really work. A way of specifying a whole icon theme along hints for each icon to make them look good across different resolutions wouldn’t necessarily be a bad idea. In fact that would be great, it’s the problem of developing the way of storing and producing those hints that would be quite challenging. XML format (with some namespace of course) that can be embedded right in the SVG’s would probably work fairly well but I’m afraid wouldn’t be enough. Then there’s also a question of how would we get artists to create those hints.

No, I think auto-hinting makes a lot more sense here. The research FreeType people did in that area is outstanding.

All in all, I think I can make it work =)

Oh, and if you have a SVG icon that you hand-adjusted to produce a better looking bitmap, I’d appreciate a lot if you could send me both examples via email to <my first name>@kde.org address so that I have some testcases to work with :)

girish
Qt
KDE
Posted by girish
 in Qt, KDE
 on Tuesday, November 21, 2006 @ 16:29

Lost in all the Qt 4.2 publicity for Widget Style Sheets and Graphics View is the auto completion framework which makes it easy to provide auto completions in just about any widget. The framework is really just one class - QCompleter. The completer provides support for three completion modes - Inline, Popup and Unfiltered Popup. It can provide completion from any role and any column of an QAbstractItemModel. You can iterate and query the completions. What more, it is super optimized for large sorted and unsorted models.

It is not hard to imagine where the QCompleter can be first put to use. Practically just about every application has the line edit and browse button combination. Using QCompleter, providing auto completions for file names from the file system is straightforward,

QCompleter *completer = new QCompleter(fileNameEdit);
QDirModel *dirModel = new QDirModel(completer);
completer->setModel(dirModel);
fileNameEdit->setCompleter(completer); // new in 4.2!

QLineEdit with a QCompleter

QCompleter can even be used in a QComboBox. By default, a QComboBox provides inline completions from the items in its drop down list. With the introduction of QCompleter, you can set up QComboBox to provide auto completions from a model independent of the items in the drop down list. The user can use the drop down list to view items previously entered.

QCompleter *completer = new QCompleter(fileNameCombo);
QDirModel *dirModel = new QDirModel(completer);
completer->setModel(dirModel);
completer->setCompletionMode(QCompleter::PopupCompletion); // check out other completion modes!
fileNameCombo->setCompleter(completer);

QComboBox with a QCompleter

Providing completions in a custom widget is all about calling complete() and setCompletionPrefix() in the right places. Check out the custom completer example for details.

Comments Off
zack
Aggregated
Posted by zack
 in Aggregated
 on Monday, November 20, 2006 @ 12:50

With 4.3 snapshots out I updated the list of my examples with a few new ones:
Animation along a path,

And text on a path that I mentioned in the previous blog.

And two examples showing perspective transformations here and here.

Last week I finally got a new laptop. I bought a Sony Vaio SZ340. Mainly because it came with two gpu’s, and for a 13″” laptop that’s a very unique feature. In general everything works ok (sleeping, cpu frequency scaling, ethernet, wifi, audio). Battery life for some reason is abysmal at around 1.5 hours even though both cores seem to be scaled correctly. I haven’t had the time or motivation to figure out what’s causing it though. All in all I’m pretty happy with it so far.

In completely unrelated news I became a WebKit reviewer. To answer all the questions about what does that mean for KDE I have to say that right now it doesn’t mean anything. KDE is a community, in which technical decisions emerge in the process of natural selection. If we’ll manage to get WebKit Qt/KDE ports working better than KHTML does right now, the transition from our own KHTML repository is going to be fluent and natural. If we won’t be able to do that, then we’ll still have our own version of KHTML. In my opinion, working on WebKit is, from a purely pragmatic point of view, the right thing to do. Working on new features and maintaining a web engine are very complex tasks that we can make a lot, lot simpler by sharing the burden with WebKit contributors.

englich
Aggregated
Posted by englich
 in Aggregated
 on Saturday, November 18, 2006 @ 18:44

How to design APIs for XML is debated daily, and has been done so for long. For too long. Now ages ago, companies formed at W3C to design the DOM, using language neutrality and document editing with load/save persistence as goals(it seems, and some says). But some needed other things, such as a streamed, less verbose approach and hence SAX was brought to use. Others found SAX cumbersome to use, and StAX was deployed. And so on, and so on.

One urge I have is to cry out: why can we never design a sensible API? But that reaction wouldn’t be justified. Software is the implementation of ideas. When the software has to change, it’s the reaction stemming from that the ideas(the requirements) changed.

Afterall, SAX works splendidly for some scenarios. I don’t expect one tool for all scenarios, because XML is used in too varied ways. But still, even though one can expect tools to become obsolete and that one size doesn’t fit all, the current situation is more worse than what is reasonable.

In Qt, the dilemma the XML community has is present as well, painfully. The QtXml module provides an (in my opinion poor) implementation of DOM, and SAX. Something needs to be added in order to make XML practical to work with using Qt. Some of the ideas I’ve heard are by the book: add StAX as a streamed-but-easy-to-use API, and a XOM-like API for doing in-memory representation. The latter would be an API that doesn’t carry the legacy of XML’s evolution(the addition of namespaces, for instance) and in general do what an XML API is supposed to do: be an interface for the XML and therefore take care of all the pesky spec details, which XOM does in an excellent way.

If Trolltech added StAX and a XOM-like API to Qt no one could blame them. Other do it and it is the politically correct alternative at this point of our civilization(just as DOM once was). But I start suspecting that it’s the wrong direction. That the step of learning a lesson of adding yet another API could be skipped, in favour of jumping directly to what would follow.

Let’s look at what XML is:

  • It is a medium, a text format for exchanging data, specified in XML 1.0 and XML namespaces. XML is absolutely terrific at this. The IT’s history is tormented with interoperability problems such as encoding issues. XML solves all that in one go. It abstracts away from primitive details, and provides a platform. This is why XML is popular.
  • A set of concepts to express ideas. This is all that about elements and nodes formed in a hierarchial structure(that from a reader’s standpoint can be difficult to distinguish from the text representation, since we humans instantly see the logical structure when looking at an XML document). Exactly what that is, is not so obvious. The different appproaches are often referred to collectively as data models, and there are plenty of them: the XPath 2.0 Data Model, the XML Information Set, the PSVI infoset extension, the DOM(that it stands for Document Object Model is a hint), and the list goes on. These are all different ideas to what a sequence of characters arranged to be valid XML, actually means.

That one can view XML as consisting of these two parts reveals a bit about how XML has evolved. First XML 1.0 arrived, taking care of syntax details. Later on, this plethora of data models arrived to formally define what XML 1.0 informally specified. Understandably many wants to make the XML specification also specify the data model. The question is of course which one to choose, and what the effects are of that.

But the list of data models doesn’t stop with the above. Those are just examples of standardized models. I believe that one data model exist for each XML scenario.

When a word processor reads in a document with the DOM, the actual data model consists of words, paragaphs, titles, sections and so on. The DOM represents that poorly, but apparently acceptably well. Similarly, when a chemistry program reads in a molecule, its data model consists of atoms.

That XML is used for different things can be seen in the APIs being created. SAX is popular because it easily allows a specialized data model to be created, by that the programmer receive the XML on a high level and from that builds the perfect data structure. DOM allows sub-classing of node classes by using factories and attaching user data to nodes, in order to make the DOM instance closer to the user’s data model.

XML is not wanted. Communication is a necessary evil, and therefore XML is as well. If programs could just mindwarp their ideas, molecules and word processor documents, to another program they would, instead of dwelving into the perils with communicating through XML.

I believe this is a good background when tackling the big topic of providing tools for working with XML. It’s not questions like “How do we design an API that avoid the namespace problems the DOM exposes?” It starts at a higher level:

How do we allow the user to in the easiest and most efficient way go from XML to the data model of choice?

Ideally, the user shouldn’t care about details such as namespaces and parent/child relationships. If the API has to push that onto the user, it’s an necessary evil. It’s again about not getting far away from the ideal data model. The idea is in general already practiced when it comes to the most primitive part: serialization. It’s widely agreed that a specialized mechanism(a class) should take care of the serialization step.

Let’s try to apply this buzzword talk to Patternist and Qt. A QAbstractItemModel is typically used to represent the data, since the data is practically separated from its presentation, with the model/view concept. The user wants to read an XML file, and produce an QAbstractItemModel instance.

Patternist, just as Saxon, is designed to be able to send its output to different destinations. It’s not constrained to produce text(XML) or SAX events or building a DOM tree, it just uses a callback. And that callback could just build an item model. It should be possible to write that glue code such that it works for arbitrary models.[1] With such a mechanism, one would only have to write an XQuery query or XSL-T stylesheet that defines a mapping between the XML and the item model, in order to do up and down conversions.

Using Patternist to directly creating item models might not be the way to go. But I do think one should concentrate on what the user wants to achieve instead of trying to fix the current tools(perhaps it doesn’t matter that the hammer is broken, because in either case a screw driver should be used). And amongst what the user wants to do, I believe converting between XML and the data model of choice is a very common scenario.

1.

In general, it all seems interesting to write “interactive” output receivers and trees with Qt. One would be able to write queries/stylesheets that generate widgets, write queries over the file system or QObject tree, etc. But that’s another topic.

Comments Off
lars
Qt
KDE
Posted by lars
 in Qt, KDE
 on Tuesday, November 14, 2006 @ 12:10

One of the great things of Open Source development is that you can follow development on a day to day basis. Look at the code, play around with it and try out some of the new features.

In that respect Qt development has unfortunately not been as open as it should have been. Qt snapshots where only available after we had released a Technology Preview or a Beta of a certain version. We have in the past gotten lots of questions about our current development version in the past. Many developers are curious as to what we’re up to and interested in getting their hands onto the new things we’re doing.

To make this possible, we’re now publishing snapshots of our bleeding edge development branch. You can either get daily snapshots from ftp://ftp.trolltech.com/qt/snapshots or one of it’s mirrors (look for the 4.3.0 snapshots) or via rsync. Here are the urls for the different platforms:

rsync://rsync.trolltech.com/qt-x11-bleeding
rsync://rsync.trolltech.com/qt-win-bleeding
rsync://rsync.trolltech.com/qt-mac-bleeding
rsync://rsync.trolltech.com/qtopia-core-bleeding

Lots of new features that will go into Qt 4.3 have already been integrated into this branch. For those of you who like running experimental code, this is your chance of playing around with it. These snapshots are completely unsupported and don’t expect things to work (or even compile) all the time, but we appreciate every feedback you might have on the new features and APIs.

harald
Qt
KDE
Posted by harald
 in Qt, KDE
 on Thursday, November 09, 2006 @ 22:06

Recently, I was playing with Dasher, to see whether it can be used as alternative input method on the Greenphone. I haven’t integrated it into Qtopia yet, but it works nicely on my desktop (tested on GNU/Linux and Mac OS X). Download the sources or simply admire the screenshot:
Dasher running with Qt4

zack
Aggregated
Posted by zack
 in Aggregated
 on Tuesday, November 07, 2006 @ 16:28

Yesterday a rather large selection of trolls went to see Borat and while waiting for the movie to start Simon and I started talking about adding support for layouting of text on a path in Qt. I’ve sat down today, did the necessary math and added some extra members to QPainterPath and QBezier to make it all work. As always I wrote a short demo to illustrate what I’m talking about. I felt a little guilty tough because while I never blog about politics I see more and more people on planetkde feeling obliged to share their opinions on the world of politics. So my hard hitting politically charged statement for today is “i really like cookies”. Discuss among yourselves.
With visual aids the results of it all are shown in this short Ogg Theora video file here and the screenshots look like this:


It’s actually pretty neat (the code, not the fact that I like cookies). It’s not yet integrated at all within the QTextDocument (also the code and not the cookies) framework but hopefully we’ll be able to figure something out (both the code and the cookies) before Qt 4.3.

lorn
Qt
Qtopia
KDE
Posted by lorn
 in Qt, Qtopia, KDE
 on Saturday, November 04, 2006 @ 20:34

It has been a while since I played with a development version of KDE, but KDE 4 was just too enticing to resist. I have been using KDE since .. hmm.. since… well, seems a bit fuzzy, but I believe since before kdevelop was at version 0.65.

I am running kubuntu on my home machine, and to get the KDE 4 packages (too lazy and busy with my own development projects and life in general to compile KDE), I had to take the plunge of upgrading from ‘dapper’ to ‘edgy’. After having to manually fix a few things, I booted up KDE 4! Woot!

I am really glad KDE 4 is progressing nicely. Hopefully, the KDE crew will be able to fully port KDE, and get rid of Qt3Support libraries in the process, but thats just my opinion, and not sure if its in KDE’s radar.

Since I am an embedded developer, my interest in KDE 4 is really for Konqueror-embedded. I would really love to see konqueror ‘ported’ to Qtopia 4 just like konq-e 2 was way back when Qtopia 1.5 was new. But also the developers tools - KDevelop, which I would like to see have a better Qtopia integration… but we’ll leave that for some other time.

Great job, KDE krew! Keep up the wonderful work. I know it’s a rather difficult job ‘porting’ to Qt 4, but it’s worth it! I might even be able to attend the next aKademy, and meet you guys and poke you to also think about small screen interfaces! ;)