How to show a process result on QT? - c++

I am using QT program test run some background process in Ubuntu.
I know how to display the Qprocess result details after the process is completed.(Using QbyteArray).
Is there any way for me to show the Qprocess progress while the process is running in the background.(ie in message box or any other such informational sub window.)

You can read process output asynchronously. For it you should connect QProcess::readyReadStandardOutput() or QProcess::readyReadStandardError() signal to your slot.
QString program = "ping";
QStringList arguments;
arguments << "google.com";
myProcess = new QProcess(parent);
connect(myProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readyR()));
myProcess->start(program, arguments);
In your slot you can read data from standart output writen by process and do what you want.
void YourClass::readyR()
{
qDebug()<<myProcess->readAllStandardOutput();
}

Related

How to run Python script from QT creator and print output to GUI

void MainWindow::on_pushButton_clicked()
{
QProcess p;
// get values from ini file
settings->setValue("EMail", ui->lineEditEMail->text());
settings->setValue("Password", ui->lineEditPassword->text());
settings->setValue("Chronological", ui->checkBox->isChecked());
settings->setValue("Current_info", ui->checkBox_2->isChecked());
settings->endGroup();
settings->sync();
// launch python code for login
QString program( "C:/projects/build-test3-Desktop_Qt_6_4_0_MinGW_64_bit-Debug/venv/Scripts/python.exe");
QStringList args = QStringList() << "index.py";
QProcess::execute( program, args );
}
I have this function that is executed after a button is clicked and I need to print the output of "index.py" in to my app. What widget should I use and how? From what I read QTextBrowser should do the trick but I'm not sure how to use it.
This is how my GUI looks like. I'd like to use to output my results somewhere in button right. I didn't add the widget yet, because I'm not sure QTextBrowser is the one I need
The widget you could use for this purpose is QTextEdit (you can set it to be read-only from the graphical user interface).
But if you want to get the output of the execution, you will need a proper instance of QProcess and call the QProcess::readAllStandardOutput() member function to get the standard output.
You may also be interested by QProcess::readAllStandardError() to get the errors in case of failure.
Edit (simple/basic example):
QProcess p;
p.start("path/to/python.exe", QStringList("script.py"));
p.waitForFinished();
QByteArray p_stdout = p.readAllStandardOutput();
QByteArray p_stderr = p.readAllStandardError();
// Do whatever you want with the results (check if they are not empty, print them, fill your QTextEdit contents, etc...)
Note: If you don't want to be blocking with QProcess::waitForFinished(), you can use a signal/slots connection on QProcess::finished() signal.

How to start a process in Windows using QT?

I'm trying to start a console application on Windows using QProcess's method 'start'. Official documentation says I can do it like this:
QProcess process;
process.start("C:/Windows/System32/cmd.exe");
I expect that a standard greeting message will appear in the calling application's console, but this does not happen, though the called process is running. What is wrong here?
use of bellow example :
QProcess *process = new QProcess(this);
QString program = "explorer.exe";
QString folder = "C:\";
process->start(program, QStringList() << folder);
also you can use of system() as bellow :
system("C:/Windows/System32/cmd.exe");
How about this static call?
QProcess::startDetached(FilePath,Arguments,StartInDir);
No need to create any objects!

Display QProcess output in another window

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);
}

QProcess unknown error

I got strange problem. QProcess just not working!
And error is unknown.
I got global var in header
QProcess *importModule;
An I got this function ( I tried both start and startDetached methods btw )
void App::openImport(){
importModule = new QProcess();
importModule->setWorkingDirectory(":\\Resources");
importModule->startDetached("importdb_module.exe");
QMessageBox::information(0,"",importModule->errorString());
}
It jsut outputs that error is unknown. Also it wont start other exes like
void App::openImport(){
importModule = new QProcess();
importModule->setWorkingDirectory("C:\\Program Files\\TortoiseHg");
importModule->startDetached("hg.exe");
QMessageBox::information(0,"",importModule->errorString());
}
What I've done wrong?
And is there other ways to run some .exe from my programm?
Or maybe .bat files(which runs exes)? (Tried with QProcess too, not working)
startDetached() is a static method and doesn't operate on importModule at all.
It starts a process and then stops caring. Thus the error()/errorState() in importModule has nothing to do with the startDetached() call. What you want is start().
However, as QProcess is asynchronous, nothing will have happened yet immediately after start() returns. You must connect to the started(), error() and finished() signals to learn about the result.
connect(importModule, SIGNAL(started()), this, SLOT(importModuleStarted()));
connect(importModule, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(importModuleFinished(int, QProcess::ExitStatus)));
CONNECT(importModule, SIGNAL(error(QProcess::ProcessError)), this, SLOT(importModuleError(QProcess::ProcessError)));
importModule->start(QStringLiteral("importdb_module"), QStringList());
Alternatively you can use the blocking wait functions:
importModule->start(QStringLiteral("importdb_module"), QStringList());
importModule->waitForStarted(); // waits until starting is completed
importModule->waitForFinished(); // waits until the process is finished
However, I strongly advise against using them in the main thread, as they block the UI then.

QMessage while waiting for a ping command response

I'm doing a ping to an IP address, and I want to show into a QMessageBox that a ping operation is going on. After that, if a response is received or one second timeout happens, I want to close the QMessageBox.
Code:
int status;
QByteArray command;
QMessageBox myBox(QMessageBox::Information, QString("Info"), QString("Checking connection"), QMessageBox::NoButton, this);
command.append("ping -w 1 172.22.1.1");
status=system(command);
myBox.setStandardButtons(0);
myBox.exec();
if (0==status){ // Response received
// Some stuff here...
myeBox.setVisible(false);
}
else { // Timeout
// Some other stuff here...
myBox.setVisible(false);
}
My guess is that I may need to use threads for this task, but since I am a Qt newbie maybe the problem is anywhere else.
EDIT:
As #atamanroman suggested I've tried to use QProcess, using signal void QProcess::finished ( int exitCode, QProcess::ExitStatus exitStatus ) [signal] as told in Qt reference:
private:
QProcess *process;
//...
QMessageBox myBox(QMessageBox::Information, QString("Info"), QString("Checking connection"), QMessageBox::NoButton, this);
QObject::connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), &myBox, SLOT(close()));
command.append("ping -w 1 172.22.1.1");
process.start(comdand);
myBox.setStandardButtons(0);
myBox.exec();
And it's not working. myBox is never closed. What's wrong?
You should use QProcess (start ping.exe and parse output) or QTcpSocket (do the ping yourself) instead of system() because they are part of Qt and can signal you when the ping has finished. Connect to that signal in order to hide your QMessageBox.
In your edit:
First:
QProcess *process; // This is a pointer, you don't need to add "&" in connect
// You should have called "process = new QProcess" before...
QMessageBox myBox; // This is an object, you need to add the "&" to connect;
We take out the first &
QObject::connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), &myBox, SLOT(close()));
second:
Using Linux ping will never stop, then you will never have the finished signal. You can provide ping some parameters like count or time to wait. Or start a timer to stop the process.
third:
You need to match the parameters between signals and slots to avoid warnings, etc.
I sugest you to create a local SLOT "processfinished(int, QProcess::ExitStatus)" and then you call to myBox.Close(), but "myBox" must be from class to have reference to this after end the method where you call it.