00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <qregexp.h>
00024
00025 #include <ksharedptr.h>
00026 #include <kdebug.h>
00027 #include <kapplication.h>
00028 #include <klocale.h>
00029
00030 #include "addresseehelper.h"
00031 #include "field.h"
00032 #include "resource.h"
00033 #include "sortmode.h"
00034
00035 #include "addressee.h"
00036
00037 using namespace KABC;
00038
00039 static bool matchBinaryPattern( int value, int pattern );
00040
00041 template <class L>
00042 static bool listEquals( const QValueList<L>&, const QValueList<L>& );
00043 static bool emailsEquals( const QStringList&, const QStringList& );
00044
00045 KABC::SortMode *Addressee::mSortMode = 0;
00046
00047 struct Addressee::AddresseeData : public KShared
00048 {
00049 QString uid;
00050 --VARIABLES--
00051
00052 PhoneNumber::List phoneNumbers;
00053 Address::List addresses;
00054 Key::List keys;
00055 QStringList emails;
00056 QStringList categories;
00057 QStringList custom;
00058
00059 Resource *resource;
00060
00061 bool empty :1;
00062 bool changed :1;
00063 };
00064
00065 Addressee::AddresseeData* Addressee::shared_null = 0;
00066
00067 Addressee::AddresseeData* Addressee::makeSharedNull()
00068 {
00069 Addressee::shared_null = new AddresseeData;
00070 shared_null->_KShared_ref();
00071 shared_null->empty = true;
00072 shared_null->changed = false;
00073 shared_null->resource = 0;
00074 return shared_null;
00075 }
00076
00077 Addressee::Addressee()
00078 {
00079 mData = shared_null ? shared_null : makeSharedNull();
00080 }
00081
00082 Addressee::~Addressee()
00083 {
00084 }
00085
00086 Addressee::Addressee( const Addressee &a )
00087 {
00088 mData = a.mData;
00089 }
00090
00091 Addressee &Addressee::operator=( const Addressee &a )
00092 {
00093 if ( this == &a )
00094 return (*this);
00095
00096 mData = a.mData;
00097 return (*this);
00098 }
00099
00100 void Addressee::detach()
00101 {
00102 if ( mData.data() == shared_null ) {
00103 mData = new AddresseeData;
00104 mData->empty = true;
00105 mData->changed = false;
00106 mData->resource = 0;
00107 mData->uid = KApplication::randomString( 10 );
00108 return;
00109 } else if ( mData.count() == 1 ) return;
00110
00111 AddresseeData data = *mData;
00112 mData = new AddresseeData( data );
00113 }
00114
00115 bool Addressee::operator==( const Addressee &a ) const
00116 {
00117 if ( uid() != a.uid() ) {
00118 kdDebug(5700) << "uid differs" << endl;
00119 return false;
00120 }
00121 --EQUALSTEST--
00122 if ( ( mData->url.isValid() || a.mData->url.isValid() ) &&
00123 ( mData->url != a.mData->url ) ) {
00124 kdDebug(5700) << "url differs" << endl;
00125 return false;
00126 }
00127 if ( !listEquals( mData->phoneNumbers, a.mData->phoneNumbers ) ) {
00128 kdDebug(5700) << "phoneNumbers differs" << endl;
00129 return false;
00130 }
00131 if ( !listEquals( mData->addresses, a.mData->addresses ) ) {
00132 kdDebug(5700) << "addresses differs" << endl;
00133 return false;
00134 }
00135 if ( !listEquals( mData->keys, a.mData->keys ) ) {
00136 kdDebug(5700) << "keys differs" << endl;
00137 return false;
00138 }
00139 if ( !emailsEquals( mData->emails, a.mData->emails ) ) {
00140 kdDebug(5700) << "emails differs" << endl;
00141 return false;
00142 }
00143 if ( !listEquals( mData->categories, a.mData->categories ) ) {
00144 kdDebug(5700) << "categories differs" << endl;
00145 return false;
00146 }
00147 if ( !listEquals( mData->custom, a.mData->custom ) ) {
00148 kdDebug(5700) << "custom differs" << endl;
00149 return false;
00150 }
00151
00152 return true;
00153 }
00154
00155 bool Addressee::operator!=( const Addressee &a ) const
00156 {
00157 return !( a == *this );
00158 }
00159
00160 bool Addressee::isEmpty() const
00161 {
00162 return mData->empty;
00163 }
00164
00165 void Addressee::setUid( const QString &id )
00166 {
00167 if ( id == mData->uid ) return;
00168 detach();
00169 mData->empty = false;
00170 mData->uid = id;
00171 }
00172
00173 QString Addressee::uid() const
00174 {
00175 return mData->uid;
00176 }
00177
00178 QString Addressee::uidLabel()
00179 {
00180 return i18n("Unique Identifier");
00181 }
00182
00183 --DEFINITIONS--
00184
00185 void Addressee::setNameFromString( const QString &s )
00186 {
00187 QString str = s;
00188
00189 if ( str.length() > 1 && s[ 0 ] == '"' && s[ s.length() - 1 ] == '"' )
00190 str = s.mid( 1, s.length() - 2 );
00191
00192 setFormattedName( str );
00193 setName( str );
00194
00195
00196 setPrefix( QString::null );
00197 setGivenName( QString::null );
00198 setAdditionalName( QString::null );
00199 setFamilyName( QString::null );
00200 setSuffix( QString::null );
00201
00202 if ( str.isEmpty() )
00203 return;
00204
00205 QString spaceStr = " ";
00206 QString emptyStr = "";
00207 AddresseeHelper *helper = AddresseeHelper::self();
00208
00209 int i = str.find( ',' );
00210 if( i < 0 ) {
00211 QStringList parts = QStringList::split( spaceStr, str );
00212 int leftOffset = 0;
00213 int rightOffset = parts.count() - 1;
00214
00215 QString suffix;
00216 while ( rightOffset >= 0 ) {
00217 if ( helper->containsSuffix( parts[ rightOffset ] ) ) {
00218 suffix.prepend(parts[ rightOffset ] + (suffix.isEmpty() ? emptyStr : spaceStr));
00219 rightOffset--;
00220 } else
00221 break;
00222 }
00223 setSuffix( suffix );
00224
00225 if ( rightOffset < 0 )
00226 return;
00227
00228 QStringList inclusionList;
00229 for ( int n = 1; (rightOffset - n >= 0) && (n < 4); ++n ) {
00230 if ( helper->containsPrefix( parts[ rightOffset - n ].lower() ) ) {
00231 inclusionList.prepend( parts[ rightOffset - n ] );
00232 } else
00233 break;
00234 }
00235
00236 if ( !inclusionList.isEmpty() ) {
00237 setFamilyName( inclusionList.join( " " ) + spaceStr + parts[ rightOffset ] );
00238 rightOffset -= inclusionList.count();
00239 } else {
00240 if ( helper->tradeAsFamilyName() )
00241 setFamilyName( parts[ rightOffset ] );
00242 else
00243 setGivenName( parts[ rightOffset ] );
00244 }
00245
00246 QString prefix;
00247 while ( leftOffset < rightOffset ) {
00248 if ( helper->containsTitle( parts[ leftOffset ] ) ) {
00249 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
00250 leftOffset++;
00251 } else
00252 break;
00253 }
00254 setPrefix( prefix );
00255
00256 if ( leftOffset < rightOffset ) {
00257 setGivenName( parts[ leftOffset ] );
00258 leftOffset++;
00259 }
00260
00261 QString additionalName;
00262 while ( leftOffset < rightOffset ) {
00263 additionalName.append( ( additionalName.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
00264 leftOffset++;
00265 }
00266 setAdditionalName( additionalName );
00267 } else {
00268 QString part1 = str.left( i );
00269 QString part2 = str.mid( i + 1 );
00270
00271 QStringList parts = QStringList::split( spaceStr, part1 );
00272 int leftOffset = 0;
00273 int rightOffset = parts.count() - 1;
00274
00275 if ( parts.count() > 0 ) {
00276
00277 QString suffix;
00278 while ( rightOffset >= 0 ) {
00279 if ( helper->containsSuffix( parts[ rightOffset ] ) ) {
00280 suffix.prepend(parts[ rightOffset ] + (suffix.isEmpty() ? emptyStr : spaceStr));
00281 rightOffset--;
00282 } else
00283 break;
00284 }
00285 setSuffix( suffix );
00286
00287 if ( rightOffset - 1 >= 0 && helper->containsPrefix( parts[ rightOffset - 1 ].lower() ) ) {
00288 setFamilyName( parts[ rightOffset - 1 ] + spaceStr + parts[ rightOffset ] );
00289 rightOffset--;
00290 } else
00291 setFamilyName( parts[ rightOffset ] );
00292
00293 QString prefix;
00294 while ( leftOffset < rightOffset ) {
00295 if ( helper->containsTitle( parts[ leftOffset ] ) ) {
00296 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
00297 leftOffset++;
00298 } else
00299 break;
00300 }
00301 } else {
00302 setPrefix( "" );
00303 setFamilyName( "" );
00304 setSuffix( "" );
00305 }
00306
00307 parts = QStringList::split( spaceStr, part2 );
00308
00309 leftOffset = 0;
00310 rightOffset = parts.count();
00311
00312 if ( parts.count() > 0 ) {
00313
00314 QString prefix;
00315 while ( leftOffset < rightOffset ) {
00316 if ( helper->containsTitle( parts[ leftOffset ] ) ) {
00317 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
00318 leftOffset++;
00319 } else
00320 break;
00321 }
00322 setPrefix( prefix );
00323
00324 if ( leftOffset < rightOffset ) {
00325 setGivenName( parts[ leftOffset ] );
00326 leftOffset++;
00327 }
00328
00329 QString additionalName;
00330 while ( leftOffset < rightOffset ) {
00331 additionalName.append( ( additionalName.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
00332 leftOffset++;
00333 }
00334 setAdditionalName( additionalName );
00335 } else {
00336 setGivenName( "" );
00337 setAdditionalName( "" );
00338 }
00339 }
00340 }
00341
00342 QString Addressee::realName() const
00343 {
00344 QString n( formattedName() );
00345 if ( !n.isEmpty() )
00346 return n;
00347
00348 n = assembledName();
00349 if ( !n.isEmpty() )
00350 return n;
00351
00352 n = name();
00353 if ( !n.isEmpty() )
00354 return n;
00355
00356 return organization();
00357 }
00358
00359 QString Addressee::assembledName() const
00360 {
00361 QString name = prefix() + " " + givenName() + " " + additionalName() + " " +
00362 familyName() + " " + suffix();
00363
00364 return name.simplifyWhiteSpace();
00365 }
00366
00367 QString Addressee::fullEmail( const QString &email ) const
00368 {
00369 QString e;
00370 if ( email.isNull() ) {
00371 e = preferredEmail();
00372 } else {
00373 e = email;
00374 }
00375 if ( e.isEmpty() ) return QString::null;
00376
00377 QString text;
00378 if ( realName().isEmpty() )
00379 text = e;
00380 else {
00381 QRegExp needQuotes( "[^ 0-9A-Za-z\\x0080-\\xFFFF]" );
00382 if ( realName().find( needQuotes ) != -1 )
00383 text = "\"" + realName() + "\" <" + e + ">";
00384 else
00385 text = realName() + " <" + e + ">";
00386 }
00387
00388 return text;
00389 }
00390
00391 void Addressee::insertEmail( const QString &email, bool preferred )
00392 {
00393 if ( email.simplifyWhiteSpace().isEmpty() )
00394 return;
00395
00396 detach();
00397 mData->empty = false;
00398
00399 QStringList::Iterator it = mData->emails.find( email );
00400
00401 if ( it != mData->emails.end() ) {
00402 if ( !preferred || it == mData->emails.begin() ) return;
00403 mData->emails.remove( it );
00404 mData->emails.prepend( email );
00405 } else {
00406 if ( preferred ) {
00407 mData->emails.prepend( email );
00408 } else {
00409 mData->emails.append( email );
00410 }
00411 }
00412 }
00413
00414 void Addressee::removeEmail( const QString &email )
00415 {
00416 detach();
00417
00418 QStringList::Iterator it = mData->emails.find( email );
00419 if ( it == mData->emails.end() ) return;
00420
00421 mData->emails.remove( it );
00422 }
00423
00424 QString Addressee::preferredEmail() const
00425 {
00426 if ( mData->emails.count() == 0 ) return QString::null;
00427 else return mData->emails.first();
00428 }
00429
00430 QStringList Addressee::emails() const
00431 {
00432 return mData->emails;
00433 }
00434 void Addressee::setEmails( const QStringList& emails ) {
00435 detach();
00436
00437 mData->emails = emails;
00438 }
00439 void Addressee::insertPhoneNumber( const PhoneNumber &phoneNumber )
00440 {
00441 detach();
00442 mData->empty = false;
00443
00444 PhoneNumber::List::Iterator it;
00445 for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) {
00446 if ( (*it).id() == phoneNumber.id() ) {
00447 *it = phoneNumber;
00448 return;
00449 }
00450 }
00451 if ( !phoneNumber.number().simplifyWhiteSpace().isEmpty() )
00452 mData->phoneNumbers.append( phoneNumber );
00453 }
00454
00455 void Addressee::removePhoneNumber( const PhoneNumber &phoneNumber )
00456 {
00457 detach();
00458
00459 PhoneNumber::List::Iterator it;
00460 for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) {
00461 if ( (*it).id() == phoneNumber.id() ) {
00462 mData->phoneNumbers.remove( it );
00463 return;
00464 }
00465 }
00466 }
00467
00468 PhoneNumber Addressee::phoneNumber( int type ) const
00469 {
00470 PhoneNumber phoneNumber( "", type );
00471 PhoneNumber::List::ConstIterator it;
00472 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
00473 if ( matchBinaryPattern( (*it).type(), type ) ) {
00474 if ( (*it).type() & PhoneNumber::Pref )
00475 return (*it);
00476 else if ( phoneNumber.number().isEmpty() )
00477 phoneNumber = (*it);
00478 }
00479 }
00480
00481 return phoneNumber;
00482 }
00483
00484 PhoneNumber::List Addressee::phoneNumbers() const
00485 {
00486 return mData->phoneNumbers;
00487 }
00488
00489 PhoneNumber::List Addressee::phoneNumbers( int type ) const
00490 {
00491 PhoneNumber::List list;
00492
00493 PhoneNumber::List::ConstIterator it;
00494 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
00495 if ( matchBinaryPattern( (*it).type(), type ) ) {
00496 list.append( *it );
00497 }
00498 }
00499 return list;
00500 }
00501
00502 PhoneNumber Addressee::findPhoneNumber( const QString &id ) const
00503 {
00504 PhoneNumber::List::ConstIterator it;
00505 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
00506 if ( (*it).id() == id ) {
00507 return *it;
00508 }
00509 }
00510 return PhoneNumber();
00511 }
00512
00513 void Addressee::insertKey( const Key &key )
00514 {
00515 detach();
00516 mData->empty = false;
00517
00518 Key::List::Iterator it;
00519 for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) {
00520 if ( (*it).id() == key.id() ) {
00521 *it = key;
00522 return;
00523 }
00524 }
00525 mData->keys.append( key );
00526 }
00527
00528 void Addressee::removeKey( const Key &key )
00529 {
00530 detach();
00531
00532 Key::List::Iterator it;
00533 for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) {
00534 if ( (*it).id() == key.id() ) {
00535 mData->keys.remove( key );
00536 return;
00537 }
00538 }
00539 }
00540
00541 Key Addressee::key( int type, QString customTypeString ) const
00542 {
00543 Key::List::ConstIterator it;
00544 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
00545 if ( (*it).type() == type ) {
00546 if ( type == Key::Custom ) {
00547 if ( customTypeString.isEmpty() ) {
00548 return *it;
00549 } else {
00550 if ( (*it).customTypeString() == customTypeString )
00551 return (*it);
00552 }
00553 } else {
00554 return *it;
00555 }
00556 }
00557 }
00558 return Key( QString(), type );
00559 }
00560
00561 void Addressee::setKeys( const Key::List& list )
00562 {
00563 detach();
00564 mData->keys = list;
00565 }
00566
00567 Key::List Addressee::keys() const
00568 {
00569 return mData->keys;
00570 }
00571
00572 Key::List Addressee::keys( int type, QString customTypeString ) const
00573 {
00574 Key::List list;
00575
00576 Key::List::ConstIterator it;
00577 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
00578 if ( (*it).type() == type ) {
00579 if ( type == Key::Custom ) {
00580 if ( customTypeString.isEmpty() ) {
00581 list.append( *it );
00582 } else {
00583 if ( (*it).customTypeString() == customTypeString )
00584 list.append( *it );
00585 }
00586 } else {
00587 list.append( *it );
00588 }
00589 }
00590 }
00591 return list;
00592 }
00593
00594 Key Addressee::findKey( const QString &id ) const
00595 {
00596 Key::List::ConstIterator it;
00597 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
00598 if ( (*it).id() == id ) {
00599 return *it;
00600 }
00601 }
00602 return Key();
00603 }
00604
00605 QString Addressee::asString() const
00606 {
00607 return "Smith, agent Smith...";
00608 }
00609
00610 void Addressee::dump() const
00611 {
00612 kdDebug(5700) << "Addressee {" << endl;
00613
00614 kdDebug(5700) << " Uid: '" << uid() << "'" << endl;
00615
00616 --DEBUG--
00617
00618 kdDebug(5700) << " Emails {" << endl;
00619 const QStringList e = emails();
00620 QStringList::ConstIterator it;
00621 for( it = e.begin(); it != e.end(); ++it ) {
00622 kdDebug(5700) << " " << (*it) << endl;
00623 }
00624 kdDebug(5700) << " }" << endl;
00625
00626 kdDebug(5700) << " PhoneNumbers {" << endl;
00627 const PhoneNumber::List p = phoneNumbers();
00628 PhoneNumber::List::ConstIterator it2;
00629 for( it2 = p.begin(); it2 != p.end(); ++it2 ) {
00630 kdDebug(5700) << " Type: " << int((*it2).type()) << " Number: " << (*it2).number() << endl;
00631 }
00632 kdDebug(5700) << " }" << endl;
00633
00634 const Address::List a = addresses();
00635 Address::List::ConstIterator it3;
00636 for( it3 = a.begin(); it3 != a.end(); ++it3 ) {
00637 (*it3).dump();
00638 }
00639
00640 kdDebug(5700) << " Keys {" << endl;
00641 const Key::List k = keys();
00642 Key::List::ConstIterator it4;
00643 for( it4 = k.begin(); it4 != k.end(); ++it4 ) {
00644 kdDebug(5700) << " Type: " << int((*it4).type()) <<
00645 " Key: " << (*it4).textData() <<
00646 " CustomString: " << (*it4).customTypeString() << endl;
00647 }
00648 kdDebug(5700) << " }" << endl;
00649
00650 kdDebug(5700) << "}" << endl;
00651 }
00652
00653
00654 void Addressee::insertAddress( const Address &address )
00655 {
00656 if ( address.isEmpty() )
00657 return;
00658
00659 detach();
00660 mData->empty = false;
00661
00662 Address::List::Iterator it;
00663 for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) {
00664 if ( (*it).id() == address.id() ) {
00665 *it = address;
00666 return;
00667 }
00668 }
00669
00670 mData->addresses.append( address );
00671 }
00672
00673 void Addressee::removeAddress( const Address &address )
00674 {
00675 detach();
00676
00677 Address::List::Iterator it;
00678 for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) {
00679 if ( (*it).id() == address.id() ) {
00680 mData->addresses.remove( it );
00681 return;
00682 }
00683 }
00684 }
00685
00686 Address Addressee::address( int type ) const
00687 {
00688 Address address( type );
00689 Address::List::ConstIterator it;
00690 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
00691 if ( matchBinaryPattern( (*it).type(), type ) ) {
00692 if ( (*it).type() & Address::Pref )
00693 return (*it);
00694 else if ( address.isEmpty() )
00695 address = (*it);
00696 }
00697 }
00698
00699 return address;
00700 }
00701
00702 Address::List Addressee::addresses() const
00703 {
00704 return mData->addresses;
00705 }
00706
00707 Address::List Addressee::addresses( int type ) const
00708 {
00709 Address::List list;
00710
00711 Address::List::ConstIterator it;
00712 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
00713 if ( matchBinaryPattern( (*it).type(), type ) ) {
00714 list.append( *it );
00715 }
00716 }
00717
00718 return list;
00719 }
00720
00721 Address Addressee::findAddress( const QString &id ) const
00722 {
00723 Address::List::ConstIterator it;
00724 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
00725 if ( (*it).id() == id ) {
00726 return *it;
00727 }
00728 }
00729 return Address();
00730 }
00731
00732 void Addressee::insertCategory( const QString &c )
00733 {
00734 detach();
00735 mData->empty = false;
00736
00737 if ( mData->categories.findIndex( c ) != -1 ) return;
00738
00739 mData->categories.append( c );
00740 }
00741
00742 void Addressee::removeCategory( const QString &c )
00743 {
00744 detach();
00745
00746 QStringList::Iterator it = mData->categories.find( c );
00747 if ( it == mData->categories.end() ) return;
00748
00749 mData->categories.remove( it );
00750 }
00751
00752 bool Addressee::hasCategory( const QString &c ) const
00753 {
00754 return ( mData->categories.findIndex( c ) != -1 );
00755 }
00756
00757 void Addressee::setCategories( const QStringList &c )
00758 {
00759 detach();
00760 mData->empty = false;
00761
00762 mData->categories = c;
00763 }
00764
00765 QStringList Addressee::categories() const
00766 {
00767 return mData->categories;
00768 }
00769
00770 void Addressee::insertCustom( const QString &app, const QString &name,
00771 const QString &value )
00772 {
00773 if ( value.isEmpty() || name.isEmpty() || app.isEmpty() ) return;
00774
00775 detach();
00776 mData->empty = false;
00777
00778 QString qualifiedName = app + "-" + name + ":";
00779
00780 QStringList::Iterator it;
00781 for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) {
00782 if ( (*it).startsWith( qualifiedName ) ) {
00783 (*it) = qualifiedName + value;
00784 return;
00785 }
00786 }
00787
00788 mData->custom.append( qualifiedName + value );
00789 }
00790
00791 void Addressee::removeCustom( const QString &app, const QString &name)
00792 {
00793 detach();
00794
00795 QString qualifiedName = app + "-" + name + ":";
00796
00797 QStringList::Iterator it;
00798 for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) {
00799 if ( (*it).startsWith( qualifiedName ) ) {
00800 mData->custom.remove( it );
00801 return;
00802 }
00803 }
00804 }
00805
00806 QString Addressee::custom( const QString &app, const QString &name ) const
00807 {
00808 QString qualifiedName = app + "-" + name + ":";
00809 QString value;
00810
00811 QStringList::ConstIterator it;
00812 for( it = mData->custom.constBegin(); it != mData->custom.constEnd(); ++it ) {
00813 if ( (*it).startsWith( qualifiedName ) ) {
00814 value = (*it).mid( (*it).find( ":" ) + 1 );
00815 break;
00816 }
00817 }
00818
00819 return value;
00820 }
00821
00822 void Addressee::setCustoms( const QStringList &l )
00823 {
00824 detach();
00825 mData->empty = false;
00826
00827 mData->custom = l;
00828 }
00829
00830 QStringList Addressee::customs() const
00831 {
00832 return mData->custom;
00833 }
00834
00835 void Addressee::parseEmailAddress( const QString &rawEmail, QString &fullName,
00836 QString &email)
00837 {
00838
00839
00840 fullName = "";
00841 email = "";
00842 if ( rawEmail.isEmpty() )
00843 return;
00844
00845
00846 QCString address = rawEmail.utf8();
00847
00848 QCString displayName;
00849 QCString addrSpec;
00850 QCString comment;
00851
00852
00853
00854
00855
00856 enum { TopLevel, InComment, InAngleAddress } context = TopLevel;
00857 bool inQuotedString = false;
00858 int commentLevel = 0;
00859 bool stop = false;
00860
00861 for ( char* p = address.data(); *p && !stop; ++p ) {
00862 switch ( context ) {
00863 case TopLevel : {
00864 switch ( *p ) {
00865 case '"' : inQuotedString = !inQuotedString;
00866 displayName += *p;
00867 break;
00868 case '(' : if ( !inQuotedString ) {
00869 context = InComment;
00870 commentLevel = 1;
00871 }
00872 else
00873 displayName += *p;
00874 break;
00875 case '<' : if ( !inQuotedString ) {
00876 context = InAngleAddress;
00877 }
00878 else
00879 displayName += *p;
00880 break;
00881 case '\\' :
00882 displayName += *p;
00883 ++p;
00884 if ( *p )
00885 displayName += *p;
00886 else
00887
00888 goto ABORT_PARSING;
00889 break;
00890 case ',' : if ( !inQuotedString ) {
00891
00892
00893
00894
00895 goto ABORT_PARSING;
00896 }
00897 else
00898 displayName += *p;
00899 break;
00900 default : displayName += *p;
00901 }
00902 break;
00903 }
00904 case InComment : {
00905 switch ( *p ) {
00906 case '(' : ++commentLevel;
00907 comment += *p;
00908 break;
00909 case ')' : --commentLevel;
00910 if ( commentLevel == 0 ) {
00911 context = TopLevel;
00912 comment += ' ';
00913 }
00914 else
00915 comment += *p;
00916 break;
00917 case '\\' :
00918 comment += *p;
00919 ++p;
00920 if ( *p )
00921 comment += *p;
00922 else
00923
00924 goto ABORT_PARSING;
00925 break;
00926 default : comment += *p;
00927 }
00928 break;
00929 }
00930 case InAngleAddress : {
00931 switch ( *p ) {
00932 case '"' : inQuotedString = !inQuotedString;
00933 addrSpec += *p;
00934 break;
00935 case '>' : if ( !inQuotedString ) {
00936 context = TopLevel;
00937 }
00938 else
00939 addrSpec += *p;
00940 break;
00941 case '\\' :
00942 addrSpec += *p;
00943 ++p;
00944 if ( *p )
00945 addrSpec += *p;
00946 else
00947
00948 goto ABORT_PARSING;
00949 break;
00950 default : addrSpec += *p;
00951 }
00952 break;
00953 }
00954 }
00955 }
00956
00957 ABORT_PARSING:
00958 displayName = displayName.stripWhiteSpace();
00959 comment = comment.stripWhiteSpace();
00960 addrSpec = addrSpec.stripWhiteSpace();
00961
00962 fullName = QString::fromUtf8( displayName );
00963 email = QString::fromUtf8( addrSpec );
00964
00965
00966 if ( inQuotedString )
00967 return;
00968 if ( context == InComment )
00969 return;
00970 if ( context == InAngleAddress )
00971 return;
00972
00973 if ( addrSpec.isEmpty() ) {
00974 if ( displayName.isEmpty() )
00975 return;
00976 else {
00977
00978
00979
00980 email = fullName;
00981 fullName = QString::fromUtf8( comment );
00982 }
00983 }
00984
00985
00986
00987 unsigned int len = fullName.length();
00988 if ( fullName[ 0 ] == '"' && fullName[ len - 1 ] == '"' )
00989 fullName = fullName.mid( 1, len - 2 );
00990 }
00991
00992 void Addressee::setResource( Resource *resource )
00993 {
00994 detach();
00995 mData->resource = resource;
00996 }
00997
00998 Resource *Addressee::resource() const
00999 {
01000 return mData->resource;
01001 }
01002
01003 void Addressee::setChanged( bool value )
01004 {
01005 detach();
01006 mData->changed = value;
01007 }
01008
01009 bool Addressee::changed() const
01010 {
01011 return mData->changed;
01012 }
01013
01014 void Addressee::setSortMode( KABC::SortMode *mode )
01015 {
01016 mSortMode = mode;
01017 }
01018
01019 bool Addressee::operator< ( const Addressee &addr )
01020 {
01021 if ( !mSortMode )
01022 return false;
01023 else
01024 return mSortMode->lesser( *this, addr );
01025 }
01026
01027 QDataStream &KABC::operator<<( QDataStream &s, const Addressee &a )
01028 {
01029 if (!a.mData) return s;
01030
01031 s << a.uid();
01032
01033 --STREAMOUT--
01034 s << a.mData->phoneNumbers;
01035 s << a.mData->addresses;
01036 s << a.mData->emails;
01037 s << a.mData->categories;
01038 s << a.mData->custom;
01039 s << a.mData->keys;
01040 return s;
01041 }
01042
01043 QDataStream &KABC::operator>>( QDataStream &s, Addressee &a )
01044 {
01045 if (!a.mData)
01046 return s;
01047
01048 a.detach();
01049
01050 s >> a.mData->uid;
01051
01052 --STREAMIN--
01053 s >> a.mData->phoneNumbers;
01054 s >> a.mData->addresses;
01055 s >> a.mData->emails;
01056 s >> a.mData->categories;
01057 s >> a.mData->custom;
01058 s >> a.mData->keys;
01059
01060 a.mData->empty = false;
01061
01062 return s;
01063 }
01064
01065 bool matchBinaryPattern( int value, int pattern )
01066 {
01073 if ( pattern == 0 )
01074 return ( value == 0 );
01075 else
01076 return ( pattern == ( pattern & value ) );
01077 }
01078
01079 template <class L>
01080 bool listEquals( const QValueList<L> &list, const QValueList<L> &pattern )
01081 {
01082 if ( list.count() != pattern.count() )
01083 return false;
01084
01085 for ( uint i = 0; i < list.count(); ++i )
01086 if ( pattern.find( list[ i ] ) == pattern.end() )
01087 return false;
01088
01089 return true;
01090 }
01091
01092 bool emailsEquals( const QStringList &list, const QStringList &pattern )
01093 {
01094 if ( list.count() != pattern.count() )
01095 return false;
01096
01097 if ( list.first() != pattern.first() )
01098 return false;
01099
01100 QStringList::ConstIterator it;
01101 for ( it = list.begin(); it != list.end(); ++it )
01102 if ( pattern.find( *it ) == pattern.end() )
01103 return false;
01104
01105 return true;
01106 }