App-Entwickler möchten möglichst verschiedene Zielplattformen beliefern. Nokia schickt dafür Qt samt der IDE Qt Creator [1] ins Rennen, seit Kurzem ergänzt durch die API-Sammlung Qt Mobility. Damit greifen Entwickler auf Telefonfunktionen zu, etwa auf Kontakte oder Multimedia-Ausgänge (Tabelle 1).

Um C++-Fremden – etwa Designern – den Zugang zur bewegten Welt mobiler Apps zu erleichtern, haben die Entwickler die Qt Metaobject Language (QML) geschaffen: Sie erlaubt es, Anwendungsoberflächen mittels Objekten und Eigenschaften in einem Javascript-Dialekt zu beschreiben. QML bildet zusammen mit anderen Teilen das “Qt UI Creation Kit” (Qt Quick, [2]) und ist Teil von Qt 4.7.
Besser hybrid
Die Autoren dieses Artikels finden: Hybride Apps sind besser als einsprachige Apps. Die Stärken von QML und C++ ergänzen sich zu schicken und performanten Anwendungen. Die Kombination ermöglicht Aktionen, die QML derzeit nicht – oder nicht elegant – implementiert: Die Beispielanwendung in Abbildung 1 schießt in QML über das Multimedia-API von Qt Mobility Fotos und versieht sie in normalem C++ mit einem Zeitstempel.

Abbildung 1: Die Qt Meta Object Language (QML) und das C++-basierte Qt-Framework bandeln mittels der API-Sammlung Qt Mobility mit Smartphone-Funktionen an.
Qt Mobility kennt derzeit erst wenige Zielplattformen. Die Preview-Version 1.1 beherrscht die Nokia-Geräte N900 mit Maemo und das N8 mit Symbian 3. Experimentell unterstützt sie die Vorabversion von Meego Netbook für Intel-Atom-Rechner. Die in diesem Artikel entwickelte App zielt auf das N900. Wer nicht im Besitz eines solchen Geräts ist oder die versprochene Zielplattform-Unabhängigkeit austesten will, findet am Ende des Artikels Hinweise für Meego.
Der Entwicklerrechner ist leicht vorbereitet (siehe Kasten “Preview Qt SDK 1.1 installieren”). Bevor es mit dem Programmieren losgeht, sind etliche Schritte zu tun, um ein Rahmenprojekt anzulegen und auf die Endgeräte zu trimmen.
| Preview Qt SDK 1.1 installieren |
|---|
Der Download des Installations-Wizard erfolgt von Nokias Webseiten [3]. Der Wizard ist beispielsweise im Ordner »$HOME/tmp_Downloads/« gut aufgehoben. Für 32-Bit-Linux startet den Wizard dann die Kommandofolge:
cd $HOME/tmp_Downloads/ chmod u+x Qt_SDK_Lin32_online_v1_1_UTP_en.run ./Qt_SDK_Lin32_online_v1_1_TP_en.run Im Wizard ist bei »Qt SDK Technology Preview Setup« die Lizenzvereinbarung durchzulesen. Nach der Wahl des Installationsverzeichnisses ist sie erneut zu bestätigen, was den Download auslöst. Der Wizard ermittelt die benötigten Dateien, lädt sie vom Server herunter und installiert die verschiedenen Komponenten des SDK auf dem System. Nach der Meldung »Installation finished!« startet ein Klick auf »Next« und noch einmal »Finish« bereits den Qt Creator und öffnet im voreingestellten HTML-Browser die Readme-Seite, der wichtige Neuerungen zu entnehmen sind. Für die Zielplattform N900 ist ferner die Doku-Seite “Setting Up Development Environment for Maemo” interessant. |
Aller Anfang ist Qt
Der im SDK 1.1 enthaltene Creator bringt für die Hybridprogrammierung bereits ein Template mit. Entwickler starten mit dem Button »Create Project …« einen Projekt-Wizard. Der erstellt ein »Qt Quick Project«, also ein QML-Projekt. Von den drei zur Wahl stehenden Projekttypen erlaubt die »Qt Quick Application« den gewünschten Typ hybrider Anwendungen. Nach einem Klick auf »Choose« auf der Folgeseite fällt die Entscheidung für einen Namen und das Verzeichnis des Projekts (im Programmierbeispiel beides »TimePic«).
»Next« bringt den Programmierer zur Ansicht »Qt Versions«, wo er dem Creator das erste Mal die gewünschten Zielplattformen mitteilt. Voreingestellt sind im neuen SDK nur »Desktop» und »Remote Compiler« – für das N900 sind zusätzlich »Qt for Fremantle PR1.3 Devices« und »Simulator Qt for GCC« zu aktivieren. Der »Next«-Button führt ihn zu den »Application Options«, wo die Tab-Seite »Maemo« ein Icon für die App entgegennimmt: Passend legt er eine 64 mal 64 Pixel große PNG-Datei in das Projektverzeichnis. Das SDK paketiert später alle darin gefundenen Dateien und Unterverzeichnisse für den Einsatz auf dem Zielgerät.
Auf der folgenden »QML Sources«-Seite erzeugt die Option »Generate a main.qml file« den Startpunkt. Abschließend erlaubt die »Summary«-Seite die Auswahl eines Versionskontrollsystems – in der Preview-Version des verwendeten SDK sind es Mercury und Git. Mit »Finish« gibt der Qtler die Einstellungen frei: Die Dateien des jungfräulichen Projekts präsentieren sich baumartig im Panel.
Mit dem »Mode Selector« von Qt Creator fügt der App-Entwickler dem Projekt mittels der Auswahl »Projects« wieder die zwei Plattformen hinzu. Dazu benutzt er zweimal das »+«-Symbol, einmal für Maemo, einmal – zu Testzwecken – für den Qt-Simulator. Ein Blick auf die Fläche »Desktop« stellt sicher, dass dort für die Betriebsmodi »Debug« und »Release« jeweils die Qt-Version »Desktop Qt for GCC (SDK)« angewählt ist.
Um die App testen zu können, teilt der Entwickler dem Simulator zuletzt den Pfad zur Bibliothek »libQtMobilitySimulator.so.1« mit. Dafür nutzt er im Bereich »Build Environment« den Dialogeintrag »Details« mit seiner Variablenliste. Mit »Add« fügt er einen neuen Eintrag hinzu, indem er die Variable »LD_LIBRARY_PATH« auf den Wert »SDK-Pfad/Simulator/QtMobility/gcc/lib« setzt.
Zur Belohnung für die umfangreichen Vorbereitungen erfüllt Leben die IDE: Der »Target Selector« unterscheidet Zielplattformen und kennt neben dem Debug- auch den Release-Modus.
Ans Eingemachte: Der Code
Die Methoden der Beispiel-App rufen eine C++-Klasse auf. Die Hilfsklasse bedarf keiner Bildschirmausgabe, daher ist sie kein sichtbares »QDeclarative«-Item: Sie leitet sich schlicht von »QObject« ab.
Tipparbeit erspart dem Programmierer der »Class Wizard« (Abbildung 2), er wählt Dateinamen nach dem Klassennamen, was sich auf Wunsch auch ändern lässt. »Next« führt zur »Summary«-Seite, ein letztes »Finish« erzeugt die Dateien. Im Editor erscheint jetzt die Datei »picturelabeler.cpp«.

Abbildung 2: Der C++-Class-Wizard erzeugt Header und Implementierungsdatei einer neuen Klasse und trägt sie in das Projekt ein.
Um die Deklaration anzupassen, erhält die vom Wizard erzeugte Klassendeklaration »picturelabeler.h« im Zweig »Headers« des Projektbaums das Makro »Q_INVOKABLE«, das QML später aufrufen wird. Der Abschnitt »public« sollte jetzt so aussehen:
public:
explicit PictureLabeler(
QObject *parent = 0 );
// returns the timestamp
// or an empty string on error
Q_INVOKABLE QString addTimestamp(
const QString& pictureFilename );
Zurück in der Implementierungsdatei klickt der Qt-Entwickler im Bereich »Open Documents« auf »picturelabeler.cpp« (Listing 1). Nach den Includes am Textbeginn bleibt der Konstruktor leer (Zeile 8). Ab Zeile 13 implementiert er die neue Methode »addTimestamp()«.
| Listing 1: »picturelabeler.cpp« |
|---|
01 #include <QDateTime>
02 #include <QFont>
03 #include <QImage>
04 #include <QPainter>
05
06 #include "picturelabeler.h"
07
08 PictureLabeler::PictureLabeler(
09 QObject *parent) : QObject(parent)
10 {
11 }
12
13 QString PictureLabeler::addTimestamp(
14 const QString& pictureFilename )
15 {
16 const QString dt =
17 QDateTime::currentDateTime().toString();
18 QImage img( pictureFilename );
19
20 if( ! img.isNull() ) {
21 QPainter painter( &img );
22 painter.setPen( Qt::blue );
23 painter.setFont(QFont( "Arial", 32 ) );
24 painter.drawText(16,img.height()-18, dt );
25
26 if( img.save( pictureFilename ) )
27 return dt;
28 }
29 return QString("");
30 }
|
Um die Klasse QML zur Verfügung zu stellen, muss die »main.cpp« des Projekts ihren Typ bei der QML-Engine registrieren. Dafür erhält sie zu Beginn die zwei benötigten Header und nach Instanzierung der »QApplication« die Template-Methode »qmlRegisterType()«:
#include "picturelabeler.h"
#include <qdeclarative.h>
[...]
QApplication app(argc, argv);
qmlRegisterType<PictureLabeler>(
"com.basyskom.qmlcomponents",
1, 0, "PictureLabeler" );[...]
Nun darf der QML-Code auf die C++-Hilfsklasse zugreifen. Die App entsteht im Weiteren allein durch Editieren der QML-Hauptdatei.
Das Beispiel spricht Qt Mobility nur von QML aus an, daher benötigt es keine Anpassungen in der Datei »TimePic.pro«. Wer auch von C++ aus auf Qt Mobility zugreifen möchte, beachtet die Hinweise im Kasten “Tipps und Tricks”. Die vollständige QML-Hauptdatei liegt mit allen anderen Sourcen auf dem Listing-Server bereit [2]. Weitere QML-Beispiele sammelt die Doku-Seite zu Qt Quick [3]. Im Folgenden zeigt ein kurzes Codebeispiel die Konzepte, die in der Beispiel-App Anwendung finden.
Hallo QML
Das in Listing 2 gezeigte QML-Programm erzeugt der Projekt-Wizard für jede neue Qt-Quick-Anwendung. Der Wizard deklariert per Default im »Hello World«-Hauptelement die »MouseArea« parallel zu einem »Text«-Element. Damit deckt sie die gesamte Fläche des umgebenden Hauptrechtecks ab: Ein Mausklick irgendwo im Fenster schließt die App. Wandert die »MouseArea« aber wie in Listing 3 in die Deklaration des »Text«-Elements, beenden nur Klicks auf den Text die App, sie ignoriert Mausereignisse in der leeren Fläche um den Text herum.
| Listing 2: Mausklick im Hauptfeld |
|---|
01 Rectangle {
02 width: 360
03 height: 360
04 Text {
05 text: "Hello World"
06 anchors.centerIn: parent
07 }
08 MouseArea {
09 anchors.fill: parent
10 onClicked: {
11 Qt.quit();
12 }
13 }
14 }
|
Zu sehen war bereits, dass der Entwickler C++-Methoden für QML verfügbar macht, indem er sie in der betreffenden Headerdatei mit dem Makro »Q_INVOKABLE« kennzeichnet. Auch in Listing 3 ruft Zeile 7 eine C++-Funktion auf, um die App zu beenden: »Qt.quit()« schließt die Hauptanwendung einschließlich Viewer mit der laufenden QML-App. Dies funktioniert nur, wenn man im Wizard durch die Wahl des Typs »Qt Quick Application« eine hybride App erzeugt. Eine solche App startet im C++-Hauptprogramm eine »QApplication« und verwendet die Klasse »QmlApplicationViewer«, um den QML-Code zu laden, zu parsen und auszuführen.
| Listing 3: Mausklick im Textfeld |
|---|
01 Text {
02 text: "Hello World"
03 anchors.centerIn: parent
04 MouseArea {
05 anchors.fill: parent
06 onClicked: {
07 Qt.quit();
08 }
09 }
10 }
|
Im Folgenden kommt außerdem das Konzept zum Tragen, dass QML-Elemente zumeist rechteckige Bereiche des Programmfensters sind. Als oberste Ebene dient oft das Element »Rectangle«, möglich wären auch andere deklarative Objekte. Die Referenz [4] führt alle QML-Elemente auf. Unsichtbare Elemente wie die »MouseArea« leisten Hilfsdienste: Ebenso wie die sichtbaren Elemente enthalten sie Deklarationen und Steuercode, der meist in kleinen Funktionen steckt (hier die »onClicked()«-Methode). Schließlich stellen Eigenschaften einen Großteil des üblichen QML-Code. Werte für »width« und »text« setzen die in »anchors« zusammengefassten Properties in Bezug zueinander, etwa »fill« oder »centerIn«. Das »Item«-Element dient als Basis aller sichtbaren QML-Elemente, ein Blick in die Dokumentation lohnt [5].
Die hybride Beispiel-App »TimePic« deklariert zu Beginn im Hauptelement zunächst drei Properties vom Typ »int«, um den in QML nicht vorhandenen Aufzählungstyp Enum zu simulieren (Listing 4, Zeilen 1 bis 3). Der symbolische Name »pageModeCommandView« in Zeile 3 ist sicherer, als wenn dort »pageMode = 2« stünde: Mögliche Tippfehler erkennt der QML-Parser bei Namen, nicht jedoch bei Zahlen.
| Listing 4: Der Labeler |
|---|
01 property int pageModeCommandView: 1;
02 property int pageModeImageView: 2;
03 property int pageMode: pageModeCommandView;
04 [...]
05 PictureLabeler {
06 id: labeler
07 }
08
09 Camera {
10 id: cameraObject
11 anchors.centerIn: parent
12 width: 100
13 height: 100
14
15 onImageCaptured: {
16 console.log("Image captured!" )
17 }
18
19 onImageSaved: {
20 console.log("Image saved!" )
21 imageFilename.color = "blue"
22 imageFilename.text = "images files " + capturedImagePath
23
24 var stamp = labeler.addTimestamp(capturedImagePath)
|
Aus den importierten C++-Modulen instanziert die App als Nächstes die Klassen »PictureLabeler« als »labeler« (Zeile 5) und »Camera« als »cameraObject« (Zeile 9). Der Labeler erhält nur eine ID, das Kamera-Objekt auch Eigenschaften. Das Namensschema der Methoden »onImageCaptured()« und »onImageSaved()« (Zeilen 15 und 19) folgt dem Präfix »on« gefolgt von einem Signal der C++-Klasse, das einen großen Anfangsbuchstaben erhält. Darum verknüpft die QML-Engine die Methode automatisch als Slot mit dem Signal.
Bei Redaktionsschluss dieses Artikels war das QML-Element »Camera« zwar in Qt Mobility 1.1 enthalten, sein API aber noch nicht dokumentiert. Die Sourcen auf Gitorious [6] stellten sich als wertvolle Informationsquellen heraus.
Die Grenze beider Welten
Die Zeile 24 von Listing 4 ist in dreifacher Hinsicht interessant, denn sie schafft den Übergang zwischen den Welten von C++ und QML. Der Anfang »var stamp« instanziert eine Javascript-Variable. Er initialisiert sie mit der eingangs in Listing 1 implementierten Methode »addTimestamp()«. Das Objekt »labeler« stammt aber aus der in Zeile 5 instanzierten Hilfsklasse »PictureLabeler«. Der Parameter »capturedImagePath« ist eine Eigenschaft der Klasse »Camera« aus Zeile 9. Sie ist für QML erreichbar, weil die Headerdatei »QDeclarativeCamera« sie als »Q_PROPERTY« deklariert.
Die Fortführung der »TimePic«-App in Listing 5 beginnt mit dem Quit-Button (Zeilen 1 bis 4). Er ist das erste sichtbare Element innerhalb des obersten QML-Elements »timePicMain«, weil das folgende Rechteck-Element »mainArea« (Zeilen 6 bis 40) seine Unterkante an der Oberkante des Quit-Buttons ausrichten soll (Zeile 9). Die »mainArea« nutzen zwei weitere Rechtecke, »commandView« (Zeilen 11 bis 21) und »imageView« (Zeilen 23 bis 39). Sie erscheinen nie gleichzeitig: Sie würden sich gegenseitig verdecken.
| Listing 5: Wechsel der Programmzustände |
|---|
01 Rectangle {
02 id: quitButton
03 [...]
04 }
05
06 Rectangle {
07 id: mainArea
08 [...]
09 anchors.bottom: quitButton.top
10
11 Rectangle {
12 id: commandView
13 [...]
14 MouseArea {
15 [...]
16 onClicked: {
17 console.log("Capturing a photo with ISO " + cameraObject.iso )
18 cameraObject.captureImage()
19 }
20 }
21 }
22
23 Rectangle {
24 id: imageView
25 [...]
26 Image {
27 [...]
28 source: cameraObject.capturedImagePath
29 }
30 MouseArea {
31 anchors.fill: parent
32 hoverEnabled: true
33 acceptedButtons: Qt.LeftButton
35 onClicked: {
36 pageMode = pageModeCommandView;
37 }
38 }
39 }
40 }
41
42 states: [
43 State {
44 name: "StateCommandView";
45 when: timePicMain.pageMode == pageModeCommandView;
46 PropertyChanges { target: commandView; opacity:1 }
47 PropertyChanges { target: imageView; opacity:0 }
48 },
49 State {
50 name: "StateImageView"
51 when: timePicMain.pageMode == pageModeImageView;
52 PropertyChanges { target: commandView; opacity:0 }
53 PropertyChanges { target: imageView; opacity:1 }
54 }
55 ]
56
57 transitions: [
58 Transition {
59 from: "StateCommandView"
60 to: "StateImageView"
61 reversible: false
62 SequentialAnimation {
63 NumberAnimation {
64 duration: 100
65 properties: "detailsOpacity,height"
66 }
67 [...]
68 }
69 },
70 Transition {
71 from: "StateImageView"
72 to: "StateCommandView"
73 reversible: false
74 [...]
75 }
76 ]
|
Wechselnde Zustände
Dieses Muster ist in QML häufig anzutreffen: ein Wechsel zwischen zwei Programmzuständen. Bei aktivem Zustand »StateCommandView« (Zeilen 43 bis 48), schießt die App über die Kamera das Foto, schreibt den Timestamp in die von der Klasse »Camera« gespeicherte Bilddatei und setzt bei Erfolg die Toplevel-Eigenschaft »pageMode« auf »pageModeImageView«.
Der Zustand »StateImageView« hingegen (Zeilen 49 bis 54) lädt über ein Image-Element das gespeicherte Bild in das Rechteck »imageView« (Zeilen 23 bis 40), dessen Name aus der Property »cameraObject.capturedImagePath« stammt. Die »onClicked()«-Methode (Zeilen 35 bis 37) des Mausbereichs dieses Rechtecks setzt den »pageMode« wieder auf »pageModeCommandView« zurück. Dann übernimmt statt des Rechtecks »imageView« wieder das Rechteck »commandView« das Ruder.
Der »States«-Abschnitt der Zeilen 42 bis 55 deklariert beide Zustände. Die »when«-Bedingungen legen fest, wann die QML State Machine den betreffenden Zustand aktiviert. Die Anweisungen »PropertyChanges« ändern die Sichtbarkeit der beiden Rechtecke über die Eigenschaft »opacity«. Genau so, wie der »States«-Abschnitt das Was und Wann der Elemente festlegt, deklariert der Abschnitt »Transitions« das Wie: Er blendet von einer Ansicht zur anderen über. Für weitere Spiele mit animierten Übergängen empfiehlt sich die Animations-Dokumentation [7].
Fertig: Ab ins Testfeld
Der Qt Creator schickt die fertige App zum Simulator, indem der Entwickler ihn im Ziel-Umschalter als aktives Target auswählt. Ein Klick auf »Run« gibt den Startschuss für den Buildvorgang. In der Voreinstellung simuliert der Creator ein N900. Im Erfolgsfall zeigt er im Simulator das Programm ähnlich wie in Abbildung 3 an.

Abbildung 3: Die Beispiel-App »TimePic« legt einen erfolgreichen Testlauf im Simulator hin. Der Testlauf dient auch dazu, Tippfehler im Code oder nicht passende Bibliotheken zu finden.
Der Simulator kann keine Fotos aufnehmen. Der Testlauf ist dennoch wichtig, etwa um Tippfehler im Code oder nicht passende Bibliotheken bereits vor dem Einsatz auf dem Gerät zu erkennen. Ist der Simulator aktiv, bietet das komplexe Fenster »Qt Simulator Control« vielfältige Möglichkeiten, sein Verhalten zu beeinflussen. Für die ersten Schritte belässt es der Entwickler bei den Voreinstellungen, die die von »TimePic« benutzte rückseitige Kamera simuliert.
Um die App auf echte Geräte zu schicken, sind weitere Schritte nötig: Das N900 braucht ein Firmware-Update und das Programm Mad-Developer (Kasten “Zielgerät N900 vorbereiten”). Das Netbook als Zielgerät bedarf des neuesten Meego und auf Seiten des Entwicklerrechners des Helferleins Mad-Admin (Kasten “Zielgerät Netbook vorbereiten”). Die Meego-Seite [12] listet die von Meego unterstützten Zielgeräte, auf denen die App laufen sollte.
| Zielgerät Netbook vorbereiten |
|---|
| Die Installation von Meego auf dem Netbook [8] unterscheidet sich nicht sehr von der Installation jeder anderen Linux-Distribution [9]. Aber aus dem Meego-SDK [10] benötigt der App-Entwickler zusätzlich MADDE (Meego Application Develop und Debug Environment). MADDE stellt mit dem Mad-Admin ein Tool bereit, das ihn beim Herunterladen und Installieren der so genannten Targets unterstützt. Diese Targets bieten dem Qt Creator eine Toolchain an – genau wie im Fall des N900. Der Creator kann nun mit angepassten Projekteinstellungen im »meego-sdk-creator« das N900-Projekt laden. Der Klick auf »Run« kompiliert die Applikation wie gewohnt, überträgt sie auf das Netbook und startet sie dort.
Vorsicht: Die Qt-Mobility-API-Integration in der Meego-1.1-Netbook-Release (Stand November 2010) ist nicht vollständig abgeschlossen. Bei Schwierigkeiten könnte daher schon ein Update auf die neueste Meego-Trunk-Version oder ein Blick auf das für Frühjahr 2011 angekündigte Meego 1.2 helfen. |
Das wahre Leben
Zum N900 führen im Target »Maemo« der Button »Run« und dort der blaue Link »Manage device configurations«. Im erscheinenden »Options«-Dialog schafft der Entwickler per »Add«-Button eine neue Konfiguration, die passenderweise N900 heißen sollte. Den auf »Key« voreingestellten Authentifizierungstyp stellt er auf »Password« um. Die dafür benötigte Zeichenfolge zeigt der auf dem N900 installierte Mad-Developer an. Der »Test«-Button prüft nun die Verbindung – ist alles in Ordnung, hat der Optionendialog ausgedient.
Nahe am Ziel wählt der App-Schöpfer – zurück auf der »Run«-Seite – jetzt im Feld »Deploy to Device« das eben angelegte N900 aus. Im Ziel-Umschalter sucht er sich »Maemo« als aktives Ziel aus, allerdings mit »Release«-Build statt des vorgegebenen »Debug«-Modus. Gespannt klickt er wieder auf »Run«.
Das SDK baut nun ein Maemo-5-Projekt, erzeugt daraus ein Debian-Paket und kopiert es über die SSH-Verbindung auf das N900. Da der Dialog »Developer Password« bei korrekter Vorbereitung auf dem N900 noch geöffnet ist, erlaubt das Gerät SSH-Zugriffe. Nach dem Kopieren installiert das SDK das neue Programmpaket auf dem N900 und startet es.
Herzlichen Glückwunsch! Wer mit der rückseitigen Kamera des N900 nun ein Ziel anvisiert und über die blaue Schaltfläche »Capture Next Photo« ein Bild schießt, sieht in den beiden vormals roten Anzeigezeilen den Namen der erzeugten Bilddatei und den Text des von der C++-Klasse eingetragenen Zeitstempels auftauchen. Das Output-Fenster des Creator freut sich ebenfalls am Erfolg seines Benutzers, wenn die letzten Zeilen Ausgabe ähnlich wie folgt lauten:
Capturing a photo with ISO 0 Image captured! Image saved! Image time stamp saved as Fri Jan 14 U 13:58:40 2011 Geschafft: Die erste hybride App ist erfolgreich getestet und installiert. Wer mag, nutzt sie künftig als Basis für eigene Projekte. (ake)
Geschafft: Die erste hybride App ist erfolgreich getestet und installiert. Wer mag, nutzt sie künftig als Basis für eigene Projekte. (ake)
| Die Autoren |
|---|
| Der Diplom-Informatiker Jeremias Bosch arbeitet seit 2009 bei der Darmstädter Basyskom GmbH als Qt Software Consultant. Er koordiniert eine internationale Arbeitsgruppe für Firefox Mobile auf Meego und leitet das Peregrine-Team.
Der Trierer Karl-Heinz Zimmer war Starwriter-Entwickler in der Star Division und Senior Developer in der Klarälvdalens Datakonsult AB. Heute koordiniert er als Senior Qt Consultant der Basyskom GmbH ein Nokia-Forschungsteam. |







