Qt application with optional gui - c++

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?

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.

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();
}

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.

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

Related

Qt Qml How to set the value of the QSG_INFO parameter to 1

I got stuck with the problem that my application on some PCs loads the processor very heavily, and does not load the video card at all. When I went to figure it out, I came across this article: https://www.qt.io/blog/2017/01/18/opengl-implementation-qt-quick-app-using-today
It describes the method of debugging, and says that it is necessary to set the value of the environment QSG_INFO = 1. Current I do not quite understand where it needs to be done.
To set an environment variable you can use qputenv():
#include <QtGlobal>
int main(int argc, char *argv[]) {
qputenv("QSG_INFO", "1");
QGuiApplication a(argv, argc);
// ...
or you can set when launching the executable:
QSG_INFO=1 ./your_executable
If you are running your application from Qt Creator you can add/overwrite environment variables from the Project tab:
Look at this Qt doc for more info.

QApplication::setApplicationDisplayName not always falls back to QApplication::applicationName()

I am running a small app on KDE Plasma 5 created with Qt and the KDE framework. Almost everything works like a charm, just one part doesn't work. I just cannot set the application display name. I have the following code:
int main(int argc, char **argv) {
QApplication application(argc, argv);
KLocalizedString::setApplicationDomain("blender-render-control");
KCrash::initialize();
KAboutData aboutData(QStringLiteral("blender-render-control-center"),
i18n("Blender Render Control Center"),
QStringLiteral("1.0"),
i18n("A simple application to control the blender render control server"),
KAboutLicense::Custom,
i18n("Copyright 2019, Knerd <knerd#knerd.knerd>"));
aboutData.addAuthor(i18n("Knerd"), i18n("Author"), QStringLiteral("knerd#knerd.knerd"));
aboutData.setOrganizationDomain("knerd.knerd");
aboutData.setDesktopFileName(QStringLiteral("knerd.knerd.blender-render-control"));
KAboutData::setApplicationData(aboutData);
QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("knerd.knerd.blender-render-control")));
application.setApplicationDisplayName(i18n("Blender Render Control Center"));
application.setApplicationName(i18n("Blender Render Control Center"));
QCommandLineParser parser;
aboutData.setupCommandLine(&parser);
parser.process(application);
aboutData.processCommandLine(&parser);
auto *window = new MainWindow();
window->show();
return QApplication::exec();
}
From reading the docs and checking some examples, this should set the application title in my KDE environment. But it doesn't, the application name is the name of the executable.
Is this a bug in KDE or am I doing something wrong?

Using pdf.js with Qt5.8

I am trying to make a pdf viewer in Qt5.8 .I know that poppler is a choice for Qt but I want to do this using pdf.js .I dont know how to embed pdf.js with Qt5.8. I have seen the hello world documentation of pdf.js but it didn't helped. Please help me.
Thanks in advance .
The basic idea would be to have some widget to display HTML if you want to make use of pdf.js - it seems that QWebEngineView (makes use of Chromium) could do the job as it takes a minimum of code to get your first implementation done.
Having an installation of pdf.js on your computer and a minimalistic gui application (QT Widgets project) prepared with your QT Creator, you could use the following code to have the basics:
#include "mainwindow.h"
#include <QApplication>
#include <QWebEngineView>
static QString pathToPDFjs = QString("file:///path-to/pdfjs-1.8.170-dist/web/viewer.html");
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow win;
QWebEngineView *view;
QString pdfFileURL;
//you could parse a widget to get the file name
pdfFileURL = QString("file:///path-to-your/file.pdf");
//init the view and attach it to the ui
view = new QWebEngineView();
win.setCentralWidget(view);
win.show();
//auto-load feature in pdf.js, pass file=filename as parameter
view->load(QUrl::fromUserInput(pathToPDFjs + QString("?file=") + pdfFileURL));
view->show();
return app.exec();
}
From there on you can add extra functionality to your user interface.
You could even add modifications to your installation of pdf.js (if needed).
If you'd need to call JavaScript on your pdf.js, you can make use of the view's page (a QWebEnginePage) which in turn can runJavaScript.
No idea why you want to use pdf.js, but you might want to have a look at QtLabs PDF module. It seems pretty recent and well integrated with current Qt. (and I guess it's more efficient than JavaScript code)
If you want to try it out, here’s how to get started:
git clone git://code.qt.io/qt-labs/qtpdf
cd qtpdf
git submodule update --init --recursive
qmake
make
cd examples/pdf/pdfviewer
qmake
make
./pdfviewer /path/to/my/file.pdf

How to print version of a Qt GUI application to console

I have a GUI application written using Qt Widgets. I've added versioning and I'm planning to write an update manager too. In order this to work the update manager must be able to determine the version of my app. I thought of implementing this by running my app with a version switch then parsing it's output. I did a research and I found out that Qt has some kind of built in solution for this.
Here is an example:
#include "mainwindow.h"
#include <QApplication>
#include <QCommandLineParser>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QApplication::setApplicationVersion("1.0.0");
QCommandLineParser parser;
auto versionOption = parser.addVersionOption();
parser.process(app);
if (parser.isSet(versionOption))
{
MainWindow w;
w.show();
return app.exec();
}
return 0;
}
If I launch this app with a -v or --version command line switch, I get a message box containing the version information.
I need to achieve the same, only the information should be printed to standard output. If the app is launched with the version switch it should only display the version in the console then close.
How could I print the version information to the standard console output with a GUI app?
As we cleared some points in comments let's move on. ;)
Take a look at the documentation (http://doc.qt.io/qt-5/qapplication.html#details). In the detail section you see a sane way how to properly parse and handle command line options.
And here (https://stackoverflow.com/a/3886128/6385043) you can see a possibility for writing to standard output. Notice the QDebug caveat.
In my opinion, stick to the text file. You may generate it during build with qmake using the variable VERSION, which you can also use with QApplication::setApplicationVersion(QString).

QProcess::execute("clear") Issue

I'm writing a small console app in Qt and I want to be able to clear the terminal on a user command. I found this:
How clear screen in QT console?
which almost answers my question, but its not working.
When the function "QProcess::execute("clear");" is run, I get this output to the terminal:
TERM environment variable not set.
I'm pretty new to Linux and though I've set environment variables before, its always been in the terminal before I ran the program. Here, I'd like to take care of this programmatically if possible.
My guess is that I could use QProcess::setProcessEnvironment() but I'm not really sure how exactly.
Is it possible to set the environment variables in this way, and if so how?
Any help would be greatly appreciated!
Here's the sample code I'm working with:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream qin(stdin);
QTextStream qout(stdout);
QString cmd;
while(1)
{
cmd = qin.readLine();
qout<<"command is: "<<cmd<<endl;
if(cmd == "clear")
{
QProcess::execute("clear");
}
}
return a.exec();
}
The code below works fine for me. Please make sure that the clear command works fine in your console first.
main.cpp
#include <QProcess>
#include <QDebug>
int main()
{
QProcess::execute("clear");
qDebug() << QProcessEnvironment::systemEnvironment().contains("TERM");
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Build and Run
qmake && make && ./main
Note that if you are using QtCreator, you will need add the environment variable with its value explicitly in the build settings tab. Here you can find more details in the documentation:
QtCreator - Using Environment Variables