1/*
2 SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "addressformat.h"
7#include "address.h"
8#include "addressformat_p.h"
9#include "addressformatparser_p.h"
10#include "addressformatscript_p.h"
11
12#include <KConfig>
13#include <KConfigGroup>
14#include <KCountry>
15
16#include <QDebug>
17#include <QLocale>
18
19using namespace KContacts;
20
21AddressFormatElement::AddressFormatElement()
22 : d(new AddressFormatElementPrivate)
23{
24}
25
26AddressFormatElement::AddressFormatElement(const AddressFormatElement &) = default;
27AddressFormatElement::~AddressFormatElement() = default;
28AddressFormatElement &AddressFormatElement::operator=(const AddressFormatElement &) = default;
29
30bool AddressFormatElement::isField() const
31{
32 return d->field != AddressFormatField::NoField;
33}
34
35AddressFormatField AddressFormatElement::field() const
36{
37 return d->field;
38}
39
40bool AddressFormatElement::isLiteral() const
41{
42 return !d->literal.isEmpty();
43}
44
45QString AddressFormatElement::literal() const
46{
47 return d->literal;
48}
49
50bool AddressFormatElement::isSeparator() const
51{
52 return !isField() && !isLiteral();
53}
54
55AddressFormat::AddressFormat()
56 : d(new AddressFormatPrivate)
57{
58}
59
60AddressFormat::AddressFormat(const AddressFormat &) = default;
61AddressFormat::~AddressFormat() = default;
62AddressFormat &AddressFormat::operator=(const AddressFormat &) = default;
63
64const std::vector<AddressFormatElement> &AddressFormat::elements() const
65{
66 return d->elements;
67}
68
69AddressFormatFields AddressFormat::requiredFields() const
70{
71 return d->required;
72}
73
74AddressFormatFields AddressFormat::usedFields() const
75{
76 return std::accumulate(first: d->elements.begin(), last: d->elements.end(), init: AddressFormatFields(AddressFormatField::NoField), binary_op: [](auto lhs, const auto &rhs) {
77 return lhs | rhs.field();
78 });
79}
80
81AddressFormatFields AddressFormat::upperCaseFields() const
82{
83 return d->upper;
84}
85
86QString AddressFormat::postalCodeRegularExpression() const
87{
88 return d->postalCodeFormat;
89}
90
91QString AddressFormat::country() const
92{
93 return d->country;
94}
95
96QList<AddressFormatElement> AddressFormat::elementsForQml() const
97{
98 QList<AddressFormatElement> l;
99 l.reserve(asize: d->elements.size());
100 std::copy(first: d->elements.begin(), last: d->elements.end(), result: std::back_inserter(x&: l));
101 return l;
102}
103
104static QString addressFormatRc()
105{
106 Q_INIT_RESOURCE(kcontacts); // must be called outside of a namespace
107 return QStringLiteral(":/org.kde.kcontacts/addressformatrc");
108}
109
110AddressFormat
111AddressFormatRepository::formatForCountry(const QString &countryCode, AddressFormatScriptPreference scriptPref, AddressFormatPreference formatPref)
112{
113 static const KConfig entry(addressFormatRc(), KConfig::SimpleConfig);
114 KConfigGroup group = entry.group(group: countryCode);
115
116 AddressFormat format;
117 auto fmt = AddressFormatPrivate::get(format);
118 fmt->required = AddressFormatParser::parseFields(s: group.readEntry(key: "Required", aDefault: QString()));
119 fmt->upper = AddressFormatParser::parseFields(s: group.readEntry(key: "Upper", aDefault: QString()));
120
121 QString formatString;
122 if (scriptPref == AddressFormatScriptPreference::Latin && formatPref == AddressFormatPreference::Business) {
123 formatString = group.readEntry(key: "LatinBusinessAddressFormat", aDefault: QString());
124 }
125 if (formatString.isEmpty() && scriptPref == AddressFormatScriptPreference::Latin) {
126 formatString = group.readEntry(key: "LatinAddressFormat", aDefault: QString());
127 }
128 if (formatString.isEmpty() && formatPref == AddressFormatPreference::Business) {
129 formatString = group.readEntry(key: "BusinessAddressFormat", aDefault: QString());
130 }
131 if (formatString.isEmpty()) {
132 formatString = group.readEntry(key: "AddressFormat", QStringLiteral("%N%n%O%n%A%nPO BOX %P%n%C %S %Z"));
133 }
134 fmt->elements = AddressFormatParser::parseElements(s: formatString);
135 fmt->postalCodeFormat = group.readEntry(key: "PostalCodeFormat", aDefault: QString());
136 fmt->country = countryCode;
137 return format;
138}
139
140AddressFormat AddressFormatRepository::formatForAddress(const Address &address, AddressFormatPreference formatPref)
141{
142 KCountry c;
143 if (address.country().size() == 2) {
144 c = KCountry::fromAlpha2(alpha2Code: address.country());
145 }
146 if (!c.isValid()) {
147 c = KCountry::fromName(name: address.country());
148 }
149 // fall back to our own country
150 if (!c.isValid()) {
151 c = KCountry::fromQLocale(country: QLocale().territory());
152 }
153
154 const auto scriptPref = AddressFormatScript::detect(addr: address) == AddressFormatScript::LatinLikeScript ? AddressFormatScriptPreference::Latin
155 : AddressFormatScriptPreference::Local;
156 return formatForCountry(countryCode: c.alpha2(), scriptPref, formatPref);
157}
158
159#include "moc_addressformat.cpp"
160

source code of kcontacts/src/addressformat.cpp