3#include "resources/config.h"
13#include <QStringBuilder>
15#if defined(QT_UTILITIES_GUI_QTWIDGETS)
16#include <QApplication>
17#elif defined(QT_UTILITIES_GUI_QTQUICK)
18#include <QGuiApplication>
20#include <QCoreApplication>
25#include <QStandardPaths>
29#include <c++utilities/conversion/stringbuilder.h>
37inline void initResources()
39 Q_INIT_RESOURCE(qtutilsicons);
42inline void cleanupResources()
44 Q_CLEANUP_RESOURCE(qtutilsicons);
78namespace TranslationFiles {
83static QList<QTranslator *> translators;
96static QString relativeBase()
98 static const auto relativeBase = [] {
99 auto appDir = QCoreApplication::applicationDirPath();
100 if (appDir.isEmpty()) {
101 appDir = QStringLiteral(
".");
145 const auto debugTranslations = qEnvironmentVariableIntValue(
"QT_DEBUG_TRANSLATIONS");
146 const auto relBase = relativeBase();
147 for (
const auto &repoName : repositoryNames) {
148 auto *
const qtTranslator =
new QTranslator(QCoreApplication::instance());
149 const auto fileName = QString(repoName % QChar(
'_') % localeName);
153 || qtTranslator->load(fileName,
155#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
156 QLibraryInfo::location(QLibraryInfo::TranslationsPath)
158 QLibraryInfo::path(QLibraryInfo::TranslationsPath)
161 || qtTranslator->load(fileName, path = relBase + QStringLiteral(
"/../share/qt/translations"))
162 || qtTranslator->load(fileName, path = QStringLiteral(
":/translations"))) {
163 QCoreApplication::installTranslator(qtTranslator);
164 translators.append(qtTranslator);
165 if (debugTranslations) {
166 cerr <<
"Loading translation file for Qt repository \"" << repoName.toLocal8Bit().data() <<
"\" and the locale \""
167 << localeName.toLocal8Bit().data() <<
"\" from \"" << path.toLocal8Bit().data() <<
"\"." << endl;
171 if (localeName.startsWith(QLatin1String(
"en"))) {
175#if defined(Q_OS_ANDROID)
176 qDebug() <<
"Unable to load translation file for Qt repository: " << repoName << localeName;
178 cerr <<
"Unable to load translation file for Qt repository \"" << repoName.toLocal8Bit().data() <<
"\" and locale "
179 << localeName.toLocal8Bit().data() <<
"." << endl;
209 const auto defaultLocale(QLocale().name());
210 if (defaultLocale != QLatin1String(
"en_US")) {
216static void logTranslationEvent(
217 const char *event,
const QString &configName,
const QString &applicationName,
const QString &localeName,
const QString &path = QString())
219#if defined(Q_OS_ANDROID)
220 qDebug() << CppUtilities::argsToString(event,
" translation file for: ").data() << applicationName << localeName;
221 if (!configName.isEmpty()) {
222 qDebug() <<
"config: " << configName;
224 if (!path.isEmpty()) {
225 qDebug() <<
"path: " << path;
228 cerr <<
event <<
" translation file for \"" << applicationName.toLocal8Bit().data() <<
"\"";
229 if (!configName.isEmpty()) {
230 cerr <<
" (config \"" << configName.toLocal8Bit().data() <<
"\")";
232 cerr <<
" and locale \"" << localeName.toLocal8Bit().data() <<
'\"';
233 if (!path.isEmpty()) {
234 cerr <<
" from \"" << path.toLocal8Bit().data() <<
'\"';
263 auto *
const appTranslator =
new QTranslator(QCoreApplication::instance());
264 const auto fileName = QString(applicationName % QChar(
'_') % localeName);
265 const auto directoryName = configName.isEmpty() ? applicationName : QString(applicationName % QChar(
'-') % configName);
266 const auto relBase = relativeBase();
269 || appTranslator->load(fileName, path = relBase) || appTranslator->load(fileName, path = relBase % QStringLiteral(
"/../") % directoryName)
270 || appTranslator->load(fileName, path = relBase % QStringLiteral(
"/../../") % directoryName)
271 || appTranslator->load(fileName, path = relBase % QStringLiteral(
"/translations"))
272 || appTranslator->load(fileName, path = relBase % QStringLiteral(
"/../share/") % directoryName % QStringLiteral(
"/translations"))
273 || appTranslator->load(fileName, path = QStringLiteral(APP_INSTALL_PREFIX
"/share/") % directoryName % QStringLiteral(
"/translations"))
274 || appTranslator->load(fileName, path = QStringLiteral(
":/translations"))) {
275 QCoreApplication::installTranslator(appTranslator);
276 translators.append(appTranslator);
277 if (qEnvironmentVariableIntValue(
"QT_DEBUG_TRANSLATIONS")) {
278 logTranslationEvent(
"Loading", configName, applicationName, localeName, path);
281 delete appTranslator;
282 if (localeName.startsWith(QLatin1String(
"en"))) {
286 logTranslationEvent(
"Unable to load", configName, applicationName, localeName);
297 for (
const QString &applicationName : applicationNames) {
310 for (
const QString &applicationName : applicationNames) {
320 for (
auto *
const translator : translators) {
321 QCoreApplication::removeTranslator(translator);
333namespace ApplicationInstances {
335#if defined(QT_UTILITIES_GUI_QTWIDGETS)
341 return qobject_cast<QApplication *>(QCoreApplication::instance()) !=
nullptr;
345#if defined(QT_UTILITIES_GUI_QTWIDGETS) || defined(QT_UTILITIES_GUI_QTQUICK)
351 return qobject_cast<QGuiApplication *>(QCoreApplication::instance()) !=
nullptr;
360 return qobject_cast<QCoreApplication *>(QCoreApplication::instance()) !=
nullptr;
376#if defined(Q_OS_WINDOWS) && (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) && (QT_VERSION < QT_VERSION_CHECK(6, 5, 0))
377 if (
const auto qtVersion = QLibraryInfo::version();
378 qtVersion >= QVersionNumber(6, 4, 0) && qtVersion < QVersionNumber(6, 5, 0) && !qEnvironmentVariableIsSet(
"QT_QPA_PLATFORM")) {
379 qputenv(
"QT_QPA_PLATFORM",
"windows:darkmode=1");
384#ifdef QT_FEATURE_fontdialog
385 if (!qEnvironmentVariableIsSet(
"FONTCONFIG_PATH") && QDir(QStringLiteral(
"/etc/fonts")).exists()) {
386 qputenv(
"FONTCONFIG_PATH",
"/etc/fonts");
391#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
392 if (!QCoreApplication::instance()) {
393 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling,
true);
395 QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps,
true);
411std::unique_ptr<QSettings>
getSettings(
const QString &organization,
const QString &application)
413 auto settings = std::unique_ptr<QSettings>();
414 const auto portableFileName
415 = application.isEmpty() ? organization + QStringLiteral(
".ini") : organization % QChar(
'/') % application % QStringLiteral(
".ini");
416 if (
const auto portableFileWorkingDir = QFile(portableFileName); portableFileWorkingDir.exists()) {
417 settings = std::make_unique<QSettings>(portableFileWorkingDir.fileName(), QSettings::IniFormat);
418 }
else if (
const auto portableFileNextToApp = QFile(QCoreApplication::applicationDirPath() % QChar(
'/') % portableFileName);
419 portableFileNextToApp.exists()) {
420 settings = std::make_unique<QSettings>(portableFileNextToApp.fileName(), QSettings::IniFormat);
422 settings = std::make_unique<QSettings>(QSettings::IniFormat, QSettings::UserScope, organization, application);
424 if (organization != QCoreApplication::organizationName() || application != QCoreApplication::applicationName()) {
426 = QSettings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName())
428 QFile::rename(oldConfig, settings->fileName()) || QFile::remove(oldConfig);
441 if (!qEnvironmentVariableIntValue(
"QT_DEBUG_SETTINGS")) {
445 if (error.isEmpty()) {
446 std::cerr <<
"Loaded/synced settings from " << settings.fileName().toStdString() <<
'\n';
448 std::cerr <<
"Unable to load settings: " << error.toStdString() <<
'\n';
458 if (!qEnvironmentVariableIntValue(
"QT_DEBUG_SETTINGS")) {
462 if (error.isEmpty()) {
463 std::cerr <<
"Saved/synced settings to " << settings.fileName().toStdString() <<
'\n';
465 std::cerr <<
"Unable to save settings: " << error.toStdString() <<
'\n';
474 auto errorMessage = QString();
475 switch (settings.status()) {
476 case QSettings::NoError:
478 case QSettings::AccessError:
479 errorMessage = QCoreApplication::translate(
"QtUtilities",
"unable to access file");
481 case QSettings::FormatError:
482 errorMessage = QCoreApplication::translate(
"QtUtilities",
"file has invalid format");
485 errorMessage = QCoreApplication::translate(
"QtUtilities",
"unknown error");
487 return QCoreApplication::translate(
"QtUtilities",
"Unable to sync settings from \"%1\": %2").arg(settings.fileName(), errorMessage);
497 const auto cachePaths = QStandardPaths::standardLocations(QStandardPaths::CacheLocation);
498 for (
const auto &cachePath : cachePaths) {
499 const auto cacheDir = QDir(cachePath);
500 const auto subdirs = cacheDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
501 for (
const auto &subdir : subdirs) {
502 if (subdir.startsWith(QLatin1String(
"qtpipelinecache"))) {
503 QFile::remove(cachePath % QChar(
'/') % subdir % QStringLiteral(
"/qqpc_opengl"));
QT_UTILITIES_EXPORT bool hasCoreApp()
Returns whether a QCoreApplication has been instantiated yet.
Functions for using the resources provided by this library.
QT_UTILITIES_EXPORT void init()
Initiates the resources used and provided by this library.
QT_UTILITIES_EXPORT void cleanup()
Frees the resources used and provided by this library.
QT_UTILITIES_EXPORT void loadQtTranslationFile(std::initializer_list< QString > repositoryNames)
Loads and installs the appropriate Qt translation file for the current locale.
QT_UTILITIES_EXPORT void clearTranslationFiles()
Clears all translation files previously loaded via the load-functions in this namespace.
QT_UTILITIES_EXPORT void loadApplicationTranslationFile(const QString &configName, const QString &applicationName)
Loads and installs the appropriate application translation file for the current locale.
QT_UTILITIES_EXPORT QString & additionalTranslationFilePath()
Allows to set an additional search path for translation files.
QT_UTILITIES_EXPORT void loadSettingsWithLogging(QSettings &settings)
Loads settings and logs a corresponding message if the env variable QT_DEBUG_SETTINGS is set.
QT_UTILITIES_EXPORT std::unique_ptr< QSettings > getSettings(const QString &organization, const QString &application=QString())
Returns the settings object for the specified organization and application.
QT_UTILITIES_EXPORT void deletePipelineCacheIfNeeded()
Deletes the Qt Quick pipeline cache on platforms where this is needed to workaround issues with the c...
QT_UTILITIES_EXPORT void setupCommonQtApplicationAttributes()
Sets Qt application attributes which are commonly used within my Qt applications.
QT_UTILITIES_EXPORT void saveSettingsWithLogging(QSettings &settings)
Saves settings and logs a corresponding message if the env variable QT_DEBUG_SETTINGS is set.
QT_UTILITIES_EXPORT QString errorMessageForSettings(const QSettings &settings)
Returns an error message for the specified settings or an empty string if there's no error.