QSortFilterProxyModel -> Manager?



  • Moin moin,

    angenommen ich baue eine Kette aus Filtern, indem ich auf den letzten Filter immer setSourceModel(vorherigerFilter) anwende.

    Gibt es in QT einen Manager oder dergleichen für sowas, dass ich z.B. gezielt einen Filter aus der Kette entfernen kann, ohne dass die späteren Filtermodelle einen invaliden Pointer als SourceModel haben?

    Oder meint ihr mein Vorhaben ist eh ein schlechtes Design? Fange gerade erst an mit Qt. Wenn ja, würde ich mich über einen besseren Vorschlag freuen. Ich habe jetzt einen simplen Filtermanager gebaut, der intern mit einer Linked List arbeitet, die die Filterobjekte beinhaltet, und bei der Löschung eines Gliedes dem child Filter statt den eigenen Filter den parent Filter gibt.

    Da ich eh selbstgeschriebene Filter einsetze, kann ich sie natürlich auch auf einem Basisfilter der eine standardmäßige enable(bool) Methode hat, basieren lassen. Allerdings will ich vom Design her von Anfang an verhindern, dass nachher 10000 Filter aufeinander gestapelt werden, von denen nur 8 etwas machen. Die Filter werden später Basisbausteine komplexerer Algorithmen werden, insofern kann das passieren.



  • Es gibt keinen Manager. Seh jetzt auch keinen Bedarf dafür. In 99% der Fälle ist die Filterkette statisch. Wenn sie es mal nicht ist, brauchst du nur zwei Zeilen, um den Zeiger umzuhängen und damit einen Filter rauszunehmen.



  • Joa ich habe mir jetzt nen simplen Manager geschrieben. Warum sind in 99% der Fälle die Filterketten statisch? Entweder bildet mein Anwendungsfall eine 1% Ausnahme, oder mein Design ist nicht ideal. Das würde mich jetzt echt interessieren, da ich neu in QT bin.

    1. Ich habe ein Baummodell, in dem diverse verzweigte Daten gespeichert sind, unter anderem in jedem Eintrag ein Tabellenmodell mit Einträgen. Da bin ich mir immer noch nicht sicher ob das gut ist, aber ich seh irgendwie auch keine Richtung, das Tabellenmodell in das Baummodell zu integrieren, allein wegen anderer header.

    2. Ich biete zwei verschiedene Formen von Basisfiltern an, einer der im Baum filtert, und einer der im Tabellenmodell filtert.

    3. Der User soll in der Lage sein, aus dem Hauptmodell verschiedene Daten gleichzeitig herauszufiltern (Baum oder Tabelle oder beides), und dabei auf eine Vielfalt von Filtern zurückgreifen, und die Reihenfolge festlegen. Er kann auch eigene Filter scripten, und muss die natürlich irgendwie debuggen können, also muss er jederzeit in der Lage sein, ein Filterergebnis anzuschauen oder einen Filter rauszuhauen.

    Das heißt ich komme weder darum herum, eine LinkedList aus den Filtern zu machen, noch FilterPointer in einer extra Liste zu lagern. Oder sehe ich das falsch?



  • Dass 99% der Filterketten das nicht brauchen, heißt noch lange nicht, dass dein Design falsch ist. Du hast eben einen komplexen Anwendungsfall, das ist schon in Ordnung. Meist ist es ja nicht so komplex und nicht dynamisch.
    Wie du dein Baum und Tabellen Modell mischt, habe ich nicht verstanden. Könntest du das genauer erklären?
    Du könntest deinen Manager selber als Modell implementieren. Dann setzt du nur ein einziges Filtermodell und das verwaltet alle anderen Modelle intern und ruft sie auf. Nach außen bietet es z.B. sowas wie void enableFilter(QProxyModel * model) und disableFilter(QProxyModel * model).



  • Die Tabellenmodelle sind Objekte in der Datenstruktur die dem Baummodell unterliegt und von einem Baumeintrag repräsentiert wird. Das Tabellenmodell wird natürlich nicht als Baumeintrag repräsentiert, sondern über einen QModelIndex (aus dem Baummodell) über internalPointer()->tabellenModell() zur Verwendung herangezogen, z.B. um den aktuell selektierten Baumeintrag in einer Tabellenview anzuzeigen.

    Damit bin ich mir unsicher. Ist das wirklich im Sinne von model/view, dass man mehrere Modelle verschachtelt?

    Mein Manager ist bereits ein Listenmodell, in dem die angewendeten Filter aufgelistet sind. Sie sind intern als Linkedlist verknüpft, wenn ein Filter aus dem Speicher geht, werden die umgebenden Filter miteinander verknüpft. Statt nur enable disable bietet mein Filterswitch SHOW_ALL, HIDE_ALL, HIDE_EXCEPT, und SHOW_EXCEPT. So lässt sich der Filter vorübergehend deaktivieren, alles wegfiltern (wohl hauptsächlich für Debugzwecke), und er lässt sich invertieren.



  • Wie ich schon geahnt habe, habe ich mit der Verschachtelung jetzt auch ein konkretes Problem:

    Das Filtern der Tabellenmodelle funktioniert nicht in Abhängigkeit von der Filterung der Baummodelle. Ich kann z. B. mit dem filterManager eine Filterkette bauen wie: BaumModell->Filter1->Filter2 und Filter2 dann als Basismodell für andere Filterketten, Views etc. benutzen. Wäre die Filterung der Tabellenmodelle nur für Views von Belang, wäre die Lösung natürlich, das jeweilig zu bearbeitende Tabellenmodell durch einen Tabellenmodell-filtermanager zu jagen. Allerdings sind die Daten im Baummodell schon teils abhängig von der Häufigkeit der vorhandenen Tabellen. Also müsste die Filterung bereits im Baummodell stattfinden. Also der Zugriff auf das Tabellenmodell über eine tabellenmodell* getMethode(QModelIndex) im Baummodell angeboten werden, die dann den filterManager dazwischenschraubt. Dadurch wäre die Tabellenfilterung aber eben nicht mehr unabhängig in zwei verschiedenen gefilterten Baummodellen möglich.

    Außer wenn ich einen Standardbaumfilter definiere, der einen eigenen Tabellenfiltermanager hat. Der würde dann statt eines Baummodells benutzt, dessen Daten ohne ihn fehlerhaft wären. Das finde ich aber auch hässlich.

    Vielleicht wäre es am sinnvollsten, das Tabellenmodell aus dem Baum herauszunehmen, so dass es nur noch eines gibt, und in dessen Datenstruktur Indizes zu speichern, durch die sich die Einträge dem Baummodell zuordnen lassen. Damit das Baummodell darauf zugreifen könnte, müsste es immer noch einen Pointer zum Tabellenmodell bekommen, womit man ja leben kann.

    Ich bilde mir aber ein dass es besser gehen muss.



  • Wenn ich dich richtig verstehe, hast du Daten, welche du zum einen in einem Baum darstellst und gleichzeitig können diese Daten auch in einer Tabelle dargestellt werden. -> Das gleiche Datenobjekt ist einmal im Baum sichtbar und zusätzlich auch in einer Tabelle. Habe ich das so richtig verstanden?

    Wenn das nicht stimmt, könntest du das ganze etwas genauer aufzeigen?



  • Ich versteh immer noch nicht so ganz, wie du das meinst. Ich würde aber die Zwei Modelle nicht mischen.
    Vielleicht mal ein Beispiel... Deine Objekte sind Excelsheets (Tabellenmodell). Die verwaltest du aber hierarchisch. Die Blätter von dem Baummodell sind die Excelsheets. Aber nicht als Modell. Sind dann wahrscheinlich auch zwei Unterschiedliche Views. Das würde ich soweit schon trennen.
    Evtl. willst du hier einen Filter haben, der sagt, ich will keine Elemente im Baum haben, wo in der dritten Spalte im Excelsheet ein Wert kleiner 10 ist. Das macht nichts, der Filter kennt dann eben die drunterliegenden Businessobjekte, aber trotzdem ist es kein verschachteltes Modell.



  • Mechanics schrieb:

    Ich versteh immer noch nicht so ganz, wie du das meinst. Ich würde aber die Zwei Modelle nicht mischen.
    Vielleicht mal ein Beispiel... Deine Objekte sind Excelsheets (Tabellenmodell). Die verwaltest du aber hierarchisch. Die Blätter von dem Baummodell sind die Excelsheets. Aber nicht als Modell. Sind dann wahrscheinlich auch zwei Unterschiedliche Views. Das würde ich soweit schon trennen.
    Evtl. willst du hier einen Filter haben, der sagt, ich will keine Elemente im Baum haben, wo in der dritten Spalte im Excelsheet ein Wert kleiner 10 ist. Das macht nichts, der Filter kennt dann eben die drunterliegenden Businessobjekte, aber trotzdem ist es kein verschachteltes Modell.

    Wie soll der Filter auf die Daten des Modells, welches er filtert, zugreifen?
    Über QModelIndex.internalPointer()? Dann wäre das keine schlechte Idee...

    Trotzdem ist mein Problem, dass das Baummodell so gedacht war, dass es bereits gefilterte Werte der "Businessmodelle" auswertet. Diese Vorabfilterung habe ich jetzt auch implementieren können, aber nicht sehr elegant.

    Verschachtelte Modelle sind ganz klar gegen das Design von Model View. Ein Modell in einem Modell macht das erste Modell schon zu einer Art View.
    Das ist eigentlich schade, weil es einen dazu zwingt, komplexe Datenstrukturen flach zu machen und viele Indextabellen anzulegen.

    Alternativ kann man natürlich seine Datenstrukturen unabhängig von QT Designen, und und Dinge wie z.B. Filterfunktionen selbst einbauen. So entwickelt man leider nicht from-the-top.

    Ich kann mir zahlreiche Ansätze für ein verschachteltes Model System vorstellen und es muss auch gehen. Wenn ein Modell eine Datenstruktur repräsentieren soll, muss es in er Lage sein, geschachtelt genauso zu funktionieren wie ohne Schachtelung.



  • Hobo schrieb:

    Wie soll der Filter auf die Daten des Modells, welches er filtert, zugreifen?
    Über QModelIndex.internalPointer()? Dann wäre das keine schlechte Idee...

    Das würde ich eher im Modell kapseln. Sagen wir, deine eigentliche Klasse heißt ExcelSheet. Und das Modell heißt ExcelSheetModell. Dann gibts z.B. noch einen ExcelSheetModelColumnFilter oder wie auch immer. Das ist von QProxyModel abgeleitet und kennt das drunterliegende ExcelSheetModel. Das hat widerum eine Methode wie

    ExcelSheet * getExcelSheet(const QModelIndex& index) const;
    

    Intern kann sie dann z.B. den internalPointer benutzen. Ich mache das normalerweise anders, weil ich den internalPointer eh schon brauche, um interne Strukturen des Modells zu speichern. Diese internen Strukturen verweisen dann wiederum auf die Businessobjekte (und haben dann weitere Daten, die ich z.B. für Lazy Loading oder Caching oder die Baumverwaltung brauche).

    Hobo schrieb:

    Trotzdem ist mein Problem, dass das Baummodell so gedacht war, dass es bereits gefilterte Werte der "Businessmodelle" auswertet.

    Das versteh ich widerum nicht ganz 😉


Anmelden zum Antworten