• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdenetwork
  • Sitemap
  • Contact Us
 

kopete/libkopete

kopeteaccountmanager.cpp

Go to the documentation of this file.
00001 /*
00002     kopeteaccountmanager.cpp - Kopete Account Manager
00003 
00004     Copyright (c) 2002-2003 by Martijn Klingens      <klingens@kde.org>
00005     Copyright (c) 2003-2004 by Olivier Goffart       <ogoffart@kde.org>
00006 
00007     Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
00008 
00009     *************************************************************************
00010     *                                                                       *
00011     * This library is free software; you can redistribute it and/or         *
00012     * modify it under the terms of the GNU Lesser General Public            *
00013     * License as published by the Free Software Foundation; either          *
00014     * version 2 of the License, or (at your option) any later version.      *
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 ) //two account are equal only if they are equal :-)
00054         return 0;  // remember than an account can be only once on the list, but two account may have the same priority when loading
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         // Going offline is always respected
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     // mark ourselves as globally away if appropriate
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     // In a perfect wold, we should check if the color is actually not used by the account.
00146     // Anyway, this is not really required,  It would be a difficult job for about nothing more.
00147     //   -- Olivier
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     // let's figure a color
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     // If this account already exists, do nothing
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     // Connect to the account's status changed signal
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     // Clean up the contact list
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 ) //we can delete the metacontact
00281         {
00282             //get the first group and it's members
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     // Clean up the account list
00292     d->accounts.removeAll( account );
00293 
00294     // Clean up configuration
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     //there is nomore account from the protocol,  we can unload it
00306 
00307     // FIXME: pluginId() should return the internal name and not the class name, so
00308     //        we can get rid of this hack - Olivier/Martijn
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     //kDebug( 14010 ) ;
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     // Iterate over all groups that start with "Account_" as those are accounts
00338     // and load the required protocols if the account is enabled.
00339     // Don't try to optimize duplicate calls out, the plugin queue is smart enough
00340     // (and fast enough) to handle that without adding complexity here
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     // Iterate over all groups that start with "Account_" as those are accounts
00363     // and parse them if they are from this protocol
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         // There's no GUI for this, but developers may want to disable an account.
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         // the account's Identity must be set here instead of in the Kopete::Account ctor, because there the
00397         // identity cannot pick up any state set in the derived Account ctor
00398         Identity *identity = Kopete::IdentityManager::self()->findIdentity( account->configGroup()->readEntry("Identity", QString()) );
00399         // if the identity was not found, use the default one which will for sure exist
00400         // FIXME: get rid of this, the account's identity should always exist at this point
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     //kDebug(14010) ;
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 } //END namespace Kopete
00430 
00431 #include "kopeteaccountmanager.moc"
00432 // vim: set noet ts=4 sts=4 sw=4:
00433 // kate: tab-width 4; indent-mode csands;

kopete/libkopete

Skip menu "kopete/libkopete"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdenetwork

Skip menu "kdenetwork"
  • kget
  • kopete
  •   kopete
  •   libkopete
  •       libpapillon
  • krfb
Generated for kdenetwork by doxygen 1.5.4
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