Ubuntu Unity Menu style für Qt Programme

Ubuntu und die globale Menubar in Unity – ich mag sie. Die alte Begründung – schneller Navigation durch Menübar on Top – gilt immer noch.

QtCreator 4.2.1
QtCreator integrated into Ubuntu’s menubar

Aber nicht immer spielen alle mit. Qt Programme die über Ubuntu’s Paketmanagement laufen, stellen kein Problem dar. Vor kurzem installierte ich allerdings ein eigenes Qt, bei dem dann prompt die Menu’s nicht mehr on Top, sondern altbacken am MainWindow plaziert waren.

Der Grund ist – dass die Qt SDK über den Online-Installer fertig kompilierte binaries (=libraries) für Linux 64bit lieferte.

Wenn man allerdings die Qt SDK selber kompiliert – was übrigens durch die filigrane configure Steuerung auch Sinn macht, sofern man eine eigene Qt Version möchte – gibt es keine Probleme. Irgendwo in den Untiefen des X-Systems (package appmenu-qt5) scheint es eine Ubuntu-modifizierte Komponente zu geben, gegen die man linkt um das globale Menu zu erhalten. Allerdings nimmt die lokale Qt-Installation (Sourcen, Kompilate und fertige Binaries) sehr viel Speicher in Beschlag – bspw. umfasst mein Ordner qt-everywhere-opensource-src-5.8.0 nach erfolgreichem Kompilieren immerhin 21GB!

Das gleiche Phänoment kann man auch mit 3rd party Qt Applikationen beobachten – linken sie gegen die Qt-Systemlibraries hat man das globale Menü – liefern sie eigene Qt-Bibliotheken mit, gibt es kein globales Menü.

Punkt oder Komma

Wenn ein Program dass Gleitkommazahlen von einer oder in eine Textdatei liest, bzw. schreibt nicht mehr funktioniert, dann sollte man sich genauer mit LC_NUMERIC befassen. Dieser Artikel behandelt die Auswirkungen auf Qt- und reine C-Programme.

LC_NUMERIC ist Bestandteil der sogenannte locales, der Lokalisierungen (oder auch Regionalisierungen) auf einem System. Diese Lokalisierungen lassen sich sehr fein einstellen – bspw. LC_MONETARY für die Währung oder eben LC_NUMERIC für das Zahlenformat – aber auch zusammenfassend mittels LC_ALL. Setzt man bspw. LC_ALL=de_CH.UTF-8, dann wird diese Einstellung auf alle sublocales übertragen und für LC_MONETARY ist der Franken gesetzt, wenn auch das meiste andere ziemlich deutsch ist.

Ok, nun aber zum Zahlenformat – und um die Sache ein bischen zu beschleunigen, soll eine Textdatei mit folgendem Inhalt ausgelesen werden.

#Hallöle
33.456,78
33456.78
33,456.78
33,99
33.98
33.777

Um die Zahlen besser zu verstehen muss noch einmal ausgeholt werden. LC_NUMERIC legt zwei Parameter fest.
Den Dezimaltrenner und den Tausender-Trenner. Er wird folgendermassen gesetzt:

Locale Dezimaltrenner Tausender-Trenner
en_US . ,
de_DE , .
C .

Das bedeutet, dass die deutsche Lokalisiserung genau andersherum als die US-Amerikanische ist. Die sog. C-Locale (auch POSIX-Locale genannt) kennt nur den Dezimaltrenner. Diese Locale ist als Rückfallebene gedacht.

Wie verhält sich nun ein Qt-Programm (Qt4), dass die o.g. Textdatei zeilenweise einliest und versucht den Text in Zahlen zu konvertieren? Zuerst einmal wird ein Testprogram unter der Umgebung LC_NUMERIC=de_DE.UTF-8 gestartet.

localeTest_de

Die Erklärung ist überrasch komplex. Zuerst einmal muss festgestellt werden, dass Qt Programme generell LC_NUMERIC-aware sind. Dies wird dadurch erreicht, dass QCoreApplication

setlocale(LC_ALL,"");

aufruft und damit locales aus dem Environment dem Programm zur Verfügung gestellt werden (dies wird durch die doppelten Anführungszeichen erreicht). Dennoch werten nicht alle Qt-Methoden LC_NUMERIC aus.

QByteArray::toDouble()
ignoriert die gesetzte locale und benutzt immer die C-Locale.

QString::toDouble()
verhält sich am kompliziertesten. Es wird der Dezimaltrenner der gesetzten locale ausgewertet, nicht aber der Tausender-Trenner (die Gründe liegen in der Kompatibilität zu C, siehe später). Gleichzeitig wird die C-Locale immer als Fallback mitausgewertet. Bei Qt5 verhält sich übrigens QString::toDouble wie QByteArray::toDouble

QLocale::toDouble()
hingegen orientiert sich ausschliesslich an der gesetzten locale.

Zum Vergleich nun die Ausgabe unter dem Environment LC_NUMERIC=en_US.UTF-8

localeTest_en

Interessant ist nun der Vergleich zu reinen C-Programme. Denn reine C-Programme mit ihren typischen Funktionen

printf/fprintf
scanf/fscanf
strtof

..usw. ignorieren standardmässig die gesetzte locale und stützen sich immer auf die C-Locale. Erst durch den schon oben genannten Aufruf von setlocale werden C-Programme locale-aware.
Werden allerdings C-Funktionen – bspw. aus einer Bibliothek – von einem Qt-Programm verwendet, sind sie automatisch locale-aware, da ja wie schon erwähnt QCoreApplication setlocale aufruft.

Dies ist eine große potentielle Fehlerquelle!

Um den Bogen zu QString::toDouble() nochmals zu spannen, sei erwähnt, dass C-Funktionen den Tausender-Trenner standardmässig ignorieren. Um z.B. printf zur Ausgabe des Tausender-Trenners bei Gleitkommazahlen zu zwingen, muss man

printf("Gezwungen zu %'f",myfloat);

einen Abostroph vor dem Formatierungszeichen einführen.
Zum Ausprobieren liegt das Qt Beispielprogramm sowie zwei plain C-Programme im diesem Archiv bei

GTK-Qt Theme

Nach einem Gnome-Update auf 2.12 an einem SuSE Linux 10.1 Rechner mit primären KDE Desktop ging der Look der GTK Programme wieder baden (Firefox,Thunderbird,Adobe Reader usw..)

Auf der Konsole wurde das Problem schnell lokalisiert:

 Gtk-WARNING **: Unable to locate theme engine in module_path: "qtengine"

Das Problem kam offenkundig von der qtk-qt Theme Engine. Mit Hilfe dieses Programms kann das KDE Kontrollcenter das aktuelle Theme/Style des KDE Desktops für GTK mit Hilfe der dynamisch erzeugten Datei:

~/.gtk_qt_engine_rc

erzeugen. Leider ist diese Paket auf den SuSE Repositories nicht mehr auf dem aktuellen Stand. Das Projekt selber ist auf diese Seite umgezogen. Dort schreiben die Maintainer, das die aktuellen Versionen (>0.6) nur noch im SourceCode erhältlich sind. Also hab ich das SuSE rpm Paket (qtk-qt….) deinstalliert, das tarball (Version 0.8) gezogen und mit der auf der Webseite stehenden Anleitung installiert (cmake muss installiert sein). Nach einem SuSEconfig erscheint der Menüpunkt „GTK-Stile und Schriftarten“ wieder im Bereich „Erscheinungsbild“ im KDE Kontrollcenter – dort nochmals den Punkt „Use my KDE Style in GTK Applications“ angewählt und schon wieder sehen alle GTK Anwendungen bestens aus.