Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Run a Terminal Code with QProcess on Ubuntu 18



  • We try to run a command on terminal with QProcess. We don't have to see the terminal but the code should work exacly at the same time with clicking the button. But somehow the code doesnt work, we tried many ways to make it.

    Here is our mainwindow.cpp:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QProcess>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    
    void MainWindow::on_pushButton_clicked()
    {
        QProcess p;
        p.setProgram("screen firefox");
        // p.setWorkingDirectory("/..."); // if needed
        p.start();
        p.waitForFinished(-1);
    }
    


  • @aliemrenebiler
    What is screen firefox supposed to do, how do we know? You need to put in error checking: slot onto all the signals for errors/finished, and grab any output on stdout/stderr. Then with that information you can figure out what is/is not going on, and ask for help if necessary.


  • Lifetime Qt Champion

    Hi

    Just a note first. p.waitForFinished(-1); will hang your app until "screen" exits which it
    normally wont.

    Anyway, if I run it like this

    void MainWindow::RunQProcess( ) {
    
      QProcess* process = new QProcess();
    
      QObject::connect(process, &QProcess::started, []() {
        qDebug() << "started";
      });
    
      QObject::connect(process, &QProcess::readyRead, [process]() {
        QTextStream outputStream(process->readAllStandardOutput());
        auto data = outputStream.readAll();
        qDebug() << "readyRead:" << data;
      });
    
      QObject::connect(process, &QProcess::readyReadStandardOutput, [process]() {
        QTextStream outputStream(process->readAllStandardOutput());
        auto data = outputStream.readAll();
        qDebug() << "readyReadStandardOutput" << " read:" << data;
      });
    
      QObject::connect(process, &QProcess::readyReadStandardError, [process]() {
        QTextStream errorStream(process->readAllStandardError());
        auto data = errorStream.readAll();
        qDebug() << "readyReadStandardError" << " read:" << data;
      });
    
      QObject::connect(process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
      [process](int exitCode, QProcess::ExitStatus exitStatus) {
        auto res = "exitcode:" + (QString::number(exitCode) + " exitStatus:" + QString::number(exitStatus));
        qDebug() << "Status:" << res;
        process->deleteLater(); // clean up
      });
    
      process->start("screen", QStringList() << "firefox" );
    
    }
    

    I get

    started
    readyRead: "Must be connected to a terminal.\r\n"
    readyReadStandardOutput  read: ""
    Status: "exitcode:1 exitStatus:0"
    

    so my guess is there is no active TTY in the QProcess inviroment.



  • @JonB It suppose to open the Firefox App. And it does when I write it in terminal. Thanks for your answer.



  • @mrjj Thank you so much. I will try this and write what happened again. We found a way to use terminal commands with QProcess, I will send the final result later.



  • @mrjj We tried your way but there is a problem with qOverload. It is an int we assume but not indentified (use of undeclared identifier). Can you help again?

    I would like to explain what we are aiming to do:
    We have a folder called "display.launch", it is a Rviz folder that will open with "roslaunch display.launch" command. We basicly open the terminal and go to the direction of /home/said/qt_ws/src/sasi_solid_v12/launch/ and start the "roslaunch display.launch" command. It opens the Rviz model automaticly. We want to do it with a button click on Qt.

    So as summary:

    1. We should start a terminal (it can be hidden, no problem)
    2. Go to the desired direction.
    3. Start a command ("roslaunch display.launch" or something else...)

  • Lifetime Qt Champion

    Hi
    for which signal do you need qOverload ?
    can you show the line that gives the error ?

    1:Well that should be ok.

    2: you can use
    https://doc.qt.io/qt-5/qprocess.html#setWorkingDirectory

    3: you might need to provide the full path to the roslaunch exe
    for Qt to find it.



  • @mrjj hi again.
    qOverload is a part of the code that you sent us. We really don't know what it does. But it says unclerified so we couldn't make the code work.

    ec8da3dc-add0-4e2b-9f9d-e95f35b34f20-image.png

    We already used setWorkingDirectory and that works fine. Thank you.

    The problem is we don't need the exe path because roslaunch is a command, not an exe. roslaunch automatically starts the Rviz exe and the folder that we wanna open in Rviz. So the need is not the path, a way to start the roslaunch command.


  • Lifetime Qt Champion

    @aliemrenebiler
    hi
    ah sorry. the eye is the first place one goes blind... ;)

    QObject::connect(process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished),

    https://doc.qt.io/qt-5/qtglobal.html#qOverload

    I forgot in which version it came. Maybe your Qt is older.

    anyway one can use a cast instead

    QObject::connect(process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
      [process](int exitCode, QProcess::ExitStatus exitStatus) {
        auto res = "exitcode:" + (QString::number(exitCode) + " exitStatus:" + QString::number(exitStatus));
        qDebug() << "Status:" << res;
        process->deleteLater(); // clean up
      });
    

    qOverload is just syntax sugar to make it read nicer.


  • Lifetime Qt Champion

    @aliemrenebiler said in Run a Terminal Code with QProcess on Ubuntu 18:

    We really don't know what it does

    Then please read documentation (https://doc.qt.io/qt-5/qtglobal.html#qOverload) and include QtGlobal as the documentation shows:

    #include <QtGlobal>
    

Log in to reply