簡體   English   中英

PySide6 上的自定義文件瀏覽器實現

[英]Custom file browser implementation on PySide6

我想在 PySide6 上實現文件瀏覽器,我的目標是:

  1. 始終在頂部顯示帶有..的文件和文件夾(無論排序如何),以便用戶可以雙擊它並將 go 上一級。
  2. 之后..我想顯示文件夾,然后是文件(就像 Windows 資源管理器一樣),無論排序如何。
  3. 有一個顯示特定文件集的替代顯示模式(它們可以位於不同的驅動器、不同的文件夾等)。

我目前正在使用以下代碼來初始化 model 和視圖:

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. 如果您認為有更好的方法來解決這個問題,請描述它。
    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的索引映射

以下解決方案有效:

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

初始化視圖和 model 的代碼與@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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM