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

时间:2018-04-08 13:49:28

标签: python pyqt pyqt5 qfilesystemmodel qfilesystemwatcher

首先,这个问题类似于另一个问题https://ci.appveyor.com/project/LudovicRousseau/pyscard,主要区别在于,在这种情况下,每次我的某个文件更新时,我都不想替换整个模型。

在现实世界的例子中,我的应用程序将打开几个文件,所以我基本上只是想了解如何更新一个特定QFileSystemModel项目的信息(大小,修改日期),下面你有一点点可以玩有,正如你在代码中看到的那样,我已经无意中尝试使用QFileSystemModel not updating when files change

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的信息?

目标是更新那个文件而不用像setData那样替换整个模型,一旦该模型项被更新,项目就不会在视图中排序/移动。< / p>

1 个答案:

答案 0 :(得分:1)

Qt v5.9.4引入了环境变量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() 以便解决QTBUG-46684,您可以在changelog中详细了解它:

  

QTBUG-46684现在可以启用每个文件观看了        设置环境变量QT_FILESYSTEMMODEL_WATCH_FILES,        允许跟踪文件大小的变化。

因此,为了使示例正常工作,您可以将envar设置为非空值,即:

{{1}}

几点意见:

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