Fragen zum QAbstractTableModel und QSortFilterProxyModel Geb

Alles rund um die Programmierung mit Qt
Antworten
SvenA
Beiträge: 7
Registriert: 7. Juli 2014 09:49

Fragen zum QAbstractTableModel und QSortFilterProxyModel Geb

Beitrag von SvenA »

Hallo!

Ich bin relativ neu bezüglich der Verwendung des Model/View Systems und versuche
eine Liste von Datensätze damit zu implementieren.
Ich habe zwei Listen (eine lokale und eine globale) welche ich zusammen in
einer Liste anzeigen möchte. Diese Liste zeigt dann alle verfügbaren Datensätze
(genauer gesagt dessen Namen) an und bei einem Doppelklick öffnet sich ein
neuer Dialog, in welchem die gesamten Daten dieses Datensatzes bearbeitet werden
können.

Da diese Liste lang werden kann, möchte ich sie sortieren und optional noch
filtern. Daher verwende ich ein ProxyModel.

Mein Test-Code ist beigefügt.

Nun meine Fragen:

1) Ist dies der richtige Weg dies zu implementieren oder mache ich es jetzt
schon fundamental falsch? Gibt es einen besseren Weg?

2) In meinem Code verwenden ich
proxyModel->sort(1, Qt::AscendingOrder);
um die Sortierreihenfolge zu setzen. Dies scheint aber keine Auswirkungen
zu haben, da es noch immer absteigend sortiert wird. Warum?

3) Wenn ich einen Eintrag ändern, so wird dieser zwar geändert aber nicht
korrekt einsortiert, d.h. die Liste wird nicht neu sortiert. Wenn ich
reset() verwende, dann verliere ich die Auswahl. Was ist hier falsch?

4) Wenn ich einen Eintrag lösche, so rufe ich "beginResetModel()" und
"endResetModel()" auf. Gibt es hier einen besseren Weg ein korrekten
Update der Liste zu erzwingen?

Im Code sind einige auskommentierte Zeilen. Diese stellen Versuche dar,
welche aber alle nicht funktioniert haben.

Bin über jeden Tip oder Hinweis dankbar. Wenn sich allerdings jemand einmal
den Code intensiv ansehen könnte, wäre ich begeistert...

Danke
Sven
Dateianhänge
main.cpp
main.cpp
(10.16 KiB) 190-mal heruntergeladen
main.h
main.h
(3.38 KiB) 161-mal heruntergeladen
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Fragen zum QAbstractTableModel und QSortFilterProxyModel

Beitrag von Christian81 »

Hallo,

nach einem kurzem Blick sieht es ok aus.
2.: in ListModel::data() gibst Du nur Daten für die 0. Spalte zurück, nie für Spalte 1. bzw. Du hast nur genau eine Spalte. Wir fangen bei 0 an zu zählen!
3.: Du modifizierst die Daten direkt ohne das Model zu informieren - wie sollte das Model und der View also wissen dass neue Daten vorliegen? Siehe QAbstractItemModel::dataChanged()
4.: Ja, wie in deinem Code schon angedeutet mit begin/endRemoveRows(), allerdings muss der Parent-Index angegeben werden, nicht der, der gelöscht wird

Allgemein noch ein paar Anmerkungen:
- goto bitte vermeiden
- die Daten (local_list / global_list) würde ich nicht als Member-Pointer sondern als Values halten. So musst Du die Daten auch über das Model ändern und kannst sie nicht (wie derzeit) einfach hinterrücks ändern und dich dann wundern dass die Anzeige nicht mehr passt.
- die Aufteilung local/global ist m.E. nicht nötig - ein weiteres Attribut in DataEntity vereinfacht das ganze Handling
- die Klassen sollte nicht in die main.cpp/main.h sondern in eigene Dateien
- (DataEntity *)&local_list->at(index.row()); - der C-Style cast auf DataEntity ist unnötig.
- die UI würde ich mit dem designer bauen, nicht von Hand
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
SvenA
Beiträge: 7
Registriert: 7. Juli 2014 09:49

Re: Fragen zum QAbstractTableModel und QSortFilterProxyModel

Beitrag von SvenA »

2.: in ListModel::data() gibst Du nur Daten für die 0. Spalte zurück, nie für Spalte 1. bzw. Du hast nur genau eine Spalte. Wir fangen bei 0 an zu zählen!
Na, dann paßt das ja. Danke für den Hinweis, aber ich habe das aus dem umfangreicheren Code zusammengeschrumpft, daher können hier noch Teile
des größeren Ganzen (wo ich in diesem Fall zwei Spalten habe) drin sein. Also nicht wunden.
3.: Du modifizierst die Daten direkt ohne das Model zu informieren - wie sollte das Model und der View also wissen dass neue Daten vorliegen? Siehe QAbstractItemModel::dataChanged()
Ja, jetzt wird es interessant! Ich habe in der editListItem() Funktion mit den Varianten der emit model->dataChanged(*index, *index); Funktion
(siehe dazu den Code in Zeile main.c:335) versucht das Model über die Änderung zu informieren. Aber irgendwie funktionierte das nicht.
Wenn das der richtige Weg ist, dann schaue ich mir das hier noch tiefer an... Vielleicht stehe ich auch nur auf dem Schlauch und übersehe etwas!

Wobei er nach der Änderungen des Namens im Dialog auch schon jetzt den Eintrag in der Liste ändert (woher weiß das View dies denn? Welches
Signal läuft da?). Aber trotz des Updates des Eintrags wird nicht neu sortiert...
4.: Ja, wie in deinem Code schon angedeutet mit begin/endRemoveRows(), allerdings muss der Parent-Index angegeben werden, nicht der, der gelöscht wird
Ok, das sehe ich mir mal an!
Allgemein noch ein paar Anmerkungen:
- goto bitte vermeiden
Klar, macht den Code hier nur kürzer. Und für das Beispiel nicht relevant. ;-)
- die Daten (local_list / global_list) würde ich nicht als Member-Pointer sondern als Values halten. So musst Du die Daten auch über das Model ändern und kannst sie nicht (wie derzeit) einfach hinterrücks ändern und dich dann wundern dass die Anzeige nicht mehr passt.
- die Aufteilung local/global ist m.E. nicht nötig - ein weiteres Attribut in DataEntity vereinfacht das ganze Handling.
Prinzipell richtig, aber die Listen werden später auch separat verwaltet und gespeichert, wo ich dann ein [quote QDataStream()[/quote] nehme und es dann dort einfacher
ist die Daten mit den Values zu speichern. Außerdem habe ich mehrere
- die Klassen sollte nicht in die main.cpp/main.h sondern in eigene Dateien
- die UI würde ich mit dem designer bauen, nicht von Hand
Das ist dem Komprimieren zu einem kompakten Beispiel geschuldet. Jede Klasse bekommt eine eigene Datei und ich baue die GUI (soweit es geht) mit
dem Designer.

Auf jeden Fall einmal Danke für die ersten Antworten und ich hoffe da kommen noch mehr Tipps!!
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Fragen zum QAbstractTableModel und QSortFilterProxyModel

Beitrag von Christian81 »

Ab und zu zeichnet der View selbst neu - z.B. wenn du mit de Maus drübergehst oder scrollst oder das Fenster in den Vordergrund holst etc. - dann werden auch die Daten neu geholt. Deshalb funktioniert es ab und zu. Ob danach automatisch neu sortiert wird weiß ich gerade nicht, notfalls musst Du da von Hand nochmal die aktuelle Sortierung neu aufrufen. Da müsste ich mal tiefer in die Qt-Sourcen schauen :)
Das dataChanged() in main.cpp:335 ist auch nicht ganz korrekt da es ja auch ein add() sein kann. Deshalb sollte dies Logik (add/change) direkt in das Model rein und nicht in die 'UI' - Klasse obendrüber. Deshalb eben auch keine Pointer da du so immer die Daten ändern kannst ohne dass das Model etwas davon mitbekommt (evtl. auch unabsichtlich). Ich würde dem Model zwei Funktionen zum Setzen / Modifzieren der Daten geben und dort alles abhandeln - dann ist es gut gekapselt.
Ich würde trotzdem die local/global im Model in einer Liste abhandeln, das macht es wirklich einfacher [;)]
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten