PDA

View Full Version : Console application on the side



Cruz
5th June 2021, 12:33
Hello there,

I developed a Qt application with gui and everything for the running and visualization of physics-related experiments. Sometimes I have to start a long running process that can take several days to try out many things in the background and in the end reports with the found results. I am looking for a way to launch this background process without a gui just by invoking a command in the shell. The process is in an Object that derives from QThread and can run on its own. As far as I see it, it is really just a question of building the project right. Does it makes sense to have two project configurations, where one would build a gui application and the other just a console application? If this is the right way, would I have two different .pro files then? Would I need two .cpp classes that have a main() function tailored to my needs?

Thanks,
Cruz

Lesiok
5th June 2021, 13:57
Maybe a command line parameter that will say whether to run the GUI or not?

Cruz
5th June 2021, 15:31
Yes, true, much easier that way. Thanks.

d_stranz
5th June 2021, 16:15
It's about as simple as not calling show() on the main window instance when the "run in the background" command line parameter is present. You could also simply make a copy of your executable, rename it, and examine the name of the executable at run time to decide how to run it up. QCoreApplication::applicationName()

Cruz
7th June 2021, 09:08
I gave this a go, but it does not work as expected yet. It does when I start my program locally, but when I try to start it remotely over ssh, I receive the error message:


qt.qpa.screen: QXcbConnection: Could not connect to display
Could not connect to any X display.

I was able to find hints that I should forward my X session, but this does not come easy to me, because I have to first ssh into a proxy server and then from there I can ssh into a protected machine. I would like to avoid any X and windows and widgets altogether. My main function looks like this:



#include "GuiSimulation.h"
#include "Experimenter.h"

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GuiSimulation w; // The gui.
Experimenter e; // The background thread.

if (argc > 1)
{
e.start();
}
else
{
w.show();
}

return a.exec();
}

Even if I minimize this to



#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
return a.exec();
}

I receive the error message above. Any help is much appreciated.

Lesiok
7th June 2021, 10:04
You should use QCoreApplication in command line mode.

Cruz
7th June 2021, 17:19
Indeed! The final result:



int main(int argc, char *argv[])
{
if (argc > 1) // Command line mode.
{
QCoreApplication a(argc, argv);
Experimenter e;
e.start();
return a.exec();
}
else // GUI mode
{
QApplication a(argc, argv);
GuiSimulation w;
w.show();
return a.exec();
}
}

Cruz
9th June 2021, 10:32
One more question though. The event loop I started with a.exec() keeps running forever and eventually I have to kill it by hand. Normally, I would connect the finished() signal of QThread to a closed() or exit() slot or something, but here in the main function I can't use connect() right? How do I go about this?

d_stranz
9th June 2021, 16:08
but here in the main function I can't use connect() right?

Why not? There is a static version of QObject::connect(), and QCoreApplication is derived from QObject, so you could also use a.connect().

Cruz
9th June 2021, 21:05
Yes! This works like a charm. Thanks.



int main(int argc, char *argv[])
{
if (argc > 1) // Command line mode.
{
QCoreApplication a(argc, argv);
Experimenter e;
e.start();
a.connect(&e, SIGNAL(finished()), &a, SLOT(quit()));
return a.exec();
}
else // GUI mode
{
QApplication a(argc, argv);
GuiSimulation w;
w.show();
return a.exec();
}
}

d_stranz
10th June 2021, 05:48
I think I would call connect() before starting the Experimenter thread. If the thread finishes before the connection is made, you'll get a hung executable.

Cruz
10th June 2021, 08:53
Yes, you are right. This thing here takes several days to run so it shouldn't be an issue, but why would we stop short of perfection...



int main(int argc, char *argv[])
{
if (argc > 1) // Command line mode.
{
QCoreApplication a(argc, argv);
Experimenter e;
a.connect(&e, SIGNAL(finished()), &a, SLOT(quit()));
e.start();
return a.exec();
}
else // GUI mode
{
QApplication a(argc, argv);
GuiSimulation w;
w.show();
return a.exec();
}
}

d_stranz
10th June 2021, 15:33
but why would we stop short of perfection...

Exactly. Someone else might read this thread and copy your next to last version, then wonder why it didn't work because their process is very quick.