KContacts

addressee.cpp
1/*
2 This file is part of the KContacts framework.
3 SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org>
4 SPDX-FileCopyrightText: 2003 Carsten Pfeiffer <pfeiffer@kde.org>
5 SPDX-FileCopyrightText: 2005 Ingo Kloecker <kloecker@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#include <QDate>
11#include <QRegularExpression>
12#include <QSharedData>
13#include <QUuid>
14
15#include "kcontacts_debug.h"
16#include <KLocalizedString>
17
18#include "addressee.h"
19#include "addresseehelper_p.h"
20#include "parametermap_p.h"
21
22using namespace KContacts;
23
24static bool matchBinaryPattern(int value, int pattern);
25
26template<class L>
27static bool listEquals(const QList<L> &list, const QList<L> &pattern);
28static bool listEquals(const QStringList &list, const QStringList &pattern);
29
30struct CustomData {
31 QString name;
32 QString value;
33};
34
35inline bool operator==(const CustomData &a, const CustomData &b)
36{
37 return std::tie(a.name, a.value) == std::tie(b.name, b.value);
38}
39
40inline bool operator!=(const CustomData &a, const CustomData &b)
41{
42 return std::tie(a.name, a.value) != std::tie(b.name, b.value);
43}
44
45inline bool operator<(const CustomData &a, const CustomData &b)
46{
47 return a.name < b.name;
48}
49
50class Q_DECL_HIDDEN Addressee::Private : public QSharedData
51{
52public:
53 Private()
54 : mUid(QUuid::createUuid().toString().mid(1, 36))
55 , mEmpty(true)
56 , mChanged(false)
57 , mBirthdayWithTime(false)
58 {
59 // We avoid the curly braces so the string is RFC4122 compliant and can be used as urn
60 }
61
62 Private(const Private &other)
63 : QSharedData(other)
64 {
65 mUid = other.mUid;
66 mName = other.mName;
67 mFormattedName = other.mFormattedName;
68 mFamilyName = other.mFamilyName;
69 mGivenName = other.mGivenName;
70 mAdditionalName = other.mAdditionalName;
71 mPrefix = other.mPrefix;
72 mSuffix = other.mSuffix;
73 mBirthday = other.mBirthday;
74 mBirthdayWithTime = other.mBirthdayWithTime;
75 mMailer = other.mMailer;
76 mTimeZone = other.mTimeZone;
77 mGeo = other.mGeo;
78 mDepartment = other.mDepartment;
79 mNote = other.mNote;
80 mProductId = other.mProductId;
81 mRevision = other.mRevision;
82 mSortString = other.mSortString;
83 mSecrecy = other.mSecrecy;
84 mLogo = other.mLogo;
85 mPhoto = other.mPhoto;
86 mSound = other.mSound;
87
88 mPhoneNumbers = other.mPhoneNumbers;
89 mAddresses = other.mAddresses;
90 mKeys = other.mKeys;
91 mLangs = other.mLangs;
92 mGender = other.mGender;
93 mEmails = other.mEmails;
94 mCategories = other.mCategories;
95 mCustomFields = other.mCustomFields;
96 mCalendarUrl = other.mCalendarUrl;
97 mSoundListExtra = other.mSoundListExtra;
98 mPhotoExtraList = other.mPhotoExtraList;
99 mLogoExtraList = other.mLogoExtraList;
100 mUrlExtraList = other.mUrlExtraList;
101 mMembers = other.mMembers;
102 mRelationships = other.mRelationships;
103 mSources = other.mSources;
104 mEmpty = other.mEmpty;
105 mImpps = other.mImpps;
106 mChanged = other.mChanged;
107 mTitleExtraList = other.mTitleExtraList;
108 mRoleExtraList = other.mRoleExtraList;
109 mOrgExtraList = other.mOrgExtraList;
110 }
111
112 ~Private()
113 {
114 }
115
116 std::vector<CustomData>::iterator findByName(const QString &qualifiedName)
117 {
118 return std::find_if(mCustomFields.begin(), mCustomFields.end(), [&qualifiedName](const CustomData &info) {
119 return info.name == qualifiedName;
120 });
121 }
122
123 std::vector<CustomData>::const_iterator findByName(const QString &qualifiedName) const
124 {
125 return std::find_if(mCustomFields.cbegin(), mCustomFields.cend(), [&qualifiedName](const CustomData &info) {
126 return info.name == qualifiedName;
127 });
128 }
129
130 QString mUid;
131 QString mName;
132 QString mFormattedName;
133 QString mFamilyName;
134 QString mGivenName;
135 QString mAdditionalName;
136 QString mPrefix;
137 QString mSuffix;
138 QDateTime mBirthday;
139 QString mMailer;
140 TimeZone mTimeZone;
141 Geo mGeo;
142 QString mDepartment;
143 QString mNote;
144 QString mProductId;
145 QDateTime mRevision;
146 QString mSortString;
147 Secrecy mSecrecy;
148 Picture mLogo;
149 Picture mPhoto;
150 Sound mSound;
151
152 PhoneNumber::List mPhoneNumbers;
153 Address::List mAddresses;
154 Key::List mKeys;
155 Email::List mEmails;
156 Lang::List mLangs;
157 Impp::List mImpps;
158 Gender mGender;
159 QString mKind;
160 QStringList mCategories;
161 std::vector<CustomData> mCustomFields;
162 CalendarUrl::List mCalendarUrl;
163 Sound::List mSoundListExtra;
164 Picture::List mPhotoExtraList;
165 Picture::List mLogoExtraList;
166 ResourceLocatorUrl::List mUrlExtraList;
167 QList<QUrl> mSources;
168 QStringList mMembers;
169 Related::List mRelationships;
170 FieldGroup::List mFieldGroupList;
171 Title::List mTitleExtraList;
172 Role::List mRoleExtraList;
173 Org::List mOrgExtraList;
174 NickName::List mNickNameExtraList;
175 ClientPidMap::List mClientPidMapList;
176 bool mEmpty : 1;
177 bool mChanged : 1;
178 bool mBirthdayWithTime;
179};
180
182 : d(new Private)
183{
184}
185
189
191 : d(other.d)
192{
193}
194
196{
197 if (this != &other) {
198 d = other.d;
199 }
200
201 return *this;
202}
203
204bool Addressee::operator==(const Addressee &addressee) const
205{
206 if (d->mUid != addressee.d->mUid) {
207 qCDebug(KCONTACTS_LOG) << "uid differs";
208 return false;
209 }
210
211 if (d->mName != addressee.d->mName //
212 && !(d->mName.isEmpty() && addressee.d->mName.isEmpty())) {
213 qCDebug(KCONTACTS_LOG) << "name differs";
214 return false;
215 }
216
217 if (d->mFormattedName != addressee.d->mFormattedName //
218 && !(d->mFormattedName.isEmpty() && addressee.d->mFormattedName.isEmpty())) {
219 qCDebug(KCONTACTS_LOG) << "formattedName differs";
220 return false;
221 }
222
223 if (d->mFamilyName != addressee.d->mFamilyName //
224 && !(d->mFamilyName.isEmpty() && addressee.d->mFamilyName.isEmpty())) {
225 qCDebug(KCONTACTS_LOG) << "familyName differs";
226 return false;
227 }
228
229 if (d->mGivenName != addressee.d->mGivenName //
230 && !(d->mGivenName.isEmpty() && addressee.d->mGivenName.isEmpty())) {
231 qCDebug(KCONTACTS_LOG) << "givenName differs";
232 return false;
233 }
234
235 if (d->mAdditionalName != addressee.d->mAdditionalName //
236 && !(d->mAdditionalName.isEmpty() && addressee.d->mAdditionalName.isEmpty())) {
237 qCDebug(KCONTACTS_LOG) << "additionalName differs";
238 return false;
239 }
240
241 if (d->mPrefix != addressee.d->mPrefix //
242 && !(d->mPrefix.isEmpty() && addressee.d->mPrefix.isEmpty())) {
243 qCDebug(KCONTACTS_LOG) << "prefix differs";
244 return false;
245 }
246
247 if (d->mSuffix != addressee.d->mSuffix //
248 && !(d->mSuffix.isEmpty() && addressee.d->mSuffix.isEmpty())) {
249 qCDebug(KCONTACTS_LOG) << "suffix differs";
250 return false;
251 }
252
253 if (d->mBirthday != addressee.d->mBirthday //
254 || d->mBirthdayWithTime != addressee.d->mBirthdayWithTime) {
255 qCDebug(KCONTACTS_LOG) << "birthday differs";
256 return false;
257 }
258
259 if (d->mMailer != addressee.d->mMailer //
260 && !(d->mMailer.isEmpty() && addressee.d->mMailer.isEmpty())) {
261 qCDebug(KCONTACTS_LOG) << "mailer differs";
262 return false;
263 }
264
265 if (d->mTimeZone != addressee.d->mTimeZone) {
266 qCDebug(KCONTACTS_LOG) << "timeZone differs";
267 return false;
268 }
269
270 if (d->mGeo != addressee.d->mGeo) {
271 qCDebug(KCONTACTS_LOG) << "geo differs";
272 return false;
273 }
274
275 if (d->mDepartment != addressee.d->mDepartment //
276 && !(d->mDepartment.isEmpty() && addressee.d->mDepartment.isEmpty())) {
277 qCDebug(KCONTACTS_LOG) << "department differs";
278 return false;
279 }
280
281 if (d->mNote != addressee.d->mNote //
282 && !(d->mNote.isEmpty() && addressee.d->mNote.isEmpty())) {
283 qCDebug(KCONTACTS_LOG) << "note differs";
284 return false;
285 }
286
287 if (d->mProductId != addressee.d->mProductId //
288 && !(d->mProductId.isEmpty() && addressee.d->mProductId.isEmpty())) {
289 qCDebug(KCONTACTS_LOG) << "productId differs";
290 return false;
291 }
292
293 if (d->mSortString != addressee.d->mSortString //
294 && !(d->mSortString.isEmpty() && addressee.d->mSortString.isEmpty())) {
295 qCDebug(KCONTACTS_LOG) << "sortString differs";
296 return false;
297 }
298
299 if (d->mSecrecy != addressee.d->mSecrecy) {
300 qCDebug(KCONTACTS_LOG) << "secrecy differs";
301 return false;
302 }
303
304 if (d->mLogo != addressee.d->mLogo) {
305 qCDebug(KCONTACTS_LOG) << "logo differs";
306 return false;
307 }
308
309 if (d->mPhoto != addressee.d->mPhoto) {
310 qCDebug(KCONTACTS_LOG) << "photo differs";
311 return false;
312 }
313
314 if (d->mSound != addressee.d->mSound) {
315 qCDebug(KCONTACTS_LOG) << "sound differs";
316 return false;
317 }
318
319 if (!listEquals(d->mPhoneNumbers, addressee.d->mPhoneNumbers)) {
320 qCDebug(KCONTACTS_LOG) << "phoneNumbers differs";
321 return false;
322 }
323
324 if (!listEquals(d->mAddresses, addressee.d->mAddresses)) {
325 qCDebug(KCONTACTS_LOG) << "addresses differs";
326 return false;
327 }
328
329 if (!listEquals(d->mKeys, addressee.d->mKeys)) {
330 qCDebug(KCONTACTS_LOG) << "keys differs";
331 return false;
332 }
333 if (!listEquals(d->mEmails, addressee.d->mEmails)) {
334 qCDebug(KCONTACTS_LOG) << "emails differs";
335 return false;
336 }
337
338 if (!listEquals(d->mCategories, addressee.d->mCategories)) {
339 qCDebug(KCONTACTS_LOG) << "categories differs";
340 return false;
341 }
342
343 if (d->mCustomFields != addressee.d->mCustomFields) {
344 qCDebug(KCONTACTS_LOG) << "custom differs";
345 return false;
346 }
347 if (d->mLangs != addressee.d->mLangs) {
348 qCDebug(KCONTACTS_LOG) << "langs differs";
349 return false;
350 }
351 if (d->mImpps != addressee.d->mImpps) {
352 qCDebug(KCONTACTS_LOG) << "impps differs";
353 return false;
354 }
355 if (d->mGender != addressee.d->mGender) {
356 qCDebug(KCONTACTS_LOG) << "gender differs";
357 return false;
358 }
359 if (d->mKind != addressee.d->mKind) {
360 qCDebug(KCONTACTS_LOG) << "kind differs";
361 return false;
362 }
363 if (!listEquals(d->mCalendarUrl, addressee.d->mCalendarUrl)) {
364 qCDebug(KCONTACTS_LOG) << "calendarUrl differs";
365 return false;
366 }
367 if (!listEquals(d->mSoundListExtra, addressee.d->mSoundListExtra)) {
368 qCDebug(KCONTACTS_LOG) << "Extra sound differs";
369 return false;
370 }
371 if (!listEquals(d->mPhotoExtraList, addressee.d->mPhotoExtraList)) {
372 qCDebug(KCONTACTS_LOG) << "Extra photo differs";
373 return false;
374 }
375 if (!listEquals(d->mLogoExtraList, addressee.d->mLogoExtraList)) {
376 qCDebug(KCONTACTS_LOG) << "Extra logo differs";
377 return false;
378 }
379 if (!listEquals(d->mUrlExtraList, addressee.d->mUrlExtraList)) {
380 qCDebug(KCONTACTS_LOG) << "Extra url differs";
381 return false;
382 }
383 if (!listEquals(d->mMembers, addressee.d->mMembers)) {
384 qCDebug(KCONTACTS_LOG) << "Extra url differs";
385 return false;
386 }
387 if (!listEquals(d->mRelationships, addressee.d->mRelationships)) {
388 qCDebug(KCONTACTS_LOG) << "Relationships differs";
389 return false;
390 }
391 if (!listEquals(d->mSources, addressee.d->mSources)) {
392 qCDebug(KCONTACTS_LOG) << "Sources differs";
393 return false;
394 }
395
396 if (!listEquals(d->mFieldGroupList, addressee.d->mFieldGroupList)) {
397 qCDebug(KCONTACTS_LOG) << "Field Groups differs";
398 return false;
399 }
400
401 if (!listEquals(d->mTitleExtraList, addressee.d->mTitleExtraList)) {
402 qCDebug(KCONTACTS_LOG) << "Extra TitleList differs";
403 return false;
404 }
405
406 if (!listEquals(d->mRoleExtraList, addressee.d->mRoleExtraList)) {
407 qCDebug(KCONTACTS_LOG) << "Extra RoleList differs";
408 return false;
409 }
410
411 if (!listEquals(d->mOrgExtraList, addressee.d->mOrgExtraList)) {
412 qCDebug(KCONTACTS_LOG) << "Extra Organization List differs";
413 return false;
414 }
415
416 if (!listEquals(d->mNickNameExtraList, addressee.d->mNickNameExtraList)) {
417 qCDebug(KCONTACTS_LOG) << "Extra NickName List differs";
418 return false;
419 }
420
421 if (!listEquals(d->mClientPidMapList, addressee.d->mClientPidMapList)) {
422 qCDebug(KCONTACTS_LOG) << "ClientPidMap List differs";
423 return false;
424 }
425 return true;
426}
427
429{
430 return !(a == *this);
431}
432
433bool Addressee::isEmpty() const
434{
435 return d->mEmpty;
436}
437
439{
440 if (id == d->mUid) {
441 return;
442 }
443
444 d->mEmpty = false;
445 d->mUid = id;
446}
447
448QString Addressee::uid() const
449{
450 return d->mUid;
451}
452
454{
455 return i18n("Unique Identifier");
456}
457
459{
460 if (name == d->mName) {
461 return;
462 }
463
464 d->mEmpty = false;
465 d->mName = name;
466}
467
468QString Addressee::name() const
469{
470 return d->mName;
471}
472
474{
475 return i18n("Name");
476}
477
478void Addressee::setKind(const QString &kind)
479{
480 if (kind == d->mKind) {
481 return;
482 }
483
484 d->mEmpty = false;
485 d->mKind = kind;
486}
487
488QString Addressee::kind() const
489{
490 return d->mKind;
491}
492
493void Addressee::insertExtraSound(const Sound &sound)
494{
495 d->mEmpty = false;
496 d->mSoundListExtra.append(sound);
497}
498
499Sound::List Addressee::extraSoundList() const
500{
501 return d->mSoundListExtra;
502}
503
504void Addressee::insertExtraPhoto(const Picture &picture)
505{
506 d->mEmpty = false;
507 d->mPhotoExtraList.append(picture);
508}
509
510Picture::List Addressee::extraPhotoList() const
511{
512 return d->mPhotoExtraList;
513}
514
515void Addressee::insertExtraLogo(const Picture &logo)
516{
517 d->mEmpty = false;
518 d->mLogoExtraList.append(logo);
519}
520
521Picture::List Addressee::extraLogoList() const
522{
523 return d->mLogoExtraList;
524}
525
526void Addressee::setExtraSoundList(const Sound::List &soundList)
527{
528 d->mEmpty = false;
529 d->mSoundListExtra = soundList;
530}
531
532void Addressee::setExtraPhotoList(const Picture::List &pictureList)
533{
534 d->mEmpty = false;
535 d->mPhotoExtraList = pictureList;
536}
537
538void Addressee::setExtraLogoList(const Picture::List &logoList)
539{
540 d->mEmpty = false;
541 d->mLogoExtraList = logoList;
542}
543
544void Addressee::insertExtraUrl(const ResourceLocatorUrl &url)
545{
546 if (url.isValid()) {
547 d->mEmpty = false;
548 d->mUrlExtraList.append(url);
549 }
550}
551
552void Addressee::setExtraUrlList(const ResourceLocatorUrl::List &urlList)
553{
554 d->mEmpty = false;
555 d->mUrlExtraList = urlList;
556}
557
558ResourceLocatorUrl::List Addressee::extraUrlList() const
559{
560 return d->mUrlExtraList;
561}
562
563void Addressee::insertSourceUrl(const QUrl &url)
564{
565 d->mEmpty = false;
566 d->mSources.append(url);
567}
568
569void Addressee::setSourcesUrlList(const QList<QUrl> &urlList)
570{
571 d->mEmpty = false;
572 d->mSources = urlList;
573}
574
575QList<QUrl> Addressee::sourcesUrlList() const
576{
577 return d->mSources;
578}
579
580FieldGroup::List Addressee::fieldGroupList() const
581{
582 return d->mFieldGroupList;
583}
584
585void Addressee::setFieldGroupList(const FieldGroup::List &fieldGroupList)
586{
587 d->mEmpty = false;
588 d->mFieldGroupList = fieldGroupList;
589}
590
591void Addressee::insertFieldGroup(const FieldGroup &fieldGroup)
592{
593 if (fieldGroup.isValid()) {
594 d->mEmpty = false;
595 // TODO don't duplicate ?
596 d->mFieldGroupList.append(fieldGroup);
597 }
598}
599
600ClientPidMap::List Addressee::clientPidMapList() const
601{
602 return d->mClientPidMapList;
603}
604
605void Addressee::setClientPidMapList(const ClientPidMap::List &clientpidmaplist)
606{
607 d->mEmpty = false;
608 d->mClientPidMapList = clientpidmaplist;
609}
610
611void Addressee::insertClientPidMap(const ClientPidMap &clientpidmap)
612{
613 if (clientpidmap.isValid()) {
614 d->mEmpty = false;
615 // TODO don't duplicate ?
616 d->mClientPidMapList.append(clientpidmap);
617 }
618}
619
620void Addressee::insertImpp(const Impp &impp)
621{
622 if (impp.isValid()) {
623 d->mEmpty = false;
624 // Don't duplicate ?
625 d->mImpps.append(impp);
626 }
627}
628
629void Addressee::setImppList(const Impp::List &imppList)
630{
631 d->mEmpty = false;
632 d->mImpps = imppList;
633}
634
635Impp::List Addressee::imppList() const
636{
637 return d->mImpps;
638}
639
640void Addressee::insertCalendarUrl(const CalendarUrl &calendarUrl)
641{
642 d->mEmpty = false;
643 // TODO verify that there is not same calendarurl
644 if (calendarUrl.isValid()) {
645 d->mCalendarUrl.append(calendarUrl);
646 }
647}
648
649CalendarUrl::List Addressee::calendarUrlList() const
650{
651 return d->mCalendarUrl;
652}
653
654void Addressee::setFormattedName(const QString &formattedName)
655{
656 if (formattedName == d->mFormattedName) {
657 return;
658 }
659
660 d->mEmpty = false;
661 d->mFormattedName = formattedName;
662}
663
664QString Addressee::formattedName() const
665{
666 return d->mFormattedName;
667}
668
670{
671 return i18n("Formatted Name");
672}
673
674void Addressee::setFamilyName(const QString &familyName)
675{
676 if (familyName == d->mFamilyName) {
677 return;
678 }
679
680 d->mEmpty = false;
681 d->mFamilyName = familyName;
682}
683
684QString Addressee::familyName() const
685{
686 return d->mFamilyName;
687}
688
690{
691 return i18n("Family Name");
692}
693
694void Addressee::setGivenName(const QString &givenName)
695{
696 if (givenName == d->mGivenName) {
697 return;
698 }
699
700 d->mEmpty = false;
701 d->mGivenName = givenName;
702}
703
704QString Addressee::givenName() const
705{
706 return d->mGivenName;
707}
708
710{
711 return i18n("Given Name");
712}
713
714void Addressee::setAdditionalName(const QString &additionalName)
715{
716 if (additionalName == d->mAdditionalName) {
717 return;
718 }
719
720 d->mEmpty = false;
721 d->mAdditionalName = additionalName;
722}
723
724QString Addressee::additionalName() const
725{
726 return d->mAdditionalName;
727}
728
730{
731 return i18n("Additional Names");
732}
733
734void Addressee::setPrefix(const QString &prefix)
735{
736 if (prefix == d->mPrefix) {
737 return;
738 }
739
740 d->mEmpty = false;
741 d->mPrefix = prefix;
742}
743
744QString Addressee::prefix() const
745{
746 return d->mPrefix;
747}
748
750{
751 return i18n("Honorific Prefixes");
752}
753
754void Addressee::setSuffix(const QString &suffix)
755{
756 if (suffix == d->mSuffix) {
757 return;
758 }
759
760 d->mEmpty = false;
761 d->mSuffix = suffix;
762}
763
764QString Addressee::suffix() const
765{
766 return d->mSuffix;
767}
768
770{
771 return i18n("Honorific Suffixes");
772}
773
774void Addressee::setNickName(const QString &nickName)
775{
776 NickName t(nickName);
777 if (!d->mNickNameExtraList.isEmpty()) {
778 t = d->mNickNameExtraList.takeFirst();
779 t.setNickName(nickName);
780 d->mNickNameExtraList.prepend(t);
781 d->mEmpty = false;
782 } else {
783 insertExtraNickName(t);
784 }
785}
786
787void Addressee::setNickName(const NickName &nickName)
788{
789 insertExtraNickName(nickName);
790}
791
792void Addressee::insertExtraNickName(const NickName &nickName)
793{
794 if (nickName.isValid()) {
795 d->mEmpty = false;
796 d->mNickNameExtraList.append(nickName);
797 }
798}
799
800void Addressee::setExtraNickNameList(const NickName::List &nickNameList)
801{
802 d->mEmpty = false;
803 d->mNickNameExtraList = nickNameList;
804}
805
806NickName::List Addressee::extraNickNameList() const
807{
808 return d->mNickNameExtraList;
809}
810
811QString Addressee::nickName() const
812{
813 if (d->mNickNameExtraList.isEmpty()) {
814 return {};
815 } else {
816 return d->mNickNameExtraList.at(0).nickname();
817 }
818}
819
821{
822 return i18n("Nick Name");
823}
824
825void Addressee::setBirthday(const QDateTime &birthday, bool withTime)
826{
827 if (birthday == d->mBirthday && d->mBirthdayWithTime == withTime) {
828 return;
829 }
830
831 d->mEmpty = false;
832 d->mBirthday = birthday;
833 if (!withTime) {
834 d->mBirthday.setTime(QTime());
835 }
836 d->mBirthdayWithTime = withTime;
837}
838
839void Addressee::setBirthday(const QDate &birthday)
840{
841 if (birthday == d->mBirthday.date() && !d->mBirthdayWithTime) {
842 return;
843 }
844
845 d->mEmpty = false;
846 d->mBirthday = QDateTime(birthday, QTime());
847 d->mBirthdayWithTime = false;
848}
849
850QDateTime Addressee::birthday() const
851{
852 return d->mBirthday;
853}
854
855bool Addressee::birthdayHasTime() const
856{
857 return d->mBirthdayWithTime;
858}
859
861{
862 return i18n("Birthday");
863}
864
866{
867 return i18n("Home Address Street");
868}
869
871{
872 return i18n("Home Address Post Office Box");
873}
874
876{
877 return i18n("Home Address City");
878}
879
881{
882 return i18n("Home Address State");
883}
884
886{
887 return i18n("Home Address Zip Code");
888}
889
891{
892 return i18n("Home Address Country");
893}
894
896{
897 return i18n("Home Address Label");
898}
899
901{
902 return i18n("Business Address Street");
903}
904
906{
907 return i18n("Business Address Post Office Box");
908}
909
911{
912 return i18n("Business Address City");
913}
914
916{
917 return i18n("Business Address State");
918}
919
921{
922 return i18n("Business Address Zip Code");
923}
924
926{
927 return i18n("Business Address Country");
928}
929
931{
932 return i18n("Business Address Label");
933}
934
936{
937 return i18n("Home Phone");
938}
939
941{
942 return i18n("Business Phone");
943}
944
946{
947 return i18n("Mobile Phone");
948}
949
951{
952 return i18n("Home Fax");
953}
954
956{
957 return i18n("Business Fax");
958}
959
961{
962 return i18n("Car Phone");
963}
964
966{
967 return i18n("ISDN");
968}
969
971{
972 return i18n("Pager");
973}
974
976{
977 return i18n("Email Address");
978}
979
980void Addressee::setMailer(const QString &mailer)
981{
982 if (mailer == d->mMailer) {
983 return;
984 }
985
986 d->mEmpty = false;
987 d->mMailer = mailer;
988}
989
990QString Addressee::mailer() const
991{
992 return d->mMailer;
993}
994
996{
997 return i18n("Mail Client");
998}
999
1001{
1002 if (timeZone == d->mTimeZone) {
1003 return;
1004 }
1005
1006 d->mEmpty = false;
1007 d->mTimeZone = timeZone;
1008}
1009
1011{
1012 return d->mTimeZone;
1013}
1014
1016{
1017 return i18n("Time Zone");
1018}
1019
1020void Addressee::setGeo(const Geo &geo)
1021{
1022 if (geo == d->mGeo) {
1023 return;
1024 }
1025
1026 d->mEmpty = false;
1027 d->mGeo = geo;
1028}
1029
1030Geo Addressee::geo() const
1031{
1032 return d->mGeo;
1033}
1034
1036{
1037 return i18n("Geographic Position");
1038}
1039
1041{
1042 Title t(title);
1043 if (!d->mTitleExtraList.isEmpty()) {
1044 t = d->mTitleExtraList.takeFirst();
1045 t.setTitle(title);
1046 d->mTitleExtraList.prepend(t);
1047 d->mEmpty = false;
1048 } else {
1049 insertExtraTitle(title);
1050 }
1051}
1052
1053void Addressee::setTitle(const Title &title)
1054{
1055 insertExtraTitle(title);
1056}
1057
1058void Addressee::insertExtraTitle(const Title &title)
1059{
1060 if (title.isValid()) {
1061 d->mEmpty = false;
1062 d->mTitleExtraList.append(title);
1063 }
1064}
1065
1066QString Addressee::title() const
1067{
1068 if (d->mTitleExtraList.isEmpty()) {
1069 return {};
1070 } else {
1071 return d->mTitleExtraList.at(0).title();
1072 }
1073}
1074
1075Title::List Addressee::extraTitleList() const
1076{
1077 return d->mTitleExtraList;
1078}
1079
1080void Addressee::setExtraTitleList(const Title::List &urltitle)
1081{
1082 d->mEmpty = false;
1083 d->mTitleExtraList = urltitle;
1084}
1085
1087{
1088 return i18nc("a person's title", "Title");
1089}
1090
1092{
1093 Role t(role);
1094 if (!d->mRoleExtraList.isEmpty()) {
1095 t = d->mRoleExtraList.takeFirst();
1096 t.setRole(role);
1097 d->mRoleExtraList.prepend(t);
1098 d->mEmpty = false;
1099 } else {
1100 insertExtraRole(t);
1101 }
1102}
1103
1104void Addressee::setRole(const Role &role)
1105{
1106 insertExtraRole(role);
1107}
1108
1109void Addressee::insertExtraRole(const Role &role)
1110{
1111 if (role.isValid()) {
1112 d->mEmpty = false;
1113 d->mRoleExtraList.append(role);
1114 }
1115}
1116
1117void Addressee::setExtraRoleList(const Role::List &roleList)
1118{
1119 d->mEmpty = false;
1120 d->mRoleExtraList = roleList;
1121}
1122
1123Role::List Addressee::extraRoleList() const
1124{
1125 return d->mRoleExtraList;
1126}
1127
1128QString Addressee::role() const
1129{
1130 if (d->mRoleExtraList.isEmpty()) {
1131 return {};
1132 } else {
1133 return d->mRoleExtraList.at(0).role();
1134 }
1135}
1136
1138{
1139 return i18nc("of a person in an organization", "Role");
1140}
1141
1142void Addressee::setOrganization(const QString &organization)
1143{
1144 Org t(organization);
1145 if (!d->mOrgExtraList.isEmpty()) {
1146 t = d->mOrgExtraList.takeFirst();
1147 t.setOrganization(organization);
1148 d->mOrgExtraList.prepend(t);
1149 d->mEmpty = false;
1150 } else {
1151 insertExtraOrganization(t);
1152 }
1153}
1154
1155void Addressee::setOrganization(const Org &organization)
1156{
1157 insertExtraOrganization(organization);
1158}
1159
1160void Addressee::insertExtraOrganization(const Org &organization)
1161{
1162 if (organization.isValid()) {
1163 d->mEmpty = false;
1164 d->mOrgExtraList.append(organization);
1165 }
1166}
1167
1168void Addressee::setExtraOrganizationList(const Org::List &orgList)
1169{
1170 d->mEmpty = false;
1171 d->mOrgExtraList = orgList;
1172}
1173
1174Org::List Addressee::extraOrganizationList() const
1175{
1176 return d->mOrgExtraList;
1177}
1178
1179QString Addressee::organization() const
1180{
1181 if (d->mOrgExtraList.isEmpty()) {
1182 return {};
1183 } else {
1184 return d->mOrgExtraList.at(0).organization();
1185 }
1186}
1187
1189{
1190 return i18n("Organization");
1191}
1192
1193void Addressee::setDepartment(const QString &department)
1194{
1195 if (department == d->mDepartment) {
1196 return;
1197 }
1198
1199 d->mEmpty = false;
1200 d->mDepartment = department;
1201}
1202
1203QString Addressee::department() const
1204{
1205 return d->mDepartment;
1206}
1207
1209{
1210 return i18n("Department");
1211}
1212
1214{
1215 if (note == d->mNote) {
1216 return;
1217 }
1218
1219 d->mEmpty = false;
1220 d->mNote = note;
1221}
1222
1223QString Addressee::note() const
1224{
1225 return d->mNote;
1226}
1227
1229{
1230 return i18n("Note");
1231}
1232
1233void Addressee::setProductId(const QString &productId)
1234{
1235 if (productId == d->mProductId) {
1236 return;
1237 }
1238
1239 d->mEmpty = false;
1240 d->mProductId = productId;
1241}
1242
1243QString Addressee::productId() const
1244{
1245 return d->mProductId;
1246}
1247
1249{
1250 return i18n("Product Identifier");
1251}
1252
1254{
1255 if (revision == d->mRevision) {
1256 return;
1257 }
1258
1259 d->mEmpty = false;
1260 d->mRevision = revision;
1261}
1262
1263QDateTime Addressee::revision() const
1264{
1265 return d->mRevision;
1266}
1267
1269{
1270 return i18n("Revision Date");
1271}
1272
1273void Addressee::setSortString(const QString &sortString)
1274{
1275 if (sortString == d->mSortString) {
1276 return;
1277 }
1278
1279 d->mEmpty = false;
1280 d->mSortString = sortString;
1281}
1282
1283QString Addressee::sortString() const
1284{
1285 return d->mSortString;
1286}
1287
1289{
1290 return i18n("Sort String");
1291}
1292
1293void Addressee::setUrl(const QUrl &url)
1294{
1295 KContacts::ResourceLocatorUrl resourceLocator;
1296 resourceLocator.setUrl(url);
1297 insertExtraUrl(resourceLocator);
1298}
1299
1301{
1302 insertExtraUrl(url);
1303}
1304
1305ResourceLocatorUrl Addressee::url() const
1306{
1307 if (d->mUrlExtraList.isEmpty()) {
1308 return ResourceLocatorUrl();
1309 } else {
1310 return d->mUrlExtraList.at(0);
1311 }
1312}
1313
1315{
1316 return i18n("Homepage");
1317}
1318
1319void Addressee::setSecrecy(const Secrecy &secrecy)
1320{
1321 if (secrecy == d->mSecrecy) {
1322 return;
1323 }
1324
1325 d->mEmpty = false;
1326 d->mSecrecy = secrecy;
1327}
1328
1330{
1331 return d->mSecrecy;
1332}
1333
1335{
1336 return i18n("Security Class");
1337}
1338
1340{
1341 if (logo == d->mLogo) {
1342 return;
1343 }
1344
1345 d->mEmpty = false;
1346 d->mLogo = logo;
1347}
1348
1350{
1351 return d->mLogo;
1352}
1353
1355{
1356 return i18n("Logo");
1357}
1358
1360{
1361 if (photo == d->mPhoto) {
1362 return;
1363 }
1364
1365 d->mEmpty = false;
1366 d->mPhoto = photo;
1367}
1368
1369Picture Addressee::photo() const
1370{
1371 return d->mPhoto;
1372}
1373
1375{
1376 return i18n("Photo");
1377}
1378
1379void Addressee::setSound(const Sound &sound)
1380{
1381 if (sound == d->mSound) {
1382 return;
1383 }
1384
1385 d->mEmpty = false;
1386 d->mSound = sound;
1387}
1388
1390{
1391 return d->mSound;
1392}
1393
1395{
1396 return i18n("Sound");
1397}
1398
1400{
1401 QString str = s;
1402 // remove enclosing quotes from string
1403 if (str.length() > 1 && s[0] == QLatin1Char('"') && s[s.length() - 1] == QLatin1Char('"')) {
1404 str = s.mid(1, s.length() - 2);
1405 }
1406
1407 setFormattedName(str);
1408 setName(str);
1409
1410 // clear all name parts
1411 setPrefix(QString());
1415 setSuffix(QString());
1416
1417 if (str.isEmpty()) {
1418 return;
1419 }
1420
1421 static QString spaceStr = QStringLiteral(" ");
1422 static QString emptyStr = QStringLiteral("");
1423 AddresseeHelper *helper = AddresseeHelper::self();
1424
1425 int i = str.indexOf(QLatin1Char(','));
1426 if (i < 0) {
1427 QStringList parts = str.split(spaceStr);
1428 int leftOffset = 0;
1429 int rightOffset = parts.count() - 1;
1430
1431 QString suffix;
1432 while (rightOffset >= 0) {
1433 if (helper->containsSuffix(parts[rightOffset])) {
1434 suffix.prepend(parts[rightOffset] + (suffix.isEmpty() ? emptyStr : spaceStr));
1435 rightOffset--;
1436 } else {
1437 break;
1438 }
1439 }
1440 setSuffix(suffix);
1441
1442 if (rightOffset < 0) {
1443 return;
1444 }
1445
1446 if (rightOffset - 1 >= 0 && helper->containsPrefix(parts[rightOffset - 1].toLower())) {
1447 setFamilyName(parts[rightOffset - 1] + spaceStr + parts[rightOffset]);
1448 rightOffset--;
1449 } else {
1450 if (helper->treatAsFamilyName()) {
1451 setFamilyName(parts[rightOffset]);
1452 } else {
1453 setGivenName(parts[rightOffset]);
1454 }
1455 }
1456
1457 QString prefix;
1458 while (leftOffset < rightOffset) {
1459 if (helper->containsTitle(parts[leftOffset])) {
1460 prefix.append((prefix.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
1461 leftOffset++;
1462 } else {
1463 break;
1464 }
1465 }
1466 setPrefix(prefix);
1467
1468 if (leftOffset < rightOffset) {
1469 setGivenName(parts[leftOffset]);
1470 leftOffset++;
1471 }
1472
1473 QString additionalName;
1474 while (leftOffset < rightOffset) {
1475 additionalName.append((additionalName.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
1476 leftOffset++;
1477 }
1478 setAdditionalName(additionalName);
1479 } else {
1480 QString part1 = str.left(i);
1481 QString part2 = str.mid(i + 1);
1482
1483 QStringList parts = part1.split(spaceStr);
1484 int leftOffset = 0;
1485 int rightOffset = parts.count() - 1;
1486
1487 if (!parts.isEmpty()) {
1488 QString suffix;
1489 while (rightOffset >= 0) {
1490 if (helper->containsSuffix(parts[rightOffset])) {
1491 suffix.prepend(parts[rightOffset] + (suffix.isEmpty() ? emptyStr : spaceStr));
1492 rightOffset--;
1493 } else {
1494 break;
1495 }
1496 }
1497 setSuffix(suffix);
1498
1499 if (rightOffset - 1 >= 0 && helper->containsPrefix(parts[rightOffset - 1].toLower())) {
1500 setFamilyName(parts[rightOffset - 1] + spaceStr + parts[rightOffset]);
1501 rightOffset--;
1502 } else {
1503 setFamilyName(parts[rightOffset]);
1504 }
1505
1506 QString prefix;
1507 while (leftOffset < rightOffset) {
1508 if (helper->containsTitle(parts[leftOffset])) {
1509 prefix.append((prefix.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
1510 leftOffset++;
1511 } else {
1512 break;
1513 }
1514 }
1515 } else {
1516 setPrefix(QString());
1518 setSuffix(QString());
1519 }
1520
1521 parts = part2.split(spaceStr);
1522
1523 leftOffset = 0;
1524 rightOffset = parts.count();
1525
1526 if (!parts.isEmpty()) {
1527 QString prefix;
1528 while (leftOffset < rightOffset) {
1529 if (helper->containsTitle(parts[leftOffset])) {
1530 prefix.append((prefix.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
1531 leftOffset++;
1532 } else {
1533 break;
1534 }
1535 }
1536 setPrefix(prefix);
1537
1538 if (leftOffset < rightOffset) {
1539 setGivenName(parts[leftOffset]);
1540 leftOffset++;
1541 }
1542
1543 QString additionalName;
1544 while (leftOffset < rightOffset) {
1545 additionalName.append((additionalName.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
1546 leftOffset++;
1547 }
1548 setAdditionalName(additionalName);
1549 } else {
1552 }
1553 }
1554}
1555
1556QString Addressee::realName() const
1557{
1558 QString n(formattedName());
1559 if (!n.isEmpty()) {
1560 return n;
1561 }
1562
1563 n = assembledName();
1564 if (!n.isEmpty()) {
1565 return n;
1566 }
1567
1568 n = name();
1569 if (!n.isEmpty()) {
1570 return n;
1571 }
1572
1573 return organization();
1574}
1575
1576QString Addressee::assembledName() const
1577{
1578 // clang-format off
1579 const QString name = prefix() + QLatin1Char(' ')
1580 + givenName() + QLatin1Char(' ')
1581 + additionalName() + QLatin1Char(' ')
1582 + familyName() + QLatin1Char(' ')
1583 + suffix();
1584 // clang-format on
1585
1586 return name.simplified();
1587}
1588
1590{
1591 QString e;
1592 if (email.isNull()) {
1593 e = preferredEmail();
1594 } else {
1595 e = email;
1596 }
1597 if (e.isEmpty()) {
1598 return QString();
1599 }
1600
1601 QString text;
1602 if (realName().isEmpty()) {
1603 text = e;
1604 } else {
1605 QRegularExpression needQuotes(QStringLiteral("[^ 0-9A-Za-z\\x{0080}-\\x{FFFF}]"));
1606 if (realName().indexOf(needQuotes) != -1) {
1607 QString name = realName();
1608 name.replace(QLatin1String("\""), QLatin1String("\\\""));
1609 text = QLatin1String("\"") + name + QLatin1String("\" <") + e + QLatin1Char('>');
1610 } else {
1611 text = realName() + QLatin1String(" <") + e + QLatin1Char('>');
1612 }
1613 }
1614
1615 return text;
1616}
1617
1618void Addressee::addEmail(const Email &email)
1619{
1620 const QString mailAddr = email.mail();
1621 auto it = std::find_if(d->mEmails.begin(), d->mEmails.end(), [&mailAddr](const Email &e) {
1622 return e.mail() == mailAddr;
1623 });
1624 if (it != d->mEmails.end()) { // Already exists, modify it
1625 *it = email;
1626 if (email.isPreferred()) {
1627 // Move it to the beginning of mEmails
1628 std::rotate(d->mEmails.begin(), it, it + 1);
1629 }
1630 return;
1631 }
1632
1633 // Add it to the list
1634 d->mEmpty = false;
1635 if (email.isPreferred()) {
1636 d->mEmails.prepend(email);
1637 } else {
1638 d->mEmails.append(email);
1639 }
1640}
1641
1643{
1644 for (int i = 0; i < d->mEmails.size(); ++i) {
1645 if (d->mEmails.at(i).mail() == email) {
1646 d->mEmails.removeAt(i);
1647 }
1648 }
1649}
1650
1651QString Addressee::preferredEmail() const
1652{
1653 if (d->mEmails.isEmpty()) {
1654 return QString();
1655 } else {
1656 return d->mEmails.first().mail();
1657 }
1658}
1659
1660QStringList Addressee::emails() const
1661{
1662 QStringList list;
1663 const int numberOfEmail = d->mEmails.size();
1664 list.reserve(numberOfEmail);
1665 for (int i = 0; i < numberOfEmail; ++i) {
1666 list << d->mEmails.at(i).mail();
1667 }
1668
1669 return list;
1670}
1671
1672Email::List Addressee::emailList() const
1673{
1674 return d->mEmails;
1675}
1676
1678{
1679 d->mEmails.clear();
1680 const int numEmails = emails.size();
1681 d->mEmails.reserve(numEmails);
1682 for (int i = 0; i < numEmails; ++i) {
1683 d->mEmails.append(Email(emails.at(i)));
1684 }
1685 d->mEmpty = false;
1686}
1687
1688void Addressee::setEmailList(const Email::List &list)
1689{
1690 d->mEmails = list;
1691 d->mEmpty = false;
1692}
1693
1694void Addressee::removeLang(const QString &language)
1695{
1696 for (int i = 0; i < d->mLangs.size(); ++i) {
1697 if (d->mLangs.at(i).language() == language) {
1698 d->mLangs.removeAt(i);
1699 }
1700 }
1701}
1702
1703void Addressee::setLangs(const Lang::List &langs)
1704{
1705 d->mLangs = langs;
1706 d->mEmpty = false;
1707}
1708
1709void Addressee::insertLang(const Lang &language)
1710{
1711 const QString languageStr = language.language();
1712 if (languageStr.simplified().isEmpty()) {
1713 return;
1714 }
1715 d->mEmpty = false;
1716
1717 auto it = std::find_if(d->mLangs.begin(), d->mLangs.end(), [&languageStr](const Lang &lang) {
1718 return lang.language() == languageStr;
1719 });
1720 if (it != d->mLangs.end()) {
1721 (*it).setParams(language.params());
1722 return;
1723 }
1724
1725 d->mLangs.append(language);
1726}
1727
1729{
1730 return d->mLangs;
1731}
1732
1733void Addressee::setGender(const Gender &gender)
1734{
1735 if (gender == d->mGender) {
1736 return;
1737 }
1738
1739 d->mEmpty = false;
1740 d->mGender = gender;
1741}
1742
1743Gender Addressee::gender() const
1744{
1745 return d->mGender;
1746}
1747
1749{
1750 d->mEmpty = false;
1751
1752 auto it = std::find_if(d->mPhoneNumbers.begin(), d->mPhoneNumbers.end(), [&phoneNumber](const PhoneNumber &pNumber) {
1753 return pNumber.id() == phoneNumber.id();
1754 });
1755 if (it != d->mPhoneNumbers.end()) {
1756 *it = phoneNumber;
1757 return;
1758 }
1759
1760 if (!phoneNumber.number().simplified().isEmpty()) {
1761 d->mPhoneNumbers.append(phoneNumber);
1762 }
1763}
1764
1766{
1767 auto it = std::find_if(d->mPhoneNumbers.begin(), d->mPhoneNumbers.end(), [&phoneNumber](const PhoneNumber &p) {
1768 return p.id() == phoneNumber.id();
1769 });
1770
1771 if (it != d->mPhoneNumbers.end()) {
1772 d->mPhoneNumbers.erase(it);
1773 }
1774}
1775
1777{
1779
1780 for (const PhoneNumber &phone : d->mPhoneNumbers) {
1781 if (matchBinaryPattern(phone.type(), type)) {
1782 if (phone.type() & PhoneNumber::Pref) {
1783 return phone;
1784 } else if (phoneNumber.number().isEmpty()) {
1785 phoneNumber = phone;
1786 }
1787 }
1788 }
1789
1790 return phoneNumber;
1791}
1792
1793PhoneNumber::List Addressee::phoneNumbers() const
1794{
1795 return d->mPhoneNumbers;
1796}
1797
1798void Addressee::setPhoneNumbers(const PhoneNumber::List &phoneNumbers)
1799{
1800 d->mEmpty = false;
1801 d->mPhoneNumbers.clear();
1802 d->mPhoneNumbers = phoneNumbers;
1803}
1804
1805PhoneNumber::List Addressee::phoneNumbers(PhoneNumber::Type type) const
1806{
1807 PhoneNumber::List list;
1808
1809 std::copy_if(d->mPhoneNumbers.cbegin(), d->mPhoneNumbers.cend(), std::back_inserter(list), [type](const auto &phone) {
1810 return matchBinaryPattern(phone.type(), type);
1811 });
1812 return list;
1813}
1814
1816{
1817 auto it = std::find_if(d->mPhoneNumbers.cbegin(), d->mPhoneNumbers.cend(), [&id](const PhoneNumber &phone) {
1818 return phone.id() == id;
1819 });
1820
1821 return it != d->mPhoneNumbers.cend() ? *it : PhoneNumber{};
1822}
1823
1825{
1826 d->mEmpty = false;
1827
1828 auto it = std::find_if(d->mKeys.begin(), d->mKeys.end(), [&key](Key &existing) {
1829 return existing.id() == key.id();
1830 });
1831 if (it != d->mKeys.end()) {
1832 *it = key;
1833 } else {
1834 d->mKeys.append(key);
1835 }
1836}
1837
1839{
1840 auto it = std::remove_if(d->mKeys.begin(), d->mKeys.end(), [&key](const Key &k) {
1841 return k.id() == key.id();
1842 });
1843 d->mKeys.erase(it, d->mKeys.end());
1844}
1845
1846Key Addressee::key(Key::Type type, const QString &customTypeString) const
1847{
1848 for (const auto &key : d->mKeys) {
1849 if (key.type() == type) {
1850 if (type == Key::Custom) {
1851 if (customTypeString.isEmpty()) {
1852 return key;
1853 } else {
1854 if (key.customTypeString() == customTypeString) {
1855 return key;
1856 }
1857 }
1858 } else {
1859 return key;
1860 }
1861 }
1862 }
1863 return Key(QString(), type);
1864}
1865
1867{
1868 d->mKeys = list;
1869 d->mEmpty = false;
1870}
1871
1873{
1874 return d->mKeys;
1875}
1876
1877Key::List Addressee::keys(Key::Type type, const QString &customTypeString) const
1878{
1879 Key::List list;
1880 auto matchFunc = [type, &customTypeString](const Key &key) {
1881 if (key.type() == type) {
1882 if (type == Key::Custom) {
1883 if (customTypeString.isEmpty()) {
1884 return true;
1885 } else {
1886 if (key.customTypeString() == customTypeString) {
1887 return true;
1888 }
1889 }
1890 } else {
1891 return true;
1892 }
1893 }
1894 return false;
1895 };
1896
1897 std::copy_if(d->mKeys.cbegin(), d->mKeys.cend(), std::back_inserter(list), matchFunc);
1898
1899 return list;
1900}
1901
1903{
1904 auto it = std::find_if(d->mKeys.cbegin(), d->mKeys.cend(), [&id](const Key &key) {
1905 return key.id() == id;
1906 });
1907
1908 return it != d->mKeys.cend() ? *it : Key{};
1909}
1910
1912{
1913 QString str = QLatin1String("Addressee {\n");
1914 str += QStringLiteral(" Uid: %1\n").arg(uid());
1915
1916 str += QStringLiteral(" Name: %1\n").arg(name());
1917 str += QStringLiteral(" FormattedName: %1\n").arg(formattedName());
1918 str += QStringLiteral(" FamilyName: %1\n").arg(familyName());
1919 str += QStringLiteral(" GivenName: %1\n").arg(givenName());
1920 str += QStringLiteral(" AdditionalName: %1\n").arg(additionalName());
1921 str += QStringLiteral(" Prefix: %1\n").arg(prefix());
1922 str += QStringLiteral(" Suffix: %1\n").arg(suffix());
1923 str += QStringLiteral(" NickName: %1\n").arg(nickName());
1924 str += QStringLiteral(" Birthday: %1\n").arg(birthday().toString());
1925 str += QStringLiteral(" Mailer: %1\n").arg(mailer());
1926 str += QStringLiteral(" TimeZone: %1\n").arg(timeZone().toString());
1927 str += QStringLiteral(" Geo: %1\n").arg(geo().toString());
1928 str += QStringLiteral(" Title: %1\n").arg(title());
1929 str += QStringLiteral(" Role: %1\n").arg(role());
1930 str += QStringLiteral(" Organization: %1\n").arg(organization());
1931 str += QStringLiteral(" Department: %1\n").arg(department());
1932 str += QStringLiteral(" Note: %1\n").arg(note());
1933 str += QStringLiteral(" ProductId: %1\n").arg(productId());
1934 str += QStringLiteral(" Revision: %1\n").arg(revision().toString());
1935 str += QStringLiteral(" SortString: %1\n").arg(sortString());
1936 str += QStringLiteral(" Url: %1\n").arg(url().url().url());
1937 str += QStringLiteral(" Secrecy: %1\n").arg(secrecy().toString());
1938 str += QStringLiteral(" Logo: %1\n").arg(logo().toString());
1939 str += QStringLiteral(" Photo: %1\n").arg(photo().toString());
1940 str += QStringLiteral(" Sound: %1\n").arg(sound().toString());
1941 str += QStringLiteral(" Gender: %1\n").arg(gender().toString());
1942 str += QStringLiteral(" Kind: %1\n").arg(kind());
1943
1944 str += QLatin1String(" Emails {\n");
1945 const Email::List listEmail = d->mEmails;
1946 for (const Email &email : listEmail) {
1947 str += email.toString();
1948 }
1949 str += QLatin1String(" }\n");
1950
1951 str += QLatin1String(" Langs {\n");
1952 const Lang::List listLang = d->mLangs;
1953 for (const Lang &lang : listLang) {
1954 str += lang.toString();
1955 }
1956 str += QLatin1String(" }\n");
1957
1958 str += QLatin1String(" PhoneNumbers {\n");
1959 const PhoneNumber::List phones = phoneNumbers();
1960 for (const auto &p : phones) {
1961 str += p.toString();
1962 }
1963 str += QLatin1String(" }\n");
1964
1965 str += QLatin1String(" Addresses {\n");
1966 const Address::List addrList = addresses();
1967 for (const auto &addr : addrList) {
1968 str += addr.toString();
1969 }
1970 str += QLatin1String(" }\n");
1971
1972 str += QLatin1String(" Keys {\n");
1973 const Key::List keyList = keys();
1974 for (const auto &k : keyList) {
1975 str += k.toString();
1976 }
1977 str += QLatin1String(" }\n");
1978
1979 str += QLatin1String("}\n");
1980
1981 return str;
1982}
1983
1985{
1986 if (address.isEmpty()) {
1987 return;
1988 }
1989
1990 d->mEmpty = false;
1991
1992 auto it = std::find_if(d->mAddresses.begin(), d->mAddresses.end(), [&address](const Address &addr) {
1993 return addr.id() == address.id();
1994 });
1995 if (it != d->mAddresses.end()) {
1996 *it = address;
1997 return;
1998 }
1999
2000 d->mAddresses.append(address);
2001}
2002
2004{
2005 auto it = std::find_if(d->mAddresses.begin(), d->mAddresses.end(), [&address](const Address &addr) {
2006 return addr.id() == address.id();
2007 });
2008 if (it != d->mAddresses.end()) {
2009 d->mAddresses.erase(it);
2010 }
2011}
2012
2014{
2015 d->mEmpty = false;
2016 d->mAddresses = addresses;
2017}
2018
2020{
2021 Address address(type);
2022 for (const Address &addr : d->mAddresses) {
2023 if (matchBinaryPattern(addr.type(), type)) {
2024 if (addr.type() & Address::Pref) {
2025 return addr;
2026 } else if (address.isEmpty()) {
2027 address = addr;
2028 }
2029 }
2030 }
2031
2032 return address;
2033}
2034
2035Address::List Addressee::addresses() const
2036{
2037 return d->mAddresses;
2038}
2039
2040Address::List Addressee::addresses(Address::Type type) const
2041{
2042 Address::List list;
2043
2044 std::copy_if(d->mAddresses.cbegin(), d->mAddresses.cend(), std::back_inserter(list), [type](const Address &addr) {
2045 return matchBinaryPattern(addr.type(), type);
2046 });
2047
2048 return list;
2049}
2050
2052{
2053 auto it = std::find_if(d->mAddresses.cbegin(), d->mAddresses.cend(), [&id](const Address &addr) {
2054 return addr.id() == id;
2055 });
2056 return it != d->mAddresses.cend() ? *it : Address{};
2057}
2058
2060{
2061 d->mEmpty = false;
2062
2063 if (d->mCategories.contains(c)) {
2064 return;
2065 }
2066
2067 d->mCategories.append(c);
2068}
2069
2071{
2072 if (d->mCategories.contains(category)) {
2073 d->mCategories.removeAll(category);
2074 }
2075}
2076
2077bool Addressee::hasCategory(const QString &category) const
2078{
2079 return d->mCategories.contains(category);
2080}
2081
2083{
2084 d->mEmpty = false;
2085
2086 d->mCategories = c;
2087}
2088
2089QStringList Addressee::categories() const
2090{
2091 return d->mCategories;
2092}
2093
2094void Addressee::insertMember(const QString &member)
2095{
2096 d->mEmpty = false;
2097
2098 if (d->mMembers.contains(member)) {
2099 return;
2100 }
2101
2102 d->mMembers.append(member);
2103}
2104
2105void Addressee::setMembers(const QStringList &m)
2106{
2107 d->mEmpty = false;
2108 d->mMembers = m;
2109}
2110
2111QStringList Addressee::members() const
2112{
2113 return d->mMembers;
2114}
2115
2116void Addressee::insertRelationship(const Related &relation)
2117{
2118 d->mEmpty = false;
2119
2120 if (d->mRelationships.contains(relation)) {
2121 return;
2122 }
2123
2124 d->mRelationships.append(relation);
2125}
2126
2127void Addressee::setRelationships(const Related::List &c)
2128{
2129 d->mEmpty = false;
2130 d->mRelationships = c;
2131}
2132
2133Related::List Addressee::relationships() const
2134{
2135 return d->mRelationships;
2136}
2137
2138static const auto VENDOR_ID = QStringLiteral("KADDRESSBOOK");
2139static const auto X_ANNIVERSARY = QStringLiteral("X-Anniversary");
2140static const auto X_ASSISTANTSNAME = QStringLiteral("X-AssistantsName");
2141static const auto BLOGFEED = QStringLiteral("BlogFeed");
2142static const auto X_MANAGERSNAME = QStringLiteral("X-ManagersName");
2143static const auto X_OFFICE = QStringLiteral("X-Office");
2144static const auto X_PROFESSION = QStringLiteral("X-Profession");
2145static const auto X_SPOUSESNAME = QStringLiteral("X-SpousesName");
2146
2147QDate Addressee::anniversary() const
2148{
2149 return QDate::fromString(custom(VENDOR_ID, X_ANNIVERSARY), Qt::ISODate);
2150}
2151
2152void Addressee::setAnniversary(const QDate &anniversary)
2153{
2154 if (anniversary.isValid()) {
2155 insertCustom(VENDOR_ID, X_ANNIVERSARY, anniversary.toString(Qt::ISODate));
2156 } else {
2157 removeCustom(VENDOR_ID, X_ANNIVERSARY);
2158 }
2159}
2160
2161QString Addressee::assistantsName() const
2162{
2163 return custom(VENDOR_ID, X_ASSISTANTSNAME);
2164}
2165
2166void Addressee::setAssistantsName(const QString &assistantsName)
2167{
2168 if (!assistantsName.isEmpty()) {
2169 insertCustom(VENDOR_ID, X_ASSISTANTSNAME, assistantsName);
2170 } else {
2171 removeCustom(VENDOR_ID, X_ASSISTANTSNAME);
2172 }
2173}
2174
2175QUrl Addressee::blogFeed() const
2176{
2177 return QUrl(custom(VENDOR_ID, BLOGFEED));
2178}
2179
2180void Addressee::setBlogFeed(const QUrl &blogFeed)
2181{
2182 if (!blogFeed.isEmpty()) {
2183 insertCustom(VENDOR_ID, BLOGFEED, blogFeed.url());
2184 } else {
2185 removeCustom(VENDOR_ID, BLOGFEED);
2186 }
2187}
2188
2189QString Addressee::managersName() const
2190{
2191 return custom(VENDOR_ID, X_MANAGERSNAME);
2192}
2193
2194void Addressee::setManagersName(const QString &managersName)
2195{
2196 if (!managersName.isEmpty()) {
2197 insertCustom(VENDOR_ID, X_MANAGERSNAME, managersName);
2198 } else {
2199 removeCustom(VENDOR_ID, X_MANAGERSNAME);
2200 }
2201}
2202
2203QString Addressee::office() const
2204{
2205 return custom(VENDOR_ID, X_OFFICE);
2206}
2207
2209{
2210 if (!office.isEmpty()) {
2211 insertCustom(VENDOR_ID, X_OFFICE, office);
2212 } else {
2213 removeCustom(VENDOR_ID, X_OFFICE);
2214 }
2215}
2216
2217QString Addressee::profession() const
2218{
2219 return custom(VENDOR_ID, X_PROFESSION);
2220}
2221
2222void Addressee::setProfession(const QString &profession)
2223{
2224 if (!profession.isEmpty()) {
2225 insertCustom(VENDOR_ID, X_PROFESSION, profession);
2226 } else {
2227 removeCustom(VENDOR_ID, X_PROFESSION);
2228 }
2229}
2230
2231QString Addressee::spousesName() const
2232{
2233 return custom(VENDOR_ID, X_SPOUSESNAME);
2234}
2235
2236void Addressee::setSpousesName(const QString &spousesName)
2237{
2238 if (!spousesName.isEmpty()) {
2239 insertCustom(VENDOR_ID, X_SPOUSESNAME, spousesName);
2240 } else {
2241 removeCustom(VENDOR_ID, X_SPOUSESNAME);
2242 }
2243}
2244
2245void Addressee::insertCustom(const QString &app, const QString &name, const QString &value)
2246{
2247 if (value.isEmpty() || name.isEmpty() || app.isEmpty()) {
2248 return;
2249 }
2250
2251 d->mEmpty = false;
2252
2253 const QString qualifiedName = app + QLatin1Char('-') + name;
2254
2255 auto it = d->findByName(qualifiedName);
2256 if (it != d->mCustomFields.end()) {
2257 it->value = value;
2258 } else {
2259 const CustomData newdata{qualifiedName, value};
2260 auto beforeIt = std::lower_bound(d->mCustomFields.begin(), d->mCustomFields.end(), newdata);
2261 d->mCustomFields.insert(beforeIt, newdata);
2262 }
2263}
2264
2265void Addressee::removeCustom(const QString &app, const QString &name)
2266{
2267 const QString qualifiedName = app + QLatin1Char('-') + name;
2268 auto it = d->findByName(qualifiedName);
2269 if (it != d->mCustomFields.end()) {
2270 d->mCustomFields.erase(it);
2271 }
2272}
2273
2274QString Addressee::custom(const QString &app, const QString &name) const
2275{
2276 const QString qualifiedName = app + QLatin1Char('-') + name;
2277 auto it = d->findByName(qualifiedName);
2278 return it != d->mCustomFields.cend() ? it->value : QString{};
2279}
2280
2282{
2283 d->mEmpty = false;
2284
2285 d->mCustomFields.clear();
2286
2287 // Less than 10 elements in "customs", we needn't use a set
2288 QStringList seen;
2289 for (const QString &custom : customs) {
2290 const int index = custom.indexOf(QLatin1Char(':'));
2291 if (index == -1) {
2292 continue;
2293 }
2294
2295 const QString qualifiedName = custom.left(index);
2296 const QString value = custom.mid(index + 1);
2297
2298 if (!seen.contains(qualifiedName)) {
2299 d->mCustomFields.push_back({qualifiedName, value});
2300 seen.push_back(qualifiedName);
2301 }
2302 }
2303 std::sort(d->mCustomFields.begin(), d->mCustomFields.end());
2304}
2305
2306QStringList Addressee::customs() const
2307{
2308 QStringList result;
2309 result.reserve(d->mCustomFields.size());
2310
2311 static const QLatin1Char sep(':');
2312 for (const auto &[name, value] : d->mCustomFields) {
2313 result << name + sep + value;
2314 }
2315
2316 return result;
2317}
2318
2319void Addressee::parseEmailAddress(const QString &rawEmail, QString &fullName, QString &email)
2320{
2321 // This is a simplified version of KPIM::splitAddress().
2322
2323 fullName.clear();
2324 email.clear();
2325 if (rawEmail.isEmpty()) {
2326 return; // KPIM::AddressEmpty;
2327 }
2328
2329 // The code works on 8-bit strings, so convert the input to UTF-8.
2330 QByteArray address = rawEmail.toUtf8();
2331
2332 QByteArray displayName;
2333 QByteArray addrSpec;
2334 QByteArray comment;
2335
2336 // The following is a primitive parser for a mailbox-list (cf. RFC 2822).
2337 // The purpose is to extract a displayable string from the mailboxes.
2338 // Comments in the addr-spec are not handled. No error checking is done.
2339
2340 enum sourceLevel {
2341 TopLevel,
2342 InComment,
2343 InAngleAddress,
2344 };
2345 sourceLevel context = TopLevel;
2346 bool inQuotedString = false;
2347 int commentLevel = 0;
2348 bool stop = false;
2349
2350 for (char *p = address.data(); *p && !stop; ++p) {
2351 switch (context) {
2352 case TopLevel:
2353 switch (*p) {
2354 case '"':
2355 inQuotedString = !inQuotedString;
2356 displayName += *p;
2357 break;
2358 case '(':
2359 if (!inQuotedString) {
2360 context = InComment;
2361 commentLevel = 1;
2362 } else {
2363 displayName += *p;
2364 }
2365 break;
2366 case '<':
2367 if (!inQuotedString) {
2368 context = InAngleAddress;
2369 } else {
2370 displayName += *p;
2371 }
2372 break;
2373 case '\\': // quoted character
2374 displayName += *p;
2375 ++p; // skip the '\'
2376 if (*p) {
2377 displayName += *p;
2378 } else {
2379 // return KPIM::UnexpectedEnd;
2380 goto ABORT_PARSING;
2381 }
2382 break;
2383 case ',':
2384 if (!inQuotedString) {
2385 // if ( allowMultipleAddresses )
2386 // stop = true;
2387 // else
2388 // return KPIM::UnexpectedComma;
2389 goto ABORT_PARSING;
2390 } else {
2391 displayName += *p;
2392 }
2393 break;
2394 default:
2395 displayName += *p;
2396 }
2397 break;
2398 case InComment:
2399 switch (*p) {
2400 case '(':
2401 ++commentLevel;
2402 comment += *p;
2403 break;
2404 case ')':
2405 --commentLevel;
2406 if (commentLevel == 0) {
2407 context = TopLevel;
2408 comment += ' '; // separate the text of several comments
2409 } else {
2410 comment += *p;
2411 }
2412 break;
2413 case '\\': // quoted character
2414 comment += *p;
2415 ++p; // skip the '\'
2416 if (*p) {
2417 comment += *p;
2418 } else {
2419 // return KPIM::UnexpectedEnd;
2420 goto ABORT_PARSING;
2421 }
2422 break;
2423 default:
2424 comment += *p;
2425 }
2426 break;
2427 case InAngleAddress:
2428 switch (*p) {
2429 case '"':
2430 inQuotedString = !inQuotedString;
2431 addrSpec += *p;
2432 break;
2433 case '>':
2434 if (!inQuotedString) {
2435 context = TopLevel;
2436 } else {
2437 addrSpec += *p;
2438 }
2439 break;
2440 case '\\': // quoted character
2441 addrSpec += *p;
2442 ++p; // skip the '\'
2443 if (*p) {
2444 addrSpec += *p;
2445 } else {
2446 // return KPIM::UnexpectedEnd;
2447 goto ABORT_PARSING;
2448 }
2449 break;
2450 default:
2451 addrSpec += *p;
2452 }
2453 break;
2454 } // switch ( context )
2455 }
2456
2457ABORT_PARSING:
2458 displayName = displayName.trimmed();
2459 comment = comment.trimmed();
2460 addrSpec = addrSpec.trimmed();
2461 fullName = QString::fromUtf8(displayName);
2462 email = QString::fromUtf8(addrSpec); // check for errors
2463 if (inQuotedString) {
2464 return; // KPIM::UnbalancedQuote;
2465 }
2466 if (context == InComment) {
2467 return; // KPIM::UnbalancedParens;
2468 }
2469 if (context == InAngleAddress) {
2470 return; // KPIM::UnclosedAngleAddr;
2471 }
2472
2473 if (addrSpec.isEmpty()) {
2474 if (displayName.isEmpty()) {
2475 return; // KPIM::NoAddressSpec;
2476 } else {
2477 // addrSpec = displayName;
2478 // displayName.truncate( 0 );
2479 // Address of the form "foo@bar" or "foo@bar (Name)".
2480 email = fullName;
2481 fullName = QString::fromUtf8(comment);
2482 }
2483 }
2484
2485 email = email.toLower();
2486
2487 // Check that the full name is not enclosed in balanced double quotes.
2488 // If it is then remove them.
2489 const unsigned int len = fullName.length();
2490 if (len < 3) { // not long enough to be
2491 return;
2492 }
2493 if (fullName.startsWith(QLatin1Char('"')) && fullName.endsWith(QLatin1Char('"'))) {
2494 fullName = fullName.mid(1, len - 2);
2495 }
2496}
2497
2499{
2500 d->mChanged = value;
2501}
2502
2503bool Addressee::changed() const
2504{
2505 return d->mChanged;
2506}
2507
2509{
2510 return QStringLiteral("text/directory");
2511}
2512
2513QDataStream &KContacts::operator<<(QDataStream &s, const Addressee &a)
2514{
2515 s << a.d->mUid;
2516
2517 s << a.d->mName;
2518 s << a.d->mFormattedName;
2519 s << a.d->mFamilyName;
2520 s << a.d->mGivenName;
2521 s << a.d->mAdditionalName;
2522 s << a.d->mPrefix;
2523 s << a.d->mSuffix;
2524 s << a.d->mBirthday;
2525 s << a.d->mBirthdayWithTime;
2526 s << a.d->mMailer;
2527 s << a.d->mTimeZone;
2528 s << a.d->mGeo;
2529 s << a.d->mDepartment;
2530 s << a.d->mNote;
2531 s << a.d->mProductId;
2532 s << a.d->mRevision;
2533 s << a.d->mSortString;
2534 s << a.d->mSecrecy;
2535 s << a.d->mLogo;
2536 s << a.d->mPhoto;
2537 s << a.d->mSound;
2538 s << a.d->mPhoneNumbers;
2539 s << a.d->mAddresses;
2540 s << a.d->mEmails;
2541 s << a.d->mCategories;
2542 s << a.customs();
2543 s << a.d->mKeys;
2544 s << a.d->mLangs;
2545 s << a.d->mGender;
2546 s << a.d->mKind;
2547 s << a.d->mCalendarUrl;
2548 s << a.d->mSoundListExtra;
2549 s << a.d->mPhotoExtraList;
2550 s << a.d->mLogoExtraList;
2551 s << a.d->mUrlExtraList;
2552 s << a.d->mMembers;
2553 s << a.d->mRelationships;
2554 s << a.d->mSources;
2555 s << a.d->mImpps;
2556 s << a.d->mFieldGroupList;
2557 s << a.d->mTitleExtraList;
2558 s << a.d->mRoleExtraList;
2559 s << a.d->mOrgExtraList;
2560 s << a.d->mNickNameExtraList;
2561 s << a.d->mClientPidMapList;
2562
2563 return s;
2564}
2565
2566QDataStream &KContacts::operator>>(QDataStream &s, Addressee &a)
2567{
2568 s >> a.d->mUid;
2569
2570 s >> a.d->mName;
2571 s >> a.d->mFormattedName;
2572 s >> a.d->mFamilyName;
2573 s >> a.d->mGivenName;
2574 s >> a.d->mAdditionalName;
2575 s >> a.d->mPrefix;
2576 s >> a.d->mSuffix;
2577 s >> a.d->mBirthday;
2578 s >> a.d->mBirthdayWithTime;
2579 s >> a.d->mMailer;
2580 s >> a.d->mTimeZone;
2581 s >> a.d->mGeo;
2582 s >> a.d->mDepartment;
2583 s >> a.d->mNote;
2584 s >> a.d->mProductId;
2585 s >> a.d->mRevision;
2586 s >> a.d->mSortString;
2587 s >> a.d->mSecrecy;
2588 s >> a.d->mLogo;
2589 s >> a.d->mPhoto;
2590 s >> a.d->mSound;
2591 s >> a.d->mPhoneNumbers;
2592 s >> a.d->mAddresses;
2593 s >> a.d->mEmails;
2594 s >> a.d->mCategories;
2595 QStringList customFields;
2596 s >> customFields;
2597 a.setCustoms(customFields);
2598 s >> a.d->mKeys;
2599 s >> a.d->mLangs;
2600 s >> a.d->mGender;
2601 s >> a.d->mKind;
2602 s >> a.d->mCalendarUrl;
2603 s >> a.d->mSoundListExtra;
2604 s >> a.d->mPhotoExtraList;
2605 s >> a.d->mLogoExtraList;
2606 s >> a.d->mUrlExtraList;
2607 s >> a.d->mMembers;
2608 s >> a.d->mRelationships;
2609 s >> a.d->mSources;
2610 s >> a.d->mImpps;
2611 s >> a.d->mFieldGroupList;
2612 s >> a.d->mTitleExtraList;
2613 s >> a.d->mRoleExtraList;
2614 s >> a.d->mOrgExtraList;
2615 s >> a.d->mNickNameExtraList;
2616 s >> a.d->mClientPidMapList;
2617 a.d->mEmpty = false;
2618
2619 return s;
2620}
2621
2622bool matchBinaryPattern(int value, int pattern)
2623{
2624 /**
2625 We want to match all telephonnumbers/addresses which have the bits in the
2626 pattern set. More are allowed.
2627 if pattern == 0 we have a special handling, then we want only those with
2628 exactly no bit set.
2629 */
2630 if (pattern == 0) {
2631 return value == 0;
2632 } else {
2633 return pattern == (pattern & value);
2634 }
2635}
2636
2637template<class L>
2638bool listEquals(const QList<L> &list, const QList<L> &pattern)
2639{
2640 if (list.count() != pattern.count()) {
2641 return false;
2642 }
2643 const int numberOfElement(list.count());
2644 for (int i = 0; i < numberOfElement; ++i) {
2645 if (!pattern.contains(list[i])) {
2646 return false;
2647 }
2648 }
2649
2650 return true;
2651}
2652
2653bool listEquals(const QStringList &list, const QStringList &pattern)
2654{
2655 if (list.count() != pattern.count()) {
2656 return false;
2657 }
2658
2659 const int numberOfElement(list.count());
2660 for (int i = 0; i < numberOfElement; ++i) {
2661 if (!pattern.contains(list[i])) {
2662 return false;
2663 }
2664 }
2665
2666 return true;
2667}
2668
2669void Addressee::setBirthdayProperty(const QDateTime &birthday) {
2670 // The property setter cannot pass withTime, so we have to guess.
2671 setBirthday(birthday, birthday.time().msecsSinceStartOfDay() != 0);
2672}
2673
2674#include "moc_addressee.cpp"
Postal address information.
Definition address.h:31
@ Pref
preferred address
Definition address.h:85
address book entry
Definition addressee.h:70
static QString businessAddressRegionLabel()
Return translated label for businessAddressRegion field.
static QString sortStringLabel()
Return translated label for sortString field.
void insertLang(const Lang &language)
Insert Language.
void setMailer(const QString &mailer)
Set mail client.
void removeKey(const Key &key)
Remove a key.
static QString businessAddressPostOfficeBoxLabel()
Return translated label for businessAddressPostOfficeBox field.
void insertCategory(const QString &category)
Insert category.
static QString homeAddressPostalCodeLabel()
Return translated label for homeAddressPostalCode field.
void setLogo(const Picture &logo)
Set logo.
static QString givenNameLabel()
Return translated label for givenName field.
void setNameFromString(const QString &s)
Set name fields by parsing the given string and trying to associate the parts of the string with acco...
void addEmail(const Email &email)
Adds an email address.
static QString noteLabel()
Return translated label for note field.
~Addressee()
Destroys the address book entry.
bool operator!=(const Addressee &other) const
Not-equal operator.
void setBirthday(const QDateTime &birthday, bool withTime=true)
Set birthday (date and time).
void setAdditionalName(const QString &additionalName)
Set additional names.
void removePhoneNumber(const PhoneNumber &phoneNumber)
Remove phone number.
void setSecrecy(const Secrecy &secrecy)
Set security class.
static QString additionalNameLabel()
Return translated label for additionalName field.
void setOrganization(const QString &organization)
Set organization.
static QString organizationLabel()
Return translated label for organization field.
void setKeys(const Key::List &keys)
Set the list of keys.
void insertPhoneNumber(const PhoneNumber &phoneNumber)
Insert a phone number.
static QString homeAddressPostOfficeBoxLabel()
Return translated label for homeAddressPostOfficeBox field.
void setPrefix(const QString &prefix)
Set honorific prefixes.
void setBlogFeed(const QUrl &blogFeed)
Set the contact's blog feed.
void insertCustom(const QString &app, const QString &name, const QString &value)
Insert custom entry.
void setProductId(const QString &productId)
Set product identifier.
static QString businessAddressLabelLabel()
Return translated label for businessAddressLabel field.
static QString mimeType()
Returns the MIME type used for Addressees.
static QString businessAddressStreetLabel()
Return translated label for businessAddressStreet field.
static QString businessAddressLocalityLabel()
Return translated label for businessAddressLocality field.
static QString mailerLabel()
Return translated label for mailer field.
Key::List keys() const
Return list of all keys.
QString custom(const QString &app, const QString &name) const
Return value of custom entry, identified by app and entry name.
static QString homeAddressCountryLabel()
Return translated label for homeAddressCountry field.
static QString logoLabel()
Return translated label for logo field.
static QString photoLabel()
Return translated label for photo field.
static QString secrecyLabel()
Return translated label for secrecy field.
void setRevision(const QDateTime &revision)
Set revision date.
void setProfession(const QString &profession)
Set the contact's profession.
void setSuffix(const QString &suffix)
Set honorific suffixes.
static QString homePhoneLabel()
Return translated label for homePhone field.
static QString soundLabel()
Return translated label for sound field.
void removeEmail(const QString &email)
Remove email address.
static QString homeAddressLabelLabel()
Return translated label for homeAddressLabel field.
void removeAddress(const Address &address)
Remove address.
Sound sound() const
Return sound.
static QString urlLabel()
Return translated label for url field.
QString toString() const
Returns string representation of the addressee.
Secrecy secrecy() const
Return security class.
Addressee()
Construct an empty address book entry.
static QString businessAddressPostalCodeLabel()
Return translated label for businessAddressPostalCode field.
static QString carPhoneLabel()
Return translated label for carPhone field.
Address address(Address::Type type) const
Return address, which matches the given type.
static QString titleLabel()
Return translated label for title field.
void setGivenName(const QString &givenName)
Set given name.
static QString prefixLabel()
Return translated label for prefix field.
bool hasCategory(const QString &category) const
Return, if addressee has the given category.
void setAddresses(const Address::List &addresses)
Set the addressee.
static QString nameLabel()
Return translated label for name field.
Addressee & operator=(const Addressee &other)
Assignment operator.
static QString homeAddressStreetLabel()
Return translated label for homeAddressStreet field.
static QString uidLabel()
Return translated label for uid field.
PhoneNumber phoneNumber(PhoneNumber::Type type) const
Return phone number, which matches the given type.
static QString pagerLabel()
Return translated label for pager field.
void setEmails(const QStringList &list)
Set the emails to list.
void setNickName(const QString &nickName)
Set nick name.
Key findKey(const QString &id) const
Return key with the given id.
static void parseEmailAddress(const QString &rawEmail, QString &fullName, QString &email)
Parse full email address.
void setDepartment(const QString &department)
Set department.
static QString homeFaxLabel()
Return translated label for homeFax field.
void setCustoms(const QStringList &customs)
Set all custom entries.
static QString timeZoneLabel()
Return translated label for timeZone field.
void removeLang(const QString &language)
Remove Language.
void setSound(const Sound &sound)
Set sound.
void setChanged(bool value)
Mark addressee as changed.
void removeCustom(const QString &app, const QString &name)
Remove custom entry.
void setTimeZone(const TimeZone &timeZone)
Set time zone.
void setOffice(const QString &office)
Set the contact's office.
Picture logo() const
Return logo.
void setNote(const QString &note)
Set note.
Key key(Key::Type type, const QString &customTypeString=QString()) const
Return key, which matches the given type.
static QString suffixLabel()
Return translated label for suffix field.
static QString geoLabel()
Return translated label for geo field.
QString fullEmail(const QString &email=QString()) const
Return email address including real name.
static QString homeAddressLocalityLabel()
Return translated label for homeAddressLocality field.
void setManagersName(const QString &managersName)
Set the contact's manager's name.
static QString roleLabel()
Return translated label for role field.
void setPhoto(const Picture &photo)
Set photo.
void setName(const QString &name)
Set name.
void removeCategory(const QString &category)
Remove category.
Lang::List langs() const
langs
void insertAddress(const Address &address)
Insert an address.
static QString birthdayLabel()
Return translated label for birthday field.
bool operator==(const Addressee &other) const
Equality operator.
TimeZone timeZone() const
Return time zone.
void insertKey(const Key &key)
Insert a key.
void setRole(const QString &role)
Set role.
static QString businessPhoneLabel()
Return translated label for businessPhone field.
void setAnniversary(const QDate &anniversary)
Sets the contact's anniversary date.
void setSpousesName(const QString &spousesName)
Set the contact's spouse's name.
static QString revisionLabel()
Return translated label for revision field.
void setFormattedName(const QString &formattedName)
Set formatted name.
static QString businessAddressCountryLabel()
Return translated label for businessAddressCountry field.
static QString homeAddressRegionLabel()
Return translated label for homeAddressRegion field.
static QString departmentLabel()
Return translated label for department field.
Address findAddress(const QString &id) const
Return address with the given id.
void setCategories(const QStringList &category)
Set categories to given value.
static QString familyNameLabel()
Return translated label for familyName field.
void setFamilyName(const QString &familyName)
Set family name.
void setTitle(const QString &title)
Set title.
static QString nickNameLabel()
Return translated label for nickName field.
static QString isdnLabel()
Return translated label for isdn field.
void setAssistantsName(const QString &assistantsName)
Set the contact's assistant's name.
static QString productIdLabel()
Return translated label for productId field.
PhoneNumber findPhoneNumber(const QString &id) const
Return phone number with the given id.
void setUid(const QString &uid)
Set unique identifier.
static QString mobilePhoneLabel()
Return translated label for mobilePhone field.
void setGeo(const Geo &geo)
Set geographic position.
static QString formattedNameLabel()
Return translated label for formattedName field.
void setUrl(const ResourceLocatorUrl &url)
Set homepage.
static QString emailLabel()
Return translated label for email field.
static QString businessFaxLabel()
Return translated label for businessFax field.
void setSortString(const QString &sortString)
Set sort string.
Class that holds a Calendar Url (FBURL/CALADRURI/CALURI)
Definition calendarurl.h:30
Class that holds a ClientPidMap for a contact.
Class that holds a Email for a contact.
Definition email.h:28
Class that holds a FieldGroup for a contact.
Definition fieldgroup.h:27
Class that holds a Gender for a contact.
Definition gender.h:20
Geographic position.
Definition geo.h:25
Class that holds a IMPP for a contact.
Definition impp.h:32
A class to store an encryption key.
Definition key.h:22
Type type() const
Returns the type, see Type.
Definition key.cpp:154
Type
Key types.
Definition key.h:35
@ Custom
Custom or IANA conform key.
Definition key.h:38
QString customTypeString() const
Returns the custom type string.
Definition key.cpp:159
Class that holds a Language for a contact.
Definition lang.h:27
Class that holds a NickName for a contact.
Definition nickname.h:27
Class that holds a Organization for a contact.
Definition org.h:27
Phonenumber information.
Definition phonenumber.h:31
@ Pref
Preferred number.
Definition phonenumber.h:55
A class to store a picture of an addressee.
Definition picture.h:27
Describes a relationship of an Addressee.
Definition related.h:25
Class that holds a Resource Locator.
Class that holds a Role for a contact.
Definition role.h:27
Describes the confidentiality of an addressee.
Definition secrecy.h:19
Class that holds a Sound clip for a contact.
Definition sound.h:46
Time zone information.
Definition timezone.h:23
Class that holds a Title for a contact.
Definition title.h:27
void stop(Ekos::AlignState mode)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
KIOCORE_EXPORT bool operator!=(const UDSEntry &entry, const UDSEntry &other)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
StandardShortcut findByName(const QString &name)
bool operator<(const PosRange< Trait > &l, const PosRange< Trait > &r)
bool operator==(const StyleDelim &l, const StyleDelim &r)
bool isEmpty() const const
QByteArray trimmed() const const
QDate fromString(QStringView string, QStringView format, QCalendar cal)
bool isValid(int year, int month, int day)
QString toString(QStringView format, QCalendar cal) const const
QTime time() const const
const_reference at(qsizetype i) const const
bool contains(const AT &value) const const
qsizetype count() const const
bool isEmpty() const const
void push_back(parameter_type value)
void reserve(qsizetype size)
qsizetype size() const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
void clear()
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
QString fromUtf8(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
bool isNull() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & prepend(QChar ch)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QString simplified() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toLower() const const
QByteArray toUtf8() const const
QString trimmed() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
int msecsSinceStartOfDay() const const
bool isEmpty() const const
QString url(FormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 22 2024 12:06:34 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.