• Skip to content
  • Skip to link menu
KDE 4.2 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 "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 ) //two account are equal only if they are equal :-)
00055         return 0;  // remember than an account can be only once on the list, but two account may have the same priority when loading
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         // Going offline is always respected
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     // mark ourselves as globally away if appropriate
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     // In a perfect wold, we should check if the color is actually not used by the account.
00147     // Anyway, this is not really required,  It would be a difficult job for about nothing more.
00148     //   -- Olivier
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     // let's figure a color
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     // If this account already exists, do nothing
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     // Connect to the account's status changed signal
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     // Clean up the contact list
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 ) //we can delete the metacontact
00282         {
00283             //get the first group and it's members
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     // Clean up the account list
00293     d->accounts.removeAll( account );
00294 
00295     // Clean up configuration
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     //there is nomore account from the protocol,  we can unload it
00307 
00308     // FIXME: pluginId() should return the internal name and not the class name, so
00309     //        we can get rid of this hack - Olivier/Martijn
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     //kDebug( 14010 ) ;
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     // Iterate over all groups that start with "Account_" as those are accounts
00339     // and load the required protocols if the account is enabled.
00340     // Don't try to optimize duplicate calls out, the plugin queue is smart enough
00341     // (and fast enough) to handle that without adding complexity here
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     // Iterate over all groups that start with "Account_" as those are accounts
00365     // and parse them if they are from this protocol
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         // There's no GUI for this, but developers may want to disable an account.
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         // the account's Identity must be set here instead of in the Kopete::Account ctor, because there the
00399         // identity cannot pick up any state set in the derived Account ctor
00400         Identity *identity = Kopete::IdentityManager::self()->findIdentity( account->configGroup()->readEntry("Identity", QString()) );
00401         // if the identity was not found, use the default one which will for sure exist
00402         // FIXME: get rid of this, the account's identity should always exist at this point
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     //kDebug(14010) ;
00420     emit accountOnlineStatusChanged(account, oldStatus, newStatus);
00421 }
00422 
00423 void AccountManager::networkConnected()
00424 {
00425     Kopete::OnlineStatusManager::Category initStatus = Kopete::OnlineStatusManager::self()->initialStatus();
00426     //we check for network availability here too
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 } //END namespace Kopete
00441 
00442 #include "kopeteaccountmanager.moc"
00443 // vim: set noet ts=4 sts=4 sw=4:
00444 // 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