0

我想在 PySide6 上实现文件浏览器,我的目标是:

  1. 始终在顶部显示文件和文件夹..(无论排序如何),以便用户可以双击它并上一级。
  2. ..我想显示文件夹然后显示文件(就像 Windows 资源管理器一样)之后,不管排序如何。
  3. 有一个显示特定文件集的替代显示模式(它们可以位于不同的驱动器、不同的文件夹等)。

我目前正在使用以下代码来初始化模型和视图:

self.model = QFileSystemModel()
self.model.setRootPath(path)
self.model.setFilter(QDir.NoDot | QDir.AllEntries)
self.model.sort(0,Qt.SortOrder.AscendingOrder)
self.ui.treeView.setModel(self.model)
self.ui.treeView.setRootIndex(self.model.index(path))
self.ui.treeView.header().setSortIndicator(0, Qt.AscendingOrder)
self.ui.treeView.setSortingEnabled(True)

而不是 QFileSystemModel() 我实际上使用的是我的自定义 QFileSystemModel 和一个附加列。

我遇到的问题是:

  • ..与其他内容一起排序,不会出现在顶部
  • 排序后目录不停留在顶部

我不明白我正在解决的问题的最佳方法是什么。

我看到以下选项:

  • 使用 QSortFilterProxyModel 并以某种方式强制..始终位于顶部,无论排序(不确定是否可能)并且还首先保留目录(有一个相关的问题),我也可以将它用于上面的第 3 点以按某些标准显示文件
  • 使用完全不同的方法,可能是我将手动填写的 QFileSystemWatcher 或 QTreeWidget(..始终保持在最前面似乎在任何情况下都会造成麻烦)。
  • 加载或排序后以某种方式添加..到 QTreeView 的顶部

我尝试实现 QSortFilterProxyModel,但遇到了另一个问题:我不明白应该如何修改treeView.setRootIndex()调用。

所以我的具体问题是:

  1. 我可以使用 QSortFilterProxyModel 来解决上面提到的所有问题吗?如果是,请提供示例实现。
  2. 如果您认为有更好的方法来解决这个问题,请描述它。
4

2 回答 2

1

以下解决方案有效:

class SortingModel(QSortFilterProxyModel):
    def lessThan(self, source_left: QModelIndex, source_right: QModelIndex):
        file_info1 = self.sourceModel().fileInfo(source_left)
        file_info2 = self.sourceModel().fileInfo(source_right)       
        
        if file_info1.fileName() == "..":
            return self.sortOrder() == Qt.SortOrder.AscendingOrder

        if file_info2.fileName() == "..":
            return self.sortOrder() == Qt.SortOrder.DescendingOrder
                
        if (file_info1.isDir() and file_info2.isDir()) or (file_info1.isFile() and file_info2.isFile()):
            return super().lessThan(source_left, source_right)

        return file_info1.isDir() and self.sortOrder() == Qt.SortOrder.AscendingOrder

初始化视图和模型的代码与@bartolo-otrit 答案中的代码相同:

    model = QFileSystemModel()
    model.setRootPath('.')
    model.setFilter(QDir.NoDot | QDir.AllEntries)
    model.sort(0, Qt.SortOrder.AscendingOrder)
    sorting_model = SortingModel()
    sorting_model.setSourceModel(model)
    view.tree_view.setModel(sorting_model)
    view.tree_view.setRootIndex(sorting_model.mapFromSource(model.index('.')))
    view.tree_view.header().setSortIndicator(0, Qt.AscendingOrder)
    view.tree_view.setSortingEnabled(True)
于 2021-02-16T12:42:11.663 回答
1
    import PySide2
    from PySide2 import QtWidgets
    from PySide2.QtWidgets import QFileSystemModel
    from PySide2.QtWidgets import QMainWindow, QWidget
    from PySide2.QtWidgets import QTreeView
    from PySide2.QtWidgets import QVBoxLayout
    from PySide2.QtCore import QDir
    from PySide2.QtCore import QSortFilterProxyModel
    from PySide2.QtCore import Qt

    class View(QMainWindow):
        def __init__(self):
            super().__init__()

            self._w_main = QWidget()
            self.setCentralWidget(self._w_main)
            self.tree_view = QTreeView(self._w_main)

            self._layout = QVBoxLayout()
            self._layout.addWidget(self.tree_view)
            self._w_main.setLayout(self._layout)

    class SortingModel(QSortFilterProxyModel):
        def lessThan(
                self,
                source_left: PySide2.QtCore.QModelIndex,
                source_right: PySide2.QtCore.QModelIndex
        ):
            file_info1 = self.sourceModel().fileInfo(source_left)
            file_info2 = self.sourceModel().fileInfo(source_right)

            if file_info1.isDir() and file_info2.isDir():
                return super().lessThan(source_left, source_right)
            return file_info1.isDir()

    app = QtWidgets.QApplication([])
    view = View()
    model = QFileSystemModel()
    model.setRootPath('.')
    model.setFilter(QDir.NoDot | QDir.AllEntries)
    model.sort(0, Qt.SortOrder.AscendingOrder)
    sorting_model = SortingModel()
    sorting_model.setSourceModel(model)
    view.tree_view.setModel(sorting_model)
    view.tree_view.setRootIndex(sorting_model.mapFromSource(model.index('.')))
    view.tree_view.header().setSortIndicator(0, Qt.AscendingOrder)
    view.tree_view.setSortingEnabled(True)
    view.showMaximized()
    return sys.exit(app.exec_())

QSortFilterProxyModel在我的机器上默认放在列表..的顶部。PySide2 5.14.1

mapFromSource用于索引映射setRootIndex

于 2021-02-16T10:38:25.260 回答