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.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jul 2 13:08:58 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003