Qt Utilities  6.4.1
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 
28 using namespace std;
29 
30 namespace QtUtilities {
31 
34 
35  QFont font;
36  QPalette palette;
37  QString widgetStyle;
38  QString styleSheetPath;
39  QString iconTheme;
40  QLocale defaultLocale;
41  QString localeName;
44  bool customFont;
50 };
51 
52 inline QtSettingsData::QtSettingsData()
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 
71 QtSettings::QtSettings()
72  : m_d(make_unique<QtSettingsData>())
73 {
74 }
75 
81 QtSettings::~QtSettings()
82 {
83 }
84 
88 bool QtSettings::hasCustomFont() const
89 {
90  return m_d->customFont;
91 }
92 
99 void 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 
123 void 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 
153 void 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 
211 OptionCategory *QtSettings::category()
212 {
213  auto *category = new OptionCategory;
214  category->setDisplayName(QCoreApplication::translate("QtGui::QtOptionCategory", "Qt"));
215  category->setIcon(QIcon::fromTheme(QStringLiteral("qtcreator"), QIcon(QStringLiteral(":/qtutilities/icons/hicolor/48x48/apps/qtcreator.svg"))));
216  category->assignPages({ new QtAppearanceOptionPage(*m_d), new QtLanguageOptionPage(*m_d), new QtEnvOptionPage(*m_d) });
217  return category;
218 }
219 
221  : QtAppearanceOptionPageBase(parentWidget)
222  , m_settings(settings)
223  , m_fontDialog(nullptr)
224 {
225 }
226 
227 QtAppearanceOptionPage::~QtAppearanceOptionPage()
228 {
229 }
230 
231 bool QtAppearanceOptionPage::apply()
232 {
233  m_settings.font = ui()->fontComboBox->font();
234  m_settings.customFont = !ui()->fontCheckBox->isChecked();
235  m_settings.widgetStyle = ui()->widgetStyleComboBox->currentText();
236  m_settings.customWidgetStyle = !ui()->widgetStyleCheckBox->isChecked();
237  m_settings.styleSheetPath = ui()->styleSheetPathSelection->lineEdit()->text();
238  m_settings.customStyleSheet = !ui()->styleSheetCheckBox->isChecked();
239  m_settings.palette = ui()->paletteToolButton->palette();
240  m_settings.customPalette = !ui()->paletteCheckBox->isChecked();
241  m_settings.iconTheme
242  = ui()->iconThemeComboBox->currentIndex() != -1 ? ui()->iconThemeComboBox->currentData().toString() : ui()->iconThemeComboBox->currentText();
243  m_settings.customIconTheme = !ui()->iconThemeCheckBox->isChecked();
244  return true;
245 }
246 
247 void QtAppearanceOptionPage::reset()
248 {
249  ui()->fontComboBox->setCurrentFont(m_settings.font);
250  ui()->fontCheckBox->setChecked(!m_settings.customFont);
251  ui()->widgetStyleComboBox->setCurrentText(
252  m_settings.widgetStyle.isEmpty() ? (QApplication::style() ? QApplication::style()->objectName() : QString()) : m_settings.widgetStyle);
253  ui()->widgetStyleCheckBox->setChecked(!m_settings.customWidgetStyle);
254  ui()->styleSheetPathSelection->lineEdit()->setText(m_settings.styleSheetPath);
255  ui()->styleSheetCheckBox->setChecked(!m_settings.customStyleSheet);
256  ui()->paletteToolButton->setPalette(m_settings.palette);
257  ui()->paletteCheckBox->setChecked(!m_settings.customPalette);
258  int iconThemeIndex = ui()->iconThemeComboBox->findData(m_settings.iconTheme);
259  if (iconThemeIndex != -1) {
260  ui()->iconThemeComboBox->setCurrentIndex(iconThemeIndex);
261  } else {
262  ui()->iconThemeComboBox->setCurrentText(m_settings.iconTheme);
263  }
264  ui()->iconThemeCheckBox->setChecked(!m_settings.customIconTheme);
265 }
266 
267 QWidget *QtAppearanceOptionPage::setupWidget()
268 {
269  // call base implementation first, so ui() is available
270  auto *widget = QtAppearanceOptionPageBase::setupWidget();
271 
272  // setup widget style selection
273  ui()->widgetStyleComboBox->addItems(QStyleFactory::keys());
274 
275  // setup style sheet selection
276  ui()->styleSheetPathSelection->provideCustomFileMode(QFileDialog::ExistingFile);
277 
278  // setup font selection
279  QObject::connect(ui()->fontPushButton, &QPushButton::clicked, [this] {
280  if (!m_fontDialog) {
281  m_fontDialog = new QFontDialog(this->widget());
282  m_fontDialog->setCurrentFont(ui()->fontComboBox->font());
283  QObject::connect(m_fontDialog, &QFontDialog::fontSelected, ui()->fontComboBox, &QFontComboBox::setCurrentFont);
284  QObject::connect(ui()->fontComboBox, &QFontComboBox::currentFontChanged, m_fontDialog, &QFontDialog::setCurrentFont);
285  }
286  m_fontDialog->show();
287  });
288 
289  // setup palette selection
290  QObject::connect(ui()->paletteToolButton, &QToolButton::clicked,
291  [this] { ui()->paletteToolButton->setPalette(PaletteEditor::getPalette(this->widget(), ui()->paletteToolButton->palette())); });
292 
293  // setup icon theme selection
294  const QStringList searchPaths = QIcon::themeSearchPaths() << QStringLiteral("/usr/share/icons/");
295  for (const QString &searchPath : searchPaths) {
296  for (const QString &iconTheme : QDir(searchPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name)) {
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 int iconThemeSection = index.indexOf("[Icon Theme]");
302  const int nameStart = index.indexOf("Name=", iconThemeSection != -1 ? iconThemeSection : 0);
303  if (nameStart != -1) {
304  int 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 
334 QtLanguageOptionPage::~QtLanguageOptionPage()
335 {
336 }
337 
338 bool QtLanguageOptionPage::apply()
339 {
340  m_settings.localeName = ui()->localeComboBox->currentText();
341  m_settings.customLocale = !ui()->localeCheckBox->isChecked();
342  return true;
343 }
344 
345 void QtLanguageOptionPage::reset()
346 {
347  ui()->localeComboBox->setCurrentText(m_settings.localeName);
348  ui()->localeCheckBox->setChecked(!m_settings.customLocale);
349 }
350 
351 QWidget *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  for (const QLocale &locale : QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry)) {
359  localeComboBox->addItem(locale.name());
360  }
361 
362  auto *languageLabel = ui()->languageLabel;
363  QObject::connect(ui()->localeComboBox, &QComboBox::currentTextChanged, [languageLabel, localeComboBox] {
364  const QLocale selectedLocale(localeComboBox->currentText());
365  const QLocale currentLocale;
366  languageLabel->setText(QCoreApplication::translate("QtGui::QtLanguageOptionPage", "recognized by Qt as") % QStringLiteral(" <i>")
367  % currentLocale.languageToString(selectedLocale.language()) % QChar(',') % QChar(' ')
368  % currentLocale.countryToString(selectedLocale.country()) % QStringLiteral("</i>"));
369  });
370  return widget;
371 }
372 
373 QtEnvOptionPage::QtEnvOptionPage(QtSettingsData &settings, QWidget *parentWidget)
374  : QtEnvOptionPageBase(parentWidget)
375  , m_settings(settings)
376 {
377 }
378 
379 QtEnvOptionPage::~QtEnvOptionPage()
380 {
381 }
382 
383 bool QtEnvOptionPage::apply()
384 {
385  m_settings.additionalPluginDirectory = ui()->pluginPathSelection->lineEdit()->text();
386  m_settings.additionalIconThemeSearchPath = ui()->iconThemeSearchPathSelection->lineEdit()->text();
387  TranslationFiles::additionalTranslationFilePath() = ui()->translationPathSelection->lineEdit()->text();
388  return true;
389 }
390 
391 void QtEnvOptionPage::reset()
392 {
393  ui()->pluginPathSelection->lineEdit()->setText(m_settings.additionalPluginDirectory);
394  ui()->iconThemeSearchPathSelection->lineEdit()->setText(m_settings.additionalIconThemeSearchPath);
395  ui()->translationPathSelection->lineEdit()->setText(TranslationFiles::additionalTranslationFilePath());
396 }
397 } // namespace QtUtilities
398 
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:373
QtAppearanceOptionPage(QtSettingsData &settings, QWidget *parentWidget=nullptr)
Definition: qtsettings.cpp:220
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