Index: signature.cpp
===================================================================
--- signature.cpp	(revision 821148)
+++ signature.cpp	(revision 821149)
@@ -33,47 +33,25 @@
 
 using namespace KPIMIdentities;
 
-Signature::Signature()
-  : mType( Disabled ),
-    mInlinedHtml( false )
-{}
+/**
+ *   Private class that helps to provide binary compatibility between releases.
+ *   @internal
+ */
+//@cond PRIVATE
+class KPIMIdentities::Signature::Private
+{
+  public:
+    QString textFromFile( bool *ok ) const;
+    QString textFromCommand( bool *ok ) const;
 
-Signature::Signature( const QString &text )
-  : mText( text ),
-    mType( Inlined ),
-    mInlinedHtml( false )
-{}
+    QString mUrl;
+    QString mText;
+    Type    mType;
+    bool mInlinedHtml;
+};
 
-Signature::Signature( const QString &url, bool isExecutable )
-  : mUrl( url ),
-    mType( isExecutable ? FromCommand : FromFile ),
-    mInlinedHtml( false )
-{}
-
-QString Signature::rawText( bool *ok ) const
+QString Signature::Private::textFromCommand( bool *ok ) const
 {
-  switch ( mType ) {
-  case Disabled:
-    if ( ok ) {
-      *ok = true;
-    }
-    return QString();
-  case Inlined:
-    if ( ok ) {
-      *ok = true;
-    }
-    return mText;
-  case FromFile:
-    return textFromFile( ok );
-  case FromCommand:
-    return textFromCommand( ok );
-  };
-  kFatal(5325) << "Signature::type() returned unknown value!";
-  return QString(); // make compiler happy
-}
-
-QString Signature::textFromCommand( bool *ok ) const
-{
   assert( mType == FromCommand );
 
   // handle pathological cases:
@@ -113,7 +91,7 @@
   return QString::fromLocal8Bit( output.data(), output.size() );
 }
 
-QString Signature::textFromFile( bool *ok ) const
+QString Signature::Private::textFromFile( bool *ok ) const
 {
   assert( mType == FromFile );
 
@@ -138,6 +116,64 @@
   return QString::fromLocal8Bit( ba.data(), ba.size() );
 }
 
+//@endcond
+
+Signature::Signature()
+  : d( new Private )
+{
+    d->mType = Disabled;
+    d->mInlinedHtml = false;
+}
+
+Signature::Signature( const QString &text )
+  : d( new Private )
+{
+    d->mText = text;
+    d->mType = Inlined;
+    d->mInlinedHtml = false;
+}
+
+Signature::Signature( const QString &url, bool isExecutable )
+  : d( new Private )
+{
+    d->mUrl = url;
+    d->mType = isExecutable ? FromCommand : FromFile;
+    d->mInlinedHtml = false;
+}
+
+Signature::Signature( const Signature &other )
+  : d( new Private )
+{
+    *d = *other.d;
+}
+
+Signature::~Signature()
+{
+  delete d;
+}
+
+QString Signature::rawText( bool *ok ) const
+{
+  switch ( d->mType ) {
+  case Disabled:
+    if ( ok ) {
+      *ok = true;
+    }
+    return QString();
+  case Inlined:
+    if ( ok ) {
+      *ok = true;
+    }
+    return d->mText;
+  case FromFile:
+    return d->textFromFile( ok );
+  case FromCommand:
+    return d->textFromCommand( ok );
+  };
+  kFatal(5325) << "Signature::type() returned unknown value!";
+  return QString(); // make compiler happy
+}
+
 QString Signature::withSeparator( bool *ok ) const
 {
   QString signature = rawText( ok );
@@ -148,7 +184,7 @@
     return signature; // don't add a separator in this case
   }
 
-  QString newline = ( isInlinedHtml() && mType == Inlined ) ? "<br>" : "\n";
+  QString newline = ( isInlinedHtml() && d->mType == Inlined ) ? "<br>" : "\n";
   if ( signature.startsWith( QString::fromLatin1( "-- " ) + newline )
     || ( signature.indexOf( newline + QString::fromLatin1( "-- " ) +
                             newline ) != -1 ) ) {
@@ -162,18 +198,18 @@
 
 void Signature::setUrl( const QString &url, bool isExecutable )
 {
-  mUrl = url;
-  mType = isExecutable ? FromCommand : FromFile;
+  d->mUrl = url;
+  d->mType = isExecutable ? FromCommand : FromFile;
 }
 
 void Signature::setInlinedHtml( bool isHtml )
 {
-  mInlinedHtml = isHtml;
+  d->mInlinedHtml = isHtml;
 }
 
 bool Signature::isInlinedHtml() const
 {
-  return mInlinedHtml;
+  return d->mInlinedHtml;
 }
 
 // config keys and values:
@@ -191,41 +227,41 @@
 {
   QString sigType = config.readEntry( sigTypeKey );
   if ( sigType == sigTypeInlineValue ) {
-    mType = Inlined;
-    mInlinedHtml = config.readEntry( sigTypeInlinedHtmlKey, false );
+    d->mType = Inlined;
+    d->mInlinedHtml = config.readEntry( sigTypeInlinedHtmlKey, false );
   } else if ( sigType == sigTypeFileValue ) {
-    mType = FromFile;
-    mUrl = config.readPathEntry( sigFileKey, QString() );
+    d->mType = FromFile;
+    d->mUrl = config.readPathEntry( sigFileKey, QString() );
   } else if ( sigType == sigTypeCommandValue ) {
-    mType = FromCommand;
-    mUrl = config.readPathEntry( sigCommandKey, QString() );
+    d->mType = FromCommand;
+    d->mUrl = config.readPathEntry( sigCommandKey, QString() );
   } else {
-    mType = Disabled;
+    d->mType = Disabled;
   }
-  mText = config.readEntry( sigTextKey );
+  d->mText = config.readEntry( sigTextKey );
 }
 
 void Signature::writeConfig( KConfigGroup &config ) const
 {
-  switch ( mType ) {
+  switch ( d->mType ) {
     case Inlined:
       config.writeEntry( sigTypeKey, sigTypeInlineValue );
-      config.writeEntry( sigTypeInlinedHtmlKey, mInlinedHtml );
+      config.writeEntry( sigTypeInlinedHtmlKey, d->mInlinedHtml );
       break;
     case FromFile:
       config.writeEntry( sigTypeKey, sigTypeFileValue );
-      config.writePathEntry( sigFileKey, mUrl );
+      config.writePathEntry( sigFileKey, d->mUrl );
       break;
     case FromCommand:
       config.writeEntry( sigTypeKey, sigTypeCommandValue );
-      config.writePathEntry( sigCommandKey, mUrl );
+      config.writePathEntry( sigCommandKey, d->mUrl );
       break;
     case Disabled:
       config.writeEntry( sigTypeKey, sigTypeDisabledValue );
     default:
       break;
   }
-  config.writeEntry( sigTextKey, mText );
+  config.writeEntry( sigTextKey, d->mText );
 }
 
 // --------------------- Operators -------------------//
@@ -233,61 +269,67 @@
 QDataStream &KPIMIdentities::operator<<
 ( QDataStream &stream, const KPIMIdentities::Signature &sig )
 {
-  return stream << static_cast<quint8>( sig.mType ) << sig.mUrl << sig.mText;
+  return stream << static_cast<quint8>( sig.d->mType ) << sig.d->mUrl << sig.d->mText;
 }
 
 QDataStream &KPIMIdentities::operator>>
 ( QDataStream &stream, KPIMIdentities::Signature &sig )
 {
   quint8 s;
-  stream >> s  >> sig.mUrl >> sig.mText;
-  sig.mType = static_cast<Signature::Type>( s );
+  stream >> s  >> sig.d->mUrl >> sig.d->mText;
+  sig.d->mType = static_cast<Signature::Type>( s );
   return stream;
 }
 
 bool Signature::operator== ( const Signature &other ) const
 {
-  if ( mType != other.mType ) {
+  if ( d->mType != other.d->mType ) {
     return false;
   }
 
-  switch ( mType ) {
+  switch ( d->mType ) {
   case Inlined:
-    return mText == other.mText;
+    return d->mText == other.d->mText;
   case FromFile:
   case FromCommand:
-    return mUrl == other.mUrl;
+    return d->mUrl == other.d->mUrl;
   default:
   case Disabled:
     return true;
   }
 }
 
+Signature Signature::operator=( const Signature &other )
+{
+    *d = *other.d;
+    return *this;
+}
+
 // --------------- Getters -----------------------//
 
 QString Signature::text() const
 {
-  return mText;
+  return d->mText;
 }
 
 QString Signature::url() const
 {
-  return mUrl;
+  return d->mUrl;
 }
 
 Signature::Type Signature::type() const
 {
-  return mType;
+  return d->mType;
 }
 
 // --------------- Setters -----------------------//
 
 void Signature::setText( const QString &text )
 {
-  mText = text;
+  d->mText = text;
 }
 
 void Signature::setType( Type type )
 {
-  mType = type;
+  d->mType = type;
 }
Index: signature.h
===================================================================
--- signature.h	(revision 821148)
+++ signature.h	(revision 821149)
@@ -68,6 +68,7 @@
 
       /** Used for comparison */
       bool operator== ( const Signature &other ) const;
+      Signature operator= ( const Signature &other );
 
       /** Constructor for disabled signature */
       Signature();
@@ -75,7 +76,12 @@
       Signature( const QString &text );
       /** Constructor for text from a file or from output of a command */
       Signature( const QString &url, bool isExecutable );
+      /** Copy constructor */
+      Signature( const Signature &other );
 
+      /** Destructor */
+      ~Signature();
+
       /** @return the raw signature text as entered resp. read from file. */
       QString rawText( bool *ok=0 ) const;
 
@@ -115,13 +121,10 @@
       void readConfig( const KConfigGroup &config );
 
     private:
-      QString textFromFile( bool *ok ) const;
-      QString textFromCommand( bool *ok ) const;
-
-      QString mUrl;
-      QString mText;
-      Type    mType;
-      bool mInlinedHtml;
+      //@cond PRIVATE
+      class Private;
+      Private *d;
+      //@endcond
   };
 
 }
Index: identitymanager.cpp
===================================================================
--- identitymanager.cpp	(revision 821148)
+++ identitymanager.cpp	(revision 821149)
@@ -54,9 +54,199 @@
   return name;
 }
 
+
+/**
+ *   Private class that helps to provide binary compatibility between releases.
+ *   @internal
+ */
+//@cond PRIVATE
+class KPIMIdentities::IdentityManager::Private
+{
+  public:
+    Private( KPIMIdentities::IdentityManager* );
+    void writeConfig() const;
+    void readConfig( KConfig *config );
+    void createDefaultIdentity();
+    QStringList groupList( KConfig *config ) const;
+    void slotIdentitiesChanged( const QString &id );
+    KConfig *mConfig;
+      
+    QList<Identity> mIdentities;
+    QList<Identity> mShadowIdentities;
+
+    // returns a new Unique Object Identifier
+    int newUoid();
+
+    bool readOnly;
+    KPIMIdentities::IdentityManager *q;
+};
+//@endcond
+
+IdentityManager::Private::Private( KPIMIdentities::IdentityManager *manager): q( manager )
+{
+}
+
+void IdentityManager::Private::writeConfig() const
+{
+  QStringList identities = groupList( mConfig );
+  for ( QStringList::Iterator group = identities.begin();
+        group != identities.end(); ++group )
+    mConfig->deleteGroup( *group );
+  int i = 0;
+  for ( ConstIterator it = mIdentities.begin();
+        it != mIdentities.end(); ++it, ++i ) {
+    KConfigGroup cg( mConfig, QString::fromLatin1( "Identity #%1" ).arg( i ) );
+    (*it).writeConfig( cg );
+    if ( (*it).isDefault() ) {
+      // remember which one is default:
+      KConfigGroup general( mConfig, "General" );
+      general.writeEntry( configKeyDefaultIdentity, (*it).uoid() );
+
+      // Also write the default identity to emailsettings
+      KEMailSettings es;
+      es.setSetting( KEMailSettings::RealName, (*it).fullName() );
+      es.setSetting( KEMailSettings::EmailAddress, (*it).emailAddr() );
+      es.setSetting( KEMailSettings::Organization, (*it).organization() );
+      es.setSetting( KEMailSettings::ReplyToAddress, (*it).replyToAddr() );
+    }
+  }
+  mConfig->sync();
+}
+
+void IdentityManager::Private::readConfig( KConfig *config )
+{
+  mIdentities.clear();
+
+  QStringList identities = groupList( config );
+  if ( identities.isEmpty() ) {
+    return; // nothing to be done...
+  }
+
+  KConfigGroup general( config, "General" );
+  uint defaultIdentity = general.readEntry( configKeyDefaultIdentity, 0 );
+  bool haveDefault = false;
+
+  for ( QStringList::Iterator group = identities.begin();
+        group != identities.end(); ++group ) {
+    KConfigGroup configGroup( config, *group );
+    Identity identity;
+    identity.readConfig( configGroup );
+    if ( !haveDefault && identity.uoid() == defaultIdentity ) {
+      haveDefault = true;
+      identity.setIsDefault( true );
+    }
+    mIdentities << identity;
+  }
+  if ( !haveDefault ) {
+    kWarning( 5325 ) << "IdentityManager: There was no default identity."
+                     << "Marking first one as default.";
+    mIdentities.first().setIsDefault( true );
+  }
+  qSort( mIdentities );
+
+  mShadowIdentities = mIdentities;
+}
+
+void IdentityManager::Private::createDefaultIdentity()
+{
+  QString fullName, emailAddress;
+  bool done = false;
+
+  // Check if the application has any settings
+  q->createDefaultIdentity( fullName, emailAddress );
+
+  // If not, then use the kcontrol settings
+  if ( fullName.isEmpty() && emailAddress.isEmpty() ) {
+    KEMailSettings emailSettings;
+    fullName = emailSettings.getSetting( KEMailSettings::RealName );
+    emailAddress = emailSettings.getSetting( KEMailSettings::EmailAddress );
+
+    if ( !fullName.isEmpty() && !emailAddress.isEmpty() ) {
+      q->newFromControlCenter( i18nc( "use default address from control center",
+                                   "Default" ) );
+      done = true;
+    } else {
+      // If KEmailSettings doesn't have name and address, generate something from KUser
+      KUser user;
+      if ( fullName.isEmpty() ) {
+        fullName = user.property( KUser::FullName ).toString();
+      }
+      if ( emailAddress.isEmpty() ) {
+        emailAddress = user.loginName();
+        if ( !emailAddress.isEmpty() ) {
+          KConfigGroup general( mConfig, "General" );
+          QString defaultdomain = general.readEntry( "Default domain" );
+          if ( !defaultdomain.isEmpty() ) {
+            emailAddress += '@' + defaultdomain;
+          } else {
+            emailAddress.clear();
+          }
+        }
+      }
+    }
+  }
+
+  if ( !done ) {
+    mShadowIdentities << Identity( i18nc( "show default identity", "Default" ), fullName, emailAddress );
+  }
+
+  mShadowIdentities.last().setIsDefault( true );
+  mShadowIdentities.last().setUoid( newUoid() );
+  if ( readOnly ) { // commit won't do it in readonly mode
+    mIdentities = mShadowIdentities;
+  }
+}
+
+QStringList IdentityManager::Private::groupList( KConfig *config ) const
+{
+  return config->groupList().filter( QRegExp( "^Identity #\\d+$" ) );
+}
+
+int IdentityManager::Private::newUoid()
+{
+  int uoid;
+
+  // determine the UOIDs of all saved identities
+  QList<uint> usedUOIDs;
+  for ( QList<Identity>::ConstIterator it = mIdentities.begin();
+        it != mIdentities.end(); ++it )
+    usedUOIDs << (*it).uoid();
+
+  if ( q->hasPendingChanges() ) {
+    // add UOIDs of all shadow identities. Yes, we will add a lot of duplicate
+    // UOIDs, but avoiding duplicate UOIDs isn't worth the effort.
+    for ( QList<Identity>::ConstIterator it = mShadowIdentities.begin();
+          it != mShadowIdentities.end(); ++it ) {
+      usedUOIDs << (*it).uoid();
+    }
+  }
+
+  usedUOIDs << 0; // no UOID must be 0 because this value always refers to the
+  // default identity
+
+  do {
+    uoid = KRandom::random();
+  } while ( usedUOIDs.indexOf( uoid ) != -1 );
+
+  return uoid;
+}
+
+void IdentityManager::Private::slotIdentitiesChanged( const QString &id )
+{
+  kDebug( 5325 ) <<" KPIMIdentities::IdentityManager::slotIdentitiesChanged :" << id;
+  if ( id != QDBusConnection::sessionBus().baseService() ) {
+    mConfig->reparseConfiguration();
+    Q_ASSERT( !q->hasPendingChanges() );
+    readConfig( mConfig );
+    emit q->changed();
+  }
+}
+
+// --- non private implementation -------
+
 IdentityManager::IdentityManager( bool readonly, QObject *parent,
                                   const char *name )
-    : QObject( parent )
+    : QObject( parent ), d( new Private( this ) )
 {
   setObjectName( name );
   new IdentityManagerAdaptor( this );
@@ -67,26 +257,26 @@
   dbus.connect( QString(), dbusPath, dbusInterface, "identitiesChanged", this,
                 SLOT( slotIdentitiesChanged( QString ) ) );
 
-  mReadOnly = readonly;
-  mConfig = new KConfig( "emailidentities" );
-  readConfig( mConfig );
-  if ( mIdentities.isEmpty() ) {
+  d->mConfig = new KConfig( "emailidentities" );
+  d->readOnly = readonly;
+  d->readConfig( d->mConfig );
+  if ( d->mIdentities.isEmpty() ) {
     kDebug( 5325 ) << "emailidentities is empty -> convert from kmailrc";
     // No emailidentities file, or an empty one due to broken conversion
     // (kconf_update bug in kdelibs <= 3.2.2)
     // => convert it, i.e. read settings from kmailrc
     KConfig kmailConf( "kmailrc" );
-    readConfig( &kmailConf );
+    d->readConfig( &kmailConf );
   }
   // we need at least a default identity:
-  if ( mIdentities.isEmpty() ) {
+  if ( d->mIdentities.isEmpty() ) {
     kDebug( 5325 ) << "IdentityManager: No identity found. Creating default.";
-    createDefaultIdentity();
+    d->createDefaultIdentity();
     commit();
   }
   // Migration: people without settings in kemailsettings should get some
   if ( KEMailSettings().getSetting( KEMailSettings::EmailAddress ).isEmpty() ) {
-    writeConfig();
+    d->writeConfig();
   }
 }
 
@@ -94,26 +284,26 @@
 {
   kWarning( hasPendingChanges(), 5325 )
   << "IdentityManager: There were uncommitted changes!";
-  delete mConfig;
+  delete d;
 }
 
 void IdentityManager::commit()
 {
   // early out:
-  if ( !hasPendingChanges() || mReadOnly ) {
+  if ( !hasPendingChanges() || d->readOnly ) {
     return;
   }
 
   QList<uint> seenUOIDs;
-  for ( QList<Identity>::ConstIterator it = mIdentities.begin();
-        it != mIdentities.end(); ++it ) {
+  for ( QList<Identity>::ConstIterator it = d->mIdentities.begin();
+        it != d->mIdentities.end(); ++it ) {
     seenUOIDs << (*it).uoid();
   }
 
   QList<uint> changedUOIDs;
   // find added and changed identities:
-  for ( QList<Identity>::ConstIterator it = mShadowIdentities.begin();
-        it != mShadowIdentities.end(); ++it ) {
+  for ( QList<Identity>::ConstIterator it = d->mShadowIdentities.begin();
+        it != d->mShadowIdentities.end(); ++it ) {
     int index = seenUOIDs.indexOf( (*it).uoid() );
     if ( index != -1 ) {
       uint uoid = seenUOIDs.at( index );
@@ -139,8 +329,8 @@
     emit deleted(*it);
   }
 
-  mIdentities = mShadowIdentities;
-  writeConfig();
+  d->mIdentities = d->mShadowIdentities;
+  d->writeConfig();
 
   // now that mIdentities has all the new info, we can emit the added/changed
   // signals that ship a uoid. This is because the slots might use
@@ -157,19 +347,19 @@
 
 void IdentityManager::rollback()
 {
-  mShadowIdentities = mIdentities;
+  d->mShadowIdentities = d->mIdentities;
 }
 
 bool IdentityManager::hasPendingChanges() const
 {
-  return mIdentities != mShadowIdentities;
+  return d->mIdentities != d->mShadowIdentities;
 }
 
 QStringList IdentityManager::identities() const
 {
   QStringList result;
-  for ( ConstIterator it = mIdentities.begin();
-        it != mIdentities.end(); ++it )
+  for ( ConstIterator it = d->mIdentities.begin();
+        it != d->mIdentities.end(); ++it )
     result << (*it).identityName();
   return result;
 }
@@ -177,101 +367,36 @@
 QStringList IdentityManager::shadowIdentities() const
 {
   QStringList result;
-  for ( ConstIterator it = mShadowIdentities.begin();
-        it != mShadowIdentities.end(); ++it )
+  for ( ConstIterator it = d->mShadowIdentities.begin();
+        it != d->mShadowIdentities.end(); ++it )
     result << (*it).identityName();
   return result;
 }
 
 void IdentityManager::sort()
 {
-  qSort( mShadowIdentities );
+  qSort( d->mShadowIdentities );
 }
 
-void IdentityManager::writeConfig() const
-{
-  QStringList identities = groupList( mConfig );
-  for ( QStringList::Iterator group = identities.begin();
-        group != identities.end(); ++group )
-    mConfig->deleteGroup( *group );
-  int i = 0;
-  for ( ConstIterator it = mIdentities.begin();
-        it != mIdentities.end(); ++it, ++i ) {
-    KConfigGroup cg( mConfig, QString::fromLatin1( "Identity #%1" ).arg( i ) );
-    (*it).writeConfig( cg );
-    if ( (*it).isDefault() ) {
-      // remember which one is default:
-      KConfigGroup general( mConfig, "General" );
-      general.writeEntry( configKeyDefaultIdentity, (*it).uoid() );
 
-      // Also write the default identity to emailsettings
-      KEMailSettings es;
-      es.setSetting( KEMailSettings::RealName, (*it).fullName() );
-      es.setSetting( KEMailSettings::EmailAddress, (*it).emailAddr() );
-      es.setSetting( KEMailSettings::Organization, (*it).organization() );
-      es.setSetting( KEMailSettings::ReplyToAddress, (*it).replyToAddr() );
-    }
-  }
-  mConfig->sync();
-
-}
-
-void IdentityManager::readConfig( KConfig *config )
-{
-  mIdentities.clear();
-
-  QStringList identities = groupList( config );
-  if ( identities.isEmpty() ) {
-    return; // nothing to be done...
-  }
-
-  KConfigGroup general( config, "General" );
-  uint defaultIdentity = general.readEntry( configKeyDefaultIdentity, 0 );
-  bool haveDefault = false;
-
-  for ( QStringList::Iterator group = identities.begin();
-        group != identities.end(); ++group ) {
-    KConfigGroup configGroup( config, *group );
-    mIdentities << Identity();
-    mIdentities.last().readConfig( configGroup );
-    if ( !haveDefault && mIdentities.last().uoid() == defaultIdentity ) {
-      haveDefault = true;
-      mIdentities.last().setIsDefault( true );
-    }
-  }
-  if ( !haveDefault ) {
-    kWarning( 5325 ) << "IdentityManager: There was no default identity."
-                     << "Marking first one as default.";
-    mIdentities.first().setIsDefault( true );
-  }
-  qSort( mIdentities );
-
-  mShadowIdentities = mIdentities;
-}
-
-QStringList IdentityManager::groupList( KConfig *config ) const
-{
-  return config->groupList().filter( QRegExp( "^Identity #\\d+$" ) );
-}
-
 IdentityManager::ConstIterator IdentityManager::begin() const
 {
-  return mIdentities.begin();
+  return d->mIdentities.begin();
 }
 
 IdentityManager::ConstIterator IdentityManager::end() const
 {
-  return mIdentities.end();
+  return d->mIdentities.end();
 }
 
 IdentityManager::Iterator IdentityManager::modifyBegin()
 {
-  return mShadowIdentities.begin();
+  return d->mShadowIdentities.begin();
 }
 
 IdentityManager::Iterator IdentityManager::modifyEnd()
 {
-  return mShadowIdentities.end();
+  return d->mShadowIdentities.end();
 }
 
 const Identity &IdentityManager::identityForUoid( uint uoid ) const
@@ -350,7 +475,7 @@
     }
   }
 
-  if ( mIdentities.isEmpty() )
+  if ( d->mIdentities.isEmpty() )
       kFatal( 5325 ) << "IdentityManager: No default identity found!";
   else
       kWarning( 5325 ) << "IdentityManager: No default identity found!";
@@ -361,8 +486,8 @@
 {
   // First, check if the identity actually exists:
   bool found = false;
-  for ( ConstIterator it = mShadowIdentities.begin();
-        it != mShadowIdentities.end(); ++it )
+  for ( ConstIterator it = d->mShadowIdentities.begin();
+        it != d->mShadowIdentities.end(); ++it )
     if ( (*it).uoid() == uoid ) {
       found = true;
       break;
@@ -384,15 +509,15 @@
 
 bool IdentityManager::removeIdentity( const QString &name )
 {
-  if ( mShadowIdentities.size() <= 1 )
+  if ( d->mShadowIdentities.size() <= 1 )
     return false;
 
   for ( Iterator it = modifyBegin(); it != modifyEnd(); ++it ) {
     if ( (*it).identityName() == name ) {
       bool removedWasDefault = (*it).isDefault();
-      mShadowIdentities.erase( it );
+      d->mShadowIdentities.erase( it );
       if ( removedWasDefault ) {
-        mShadowIdentities.first().setIsDefault( true );
+        d->mShadowIdentities.first().setIsDefault( true );
       }
       return true;
     }
@@ -421,95 +546,17 @@
 Identity &IdentityManager::newFromExisting( const Identity &other,
     const QString &name )
 {
-  mShadowIdentities << other;
-  Identity &result = mShadowIdentities.last();
+  d->mShadowIdentities << other;
+  Identity &result = d->mShadowIdentities.last();
   result.setIsDefault( false );  // we don't want two default identities!
-  result.setUoid( newUoid() );  // we don't want two identies w/ same UOID
+  result.setUoid( d->newUoid() );  // we don't want two identies w/ same UOID
   if ( !name.isNull() ) {
     result.setIdentityName( name );
   }
   return result;
 }
 
-void IdentityManager::createDefaultIdentity()
-{
-  QString fullName, emailAddress;
-  bool done = false;
 
-  // Check if the application has any settings
-  createDefaultIdentity( fullName, emailAddress );
-
-  // If not, then use the kcontrol settings
-  if ( fullName.isEmpty() && emailAddress.isEmpty() ) {
-    KEMailSettings emailSettings;
-    fullName = emailSettings.getSetting( KEMailSettings::RealName );
-    emailAddress = emailSettings.getSetting( KEMailSettings::EmailAddress );
-
-    if ( !fullName.isEmpty() && !emailAddress.isEmpty() ) {
-      newFromControlCenter( i18nc( "use default address from control center",
-                                   "Default" ) );
-      done = true;
-    } else {
-      // If KEmailSettings doesn't have name and address, generate something from KUser
-      KUser user;
-      if ( fullName.isEmpty() ) {
-        fullName = user.property( KUser::FullName ).toString();
-      }
-      if ( emailAddress.isEmpty() ) {
-        emailAddress = user.loginName();
-        if ( !emailAddress.isEmpty() ) {
-          KConfigGroup general( mConfig, "General" );
-          QString defaultdomain = general.readEntry( "Default domain" );
-          if ( !defaultdomain.isEmpty() ) {
-            emailAddress += '@' + defaultdomain;
-          } else {
-            emailAddress.clear();
-          }
-        }
-      }
-    }
-  }
-
-  if ( !done ) {
-    mShadowIdentities << Identity( i18nc( "show default identity", "Default" ), fullName, emailAddress );
-  }
-
-  mShadowIdentities.last().setIsDefault( true );
-  mShadowIdentities.last().setUoid( newUoid() );
-  if ( mReadOnly ) { // commit won't do it in readonly mode
-    mIdentities = mShadowIdentities;
-  }
-}
-
-int IdentityManager::newUoid()
-{
-  int uoid;
-
-  // determine the UOIDs of all saved identities
-  QList<uint> usedUOIDs;
-  for ( QList<Identity>::ConstIterator it = mIdentities.begin();
-        it != mIdentities.end(); ++it )
-    usedUOIDs << (*it).uoid();
-
-  if ( hasPendingChanges() ) {
-    // add UOIDs of all shadow identities. Yes, we will add a lot of duplicate
-    // UOIDs, but avoiding duplicate UOIDs isn't worth the effort.
-    for ( QList<Identity>::ConstIterator it = mShadowIdentities.begin();
-          it != mShadowIdentities.end(); ++it ) {
-      usedUOIDs << (*it).uoid();
-    }
-  }
-
-  usedUOIDs << 0; // no UOID must be 0 because this value always refers to the
-  // default identity
-
-  do {
-    uoid = KRandom::random();
-  } while ( usedUOIDs.indexOf( uoid ) != -1 );
-
-  return uoid;
-}
-
 QStringList KPIMIdentities::IdentityManager::allEmails() const
 {
   QStringList lst;
@@ -524,15 +571,4 @@
   rollback();
 }
 
-void KPIMIdentities::IdentityManager::slotIdentitiesChanged( const QString &id )
-{
-  kDebug( 5325 ) <<" KPIMIdentities::IdentityManager::slotIdentitiesChanged :" << id;
-  if ( id != QDBusConnection::sessionBus().baseService() ) {
-    mConfig->reparseConfiguration();
-    Q_ASSERT( !hasPendingChanges() );
-    readConfig( mConfig );
-    emit changed();
-  }
-}
-
 #include "identitymanager.moc"
Index: identitymanager.h
===================================================================
--- identitymanager.h	(revision 821148)
+++ identitymanager.h	(revision 821149)
@@ -192,30 +192,17 @@
       void slotRollback();
 
     protected:
-      /** The list that will be seen by everyone */
-      QList<Identity> mIdentities;
-      /** The list that will be seen by the config dialog */
-      QList<Identity> mShadowIdentities;
 
     Q_SIGNALS:
       void identitiesChanged( const QString &id );
 
-    private Q_SLOTS:
-      // Connected to the DBus signal
-      void slotIdentitiesChanged( const QString &id );
-
     private:
-      void writeConfig() const;
-      void readConfig( KConfig *config );
-      QStringList groupList( KConfig *config ) const;
-      void createDefaultIdentity();
+     //@cond PRIVATE
+     class Private;
+     Private *d;
+     //@endcond
 
-      // returns a new Unique Object Identifier
-      int newUoid();
-
-    private:
-      KConfig *mConfig;
-      bool mReadOnly;
+     Q_PRIVATE_SLOT( d, void slotIdentitiesChanged( const QString &id ) )
 };
 
 } // namespace
