Improve behavior of `QtSettings::apply()` to be called multiple times

* Restore default settings
* Remove previously configured paths
This commit is contained in:
Martchus 2023-03-26 21:05:13 +02:00
parent 3e0754ebe5
commit bd1e603fcf
1 changed files with 60 additions and 19 deletions

View File

@ -24,6 +24,7 @@
#include <QStringBuilder> #include <QStringBuilder>
#include <QStyleFactory> #include <QStyleFactory>
#include <optional>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
@ -35,13 +36,18 @@ struct QtSettingsData {
QtSettingsData(); QtSettingsData();
QFont font; QFont font;
std::optional<QFont> initialFont;
QPalette palette; QPalette palette;
QString widgetStyle; QString widgetStyle;
QString initialWidgetStyle;
QString styleSheetPath; QString styleSheetPath;
QString iconTheme; QString iconTheme;
QString initialIconTheme;
QLocale defaultLocale; QLocale defaultLocale;
QString localeName; QString localeName;
QString previousPluginDirectory;
QString additionalPluginDirectory; QString additionalPluginDirectory;
QString previousIconThemeSearchPath;
QString additionalIconThemeSearchPath; QString additionalIconThemeSearchPath;
bool customFont; bool customFont;
bool customPalette; bool customPalette;
@ -54,6 +60,7 @@ struct QtSettingsData {
inline QtSettingsData::QtSettingsData() inline QtSettingsData::QtSettingsData()
: iconTheme(QIcon::themeName()) : iconTheme(QIcon::themeName())
, initialIconTheme(iconTheme)
, localeName(defaultLocale.name()) , localeName(defaultLocale.name())
, customFont(false) , customFont(false)
, customPalette(false) , customPalette(false)
@ -182,26 +189,42 @@ static QMap<QString, QString> scanIconThemes(const QStringList &searchPaths)
/*! /*!
* \brief Applies the current configuration. * \brief Applies the current configuration.
* \remarks * \remarks
* - Some settings take only affect after restarting the application. * QApplication/QGuiApplication must be instantiated before calling this
* - QApplication/QGuiApplication must be instantiated before calling this * method. Hence it makes most sense to call this directly after instantiating
* method.
* - Hence it makes most sense to call this directly after instantiating
* QApplication/QGuiApplication. * QApplication/QGuiApplication.
*
* This function may be called multiple times. This supports restoring default
* settings (e.g. if use of a custom icon theme has been disabled again after it
* was enabled the default icon theme will be configured again).
*/ */
void QtSettings::apply() void QtSettings::apply()
{ {
// apply environment // apply environment
if (m_d->additionalPluginDirectory.isEmpty()) { if (m_d->additionalPluginDirectory != m_d->previousPluginDirectory) {
QCoreApplication::addLibraryPath(m_d->additionalPluginDirectory); if (!m_d->previousPluginDirectory.isEmpty()) {
QCoreApplication::removeLibraryPath(m_d->previousPluginDirectory);
}
if (!m_d->additionalPluginDirectory.isEmpty()) {
QCoreApplication::addLibraryPath(m_d->additionalPluginDirectory);
}
m_d->previousPluginDirectory = m_d->additionalPluginDirectory;
} }
if (!m_d->additionalIconThemeSearchPath.isEmpty()) { if (m_d->additionalIconThemeSearchPath != m_d->previousIconThemeSearchPath) {
QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << m_d->additionalIconThemeSearchPath); auto paths = QIcon::themeSearchPaths();
if (!m_d->previousIconThemeSearchPath.isEmpty()) {
paths.removeAll(m_d->previousIconThemeSearchPath);
}
if (!m_d->additionalIconThemeSearchPath.isEmpty()) {
paths.append(m_d->additionalIconThemeSearchPath);
}
m_d->previousIconThemeSearchPath = m_d->additionalIconThemeSearchPath;
QIcon::setThemeSearchPaths(paths);
} }
// read style sheet // read style sheet
QString styleSheet; auto styleSheet = QString();
if (m_d->customStyleSheet && !m_d->styleSheetPath.isEmpty()) { if (m_d->customStyleSheet && !m_d->styleSheetPath.isEmpty()) {
QFile file(m_d->styleSheetPath); auto file = QFile(m_d->styleSheetPath);
if (!file.open(QFile::ReadOnly)) { if (!file.open(QFile::ReadOnly)) {
cerr << "Unable to open the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << endl; cerr << "Unable to open the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << endl;
} }
@ -213,26 +236,44 @@ void QtSettings::apply()
// apply appearance // apply appearance
if (m_d->customFont) { if (m_d->customFont) {
if (!m_d->initialFont.has_value()) {
m_d->initialFont = QGuiApplication::font();
}
QGuiApplication::setFont(m_d->font); QGuiApplication::setFont(m_d->font);
} else if (m_d->initialFont.has_value()) {
QGuiApplication::setFont(m_d->initialFont.value());
} }
if (m_d->customWidgetStyle) { if (m_d->customWidgetStyle) {
QApplication::setStyle(m_d->widgetStyle); #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
} const auto *const currentStyle = QApplication::style();
if (!styleSheet.isEmpty()) { if (m_d->initialWidgetStyle.isEmpty() && currentStyle) {
if (auto *qapp = qobject_cast<QApplication *>(QApplication::instance())) { m_d->initialWidgetStyle = currentStyle->name();
qapp->setStyleSheet(styleSheet);
} else {
cerr << "Unable to apply the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data()
<< "\" because no QApplication has been instantiated." << endl;
} }
#endif
QApplication::setStyle(m_d->widgetStyle);
} else if (!m_d->initialWidgetStyle.isEmpty()) {
QApplication::setStyle(m_d->initialWidgetStyle);
}
if (auto *const qapp = qobject_cast<QApplication *>(QApplication::instance())) {
qapp->setStyleSheet(styleSheet);
} else {
cerr << "Unable to apply the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data()
<< "\" because no QApplication has been instantiated." << endl;
} }
if (m_d->customPalette) { if (m_d->customPalette) {
QGuiApplication::setPalette(m_d->palette); QGuiApplication::setPalette(m_d->palette);
} else {
QGuiApplication::setPalette(QPalette());
} }
m_d->isPaletteDark = isPaletteDark(); m_d->isPaletteDark = isPaletteDark();
if (m_d->customIconTheme) { if (m_d->customIconTheme) {
QIcon::setThemeName(m_d->iconTheme); QIcon::setThemeName(m_d->iconTheme);
} else if (QIcon::themeName().isEmpty()) { } else if (!m_d->initialIconTheme.isEmpty()) {
if (m_d->iconTheme != m_d->initialIconTheme) {
// set the icon theme back to what it was before changing anything (not sure how to read the current system icon theme again)
QIcon::setThemeName(m_d->initialIconTheme);
}
} else {
// use bundled default icon theme matching the current palette // use bundled default icon theme matching the current palette
// notes: - It is ok that search paths specified via CLI arguments are not set here yet. When doing so one should also // notes: - It is ok that search paths specified via CLI arguments are not set here yet. When doing so one should also
// specify the desired icon theme explicitly. // specify the desired icon theme explicitly.