PyQt5 QFileSystemWatcher test

2021/03/13 categories:PyQt5| tags:PyQt5|Python|

I tried using QFileSystemWatcher to try out file monitoring with PyQt5.

View file list

I decided to display the file path in the folder to be monitored in QListView. To display the file path, get the file in the folder as shown in the code below, delete all the lines, add the line, and register the data.

def updateListView(self, path):
    paths = list( path.glob('*.*') )
    self.model.removeRows( 0, self.model.rowCount() )
    self.model.insertRows( 0, len(paths) )
    for row, p in enumerate(paths):
        self.model.setData( self.model.index(row, 0), str(p) )

Specify the path of the folder to be monitored with QLineEdit

I decided to enter the path of the folder to be monitored in QLineEdit. When the text of QLineEdit changes, execute the following code to delete the path of the folder to be monitored, update the file list, and add the path of the folder to be monitored.

def lineEditChanged(self, text):
    path = Path(text)
    for d in self.fileSystemWatcher.directories():
        self.fileSystemWatcher.removePath(d)
    if not path.exists():
        return
    self.updateListView(path)
    self.fileSystemWatcher.addPath(text)

What to do when a file in a folder changes

Connect directory_changed to directoryChanged in QFileSystemWatcher so that directory_changed is executed when the files in the folder are changed.

    self.fileSystemWatcher.directoryChanged.connect(self.directory_changed)

def directory_changed(self, string):
    self.updateListView(Path(string))

State of operation

Source code

import sys
from pathlib import Path
from PyQt5 import QtWidgets, QtCore

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.centralWidget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.centralWidget)
        self.centralLayout = QtWidgets.QVBoxLayout(self.centralWidget)
        self.centralWidget.setLayout(self.centralLayout)

        self.lineEdit = QtWidgets.QLineEdit(self.centralWidget)
        self.listView = QtWidgets.QListView(self.centralWidget)
        self.centralLayout.addWidget(self.lineEdit)
        self.centralLayout.addWidget(self.listView)

        self.model = Model(self.listView)
        self.listView.setModel(self.model)
        self.listView.setItemDelegate(Delegate())

        self.fileSystemWatcher = QtCore.QFileSystemWatcher(self)

        self.lineEdit.textChanged.connect(self.lineEditChanged)
        self.fileSystemWatcher.directoryChanged.connect(self.directory_changed)

    def updateListView(self, path):
        paths = list( path.glob('*.*') )
        self.model.removeRows( 0, self.model.rowCount() )
        self.model.insertRows( 0, len(paths) )
        for row, p in enumerate(paths):
            self.model.setData( self.model.index(row, 0), str(p) )

    def lineEditChanged(self, text):
        path = Path(text)
        for d in self.fileSystemWatcher.directories():
            self.fileSystemWatcher.removePath(d)
        if not path.exists():
            return
        self.updateListView(path)
        self.fileSystemWatcher.addPath(text)

    def directory_changed(self, string):
        self.updateListView(Path(string))

class Model(QtCore.QAbstractItemModel):
    def __init__(self, parent):
        super(Model, self).__init__(parent)
        self.item = []

    def columnCount(self, parent=QtCore.QModelIndex()):
        return 1

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if not index.isValid():
            return QtCore.QVariant()
        if role == QtCore.Qt.EditRole or role == QtCore.Qt.DisplayRole:
            return self.item[index.row()]
        return QtCore.QVariant()

    def flags(self, index):
        if index.isValid():
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
        return QtCore.Qt.ItemIsEnabled
        
    def index(self, row, column, parent=QtCore.QModelIndex()):
        return self.createIndex( row, column, self.item[row] )

    def insertRow(self, row, parent=QtCore.QModelIndex()):
        self.insertRows(row, 1, parent)

    def insertRows(self, row, count, parent=QtCore.QModelIndex()):
        self.beginInsertRows(parent, row, row + count - 1)
        self.item[row:row] = [ None for _ in range(count) ]
        self.endInsertRows()

    def parent(self, index):
        return QtCore.QModelIndex()

    def removeRow(self, row, parent=QtCore.QModelIndex()):
        self.removeRows(row, 1, parent)

    def removeRows(self, row, count, parent=QtCore.QModelIndex()):
        self.beginRemoveRows(parent, row, row + count - 1)
        del self.item[row:row+count]
        self.endRemoveRows()

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.item)

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if role == QtCore.Qt.EditRole:
            self.item[index.row()] = value
            return True
        return False

class Delegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent=None, setModelDataEvent=None):
        super(Delegate, self).__init__(parent)
        self.setModelDataEvent = setModelDataEvent
 
    def createEditor(self, parent, option, index):
        return QtWidgets.QLineEdit(parent)
 
    def setEditorData(self, editor, index):
        value = index.model().data(index, QtCore.Qt.EditRole)
        editor.setText(str(value))
 
    def setModelData(self, editor, model, index):
        model.setData(index, editor.text())
        if not self.setModelDataEvent is None:
            self.setModelDataEvent()

def main():
    app = QtWidgets.QApplication(sys.argv)
    mainwindow = MainWindow()
    mainwindow.show()
    app.exec()

if __name__ == '__main__':
    main()

Share post

Related Posts

コメント