Я пытаюсь создать файловый браузер, который будет группировать последовательные файлы в одном и том же каталоге вместе в виде дерева. Например, если в каталоге были следующие файлы: 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_())