Checking if running as command-line (QCoreApplication) or GUI
-
Is it correct to write:
if (qApp) { // Do gui stuff } else { // Do command line stuff }Thanks, David
@Perdrix
I imagine that is a reasonable test if you want to do a Qt call, as in: "is there aQApplicationobject?"A global pointer referring to the unique application object. It is equivalent to QCoreApplication::instance(), but cast as a QApplication pointer, so only valid when the unique application object is a QApplication.
However, are you intending to use single-source with two separate compilations/links, one for GUI and one for console? Because if you are thinking you can do just one compilation/link and decide at runtime whether to run as GUI or command line you are going to stall. Under Windows at least --- which ISTR you use --- an executable is linked as either "windows" (GUI) or "console" (command-line) and you are stuck with that at runtime.
-
@JonB I build a GUI application which instantiates a QApplication in its main(), and a completely different piece of code is used for the command line application which creates a QCoreApplication.
So I think that qApp will work in that case?
-
@JonB I build a GUI application which instantiates a QApplication in its main(), and a completely different piece of code is used for the command line application which creates a QCoreApplication.
So I think that qApp will work in that case?
@Perdrix said in Checking if running as command-line (QCoreApplication) or GUI:
@JonB I build a GUI application which instantiates a QApplication in its main(), and a completely different piece of code is used for the command line application which creates a QCoreApplication.
So I think that qApp will work in that case?
Hi,
Something is not clear: are you starting both the CLI and the GUI from the same main function ?
-
As you can see here: https://doc.qt.io/qt-6/qapplication.html#qApp - qApp is not valid (undefined) when no QApplication instance exixst. When you simply look at the definition you will see what is happening:
#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))So no, it will not work and you will have to do it by yourself by calling dynamic_cast<> on the QCoreApplication::instance()
-
@Christian-Ehrlicher Well that's quite a surprise - from the documentation I had expected the macro to use a dynamic_cast<>
-
@Christian-Ehrlicher Well that's quite a surprise - from the documentation I had expected the macro to use a dynamic_cast<>
@Perdrix said in Checking if running as command-line (QCoreApplication) or GUI:
from the documentation I had expected the macro to use a dynamic_cast<>Why? It's clearly stated:
"so only valid when the unique application object is a QApplication."
-
Which clearly said to me that it would be null if the application object is just a QCoreApplication...
So the docs really could be clearer (state that is it using a static_cast<>), or change the code to use a dynamic_cast<>!
@Perdrix said in Checking if running as command-line (QCoreApplication) or GUI:
Which clearly said to me that it would be null if the application object is just a QCoreApplication...
undefined and a nullptr are two completely different things in c++ - the docs are very clear here.
https://en.cppreference.com/cpp/language/ub -
"only valid" = undefined if the precondition is not met.
/edit:
valid pointer - a pointer to an object which is not yet deleted and has the correct class
invalid / not valid pointer - a pointer to an object which was already deleted or has an incorrect class
nullptr - a pointer to null -
I still think the wording is open to my interpretation, however I have now defined my own convenience macro:
// // Define a convenience macro for checking if we're using a Qt GUI or command line application // #define qtGUI (dynamic_cast<QApplication *>(QCoreApplication::instance())) -
@Perdrix
I imagine that is a reasonable test if you want to do a Qt call, as in: "is there aQApplicationobject?"A global pointer referring to the unique application object. It is equivalent to QCoreApplication::instance(), but cast as a QApplication pointer, so only valid when the unique application object is a QApplication.
However, are you intending to use single-source with two separate compilations/links, one for GUI and one for console? Because if you are thinking you can do just one compilation/link and decide at runtime whether to run as GUI or command line you are going to stall. Under Windows at least --- which ISTR you use --- an executable is linked as either "windows" (GUI) or "console" (command-line) and you are stuck with that at runtime.
After further experiments this seems to be a non-starter. I wanted to use a message box for GUI and cout for command line, but of course the command line code isn't going to be linked with the libraries necessary to use QMessageBox.
Hey ho! Compile time checks ...
-
After further experiments this seems to be a non-starter. I wanted to use a message box for GUI and cout for command line, but of course the command line code isn't going to be linked with the libraries necessary to use QMessageBox.
Hey ho! Compile time checks ...
@Perdrix
This is the sort of thing I was trying to discuss with you once you start trying to useqAppfrom a command-line executable.I wanted to use a message box for GUI and cout for command line, but of course the command line code isn't going to be linked with the libraries necessary to use QMessageBox.
You implement this requirement via pointers-to-functions or subclassing-virtual-methods. It's a common paradigm. So that your code calls something like
utilty.alert("Message")and that ends up calling either the GUI or the command-line implementation depending what functionalert()pointer/virtual resolves to as set in construction/start-up. That keeps the command-line from needing to include/link with anything GUI.