QProcess - read from stdout lively
Hi, I am using using the following code to successfully collect the stout of the program I run with QProcess.
Code:
Process->start(program, args);
Process->waitForFinished();
QTextStream rsyncStdoutStream
(rsyncProcess
->readAllStandardOutput
());
while (true)
{
QString line
= rsyncStdoutStream.
readLine();
if (line.isNull())
break;
else
newFiles.append(line);
}
The problem is that with this code the output is actually collected once the program is finished, so I do not have "live" access to it, which is actually what I am looking for (I would need this for other purpose). Simply not using the waitForFinished() function makes my program to crash.
i thought that using the QProcess::readyReadStandardOutput signal could be a solution, but AFAIK this would need to call a SLOT and with this it is not possible to return any value, which is my need. So I am a bit stuck at this point..
Thanks,
Jan
Re: QProcess - read from stdout lively
Ok, I investigated it further and I have now the following code.
Code:
progress->setWindowModality(Qt::WindowModal);
progress->setLabelText("Calculating..");
progress->setMinimumSize(400, 40);
progress->setRange(0, 100);
progress->setValue(1); // AFAIU this is what shows the progress dialog
rsyncProcess->start(program, args);
rsyncProcess->waitForFinished();
progress->setValue(100); // AFAIU this is where the progress dialog closes
The problem with this is that the dialog seems to be actually shown _after_ the rsyncprocess is finished and so it always appears only for few milliseconds, no matter the time the rsyncProcess actually takes, which is not what I need of course. I have also tried using a busy indicator with range 0, 0 but this does not change the described behavior, the dialog seems to appear after te rsyncprocess is finished.
Code:
progress->setWindowModality(Qt::WindowModal);
progress->setLabelText("Calculating..");
progress->setMinimumSize(400, 40);
progress->setRange(0, 0);
progress->setValue(1); // AFAIU this is what shows the progress dialog
rsyncProcess->start(program, args);
rsyncProcess->waitForFinished();
progress->setValue(0); // AFAIU this is where the progress dialog closes
Any suggestion please?
Re: QProcess - read from stdout lively
You are doing it wrong.
Try something like this:
Code:
MainWindow
::MainWindow(QWidget *parent, Qt
::WFlags flags
){
process
= new QProcess(this);
// create on the heap, so it doesn't go out of scope connect (process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput())); // connect process signals with your code
connect (process, SIGNAL(readyReadStandardError()), this, SLOT(processOutput())); // same here
process->start(program, args); // start the process
}
// this gets called whenever the process has something to say...
void MainWindow::processOutput()
{
qDebug() << process->readAllStandardOutput(); // read normal output
qDebug() << process->readAllStandardError(); // read error channel
}
Success
Re: QProcess - read from stdout lively
Be mindful that, depending on how the child program manages its output, you may get partial lines in processOutput() and you may need to cope with that.
Re: QProcess - read from stdout lively
Thanks boudie, this clarify a bit about how I should do with the QProcess object. However I do not understand the benefit to have it in the heap so that it does not go out of the scope.. Just to clarify it to myself, having it in the heap is not enough, I also need to have it defined as class member in order to be available also for other functions of the class. Do I get it right?
Also, in my program now I have
Code:
progress
= new QProgressDialog("Processing...",
"Abort",
0,
INT_MAX,
this);
progress->setWindowModality(Qt::WindowModal);
progress->setLabelText("Calculating..");
progress->setMinimumSize(400, 40);
progress->setRange(0, 100);
progress->setValue(1);
connect(rsyncProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(showProgress()));
rsyncProcess->start(program, args);
Code:
void SyncHandler::showProgress()
{
static int x = 1;
QTextStream rsyncStdoutStream
(rsyncProcess
->readAllStandardOutput
());
while (true)
{
QString line
= rsyncStdoutStream.
readLine();
if (line.isNull()) {
break;
} else {
newFiles.append(line);
progress->setValue(++x);
//qDebug() << x;
}
}
qDebug() << x;
} }
In this way it works as long as x is actually increased exactly to 100, the value set with setRange(0,100). If x is lower than 100 the progress dialog just stay there waiting for the maximum value in the range, if higher a new one progress dialog is created.
Added after 48 minutes:
I have another problem with this. I actuially need to wait for process to finish before continuing as the next part of my code is based on the result of this process. So if I remove rsyncProcess->waitForFinished(); is a problem, my application goes ahead without having the needed information as process is running somehow in background and it is not finished yet.
Re: QProcess - read from stdout lively
Add this connection:
Code:
connect(rsyncProcess, SIGNAL(finished()), this, SLOT(processFinished()));
and create a function processFinished() where you do what has to be done.
You should do yourself a favour and read the docs. It's really a very good investment of your time (and ours...). ;)
Re: QProcess - read from stdout lively
Hi, finally I could figure it out. I was completely missing the logic and so some pieces in the code, not the function itself which of course I had already come across.... BTW, sometimes the problem is not about not reading docs but fully understanding it, I think that's we novices ask this basic things to you experts.... Thanks for your time anyway...
Re: QProcess - read from stdout lively
how do i wrap the codes from line 4 to 7 and bind with `processOutput`?
Quote:
Originally Posted by
boudie
You are doing it wrong.
Try something like this:
Code:
MainWindow
::MainWindow(QWidget *parent, Qt
::WFlags flags
){
process
= new QProcess(this);
// create on the heap, so it doesn't go out of scope connect (process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput())); // connect process signals with your code
connect (process, SIGNAL(readyReadStandardError()), this, SLOT(processOutput())); // same here
process->start(program, args); // start the process
}
// this gets called whenever the process has something to say...
void MainWindow::processOutput()
{
qDebug() << process->readAllStandardOutput(); // read normal output
qDebug() << process->readAllStandardError(); // read error channel
}
Success
how do i wrap the codes from line 4 to 7 and bind with `processOutput`?
Re: QProcess - read from stdout lively
Lines 5 and 6 specifically connect the process output notifier signals to the slot.