Wie versprochen eine kurze Erklärung, wie man die Konfiguration ohne KConfigXT verwalten kann.Die zentrale Funktionalität befindet sich in der Klasse
ConfigurationWidgetMixin. Eine Anwendung des Mixins findet sich in
TouchpadManagementWidget. Die Konfiguration wird in dieser Anwendung in Objekten abgelegt, die dieselbe Schnittstelle haben wie "dict()" (auf Basis von "collections.MutableMapping").
Letztlich muss ConfigurationWidgetMixin nun nur zwei Dinge tun. Zuerst wäre da das Laden der Konfiguration in die Steuerelemente und umgekehrt. Das geschieht in ".load_configuration()" und ".apply_configuration()". Erstere muss dann bei der Anzeige des Dialogs aufgerufen werden, zweitere dient als Slot für den "Anwenden"-Knopf des Dialogs. Diese sind im Konfigurationsfenster nicht enthalten, damit es auch an Stellen genutzt werden kann, an dem diese Knöpfe von außen vorgegeben werden (prominentes Beispiel sind Module für die Systemeinstellungen von KDE).
In diesen Methoden wird zuerst "._find_configuration_widgets()" aufgerufen, um alle Steuerelemente zu finden, die einem Konfigurationsschlüssel zugeordnet sind. Diese Zuordnung wird genau wie in KConfigXT über ein bestimmtes Präfix im Objektnamen hergestellt, wobei der Name minus Präfix dann auch gleich der Konfigurationsschlüssel ist. Anschließend muss der Inhalt dieser Steuerelemente nun mit dem Inhalt des Konfigurationsobjekts aktualisiert werden.
Der Inhalt von Steuerelementen kann man über die Qt-Eigenschaften der Objekte setzen., allerdings stellt sich die Frage, welche Eigenschaft den Inhalt eines Steuerelements enthält, schließlich ist das je nach Steuerelement eine andere (bei Checkboxen beispielsweise "toggled", bei Eingabefeldern dagegen "text"). Man könnte einfach die "user property" heranziehen, die ist dafür eigentlich da, wenn denn alle KDE-Steuerelemente auch eine solche hätten. Natürlich ist das nicht der Fall, also behelfe ich mir mit einer manuellen Abbildung von Klassennamen auf den Namen derjenigen Eigenschaft, welche den Inhalt des Steuerelements trägt (siehe z.B. "TouchpadManagementWidget"). Damit erhält man dann die Eigenschaft, die man setzen muss, um den Inhalt des Steuerelements zu ändern. Dieser Eigenschaft muss ich dann nur den entsprechenden Wert aus dem Konfigurationsobjekt zuweisen, und dabei natürlich zwischen Python- und Qt-Typ konvertieren.
Das Speichern der Konfiguration verläuft nahezu identisch, nur dass eben die Eigenschaft ausgelesen und in einem "dict()" gespeichert wird (siehe "apply_configuration()").
Die zweite Sache, die man bewerkstelligen muss, ist sich zu merken, welche Steuerelemente aktualisiert wurden, und ein Signal auslösen, wenn das der Fall ist. Dazu verbindet man beim Erzeugen des Steuerelements (siehe "._setup()") einfach die Signale der Steuerelemente, die diese auslösen, wenn sich ihr Inhalt ändert, mit einem Slot, der Buch über diejenigen Steuerelemente führt, deren Inhalt vom Inhalt des Konfigurationsobjekts abweicht. Auch hier ist das größte Problem wieder, das richtige Signal für ein Steuerelement zu finden. Man könnte einfach das "notify"-Signal der "user property" heranziehen, aber es gilt wieder das oben gesagte über "user properties", und somit ist die Lösung wieder eine manuelle Abbildung, um das richtige Signal zu finden. Der Slot für diese Änderungssignale ist "._check_for_changes()". Dieser Slot prüft einfach nur, ob der neue Wert des Steuerelements dem Wert in der Konfiguration gleicht. Falls nein, dann wird das Steuerelement zur Liste der geänderten Steuerelemente hinzugefügt, andernfalls entfernt. Ist diese Liste leer, so zeigen alle Steuerelemente den Inhalt der Konfiguration an, und wurden nicht verändert. Zum Schluss löst der Slot noch ein Signal aus, welches dem Dialog dann dazu dient, den "Anwenden"-Knopf entsprechend zu aktivieren oder zu deaktivieren.
Diese Implementierung ist aufgrund der beschriebenen Workarounds für Bugs in KDE und aufgrund der Tatsache, dass sie gegen Version 1 der QVariant-API geschrieben wurde, ein bisschen aufwendiger als nötig.
Der Vorteil dieses Ansatzes ist wie gesagt, dass er auch in reinen Qt-Anwendungen ohne KDE-Abhängigkeiten funktioniert, und das man nicht nur Konfigurationsdaten, sondern eigentlich jedes beliebige Objekt, welches die "Mapping"-Schnittstelle implementiert, so verwalten kann. Die Anwendung macht davon auch Gebrauch, den beide Konfigurationsklassen repräsentieren eigentlich nicht direkt Konfigurationsdateien, sondern vielmehr die aktuellen Zustand bestimmter Objekte. Das ist in dieser Anwendung deswegen nötig, weil der Zustand dieser Objekte bei laufender Anwendung von außen geändert werden kann.
Sollten noch Fragen zum Quelltext bestehen, oder Bedarf nach noch detaillierten Erklärungen, so möge man sich melden.