Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QFileSystemWatcher sending only one signal
Forum Updated to NodeBB v4.3 + New Features

QFileSystemWatcher sending only one signal

Scheduled Pinned Locked Moved Unsolved General and Desktop
4 Posts 2 Posters 370 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mateus Interciso
    wrote on last edited by
    #1

    Hello, I'm trying to make a very simple widget to test the QFileSystemWatcher and know how many times a file was saved (even if not changed). I think I got almost everything right, but it seems that once the QFileSystemWatcher sends the signal to the slot, it removes the file from the watcher path, and I have to re-add it.
    For now, the code I have is:

    widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QFileSystemWatcher>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACE
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent = nullptr);
        ~Widget();
    
    public slots:
        void showModified(const QString &str);
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::Widget *ui;
        QFileSystemWatcher *watcher;
        int numChanges;
    };
    #endif // WIDGET_H
    

    widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include <QDebug>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
        , watcher(new QFileSystemWatcher)
        , numChanges(0)
    {
        ui->setupUi(this);
        QObject::connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(showModified(QString)));
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    void Widget::showModified(const QString &str){
        Q_UNUSED(str);
        this->numChanges++;
        this->ui->fileChangedMonitor->setText("Yes");
        QStringList fileList = watcher->files();
        qDebug() << "Changed " << this->numChanges << " times";
        qDebug() << "Files being wathced:";
        Q_FOREACH(QString file, fileList)
                    qDebug() << "- " << file << " on watch list";
    }
    
    void Widget::on_pushButton_clicked()
    {
        watcher->addPath(this->ui->filePath->text());
    }
    

    If I leave like this, the console writes (even if changing more than once):

    11:32:01: Starting /home/minterciso/Programacao/qt/build-sampleFileWatcher-Desktop-Debug/sampleFileWatcher ...
    qt.qpa.xcb: QXcbConnection: XCB error: 5 (BadAtom), sequence: 481, resource id: 0, major code: 20 (GetProperty), minor code: 0
    Changed  1  times
    Files being wathced:
    11:32:24: /home/minterciso/Programacao/qt/build-sampleFileWatcher-Desktop-Debug/sampleFileWatcher exited with code 0
    

    If however I change the public slot to:

    void Widget::showModified(const QString &str){
        this->numChanges++;
        this->ui->fileChangedMonitor->setText("Yes");
        watcher->removePath(str);
        watcher->addPath(str);
        QStringList fileList = watcher->files();
        qDebug() << "Changed " << this->numChanges << " times";
        qDebug() << "Files being wathced:";
        Q_FOREACH(QString file, fileList)
                    qDebug() << "- " << file << " on watch list";
    }
    

    Then I get 2 signals on every change (I've saved the file 4 times):

    11:33:34: Starting /home/minterciso/Programacao/qt/build-sampleFileWatcher-Desktop-Debug/sampleFileWatcher ...
    qt.qpa.xcb: QXcbConnection: XCB error: 5 (BadAtom), sequence: 481, resource id: 0, major code: 20 (GetProperty), minor code: 0
    Changed  1  times
    Files being wathced:
    -  "/home/minterciso/tst.txt"  on watch list
    Changed  2  times
    Files being wathced:
    -  "/home/minterciso/tst.txt"  on watch list
    Changed  3  times
    Files being wathced:
    -  "/home/minterciso/tst.txt"  on watch list
    Changed  4  times
    Files being wathced:
    -  "/home/minterciso/tst.txt"  on watch list
    Changed  5  times
    Files being wathced:
    -  "/home/minterciso/tst.txt"  on watch list
    Changed  6  times
    Files being wathced:
    -  "/home/minterciso/tst.txt"  on watch list
    Changed  7  times
    Files being wathced:
    -  "/home/minterciso/tst.txt"  on watch list
    Changed  8  times
    Files being wathced:
    -  "/home/minterciso/tst.txt"  on watch list
    11:33:48: /home/minterciso/Programacao/qt/build-sampleFileWatcher-Desktop-Debug/sampleFileWatcher exited with code 0
    

    Is it really like this that I should make? Or is there any other way of making this?

    Best regards

    jsulmJ 1 Reply Last reply
    0
    • M Mateus Interciso

      Hello, I'm trying to make a very simple widget to test the QFileSystemWatcher and know how many times a file was saved (even if not changed). I think I got almost everything right, but it seems that once the QFileSystemWatcher sends the signal to the slot, it removes the file from the watcher path, and I have to re-add it.
      For now, the code I have is:

      widget.h

      #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QFileSystemWatcher>
      
      QT_BEGIN_NAMESPACE
      namespace Ui { class Widget; }
      QT_END_NAMESPACE
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          Widget(QWidget *parent = nullptr);
          ~Widget();
      
      public slots:
          void showModified(const QString &str);
      
      private slots:
          void on_pushButton_clicked();
      
      private:
          Ui::Widget *ui;
          QFileSystemWatcher *watcher;
          int numChanges;
      };
      #endif // WIDGET_H
      

      widget.cpp

      #include "widget.h"
      #include "ui_widget.h"
      #include <QDebug>
      
      Widget::Widget(QWidget *parent)
          : QWidget(parent)
          , ui(new Ui::Widget)
          , watcher(new QFileSystemWatcher)
          , numChanges(0)
      {
          ui->setupUi(this);
          QObject::connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(showModified(QString)));
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      void Widget::showModified(const QString &str){
          Q_UNUSED(str);
          this->numChanges++;
          this->ui->fileChangedMonitor->setText("Yes");
          QStringList fileList = watcher->files();
          qDebug() << "Changed " << this->numChanges << " times";
          qDebug() << "Files being wathced:";
          Q_FOREACH(QString file, fileList)
                      qDebug() << "- " << file << " on watch list";
      }
      
      void Widget::on_pushButton_clicked()
      {
          watcher->addPath(this->ui->filePath->text());
      }
      

      If I leave like this, the console writes (even if changing more than once):

      11:32:01: Starting /home/minterciso/Programacao/qt/build-sampleFileWatcher-Desktop-Debug/sampleFileWatcher ...
      qt.qpa.xcb: QXcbConnection: XCB error: 5 (BadAtom), sequence: 481, resource id: 0, major code: 20 (GetProperty), minor code: 0
      Changed  1  times
      Files being wathced:
      11:32:24: /home/minterciso/Programacao/qt/build-sampleFileWatcher-Desktop-Debug/sampleFileWatcher exited with code 0
      

      If however I change the public slot to:

      void Widget::showModified(const QString &str){
          this->numChanges++;
          this->ui->fileChangedMonitor->setText("Yes");
          watcher->removePath(str);
          watcher->addPath(str);
          QStringList fileList = watcher->files();
          qDebug() << "Changed " << this->numChanges << " times";
          qDebug() << "Files being wathced:";
          Q_FOREACH(QString file, fileList)
                      qDebug() << "- " << file << " on watch list";
      }
      

      Then I get 2 signals on every change (I've saved the file 4 times):

      11:33:34: Starting /home/minterciso/Programacao/qt/build-sampleFileWatcher-Desktop-Debug/sampleFileWatcher ...
      qt.qpa.xcb: QXcbConnection: XCB error: 5 (BadAtom), sequence: 481, resource id: 0, major code: 20 (GetProperty), minor code: 0
      Changed  1  times
      Files being wathced:
      -  "/home/minterciso/tst.txt"  on watch list
      Changed  2  times
      Files being wathced:
      -  "/home/minterciso/tst.txt"  on watch list
      Changed  3  times
      Files being wathced:
      -  "/home/minterciso/tst.txt"  on watch list
      Changed  4  times
      Files being wathced:
      -  "/home/minterciso/tst.txt"  on watch list
      Changed  5  times
      Files being wathced:
      -  "/home/minterciso/tst.txt"  on watch list
      Changed  6  times
      Files being wathced:
      -  "/home/minterciso/tst.txt"  on watch list
      Changed  7  times
      Files being wathced:
      -  "/home/minterciso/tst.txt"  on watch list
      Changed  8  times
      Files being wathced:
      -  "/home/minterciso/tst.txt"  on watch list
      11:33:48: /home/minterciso/Programacao/qt/build-sampleFileWatcher-Desktop-Debug/sampleFileWatcher exited with code 0
      

      Is it really like this that I should make? Or is there any other way of making this?

      Best regards

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @Mateus-Interciso What Qt version do you use?

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Mateus Interciso
        wrote on last edited by
        #3

        @jsulm I'm using 5.15.2 on a kubuntu 21.04.

        Looking a little more on the signal documentation, it seems that this may happen from application to application that is writing the file (maybe vi is one of those):

        Note: As a safety measure, many applications save an open file by writing a new file and then deleting the old one. In your slot function, you can check watcher.files().contains(path). If it returns false, check whether the file still exists and then call addPath() to continue watching it.
        

        So I've updated the slot to:

        if(this->watcher->files().contains(str) == false)
                this->watcher->addPath(str);
        

        And of course, it's working. I'm still finding odd however the amount of time the slot is being called, but if the application removes and create a new one, then it may be because:

        1. Remove the file (send one signal)
        2. Create a new file (sent another signal)

        If this is the case, is there any option to check why the file was changed? I mean, without using inotify of course.

        jsulmJ 1 Reply Last reply
        0
        • M Mateus Interciso

          @jsulm I'm using 5.15.2 on a kubuntu 21.04.

          Looking a little more on the signal documentation, it seems that this may happen from application to application that is writing the file (maybe vi is one of those):

          Note: As a safety measure, many applications save an open file by writing a new file and then deleting the old one. In your slot function, you can check watcher.files().contains(path). If it returns false, check whether the file still exists and then call addPath() to continue watching it.
          

          So I've updated the slot to:

          if(this->watcher->files().contains(str) == false)
                  this->watcher->addPath(str);
          

          And of course, it's working. I'm still finding odd however the amount of time the slot is being called, but if the application removes and create a new one, then it may be because:

          1. Remove the file (send one signal)
          2. Create a new file (sent another signal)

          If this is the case, is there any option to check why the file was changed? I mean, without using inotify of course.

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @Mateus-Interciso I think your observation is correct. Considering "Note that QFileSystemWatcher stops monitoring files once they have been renamed or removed from disk, and directories once they have been removed from disk." it explains why the path disappears from the watcher in case an editor uses a temp file.
          As far as I know there is no way to get the exact information about what triggered the watcher.

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved