Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QFileSystemWatcher doesnt send signals to my slots



  • so I have a QFileSystemWatcher to essentially watch a folder for new files. I have connected to both "directoryChanged" and "fileChanged" slots but nothing happens when I create a new file, delete an existing file, or rename an existing file inside that directory.

    My basic setup is this:

    // exists in my header file:
    QFileSystemWatcher m_Watcher;
    
    // in my cpp constructor
    MyClass::MyClass() 
    : QObject(nullptr)
    , m_Watcher(this)
    {
    }
    
    // in my cpp:
    void WatchPath(const QString& path)
    {
        m_Watcher.addPath(path);
        connect(&m_Watcher, &QFileSystemWatcher::directoryChanged, this, &MyClass::on_directory_changed);
        connect(&m_Watcher, &QFileSystemWatcher::fileChanged, this, &MyClass::on_file_changed);
    }
    
    // and then my slot functions in my cpp
    void MyClass::on_directory_changed(const QString& path)
    {
        qDebug() << path << " changed";
        for(const QString& file : m_Watcher.files())
        {
            qDebug() << "on_directory_changed: " << file;
        }
    }
    
    void MyClass::on_file_changed(const QString& path)
    {
        qDebug() << path << " changed";
        for(const QString& file : m_Watcher.files())
        {
            qDebug() << "on_file_changed: " << file;
        }
    }
    
    // and then elsewhere not in a QObject
    MyClass* my_class = new MyClass();
    
    // and then in a widget somewhere else using the same MyClass pointer
    my_class->setParent(this);
    my_class->WatchPath("/full/system/path");
    

    I feel like im missing something, but based on the documentation i dont think I am. Since its dealing with filesystem, it might be relevant that im on debian(albeit i havnt updated in a while)

    $ uname -a
    Linux system76-debian 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64 GNU/Linux
    

    Any help would be appreciated.

    Thanks

    edit: i should note that "m_Watcher.addPath(path);" does return true



  • @RetroZelda
    Don't know if this helps, but your code looks OK in principle. (Though you are asking for both directoryChanged and fileChanged on the same path, I'm not sure whether both of those can be emitted.) I presume path refers to a directory.

    QFileSystemWatcher will have problems/won't work if the path is on a network (e.g. NFS), or if it is a mount point. But I don't suppose you're using either of those. Try it on your home directory, or one directory down, and do specify a full path for path.



  • You may have included the Q_OBJECT macro elsewhere in your code, I just don't see it here. You need it and you need to construct an instance of QApplication(int &, char **) (or QCoreApplication) in your main.cpp. If one if the latter is missing, QFileWatcher will still gladly accept whatever you tell it to do. When it fires signals, however, the callback to your slots will not take place.



  • @AxelVienna said in QFileSystemWatcher doesnt send signals to my slots:

    You may have included the Q_OBJECT macro elsewhere in your code, I just don't see it here.

    Untested, but unless you prove to me otherwise I don't think the OP has to have Q_OBJECT macro anywhere here, for the purposes of getting this to work. MyClass does not emit signals.



  • @JonB You are right, thanks for correcting!



  • @AxelVienna
    It's not that it might not be a good idea, it was just that I didn't want the OP to think that would actually solve anything!

    It wouldn't do any harm for OP to verify the return results of the connect()s succeeded, to make sure, just I find that these days with the new style syntax it rarely fails, and they look OK to me.



  • @JonB said in QFileSystemWatcher doesnt send signals to my slots:

    @RetroZelda
    Don't know if this helps, but your code looks OK in principle. (Though you are asking for both directoryChanged and fileChanged on the same path, I'm not sure whether both of those can be emitted.) I presume path refers to a directory.

    QFileSystemWatcher will have problems/won't work if the path is on a network (e.g. NFS), or if it is a mount point. But I don't suppose you're using either of those. Try it on your home directory, or one directory down, and do specify a full path for path.

    I just attempted to connect a slot to only the "directoryChanged" signal with no luck.

    @AxelVienna said in QFileSystemWatcher doesnt send signals to my slots:

    You may have included the Q_OBJECT macro elsewhere in your code, I just don't see it here. You need it and you need to construct an instance of QApplication(int &, char **) (or QCoreApplication) in your main.cpp. If one if the latter is missing, QFileWatcher will still gladly accept whatever you tell it to do. When it fires signals, however, the callback to your slots will not take place.

    I dont have Q_OBJECT defined for this type. I think i'll eventually do this regardless based on what @JonB suggested

    @JonB said in QFileSystemWatcher doesnt send signals to my slots:

    @AxelVienna

    It wouldn't do any harm for OP to verify the return results of the connect()s succeeded, to make sure, just I find that these days with the new style syntax it rarely fails, and they look OK to me.

    I did edit my original post with the info about 10 minutes after posting it, so you might not have seen it. connect() does return "true" for everything

    However, I do have this getting printed in the output:

    "qt.qpa.xcb: QXcbConnection: XCB error: 5 (BadAtom), sequence: 462, resource id: 0, major code: 20 (GetProperty), minor code: 0".

    Im not exactly sure when this appeared, could this be related? It doesnt get printed immediately.

    Edit:
    I just attempted to run without any of these connections and that error does still get logged. I dont believe it would be related, so ill do some resaerch to get this addressed



  • @RetroZelda said in QFileSystemWatcher doesnt send signals to my slots:

    "qt.qpa.xcb: QXcbConnection: ....

    I believe this message has been reported elsewhere as a harmless one. It has nothing to do with your issue.



  • @RetroZelda
    Try the following standalone program (tested under Ubuntu 20.04) on your system:

    #include <QApplication>
    #include <QDir>
    #include <QFileSystemWatcher>
    #include <QTextEdit>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QTextEdit w;
        w.show();
        QFileSystemWatcher fsw;
        fsw.addPath(QDir::homePath());
        fsw.addPath(QDir::homePath() + "/testfile");  // create this before running
        QObject::connect(&fsw, &QFileSystemWatcher::directoryChanged, [&w](const QString &path) { w.append(QString("directoryChanged : %1").arg(path)); });
        QObject::connect(&fsw, &QFileSystemWatcher::fileChanged, [&w](const QString &path) { w.append(QString("fileChanged : %1").arg(path)); });
        return a.exec();
    }
    

    If you don't get any output as you play with files in your home directory you have some problem with QFileSystemWatcher not working on your system.



  • @JonB

    @JonB said in QFileSystemWatcher doesnt send signals to my slots:

    @RetroZelda
    Try the following standalone program (tested under Ubuntu 20.04) on your system:

    #include <QApplication>
    #include <QDir>
    #include <QFileSystemWatcher>
    #include <QTextEdit>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QTextEdit w;
        w.show();
        QFileSystemWatcher fsw;
        fsw.addPath(QDir::homePath());
        fsw.addPath(QDir::homePath() + "/testfile");  // create this before running
        QObject::connect(&fsw, &QFileSystemWatcher::directoryChanged, [&w](const QString &path) { w.append(QString("directoryChanged : %1").arg(path)); });
        QObject::connect(&fsw, &QFileSystemWatcher::fileChanged, [&w](const QString &path) { w.append(QString("fileChanged : %1").arg(path)); });
        return a.exec();
    }
    

    If you don't get any output as you play with files in your home directory you have some problem with QFileSystemWatcher not working on your system.

    I just tested this and I do not get any prints when adding, renaming, editing, or removing a file in my home directory.

    I made this test script to ensure I could watch any directory, and this does work for me. I even tested it from calling it within "main" in the test program to see if there was a permissions issue, but it worked in there as well.

    #!/bin/bash
    inotifywait -m ~ -e create -e moved_to |
    while read dir action file; do
        echo "$file - $action - $dir"
    done
    

    is there a method towards enabling more "verbose logging", or would any kind of issue(like an assert or internal error) already be logged if one occurred?

    edit:
    also, this is my QT version

    $ qmake --version
    QMake version 3.1
    Using Qt version 5.15.2 in /usr/lib/x86_64-linux-gnu
    


  • @RetroZelda
    The code is correct, and should work. I note that your command line inotifywait does work.

    I do not know why Qt's QFileSystemWatcher is not working for you under Debian. I can only suggest you look at the source code at https://code.woboq.org/qt5/qtbase/src/corelib/io/qfilesystemwatcher.cpp.html and https://code.woboq.org/linux/linux/fs/notify/inotify/inotify.h.html to see if you can figure what the issue is in your platform.

    It may not be "nice", but you have the option of copying/amending some of this code to make the necessary direct OS call in your own code if necessary.


Log in to reply