Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to fix QSortFilterProxyModel() with QFileSystemModel() for sorting by size or date?



  • Here's the problem. I'm using QFileSystemModel() with the custom implementation of QSortFilterProxyModel() that does some sorting inside the folder (keeps .. at the top, etc.)
    The problem is that QSortFilterProxyModel() doesn't correctly sort by file size or date - it uses the string representations instead of the actual size and date values.

    Here's the example:

    from PySide6.QtCore import *
    from PySide6.QtGui import *
    from PySide6.QtWidgets import *
    
    if __name__ == '__main__':
        class Dialog(QDialog):
            def __init__(self, parent=None):
                super(Dialog, self).__init__(parent)
                self.initUI()
                self.model = QFileSystemModel()
                self.model.setRootPath(".")
                self.sorting_model = QSortFilterProxyModel()          
                self.sorting_model.setSourceModel(self.model)
    
                # self.view.setModel(self.model)
                self.view.setModel(self.sorting_model)
                # self.view.setRootIndex(self.model.index("."))            
                self.view.setRootIndex(self.sorting_model.mapFromSource(self.model.index(".")))
    
                self.view.setSortingEnabled(True)
                self.view.setRootIsDecorated(False)
    
            def initUI(self):
                self.view = QTreeView(self)
                self.view.setWindowTitle('Simple Tree Model')
                self.view.setGeometry(10, 10, 600, 400)
                self.setGeometry(300, 300, 920, 620)
    
        import sys
    
        app = QApplication(sys.argv)
        dialog = Dialog()
        dialog.show()
        sys.exit(app.exec_())
    

    In this example sorting won't work fine for date and size. If you switch to using self.model instead of self.sorting model (comment/uncomment in the section in the middle) you'll see that sorting by date and size works fine with plain QFileSystemModel().

    How to make it work the same way with QSortFilterProxyModel()? I tried implementing sort() function and calling self.sourceModel().sort(column, order), but it didn't fully work.

    Thanks.


  • Lifetime Qt Champion

    Hi,

    I would go with reading the implementation of QFileSystemModel to see how it is done there.

    By the way, do you have the same result with PySide2 ?



  • @SGaist It's the same in PySide2 and PySide6.
    I know a possible workaround: I could slightly modify the data() function of my implementation of QFileSystemModel() so that it returns sizes as int and dates in unified format then inside lessThan() of QSortFilterProxyModel() I could convert date string to date using QDateTime.fromString() and sort by them, but that would be quite inelegant.



  • I ended up with this solution (in lessThan() code of my proxy model):

    # size
    if source_left.column() == 1:
        return self.sourceModel().size(source_left) < self.sourceModel().size(source_right)
    
    # date
    if source_left.column() == 3:
        return self.sourceModel().lastModified(source_left).__le__(self.sourceModel().lastModified(source_right))
    

    By the way, not sure if it's enough to check the column number of source_left only. Should I also check the column number of source_right?



  • @midnightdim
    Yes, this is the correct way to compare sizes or dates.

    You may assume Qt infrastructure will only call lessThan() with source_left.column() == source_right.column(). You can put in an assert source_left.column() == source_right.column() to verify.


Log in to reply