• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

kpimidentities

identitymanager.cpp

00001 /*
00002     Copyright (c) 2002 Marc Mutz <mutz@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 // config keys:
00021 static const char configKeyDefaultIdentity[] = "Default Identity";
00022 
00023 #include "identitymanager.h"
00024 #include "identity.h" // for IdentityList::{export,import}Data
00025 
00026 #include <kpimutils/email.h> // for static helper functions
00027 
00028 #include <kemailsettings.h> // for IdentityEntry::fromControlCenter()
00029 #include <klocale.h>
00030 #include <kdebug.h>
00031 #include <kconfig.h>
00032 #include <kuser.h>
00033 #include <kconfiggroup.h>
00034 
00035 #include <QList>
00036 #include <QRegExp>
00037 #include <QtDBus/QtDBus>
00038 
00039 #include <assert.h>
00040 #include <krandom.h>
00041 
00042 #include "identitymanageradaptor.h"
00043 
00044 using namespace KPIMIdentities;
00045 
00046 static QString newDBusObjectName()
00047 {
00048   static int s_count = 0;
00049   QString name( "/KPIMIDENTITIES_IdentityManager" );
00050   if ( s_count++ ) {
00051     name += '_';
00052     name += QString::number( s_count );
00053   }
00054   return name;
00055 }
00056 
00057 IdentityManager::IdentityManager( bool readonly, QObject *parent,
00058                                   const char *name )
00059     : QObject( parent )
00060 {
00061   setObjectName( name );
00062   new IdentityManagerAdaptor( this );
00063   QDBusConnection dbus = QDBusConnection::sessionBus();
00064   const QString dbusPath = newDBusObjectName();
00065   const QString dbusInterface = "org.kde.pim.IdentityManager";
00066   dbus.registerObject( dbusPath, this );
00067   dbus.connect( QString(), dbusPath, dbusInterface, "identitiesChanged", this,
00068                 SLOT( slotIdentitiesChanged( QString ) ) );
00069 
00070   mReadOnly = readonly;
00071   mConfig = new KConfig( "emailidentities" );
00072   readConfig( mConfig );
00073   if ( mIdentities.isEmpty() ) {
00074     kDebug( 5325 ) << "emailidentities is empty -> convert from kmailrc";
00075     // No emailidentities file, or an empty one due to broken conversion
00076     // (kconf_update bug in kdelibs <= 3.2.2)
00077     // => convert it, i.e. read settings from kmailrc
00078     KConfig kmailConf( "kmailrc" );
00079     readConfig( &kmailConf );
00080   }
00081   // we need at least a default identity:
00082   if ( mIdentities.isEmpty() ) {
00083     kDebug( 5325 ) << "IdentityManager: No identity found. Creating default.";
00084     createDefaultIdentity();
00085     commit();
00086   }
00087   // Migration: people without settings in kemailsettings should get some
00088   if ( KEMailSettings().getSetting( KEMailSettings::EmailAddress ).isEmpty() ) {
00089     writeConfig();
00090   }
00091 }
00092 
00093 IdentityManager::~IdentityManager()
00094 {
00095   kWarning( hasPendingChanges(), 5325 )
00096   << "IdentityManager: There were uncommitted changes!";
00097   delete mConfig;
00098 }
00099 
00100 void IdentityManager::commit()
00101 {
00102   // early out:
00103   if ( !hasPendingChanges() || mReadOnly ) {
00104     return;
00105   }
00106 
00107   QList<uint> seenUOIDs;
00108   for ( QList<Identity>::ConstIterator it = mIdentities.begin();
00109         it != mIdentities.end(); ++it ) {
00110     seenUOIDs << (*it).uoid();
00111   }
00112 
00113   QList<uint> changedUOIDs;
00114   // find added and changed identities:
00115   for ( QList<Identity>::ConstIterator it = mShadowIdentities.begin();
00116         it != mShadowIdentities.end(); ++it ) {
00117     int index = seenUOIDs.indexOf( (*it).uoid() );
00118     if ( index != -1 ) {
00119       uint uoid = seenUOIDs.at( index );
00120       const Identity &orig = identityForUoid( uoid );  // look up in mIdentities
00121       if ( *it != orig ) {
00122         // changed identity
00123         kDebug( 5325 ) << "emitting changed() for identity" << uoid;
00124         emit changed(*it);
00125         changedUOIDs << uoid;
00126       }
00127       seenUOIDs.removeAll( uoid );
00128     } else {
00129       // new identity
00130       kDebug( 5325 ) << "emitting added() for identity" << (*it).uoid();
00131       emit added(*it);
00132     }
00133   }
00134 
00135   // what's left are deleted identities:
00136   for ( QList<uint>::ConstIterator it = seenUOIDs.begin();
00137         it != seenUOIDs.end(); ++it ) {
00138     kDebug( 5325 ) << "emitting deleted() for identity" << (*it);
00139     emit deleted(*it);
00140   }
00141 
00142   mIdentities = mShadowIdentities;
00143   writeConfig();
00144 
00145   // now that mIdentities has all the new info, we can emit the added/changed
00146   // signals that ship a uoid. This is because the slots might use
00147   // identityForUoid(uoid)...
00148   for ( QList<uint>::ConstIterator it = changedUOIDs.begin();
00149         it != changedUOIDs.end(); ++it )
00150     emit changed(*it);
00151 
00152   emit changed(); // normal signal
00153 
00154   // DBus signal for other IdentityManager instances
00155   emit identitiesChanged( QDBusConnection::sessionBus().baseService() );
00156 }
00157 
00158 void IdentityManager::rollback()
00159 {
00160   mShadowIdentities = mIdentities;
00161 }
00162 
00163 bool IdentityManager::hasPendingChanges() const
00164 {
00165   return mIdentities != mShadowIdentities;
00166 }
00167 
00168 QStringList IdentityManager::identities() const
00169 {
00170   QStringList result;
00171   for ( ConstIterator it = mIdentities.begin();
00172         it != mIdentities.end(); ++it )
00173     result << (*it).identityName();
00174   return result;
00175 }
00176 
00177 QStringList IdentityManager::shadowIdentities() const
00178 {
00179   QStringList result;
00180   for ( ConstIterator it = mShadowIdentities.begin();
00181         it != mShadowIdentities.end(); ++it )
00182     result << (*it).identityName();
00183   return result;
00184 }
00185 
00186 void IdentityManager::sort()
00187 {
00188   qSort( mShadowIdentities );
00189 }
00190 
00191 void IdentityManager::writeConfig() const
00192 {
00193   QStringList identities = groupList( mConfig );
00194   for ( QStringList::Iterator group = identities.begin();
00195         group != identities.end(); ++group )
00196     mConfig->deleteGroup( *group );
00197   int i = 0;
00198   for ( ConstIterator it = mIdentities.begin();
00199         it != mIdentities.end(); ++it, ++i ) {
00200     KConfigGroup cg( mConfig, QString::fromLatin1( "Identity #%1" ).arg( i ) );
00201     (*it).writeConfig( cg );
00202     if ( (*it).isDefault() ) {
00203       // remember which one is default:
00204       KConfigGroup general( mConfig, "General" );
00205       general.writeEntry( configKeyDefaultIdentity, (*it).uoid() );
00206 
00207       // Also write the default identity to emailsettings
00208       KEMailSettings es;
00209       es.setSetting( KEMailSettings::RealName, (*it).fullName() );
00210       es.setSetting( KEMailSettings::EmailAddress, (*it).emailAddr() );
00211       es.setSetting( KEMailSettings::Organization, (*it).organization() );
00212       es.setSetting( KEMailSettings::ReplyToAddress, (*it).replyToAddr() );
00213     }
00214   }
00215   mConfig->sync();
00216 
00217 }
00218 
00219 void IdentityManager::readConfig( KConfig *config )
00220 {
00221   mIdentities.clear();
00222 
00223   QStringList identities = groupList( config );
00224   if ( identities.isEmpty() ) {
00225     return; // nothing to be done...
00226   }
00227 
00228   KConfigGroup general( config, "General" );
00229   uint defaultIdentity = general.readEntry( configKeyDefaultIdentity, 0 );
00230   bool haveDefault = false;
00231 
00232   for ( QStringList::Iterator group = identities.begin();
00233         group != identities.end(); ++group ) {
00234     KConfigGroup configGroup( config, *group );
00235     mIdentities << Identity();
00236     mIdentities.last().readConfig( configGroup );
00237     if ( !haveDefault && mIdentities.last().uoid() == defaultIdentity ) {
00238       haveDefault = true;
00239       mIdentities.last().setIsDefault( true );
00240     }
00241   }
00242   if ( !haveDefault ) {
00243     kWarning( 5325 ) << "IdentityManager: There was no default identity."
00244                      << "Marking first one as default.";
00245     mIdentities.first().setIsDefault( true );
00246   }
00247   qSort( mIdentities );
00248 
00249   mShadowIdentities = mIdentities;
00250 }
00251 
00252 QStringList IdentityManager::groupList( KConfig *config ) const
00253 {
00254   return config->groupList().filter( QRegExp( "^Identity #\\d+$" ) );
00255 }
00256 
00257 IdentityManager::ConstIterator IdentityManager::begin() const
00258 {
00259   return mIdentities.begin();
00260 }
00261 
00262 IdentityManager::ConstIterator IdentityManager::end() const
00263 {
00264   return mIdentities.end();
00265 }
00266 
00267 IdentityManager::Iterator IdentityManager::modifyBegin()
00268 {
00269   return mShadowIdentities.begin();
00270 }
00271 
00272 IdentityManager::Iterator IdentityManager::modifyEnd()
00273 {
00274   return mShadowIdentities.end();
00275 }
00276 
00277 const Identity &IdentityManager::identityForUoid( uint uoid ) const
00278 {
00279   for ( ConstIterator it = begin(); it != end(); ++it ) {
00280     if ( (*it).uoid() == uoid ) {
00281       return (*it);
00282     }
00283   }
00284   return Identity::null();
00285 }
00286 
00287 const Identity &IdentityManager::identityForUoidOrDefault( uint uoid ) const
00288 {
00289   const Identity &ident = identityForUoid( uoid );
00290   if ( ident.isNull() ) {
00291     return defaultIdentity();
00292   } else {
00293     return ident;
00294   }
00295 }
00296 
00297 const Identity &IdentityManager::identityForAddress(
00298   const QString &addresses ) const
00299 {
00300   QStringList addressList = KPIMUtils::splitAddressList( addresses );
00301   for ( ConstIterator it = begin(); it != end(); ++it ) {
00302     for ( QStringList::ConstIterator addrIt = addressList.begin();
00303           addrIt != addressList.end(); ++addrIt ) {
00304       if ( (*it).emailAddr().toLower() == KPIMUtils::extractEmailAddress( *addrIt ).toLower() ) {
00305         return (*it);
00306       }
00307     }
00308   }
00309   return Identity::null();
00310 }
00311 
00312 bool IdentityManager::thatIsMe( const QString &addressList ) const
00313 {
00314   return !identityForAddress( addressList ).isNull();
00315 }
00316 
00317 Identity &IdentityManager::modifyIdentityForName( const QString &name )
00318 {
00319   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00320     if ( (*it).identityName() == name ) {
00321       return (*it);
00322     }
00323   }
00324 
00325   kWarning( 5325 ) << "IdentityManager::modifyIdentityForName() used as"
00326                    << "newFromScratch() replacement!"
00327                    << endl << "  name == \"" << name << "\"";
00328   return newFromScratch( name );
00329 }
00330 
00331 Identity &IdentityManager::modifyIdentityForUoid( uint uoid )
00332 {
00333   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00334     if ( (*it).uoid() == uoid ) {
00335       return (*it);
00336     }
00337   }
00338 
00339   kWarning( 5325 ) << "IdentityManager::identityForUoid() used as"
00340                    << "newFromScratch() replacement!"
00341                    << endl << "  uoid == \"" << uoid << "\"";
00342   return newFromScratch( i18n( "Unnamed" ) );
00343 }
00344 
00345 const Identity &IdentityManager::defaultIdentity() const
00346 {
00347   for ( ConstIterator it = begin(); it != end(); ++it ) {
00348     if ( (*it).isDefault() ) {
00349       return (*it);
00350     }
00351   }
00352 
00353   if ( mIdentities.isEmpty() )
00354       kFatal( 5325 ) << "IdentityManager: No default identity found!";
00355   else
00356       kWarning( 5325 ) << "IdentityManager: No default identity found!";
00357   return *begin();
00358 }
00359 
00360 bool IdentityManager::setAsDefault( uint uoid )
00361 {
00362   // First, check if the identity actually exists:
00363   bool found = false;
00364   for ( ConstIterator it = mShadowIdentities.begin();
00365         it != mShadowIdentities.end(); ++it )
00366     if ( (*it).uoid() == uoid ) {
00367       found = true;
00368       break;
00369     }
00370 
00371   if ( !found ) {
00372     return false;
00373   }
00374 
00375   // Then, change the default as requested:
00376   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00377     (*it).setIsDefault( (*it).uoid() == uoid );
00378   }
00379 
00380   // and re-sort:
00381   sort();
00382   return true;
00383 }
00384 
00385 bool IdentityManager::removeIdentity( const QString &name )
00386 {
00387   if ( mShadowIdentities.size() <= 1 )
00388     return false;
00389 
00390   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00391     if ( (*it).identityName() == name ) {
00392       bool removedWasDefault = (*it).isDefault();
00393       mShadowIdentities.erase( it );
00394       if ( removedWasDefault ) {
00395         mShadowIdentities.first().setIsDefault( true );
00396       }
00397       return true;
00398     }
00399   }
00400   return false;
00401 }
00402 
00403 Identity &IdentityManager::newFromScratch( const QString &name )
00404 {
00405   return newFromExisting( Identity( name ) );
00406 }
00407 
00408 Identity &IdentityManager::newFromControlCenter( const QString &name )
00409 {
00410   KEMailSettings es;
00411   es.setProfile( es.defaultProfileName() );
00412 
00413   return
00414     newFromExisting( Identity( name,
00415                                es.getSetting( KEMailSettings::RealName ),
00416                                es.getSetting( KEMailSettings::EmailAddress ),
00417                                es.getSetting( KEMailSettings::Organization ),
00418                                es.getSetting( KEMailSettings::ReplyToAddress ) ) );
00419 }
00420 
00421 Identity &IdentityManager::newFromExisting( const Identity &other,
00422     const QString &name )
00423 {
00424   mShadowIdentities << other;
00425   Identity &result = mShadowIdentities.last();
00426   result.setIsDefault( false );  // we don't want two default identities!
00427   result.setUoid( newUoid() );  // we don't want two identies w/ same UOID
00428   if ( !name.isNull() ) {
00429     result.setIdentityName( name );
00430   }
00431   return result;
00432 }
00433 
00434 void IdentityManager::createDefaultIdentity()
00435 {
00436   QString fullName, emailAddress;
00437   bool done = false;
00438 
00439   // Check if the application has any settings
00440   createDefaultIdentity( fullName, emailAddress );
00441 
00442   // If not, then use the kcontrol settings
00443   if ( fullName.isEmpty() && emailAddress.isEmpty() ) {
00444     KEMailSettings emailSettings;
00445     fullName = emailSettings.getSetting( KEMailSettings::RealName );
00446     emailAddress = emailSettings.getSetting( KEMailSettings::EmailAddress );
00447 
00448     if ( !fullName.isEmpty() && !emailAddress.isEmpty() ) {
00449       newFromControlCenter( i18n( "Default" ) );
00450       done = true;
00451     } else {
00452       // If KEmailSettings doesn't have name and address, generate something from KUser
00453       KUser user;
00454       if ( fullName.isEmpty() ) {
00455         fullName = user.property( KUser::FullName ).toString();
00456       }
00457       if ( emailAddress.isEmpty() ) {
00458         emailAddress = user.loginName();
00459         if ( !emailAddress.isEmpty() ) {
00460           KConfigGroup general( mConfig, "General" );
00461           QString defaultdomain = general.readEntry( "Default domain" );
00462           if ( !defaultdomain.isEmpty() ) {
00463             emailAddress += '@' + defaultdomain;
00464           } else {
00465             emailAddress.clear();
00466           }
00467         }
00468       }
00469     }
00470   }
00471 
00472   if ( !done ) {
00473     mShadowIdentities << Identity( i18n( "Default" ), fullName, emailAddress );
00474   }
00475 
00476   mShadowIdentities.last().setIsDefault( true );
00477   mShadowIdentities.last().setUoid( newUoid() );
00478   if ( mReadOnly ) { // commit won't do it in readonly mode
00479     mIdentities = mShadowIdentities;
00480   }
00481 }
00482 
00483 int IdentityManager::newUoid()
00484 {
00485   int uoid;
00486 
00487   // determine the UOIDs of all saved identities
00488   QList<uint> usedUOIDs;
00489   for ( QList<Identity>::ConstIterator it = mIdentities.begin();
00490         it != mIdentities.end(); ++it )
00491     usedUOIDs << (*it).uoid();
00492 
00493   if ( hasPendingChanges() ) {
00494     // add UOIDs of all shadow identities. Yes, we will add a lot of duplicate
00495     // UOIDs, but avoiding duplicate UOIDs isn't worth the effort.
00496     for ( QList<Identity>::ConstIterator it = mShadowIdentities.begin();
00497           it != mShadowIdentities.end(); ++it ) {
00498       usedUOIDs << (*it).uoid();
00499     }
00500   }
00501 
00502   usedUOIDs << 0; // no UOID must be 0 because this value always refers to the
00503   // default identity
00504 
00505   do {
00506     uoid = KRandom::random();
00507   } while ( usedUOIDs.indexOf( uoid ) != -1 );
00508 
00509   return uoid;
00510 }
00511 
00512 QStringList KPIMIdentities::IdentityManager::allEmails() const
00513 {
00514   QStringList lst;
00515   for ( ConstIterator it = begin(); it != end(); ++it ) {
00516     lst << (*it).emailAddr();
00517   }
00518   return lst;
00519 }
00520 
00521 void KPIMIdentities::IdentityManager::slotRollback()
00522 {
00523   rollback();
00524 }
00525 
00526 void KPIMIdentities::IdentityManager::slotIdentitiesChanged( const QString &id )
00527 {
00528   kDebug( 5325 ) <<" KPIMIdentities::IdentityManager::slotIdentitiesChanged :" << id;
00529   if ( id != QDBusConnection::sessionBus().baseService() ) {
00530     mConfig->reparseConfiguration();
00531     Q_ASSERT( !hasPendingChanges() );
00532     readConfig( mConfig );
00533     emit changed();
00534   }
00535 }
00536 
00537 #include "identitymanager.moc"

kpimidentities

Skip menu "kpimidentities"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal