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