/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)GPL2+ * * * Copyright: 2014 LXQt team * 2014 Sebastian Kügler * Authors: * Julien Lavergne * Sebastian Kügler * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * * END_COMMON_COPYRIGHT_HEADER * * Based on plasma-desktop/kcms/formats module */ #include "localeconfig.h" #include "ui_localeconfig.h" #include #include #include #include #include #include #include #include #include #include const static QString lcLang = QStringLiteral("LANG"); const static QString lcNumeric = QStringLiteral("LC_NUMERIC"); const static QString lcTime = QStringLiteral("LC_TIME"); const static QString lcMonetary = QStringLiteral("LC_MONETARY"); const static QString lcMeasurement = QStringLiteral("LC_MEASUREMENT"); const static QString lcCollate = QStringLiteral("LC_COLLATE"); const static QString lcCtype = QStringLiteral("LC_CTYPE"); const static QString lcLanguage = QStringLiteral("LANGUAGE"); LocaleConfig::LocaleConfig(LXQt::Settings* settings, LXQt::Settings* session_settings, QWidget* parent) : QWidget(parent), m_ui(new Ui::LocaleConfig), hasChanged(new bool), mSettings(settings), sSettings(session_settings) { m_ui->setupUi(this); m_combos << m_ui->comboGlobal << m_ui->comboNumbers << m_ui->comboTime << m_ui->comboCurrency << m_ui->comboMeasurement << m_ui->comboCollate; hasChanged = false; initControls(); } LocaleConfig::~LocaleConfig() { delete m_ui; } bool countryLessThan(const QLocale & c1, const QLocale & c2) { return QString::localeAwareCompare(c1.nativeCountryName(), c2.nativeCountryName()) < 0; } void LocaleConfig::load() { QList allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); qSort(allLocales.begin(), allLocales.end(), countryLessThan); foreach(QComboBox * combo, m_combos) { initCombo(combo, allLocales); } readConfig(); foreach(QComboBox * combo, m_combos) { connectCombo(combo); } connect(m_ui->checkDetailed, &QAbstractButton::toggled, [ = ]() { updateExample(); updateEnabled(); hasChanged = true; }); updateEnabled(); updateExample(); hasChanged = false; } void LocaleConfig::initCombo(QComboBox *combo, const QList & allLocales) { combo->clear(); const QString clabel = tr("No change"); combo->setInsertPolicy(QComboBox::InsertAlphabetically); combo->addItem(clabel, QString()); foreach(const QLocale & l, allLocales) { addLocaleToCombo(combo, l); } } void LocaleConfig::connectCombo(QComboBox *combo) { connect(combo, &QComboBox::currentTextChanged, [ = ]() { hasChanged = true; updateExample(); }); } void LocaleConfig::addLocaleToCombo(QComboBox *combo, const QLocale &locale) { const QString clabel = !locale.nativeCountryName().isEmpty() ? locale.nativeCountryName() : locale.countryToString(locale.country()); // This needs to use name() rather than bcp47name() or later on the export will generate a non-sense locale (e.g. "it" instead of // "it_IT") // TODO: Properly handle scripts (@foo) QString cvalue = locale.name(); if (!cvalue.contains('.')) { // explicitely add the encoding, otherwise Qt doesn't accept dead keys and garbles the output as well cvalue.append(QLatin1Char('.') + QTextCodec::codecForLocale()->name()); } QString flagcode; const QStringList split = locale.name().split('_'); if (split.count() > 1) { flagcode = split[1].toLower(); } /* TODO Find a better place for flags ... */ QString flag(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/locale/countries/%1/flag.png").arg(flagcode))); QIcon flagIcon; if (!flag.isEmpty()) { flagIcon = QIcon(flag); } QString itemResult; itemResult = QString("%1 - %2 (%3)") .arg(clabel) .arg(locale.nativeLanguageName()) .arg(locale.name()); combo->addItem(flagIcon, itemResult, cvalue); } void setCombo(QComboBox *combo, const QString &key) { const int ix = combo->findData(key); if (ix > -1) { combo->setCurrentIndex(ix); } } void LocaleConfig::readConfig() { mSettings->beginGroup("Formats"); bool useDetailed = mSettings->value("useDetailed", false).toBool(); m_ui->checkDetailed->setChecked(useDetailed); setCombo(m_ui->comboGlobal, mSettings->value(lcLang, qgetenv(lcLang.toLatin1())).toString()); setCombo(m_ui->comboNumbers, mSettings->value(lcNumeric, qgetenv(lcNumeric.toLatin1())).toString()); setCombo(m_ui->comboTime, mSettings->value(lcTime, qgetenv(lcTime.toLatin1())).toString()); setCombo(m_ui->comboCollate, mSettings->value(lcCollate, qgetenv(lcCollate.toLatin1())).toString()); setCombo(m_ui->comboCurrency, mSettings->value(lcMonetary, qgetenv(lcMonetary.toLatin1())).toString()); setCombo(m_ui->comboMeasurement, mSettings->value(lcMeasurement, qgetenv(lcMeasurement.toLatin1())).toString()); updateEnabled(); mSettings->endGroup(); } void LocaleConfig::writeConfig() { mSettings->beginGroup("Formats"); // global ends up empty here when OK button is clicked from kcmshell5, // apparently the data in the combo is gone by the time save() is called. // This might be a problem in KCModule, but does not directly affect us // since within systemsettings, it works fine. // See https://bugs.kde.org/show_bug.cgi?id=334624 if (m_ui->comboGlobal->count() == 0) { qWarning() << "Couldn't read data from UI, writing configuration failed."; return; } const QString global = m_ui->comboGlobal->currentData().toString(); if (!m_ui->checkDetailed->isChecked()) { // Global setting, clean up config mSettings->remove("useDetailed"); if (global.isEmpty()) { mSettings->remove(lcLang); } else { mSettings->setValue(lcLang, global); } mSettings->remove(lcNumeric); mSettings->remove(lcTime); mSettings->remove(lcMonetary); mSettings->remove(lcMeasurement); mSettings->remove(lcCollate); mSettings->remove(lcCtype); } else { // Save detailed settings mSettings->setValue("useDetailed", true); if (global.isEmpty()) { mSettings->remove(lcLang); } else { mSettings->setValue(lcLang, global); } const QString numeric = m_ui->comboNumbers->currentData().toString(); if (numeric.isEmpty()) { mSettings->remove(lcNumeric); } else { mSettings->setValue(lcNumeric, numeric); } const QString time = m_ui->comboTime->currentData().toString(); if (time.isEmpty()) { mSettings->remove(lcTime); } else { mSettings->setValue(lcTime, time); } const QString monetary = m_ui->comboCurrency->currentData().toString(); if (monetary.isEmpty()) { mSettings->remove(lcMonetary); } else { mSettings->setValue(lcMonetary, monetary); } const QString measurement = m_ui->comboMeasurement->currentData().toString(); if (measurement.isEmpty()) { mSettings->remove(lcMeasurement); } else { mSettings->setValue(lcMeasurement, measurement); } const QString collate = m_ui->comboCollate->currentData().toString(); if (collate.isEmpty()) { mSettings->remove(lcCollate); } else { mSettings->setValue(lcCollate, collate); } } mSettings->endGroup(); } void LocaleConfig::saveSettings() { if (hasChanged) { QMessageBox msgBox; msgBox.setWindowTitle(tr("Format Settings Changed")); msgBox.setText(tr("Do you want to save your changes? They will take effect the next time you log in.")); msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Cancel); int ret = msgBox.exec(); if( ret == QMessageBox::Save ) { writeConfig(); writeExports(); } } } void LocaleConfig::writeExports() { sSettings->beginGroup("Environment"); mSettings->beginGroup("Formats"); if (!mSettings->value(lcLang).toString().isNull()) { sSettings->setValue(lcLang, mSettings->value(lcLang).toString()); if (mSettings->value("useDetailed").toBool()) { if (!mSettings->value(lcNumeric).toString().isNull()) { sSettings->setValue(lcNumeric, mSettings->value(lcNumeric).toString()); } if (!mSettings->value(lcTime).toString().isNull()) { sSettings->setValue(lcTime, mSettings->value(lcTime).toString()); } if (!mSettings->value(lcCollate).toString().isNull()) { sSettings->setValue(lcCollate, mSettings->value(lcCollate).toString()); } if (!mSettings->value(lcMonetary).toString().isNull()) { sSettings->setValue(lcMonetary, mSettings->value(lcMonetary).toString()); } if (!mSettings->value(lcMeasurement).toString().isNull()) { sSettings->setValue(lcMeasurement, mSettings->value(lcMeasurement).toString()); } } else { sSettings->setValue(lcNumeric, mSettings->value(lcLang).toString()); sSettings->setValue(lcTime, mSettings->value(lcLang).toString()); sSettings->setValue(lcCollate, mSettings->value(lcLang).toString()); sSettings->setValue(lcMonetary, mSettings->value(lcLang).toString()); sSettings->setValue(lcMeasurement, mSettings->value(lcLang).toString()); } } mSettings->endGroup(); sSettings->endGroup(); sSettings->sync(); } void LocaleConfig::defaults() { m_ui->checkDetailed->setChecked(false); // restore user defaults from env vars setCombo(m_ui->comboGlobal, qgetenv(lcLang.toLatin1())); setCombo(m_ui->comboNumbers, qgetenv(lcNumeric.toLatin1())); setCombo(m_ui->comboTime, qgetenv(lcTime.toLatin1())); setCombo(m_ui->comboCollate, qgetenv(lcCollate.toLatin1())); setCombo(m_ui->comboCurrency, qgetenv(lcMonetary.toLatin1())); setCombo(m_ui->comboMeasurement, qgetenv(lcMeasurement.toLatin1())); updateEnabled(); } void LocaleConfig::updateEnabled() { const bool enabled = m_ui->checkDetailed->isChecked(); m_ui->labelNumbers->setEnabled(enabled); m_ui->labelTime->setEnabled(enabled); m_ui->labelCurrency->setEnabled(enabled); m_ui->labelMeasurement->setEnabled(enabled); m_ui->labelCollate->setEnabled(enabled); m_ui->comboNumbers->setEnabled(enabled); m_ui->comboTime->setEnabled(enabled); m_ui->comboCurrency->setEnabled(enabled); m_ui->comboMeasurement->setEnabled(enabled); m_ui->comboCollate->setEnabled(enabled); } void LocaleConfig::updateExample() { const bool useDetailed = m_ui->checkDetailed->isChecked(); QLocale nloc; QLocale tloc; QLocale cloc; QLocale mloc; if (useDetailed) { nloc = QLocale(m_ui->comboNumbers->currentData().toString()); tloc = QLocale(m_ui->comboTime->currentData().toString()); cloc = QLocale(m_ui->comboCurrency->currentData().toString()); mloc = QLocale(m_ui->comboMeasurement->currentData().toString()); } else { nloc = QLocale(m_ui->comboGlobal->currentData().toString()); tloc = QLocale(m_ui->comboGlobal->currentData().toString()); cloc = QLocale(m_ui->comboGlobal->currentData().toString()); mloc = QLocale(m_ui->comboGlobal->currentData().toString()); } const QString numberExample = nloc.toString(1000.01); const QString timeExample = tloc.toString(QDateTime::currentDateTime()); const QString currencyExample = cloc.toCurrencyString(24); QString measurementSetting; if (mloc.measurementSystem() == QLocale::ImperialUKSystem) { measurementSetting = tr("Imperial UK"); } else if (mloc.measurementSystem() == QLocale::ImperialUSSystem) { measurementSetting = tr("Imperial US"); } else { measurementSetting = tr("Metric"); } m_ui->exampleNumbers->setText(numberExample); m_ui->exampleTime->setText(timeExample); m_ui->exampleCurrency->setText(currencyExample); m_ui->exampleMeasurement->setText(measurementSetting); } void LocaleConfig::initControls() { defaults(); load(); hasChanged = false; }