File indexing completed on 2024-04-14 03:51:24

0001 /*
0002     SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include "addressformat.h"
0007 #include "address.h"
0008 #include "addressformat_p.h"
0009 #include "addressformatparser_p.h"
0010 #include "addressformatscript_p.h"
0011 
0012 #include <KConfig>
0013 #include <KConfigGroup>
0014 #include <KCountry>
0015 
0016 #include <QDebug>
0017 #include <QLocale>
0018 
0019 using namespace KContacts;
0020 
0021 AddressFormatElement::AddressFormatElement()
0022     : d(new AddressFormatElementPrivate)
0023 {
0024 }
0025 
0026 AddressFormatElement::AddressFormatElement(const AddressFormatElement &) = default;
0027 AddressFormatElement::~AddressFormatElement() = default;
0028 AddressFormatElement &AddressFormatElement::operator=(const AddressFormatElement &) = default;
0029 
0030 bool AddressFormatElement::isField() const
0031 {
0032     return d->field != AddressFormatField::NoField;
0033 }
0034 
0035 AddressFormatField AddressFormatElement::field() const
0036 {
0037     return d->field;
0038 }
0039 
0040 bool AddressFormatElement::isLiteral() const
0041 {
0042     return !d->literal.isEmpty();
0043 }
0044 
0045 QString AddressFormatElement::literal() const
0046 {
0047     return d->literal;
0048 }
0049 
0050 bool AddressFormatElement::isSeparator() const
0051 {
0052     return !isField() && !isLiteral();
0053 }
0054 
0055 AddressFormat::AddressFormat()
0056     : d(new AddressFormatPrivate)
0057 {
0058 }
0059 
0060 AddressFormat::AddressFormat(const AddressFormat &) = default;
0061 AddressFormat::~AddressFormat() = default;
0062 AddressFormat &AddressFormat::operator=(const AddressFormat &) = default;
0063 
0064 const std::vector<AddressFormatElement> &AddressFormat::elements() const
0065 {
0066     return d->elements;
0067 }
0068 
0069 AddressFormatFields AddressFormat::requiredFields() const
0070 {
0071     return d->required;
0072 }
0073 
0074 AddressFormatFields AddressFormat::usedFields() const
0075 {
0076     return std::accumulate(d->elements.begin(), d->elements.end(), AddressFormatFields(AddressFormatField::NoField), [](auto lhs, const auto &rhs) {
0077         return lhs | rhs.field();
0078     });
0079 }
0080 
0081 AddressFormatFields AddressFormat::upperCaseFields() const
0082 {
0083     return d->upper;
0084 }
0085 
0086 QString AddressFormat::postalCodeRegularExpression() const
0087 {
0088     return d->postalCodeFormat;
0089 }
0090 
0091 QString AddressFormat::country() const
0092 {
0093     return d->country;
0094 }
0095 
0096 QList<AddressFormatElement> AddressFormat::elementsForQml() const
0097 {
0098     QList<AddressFormatElement> l;
0099     l.reserve(d->elements.size());
0100     std::copy(d->elements.begin(), d->elements.end(), std::back_inserter(l));
0101     return l;
0102 }
0103 
0104 static QString addressFormatRc()
0105 {
0106     Q_INIT_RESOURCE(kcontacts); // must be called outside of a namespace
0107     return QStringLiteral(":/org.kde.kcontacts/addressformatrc");
0108 }
0109 
0110 AddressFormat
0111 AddressFormatRepository::formatForCountry(const QString &countryCode, AddressFormatScriptPreference scriptPref, AddressFormatPreference formatPref)
0112 {
0113     static const KConfig entry(addressFormatRc(), KConfig::SimpleConfig);
0114     KConfigGroup group = entry.group(countryCode);
0115 
0116     AddressFormat format;
0117     auto fmt = AddressFormatPrivate::get(format);
0118     fmt->required = AddressFormatParser::parseFields(group.readEntry("Required", QString()));
0119     fmt->upper = AddressFormatParser::parseFields(group.readEntry("Upper", QString()));
0120 
0121     QString formatString;
0122     if (scriptPref == AddressFormatScriptPreference::Latin && formatPref == AddressFormatPreference::Business) {
0123         formatString = group.readEntry("LatinBusinessAddressFormat", QString());
0124     }
0125     if (formatString.isEmpty() && scriptPref == AddressFormatScriptPreference::Latin) {
0126         formatString = group.readEntry("LatinAddressFormat", QString());
0127     }
0128     if (formatString.isEmpty() && formatPref == AddressFormatPreference::Business) {
0129         formatString = group.readEntry("BusinessAddressFormat", QString());
0130     }
0131     if (formatString.isEmpty()) {
0132         formatString = group.readEntry("AddressFormat", QStringLiteral("%N%n%O%n%A%nPO BOX %P%n%C %S %Z"));
0133     }
0134     fmt->elements = AddressFormatParser::parseElements(formatString);
0135     fmt->postalCodeFormat = group.readEntry("PostalCodeFormat", QString());
0136     fmt->country = countryCode;
0137     return format;
0138 }
0139 
0140 AddressFormat AddressFormatRepository::formatForAddress(const Address &address, AddressFormatPreference formatPref)
0141 {
0142     KCountry c;
0143     if (address.country().size() == 2) {
0144         c = KCountry::fromAlpha2(address.country());
0145     }
0146     if (!c.isValid()) {
0147         c = KCountry::fromName(address.country());
0148     }
0149     // fall back to our own country
0150     if (!c.isValid()) {
0151         c = KCountry::fromQLocale(QLocale().territory());
0152     }
0153 
0154     const auto scriptPref = AddressFormatScript::detect(address) == AddressFormatScript::LatinLikeScript ? AddressFormatScriptPreference::Latin
0155                                                                                                          : AddressFormatScriptPreference::Local;
0156     return formatForCountry(c.alpha2(), scriptPref, formatPref);
0157 }
0158 
0159 #include "moc_addressformat.cpp"