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 bothdirectoryChanged
andfileChanged
on the samepath
, I'm not sure whether both of those can be emitted.) I presumepath
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 forpath
. -
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 ofQApplication(int &, char **)
(orQCoreApplication
) in yourmain.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. -
@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 bothdirectoryChanged
andfileChanged
on the samepath
, I'm not sure whether both of those can be emitted.) I presumepath
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 forpath
.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 ofQApplication(int &, char **)
(orQCoreApplication
) in yourmain.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:
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 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 lineinotifywait
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.