25 #include <ksharedptr.h>
27 #include <tdeapplication.h>
30 #include "addresseehelper.h"
35 #include "addressee.h"
39 static bool matchBinaryPattern(
int value,
int pattern );
42 static bool listEquals(
const TQValueList<L>&,
const TQValueList<L>& );
43 static bool emailsEquals(
const TQStringList&,
const TQStringList& );
47 struct Addressee::AddresseeData :
public TDEShared
66 Addressee::AddresseeData* Addressee::shared_null = 0;
68 Addressee::AddresseeData* Addressee::makeSharedNull()
70 Addressee::shared_null =
new AddresseeData;
71 shared_null->_TDEShared_ref();
72 shared_null->empty =
true;
73 shared_null->changed =
false;
74 shared_null->resource = 0;
80 mData = shared_null ? shared_null : makeSharedNull();
83 Addressee::~Addressee()
101 void Addressee::detach()
103 if ( mData.
data() == shared_null ) {
104 mData =
new AddresseeData;
106 mData->changed =
false;
110 }
else if ( mData.
count() == 1 )
return;
112 AddresseeData data = *mData;
113 mData =
new AddresseeData( data );
116 bool Addressee::operator==(
const Addressee &a )
const
123 if ( ( mData->url.isValid() || a.mData->url.isValid() ) &&
124 ( mData->url != a.mData->url ) ) {
128 if ( !listEquals( mData->phoneNumbers, a.mData->phoneNumbers ) ) {
132 if ( !listEquals( mData->addresses, a.mData->addresses ) ) {
136 if ( !listEquals( mData->keys, a.mData->keys ) ) {
140 if ( !emailsEquals( mData->emails, a.mData->emails ) ) {
144 if ( !listEquals( mData->categories, a.mData->categories ) ) {
148 if ( !listEquals( mData->custom, a.mData->custom ) ) {
156 bool Addressee::operator!=(
const Addressee &a )
const
158 return !( a == *this );
168 if (
id == mData->uid )
return;
170 mData->empty =
false;
181 return i18n(
"Unique Identifier");
186 if (
id == mData->uri )
return;
188 mData->empty =
false;
199 return i18n(
"Unique Resource Identifier");
208 if ( str.length() > 1 && s[ 0 ] ==
'"' && s[ s.length() - 1 ] ==
'"' )
209 str = s.mid( 1, s.length() - 2 );
211 setFormattedName( str );
215 setPrefix( TQString() );
216 setGivenName( TQString() );
217 setAdditionalName( TQString() );
218 setFamilyName( TQString() );
219 setSuffix( TQString() );
224 TQString spaceStr =
" ";
225 TQString emptyStr =
"";
226 AddresseeHelper *helper = AddresseeHelper::self();
228 int i = str.find(
',' );
230 TQStringList parts = TQStringList::split( spaceStr, str );
232 int rightOffset = parts.count() - 1;
235 while ( rightOffset >= 0 ) {
236 if ( helper->containsSuffix( parts[ rightOffset ] ) ) {
237 suffix.prepend(parts[ rightOffset ] + (suffix.isEmpty() ? emptyStr : spaceStr));
244 if ( rightOffset < 0 )
247 TQStringList inclusionList;
248 for (
int n = 1; (rightOffset - n >= 0) && (n < 4); ++n ) {
249 if ( helper->containsPrefix( parts[ rightOffset - n ].lower() ) ) {
250 inclusionList.prepend( parts[ rightOffset - n ] );
255 if ( !inclusionList.isEmpty() ) {
256 setFamilyName( inclusionList.join(
" " ) + spaceStr + parts[ rightOffset ] );
257 rightOffset -= inclusionList.count();
259 if ( helper->tradeAsFamilyName() )
260 setFamilyName( parts[ rightOffset ] );
262 setGivenName( parts[ rightOffset ] );
266 while ( leftOffset < rightOffset ) {
267 if ( helper->containsTitle( parts[ leftOffset ] ) ) {
268 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
275 if ( leftOffset < rightOffset ) {
276 setGivenName( parts[ leftOffset ] );
280 TQString additionalName;
281 while ( leftOffset < rightOffset ) {
282 additionalName.append( ( additionalName.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
285 setAdditionalName( additionalName );
287 TQString part1 = str.left( i );
288 TQString part2 = str.mid( i + 1 );
290 TQStringList parts = TQStringList::split( spaceStr, part1 );
292 int rightOffset = parts.count() - 1;
294 if ( parts.count() > 0 ) {
297 while ( rightOffset >= 0 ) {
298 if ( helper->containsSuffix( parts[ rightOffset ] ) ) {
299 suffix.prepend(parts[ rightOffset ] + (suffix.isEmpty() ? emptyStr : spaceStr));
306 if ( rightOffset - 1 >= 0 && helper->containsPrefix( parts[ rightOffset - 1 ].lower() ) ) {
307 setFamilyName( parts[ rightOffset - 1 ] + spaceStr + parts[ rightOffset ] );
310 setFamilyName( parts[ rightOffset ] );
313 while ( leftOffset < rightOffset ) {
314 if ( helper->containsTitle( parts[ leftOffset ] ) ) {
315 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
326 parts = TQStringList::split( spaceStr, part2 );
329 rightOffset = parts.count();
331 if ( parts.count() > 0 ) {
334 while ( leftOffset < rightOffset ) {
335 if ( helper->containsTitle( parts[ leftOffset ] ) ) {
336 prefix.append( ( prefix.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
343 if ( leftOffset < rightOffset ) {
344 setGivenName( parts[ leftOffset ] );
348 TQString additionalName;
349 while ( leftOffset < rightOffset ) {
350 additionalName.append( ( additionalName.isEmpty() ? emptyStr : spaceStr) + parts[ leftOffset ] );
353 setAdditionalName( additionalName );
356 setAdditionalName(
"" );
363 TQString n( formattedName() );
375 return organization();
380 TQString name = prefix() +
" " + givenName() +
" " + additionalName() +
" " +
381 familyName() +
" " + suffix();
383 return name.simplifyWhiteSpace();
389 if ( email.isNull() ) {
394 if ( e.isEmpty() )
return TQString();
400 TQRegExp needQuotes(
"[^ 0-9A-Za-z\\x0080-\\xFFFF]" );
401 if (
realName().find( needQuotes ) != -1 ) {
403 name.replace(
"\"",
"\\\"" );
404 text =
"\"" + name +
"\" <" + e +
">";
414 if ( email.simplifyWhiteSpace().isEmpty() )
418 mData->empty =
false;
420 TQStringList::Iterator it = mData->emails.find( email );
422 if ( it != mData->emails.end() ) {
423 if ( !preferred || it == mData->emails.begin() )
return;
424 mData->emails.remove( it );
425 mData->emails.prepend( email );
428 mData->emails.prepend( email );
430 mData->emails.append( email );
439 TQStringList::Iterator it = mData->emails.find( email );
440 if ( it == mData->emails.end() )
return;
442 mData->emails.remove( it );
447 if ( mData->emails.
count() == 0 )
return TQString();
448 else return mData->emails.first();
453 return mData->emails;
463 mData->empty =
false;
465 PhoneNumber::List::Iterator it;
466 for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) {
480 PhoneNumber::List::Iterator it;
481 for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) {
483 mData->phoneNumbers.remove( it );
492 PhoneNumber::List::ConstIterator it;
493 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
494 if ( matchBinaryPattern( (*it).type(), type ) ) {
495 if ( (*it).type() & PhoneNumber::Pref )
507 return mData->phoneNumbers;
512 PhoneNumber::List list;
514 PhoneNumber::List::ConstIterator it;
515 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
516 if ( matchBinaryPattern( (*it).type(), type ) ) {
525 PhoneNumber::List::ConstIterator it;
526 for( it = mData->phoneNumbers.constBegin(); it != mData->phoneNumbers.constEnd(); ++it ) {
527 if ( (*it).id() ==
id ) {
537 mData->empty =
false;
539 Key::List::Iterator it;
540 for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) {
541 if ( (*it).id() ==
key.
id() ) {
546 mData->keys.append(
key );
553 Key::List::Iterator it;
554 for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) {
555 if ( (*it).id() ==
key.
id() ) {
556 mData->keys.remove(
key );
564 Key::List::ConstIterator it;
565 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
566 if ( (*it).type() == type ) {
567 if ( type == Key::Custom ) {
568 if ( customTypeString.isEmpty() ) {
571 if ( (*it).customTypeString() == customTypeString )
579 return Key( TQString(), type );
597 Key::List::ConstIterator it;
598 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
599 if ( (*it).type() == type ) {
600 if ( type == Key::Custom ) {
601 if ( customTypeString.isEmpty() ) {
604 if ( (*it).customTypeString() == customTypeString )
617 Key::List::ConstIterator it;
618 for( it = mData->keys.constBegin(); it != mData->keys.constEnd(); ++it ) {
619 if ( (*it).id() ==
id ) {
628 return "Smith, agent Smith...";
640 const TQStringList e =
emails();
641 TQStringList::ConstIterator it;
642 for( it = e.begin(); it != e.end(); ++it ) {
649 PhoneNumber::List::ConstIterator it2;
650 for( it2 = p.begin(); it2 != p.end(); ++it2 ) {
651 kdDebug(5700) <<
" Type: " << int((*it2).type()) <<
" Number: " << (*it2).number() <<
endl;
656 Address::List::ConstIterator it3;
657 for( it3 = a.begin(); it3 != a.end(); ++it3 ) {
662 const Key::List k =
keys();
663 Key::List::ConstIterator it4;
664 for( it4 = k.begin(); it4 != k.end(); ++it4 ) {
665 kdDebug(5700) <<
" Type: " << int((*it4).type()) <<
666 " Key: " << (*it4).textData() <<
667 " CustomString: " << (*it4).customTypeString() <<
endl;
681 mData->empty =
false;
683 Address::List::Iterator it;
684 for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) {
685 if ( (*it).id() ==
address.id() ) {
691 mData->addresses.append(
address );
698 Address::List::Iterator it;
699 for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) {
700 if ( (*it).id() ==
address.id() ) {
701 mData->addresses.remove( it );
710 Address::List::ConstIterator it;
711 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
712 if ( matchBinaryPattern( (*it).type(), type ) ) {
713 if ( (*it).type() & Address::Pref )
725 return mData->addresses;
732 Address::List::ConstIterator it;
733 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
734 if ( matchBinaryPattern( (*it).type(), type ) ) {
744 Address::List::ConstIterator it;
745 for( it = mData->addresses.constBegin(); it != mData->addresses.constEnd(); ++it ) {
746 if ( (*it).id() ==
id ) {
756 mData->empty =
false;
758 if ( mData->categories.findIndex( c ) != -1 )
return;
760 mData->categories.append( c );
767 TQStringList::Iterator it = mData->categories.find( c );
768 if ( it == mData->categories.end() )
return;
770 mData->categories.remove( it );
775 return ( mData->categories.findIndex( c ) != -1 );
781 mData->empty =
false;
783 mData->categories = c;
788 return mData->categories;
792 const TQString &value )
794 if ( value.isEmpty() || name.isEmpty() || app.isEmpty() )
return;
797 mData->empty =
false;
799 TQString qualifiedName = app +
"-" + name +
":";
801 TQStringList::Iterator it;
802 for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) {
803 if ( (*it).startsWith( qualifiedName ) ) {
804 (*it) = qualifiedName + value;
809 mData->custom.append( qualifiedName + value );
816 TQString qualifiedName = app +
"-" + name +
":";
818 TQStringList::Iterator it;
819 for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) {
820 if ( (*it).startsWith( qualifiedName ) ) {
821 mData->custom.remove( it );
829 TQString qualifiedName = app +
"-" + name +
":";
832 TQStringList::ConstIterator it;
833 for( it = mData->custom.constBegin(); it != mData->custom.constEnd(); ++it ) {
834 if ( (*it).startsWith( qualifiedName ) ) {
835 value = (*it).mid( (*it).find(
":" ) + 1 );
846 mData->empty =
false;
853 return mData->custom;
863 if ( rawEmail.isEmpty() )
867 TQCString
address = rawEmail.utf8();
869 TQCString displayName;
877 enum { TopLevel, InComment, InAngleAddress } context = TopLevel;
878 bool inQuotedString =
false;
879 int commentLevel = 0;
882 for (
char* p =
address.data(); *p && !stop; ++p ) {
886 case '"' : inQuotedString = !inQuotedString;
889 case '(' :
if ( !inQuotedString ) {
896 case '<' :
if ( !inQuotedString ) {
897 context = InAngleAddress;
911 case ',' :
if ( !inQuotedString ) {
921 default : displayName += *p;
927 case '(' : ++commentLevel;
930 case ')' : --commentLevel;
931 if ( commentLevel == 0 ) {
947 default : comment += *p;
951 case InAngleAddress : {
953 case '"' : inQuotedString = !inQuotedString;
956 case '>' :
if ( !inQuotedString ) {
971 default : addrSpec += *p;
979 displayName = displayName.stripWhiteSpace();
980 comment = comment.stripWhiteSpace();
981 addrSpec = addrSpec.stripWhiteSpace();
983 fullName = TQString::fromUtf8( displayName );
984 email = TQString::fromUtf8( addrSpec );
987 if ( inQuotedString )
989 if ( context == InComment )
991 if ( context == InAngleAddress )
994 if ( addrSpec.isEmpty() ) {
995 if ( displayName.isEmpty() )
1002 fullName = TQString::fromUtf8( comment );
1008 unsigned int len = fullName.length();
1009 if ( fullName[ 0 ] ==
'"' && fullName[ len - 1 ] ==
'"' )
1010 fullName = fullName.mid( 1, len - 2 );
1021 return mData->resource;
1027 mData->changed = value;
1032 return mData->changed;
1040 bool Addressee::operator< (
const Addressee &addr )
1045 return mSortMode->
lesser( *
this, addr );
1048 TQDataStream &TDEABC::operator<<( TQDataStream &s,
const Addressee &a )
1050 if (!a.mData)
return s;
1055 s << a.mData->phoneNumbers;
1056 s << a.mData->addresses;
1057 s << a.mData->emails;
1058 s << a.mData->categories;
1059 s << a.mData->custom;
1064 TQDataStream &TDEABC::operator>>( TQDataStream &s,
Addressee &a )
1074 s >> a.mData->phoneNumbers;
1075 s >> a.mData->addresses;
1076 s >> a.mData->emails;
1077 s >> a.mData->categories;
1078 s >> a.mData->custom;
1081 a.mData->empty =
false;
1086 bool matchBinaryPattern(
int value,
int pattern )
1095 return ( value == 0 );
1097 return ( pattern == ( pattern & value ) );
1101 bool listEquals(
const TQValueList<L> &list,
const TQValueList<L> &pattern )
1103 if ( list.count() != pattern.count() )
1106 for ( uint i = 0; i < list.count(); ++i )
1107 if ( pattern.find( list[ i ] ) == pattern.end() )
1113 bool emailsEquals(
const TQStringList &list,
const TQStringList &pattern )
1115 if ( list.count() != pattern.count() )
1118 if ( list.first() != pattern.first() )
1121 TQStringList::ConstIterator it;
1122 for ( it = list.begin(); it != list.end(); ++it )
1123 if ( pattern.find( *it ) == pattern.end() )
Postal address information.
bool isEmpty() const
Returns true, if the address is empty.
TQValueList< Address > List
List of addresses.
static TQString uidLabel()
Return translated label for uid field.
void removeCustom(const TQString &app, const TQString &name)
Remove custom entry.
void removeKey(const Key &key)
Remove a key.
void setUid(const TQString &uid)
Set unique identifier.
void removeEmail(const TQString &email)
Remove email address.
TQStringList categories() const
Return list of all set categories.
void setCategories(const TQStringList &)
Set categories to given value.
void removePhoneNumber(const PhoneNumber &phoneNumber)
Remove phone number.
void setKeys(const Key::List &keys)
Set the list of keys.
TQStringList emails() const
Return list of all email addresses.
void insertPhoneNumber(const PhoneNumber &phoneNumber)
Insert a phone number.
void insertCustom(const TQString &app, const TQString &name, const TQString &value)
Insert custom entry.
Key::List keys() const
Return list of all keys.
Address findAddress(const TQString &id) const
Return address with the given id.
void setUri(const TQString &uid)
Set unique resource identifier.
void removeAddress(const Address &address)
Remove address.
TQString fullEmail(const TQString &email=TQString::null) const
Return email address including real name.
Addressee()
Construct an empty address book entry.
TQStringList customs() const
Return list of all custom entries.
TQString uri() const
Return unique resource identifier.
bool isEmpty() const
Return, if the address book entry is empty.
void removeCategory(const TQString &)
Remove category.
void dump() const
Debug output.
TQString assembledName() const
Return the name that consists of all name parts.
void setChanged(bool value)
Mark addressee as changed.
void setCustoms(const TQStringList &)
Set all custom entries.
TQString realName() const
Return the name of the addressee.
void insertCategory(const TQString &)
Insert category.
bool hasCategory(const TQString &) const
Return, if addressee has the given category.
Address address(int type) const
Return address, which matches the given type.
Key findKey(const TQString &id) const
Return key with the given id.
void insertEmail(const TQString &email, bool preferred=false)
Insert an email address.
void setEmails(const TQStringList &list)
Set the emails to list.
void insertAddress(const Address &address)
Insert an address.
Address::List addresses() const
Return list of all addresses.
DECLARATIONS void setNameFromString(const TQString &)
Set name fields by parsing the given string and trying to associate the parts of the string with acco...
bool changed() const
Return whether the addressee is changed.
static void parseEmailAddress(const TQString &rawEmail, TQString &fullName, TQString &email)
Parse full email address.
void insertKey(const Key &key)
Insert a key.
PhoneNumber phoneNumber(int type) const
Return phone number, which matches the given type.
TQString asString() const
Returns string representation of the addressee.
void setResource(Resource *resource)
Set resource where the addressee is from.
TQString custom(const TQString &app, const TQString &name) const
Return value of custom entry, identified by app and entry name.
Resource * resource() const
Return pointer to resource.
TQString uid() const
Return unique identifier.
TQString preferredEmail() const
Return preferred email address.
static TQString uriLabel()
Return translated label for uri field.
PhoneNumber::List phoneNumbers() const
Return list of all phone numbers.
Key key(int type, TQString customTypeString=TQString::null) const
Return key, which matches the given type.
PhoneNumber findPhoneNumber(const TQString &id) const
Return phone number with the given id.
A class to store an encryption key.
TQString id() const
Returns the unique identifier.
TQString number() const
Returns the number.
TQString id() const
Returns the unique identifier.
Sort method for sorting an addressee list.
virtual bool lesser(const TDEABC::Addressee &first, const TDEABC::Addressee &second) const =0
Reimplement this method and return whether the first contact is 'smaller' than the second.
static TQString randomString(int length)
kndbgstream & endl(kndbgstream &s)
kdbgstream kdDebug(int area=0)
static data, shared by ALL addressee objects