KCalCore Library
person.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00036 #include "person.h"
00037 #include <QtCore/QRegExp>
00038
00039 using namespace KCalCore;
00040
00045
00046 class KCalCore::Person::Private
00047 {
00048 public:
00049 Private() : mCount( 0 ) {}
00050 QString mName;
00051 QString mEmail;
00052 int mCount;
00053 };
00054
00055
00056 Person::Person() : d( new KCalCore::Person::Private )
00057 {
00058 }
00059
00060 Person::Person( const QString &name, const QString &email )
00061 : d( new KCalCore::Person::Private )
00062 {
00063 d->mName = name;
00064 d->mEmail = email;
00065 }
00066
00067 Person::Person( const Person &person )
00068 : d( new KCalCore::Person::Private( *person.d ) )
00069 {
00070 }
00071
00072 Person::~Person()
00073 {
00074 delete d;
00075 }
00076
00077 bool KCalCore::Person::operator==( const Person &person ) const
00078 {
00079 return
00080 d->mName == person.d->mName &&
00081 d->mEmail == person.d->mEmail;
00082 }
00083
00084 bool KCalCore::Person::operator!=( const Person &person ) const
00085 {
00086 return !( *this == person );
00087 }
00088
00089 Person &KCalCore::Person::operator=( const Person &person )
00090 {
00091
00092 if ( &person == this ) {
00093 return *this;
00094 }
00095
00096 *d = *person.d;
00097 return *this;
00098 }
00099
00100 QString Person::fullName() const
00101 {
00102 if ( d->mName.isEmpty() ) {
00103 return d->mEmail;
00104 } else {
00105 if ( d->mEmail.isEmpty() ) {
00106 return d->mName;
00107 } else {
00108
00109 QString name = d->mName;
00110 QRegExp needQuotes( "[^ 0-9A-Za-z\\x0080-\\xFFFF]" );
00111 bool weNeedToQuote = name.indexOf( needQuotes ) != -1;
00112 if ( weNeedToQuote ) {
00113 if ( name[0] != '"' ) {
00114 name.prepend( '"' );
00115 }
00116 if ( name[ name.length()-1 ] != '"' ) {
00117 name.append( '"' );
00118 }
00119 }
00120 return name + " <" + d->mEmail + '>';
00121 }
00122 }
00123 }
00124
00125 QString Person::name() const
00126 {
00127 return d->mName;
00128 }
00129
00130 QString Person::email() const
00131 {
00132 return d->mEmail;
00133 }
00134
00135 bool Person::isEmpty() const
00136 {
00137 return d->mEmail.isEmpty() && d->mName.isEmpty();
00138 }
00139
00140 void Person::setName( const QString &name )
00141 {
00142 d->mName = name;
00143 }
00144
00145 void Person::setEmail( const QString &email )
00146 {
00147 if ( email.startsWith( QLatin1String( "mailto:" ), Qt::CaseInsensitive ) ) {
00148 d->mEmail = email.mid( 7 );
00149 } else {
00150 d->mEmail = email;
00151 }
00152 }
00153
00155 bool Person::isValidEmail( const QString &email )
00156 {
00157 int pos = email.lastIndexOf( "@" );
00158 return ( pos > 0 ) && ( email.lastIndexOf( "." ) > pos ) && ( ( email.length() - pos ) > 4 );
00159 }
00160
00161 void Person::setCount( int count )
00162 {
00163 d->mCount = count;
00164 }
00165
00166 int Person::count() const
00167 {
00168 return d->mCount;
00169 }
00170
00171 uint qHash( const KCalCore::Person &key )
00172 {
00173 return qHash( key.fullName() );
00174 }
00175
00176 QDataStream &KCalCore::operator<<( QDataStream &stream, const KCalCore::Person::Ptr &person )
00177 {
00178 return stream << person->d->mName
00179 << person->d->mEmail
00180 << person->d->mCount;
00181 }
00182
00183 QDataStream &KCalCore::operator>>( QDataStream &stream, Person::Ptr &person )
00184 {
00185 QString name, email;
00186 int count;
00187
00188 stream >> name >> email >> count;
00189
00190 Person::Ptr person_tmp( new Person( name, email ) );
00191 person_tmp->setCount( count );
00192 person.swap( person_tmp );
00193 return stream;
00194 }
00195
00196
00197
00198
00199 static bool extractEmailAddressAndName( const QString &aStr, QString &mail, QString &name )
00200 {
00201 name.clear();
00202 mail.clear();
00203
00204 const int len = aStr.length();
00205 const char cQuotes = '"';
00206
00207 bool bInComment = false;
00208 bool bInQuotesOutsideOfEmail = false;
00209 int i=0, iAd=0, iMailStart=0, iMailEnd=0;
00210 QChar c;
00211 unsigned int commentstack = 0;
00212
00213
00214
00215 while ( i < len ) {
00216 c = aStr[i];
00217 if ( '(' == c ) {
00218 commentstack++;
00219 }
00220 if ( ')' == c ) {
00221 commentstack--;
00222 }
00223 bInComment = commentstack != 0;
00224 if ( '"' == c && !bInComment ) {
00225 bInQuotesOutsideOfEmail = !bInQuotesOutsideOfEmail;
00226 }
00227
00228 if( !bInComment && !bInQuotesOutsideOfEmail ) {
00229 if ( '@' == c ) {
00230 iAd = i;
00231 break;
00232 }
00233 }
00234 ++i;
00235 }
00236
00237 if ( !iAd ) {
00238
00239
00240
00241 for ( i = 0; len > i; ++i ) {
00242 c = aStr[i];
00243 if ( '<' != c ) {
00244 name.append( c );
00245 } else {
00246 break;
00247 }
00248 }
00249 mail = aStr.mid( i + 1 );
00250 if ( mail.endsWith( '>' ) ) {
00251 mail.truncate( mail.length() - 1 );
00252 }
00253
00254 } else {
00255
00256
00257
00258 bInComment = false;
00259 bInQuotesOutsideOfEmail = false;
00260 for ( i = iAd-1; 0 <= i; --i ) {
00261 c = aStr[i];
00262 if ( bInComment ) {
00263 if ( '(' == c ) {
00264 if ( !name.isEmpty() ) {
00265 name.prepend( ' ' );
00266 }
00267 bInComment = false;
00268 } else {
00269 name.prepend( c );
00270 }
00271 } else if ( bInQuotesOutsideOfEmail ) {
00272 if ( cQuotes == c ) {
00273 bInQuotesOutsideOfEmail = false;
00274 } else if ( c != '\\' ) {
00275 name.prepend( c );
00276 }
00277 } else {
00278
00279 if ( ',' == c ) {
00280 break;
00281 }
00282
00283 if ( iMailStart ) {
00284 if ( cQuotes == c ) {
00285 bInQuotesOutsideOfEmail = true;
00286 } else {
00287 name.prepend( c );
00288 }
00289 } else {
00290 switch ( c.toLatin1() ) {
00291 case '<':
00292 iMailStart = i;
00293 break;
00294 case ')':
00295 if ( !name.isEmpty() ) {
00296 name.prepend( ' ' );
00297 }
00298 bInComment = true;
00299 break;
00300 default:
00301 if ( ' ' != c ) {
00302 mail.prepend( c );
00303 }
00304 }
00305 }
00306 }
00307 }
00308
00309 name = name.simplified();
00310 mail = mail.simplified();
00311
00312 if ( mail.isEmpty() ) {
00313 return false;
00314 }
00315
00316 mail.append( '@' );
00317
00318
00319
00320
00321 bInComment = false;
00322 bInQuotesOutsideOfEmail = false;
00323 int parenthesesNesting = 0;
00324 for ( i = iAd+1; len > i; ++i ) {
00325 c = aStr[i];
00326 if ( bInComment ) {
00327 if ( ')' == c ) {
00328 if ( --parenthesesNesting == 0 ) {
00329 bInComment = false;
00330 if ( !name.isEmpty() ) {
00331 name.append( ' ' );
00332 }
00333 } else {
00334
00335 name.append( ')' );
00336 }
00337 } else {
00338 if ( '(' == c ) {
00339
00340 ++parenthesesNesting;
00341 }
00342 name.append( c );
00343 }
00344 } else if ( bInQuotesOutsideOfEmail ) {
00345 if ( cQuotes == c ) {
00346 bInQuotesOutsideOfEmail = false;
00347 } else if ( c != '\\' ) {
00348 name.append( c );
00349 }
00350 } else {
00351
00352 if ( ',' == c ) {
00353 break;
00354 }
00355
00356 if ( iMailEnd ){
00357 if ( cQuotes == c ) {
00358 bInQuotesOutsideOfEmail = true;
00359 } else {
00360 name.append( c );
00361 }
00362 } else {
00363 switch ( c.toLatin1() ) {
00364 case '>':
00365 iMailEnd = i;
00366 break;
00367 case '(':
00368 if ( !name.isEmpty() ) {
00369 name.append( ' ' );
00370 }
00371 if ( ++parenthesesNesting > 0 ) {
00372 bInComment = true;
00373 }
00374 break;
00375 default:
00376 if ( ' ' != c ) {
00377 mail.append( c );
00378 }
00379 }
00380 }
00381 }
00382 }
00383 }
00384
00385 name = name.simplified();
00386 mail = mail.simplified();
00387
00388 return ! ( name.isEmpty() || mail.isEmpty() );
00389 }
00390
00392 Person::Ptr Person::fromFullName( const QString &fullName )
00393 {
00394 QString email, name;
00395 extractEmailAddressAndName( fullName, email, name );
00396 return Person::Ptr( new Person( name, email ) );
00397 }