1

I borrowed this code from another StackOverflow answer:

from PyQt4 import QtCore

@QtCore.pyqtSlot(str)
def directory_changed(path):
    print('Directory Changed!!!')

@QtCore.pyqtSlot(str)
def file_changed(path):
    print('File Changed!!!')

fs_watcher = QtCore.QFileSystemWatcher(['/path/to/files_1', '/path/to/files_2', '/path/to/files_3'])

fs_watcher.connect(fs_watcher, QtCore.SIGNAL('directoryChanged(QString)'), directory_changed)
fs_watcher.connect(fs_watcher, QtCore.SIGNAL('fileChanged(QString)'), file_changed)

The problem is, file_changed never gets called, no matter what. directory_changed is reliably called when a file is added, for example, but changing the files content does not result in file_changed being called.

I called a few variations of QtCore.SIGNAL('fileChanged(QString)'), eg, QtCore.SIGNAL('fileChanged(const QString &)'), to no avail. There are no warnings, or errors -- it simply does not trigger the function.

Recommendations?

Community
  • 1
  • 1
Ken Kinder
  • 12,654
  • 6
  • 50
  • 70

2 Answers2

5

It's hard to be certain what's going wrong, because the example code is incomplete, and so cannot work at all as it stands.

However, assuming the real code you are running is more or less sane/complete, your problem is probably caused by not adding the directory itself to the list of paths.

A basic script should look something like this:

import sys
from PyQt4 import QtCore

def directory_changed(path):
    print('Directory Changed: %s' % path)

def file_changed(path):
    print('File Changed: %s' % path)

app = QtCore.QCoreApplication(sys.argv)

paths = [
    '/path/to',
    '/path/to/files_1',
    '/path/to/files_2',
    '/path/to/files_3',
    ]

fs_watcher = QtCore.QFileSystemWatcher(paths)
fs_watcher.directoryChanged.connect(directory_changed)
fs_watcher.fileChanged.connect(file_changed)

sys.exit(app.exec_())
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • 1
    You're right, though my problem was not adding files to the list of paths. I misunderstood that the class isn't recursive. – Ken Kinder Nov 23 '12 at 22:21
  • In the case where you get file_changed to be called, what is the way to update the model or QTreeView to show the updated file. In my case I want to see the updated date/timestamp when I know it's changed. I have a compile button and I would like the new .mpy file to show the updated timestamp – Eradicatore Jun 28 '17 at 19:16
  • @Eradicatore. Please ask a new question. – ekhumoro Jun 28 '17 at 19:19
  • Ok, sure. Didn't want to create new if my question was sort of already covered, but I'll do that now. – Eradicatore Jun 28 '17 at 19:29
  • I've asked my question here just FYI: https://stackoverflow.com/questions/44839096/how-can-i-get-a-pyqt-slot-to-update-the-qtreeview-during-the-slot – Eradicatore Jun 30 '17 at 05:23
2
import argparse
import configparser
import os
import sys

from PyQt5 import QtCore
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QDesktopWidget, QMessageBox
from PyQt5.QtWidgets import QMainWindow

from ProgressBar_ui import Ui_Form


class ProgressBarWindow(QMainWindow, Ui_Form):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.ui.progressBar.setMinimum(0)
        self.ui.progressBar.setMaximum(0)
        self.ui.progressBar.setValue(0)
        self.setWindowTitle("Progress Bar")
        self.MSversion = ""
        self.LOADING_LOG_PATH = ""
        mainIco = ("Icons\myIcon.ico")
        self.setWindowIcon(QIcon(mainIco))
        self.ui.label.setText("")
        self.ui.label.setWordWrap(True)



    def location_on_the_screen(self):
        ag = QDesktopWidget().availableGeometry()
        sg = QDesktopWidget().screenGeometry()

        widget = self.geometry()
        x = ag.width() - widget.width()
        y = 2 * ag.height() - sg.height() - widget.height()
        self.move(x, y)


    def file_changed(self, pathPassed):
        if os.path.exists(pathPassed):
            f = open(pathPassed, "r")
            for x in f:
                #print(x)
                label =x
                self.ui.label.setText(label)
                if x == "CloseLoading":
                    self.close()

def main():
    app = QApplication(sys.argv)
    w = ProgressBarWindow()
    w.setWindowFlags(w.windowFlags() & ~QtCore.Qt.WindowMaximizeButtonHint)

    parser = argparse.ArgumentParser()
    parser = argparse.ArgumentParser(description='ProgressBar Arguments')

    parser.add_argument('version', action="store", type=str)

    args = vars(parser.parse_args())

    if len(sys.argv) < 1:
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Critical)
        errorMsg = "There are less than 2 command line arguments provided.\nLauncher can not be run."
        msg.setText(errorMsg)
        msg.setWindowTitle("Save paths..")
        msg.exec_()
        sys.exit()



    p= '/path/toFile/'
    paths = [ p ]

    fs_watcher = QtCore.QFileSystemWatcher(paths)
    #fs_watcher.directoryChanged.connect(w.directory_changed)
    fs_watcher.fileChanged.connect(w.file_changed)
    w.location_on_the_screen()
    w.show()
    app.exec_()

if __name__ == "__main__":
    sys.exit(main())
Vkoder
  • 103
  • 1
  • 9
  • The above code, creates a FORM with a progressBar and a label and reads a file and updates the label on the GUI. QFileSystemWatcher is looking for the updates on the file and calling fileChanged method to update the label's text. Also, notice the watcher works in main function but not in any other class and the file_changed signal is a private signal and cannot be emitted by the user. – Vkoder Feb 04 '20 at 14:14