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