• Skip to content
  • Skip to link menu
KDE 4.2 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 QString IdentityManager::makeUnique( const QString &name ) const
00101 {
00102   int suffix = 1;
00103   QString result = name;
00104   while ( identities().contains( result ) ) {
00105     result = i18nc( "%1: name; %2: number appended to it to make it unique "
00106                     "among a list of names", "%1 #%2",
00107                     name, suffix );
00108     suffix++;
00109   }
00110   return result;
00111 }
00112 
00113 bool IdentityManager::isUnique( const QString &name ) const
00114 {
00115   return !identities().contains( name );
00116 }
00117 
00118 void IdentityManager::commit()
00119 {
00120   // early out:
00121   if ( !hasPendingChanges() || mReadOnly ) {
00122     return;
00123   }
00124 
00125   QList<uint> seenUOIDs;
00126   for ( QList<Identity>::ConstIterator it = mIdentities.constBegin();
00127         it != mIdentities.constEnd(); ++it ) {
00128     seenUOIDs << (*it).uoid();
00129   }
00130 
00131   QList<uint> changedUOIDs;
00132   // find added and changed identities:
00133   for ( QList<Identity>::ConstIterator it = mShadowIdentities.constBegin();
00134         it != mShadowIdentities.constEnd(); ++it ) {
00135     int index = seenUOIDs.indexOf( (*it).uoid() );
00136     if ( index != -1 ) {
00137       uint uoid = seenUOIDs.at( index );
00138       const Identity &orig = identityForUoid( uoid );  // look up in mIdentities
00139       if ( *it != orig ) {
00140         // changed identity
00141         kDebug( 5325 ) << "emitting changed() for identity" << uoid;
00142         emit changed(*it);
00143         changedUOIDs << uoid;
00144       }
00145       seenUOIDs.removeAll( uoid );
00146     } else {
00147       // new identity
00148       kDebug( 5325 ) << "emitting added() for identity" << (*it).uoid();
00149       emit added(*it);
00150     }
00151   }
00152 
00153   // what's left are deleted identities:
00154   for ( QList<uint>::ConstIterator it = seenUOIDs.constBegin();
00155         it != seenUOIDs.constEnd(); ++it ) {
00156     kDebug( 5325 ) << "emitting deleted() for identity" << (*it);
00157     emit deleted(*it);
00158   }
00159 
00160   mIdentities = mShadowIdentities;
00161   writeConfig();
00162 
00163   // now that mIdentities has all the new info, we can emit the added/changed
00164   // signals that ship a uoid. This is because the slots might use
00165   // identityForUoid(uoid)...
00166   for ( QList<uint>::ConstIterator it = changedUOIDs.constBegin();
00167         it != changedUOIDs.constEnd(); ++it )
00168     emit changed(*it);
00169 
00170   emit changed(); // normal signal
00171 
00172   // DBus signal for other IdentityManager instances
00173   emit identitiesChanged( QDBusConnection::sessionBus().baseService() );
00174 }
00175 
00176 void IdentityManager::rollback()
00177 {
00178   mShadowIdentities = mIdentities;
00179 }
00180 
00181 bool IdentityManager::hasPendingChanges() const
00182 {
00183   return mIdentities != mShadowIdentities;
00184 }
00185 
00186 QStringList IdentityManager::identities() const
00187 {
00188   QStringList result;
00189   for ( ConstIterator it = mIdentities.begin();
00190         it != mIdentities.end(); ++it )
00191     result << (*it).identityName();
00192   return result;
00193 }
00194 
00195 QStringList IdentityManager::shadowIdentities() const
00196 {
00197   QStringList result;
00198   for ( ConstIterator it = mShadowIdentities.begin();
00199         it != mShadowIdentities.end(); ++it )
00200     result << (*it).identityName();
00201   return result;
00202 }
00203 
00204 void IdentityManager::sort()
00205 {
00206   qSort( mShadowIdentities );
00207 }
00208 
00209 void IdentityManager::writeConfig() const
00210 {
00211   const QStringList identities = groupList( mConfig );
00212   for ( QStringList::const_iterator group = identities.begin();
00213         group != identities.end(); ++group )
00214     mConfig->deleteGroup( *group );
00215   int i = 0;
00216   for ( ConstIterator it = mIdentities.begin();
00217         it != mIdentities.end(); ++it, ++i ) {
00218     KConfigGroup cg( mConfig, QString::fromLatin1( "Identity #%1" ).arg( i ) );
00219     (*it).writeConfig( cg );
00220     if ( (*it).isDefault() ) {
00221       // remember which one is default:
00222       KConfigGroup general( mConfig, "General" );
00223       general.writeEntry( configKeyDefaultIdentity, (*it).uoid() );
00224 
00225       // Also write the default identity to emailsettings
00226       KEMailSettings es;
00227       es.setSetting( KEMailSettings::RealName, (*it).fullName() );
00228       es.setSetting( KEMailSettings::EmailAddress, (*it).emailAddr() );
00229       es.setSetting( KEMailSettings::Organization, (*it).organization() );
00230       es.setSetting( KEMailSettings::ReplyToAddress, (*it).replyToAddr() );
00231     }
00232   }
00233   mConfig->sync();
00234 
00235 }
00236 
00237 void IdentityManager::readConfig( KConfig *config )
00238 {
00239   mIdentities.clear();
00240 
00241   const QStringList identities = groupList( config );
00242   if ( identities.isEmpty() ) {
00243     return; // nothing to be done...
00244   }
00245 
00246   KConfigGroup general( config, "General" );
00247   uint defaultIdentity = general.readEntry( configKeyDefaultIdentity, 0 );
00248   bool haveDefault = false;
00249 
00250   for ( QStringList::const_iterator group = identities.begin();
00251         group != identities.end(); ++group ) {
00252     KConfigGroup configGroup( config, *group );
00253     mIdentities << Identity();
00254     mIdentities.last().readConfig( configGroup );
00255     if ( !haveDefault && mIdentities.last().uoid() == defaultIdentity ) {
00256       haveDefault = true;
00257       mIdentities.last().setIsDefault( true );
00258     }
00259   }
00260   if ( !haveDefault ) {
00261     kWarning( 5325 ) << "IdentityManager: There was no default identity."
00262                      << "Marking first one as default.";
00263     mIdentities.first().setIsDefault( true );
00264   }
00265   qSort( mIdentities );
00266 
00267   mShadowIdentities = mIdentities;
00268 }
00269 
00270 QStringList IdentityManager::groupList( KConfig *config ) const
00271 {
00272   return config->groupList().filter( QRegExp( "^Identity #\\d+$" ) );
00273 }
00274 
00275 IdentityManager::ConstIterator IdentityManager::begin() const
00276 {
00277   return mIdentities.begin();
00278 }
00279 
00280 IdentityManager::ConstIterator IdentityManager::end() const
00281 {
00282   return mIdentities.end();
00283 }
00284 
00285 IdentityManager::Iterator IdentityManager::modifyBegin()
00286 {
00287   return mShadowIdentities.begin();
00288 }
00289 
00290 IdentityManager::Iterator IdentityManager::modifyEnd()
00291 {
00292   return mShadowIdentities.end();
00293 }
00294 
00295 const Identity &IdentityManager::identityForUoid( uint uoid ) const
00296 {
00297   for ( ConstIterator it = begin(); it != end(); ++it ) {
00298     if ( (*it).uoid() == uoid ) {
00299       return (*it);
00300     }
00301   }
00302   return Identity::null();
00303 }
00304 
00305 const Identity &IdentityManager::identityForUoidOrDefault( uint uoid ) const
00306 {
00307   const Identity &ident = identityForUoid( uoid );
00308   if ( ident.isNull() ) {
00309     return defaultIdentity();
00310   } else {
00311     return ident;
00312   }
00313 }
00314 
00315 const Identity &IdentityManager::identityForAddress(
00316   const QString &addresses ) const
00317 {
00318   QStringList addressList = KPIMUtils::splitAddressList( addresses );
00319   for ( ConstIterator it = begin(); it != end(); ++it ) {
00320     for ( QStringList::ConstIterator addrIt = addressList.constBegin();
00321           addrIt != addressList.constEnd(); ++addrIt ) {
00322       if ( (*it).emailAddr().toLower() == KPIMUtils::extractEmailAddress( *addrIt ).toLower() ) {
00323         return (*it);
00324       }
00325     }
00326   }
00327   return Identity::null();
00328 }
00329 
00330 bool IdentityManager::thatIsMe( const QString &addressList ) const
00331 {
00332   return !identityForAddress( addressList ).isNull();
00333 }
00334 
00335 Identity &IdentityManager::modifyIdentityForName( const QString &name )
00336 {
00337   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00338     if ( (*it).identityName() == name ) {
00339       return (*it);
00340     }
00341   }
00342 
00343   kWarning( 5325 ) << "IdentityManager::modifyIdentityForName() used as"
00344                    << "newFromScratch() replacement!"
00345                    << endl << "  name == \"" << name << "\"";
00346   return newFromScratch( name );
00347 }
00348 
00349 Identity &IdentityManager::modifyIdentityForUoid( uint uoid )
00350 {
00351   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00352     if ( (*it).uoid() == uoid ) {
00353       return (*it);
00354     }
00355   }
00356 
00357   kWarning( 5325 ) << "IdentityManager::identityForUoid() used as"
00358                    << "newFromScratch() replacement!"
00359                    << endl << "  uoid == \"" << uoid << "\"";
00360   return newFromScratch( i18n( "Unnamed" ) );
00361 }
00362 
00363 const Identity &IdentityManager::defaultIdentity() const
00364 {
00365   for ( ConstIterator it = begin(); it != end(); ++it ) {
00366     if ( (*it).isDefault() ) {
00367       return (*it);
00368     }
00369   }
00370 
00371   if ( mIdentities.isEmpty() )
00372       kFatal( 5325 ) << "IdentityManager: No default identity found!";
00373   else
00374       kWarning( 5325 ) << "IdentityManager: No default identity found!";
00375   return *begin();
00376 }
00377 
00378 bool IdentityManager::setAsDefault( uint uoid )
00379 {
00380   // First, check if the identity actually exists:
00381   bool found = false;
00382   for ( ConstIterator it = mShadowIdentities.constBegin();
00383         it != mShadowIdentities.constEnd(); ++it )
00384     if ( (*it).uoid() == uoid ) {
00385       found = true;
00386       break;
00387     }
00388 
00389   if ( !found ) {
00390     return false;
00391   }
00392 
00393   // Then, change the default as requested:
00394   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00395     (*it).setIsDefault( (*it).uoid() == uoid );
00396   }
00397 
00398   // and re-sort:
00399   sort();
00400   return true;
00401 }
00402 
00403 bool IdentityManager::removeIdentity( const QString &name )
00404 {
00405   if ( mShadowIdentities.size() <= 1 )
00406     return false;
00407 
00408   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
00409     if ( (*it).identityName() == name ) {
00410       bool removedWasDefault = (*it).isDefault();
00411       mShadowIdentities.erase( it );
00412       if ( removedWasDefault ) {
00413         mShadowIdentities.first().setIsDefault( true );
00414       }
00415       return true;
00416     }
00417   }
00418   return false;
00419 }
00420 
00421 Identity &IdentityManager::newFromScratch( const QString &name )
00422 {
00423   return newFromExisting( Identity( name ) );
00424 }
00425 
00426 Identity &IdentityManager::newFromControlCenter( const QString &name )
00427 {
00428   KEMailSettings es;
00429   es.setProfile( es.defaultProfileName() );
00430 
00431   return
00432     newFromExisting( Identity( name,
00433                                es.getSetting( KEMailSettings::RealName ),
00434                                es.getSetting( KEMailSettings::EmailAddress ),
00435                                es.getSetting( KEMailSettings::Organization ),
00436                                es.getSetting( KEMailSettings::ReplyToAddress ) ) );
00437 }
00438 
00439 Identity &IdentityManager::newFromExisting( const Identity &other,
00440     const QString &name )
00441 {
00442   mShadowIdentities << other;
00443   Identity &result = mShadowIdentities.last();
00444   result.setIsDefault( false );  // we don't want two default identities!
00445   result.setUoid( newUoid() );  // we don't want two identies w/ same UOID
00446   if ( !name.isNull() ) {
00447     result.setIdentityName( name );
00448   }
00449   return result;
00450 }
00451 
00452 void IdentityManager::createDefaultIdentity()
00453 {
00454   QString fullName, emailAddress;
00455   bool done = false;
00456 
00457   // Check if the application has any settings
00458   createDefaultIdentity( fullName, emailAddress );
00459 
00460   // If not, then use the kcontrol settings
00461   if ( fullName.isEmpty() && emailAddress.isEmpty() ) {
00462     KEMailSettings emailSettings;
00463     fullName = emailSettings.getSetting( KEMailSettings::RealName );
00464     emailAddress = emailSettings.getSetting( KEMailSettings::EmailAddress );
00465 
00466     if ( !fullName.isEmpty() && !emailAddress.isEmpty() ) {
00467       newFromControlCenter( i18nc( "use default address from control center",
00468                                    "Default" ) );
00469       done = true;
00470     } else {
00471       // If KEmailSettings doesn't have name and address, generate something from KUser
00472       KUser user;
00473       if ( fullName.isEmpty() ) {
00474         fullName = user.property( KUser::FullName ).toString();
00475       }
00476       if ( emailAddress.isEmpty() ) {
00477         emailAddress = user.loginName();
00478         if ( !emailAddress.isEmpty() ) {
00479           KConfigGroup general( mConfig, "General" );
00480           QString defaultdomain = general.readEntry( "Default domain" );
00481           if ( !defaultdomain.isEmpty() ) {
00482             emailAddress += '@' + defaultdomain;
00483           } else {
00484             emailAddress.clear();
00485           }
00486         }
00487       }
00488     }
00489   }
00490 
00491   if ( !done ) {
00492     // Default identity name
00493     QString name( i18nc( "Default name for new email accounts/identities.", "Unnamed" ) );
00494 
00495     if ( !emailAddress.isEmpty() ) {
00496       // If we have an email address, create a default identity name from it
00497       QString idName = emailAddress;
00498       int pos = idName.indexOf( '@' );
00499       if ( pos != -1 ) {
00500         name = idName.mid( pos + 1, -1 );
00501       }
00502 
00503       // Make the name a bit more human friendly
00504       name.replace( '.', ' ' );
00505       pos = name.indexOf( ' ' );
00506       if ( pos != 0 ) {
00507         name[pos + 1] = name[pos + 1].toUpper();
00508       }
00509       name[0] = name[0].toUpper();
00510     } else if ( !fullName.isEmpty() ) {
00511       // If we have a full name, create a default identity name from it
00512       name = fullName;
00513     }
00514     mShadowIdentities << Identity( name, fullName, emailAddress );
00515   }
00516 
00517   mShadowIdentities.last().setIsDefault( true );
00518   mShadowIdentities.last().setUoid( newUoid() );
00519   if ( mReadOnly ) { // commit won't do it in readonly mode
00520     mIdentities = mShadowIdentities;
00521   }
00522 }
00523 
00524 int IdentityManager::newUoid()
00525 {
00526   int uoid;
00527 
00528   // determine the UOIDs of all saved identities
00529   QList<uint> usedUOIDs;
00530   for ( QList<Identity>::ConstIterator it = mIdentities.constBegin();
00531         it != mIdentities.constEnd(); ++it )
00532     usedUOIDs << (*it).uoid();
00533 
00534   if ( hasPendingChanges() ) {
00535     // add UOIDs of all shadow identities. Yes, we will add a lot of duplicate
00536     // UOIDs, but avoiding duplicate UOIDs isn't worth the effort.
00537     for ( QList<Identity>::ConstIterator it = mShadowIdentities.constBegin();
00538           it != mShadowIdentities.constEnd(); ++it ) {
00539       usedUOIDs << (*it).uoid();
00540     }
00541   }
00542 
00543   usedUOIDs << 0; // no UOID must be 0 because this value always refers to the
00544   // default identity
00545 
00546   do {
00547     uoid = KRandom::random();
00548   } while ( usedUOIDs.indexOf( uoid ) != -1 );
00549 
00550   return uoid;
00551 }
00552 
00553 QStringList KPIMIdentities::IdentityManager::allEmails() const
00554 {
00555   QStringList lst;
00556   for ( ConstIterator it = begin(); it != end(); ++it ) {
00557     lst << (*it).emailAddr();
00558   }
00559   return lst;
00560 }
00561 
00562 void KPIMIdentities::IdentityManager::slotRollback()
00563 {
00564   rollback();
00565 }
00566 
00567 void KPIMIdentities::IdentityManager::slotIdentitiesChanged( const QString &id )
00568 {
00569   kDebug( 5325 ) <<" KPIMIdentities::IdentityManager::slotIdentitiesChanged :" << id;
00570   if ( id != QDBusConnection::sessionBus().baseService() ) {
00571     mConfig->reparseConfiguration();
00572     Q_ASSERT( !hasPendingChanges() );
00573     readConfig( mConfig );
00574     emit changed();
00575   }
00576 }
00577 
00578 #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"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.6
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