Quitting a Qt application from the Mac OS X dock

May 2, 2010 – 23:25

So for some weird reason my application was not closable from the Mac OS X dock – it quit properly when you selected “Quit” from the application menu or hit the Cmd-Q shortcut – but the dock menu’s quit action was completely ignored.

While debugging the issue I hooked into QApplication::notify(QObject *, QEvent *) and noted that a QCloseEvent was send to my application… wait, what? A QCloseEvent? Yes, I also thought that these kinds of events would only be send to widgets, namely, top level widgets, but I got one for my application, and Qt plainly ignored it. So I went further ahead and tried to quit the application directly when the event occured, similar to this

bool MyApp::event(QEvent * ev)
{
    bool eaten = false;
    switch (ev->type())
    {
        // other stuff ...
#ifdef Q_WS_MAC:
        case QEvent::Close:
        {
            quit();
            eaten = true;
        }
#endif
        default:
            eaten = QCoreApplication::event(ev);
            break;
    }
    return eaten;
}
but this didn’t work out so nicely: while the application quitted correctly, the quit() slot was apparently called twice in a row. My guess is that Qt ignores the quitOnLastWindowClosed property – which I’ve set to false – and since I close all windows in the quit slot it executes quit again, or something else, so I decided to just close all open windows when the QCloseEvent arrived – without calling quit() directly, and tada, my application quitted and the slot was also only called once. Fun times.

monotone plugin for indefero (updated)

April 29, 2010 – 11:44

I’ve started hacking on a monotone plugin for indefero – a source code / project management tool which supports various SCM backends. You can find the code for it on github (git, because, well, indefero uses git…).

While there are a couple of web-related tools for monotone, namely TracMonotone and ViewMTN, both projects haven’t seen many updates over the last couple of years and are now even maintained by a single person who has not much time either. Having very good and broad tool support is however crucial for an SCM system, because only very few people are willing to use the command line for everything, so I hope that the addition of indefero as tool which will support monotone in one of its next versions will help both projects a little.

The code is still in alpha state, but one can already browse branches and revisions. My current TODO is as follows:

  • finalize the implementation of the changelog view done
  • make branch names shorter in the UI so they don’t overlap with the tree contents done
  • add automate stdio support for the SCM backend class, so we don’t need to create a separate process for every data request done
  • add automate remote_stdio support (possibly by adding a configuration option which allows either setup)
  • truncate the log message in the tree view to a proper size
  • dynamically change the clone url to the branch which the user is currently browsing done
  • check the inTags() and inBranch() implementations – apparently this does not work as it should done

Especially the multi-project nature of indefero requires some additional hacks in monotone and also one of its tools, usher (which is able to serve multiple distinct databases over one connection), so this plugin project really drives a lot of development. If you’re interested in either part and want to team up, drop me a note ;)

guitone 1.0rc3 released

April 25, 2010 – 14:14

I’m proud to announce the third release candidate of guitone 1.0. This release fixes some critical bugs and also adds support for drag’n'drop renames in the workspace amongst other minor improvements.

The complete list of changes is as always listed in NEWS. A Mac OS X binary is also already available, a package for Windows will follow tomorrow.

I’m still looking for translators – if you’re interested, please drop me a note.

openSUSE build service automation

April 18, 2010 – 01:44

A few weeks ago I’ve hacked together some scripts to use the openSUSE build service as platform for nightly builds. The build is kicked off every hour when something new can be build.

Additionally I’ve created a small PHP client which queries the openSUSE RESTful API and shows packages, binaries, the build log of the last build and a build history.

The code for this is GPL’d and can be cloned via monotone:

$ mtn clone thomaskeller.biz biz.thomaskeller.monotone-nightly

All this could be polished and secured quite a bit more and its even arguable if its a good idea to “misuse” the openSUSE’s infrastructure for nightly builds like this, but I see it more as a proof of concept. Since their build infrastructure code is open source as well, somebody can always just setup a build server together with a service and a couple of predefined XEN images and should be good to go.

The concept can now be horizontally applied to other distros and versions as well, basically anything what can run within a Xen instance (unfortunately this does not include Mac OS X or Windows, so there is still the need for some kind of alternative build infrastructure). I eventually plan to add a couple of more Xen instances to my project and try to get them build – of course you can be my guest and play with it yourself and lend me a helping hand here :)

guitone 1.0rc2 released

April 6, 2010 – 12:08

I’m proud to announce the immediate release of guitone-1.0rc2. This is the second release in a series of smaller releases which aims at the stabilization of the guitone codebase. A lot of bug fixes went into the code, only a few outstanding issues remain. The addition of an annotation view is the most visible new feature of this release. Please test and report bugs if possible.

The complete list of changes is written down in the NEWS file as always. I’ll try and prepare a Windows binary tomorrow, a binary for Mac OS X should arrive shortly as well.

Qt itemviews trouble

March 31, 2010 – 23:59

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?

March 30, 2010 – 17:43

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

March 23, 2010 – 14:33

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

March 16, 2010 – 21:38

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

March 14, 2010 – 23:22

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!