Qt itemviews trouble

Whoever digged a little deeper into Qt’s item views and models in the past knows that they’re quite tricky beasts sometimes. Two problems where driving me nuts recently:

1. How can I auto-expand the root node of a `QTreeView` whenever the view is resetted?
2. How can I restore the expansion / root state of a `QTreeView` when a model filter cleared all the items out before, effectively resetting the view as in 1.?

After a lot of struggling and lots of debugging I think I found a solution for both problems, which are slightly connected.

To get the auto-expansion feature, I connected the `layoutChanged()` signal of the model to a timer in my view, whose `timeout()` signal then again called the following slot:

void MyTreeView::delayedLayoutChanged()
{
    QModelIndex index = model()->index(0, 0, QModelIndex());
    expand(index); // or alternatively: setRootIndex(index);
}

This simply takes the first element of the model and expands it. Why the trick with the timer? Well, apparently the `layoutChanged()` signal is already processed internally by `QAbstractItemView` or `QTreeView` and its implementation resets the view state completly – which is of course problematic if it gets executed _after_ our own slot. A single-shot timer with an interval of 0 ms is enough here to make Qt use the next event loop cycle and do the right thing for us.

Now, things get more complex if you have a `QSortFilterProxyModel` attached to your tree view – imagine one of these fancy find-as-you-type inputs. If a user enters a search word which clears out all items from your current view and then resets the input again to see the original view, the view eventually gets a `layoutChanged()` signal as well, but because of the clearing you may have lost the expansion level in which the user was before!

`QPersistentModelIndex` is here for the rescue. All you have to do is remember the model index you previously used to expand your view and use that instead of the static one if it is still valid:

QPersistentModelIndex MyTreeView::lastExpansion;
void MyTreeView::expandSomething(const QModelIndex & index)
{
    lastExpansion = static_cast(model())
        ->mapToSource(index);
    expand(index);
}
void MyTreeView::delayedLayoutChanged()
{
    QModelIndex index;
    // is the item still part of the source model? 
    // (important for dynamic source models)
    if (lastExpansion.isValid())
    {
        index = static_cast(model())
              ->mapFromSource(lastExpansion);
    }
    else
    {
        index = model()->index(0, 0, QModelIndex());
    }
    expand(index); // or alternatively: setRootIndex(index);
}

While `QPersistentModelIndex` and `QModelIndex` are two distinct classes, the Trolls made them easily interchangable without special casting magic.

Note that you always need to save the source index and never the proxy index which might be invalidated if it is removed from the view. Things get of course even more complex if you have not one, but two proxy models which filter your view…

Interoperatibility without openess?

I was pointed yesterday to a page from the Free Software Foundation Europe (fsfe short) which describes the changes between the original and current draft for the “European Interoperatibility Framework” EIF – to quote the conclusion:

[…] we can only conclude that the European Commission is giving strong preference to the viewpoint of a single lobby group. Regarding interoperability and open standards, key places of the consultation document were modified to comply with the demands of the BSA. Input given by other groups was not considered on this issue. Beyond ignoring this input, the Commission has apparently decided to ignore the success of the first version of the EIF, and to abandon its efforts towards actually achieving interoperability in eGovernment services.

EIFv2: Tracking the loss of interoperability – enjoy the read…

Fuck php

Seriously, fuck it. Not only for it long-standing inconsistencies in the “user API”, no, I’ve rarely seen a piece of source code crap with such a low comment / code ratio.

What I’m trying to do? Debugging `SoapClient` from `ext/soap` and figure out why it ignores my `typemap`. Yes, there is a trace mode – but this will only fill the “private” `__getLastXXX()` methods, so I’m doing `printf()` debugging, within PHP’s source, as if it would be 1996 again. An amazing blaze from the past.

Oh, and in case you wonder if PHP can finally fully interoperate with other standard SOAP servers like Apache’s Axis, no, it still can’t. The developer of ext/soap is busy with other tasks these days, quoting him “[…] your WSDL uses overloaded functions […] and ext/soap doesn’t support them. I hardly believe it’ll support them in the future, in case nobody provide a patch.”, but hey, the aforementioned bug is only open for 5 or so years, right?

Apparently those people who give PHP the “enterprise ready” notion now are just waiting until SOAP died completly and everything has been replaced by the next best thing or what? Stupid morons, they should look at the source code of their “product”, think about it for ten seconds and finally run away screaming loud and beg the lord for forgiveness.

Bananenrepublik Deutschland

Auf Spiegel online ist heute ein sehr lesenswerter Artikel über die Hintergründe des Rückzugs von Peter Sawicki – einem international renommierten Mediziner – als Leiter des Instituts für Qualität und Wirtschaftlichkeit im Gesundheitswesen (IQWiG) erschienen.

Dieses Institut wurde mit seinen mittlerweile über 100 Mitarbeitern erst 2004 von der rot-grünen Bundesregierung mit dem Ziel ins Leben gerufen, neue Entwicklungen der Pharmaindustrie auf Wirksamkeit und Wirtschaftlichkeit hin zu untersuchen und interessierten Gruppen wie Krankenkassen und Ärzten Empfehlungen hinsichtlich dieser neuen Medikamente auszusprechen.

Klar, dass diese Institution und vor allem der engagierte Leiter der Pharmalobby ein Dorn im Auge war und so wurden mit einigen Intrigen, auch und vor allem aus dem heutigen Gesundheitsministerium, kleinere Unachtsamkeiten des Herrn Sawicki als Fauxpas größten Ausmaßes dargestellt, die in der Ablösung des charismatischen Frontmannes nach nur vier Monaten Schwarz-Gelb münden sollten.

CDU-Mann Spahn poltert in [“Hart aber Fair”]: Wenn heute schon jemand wegen zwei Maultaschen fristlos gekündigt werde, könne man die Verfehlungen Sawickis nicht einfach so abtun. Fast wortgleich meldet sich auch Gesundheitsminister Rösler: “Wenn einer Altenpflegerin wegen der Entwendung von Maultaschen fristlos gekündigt wird, kann ein Institutsleiter nicht im Amt bleiben, der Rasenmäherbenzin dienstlich abrechnet.” Ob die beiden es richtig finden, dass jemandem wegen zwei Maultaschen gekündigt wird, verraten sie nicht.

Im Endeffekt ging es bei Sawicki nicht um Maultaschen, sondern um die korrekte (private) Abrechnung von Spesen für seinen Dienstwagen. Im Laufe von drei Jahren waren laut seiner Rechnung etwa 1000 Euro angefallen, die er zu viel an Spesen erhalten und prompt dem Institut zurückerstattet hat:

Weitere Führungsleute des IQWiG sollen stichprobenartig überprüft werden. Unter Punkt VI ist geregelt: “Wir werden den Auftrag zu einem Nettohonorar von EUR 20. 000 durchführen.” Plus Mehrwertsteuer. Plus Spesen. Mehrere Profis werden auf Sawicki angesetzt.

Es kostet sehr viel Geld, die Reisespesen und Dienstwagen des IQWiG-Chefs zu überprüfen. Noch seltsamer: Laut Vergabeverordnung müssen alle Aufträge ab 12 500 Euro ausgeschrieben werden. Warum der Sawicki-Auftrag ohne Rücksprache vergeben wurde, will IQWiG-Vorstand Stackelberg nicht beantworten.

Das Ergebnis ist nun bekannt. Hier ging es nie um 1000 Euro falsch abgerechnete Spesen, hier ging es von Anfang an um viel, viel mehr…

monotone 0.47 released

The monotone team is proud to announce the release 0.47 of our beloved version control system! This release features many bugfixes, a new translation (Portuguese) and major performance improvements for projects with larger trees. A complete list of changes can be found in NEWS.

You can grab it at the usual location – binaries are posted there as they come in.

Thanks to all people who made this possible!

openSUSE madness

Just in case you wonder why a simple `sudo zypper install
` sometimes loads dozens or more unneeded, but possibly related packages, its not a bug, its a feature!

While Debian by default only hints you to these additional packages during the install phase, openSUSE installs them all by default. Try it with `git` and you’ll get everything here: `cvsps git git-core git-cvs git-email git-gui gitk git-svn git-web libpurple-tcl subversion-perl tcl tk xchat-tcl`.

There are two ways to get rid of this nasty behaviour:

1. Temporarily by adding the `–no-recommends` option to your call

2. Permanently by editing `/etc/zypp/zypper.conf` and configuring `installRecommends = no` in the `[solver]` section.

Hey, at least they have an option to disable it, though its completely beyond me why somebody wants to have this enabled by default. Maybe they get a cookie for every additional package download…?

Symfony development

Last week the second incarnation of Symfony Live came to an end and I just had the time to check a couple of shared slides from the event.

Definitely interesting stuff going on there, especially the preview release of Symfony 2.0 whose code is available on GitHub since a couple of weeks and which makes major changes to the “good old way” one used to write symfony applications (actions are now “controllers” and extensions “bundles” and well, a dozen of other things changed as well of course… you can read everything in detail here).

Also, Doctrine 2.0 seems to be the first PHP ORM which decouples the modelling approach from the actual database abstraction layer, skips the need for base classes and enables the model definition via annotations. Also, they seem to fight against the overly complex magic from Doctrine 1.x (one of my top complaints on Doctrine in comparison to, f.e. Propel) – maybe I’ll revisit Doctrine again when the next version gets stable.

The guys at Sensio labs do really have a fast development pace and I get more and more the impression that the Symfony ecosystem is the major competitor for the Zend framework. Community-wise I think Symfony is already much bigger than any other PHP framework.

Twitter

A hail to all the twitter users posting “I’m currently at XXX” status messages, otherwise useful information like those on pleaserobme.com would not be possible.

Darling, do you happen to know where I’ve put my lock pick in…?

guitone 1.0rc1 released

I’m proud to announce the immediate release of guitone-1.0rc1. This is the first release in a series of smaller releases which aims at the stabilization of the guitone codebase. Many (if not most) of the features one would consider needed for a “1.0” release have been implemented, a couple of outstanding bugs (noticable FS#39, FS#41 and
FS#42) have to get fixed beforehand though before that happens. Please test and report bugs if possible.

Outstanding news of this release:

  • Synchronization with other monotone nodes is no possible
  • Workspace action implementation almost feature-complete (add, drop, revert, rename, ignore, unignore and update finally work)
  • guitone can now create new monotone databases and setup new projects
  • Much improved key management with the ability to change the passphrase of keys, filter the key output and also drop keys
  • Many more bugfixes and smaller improvements as well as stabilization of the codebase

For a complete list of changes please check the NEWS file. I’ll try and prepare a Windows binary in the next couple of days, but probably won’t get to that before Wednesday, so if you want to help out, drop me
a note. A binary for Mac OS X should arrive shortly as well.

Tip: Enforce specific key usage for a single SSH connection

In case you have to access a very restricted SSH server which only accepts a single key (ie. the one which is set up in `~/.ssh/authorized_keys`) and otherwise fails, its the easiest to set the specific key in your local `~/.ssh/config` file as follows:

Host very.secure.server
    IdentityFile ~/.ssh/id_dsa
    IdentitiesOnly true

The second entry, `IdentitiesOnly`, forces SSH to only use known identity files and not look for more available identities f.e. from a running `ssh_agent` instance (which are always tried in first instance as it seems).