7#include "../paletteeditor/paletteeditor.h"
9#include "../widgets/clearlineedit.h"
11#include "../resources/resources.h"
13#include "../misc/desktoputils.h"
15#include "ui_qtappearanceoptionpage.h"
16#include "ui_qtenvoptionpage.h"
17#include "ui_qtlanguageoptionpage.h"
24#include <QStringBuilder>
25#include <QStyleFactory>
27#if defined(Q_OS_WINDOWS) && (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
28#include <QOperatingSystemVersion>
29#define QT_UTILITIES_USE_FUSION_ON_WINDOWS_11
69 : iconTheme(QIcon::themeName())
70 , initialIconTheme(iconTheme)
71 , localeName(defaultLocale.name())
73 , customPalette(false)
74 , customWidgetStyle(false)
75 , customStyleSheet(false)
76 , customIconTheme(false)
90QtSettings::QtSettings()
100QtSettings::~QtSettings()
112void QtSettings::disableNotices()
114 m_d->showNotices =
false;
120bool QtSettings::hasCustomFont()
const
122 return m_d->customFont;
131void QtSettings::restore(QSettings &settings)
133 settings.beginGroup(QStringLiteral(
"qt"));
134 m_d->font.fromString(settings.value(QStringLiteral(
"font")).toString());
135 m_d->customFont = settings.value(QStringLiteral(
"customfont"),
false).toBool();
136 m_d->palette = settings.value(QStringLiteral(
"palette")).value<QPalette>();
137 m_d->customPalette = settings.value(QStringLiteral(
"custompalette"),
false).toBool();
138 m_d->widgetStyle = settings.value(QStringLiteral(
"widgetstyle"), m_d->widgetStyle).toString();
139 m_d->customWidgetStyle = settings.value(QStringLiteral(
"customwidgetstyle"),
false).toBool();
140 m_d->styleSheetPath = settings.value(QStringLiteral(
"stylesheetpath"), m_d->styleSheetPath).toString();
141 m_d->customStyleSheet = settings.value(QStringLiteral(
"customstylesheet"),
false).toBool();
142 m_d->iconTheme = settings.value(QStringLiteral(
"icontheme"), m_d->iconTheme).toString();
143 m_d->customIconTheme = settings.value(QStringLiteral(
"customicontheme"),
false).toBool();
144 m_d->localeName = settings.value(QStringLiteral(
"locale"), m_d->localeName).toString();
145 m_d->customLocale = settings.value(QStringLiteral(
"customlocale"),
false).toBool();
146 m_d->additionalPluginDirectory = settings.value(QStringLiteral(
"plugindir")).toString();
147 m_d->additionalIconThemeSearchPath = settings.value(QStringLiteral(
"iconthemepath")).toString();
155void QtSettings::save(QSettings &settings)
const
157 settings.beginGroup(QStringLiteral(
"qt"));
158 settings.setValue(QStringLiteral(
"font"), QVariant(m_d->font.toString()));
159 settings.setValue(QStringLiteral(
"customfont"), m_d->customFont);
160 settings.setValue(QStringLiteral(
"palette"), QVariant(m_d->palette));
161 settings.setValue(QStringLiteral(
"custompalette"), m_d->customPalette);
162 settings.setValue(QStringLiteral(
"widgetstyle"), m_d->widgetStyle);
163 settings.setValue(QStringLiteral(
"customwidgetstyle"), m_d->customWidgetStyle);
164 settings.setValue(QStringLiteral(
"stylesheetpath"), m_d->styleSheetPath);
165 settings.setValue(QStringLiteral(
"customstylesheet"), m_d->customStyleSheet);
166 settings.setValue(QStringLiteral(
"icontheme"), m_d->iconTheme);
167 settings.setValue(QStringLiteral(
"customicontheme"), m_d->customIconTheme);
168 settings.setValue(QStringLiteral(
"locale"), m_d->localeName);
169 settings.setValue(QStringLiteral(
"customlocale"), m_d->customLocale);
170 settings.setValue(QStringLiteral(
"plugindir"), m_d->additionalPluginDirectory);
171 settings.setValue(QStringLiteral(
"iconthemepath"), m_d->additionalIconThemeSearchPath);
181static QMap<QString, QString> scanIconThemes(
const QStringList &searchPaths)
183 auto res = QMap<QString, QString>();
184 for (
const auto &searchPath : searchPaths) {
185 const auto dir = QDir(searchPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
186 for (
const auto &iconTheme : dir) {
187 auto indexFile = QFile(searchPath % QChar(
'/') % iconTheme % QStringLiteral(
"/index.theme"));
188 auto index = QByteArray();
189 if (indexFile.open(QFile::ReadOnly) && !(index = indexFile.readAll()).isEmpty()) {
190 const auto iconThemeSection = index.indexOf(
"[Icon Theme]");
191 const auto nameStart = index.indexOf(
"Name=", iconThemeSection != -1 ? iconThemeSection : 0);
192 if (nameStart != -1) {
193 auto nameLength = index.indexOf(
"\n", nameStart) - nameStart - 5;
194 if (nameLength > 0) {
195 auto displayName = QString::fromUtf8(index.mid(nameStart + 5, nameLength));
196 if (displayName != iconTheme) {
197 displayName += QChar(
' ') % QChar(
'(') % iconTheme % QChar(
')');
199 res[displayName] = iconTheme;
204 res[iconTheme] = iconTheme;
221void QtSettings::apply()
224 if (m_d->additionalPluginDirectory != m_d->previousPluginDirectory) {
225 if (!m_d->previousPluginDirectory.isEmpty()) {
226 QCoreApplication::removeLibraryPath(m_d->previousPluginDirectory);
228 if (!m_d->additionalPluginDirectory.isEmpty()) {
229 QCoreApplication::addLibraryPath(m_d->additionalPluginDirectory);
231 m_d->previousPluginDirectory = m_d->additionalPluginDirectory;
233 if (m_d->additionalIconThemeSearchPath != m_d->previousIconThemeSearchPath) {
234 auto paths = QIcon::themeSearchPaths();
235 if (!m_d->previousIconThemeSearchPath.isEmpty()) {
236 paths.removeAll(m_d->previousIconThemeSearchPath);
238 if (!m_d->additionalIconThemeSearchPath.isEmpty()) {
239 paths.append(m_d->additionalIconThemeSearchPath);
241 m_d->previousIconThemeSearchPath = m_d->additionalIconThemeSearchPath;
242 QIcon::setThemeSearchPaths(paths);
246 auto styleSheet = QString();
247 if (m_d->customStyleSheet && !m_d->styleSheetPath.isEmpty()) {
248 auto file = QFile(m_d->styleSheetPath);
249 if (!file.open(QFile::ReadOnly)) {
250 cerr <<
"Unable to open the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() <<
"\"." << endl;
252 styleSheet.append(file.readAll());
253 if (file.error() != QFile::NoError) {
254 cerr <<
"Unable to read the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() <<
"\"." << endl;
259 if (m_d->customFont) {
260 if (!m_d->initialFont.has_value()) {
261 m_d->initialFont = QGuiApplication::font();
263 QGuiApplication::setFont(m_d->font);
264 }
else if (m_d->initialFont.has_value()) {
265 QGuiApplication::setFont(m_d->initialFont.value());
267#ifdef QT_UTILITIES_USE_FUSION_ON_WINDOWS_11
268 if (m_d->initialWidgetStyle.isEmpty()) {
271 if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11) {
272 m_d->initialWidgetStyle = QStringLiteral(
"Fusion");
276 if (m_d->customWidgetStyle) {
277#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
278 const auto *
const currentStyle = QApplication::style();
279 if (m_d->initialWidgetStyle.isEmpty() && currentStyle) {
280 m_d->initialWidgetStyle = currentStyle->name();
283 QApplication::setStyle(m_d->widgetStyle);
284 }
else if (!m_d->initialWidgetStyle.isEmpty()) {
285 QApplication::setStyle(m_d->initialWidgetStyle);
287 if (
auto *
const qapp = qobject_cast<QApplication *>(QApplication::instance())) {
288 qapp->setStyleSheet(styleSheet);
290 cerr <<
"Unable to apply the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data()
291 <<
"\" because no QApplication has been instantiated." << endl;
293 if (m_d->customPalette) {
294 QGuiApplication::setPalette(m_d->palette);
296 QGuiApplication::setPalette(QPalette());
299 if (m_d->customIconTheme) {
300 QIcon::setThemeName(m_d->iconTheme);
301 }
else if (!m_d->initialIconTheme.isEmpty()) {
302 if (m_d->iconTheme != m_d->initialIconTheme) {
304 QIcon::setThemeName(m_d->initialIconTheme);
313 const auto bundledIconThemes = scanIconThemes(QStringList(QStringLiteral(
":/icons")));
314 if (m_d->isPaletteDark && bundledIconThemes.contains(QStringLiteral(
"default-dark"))) {
315 QIcon::setThemeName(QStringLiteral(
"default-dark"));
316 }
else if (bundledIconThemes.contains(QStringLiteral(
"default"))) {
317 QIcon::setThemeName(QStringLiteral(
"default"));
322 QLocale::setDefault(m_d->customLocale ? QLocale(m_d->localeName) : m_d->defaultLocale);
335void QtSettings::reevaluatePaletteAndDefaultIconTheme()
342 if (
auto iconTheme = QIcon::themeName(); iconTheme == QStringLiteral(
"default") || iconTheme == QStringLiteral(
"default-dark")) {
343 QIcon::setThemeName(m_d->isPaletteDark ? QStringLiteral(
"default-dark") : QStringLiteral(
"default"));
353bool QtSettings::isPaletteDark()
355 return m_d->isPaletteDark;
366OptionCategory *QtSettings::category()
368 auto *category =
new OptionCategory;
369 category->setDisplayName(QCoreApplication::translate(
"QtGui::QtOptionCategory",
"Qt"));
370 category->setIcon(QIcon::fromTheme(QStringLiteral(
"qtcreator"), QIcon(QStringLiteral(
":/qtutilities/icons/hicolor/48x48/apps/qtcreator.svg"))));
375QtAppearanceOptionPage::QtAppearanceOptionPage(
QtSettingsData &settings, QWidget *parentWidget)
376 : QtAppearanceOptionPageBase(parentWidget)
377 , m_settings(settings)
378 , m_fontDialog(nullptr)
382QtAppearanceOptionPage::~QtAppearanceOptionPage()
386bool QtAppearanceOptionPage::apply()
388 m_settings.
font = ui()->fontComboBox->currentFont();
389 m_settings.
customFont = !ui()->fontCheckBox->isChecked();
390 m_settings.
widgetStyle = ui()->widgetStyleComboBox->currentText();
392 m_settings.
styleSheetPath = ui()->styleSheetPathSelection->lineEdit()->text();
395 m_settings.
customPalette = !ui()->paletteCheckBox->isChecked();
397 = ui()->iconThemeComboBox->currentIndex() != -1 ? ui()->iconThemeComboBox->currentData().toString() : ui()->iconThemeComboBox->currentText();
402void QtAppearanceOptionPage::reset()
404 ui()->fontComboBox->setCurrentFont(m_settings.
font);
405 ui()->fontCheckBox->setChecked(!m_settings.
customFont);
406 ui()->widgetStyleComboBox->setCurrentText(
407 m_settings.
widgetStyle.isEmpty() ? (QApplication::style() ? QApplication::style()->objectName() : QString()) : m_settings.widgetStyle);
409 ui()->styleSheetPathSelection->lineEdit()->setText(m_settings.
styleSheetPath);
412 ui()->paletteCheckBox->setChecked(!m_settings.
customPalette);
413 int iconThemeIndex = ui()->iconThemeComboBox->findData(m_settings.
iconTheme);
414 if (iconThemeIndex != -1) {
415 ui()->iconThemeComboBox->setCurrentIndex(iconThemeIndex);
417 ui()->iconThemeComboBox->setCurrentText(m_settings.
iconTheme);
422QWidget *QtAppearanceOptionPage::setupWidget()
425 auto *widget = QtAppearanceOptionPageBase::setupWidget();
431 ui()->widgetStyleComboBox->addItems(QStyleFactory::keys());
434 ui()->styleSheetPathSelection->provideCustomFileMode(QFileDialog::ExistingFile);
437 QObject::connect(ui()->fontPushButton, &QPushButton::clicked, m_fontDialog, [
this] {
439 m_fontDialog =
new QFontDialog(this->widget());
440 m_fontDialog->setCurrentFont(ui()->fontComboBox->font());
441 QObject::connect(m_fontDialog, &QFontDialog::fontSelected, ui()->fontComboBox, &QFontComboBox::setCurrentFont);
442 QObject::connect(ui()->fontComboBox, &QFontComboBox::currentFontChanged, m_fontDialog, &QFontDialog::setCurrentFont);
444 m_fontDialog->show();
448 QObject::connect(ui()->paletteToolButton, &QToolButton::clicked, ui()->paletteToolButton,
452 const auto iconThemes = scanIconThemes(QIcon::themeSearchPaths() << QStringLiteral(
"/usr/share/icons/"));
453 auto *iconThemeComboBox = ui()->iconThemeComboBox;
454 for (
auto i = iconThemes.begin(), end = iconThemes.end(); i != end; ++i) {
455 const auto &displayName = i.key();
456 const auto &
id = i.value();
457 if (
const auto existingItemIndex = iconThemeComboBox->findData(
id); existingItemIndex != -1) {
458 iconThemeComboBox->setItemText(existingItemIndex, displayName);
460 iconThemeComboBox->addItem(displayName,
id);
467QtLanguageOptionPage::QtLanguageOptionPage(
QtSettingsData &settings, QWidget *parentWidget)
468 : QtLanguageOptionPageBase(parentWidget)
469 , m_settings(settings)
473QtLanguageOptionPage::~QtLanguageOptionPage()
477bool QtLanguageOptionPage::apply()
479 m_settings.
localeName = ui()->localeComboBox->currentText();
480 m_settings.
customLocale = !ui()->localeCheckBox->isChecked();
484void QtLanguageOptionPage::reset()
486 ui()->localeComboBox->setCurrentText(m_settings.
localeName);
487 ui()->localeCheckBox->setChecked(!m_settings.
customLocale);
490QWidget *QtLanguageOptionPage::setupWidget()
493 auto *widget = QtLanguageOptionPageBase::setupWidget();
499 auto *localeComboBox = ui()->localeComboBox;
500 const auto locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
501 for (
const QLocale &locale : locales) {
502 localeComboBox->addItem(locale.name());
505 auto *languageLabel = ui()->languageLabel;
506 QObject::connect(ui()->localeComboBox, &QComboBox::currentTextChanged, languageLabel, [languageLabel, localeComboBox] {
507 const QLocale selectedLocale(localeComboBox->currentText());
508 const QLocale currentLocale;
509 languageLabel->setText(QCoreApplication::translate(
"QtGui::QtLanguageOptionPage",
"recognized by Qt as") % QStringLiteral(
" <i>")
510 % currentLocale.languageToString(selectedLocale.language()) % QChar(
',') % QChar(
' ')
511 % currentLocale.countryToString(selectedLocale.country()) % QStringLiteral(
"</i>"));
517 : QtEnvOptionPageBase(parentWidget)
518 , m_settings(settings)
522QtEnvOptionPage::~QtEnvOptionPage()
526bool QtEnvOptionPage::apply()
530 TranslationFiles::additionalTranslationFilePath() = ui()->translationPathSelection->lineEdit()->text();
534void QtEnvOptionPage::reset()
538 ui()->translationPathSelection->lineEdit()->setText(TranslationFiles::additionalTranslationFilePath());
541QWidget *QtEnvOptionPage::setupWidget()
544 auto *widget = QtEnvOptionPageBase::setupWidget();
QT_UTILITIES_EXPORT QString & additionalTranslationFilePath()
Allows to set an additional search path for translation files.
QtEnvOptionPage(QtSettingsData &settings, QWidget *parentWidget=nullptr)
QtAppearanceOptionPage(QtSettingsData &settings, QWidget *parentWidget=nullptr)
QtLanguageOptionPage(QtSettingsData &settings, QWidget *parentWidget=nullptr)
QT_UTILITIES_EXPORT bool isPaletteDark(const QPalette &palette=QPalette())
Returns whether palette is dark.
#define INSTANTIATE_UI_FILE_BASED_OPTION_PAGE(SomeClass)
Instantiates a class declared with BEGIN_DECLARE_UI_FILE_BASED_OPTION_PAGE in a convenient way.
QString previousPluginDirectory
QString previousIconThemeSearchPath
QString initialWidgetStyle
QString additionalPluginDirectory
std::optional< QFont > initialFont
QString additionalIconThemeSearchPath