QTreeView Daten dynamisch nachladen (QAbstractItemModel)

Alles rund um die Programmierung mit Qt
Antworten
zwutz
Beiträge: 14
Registriert: 20. November 2007 09:13

QTreeView Daten dynamisch nachladen (QAbstractItemModel)

Beitrag von zwutz »

so... folgendes:

ich versuch hier grad ne TreeView zu realisieren.
Klappt auch wunderbar, allerdings lässt die Performance zu wünschen übrig.
Es sind zwar recht wenige Daten (<100), allerdings liegen einige Datenbankoperationen dahinter, was das ganze extrem verlangsamt.

Also hab ich mir gedacht, ich lad beim Aufruf nur die erste "Schicht" ohne ChildItems, da das relativ schnell geht.
Klickt der User dann auf ein Item, um es aufzuklappen, sollen die entsprechenden ChildItems geladen, aufgebaut und angezeigt werden.
Nur dabei stoß ich an einige Grenzen. Laut der "Model Subclassing Reference" von Qt bin ich auf "canFetchMore()" bzw. "fetchMore()" gestoßen, was eigentlich soweit passend klingt, allerdings wird letztere nicht mal aufgerufen, wenn ich diese ableite.

Ich hab dann versucht, diese Funktion als Slot zu definieren und entsprechend aufzurufen, wenn in der View das Item geöffnet wird, was zwar auch halbwegs geklappt hat, aber die Daten wurden nicht angezeigt (erst, nachdem der parent nochmal geöffnet wurde).

Ein Senden des Signals "layoutChanged()" innerhalb der fetchMore-Methode führte zu einer Endlosschleife (also auch der falsche Weg)

Meine Frage(n) daher:
Wie genau arbeitet die Methode "fetchMore()" oder wie soll sie arbeiten?
Warum wird sie nicht aufgerufen, wenn ich sie ganz normal ableite (nicht als Slot)? Hab ich was übersehen?
Und wie geht man bei sowas generell vor (nachladen von Daten zur Laufzeit)?

Falls noch Infos oder Codeausschnitte gebraucht werden, sagt bitte bescheid

Danke
DarkWotan
Beiträge: 65
Registriert: 18. Mai 2006 10:03

Beitrag von DarkWotan »

Ich weiß, der Thread ist uralt. Ich habe gerade die Suchfunktion benutzt und dank der bin ich darauf gestoßen. Hier geht's um ein Problem, das ich ebenfalls habe. Gibt's nach fast einem Jahr schon erste Ansätze? :-)
CLRS530
Beiträge: 155
Registriert: 8. Oktober 2007 18:00

Beitrag von CLRS530 »

Im grunde brauchst du diese Funktionen gar nicht. Schau dir z.B. die Sources von QDirModel an. Wenn ein Element erweitert wird, wird index bzw rowCount mit diesem Element als parent aufgerufen. In dem Fall weißt du, dass diese Daten "demnächst" in data abgerufen werden und kannst sie vorbereiten.
Das ist eigentlich auch nichts außergewöhnliches und so gut wie jedes Model arbeitet auf diese Art und Weise.
DarkWotan
Beiträge: 65
Registriert: 18. Mai 2006 10:03

Beitrag von DarkWotan »

Mein bisheriger Ansatz ohne diese beiden Methoden wäre gewesen, das Model via mutable Daten in index() aufzubereiten. mutable deswegen weil die Methode ja const ist. Allerdings hat das zu unerwarteten Ergebnissen geführt. Oder wie hast du das gemeint?
Ich guck mir QDirModel mal an.
CLRS530
Beiträge: 155
Registriert: 8. Oktober 2007 18:00

Beitrag von CLRS530 »

Ja genau so habe ich das auch gemacht. Du musst halt aufpassen, da rowCount öfter vor index aufgerufen wird und du die Funktion zum Aufbereiten somit aus beiden aufrufen musst.
DarkWotan
Beiträge: 65
Registriert: 18. Mai 2006 10:03

Beitrag von DarkWotan »

Schön und gut, aber das kann ja nicht Sinn und Zweck sein? Ich meine alleine die Verwendung von mutable ist ja eher eine Seltenheit. Die Entwickler von Qt haben sich ja sicher auch was dabei gedacht, warum index() const ist.
Ich nehme zwar deinen Vorschlag als Lösung an, stelle aber gleichzeitig die Original-Frage wieder in den Raum mit dem Hintergrund, Wert auf Eleganz zu legen. fetchMore() und canFetchMore() haben ja auch ihre Daseinsberechtigung. Ich versuch's nochmal...
CLRS530
Beiträge: 155
Registriert: 8. Oktober 2007 18:00

Beitrag von CLRS530 »

Ich kann nur das weitergeben, was ich selbst gemacht habe. Du hast wohl absolut recht.
Nur ich sehe keine Probleme die canFetchMore Sache einzubauen. Ich weiß nichtw as ihr da falsch macht.
canfetchMore ist doch im Grunde nichts anderes als hasChildren, nur dass canFetchMore erst aufgerufen wird, wenn explizit Daten angefordert werden (durch Klick auf das +) und hasChildren steuert, ob überhaupt ein + Symbol angezeigt wird.
Wobei die Doku das nur über fetchMore aussagt. Wäre allerdings meines erachtens wiedersinnig, wenn canFetchMore früher aufgerufen wird. Wenn canFetchMore dann true zurück gibt kannst du in fetchMore deine Daten zusammensetzten.

Ich sollte wohl wirklich auf diese Funktionen zurückgreifen, da es erstens schöner ist und zweitens viele Abfragen in index und rowCount umgeht.
Frag mich nicht, wieso die Trolls selber in QDirModel nicht mit diesen Funktionen vorgehen.

Ich hoffe ich habe dich mit der Erklärung eventuell auf eine Fehlerquelle aufmerksam gemacht.
Du musst auf jeden Fall beide Funktionen reimplementieren.
CLRS530
Beiträge: 155
Registriert: 8. Oktober 2007 18:00

Beitrag von CLRS530 »

Dank deiner Nachfrage ist mein Quellcode nun ein wenig besser :).
Ich habe jetzt bei all meinen populate Routinen (populate, populateDir...) const entfernen können, genauso wie das mutable bei meinem struct.
Ich hatte keinerlei Probleme. Eventuell hilft es dir, wenn ich dir die 2 kurzen Funktionen reinstelle, auch wenn du keine weiteren Informationen über die Strukturen hast.

Code: Alles auswählen

bool VariableDirModel::canFetchMore(const QModelIndex &parent) const
{
    DirModelEntry *parentEntry = parent.isValid() ? static_cast<DirModelEntry*>(parent.internalPointer()) : rootFolder;

    return !parentEntry->populated;
}

void VariableDirModel::fetchMore(const QModelIndex &parent)
{
    DirModelEntry *parentEntry = parent.isValid() ? static_cast<DirModelEntry*>(parent.internalPointer()) : rootFolder;

    populate(parentEntry);
}
Sollte eine Frage auftreten, nur zu. Der ganze Aufbau orientiert sich auf jeden fall an das vom QDirModel.
Antworten