Anmelden Registrieren

Badges

Follow Peter Bouda on Google Plus

Feeds

Neueste BlogeinträgeBlog

Tutorial zur App-Entwicklung mit dem Nokia Qt SDK für Maemo und Symbian

Bearbeitet am Donnerstag, 30. September 2010, 12:53 Uhr von pbouda

Dieses Tutorial wird und wurde auch auf meego.de veröffentlicht, und zwar als Fortsetzungsserie. Ich werde hier im Wiki die Teile auch nach und nach veröffentlichen, jeweils zeitgleich mit der Veröffentlichung auf meego.de. Solange dieser Hinweis also hier steht, ist das Tutorial noch nicht vollständig.

Los geht’s

Als mobiler Qt-Programmierer wird man von Nokia mit dem Qt-SDK richtiggehend verwöhnt, wenn man die Software mit früheren SDKs für Symbian und Java vergleicht. Ein schöner Designer zum Zusammenklicken von GUIs, ein hervorragender C++-Code-Editor und eine exzellente Integration diverser Code-Repository-Systeme bietet das Entwicklungskit. Nach den ersten Versuchen erfolgt aber bald die Ernüchterung: die Qt-Maemo-Anwendung sieht auf dem N900 richtig schön aus, aber schon die Kompilation für Symbian gestaltet sich etwas holprig, und die Anwendung sieht dann auf dem Gerät ganz und gar nicht so aus, wie noch am Anfang im Designer. Hier zeige ich euch, wie ihr am Besten das Grundgerüst für eine plattformunabhängige, mobile Qt-Anwendung erzeugt, das ihr einfach für Maemo und Symbian kompilieren könnt und das euch auf beiden Plattformen sogar “Autorotation” bietet, d.h. ein flexibles GUI für ein horizontales und vertikales Layout enthält. Alle Schritte beschreibe ich in diesem Fall für das Qt-SDK unter Windows, da z.Zt. ja nur Windows eine out-of-the-box Kompilierung von Symbian-Anwendungen erlaubt.

Voraussetzung ist also schon einmal ein installiertes Nokia Qt SDK.

Projekterstellung

Zunächst erstellen wir ein Projekt, aber nicht direkt im Qt Creator. Dieser bietet natürlich die Funktion “Neues Projekt erstellen”, aber dann fehlt uns der gesamte debian-Ordner für die spätere Paketerstellung für Maemo. Das SDK wird aber mit MADDE geliefert, und über dieses können wir ganz einfach ein sinnvolles Projektgerüst erstellen (s. auch Artikel Wie man mit MADDE ein Qt-Projekt für Maemo erstellt). Dazu starten wir als erstes im Windows-Starmenü das “MADDE-Terminal”:

Ihr seht jetzt folgendes Fenster vor euch:

Um ein Projektgerüst anzulegen reicht ein Befehl im Terminal:

mad pscreate -t qt_simple mobileqt

Dieser Befehl legt eine komplette Projektstruktur (per Template “qt_simple”) im Ordner mobileqt an. Um eine Liste aller verfügbaren Templates auszugeben gibt es den Befehl:

mad pscreate -l

mad ist sozusagen die Hauptanwendung in MADDE, über sie erreicht ihr alle nötigen Befehle für die Projektverwaltung. Die Projektstruktur eures Projekts sollte jetzt folgendermaßen ausschauen:

Der Ordner data enthält eine .desktop-Datei und zwei Icons, damit ihr die Anwendung später über das Anwendungsmenü auf dem Gerät starten könnt. Im src-Ordner liegt eine eure Hautanwendungsdatei qtmain.cpp, der uis-Ordner ist leer und kann später für die .ui-Dateien für die Oberfläche der Anwendung verwendet werden. Der debian-Ordner enthält die Dateien zur Erstellung des .deb-Pakets, dabei sind vor allem folgende Dateien für euch interessant:

  • changelog: Für spätere Versionen muss das changelog jeweils erweitert werden, und zwar über den Befehl debchange. Genaueres dazu gibt es hier.
  • control: Hier solltet ihr noch eine Projektbeschreibung eintragen. In der Zeile Maintainer: sollte euer Name und E-Mail-Adresse stehen. Das Feld XB-Maemo-Icon-26: git ein Icon für den Programmmanager auf dem N900 an. Wenn ihr diese Felder leer lasst, dann wird kein Icon verwendet. Das Icon muss die Größe 48×48 haben. Wie ihr den Icon-Code für die control-Datei erstellt, könnt ihr hier nachlesen. Wenn ihr kein Icon braucht dann könnt ihr das entsprechende Feld einfach aus control entfernen. Dieses Icon ist wie gesagt nur für den Programmmanager. Das Anwendungsicon für den Desktop wird separat aus dem data-Verzeichnis installiert.
  • copyright: Hier müsst hier halt euren Namen und die entsprechenden Copyright-Informationen eintragen.

Eine genauere Beschreibung der einzelnen Dateien findet ihr beispielsweise hier.

Projekt im Qt Creator

Der Projektordner mobilqt enthält nun u.a. die Datei qtprog.pro. Wenn das Nokia Qt SDK standardmäßig installiert wurde, dann lässt sich diese Datei einfach per Doppelklick im Qt Creator öffnen. Alternativ kann man natürlich auch gern den Qt Creator über das Startmenü starten und die Projektdatei per “Datei→Datei oder Projekt öffnen…” laden. Beim ersten Öffnen der Datei fragt der Qt Creator zunächst nach den sog. targets (deutsch “Ziele”) für das Projekt. In diesem Fenster könnt ihr einfach alle Zeile markieren:

Das Projekt lässt sich so sowohl für Maemo, den Qt Simulator und Symbian kompilieren. Ein Klick auf “Abschließen”, und schon habt ihr das Hauptfenster des Qt Creator mit dem geladenen Projekt vor euch:

Unten Links seht ihr einen grünen Pfeil (der obere, ohne Lupe). Über dem grünen Pfeil ist am Anfang immer das Ziel “Qt Simulator / Debug” ausgewählt. Alle für das Projekt aktivierten Ziele seht ihr, wenn ihr auf das Symbol über dem grünen Pfeil klickt:

Diese Einstellung können wir aber erst einmal lassen, wie sie ist. Wenn ihr jetzt auf den grünen Pfeil klickt, startet das Projekt auch schon im Qt Simulator:

“Hello World!”, na klar! Somit habt ihr schon ein lauffähiges Projekt, das ihr jetzt sofort für Maemo und Symbian kompilieren könntet. Vorher wollen wir das Projektgerüst aber noch etwas aufpimpen, damit die Anwendung später sowohl unter Symbian als auch unter Maemo gut aussieht. Außerdem soll ja auch der Portraitmodus unterstützt werden.

Erweiteres Programmgerüst

Wie wir gesehen haben lässt sich mit dem Qt SDK sehr einfach ein Hallo-Welt-Programm erstellen, MADDE und der Qt Creator legen dazu alle nötigen Dateien für uns an. Um das Programm aber allgemein einsetzbar zu machen, sowohl unter Symbian als auch unter Maemo, fehlen noch ein paar Zutaten. Das folgende Programmgerüst hilft da ein gutes Stück weiter. Zunächst präsentiere ich euch den Quellcode, den ich dann Stück für Stück erläutere.

Quellcode

Das gesamte Paket könnt ihr euch auch hier herunterladen. Entpackt einfach das Archiv und öffnet aus dem Ordner mobileqt die Datei qtprog.pro im Qt Creator.

Die Hauptklasse der Anwendung befindet sich in der Datei mainwindow.cpp und heißt MainWindow. Ein zweite Klasse namens PLLayout ist für das flexible Layout zuständig. Diese Klasse stammt aus einem Wiki-Eintrag im Forum Nokia. Ich werde sie in diesem Tutorial nicht näher erläutern, wir verwenden sie einfach so, wie sie von Nokia zur Verfügung gestellt wird.

Der Kontruktor: MainWindow::MainWindow()

Der Konstruktor unserer MainWindow-Klasse macht in diesem Fall eigentlich nichts anderes, als eine Reihe von Klassenfunktionen aufzurufen. Am Ende gibt es dann die #ifdef-Verzweigung: unter Maemo muss das Flag Qt::WA_Maemo5AutoOrientation für die Unterstützung des automatischen Rotierens gesetzt werden, damit der entsprechende Sensor aktiviert wird.

Die Menüleiste: createMenu()

Auch diese Funktion ist recht übersichtlich. Es wird nur ein Objekt der Klasse QMenuBar angelegt. Die Menüleiste gehört automatisch zum Hauptfenster, da beim Erstellen das aktuelle Objekt (also das Hauptfenster) per this als Elternobjekt an die Menüleiste übergeben wird. Dann wird dem Menü eine QAction hinzugefügt, der wir den Namen “Open” geben. Der eigentlich Text, der später im Menü erscheinen soll, wird in der Funktion retranslateUi gesetzt; dazu weiter unten mehr. Wenn man mehr Menüeinträge wünscht muss man ensprechend mehrere QActions anlegen und dem Menü per addAction zuweisen

Inhaltliches: createComponents()

In der Funktion createComponents werden alle Komponenten des Hauptfensters erstellt. Dazu gehören Text- und Eingabefelder, Buttons, usw. In unserem Fall enthält das Fenster nur einen QTextBrowser, und dieser wiederum den Text “Hallo Welt”.

Wer sich schon ein bisschen im SDK und Qt Creator umgeschaut hat, der wird natürlich gleich fragen: und was ist mit dem Qt Designer? Wird die GUI nicht am Besten damit erstellt? Nun, für Desktop-Anwendungen gibt es tatsächlich nichts Besseres. Leider gibt es im Moment aber keine Möglichkeit, eine mobile Anwendung vernünftig für den Landscape- und Portraitmodus zu entwickeln, wenn man den Qt Designer benutzt. Man hätte in diesem Fall immer nur ein einziges Layout für die Anwendung. Deswegen fällt er in unserem Fall als Entwicklungswerkzeug weg, der mobile Qt-Entwickler baut sich die Oberfläche manuell zusammen.

Verbindungen schaffen: createConnects()

Der Programmablauf wird unter Qt vor allem durch das Signal-Slot-Konzept gesteuert. Dabei kommunizieren Objekte untereinander, indem sie Signale aussenden. Jedes Objekt, das einen entsprechenden Slot für das Signal hat, kann dieses weiterverarbeiten. In unserem Fall haben wir erst einmal nur ein Signal verknüpft, das durch ein Klick auf die Aktion “Open” im Menü ausgesendet wird. Das entsprechende Signal heißt triggered(), und wir verknüpfen es mit dem Slot unseres Hauptfenster openFile(). Bei Slots handelt es sich im Prinzip um ganz normale C++-Funktionen, die aber im Header mainwindow.h als Slots gekennzeichnet werden müssen.

Zwei Layouts für die Rotation: createPortraitLayout() und createLandscapeLayout()

Diese beiden Funktionen erstellen nun die Oberfläche einmal für das horizontale, und einmal für das vertikale GUI. Wichtig ist, dass ihr immer alle Komponenten aus createComponents() in beide Layouts einbaut. Sonst kann es schnell zu Fehlern kommen, die äußerst schwer zu finden sind. In unserem Fall ist das leicht, weil wir bisher nur eine Komponente definiert haben, nämlich den Textbrowser.

Damit’s automatisch rotiert: createAutoLayout(), selfAssignLayout() und resizeEvent()

In createAutoLayout() werden nun die beiden Layouts verknüpft, und zwar durch eine eigene Klasse PLLayout(). Bei dieser Klasse handelt es sich um eine Hilfsklasse für die Symbian-Autorotation, die im Wiki von Forum Nokia veröffentlicht wurde. Die Klasse funktioniert aber auch tadellos unter Maemo.

Für was brauchen wir aber diese Klasse? Nun, im Prinzip ist die Anwendung auch ohne diese Hilfsklasse für die Autorotation vorbereitet. Unter Symbian je nach systemweiter Einstellung der Sensoren, unter Maemo, indem man einfach das Attribut Qt::WA_Maemo5AutoOrientation setzt (s. oben, “Der Konstruktor”). Qt versucht dann selbstständig, alle Komponenten möglichst sinnvoll in den beiden Ausrichtungen anzuordnen. Das funktioniert bei sehr einfachen Layouts auch einwandfrei, wenn nur wenige Komponenten vorhanden sind. Recht schnell stößt dieser Automatismus aber an seine Grenzen. Die Klasse PLLayout erlaubt es uns, dedizierte Layouts für beide Ausrichtungen zu definieren. Damit können wir das Layout flexibel an unsere Bedürfnisse anpassen, in den meisten Fällen entsteht so überhaupt erst eine bedienbare Oberfläche für beide Ausrichtungen.

Als nächstes weist die Funktion selfAssignLayout() unserem Hauptfenster ein zentrales Widget zu, das das dynamische Layout erhält. In Qt können wir Layouts nicht direkt dem Hauptfenster zuweisen, stattdessen muss immer ein Widget als “zentrales Widget” definiert sein. Nur Widgts können per setLayout() ein Layout erhalten.

Ganz am Ende unserer MainWindow-Klasse wird schließlich noch der resizeEvent-Event-Handler für Ereignisse überschrieben, die eine Größenänderung des Fensters betreffen. Dazu gehört eine Änderung des Seitenverhältnis, wie bei der Drehung des Bildschirminhalts. Dieses Ereignis reichen wir weiter an unser automatisches Layout (die Klasse PLLayout), dass dann die richtige GUI aktiviert. Anschließend rufen wir noch den Standard-Event-Handler der MainWindow-Elternklasse auf, auf Symbian muss das Fenster noch einmal maximiert werden, und: fertig!

Lokalisierte Strings: retranslateUi() und changeEvent()

Die mit createComponents() und createMenu() erstellten Komponenten und Menüeinträge sind noch ohne Aufschriften. Diese fügt nun die Funktion retranslateUi() ein. Damit haben wir zum einen alle Strings an einer Stelle versammelt, zum anderen können wir die Oberfläche auch dynamisch übersetzen. Für den zugegebeneraßen seltenen Fall, dass der Benutzer die Oberflächensprache des Betriebssystems ändert, während die Anwendung läuft. Bei Bedarf können wir so aber später schnell einen eigenen Konfigurationsdialog erstellen, der die Oberflächensprache unserer Anwendung ändert.

Für Letzteres überschreiben wir den changeEvent-Event-Handler. Falls es sich um einen QEvent::LanguageChange-Event handelt, dann rufen wir die Funktion retranslateUi() auf.

Prinzipiell sollten alle (sichtbaren) Strings in Qt durch die Funktion tr() umschlossen werden. Diese Funktion sucht sich entsprechende Übersetzungen aus den Qt-System- und Anwendungsübersetzungsdateien heraus. Zur Erstellung und Verwaltung von Übersetzungen gibt es den Qt Linguist, sowie die Tools lupdate und lrelease (näheres in der Qt-Dokumentation).

PLLayout zur MADDE-Basis hinzufügen

Ihr könnt euch wie gesagt einfach das oben verlinkte Beispielprojekt herunterladen, und auf Basis dieses Projekts weiter entwickeln. So könnt ihr einfach schon ein paar Sachen ausprobieren. Schwierig wird es z.B. aber dann, wenn ihr den Namen der Anwendung ändern wollt. Ihr müsst dann alle möglchen Dateinamen und -inhalte ändern, und jeweils “mobileqt” in den gewünschten Namen ändern. Einfacher ist es in diesem Fall dem MADDE-Gründgerüst, das wir unter “Projekterstellung” erstellt haben, die Klasse PLLayout hinzuzufügen und die mainwindow.cpp und mainwindow.h entsprechend abzuändern. Dazu genügen folgende Schritte:

  • Ihr habt also das MADDE-Gründgerüst. Kopiert als erstes die Dateien mainwindow.cpp, mainwindow.h, PLLayout.cpp und PLLayout.h in den Ordner src des MADDE-Projekts. Die vorhandenen mainwindow-Dateien könnt ihr getrost überschreiben.
  • Öffnet jetzt das Projekt im Qt Creator. Im Projektbaum oben links gibt es eine Datei qtprog.pro, die Verwaltungsdatei des Projekts. Öffnet diese per Doppelklick. Ersetzt die beiden Zeilen mit HEADERS und SOURCES am Anfang durch folgende Zeilen:
HEADERS     += \ 
    src/mainwindow.h \
    src/PLLayout.h
SOURCES     +=  qtmain.cpp \
    src/mainwindow.cpp \
    src/PLLayout.cpp

Damit fügt ihr dem Projekt die beiden Klassen MainWindow und PLLayout hinzu, samt den Header-Dateien. Wenn ihr jetzt die Datei speichert, dann erscheinen die entsprechenden Dateien auch sofort im Projektbaum des Qt Creator oben links:

  • Als letztes müsst ihr nur noch den Inhalt der qtmain.cpp anpassen, damit auch die MainWindow-Klasse für die Anwendung verwendet wird. Klickt im Qt Creator doppelt auf qtmain.cpp, um die Datei zu öffnen. Ersetzt dann einfach den gesamten Inhalt der Datei mit folgendem Code:
#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
#ifdef Q_OS_SYMBIAN
    w.showMaximized();
#else
    w.show();
#endif
    return a.exec();
}

Damit erhält die Anwendung unsere Klasse als Hauptfenster, auf Symbian-Betriebssystemen wird dieses per showMaximized() statt show() angezeigt.

Jetzt könnt ihr das Projekt wieder mit dem grünen Pfeil unten links starten. Und wieder: “Hallo Welt!”:

Was jetzt noch fehlt ist natürlich die Programmlogik. Diese werden wir in den nachfolgenden Kapiteln Schritt für Schritt implementieren.