You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

361 lines
11 KiB

/* -*- c++ -*-
identitymanager.cpp
KMail, the KDE mail client.
Copyright (c) 2002 the KMail authors.
See file AUTHORS for details
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License,
version 2.0, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US
*/
// config keys:
static const char * configKeyDefaultIdentity = "Default Identity";
#include "identitymanager.h"
#include "kmidentity.h" // for IdentityList::{export,import}Data
#ifndef KMAIL_TESTING
#include "kmkernel.h"
#endif
#include <kemailsettings.h> // for IdentityEntry::fromControlCenter()
#include <kapplication.h>
#include <klocale.h>
#include <kconfig.h>
#include <kdebug.h>
#include <qregexp.h>
#include <qtl.h>
#include <pwd.h> // for struct pw;
#include <unistd.h> // for getuid
#include <assert.h>
IdentityManager::IdentityManager( QObject * parent, const char * name )
: ConfigManager( parent, name )
{
readConfig();
mShadowIdentities = mIdentities;
// we need at least a default identity:
if ( mIdentities.isEmpty() ) {
kdDebug( 5006 ) << "IdentityManager: No identity found. Creating default." << endl;
createDefaultIdentity();
commit();
}
}
IdentityManager::~IdentityManager()
{
kdWarning( hasPendingChanges(), 5006 )
<< "IdentityManager: There were uncommited changes!" << endl;
}
void IdentityManager::commit()
{
// early out:
if ( !hasPendingChanges() ) return;
QValueList<uint> seenUOIDs;
for ( QValueList<KMIdentity>::ConstIterator it = mIdentities.begin() ;
it != mIdentities.end() ; ++it )
seenUOIDs << (*it).uoid();
// find added and changed identities:
for ( QValueList<KMIdentity>::ConstIterator it = mShadowIdentities.begin() ;
it != mShadowIdentities.end() ; ++it ) {
QValueList<uint>::Iterator uoid = seenUOIDs.find( (*it).uoid() );
if ( uoid != seenUOIDs.end() ) {
// changed identity
kdDebug( 5006 ) << "emitting changed() for identity " << *uoid << endl;
emit changed( *it );
emit changed( *uoid );
seenUOIDs.remove( uoid );
} else {
// new identity
kdDebug( 5006 ) << "emitting added() for identity " << (*it).uoid() << endl;
emit added( *it );
}
}
// what's left are deleted identities:
for ( QValueList<uint>::ConstIterator it = seenUOIDs.begin() ;
it != seenUOIDs.end() ; ++it ) {
kdDebug( 5006 ) << "emitting deleted() for identity " << (*it) << endl;
emit deleted( *it );
}
mIdentities = mShadowIdentities;
writeConfig();
emit ConfigManager::changed();
}
void IdentityManager::rollback()
{
mShadowIdentities = mIdentities;
}
bool IdentityManager::hasPendingChanges() const
{
return mIdentities != mShadowIdentities;
}
QStringList IdentityManager::identities() const
{
QStringList result;
for ( ConstIterator it = mIdentities.begin() ;
it != mIdentities.end() ; ++it )
result << (*it).identityName();
return result;
}
QStringList IdentityManager::shadowIdentities() const
{
QStringList result;
for ( ConstIterator it = mShadowIdentities.begin() ;
it != mShadowIdentities.end() ; ++it )
result << (*it).identityName();
return result;
}
// hmm, anyone can explain why I need to explicitely instantate qHeapSort?
//template void qHeapSort( QValueList<KMIdentity> & );
void IdentityManager::sort() {
qHeapSort( mShadowIdentities );
}
void IdentityManager::writeConfig() const {
QStringList identities = groupList();
KConfig * config = kapp->config();
for ( QStringList::Iterator group = identities.begin() ;
group != identities.end() ; ++group )
config->deleteGroup( *group );
int i = 0;
for ( ConstIterator it = mIdentities.begin() ;
it != mIdentities.end() ; ++it, ++i ) {
KConfigGroup cg( config, QString::fromLatin1("Identity #%1").arg(i) );
(*it).writeConfig( &cg );
if ( (*it).isDefault() ) {
// remember which one is default:
KConfigGroup general( config, "General" );
general.writeEntry( configKeyDefaultIdentity, (*it).uoid() );
}
}
#ifndef KMAIL_TESTING
kernel->slotRequestConfigSync();
#else
config->sync();
#endif
}
void IdentityManager::readConfig() {
mIdentities.clear();
QStringList identities = groupList();
if ( identities.isEmpty() ) return; // nothing to be done...
KConfigGroup general( kapp->config(), "General" );
uint defaultIdentity = general.readUnsignedNumEntry( configKeyDefaultIdentity );
bool haveDefault = false;
for ( QStringList::Iterator group = identities.begin() ;
group != identities.end() ; ++group ) {
KConfigGroup config( kapp->config(), *group );
mIdentities << KMIdentity();
mIdentities.last().readConfig( &config );
if ( !haveDefault && mIdentities.last().uoid() == defaultIdentity ) {
haveDefault = true;
mIdentities.last().setIsDefault( true );
}
}
if ( !haveDefault ) {
kdWarning( 5006 ) << "IdentityManager: There was no default identity. Marking first one as default." << endl;
mIdentities.first().setIsDefault( true );
}
qHeapSort( mIdentities );
}
QStringList IdentityManager::groupList() const {
return kapp->config()->groupList().grep( QRegExp("^Identity #\\d+$") );
}
IdentityManager::ConstIterator IdentityManager::begin() const {
return mIdentities.begin();
}
IdentityManager::ConstIterator IdentityManager::end() const {
return mIdentities.end();
}
IdentityManager::Iterator IdentityManager::begin() {
return mShadowIdentities.begin();
}
IdentityManager::Iterator IdentityManager::end() {
return mShadowIdentities.end();
}
const KMIdentity & IdentityManager::identityForName( const QString & name ) const
{
kdWarning( 5006 )
<< "deprecated method IdentityManager::identityForName() called!" << endl;
for ( ConstIterator it = begin() ; it != end() ; ++it )
if ( (*it).identityName() == name ) return (*it);
return KMIdentity::null;
}
const KMIdentity & IdentityManager::identityForUoid( uint ouid ) const {
for ( ConstIterator it = begin() ; it != end() ; ++it )
if ( (*it).uoid() == ouid ) return (*it);
return KMIdentity::null;
}
const KMIdentity & IdentityManager::identityForNameOrDefault( const QString & name ) const
{
const KMIdentity & ident = identityForName( name );
if ( ident.isNull() )
return defaultIdentity();
else
return ident;
}
const KMIdentity & IdentityManager::identityForUoidOrDefault( uint ouid ) const
{
const KMIdentity & ident = identityForUoid( ouid );
if ( ident.isNull() )
return defaultIdentity();
else
return ident;
}
const KMIdentity & IdentityManager::identityForAddress( const QString & addressList ) const
{
for ( ConstIterator it = begin() ; it != end() ; ++it )
if ( addressList.find( (*it).emailAddr(), 0, false ) != -1 )
return (*it);
return KMIdentity::null;
}
KMIdentity & IdentityManager::identityForName( const QString & name )
{
for ( Iterator it = begin() ; it != end() ; ++it )
if ( (*it).identityName() == name ) return (*it);
kdWarning( 5006 ) << "IdentityManager::identityForName() used as newFromScratch() replacement!"
<< "\n name == \"" << name << "\"" << endl;
return newFromScratch( name );
}
const KMIdentity & IdentityManager::defaultIdentity() const {
for ( ConstIterator it = begin() ; it != end() ; ++it )
if ( (*it).isDefault() ) return (*it);
(mIdentities.isEmpty() ? kdFatal( 5006 ) : kdWarning( 5006 ) )
<< "IdentityManager: No default identity found!" << endl;
return *begin();
}
bool IdentityManager::setAsDefault( const QString & name ) {
// First, check if the identity actually exists:
QStringList names = shadowIdentities();
if ( names.find( name ) == names.end() ) return false;
// Then, change the default as requested:
for ( Iterator it = begin() ; it != end() ; ++it )
(*it).setIsDefault( (*it).identityName() == name );
// and re-sort:
sort();
return true;
}
bool IdentityManager::setAsDefault( uint uoid ) {
// First, check if the identity actually exists:
bool found = false;
for ( ConstIterator it = mShadowIdentities.begin() ;
it != mShadowIdentities.end() ; ++it )
if ( (*it).uoid() == uoid ) {
found = true;
break;
}
if ( !found ) return false;
// Then, change the default as requested:
for ( Iterator it = begin() ; it != end() ; ++it )
(*it).setIsDefault( (*it).uoid() == uoid );
// and re-sort:
sort();
return true;
}
bool IdentityManager::removeIdentity( const QString & name ) {
for ( Iterator it = begin() ; it != end() ; ++it )
if ( (*it).identityName() == name ) {
bool removedWasDefault = (*it).isDefault();
mShadowIdentities.remove( it );
if ( removedWasDefault )
mShadowIdentities.first().setIsDefault( true );
return true;
}
return false;
}
KMIdentity & IdentityManager::newFromScratch( const QString & name ) {
return newFromExisting( KMIdentity( name ) );
}
KMIdentity & IdentityManager::newFromControlCenter( const QString & name ) {
KEMailSettings es;
es.setProfile( es.defaultProfileName() );
return newFromExisting( KMIdentity( name,
es.getSetting( KEMailSettings::RealName ),
es.getSetting( KEMailSettings::EmailAddress ),
es.getSetting( KEMailSettings::Organization ),
es.getSetting( KEMailSettings::ReplyToAddress )
) );
}
KMIdentity & IdentityManager::newFromExisting( const KMIdentity & other,
const QString & name ) {
mShadowIdentities << other;
KMIdentity & result = mShadowIdentities.last();
result.setIsDefault( false ); // we don't want two default identities!
result.setUoid( kapp->random() ); // we don't want two identies w/ same UOID
if ( !name.isNull() )
result.setIdentityName( name );
return result;
}
void IdentityManager::createDefaultIdentity() {
struct passwd * pw = getpwuid( getuid() );
QString fullName/*, emailAddr*/;
if ( pw ) {
// extract possible full name from /etc/passwd
fullName = QString::fromLocal8Bit( pw->pw_gecos );
int i = fullName.find(',');
if ( i > 0 ) fullName.truncate( i );
/* ### This code is commented out because the guessed email address
### is most likely anyway wrong (because it contains the full hostname).
### Marc wanted to keep this stuff in the code for a future Config Wizard.
// extract login name from /etc/passwd and get hostname to form an
// educated guess about the possible email address:
char str[256];
if ( !gethostname( str, 255 ) )
// str need not be NUL-terminated if it has full length:
str[255] = 0;
else
str[0] = 0;
emailAddr = QString::fromLatin1("%1@%2")
.arg( QString::fromLocal8Bit( pw->pw_name ) )
.arg( QString::fromLatin1( *str ? str : "localhost" ) );
*/
}
mShadowIdentities << KMIdentity( i18n("Default"), fullName/*, emailAddr*/ );
mShadowIdentities.last().setIsDefault( true );
}
#include "identitymanager.moc"