00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kopeteaccountmanager.h"
00020
00021 #include <QtGui/QApplication>
00022 #include <QtCore/QRegExp>
00023 #include <QtCore/QTimer>
00024 #include <QtCore/QHash>
00025
00026 #include <ksharedconfig.h>
00027 #include <kdebug.h>
00028 #include <kglobal.h>
00029 #include <kplugininfo.h>
00030 #include <kconfiggroup.h>
00031 #include <solid/networking.h>
00032
00033 #include "kopeteaccount.h"
00034 #include "kopeteaway.h"
00035 #include "kopetebehaviorsettings.h"
00036 #include "kopeteprotocol.h"
00037 #include "kopetecontact.h"
00038 #include "kopetecontactlist.h"
00039 #include "kopeteidentitymanager.h"
00040 #include "kopetepluginmanager.h"
00041 #include "kopeteonlinestatus.h"
00042 #include "kopeteonlinestatusmanager.h"
00043 #include "kopetemetacontact.h"
00044 #include "kopetegroup.h"
00045
00046 namespace Kopete {
00047
00048 static int compareAccountsByPriority( Account *a, Account *b )
00049 {
00050 uint priority1 = a->priority();
00051 uint priority2 = b->priority();
00052
00053 if( a==b )
00054 return 0;
00055 else if( priority1 > priority2 )
00056 return 1;
00057 else
00058 return -1;
00059 }
00060
00061 class AccountManager::Private
00062 {
00063 public:
00064 QList<Account *> accounts;
00065 };
00066
00067 AccountManager * AccountManager::s_self = 0L;
00068
00069 AccountManager * AccountManager::self()
00070 {
00071 if ( !s_self )
00072 s_self = new AccountManager;
00073
00074 return s_self;
00075 }
00076
00077
00078 AccountManager::AccountManager()
00079 : QObject( qApp )
00080 {
00081 setObjectName( "KopeteAccountManager" );
00082 d = new Private;
00083 connect( Solid::Networking::notifier(), SIGNAL(shouldConnect()), this, SLOT( networkConnected() ) );
00084 connect( Solid::Networking::notifier(), SIGNAL(shouldDisconnect()), this, SLOT( networkDisconnected() ) );
00085 }
00086
00087
00088 AccountManager::~AccountManager()
00089 {
00090 s_self = 0L;
00091
00092 delete d;
00093 }
00094
00095 bool AccountManager::isAnyAccountConnected() const
00096 {
00097 foreach( Account *a , d->accounts )
00098 {
00099 if( a->isConnected() )
00100 return true;
00101 }
00102
00103 return false;
00104 }
00105
00106 void AccountManager::setOnlineStatus( uint category, const QString& awayMessage, uint flags )
00107 {
00108 kDebug() << "category: " << category << ", Kopete::OnlineStatusManager::Away: " << Kopete::OnlineStatusManager::Away;
00109 OnlineStatusManager::Categories categories
00110 = (OnlineStatusManager::Categories)category;
00111 bool onlyChangeConnectedAccounts = isAnyAccountConnected();
00112
00113 foreach( Account *account, d->accounts )
00114 {
00115 Kopete::OnlineStatus status = OnlineStatusManager::self()->onlineStatus( account->protocol(), categories );
00116
00117 if ( category & Kopete::OnlineStatusManager::Offline ) {
00118 account->setOnlineStatus( status, awayMessage );
00119 continue;
00120 }
00121
00122 if ( onlyChangeConnectedAccounts ) {
00123 if ( account->isConnected() || ( (flags & ConnectIfOffline) && !account->excludeConnect() ) )
00124 account->setOnlineStatus( status, awayMessage );
00125 }
00126 else {
00127 if ( !account->excludeConnect() )
00128 account->setOnlineStatus( status, awayMessage );
00129 }
00130 }
00131
00132 Away::setGlobalAway( category & Kopete::OnlineStatusManager::Away );
00133 }
00134
00135 void AccountManager::setStatusMessage(const QString &message)
00136 {
00137 foreach( Account *account, d->accounts )
00138 {
00139 account->setStatusMessage(message);
00140 }
00141 }
00142
00143 QColor AccountManager::guessColor( Protocol *protocol ) const
00144 {
00145
00146
00147
00148 int protocolCount = 0;
00149
00150 for ( QListIterator<Account *> it( d->accounts ); it.hasNext(); )
00151 {
00152 Account *a = it.next();
00153 if ( a->protocol()->pluginId() == protocol->pluginId() )
00154 protocolCount++;
00155 }
00156
00157
00158 QColor color;
00159 switch ( protocolCount % 7 )
00160 {
00161 case 0:
00162 color = QColor();
00163 break;
00164 case 1:
00165 color = Qt::red;
00166 break;
00167 case 2:
00168 color = Qt::green;
00169 break;
00170 case 3:
00171 color = Qt::blue;
00172 break;
00173 case 4:
00174 color = Qt::yellow;
00175 break;
00176 case 5:
00177 color = Qt::magenta;
00178 break;
00179 case 6:
00180 color = Qt::cyan;
00181 break;
00182 }
00183
00184 return color;
00185 }
00186
00187 Account* AccountManager::registerAccount( Account *account )
00188 {
00189 if( !account || d->accounts.contains( account ) )
00190 return account;
00191
00192 if( account->accountId().isEmpty() )
00193 {
00194 account->deleteLater();
00195 return 0L;
00196 }
00197
00198
00199 QListIterator<Account *> it( d->accounts );
00200 while ( it.hasNext() )
00201 {
00202 Account *curracc = it.next();
00203 if ( ( account->protocol() == curracc->protocol() ) && ( account->accountId() == curracc->accountId() ) )
00204 {
00205 account->deleteLater();
00206 return 0L;
00207 }
00208 }
00209
00210 d->accounts.append( account );
00211 qSort( d->accounts.begin(), d->accounts.end(), compareAccountsByPriority );
00212
00213
00214 connect(account->myself(), SIGNAL(onlineStatusChanged(Kopete::Contact *,
00215 const Kopete::OnlineStatus &, const Kopete::OnlineStatus &)),
00216 this, SLOT(slotAccountOnlineStatusChanged(Kopete::Contact *,
00217 const Kopete::OnlineStatus &, const Kopete::OnlineStatus &)));
00218
00219 connect(account, SIGNAL(accountDestroyed(const Kopete::Account *)) , this, SLOT( unregisterAccount(const Kopete::Account *) ));
00220
00221 emit accountRegistered( account );
00222 return account;
00223 }
00224
00225 void AccountManager::unregisterAccount( const Account *account )
00226 {
00227 kDebug( 14010 ) << "Unregistering account " << account->accountId();
00228 d->accounts.removeAll( const_cast<Account*>(account) );
00229 emit accountUnregistered( account );
00230 }
00231
00232 const QList<Account *>& AccountManager::accounts() const
00233 {
00234 return d->accounts;
00235 }
00236
00237 QList<Account*> AccountManager::accounts( Protocol* protocol ) const
00238 {
00239 QList<Account*> protocolAccounts;
00240 foreach( Account* acct, d->accounts )
00241 {
00242 if ( acct->protocol() == protocol )
00243 protocolAccounts.append( acct );
00244 }
00245 return protocolAccounts;
00246 }
00247
00248 Account * AccountManager::findAccount( const QString &protocolId, const QString &accountId )
00249 {
00250 for ( QListIterator<Account *> it( d->accounts ); it.hasNext(); )
00251 {
00252 Account *a = it.next();
00253 if ( a->protocol()->pluginId() == protocolId && a->accountId() == accountId )
00254 return a;
00255 }
00256 return 0L;
00257 }
00258
00259 void AccountManager::removeAccount( Account *account )
00260 {
00261 if(!account->removeAccount())
00262 return;
00263
00264 Protocol *protocol = account->protocol();
00265
00266 KConfigGroup *configgroup = account->configGroup();
00267
00268
00269 const QHash<QString, Kopete::Contact*> contactList = account->contacts();
00270 QHash<QString, Kopete::Contact*>::ConstIterator it, itEnd = contactList.constEnd();
00271
00272 for ( it = contactList.constBegin(); it != itEnd; ++it )
00273 {
00274 Contact* c = it.value();
00275 MetaContact* mc = c->metaContact();
00276 if ( mc == ContactList::self()->myself() )
00277 continue;
00278 mc->removeContact( c );
00279 c->deleteLater();
00280 if ( mc->contacts().count() == 0 )
00281 {
00282
00283 Group* group = mc->groups().first();
00284 MetaContact::List groupMembers = group->members();
00285 ContactList::self()->removeMetaContact( mc );
00286 if ( groupMembers.count() == 1 && groupMembers.indexOf( mc ) != -1 )
00287 ContactList::self()->removeGroup( group );
00288 }
00289 }
00290
00291
00292 d->accounts.removeAll( account );
00293
00294
00295 configgroup->deleteGroup();
00296 configgroup->sync();
00297
00298 delete account;
00299
00300 foreach( Account *account , d->accounts )
00301 {
00302 if( account->protocol() == protocol )
00303 return;
00304 }
00305
00306
00307
00308
00309 QString protocolName = protocol->pluginId().remove( QString::fromLatin1( "Protocol" ) ).toLower();
00310
00311 PluginManager::self()->setPluginEnabled( protocolName, false );
00312 PluginManager::self()->unloadPlugin( protocolName );
00313 }
00314
00315 void AccountManager::save()
00316 {
00317
00318 qSort( d->accounts.begin(), d->accounts.end(), compareAccountsByPriority );
00319
00320 for ( QListIterator<Account *> it( d->accounts ); it.hasNext(); )
00321 {
00322 Account *a = it.next();
00323 KConfigGroup *config = a->configGroup();
00324
00325 config->writeEntry( "Protocol", a->protocol()->pluginId() );
00326 config->writeEntry( "AccountId", a->accountId() );
00327 }
00328
00329 KGlobal::config()->sync();
00330 }
00331
00332 void AccountManager::load()
00333 {
00334 connect( PluginManager::self(), SIGNAL( pluginLoaded( Kopete::Plugin * ) ),
00335 this, SLOT( slotPluginLoaded( Kopete::Plugin * ) ) );
00336
00337
00338
00339
00340
00341 KSharedConfig::Ptr config = KGlobal::config();
00342 QStringList accountGroups = config->groupList().filter( QRegExp( QString::fromLatin1( "^Account_" ) ) );
00343 for ( QStringList::Iterator it = accountGroups.begin(); it != accountGroups.end(); ++it )
00344 {
00345 KConfigGroup cg( config, *it );
00346
00347 QString protocol = cg.readEntry( "Protocol", QString() );
00348 if ( protocol.endsWith( QString::fromLatin1( "Protocol" ) ) )
00349 protocol = QString::fromLatin1( "kopete_" ) + protocol.toLower().remove( QString::fromLatin1( "protocol" ) );
00350
00351 if ( cg.readEntry( "Enabled", true ) )
00352 PluginManager::self()->loadPlugin( protocol, PluginManager::LoadAsync );
00353 }
00354 }
00355
00356 void AccountManager::slotPluginLoaded( Plugin *plugin )
00357 {
00358 Protocol* protocol = dynamic_cast<Protocol*>( plugin );
00359 if ( !protocol )
00360 return;
00361
00362
00363
00364 KSharedConfig::Ptr config = KGlobal::config();
00365 QStringList accountGroups = config->groupList().filter( QRegExp( QString::fromLatin1( "^Account_" ) ) );
00366 for ( QStringList::Iterator it = accountGroups.begin(); it != accountGroups.end(); ++it )
00367 {
00368 KConfigGroup cg( config, *it );
00369
00370 if ( cg.readEntry( "Protocol" ) != protocol->pluginId() )
00371 continue;
00372
00373
00374 if ( !cg.readEntry( "Enabled", true ) )
00375 continue;
00376
00377 QString accountId = cg.readEntry( "AccountId", QString() );
00378 if ( accountId.isEmpty() )
00379 {
00380 kWarning( 14010 ) <<
00381 "Not creating account for empty accountId." << endl;
00382 continue;
00383 }
00384
00385 kDebug( 14010 ) <<
00386 "Creating account for '" << accountId << "'" << endl;
00387
00388 Account *account = 0L;
00389 account = registerAccount( protocol->createNewAccount( accountId ) );
00390 if ( !account )
00391 {
00392 kWarning( 14010 ) <<
00393 "Failed to create account for '" << accountId << "'" << endl;
00394 continue;
00395 }
00396
00397
00398 Identity *identity = Kopete::IdentityManager::self()->findIdentity( account->configGroup()->readEntry("Identity", QString()) );
00399
00400
00401 if (!identity)
00402 identity = Kopete::IdentityManager::self()->defaultIdentity();
00403 account->setIdentity( identity );
00404 }
00405 }
00406
00407 void AccountManager::slotAccountOnlineStatusChanged(Contact *c,
00408 const OnlineStatus &oldStatus, const OnlineStatus &newStatus)
00409 {
00410 Account *account = c->account();
00411 if (!account)
00412 return;
00413
00414
00415 emit accountOnlineStatusChanged(account, oldStatus, newStatus);
00416 }
00417
00418 void AccountManager::networkConnected()
00419 {
00420 if ( Kopete::BehaviorSettings::self()->autoConnect() )
00421 setOnlineStatus( Kopete::OnlineStatusManager::Online, QString(), ConnectIfOffline );
00422 }
00423
00424 void AccountManager::networkDisconnected()
00425 {
00426 setOnlineStatus( Kopete::OnlineStatusManager::Offline );
00427 }
00428
00429 }
00430
00431 #include "kopeteaccountmanager.moc"
00432
00433