in my files console.h/.cpp i have a small class which just asks the user to type in some text and then just prints the text again until the user enters "quit" (see method consoleMain()
). However, in main.cpp I also have a
QFileSystemWatcher
which watches the file MyTextFile.txt and calls Console::slotFileChanged(QString)
whenever the text file changes. Unfortunately the QFileSystemWatcher
does not work. Console::slotFileChanged(QString)
is never executed when I change the text file. As far as I know, QFileSystemWatcher
works only if the main event loop has been started and this is also the case in my code.
When I disable the QTimer::singlaShot
in the main.cpp and replace it by emit console.signalStart()
the main event loop will not be entered, but I see the message of the QFileSystemWatcher
("File changed!") after I enter "quit".
The question is: Is it possible to let the user interact with the console and let the FileWatcher emit the signal when the text file is changed in parallel?
(I've also tried to put the QFileSystemWatcher
into the console class and creating it on the heap; unfortunately it didn't change anything)
Here is my code:
console.h
#ifndef CONSOLE_H
#define CONSOLE_H
#include <iostream>
#include <QObject>
#include <QFileSystemWatcher>
class Console: public QObject
{
Q_OBJECT
public:
Console(QObject *parent = 0);
~Console();
signals:
void signalStart();
void signalEnd();
public slots:
void consoleMain();
void slotFileChanged(QString text);
void slotEmit();
};
#endif // CONSOLE_H
console.cpp
#include "console.h"
Console::Console(QObject *parent): QObject(parent)
{
}
Console::~Console()
{
}
void Console::consoleMain()
{
bool isRunning = true;
std::string in;
while (isRunning)
{
std::cout << ">" << std::flush;
std::getline(std::cin, in);
if (in.compare("quit") == 0)
isRunning = false;
else
std::cout << "You have entered: " << in << std::endl;
}
emit signalEnd();
}
void Console::slotFileChanged(QString text)
{
Q_UNUSED(text);
std::cout << "File changed!" << std::endl;
}
void Console::slotEmit()
{
emit signalStart();
}
main.cpp
#include "console.h"
#include <QCoreApplication>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFileSystemWatcher watcher(&a);
watcher.addPath("C:/MyTextFile.txt");
Console console(&a);
QObject::connect(&console, SIGNAL(signalStart()), &console, SLOT(consoleMain()));
QObject::connect(&console, SIGNAL(signalEnd()), &a, SLOT(quit()));
QObject::connect(&watcher, SIGNAL(fileChanged(QString)), &console, SLOT(slotFileChanged(QString)));
QTimer::singleShot(0, &console, SLOT(slotEmit()));
//emit console.signalStart();
std::cout << "Enter main event loop now" << std::endl;
return a.exec();
}
Ok, it is solved. I've tried Yakk's idea using different threads (thanks for the idea Yakk). I had to introduce a new subclass of QObject
called MyObject
. In its constructor I create the Console
and a new QThread
for the console object. The QFileSystemWatcher
is created in main.cpp as well as an instance of MyObjcet
. See code below:
myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include "console.h"
#include <QThread>
#include <QCoreApplication>
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject(QObject *parent = 0);
~MyObject();
private:
QThread *thread;
Console *console;
signals:
void signalStart();
public slots:
void slotFileChanged(QString text);
void slotEnd();
};
#endif // MYOBJECT_H
myobject.cpp
#include "myobject.h"
MyObject::MyObject(QObject *parent): QObject(parent)
{
console = new Console;
thread = new QThread(this);
console->moveToThread(thread);
thread->start();
connect(this, SIGNAL(signalStart()), console, SLOT(consoleMain()));
connect(console, SIGNAL(signalEnd()), this, SLOT(slotEnd()));
emit signalStart();
}
MyObject::~MyObject()
{
thread->quit();
thread->wait();
}
void MyObject::slotFileChanged(QString text)
{
console->displayChangedFileText(text);
}
void MyObject::slotEnd()
{
QCoreApplication::exit(0);
}
main.cpp
#include "myobject.h"
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFileSystemWatcher *watcher = new QFileSystemWatcher(&a);
watcher->addPath("C:/MyTextFile.txt");
MyObject *object = new MyObject(&a);
QObject::connect(watcher, SIGNAL(fileChanged(QString)), object, SLOT(slotFileChanged(QString)));
std::cout << "Enter main event loop now" << std::endl;
return a.exec();
}
console.h/.cpp are unchnaged, only Console::slotFileChanged(QString)
was replaced by Console::displayChangedFileText(QString)
.