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 QString name = realName();
00384 name.replace( "\"", "\\\"" );
00385 text = "\"" + name + "\" <" + e + ">";
00386 } else
00387 text = realName() + " <" + e + ">";
00388 }
00389
00390 return text;
00391 }
00392
00393 void Addressee::insertEmail( const QString &email, bool preferred )
00394 {
00395 if ( email.simplifyWhiteSpace().isEmpty() )
00396 return;
00397
00398 detach();
00399 mData->empty = false;
00400
00401 QStringList::Iterator it = mData->emails.find( email );
00402
00403 if ( it != mData->emails.end() ) {
00404 if ( !preferred || it == mData->emails.begin() ) return;
00405 mData->emails.remove( it );
00406 mData->emails.prepend( email );
00407 } else {
00408 if ( preferred ) {
00409 mData->emails.prepend( email );
00410 } else {
00411 mData->emails.append( email );
00412 }
00413 }
00414 }
00415
00416 void Addressee::removeEmail( const QString &email )
00417 {
00418 detach();
00419
00420 QStringList::Iterator it = mData->emails.find( email );
00421 if ( it == mData->emails.end() ) return;
00422
00423 mData->emails.remove( it );
00424 }
00425
00426 QString Addressee::preferredEmail() const
00427 {
00428 if ( mData->emails.count() == 0 ) return QString::null;
00429 else return mData->emails.first();
00430 }
00431
00432 QStringList Addressee::emails() const
00433 {
00434 return mData->emails;
00435 }
00436 void Addressee::setEmails( const QStringList& emails ) {
00437 detach();
00438
00439 mData->emails = emails;
00440 }
00441 void Addressee::insertPhoneNumber( const PhoneNumber &phoneNumber )
00442 {
00443 detach();
00444 mData->empty = false;
00445
00446 PhoneNumber::List::Iterator it;
00447 for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) {
00448 if ( (*it).id() == phoneNumber.id() ) {
00449 *it = phoneNumber;
00450 return;
00451 }
00452 }
00453 if ( !phoneNumber.number().simplifyWhiteSpace().isEmpty() )
00454 mData->phoneNumbers.append( phoneNumber );
00455 }
00456
00457 void Addressee::removePhoneNumber( const PhoneNumber &phoneNumber )
00458 {
00459 detach();
00460
00461 PhoneNumber::List::Iterator it;
00462 for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) {
00463 if ( (*it).id() == phoneNumber.id() ) {
00464 mData->phoneNumbers.remove( it );
00465 return;
00466 }
00467 }
00468 }
00469
00470 PhoneNumber Addressee::phoneNumber( int type ) const
00471 {
00472 PhoneNumber phoneNumber( "", type );
00473 PhoneNumber::List::ConstIterator it;
00474 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
00475 if ( matchBinaryPattern( (*it).type(), type ) ) {
00476 if ( (*it).type() & PhoneNumber::Pref )
00477 return (*it);
00478 else if ( phoneNumber.number().isEmpty() )
00479 phoneNumber = (*it);
00480 }
00481 }
00482
00483 return phoneNumber;
00484 }
00485
00486 PhoneNumber::List Addressee::phoneNumbers() const
00487 {
00488 return mData->phoneNumbers;
00489 }
00490
00491 PhoneNumber::List Addressee::phoneNumbers( int type ) const
00492 {
00493 PhoneNumber::List list;
00494
00495 PhoneNumber::List::ConstIterator it;
00496 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
00497 if ( matchBinaryPattern( (*it).type(), type ) ) {
00498 list.append( *it );
00499 }
00500 }
00501 return list;
00502 }
00503
00504 PhoneNumber Addressee::findPhoneNumber( const QString &id ) const
00505 {
00506 PhoneNumber::List::ConstIterator it;
00507 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
00508 if ( (*it).id() == id ) {
00509 return *it;
00510 }
00511 }
00512 return PhoneNumber();
00513 }
00514
00515 void Addressee::insertKey( const Key &key )
00516 {
00517 detach();
00518 mData->empty = false;
00519
00520 Key::List::Iterator it;
00521 for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) {
00522 if ( (*it).id() == key.id() ) {
00523 *it = key;
00524 return;
00525 }
00526 }
00527 mData->keys.append( key );
00528 }
00529
00530 void Addressee::removeKey( const Key &key )
00531 {
00532 detach();
00533
00534 Key::List::Iterator it;
00535 for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) {
00536 if ( (*it).id() == key.id() ) {
00537 mData->keys.remove( key );
00538 return;
00539 }
00540 }
00541 }
00542
00543 Key Addressee::key( int type, QString customTypeString ) const
00544 {
00545 Key::List::ConstIterator it;
00546 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
00547 if ( (*it).type() == type ) {
00548 if ( type == Key::Custom ) {
00549 if ( customTypeString.isEmpty() ) {
00550 return *it;
00551 } else {
00552 if ( (*it).customTypeString() == customTypeString )
00553 return (*it);
00554 }
00555 } else {
00556 return *it;
00557 }
00558 }
00559 }
00560 return Key( QString(), type );
00561 }
00562
00563 void Addressee::setKeys( const Key::List& list )
00564 {
00565 detach();
00566 mData->keys = list;
00567 }
00568
00569 Key::List Addressee::keys() const
00570 {
00571 return mData->keys;
00572 }
00573
00574 Key::List Addressee::keys( int type, QString customTypeString ) const
00575 {
00576 Key::List list;
00577
00578 Key::List::ConstIterator it;
00579 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
00580 if ( (*it).type() == type ) {
00581 if ( type == Key::Custom ) {
00582 if ( customTypeString.isEmpty() ) {
00583 list.append( *it );
00584 } else {
00585 if ( (*it).customTypeString() == customTypeString )
00586 list.append( *it );
00587 }
00588 } else {
00589 list.append( *it );
00590 }
00591 }
00592 }
00593 return list;
00594 }
00595
00596 Key Addressee::findKey( const QString &id ) const
00597 {
00598 Key::List::ConstIterator it;
00599 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
00600 if ( (*it).id() == id ) {
00601 return *it;
00602 }
00603 }
00604 return Key();
00605 }
00606
00607 QString Addressee::asString() const
00608 {
00609 return "Smith, agent Smith...";
00610 }
00611
00612 void Addressee::dump() const
00613 {
00614 kdDebug(5700) << "Addressee {" << endl;
00615
00616 kdDebug(5700) << " Uid: '" << uid() << "'" << endl;
00617
00618 --DEBUG--
00619
00620 kdDebug(5700) << " Emails {" << endl;
00621 const QStringList e = emails();
00622 QStringList::ConstIterator it;
00623 for( it = e.begin(); it != e.end(); ++it ) {
00624 kdDebug(5700) << " " << (*it) << endl;
00625 }
00626 kdDebug(5700) << " }" << endl;
00627
00628 kdDebug(5700) << " PhoneNumbers {" << endl;
00629 const PhoneNumber::List p = phoneNumbers();
00630 PhoneNumber::List::ConstIterator it2;
00631 for( it2 = p.begin(); it2 != p.end(); ++it2 ) {
00632 kdDebug(5700) << " Type: " << int((*it2).type()) << " Number: " << (*it2).number() << endl;
00633 }
00634 kdDebug(5700) << " }" << endl;
00635
00636 const Address::List a = addresses();
00637 Address::List::ConstIterator it3;
00638 for( it3 = a.begin(); it3 != a.end(); ++it3 ) {
00639 (*it3).dump();
00640 }
00641
00642 kdDebug(5700) << " Keys {" << endl;
00643 const Key::List k = keys();
00644 Key::List::ConstIterator it4;
00645 for( it4 = k.begin(); it4 != k.end(); ++it4 ) {
00646 kdDebug(5700) << " Type: " << int((*it4).type()) <<
00647 " Key: " << (*it4).textData() <<
00648 " CustomString: " << (*it4).customTypeString() << endl;
00649 }
00650 kdDebug(5700) << " }" << endl;
00651
00652 kdDebug(5700) << "}" << endl;
00653 }
00654
00655
00656 void Addressee::insertAddress( const Address &address )
00657 {
00658 if ( address.isEmpty() )
00659 return;
00660
00661 detach();
00662 mData->empty = false;
00663
00664 Address::List::Iterator it;
00665 for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) {
00666 if ( (*it).id() == address.id() ) {
00667 *it = address;
00668 return;
00669 }
00670 }
00671
00672 mData->addresses.append( address );
00673 }
00674
00675 void Addressee::removeAddress( const Address &address )
00676 {
00677 detach();
00678
00679 Address::List::Iterator it;
00680 for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) {
00681 if ( (*it).id() == address.id() ) {
00682 mData->addresses.remove( it );
00683 return;
00684 }
00685 }
00686 }
00687
00688 Address Addressee::address( int type ) const
00689 {
00690 Address address( type );
00691 Address::List::ConstIterator it;
00692 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
00693 if ( matchBinaryPattern( (*it).type(), type ) ) {
00694 if ( (*it).type() & Address::Pref )
00695 return (*it);
00696 else if ( address.isEmpty() )
00697 address = (*it);
00698 }
00699 }
00700
00701 return address;
00702 }
00703
00704 Address::List Addressee::addresses() const
00705 {
00706 return mData->addresses;
00707 }
00708
00709 Address::List Addressee::addresses( int type ) const
00710 {
00711 Address::List list;
00712
00713 Address::List::ConstIterator it;
00714 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
00715 if ( matchBinaryPattern( (*it).type(), type ) ) {
00716 list.append( *it );
00717 }
00718 }
00719
00720 return list;
00721 }
00722
00723 Address Addressee::findAddress( const QString &id ) const
00724 {
00725 Address::List::ConstIterator it;
00726 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
00727 if ( (*it).id() == id ) {
00728 return *it;
00729 }
00730 }
00731 return Address();
00732 }
00733
00734 void Addressee::insertCategory( const QString &c )
00735 {
00736 detach();
00737 mData->empty = false;
00738
00739 if ( mData->categories.findIndex( c ) != -1 ) return;
00740
00741 mData->categories.append( c );
00742 }
00743
00744 void Addressee::removeCategory( const QString &c )
00745 {
00746 detach();
00747
00748 QStringList::Iterator it = mData->categories.find( c );
00749 if ( it == mData->categories.end() ) return;
00750
00751 mData->categories.remove( it );
00752 }
00753
00754 bool Addressee::hasCategory( const QString &c ) const
00755 {
00756 return ( mData->categories.findIndex( c ) != -1 );
00757 }
00758
00759 void Addressee::setCategories( const QStringList &c )
00760 {
00761 detach();
00762 mData->empty = false;
00763
00764 mData->categories = c;
00765 }
00766
00767 QStringList Addressee::categories() const
00768 {
00769 return mData->categories;
00770 }
00771
00772 void Addressee::insertCustom( const QString &app, const QString &name,
00773 const QString &value )
00774 {
00775 if ( value.isEmpty() || name.isEmpty() || app.isEmpty() ) return;
00776
00777 detach();
00778 mData->empty = false;
00779
00780 QString qualifiedName = app + "-" + name + ":";
00781
00782 QStringList::Iterator it;
00783 for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) {
00784 if ( (*it).startsWith( qualifiedName ) ) {
00785 (*it) = qualifiedName + value;
00786 return;
00787 }
00788 }
00789
00790 mData->custom.append( qualifiedName + value );
00791 }
00792
00793 void Addressee::removeCustom( const QString &app, const QString &name)
00794 {
00795 detach();
00796
00797 QString qualifiedName = app + "-" + name + ":";
00798
00799 QStringList::Iterator it;
00800 for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) {
00801 if ( (*it).startsWith( qualifiedName ) ) {
00802 mData->custom.remove( it );
00803 return;
00804 }
00805 }
00806 }
00807
00808 QString Addressee::custom( const QString &app, const QString &name ) const
00809 {
00810 QString qualifiedName = app + "-" + name + ":";
00811 QString value;
00812
00813 QStringList::ConstIterator it;
00814 for( it = mData->custom.constBegin(); it != mData->custom.constEnd(); ++it ) {
00815 if ( (*it).startsWith( qualifiedName ) ) {
00816 value = (*it).mid( (*it).find( ":" ) + 1 );
00817 break;
00818 }
00819 }
00820
00821 return value;
00822 }
00823
00824 void Addressee::setCustoms( const QStringList &l )
00825 {
00826 detach();
00827 mData->empty = false;
00828
00829 mData->custom = l;
00830 }
00831
00832 QStringList Addressee::customs() const
00833 {
00834 return mData->custom;
00835 }
00836
00837 void Addressee::parseEmailAddress( const QString &rawEmail, QString &fullName,
00838 QString &email)
00839 {
00840
00841
00842 fullName = "";
00843 email = "";
00844 if ( rawEmail.isEmpty() )
00845 return;
00846
00847
00848 QCString address = rawEmail.utf8();
00849
00850 QCString displayName;
00851 QCString addrSpec;
00852 QCString comment;
00853
00854
00855
00856
00857
00858 enum { TopLevel, InComment, InAngleAddress } context = TopLevel;
00859 bool inQuotedString = false;
00860 int commentLevel = 0;
00861 bool stop = false;
00862
00863 for ( char* p = address.data(); *p && !stop; ++p ) {
00864 switch ( context ) {
00865 case TopLevel : {
00866 switch ( *p ) {
00867 case '"' : inQuotedString = !inQuotedString;
00868 displayName += *p;
00869 break;
00870 case '(' : if ( !inQuotedString ) {
00871 context = InComment;
00872 commentLevel = 1;
00873 }
00874 else
00875 displayName += *p;
00876 break;
00877 case '<' : if ( !inQuotedString ) {
00878 context = InAngleAddress;
00879 }
00880 else
00881 displayName += *p;
00882 break;
00883 case '\\' :
00884 displayName += *p;
00885 ++p;
00886 if ( *p )
00887 displayName += *p;
00888 else
00889
00890 goto ABORT_PARSING;
00891 break;
00892 case ',' : if ( !inQuotedString ) {
00893
00894
00895
00896
00897 goto ABORT_PARSING;
00898 }
00899 else
00900 displayName += *p;
00901 break;
00902 default : displayName += *p;
00903 }
00904 break;
00905 }
00906 case InComment : {
00907 switch ( *p ) {
00908 case '(' : ++commentLevel;
00909 comment += *p;
00910 break;
00911 case ')' : --commentLevel;
00912 if ( commentLevel == 0 ) {
00913 context = TopLevel;
00914 comment += ' ';
00915 }
00916 else
00917 comment += *p;
00918 break;
00919 case '\\' :
00920 comment += *p;
00921 ++p;
00922 if ( *p )
00923 comment += *p;
00924 else
00925
00926 goto ABORT_PARSING;
00927 break;
00928 default : comment += *p;
00929 }
00930 break;
00931 }
00932 case InAngleAddress : {
00933 switch ( *p ) {
00934 case '"' : inQuotedString = !inQuotedString;
00935 addrSpec += *p;
00936 break;
00937 case '>' : if ( !inQuotedString ) {
00938 context = TopLevel;
00939 }
00940 else
00941 addrSpec += *p;
00942 break;
00943 case '\\' :
00944 addrSpec += *p;
00945 ++p;
00946 if ( *p )
00947 addrSpec += *p;
00948 else
00949
00950 goto ABORT_PARSING;
00951 break;
00952 default : addrSpec += *p;
00953 }
00954 break;
00955 }
00956 }
00957 }
00958
00959 ABORT_PARSING:
00960 displayName = displayName.stripWhiteSpace();
00961 comment = comment.stripWhiteSpace();
00962 addrSpec = addrSpec.stripWhiteSpace();
00963
00964 fullName = QString::fromUtf8( displayName );
00965 email = QString::fromUtf8( addrSpec );
00966
00967
00968 if ( inQuotedString )
00969 return;
00970 if ( context == InComment )
00971 return;
00972 if ( context == InAngleAddress )
00973 return;
00974
00975 if ( addrSpec.isEmpty() ) {
00976 if ( displayName.isEmpty() )
00977 return;
00978 else {
00979
00980
00981
00982 email = fullName;
00983 fullName = QString::fromUtf8( comment );
00984 }
00985 }
00986
00987
00988
00989 unsigned int len = fullName.length();
00990 if ( fullName[ 0 ] == '"' && fullName[ len - 1 ] == '"' )
00991 fullName = fullName.mid( 1, len - 2 );
00992 }
00993
00994 void Addressee::setResource( Resource *resource )
00995 {
00996 detach();
00997 mData->resource = resource;
00998 }
00999
01000 Resource *Addressee::resource() const
01001 {
01002 return mData->resource;
01003 }
01004
01005 void Addressee::setChanged( bool value )
01006 {
01007 detach();
01008 mData->changed = value;
01009 }
01010
01011 bool Addressee::changed() const
01012 {
01013 return mData->changed;
01014 }
01015
01016 void Addressee::setSortMode( KABC::SortMode *mode )
01017 {
01018 mSortMode = mode;
01019 }
01020
01021 bool Addressee::operator< ( const Addressee &addr )
01022 {
01023 if ( !mSortMode )
01024 return false;
01025 else
01026 return mSortMode->lesser( *this, addr );
01027 }
01028
01029 QDataStream &KABC::operator<<( QDataStream &s, const Addressee &a )
01030 {
01031 if (!a.mData) return s;
01032
01033 s << a.uid();
01034
01035 --STREAMOUT--
01036 s << a.mData->phoneNumbers;
01037 s << a.mData->addresses;
01038 s << a.mData->emails;
01039 s << a.mData->categories;
01040 s << a.mData->custom;
01041 s << a.mData->keys;
01042 return s;
01043 }
01044
01045 QDataStream &KABC::operator>>( QDataStream &s, Addressee &a )
01046 {
01047 if (!a.mData)
01048 return s;
01049
01050 a.detach();
01051
01052 s >> a.mData->uid;
01053
01054 --STREAMIN--
01055 s >> a.mData->phoneNumbers;
01056 s >> a.mData->addresses;
01057 s >> a.mData->emails;
01058 s >> a.mData->categories;
01059 s >> a.mData->custom;
01060 s >> a.mData->keys;
01061
01062 a.mData->empty = false;
01063
01064 return s;
01065 }
01066
01067 bool matchBinaryPattern( int value, int pattern )
01068 {
01075 if ( pattern == 0 )
01076 return ( value == 0 );
01077 else
01078 return ( pattern == ( pattern & value ) );
01079 }
01080
01081 template <class L>
01082 bool listEquals( const QValueList<L> &list, const QValueList<L> &pattern )
01083 {
01084 if ( list.count() != pattern.count() )
01085 return false;
01086
01087 for ( uint i = 0; i < list.count(); ++i )
01088 if ( pattern.find( list[ i ] ) == pattern.end() )
01089 return false;
01090
01091 return true;
01092 }
01093
01094 bool emailsEquals( const QStringList &list, const QStringList &pattern )
01095 {
01096 if ( list.count() != pattern.count() )
01097 return false;
01098
01099 if ( list.first() != pattern.first() )
01100 return false;
01101
01102 QStringList::ConstIterator it;
01103 for ( it = list.begin(); it != list.end(); ++it )
01104 if ( pattern.find( *it ) == pattern.end() )
01105 return false;
01106
01107 return true;
01108 }