Das Komponentenmodell


... [ Seminar Linux und Apache ] ... [ Thema Komponentenmodell von KDE 2 ] ... [ Qt ] ...

Übersicht: Das Komponentenmodell


Warum ein Komponentenmodell ?

Die grundlegende Idee einer Komponente ist, die Funktionalität der Komponente einer breite Anzahl von Applikationen bereitzustellen, d.h. es muß möglich sein, sie in den verschiedensten Applikationen wiederzuverwenden.
Ein Mail-Programm kann z.B. einen Text-Editor einbinden und muß somit nicht die Funktionen des Editor (copy and paste, Rechtschreibprüfung usw.) selber implementieren.

Eine einfache Methode dieses Ziel der Wiederverwendbarkeit zu erreichen, ist der Einsatz von shared libraries die alle Applikationen gemeinsam benutzen. Aber ohne einen vorhandenen, einheitlichen Rahmen ist die Umsetzung dieses Gedanken mit Hindernissen verbunden.
Da die Applikation sehr eng an die API (Application Programming Interface ) der Library gebunden sind, wäre beim Austausch der Library einer einzelnen Applikation das Chaos vorprogrammiert. Es müßten Änderungen an vielen weiteren Applikationen (die diese wiederverwenden) vorgenommen werden, um diese an die neue Library anzupassen. Außerdem muß die Integration der wiederverwendeten Funktionen in jeder Applikation per Hand vorgenommen werden.

Die Lösung für die beschriebenen Probleme ist ein einheitlicher Rahmen (Framework), in das sich alle Applikationen einfügen lassen. Hierbei sind die Schnittstellen genauestens festgelegt, so das Implementationen von Komponenten komplett ausgetauscht werden können, ohne das Änderungen an weiteren Applikationen vorgenommen werden müssen, da die Schnittstellen identisch bleiben.
Ebenso ist es jetzt möglich Komponenten in Applikationen einzufügen, von denen die Applikationen selber noch nie gehört haben, bzw. für die sie nicht geschrieben worden sind. Applikation sowie Komponente wissen aufgrund des einheitlichen Rahmens genau, was sie vom anderen zu erwarten, bzw. was sie zu liefern haben.
Wer also gerne in sein Mail-Programm ein MP3-Player integriert haben möchte, wird hierbei auf keine Probleme stoßen.


Zusammenfassend sollte eine gute Komponenten-Technologie folgende Charakteristik haben:
  1. es ist einfach eine Applikation als Komponente zu verwenden
  2. es ist einfach eine Komponente in eine andere Applikation zu integrieren
  3. die Komponenten können schnell aktiviert werden (nach Möglichkeit sofort)

KDE Framework für Komponenten

Frameworks existieren für die verschiedensten Rechnerplatformen und Umgebungen, wie z.B. IBM und Apple's OpenDoc, Microsoft's OLE oder Gnome's Bonobo.
Das KDE-Projekt entschied sich für den Namen KParts.

KParts basiert auf Standard KDE/Qt Objekten wie QWidget und KTMainWindow und stellt eine kleine, einfache Menge von Klassen zur Verfügung: Neben diesen Basisklassen für die Entwicklung von Komponenten übernimmt das Framework weitere wichtige Aufgaben im Zusammenspiel der Komponenten/Applikationen einerseits und der Umwelt andererseits.
KDE versucht eine vollständige Netzwerk-Transparenz zu erreichen, d.h. es darf keine Rolle spielen, ob eine zu bearbeitende Datei auf dem eigenen Rechner, im lokalen Netz, oder sogar irgendwo im Internet liegt. Das Framework bietet hierfür Zugriffsmethoden für URLs.
Der Entwickler einer Komponente braucht sich um den Zugriff auf eine Datei keine Gedanken zu machen. Das Framework übernimmt bei entfernt liegenden Dateien alle nötigen Aufgaben, wie Download starten, überwachen und die Meldung wenn der Download beendet ist. Es wird eine lokale Kopie der Datei erzeugt mit der der Entwickler arbeiten kann. Auch bei Veränderungen an entfernt liegenden Dateien treten für den Entwickler keine Hürden auf, da der Upload der veränderten Dateien natürlich auch vom Framework organisiert wird.

Bestandteile einer Komponente

Eine KDE-Komponente, genannt Part, besteht aus folgenden Bestandteilen: Das Widget ist die graphische (sichtbare) Oberfläche der Komponente, es enthält z.B. Buttons, Lables, Textfields, usw.
Jede Aktion, jedes Ereignis (Funktionalität) das eine Komponente ausführen kann, wird weiterhin als C++ Code implementiert. Die Qt Bibliothek wird dabei als grundlegende Klassenbibliothek verwendet, sie enthält einerseits Klassen zur Erzeugung des Widgets und darin integriert Elemente, andererseits wird auch die Kommunikation zwischen Komponente und Applikation mit Hilfe der Qt Klassen gesteuert. Der genaue Ablauf wird im Kapitel Qt betrachtet.

Die KDE-Klassenbibliothek setzt auf der Qt-Bibliothek auf, sie stellt ebenfalls sichtbare Elemente (Buttons,..) zur Verfügung. Der Entwickler sollte, wenn möglich, die Elemente der KDE-Bibliothek verwenden, um ein einheitliches Bild (look and feel) aller KDE-Anwendungen zu erreichen.
Das Userinterface einer Komponente wird in einer XML-Datei beschrieben.

Userinterface (XML)

Die XML-Datei, die jede Komponente und jedes Mainwindow besitzen, beschreibt nur das Layout des Userinterface, es wird in ihr keine Aktion beschrieben. Es existiert also kein Ereigniscode.

Gekürzte XML-Datei aus dem KDE-Konqueror
	   1 
	   2 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
	   3 <kpartgui name="Konqueror" version="1">
	   4   <MenuBar>
	   5    <Menu name="file"><Text>&amp;File</Text>
	   6     <Action name="find"/>
	   7     <Separator/>
	   8     <Action name="close"/>
	   9    </Menu>
	  10    <Menu name="edit"><Text>&amp;Edit</Text>
	  11     <Action name="cut"/>
	  12     <Action name="copy"/>
	  13     <Separator/>
	  14     <Merge/>
	  15     <Separator/>
	  16    </Menu>
	  17    <Merge/>
	  18   </MenuBar>
	  19   <ToolBar fullWidth="true" name="mainToolBar"><Text>Main</Text>
	  20    <Action name="cut"/>
	  21    <Action name="copy"/>
	  22    <Separator/>
	  23    <Merge/>
	  24    <Separator/>
	  25    <Action name="animated_logo"/>
	  26   </ToolBar>
	  27   <ToolBar name="locationToolBar"><Text>Location</Text>
	  28    <Action name="toolbar_url_combo"/>
	  29   </ToolBar>
	  30 </kpartgui>
	  31 				
	

Die beiden top-level Elemente des XML-Baumes sind MenuBar und Toolbar.
In die nächsten Ebenen werden dann die einzelnen Menüpunkte, gefolgt von den Menüeinträgen angesiedelt. Bei den Menüeinträgen ist ein besonderer Augenmerk auf den Action-Name zu legen. Er muß identisch zu dem Namen der Methode sein, die in der Komponente den Funktionalitäts-Code enthält.

Für das Komponentenmodell ist der Merge-Tag von besonderer Bedeutung. Er markiert die Stelle an der das Userinterface der Komponente in das Userinterface der Applikation eingegliedert wird. Im Menüeintrag edit (Zeile 10) werden Einträge der Komponente zwischen 2 Seperator (Z. 13,15) eingegliedert, da dort der Merge-Tag (Z.14) angegeben wurde.
Für den Menüeintrag file (Z.5) wurde kein Merge-Tag angegeben, möchte die Komponente dieses Menü erweitern, werden die Einträge ans Ende des Menüs gestellt.
Für die Toolbar gilt das gleiche, ist ein Merge-Tag vorhanden, wird an dieser Position eingefügt, ansonsten werden die Einträge allerdings nicht drunter, sondern an der rechte Seite der Applikation-Toolbar positioniert.

Merge-Tag mit Namen
   1 
   2 <Merge name="MyPart"/>
   3 ....
   4 <Merge />
   5 

Es ist auch möglich dem Merge-Tag einen Namen zu geben, um so die Positionierung der Einträge nach genauer steuern zu können. Diese Möglichkeit wird verwendet, wenn mehr als eine Komponente in eine Applikation eingebunden werden soll und die Komponenteneinträge an verschiedenen Stellen innerhalb eines Menüeintrages stattfinden sollen.

KSycoca

KDE hat von Anfang an darauf gesetzt, sämtliche Konfigurationsdaten (siehe obige XML-Datei) in ASCII-Dateien zu halten, was zu einer hohen Systemsicherheit geführt hat, da man selbst nach dem schlimmsten Absturz solche Dateien gegebenenfalls mit einem Texteditor reparieren konnte.
Außerdem war es möglich, den Desktops mit Hilfe von Skriptsprachen zu steuern, was bei einem Mehrbenutzer-System, wie es UNIX zweifellos ist, den großen Vorteil bringt, Konfigurations-Änderungen für alle Benutzer einfach und schnell vornehmen zu können.
Mit dem ständigen Wachsen von KDE und immer mehr Konfigurationsmöglichkeiten wurden diese textuellen Konfigurationsdateien allerdings zu einem Flaschenhals, das Einlesen und Parsen dauerte immer länger, insbesondere beim Neustart des Desktops. Daher wurde mit KSycoca (KDE SYstem COnfiguration CAche) eine Lösung geschaffen, die die Vorteile von textuellen und binären Konfigurationsdateien verbindet.
KDE-Applikationen schreiben ihre Konfigurationsdateien weiterhin unverändert im bekannten textuellen Format, erfragen aber Konfigurationswerte nicht direkt aus den Konfigurationsdateien, sondern von KSycoca, einem im Hintergrund laufenden Programm, das eine ständig aktualisierte binäre Version der Konfigurationsdaten bereithält, auf die daher schnell zugegriffen werden kann.
KSycoca liest aber immer nur und schreibt nie Konfigurationsdateien, so daß nach einem eventuellen Systemabsturz weiterhin gegebenenfalls die Dateien von Hand mit einem Texteditor repariert werden können und dann von KSycoca neu geparst und in die interne Cache-Repräsentation überführt werden.

Integration einer Komponente

An einem kurzen Beispiel soll nun erläutert werden, wie die einzelnen Teile zusammenspielen und wie einfach es ist, mit Hilfe des Komponentenmodells, eine Komponente in einer Applikationen zu verwenden.

Integration von Ghostview in die Applikation ghostviewtest (Code ist nicht vollständig)
   1 
   2   Shell::Shell()
   3   {
   4     setXMLFile( "ghostviewtest.rc" );
   5     KAction * paQuit = new KAction( i18n( "&Quit" ), "exit", 0,
   6               this, SLOT( close() ), actionCollection(), "file_quit" );
   7 
   8     KLibFactory *factory = KLibLoader::self()->factory( "libkghostview" );
   9     if (factory) // Try to find libkghostview
  10     {
  11       m_gvpart = (KParts::ReadOnlyPart *)factory->create( this, "kgvpart",
  12                  "KParts::ReadOnlyPart" ); // Create the part
  13       setView( m_gvpart->widget() ); // Set the main widget
  14       createGUI( m_gvpart ); // Integrate its GUI
  15     }
  16     else
  17       kdFatal() << "No libkghostview found !" << endl;
  18   }
  19 			
  

Nachdem in Zeile 4 mit setXMLFile() das Userinterface der Applikation geladen worden ist, wird versucht die zu integrierende Library von ghostview (libkghostview) zu laden (Zeile 8).
Sollte das funktioniert haben (Z.9), wird eine Instanz von KParts (die Komponente) erzeugt (Z.11/12). Da nur eine Komponente integriert worden ist, wird deren widget als sichtbares Element der Applikation verwendet (Z.13).
createGUI (Z.14) übernimmt das Mergen. Die GUI der Komponente, also die beschreibende XML-Datei, wird in die geladene XML-Datei (Z.4) eingegliedert. Es entsteht ein XML-Baum der eine Kombination beider GUIs ist und das Layout des neuen vereinigten Userinterfaces beschreibt.

Nachdem Komponenten, wie oben gesehen, sehr einfach in Applikationen eingebettet werden können, ist die Kommunikation zwischen Komponente und Applikation, sowie die Kommunikation zwischen verschiedenen Applikationen über den Desktop interessant.
Die nächsten beiden Kapitel widmen sich dem Thema Kommunikation zwischen Komponente/Applikation (Qt) und Applikation/Applikation über den Desktop (DCOP).
... [ Seminar Linux und Apache] ... [ Thema Komponentenmodell von KDE 2 ] ... [ nach oben ] ... [ Qt ] ...