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() )