具有按日期排序的代理模型的 QFileDialog 实际上使用日期的字母顺序

QFileDialog with proxy model sort by date actually uses alphabetical order of date

在 PyQt 5.11.2(在 Windows 10)中,设置了 DontUseNativeDialog 选项的 QFileDialog 在按 'Date Modified' 列排序时有一个错误:它不按实际日期排序 - 它按非零填充的 MM-DD-YYYY 字符串按字母顺序排序,这意味着 9-12-2018 显示为比 12-12-2018 更新。 有解决方法或修复方法吗?

本机对话框确实按日期正确排序,但是,使用非本机对话框的动机是本机对话框不遵守 fileDialog.setProxyModel(用于通过更复杂的正则表达式规则过滤掉某些文件),描述了 here and ,我认为文档中的这一行详细说明/暗示了这一点:

By default, a platform-native file dialog will be used if the platform has one. In that case, the widgets which would otherwise be used to construct the dialog will not be instantiated, so related accessors such as layout() and itemDelegate() will return null. You can set the DontUseNativeDialog option to ensure that the widget-based implementation will be used instead of the native dialog.

代码:通过调用 self.load()(无参数)生成对话框

def load(self,fileName=None):
    if not fileName:
        fileDialog=QFileDialog()
        fileDialog.setOption(QFileDialog.DontUseNativeDialog)
        fileDialog.setProxyModel(CSVFileSortFilterProxyModel(self))
        fileDialog.setNameFilter("CSV Radio Log Data Files (*.csv)")
        fileDialog.setDirectory(self.firstWorkingDir)
        if fileDialog.exec_():
            fileName=fileDialog.selectedFiles()[0]

... 和整个 CSVFileSortFilterProxyModel class 只有一个功能:

# code for CSVFileSortFilterProxyModel partially taken from
#  https://github.com/ZhuangLab/storm-control/blob/master/steve/qtRegexFileDialog.py
class CSVFileSortFilterProxyModel(QSortFilterProxyModel):
    def __init__(self,parent=None):
#       print("initializing CSVFileSortFilterProxyModel")
        super(CSVFileSortFilterProxyModel,self).__init__(parent)

    # filterAcceptsRow - return True if row should be included in the model, False otherwise
    #
    # do not list files named *_fleetsync.csv or *_clueLog.csv
    #  do a case-insensitive comparison just in case
    def filterAcceptsRow(self,source_row,source_parent):
#       print("CSV filterAcceptsRow called")
        source_model=self.sourceModel()
        index0=source_model.index(source_row,0,source_parent)
        # Always show directories
        if source_model.isDir(index0):
            return True
        # filter files
        filename=source_model.fileName(index0).lower()
#       filename=self.sourceModel().index(row,0,parent).data().lower()
#       print("testing lowercased filename:"+filename)
        # never show non- .csv files
        if filename.count(".csv")<1:
            return False
        if filename.count("_fleetsync.csv")+filename.count("_cluelog.csv")==0:
            return True
        else:
            return False

问题是由自定义的QSortFilterProxyModel引起的,因为在lessThan方法中,值是字符串,解决方法是转换为适合比较的类型:

class CSVFileSortFilterProxyModel(QtCore.QSortFilterProxyModel):
    def filterAcceptsRow(self,source_row,source_parent):
        source_model = self.sourceModel()
        index0=source_model.index(source_row,0,source_parent)
        if source_model.isDir(index0):
            return True
        filename = source_model.fileName(index0).lower()
        if filename.count(".csv")<1:
            return False
        return filename.count("_fleetsync.csv")+filename.count("_cluelog.csv") == 0

    def lessThan(self, left, right):
        source_model = self.sourceModel()

        if left.column() == right.column() == 1: 
            if source_model.isDir(left) and not source_model.isDir(right):
                return True
            return source_model.size(left) < source_model.size(right)

        if left.column() == right.column() == 2:
            return source_model.type(left) < source_model.type(right)

        if left.column() == right.column() == 3:
            return source_model.lastModified(left) < source_model.lastModified(right)
        return super(CSVFileSortFilterProxyModel, self).lessThan(left, right)

@ekhumoro 所示,一个更简单的选项是覆盖代理排序:

class CSVFileSortFilterProxyModel(QtCore.QSortFilterProxyModel):
    def filterAcceptsRow(self,source_row,source_parent):
        source_model = self.sourceModel()
        index0=source_model.index(source_row,0,source_parent)
        if source_model.isDir(index0):
            return True
        filename = source_model.fileName(index0).lower()
        if filename.count(".csv")<1:
            return False
        return filename.count("_fleetsync.csv")+filename.count("_cluelog.csv") == 0

    def sort(self, column, order):
        self.sourceModel().sort(column, order)