/* optionsmodel.cpp SPDX-FileCopyrightText: 2021 Han Young SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include "exampleutility.h" #include "kcmregionandlang.h" #include "optionsmodel.h" #include "settingtype.h" using namespace KCM_RegionAndLang; using namespace Qt::StringLiterals; void OptionsModel::load() { m_numberExample = Utility::numericExample(QLocale(m_settings->LC_LocaleWithLang(SettingType::Numeric))); m_timeExample = Utility::timeExample(QLocale(m_settings->LC_LocaleWithLang(SettingType::Time))); m_measurementExample = Utility::measurementExample(QLocale(m_settings->LC_LocaleWithLang(SettingType::Measurement))); m_currencyExample = Utility::monetaryExample(QLocale(m_settings->LC_LocaleWithLang(SettingType::Currency))); m_paperSizeExample = Utility::paperSizeExample(QLocale(m_settings->LC_LocaleWithLang(SettingType::PaperSize))); #ifdef LC_ADDRESS m_addressExample = Utility::addressExample(QLocale(m_settings->LC_LocaleWithLang(SettingType::Address))); m_nameStyleExample = Utility::nameStyleExample(QLocale(m_settings->LC_LocaleWithLang(SettingType::NameStyle))); m_phoneNumbersExample = Utility::phoneNumbersExample(QLocale(m_settings->LC_LocaleWithLang(SettingType::PhoneNumbers))); #endif KSharedConfigPtr globalConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals")); KConfigGroup localeGroup(globalConfig, QStringLiteral("Locale")); int i = localeGroup.readEntry("BinaryUnitDialect", static_cast(KFormat::IECBinaryDialect)); if (i < KFormat::DefaultBinaryDialect || i > KFormat::BinaryUnitDialect::LastBinaryDialect) { i = KFormat::IECBinaryDialect; } setBinaryDialect(i); } OptionsModel::OptionsModel(KCMRegionAndLang *parent) : QAbstractListModel(parent) , m_settings(parent->settings()) { m_staticNames = {{{i18nc("@info:title", "Language"), SettingType::Lang}, {i18nc("@info:title", "Numbers"), SettingType::Numeric}, {i18nc("@info:title", "Time"), SettingType::Time}, {i18nc("@info:title", "Currency"), SettingType::Currency}, {i18nc("@info:title", "Measurements"), SettingType::Measurement}, {i18nc("@info:title", "Paper Size"), SettingType::PaperSize}}}; #ifdef LC_ADDRESS m_staticNames.push_back(std::make_pair(i18nc("@info:title", "Address"), SettingType::Address)); m_staticNames.push_back(std::make_pair(i18nc("@info:title", "Name Style"), SettingType::NameStyle)); m_staticNames.push_back(std::make_pair(i18nc("@info:title", "Phone Numbers"), SettingType::PhoneNumbers)); #endif m_staticNames.push_back(std::make_pair(i18nc("@info:title", "Data and Storage Sizes"), SettingType::BinaryDialect)); connect(m_settings, &RegionAndLangSettings::langChanged, this, &OptionsModel::handleLangChange); connect(m_settings, &RegionAndLangSettings::numericChanged, this, [this] { QLocale locale(m_settings->LC_LocaleWithLang(SettingType::Numeric)); m_numberExample = Utility::numericExample(locale); Q_EMIT dataChanged(createIndex(SettingType::Numeric, 0), createIndex(SettingType::Numeric, 0), {Subtitle, Example}); }); connect(m_settings, &RegionAndLangSettings::timeChanged, this, [this] { QLocale locale(m_settings->LC_LocaleWithLang(SettingType::Time)); m_timeExample = Utility::timeExample(locale); Q_EMIT dataChanged(createIndex(SettingType::Time, 0), createIndex(SettingType::Time, 0), {Subtitle, Example}); }); connect(m_settings, &RegionAndLangSettings::monetaryChanged, this, [this] { QLocale locale(m_settings->LC_LocaleWithLang(SettingType::Currency)); m_currencyExample = Utility::monetaryExample(locale); Q_EMIT dataChanged(createIndex(SettingType::Currency, 0), createIndex(SettingType::Currency, 0), {Subtitle, Example}); }); connect(m_settings, &RegionAndLangSettings::measurementChanged, this, [this] { QLocale locale(m_settings->LC_LocaleWithLang(SettingType::Measurement)); m_measurementExample = Utility::measurementExample(locale); Q_EMIT dataChanged(createIndex(SettingType::Measurement, 0), createIndex(SettingType::Measurement, 0), {Subtitle, Example}); }); connect(m_settings, &RegionAndLangSettings::paperSizeChanged, this, [this] { QLocale locale(m_settings->LC_LocaleWithLang(SettingType::PaperSize)); m_paperSizeExample = Utility::paperSizeExample(locale); Q_EMIT dataChanged(createIndex(SettingType::PaperSize, 0), createIndex(SettingType::PaperSize, 0), {Subtitle, Example}); }); #ifdef LC_ADDRESS connect(m_settings, &RegionAndLangSettings::addressChanged, this, [this] { QLocale locale(m_settings->LC_LocaleWithLang(SettingType::Address)); m_addressExample = Utility::addressExample(locale); Q_EMIT dataChanged(createIndex(SettingType::Address, 0), createIndex(SettingType::Address, 0), {Subtitle, Example}); }); connect(m_settings, &RegionAndLangSettings::nameStyleChanged, this, [this] { QLocale locale(m_settings->LC_LocaleWithLang(SettingType::NameStyle)); m_nameStyleExample = Utility::nameStyleExample(locale); Q_EMIT dataChanged(createIndex(SettingType::NameStyle, 0), createIndex(SettingType::NameStyle, 0), {Subtitle, Example}); }); connect(m_settings, &RegionAndLangSettings::phoneNumbersChanged, this, [this] { QLocale locale(m_settings->LC_LocaleWithLang(SettingType::PhoneNumbers)); m_phoneNumbersExample = Utility::phoneNumbersExample(locale); Q_EMIT dataChanged(createIndex(SettingType::PhoneNumbers, 0), createIndex(SettingType::PhoneNumbers, 0), {Subtitle, Example}); }); #endif load(); } int OptionsModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent) return m_staticNames.size(); } QVariant OptionsModel::data(const QModelIndex &index, int role) const { using namespace KCM_RegionAndLang; const int row = index.row(); if (row < 0 || row >= (int)m_staticNames.size()) { return {}; } switch (static_cast(role)) { case Name: return m_staticNames.at(row).first; case Subtitle: { switch (static_cast(row)) { case Language: Q_ASSERT(false); // shouldn't happen return {}; case Lang: if (m_settings->defaultLangValue().isEmpty() && m_settings->isDefaultSetting(SettingType::Lang)) { // no Lang configured, no $LANG in env return i18nc("@info:title, the current setting is system default", "System Default"); } else if (!m_settings->lang().isEmpty() && m_settings->lang() != m_settings->defaultLangValue()) { // Lang configured and not empty return getNativeName(m_settings->lang()); } else { // Lang configured but empty, try to read from $LANGUAGE first. if (const QString languages = m_settings->defaultLanguageValue(); !languages.isEmpty()) { // If the first language is invalid, just fall through to $LANG const QStringList languageList = languages.split(QLatin1Char(':')); if (const QString firstLanguage = getNativeName(languageList[0]); !firstLanguage.isEmpty()) { return firstLanguage; } } // Lang configured but empty, try to read from $LANG, shouldn't happen on a valid config file return getNativeName(m_settings->defaultLangValue()); } case Numeric: if (m_settings->isDefaultSetting(SettingType::Numeric)) { return getNativeName(m_settings->numeric()); } break; case Time: if (m_settings->isDefaultSetting(SettingType::Time)) { return getNativeName(m_settings->time()); } break; case Currency: if (m_settings->isDefaultSetting(SettingType::Currency)) { return getNativeName(m_settings->monetary()); } break; case Measurement: if (m_settings->isDefaultSetting(SettingType::Measurement)) { return getNativeName(m_settings->measurement()); } break; case PaperSize: if (m_settings->isDefaultSetting(SettingType::PaperSize)) { return getNativeName(m_settings->paperSize()); } break; #ifdef LC_ADDRESS case Address: if (m_settings->isDefaultSetting(SettingType::Address)) { return getNativeName(m_settings->address()); } break; case NameStyle: if (m_settings->isDefaultSetting(SettingType::NameStyle)) { return getNativeName(m_settings->nameStyle()); } break; case PhoneNumbers: if (m_settings->isDefaultSetting(SettingType::PhoneNumbers)) { return getNativeName(m_settings->phoneNumbers()); } break; #endif case BinaryDialect: Q_UNREACHABLE(); } return {}; // implicit locale } case Example: { switch (static_cast(row)) { case Language: Q_ASSERT(false); // shouldn't happen return {}; case Lang: return {}; case Numeric: { QString example = m_numberExample; if (m_settings->isDefaultSetting(SettingType::Numeric)) { example += implicitFormatExampleMsg(); } return example; } case Time: { QString example = m_timeExample; if (m_settings->isDefaultSetting(SettingType::Time)) { example += implicitFormatExampleMsg(); } return example; } case Currency: { QString example = m_currencyExample; if (m_settings->isDefaultSetting(SettingType::Currency)) { example += implicitFormatExampleMsg(); } return example; } case Measurement: { QString example = m_measurementExample; if (m_settings->isDefaultSetting(SettingType::Measurement)) { example += implicitFormatExampleMsg(); } return example; } case PaperSize: { QString example = m_paperSizeExample; if (m_settings->isDefaultSetting(SettingType::PaperSize)) { example += implicitFormatExampleMsg(); } return example; } #ifdef LC_ADDRESS case Address: { QString example = m_addressExample; if (m_settings->isDefaultSetting(SettingType::Address)) { example += implicitFormatExampleMsg(); } return example; } case NameStyle: { QString example = m_nameStyleExample; if (m_settings->isDefaultSetting(SettingType::NameStyle)) { example += implicitFormatExampleMsg(); } return example; } case PhoneNumbers: { QString example = m_phoneNumbersExample; if (m_settings->isDefaultSetting(SettingType::PhoneNumbers)) { example += implicitFormatExampleMsg(); } return example; } #endif case BinaryDialect: return m_binaryDialectExample; } return {}; } case Page: return m_staticNames.at(row).second; } return {}; } QHash OptionsModel::roleNames() const { return {{Name, QByteArrayLiteral("name")}, {Subtitle, QByteArrayLiteral("localeName")}, {Example, QByteArrayLiteral("example")}, {Page, QByteArrayLiteral("page")}}; } KFormat::BinaryUnitDialect OptionsModel::binaryDialect() { return m_binaryDialect; } void OptionsModel::updateBinaryDialectExample() { int defbase = 1024; if (m_binaryDialect == KFormat::MetricBinaryDialect) { defbase = 1000; } const KFormat f; m_binaryDialectExample = f.formatByteSize(defbase, 1, m_binaryDialect, KFormat::BinarySizeUnits::UnitKiloByte) + u" = " + f.formatByteSize(defbase, 1, m_binaryDialect, KFormat::BinarySizeUnits::UnitByte); switch (m_binaryDialect) { case KFormat::DefaultBinaryDialect: case KFormat::IECBinaryDialect: m_binaryDialectExample = i18nc("the prefix for IECBinaryDialect, %1 is an example for 1 KiB", "KiB, MiB, GiB; %1", m_binaryDialectExample); break; case KFormat::JEDECBinaryDialect: m_binaryDialectExample = i18nc("the prefix for JEDECBinaryDialect, %1 is an example for 1 KB", "KB, MB, GB; %1", m_binaryDialectExample); break; case KFormat::MetricBinaryDialect: m_binaryDialectExample = i18nc("the prefix for MetricBinaryDialect, %1 is an example for 1 kB", "kB, MB, GB; %1", m_binaryDialectExample); break; } } void OptionsModel::setBinaryDialect(QVariant value) { if (value.metaType().id() != QMetaType::Int) { return; } int i = value.toInt(); if (i < KFormat::DefaultBinaryDialect || i > KFormat::LastBinaryDialect) { i = KFormat::IECBinaryDialect; } m_binaryDialect = static_cast(i); updateBinaryDialectExample(); const auto idx = createIndex(SettingType::BinaryDialect, 0); Q_EMIT dataChanged(idx, idx, {Subtitle, Example}); Q_EMIT binaryDialectChanged(); } void OptionsModel::handleLangChange() { Q_EMIT dataChanged(createIndex(SettingType::Lang, 0), createIndex(SettingType::Lang, 0), {Subtitle, Example}); QLocale lang = QLocale(m_settings->lang()); if (m_settings->isDefaultSetting(SettingType::Numeric)) { m_numberExample = Utility::numericExample(lang); Q_EMIT dataChanged(createIndex(SettingType::Numeric, 0), createIndex(SettingType::Numeric, 0), {Subtitle, Example}); } if (m_settings->isDefaultSetting(SettingType::Time)) { m_timeExample = Utility::timeExample(lang); Q_EMIT dataChanged(createIndex(SettingType::Time, 0), createIndex(SettingType::Time, 0), {Subtitle, Example}); } if (m_settings->isDefaultSetting(SettingType::Currency)) { m_currencyExample = Utility::monetaryExample(lang); Q_EMIT dataChanged(createIndex(SettingType::Currency, 0), createIndex(SettingType::Currency, 0), {Subtitle, Example}); } if (m_settings->isDefaultSetting(SettingType::Measurement)) { m_measurementExample = Utility::measurementExample(lang); Q_EMIT dataChanged(createIndex(SettingType::Measurement, 0), createIndex(SettingType::Measurement, 0), {Subtitle, Example}); } if (m_settings->isDefaultSetting(SettingType::PaperSize)) { m_paperSizeExample = Utility::paperSizeExample(lang); Q_EMIT dataChanged(createIndex(SettingType::PaperSize, 0), createIndex(SettingType::PaperSize, 0), {Subtitle, Example}); } #ifdef LC_ADDRESS if (m_settings->isDefaultSetting(SettingType::Address)) { m_addressExample = Utility::addressExample(lang); Q_EMIT dataChanged(createIndex(SettingType::Address, 0), createIndex(SettingType::Address, 0), {Subtitle, Example}); } if (m_settings->isDefaultSetting(SettingType::NameStyle)) { m_nameStyleExample = Utility::nameStyleExample(lang); Q_EMIT dataChanged(createIndex(SettingType::NameStyle, 0), createIndex(SettingType::NameStyle, 0), {Subtitle, Example}); } if (m_settings->isDefaultSetting(SettingType::PhoneNumbers)) { m_phoneNumbersExample = Utility::phoneNumbersExample(lang); Q_EMIT dataChanged(createIndex(SettingType::PhoneNumbers, 0), createIndex(SettingType::PhoneNumbers, 0), {Subtitle, Example}); } #endif } QString OptionsModel::implicitFormatExampleMsg() const { QString locale; if (!m_settings->lang().isEmpty()) { locale = getNativeName(m_settings->lang()); } else if (!m_settings->defaultLangValue().isEmpty()) { locale = getNativeName(m_settings->defaultLangValue()); } else { locale = i18nc("@info:title, the current setting is system default", "System Default"); } return i18nc("as subtitle, remind user that the format used now is inherited from locale %1", " (Standard format for %1)", locale); } QString OptionsModel::getNativeName(const QString &locale) const { const QString nativeName = QLocale(locale).nativeLanguageName(); if (nativeName.isEmpty()) { return locale; } return nativeName; }