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