\
KDE ist ein sich sehr rasant entwickelndes Projekt, das den Versuch unternimmt, eine einheitliche Oberfläche mit vielen Applikationen auf möglichst vielen Unix-Systemen zur Verfügung zu stellen. Der Vortrag gibt einen Einblick in die Programmierung von Applikationen mit den von KDE bereitgestellten Bibliotheken und erläutert die Grundlagen der graphischen Bibliothek Qt, die als Grundlage des KDE-Projektes dient.
KDE (K Desktop Environment) ist ein Projekt, das es sich als Ziel gesetzt hat, eine einheitliche grafische Benutzeroberfläche für alle Applikationen zur Verfügung zu stellen, die auf möglichst vielen UNIX-Plattformen läuft. Es soll dadurch eine benutzerfreundliche, intuitive Bedienbarkeit erreicht werden.
Die wichtigesten Programme des KDE-Projektes sind:
...und viele andere mehr. Fast täglich erscheinen neue Applikationen für das KDE-Projekt im Internet. Nahezu alle bisher im KDE-Projekt veröffentlichten Applikationen sind unter der General Public Licence (GPL bzw. LGPL) veröffentlicht, daher sind Programme und Quellcodes frei verfügbar.
Die Grundlage für die grafische Benutzeroberfläche für KDE-Programme ist die Bibliothek Qt der Firma Troll-Tech in Norwegen. Qt stellt eine sehr komfortable und mächtige Schnittstelle zur XLib dar und enthält eine große Anzahl an vordefinierten Widgets (Elemente für ein grafisches User-Interface) wie z.B. Buttons, Input-Felder, Menüs, Combo-Boxen, Schieberegler, Tabellen und vieles andere mehr. Außerdem enthält es eine Reihe von sehr nützlichen C++-Klassen und Templates, die einem Programmierer das Leben erleichtern, z.B. Strings, dynamische Arrays, Listen, Hash-Tabellen.
Qt ist ein kommerzielles Produkt, Lizenzen verkauft die Firma Troll Tech auf Developer-Basis: Für $1200 kann ein Programmierer eine Lizenz für UNIX-Systeme erhalten, und darf dann alle von ihm mit Qt entwickelten Programme verkaufen, ohne dass weiter Lizenzgebühren fällig werden. Er darf dabei sowohl statisch als auch dynamisch gelinkte Programme vertreiben. Speziell für den Free Software-Bereich bietet Troll Tech aber auch die Qt Free Edition an: Man kann das vollwertige Qt kostenlos als Binaries für verschiedenen Unix-Plattformen oder als Quelltext(!) bei Troll Tech downloaden und benutzen, mit zwei Einschränkungen:
Qt ist also keine freie Software, darf aber zur Entwicklung von freier Software kostenlos genutzt werden. Die genauen Lizenzbedingungen, die sehr ausführliche und übersichtliche Dokumentation sowie ein Tutorial für Einsteiger sind unter http://www.troll.no/ erhältlich. Unter dieser URL ist auch ein Download der Qt Free Edition möglich.
Als KDE-Programmierer sollte man sich also in folgende Dinge einarbeiten:
Kenntnisse über den Aufbau und die Funktionsweise von X-Servern und der XLib sind nicht nötig, können aber vielleicht manchmal hilfreich sein. Kenntnisse über Makefiles sind oft nützlich.
Für Ihre eigenen Versuche benötigen Sie das Paket Qt (zur Zeit in der Version 1.33) in der Developers-Version (!), sowie mindestens die KDE-Pakete kdebase, kdelibs, kdesupport und kdesdk (zur Zeit in der Version Beta-4). Diese finden Sie zum Beispiel auch auf der CD zum Linuxtag 1998.
Folgendes Programm stellt wahrscheinlich gleichzeitig eines der kürzesten KDE-Programme und eines der komfortabelsten ``Hello, World''-Programme dar.
1. // khelloworld.cpp 2. 3. // Hello World for KDE 4. // by Burkhard Lehner <b_lehner@informatik.uni-kl.de> 5. 6. #include <kapp.h> 7. #include <kmenubar.h> 8. #include <ktopwidget.h> 9. #include <qlabel.h> 10. #include <qkeycode.h> 11. 12. int main (int argc, char **argv) { 13. 14. const char *aboutText = "KDE Hello World\nby Burkhard Lehner"; 15. 16. KApplication a (argc, argv); 17. KTopLevelWidget top; 18. 19. QPopupMenu *filePopup = new QPopupMenu (); 20. filePopup->insertItem (i18n ("&Quit"), &a, SLOT (quit ()), CTRL + Key_Q); 21. 22. KMenuBar *menu = new KMenuBar (&top); 23. menu->insertItem (i18n ("&File"), filePopup); 24. menu->insertSeparator (); 25. menu->insertItem (i18n ("&Help"), a.getHelpMenu (TRUE, aboutText)); 26. 27. top.setMenu (menu); 28. 29. QLabel *text = new QLabel (i18n ("Hello, World"), &top); 30. text->setAlignment (AlignCenter); 31. text->setFont (QFont ("charter", 64, QFont::Bold, TRUE)); 32. text->setMinimumSize (text->sizeHint ()); 33. top.setView (text); 34. 35. top.show (); 36. return a.exec (); 37. }
Kurze Erläuterung zum Quellcode:
Hier eine kleine Auswahl der wichtigsten Klassen und Templates:
Allgemeine Klassen / Templates:
Klassen für GUI-Elemente:
Callback-Routinen sind Funktionen oder Methoden, die ausgeführt werden sollen, sobald ein Widget einer Interaktion des Benutzers unterliegt, z.B. wenn ein Button gedrückt wird, ein Menüpunkt ausgewählt oder ein Scrollbar verschoben wird.
Callback-Routinen in Qt werden durch das sehr mächtige Signal-/Slot-Konzept realisiert. Dazu sind in den Klassendefinitionen der Qt-Klassen zusätzliche Methoden als signal oder slot deklariert. Diese Methoden können beliebige Parameteranzahlen und Typen haben, der Rückgabewert muss aber in jedem Fall void sein. Verwechseln Sie nicht Signal-Methoden von Qt mit Signalen des UNIX-Kernels, wie z.B. SIGTERM oder SIGKILL. Diese beiden Dinge haben nichts miteinander zu tun. Damit eine Klasse Signal- und Slot-Methoden benutzen kann, muss sie von der Klasse QObject abgeleitet sein. (Das sind z.B. alle GUI-Widgets, da sie von QWidget abgeleitet sind, welches seinerseits von QObject abgeleitet ist.)
Die Slot-Methoden sind Methoden, die eine Aktion als Folge einer Interaktion ausführen sollen. Sie müssen vom Programmierer mit Code gefüllt werden. Sie können weiterhin als private, protected oder public deklariert werden, ganz analog zu anderen Methoden, und können auch wie ganz normale Methoden aufgerufen werden.
Signal-Methoden werden vom Programmierer nur deklariert, jedoch nicht mit Code gefüllt. Der Code für die Methode wird vom Meta-Object-Compiler (moc) generiert und nachher zum Programm hinzugelinkt. Signal-Methoden werden innerhalb der Klasse aufgerufen, um anzuzeigen, dass eine Interaktion erfolgt ist, die eventuell eine Reaktion hervorrufen soll. Signal-Methoden führen keine Aktionen aus, sondern rufen nur Slot-Methoden auf, mit denen sie verbunden sind.
Um ein Signal mit einem Slot zu verbinden, benutzt man die Methode connect. Die einfachste Form der connect-Methode hat folgende Gestalt:
bool QObject::connect (const QObject * sender, const char * signal, const QObject * receiver, const char * member)
Die Parameter sind dabei:
Die Signal- und die Slot-Methode müssen in Parameteranzahl und -typen übereinstimmen.
Ein einfaches Beispiel soll zunächst erläutern, wie Signals und Slots verbunden werden:
QScrollBar *scroll = new QScrollBar; QLabel *label = new QLabel; QObject::connect(scroll, SIGNAL(valueChanged(int)), label, SLOT(setNum(int)));
Die Klasse QScrollBar enthält eine Signal-Methode void valueChanged (int), die aufgerufen wird, sobald die Position des Scrollbars sich geändert hat. Die Klasse QLabel besitzt eine Slot-Methode void setNum (int), mit der man den Labeltext auf eine Zahl setzen kann.
Durch den Aufruf der Methode connect werden diese nun verbunden. Die Makros SIGNAL und SLOT übernehmen dabei die Umsetzung der Methodennamen in korrekte Zeichenstrings und müssen in der Methode connect immer benutzt werden. Nachdem Signal und Slot miteinander verbunden sind, führt jede Veränderung der Scrollbarposition durch den Benutzer zu einem Aufruf des Signals valueChanged, das alle damit verbundenen Slots aufruft, in diesem Fall also setNum, wodurch sich der Wert im Label ändert.
Ein Signal kann mit einer beliebigen Anzahl von Slots verbunden sein. Insbesondere kann sein Signal auch unverbunden bleiben. Verbindungen können mit der Methode disconnect wieder gelöst werden. Qt übernimmt das Lösen von Verbindungen automatisch im Destruktor von QObject, so dass ein Programmabsturz aufgrund eines Aufrufs einer nicht mehr vorhandenen Slot-Methode ausgeschlossen ist.
Hier nun ein Beispiel einer selbstdefinierten Klasse, die einen Slot definiert:
class myObject : QObject { Q_OBJECT // Dieses Makro definiert Signals und Slots public: myObject (QObject * parent=0, const char * name=0); ~myObject (); public slots: void printMessage () {printf ("Knopf gedrückt!\n");} }
Ist diese Klassendeklaration z.B. in der Datei myObject.h enthalten, so ist anschließend der Meta Object Compiler für dieses Header-File aufzurufen:
% moc myObject.h -o m_myObject.cpp
Dieser Aufruf erzeugt eine Datei m_myObject.cpp, die anschließend noch compiliert und zur ausführbaren Datei hinzugelinkt werden muss. (Alternativ kann man auch in der Datei, in der die Methoden der Klasse definiert sind, eine Zeile einfügen.)
Eine Verbindung sieht dann z.B. so aus:
QPushButton *button; myObject *obj; QObject::connect (button, SIGNAL (clicked ()), obj, SLOT (printMessage ()));
Anschließend wird bei jedem Druck auf die Taste der Text ``Knopf gedrückt'' ausgegeben.
Neben den Klassen, die Qt dem Programmierer zur Verfügung stellt, enthält auch das KDE-Paket eine Reihe von Klassen, von denen hier einige stichwortartig vorgestellt werden sollen:
Nicht-grafische Klassen (KDE-core):
Jeder, der schon einmal eine KDE-Applikation compiliert hat, kennt den Dreisatz:
% ./configure % make % make install
Der Aufruf des Shell-Skripts configure bestimmt die compilerrelevanten Daten des Systems, wie z.B. den Compiler, die KDE- und Qt-Pfade. Anschließend werden mit diesen Daten aus den Dateien Makefile.in die Dateien Makefile in allen Unterverzeichnissen der Applikation erstellt. Der Aufruf von make compiliert nun alle Source-Dateien und linkt sie zur einer ausführbaren Datei zusammen. make install kopiert schließlich alle Dateien an die richtige Stelle in der Verzeichnisstruktur.
Will man als Programmierer ebenfalls diese Methode übernehmen (was sehr anzuraten ist!), so lädt man sich am besten das Paket kdesdk (KDE Software Development Kit) vom KDE-FTP-Server und kopiert die darin enthaltene Beispielapplikation khexdit in ein eigenes Verzeichnis. Weiterhin ist es empfehlenswert, sich automake und autoconf von GNU zu installieren. In das Verzeichnis khexdit (das man am besten an den Namen seiner Applikation anpasst) kopiert man nun die eigenen Sourcedateien. Anschließend passt man in allen Unterverzeichnissen die Dateien Makefile.am an sowie die Datei configure.in im Hauptverzeichnis (hier wird angenommen, dass Ihre Applikation den Namen kapplication hat):
Anschließend können Sie make -f Makefile.dist aufrufen. Dadurch wird das Skript configure aus der Datei configure.in erzeugt.
Nun sollten Sie noch drei Dateien erzeugen im Verzeichnis ./kapplication:
Die kdelnk-Datei können Sie leicht aus dem Beispiel in kexample ableiten.
Danach können Sie mit ./configure, make und make install testen, ob das Compilieren und Installieren funktioniert. Eventuell brauchen Sie für das make install Superuser-Rechte.
Wenn Ihre Applikation soweit lauffähig ist und Sie sie der Welt präsentieren möchten, so können Sie ganz einfach ein Source-Paket im .tar.gz-Format erzeugen lassen, indem Sie im Hauptverzeichnis Ihrer Applikation make dist eingeben. Es wird dann das File kapplication-version.tar.gz erzeugt. Sie sollten jedoch vor der Weitergabe einmal testen, ob in dem Archiv auch alle benötigten Dateien enthalten sind. Sollten einige Dateien fehlen (häufig zum Beispiel Header-Dateien), so fügen Sie diese im File ./kapplication/Makefile.am in noinst_HEADERS ein.
KDE bietet eine komfortable Methode für Programmierer, die Programme in vielen verschiedenen Sprachen verfügbar zu machen. Die zentrale Rolle übernimmt dabei das Makro i18n, das bereits im ``Hello, World''-Programm in Kapitel 2 verwendet wurde. Wenn sie das configure-Skript aus Kapitel 4.2 benutzen, wird ihnen nochmals viel Verwaltungsarbeit abgenommen.
Gehen Sie folgendermaßen vor, um Ihr Programm zu internationalisieren:
vorher: | printf ("Result of calculation: %d\n", res); |
nachher: | printf (i18n ("Result of calculation:%d\n"), res); |
Die Namen von Einträgen und Gruppen in Konfigurationsdateien sollten nicht übersetzt werden, da es sonst Probleme beim Einlesen der Konfigurationsdateien gibt, falls die Landessprache gewechselt wird.
$(XGETTEXT) -C -ktranslate $(khexdit_SOURCES)
um in:
$(XGETTEXT) -C -ki18n $(khexdit_SOURCES)
Am Zeilenanfang muss ein Tabulator stehen!
# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Free Software Foundation, Inc. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 1998-05-18 21:49+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" #: khelloworld.cpp:18 msgid "&Quit" msgstr "" #: khelloworld.cpp:21 msgid "&File" msgstr "" #: khelloworld.cpp:23 msgid "&Help" msgstr "" #: khelloworld.cpp:27 msgid "Hello, World" msgstr ""
Tragen Sie zunächst im oberen Teil die Informationen zum Programm ein. Anschließend schreiben Sie zwischen die Anführungsstriche hinter einem msgstr-Eintrag die Übersetzung des vorangegangenen msgid-Eintrags. Achten Sie dabei darauf, dass Sie das Format möglichst genau beibehalten. Im Beispiel von oben sähe eine Übersetzung dann z.B. so aus:
msgid "Result of calculation: %d\n" msgstr "Ergebnis der Berechnung: %d\n"
Einträge mit der Ergänzung #, fuzzy (außer dem Header-Eintrag) sind neu hinzugekommene Texte. Es wurde dabei versucht, die Übersetzung aus einem älteren Übersetzungstext zu erraten, was jedoch oftmals nicht ganz richtig ist. Wenn Sie auf einen solchen Eintrag stoßen, so korrigieren Sie evtl. den Eintrag in msgstr und löschen Sie die Zeile #, fuzzy. (Aber nicht im Header der .po-Datei!)
Da nicht jeder Programmierer 20 oder mehr Sprachen sprechen kann, gibt es im KDE-Projekt ein Übersetzungsteam. Um davon Gebrauch zu machen, schicken Sie einfach Ihr messages.po-File an Pedro Morais <pmmm@camoes.rnl.ist.utl.pt>. Sie werden dann nach und nach die übersetzten Versionen erhalten, die Sie zu Ihrem Programm hinzufügen können.
Bei weiteren Fragen zum Thema Internationalisation (i18n), lesen Sie eine ausführlichere Anleitung unter http://www.kde.org/i18n.html, oder wenden Sie sich an die kde-i18n Mailing-Liste (kde-i18n@kde.org, vorübergehend auch kde-i18n-doc@kde.org).
KDE allgemein: | http://www.kde.org/ |
KDE Developers Center: | http://www.ph.unimelb.edu.au/~ssk/kde/devel/ |
KDE i18n: | http://www.kde.org/i18n.html |
KDE Standards: | http://www.kde.org/standards.html |
Qt: | http://www.troll.no/ |
KDE: | ftp://ftp.kde.org/ |
KDE-upload: | ftp://upload.kde.org/ |
kde: | Allgemeines Diskussionsforum |
kde-announce: | Ankündigungen neuer Versionen und Applikationen |
kde-user: | Hilfestellungen für Anwender |
kde-devel: | Hilfestellungen für Programmierer (post-Rechte müssen erst |
beantragt werden bei Martin Konold <konold@kde.org>) | |
kde-licensing: | Diskussion über rechtliche Lizenz-Fragen |
kde-look: | Diskussionen über die äußere Gestalt von KDE |
Nähere Informationen zum Subscriben in den Listen finden Sie unter http://www.kde.org/contact.html. Alte Artikel finden Sie im Archiv unter http://lists.kde.org/.