Switching between QFileSystemModel filters

Viewed 25

The contents of QFileSystemModel are displayed in a QTreeView, and I want to switch between listing folders only and files only in the current directory. It is first initialized with a filter for folders model.setFilter(QDir.Dirs | QDir.NoDotAndDotDot). Then, when setting the filter for files QDir.Files | QDir.NoDotAndDotDot, the first folder that was displayed before is still shown. I figured it had to do with the first item being the view's currentIndex, so adding view.setCurrentIndex(QModelIndex()) does fix that. However, if a folder is selected and then the filter is switched for displaying files only, that folder will still be shown, even when calling view.clearSelection() right before. (And I would like to keep the selection mode on SingleSelection).

I was wondering if QFileSystemModel was not intended to be used that way, and setFilter should only be used once, or if there is a solution. If I create a new model every time I want to change the filter then it does work properly, but I can't imagine that's the best usage either.

Ultimately, I'll be using a proxy model for other custom filtering. Trying this with a default QSortFilterProxyModel does not update the contents at all when the filter is changed, it only shows the folders. If I include QDir.AllDirs in the filter, as instructed in the docs, it does seem to update the contents correctly. But that option will include folders and files together, when I just want to show files.

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class Model(QWidget):

    def __init__(self):
        super().__init__()
        model = QFileSystemModel()
        model.setFilter(QDir.Dirs | QDir.NoDotAndDotDot | QDir.AllDirs)
        model.setRootPath(QDir.rootPath())
        self.view = QTreeView(uniformRowHeights=True, itemsExpandable=False, rootIsDecorated=False)
        self.view.setModel(model)
        self.view.setRootIndex(model.index(QDir.currentPath()))
        grid = QGridLayout(self)
        grid.addWidget(self.view, 0, 0, 1, 2)
        grid.addWidget(QRadioButton('Folders', checked=True), 1, 0, Qt.AlignRight)
        grid.addWidget(QRadioButton('Files', toggled=self.changefilter), 1, 1)

    def changefilter(self, checked):
        self.view.clearSelection()
        self.view.setCurrentIndex(QModelIndex())
        model = self.view.model()
        if checked:
            model.setFilter(QDir.Files | QDir.NoDotAndDotDot)# | QDir.AllDirs)
        else:
            model.setFilter(QDir.Dirs | QDir.NoDotAndDotDot | QDir.AllDirs)


class ModelWithProxy(QWidget):

    def __init__(self):
        super().__init__()
        model = QFileSystemModel()
        model.setFilter(QDir.Dirs | QDir.NoDotAndDotDot | QDir.AllDirs)
        model.setRootPath(QDir.rootPath())
        proxy = QSortFilterProxyModel()
        proxy.setSourceModel(model)
        self.view = QTreeView(uniformRowHeights=True, itemsExpandable=False, rootIsDecorated=False)
        self.view.setModel(proxy)
        self.view.setRootIndex(proxy.mapFromSource(model.index(QDir.currentPath())))
        grid = QGridLayout(self)
        grid.addWidget(self.view, 0, 0, 1, 2)
        grid.addWidget(QRadioButton('Folders', checked=True), 1, 0, Qt.AlignRight)
        grid.addWidget(QRadioButton('Files', toggled=self.changefilter), 1, 1)

    def changefilter(self, checked):
        self.view.clearSelection()
        self.view.setCurrentIndex(QModelIndex())
        proxy = self.view.model()
        model = proxy.sourceModel()
        if checked:
            model.setFilter(QDir.Files | QDir.NoDotAndDotDot)# | QDir.AllDirs)
        else:
            model.setFilter(QDir.Dirs | QDir.NoDotAndDotDot | QDir.AllDirs)
        

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = QWidget()
    hbox = QHBoxLayout(window)
    hbox.addWidget(Model())
    hbox.addWidget(ModelWithProxy())
    window.show()
    sys.exit(app.exec_())

I reproduced this behavior with several versions up to PyQt5 5.15 on both Windows and macOS.

0 Answers
Related