QDir Verzeichnis auflisten in Funktion einer Klasse

Verschiedenes zu Qt
Mefisto
Beiträge: 27
Registriert: 6. September 2008 13:37

QDir Verzeichnis auflisten in Funktion einer Klasse

Beitrag von Mefisto »

Hallo!

Natürlich ist folgender Code-Schnippsel noch nicht fertig und erfüllt im Moment noch keine elementare Funktion in meinem Programm. Das wird kommen, aber erst wenns funktioniert. Ich habe einiges eingefügt (zum Beispiel die QMessageBox), um das ganze bis hierher zu testen. Weil ich teste lieber immer kleine Stücke als am Ende den ganzen Code auf einmal und wenn was nicht funktioniert muss ich 100 Zeilen überprüfen: Sowas ist ziemlich doof. Also hier mal mein Code-Schnippsel, der nicht funktioniert:

Code: Alles auswählen

void listDatabases::setPath(QString pathParameter) { basePath = QDir::current().path()+"/"+pathParameter; }

QStringList listDatabases::databases(QString appendPath) {
	base.setPath("");
	if(appendPath=="") { databaseList.clear(); base.setPath(basePath); } else { base.setPath(basePath+appendPath); }
	if (!base.exists()) { qWarning("It seems that the base directory for database-browsing doesn't exist."); }
	base.setFilter(QDir::NoSymLinks | QDir::NoDotAndDotDot);
	allList = base.entryList();
	allListLength = allList.size();
	for(int i = 0; i<allListLength; i++) { databaseList.append(allList.at(i)); }
	QMessageBox msgBox;
	msgBox.setText(databaseList.join(", "));
	msgBox.exec();
	return allList;
}
Und die Klasse dazu:

Code: Alles auswählen

class listDatabases {
	public:
		QStringList databases(QString appendPath = "");
		void setPath(QString pathParameter);
	private:
		QStringList databaseList;
		QStringList allList;
		int allListLength;
		QDir base;
		QString basePath;
};
Bei diesem Code handelt es sich um eine Klasse, über die ich in meinem Programm alle Datenbanken (Dateien mit .sql als Dateiendung) auflisten lassen will. Wie man sieht. Fehlt dieses auflisten noch. Im Moment sollten eigentlich alle Dateien und Ordner eines Verzeichnisses aufgelistet, in der allList temporär gespeichert (bisher eher sinnlos, aber hier soll später die Überprüfung der Dateiendung statt finden) und anschließend in die QStringList "databaseList" kopiert werden. Diese sollte dann in der QMessageBox ausgegeben werden, aber der aufploppende Dialog ist leer. Nun finde ich leider nicht den Fehler. Kann mir vielleicht einer dabei helfen? Ich bin recht neu in Qt und C++ und muss noch eine Menge lernen, also seid bitte geduldig und habt Nachsicht mit meiner Unwissenheit ;)

Achso, und der Parameter der Funktion erfüllt noch keinen Zweck, genau so wie die if-Abfrage in der zweiten Zeile der Funktion. Beides soll später die Funktion rekursiv machen :)

Ich würde mich sehr über Hilfe freuen! Vielen Dank im Voraus,
Jonathan
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Zum einen würde ich mal den Code formatieren, so kann man sich auch nicht auskennen...

Dann würde ich den QDirIterator verwenden, da dort Rekursion kostenlos mitgeliefert wird...
Mefisto
Beiträge: 27
Registriert: 6. September 2008 13:37

Beitrag von Mefisto »

Ok, danke für den Tipp, habe es nun umgestellt auf den QDirIterator. Er ist für mich wohl am geeignetsten, ich brauche keine Sortierung. Leider funktioniert das ganze aber immer noch nicht. Hier der Code, wie er jetzt aussieht (was war denn bitte unformatiert?):

Code: Alles auswählen

void listDatabases::setPath(QString pathParameter) { basePath = QDir::current().path()+"/"+pathParameter; }
QStringList listDatabases::databases() {
	QDirIterator base(basePath, QDirIterator::Subdirectories);
	while (base.hasNext()) {
		tempName = base.next();
		if(tempName.endsWith(".sql")) {
		    databaseList.append(tempName); }
	}
	
	QMessageBox msgBox;
		msgBox.setText(databaseList.join(", "));
		msgBox.exec();
	
	return allList;
}
Ich rufe das ganze so auf:

Code: Alles auswählen

databases = new listDatabases();
databases->setPath("language");
databases->databases();
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

irgendwie schreibt man hier immer wieder das gleiche: was bedeutet "Leider funktioniert das ganze aber immer noch nicht"? Programmieren ist doch so einfach: man muss einfach nur das Verhalten des geschriebenen Codes verifizieren. Auf Wunsch auch ohne Debugger:

Code: Alles auswählen

QStringList listDatabases::databases() 
{
  qDebug() << "durchsuche" << basePath;
   QDirIterator base(basePath, QDirIterator::Subdirectories);
   while (base.hasNext()) {
      tempName = base.next();
      qDebug() << "naechster Eintrag:" << tempName;
      if(tempName.endsWith(".sql")) {
          databaseList.append(tempName); 
          qDebug() << "gefunden: " << tempName << "liste: " << databaseList;
      }
   }
}
Die Sache ist nun ganz einfach: Was für eine Ausgabe liefert das Programm.. und was SOLLTE es liefern?

was war denn bitte unformatiert?
Kann ich auch nicht verstehen.. kleiner Tipp: das nächste mal einfach das Programm in _eine_ Zeile schreiben.. dann wird's noch viel kleiner (und damit auch übersichtlicher)...
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Code: Alles auswählen

databases = new listDatabases();
databases->setPath("language");
databases->databases();
Was erwartest du dir von der letzten Zeile? Geht die MsgBox mit nicht erwartetem Inhalt auf? Crasht dein Prgramm? Da brauchts noch mehr Info...

Und wegen unübersichtlich:

Code: Alles auswählen

if(appendPath=="") { databaseList.clear(); base.setPath(basePath); } else { base.setPath(basePath+appendPath); } 
if (!base.exists()) { qWarning("It seems that the base directory for database-browsing doesn't exist."); }
Jede Anweisung in einer Zeile ist schon nicht schlecht, wenn man wie hier im Forum kein code-highlichting hat...
Mefisto
Beiträge: 27
Registriert: 6. September 2008 13:37

Beitrag von Mefisto »

Ok, sorry, ich persönlich halte es für übersichtlich, wenn man Code-Zeilen, die mit Sicherheit funktionieren, "komprimiert". Aber das ist sicher Geschmackssache. Ich habe da als Faustregel, dass Zeilen lang werden dürfen, jedoch der Editor sie nicht umbrechen darf (also höchstens so lang wie der Editor).

Ich habe den Fehler gefunden und muss mich wohl für die Frage entschuldigen: Ich habe einfach nur QDir::current() mit QCoreApplication::applicationDirPath() verwechselt. Dummer Fehler beim Lesen von der QDir-Docu...

Vielen Dank aber trotzdem für die Hilfe und die Tipps!
Jonathan
Mefisto
Beiträge: 27
Registriert: 6. September 2008 13:37

Beitrag von Mefisto »

Ok, jetzt habe ich dann doch noch ein Problem, das irgendwie sehr merkwürdig ist. Ich habe folgende zwei Header-Dateien:

mainwindow.h:

Code: Alles auswählen

#ifndef mainwindow_H
#define mainwindow_H
#include "listDatabases.h"
#include "ui_mainwindow.h"

using namespace std;

class listDatabases;

class userEdit : public QLineEdit {
    Q_OBJECT
	public:
		// Hier habe ich Code ausgelassen
	private:
		// Hier habe ich Code ausgelassen
};

class mainwindow : public QMainWindow, private Ui::MainWindow {
	Q_OBJECT
	public:
		mainwindow();
		userEdit *userEditLineEdit;
		listDatabases *databasesHandler;
	public slots:
		// Hier habe ich Code ausgelassen
	private:
		// Hier habe ich Code ausgelassen
};

#endif
listDatabases.h:

Code: Alles auswählen

#ifndef listDatabases_H
#define listDatabases_H

using namespace std;

class listDatabases {
	public:
		QStringList databases();
		void setPath(QString pathParameter);
	private:
		QStringList databaseList;
		QString tempName;
		QString basePath;
};

#endif
Soweit so gut, nun ist der Plan, dass ich eine Instanz der Klasse "listDatabases" in meiner Deffinition der Klasse "mainwindow" mitdeffiniere, genau so wie es mit der Klasse "userEdit" hervorragend klappt. Allerdings gibt mir g++ folgende Fehlermeldung aus:

mainwindow.h:25: Fehler: ISO-C++ verbietet Deklaration von »listDatabases« ohne Typ
mainwindow.h:25: Fehler: expected »;« before »*« token

Die Zeile, auf der sich der Compiler bezieht, ist folgende, aus der mainwindow.h:

Code: Alles auswählen

listDatabases *databasesHandler;
Ich habe keine Ahnung, was ich falsch mache und probiere schon seit ein oder zwei Stunden daran rum. In IRC Channels konnte man mir nur sagen, dass mein Code richtig sei, was ja aber offenbar nicht der Fall sein kann... Und was an dem ganzen so merkwürdig ist: Es funktioniert mit der anderen Klasse (userEdit -> siehe mainwindow.h) völlig ohne Probleme! Und bis ich mein erstes Problem in diesem Thread gelöst hatte, funktionierte auch die "listDatabases" Classe problemlos. Ich habe also absolut keine Idee mehr und wäre für Hilfe wieder Mal sehr dankbar! Also: Danke im Voraus und liebe Grüße,

Jonathan
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Das sind aber zwei völlig verschiedene paar Stiefel, mit den beiden Klassen.
listDatabases hat seinen eigenen Header, wohingegen userEdit nur in der mainwindow.h definiert ist.
Außerdem solltest du dich entscheiden: listDatabases forward deklarieren oder header inclduden.
Besser ist immer so weit als möglich im Header die Forward-Declaration zu verwenden und erst im .cpp zu includen.
Mefisto
Beiträge: 27
Registriert: 6. September 2008 13:37

Beitrag von Mefisto »

Ok, also was du sagst klingt einleuchtend. Aber ich habe den selben Fehler bekommen, als ich wie mit der Klasse userEdit, die listDatabases in der selben Header-Datei hatte. Ich habe es auch schon mit Forward-Deklination und ohne und mit Header inkludieren und ohne in sämtlichen Kombinationen probiert... Es funktioniert einfach nicht... Also somit habe ich all deine Vorschläge ohne Erfolg schon durchprobiert...
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Kannst du dann mal dein Projekt so weit reduzieren, dass der Rehler reproduzierbar bleibt und man das Ding kompilieren "könnte", packs in ein Zip und hängs an.

Dir ist auch bewusst, dass wenn du im Header ne forward-Deklaration (class listDatabases;) machst, du in der .cpp den Header in jedem Fall includieren musst? Falls das der Fall war hätte der Fehler ähnlich ausgesehen.

Also nimm nochmal das #include "listDatabases.h" aus deinem mainwindow.h raus, class listDatabases; lässt du da stehen.
in mainwindow.cpp musst du den Header "listDatabases.h" dann includieren.
Mefisto
Beiträge: 27
Registriert: 6. September 2008 13:37

Beitrag von Mefisto »

Hatte ich schon probiert gleich nach Deinem letzten Beitrag; ich habe die Inkludierung aus der mainwindow.h rausgenommen und in mainwindow.cpp war schon eine drin... Ich habe es jetzt also wie gewünscht zusammengepackt, aber man braucht die Qt Libraries um es zu kompillieren. Da ich hier in einem Qt-Forum bin, ist das ja aber wahrscheinlich kein Problem ;) Ich habe es so weit es geht abgespeckt, also alles, was nichts mit dem Problem zutun hat, gelöscht.

Ich habe aber zum Vergleich auch in der mainwindow.cpp den Teil, der sich auf die andere, problemlose Klasse bezieht (userEdit), drin gelassen. Vielen Dank schon Mal im Voraus,

Jonathan

Achso, "qmake -project" ist nicht nötig, es löscht die "qt+=sql"-Inkludierung aus der .pro-Datei und dann kompilliert es nicht mehr.
Dateianhänge
demoQTForum.tar.gz
Abgespeckte Version des Programmes. Kleiner gehts nicht ;)
(35.78 KiB) 140-mal heruntergeladen
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Code: Alles auswählen

using namespace std; 
Was soll das denn? Und dazu noch im Header...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Mefisto
Beiträge: 27
Registriert: 6. September 2008 13:37

Beitrag von Mefisto »

Ich habe mal in einem Forum gelesen, dass man das so machen soll... Es hat damals ein Problem gelöst, also war ich der überzeugung dass das so muss...

Ist es denn für das Problem verantwortlich?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Das ganze beruht auf einem Namenskonflikt :P
Du hast eine Klasse "listDatabases" und eine Variable "listDatabases" vom Typ "QListWidget" in deiner "ui_mainwindow.h". Sowas kann nur schief gehen!

Nicht umsonst gibt es Konventionen wie "Klassennamen fangen immer mit einem Großbuchstaben an" und "Funktionen und Variablen immer mit einem Kleinbuchstaben".
Wenn du dich daran nicht halten kannst/willst, pack alles in einen namespace (wie z.B. std:: ) und sorg in deinen Sourcen dafür, dass NIE ein using namespace MyNamespace; steht, sonst gibts wieder Konfliktpotential :P

Grüße
Franz

// edit
Außerdem hört sich "listDatabases" mehr nach ner Funktion an als nach ner Klasse. "DatabaseLister" würd ich das nennen.
Zuletzt geändert von franzf am 21. Mai 2009 09:56, insgesamt 1-mal geändert.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Mefisto hat geschrieben:Ich habe mal in einem Forum gelesen, dass man das so machen soll... Es hat damals ein Problem gelöst, also war ich der überzeugung dass das so muss...

Ist es denn für das Problem verantwortlich?
using namespace std ist in einem HEADER das schlimmste was du machen kannst! Gilt für alle Namespaces. Denn sobald dieser Header eingebunden wird, ist dieser namespace komplett aufgehoben, und es kann zu Namenskonflikten kommen.
Im übrigen verwendest du in deinen SOurcen kein std::-Klassen :P also überflüssig.
Antworten