You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
359 lines
12 KiB
359 lines
12 KiB
/* |
|
kcmformats.cpp |
|
SPDX-FileCopyrightText: 2014 Sebastian Kügler <sebas@kde.org> |
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later |
|
*/ |
|
|
|
// own |
|
#include "kcmformats.h" |
|
#include "ui_kcmformatswidget.h" |
|
|
|
// Qt |
|
#include <QApplication> |
|
#include <QComboBox> |
|
#include <QDebug> |
|
#include <QFile> |
|
#include <QLocale> |
|
#include <QStandardPaths> |
|
#include <QTextCodec> |
|
|
|
// Frameworks |
|
#include <KLocalizedString> |
|
#include <KMessageBox> |
|
#include <KPluginFactory> |
|
#include <KSharedConfig> |
|
|
|
K_PLUGIN_CLASS_WITH_JSON(KCMFormats, "formats.json") |
|
|
|
KCMFormats::KCMFormats(QWidget *parent, const QVariantList &args) |
|
: KCModule(parent, args) |
|
{ |
|
setQuickHelp( |
|
i18n("<h1>Formats</h1>" |
|
"You can configure the formats used for time, dates, money and other numbers here.")); |
|
|
|
m_ui = new Ui::KCMFormatsWidget; |
|
m_ui->setupUi(this); |
|
m_combos << m_ui->comboGlobal << m_ui->comboNumbers << m_ui->comboTime << m_ui->comboCurrency << m_ui->comboMeasurement << m_ui->comboCollate; |
|
} |
|
|
|
KCMFormats::~KCMFormats() |
|
{ |
|
delete m_ui; |
|
} |
|
|
|
bool countryLessThan(const QLocale &c1, const QLocale &c2) |
|
{ |
|
// Ensure that the "Default (C)" locale always appears at the top |
|
if (c1.name() == QLatin1Char('C') && c2.name() != QLatin1String("C")) |
|
return true; |
|
if (c2.name() == QLatin1Char('C')) |
|
return false; |
|
|
|
const QString ncn1 = !c1.nativeCountryName().isEmpty() ? c1.nativeCountryName() : QLocale::countryToString(c1.country()); |
|
const QString ncn2 = !c2.nativeCountryName().isEmpty() ? c2.nativeCountryName() : QLocale::countryToString(c2.country()); |
|
return QString::localeAwareCompare(ncn1, ncn2) < 0; |
|
} |
|
|
|
void KCMFormats::load() |
|
{ |
|
QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); |
|
std::sort(allLocales.begin(), allLocales.end(), countryLessThan); |
|
for (QComboBox *combo : qAsConst(m_combos)) { |
|
initCombo(combo, allLocales); |
|
} |
|
|
|
readConfig(); |
|
|
|
for (QComboBox *combo : qAsConst(m_combos)) { |
|
connectCombo(combo); |
|
} |
|
|
|
connect(m_ui->checkDetailed, &QAbstractButton::toggled, [=]() { |
|
updateExample(); |
|
updateEnabled(); |
|
emit changed(true); |
|
}); |
|
|
|
updateEnabled(); |
|
updateExample(); |
|
emit changed(false); |
|
} |
|
|
|
void KCMFormats::initCombo(QComboBox *combo, const QList<QLocale> &allLocales) |
|
{ |
|
combo->clear(); |
|
const QString clabel = i18n("No change"); |
|
combo->addItem(clabel, QString()); |
|
for (const auto &locale : allLocales) { |
|
addLocaleToCombo(combo, locale); |
|
} |
|
} |
|
|
|
void KCMFormats::connectCombo(QComboBox *combo) |
|
{ |
|
connect(combo, &QComboBox::currentTextChanged, [=]() { |
|
emit changed(true); |
|
updateExample(); |
|
}); |
|
} |
|
|
|
void KCMFormats::addLocaleToCombo(QComboBox *combo, const QLocale &locale) |
|
{ |
|
const QString clabel = !locale.nativeCountryName().isEmpty() ? locale.nativeCountryName() : QLocale::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(QLatin1Char('.')) && cvalue != QLatin1Char('C')) { |
|
// explicitly 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(QLatin1Char('_')); |
|
if (split.count() > 1) { |
|
flagcode = split[1].toLower(); |
|
} |
|
QIcon flagIcon = loadFlagIcon(flagcode); |
|
|
|
const QString nativeLangName = locale.nativeLanguageName(); |
|
if (!nativeLangName.isEmpty()) { |
|
combo->addItem(flagIcon, i18n("%1 - %2 (%3)", clabel, nativeLangName, locale.name()), cvalue); |
|
} else { |
|
combo->addItem(flagIcon, i18n("%1 (%2)", clabel, locale.name()), cvalue); |
|
} |
|
} |
|
|
|
void setCombo(QComboBox *combo, const QString &key) |
|
{ |
|
const int ix = combo->findData(key); |
|
if (ix > -1) { |
|
combo->setCurrentIndex(ix); |
|
} |
|
} |
|
|
|
QIcon KCMFormats::loadFlagIcon(const QString &flagCode) |
|
{ |
|
QIcon icon = m_cachedFlags.value(flagCode); |
|
if (!icon.isNull()) { |
|
return icon; |
|
} |
|
|
|
QString flag(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/locale/countries/%1/flag.png").arg(flagCode))); |
|
if (!flag.isEmpty()) { |
|
icon = QIcon(flag); |
|
} else { |
|
if (m_cachedUnknown.isNull()) { |
|
m_cachedUnknown = QIcon::fromTheme("unknown"); |
|
} |
|
icon = m_cachedUnknown; |
|
} |
|
m_cachedFlags.insert(flagCode, icon); |
|
|
|
return icon; |
|
} |
|
|
|
const static QString configFile = QStringLiteral("plasma-localerc"); |
|
const static QString exportFile = QStringLiteral("plasma-locale-settings.sh"); |
|
|
|
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"); |
|
|
|
void KCMFormats::readConfig() |
|
{ |
|
m_config = KConfigGroup(KSharedConfig::openConfig(configFile), "Formats"); |
|
|
|
bool useDetailed = m_config.readEntry("useDetailed", false); |
|
m_ui->checkDetailed->setChecked(useDetailed); |
|
|
|
setCombo(m_ui->comboGlobal, m_config.readEntry(lcLang, qgetenv(lcLang.toLatin1()))); |
|
|
|
setCombo(m_ui->comboNumbers, m_config.readEntry(lcNumeric, qgetenv(lcNumeric.toLatin1()))); |
|
setCombo(m_ui->comboTime, m_config.readEntry(lcTime, qgetenv(lcTime.toLatin1()))); |
|
setCombo(m_ui->comboCollate, m_config.readEntry(lcCollate, qgetenv(lcCollate.toLatin1()))); |
|
setCombo(m_ui->comboCurrency, m_config.readEntry(lcMonetary, qgetenv(lcMonetary.toLatin1()))); |
|
setCombo(m_ui->comboMeasurement, m_config.readEntry(lcMeasurement, qgetenv(lcMeasurement.toLatin1()))); |
|
|
|
updateEnabled(); |
|
} |
|
|
|
void KCMFormats::writeConfig() |
|
{ |
|
m_config = KConfigGroup(KSharedConfig::openConfig(configFile), "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 |
|
m_config.deleteEntry("useDetailed"); |
|
if (global.isEmpty()) { |
|
m_config.deleteEntry(lcLang); |
|
} else { |
|
m_config.writeEntry(lcLang, global); |
|
} |
|
m_config.deleteEntry(lcNumeric); |
|
m_config.deleteEntry(lcTime); |
|
m_config.deleteEntry(lcMonetary); |
|
m_config.deleteEntry(lcMeasurement); |
|
m_config.deleteEntry(lcCollate); |
|
m_config.deleteEntry(lcCtype); |
|
} else { |
|
// Save detailed settings |
|
m_config.writeEntry("useDetailed", true); |
|
|
|
if (global.isEmpty()) { |
|
m_config.deleteEntry(lcLang); |
|
} else { |
|
m_config.writeEntry(lcLang, global); |
|
} |
|
|
|
const QString numeric = m_ui->comboNumbers->currentData().toString(); |
|
if (numeric.isEmpty()) { |
|
m_config.deleteEntry(lcNumeric); |
|
} else { |
|
m_config.writeEntry(lcNumeric, numeric); |
|
} |
|
|
|
const QString time = m_ui->comboTime->currentData().toString(); |
|
if (time.isEmpty()) { |
|
m_config.deleteEntry(lcTime); |
|
} else { |
|
m_config.writeEntry(lcTime, time); |
|
} |
|
|
|
const QString monetary = m_ui->comboCurrency->currentData().toString(); |
|
if (monetary.isEmpty()) { |
|
m_config.deleteEntry(lcMonetary); |
|
} else { |
|
m_config.writeEntry(lcMonetary, monetary); |
|
} |
|
|
|
const QString measurement = m_ui->comboMeasurement->currentData().toString(); |
|
if (measurement.isEmpty()) { |
|
m_config.deleteEntry(lcMeasurement); |
|
} else { |
|
m_config.writeEntry(lcMeasurement, measurement); |
|
} |
|
|
|
const QString collate = m_ui->comboCollate->currentData().toString(); |
|
if (collate.isEmpty()) { |
|
m_config.deleteEntry(lcCollate); |
|
} else { |
|
m_config.writeEntry(lcCollate, collate); |
|
} |
|
} |
|
|
|
m_config.sync(); |
|
} |
|
|
|
void KCMFormats::save() |
|
{ |
|
writeConfig(); |
|
KMessageBox::information(this, |
|
i18n("Your changes will take effect the next time you log in."), |
|
i18n("Format Settings Changed"), |
|
QStringLiteral("FormatSettingsChanged")); |
|
} |
|
|
|
void KCMFormats::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 KCMFormats::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 KCMFormats::updateExample() |
|
{ |
|
const bool useDetailed = m_ui->checkDetailed->isChecked(); |
|
|
|
QLocale nloc; |
|
QLocale tloc; |
|
QLocale cloc; |
|
QLocale mloc; |
|
|
|
QString str; |
|
QString glob = m_ui->comboGlobal->currentData().toString(); |
|
|
|
if (useDetailed) { |
|
str = m_ui->comboNumbers->currentData().toString(); |
|
nloc = str.isEmpty() ? QLocale(glob) : QLocale(str); |
|
|
|
str = m_ui->comboTime->currentData().toString(); |
|
tloc = str.isEmpty() ? QLocale(glob) : QLocale(str); |
|
|
|
str = m_ui->comboCurrency->currentData().toString(); |
|
cloc = str.isEmpty() ? QLocale(glob) : QLocale(str); |
|
|
|
str = m_ui->comboMeasurement->currentData().toString(); |
|
mloc = str.isEmpty() ? QLocale(glob) : QLocale(str); |
|
} else { |
|
nloc = QLocale(glob); |
|
tloc = QLocale(glob); |
|
cloc = QLocale(glob); |
|
mloc = QLocale(glob); |
|
} |
|
|
|
const QString numberExample = nloc.toString(1000.01); |
|
const QString timeExample = i18n("%1 (long format)", tloc.toString(QDateTime::currentDateTime())) + QLatin1Char('\n') |
|
+ i18n("%1 (short format)", tloc.toString(QDateTime::currentDateTime(), QLocale::ShortFormat)); |
|
const QString currencyExample = cloc.toCurrencyString(24.00); |
|
|
|
QString measurementSetting; |
|
if (mloc.measurementSystem() == QLocale::ImperialUKSystem) { |
|
measurementSetting = i18nc("Measurement combobox", "Imperial UK"); |
|
} else if (mloc.measurementSystem() == QLocale::ImperialUSSystem || mloc.measurementSystem() == QLocale::ImperialSystem) { |
|
measurementSetting = i18nc("Measurement combobox", "Imperial US"); |
|
} else { |
|
measurementSetting = i18nc("Measurement combobox", "Metric"); |
|
} |
|
|
|
m_ui->exampleNumbers->setText(numberExample); |
|
m_ui->exampleTime->setText(timeExample); |
|
m_ui->exampleCurrency->setText(currencyExample); |
|
m_ui->exampleMeasurement->setText(measurementSetting); |
|
} |
|
|
|
#include "kcmformats.moc"
|
|
|