Seite 1 von 2
QDir Verzeichnis auflisten in Funktion einer Klasse
Verfasst: 20. Mai 2009 21:04
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
Verfasst: 20. Mai 2009 21:30
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...
Verfasst: 20. Mai 2009 22:05
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();
Verfasst: 20. Mai 2009 22:40
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)...
Verfasst: 20. Mai 2009 22:42
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...
Verfasst: 20. Mai 2009 23:10
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
Verfasst: 21. Mai 2009 00:21
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:
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
Verfasst: 21. Mai 2009 06:57
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.
Verfasst: 21. Mai 2009 08:42
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...
Verfasst: 21. Mai 2009 08:57
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.
Verfasst: 21. Mai 2009 09:34
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.
Verfasst: 21. Mai 2009 09:42
von Christian81
Was soll das denn? Und dazu noch im Header...
Verfasst: 21. Mai 2009 09:47
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?
Verfasst: 21. Mai 2009 09:50
von franzf
Das ganze beruht auf einem Namenskonflikt

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
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.
Verfasst: 21. Mai 2009 09:52
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

also überflüssig.