0

I have to check whether my process has finished and I need to convert it to bool because I want to you if.
In MainWindow.h I have created an object

QProcess *action;

In mainwindow.cpp

void MainWindow:: shutdown()
{
action=new QProcess(this);
action->start("shutdown -s -t 600");
//and now I want to use if
if (action has finished)
{
  QMessageBox msgBox;
  msgBox.setText("Your computer will shutdown in 1 minute.");
  msgBox.exec();
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 2
    What's wrong with the [`waitForFinished`](http://doc.qt.io/qt-5/qprocess.html#waitForFinished) function or the [`finished`](http://doc.qt.io/qt-5/qprocess.html#finished) signal which notifies as soon as it's finished? – James Adkison Jul 06 '16 at 19:30
  • @JamesAdkison The two suggestions don't belong in the same sentence. `waitForFinished` is a blocking method that makes the UI unresponsive. It's not meant to be used in an interactive thread. – Kuba hasn't forgotten Monica Jul 06 '16 at 19:54
  • @KubaOber I don't follow your comment. The first (before _or_) is a blocking function and the second (after _or_) is a non-blocking solution which uses the Qt signal-slot mechanism. – James Adkison Jul 06 '16 at 19:58
  • @JamesAdkison Suggesting to use either the `waitForFinished` method or the `finished` signal is like saying "Have an apple. Or a stratofortress.". There are very, very few cases where a `waitFor` method is ever appropriate. Most people who try to use it in a SO question (or answer) shouldn't be. – Kuba hasn't forgotten Monica Jul 06 '16 at 20:05
  • @KubaOber Okay, I understand your point. To be clear, I'm not asserting it's appropriate for their use case (which definitely _appears_ that `shutdown` is executed in context of the main thread). I'm essentially asking "Why doesn't this (blocking solution) or (non-blocking solution) work for you?" – James Adkison Jul 06 '16 at 20:09

1 Answers1

1

You should connect to the process's finished signal. Your code will get invoked whenever the process finishes. E.g.

// https://github.com/KubaO/stackoverflown/tree/master/questions/process-finished-msg-38232236
#include <QtWidgets>

class Window : public QWidget {
   QVBoxLayout m_layout{this};
   QPushButton m_button{tr("Sleep")};
   QMessageBox m_box{QMessageBox::Information,
            tr("Wakey-wakey"),
            tr("A process is done sleeping."),
            QMessageBox::Ok, this};
   QProcess m_process;
public:
   Window() {
      m_layout.addWidget(&m_button);
      m_process.setProgram("sleep");
      m_process.setArguments({"5"});
      connect(&m_button, &QPushButton::clicked, &m_process, [=]{ m_process.start(); });
      connect(&m_process, (void(QProcess::*)(int))&QProcess::finished, [=]{ m_box.show(); });
   }
};

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   Window window;
   window.show();
   return app.exec();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • when I want to use this http://txt.wklej.se/37d7 I get an error passing 'const QMessageBox' as 'this' argument of 'void QWidget::show()' discards qualifiers [-fpermissive] – Michał Urban Jul 07 '16 at 14:59
  • @MichałUrban You need to understand what the code means, you can't just copy-paste and expect it to work by chance. Your code won't work for two reasons: 1. The message box will get destructed as soon as the `shutdown` method returns, and 2. You can't capture a `QObject` instance by value in the lambda. In the answer, the capture-by-value applies to `this` pointer, as that's the only variable that the lambda is capturing. You could use `std::bind(&QMessageBox::show, m_box)` if it made it more obvious for you. There are important differences between the code I show in the answer and your paste. – Kuba hasn't forgotten Monica Jul 07 '16 at 15:34
  • Note that I would attach to finished, but you can also ask the process its state if for some reason you want to busy wait. http://doc.qt.io/qt-5/qprocess.html#state – Andrew Jul 07 '16 at 18:22