Qt Utilities 6.6.2
Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models
qtsettings.cpp
Go to the documentation of this file.
1#include "./qtsettings.h"
2#include "./optioncategory.h"
5#include "./optionpage.h"
6
7#include "../paletteeditor/paletteeditor.h"
8
9#include "../widgets/clearlineedit.h"
10
11#include "../resources/resources.h"
12
13#include "ui_qtappearanceoptionpage.h"
14#include "ui_qtenvoptionpage.h"
15#include "ui_qtlanguageoptionpage.h"
16
17#include <QDir>
18#include <QFileDialog>
19#include <QFontDialog>
20#include <QIcon>
21#include <QSettings>
22#include <QStringBuilder>
23#include <QStyleFactory>
24
25#include <iostream>
26#include <memory>
27
28using namespace std;
29
30namespace QtUtilities {
31
34
35 QFont font;
36 QPalette palette;
37 QString widgetStyle;
39 QString iconTheme;
41 QString localeName;
50};
51
53 : iconTheme(QIcon::themeName())
54 , localeName(defaultLocale.name())
55 , customFont(false)
56 , customPalette(false)
57 , customWidgetStyle(false)
58 , customStyleSheet(false)
59 , customIconTheme(false)
60 , customLocale(false)
61{
62}
63
71QtSettings::QtSettings()
72 : m_d(make_unique<QtSettingsData>())
73{
74}
75
81QtSettings::~QtSettings()
82{
83}
84
88bool QtSettings::hasCustomFont() const
89{
90 return m_d->customFont;
91}
92
99void QtSettings::restore(QSettings &settings)
100{
101 settings.beginGroup(QStringLiteral("qt"));
102 m_d->font.fromString(settings.value(QStringLiteral("font")).toString());
103 m_d->customFont = settings.value(QStringLiteral("customfont"), false).toBool();
104 m_d->palette = settings.value(QStringLiteral("palette")).value<QPalette>();
105 m_d->customPalette = settings.value(QStringLiteral("custompalette"), false).toBool();
106 m_d->widgetStyle = settings.value(QStringLiteral("widgetstyle"), m_d->widgetStyle).toString();
107 m_d->customWidgetStyle = settings.value(QStringLiteral("customwidgetstyle"), false).toBool();
108 m_d->styleSheetPath = settings.value(QStringLiteral("stylesheetpath"), m_d->styleSheetPath).toString();
109 m_d->customStyleSheet = settings.value(QStringLiteral("customstylesheet"), false).toBool();
110 m_d->iconTheme = settings.value(QStringLiteral("icontheme"), m_d->iconTheme).toString();
111 m_d->customIconTheme = settings.value(QStringLiteral("customicontheme"), false).toBool();
112 m_d->localeName = settings.value(QStringLiteral("locale"), m_d->localeName).toString();
113 m_d->customLocale = settings.value(QStringLiteral("customlocale"), false).toBool();
114 m_d->additionalPluginDirectory = settings.value(QStringLiteral("plugindir")).toString();
115 m_d->additionalIconThemeSearchPath = settings.value(QStringLiteral("iconthemepath")).toString();
116 TranslationFiles::additionalTranslationFilePath() = settings.value(QStringLiteral("trpath")).toString();
117 settings.endGroup();
118}
119
123void QtSettings::save(QSettings &settings) const
124{
125 settings.beginGroup(QStringLiteral("qt"));
126 settings.setValue(QStringLiteral("font"), QVariant(m_d->font.toString()));
127 settings.setValue(QStringLiteral("customfont"), m_d->customFont);
128 settings.setValue(QStringLiteral("palette"), QVariant(m_d->palette));
129 settings.setValue(QStringLiteral("custompalette"), m_d->customPalette);
130 settings.setValue(QStringLiteral("widgetstyle"), m_d->widgetStyle);
131 settings.setValue(QStringLiteral("customwidgetstyle"), m_d->customWidgetStyle);
132 settings.setValue(QStringLiteral("stylesheetpath"), m_d->styleSheetPath);
133 settings.setValue(QStringLiteral("customstylesheet"), m_d->customStyleSheet);
134 settings.setValue(QStringLiteral("icontheme"), m_d->iconTheme);
135 settings.setValue(QStringLiteral("customicontheme"), m_d->customIconTheme);
136 settings.setValue(QStringLiteral("locale"), m_d->localeName);
137 settings.setValue(QStringLiteral("customlocale"), m_d->customLocale);
138 settings.setValue(QStringLiteral("plugindir"), m_d->additionalPluginDirectory);
139 settings.setValue(QStringLiteral("iconthemepath"), m_d->additionalIconThemeSearchPath);
140 settings.setValue(QStringLiteral("trpath"), QVariant(TranslationFiles::additionalTranslationFilePath()));
141 settings.endGroup();
142}
143
153void QtSettings::apply()
154{
155 // read style sheet
156 QString styleSheet;
157 if (m_d->customStyleSheet && !m_d->styleSheetPath.isEmpty()) {
158 QFile file(m_d->styleSheetPath);
159 if (!file.open(QFile::ReadOnly)) {
160 cerr << "Unable to open the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << endl;
161 }
162 styleSheet.append(file.readAll());
163 if (file.error() != QFile::NoError) {
164 cerr << "Unable to read the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data() << "\"." << endl;
165 }
166 }
167
168 // apply appearance
169 if (m_d->customFont) {
170 QGuiApplication::setFont(m_d->font);
171 }
172 if (m_d->customWidgetStyle) {
173 QApplication::setStyle(m_d->widgetStyle);
174 }
175 if (!styleSheet.isEmpty()) {
176 if (auto *qapp = qobject_cast<QApplication *>(QApplication::instance())) {
177 qapp->setStyleSheet(styleSheet);
178 } else {
179 cerr << "Unable to apply the specified stylesheet \"" << m_d->styleSheetPath.toLocal8Bit().data()
180 << "\" because no QApplication has been instantiated." << endl;
181 }
182 }
183 if (m_d->customPalette) {
184 QGuiApplication::setPalette(m_d->palette);
185 }
186 if (m_d->customIconTheme) {
187 QIcon::setThemeName(m_d->iconTheme);
188 }
189
190 // apply locale
191 QLocale::setDefault(m_d->customLocale ? QLocale(m_d->localeName) : m_d->defaultLocale);
192
193 // apply environment
194 if (m_d->additionalPluginDirectory.isEmpty()) {
195 QCoreApplication::addLibraryPath(m_d->additionalPluginDirectory);
196 }
197 if (!m_d->additionalIconThemeSearchPath.isEmpty()) {
198 QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << m_d->additionalIconThemeSearchPath);
199 }
200}
201
210OptionCategory *QtSettings::category()
211{
212 auto *category = new OptionCategory;
213 category->setDisplayName(QCoreApplication::translate("QtGui::QtOptionCategory", "Qt"));
214 category->setIcon(QIcon::fromTheme(QStringLiteral("qtcreator"), QIcon(QStringLiteral(":/qtutilities/icons/hicolor/48x48/apps/qtcreator.svg"))));
215 category->assignPages({ new QtAppearanceOptionPage(*m_d), new QtLanguageOptionPage(*m_d), new QtEnvOptionPage(*m_d) });
216 return category;
217}
218
220 : QtAppearanceOptionPageBase(parentWidget)
221 , m_settings(settings)
222 , m_fontDialog(nullptr)
223{
224}
225
226QtAppearanceOptionPage::~QtAppearanceOptionPage()
227{
228}
229
230bool QtAppearanceOptionPage::apply()
231{
232 m_settings.font = ui()->fontComboBox->currentFont();
233 m_settings.customFont = !ui()->fontCheckBox->isChecked();
234 m_settings.widgetStyle = ui()->widgetStyleComboBox->currentText();
235 m_settings.customWidgetStyle = !ui()->widgetStyleCheckBox->isChecked();
236 m_settings.styleSheetPath = ui()->styleSheetPathSelection->lineEdit()->text();
237 m_settings.customStyleSheet = !ui()->styleSheetCheckBox->isChecked();
238 m_settings.palette = ui()->paletteToolButton->palette();
239 m_settings.customPalette = !ui()->paletteCheckBox->isChecked();
240 m_settings.iconTheme
241 = ui()->iconThemeComboBox->currentIndex() != -1 ? ui()->iconThemeComboBox->currentData().toString() : ui()->iconThemeComboBox->currentText();
242 m_settings.customIconTheme = !ui()->iconThemeCheckBox->isChecked();
243 return true;
244}
245
246void QtAppearanceOptionPage::reset()
247{
248 ui()->fontComboBox->setCurrentFont(m_settings.font);
249 ui()->fontCheckBox->setChecked(!m_settings.customFont);
250 ui()->widgetStyleComboBox->setCurrentText(
251 m_settings.widgetStyle.isEmpty() ? (QApplication::style() ? QApplication::style()->objectName() : QString()) : m_settings.widgetStyle);
252 ui()->widgetStyleCheckBox->setChecked(!m_settings.customWidgetStyle);
253 ui()->styleSheetPathSelection->lineEdit()->setText(m_settings.styleSheetPath);
254 ui()->styleSheetCheckBox->setChecked(!m_settings.customStyleSheet);
255 ui()->paletteToolButton->setPalette(m_settings.palette);
256 ui()->paletteCheckBox->setChecked(!m_settings.customPalette);
257 int iconThemeIndex = ui()->iconThemeComboBox->findData(m_settings.iconTheme);
258 if (iconThemeIndex != -1) {
259 ui()->iconThemeComboBox->setCurrentIndex(iconThemeIndex);
260 } else {
261 ui()->iconThemeComboBox->setCurrentText(m_settings.iconTheme);
262 }
263 ui()->iconThemeCheckBox->setChecked(!m_settings.customIconTheme);
264}
265
266QWidget *QtAppearanceOptionPage::setupWidget()
267{
268 // call base implementation first, so ui() is available
269 auto *widget = QtAppearanceOptionPageBase::setupWidget();
270
271 // setup widget style selection
272 ui()->widgetStyleComboBox->addItems(QStyleFactory::keys());
273
274 // setup style sheet selection
275 ui()->styleSheetPathSelection->provideCustomFileMode(QFileDialog::ExistingFile);
276
277 // setup font selection
278 QObject::connect(ui()->fontPushButton, &QPushButton::clicked, [this] {
279 if (!m_fontDialog) {
280 m_fontDialog = new QFontDialog(this->widget());
281 m_fontDialog->setCurrentFont(ui()->fontComboBox->font());
282 QObject::connect(m_fontDialog, &QFontDialog::fontSelected, ui()->fontComboBox, &QFontComboBox::setCurrentFont);
283 QObject::connect(ui()->fontComboBox, &QFontComboBox::currentFontChanged, m_fontDialog, &QFontDialog::setCurrentFont);
284 }
285 m_fontDialog->show();
286 });
287
288 // setup palette selection
289 QObject::connect(ui()->paletteToolButton, &QToolButton::clicked,
290 [this] { ui()->paletteToolButton->setPalette(PaletteEditor::getPalette(this->widget(), ui()->paletteToolButton->palette())); });
291
292 // setup icon theme selection
293 const QStringList searchPaths = QIcon::themeSearchPaths() << QStringLiteral("/usr/share/icons/");
294 for (const QString &searchPath : searchPaths) {
295 const auto dir = QDir(searchPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
296 for (const QString &iconTheme : dir) {
297 const int existingItemIndex = ui()->iconThemeComboBox->findData(iconTheme);
298 QFile indexFile(searchPath % QChar('/') % iconTheme % QStringLiteral("/index.theme"));
299 QByteArray index;
300 if (indexFile.open(QFile::ReadOnly) && !(index = indexFile.readAll()).isEmpty()) {
301 const auto iconThemeSection = index.indexOf("[Icon Theme]");
302 const auto nameStart = index.indexOf("Name=", iconThemeSection != -1 ? iconThemeSection : 0);
303 if (nameStart != -1) {
304 auto nameLength = index.indexOf("\n", nameStart) - nameStart - 5;
305 if (nameLength > 0) {
306 QString displayName = index.mid(nameStart + 5, nameLength);
307 if (displayName != iconTheme) {
308 displayName += QChar(' ') % QChar('(') % iconTheme % QChar(')');
309 }
310 if (existingItemIndex != -1) {
311 ui()->iconThemeComboBox->setItemText(existingItemIndex, displayName);
312 } else {
313 ui()->iconThemeComboBox->addItem(displayName, iconTheme);
314 }
315 continue;
316 }
317 }
318 }
319 if (existingItemIndex == -1) {
320 ui()->iconThemeComboBox->addItem(iconTheme, iconTheme);
321 }
322 }
323 }
324
325 return widget;
326}
327
329 : QtLanguageOptionPageBase(parentWidget)
330 , m_settings(settings)
331{
332}
333
334QtLanguageOptionPage::~QtLanguageOptionPage()
335{
336}
337
338bool QtLanguageOptionPage::apply()
339{
340 m_settings.localeName = ui()->localeComboBox->currentText();
341 m_settings.customLocale = !ui()->localeCheckBox->isChecked();
342 return true;
343}
344
345void QtLanguageOptionPage::reset()
346{
347 ui()->localeComboBox->setCurrentText(m_settings.localeName);
348 ui()->localeCheckBox->setChecked(!m_settings.customLocale);
349}
350
351QWidget *QtLanguageOptionPage::setupWidget()
352{
353 // call base implementation first, so ui() is available
354 auto *widget = QtLanguageOptionPageBase::setupWidget();
355
356 // add all available locales to combo box
357 auto *localeComboBox = ui()->localeComboBox;
358 const auto locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
359 for (const QLocale &locale : locales) {
360 localeComboBox->addItem(locale.name());
361 }
362
363 auto *languageLabel = ui()->languageLabel;
364 QObject::connect(ui()->localeComboBox, &QComboBox::currentTextChanged, [languageLabel, localeComboBox] {
365 const QLocale selectedLocale(localeComboBox->currentText());
366 const QLocale currentLocale;
367 languageLabel->setText(QCoreApplication::translate("QtGui::QtLanguageOptionPage", "recognized by Qt as") % QStringLiteral(" <i>")
368 % currentLocale.languageToString(selectedLocale.language()) % QChar(',') % QChar(' ')
369 % currentLocale.countryToString(selectedLocale.country()) % QStringLiteral("</i>"));
370 });
371 return widget;
372}
373
374QtEnvOptionPage::QtEnvOptionPage(QtSettingsData &settings, QWidget *parentWidget)
375 : QtEnvOptionPageBase(parentWidget)
376 , m_settings(settings)
377{
378}
379
380QtEnvOptionPage::~QtEnvOptionPage()
381{
382}
383
384bool QtEnvOptionPage::apply()
385{
386 m_settings.additionalPluginDirectory = ui()->pluginPathSelection->lineEdit()->text();
387 m_settings.additionalIconThemeSearchPath = ui()->iconThemeSearchPathSelection->lineEdit()->text();
388 TranslationFiles::additionalTranslationFilePath() = ui()->translationPathSelection->lineEdit()->text();
389 return true;
390}
391
392void QtEnvOptionPage::reset()
393{
394 ui()->pluginPathSelection->lineEdit()->setText(m_settings.additionalPluginDirectory);
395 ui()->iconThemeSearchPathSelection->lineEdit()->setText(m_settings.additionalIconThemeSearchPath);
396 ui()->translationPathSelection->lineEdit()->setText(TranslationFiles::additionalTranslationFilePath());
397}
398} // namespace QtUtilities
399
QT_UTILITIES_EXPORT QString & additionalTranslationFilePath()
Allows to set an additional search path for translation files.
Definition: resources.cpp:75
QtEnvOptionPage(QtSettingsData &settings, QWidget *parentWidget=nullptr)
Definition: qtsettings.cpp:374
QtAppearanceOptionPage(QtSettingsData &settings, QWidget *parentWidget=nullptr)
Definition: qtsettings.cpp:219
QtLanguageOptionPage(QtSettingsData &settings, QWidget *parentWidget=nullptr)
Definition: qtsettings.cpp:328
#define INSTANTIATE_UI_FILE_BASED_OPTION_PAGE(SomeClass)
Instantiates a class declared with BEGIN_DECLARE_UI_FILE_BASED_OPTION_PAGE in a convenient way.
Definition: optionpage.h:230