Seite 1 von 1

QTreeView mit QSortFilterProxyModell

Verfasst: 20. Oktober 2009 11:42
von Yukirin
Hallo

Seit knapp einer Woche arbeite ich nun mit QT4.5.2.

Ich möchte in einem QTreeView meine Windows Ordnerstruktur darstellen.
Allerdings sollen nicht alle Ordner und Unterordner angezeigt werden, sondern nur die Ordner die zu einem Ordner mit Namen „Test“ führen.

Z.B. Das ist die Ordnerstruktur:

C:
--Ordner1
--Ordner2
----Ordner 2.1
----Ordner 2.2
------Ordner XY
------Test
----Ordner 2.3
--Ordner3
D:
F:
H:
--Ordner1
----Test
----Ordner XYZ
--Ordner2


In meinem TreeView soll aber dann nur das angezeigt werden:

C:
--Ordner2
----Ordner 2.2
------Test
H:
--Ordner 1
----Test


Ich habe ein QFileSystemModel einer abgeleiteten Klasse von QSortFilterProxyModel zugewiesen und das QSortFilterProxyModel einem QTreeView zugewiesen.

Die Funktion filterAcceptsRow des QSortFilterProxyModel habe ich überschrieben und damit kann man ja auch bevor das TreeView angezeigt wird durch alle Knoten gehen und prüfen ob der Knoten "Test" heißt oder nicht, aber ich muss ja dann wieder zu den Elterknoten hoch um diese zuzulassen oder nicht.

Also möchte ich mein Model vor der Anzeige im TreeView durchgehen und prüfen ob es eben den Ordner "Test" gibt und mit Rückgabewerten an die Elternknoten entscheiden ob sie angezeigt werden müssen oder nicht.

Aber es gelingt mir nicht das QSortFilterProxyModel so zu durchlaufen.

Hat evtl jemand einen Tipp für mich?
Mit der Suche hab ich zwar einige Dinge gefunden, aber nichts was mir meiner Meinung nach bei meinem Problem weiterhelfen würde.

Grüße Yukirin

Verfasst: 20. Oktober 2009 12:06
von archer
Ich habe das so gemacht, vielleicht hilft es dir:

Code: Alles auswählen

//----------------------------------------------------------------------------------------
// filterAcceptsRow()                                                       [ protected ]
//----------------------------------------------------------------------------------------
/*!
 * @brief       Reihe filtern
 *
 * @param[in]   aSourceRow       - Reihe
 * @param[in]   acrSourceParent  - Modell-Index
 *
 * @return      @c true Anzeigen, @c false nicht anzeigen
 */
//----------------------------------------------------------------------------------------
bool MyProxyModel::filterAcceptsRow(
        int                aSourceRow,
        const QModelIndex& acrSourceParent) const
{
    if (filterRegExp().isEmpty() == true)
        return true;

    return search(sourceModel()->index(aSourceRow, 0, acrSourceParent));
}


//----------------------------------------------------------------------------------------
// search()                                                                 [ protected ]
//----------------------------------------------------------------------------------------
/*!
 * @brief       Den Baum rekursiv durchgehen
 *
 * @param[in]   acrSourceIndex   - Index der überprüft wird
 *
 * @return      @c true: Index anzeigen, @c false: nicht anzeigen
 */
//----------------------------------------------------------------------------------------
bool MyProxyModel::search(const QModelIndex& acrSourceIndex) const
{
    if (acrSourceIndex.isValid())
    {
        QString itemValue("");
        itemValue = sourceModel()->data(acrSourceIndex, Qt::DisplayRole).toString();

        if (itemValue.contains(filterRegExp()) == true)
            return true;

        if (sourceModel()->hasChildren(acrSourceIndex) == true)
        {
            for (int i = 0; i < sourceModel()->rowCount(acrSourceIndex); i++)
            {
                QModelIndex idx(sourceModel()->index(i, 0, acrSourceIndex));
                if (search(idx) == true)
                    return true;
            }
        }
    }
    return false;
}

Verfasst: 20. Oktober 2009 12:17
von RHBaum
DU kommst per "QAbstractItemModel * sourceModel () const" immer auf das Basis(Source)Model zurueck.

aus filterAcceptsRow heraus, solltest das BasisModel fragen, ob es subelemente hat .... und ob diese subelemente irgendwas mit dem namen "test" selber enthalten (rekursion!)
fuer das Abfragen sollstest dich gegenueber dem SourceModel verhalten wie nen View und die methoden des QAbstractItemModel - Interfaces verwenden.

ups, zu spaet :-)
Archer macht es Sir ja wieder zu einfach :-)

Ciao ....

Verfasst: 20. Oktober 2009 14:06
von Yukirin
Vielen Dank für eure schnellen und ausführlichen Antworten. Ich werd das gleich mal versuchen.

Danke :D

Verfasst: 21. Oktober 2009 14:19
von Yukirin
Hallo

Nun muss ich dazu doch noch mal ne Frage stellen.

Ich hab mir jetzt ne eigene Funktion geschrieben, die von „filterAcceptsRow()“ aufgerufen wird.
In dieser Funktion habe ich einen „const QModelIndex& Knoten“,
für den dann überprüft werden soll, ob es einen Unterknoten „Test“ gibt.

Ich rufe die Funktion „sourceModel()->hasChildren(Knoten)“ auf, die mir true zurückliefert und sagt, dass der Knoten Unterknoten hat. Wenn ich jetzt aber eine Zeile später die Funktion „sourceModel ()->rowCount(Knoten)“ aufrufe, sagt mir die Funktion das die Anzahl 0 ist.

So kann ich die Funktion also nicht noch mal für die Unterknoten aufrufen. Es ist mir nun aber absolut schleierhaft, warum die Funktion „rowCount()“ mir sagt, dass es keine Unterknoten gibt.

Habt ihr evtl eine Idee dazu?

Verfasst: 21. Oktober 2009 14:26
von archer
Schau dir mal die Dokumentation zu QFileSystemModel an.
Calls to rowCount() will return 0 until the model populates a directory.
Vielleicht hat das mit deinem Problem zutun.

Verfasst: 22. Oktober 2009 11:52
von Yukirin
Hallo

Ich habe mir die Doku zu dem QFileSystemModel angeschaut. Und das rowCount gibt dann wohl 0 zurück, weil ich es an einer Stelle aufrufe wo das Model noch mit Ordnern bestückt wird. Verstehe ich das richtig? Also muss ich meine Funktion zum Durchgehen der Ordner wann anders aufrufen.

FilterAcceptsRows wird ja aufgerufen bevor das TreeView angezeigt wird und da rufe ich dann auch meine Suchfunktion auf. Und das scheint ja kein guter Zeitpunkt zu sein. Aber wenn mein TreeView angezeigt wird, ist es schon zu spät nach den Ordnern zu suchen und zu filtern.

Ich hab es nun mit einem QDirModel statt eines QFileSystemModels probiert. Da funtkioniert das mit dem rowCount ja an der Stelle.

Aber das QFileSystemModel scheint ja schneller zu sein als das QDirModell.
Wenn ich das QDirModell verwende muss der Anwender ewig warten, bevor ihm das Fenster mit dem TreeView angezeigt wird.

Also möchte ich doch wieder auf QFileSystemModel umsteigen.
Aber wann muss ich denn dann meine Funktion aufrufen, damit rowCount nicht 0 anzeigt?

Ich bin ratlos. :(

Verfasst: 22. Oktober 2009 12:13
von archer
Hast das schon mal ohne ein Proxymodel mit den Filterfunktionen von QFileSystemModel versucht. Ich selber habe noch nicht mit QFileSystemModel gearbeitet. aber man kann dort Filter vorgeben.

Code: Alles auswählen

void setFilter ( Filters filters )
void setNameFilters ( const QStringList & nameFilters )