gpt4 book ai didi

python - 如何更新 QFileSystemModel 中的文件信息?

转载 作者:行者123 更新时间:2023-12-01 09:33:47 39 4
gpt4 key购买 nike

首先,这个问题与另一个问题类似QFileSystemModel not updating when files change与本例的主要区别是,我不想每次更新我的文件之一时都替换整个模型。

在现实世界的示例中,我的应用程序将打开几个文件,所以我基本上只是想了解如何更新一个特定 QFileSystemModel 项目的信息(大小、修改日期),下面有一些 mcve 可以玩正如您在该代码中看到的那样,我尝试使用 setData 失败了:

import sys
import os

from PyQt5.Qt import * # noqa


class DirectoryTreeWidget(QTreeView):

def __init__(self, path=QDir.currentPath(), *args, **kwargs):
super().__init__(*args, **kwargs)

self.init_model(path)
self.expandsOnDoubleClick = False
self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
self.setAutoScroll(True)

def init_model(self, path):
self.extensions = ["*.*"]
self.path = path
model = QFileSystemModel(self)
model.setRootPath(QDir.rootPath())
model.setReadOnly(False)
model.setFilter(QDir.AllDirs | QDir.NoDot | QDir.AllEntries)
self.setModel(model)
self.set_path(path)

def set_path(self, path):
self.path = path
model = self.model()
index = model.index(str(self.path))

if os.path.isfile(path):
self.setRootIndex(model.index(
os.path.dirname(str(self.path))))
self.scrollTo(index)
self.setCurrentIndex(index)
else:
self.setRootIndex(index)


class Foo(QWidget):

def __init__(self, path):
super().__init__()

self.path = path

self.tree_view = DirectoryTreeWidget(path=".")
self.tree_view.show()
bt = QPushButton(f"Update {path}")
bt.pressed.connect(self.update_file)

layout = QVBoxLayout()
layout.addWidget(self.tree_view)
layout.addWidget(bt)

self.setLayout(layout)

# New file will automatically refresh QFileSystemModel
self.create_file()

def create_file(self):
with open(self.path, "w") as f:
data = "This new file contains xx bytes"
f.write(data.replace("xx", str(len(data))))

def update_file(self):
model = self.tree_view.model()

# Updating a file won't refresh QFileSystemModel, the question is,
# how can we update that particular item to be refreshed?
data = "The file updated is much larger, it contains xx bytes"
with open(self.path, "w") as f:
f.write(data.replace("xx", str(len(data))))

# file_info = self.obj.model.fileInfo(index)
# file_info.refresh()
index = model.index(self.path)
model.setData(index, model.data(index))
QMessageBox.about(None, "Info", f"{self.path} updated, new size is {len(data)}")


def main():
app = QApplication(sys.argv)
foo = Foo("foo.txt")
foo.setMinimumSize(640, 480)
foo.show()
sys.exit(app.exec_())


if __name__ == "__main__":
main()

所以问题是,如何实现 update_file 更新该特定文件 foo.txt 的信息?

目标是仅更新该文件,而不替换整个模型,如图 here 所示,而且一旦该模型项目更新,该项目根本不会在 View 中排序/移动,那就太好了。

最佳答案

Qt v5.9.4 引入了环境变量 QT_FILESYSTEMMODEL_WATCH_FILES 来解决 QTBUG-46684 ,您可以在changelog中阅读更多相关信息。 :

QTBUG-46684 It is now possible to enable per-file watching by setting the environment variable QT_FILESYSTEMMODEL_WATCH_FILES, allowing to track for example changes in file size.

因此,要使示例正常工作,您只需将 envar 设置为非空值一次,即:

import sys
import os

from PyQt5.Qt import * # noqa


class DirectoryTreeWidget(QTreeView):

def __init__(self, path=QDir.currentPath(), *args, **kwargs):
super().__init__(*args, **kwargs)

self.init_model(path)
self.expandsOnDoubleClick = False
self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
self.setAutoScroll(True)

def init_model(self, path):
os.environ["QT_FILESYSTEMMODEL_WATCH_FILES"] = '1'

self.extensions = ["*.*"]
self.path = path
model = QFileSystemModel(self)
model.setRootPath(QDir.rootPath())
model.setReadOnly(False)
model.setFilter(QDir.AllDirs | QDir.NoDot | QDir.AllEntries)
self.setModel(model)
self.set_path(path)

def set_path(self, path):
self.path = path
model = self.model()
index = model.index(str(self.path))

if os.path.isfile(path):
self.setRootIndex(model.index(
os.path.dirname(str(self.path))))
self.scrollTo(index)
self.setCurrentIndex(index)
else:
self.setRootIndex(index)


class Foo(QWidget):

def __init__(self, path):
super().__init__()

self.path = path

self.tree_view = DirectoryTreeWidget(path=".")
self.tree_view.show()
bt = QPushButton(f"Update {path}")
bt.pressed.connect(self.update_file)

layout = QVBoxLayout()
layout.addWidget(self.tree_view)
layout.addWidget(bt)

self.setLayout(layout)
self.create_file()

def create_file(self):
with open(self.path, "w") as f:
data = "This new file contains xx bytes"
f.write(data.replace("xx", str(len(data))))

def update_file(self):
model = self.tree_view.model()

data = "The file updated is much larger, it contains xx bytes"
with open(self.path, "w") as f:
f.write(data.replace("xx", str(len(data))))

index = model.index(self.path)
model.setData(index, model.data(index))
QMessageBox.about(None, "Info", f"{self.path} updated, new size is {len(data)}")


def main():
app = QApplication(sys.argv)
foo = Foo("foo.txt")
foo.setMinimumSize(640, 480)
foo.show()
sys.exit(app.exec_())


if __name__ == "__main__":
main()

一些评论:

  • 您需要设置此env.var before initializing the model .
  • 不过,此功能的代价是潜在的重负载。如果此 env.var 打开,将监视缓存的文件。

关于python - 如何更新 QFileSystemModel 中的文件信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49718552/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com