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