Home > Software engineering >  QFileSystemWatcher not sending fileChanged() SIGNAL
QFileSystemWatcher not sending fileChanged() SIGNAL

Time:07-12

I apologize in advance am very new to QT (and fairly new to C )

I am trying setup a program that will execute a function anytime a specific file is changed. Despite hours on google and reading the docs provided on QT I cant find a way to get myfunction() to execute when SSOpen_Log is edited

currently my code looks something like this (SOpen_Log is a QString declared in .h):

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    QFileSystemWatcher watcher;
    watcher.addPath(SOpen_Log);
    MainWindow::connect(&watcher, SIGNAL(fileChanged(QString)), this, SLOT(myfunction()));
}

MainWindow::myfunction()
{
    //mycode executes here
}

CodePudding user response:

You allocated your instance on the stack and it thus get destructed when the constructor ends. I would suggest that you make a class member for the instance so that it remains valid throughout the class.

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    m_watcher.addPath(SOpen_Log);
    MainWindow::connect(&m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(myfunction()));
}

There is no need to complicate this by putting it on the heap, effectively using a pointer, although that is also an option to consider.

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    QFileSystemWatcher *watcher = new QFileSystemWatcher(this);
    watcher->addPath(SOpen_Log);
    MainWindow::connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(myfunction()));
}

While we are at it, I would also like to mention to use the new signal-slot syntax style rather than the old. The old one is checked at runtime and the new one is checked at compilation time. So, you catch any issues with it during compilation rather than at runtime.

CodePudding user response:

This is my code , it works well.

QFileSystemWatcher *watcher = new QFileSystemWatcher;
watcher ->addPath("D:/work/todolistlater.txt");
connect(watcher,QFileSystemWatcher::fileChanged,[]()
{
    qDebug()<<"Changed";
    //myfunction()  //add your function here;
});

Raise watcher to pointer;

CodePudding user response:

A complete and simple example: Dirwatcher.h

   class DirWatcher : public QObject
{
    Q_OBJECT
public:
    static const int sMaxCount = 5;

    explicit DirWatcher(const QString& root, QObject* parent = nullptr);
    virtual ~DirWatcher();

private slots:

    void hDirChanged(const QString&);

    void hFileChanged(const QString&);

private:

    quint64 m_rbSize;
    QByteArray m_ringBuffer[10];
    QFileSystemWatcher m_watcher;
    QDir m_root;
    QSet<QString> m_directories;
    QMap<QString, QSet<QString>> m_abspaths;
    QString m_lastKey;

};

and Dirwatcher.cpp

namespace
{

    void split(const char* str, const char* delim, std::vector<std::string>& out)
    {
        const char* begin = str;
        const char* it = strstr(str, delim);
        if (it != NULL)
        {
            std::string data{begin, it};
            out.push_back(data);
            it  ;
            split(it, delim, out);
        } else {
            std::string data{str};
            out.push_back(data);
        }
    }
}


DirWatcher::DirWatcher(const QString &root, QObject* parent):
    QObject(parent), m_root(root), m_rbSize{10}
{

    m_watcher.addPath(root);

    QObject::connect(&m_watcher, SIGNAL(directoryChanged(const QString&)),
                                        this, SLOT(hDirChanged(const QString&)));


    QObject::connect(&m_watcher, SIGNAL(fileChanged(const QString&)),
                                        this, SLOT(hFileChanged(const QString&)));


}

DirWatcher::~DirWatcher()
{

}


void DirWatcher::hDirChanged(const QString &path)
{
    QDirIterator it(m_root.path());
    while (it.hasNext()) {
        QString d = it.next();
        if (d.at(0) == '.' || d.at(d.size()-1) == '.') {
        } else {
            if (!m_directories.contains(d)){
                m_directories << d;
                m_lastKey = d;
            }
        }

    }

#if 0 //delete directories when count reaches...
    if (m_directories.count() > DirWatcher::sMaxCount) {
        QSetIterator<QString> setit(m_directories);
        while (setit.hasNext()) {
            QString toDel = setit.next();
            if (toDel != m_lastKey) {
                QDir rem (toDel);
                rem.removeRecursively();
            }
        }
        m_directories.clear();
        m_directories << m_lastKey;
    }
#endif
    std::cout << "##############################################\r\n";
    QSetIterator<QString> setit(m_directories);
    while (setit.hasNext()) {
        QString d = setit.next();
        if (d.contains(".tlf")) {
            m_watcher.addPath(d);
        }
        std::cout << d.toStdString() << std::endl;
    }
}


void DirWatcher::hFileChanged(const QString& file)
{
    static size_t cnt = 0;
    QFile f{file};
    if (f.open(QFile::ReadOnly)) {
        quint64 s = f.size();
        f.seek(f.size()-f.size()/2);
        while (!f.atEnd()) {
            QByteArray data = f.readLine();
            m_ringBuffer[cnt   % m_rbSize]=data;
        }
    }

    std::cout << "----------------- B E G I N ----------------------\r\n";
    for(auto i : m_ringBuffer) {
        std::cout << "~~~~~~\r\n";
        std::cout << i.toStdString().c_str() << "\r\n";
    }
}

It's a real background monitoring job process for deleting files on a given time or count, but you will understand what is missing in your code if you debug it.

  •  Tags:  
  • c qt
  • Related