Datenbankfrontends mit Qt generieren

2010-01-24 17:28


Ich möchte mich in diesem Beitrag der Erstellung von Datenbank Frontends mit Qt widmen. Qt bietet mit QtSql einen Abstraktionslayer für Datenbankzugriff, welcher (fast) alle gängigen Datenbanken abdeckt. Es gibt auch andere Libraries die sich dies zum Ziel gesetzt haben, aber so fehlt z.B. SOCI bis heute die Unterstützung für MS SQL. Für ODBC böte sich die DTL als Alternative an. Jedoch bringt Qt noch etwas mit, was denen anderen fehlt: die Integration in eine Model/View Architektur, welche es relativ einfach macht, eine Tabelle als eine art Grid dem User zu Repräsentieren. Jede Zeile entspricht dann einem Datensatz. Dieser ist auch direkt bearbeitbar, so das je nach gewählter Strategie das Model entsprechend auch die Änderungen an die Datenbank weiterreicht.

Dies alles ist schon wunderbar, aber mir war dies nicht genug, Ich wollte mehr. Mir geht es darum, die Information die man aus der Datenbank bezieht, so auszuwerten, das man daraus ein Frontend nicht mehr von Hand erstellen muss, sondern dieses automatisch generiert wird. Denn schon länger beschäftige ich mich mit Codegenerierung und Codeanalyse, so entstand seit 2007 ein Framework für Codegenerierung in C++. Mein Ziel ist es nun also, aus den Typinformationen einer Tabelle ein Frontend zu generieren. Momentan geschieht dies mittels Auswertung von CREATE TABLE Statements, Fremdschlüssel werden dabei ebenfalls beachtet, so dass ein Frontend hier auch die richtigen Zuordnungen der Datensätze hinbekommt.

Am verständlichsten lässt sich dies alles wohl an einer kleinen Beispieldatenbank darstellen. Es gibt die 3 Tabellen Person, Animaltype und Animal. Wobei Person normale Personendaten wie Vorname, Nachname, Email, Geburtsdatum etc. enthält. Animaltype definiert einfach nur Tiere, eine Tabelle die nur aus einem ID Wert und einem Varchar pro Zeile bestehen könnte, jedoch wird hier auch noch ein Preis für diese Tierart festgelegt. Animals enthält dann eine Zuordnung nach Typ und Anzahl. Diese Datenbank ist nur ein Beispiel, daher habe ich auch nicht versucht, eine größere Logik in die Tabellen Beziehungen zu legen. Es könnte genauso gut eine Datenbank eines Bauernhofs sein, wie die eines Zoos oder einer Zoohandlung.

Im SQL sieht die Beispieldatenbank nun so aus:

CREATE TABLE IF NOT EXISTS person
(id INTEGER PRIMARY KEY autoincrement,
firstname VARCHAR(55),
lastname VARCHAR(55),
email VARCHAR(100),
birthdate DATE NOT NULL,
send_email BOOLEAN NOT NULL);

CREATE TABLE IF NOT EXISTS animaltype
(id INTEGER PRIMARY KEY autoincrement,
name VARCHAR(55),
price_per_animal DOUBLE);

CREATE TABLE IF NOT EXISTS animal
(id INTEGER PRIMARY KEY autoincrement,
animaltype_id INTEGER,
count INTEGER,
FOREIGN KEY ("animaltype_id") REFERENCES "animaltype" ("id"));


Wie ich bereits erwähnte, wird nun momentan für jede Tabelle eine Ansicht generiert, welche momentan einen QTableView enthält für die Darstellung der Tabelle selber, sowie einem QPushButton für das Erstellen eines neuen Datensatzes und einen weiteren Button für das Löschen ausgewählter Datensätze:

tl_files/codenode/sql2cpp/tbl_view.png

Zusätzlich zu einem View für jede Tabelle wird ein Dialog mit den Eingabemöglichkeiten für einen Datensatz generiert, welcher auch um Pflichtfelder und die Auswahl von Fremdschlüsseln ergänzt werden kann:

tl_files/codenode/sql2cpp/tbl_dlg.png

Dieses Frontend ist mit Hilfe meines Tools SQL2C++ generiert worden, es ist nicht nur eine Klasse für jeweils den View und den Dialog generiert, sondern auch jeweils ein eigenes UI File, so das man die Oberfläche relativ leicht anpassen kann. Eine Schwierigkeit bei der Generierung sind die Bezeichner und Beschriftungen, diese sind i.d.R. nicht in einer Datenbank enthalten, so das hier die Spaltennamen als Bezeichner dienen. Dies kann aber dank des UI Files relativ einfach angepasst werden. Auch wird das MainWindow der Anwendung zur Zeit nicht generiert, da es hier zu viele Möglichkeiten der Darstellung und Verwendung des Codes gibt. Der gesamte Aufwand für die Erstellung eines Datenbank Frontends lässt sich so erheblich reduzieren. Auch kann das Tool bereits Code für andere Libraries wie SOCI oder DTL generieren, es ist also auch möglich C++ Code zu generieren der nicht für die Benutzung in einem Frontend vorgesehen ist.

Ich plane die Generierung auch für weitere Sprachen, bin mir hier allerdings zur Zeit nicht sicher, was genau in welcher Richtung sinnvoll ist. Wenn sie Verwendung für einen Generator in XYZ haben, dann sprechen sie mich an, die Erstellung und Umsetzung eines Codegenerators kann ich dann gerne für sie übernehmen.
Kontaktieren sie mich einfach bei Interesse.

Die Beispiel Anwendung lässt sich hier herunterladen.

Zurück