Qt custom QFileSystemModel для группировки последовательных файлов - PullRequest
0 голосов
/ 11 марта 2020

Я пытаюсь создать файловый браузер, который будет группировать последовательные файлы в одном и том же каталоге вместе в виде дерева. Например, если в каталоге были следующие файлы: img.001.png img.002.png img.003.png, изображения 2 и 3 будут отображаться как дочерние элементы изображения 1 в QTreeView. Они просто стали бы потомками первого последовательного элемента в каталоге.

Я пробовал несколько способов выполнить sh, но до сих пор производительность была огромной проблемой. Делать все это вручную с помощью модуля QStandardItemModel и python os было очень медленно и громоздко. QFileSystemModel на удивление быстр и включает в себя множество удобных функций для переименования файлов и т. Д. c, поэтому я пытаюсь использовать его в качестве своей базы. Я попытался создать QStandardItemModel в качестве своего рода «прокси-модели», которая перебирала QFileSystemModel при изменении директории root. Это позволило мне создать всю необходимую функциональность, но шокирующе медленно (я думаю, что под капотом много сигналов или что-то в этом роде?). Установка root dir в FileSystemModel практически не занимает много времени, но с пользовательской моделью, выполняющей итерации по строкам и повторной интерпретации данных, это может занять 5-10 секунд для одной папки с 1000+ файлами.

Так что я Я думаю, что лучшим решением было бы создать подкласс QFileSystemModel напрямую, потому что он имеет встроенные методы, которые я хочу, и молниеносно. Однако я не очень разбираюсь в моделях и не совсем уверен, с чего начать. Я вижу, что есть довольно много сигналов, которые могут уведомить меня, когда строки будут вставлены, были вставлены, перемещаются, и т. Д. c, и т. c. Но в какой момент я смогу проверить, была ли строка последовательным файлом, и если это так, «перенаправить» ее на дочерний элемент другого индекса?

Надеюсь, все ясно, вот фрагмент, чтобы встать и бежать. Я обычно не публикую такие общие вопросы по SO, но я потратил много времени на эту проблему и мне нужно какое-то направление относительно того, где go. Мне не нужно, чтобы вы написали мой код для меня, но было бы очень полезно указать мне правильное направление!

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_())
...