Qt application with optional gui
Asked Answered
T

5

7

I am going to write program using Qt for some image processing and I want it to be able to run in non-gui mode (daemon mode?). I'm inspired by VLC player, which is "typically" GUI program, where you can configure it using GUI, but you can also run it in non-gui option when it runs without GUI. Then it uses some configuration file created in GUI mode.

Question is how should be such a program design? Should be some program core, which is GUI independent and depending on options it is being connected with GUI interface?

Traps answered 24/5, 2014 at 12:10 Comment(1)
Kind of - I mean I didn't check if it works for me, but I changed approach - I will make core as stand alone program, and I will use gui for creating config file and running it.Traps
C
9

Yes, you could use a "headless" or "gui" option for the binary using QCommandLineParser. Note that it is only available from 5.3, but the migration path is pretty smooth within the major series if you still do not use that.

main.cpp

#include <QApplication>
#include <QLabel>
#include <QDebug>
#include <QCommandLineParser>
#include <QCommandLineOption>

int main(int argc, char **argv)
{
    QApplication application(argc, argv);
    QCommandLineParser parser;
    parser.setApplicationDescription("My program");
    parser.addHelpOption();
    parser.addVersionOption();

    // A boolean option for running it via GUI (--gui)
    QCommandLineOption guiOption(QStringList() << "gui", "Running it via GUI.");
    parser.addOption(guiOption);

    // Process the actual command line arguments given by the user
    parser.process(application);
    QLabel label("Runninig in GUI mode");
    if (parser.isSet(guiOption))
        label.show();
    else
        qDebug() << "Running in headless mode";

    return application.exec();
}

main.pro

TEMPLATE = app
TARGET = main
QT += widgets
SOURCES += main.cpp

Build and Run

qmake && make && ./main
qmake && make && ./main --gui

Usage

    Usage: ./main [options]
My program

Options:
  -h, --help     Displays this help.
  -v, --version  Displays version information.
  --gui          Running it via GUI.
Crier answered 24/5, 2014 at 12:21 Comment(6)
When I was making simple applications in qt, I was implementing all functions, CONNECTions, inside of constructor MainWindow (equivalent to Label in your answer). I understand that I should everything in the same way and add something like this to start some process: else { qDebug() << "Running in headless mode"; label.startSomeProcess()} ?Traps
@d21d3q: label should be used in the non-headless mode, i.e. the if branch.Dichroscope
You mean it should be used in non-headless mode in case of gui mode? How about this lable.startSomeProcess() in case of headless mode?Traps
@d21d3q: headless: console, non-headless: gui. Also, I think you slightly misunderstood what a label means in the Qt world. QLabel is a gui element. It does not start any processes...Dichroscope
I know that it is gui element. By this time I was working only with situation when in main.c MainWindow is beeing created (and showed) and inside of it whole program is implemented. I think I get it - I should make it as always, but without showing it?Traps
@d21d3q: I suggest not to implement the logic in the main window. It should be only used for gui interactions. Grab the logic out of that which you can use directly from the main.cpp or the mainwindow.cpp. The quick around might be not to show it, yeah.Dichroscope
C
4

You can pass an argument to your application when starting to show in gui or non-gui modes. For example if you pass -non-gui parameter when running in command line then the application should not show the main window and it should do some other stuff :

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow w;

    bool GUIMode=true;

    int num = qApp->argc() ;
    for ( int i = 0; i < num; i++ )
    {
        QString s = qApp->argv()[i] ;
        if ( s.startsWith( "-non-gui" ) )
            GUIMode = false;
    }

    if(GUIMode)
    {
         w.show();
    }
    else
    {
        //start some non gui functions
    }

    return a.exec();
}
Crake answered 24/5, 2014 at 12:28 Comment(0)
S
2

The example by lpapp above didn't work for me, as I got

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

when running without an X display (any value for DISPLAY, not just localhost:10.0).

There was a workaround - export QT_QPA_PLATFORM='offscreen' - but that's not a command line option, your user is expected to do it, which isn't nice.

So, following posting a question here, further research lead me to the following QT5 document that explains the "approved" way to start up with or without a GUI depending on command line options:

https://doc.qt.io/qt-5/qapplication.html#details

However, your mileage may vary. The example there didn't "just work" for me, either!

I had to use the command line arg to then choose one of two methods to run. Each method created its own app object (QCoreApplication for headless, QApplication for GUI, as the docs show) and then running the app.

It may be because I'm working with "mostly Qt 4" code and compiling on Qt 5 that things are being a bit odd but this method now works, so I've not investigated further.

Streaming answered 3/3, 2019 at 14:45 Comment(0)
G
1

With Qt5, running a Qt application with the command line argument -platform offscreen does draw offscreen.

See the documentation https://doc.qt.io/qt-5/qguiapplication.html#QGuiApplication

The options currently supported are the following:

-platform platformName[:options], specifies the Qt Platform Abstraction (QPA) plugin.

Overrides the QT_QPA_PLATFORM environment variable.

The supported platform names are listed in the platformName docs.

Tested with Qt 5.15.1

Gadgetry answered 15/9, 2020 at 12:3 Comment(0)
N
0

I ran into this with Qt6, 6.6.1, in a Windows docker container. My unit-test executable would fail because Qt6 could not find some Windows related GUI DLLs. Setting -platform offscreen did not help on Windows.

This was the failure I saw:

unknown file: error: Unknown C++ exception thrown in the test fixture's constructor.

Then I used depends in console mode to profile my test executable to see the missing windows DLLs.

LoadLibraryW("Windows.UI.ViewManagement.dll") called from "c:\build\source\debug\platforms\QWINDOWSD.DLL" at address 0x00007FF83EF9F33C.
LoadLibraryW("Windows.UI.ViewManagement.dll") returned NULL. Error: The specified module could not be found (126).
LoadLibraryW("Windows.UI.dll") called from "c:\build\source\debug\platforms\QWINDOWSD.DLL" at address 0x00007FF83EF9F33C.
LoadLibraryW("Windows.UI.dll") returned NULL. Error: The specified module could not be found (126).
LoadLibraryW("Windows.dll") called from "c:\build\source\debug\platforms\QWINDOWSD.DLL" at address 0x00007FF83EF9F33C.
LoadLibraryW("Windows.dll") returned NULL. Error: The specified module could not be found (126).
LoadLibraryW("combase.dll") called from "c:\build\source\debug\platforms\QWINDOWSD.DLL" at address 0x00007FF83EFA02B0.
LoadLibraryW("combase.dll") returned 0x00007FF84B150000.

Next, I ran my test executable with the QT_LOGGING_RULES="*.debug=true" and found this debug line from Qt:

Attempting to create platform theme "windows" via CreatePlatformTheme

This led me to QGuiApplication docs and I found I needed to set QT_QPA_PLATFORMTHEME=null

Novella answered 13/12, 2023 at 16:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.