kabc Library API Documentation

addressee.src.cpp

00001 /* 00002 This file is part of libkabc. 00003 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> 00004 Copyright (c) 2003 Carsten Pfeiffer <pfeiffer@kde.org> 00005 Copyright (c) 2005 Ingo Kloecker <kloecker@kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00020 Boston, MA 02111-1307, USA. 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(); //just in case (we should add KSD) 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 mData = a.mData; 00094 return (*this); 00095 } 00096 00097 void Addressee::detach() 00098 { 00099 if ( mData.data() == shared_null ) { 00100 mData = new AddresseeData; 00101 mData->empty = true; 00102 mData->changed = false; 00103 mData->resource = 0; 00104 mData->uid = KApplication::randomString( 10 ); 00105 return; 00106 } else if ( mData.count() == 1 ) return; 00107 00108 AddresseeData data = *mData; 00109 mData = new AddresseeData( data ); 00110 } 00111 00112 bool Addressee::operator==( const Addressee &a ) const 00113 { 00114 if ( uid() != a.uid() ) { 00115 kdDebug(5700) << "uid differs" << endl; 00116 return false; 00117 } 00118 --EQUALSTEST-- 00119 if ( ( mData->url.isValid() || a.mData->url.isValid() ) && 00120 ( mData->url != a.mData->url ) ) { 00121 kdDebug(5700) << "url differs" << endl; 00122 return false; 00123 } 00124 if ( !listEquals( mData->phoneNumbers, a.mData->phoneNumbers ) ) { 00125 kdDebug(5700) << "phoneNumbers differs" << endl; 00126 return false; 00127 } 00128 if ( !listEquals( mData->addresses, a.mData->addresses ) ) { 00129 kdDebug(5700) << "addresses differs" << endl; 00130 return false; 00131 } 00132 if ( !listEquals( mData->keys, a.mData->keys ) ) { 00133 kdDebug(5700) << "keys differs" << endl; 00134 return false; 00135 } 00136 if ( !emailsEquals( mData->emails, a.mData->emails ) ) { 00137 kdDebug(5700) << "emails differs" << endl; 00138 return false; 00139 } 00140 if ( !listEquals( mData->categories, a.mData->categories ) ) { 00141 kdDebug(5700) << "categories differs" << endl; 00142 return false; 00143 } 00144 if ( !listEquals( mData->custom, a.mData->custom ) ) { 00145 kdDebug(5700) << "custom differs" << endl; 00146 return false; 00147 } 00148 00149 return true; 00150 } 00151 00152 bool Addressee::operator!=( const Addressee &a ) const 00153 { 00154 return !( a == *this ); 00155 } 00156 00157 bool Addressee::isEmpty() const 00158 { 00159 return mData->empty; 00160 } 00161 00162 void Addressee::setUid( const QString &id ) 00163 { 00164 if ( id == mData->uid ) return; 00165 detach(); 00166 mData->empty = false; 00167 mData->uid = id; 00168 } 00169 00170 QString Addressee::uid() const 00171 { 00172 return mData->uid; 00173 } 00174 00175 QString Addressee::uidLabel() 00176 { 00177 return i18n("Unique Identifier"); 00178 } 00179 00180 --DEFINITIONS-- 00181 00182 void Addressee::setNameFromString( const QString &str ) 00183 { 00184 setFormattedName( str ); 00185 setName( str ); 00186 00187 // clear all name parts 00188 setPrefix( QString::null ); 00189 setGivenName( QString::null ); 00190 setAdditionalName( QString::null ); 00191 setFamilyName( QString::null ); 00192 setSuffix( QString::null ); 00193 00194 if ( str.isEmpty() ) 00195 return; 00196 00197 QString spaceStr = " "; 00198 QString emptyStr = ""; 00199 AddresseeHelper *helper = AddresseeHelper::self(); 00200 00201 int i = str.find( ',' ); 00202 if( i < 0 ) { 00203 QStringList parts = QStringList::split( spaceStr, str ); 00204 int leftOffset = 0; 00205 int rightOffset = parts.count() - 1; 00206 00207 QString suffix; 00208 while ( rightOffset >= 0 ) { 00209 if ( helper->containsSuffix( parts[ rightOffset ] ) ) { 00210 suffix.prepend(parts[ rightOffset ] + (suffix.isEmpty() ? emptyStr : spaceStr)); 00211 rightOffset--; 00212 } else 00213 break; 00214 } 00215 setSuffix( suffix ); 00216 00217 if ( rightOffset < 0 ) 00218 return; 00219 00220 if ( rightOffset - 1 >= 0 && helper->containsPrefix( parts[ rightOffset - 1 ].lower() ) ) { 00221 setFamilyName( parts[ rightOffset - 1 ] + spaceStr + parts[ rightOffset ] ); 00222 rightOffset--; 00223 } else { 00224 if ( helper->tradeAsFamilyName() ) 00225 setFamilyName( parts[ rightOffset ] ); 00226 else 00227 setGivenName( parts[ rightOffset ] ); 00228 } 00229 00230 QString prefix; 00231 while ( leftOffset < rightOffset ) { 00232 if ( helper->containsTitle( parts[ leftOffset ] ) ) { 00233 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] ); 00234 leftOffset++; 00235 } else 00236 break; 00237 } 00238 setPrefix( prefix ); 00239 00240 if ( leftOffset < rightOffset ) { 00241 setGivenName( parts[ leftOffset ] ); 00242 leftOffset++; 00243 } 00244 00245 QString additionalName; 00246 while ( leftOffset < rightOffset ) { 00247 additionalName.append( ( additionalName.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] ); 00248 leftOffset++; 00249 } 00250 setAdditionalName( additionalName ); 00251 } else { 00252 QString part1 = str.left( i ); 00253 QString part2 = str.mid( i + 1 ); 00254 00255 QStringList parts = QStringList::split( spaceStr, part1 ); 00256 int leftOffset = 0; 00257 int rightOffset = parts.count() - 1; 00258 00259 if ( parts.count() > 0 ) { 00260 00261 QString suffix; 00262 while ( rightOffset >= 0 ) { 00263 if ( helper->containsSuffix( parts[ rightOffset ] ) ) { 00264 suffix.prepend(parts[ rightOffset ] + (suffix.isEmpty() ? emptyStr : spaceStr)); 00265 rightOffset--; 00266 } else 00267 break; 00268 } 00269 setSuffix( suffix ); 00270 00271 if ( rightOffset - 1 >= 0 && helper->containsPrefix( parts[ rightOffset - 1 ].lower() ) ) { 00272 setFamilyName( parts[ rightOffset - 1 ] + spaceStr + parts[ rightOffset ] ); 00273 rightOffset--; 00274 } else 00275 setFamilyName( parts[ rightOffset ] ); 00276 00277 QString prefix; 00278 while ( leftOffset < rightOffset ) { 00279 if ( helper->containsTitle( parts[ leftOffset ] ) ) { 00280 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] ); 00281 leftOffset++; 00282 } else 00283 break; 00284 } 00285 } else { 00286 setPrefix( "" ); 00287 setFamilyName( "" ); 00288 setSuffix( "" ); 00289 } 00290 00291 parts = QStringList::split( spaceStr, part2 ); 00292 00293 leftOffset = 0; 00294 rightOffset = parts.count(); 00295 00296 if ( parts.count() > 0 ) { 00297 00298 QString prefix; 00299 while ( leftOffset < rightOffset ) { 00300 if ( helper->containsTitle( parts[ leftOffset ] ) ) { 00301 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] ); 00302 leftOffset++; 00303 } else 00304 break; 00305 } 00306 setPrefix( prefix ); 00307 00308 if ( leftOffset < rightOffset ) { 00309 setGivenName( parts[ leftOffset ] ); 00310 leftOffset++; 00311 } 00312 00313 QString additionalName; 00314 while ( leftOffset < rightOffset ) { 00315 additionalName.append( ( additionalName.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] ); 00316 leftOffset++; 00317 } 00318 setAdditionalName( additionalName ); 00319 } else { 00320 setGivenName( "" ); 00321 setAdditionalName( "" ); 00322 } 00323 } 00324 } 00325 00326 QString Addressee::realName() const 00327 { 00328 QString n( formattedName() ); 00329 if ( !n.isEmpty() ) 00330 return n; 00331 00332 n = assembledName(); 00333 if ( !n.isEmpty() ) 00334 return n; 00335 00336 n = name(); 00337 if ( !n.isEmpty() ) 00338 return n; 00339 00340 return organization(); 00341 } 00342 00343 QString Addressee::assembledName() const 00344 { 00345 QString name = prefix() + " " + givenName() + " " + additionalName() + " " + 00346 familyName() + " " + suffix(); 00347 00348 return name.simplifyWhiteSpace(); 00349 } 00350 00351 QString Addressee::fullEmail( const QString &email ) const 00352 { 00353 QString e; 00354 if ( email.isNull() ) { 00355 e = preferredEmail(); 00356 } else { 00357 e = email; 00358 } 00359 if ( e.isEmpty() ) return QString::null; 00360 00361 QString text; 00362 if ( realName().isEmpty() ) 00363 text = e; 00364 else { 00365 QRegExp needQuotes( "[^ 0-9A-Za-z\\x0080-\\xFFFF]" ); 00366 if ( realName().find( needQuotes ) != -1 ) 00367 text = "\"" + realName() + "\" <" + e + ">"; 00368 else 00369 text = realName() + " <" + e + ">"; 00370 } 00371 00372 return text; 00373 } 00374 00375 void Addressee::insertEmail( const QString &email, bool preferred ) 00376 { 00377 if ( email.simplifyWhiteSpace().isEmpty() ) 00378 return; 00379 00380 detach(); 00381 00382 QStringList::Iterator it = mData->emails.find( email ); 00383 00384 if ( it != mData->emails.end() ) { 00385 if ( !preferred || it == mData->emails.begin() ) return; 00386 mData->emails.remove( it ); 00387 mData->emails.prepend( email ); 00388 } else { 00389 if ( preferred ) { 00390 mData->emails.prepend( email ); 00391 } else { 00392 mData->emails.append( email ); 00393 } 00394 } 00395 } 00396 00397 void Addressee::removeEmail( const QString &email ) 00398 { 00399 detach(); 00400 00401 QStringList::Iterator it = mData->emails.find( email ); 00402 if ( it == mData->emails.end() ) return; 00403 00404 mData->emails.remove( it ); 00405 } 00406 00407 QString Addressee::preferredEmail() const 00408 { 00409 if ( mData->emails.count() == 0 ) return QString::null; 00410 else return mData->emails.first(); 00411 } 00412 00413 QStringList Addressee::emails() const 00414 { 00415 return mData->emails; 00416 } 00417 void Addressee::setEmails( const QStringList& emails ) { 00418 detach(); 00419 00420 mData->emails = emails; 00421 } 00422 void Addressee::insertPhoneNumber( const PhoneNumber &phoneNumber ) 00423 { 00424 detach(); 00425 mData->empty = false; 00426 00427 PhoneNumber::List::Iterator it; 00428 for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) { 00429 if ( (*it).id() == phoneNumber.id() ) { 00430 *it = phoneNumber; 00431 return; 00432 } 00433 } 00434 if ( !phoneNumber.number().simplifyWhiteSpace().isEmpty() ) 00435 mData->phoneNumbers.append( phoneNumber ); 00436 } 00437 00438 void Addressee::removePhoneNumber( const PhoneNumber &phoneNumber ) 00439 { 00440 detach(); 00441 00442 PhoneNumber::List::Iterator it; 00443 for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) { 00444 if ( (*it).id() == phoneNumber.id() ) { 00445 mData->phoneNumbers.remove( it ); 00446 return; 00447 } 00448 } 00449 } 00450 00451 PhoneNumber Addressee::phoneNumber( int type ) const 00452 { 00453 PhoneNumber phoneNumber( "", type ); 00454 PhoneNumber::List::ConstIterator it; 00455 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) { 00456 if ( matchBinaryPattern( (*it).type(), type ) ) { 00457 if ( (*it).type() & PhoneNumber::Pref ) 00458 return (*it); 00459 else if ( phoneNumber.number().isEmpty() ) 00460 phoneNumber = (*it); 00461 } 00462 } 00463 00464 return phoneNumber; 00465 } 00466 00467 PhoneNumber::List Addressee::phoneNumbers() const 00468 { 00469 return mData->phoneNumbers; 00470 } 00471 00472 PhoneNumber::List Addressee::phoneNumbers( int type ) const 00473 { 00474 PhoneNumber::List list; 00475 00476 PhoneNumber::List::ConstIterator it; 00477 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) { 00478 if ( matchBinaryPattern( (*it).type(), type ) ) { 00479 list.append( *it ); 00480 } 00481 } 00482 return list; 00483 } 00484 00485 PhoneNumber Addressee::findPhoneNumber( const QString &id ) const 00486 { 00487 PhoneNumber::List::ConstIterator it; 00488 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) { 00489 if ( (*it).id() == id ) { 00490 return *it; 00491 } 00492 } 00493 return PhoneNumber(); 00494 } 00495 00496 void Addressee::insertKey( const Key &key ) 00497 { 00498 detach(); 00499 mData->empty = false; 00500 00501 Key::List::Iterator it; 00502 for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) { 00503 if ( (*it).id() == key.id() ) { 00504 *it = key; 00505 return; 00506 } 00507 } 00508 mData->keys.append( key ); 00509 } 00510 00511 void Addressee::removeKey( const Key &key ) 00512 { 00513 detach(); 00514 00515 Key::List::Iterator it; 00516 for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) { 00517 if ( (*it).id() == key.id() ) { 00518 mData->keys.remove( key ); 00519 return; 00520 } 00521 } 00522 } 00523 00524 Key Addressee::key( int type, QString customTypeString ) const 00525 { 00526 Key::List::ConstIterator it; 00527 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) { 00528 if ( (*it).type() == type ) { 00529 if ( type == Key::Custom ) { 00530 if ( customTypeString.isEmpty() ) { 00531 return *it; 00532 } else { 00533 if ( (*it).customTypeString() == customTypeString ) 00534 return (*it); 00535 } 00536 } else { 00537 return *it; 00538 } 00539 } 00540 } 00541 return Key( QString(), type ); 00542 } 00543 00544 void Addressee::setKeys( const Key::List& list ) 00545 { 00546 detach(); 00547 mData->keys = list; 00548 } 00549 00550 Key::List Addressee::keys() const 00551 { 00552 return mData->keys; 00553 } 00554 00555 Key::List Addressee::keys( int type, QString customTypeString ) const 00556 { 00557 Key::List list; 00558 00559 Key::List::ConstIterator it; 00560 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) { 00561 if ( (*it).type() == type ) { 00562 if ( type == Key::Custom ) { 00563 if ( customTypeString.isEmpty() ) { 00564 list.append( *it ); 00565 } else { 00566 if ( (*it).customTypeString() == customTypeString ) 00567 list.append( *it ); 00568 } 00569 } else { 00570 list.append( *it ); 00571 } 00572 } 00573 } 00574 return list; 00575 } 00576 00577 Key Addressee::findKey( const QString &id ) const 00578 { 00579 Key::List::ConstIterator it; 00580 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) { 00581 if ( (*it).id() == id ) { 00582 return *it; 00583 } 00584 } 00585 return Key(); 00586 } 00587 00588 QString Addressee::asString() const 00589 { 00590 return "Smith, agent Smith..."; 00591 } 00592 00593 void Addressee::dump() const 00594 { 00595 kdDebug(5700) << "Addressee {" << endl; 00596 00597 kdDebug(5700) << " Uid: '" << uid() << "'" << endl; 00598 00599 --DEBUG-- 00600 00601 kdDebug(5700) << " Emails {" << endl; 00602 const QStringList e = emails(); 00603 QStringList::ConstIterator it; 00604 for( it = e.begin(); it != e.end(); ++it ) { 00605 kdDebug(5700) << " " << (*it) << endl; 00606 } 00607 kdDebug(5700) << " }" << endl; 00608 00609 kdDebug(5700) << " PhoneNumbers {" << endl; 00610 const PhoneNumber::List p = phoneNumbers(); 00611 PhoneNumber::List::ConstIterator it2; 00612 for( it2 = p.begin(); it2 != p.end(); ++it2 ) { 00613 kdDebug(5700) << " Type: " << int((*it2).type()) << " Number: " << (*it2).number() << endl; 00614 } 00615 kdDebug(5700) << " }" << endl; 00616 00617 const Address::List a = addresses(); 00618 Address::List::ConstIterator it3; 00619 for( it3 = a.begin(); it3 != a.end(); ++it3 ) { 00620 (*it3).dump(); 00621 } 00622 00623 kdDebug(5700) << " Keys {" << endl; 00624 const Key::List k = keys(); 00625 Key::List::ConstIterator it4; 00626 for( it4 = k.begin(); it4 != k.end(); ++it4 ) { 00627 kdDebug(5700) << " Type: " << int((*it4).type()) << 00628 " Key: " << (*it4).textData() << 00629 " CustomString: " << (*it4).customTypeString() << endl; 00630 } 00631 kdDebug(5700) << " }" << endl; 00632 00633 kdDebug(5700) << "}" << endl; 00634 } 00635 00636 00637 void Addressee::insertAddress( const Address &address ) 00638 { 00639 if ( address.isEmpty() ) 00640 return; 00641 00642 detach(); 00643 mData->empty = false; 00644 00645 Address::List::Iterator it; 00646 for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) { 00647 if ( (*it).id() == address.id() ) { 00648 *it = address; 00649 return; 00650 } 00651 } 00652 00653 mData->addresses.append( address ); 00654 } 00655 00656 void Addressee::removeAddress( const Address &address ) 00657 { 00658 detach(); 00659 00660 Address::List::Iterator it; 00661 for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) { 00662 if ( (*it).id() == address.id() ) { 00663 mData->addresses.remove( it ); 00664 return; 00665 } 00666 } 00667 } 00668 00669 Address Addressee::address( int type ) const 00670 { 00671 Address address( type ); 00672 Address::List::ConstIterator it; 00673 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) { 00674 if ( matchBinaryPattern( (*it).type(), type ) ) { 00675 if ( (*it).type() & Address::Pref ) 00676 return (*it); 00677 else if ( address.isEmpty() ) 00678 address = (*it); 00679 } 00680 } 00681 00682 return address; 00683 } 00684 00685 Address::List Addressee::addresses() const 00686 { 00687 return mData->addresses; 00688 } 00689 00690 Address::List Addressee::addresses( int type ) const 00691 { 00692 Address::List list; 00693 00694 Address::List::ConstIterator it; 00695 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) { 00696 if ( matchBinaryPattern( (*it).type(), type ) ) { 00697 list.append( *it ); 00698 } 00699 } 00700 00701 return list; 00702 } 00703 00704 Address Addressee::findAddress( const QString &id ) const 00705 { 00706 Address::List::ConstIterator it; 00707 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) { 00708 if ( (*it).id() == id ) { 00709 return *it; 00710 } 00711 } 00712 return Address(); 00713 } 00714 00715 void Addressee::insertCategory( const QString &c ) 00716 { 00717 detach(); 00718 mData->empty = false; 00719 00720 if ( mData->categories.findIndex( c ) != -1 ) return; 00721 00722 mData->categories.append( c ); 00723 } 00724 00725 void Addressee::removeCategory( const QString &c ) 00726 { 00727 detach(); 00728 00729 QStringList::Iterator it = mData->categories.find( c ); 00730 if ( it == mData->categories.end() ) return; 00731 00732 mData->categories.remove( it ); 00733 } 00734 00735 bool Addressee::hasCategory( const QString &c ) const 00736 { 00737 return ( mData->categories.findIndex( c ) != -1 ); 00738 } 00739 00740 void Addressee::setCategories( const QStringList &c ) 00741 { 00742 detach(); 00743 mData->empty = false; 00744 00745 mData->categories = c; 00746 } 00747 00748 QStringList Addressee::categories() const 00749 { 00750 return mData->categories; 00751 } 00752 00753 void Addressee::insertCustom( const QString &app, const QString &name, 00754 const QString &value ) 00755 { 00756 if ( value.isEmpty() || name.isEmpty() || app.isEmpty() ) return; 00757 00758 detach(); 00759 mData->empty = false; 00760 00761 QString qualifiedName = app + "-" + name + ":"; 00762 00763 QStringList::Iterator it; 00764 for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) { 00765 if ( (*it).startsWith( qualifiedName ) ) { 00766 (*it) = qualifiedName + value; 00767 return; 00768 } 00769 } 00770 00771 mData->custom.append( qualifiedName + value ); 00772 } 00773 00774 void Addressee::removeCustom( const QString &app, const QString &name) 00775 { 00776 detach(); 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 mData->custom.remove( it ); 00784 return; 00785 } 00786 } 00787 } 00788 00789 QString Addressee::custom( const QString &app, const QString &name ) const 00790 { 00791 QString qualifiedName = app + "-" + name + ":"; 00792 QString value; 00793 00794 QStringList::ConstIterator it; 00795 for( it = mData->custom.constBegin(); it != mData->custom.constEnd(); ++it ) { 00796 if ( (*it).startsWith( qualifiedName ) ) { 00797 value = (*it).mid( (*it).find( ":" ) + 1 ); 00798 break; 00799 } 00800 } 00801 00802 return value; 00803 } 00804 00805 void Addressee::setCustoms( const QStringList &l ) 00806 { 00807 detach(); 00808 mData->empty = false; 00809 00810 mData->custom = l; 00811 } 00812 00813 QStringList Addressee::customs() const 00814 { 00815 return mData->custom; 00816 } 00817 00818 void Addressee::parseEmailAddress( const QString &rawEmail, QString &fullName, 00819 QString &email) 00820 { 00821 // This is a simplified version of KPIM::splitAddress(). 00822 00823 fullName = ""; 00824 email = ""; 00825 if ( rawEmail.isEmpty() ) 00826 return; // KPIM::AddressEmpty; 00827 00828 // The code works on 8-bit strings, so convert the input to UTF-8. 00829 QCString address = rawEmail.utf8(); 00830 00831 QCString displayName; 00832 QCString addrSpec; 00833 QCString comment; 00834 00835 // The following is a primitive parser for a mailbox-list (cf. RFC 2822). 00836 // The purpose is to extract a displayable string from the mailboxes. 00837 // Comments in the addr-spec are not handled. No error checking is done. 00838 00839 enum { TopLevel, InComment, InAngleAddress } context = TopLevel; 00840 bool inQuotedString = false; 00841 int commentLevel = 0; 00842 bool stop = false; 00843 00844 for ( char* p = address.data(); *p && !stop; ++p ) { 00845 switch ( context ) { 00846 case TopLevel : { 00847 switch ( *p ) { 00848 case '"' : inQuotedString = !inQuotedString; 00849 displayName += *p; 00850 break; 00851 case '(' : if ( !inQuotedString ) { 00852 context = InComment; 00853 commentLevel = 1; 00854 } 00855 else 00856 displayName += *p; 00857 break; 00858 case '<' : if ( !inQuotedString ) { 00859 context = InAngleAddress; 00860 } 00861 else 00862 displayName += *p; 00863 break; 00864 case '\\' : // quoted character 00865 displayName += *p; 00866 ++p; // skip the '\' 00867 if ( *p ) 00868 displayName += *p; 00869 else 00870 //return KPIM::UnexpectedEnd; 00871 goto ABORT_PARSING; 00872 break; 00873 case ',' : if ( !inQuotedString ) { 00874 //if ( allowMultipleAddresses ) 00875 // stop = true; 00876 //else 00877 // return KPIM::UnexpectedComma; 00878 goto ABORT_PARSING; 00879 } 00880 else 00881 displayName += *p; 00882 break; 00883 default : displayName += *p; 00884 } 00885 break; 00886 } 00887 case InComment : { 00888 switch ( *p ) { 00889 case '(' : ++commentLevel; 00890 comment += *p; 00891 break; 00892 case ')' : --commentLevel; 00893 if ( commentLevel == 0 ) { 00894 context = TopLevel; 00895 comment += ' '; // separate the text of several comments 00896 } 00897 else 00898 comment += *p; 00899 break; 00900 case '\\' : // quoted character 00901 comment += *p; 00902 ++p; // skip the '\' 00903 if ( *p ) 00904 comment += *p; 00905 else 00906 //return KPIM::UnexpectedEnd; 00907 goto ABORT_PARSING; 00908 break; 00909 default : comment += *p; 00910 } 00911 break; 00912 } 00913 case InAngleAddress : { 00914 switch ( *p ) { 00915 case '"' : inQuotedString = !inQuotedString; 00916 addrSpec += *p; 00917 break; 00918 case '>' : if ( !inQuotedString ) { 00919 context = TopLevel; 00920 } 00921 else 00922 addrSpec += *p; 00923 break; 00924 case '\\' : // quoted character 00925 addrSpec += *p; 00926 ++p; // skip the '\' 00927 if ( *p ) 00928 addrSpec += *p; 00929 else 00930 //return KPIM::UnexpectedEnd; 00931 goto ABORT_PARSING; 00932 break; 00933 default : addrSpec += *p; 00934 } 00935 break; 00936 } 00937 } // switch ( context ) 00938 } 00939 00940 ABORT_PARSING: 00941 displayName = displayName.stripWhiteSpace(); 00942 comment = comment.stripWhiteSpace(); 00943 addrSpec = addrSpec.stripWhiteSpace(); 00944 00945 fullName = QString::fromUtf8( displayName ); 00946 email = QString::fromUtf8( addrSpec ); 00947 00948 // check for errors 00949 if ( inQuotedString ) 00950 return; // KPIM::UnbalancedQuote; 00951 if ( context == InComment ) 00952 return; // KPIM::UnbalancedParens; 00953 if ( context == InAngleAddress ) 00954 return; // KPIM::UnclosedAngleAddr; 00955 00956 if ( addrSpec.isEmpty() ) { 00957 if ( displayName.isEmpty() ) 00958 return; // KPIM::NoAddressSpec; 00959 else { 00960 //addrSpec = displayName; 00961 //displayName.truncate( 0 ); 00962 // Address of the form "foo@bar" or "foo@bar (Name)". 00963 email = fullName; 00964 fullName = QString::fromUtf8( comment ); 00965 } 00966 } 00967 00968 // Check that we do not have any extra characters on the end of the 00969 // strings 00970 unsigned int len = fullName.length(); 00971 if ( fullName[ 0 ] == '"' && fullName[ len - 1 ] == '"' ) 00972 fullName = fullName.mid( 1, len - 2 ); 00973 } 00974 00975 void Addressee::setResource( Resource *resource ) 00976 { 00977 detach(); 00978 mData->resource = resource; 00979 } 00980 00981 Resource *Addressee::resource() const 00982 { 00983 return mData->resource; 00984 } 00985 00986 void Addressee::setChanged( bool value ) 00987 { 00988 detach(); 00989 mData->changed = value; 00990 } 00991 00992 bool Addressee::changed() const 00993 { 00994 return mData->changed; 00995 } 00996 00997 void Addressee::setSortMode( KABC::SortMode *mode ) 00998 { 00999 mSortMode = mode; 01000 } 01001 01002 bool Addressee::operator< ( const Addressee &addr ) 01003 { 01004 if ( !mSortMode ) 01005 return false; 01006 else 01007 return mSortMode->lesser( *this, addr ); 01008 } 01009 01010 QDataStream &KABC::operator<<( QDataStream &s, const Addressee &a ) 01011 { 01012 if (!a.mData) return s; 01013 01014 s << a.uid(); 01015 01016 --STREAMOUT-- 01017 s << a.mData->phoneNumbers; 01018 s << a.mData->addresses; 01019 s << a.mData->emails; 01020 s << a.mData->categories; 01021 s << a.mData->custom; 01022 s << a.mData->keys; 01023 return s; 01024 } 01025 01026 QDataStream &KABC::operator>>( QDataStream &s, Addressee &a ) 01027 { 01028 if (!a.mData) return s; 01029 01030 s >> a.mData->uid; 01031 01032 --STREAMIN-- 01033 s >> a.mData->phoneNumbers; 01034 s >> a.mData->addresses; 01035 s >> a.mData->emails; 01036 s >> a.mData->categories; 01037 s >> a.mData->custom; 01038 s >> a.mData->keys; 01039 01040 a.mData->empty = false; 01041 01042 return s; 01043 } 01044 01045 bool matchBinaryPattern( int value, int pattern ) 01046 { 01053 if ( pattern == 0 ) 01054 return ( value == 0 ); 01055 else 01056 return ( pattern == ( pattern & value ) ); 01057 } 01058 01059 template <class L> 01060 bool listEquals( const QValueList<L> &list, const QValueList<L> &pattern ) 01061 { 01062 if ( list.count() != pattern.count() ) 01063 return false; 01064 01065 for ( uint i = 0; i < list.count(); ++i ) 01066 if ( pattern.find( list[ i ] ) == pattern.end() ) 01067 return false; 01068 01069 return true; 01070 } 01071 01072 bool emailsEquals( const QStringList &list, const QStringList &pattern ) 01073 { 01074 if ( list.count() != pattern.count() ) 01075 return false; 01076 01077 if ( list.first() != pattern.first() ) 01078 return false; 01079 01080 QStringList::ConstIterator it; 01081 for ( it = list.begin(); it != list.end(); ++it ) 01082 if ( pattern.find( *it ) == pattern.end() ) 01083 return false; 01084 01085 return true; 01086 }
KDE Logo
This file is part of the documentation for kabc Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:35:16 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003