I'm tracking a log file that is changed by another application. In linux I receive the fileChanged signal correctly as soon as the other application changes the file. In windows QFileSystemWatcher doesn't emit any fileChanged signal until the other application is closed.
I have tried to open the log with notepad to make sure is actually been changed and as soon as the notepad open the log ,QFileSystemWatcher sends the fileChanged signal.
My code:
void LogLoader::createFileWatcher()
{
if(fileWatcher != NULL) delete fileWatcher;
fileWatcher = new QFileSystemWatcher(this);
connect(fileWatcher, SIGNAL(fileChanged(QString)),
this, SLOT(prepareLogWorker(QString)));
if(fileWatcher->addPath(logPath))
{
qDebug() << "LogLoader: "<< "FileWatcher linked.";
}
}
void LogLoader::prepareLogWorker(QString path)
{
//Added this just in case because I read it as solution
//in other question. But in my case the file is not removed.
if (!fileWatcher->files().contains(path))
{
fileWatcher->addPath(path);
}
QTimer::singleShot(1000, this, SLOT(sendLogWorker()));
}
Am I doing something wrong? Is there any other solution than checking
the file manually from time to time?
Related
I am working on an Qt application which has the possability to use a script to perform several actions. One command within the script requires an external event to happen until the next command in the list can be computed (which is
not the case for the rest of the commands).
Usually, I open the file, read a line of the script and process it. This is repeated until the EOF is reached.
Emitting a signal when the external event occured is possible, but the function which runs through the script hast so to be stopped during this timespan.
How can i archive this whithout locking the GUI response?
Thank you!
I would do it this way:
public:
void execute_script() {
//open file
continue_execution();
}
public slots:
void continue_execution() {
while(!file.atEnd()) {
//read and process command
if(async_command) {
//make sure the signal indicating command completion
//is connected to continue_execution() slot
return;
}
}
emit script_finished();
}
I am running a Qt app that launches a process. (The Assistant, launched from the main app).
When I close the app, I get the warning
QProcess: Destroyed while process is still running.
How can I get rid of it ?
I saw this similar question and tried to kill... Nothing happened.
This question seems to say maybe I should add waitForFinished()... Help won't close when app does.
Help::Help():m_helpProcess(0) {}
Help::~Help()
{
if (m_helpProcess) {
m_helpProcess.waitForFinished(); // help stays open after app closes
m_helpProcess->kill(); // added with no effect
delete m_helpProcess;
}
}
bool Help::start()
{
if (!m_helpProcess)
process = new QProcess();
QStringList args;
args << QLatin1String("-collectionFile")
<< QLatin1String("mycollection.qhc");
process->start(QLatin1String("Assistant.app"), args);
if (!process->waitForStarted())
return;
}
It should be sufficient to rewrite the destructor using close():
Closes all communication with the process and kills it. After calling this function, QProcess will no longer emit readyRead(), and data can no longer be read or written.
Help::~Help()
{
if (m_helpProcess) {
// m_helpProcess->waitForFinished(); // help stays open after app closes
m_helpProcess->close(); // close channels
delete m_helpProcess; // destructor actually kills the process
}
}
I'm using the QT Creator on Ubuntu.
I have GUI with a mainwindow and another window called "progress".
Upon clicking a button the QProcess starts and executes an rsync command which copies a folder into a specific directory. I created a textbrowser which reads the output from the rsync command. Also clicking the button causes the "progress" window to pop up.
So far so so good, now my problem.
Instead of showing the rsync output in my mainwindow i want it to be in progress.
I've tried several methods to get the QProcess into the progress via connect but that doesn't seem to work.
mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
if (ui->checkBox->isChecked()
)
m_time ="-t";
QObject parent;
m_myProcess = new QProcess();
connect(m_myProcess, SIGNAL(readyReadStandardOutput()),this, SLOT(printOutput()));
QString program = "/usr/bin/rsync";
arguments << "-r" << m_time << "-v" <<"--progress" <<"-s"
<< m_dir
<< m_dir2;
m_myProcess->start(program, arguments);
}
progress.cpp
void Progress::printOutput()
{
ui->textBrowser->setPlainText(m_myProcess->readAllStandardOutput());
}
I know it's pretty messy iv'e tried alot of things and haven't cleaned the code yet also I'm pretty new to c++.
My goal was to send the QProcess (m_myProcess) to progress via connect but that didn't seem to work.
Can you send commands like readyReadAllStandardOutput via connect to other windows (I don't know the right term )?
Am I doing a mistake or is there just another way to get the output to my progress window ?
m_myProcess is a member of the class MainWindow and you haven't made it visible to the class Progress. That's why you have the compilation error
m_myProcess was not declared in this scope
What you could do:
Redirect standard error of m_myProcess to standard output, such that you also print what is sent to standard error (unless you want to do something else with it). Using
m_myProcess.setProcessChannelMode(QProcess::MergedChannels);
Make the process object available outside MainWindow
QProcess* MainWindow::getProcess()
{
return m_myProcess;
}
Read the process output line by line in Progress. It needs to be saved in a buffer because readAllStandardOutput() only return the data which has been written since the last read.
... // somewhere
connect(window->getProcess(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput())
...
void Progress::printOutput(){
//bigbuffer is member
bigbuffer.append(myProcess->readAllStandardOutput();)
ui->textBrowser->setPlainText(bigbuffer);
}
void OBJ_Loader::on_actionOpen_triggered()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Open a File"));
if (!filename.isEmpty()) {
filepath=filename.toUtf8().constData();
command.append(filepath);
int TempNumOne=command.size();
for (int a=0;a<=TempNumOne;a++) { //get letters to a char list so it can be used by system();
cmd[a]=command[a];
}
openfile=true;
if (openfile) {
openfile=false;
system(cmd);
}
}
}
When the system(cmd); is called the QFileDialog window does not close till the system command finishes. I would like to know if I can close the search window after clicking open.
The system function blocks the event loop: the user interaction requires the event loop to run, and it runs when your code isn't running. Since the system invocation is in your code, you can't simply have it block your process. You need to use QProcess as it has an asynchronous interface. This answer provides a complete example of one process calling itself -- all done from a single executable.
I have a program which is supposed to download files over the net. And everything is fine as long as files are small'ish(<1GB). But when files are larger than 1GB one of two things happen:
a) if I connect signal from QNetworkReply with download progress to one of my slots, application crashes with std::bad_alloc
b) if I don't connect any signal from QNetworkReply, application stops on 73%.
Any help mostly appreciated.
Here is the code I use in my connection, and slot:
QNetworkReply* reply = network_access_manager_->get(request);
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),parent_,SLOT(downloadProgress(qint64,qint64)));
And here is the slot:
void MainWindow::downloadProgress(qint64 bytesReceived,qint64 bytesTotal)
{
try
{
ui->label->setText(QString::number(bytesReceived));
ui->label_2->setText(QString::number(bytesTotal));
ui->progressBar->setRange(0,bytesTotal);
ui->progressBar->setValue(bytesReceived);
}
catch(std::exception& e)
{
qDebug() << e.what();
}
}
Read the documentation of QNetworkReply:
QNetworkReply is a sequential-access QIODevice, which means that once
data is read from the object, it no longer kept by the device. It is
therefore the application's responsibility to keep this data if it
needs to. Whenever more data is received from the network and
processed, the readyRead() signal is emitted.
Therefore, just read from QNetworkReply during download, whenever you want, using the readyRead() signal, and write to file or wherever you want.
Here you can find some other information (read Frank Osterfeld's answer in particular): Downloading File in Qt From URL.