1 | /* |
2 | This file is part of libkabc. |
3 | Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> |
4 | Copyright (c) 2003 Carsten Pfeiffer <pfeiffer@kde.org> |
5 | Copyright (c) 2005 Ingo Kloecker <kloecker@kde.org> |
6 | |
7 | This library is free software; you can redistribute it and/or |
8 | modify it under the terms of the GNU Library General Public |
9 | License as published by the Free Software Foundation; either |
10 | version 2 of the License, or (at your option) any later version. |
11 | |
12 | This library is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | Library General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU Library General Public License |
18 | along with this library; see the file COPYING.LIB. If not, write to |
19 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 | Boston, MA 02110-1301, USA. |
21 | */ |
22 | |
23 | #include <QtCore/QList> |
24 | #include <QtCore/QRegExp> |
25 | #include <QtCore/QSharedData> |
26 | #include <QtCore/QUuid> |
27 | |
28 | #include <kdebug.h> |
29 | #include <klocale.h> |
30 | #include <klocalizedstring.h> |
31 | |
32 | #include "addresseehelper.h" |
33 | #include "field.h" |
34 | #ifndef KDEPIM_NO_KRESOURCES |
35 | #include "resource.h" |
36 | #endif |
37 | #include "sortmode.h" |
38 | |
39 | #include "addressee.h" |
40 | |
41 | using namespace KABC; |
42 | |
43 | static bool matchBinaryPattern( int value, int pattern ); |
44 | |
45 | template <class L> |
46 | static bool listEquals( const QList<L>&, const QList<L>& ); |
47 | static bool listEquals( const QStringList&, const QStringList& ); |
48 | static bool emailsEquals( const QStringList&, const QStringList& ); |
49 | |
50 | class Addressee::Private : public QSharedData |
51 | { |
52 | public: |
53 | Private() |
54 | : mUid( QUuid::createUuid().toString().mid(1, 36) ), //We avoid the curly braces so the string is RFC4122 compliant and can be used as urn |
55 | #ifndef KDEPIM_NO_KRESOURCES |
56 | mResource( 0 ), |
57 | #endif |
58 | mEmpty( true ), mChanged( false ) |
59 | { |
60 | } |
61 | |
62 | Private( const Private &other ) |
63 | : QSharedData( other ) |
64 | #ifndef KDEPIM_NO_KRESOURCES |
65 | ,mResource( 0 ) |
66 | #endif |
67 | { |
68 | mUid = other.mUid; |
69 | mName = other.mName; |
70 | mFormattedName = other.mFormattedName; |
71 | mFamilyName = other.mFamilyName; |
72 | mGivenName = other.mGivenName; |
73 | mAdditionalName = other.mAdditionalName; |
74 | mPrefix = other.mPrefix; |
75 | mSuffix = other.mSuffix; |
76 | mNickName = other.mNickName; |
77 | mBirthday = other.mBirthday; |
78 | mMailer = other.mMailer; |
79 | mTimeZone = other.mTimeZone; |
80 | mGeo = other.mGeo; |
81 | mTitle = other.mTitle; |
82 | mRole = other.mRole; |
83 | mOrganization = other.mOrganization; |
84 | mDepartment = other.mDepartment; |
85 | mNote = other.mNote; |
86 | mProductId = other.mProductId; |
87 | mRevision = other.mRevision; |
88 | mSortString = other.mSortString; |
89 | mUrl = other.mUrl; |
90 | mSecrecy = other.mSecrecy; |
91 | mLogo = other.mLogo; |
92 | mPhoto = other.mPhoto; |
93 | mSound = other.mSound; |
94 | |
95 | mPhoneNumbers = other.mPhoneNumbers; |
96 | mAddresses = other.mAddresses; |
97 | mKeys = other.mKeys; |
98 | mEmails = other.mEmails; |
99 | mCategories = other.mCategories; |
100 | mCustomFields = other.mCustomFields; |
101 | |
102 | #ifndef KDEPIM_NO_KRESOURCES |
103 | mResource = other.mResource; |
104 | #endif |
105 | mEmpty = other.mEmpty; |
106 | mChanged = other.mChanged; |
107 | } |
108 | |
109 | ~Private() |
110 | { |
111 | } |
112 | |
113 | QString mUid; |
114 | QString mName; |
115 | QString mFormattedName; |
116 | QString mFamilyName; |
117 | QString mGivenName; |
118 | QString mAdditionalName; |
119 | QString mPrefix; |
120 | QString mSuffix; |
121 | QString mNickName; |
122 | QDateTime mBirthday; |
123 | QString mMailer; |
124 | TimeZone mTimeZone; |
125 | Geo mGeo; |
126 | QString mTitle; |
127 | QString mRole; |
128 | QString mOrganization; |
129 | QString mDepartment; |
130 | QString mNote; |
131 | QString mProductId; |
132 | QDateTime mRevision; |
133 | QString mSortString; |
134 | KUrl mUrl; |
135 | Secrecy mSecrecy; |
136 | Picture mLogo; |
137 | Picture mPhoto; |
138 | Sound mSound; |
139 | |
140 | PhoneNumber::List mPhoneNumbers; |
141 | Address::List mAddresses; |
142 | Key::List mKeys; |
143 | QStringList mEmails; |
144 | QStringList mCategories; |
145 | QMap<QString, QString> mCustomFields; |
146 | |
147 | #ifndef KDEPIM_NO_KRESOURCES |
148 | Resource *mResource; |
149 | #endif |
150 | |
151 | bool mEmpty :1; |
152 | bool mChanged :1; |
153 | |
154 | static KABC::SortMode *mSortMode; |
155 | }; |
156 | |
157 | KABC::SortMode *Addressee::Private::mSortMode = 0; |
158 | |
159 | Addressee::Addressee() |
160 | : d( new Private ) |
161 | { |
162 | } |
163 | |
164 | Addressee::~Addressee() |
165 | { |
166 | } |
167 | |
168 | Addressee::Addressee( const Addressee &other ) |
169 | : d( other.d ) |
170 | { |
171 | } |
172 | |
173 | Addressee& Addressee::operator=( const Addressee &other ) |
174 | { |
175 | if ( this != &other ) |
176 | d = other.d; |
177 | |
178 | return *this; |
179 | } |
180 | |
181 | bool Addressee::operator==( const Addressee &addressee ) const |
182 | { |
183 | if ( d->mUid != addressee.d->mUid ) { |
184 | kDebug() << "uid differs" ; |
185 | return false; |
186 | } |
187 | |
188 | if ( d->mName != addressee.d->mName && |
189 | !( d->mName.isEmpty() && addressee.d->mName.isEmpty() ) ) { |
190 | kDebug(5700) << "name differs" ; |
191 | return false; |
192 | } |
193 | |
194 | if ( d->mFormattedName != addressee.d->mFormattedName && |
195 | !( d->mFormattedName.isEmpty() && addressee.d->mFormattedName.isEmpty() ) ) { |
196 | kDebug(5700) << "formattedName differs" ; |
197 | return false; |
198 | } |
199 | |
200 | if ( d->mFamilyName != addressee.d->mFamilyName && |
201 | !( d->mFamilyName.isEmpty() && addressee.d->mFamilyName.isEmpty() ) ) { |
202 | kDebug(5700) << "familyName differs" ; |
203 | return false; |
204 | } |
205 | |
206 | if ( d->mGivenName != addressee.d->mGivenName && |
207 | !( d->mGivenName.isEmpty() && addressee.d->mGivenName.isEmpty() ) ) { |
208 | kDebug(5700) << "givenName differs" ; |
209 | return false; |
210 | } |
211 | |
212 | if ( d->mAdditionalName != addressee.d->mAdditionalName && |
213 | !( d->mAdditionalName.isEmpty() && addressee.d->mAdditionalName.isEmpty() ) ) { |
214 | kDebug(5700) << "additionalName differs" ; |
215 | return false; |
216 | } |
217 | |
218 | if ( d->mPrefix != addressee.d->mPrefix && |
219 | !( d->mPrefix.isEmpty() && addressee.d->mPrefix.isEmpty() ) ) { |
220 | kDebug(5700) << "prefix differs" ; |
221 | return false; |
222 | } |
223 | |
224 | if ( d->mSuffix != addressee.d->mSuffix && |
225 | !( d->mSuffix.isEmpty() && addressee.d->mSuffix.isEmpty() ) ) { |
226 | kDebug(5700) << "suffix differs" ; |
227 | return false; |
228 | } |
229 | |
230 | if ( d->mNickName != addressee.d->mNickName && |
231 | !( d->mNickName.isEmpty() && addressee.d->mNickName.isEmpty() ) ) { |
232 | kDebug(5700) << "nickName differs" ; |
233 | return false; |
234 | } |
235 | |
236 | if ( d->mBirthday != addressee.d->mBirthday ) { |
237 | kDebug(5700) << "birthday differs" ; |
238 | return false; |
239 | } |
240 | |
241 | if ( d->mMailer != addressee.d->mMailer && |
242 | !( d->mMailer.isEmpty() && addressee.d->mMailer.isEmpty() ) ) { |
243 | kDebug(5700) << "mailer differs" ; |
244 | return false; |
245 | } |
246 | |
247 | if ( d->mTimeZone != addressee.d->mTimeZone ) { |
248 | kDebug(5700) << "timeZone differs" ; |
249 | return false; |
250 | } |
251 | |
252 | if ( d->mGeo != addressee.d->mGeo ) { |
253 | kDebug(5700) << "geo differs" ; |
254 | return false; |
255 | } |
256 | |
257 | if ( d->mTitle != addressee.d->mTitle && |
258 | !( d->mTitle.isEmpty() && addressee.d->mTitle.isEmpty() ) ) { |
259 | kDebug(5700) << "title differs" ; |
260 | return false; |
261 | } |
262 | |
263 | if ( d->mRole != addressee.d->mRole && |
264 | !( d->mRole.isEmpty() && addressee.d->mRole.isEmpty() ) ) { |
265 | kDebug(5700) << "role differs" ; |
266 | return false; |
267 | } |
268 | |
269 | if ( d->mOrganization != addressee.d->mOrganization && |
270 | !( d->mOrganization.isEmpty() && addressee.d->mOrganization.isEmpty() ) ) { |
271 | kDebug(5700) << "organization differs" ; |
272 | return false; |
273 | } |
274 | |
275 | if ( d->mDepartment != addressee.d->mDepartment && |
276 | !( d->mDepartment.isEmpty() && addressee.d->mDepartment.isEmpty() ) ) { |
277 | kDebug(5700) << "department differs" ; |
278 | return false; |
279 | } |
280 | |
281 | if ( d->mNote != addressee.d->mNote && |
282 | !( d->mNote.isEmpty() && addressee.d->mNote.isEmpty() ) ) { |
283 | kDebug(5700) << "note differs" ; |
284 | return false; |
285 | } |
286 | |
287 | if ( d->mProductId != addressee.d->mProductId && |
288 | !( d->mProductId.isEmpty() && addressee.d->mProductId.isEmpty() ) ) { |
289 | kDebug(5700) << "productId differs" ; |
290 | return false; |
291 | } |
292 | |
293 | if ( d->mSortString != addressee.d->mSortString && |
294 | !( d->mSortString.isEmpty() && addressee.d->mSortString.isEmpty() ) ) { |
295 | kDebug(5700) << "sortString differs" ; |
296 | return false; |
297 | } |
298 | |
299 | if ( d->mSecrecy != addressee.d->mSecrecy ) { |
300 | kDebug(5700) << "secrecy differs" ; |
301 | return false; |
302 | } |
303 | |
304 | if ( d->mLogo != addressee.d->mLogo ) { |
305 | kDebug(5700) << "logo differs" ; |
306 | return false; |
307 | } |
308 | |
309 | if ( d->mPhoto != addressee.d->mPhoto ) { |
310 | kDebug(5700) << "photo differs" ; |
311 | return false; |
312 | } |
313 | |
314 | if ( d->mSound != addressee.d->mSound ) { |
315 | kDebug(5700) << "sound differs" ; |
316 | return false; |
317 | } |
318 | |
319 | if ( ( d->mUrl.isValid() || addressee.d->mUrl.isValid() ) && |
320 | ( d->mUrl != addressee.d->mUrl ) ) { |
321 | kDebug() << "url differs" ; |
322 | return false; |
323 | } |
324 | |
325 | if ( !listEquals( d->mPhoneNumbers, addressee.d->mPhoneNumbers ) ) { |
326 | kDebug() << "phoneNumbers differs" ; |
327 | return false; |
328 | } |
329 | |
330 | if ( !listEquals( d->mAddresses, addressee.d->mAddresses ) ) { |
331 | kDebug() << "addresses differs" ; |
332 | return false; |
333 | } |
334 | |
335 | if ( !listEquals( d->mKeys, addressee.d->mKeys ) ) { |
336 | kDebug() << "keys differs" ; |
337 | return false; |
338 | } |
339 | |
340 | if ( !emailsEquals( d->mEmails, addressee.d->mEmails ) ) { |
341 | kDebug() << "emails differs" ; |
342 | return false; |
343 | } |
344 | |
345 | if ( !listEquals( d->mCategories, addressee.d->mCategories ) ) { |
346 | kDebug() << "categories differs" ; |
347 | return false; |
348 | } |
349 | |
350 | if ( d->mCustomFields != addressee.d->mCustomFields ) { |
351 | kDebug() << "custom differs" ; |
352 | return false; |
353 | } |
354 | |
355 | return true; |
356 | } |
357 | |
358 | bool Addressee::operator!=( const Addressee &a ) const |
359 | { |
360 | return !( a == *this ); |
361 | } |
362 | |
363 | bool Addressee::isEmpty() const |
364 | { |
365 | return d->mEmpty; |
366 | } |
367 | |
368 | void Addressee::setUid( const QString &id ) |
369 | { |
370 | if ( id == d->mUid ) |
371 | return; |
372 | |
373 | d->mEmpty = false; |
374 | d->mUid = id; |
375 | } |
376 | |
377 | QString Addressee::uid() const |
378 | { |
379 | return d->mUid; |
380 | } |
381 | |
382 | QString Addressee::uidLabel() |
383 | { |
384 | return i18n( "Unique Identifier" ); |
385 | } |
386 | |
387 | void Addressee::setName( const QString &name ) |
388 | { |
389 | if ( name == d->mName ) |
390 | return; |
391 | |
392 | d->mEmpty = false; |
393 | d->mName = name; |
394 | } |
395 | |
396 | QString Addressee::name() const |
397 | { |
398 | return d->mName; |
399 | } |
400 | |
401 | QString Addressee::nameLabel() |
402 | { |
403 | return i18n( "Name" ); |
404 | } |
405 | |
406 | |
407 | void Addressee::setFormattedName( const QString &formattedName ) |
408 | { |
409 | if ( formattedName == d->mFormattedName ) |
410 | return; |
411 | |
412 | d->mEmpty = false; |
413 | d->mFormattedName = formattedName; |
414 | } |
415 | |
416 | QString Addressee::formattedName() const |
417 | { |
418 | return d->mFormattedName; |
419 | } |
420 | |
421 | QString Addressee::formattedNameLabel() |
422 | { |
423 | return i18n( "Formatted Name" ); |
424 | } |
425 | |
426 | |
427 | void Addressee::setFamilyName( const QString &familyName ) |
428 | { |
429 | if ( familyName == d->mFamilyName ) |
430 | return; |
431 | |
432 | d->mEmpty = false; |
433 | d->mFamilyName = familyName; |
434 | } |
435 | |
436 | QString Addressee::familyName() const |
437 | { |
438 | return d->mFamilyName; |
439 | } |
440 | |
441 | QString Addressee::familyNameLabel() |
442 | { |
443 | return i18n( "Family Name" ); |
444 | } |
445 | |
446 | |
447 | void Addressee::setGivenName( const QString &givenName ) |
448 | { |
449 | if ( givenName == d->mGivenName ) |
450 | return; |
451 | |
452 | d->mEmpty = false; |
453 | d->mGivenName = givenName; |
454 | } |
455 | |
456 | QString Addressee::givenName() const |
457 | { |
458 | return d->mGivenName; |
459 | } |
460 | |
461 | QString Addressee::givenNameLabel() |
462 | { |
463 | return i18n( "Given Name" ); |
464 | } |
465 | |
466 | |
467 | void Addressee::setAdditionalName( const QString &additionalName ) |
468 | { |
469 | if ( additionalName == d->mAdditionalName ) |
470 | return; |
471 | |
472 | d->mEmpty = false; |
473 | d->mAdditionalName = additionalName; |
474 | } |
475 | |
476 | QString Addressee::additionalName() const |
477 | { |
478 | return d->mAdditionalName; |
479 | } |
480 | |
481 | QString Addressee::additionalNameLabel() |
482 | { |
483 | return i18n( "Additional Names" ); |
484 | } |
485 | |
486 | |
487 | void Addressee::setPrefix( const QString &prefix ) |
488 | { |
489 | if ( prefix == d->mPrefix ) |
490 | return; |
491 | |
492 | d->mEmpty = false; |
493 | d->mPrefix = prefix; |
494 | } |
495 | |
496 | QString Addressee::prefix() const |
497 | { |
498 | return d->mPrefix; |
499 | } |
500 | |
501 | QString Addressee::prefixLabel() |
502 | { |
503 | return i18n( "Honorific Prefixes" ); |
504 | } |
505 | |
506 | |
507 | void Addressee::setSuffix( const QString &suffix ) |
508 | { |
509 | if ( suffix == d->mSuffix ) |
510 | return; |
511 | |
512 | d->mEmpty = false; |
513 | d->mSuffix = suffix; |
514 | } |
515 | |
516 | QString Addressee::suffix() const |
517 | { |
518 | return d->mSuffix; |
519 | } |
520 | |
521 | QString Addressee::suffixLabel() |
522 | { |
523 | return i18n( "Honorific Suffixes" ); |
524 | } |
525 | |
526 | |
527 | void Addressee::setNickName( const QString &nickName ) |
528 | { |
529 | if ( nickName == d->mNickName ) |
530 | return; |
531 | |
532 | d->mEmpty = false; |
533 | d->mNickName = nickName; |
534 | } |
535 | |
536 | QString Addressee::nickName() const |
537 | { |
538 | return d->mNickName; |
539 | } |
540 | |
541 | QString Addressee::nickNameLabel() |
542 | { |
543 | return i18n( "Nick Name" ); |
544 | } |
545 | |
546 | |
547 | void Addressee::setBirthday( const QDateTime &birthday ) |
548 | { |
549 | if ( birthday == d->mBirthday ) |
550 | return; |
551 | |
552 | d->mEmpty = false; |
553 | d->mBirthday = birthday; |
554 | } |
555 | |
556 | QDateTime Addressee::birthday() const |
557 | { |
558 | return d->mBirthday; |
559 | } |
560 | |
561 | QString Addressee::birthdayLabel() |
562 | { |
563 | return i18n( "Birthday" ); |
564 | } |
565 | |
566 | |
567 | QString Addressee::homeAddressStreetLabel() |
568 | { |
569 | return i18n( "Home Address Street" ); |
570 | } |
571 | |
572 | |
573 | QString Addressee::homeAddressPostOfficeBoxLabel() |
574 | { |
575 | return i18n( "Home Address Post Office Box" ); |
576 | } |
577 | |
578 | |
579 | QString Addressee::homeAddressLocalityLabel() |
580 | { |
581 | return i18n( "Home Address City" ); |
582 | } |
583 | |
584 | |
585 | QString Addressee::homeAddressRegionLabel() |
586 | { |
587 | return i18n( "Home Address State" ); |
588 | } |
589 | |
590 | |
591 | QString Addressee::homeAddressPostalCodeLabel() |
592 | { |
593 | return i18n( "Home Address Zip Code" ); |
594 | } |
595 | |
596 | |
597 | QString Addressee::homeAddressCountryLabel() |
598 | { |
599 | return i18n( "Home Address Country" ); |
600 | } |
601 | |
602 | |
603 | QString Addressee::homeAddressLabelLabel() |
604 | { |
605 | return i18n( "Home Address Label" ); |
606 | } |
607 | |
608 | |
609 | QString Addressee::businessAddressStreetLabel() |
610 | { |
611 | return i18n( "Business Address Street" ); |
612 | } |
613 | |
614 | |
615 | QString Addressee::businessAddressPostOfficeBoxLabel() |
616 | { |
617 | return i18n( "Business Address Post Office Box" ); |
618 | } |
619 | |
620 | |
621 | QString Addressee::businessAddressLocalityLabel() |
622 | { |
623 | return i18n( "Business Address City" ); |
624 | } |
625 | |
626 | |
627 | QString Addressee::businessAddressRegionLabel() |
628 | { |
629 | return i18n( "Business Address State" ); |
630 | } |
631 | |
632 | |
633 | QString Addressee::businessAddressPostalCodeLabel() |
634 | { |
635 | return i18n( "Business Address Zip Code" ); |
636 | } |
637 | |
638 | |
639 | QString Addressee::businessAddressCountryLabel() |
640 | { |
641 | return i18n( "Business Address Country" ); |
642 | } |
643 | |
644 | |
645 | QString Addressee::businessAddressLabelLabel() |
646 | { |
647 | return i18n( "Business Address Label" ); |
648 | } |
649 | |
650 | |
651 | QString Addressee::homePhoneLabel() |
652 | { |
653 | return i18n( "Home Phone" ); |
654 | } |
655 | |
656 | |
657 | QString Addressee::businessPhoneLabel() |
658 | { |
659 | return i18n( "Business Phone" ); |
660 | } |
661 | |
662 | |
663 | QString Addressee::mobilePhoneLabel() |
664 | { |
665 | return i18n( "Mobile Phone" ); |
666 | } |
667 | |
668 | |
669 | QString Addressee::homeFaxLabel() |
670 | { |
671 | return i18n( "Home Fax" ); |
672 | } |
673 | |
674 | |
675 | QString Addressee::businessFaxLabel() |
676 | { |
677 | return i18n( "Business Fax" ); |
678 | } |
679 | |
680 | |
681 | QString Addressee::carPhoneLabel() |
682 | { |
683 | return i18n( "Car Phone" ); |
684 | } |
685 | |
686 | |
687 | QString Addressee::isdnLabel() |
688 | { |
689 | return i18n( "ISDN" ); |
690 | } |
691 | |
692 | |
693 | QString Addressee::() |
694 | { |
695 | return i18n( "Pager" ); |
696 | } |
697 | |
698 | |
699 | QString Addressee::emailLabel() |
700 | { |
701 | return i18n( "Email Address" ); |
702 | } |
703 | |
704 | |
705 | void Addressee::setMailer( const QString &mailer ) |
706 | { |
707 | if ( mailer == d->mMailer ) |
708 | return; |
709 | |
710 | d->mEmpty = false; |
711 | d->mMailer = mailer; |
712 | } |
713 | |
714 | QString Addressee::mailer() const |
715 | { |
716 | return d->mMailer; |
717 | } |
718 | |
719 | QString Addressee::mailerLabel() |
720 | { |
721 | return i18n( "Mail Client" ); |
722 | } |
723 | |
724 | |
725 | void Addressee::setTimeZone( const TimeZone &timeZone ) |
726 | { |
727 | if ( timeZone == d->mTimeZone ) |
728 | return; |
729 | |
730 | d->mEmpty = false; |
731 | d->mTimeZone = timeZone; |
732 | } |
733 | |
734 | TimeZone Addressee::timeZone() const |
735 | { |
736 | return d->mTimeZone; |
737 | } |
738 | |
739 | QString Addressee::timeZoneLabel() |
740 | { |
741 | return i18n( "Time Zone" ); |
742 | } |
743 | |
744 | |
745 | void Addressee::setGeo( const Geo &geo ) |
746 | { |
747 | if ( geo == d->mGeo ) |
748 | return; |
749 | |
750 | d->mEmpty = false; |
751 | d->mGeo = geo; |
752 | } |
753 | |
754 | Geo Addressee::geo() const |
755 | { |
756 | return d->mGeo; |
757 | } |
758 | |
759 | QString Addressee::geoLabel() |
760 | { |
761 | return i18n( "Geographic Position" ); |
762 | } |
763 | |
764 | |
765 | void Addressee::setTitle( const QString &title ) |
766 | { |
767 | if ( title == d->mTitle ) |
768 | return; |
769 | |
770 | d->mEmpty = false; |
771 | d->mTitle = title; |
772 | } |
773 | |
774 | QString Addressee::title() const |
775 | { |
776 | return d->mTitle; |
777 | } |
778 | |
779 | QString Addressee::titleLabel() |
780 | { |
781 | return i18nc( "a person's title" , "Title" ); |
782 | } |
783 | |
784 | |
785 | void Addressee::setRole( const QString &role ) |
786 | { |
787 | if ( role == d->mRole ) |
788 | return; |
789 | |
790 | d->mEmpty = false; |
791 | d->mRole = role; |
792 | } |
793 | |
794 | QString Addressee::role() const |
795 | { |
796 | return d->mRole; |
797 | } |
798 | |
799 | QString Addressee::roleLabel() |
800 | { |
801 | return i18nc( "of a person in an organization" , "Role" ); |
802 | } |
803 | |
804 | |
805 | void Addressee::setOrganization( const QString &organization ) |
806 | { |
807 | if ( organization == d->mOrganization ) |
808 | return; |
809 | |
810 | d->mEmpty = false; |
811 | d->mOrganization = organization; |
812 | } |
813 | |
814 | QString Addressee::organization() const |
815 | { |
816 | return d->mOrganization; |
817 | } |
818 | |
819 | QString Addressee::organizationLabel() |
820 | { |
821 | return i18n( "Organization" ); |
822 | } |
823 | |
824 | |
825 | void Addressee::setDepartment( const QString &department ) |
826 | { |
827 | if ( department == d->mDepartment ) |
828 | return; |
829 | |
830 | d->mEmpty = false; |
831 | d->mDepartment = department; |
832 | } |
833 | |
834 | QString Addressee::department() const |
835 | { |
836 | return d->mDepartment; |
837 | } |
838 | |
839 | QString Addressee::departmentLabel() |
840 | { |
841 | return i18n( "Department" ); |
842 | } |
843 | |
844 | |
845 | void Addressee::setNote( const QString ¬e ) |
846 | { |
847 | if ( note == d->mNote ) |
848 | return; |
849 | |
850 | d->mEmpty = false; |
851 | d->mNote = note; |
852 | } |
853 | |
854 | QString Addressee::note() const |
855 | { |
856 | return d->mNote; |
857 | } |
858 | |
859 | QString Addressee::noteLabel() |
860 | { |
861 | return i18n( "Note" ); |
862 | } |
863 | |
864 | |
865 | void Addressee::setProductId( const QString &productId ) |
866 | { |
867 | if ( productId == d->mProductId ) |
868 | return; |
869 | |
870 | d->mEmpty = false; |
871 | d->mProductId = productId; |
872 | } |
873 | |
874 | QString Addressee::productId() const |
875 | { |
876 | return d->mProductId; |
877 | } |
878 | |
879 | QString Addressee::productIdLabel() |
880 | { |
881 | return i18n( "Product Identifier" ); |
882 | } |
883 | |
884 | |
885 | void Addressee::setRevision( const QDateTime &revision ) |
886 | { |
887 | if ( revision == d->mRevision ) |
888 | return; |
889 | |
890 | d->mEmpty = false; |
891 | d->mRevision = revision; |
892 | } |
893 | |
894 | QDateTime Addressee::revision() const |
895 | { |
896 | return d->mRevision; |
897 | } |
898 | |
899 | QString Addressee::revisionLabel() |
900 | { |
901 | return i18n( "Revision Date" ); |
902 | } |
903 | |
904 | |
905 | void Addressee::setSortString( const QString &sortString ) |
906 | { |
907 | if ( sortString == d->mSortString ) |
908 | return; |
909 | |
910 | d->mEmpty = false; |
911 | d->mSortString = sortString; |
912 | } |
913 | |
914 | QString Addressee::sortString() const |
915 | { |
916 | return d->mSortString; |
917 | } |
918 | |
919 | QString Addressee::sortStringLabel() |
920 | { |
921 | return i18n( "Sort String" ); |
922 | } |
923 | |
924 | |
925 | void Addressee::setUrl( const KUrl &url ) |
926 | { |
927 | if ( url == d->mUrl ) |
928 | return; |
929 | |
930 | d->mEmpty = false; |
931 | d->mUrl = url; |
932 | } |
933 | |
934 | KUrl Addressee::url() const |
935 | { |
936 | return d->mUrl; |
937 | } |
938 | |
939 | QString Addressee::urlLabel() |
940 | { |
941 | return i18n( "Homepage" ); |
942 | } |
943 | |
944 | |
945 | void Addressee::setSecrecy( const Secrecy &secrecy ) |
946 | { |
947 | if ( secrecy == d->mSecrecy ) |
948 | return; |
949 | |
950 | d->mEmpty = false; |
951 | d->mSecrecy = secrecy; |
952 | } |
953 | |
954 | Secrecy Addressee::secrecy() const |
955 | { |
956 | return d->mSecrecy; |
957 | } |
958 | |
959 | QString Addressee::secrecyLabel() |
960 | { |
961 | return i18n( "Security Class" ); |
962 | } |
963 | |
964 | |
965 | void Addressee::setLogo( const Picture &logo ) |
966 | { |
967 | if ( logo == d->mLogo ) |
968 | return; |
969 | |
970 | d->mEmpty = false; |
971 | d->mLogo = logo; |
972 | } |
973 | |
974 | Picture Addressee::logo() const |
975 | { |
976 | return d->mLogo; |
977 | } |
978 | |
979 | QString Addressee::logoLabel() |
980 | { |
981 | return i18n( "Logo" ); |
982 | } |
983 | |
984 | |
985 | void Addressee::setPhoto( const Picture &photo ) |
986 | { |
987 | if ( photo == d->mPhoto ) |
988 | return; |
989 | |
990 | d->mEmpty = false; |
991 | d->mPhoto = photo; |
992 | } |
993 | |
994 | Picture Addressee::photo() const |
995 | { |
996 | return d->mPhoto; |
997 | } |
998 | |
999 | QString Addressee::photoLabel() |
1000 | { |
1001 | return i18n( "Photo" ); |
1002 | } |
1003 | |
1004 | |
1005 | void Addressee::setSound( const Sound &sound ) |
1006 | { |
1007 | if ( sound == d->mSound ) |
1008 | return; |
1009 | |
1010 | d->mEmpty = false; |
1011 | d->mSound = sound; |
1012 | } |
1013 | |
1014 | Sound Addressee::sound() const |
1015 | { |
1016 | return d->mSound; |
1017 | } |
1018 | |
1019 | QString Addressee::soundLabel() |
1020 | { |
1021 | return i18n( "Sound" ); |
1022 | } |
1023 | |
1024 | |
1025 | void Addressee::setNameFromString( const QString &s ) |
1026 | { |
1027 | QString str = s; |
1028 | //remove enclosing quotes from string |
1029 | if ( str.length() > 1 && |
1030 | s[ 0 ] == QLatin1Char( '"' ) && |
1031 | s[ s.length() - 1 ] == QLatin1Char( '"' ) ) { |
1032 | str = s.mid( 1, s.length() - 2 ); |
1033 | } |
1034 | |
1035 | setFormattedName( str ); |
1036 | setName( str ); |
1037 | |
1038 | // clear all name parts |
1039 | setPrefix( QString() ); |
1040 | setGivenName( QString() ); |
1041 | setAdditionalName( QString() ); |
1042 | setFamilyName( QString() ); |
1043 | setSuffix( QString() ); |
1044 | |
1045 | if ( str.isEmpty() ) |
1046 | return; |
1047 | |
1048 | static QString spaceStr = QString::fromLatin1( " " ); |
1049 | static QString emptyStr = QString::fromLatin1( "" ); |
1050 | AddresseeHelper *helper = AddresseeHelper::self(); |
1051 | |
1052 | int i = str.indexOf( QLatin1Char( ',' ) ); |
1053 | if ( i < 0 ) { |
1054 | QStringList parts = str.split( spaceStr ); |
1055 | int leftOffset = 0; |
1056 | int rightOffset = parts.count() - 1; |
1057 | |
1058 | QString suffix; |
1059 | while ( rightOffset >= 0 ) { |
1060 | if ( helper->containsSuffix( parts[ rightOffset ] ) ) { |
1061 | suffix.prepend( parts[ rightOffset ] + ( suffix.isEmpty() ? emptyStr : spaceStr ) ); |
1062 | rightOffset--; |
1063 | } else |
1064 | break; |
1065 | } |
1066 | setSuffix( suffix ); |
1067 | |
1068 | if ( rightOffset < 0 ) |
1069 | return; |
1070 | |
1071 | if ( rightOffset - 1 >= 0 && helper->containsPrefix( parts[ rightOffset - 1 ].toLower() ) ) { |
1072 | setFamilyName( parts[ rightOffset - 1 ] + spaceStr + parts[ rightOffset ] ); |
1073 | rightOffset--; |
1074 | } else { |
1075 | if ( helper->tradeAsFamilyName() ) |
1076 | setFamilyName( parts[ rightOffset ] ); |
1077 | else |
1078 | setGivenName( parts[ rightOffset ] ); |
1079 | } |
1080 | |
1081 | QString prefix; |
1082 | while ( leftOffset < rightOffset ) { |
1083 | if ( helper->containsTitle( parts[ leftOffset ] ) ) { |
1084 | prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr ) + parts[ leftOffset ] ); |
1085 | leftOffset++; |
1086 | } else |
1087 | break; |
1088 | } |
1089 | setPrefix( prefix ); |
1090 | |
1091 | if ( leftOffset < rightOffset ) { |
1092 | setGivenName( parts[ leftOffset ] ); |
1093 | leftOffset++; |
1094 | } |
1095 | |
1096 | QString additionalName; |
1097 | while ( leftOffset < rightOffset ) { |
1098 | additionalName.append( ( additionalName.isEmpty() ? emptyStr : spaceStr ) + parts[ leftOffset ] ); |
1099 | leftOffset++; |
1100 | } |
1101 | setAdditionalName( additionalName ); |
1102 | } else { |
1103 | QString part1 = str.left( i ); |
1104 | QString part2 = str.mid( i + 1 ); |
1105 | |
1106 | QStringList parts = part1.split( spaceStr ); |
1107 | int leftOffset = 0; |
1108 | int rightOffset = parts.count() - 1; |
1109 | |
1110 | if ( parts.count() > 0 ) { |
1111 | |
1112 | QString suffix; |
1113 | while ( rightOffset >= 0 ) { |
1114 | if ( helper->containsSuffix( parts[ rightOffset ] ) ) { |
1115 | suffix.prepend( parts[ rightOffset ] + ( suffix.isEmpty() ? emptyStr : spaceStr ) ); |
1116 | rightOffset--; |
1117 | } else |
1118 | break; |
1119 | } |
1120 | setSuffix( suffix ); |
1121 | |
1122 | if ( rightOffset - 1 >= 0 && helper->containsPrefix( parts[ rightOffset - 1 ].toLower() ) ) { |
1123 | setFamilyName( parts[ rightOffset - 1 ] + spaceStr + parts[ rightOffset ] ); |
1124 | rightOffset--; |
1125 | } else |
1126 | setFamilyName( parts[ rightOffset ] ); |
1127 | |
1128 | QString prefix; |
1129 | while ( leftOffset < rightOffset ) { |
1130 | if ( helper->containsTitle( parts[ leftOffset ] ) ) { |
1131 | prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr ) + parts[ leftOffset ] ); |
1132 | leftOffset++; |
1133 | } else |
1134 | break; |
1135 | } |
1136 | } else { |
1137 | setPrefix( QString() ); |
1138 | setFamilyName( QString() ); |
1139 | setSuffix( QString() ); |
1140 | } |
1141 | |
1142 | parts = part2.split( spaceStr ); |
1143 | |
1144 | leftOffset = 0; |
1145 | rightOffset = parts.count(); |
1146 | |
1147 | if ( parts.count() > 0 ) { |
1148 | |
1149 | QString prefix; |
1150 | while ( leftOffset < rightOffset ) { |
1151 | if ( helper->containsTitle( parts[ leftOffset ] ) ) { |
1152 | prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr ) + parts[ leftOffset ] ); |
1153 | leftOffset++; |
1154 | } else |
1155 | break; |
1156 | } |
1157 | setPrefix( prefix ); |
1158 | |
1159 | if ( leftOffset < rightOffset ) { |
1160 | setGivenName( parts[ leftOffset ] ); |
1161 | leftOffset++; |
1162 | } |
1163 | |
1164 | QString additionalName; |
1165 | while ( leftOffset < rightOffset ) { |
1166 | additionalName.append( ( additionalName.isEmpty() ? emptyStr : spaceStr ) + parts[ leftOffset ] ); |
1167 | leftOffset++; |
1168 | } |
1169 | setAdditionalName( additionalName ); |
1170 | } else { |
1171 | setGivenName( QString() ); |
1172 | setAdditionalName( QString() ); |
1173 | } |
1174 | } |
1175 | } |
1176 | |
1177 | QString Addressee::realName() const |
1178 | { |
1179 | QString n( formattedName() ); |
1180 | if ( !n.isEmpty() ) |
1181 | return n; |
1182 | |
1183 | n = assembledName(); |
1184 | if ( !n.isEmpty() ) |
1185 | return n; |
1186 | |
1187 | n = name(); |
1188 | if ( !n.isEmpty() ) |
1189 | return n; |
1190 | |
1191 | return organization(); |
1192 | } |
1193 | |
1194 | QString Addressee::assembledName() const |
1195 | { |
1196 | const QString name = prefix() + QLatin1Char( ' ' ) + |
1197 | givenName() + QLatin1Char( ' ' ) + |
1198 | additionalName() + QLatin1Char( ' ' ) + |
1199 | familyName() + QLatin1Char( ' ' ) + |
1200 | suffix(); |
1201 | |
1202 | return name.simplified(); |
1203 | } |
1204 | |
1205 | QString Addressee::fullEmail( const QString &email ) const |
1206 | { |
1207 | QString e; |
1208 | if ( email.isNull() ) { |
1209 | e = preferredEmail(); |
1210 | } else { |
1211 | e = email; |
1212 | } |
1213 | if ( e.isEmpty() ) return QString(); |
1214 | |
1215 | QString text; |
1216 | if ( realName().isEmpty() ) |
1217 | text = e; |
1218 | else { |
1219 | QRegExp needQuotes( QLatin1String( "[^ 0-9A-Za-z\\x0080-\\xFFFF]" ) ); |
1220 | if ( realName().indexOf( needQuotes ) != -1 ) { |
1221 | QString name = realName(); |
1222 | name.replace( QLatin1String( "\"" ), QLatin1String( "\\\"" ) ); |
1223 | text = QLatin1String( "\"" ) + name + QLatin1String( "\" <" ) + e + QLatin1Char( '>' ); |
1224 | } else |
1225 | text = realName() + QLatin1String( " <" ) + e + QLatin1Char( '>' ); |
1226 | } |
1227 | |
1228 | return text; |
1229 | } |
1230 | |
1231 | void Addressee::insertEmail( const QString &email, bool preferred ) |
1232 | { |
1233 | if ( email.simplified().isEmpty() ) |
1234 | return; |
1235 | |
1236 | if ( d->mEmails.contains( email ) ) { |
1237 | if ( !preferred || d->mEmails.first() == email ) |
1238 | return; |
1239 | |
1240 | d->mEmails.removeAll( email ); |
1241 | d->mEmails.prepend( email ); |
1242 | } else { |
1243 | d->mEmpty = false; |
1244 | if ( preferred ) { |
1245 | d->mEmails.prepend( email ); |
1246 | } else { |
1247 | d->mEmails.append( email ); |
1248 | } |
1249 | } |
1250 | } |
1251 | |
1252 | void Addressee::removeEmail( const QString &email ) |
1253 | { |
1254 | if ( d->mEmails.contains( email ) ) { |
1255 | d->mEmails.removeAll( email ); |
1256 | } |
1257 | } |
1258 | |
1259 | QString Addressee::preferredEmail() const |
1260 | { |
1261 | if ( d->mEmails.count() == 0 ) |
1262 | return QString(); |
1263 | else |
1264 | return d->mEmails.first(); |
1265 | } |
1266 | |
1267 | QStringList Addressee::emails() const |
1268 | { |
1269 | return d->mEmails; |
1270 | } |
1271 | |
1272 | void Addressee::setEmails( const QStringList& emails ) |
1273 | { |
1274 | d->mEmails = emails; |
1275 | } |
1276 | void Addressee::insertPhoneNumber( const PhoneNumber &phoneNumber ) |
1277 | { |
1278 | d->mEmpty = false; |
1279 | |
1280 | PhoneNumber::List::Iterator it; |
1281 | for ( it = d->mPhoneNumbers.begin(); it != d->mPhoneNumbers.end(); ++it ) { |
1282 | if ( ( *it ).id() == phoneNumber.id() ) { |
1283 | *it = phoneNumber; |
1284 | return; |
1285 | } |
1286 | } |
1287 | if ( !phoneNumber.number().simplified().isEmpty() ) |
1288 | d->mPhoneNumbers.append( phoneNumber ); |
1289 | } |
1290 | |
1291 | void Addressee::removePhoneNumber( const PhoneNumber &phoneNumber ) |
1292 | { |
1293 | PhoneNumber::List::Iterator it; |
1294 | for ( it = d->mPhoneNumbers.begin(); it != d->mPhoneNumbers.end(); ++it ) { |
1295 | if ( ( *it ).id() == phoneNumber.id() ) { |
1296 | d->mPhoneNumbers.erase( it ); |
1297 | return; |
1298 | } |
1299 | } |
1300 | } |
1301 | |
1302 | PhoneNumber Addressee::phoneNumber( PhoneNumber::Type type ) const |
1303 | { |
1304 | PhoneNumber phoneNumber( QString(), type ); |
1305 | PhoneNumber::List::ConstIterator it; |
1306 | for ( it = d->mPhoneNumbers.constBegin(); it != d->mPhoneNumbers.constEnd(); ++it ) { |
1307 | if ( matchBinaryPattern( ( *it ).type(), type ) ) { |
1308 | if ( ( *it ).type() & PhoneNumber::Pref ) { |
1309 | return ( *it ); |
1310 | } else if ( phoneNumber.number().isEmpty() ) { |
1311 | phoneNumber = ( *it ); |
1312 | } |
1313 | } |
1314 | } |
1315 | |
1316 | return phoneNumber; |
1317 | } |
1318 | |
1319 | PhoneNumber::List Addressee::phoneNumbers() const |
1320 | { |
1321 | return d->mPhoneNumbers; |
1322 | } |
1323 | |
1324 | PhoneNumber::List Addressee::phoneNumbers( PhoneNumber::Type type ) const |
1325 | { |
1326 | PhoneNumber::List list; |
1327 | |
1328 | PhoneNumber::List::ConstIterator it; |
1329 | PhoneNumber::List::ConstIterator end( d->mPhoneNumbers.constEnd() ); |
1330 | for ( it = d->mPhoneNumbers.constBegin(); it != end; ++it ) { |
1331 | if ( matchBinaryPattern( ( *it ).type(), type ) ) { |
1332 | list.append( *it ); |
1333 | } |
1334 | } |
1335 | return list; |
1336 | } |
1337 | |
1338 | PhoneNumber Addressee::findPhoneNumber( const QString &id ) const |
1339 | { |
1340 | PhoneNumber::List::ConstIterator it; |
1341 | PhoneNumber::List::ConstIterator end( d->mPhoneNumbers.constEnd() ); |
1342 | for ( it = d->mPhoneNumbers.constBegin(); it != end; ++it ) { |
1343 | if ( ( *it ).id() == id ) { |
1344 | return *it; |
1345 | } |
1346 | } |
1347 | return PhoneNumber(); |
1348 | } |
1349 | |
1350 | void Addressee::insertKey( const Key &key ) |
1351 | { |
1352 | d->mEmpty = false; |
1353 | |
1354 | Key::List::Iterator it; |
1355 | for ( it = d->mKeys.begin(); it != d->mKeys.end(); ++it ) { |
1356 | if ( ( *it ).id() == key.id() ) { |
1357 | *it = key; |
1358 | return; |
1359 | } |
1360 | } |
1361 | d->mKeys.append( key ); |
1362 | } |
1363 | |
1364 | void Addressee::removeKey( const Key &key ) |
1365 | { |
1366 | Key::List::Iterator it; |
1367 | for ( it = d->mKeys.begin(); it != d->mKeys.end(); ++it ) { |
1368 | if ( ( *it ).id() == key.id() ) { |
1369 | d->mKeys.removeAll( key ); |
1370 | return; |
1371 | } |
1372 | } |
1373 | } |
1374 | |
1375 | Key Addressee::key( Key::Type type, QString customTypeString ) const |
1376 | { |
1377 | Key::List::ConstIterator it; |
1378 | Key::List::ConstIterator end( d->mKeys.constEnd() ); |
1379 | for ( it = d->mKeys.constBegin(); it != end; ++it ) { |
1380 | if ( ( *it ).type() == type ) { |
1381 | if ( type == Key::Custom ) { |
1382 | if ( customTypeString.isEmpty() ) { |
1383 | return *it; |
1384 | } else { |
1385 | if ( ( *it ).customTypeString() == customTypeString ) |
1386 | return ( *it ); |
1387 | } |
1388 | } else { |
1389 | return *it; |
1390 | } |
1391 | } |
1392 | } |
1393 | return Key( QString(), type ); |
1394 | } |
1395 | |
1396 | void Addressee::setKeys( const Key::List& list ) |
1397 | { |
1398 | d->mKeys = list; |
1399 | } |
1400 | |
1401 | Key::List Addressee::keys() const |
1402 | { |
1403 | return d->mKeys; |
1404 | } |
1405 | |
1406 | Key::List Addressee::keys( Key::Type type, QString customTypeString ) const |
1407 | { |
1408 | Key::List list; |
1409 | |
1410 | Key::List::ConstIterator it; |
1411 | Key::List::ConstIterator end( d->mKeys.constEnd() ); |
1412 | for ( it = d->mKeys.constBegin(); it != end; ++it ) { |
1413 | if ( ( *it ).type() == type ) { |
1414 | if ( type == Key::Custom ) { |
1415 | if ( customTypeString.isEmpty() ) { |
1416 | list.append( *it ); |
1417 | } else { |
1418 | if ( ( *it ).customTypeString() == customTypeString ) |
1419 | list.append( *it ); |
1420 | } |
1421 | } else { |
1422 | list.append( *it ); |
1423 | } |
1424 | } |
1425 | } |
1426 | return list; |
1427 | } |
1428 | |
1429 | Key Addressee::findKey( const QString &id ) const |
1430 | { |
1431 | Key::List::ConstIterator it; |
1432 | Key::List::ConstIterator end( d->mKeys.constEnd() ); |
1433 | for ( it = d->mKeys.constBegin(); it != end; ++it ) { |
1434 | if ( ( *it ).id() == id ) { |
1435 | return *it; |
1436 | } |
1437 | } |
1438 | return Key(); |
1439 | } |
1440 | |
1441 | QString Addressee::toString() const |
1442 | { |
1443 | QString str; |
1444 | |
1445 | str += QLatin1String( "Addressee {\n" ); |
1446 | str += QString::fromLatin1( " Uid: %1\n" ).arg( uid() ); |
1447 | |
1448 | str += QString::fromLatin1( " Name: %1\n" ).arg( name() ); |
1449 | str += QString::fromLatin1( " FormattedName: %1\n" ).arg( formattedName() ); |
1450 | str += QString::fromLatin1( " FamilyName: %1\n" ).arg( familyName() ); |
1451 | str += QString::fromLatin1( " GivenName: %1\n" ).arg( givenName() ); |
1452 | str += QString::fromLatin1( " AdditionalName: %1\n" ).arg( additionalName() ); |
1453 | str += QString::fromLatin1( " Prefix: %1\n" ).arg( prefix() ); |
1454 | str += QString::fromLatin1( " Suffix: %1\n" ).arg( suffix() ); |
1455 | str += QString::fromLatin1( " NickName: %1\n" ).arg( nickName() ); |
1456 | str += QString::fromLatin1( " Birthday: %1\n" ).arg( birthday().toString() ); |
1457 | str += QString::fromLatin1( " Mailer: %1\n" ).arg( mailer() ); |
1458 | str += QString::fromLatin1( " TimeZone: %1\n" ).arg( timeZone().toString() ); |
1459 | str += QString::fromLatin1( " Geo: %1\n" ).arg( geo().toString() ); |
1460 | str += QString::fromLatin1( " Title: %1\n" ).arg( title() ); |
1461 | str += QString::fromLatin1( " Role: %1\n" ).arg( role() ); |
1462 | str += QString::fromLatin1( " Organization: %1\n" ).arg( organization() ); |
1463 | str += QString::fromLatin1( " Department: %1\n" ).arg( department() ); |
1464 | str += QString::fromLatin1( " Note: %1\n" ).arg( note() ); |
1465 | str += QString::fromLatin1( " ProductId: %1\n" ).arg( productId() ); |
1466 | str += QString::fromLatin1( " Revision: %1\n" ).arg( revision().toString() ); |
1467 | str += QString::fromLatin1( " SortString: %1\n" ).arg( sortString() ); |
1468 | str += QString::fromLatin1( " Url: %1\n" ).arg( url().url() ); |
1469 | str += QString::fromLatin1( " Secrecy: %1\n" ).arg( secrecy().toString() ); |
1470 | str += QString::fromLatin1( " Logo: %1\n" ).arg( logo().toString() ); |
1471 | str += QString::fromLatin1( " Photo: %1\n" ).arg( photo().toString() ); |
1472 | str += QString::fromLatin1( " Sound: %1\n" ).arg( sound().toString() ); |
1473 | |
1474 | str += QLatin1String( " Emails {\n" ); |
1475 | const QStringList e = emails(); |
1476 | QStringList::ConstIterator it; |
1477 | for ( it = e.begin(); it != e.end(); ++it ) { |
1478 | str += QString::fromLatin1( " %1\n" ).arg( *it ); |
1479 | } |
1480 | str += QLatin1String( " }\n" ); |
1481 | |
1482 | str += QLatin1String( " PhoneNumbers {\n" ); |
1483 | const PhoneNumber::List p = phoneNumbers(); |
1484 | PhoneNumber::List::ConstIterator it2; |
1485 | for ( it2 = p.begin(); it2 != p.end(); ++it2 ) { |
1486 | str += ( *it2 ).toString(); |
1487 | } |
1488 | str += QLatin1String( " }\n" ); |
1489 | |
1490 | str += QLatin1String( " Addresses {\n" ); |
1491 | const Address::List a = addresses(); |
1492 | Address::List::ConstIterator it3; |
1493 | for ( it3 = a.begin(); it3 != a.end(); ++it3 ) { |
1494 | str += ( *it3 ).toString(); |
1495 | } |
1496 | str += QLatin1String( " }\n" ); |
1497 | |
1498 | str += QLatin1String( " Keys {\n" ); |
1499 | const Key::List k = keys(); |
1500 | Key::List::ConstIterator it4; |
1501 | for ( it4 = k.begin(); it4 != k.end(); ++it4 ) { |
1502 | str += ( *it4 ).toString(); |
1503 | } |
1504 | str += QLatin1String( " }\n" ); |
1505 | |
1506 | str += QLatin1String( "}\n" ); |
1507 | |
1508 | return str; |
1509 | } |
1510 | |
1511 | |
1512 | void Addressee::insertAddress( const Address &address ) |
1513 | { |
1514 | if ( address.isEmpty() ) |
1515 | return; |
1516 | |
1517 | d->mEmpty = false; |
1518 | |
1519 | Address::List::Iterator it; |
1520 | for ( it = d->mAddresses.begin(); it != d->mAddresses.end(); ++it ) { |
1521 | if ( ( *it ).id() == address.id() ) { |
1522 | *it = address; |
1523 | return; |
1524 | } |
1525 | } |
1526 | |
1527 | d->mAddresses.append( address ); |
1528 | } |
1529 | |
1530 | void Addressee::removeAddress( const Address &address ) |
1531 | { |
1532 | Address::List::Iterator it; |
1533 | for ( it = d->mAddresses.begin(); it != d->mAddresses.end(); ++it ) { |
1534 | if ( ( *it ).id() == address.id() ) { |
1535 | d->mAddresses.erase( it ); |
1536 | return; |
1537 | } |
1538 | } |
1539 | } |
1540 | |
1541 | Address Addressee::address( Address::Type type ) const |
1542 | { |
1543 | Address address( type ); |
1544 | Address::List::ConstIterator it; |
1545 | Address::List::ConstIterator end( d->mAddresses.constEnd() ); |
1546 | for ( it = d->mAddresses.constBegin(); it != end; ++it ) { |
1547 | if ( matchBinaryPattern( ( *it ).type(), type ) ) { |
1548 | if ( ( *it ).type() & Address::Pref ) { |
1549 | return ( *it ); |
1550 | } else if ( address.isEmpty() ) { |
1551 | address = ( *it ); |
1552 | } |
1553 | } |
1554 | } |
1555 | |
1556 | return address; |
1557 | } |
1558 | |
1559 | Address::List Addressee::addresses() const |
1560 | { |
1561 | return d->mAddresses; |
1562 | } |
1563 | |
1564 | Address::List Addressee::addresses( Address::Type type ) const |
1565 | { |
1566 | Address::List list; |
1567 | |
1568 | Address::List::ConstIterator it; |
1569 | Address::List::ConstIterator end( d->mAddresses.constEnd() ); |
1570 | for ( it = d->mAddresses.constBegin(); it != end; ++it ) { |
1571 | if ( matchBinaryPattern( ( *it ).type(), type ) ) { |
1572 | list.append( *it ); |
1573 | } |
1574 | } |
1575 | |
1576 | return list; |
1577 | } |
1578 | |
1579 | Address Addressee::findAddress( const QString &id ) const |
1580 | { |
1581 | Address::List::ConstIterator it; |
1582 | Address::List::ConstIterator end( d->mAddresses.constEnd() ); |
1583 | for ( it = d->mAddresses.constBegin(); it != end; ++it ) { |
1584 | if ( ( *it ).id() == id ) { |
1585 | return *it; |
1586 | } |
1587 | } |
1588 | return Address(); |
1589 | } |
1590 | |
1591 | void Addressee::insertCategory( const QString &c ) |
1592 | { |
1593 | d->mEmpty = false; |
1594 | |
1595 | if ( d->mCategories.contains( c ) ) |
1596 | return; |
1597 | |
1598 | d->mCategories.append( c ); |
1599 | } |
1600 | |
1601 | void Addressee::removeCategory( const QString &category ) |
1602 | { |
1603 | if ( d->mCategories.contains( category ) ) { |
1604 | d->mCategories.removeAll( category ); |
1605 | } |
1606 | } |
1607 | |
1608 | bool Addressee::hasCategory( const QString &category ) const |
1609 | { |
1610 | return d->mCategories.contains( category ); |
1611 | } |
1612 | |
1613 | void Addressee::setCategories( const QStringList &c ) |
1614 | { |
1615 | d->mEmpty = false; |
1616 | |
1617 | d->mCategories = c; |
1618 | } |
1619 | |
1620 | QStringList Addressee::categories() const |
1621 | { |
1622 | return d->mCategories; |
1623 | } |
1624 | |
1625 | void Addressee::insertCustom( const QString &app, const QString &name, |
1626 | const QString &value ) |
1627 | { |
1628 | if ( value.isEmpty() || name.isEmpty() || app.isEmpty() ) { |
1629 | return; |
1630 | } |
1631 | |
1632 | d->mEmpty = false; |
1633 | |
1634 | const QString qualifiedName = app + QLatin1Char( '-' ) + name; |
1635 | |
1636 | d->mCustomFields.insert( qualifiedName, value ); |
1637 | } |
1638 | |
1639 | void Addressee::removeCustom( const QString &app, const QString &name ) |
1640 | { |
1641 | const QString qualifiedName = app + QLatin1Char( '-' ) + name; |
1642 | |
1643 | d->mCustomFields.remove( qualifiedName ); |
1644 | } |
1645 | |
1646 | QString Addressee::custom( const QString &app, const QString &name ) const |
1647 | { |
1648 | const QString qualifiedName = app + QLatin1Char( '-' ) + name; |
1649 | |
1650 | return d->mCustomFields.value( qualifiedName ); |
1651 | } |
1652 | |
1653 | void Addressee::setCustoms( const QStringList &customs ) |
1654 | { |
1655 | d->mEmpty = false; |
1656 | |
1657 | d->mCustomFields.clear(); |
1658 | |
1659 | foreach ( const QString &custom, customs ) { |
1660 | const int index = custom.indexOf( QLatin1Char( ':' ) ); |
1661 | if ( index == -1 ) |
1662 | continue; |
1663 | |
1664 | const QString qualifiedName = custom.left( index ); |
1665 | const QString value = custom.mid( index + 1 ); |
1666 | |
1667 | d->mCustomFields.insert( qualifiedName, value ); |
1668 | } |
1669 | } |
1670 | |
1671 | QStringList Addressee::customs() const |
1672 | { |
1673 | QStringList result; |
1674 | |
1675 | QMapIterator<QString, QString> it( d->mCustomFields ); |
1676 | while ( it.hasNext() ) { |
1677 | it.next(); |
1678 | result << it.key() + QLatin1Char( ':' ) + it.value(); |
1679 | } |
1680 | |
1681 | return result; |
1682 | } |
1683 | |
1684 | void Addressee::parseEmailAddress( const QString &rawEmail, QString &fullName, |
1685 | QString &email ) |
1686 | { |
1687 | // This is a simplified version of KPIM::splitAddress(). |
1688 | |
1689 | fullName.clear(); |
1690 | email.clear(); |
1691 | if ( rawEmail.isEmpty() ) |
1692 | return; // KPIM::AddressEmpty; |
1693 | |
1694 | // The code works on 8-bit strings, so convert the input to UTF-8. |
1695 | QByteArray address = rawEmail.toUtf8(); |
1696 | |
1697 | QByteArray displayName; |
1698 | QByteArray addrSpec; |
1699 | QByteArray ; |
1700 | |
1701 | // The following is a primitive parser for a mailbox-list (cf. RFC 2822). |
1702 | // The purpose is to extract a displayable string from the mailboxes. |
1703 | // Comments in the addr-spec are not handled. No error checking is done. |
1704 | |
1705 | enum { TopLevel, , InAngleAddress } context = TopLevel; |
1706 | bool inQuotedString = false; |
1707 | int = 0; |
1708 | bool stop = false; |
1709 | |
1710 | for ( char* p = address.data(); *p && !stop; ++p ) { |
1711 | switch ( context ) { |
1712 | case TopLevel : { |
1713 | switch ( *p ) { |
1714 | case '"' : inQuotedString = !inQuotedString; |
1715 | displayName += *p; |
1716 | break; |
1717 | case '(' : if ( !inQuotedString ) { |
1718 | context = InComment; |
1719 | commentLevel = 1; |
1720 | } |
1721 | else |
1722 | displayName += *p; |
1723 | break; |
1724 | case '<' : if ( !inQuotedString ) { |
1725 | context = InAngleAddress; |
1726 | } |
1727 | else |
1728 | displayName += *p; |
1729 | break; |
1730 | case '\\' : // quoted character |
1731 | displayName += *p; |
1732 | ++p; // skip the '\' |
1733 | if ( *p ) |
1734 | displayName += *p; |
1735 | else |
1736 | //return KPIM::UnexpectedEnd; |
1737 | goto ABORT_PARSING; |
1738 | break; |
1739 | case ',' : if ( !inQuotedString ) { |
1740 | //if ( allowMultipleAddresses ) |
1741 | // stop = true; |
1742 | //else |
1743 | // return KPIM::UnexpectedComma; |
1744 | goto ABORT_PARSING; |
1745 | } |
1746 | else |
1747 | displayName += *p; |
1748 | break; |
1749 | default : displayName += *p; |
1750 | } |
1751 | break; |
1752 | } |
1753 | case InComment : { |
1754 | switch ( *p ) { |
1755 | case '(' : ++commentLevel; |
1756 | comment += *p; |
1757 | break; |
1758 | case ')' : --commentLevel; |
1759 | if ( commentLevel == 0 ) { |
1760 | context = TopLevel; |
1761 | comment += ' '; // separate the text of several comments |
1762 | } |
1763 | else |
1764 | comment += *p; |
1765 | break; |
1766 | case '\\' : // quoted character |
1767 | comment += *p; |
1768 | ++p; // skip the '\' |
1769 | if ( *p ) |
1770 | comment += *p; |
1771 | else |
1772 | //return KPIM::UnexpectedEnd; |
1773 | goto ABORT_PARSING; |
1774 | break; |
1775 | default : comment += *p; |
1776 | } |
1777 | break; |
1778 | } |
1779 | case InAngleAddress : { |
1780 | switch ( *p ) { |
1781 | case '"' : inQuotedString = !inQuotedString; |
1782 | addrSpec += *p; |
1783 | break; |
1784 | case '>' : if ( !inQuotedString ) { |
1785 | context = TopLevel; |
1786 | } |
1787 | else |
1788 | addrSpec += *p; |
1789 | break; |
1790 | case '\\' : // quoted character |
1791 | addrSpec += *p; |
1792 | ++p; // skip the '\' |
1793 | if ( *p ) |
1794 | addrSpec += *p; |
1795 | else |
1796 | //return KPIM::UnexpectedEnd; |
1797 | goto ABORT_PARSING; |
1798 | break; |
1799 | default : addrSpec += *p; |
1800 | } |
1801 | break; |
1802 | } |
1803 | } // switch ( context ) |
1804 | } |
1805 | |
1806 | ABORT_PARSING: |
1807 | displayName = displayName.trimmed(); |
1808 | comment = comment.trimmed(); |
1809 | addrSpec = addrSpec.trimmed(); |
1810 | |
1811 | fullName = QString::fromUtf8( displayName ); |
1812 | email = QString::fromUtf8( addrSpec ); |
1813 | |
1814 | // check for errors |
1815 | if ( inQuotedString ) |
1816 | return; // KPIM::UnbalancedQuote; |
1817 | if ( context == InComment ) |
1818 | return; // KPIM::UnbalancedParens; |
1819 | if ( context == InAngleAddress ) |
1820 | return; // KPIM::UnclosedAngleAddr; |
1821 | |
1822 | if ( addrSpec.isEmpty() ) { |
1823 | if ( displayName.isEmpty() ) |
1824 | return; // KPIM::NoAddressSpec; |
1825 | else { |
1826 | //addrSpec = displayName; |
1827 | //displayName.truncate( 0 ); |
1828 | // Address of the form "foo@bar" or "foo@bar (Name)". |
1829 | email = fullName; |
1830 | fullName = QString::fromUtf8( comment ); |
1831 | } |
1832 | } |
1833 | |
1834 | email = email.toLower(); |
1835 | // Check that we do not have any extra characters on the end of the |
1836 | // strings |
1837 | unsigned int len = fullName.length(); |
1838 | if ( fullName[ 0 ] == QLatin1Char( '"' ) && fullName[ len - 1 ] == QLatin1Char( '"' ) ) { |
1839 | fullName = fullName.mid( 1, len - 2 ); |
1840 | } |
1841 | } |
1842 | |
1843 | #ifndef KDEPIM_NO_KRESOURCES |
1844 | void Addressee::setResource( Resource *resource ) |
1845 | { |
1846 | d->mResource = resource; |
1847 | } |
1848 | |
1849 | Resource *Addressee::resource() const |
1850 | { |
1851 | return d->mResource; |
1852 | } |
1853 | #endif |
1854 | |
1855 | void Addressee::setChanged( bool value ) |
1856 | { |
1857 | d->mChanged = value; |
1858 | } |
1859 | |
1860 | bool Addressee::changed() const |
1861 | { |
1862 | return d->mChanged; |
1863 | } |
1864 | |
1865 | void Addressee::setSortMode( KABC::SortMode *mode ) |
1866 | { |
1867 | Private::mSortMode = mode; |
1868 | } |
1869 | |
1870 | bool Addressee::operator< ( const Addressee &addr ) const |
1871 | { |
1872 | if ( !Private::mSortMode ) |
1873 | return false; |
1874 | else |
1875 | return Private::mSortMode->lesser( *this, addr ); |
1876 | } |
1877 | |
1878 | QString Addressee::mimeType() |
1879 | { |
1880 | return QLatin1String( "text/directory" ); |
1881 | } |
1882 | |
1883 | QDataStream &KABC::operator<<( QDataStream &s, const Addressee &a ) |
1884 | { |
1885 | s << a.d->mUid; |
1886 | |
1887 | s << a.d->mName; |
1888 | s << a.d->mFormattedName; |
1889 | s << a.d->mFamilyName; |
1890 | s << a.d->mGivenName; |
1891 | s << a.d->mAdditionalName; |
1892 | s << a.d->mPrefix; |
1893 | s << a.d->mSuffix; |
1894 | s << a.d->mNickName; |
1895 | s << a.d->mBirthday; |
1896 | s << a.d->mMailer; |
1897 | s << a.d->mTimeZone; |
1898 | s << a.d->mGeo; |
1899 | s << a.d->mTitle; |
1900 | s << a.d->mRole; |
1901 | s << a.d->mOrganization; |
1902 | s << a.d->mDepartment; |
1903 | s << a.d->mNote; |
1904 | s << a.d->mProductId; |
1905 | s << a.d->mRevision; |
1906 | s << a.d->mSortString; |
1907 | s << a.d->mUrl; |
1908 | s << a.d->mSecrecy; |
1909 | s << a.d->mLogo; |
1910 | s << a.d->mPhoto; |
1911 | s << a.d->mSound; |
1912 | s << a.d->mPhoneNumbers; |
1913 | s << a.d->mAddresses; |
1914 | s << a.d->mEmails; |
1915 | s << a.d->mCategories; |
1916 | s << a.customs(); |
1917 | s << a.d->mKeys; |
1918 | return s; |
1919 | } |
1920 | |
1921 | QDataStream &KABC::operator>>( QDataStream &s, Addressee &a ) |
1922 | { |
1923 | s >> a.d->mUid; |
1924 | |
1925 | s >> a.d->mName; |
1926 | s >> a.d->mFormattedName; |
1927 | s >> a.d->mFamilyName; |
1928 | s >> a.d->mGivenName; |
1929 | s >> a.d->mAdditionalName; |
1930 | s >> a.d->mPrefix; |
1931 | s >> a.d->mSuffix; |
1932 | s >> a.d->mNickName; |
1933 | s >> a.d->mBirthday; |
1934 | s >> a.d->mMailer; |
1935 | s >> a.d->mTimeZone; |
1936 | s >> a.d->mGeo; |
1937 | s >> a.d->mTitle; |
1938 | s >> a.d->mRole; |
1939 | s >> a.d->mOrganization; |
1940 | s >> a.d->mDepartment; |
1941 | s >> a.d->mNote; |
1942 | s >> a.d->mProductId; |
1943 | s >> a.d->mRevision; |
1944 | s >> a.d->mSortString; |
1945 | s >> a.d->mUrl; |
1946 | s >> a.d->mSecrecy; |
1947 | s >> a.d->mLogo; |
1948 | s >> a.d->mPhoto; |
1949 | s >> a.d->mSound; |
1950 | s >> a.d->mPhoneNumbers; |
1951 | s >> a.d->mAddresses; |
1952 | s >> a.d->mEmails; |
1953 | s >> a.d->mCategories; |
1954 | QStringList customFields; |
1955 | s >> customFields; |
1956 | a.setCustoms( customFields ); |
1957 | s >> a.d->mKeys; |
1958 | |
1959 | a.d->mEmpty = false; |
1960 | |
1961 | return s; |
1962 | } |
1963 | |
1964 | bool matchBinaryPattern( int value, int pattern ) |
1965 | { |
1966 | /** |
1967 | We want to match all telephonnumbers/addresses which have the bits in the |
1968 | pattern set. More are allowed. |
1969 | if pattern == 0 we have a special handling, then we want only those with |
1970 | exactly no bit set. |
1971 | */ |
1972 | if ( pattern == 0 ) |
1973 | return ( value == 0 ); |
1974 | else |
1975 | return ( pattern == ( pattern & value ) ); |
1976 | } |
1977 | |
1978 | template <class L> |
1979 | bool listEquals( const QList<L> &list, const QList<L> &pattern ) |
1980 | { |
1981 | if ( list.count() != pattern.count() ) |
1982 | return false; |
1983 | const int numberOfElement( list.count() ); |
1984 | for ( int i = 0; i < numberOfElement; ++i ) { |
1985 | if ( !pattern.contains( list[ i ] ) ) { |
1986 | return false; |
1987 | } |
1988 | } |
1989 | |
1990 | return true; |
1991 | } |
1992 | |
1993 | bool listEquals( const QStringList &list, const QStringList &pattern ) |
1994 | { |
1995 | if ( list.count() != pattern.count() ) |
1996 | return false; |
1997 | |
1998 | const int numberOfElement( list.count() ); |
1999 | for ( int i = 0; i < numberOfElement; ++i ) { |
2000 | if ( !pattern.contains( list[ i ] ) ) { |
2001 | return false; |
2002 | } |
2003 | } |
2004 | |
2005 | return true; |
2006 | } |
2007 | |
2008 | bool emailsEquals( const QStringList &list, const QStringList &pattern ) |
2009 | { |
2010 | if ( list.count() != pattern.count() ) |
2011 | return false; |
2012 | |
2013 | if ( list.isEmpty() ) |
2014 | return true; |
2015 | |
2016 | if ( list.first() != pattern.first() ) |
2017 | return false; |
2018 | |
2019 | QStringList::ConstIterator it; |
2020 | QStringList::ConstIterator end( list.constEnd() ); |
2021 | for ( it = list.constBegin(); it != end; ++it ) { |
2022 | if ( !pattern.contains( *it ) ) { |
2023 | return false; |
2024 | } |
2025 | } |
2026 | |
2027 | return true; |
2028 | } |
2029 | |