Is Qt forcing the system locale? - qt

The following example seems to show a bug in Qt. Or am i mistaken ?
std::cout << atof("0.456") << std::endl; // OK prints 0.456
QApplication app (argc, argv);
//QLocale::setDefault(QLocale::C); // No effect at all.
std::cout << atof("0.456") << std::endl; // do not work on on fr_FR.UTF-8, print 0.
When using a non standard locale, in my example fr_FR.UTF-8, creating the QApplication seems to change the system locale, as it is used by atof to do the conversion.
To me it looks like the creation of the QApplication will pull the system locale and call a setenv with it.

From Qt documentation
Locale Settings
On Unix/Linux Qt is configured to use the system locale settings by default.
This can cause a conflict when using POSIX functions, for instance,
when converting between data types such as floats and strings, since the notation may differ between locales.
To get around this problem, call the POSIX function setlocale(LC_NUMERIC,"C")
right after initializing QApplication or QCoreApplication to reset the locale that is used for number formatting to "C"-locale.

To me it looks like the creation of the QApplication will pull the system locale and call a setenv with it.
No, it will call setlocale:
void QCoreApplicationPrivate::initLocale()
{
if (qt_locale_initialized)
return;
qt_locale_initialized = true;
#if defined(Q_OS_UNIX) && !defined(QT_BOOTSTRAPPED)
setlocale(LC_ALL, "");
#endif
}
Which in turn fetches the locale from the environment variables, as the empty string stands for the user-preferred locale. Otherwise you'd be using the C locale.

Related

Can I use QApplication AND QCoreApplication?

I have a console application using QCoreApplication in Qt5. This application has different functions like "printABC" or "printSUV". The output will appear in the terminal.
Now I want to make a Gui, where I can push the buttons "printABC" or "printSUV" and the output will appear in the terminal too, so that it is 'easier' to use the application.
In Qt5, I can make a console application using QCoreApplication, which I have already done.
So my question is how can I add a QApplication which runs along the way?
In the docs, it is recommended to create a QApplication/QCoreApplication in the main function, so how can I create both?
You can easily have a single application which supports both command-line (terminal) mode and GUI mode. Just use QApplication (or QGuiApplication for QML-only app).
UPDATE 1: The commenters are correct, it would be better to instantiate QCoreApplication or Q[Gui]Application depending on which is actually needed...
Then, for example, if a user passes CLI options, you just run the function(s) and send the result to sdtout (presumably like you're doing now). Otherwise show the GUI and use the same functions but to display the data some other way (in the UI).
UPDATE 2: ... So it would be better to parse the command line first and determine which Q*Application "flavor" should be used...
If you haven't yet, you can look into QCommandLineParser to help handle the CLI options. Just keep in mind that it works exactly the same with a Q[Gui]Application as well.
UPDATE 3: ... In fact QCommandLineParser can be used before a Q*Application is created. One just needs to call parse() with a list of options from argv, instead of process() with the app instance. See code example below.
In main(), handle any CLI options first. Then to NOT launch the GUI you could simply exit(0) from main() before calling app.exec().
A basic example:
int main(int argc, char *argv[]) {
QCoreApplication *app;
QCommandLineParser clp;
clp.setApplicationDescription("My app does great things.");
clp.addOptions({{"cli", "Use CLI interface"}});
QStringList opts;
for (int i=0; i < argc; ++i)
opts << QString(argv[i]);
clp.parse(opts);
if (clp.isSet("cli"))
app = new QCoreApplication(argc, argv);
else
app = new QApplication(argc, argv);
...
return app->exec(); // or maybe just 0, or app->exit(), if no event loop is needed.
}
If you want to show the output in the console from which the application was started, then you can still simply print to stdout (or whatever you're doing now). However if you want this to work on Windows, additional steps may be required... and there are a few things to consider. This would really be the topic of a different question, I think. IMHO mixing the two (GUI in one window and output in console) could be rather awkward, and showing output in GUI makes it all nicely self-contained.

Using QSettings in a global static class

My task is to create a QSettings wrapper class (wrapping is mostly needed by QML) which I can reach everywhere from the model, too.
The obvious choice is a static global instance of this class. However the problem is with this approach is that it's destroyed after main, after QApplication is destroyed, thus giving me the following warning:
QApplication::qAppName: Please instantiate the QApplication object first
Here is a simplified, sample code showing a really simple wrapper, and the destruction phases:
#include <QCoreApplication>
#include <QDebug>
#include <QGlobalStatic>
#include <QSettings>
#include <QTimer>
class Settings: public QObject
{
public:
~Settings() { qDebug() << "~Settings"; }
QSettings settings;
};
Q_GLOBAL_STATIC(Settings, globalSettings)
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QObject::connect(&app, &QCoreApplication::aboutToQuit, [](){qDebug() << "~QCoreApplication aboutToQuit";});
QObject::connect(&app, &QCoreApplication::aboutToQuit, [](){globalSettings->settings.setValue("Hi", 2);});
QObject::connect(&app, &QCoreApplication::destroyed, [](){qDebug() << "~QCoreApplication destroyed";});
QTimer::singleShot(0, &app, SLOT(quit()));
return app.exec();
}
It prints out the following:
~QCoreApplication aboutToQuit
~QCoreApplication destroyed
~Settings
QApplication::qAppName: Please instantiate the QApplication object first
My question is: providing, in my program QSettings is used after QCoreApplication::aboutToQuit is emitted but before QCoreApplication::destroyed, how can I avoid this warning?
Using QSettings
I've used QSettings in pretty much every project I've ever made. Here is the pattern that I tend to use it:
in main.cpp
#include <QSettings>
//...
// Then in main(), after QApplication is instantiated, but before any settings are accessed
QSettings::setDefaultFormat(QSettings::IniFormat);
QApplication::setOrganizationName("MyOrg");
QApplication::setApplicationName("MyApp"):
Then anytime you are about to access QSettings, you just do this:
QSettings s;
s.value(// reading a value
s.setValue(// writing a value
Everything gets saved in the User Scope in an INI text file. It will be located in Windows under C:/Users/<username>/AppData/Roaming/MyOrg/MyApp.ini.
This usage of QSettings (IMHO) is very clean, doesn't require global variables or static references and is very fast and efficient. And it is very readable.
Now to be able to have things load settings at the right times, and not get the errors you mentioned in your question, see the initial example in the links below:
http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application
http://doc.qt.io/qt-5/qtwidgets-mainwindows-application-example.html
It works much better in the timeline of a Qt application and works great. I tend to make a readSettings and writeSettings for most of my GUI classes and for a number of my backend classes. readSettings happens when the widget has its showEvent or constructor happen and the writeSettings happens in the closeEvent. Also if I have a dedicated settings dialog, I emit a signal to have any affected classes to readSettings, right after the settings dialog writes those specific settings.
If you use the QML port of QSettings, it also uses the Organization name and Application name and the default format of QSettings to pick its filename and location.
http://doc.qt.io/qt-5/qml-qt-labs-settings-settings.html
I believe the default functionality of that QML component is just to read the setting when the component is created, and to write the setting whenever QML changes it. So to change it from C++ and have it recognized by QML, you should probably use the standard QML/C++ methods out there such as:
http://doc.qt.io/qt-5/qtqml-cppintegration-topic.html
And lastly if I am planning on installing defaults for a program that are decided for a build and I don't want to hardcode them, I hand write an INI file and have the installer place it in the system scope location: C:/ProgramData/MyOrg/MyApp.ini
And in the case that the settings of your program are more complex than what you want to store in an INI file, I would look into using QJson, and the SaveGame example.
Hope that helps.

And so a QVariant instantiation silently registeres a (previously declared) metatype

Take this program (adapted from an exploratory test-case, where I noticed that a custom metatype bahaves as if it was registered, although qRegisterMetaType had not been called):
#include <QMetaType>
#include <QVariant>
#include <iostream>
class C1 {
};
Q_DECLARE_METATYPE(C1)
int main() {
std::cout << QMetaType::type("C1") << std::endl;
QVariant v = QVariant::fromValue<C1>(C1());
std::cout << QMetaType::type("C1") << std::endl;
return 0;
}
This outputs:
0
256
(and further tests do show that the metatype is indeed registered -- it can be construct'ed (even in places where Q_DECLARE_METATYPE(..) is not visible), etc)
Is this behaviour well-known? Relied on? (Probably not, but attempting to get a failing test following the "official" rule to register a metatype first got me puzzled, hence the question)
P.S. Of course, one can see qRegisterMetaType called within Q_DECLARE_METATYPE(..), but the question still holds (at least I would like it to).
Thanks in advance.
Q_DECLARE_METATYPE doesn't call qRegisterMetaType, it defines a function that does. But QVariant::fromValue<C1> calls qRegisterMetaType indirectly, by calling the previously defined function.
The documentation suggests that calling qRegisterMetaType is only needed for things like queued connections.
Which means that you don't need to call qRegisterMetaType before using QVariant template functions for your type (but Q_DECLARE_METATYPE has to be called in each compilation unit where those template functions are used or the compilation will fail).

Correct way to quit a Qt program?

How should I quit a Qt Program, e.g when loading a data file, and discovered file corruption, and user need to quit this app or re-initiate data file?
Should I:
call exit(EXIT_FAILURE)
call QApplication::quit()
call QCoreApplication::quit()
And difference between (2) and (3)?
QApplication is derived from QCoreApplication and thereby inherits quit() which is a public slot of QCoreApplication, so there is no difference between QApplication::quit() and QCoreApplication::quit().
As we can read in the documentation of QCoreApplication::quit() it "tells the application to exit with return code 0 (success).". If you want to exit because you discovered file corruption then you may not want to exit with return code zero which means success, so you should call QCoreApplication::exit() because you can provide a non-zero returnCode which, by convention, indicates an error.
It is important to note that "if the event loop is not running, this function (QCoreApplication::exit()) does nothing", so in that case you should call exit(EXIT_FAILURE).
You can call qApp->exit();. I always use that and never had a problem with it.
If you application is a command line application, you might indeed want to return an exit code. It's completely up to you what the code is.
While searching this very question I discovered this example in the documentation.
QPushButton *quitButton = new QPushButton("Quit");
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection);
Mutatis mutandis for your particular action of course.
Along with this note.
It's good practice to always connect signals to this slot using a
QueuedConnection. If a signal connected (non-queued) to this slot is
emitted before control enters the main event loop (such as before "int
main" calls exec()), the slot has no effect and the application never
exits. Using a queued connection ensures that the slot will not be
invoked until after control enters the main event loop.
It's common to connect the QGuiApplication::lastWindowClosed() signal
to quit()
If you're using Qt Jambi, this should work:
QApplication.closeAllWindows();
if you need to close your application from main() you can use this code
int main(int argc, char *argv[]){
QApplication app(argc, argv);
...
if(!QSslSocket::supportsSsl()) return app.exit(0);
...
return app.exec();
}
The program will terminated if OpenSSL is not installed
//How to Run App
bool ok = QProcess::startDetached("C:\\TTEC\\CozxyLogger\\CozxyLogger.exe");
qDebug() << "Run = " << ok;
//How to Kill App
system("taskkill /im CozxyLogger.exe /f");
qDebug() << "Close";
example

Getting font metrics without GUI (console mode)

Let's say some images have to be generated by a Qt console program and that font metrics are needed by internal algorithms (they use the text width/height as input to compute the position where the drawing should occur). This program has to be runable on a Linux without any GUI (runlevel-3, basically a cluster without any display server).
Problem: QFontMetrics are only available when running a Qt application in GUI mode.
Any workaround to get string metrics without any display server ?
Ok after additional comments I think I understand your problem.
Just do it like that:
include <QApplication>
int main(int argv, char **args)
{
QApplication app(argv, args);
QApplication::processEvents(); // this should allow `QApplication` to complete its initialization
// do here whatever you need
return 0; // or some other value to report errors
}
You can also try use QGuiApplication this version doesn't require (doesn't use) widgets.
See also example in documentation how to handle none gui cases.
This code works perfectly on my Ubnutu with Qt 5.3
#include <QGuiApplication>
#include <QFontMetrics>
#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
QFont font("Times", 10, QFont::Bold);
qDebug() << font;
QFontMetrics metrics(font);
qDebug() << metrics.boundingRect("test");
return 0;
}
It also works with Qt 4.8 when QApplication is used.
Project file was quite simple
QT += core
TARGET = MetricsNoGui
TEMPLATE = app
SOURCES += main.cpp
Qt 4.8 has such QApplication constructor, whose 3rd parameter can help to solve the issue. Simple provide false as 3rd argument and enjoy using QFontMetrics in Qt console application. There will be no crashes if one starts app on systems without X server.
I didn't find a way to use QFont or QPrinter with QCoreApplication :( However, if you are able to install Xvfb, then your QApplication will be runnable also on a server without any display. I'm using this setup on a headless Raspberry Pi Zero.
Xvfb :1 -screen 0 1024x768x16 &
export DISPLAY=:1.0
./YourQApplication
This isn't the most elegant solution, but after hours of desperate searching, it's the only one I found.

Resources