[gelöst] Datenbankklasse und Signal Slot Prinzip

Alles rund um die Programmierung mit Qt
Antworten
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

[gelöst] Datenbankklasse und Signal Slot Prinzip

Beitrag von Illuminatus »

hi und zwar gehts darum, dass ich eine Oberfläche habe, die mithilfe eines von QT vorfefinierten Signals auf einer Datenbank verbindung die schon beim Konstruktor der Oberflächenklasse erstellt wird, eine Query absetzt.

wie kann ich nun also ein Slot in der Klasse connection definieren, so dass wenn die query abgesetzt wird gleichzeitig wieder ein Signal an die Oberfläche und den QTextEdit abgesetzt wird und darauf deas Ergebnistupel erscheint? also mir gehts eigentlich darum woher die klasse connection weiß dass es die oberfläche gibt`, bzw. die eine instanz davon?



Code: Alles auswählen

#ifndef CONNECTION_H
#define CONNECTION_H
#include <QtSql>
#include <QObject>

class connection : public QObject
{
	Q_OBJECT

public:
	connection(QString driver, QString hostname, QString databasename, QString user, QString password);
	QSqlDatabase db;

public slots:

signals:
	
private:
};
#endif //CONNECTION_H

Code: Alles auswählen

#include "connection.h"


connection::connection(QString driver, QString hostname, QString databasename, QString user, QString password) {
	db = QSqlDatabase::addDatabase(driver);
	db.setHostName(hostname);
	db.setDatabaseName(databasename);
	db.setUserName(user);
	db.setPassword(password);
	bool okay = db.open();
}
Zuletzt geändert von Illuminatus am 22. Februar 2009 18:08, insgesamt 1-mal geändert.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Datenbankklasse und Signal Slot Prinzip

Beitrag von franzf »

Illuminatus hat geschrieben:wie kann ich nun also ein Slot in der Klasse connection definieren, so dass wenn die query abgesetzt wird gleichzeitig wieder ein Signal an die Oberfläche und den QTextEdit abgesetzt wird und darauf deas Ergebnistupel erscheint?
Warum du eine zusätzliche Klasse "connection" brauchst, versteh ich nicht ganz, oder hast du da ein paar entscheidende Member weggelassen? Und dass db public ist, solltest du bei OOP eigentlich lassen (Stichwort "Datenkapselung").

Ansonsten hast du eigentlich kein wirkliches Problem (oder ich verstehs nicht). Denn ein QSqlQuery liefert dir sofort das Ergebnis des Query zurück, also gibts gar keinen Grund da erst Signals durch die Gegend zu schießen.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

hi
hab ne extra klasse erstellt, da ich das ganze programm schön modular erstellen will. ist für ein seminar und soll später von den teilnehmern leicht verstanden werden. hab nun ein slot definiert, der auf die QLineEdit "sql_in" (als Eingabefeld für den query) und "sql_out" (QTextArea für Tupelwiedergabe) zugreift.

Code: Alles auswählen

//dbvis.cpp <--- von QMainWindow abgeleitete Klasse 



void dbvis::query_slot(){
	QString temp_anfrage = sql_in->text();
	QString temp = "";
	
	sql_in->setText("");
	if(conn->db.open()) {
		QSqlQuery query;
		query.exec(temp_anfrage);
		// ResultSet auslesen
		while(query.next()){
			temp.append(query.value(1).toString());
			temp.append(" ");
		}
	}
	sql_out->setText(temp);
}



Weist du/ Wisst ihr wie man es eventuell machen kann, dass er herausfindet welche Datentypen sich in den Tupelattributen befinden? also dass ich unabhängig von bestimmten Attributtypen jedes Anfrageergebnis auslesen kann?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Die Datentypen findest du im QSqlRecord.

Und wenn das ganze für ein Seminar ist, dann solltest du mal an deiner Rechtschreibung und deinen Code-Konventionen arbeiten.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Ein paar andere Sachen noch:
wenn connection wirklich nur benötigt wird, um das db-Object zu speichern, ist es absolut überflüssig. Das wird nämlich schon in QSqlDatabase gespeichert. Bei addDatabase kannst du noch nen Namen mitgeben, über den du dann die Database mittels QSqlDatabase::database(name) holen kannst. Und wenn du es unbedingt Speichern willst, kannst du das auch in deiner MainWindow-Klasse machen.
Implizit gehst du ja auch davon aus, dass du eine "defaultConnection" hast, denn QSqlQuery ohne Database im Konstruktor nimmt die default.

Dann solltest du dir überlegen, ob der ein oder andere Check vor dem Ausführen des Query nützlich sein könnte. Denn jetzt wird auch ein drop table oder delete ohne Kommentar ausgeführt.
Und nur den index "1" an den String anhängen (Für was gibt es eigentlich QStringList?!?) ist auch doof, wenn man explizit nach bestimmten Spalten fragt. Da werden die Seminarteilnehmer doof schauen, wenn die Query nicht das zurück gibt, was man will.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

hi sorry war vllt missverständlich^^ ich bin teilnehmer des seminars und werde das programm präsentieren (müssen). also das mit den konventionen^^ ich weis ;) is nicht so prickeln, bin auch erst im 3.semester und komm eigentlich eher aus der java ecke. hab C++ auch extra wegen dem seminar mir ein bisschen angeeignet.

Also ich habe vor die ganzen Datentupel die mir diese Anfrage zurückwirft in eine ArrayList zu speichern. Dafür will ich dann einen extra Datentyp entwerfen der wiederum eine ArrayList jeweils für die einzelnen Elemente (Attribute des Tupels) innehat. Wie kann ich es nun also machen, dass das Programm zur Laufzeit entscheidet, als welchen Datentyp er die Objekte in die ArrayList eines Elements <Tupel> einfügt?

Ich hoffe ihr versteht was ich meine?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Der query.record().value() ist doch ein QVariant, oder?
Ein QVariant hat eine wundervollbringende Methode "type()" über die du ohne weiteres den (na?) Typ ermitteln kannst ;)

Im übrigen solltest du doch selbst die Definition deiner table kennen und somit auch, was drinnen steckt. Oder hab ich dich jetzt komplett falsch verstanden?
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

ja natürlich, aber das programm soll universell auf jede datenbank relation anwendbar sein, also nicht nur auf meine tabellen ;)

danke ich versuch das mal zu implementieren =)

ich hab das mit dem QVariant bisher so verstanden dass das nur ein feld ist welches verschiedene datentypen definiert???

also versteh ich das richtig:
ich muss zuerst die anzahl der spalten feststellen?
dann durch diese durchiterieren und jedesmal muss ich dann doch feststellen welchem datentyp in Qt der sql-konforme entspricht! aber mit welchem befehl kann ich das machen?
lad ich die einfach als QVariant und finde mit type() den gleichwertigen raus?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Illuminatus hat geschrieben:ich hab das mit dem QVariant bisher so verstanden dass das nur ein feld ist welches verschiedene datentypen definiert???
Verschiedene Datentypen definieren kann es sicher nicht.
Es "behebt" halt die feste Typisierung von C++ und die damit einhergehende Unfähigkeit, in einer Variable mehrere Typen abzuspeichern, so wie z.B. in den ganzen Scriptsprachen.
Um dann wieder an die korrekt typisierten Daten zu kommen, gibt es Methoden wie toString() usw.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

ahh okay, das hat mir nun echt weitergeholfen!!! ich arbeit auch gerade mit dem assistenten und versuch das dort zu verstehen!
wenn ich also ein element QVariant hab, wie bekomm ich dann raus ob das zum beispiel ein integer ist, oder ein string?
klar ist das in den meisten fällen kein problem da ein integer au als string dargestellt wird, aber in komplexeren fällen weis man ja nie.

Habe folgendes im Assi gefunden und nun auf meine Bedürfnisse leicht verändert:

Code: Alles auswählen

QVariant v;
QString c;

if (v.canConvert<QString>())
     c = v.value<QString>(v);

ist diese überprüfung korrekt?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Das was du machst, bringt dich nciht wirklich darauf, was für ein Type drinstackt, sondern ob du ihn nach String konvertieren kannst, und das geht mit fast allen Typen.

Code: Alles auswählen

QVariant v(100);
qDebug() << v.typeName();
Und um zu wissen, ob da grad ein int drinnensteckt, mach Folgendes:

Code: Alles auswählen

if( v.type() == QVariant::Int ) {
    // irgend was schönes und dolles mit dem int anstellen
}
Schau dir halt einfach mal die ganzen Beispiele im assistant zu QVariant an.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

lässt sich eigentlich über SqlQuery irgendiwe die anzahl der attribute (spalten) bestimmen?
hab dazu im assistenten nichts gefunden?
oder gibts eine schönere möglichkeit als
for(int i=0; i<ATTRIBUTE; i++)
{
container= result.value(i);
}
durch die attribute durchzugehen?

ich meine nicht die tupel!!! dafür gibts darüber nochmal ne schleife die bis result.size() läuft!
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Nimm dir doch einfach das erste record(), und speicher die size(). Das enthält die Anzahl der Spalten.
QSqlQuery::size() gibt ja nur die Anzahl der Zeilen.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

jo so hab ichs nun gemacht

Code: Alles auswählen

if(result.size()!=-1)
		{
			while(result.next()){
				for(int i=0;i<result.size(); i++)
				{
					tupel *current = new tupel(i);
					for(int y=0; y<meta_result.count(); y++)
					{
						current->getAttributes.append(result.value(y));
					}
				}
			}
		}

Die tupelklasse enthält ein privates element QList<QVariant> in die ich nun die ganzen attribute eines ergebnistupels verpacken möchte...
er mosert mir allerdings urm, dass er links von append keine klasse hat?

bei mir is meta_result vom typ QSqlRecord und da stand dass irgendwie count() die anzahl wiedergibt?


FEHLER GEFUNDEN!!! Vieln dank für eure hilfe ;)
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Warum packst du das ganze nicht einfach in eine QTableView und verwendest ein QSqlQueryModel oder QSqlTableModel? QTextEdit eignet sich nur bedingt zur Darstellung der Ergebnismenge, und bei View/Model brauchst du nichts händisch konvertieren.

Code: Alles auswählen

QTableView* view = new QTableView(...);
QSqlQueryModel* model = new QSqlQueryModel(...);

view->setModel(model);

model->setQuery("select foo from bar where ...");
oder

Code: Alles auswählen

QTableView* view = new QTableView(...);
QSqlTableModel* model = new QSqlTableModel(...);

view->setModel(model);

model->setTable("tb_seminar");

// ggfs:
model->setFilter("col_userid = 5");

model->select();
Antworten