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