Qt自定义QFileSystemModel对顺序文件进行分组

2024-04-25 17:52:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个文件浏览器,它将同一控制器中的顺序文件以树状视图组合在一起。例如,如果目录中有以下文件:img.001.png{}{},则图像2&;3将在QTreeView中显示为图像1的子对象。它们只是目录中第一个连续项的子项

我尝试了很多方法来实现这一点,但到目前为止,性能一直是一个巨大的问题。使用QStandarItemModel和python os模块手动完成这一切非常缓慢和繁琐。QFileSystemModel出人意料地快,包括大量用于重命名文件等的方便函数,因此我尝试将其作为我的基础。我尝试创建一个QStandardItemModel作为一种“代理模型”,当根目录发生变化时,它会在QFileSystemModel上迭代。这使我能够创建我所需要的所有功能,但速度惊人地慢(我猜引擎盖下有很多信号还是什么的?)。在FileSystemModel中设置根目录几乎不需要时间,但是对于一个包含1000多个文件的文件夹,使用自定义模型迭代行并重新解释数据可能需要5-10秒

所以我认为最好的解决方案是直接将QFileSystemModel子类化,因为它有我想要的内置方法,而且速度非常快。然而,我对模型了解不多,我也不太确定从哪里开始。我看到有相当多的信号可以通知我何时将要插入行、已插入行、正在移动行等等。但在什么时候我才能检查一行是否是顺序文件,如果是,则“重新定向”为另一个索引的子行

希望这一切都清楚了,这里有一个片段可以启动并运行。我通常不会在SO上发布这样的一般性问题,但我在这个问题上花了很多时间,并且需要一些方向,以确定去哪里。我不需要你为我写代码,但是给我指出正确的方向会非常有帮助

import sys, os, re
from PyQt5 import QtWidgets

class TestApp(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()

        self.tree = QtWidgets.QTreeView(self)

        self.model = QtWidgets.QFileSystemModel()
        self.proxyModel = ProxyModel(self.model)
        self.tree.setModel(self.proxyModel)
        self.model.setRootPath("test/dir/with/lots/of/files")
        self.model.directoryLoaded.connect(self.update)

    def update(self):
        self.proxyModel.update_model_from_source()

class ProxyModel(QtGui.QStandardItemModel):
    def __init__(self, sourceModel):
        super().__init__()
        self.sourceModel = sourceModel

    def update_model_from_source(self):
        self.removeRows(0, self.rowCount())

        self.sourceModel.sort(0, QtCore.Qt.AscendingOrder)

        candidates = {}

        parent = self.sourceModel.index(self.sourceModel.rootPath())
        for row in range(self.sourceModel.rowCount(parent)):
            index = self.sourceModel.index(row, 0, parent)
            filename = self.sourceModel.fileName(index)

            file_item = QtGui.QStandardItem(filename)
            file_item.setIcon(self.sourceModel.fileIcon(index))
            filetype = QtGui.QStandardItem(self.sourceModel.type(index))
            date = QtGui.QStandardItem(self.sourceModel.lastModified(index).toString("yyyy-MM-dd h:mm.ss")))
            size = QtGui.QStandardItem(str(self.sourceModel.size(indes)))

            # check for sequences
            sequence = False
            if not self.sourceModel.isDir(index):
                search_str = os.path.splitext(filename)[0]
                matches = re.search(r'([0-9]+)$', search_str)
                if matches:
                    candidate = filename[0:matches.start(0)]

                    if candidate in candidates:
                        parent_item = candidates[candidate]
                        sequence = True
                    else:
                        candidates[candidate] = file_item

            row = [file_item, filetype, date, size]
            if sequence:
                parent_item.appendRow(row)
            else:
                self.appendRow(row)


if __name__ == "__main__":
    app = QtWidgets.QApplication()
    ex = TestApp()
    ex.show()
    sys.exit(app.exec_())

Tags: 文件selfindexmodelifinitdefupdate