1/*
2 This file is part of the KContacts framework.
3 SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "phonenumber.h"
9#include "parametermap_p.h"
10
11#include <KLocalizedString>
12#include <krandom.h>
13
14#include <QDataStream>
15#include <QSharedData>
16
17using namespace KContacts;
18
19static QString cleanupNumber(const QString &input)
20{
21 return input.simplified();
22}
23
24class Q_DECL_HIDDEN PhoneNumber::Private : public QSharedData
25{
26public:
27 Private(Type type)
28 : mId(KRandom::randomString(length: 8))
29 , mType(type)
30 {
31 }
32
33 Private(const Private &other)
34 : QSharedData(other)
35 {
36 mId = other.mId;
37 mType = other.mType;
38 mNumber = other.mNumber;
39 }
40
41 QString mId;
42 QString mNumber;
43 Type mType;
44 ParameterMap mParamMap;
45};
46
47PhoneNumber::PhoneNumber()
48 : d(new Private(Home))
49{
50}
51
52PhoneNumber::PhoneNumber(const QString &number, Type type)
53 : d(new Private(type))
54{
55 d->mNumber = cleanupNumber(input: number);
56}
57
58PhoneNumber::PhoneNumber(const PhoneNumber &other)
59 : d(other.d)
60{
61}
62
63PhoneNumber::~PhoneNumber() = default;
64
65bool PhoneNumber::operator==(const PhoneNumber &other) const
66{
67 if (d->mId != other.d->mId) {
68 return false;
69 }
70
71 if (d->mNumber != other.d->mNumber) {
72 return false;
73 }
74
75 if (d->mType != other.d->mType) {
76 return false;
77 }
78
79 if (d->mParamMap != other.d->mParamMap) {
80 return false;
81 }
82
83 return true;
84}
85
86bool PhoneNumber::operator!=(const PhoneNumber &other) const
87{
88 return !(other == *this);
89}
90
91PhoneNumber &PhoneNumber::operator=(const PhoneNumber &other)
92{
93 if (this != &other) {
94 d = other.d;
95 }
96
97 return *this;
98}
99
100bool PhoneNumber::isEmpty() const
101{
102 return d->mNumber.isEmpty();
103}
104
105void PhoneNumber::setId(const QString &id)
106{
107 d->mId = id;
108}
109
110QString PhoneNumber::id() const
111{
112 return d->mId;
113}
114
115void PhoneNumber::setNumber(const QString &number)
116{
117 d->mNumber = cleanupNumber(input: number);
118}
119
120QString PhoneNumber::number() const
121{
122 return d->mNumber;
123}
124
125QString PhoneNumber::normalizedNumber() const
126{
127 QString result;
128 result.reserve(asize: d->mNumber.size());
129 for (const auto &c : d->mNumber) {
130 if (c.isDigit() || (c == QLatin1Char('+') && result.isEmpty())) {
131 result.push_back(c);
132 }
133 }
134 return result;
135}
136
137void PhoneNumber::setType(Type type)
138{
139 d->mType = type;
140}
141
142PhoneNumber::Type PhoneNumber::type() const
143{
144 return d->mType;
145}
146
147QString PhoneNumber::typeLabel() const
148{
149 return typeLabel(type: type());
150}
151
152PhoneNumber::TypeList PhoneNumber::typeList()
153{
154 static TypeList list;
155
156 if (list.isEmpty()) {
157 list << Home << Work << Msg << Pref << Voice << Fax << Cell << Video //
158 << Bbs << Modem << Car << Isdn << Pcs << Pager << Undefined;
159 }
160
161 return list;
162}
163
164QString PhoneNumber::typeFlagLabel(TypeFlag type)
165{
166 switch (type) {
167 case Undefined:
168 return i18nc("Undefined phone type", "Telephone number");
169 case Home:
170 return i18nc("Home phone", "Home");
171 case Work:
172 return i18nc("Work phone", "Work");
173 case Msg:
174 return i18n("Messenger");
175 case Pref:
176 return i18nc("Preferred phone", "Preferred");
177 case Voice:
178 return i18n("Voice");
179 case Fax:
180 return i18n("Fax");
181 case Cell:
182 return i18nc("Mobile Phone", "Mobile");
183 case Video:
184 return i18nc("Video phone", "Video");
185 case Bbs:
186 return i18n("Mailbox");
187 case Modem:
188 return i18n("Modem");
189 case Car:
190 return i18nc("Car Phone", "Car");
191 case Isdn:
192 return i18n("ISDN");
193 case Pcs:
194 return i18n("PCS");
195 case Pager:
196 return i18n("Pager");
197 default:
198 return i18nc("another type of phone", "Other");
199 }
200}
201
202QString PhoneNumber::typeLabel(Type type)
203{
204 QString label;
205 bool first = true;
206
207 // special cases
208 // Pref stand alone -> Preferred Number
209 // Home+Fax or Work+Fax -> combine as initial string
210 if (type == Pref) {
211 return i18n("Preferred Number");
212 }
213
214 if (type & Fax) {
215 if (type & Home) {
216 label = i18n("Home Fax");
217 first = false;
218 type &= ~Fax;
219 type &= ~Home;
220 } else if (type & Work) {
221 label = i18n("Work Fax");
222 first = false;
223 type &= ~Fax;
224 type &= ~Work;
225 }
226 }
227
228 const TypeList list = typeList();
229 for (const auto f : list) {
230 // these are actually flags
231 const TypeFlag flag = static_cast<TypeFlag>(static_cast<int>(f));
232 if (type & flag) {
233 if (!first) {
234 label.append(c: QLatin1Char('/'));
235 }
236
237 label.append(s: typeFlagLabel(type: flag));
238
239 if (first) {
240 first = false;
241 }
242 }
243 }
244
245 return label;
246}
247
248bool PhoneNumber::isPreferred() const
249{
250 return type() & Pref;
251}
252
253bool PhoneNumber::supportsSms() const
254{
255 return type() & Cell;
256}
257
258QString PhoneNumber::toString() const
259{
260 QString str = QLatin1String("PhoneNumber {\n");
261 str += QStringLiteral(" Id: %1\n").arg(a: d->mId);
262 str += QStringLiteral(" Type: %1\n").arg(a: typeLabel(type: d->mType));
263 str = d->mParamMap.toString();
264 str += QStringLiteral(" Number: %1\n").arg(a: d->mNumber);
265 str += QLatin1String("}\n");
266
267 return str;
268}
269
270void PhoneNumber::setParams(const ParameterMap &params)
271{
272 d->mParamMap = params;
273}
274
275ParameterMap PhoneNumber::params() const
276{
277 return d->mParamMap;
278}
279
280QDataStream &KContacts::operator<<(QDataStream &s, const PhoneNumber &phone)
281{
282 return s << phone.d->mId << static_cast<uint>(phone.d->mType) << phone.d->mNumber << phone.d->mParamMap;
283}
284
285QDataStream &KContacts::operator>>(QDataStream &s, PhoneNumber &phone)
286{
287 uint type;
288 s >> phone.d->mId >> type >> phone.d->mNumber >> phone.d->mParamMap;
289 phone.d->mType = PhoneNumber::Type(type);
290
291 return s;
292}
293
294#include "moc_phonenumber.cpp"
295

source code of kcontacts/src/phonenumber.cpp