Seite 1 von 3

[sloved]QString Zerlegen und im Array Speichern

Verfasst: 29. Januar 2008 12:54
von jd
Hallo Gemeinde, ich bin neu im Forum und grüße hiermit erst einmal alle.

So dann mal zu meinem Vorhaben und meinem Problemen dir mir seit ein paar Tagen den Nerv rauben :)

Aufgabe:
Ich möchte den Genutzt und Freien Speicherplatz der Partitionen auslesen, Ich habe mich dafür entschieden df -h zu parsen, ohne txt Datei. Das ganze wird in einem QString gespeichert, der dann in einem QLabel ausgegeben wird. Nun soll das ganze auch etwas schick aussehen, also Grafisch dargestellt werden.

Beispiel:
/dev/sda2 15G 3.9G 9.9G 29% /
tmpfs 506M 4.0K 506M 1% /dev/shm
/dev/sda4 20G 15G 4.2G 78% /home
/dev/sda1 20G 20G 462M 98% /media/disk0
/dev/sdb1 75G 29G 47G 39% /media/disk
/dev/sdc1 150G 37G 113G 25% /media/WD Passport

Das wird im QString gespeichert.

Problem1:
Ich brauche ein 2-Dimensionales Array, weiß aber nicht so rech wo ich da ansetzen muss mit QChar oder QByteArray...

Das Array soll folgenden Aufbau haben:

Array[x][y]
x steht für die Partition.
y steht für werte der Partition

Beispiel:
Array[0][0] = partition(dev/sda2), mountpoint(/)
Array[0][1] = partition(dev/sda2), fullSize(15GB)
Array[0][2] = partition(dev/sda2), usedSpace(3,9GB)
Array[0][3] = partition(dev/sda2), FreeSpace(9,9GB)
Array[0][4] = partition(dev/sda2), used in % (29%)

Array[1][0] = partition(dev/sda4), mountpoint(/home)
Array[1][1] = partition(dev/sda4), fullSize(20GB)
Array[1][2] = partition(dev/sda4), usedSpace(15GB)
Array[1][3] = partition(dev/sda4), FreeSpace(4,2GB)
Array[1][4] = partition(dev/sda4), used in % (78%)

etc.

Sprich ich muss meinen QString vollkommen Zerlegen, nur wie?

Problem2:
Wenn ich das erst einmal in einem Array habe, würde ich das gerne grafisch darstellen in Form eines Balken (Farbig) um die Auslastung zu Zeigen. Ich habe mir gedacht das ganze mit einem QFrame zu gestalten, und den dann je nach den belegten Prozenten eine Farbe geben:

Beispiel:
QFrame1 hat eine breite von 100px (Grund Frame)
QFrame2 hat eine breite von 50px (Auslastung) mit der Hintergrundfarbe grün, sprich man sieht visuell wie es mit der Partition steht

Wobei sich QFrame2 innerhalb QFrame1 befindet, oder gibt es da eine bessere Vorgehensweise?

So das wäre mein Anliegen, anbei poste ich auch meinen Code, damit mein vorhaben etwas besser nach zu voll ziehen ist.




Code: Alles auswählen

void CMainWindow::calculateDiskSpace() {
	QString cmd("df -h | grep /dev/");
	FILE *infile = popen( QFile::encodeName(cmd).data(), "r" );
	if (infile == NULL) {
		QMessageBox::warning(0, tr("Error"), tr("Failed to parse command.\n"));
		return;
	}

	QFile file;
	if (!file.open(infile, QIODevice::ReadOnly)) {
		QMessageBox::warning(0, tr("Error"), tr("Failed open file.\n"));
		return;
	}

	QTextStream in(&file);
	QString line = in.readLine();
	while (!in.atEnd()) {
		line.append("\n");
		line.append(in.readLine());
	}

	labelDiskSpace->setText(line);
	labelDiskSpace->adjustSize();
}
Ich hoffe mir kann jemand ein paar Tipps geben, wie an die Geschichte ran gehen sollte.

so long

jd

Verfasst: 29. Januar 2008 13:36
von macman
Zerleg deinen String nach Zeilenenden, dann hast für jede Partition einen String. Den kannst Du dann weiter zerlegen in das was Du brauchst.

Verfasst: 29. Januar 2008 14:38
von jd
Das verstehe ich nicht so ganz, also soll ich kein Array nehmen? Ich dachte das wäre praktisch, da ich dann nicht so viele Strings habe. Wie mache ich das ich jede Zeile in ein String speichere? In der Doku finde ich auch nichts zu mehrdimensionalen Arrays.

Verfasst: 29. Januar 2008 14:53
von macman
Wie du die Daten vorhältst ist deine Sache, ich habe nur vorgeschlagen wie du die Ausgabe von df zerlegst. Ein Array wäre mir zu statisch, ich hätte für jede Partition eine Struktur erstellt und die dann in eine Liste. Andere würden sogar eine Partitionsklasse erstellen.

Verfasst: 29. Januar 2008 15:05
von jd
Das Problem was ich habe, ist ich weiß ja nicht wie viele Partitionen ich habe... Ich durchlaufe ja mit

Code: Alles auswählen

while (!in.atEnd()) {
      line.append("\n");
      line.append(in.readLine());
}
 
Zeile für Zeile, sprich jede Zeile = eine Partition.

Das mit der Struktur ist eine super idee, die gefällt mir, jedoch muss ich die Informationen innerhalb der while-Schleife in die Struktur speichern. Ich weiß jedoch nicht wie ich an die "Daten ran komme" Ich bekomme nur die komplette Zeile, sprich das Problem liegt da ran, wie Zerlege ich den String so das ich an die einzelnen Daten komme, weil dann könnte ich das in eine Struktur packen, wie du das vorgeschlagen hast.

Beispiel:

Was muss ich machen um diese Zeile zu zerlegen.
/dev/sda2 15G 3.9G 9.9G 29% /

Muss ich da von leerzeichen zu leezeichen hüpfen von tab zu tab? Wenn ja wie geht das? Muss ich da QRegExp nutzen?

so long

Verfasst: 29. Januar 2008 15:39
von macman

Verfasst: 29. Januar 2008 19:03
von upsala
QRegExp("(\\S+)\\s+([0-9.][kMG])\\s+([0-9.][kMG])\\s+([0-9.][kMG])\\s+(\\d+)%\s+(\\S+)$")

Und die Daten nicht als String abspeichern, sondern die Größen gleich in int-Values umrechnen.

Verfasst: 29. Januar 2008 20:16
von jd
Hallo, ich habe mein Code jetzt um einiges erweitert, und das mit der Struktur realisiert, es ist noch nicht ganz ausgereift, aber es klappt.

nur habe ich ein Problem, ab und zu wenn ich das Programm starte erhalte ich folgende Meldung:
ASSERT failure in QList<T>::operator[]: "index out of range", file /usr/include/qt4/QtCore/qlist.h, line 392
Jedoch nicht immer, kann damit nicht wirklich was anfangen, da ich nicht weiß wo der Fehler herkommt.

Mein Code:

Code: Alles auswählen

void CMainWindow::calculateDiskSpace() {
	struct SHardDrive {
		QString filesystem;
		QString size;
		QString used;
		QString avail;
		QString usedPercent;
		QString mountPoint;
	};

	int const HDDNUMBER = 10;
	int counter = 0;

	struct SHardDrive hdd[HDDNUMBER];

	QString cmd("df -h | grep /dev/");
	FILE *infile = popen( QFile::encodeName(cmd).data(), "r" );
	if (infile == NULL) {
		QMessageBox::warning(0, tr("Error"), tr("Failed to parse command.\n"));
		return;
	}

	QFile file;
	if (!file.open(infile, QIODevice::ReadOnly)) {
		QMessageBox::warning(0, tr("Error"), tr("Failed to open file.\n"));
		return;
	}

	QTextStream in(&file);
	QString line;

	while (!in.atEnd()) {
		counter++;
		line = in.readLine();

		QStringList list;
		list = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);

		hdd[counter].filesystem = list[0];
		hdd[counter].size = list[1];
		hdd[counter].used = list[2];
		hdd[counter].avail = list[3];
		hdd[counter].usedPercent = list[4];
		hdd[counter].mountPoint = list[5];

	}

	labelDiskSpace->setText(hdd[1].mountPoint);
	QRegExp rx("%");

	QString tmp = hdd[1].usedPercent.replace(rx, "");

	int x = hdd[1].usedPercent.toInt() * 4;
	int y = 16;

	QSize newSize(x, y);
	frameDrive1->resize(newSize);
	frameDrive1->setStyleSheet("background-color: green;");

	labelDiskSpace->adjustSize();
}
Ich weiß, das mit der Struktur ist nicht gerade gut gelöst, aber das kommt noch, nur der Start-Fehler da da ab und zu kommt nervt.

Verfasst: 29. Januar 2008 20:20
von upsala
Ein Debugger kann hin und wieder auch einen Fehler verraten, aber nur wenn man ihn auch benutzt. Wann wird hdd[count] eigentlich initalisiert?

Verfasst: 29. Januar 2008 20:53
von jd
Gleich nach dem ich die Struktur definiere, siehe Code da oben... Ich habe Eclipse... und der Debugger macht irgendwie nix

Verfasst: 29. Januar 2008 21:22
von upsala
Hoffentlich hast du nie mehr als 9 Einträge, freunde dich mal mit der Doku von QList an.

Verfasst: 30. Januar 2008 07:18
von macman
jd hat geschrieben:

Code: Alles auswählen

	int const HDDNUMBER = 10;
	int counter = 0;

	struct SHardDrive hdd[HDDNUMBER];
Jetzt packst Du es ja wieder in ein statisches Array, obwohl Du selbst geschrieben hast, Du weißt nicht wieviele Partitionen vorhanden sind. Wie upsala schon schrieb, schau dir mal QList an.

Verfasst: 30. Januar 2008 10:52
von jd
Guten Morgen,

so ich habe mal die Doku von QList durch gearbeitet und was probiert,

und zwar habe ich ja eine Struktur wo die ganzen Daten pro Partition abgespeichert werden, jedoch unterstützt QList nur QString und int was mich zu der Frage führt wie bekomme ich meine Struktur in QList

Das einzige was geklappt hat ist folgendes:

Abgespeckter Code:

Code: Alles auswählen

struct SHardDrive {
		QString filesystem;
		QString size;
		QString used;
		QString avail;
		QString usedPercent;
		QString mountPoint;
	};

	struct SHardDrive hdd;

	QList<QString> disk;
while (!in.atEnd()) {
		line = in.readLine();
		QStringList list;
		list = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);

		hdd.filesystem = list[0];
		hdd.size = list[1];
		hdd.used = list[2];
		hdd.avail = list[3];
		hdd.usedPercent = list[4];
		hdd.mountPoint = list[5];

		disk.append(hdd.filesystem);
	}
Problematik ist, das dann in der QList disk ein abolutes Chaos herrscht, da disk[0-5] für hdd1 verwendet wird usw.

Wie kann ich das jetzt optimieren? Oder habe ich was total missverstanden?

so long

jd

Verfasst: 30. Januar 2008 12:15
von upsala

Code: Alles auswählen

QList<SHardDrive> daten; 

Verfasst: 30. Januar 2008 12:28
von jd
Ja genau das hatte ich mir auch gedacht, da ich dann Fehlermeldungen bekommen habe, habe ich Google gefragt:

http://lists.trolltech.com/qt-interest/ ... 711-0.html

Da hat jemand ein ähnliches Problem. Und da steht das Qt das irgendwie nicht kann, da struct kein Type von Qt sondern User definierte Typen.

Der Compiler schmeißt mir folgende Meldung raus:
src/MainWindow/MainWindow.cpp:37: error: template argument for ‘template<class T> class QList’ uses local type ‘CMainWindow::calculateDiskSpace()::SHardDrive’
src/MainWindow/MainWindow.cpp:37: error: trying to instantiate ‘template<class T> class QList’
src/MainWindow/MainWindow.cpp:37: error: invalid type in declaration before ‘;’ token
Mein Code ablauf ist folgender:

Code: Alles auswählen

struct SHardDrive {
		QString filesystem;
		QString size;
		QString used;
		QString avail;
		QString usedPercent;
		QString mountPoint;
	};

	struct SHardDrive hdd;

	QList<SHardDrive> daten; // Compiler meckert
while (!in.atEnd()) {
		line = in.readLine();
		QStringList list;
		list = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);

		hdd.filesystem = list[0];
		hdd.size = list[1];
		hdd.used = list[2];
		hdd.avail = list[3];
		hdd.usedPercent = list[4];
		hdd.mountPoint = list[5];

		daten.append(hdd); // Compiler meckert
	}
Weil die Idee hatte ich auch QList ist ja eine Template klasse, somit dachte ich mir halt auch das ich einfach QList<T> angeben kann. Aber das will er nicht.

so long

jd