00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 static const char configKeyDefaultIdentity[] = "Default Identity";
00022
00023 #include "identitymanager.h"
00024 #include "identity.h"
00025
00026 #include <kpimutils/email.h>
00027
00028 #include <kemailsettings.h>
00029 #include <klocale.h>
00030 #include <kglobal.h>
00031 #include <kdebug.h>
00032 #include <kconfig.h>
00033 #include <kuser.h>
00034 #include <kconfiggroup.h>
00035
00036 #include <QList>
00037 #include <QRegExp>
00038 #include <QtDBus/QtDBus>
00039
00040 #include <assert.h>
00041 #include <krandom.h>
00042
00043 #include "identitymanageradaptor.h"
00044
00045 using namespace KPIMIdentities;
00046
00047 static QString newDBusObjectName()
00048 {
00049 static int s_count = 0;
00050 QString name( "/KPIMIDENTITIES_IdentityManager" );
00051 if ( s_count++ ) {
00052 name += '_';
00053 name += QString::number( s_count );
00054 }
00055 return name;
00056 }
00057
00058 IdentityManager::IdentityManager( bool readonly, QObject *parent,
00059 const char *name )
00060 : QObject( parent )
00061 {
00062 setObjectName( name );
00063 KGlobal::locale()->insertCatalog("libkpimidentities");
00064 new IdentityManagerAdaptor( this );
00065 QDBusConnection dbus = QDBusConnection::sessionBus();
00066 const QString dbusPath = newDBusObjectName();
00067 const QString dbusInterface = "org.kde.pim.IdentityManager";
00068 dbus.registerObject( dbusPath, this );
00069 dbus.connect( QString(), dbusPath, dbusInterface, "identitiesChanged", this,
00070 SLOT( slotIdentitiesChanged( QString ) ) );
00071
00072 mReadOnly = readonly;
00073 mConfig = new KConfig( "emailidentities" );
00074 readConfig( mConfig );
00075 if ( mIdentities.isEmpty() ) {
00076 kDebug( 5325 ) << "emailidentities is empty -> convert from kmailrc";
00077
00078
00079
00080 KConfig kmailConf( "kmailrc" );
00081 readConfig( &kmailConf );
00082 }
00083
00084 if ( mIdentities.isEmpty() ) {
00085 kDebug( 5325 ) << "IdentityManager: No identity found. Creating default.";
00086 createDefaultIdentity();
00087 commit();
00088 }
00089
00090 if ( KEMailSettings().getSetting( KEMailSettings::EmailAddress ).isEmpty() ) {
00091 writeConfig();
00092 }
00093 }
00094
00095 IdentityManager::~IdentityManager()
00096 {
00097 kWarning( hasPendingChanges(), 5325 )
00098 << "IdentityManager: There were uncommitted changes!";
00099 delete mConfig;
00100 }
00101
00102 QString IdentityManager::makeUnique( const QString &name ) const
00103 {
00104 int suffix = 1;
00105 QString result = name;
00106 while ( identities().contains( result ) ) {
00107 result = i18nc( "%1: name; %2: number appended to it to make it unique "
00108 "among a list of names", "%1 #%2",
00109 name, suffix );
00110 suffix++;
00111 }
00112 return result;
00113 }
00114
00115 bool IdentityManager::isUnique( const QString &name ) const
00116 {
00117 return !identities().contains( name );
00118 }
00119
00120 void IdentityManager::commit()
00121 {
00122
00123 if ( !hasPendingChanges() || mReadOnly ) {
00124 return;
00125 }
00126
00127 QList<uint> seenUOIDs;
00128 for ( QList<Identity>::ConstIterator it = mIdentities.constBegin();
00129 it != mIdentities.constEnd(); ++it ) {
00130 seenUOIDs << (*it).uoid();
00131 }
00132
00133 QList<uint> changedUOIDs;
00134
00135 for ( QList<Identity>::ConstIterator it = mShadowIdentities.constBegin();
00136 it != mShadowIdentities.constEnd(); ++it ) {
00137 int index = seenUOIDs.indexOf( (*it).uoid() );
00138 if ( index != -1 ) {
00139 uint uoid = seenUOIDs.at( index );
00140 const Identity &orig = identityForUoid( uoid );
00141 if ( *it != orig ) {
00142
00143 kDebug( 5325 ) << "emitting changed() for identity" << uoid;
00144 emit changed(*it);
00145 changedUOIDs << uoid;
00146 }
00147 seenUOIDs.removeAll( uoid );
00148 } else {
00149
00150 kDebug( 5325 ) << "emitting added() for identity" << (*it).uoid();
00151 emit added(*it);
00152 }
00153 }
00154
00155
00156 for ( QList<uint>::ConstIterator it = seenUOIDs.constBegin();
00157 it != seenUOIDs.constEnd(); ++it ) {
00158 kDebug( 5325 ) << "emitting deleted() for identity" << (*it);
00159 emit deleted(*it);
00160 }
00161
00162 mIdentities = mShadowIdentities;
00163 writeConfig();
00164
00165
00166
00167
00168 for ( QList<uint>::ConstIterator it = changedUOIDs.constBegin();
00169 it != changedUOIDs.constEnd(); ++it )
00170 emit changed(*it);
00171
00172 emit changed();
00173
00174
00175 emit identitiesChanged( QDBusConnection::sessionBus().baseService() );
00176 }
00177
00178 void IdentityManager::rollback()
00179 {
00180 mShadowIdentities = mIdentities;
00181 }
00182
00183 bool IdentityManager::hasPendingChanges() const
00184 {
00185 return mIdentities != mShadowIdentities;
00186 }
00187
00188 QStringList IdentityManager::identities() const
00189 {
00190 QStringList result;
00191 for ( ConstIterator it = mIdentities.begin();
00192 it != mIdentities.end(); ++it )
00193 result << (*it).identityName();
00194 return result;
00195 }
00196
00197 QStringList IdentityManager::shadowIdentities() const
00198 {
00199 QStringList result;
00200 for ( ConstIterator it = mShadowIdentities.begin();
00201 it != mShadowIdentities.end(); ++it )
00202 result << (*it).identityName();
00203 return result;
00204 }
00205
00206 void IdentityManager::sort()
00207 {
00208 qSort( mShadowIdentities );
00209 }
00210
00211 void IdentityManager::writeConfig() const
00212 {
00213 const QStringList identities = groupList( mConfig );
00214 for ( QStringList::const_iterator group = identities.begin();
00215 group != identities.end(); ++group )
00216 mConfig->deleteGroup( *group );
00217 int i = 0;
00218 for ( ConstIterator it = mIdentities.begin();
00219 it != mIdentities.end(); ++it, ++i ) {
00220 KConfigGroup cg( mConfig, QString::fromLatin1( "Identity #%1" ).arg( i ) );
00221 (*it).writeConfig( cg );
00222 if ( (*it).isDefault() ) {
00223
00224 KConfigGroup general( mConfig, "General" );
00225 general.writeEntry( configKeyDefaultIdentity, (*it).uoid() );
00226
00227
00228 KEMailSettings es;
00229 es.setSetting( KEMailSettings::RealName, (*it).fullName() );
00230 es.setSetting( KEMailSettings::EmailAddress, (*it).emailAddr() );
00231 es.setSetting( KEMailSettings::Organization, (*it).organization() );
00232 es.setSetting( KEMailSettings::ReplyToAddress, (*it).replyToAddr() );
00233 }
00234 }
00235 mConfig->sync();
00236
00237 }
00238
00239 void IdentityManager::readConfig( KConfig *config )
00240 {
00241 mIdentities.clear();
00242
00243 const QStringList identities = groupList( config );
00244 if ( identities.isEmpty() ) {
00245 return;
00246 }
00247
00248 KConfigGroup general( config, "General" );
00249 uint defaultIdentity = general.readEntry( configKeyDefaultIdentity, 0 );
00250 bool haveDefault = false;
00251
00252 for ( QStringList::const_iterator group = identities.begin();
00253 group != identities.end(); ++group ) {
00254 KConfigGroup configGroup( config, *group );
00255 mIdentities << Identity();
00256 mIdentities.last().readConfig( configGroup );
00257 if ( !haveDefault && mIdentities.last().uoid() == defaultIdentity ) {
00258 haveDefault = true;
00259 mIdentities.last().setIsDefault( true );
00260 }
00261 }
00262 if ( !haveDefault ) {
00263 kWarning( 5325 ) << "IdentityManager: There was no default identity."
00264 << "Marking first one as default.";
00265 mIdentities.first().setIsDefault( true );
00266 }
00267 qSort( mIdentities );
00268
00269 mShadowIdentities = mIdentities;
00270 }
00271
00272 QStringList IdentityManager::groupList( KConfig *config ) const
00273 {
00274 return config->groupList().filter( QRegExp( "^Identity #\\d+$" ) );
00275 }
00276
00277 IdentityManager::ConstIterator IdentityManager::begin() const
00278 {
00279 return mIdentities.begin();
00280 }
00281
00282 IdentityManager::ConstIterator IdentityManager::end() const
00283 {
00284 return mIdentities.end();
00285 }
00286
00287 IdentityManager::Iterator IdentityManager::modifyBegin()
00288 {
00289 return mShadowIdentities.begin();
00290 }
00291
00292 IdentityManager::Iterator IdentityManager::modifyEnd()
00293 {
00294 return mShadowIdentities.end();
00295 }
00296
00297 const Identity &IdentityManager::identityForUoid( uint uoid ) const
00298 {
00299 for ( ConstIterator it = begin(); it != end(); ++it ) {
00300 if ( (*it).uoid() == uoid ) {
00301 return (*it);
00302 }
00303 }
00304 return Identity::null();
00305 }
00306
00307 const Identity &IdentityManager::identityForUoidOrDefault( uint uoid ) const
00308 {
00309 const Identity &ident = identityForUoid( uoid );
00310 if ( ident.isNull() ) {
00311 return defaultIdentity();
00312 } else {
00313 return ident;
00314 }
00315 }
00316
00317 const Identity &IdentityManager::identityForAddress(
00318 const QString &addresses ) const
00319 {
00320 QStringList addressList = KPIMUtils::splitAddressList( addresses );
00321 for ( ConstIterator it = begin(); it != end(); ++it ) {
00322 for ( QStringList::ConstIterator addrIt = addressList.constBegin();
00323 addrIt != addressList.constEnd(); ++addrIt ) {
00324 if ( (*it).emailAddr().toLower() == KPIMUtils::extractEmailAddress( *addrIt ).toLower() ) {
00325 return (*it);
00326 }
00327 }
00328 }
00329 return Identity::null();
00330 }
00331
00332 bool IdentityManager::thatIsMe( const QString &addressList ) const
00333 {
00334 return !identityForAddress( addressList ).isNull();
00335 }
00336
00337 Identity &IdentityManager::modifyIdentityForName( const QString &name )
00338 {
00339 for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00340 if ( (*it).identityName() == name ) {
00341 return (*it);
00342 }
00343 }
00344
00345 kWarning( 5325 ) << "IdentityManager::modifyIdentityForName() used as"
00346 << "newFromScratch() replacement!"
00347 << endl << " name == \"" << name << "\"";
00348 return newFromScratch( name );
00349 }
00350
00351 Identity &IdentityManager::modifyIdentityForUoid( uint uoid )
00352 {
00353 for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00354 if ( (*it).uoid() == uoid ) {
00355 return (*it);
00356 }
00357 }
00358
00359 kWarning( 5325 ) << "IdentityManager::identityForUoid() used as"
00360 << "newFromScratch() replacement!"
00361 << endl << " uoid == \"" << uoid << "\"";
00362 return newFromScratch( i18n( "Unnamed" ) );
00363 }
00364
00365 const Identity &IdentityManager::defaultIdentity() const
00366 {
00367 for ( ConstIterator it = begin(); it != end(); ++it ) {
00368 if ( (*it).isDefault() ) {
00369 return (*it);
00370 }
00371 }
00372
00373 if ( mIdentities.isEmpty() )
00374 kFatal( 5325 ) << "IdentityManager: No default identity found!";
00375 else
00376 kWarning( 5325 ) << "IdentityManager: No default identity found!";
00377 return *begin();
00378 }
00379
00380 bool IdentityManager::setAsDefault( uint uoid )
00381 {
00382
00383 bool found = false;
00384 for ( ConstIterator it = mShadowIdentities.constBegin();
00385 it != mShadowIdentities.constEnd(); ++it )
00386 if ( (*it).uoid() == uoid ) {
00387 found = true;
00388 break;
00389 }
00390
00391 if ( !found ) {
00392 return false;
00393 }
00394
00395
00396 for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00397 (*it).setIsDefault( (*it).uoid() == uoid );
00398 }
00399
00400
00401 sort();
00402 return true;
00403 }
00404
00405 bool IdentityManager::removeIdentity( const QString &name )
00406 {
00407 if ( mShadowIdentities.size() <= 1 )
00408 return false;
00409
00410 for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00411 if ( (*it).identityName() == name ) {
00412 bool removedWasDefault = (*it).isDefault();
00413 mShadowIdentities.erase( it );
00414 if ( removedWasDefault ) {
00415 mShadowIdentities.first().setIsDefault( true );
00416 }
00417 return true;
00418 }
00419 }
00420 return false;
00421 }
00422
00423 Identity &IdentityManager::newFromScratch( const QString &name )
00424 {
00425 return newFromExisting( Identity( name ) );
00426 }
00427
00428 Identity &IdentityManager::newFromControlCenter( const QString &name )
00429 {
00430 KEMailSettings es;
00431 es.setProfile( es.defaultProfileName() );
00432
00433 return
00434 newFromExisting( Identity( name,
00435 es.getSetting( KEMailSettings::RealName ),
00436 es.getSetting( KEMailSettings::EmailAddress ),
00437 es.getSetting( KEMailSettings::Organization ),
00438 es.getSetting( KEMailSettings::ReplyToAddress ) ) );
00439 }
00440
00441 Identity &IdentityManager::newFromExisting( const Identity &other,
00442 const QString &name )
00443 {
00444 mShadowIdentities << other;
00445 Identity &result = mShadowIdentities.last();
00446 result.setIsDefault( false );
00447 result.setUoid( newUoid() );
00448 if ( !name.isNull() ) {
00449 result.setIdentityName( name );
00450 }
00451 return result;
00452 }
00453
00454 void IdentityManager::createDefaultIdentity()
00455 {
00456 QString fullName, emailAddress;
00457 bool done = false;
00458
00459
00460 createDefaultIdentity( fullName, emailAddress );
00461
00462
00463 if ( fullName.isEmpty() && emailAddress.isEmpty() ) {
00464 KEMailSettings emailSettings;
00465 fullName = emailSettings.getSetting( KEMailSettings::RealName );
00466 emailAddress = emailSettings.getSetting( KEMailSettings::EmailAddress );
00467
00468 if ( !fullName.isEmpty() && !emailAddress.isEmpty() ) {
00469 newFromControlCenter( i18nc( "use default address from control center",
00470 "Default" ) );
00471 done = true;
00472 } else {
00473
00474 KUser user;
00475 if ( fullName.isEmpty() ) {
00476 fullName = user.property( KUser::FullName ).toString();
00477 }
00478 if ( emailAddress.isEmpty() ) {
00479 emailAddress = user.loginName();
00480 if ( !emailAddress.isEmpty() ) {
00481 KConfigGroup general( mConfig, "General" );
00482 QString defaultdomain = general.readEntry( "Default domain" );
00483 if ( !defaultdomain.isEmpty() ) {
00484 emailAddress += '@' + defaultdomain;
00485 } else {
00486 emailAddress.clear();
00487 }
00488 }
00489 }
00490 }
00491 }
00492
00493 if ( !done ) {
00494
00495 QString name( i18nc( "Default name for new email accounts/identities.", "Unnamed" ) );
00496
00497 if ( !emailAddress.isEmpty() ) {
00498
00499 QString idName = emailAddress;
00500 int pos = idName.indexOf( '@' );
00501 if ( pos != -1 ) {
00502 name = idName.mid( pos + 1, -1 );
00503 }
00504
00505
00506 name.replace( '.', ' ' );
00507 pos = name.indexOf( ' ' );
00508 if ( pos != 0 ) {
00509 name[pos + 1] = name[pos + 1].toUpper();
00510 }
00511 name[0] = name[0].toUpper();
00512 } else if ( !fullName.isEmpty() ) {
00513
00514 name = fullName;
00515 }
00516 mShadowIdentities << Identity( name, fullName, emailAddress );
00517 }
00518
00519 mShadowIdentities.last().setIsDefault( true );
00520 mShadowIdentities.last().setUoid( newUoid() );
00521 if ( mReadOnly ) {
00522 mIdentities = mShadowIdentities;
00523 }
00524 }
00525
00526 int IdentityManager::newUoid()
00527 {
00528 int uoid;
00529
00530
00531 QList<uint> usedUOIDs;
00532 for ( QList<Identity>::ConstIterator it = mIdentities.constBegin();
00533 it != mIdentities.constEnd(); ++it )
00534 usedUOIDs << (*it).uoid();
00535
00536 if ( hasPendingChanges() ) {
00537
00538
00539 for ( QList<Identity>::ConstIterator it = mShadowIdentities.constBegin();
00540 it != mShadowIdentities.constEnd(); ++it ) {
00541 usedUOIDs << (*it).uoid();
00542 }
00543 }
00544
00545 usedUOIDs << 0;
00546
00547
00548 do {
00549 uoid = KRandom::random();
00550 } while ( usedUOIDs.indexOf( uoid ) != -1 );
00551
00552 return uoid;
00553 }
00554
00555 QStringList KPIMIdentities::IdentityManager::allEmails() const
00556 {
00557 QStringList lst;
00558 for ( ConstIterator it = begin(); it != end(); ++it ) {
00559 lst << (*it).emailAddr();
00560 }
00561 return lst;
00562 }
00563
00564 void KPIMIdentities::IdentityManager::slotRollback()
00565 {
00566 rollback();
00567 }
00568
00569 void KPIMIdentities::IdentityManager::slotIdentitiesChanged( const QString &id )
00570 {
00571 kDebug( 5325 ) <<" KPIMIdentities::IdentityManager::slotIdentitiesChanged :" << id;
00572 if ( id != QDBusConnection::sessionBus().baseService() ) {
00573 mConfig->reparseConfiguration();
00574 Q_ASSERT( !hasPendingChanges() );
00575 readConfig( mConfig );
00576 emit changed();
00577 }
00578 }
00579
00580 #include "identitymanager.moc"