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

akonadi

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • 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
Generated for KDE-PIM Libraries by doxygen 1.7.5
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