2017-12-17 24 views
1

QFileSystemModel에 파일 변경 사항이 표시되지 않습니다. 파일이 처음 만들어지면 바로 나타납니다. 그러나 파일 자체가 변경되면 크기와 타임 스탬프가 업데이트되지 않습니다. 나는 실제 성공없이 모델을 업데이트하도록 여러 번 시도했다. 내가 얻은 최선은 모델을 완전히 대체하는 것입니다. 이 오류가 발생하더라도 :파일이 변경 될 때 QFileSystemModel이 업데이트되지 않습니다.

QSortFilterProxyModel: index from wrong model passed to mapToSource 

아래 테스트 코드는 빈 디렉터리의 테이블보기를 만듭니다. 왼쪽 버튼은 클릭하면 파일 (foo.txt)을 생성합니다. 연속적인 클릭은 파일에 데이터를 추가합니다. QFileSystemModel이 새로 고침을 필요로하지 않는다는 것을 이해했지만 두 번째 단추는이를 시도한 것입니다.

제가 뭘 잘못하고 있는지에 대한 도움은 크게 감사하겠습니다!

# Testing with python3.6.3 and pip installed pyqt5 5.9.2 in virtualenv on Ubuntu 
import os, sys, tempfile 
from PyQt5 import QtCore, QtWidgets 


class Widget(QtWidgets.QWidget): 
    def __init__(self, parent=None): 
     QtWidgets.QWidget.__init__(self, parent) 

     layout = QtWidgets.QVBoxLayout() 
     self.setLayout(layout) 
     self._view = QtWidgets.QTableView() 
     layout.addWidget(self._view) 

     self._modify_button = QtWidgets.QPushButton('Create') 
     layout.addWidget(self._modify_button) 
     self._refresh_button = QtWidgets.QPushButton('Refresh') 
     layout.addWidget(self._refresh_button) 

     self._modify_button.clicked.connect(self._modify) 
     self._refresh_button.clicked.connect(self._refresh) 

     self._model, self._proxy = None, None 
     self.temp_dir = tempfile.TemporaryDirectory(dir=os.path.dirname(os.path.abspath(__file__))) 
     self.init_model(self.temp_dir.name) 

    def init_model(self, path): 
     self._model = QtWidgets.QFileSystemModel() 
     self._model.setFilter(QtCore.QDir.AllDirs | QtCore.QDir.AllEntries) 

     self._proxy = QtCore.QSortFilterProxyModel(self) 
     self._proxy.setSourceModel(self._model) 
     self._view.setModel(self._proxy) 
     # self._view.setModel(self._model) 

     self._model.directoryLoaded.connect(self._loaded) 
     self._model.setRootPath(path) 

    def _loaded(self): 
     path = self._model.rootPath() 
     source_index = self._model.index(path) 
     index = self._proxy.mapFromSource(source_index) 
     self._view.setRootIndex(index) 
     # self._view.setRootIndex(source_index) 

    def _modify(self): 
     """Create or modify foo.txt..model should see and update""" 
     self._modify_button.setText('Modify') 
     file_name = os.path.join(self.temp_dir.name, 'foo.txt') 
     with open(file_name, 'a') as txt_file: 
      print('foo', file=txt_file) 

    # def _refresh(self): 
    #  # This only seems to work once..and its a flawed approach since it requires permission to write 
    #  temp = tempfile.NamedTemporaryFile(dir=self.temp_dir.name) 

    # def _refresh(self): 
    #  self._model.beginResetModel() 
    #  self._model.endResetModel() 

    # def _refresh(self): 
    #  self._proxy.setFilterRegExp('foo') 
    #  self._proxy.setFilterRegExp(None) 
    #  self._proxy.invalidate() 
    #  self._proxy.invalidateFilter() 
    #  self._proxy.reset() 
    # 
    #  root_index = self._model.index(self._model.rootPath()) 
    #  rows = self._model.rowCount(root_index) 
    #  proxy_root_index = self._proxy.mapFromSource(root_index) 
    #  topLeft = self._proxy.index(0, 0, proxy_root_index) 
    #  bottomRight = self._proxy.index(rows - 1, self._model.columnCount(proxy_root_index) - 1, proxy_root_index) 
    #  # self._proxy.dataChanged.emit(topLeft, bottomRight) 
    #  self._model.dataChanged.emit(topLeft, bottomRight) 

    # def _refresh(self): 
    #  # This only seems to work once 
    #  self._model.setRootPath('') 
    #  self._model.setRootPath(self.temp_dir.name) 

    def _refresh(self): 
     # This seems heavy handed..but seems to work 
     # ..though generates "QSortFilterProxyModel: index from wrong model passed to mapToSource" spam in console 
     self.init_model(self.temp_dir.name) 


if __name__ == "__main__": 
    app = QtWidgets.QApplication(sys.argv) 
    widget = Widget() 
    widget.show() 
    sys.exit(app.exec_()) 
+0

['QFileSystemWatcher'] (http://doc.qt.io/qt-5/qfilesystemwatcher.html)를 파일에 직접 사용해보십시오. 그러나 많은 파일을 보게되면 성능이 저하 될 수 있습니다. –

답변

2

이 문제는 오랜 Qt 버그로 인해 발생합니다 : QTBUG-2276. 불행하게도, 현재로서는 언제든지 고쳐질 것 같지 않습니다. 버그 보고서 주석에 나타난 바와 같이, 문제의 핵심이 될 것으로 보인다 :

It's an OS limitation. A change to a file does not mean the directory is modified.

이에 대한 유일한 주위 작품은 분명히 될 것이라고하는 QFileSystemWatcher에 대한 모든 단일 파일을 첨부 할 것 prohibitively expensive (대부분의 플랫폼에서, 어쨌든).

QFileSystemModel 클래스는 현재 새로 고침을 강제하는 API를 제공하지 않으며, 사용자가 알 수 있듯이이를 위해 안정적인 해결 방법이없는 것 같습니다. 방식으로 인해 파일 정보 캐싱의 몇 가지 특질에 아마 현재 구현 -이 한 번만 작동하는 것 같다 당신이 알고

root = fsmodel.rootPath() 
fsmodel.setRootPath('') 
fsmodel.setRootPath(root) 

그러나 : SO와 다른 곳에서 제공하는 대부분의 "솔루션"이 중 일부 변형을 제안 .

현재 업데이트를 수행하는 유일한 방법은 전체 모델을 대체하는 것입니다. 이 당신의 현재 구현에 의해 생성 된 오류 메시지는이처럼 init_model 방법을 리팩토링에 의해 방지 할 수 있습니다

def init_model(self, path): 
    if self._proxy is None: 
     self._proxy = QtCore.QSortFilterProxyModel(self) 
    else: 
     # remove the current source model 
     self._proxy.setSourceModel(None) 
    self._model = QtWidgets.QFileSystemModel() 
    self._model.setFilter(QtCore.QDir.AllDirs | QtCore.QDir.AllEntries) 
    self._proxy.setSourceModel(self._model) 
    self._view.setModel(self._proxy) 
    self._model.directoryLoaded.connect(self._loaded) 
    self._model.setRootPath(path) 

이것은 매우 만족스럽지 못한 상황이지만, 단지 그것을 주위에 명백한 방법이있을 것 같지 않습니다 순간.

+0

설명을 듣고 문제를 해결하고 모델을 다시 초기화하려는 시도에서 얻은 경고에 대해 고맙습니다! –