• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

akonadi

agentbase.cpp
00001 /*
00002     Copyright (c) 2006 Till Adam <adam@kde.org>
00003     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00004     Copyright (c) 2007 Bruno Virlet <bruno.virlet@gmail.com>
00005     Copyright (c) 2008 Kevin Krammer <kevin.krammer@gmx.at>
00006 
00007     This library is free software; you can redistribute it and/or modify it
00008     under the terms of the GNU Library General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or (at your
00010     option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful, but WITHOUT
00013     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00015     License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public License
00018     along with this library; see the file COPYING.LIB.  If not, write to the
00019     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00020     02110-1301, USA.
00021 */
00022 
00023 #include "agentbase.h"
00024 #include "agentbase_p.h"
00025 
00026 #include "agentmanager.h"
00027 #include "changerecorder.h"
00028 #include "controladaptor.h"
00029 #include "dbusconnectionpool.h"
00030 #include "itemfetchjob.h"
00031 #include "kdepimlibs-version.h"
00032 #include "monitor_p.h"
00033 #include "servermanager_p.h"
00034 #include "session.h"
00035 #include "session_p.h"
00036 #include "statusadaptor.h"
00037 #include "xdgbasedirs_p.h"
00038 
00039 #include <kaboutdata.h>
00040 #include <kcmdlineargs.h>
00041 #include <kdebug.h>
00042 #include <klocale.h>
00043 #include <kstandarddirs.h>
00044 
00045 #include <Solid/PowerManagement>
00046 
00047 #include <QtCore/QDir>
00048 #include <QtCore/QSettings>
00049 #include <QtCore/QTimer>
00050 #include <QtDBus/QtDBus>
00051 #include <QtGui/QApplication>
00052 
00053 #include <signal.h>
00054 #include <stdlib.h>
00055 
00056 
00057 //#define EXPERIMENTAL_INPROCESS_AGENTS 1
00058 
00059 using namespace Akonadi;
00060 
00061 static AgentBase *sAgentBase = 0;
00062 
00063 AgentBase::Observer::Observer()
00064 {
00065 }
00066 
00067 AgentBase::Observer::~Observer()
00068 {
00069 }
00070 
00071 void AgentBase::Observer::itemAdded( const Item &item, const Collection &collection )
00072 {
00073   Q_UNUSED( item );
00074   Q_UNUSED( collection );
00075   if ( sAgentBase != 0 )
00076     sAgentBase->d_ptr->changeProcessed();
00077 }
00078 
00079 void AgentBase::Observer::itemChanged( const Item &item, const QSet<QByteArray> &partIdentifiers )
00080 {
00081   Q_UNUSED( item );
00082   Q_UNUSED( partIdentifiers );
00083   if ( sAgentBase != 0 )
00084     sAgentBase->d_ptr->changeProcessed();
00085 }
00086 
00087 void AgentBase::Observer::itemRemoved( const Item &item )
00088 {
00089   Q_UNUSED( item );
00090   if ( sAgentBase != 0 )
00091     sAgentBase->d_ptr->changeProcessed();
00092 }
00093 
00094 void AgentBase::Observer::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
00095 {
00096   Q_UNUSED( collection );
00097   Q_UNUSED( parent );
00098   if ( sAgentBase != 0 )
00099     sAgentBase->d_ptr->changeProcessed();
00100 }
00101 
00102 void AgentBase::Observer::collectionChanged( const Collection &collection )
00103 {
00104   Q_UNUSED( collection );
00105   if ( sAgentBase != 0 )
00106     sAgentBase->d_ptr->changeProcessed();
00107 }
00108 
00109 void AgentBase::Observer::collectionRemoved( const Collection &collection )
00110 {
00111   Q_UNUSED( collection );
00112   if ( sAgentBase != 0 )
00113     sAgentBase->d_ptr->changeProcessed();
00114 }
00115 
00116 void AgentBase::ObserverV2::itemMoved( const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest )
00117 {
00118   Q_UNUSED( item );
00119   Q_UNUSED( source );
00120   Q_UNUSED( dest );
00121   if ( sAgentBase != 0 )
00122     sAgentBase->d_ptr->changeProcessed();
00123 }
00124 
00125 void AgentBase::ObserverV2::itemLinked( const Akonadi::Item& item, const Akonadi::Collection& collection )
00126 {
00127   Q_UNUSED( item );
00128   Q_UNUSED( collection );
00129   if ( sAgentBase != 0 ) {
00130     // not implementation, let's disconnect the signal to enable optimizations in Monitor
00131     QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
00132                          sAgentBase->d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
00133     sAgentBase->d_ptr->changeProcessed();
00134   }
00135 }
00136 
00137 void AgentBase::ObserverV2::itemUnlinked( const Akonadi::Item& item, const Akonadi::Collection& collection )
00138 {
00139   Q_UNUSED( item );
00140   Q_UNUSED( collection );
00141   if ( sAgentBase != 0 ) {
00142     // not implementation, let's disconnect the signal to enable optimizations in Monitor
00143     QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
00144                          sAgentBase->d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
00145     sAgentBase->d_ptr->changeProcessed();
00146   }
00147 }
00148 
00149 void AgentBase::ObserverV2::collectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &dest )
00150 {
00151   Q_UNUSED( collection );
00152   Q_UNUSED( source );
00153   Q_UNUSED( dest );
00154   if ( sAgentBase != 0 )
00155     sAgentBase->d_ptr->changeProcessed();
00156 }
00157 
00158 void AgentBase::ObserverV2::collectionChanged( const Akonadi::Collection &collection, const QSet<QByteArray> &partIdentifiers )
00159 {
00160   Q_UNUSED( partIdentifiers );
00161   collectionChanged( collection );
00162 }
00163 
00164 //@cond PRIVATE
00165 
00166 AgentBasePrivate::AgentBasePrivate( AgentBase *parent )
00167   : q_ptr( parent ),
00168     mDBusConnection( QString() ),
00169     mStatusCode( AgentBase::Idle ),
00170     mProgress( 0 ),
00171     mNeedsNetwork( false ),
00172     mOnline( false ),
00173     mSettings( 0 ),
00174     mObserver( 0 )
00175 {
00176 #ifdef Q_OS_WINCE
00177   QThread::currentThread()->setPriority(QThread::LowPriority);
00178 #endif
00179   Internal::setClientType( Internal::Agent );
00180 }
00181 
00182 AgentBasePrivate::~AgentBasePrivate()
00183 {
00184   mChangeRecorder->setConfig( 0 );
00185   delete mSettings;
00186 }
00187 
00188 void AgentBasePrivate::init()
00189 {
00190   Q_Q( AgentBase );
00191 
00195   SessionPrivate::createDefaultSession( mId.toLatin1() );
00196 
00197   if ( QThread::currentThread() != QCoreApplication::instance()->thread() ) {
00198     mDBusConnection = QDBusConnection::connectToBus( QDBusConnection::SessionBus, q->identifier() );
00199     Q_ASSERT( mDBusConnection.isConnected() );
00200   }
00201 
00202   mTracer = new org::freedesktop::Akonadi::Tracer( QLatin1String( "org.freedesktop.Akonadi" ),
00203                                                    QLatin1String( "/tracing" ),
00204                                                    DBusConnectionPool::threadConnection(), q );
00205 
00206   new Akonadi__ControlAdaptor( q );
00207   new Akonadi__StatusAdaptor( q );
00208   if ( !DBusConnectionPool::threadConnection().registerObject( QLatin1String( "/" ), q, QDBusConnection::ExportAdaptors ) )
00209     q->error( QString::fromLatin1( "Unable to register object at dbus: %1" ).arg( DBusConnectionPool::threadConnection().lastError().message() ) );
00210 
00211   mSettings = new QSettings( QString::fromLatin1( "%1/agent_config_%2" ).arg( XdgBaseDirs::saveDir( "config", QLatin1String( "akonadi" ) ), mId ), QSettings::IniFormat );
00212 
00213   mChangeRecorder = new ChangeRecorder( q );
00214   mChangeRecorder->ignoreSession( Session::defaultSession() );
00215   mChangeRecorder->itemFetchScope().setCacheOnly( true );
00216   mChangeRecorder->setConfig( mSettings );
00217 
00218   mOnline = mSettings->value( QLatin1String( "Agent/Online" ), true ).toBool();
00219 
00220   // reinitialize the status message now that online state is available
00221   mStatusMessage = defaultReadyMessage();
00222 
00223   mName = mSettings->value( QLatin1String( "Agent/Name" ) ).toString();
00224   if ( mName.isEmpty() ) {
00225     mName = mSettings->value( QLatin1String( "Resource/Name" ) ).toString();
00226     if ( !mName.isEmpty() ) {
00227       mSettings->remove( QLatin1String( "Resource/Name" ) );
00228       mSettings->setValue( QLatin1String( "Agent/Name" ), mName );
00229     }
00230   }
00231 
00232   connect( mChangeRecorder, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)),
00233            SLOT(itemAdded(Akonadi::Item,Akonadi::Collection)) );
00234   connect( mChangeRecorder, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)),
00235            SLOT(itemChanged(Akonadi::Item,QSet<QByteArray>)) );
00236   connect( mChangeRecorder, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
00237            SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)) );
00238   connect( mChangeRecorder, SIGNAL(itemRemoved(Akonadi::Item)),
00239            SLOT(itemRemoved(Akonadi::Item)) );
00240   connect( mChangeRecorder, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)),
00241            SLOT(collectionAdded(Akonadi::Collection,Akonadi::Collection)) );
00242   connect( mChangeRecorder, SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
00243            SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
00244   connect( mChangeRecorder, SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
00245            SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
00246   connect( mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection)),
00247            SLOT(collectionChanged(Akonadi::Collection)) );
00248   connect( mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>)),
00249            SLOT(collectionChanged(Akonadi::Collection,QSet<QByteArray>)) );
00250   connect( mChangeRecorder, SIGNAL(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)),
00251            SLOT(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)) );
00252   connect( mChangeRecorder, SIGNAL(collectionRemoved(Akonadi::Collection)),
00253            SLOT(collectionRemoved(Akonadi::Collection)) );
00254   connect( mChangeRecorder, SIGNAL(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)),
00255            SLOT(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)) );
00256   connect( mChangeRecorder, SIGNAL(collectionUnsubscribed(Akonadi::Collection)),
00257            SLOT(collectionUnsubscribed(Akonadi::Collection)) );
00258 
00259   connect( q, SIGNAL(status(int,QString)), q, SLOT(slotStatus(int,QString)) );
00260   connect( q, SIGNAL(percent(int)), q, SLOT(slotPercent(int)) );
00261   connect( q, SIGNAL(warning(QString)), q, SLOT(slotWarning(QString)) );
00262   connect( q, SIGNAL(error(QString)), q, SLOT(slotError(QString)) );
00263 
00264   connect( Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), q, SLOT(slotResumedFromSuspend()) );
00265 
00266   // Use reference counting to allow agents to finish internal jobs when the
00267   // agent is stopped.
00268   KGlobal::ref();
00269   if ( QThread::currentThread() == QCoreApplication::instance()->thread() )
00270     KGlobal::setAllowQuit( true );
00271 
00272 #ifndef Q_OS_WINCE
00273   // disable session management
00274   if ( KApplication::kApplication() )
00275     KApplication::kApplication()->disableSessionManagement();
00276 #endif
00277 
00278   mResourceTypeName = AgentManager::self()->instance(mId).type().name();
00279   setProgramName();
00280 
00281   QTimer::singleShot( 0, q, SLOT(delayedInit()) );
00282 }
00283 
00284 void AgentBasePrivate::delayedInit()
00285 {
00286   Q_Q( AgentBase );
00287   if ( !DBusConnectionPool::threadConnection().registerService( QLatin1String( "org.freedesktop.Akonadi.Agent." ) + mId ) )
00288     kFatal() << "Unable to register service at dbus:" << DBusConnectionPool::threadConnection().lastError().message();
00289   q->setOnline( mOnline );
00290 }
00291 
00292 void AgentBasePrivate::setProgramName()
00293 {
00294   // ugly, really ugly, if you find another solution, change it and blame me for this code (Andras)
00295   QString programName = mResourceTypeName;
00296   if ( !mName.isEmpty() ) {
00297     programName = i18nc( "Name and type of Akonadi resource", "%1 of type %2", mName, mResourceTypeName ) ;
00298   }
00299   const_cast<KAboutData*>( KGlobal::mainComponent().aboutData() )->setProgramName( ki18n( programName.toUtf8() ) );
00300 }
00301 
00302 void AgentBasePrivate::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
00303 {
00304   if ( mObserver != 0 )
00305     mObserver->itemAdded( item, collection );
00306 }
00307 
00308 void AgentBasePrivate::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers )
00309 {
00310   if ( mObserver != 0 )
00311     mObserver->itemChanged( item, partIdentifiers );
00312 }
00313 
00314 void AgentBasePrivate::itemMoved( const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest )
00315 {
00316   AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
00317   if ( mObserver ) {
00318     // inter-resource moves, requires we know which resources the source and destination are in though
00319     if ( !source.resource().isEmpty() && !dest.resource().isEmpty() ) {
00320       if ( source.resource() != dest.resource() ) {
00321         if ( source.resource() == q_ptr->identifier() ) { // moved away from us
00322           Akonadi::Item i( item );
00323           i.setParentCollection( source );
00324           mObserver->itemRemoved( i );
00325         }
00326         else if ( dest.resource() == q_ptr->identifier() ) // moved to us
00327           mObserver->itemAdded( item, dest );
00328         else if ( observer2 )
00329           observer2->itemMoved( item, source, dest );
00330         else
00331           // not for us, not sure if we should get here at all
00332           changeProcessed();
00333         return;
00334       }
00335     }
00336     // intra-resource move
00337     if ( observer2 ) {
00338       observer2->itemMoved( item, source, dest );
00339     } else {
00340       // ### we cannot just call itemRemoved here as this will already trigger changeProcessed()
00341       // so, just itemAdded() is good enough as no resource can have implemented intra-resource moves anyway
00342       // without using ObserverV2
00343       mObserver->itemAdded( item, dest );
00344       // mObserver->itemRemoved( item );
00345     }
00346   }
00347 }
00348 
00349 void AgentBasePrivate::itemRemoved( const Akonadi::Item &item )
00350 {
00351   if ( mObserver != 0 )
00352     mObserver->itemRemoved( item );
00353 }
00354 
00355 void AgentBasePrivate::itemLinked( const Akonadi::Item &item, const Akonadi::Collection &collection )
00356 {
00357   AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
00358   if ( observer2 )
00359     observer2->itemLinked( item, collection );
00360   else
00361     changeProcessed();
00362 }
00363 
00364 void AgentBasePrivate::itemUnlinked( const Akonadi::Item &item, const Akonadi::Collection &collection )
00365 {
00366   AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
00367   if ( observer2 )
00368     observer2->itemUnlinked( item, collection );
00369   else
00370     changeProcessed();
00371 }
00372 
00373 void AgentBasePrivate::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
00374 {
00375   if ( mObserver != 0 )
00376     mObserver->collectionAdded( collection, parent );
00377 }
00378 
00379 void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection )
00380 {
00381   AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
00382   if ( mObserver != 0 && observer2 == 0 ) // For ObserverV2 we use the variant with the part identifiers
00383     mObserver->collectionChanged( collection );
00384 }
00385 
00386 void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection, const QSet<QByteArray> &partIdentifiers )
00387 {
00388   AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
00389   if ( observer2 != 0 )
00390     observer2->collectionChanged( collection, partIdentifiers );
00391 }
00392 
00393 void AgentBasePrivate::collectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &dest )
00394 {
00395   AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
00396   if ( mObserver ) {
00397     // inter-resource moves, requires we know which resources the source and destination are in though
00398     if ( !source.resource().isEmpty() && !dest.resource().isEmpty() ) {
00399       if ( source.resource() != dest.resource() ) {
00400         if ( source.resource() == q_ptr->identifier() ) // moved away from us
00401           mObserver->collectionRemoved( collection );
00402         else if ( dest.resource() == q_ptr->identifier() ) // moved to us
00403           mObserver->collectionAdded( collection, dest );
00404         else if ( observer2 )
00405           observer2->collectionMoved( collection, source, dest );
00406         else // not for us, not sure if we should get here at all
00407           changeProcessed();
00408         return;
00409       }
00410     }
00411     // intra-resource move
00412     if ( observer2 ) {
00413       observer2->collectionMoved( collection, source, dest );
00414     } else {
00415       // ### we cannot just call collectionRemoved here as this will already trigger changeProcessed()
00416       // so, just collectionAdded() is good enough as no resource can have implemented intra-resource moves anyway
00417       // without using ObserverV2
00418       mObserver->collectionAdded( collection, dest );
00419     }
00420   }
00421 }
00422 
00423 void AgentBasePrivate::collectionRemoved( const Akonadi::Collection &collection )
00424 {
00425   if ( mObserver != 0 )
00426     mObserver->collectionRemoved( collection );
00427 }
00428 
00429 void AgentBasePrivate::collectionSubscribed( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
00430 {
00431   Q_UNUSED( collection );
00432   Q_UNUSED( parent );
00433   changeProcessed();
00434 }
00435 
00436 void AgentBasePrivate::collectionUnsubscribed( const Akonadi::Collection &collection )
00437 {
00438   Q_UNUSED( collection );
00439   changeProcessed();
00440 }
00441 
00442 void AgentBasePrivate::changeProcessed()
00443 {
00444   mChangeRecorder->changeProcessed();
00445   QTimer::singleShot( 0, mChangeRecorder, SLOT(replayNext()) );
00446 }
00447 
00448 void AgentBasePrivate::slotStatus( int status, const QString &message )
00449 {
00450   mStatusMessage = message;
00451   mStatusCode = 0;
00452 
00453   switch ( status ) {
00454     case AgentBase::Idle:
00455       if ( mStatusMessage.isEmpty() )
00456         mStatusMessage = defaultReadyMessage();
00457 
00458       mStatusCode = 0;
00459       break;
00460     case AgentBase::Running:
00461       if ( mStatusMessage.isEmpty() )
00462         mStatusMessage = defaultSyncingMessage();
00463 
00464       mStatusCode = 1;
00465       break;
00466     case AgentBase::Broken:
00467       if ( mStatusMessage.isEmpty() )
00468         mStatusMessage = defaultErrorMessage();
00469 
00470       mStatusCode = 2;
00471       break;
00472     default:
00473       Q_ASSERT( !"Unknown status passed" );
00474       break;
00475   }
00476 }
00477 
00478 void AgentBasePrivate::slotPercent( int progress )
00479 {
00480   mProgress = progress;
00481 }
00482 
00483 void AgentBasePrivate::slotWarning( const QString& message )
00484 {
00485   mTracer->warning( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message );
00486 }
00487 
00488 void AgentBasePrivate::slotError( const QString& message )
00489 {
00490   mTracer->error( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message );
00491 }
00492 
00493 void AgentBasePrivate::slotNetworkStatusChange( Solid::Networking::Status stat )
00494 {
00495   Q_Q( AgentBase );
00496   q->setOnline( stat == Solid::Networking::Unknown || stat == Solid::Networking::Connected );
00497 }
00498 
00499 void AgentBasePrivate::slotResumedFromSuspend()
00500 {
00501   if ( mNeedsNetwork )
00502     slotNetworkStatusChange( Solid::Networking::status() );
00503 }
00504 
00505 AgentBase::AgentBase( const QString & id )
00506   : d_ptr( new AgentBasePrivate( this ) )
00507 {
00508   sAgentBase = this;
00509   d_ptr->mId = id;
00510   d_ptr->init();
00511 }
00512 
00513 AgentBase::AgentBase( AgentBasePrivate* d, const QString &id ) :
00514     d_ptr( d )
00515 {
00516   sAgentBase = this;
00517   d_ptr->mId = id;
00518   d_ptr->init();
00519 }
00520 
00521 AgentBase::~AgentBase()
00522 {
00523   delete d_ptr;
00524 }
00525 
00526 QString AgentBase::parseArguments( int argc, char **argv )
00527 {
00528   QString identifier;
00529   if ( argc < 3 ) {
00530     kDebug() << "Not enough arguments passed...";
00531     exit( 1 );
00532   }
00533 
00534   for ( int i = 1; i < argc - 1; ++i ) {
00535     if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) )
00536       identifier = QLatin1String( argv[ i + 1 ] );
00537   }
00538 
00539   if ( identifier.isEmpty() ) {
00540     kDebug() << "Identifier argument missing";
00541     exit( 1 );
00542   }
00543 
00544   const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
00545   // strip off full path and possible .exe suffix
00546   const QByteArray catalog = fi.baseName().toLatin1();
00547 
00548   KCmdLineArgs::init( argc, argv, identifier.toLatin1(), catalog, ki18n( "Akonadi Agent" ), KDEPIMLIBS_VERSION,
00549                       ki18n( "Akonadi Agent" ) );
00550 
00551   KCmdLineOptions options;
00552   options.add( "identifier <argument>", ki18n( "Agent identifier" ) );
00553   KCmdLineArgs::addCmdLineOptions( options );
00554 
00555   return identifier;
00556 }
00557 
00558 // @endcond
00559 
00560 int AgentBase::init( AgentBase *r )
00561 {
00562   QApplication::setQuitOnLastWindowClosed( false );
00563   KGlobal::locale()->insertCatalog( QLatin1String( "libakonadi" ) );
00564   int rv = kapp->exec();
00565   delete r;
00566   return rv;
00567 }
00568 
00569 int AgentBase::status() const
00570 {
00571   Q_D( const AgentBase );
00572 
00573   return d->mStatusCode;
00574 }
00575 
00576 QString AgentBase::statusMessage() const
00577 {
00578   Q_D( const AgentBase );
00579 
00580   return d->mStatusMessage;
00581 }
00582 
00583 int AgentBase::progress() const
00584 {
00585   Q_D( const AgentBase );
00586 
00587   return d->mProgress;
00588 }
00589 
00590 QString AgentBase::progressMessage() const
00591 {
00592   Q_D( const AgentBase );
00593 
00594   return d->mProgressMessage;
00595 }
00596 
00597 bool AgentBase::isOnline() const
00598 {
00599   Q_D( const AgentBase );
00600 
00601   return d->mOnline;
00602 }
00603 
00604 void AgentBase::setNeedsNetwork( bool needsNetwork )
00605 {
00606   Q_D( AgentBase );
00607   d->mNeedsNetwork = needsNetwork;
00608 
00609   if ( d->mNeedsNetwork ) {
00610     connect( Solid::Networking::notifier()
00611            , SIGNAL(statusChanged(Solid::Networking::Status))
00612            , this, SLOT(slotNetworkStatusChange(Solid::Networking::Status))
00613            , Qt::UniqueConnection );
00614 
00615   } else {
00616     disconnect( Solid::Networking::notifier(), 0, 0, 0 );
00617     setOnline( true );
00618   }
00619 }
00620 
00621 void AgentBase::setOnline( bool state )
00622 {
00623   Q_D( AgentBase );
00624   d->mOnline = state;
00625 
00626   const QString newMessage = d->defaultReadyMessage();
00627   if ( d->mStatusMessage != newMessage && d->mStatusCode != AgentBase::Broken )
00628     emit status( d->mStatusCode, newMessage );
00629 
00630   d->mSettings->setValue( QLatin1String( "Agent/Online" ), state );
00631   doSetOnline( state );
00632   emit onlineChanged( state );
00633 }
00634 
00635 void AgentBase::doSetOnline( bool online )
00636 {
00637   Q_UNUSED( online );
00638 }
00639 
00640 void AgentBase::configure( WId windowId )
00641 {
00642   Q_UNUSED( windowId );
00643   emit configurationDialogAccepted();
00644 }
00645 
00646 #ifdef Q_OS_WIN //krazy:exclude=cpp
00647 void AgentBase::configure( qlonglong windowId )
00648 {
00649   configure( reinterpret_cast<WId>( windowId ) );
00650 }
00651 #endif
00652 
00653 WId AgentBase::winIdForDialogs() const
00654 {
00655   const bool registered = DBusConnectionPool::threadConnection().interface()->isServiceRegistered( QLatin1String( "org.freedesktop.akonaditray" ) );
00656   if ( !registered )
00657     return 0;
00658 
00659   QDBusInterface dbus( QLatin1String( "org.freedesktop.akonaditray" ), QLatin1String( "/Actions" ),
00660                        QLatin1String( "org.freedesktop.Akonadi.Tray" ) );
00661   const QDBusMessage reply = dbus.call( QLatin1String( "getWinId" ) );
00662 
00663   if ( reply.type() == QDBusMessage::ErrorMessage )
00664     return 0;
00665 
00666   const WId winid = (WId)reply.arguments().at( 0 ).toLongLong();
00667 
00668   return winid;
00669 }
00670 
00671 void AgentBase::quit()
00672 {
00673   Q_D( AgentBase );
00674   aboutToQuit();
00675 
00676   if ( d->mSettings ) {
00677     d->mChangeRecorder->setConfig( 0 );
00678     d->mSettings->sync();
00679   }
00680 
00681   KGlobal::deref();
00682 }
00683 
00684 void AgentBase::aboutToQuit()
00685 {
00686 }
00687 
00688 void AgentBase::cleanup()
00689 {
00690   Q_D( AgentBase );
00691   // prevent the monitor from picking up deletion signals for our own data if we are a resource
00692   // and thus avoid that we kill our own data as last act before our own death
00693   d->mChangeRecorder->blockSignals( true );
00694 
00695   aboutToQuit();
00696 
00697   const QString fileName = d->mSettings->fileName();
00698 
00699   /*
00700    * First destroy the settings object...
00701    */
00702   d->mChangeRecorder->setConfig( 0 );
00703   delete d->mSettings;
00704   d->mSettings = 0;
00705 
00706   /*
00707    * ... then remove the file from hd.
00708    */
00709   QFile::remove( fileName );
00710 
00711   /*
00712    * ... and remove the changes file from hd.
00713    */
00714   QFile::remove( fileName + QLatin1String( "_changes.dat" ) );
00715 
00716   /*
00717    * ... and also remove the agent configuration file if there is one.
00718    */
00719   QString configFile = KStandardDirs::locateLocal( "config", config()->name() );
00720   QFile::remove( configFile );
00721 
00722   KGlobal::deref();
00723 }
00724 
00725 void AgentBase::registerObserver( Observer *observer )
00726 {
00727   // TODO in theory we should re-connect change recorder signals here that we disconnected previously
00728   d_ptr->mObserver = observer;
00729 }
00730 
00731 QString AgentBase::identifier() const
00732 {
00733   return d_ptr->mId;
00734 }
00735 
00736 void AgentBase::setAgentName( const QString &name )
00737 {
00738   Q_D( AgentBase );
00739   if ( name == d->mName )
00740     return;
00741 
00742   // TODO: rename collection
00743   d->mName = name;
00744 
00745   if ( d->mName.isEmpty() || d->mName == d->mId ) {
00746     d->mSettings->remove( QLatin1String( "Resource/Name" ) );
00747     d->mSettings->remove( QLatin1String( "Agent/Name" ) );
00748   } else
00749     d->mSettings->setValue( QLatin1String( "Agent/Name" ), d->mName );
00750 
00751   d->mSettings->sync();
00752 
00753   d->setProgramName();
00754 
00755   emit agentNameChanged( d->mName );
00756 }
00757 
00758 QString AgentBase::agentName() const
00759 {
00760   Q_D( const AgentBase );
00761   if ( d->mName.isEmpty() )
00762     return d->mId;
00763   else
00764     return d->mName;
00765 }
00766 
00767 void AgentBase::changeProcessed()
00768 {
00769   Q_D( AgentBase );
00770   d->changeProcessed();
00771 }
00772 
00773 ChangeRecorder * AgentBase::changeRecorder() const
00774 {
00775   return d_ptr->mChangeRecorder;
00776 }
00777 
00778 KSharedConfigPtr AgentBase::config()
00779 {
00780   if ( QCoreApplication::instance()->thread() == QThread::currentThread() )
00781     return KGlobal::config();
00782   else
00783     return componentData().config();
00784 }
00785 
00786 void AgentBase::abort()
00787 {
00788   emit abortRequested();
00789 }
00790 
00791 void AgentBase::reconfigure()
00792 {
00793   emit reloadConfiguration();
00794 }
00795 
00796 extern QThreadStorage<KComponentData*> s_agentComponentDatas;
00797 
00798 KComponentData AgentBase::componentData()
00799 {
00800   if ( QThread::currentThread() == QCoreApplication::instance()->thread() ) {
00801     if ( s_agentComponentDatas.hasLocalData() )
00802       return *(s_agentComponentDatas.localData());
00803     else
00804       return KGlobal::mainComponent();
00805   }
00806 
00807   Q_ASSERT( s_agentComponentDatas.hasLocalData() );
00808   return *(s_agentComponentDatas.localData());
00809 }
00810 
00811 #include "agentbase.moc"
00812 #include "agentbase_p.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:25:17 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs-4.8.5 API Reference

Skip menu "kdepimlibs-4.8.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal