00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "agentbase.h"
00024 #include "agentbase_p.h"
00025
00026 #include "controladaptor.h"
00027 #include "statusadaptor.h"
00028 #include "monitor_p.h"
00029 #include "xdgbasedirs_p.h"
00030
00031 #include "session.h"
00032 #include "session_p.h"
00033 #include "changerecorder.h"
00034 #include "itemfetchjob.h"
00035
00036 #include <kaboutdata.h>
00037 #include <kcmdlineargs.h>
00038 #include <kdebug.h>
00039 #include <klocale.h>
00040 #include <kstandarddirs.h>
00041
00042 #include <QtCore/QDir>
00043 #include <QtCore/QSettings>
00044 #include <QtCore/QTimer>
00045 #include <QtGui/QApplication>
00046 #include <QtDBus/QtDBus>
00047
00048 #include <signal.h>
00049 #include <stdlib.h>
00050
00051 using namespace Akonadi;
00052
00053 static AgentBase *sAgentBase = 0;
00054
00055 AgentBase::Observer::Observer()
00056 {
00057 }
00058
00059 AgentBase::Observer::~Observer()
00060 {
00061 }
00062
00063 void AgentBase::Observer::itemAdded( const Item &item, const Collection &collection )
00064 {
00065 kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this;
00066 Q_UNUSED( item );
00067 Q_UNUSED( collection );
00068 if ( sAgentBase != 0 )
00069 sAgentBase->d_ptr->changeProcessed();
00070 }
00071
00072 void AgentBase::Observer::itemChanged( const Item &item, const QSet<QByteArray> &partIdentifiers )
00073 {
00074 kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this;
00075 Q_UNUSED( item );
00076 Q_UNUSED( partIdentifiers );
00077 if ( sAgentBase != 0 )
00078 sAgentBase->d_ptr->changeProcessed();
00079 }
00080
00081 void AgentBase::Observer::itemRemoved( const Item &item )
00082 {
00083 kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this;
00084 Q_UNUSED( item );
00085 if ( sAgentBase != 0 )
00086 sAgentBase->d_ptr->changeProcessed();
00087 }
00088
00089 void AgentBase::Observer::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
00090 {
00091 kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this;
00092 Q_UNUSED( collection );
00093 Q_UNUSED( parent );
00094 if ( sAgentBase != 0 )
00095 sAgentBase->d_ptr->changeProcessed();
00096 }
00097
00098 void AgentBase::Observer::collectionChanged( const Collection &collection )
00099 {
00100 kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this;
00101 Q_UNUSED( collection );
00102 if ( sAgentBase != 0 )
00103 sAgentBase->d_ptr->changeProcessed();
00104 }
00105
00106 void AgentBase::Observer::collectionRemoved( const Collection &collection )
00107 {
00108 kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this;
00109 Q_UNUSED( collection );
00110 if ( sAgentBase != 0 )
00111 sAgentBase->d_ptr->changeProcessed();
00112 }
00113
00114
00115
00116 AgentBasePrivate::AgentBasePrivate( AgentBase *parent )
00117 : q_ptr( parent ),
00118 mStatusCode( AgentBase::Idle ),
00119 mProgress( 0 ),
00120 mNeedsNetwork( false ),
00121 mOnline( false ),
00122 mSettings( 0 ),
00123 mObserver( 0 )
00124 {
00125 }
00126
00127 AgentBasePrivate::~AgentBasePrivate()
00128 {
00129 mMonitor->setConfig( 0 );
00130 delete mSettings;
00131 }
00132
00133 void AgentBasePrivate::init()
00134 {
00135 Q_Q( AgentBase );
00136
00140 SessionPrivate::createDefaultSession( mId.toLatin1() );
00141
00142 mTracer = new org::freedesktop::Akonadi::Tracer( QLatin1String( "org.freedesktop.Akonadi" ), QLatin1String( "/tracing" ),
00143 QDBusConnection::sessionBus(), q );
00144
00145 new ControlAdaptor( q );
00146 new StatusAdaptor( q );
00147 if ( !QDBusConnection::sessionBus().registerObject( QLatin1String( "/" ), q, QDBusConnection::ExportAdaptors ) )
00148 q->error( QString::fromLatin1( "Unable to register object at dbus: %1" ).arg( QDBusConnection::sessionBus().lastError().message() ) );
00149
00150 mSettings = new QSettings( QString::fromLatin1( "%1/agent_config_%2" ).arg( XdgBaseDirs::saveDir( "config", QLatin1String( "akonadi" ) ), mId ), QSettings::IniFormat );
00151
00152 mMonitor = new ChangeRecorder( q );
00153 mMonitor->ignoreSession( Session::defaultSession() );
00154 mMonitor->itemFetchScope().setCacheOnly( true );
00155 mMonitor->setConfig( mSettings );
00156
00157 mOnline = mSettings->value( QLatin1String( "Agent/Online" ), true ).toBool();
00158
00159 connect( mMonitor, SIGNAL( itemAdded( const Akonadi::Item&, const Akonadi::Collection& ) ),
00160 SLOT( itemAdded( const Akonadi::Item&, const Akonadi::Collection& ) ) );
00161 connect( mMonitor, SIGNAL( itemChanged( const Akonadi::Item&, const QSet<QByteArray>& ) ),
00162 SLOT( itemChanged( const Akonadi::Item&, const QSet<QByteArray>& ) ) );
00163 connect( mMonitor, SIGNAL( itemRemoved( const Akonadi::Item& ) ),
00164 SLOT( itemRemoved( const Akonadi::Item& ) ) );
00165 connect( mMonitor, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)),
00166 SLOT(collectionAdded(Akonadi::Collection,Akonadi::Collection)) );
00167 connect( mMonitor, SIGNAL( collectionChanged( const Akonadi::Collection& ) ),
00168 SLOT( collectionChanged( const Akonadi::Collection& ) ) );
00169 connect( mMonitor, SIGNAL( collectionRemoved( const Akonadi::Collection& ) ),
00170 SLOT( collectionRemoved( const Akonadi::Collection& ) ) );
00171
00172 connect( q, SIGNAL( status( int, QString ) ), q, SLOT( slotStatus( int, QString ) ) );
00173 connect( q, SIGNAL( percent( int ) ), q, SLOT( slotPercent( int ) ) );
00174 connect( q, SIGNAL( warning( QString ) ), q, SLOT( slotWarning( QString ) ) );
00175 connect( q, SIGNAL( error( QString ) ), q, SLOT( slotError( QString ) ) );
00176
00177
00178
00179 KGlobal::ref();
00180 KGlobal::setAllowQuit(true);
00181
00182 QTimer::singleShot( 0, q, SLOT( delayedInit() ) );
00183 }
00184
00185 void AgentBasePrivate::delayedInit()
00186 {
00187 Q_Q( AgentBase );
00188 if ( !QDBusConnection::sessionBus().registerService( QLatin1String( "org.freedesktop.Akonadi.Agent." ) + mId ) )
00189 kFatal() << "Unable to register service at dbus:" << QDBusConnection::sessionBus().lastError().message();
00190 q->setOnline( mOnline );
00191 }
00192
00193 void AgentBasePrivate::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
00194 {
00195 kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this;
00196 if ( mObserver != 0 )
00197 mObserver->itemAdded( item, collection );
00198 }
00199
00200 void AgentBasePrivate::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers )
00201 {
00202 kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this;
00203 if ( mObserver != 0 )
00204 mObserver->itemChanged( item, partIdentifiers );
00205 }
00206
00207 void AgentBasePrivate::itemRemoved( const Akonadi::Item &item )
00208 {
00209 kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this;
00210 if ( mObserver != 0 )
00211 mObserver->itemRemoved( item );
00212 }
00213
00214 void AgentBasePrivate::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
00215 {
00216 kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this;
00217 if ( mObserver != 0 )
00218 mObserver->collectionAdded( collection, parent );
00219 }
00220
00221 void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection )
00222 {
00223 kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this;
00224 if ( mObserver != 0 )
00225 mObserver->collectionChanged( collection );
00226 }
00227
00228 void AgentBasePrivate::collectionRemoved( const Akonadi::Collection &collection )
00229 {
00230 kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this;
00231 if ( mObserver != 0 )
00232 mObserver->collectionRemoved( collection );
00233 }
00234
00235 void AgentBasePrivate::changeProcessed()
00236 {
00237 mMonitor->changeProcessed();
00238 QTimer::singleShot( 0, mMonitor, SLOT( replayNext() ) );
00239 }
00240
00241 void AgentBasePrivate::slotStatus( int status, const QString &message )
00242 {
00243 mStatusMessage = message;
00244 mStatusCode = 0;
00245
00246 switch ( status ) {
00247 case AgentBase::Idle:
00248 if ( mStatusMessage.isEmpty() )
00249 mStatusMessage = defaultReadyMessage();
00250
00251 mStatusCode = 0;
00252 break;
00253 case AgentBase::Running:
00254 if ( mStatusMessage.isEmpty() )
00255 mStatusMessage = defaultSyncingMessage();
00256
00257 mStatusCode = 1;
00258 break;
00259 case AgentBase::Broken:
00260 if ( mStatusMessage.isEmpty() )
00261 mStatusMessage = defaultErrorMessage();
00262
00263 mStatusCode = 2;
00264 break;
00265 default:
00266 Q_ASSERT( !"Unknown status passed" );
00267 break;
00268 }
00269 }
00270
00271 void AgentBasePrivate::slotPercent( int progress )
00272 {
00273 mProgress = progress;
00274 }
00275
00276 void AgentBasePrivate::slotWarning( const QString& message )
00277 {
00278 mTracer->warning( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message );
00279 }
00280
00281 void AgentBasePrivate::slotError( const QString& message )
00282 {
00283 mTracer->error( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message );
00284 }
00285
00286 void AgentBasePrivate::slotNetworkStatusChange( Solid::Networking::Status stat )
00287 {
00288 Q_Q( AgentBase );
00289 q->setOnline( stat == Solid::Networking::Connected );
00290 }
00291
00292
00293 AgentBase::AgentBase( const QString & id )
00294 : d_ptr( new AgentBasePrivate( this ) )
00295 {
00296 sAgentBase = this;
00297 d_ptr->mId = id;
00298 d_ptr->init();
00299 if ( KApplication::kApplication() )
00300 KApplication::kApplication()->disableSessionManagement();
00301 }
00302
00303 AgentBase::AgentBase( AgentBasePrivate* d, const QString &id ) :
00304 d_ptr( d )
00305 {
00306 sAgentBase = this;
00307 d_ptr->mId = id;
00308 d_ptr->init();
00309 }
00310
00311 AgentBase::~AgentBase()
00312 {
00313 delete d_ptr;
00314 }
00315
00316 static char* sAgentAppName = 0;
00317
00318 QString AgentBase::parseArguments( int argc, char **argv )
00319 {
00320 QString identifier;
00321 if ( argc < 3 ) {
00322 kDebug( 5250 ) << "Not enough arguments passed...";
00323 exit( 1 );
00324 }
00325
00326 for ( int i = 1; i < argc - 1; ++i ) {
00327 if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) )
00328 identifier = QLatin1String( argv[ i + 1 ] );
00329 }
00330
00331 if ( identifier.isEmpty() ) {
00332 kDebug( 5250 ) << "Identifier argument missing";
00333 exit( 1 );
00334 }
00335
00336 sAgentAppName = qstrdup( identifier.toLatin1().constData() );
00337 KCmdLineArgs::init( argc, argv, sAgentAppName, 0, ki18n("Akonadi Agent"),"0.1" ,
00338 ki18n("Akonadi Agent") );
00339
00340 KCmdLineOptions options;
00341 options.add("identifier <argument>", ki18n("Agent identifier"));
00342 KCmdLineArgs::addCmdLineOptions( options );
00343
00344 return identifier;
00345 }
00346
00347
00348
00349 int AgentBase::init( AgentBase *r )
00350 {
00351 QApplication::setQuitOnLastWindowClosed( false );
00352 KGlobal::locale()->insertCatalog( "libakonadi" );
00353 int rv = kapp->exec();
00354 delete r;
00355 delete[] sAgentAppName;
00356 return rv;
00357 }
00358
00359 int AgentBase::status() const
00360 {
00361 Q_D( const AgentBase );
00362
00363 return d->mStatusCode;
00364 }
00365
00366 QString AgentBase::statusMessage() const
00367 {
00368 Q_D( const AgentBase );
00369
00370 return d->mStatusMessage;
00371 }
00372
00373 int AgentBase::progress() const
00374 {
00375 Q_D( const AgentBase );
00376
00377 return d->mProgress;
00378 }
00379
00380 QString AgentBase::progressMessage() const
00381 {
00382 Q_D( const AgentBase );
00383
00384 return d->mProgressMessage;
00385 }
00386
00387 bool AgentBase::isOnline() const
00388 {
00389 Q_D( const AgentBase );
00390
00391 return d->mOnline;
00392 }
00393
00394 void AgentBase::setNeedsNetwork( bool needsNetwork )
00395 {
00396 Q_D( AgentBase );
00397 d->mNeedsNetwork = needsNetwork;
00398
00399 if ( d->mNeedsNetwork ) {
00400 connect( Solid::Networking::notifier()
00401 , SIGNAL( statusChanged( Solid::Networking::Status ) )
00402 , d, SLOT( slotNetworkStatusChange( Solid::Networking::Status ) ) );
00403 } else {
00404 disconnect( Solid::Networking::notifier(), 0, 0, 0 );
00405 setOnline( true );
00406 }
00407 }
00408
00409 void AgentBase::setOnline( bool state )
00410 {
00411 Q_D( AgentBase );
00412 d->mOnline = state;
00413 d->mSettings->setValue( QLatin1String( "Agent/Online" ), state );
00414 doSetOnline( state );
00415 emit onlineChanged( state );
00416 }
00417
00418 void AgentBase::doSetOnline( bool online )
00419 {
00420 Q_UNUSED( online );
00421 }
00422
00423 void AgentBase::configure( WId windowId )
00424 {
00425 Q_UNUSED( windowId );
00426 }
00427
00428 #ifdef Q_OS_WIN
00429 void AgentBase::configure( qlonglong windowId )
00430 {
00431 configure( reinterpret_cast<WId>( windowId ) );
00432 }
00433 #endif
00434
00435 WId AgentBase::winIdForDialogs() const
00436 {
00437 bool registered = QDBusConnection::sessionBus().interface()->isServiceRegistered( QLatin1String("org.freedesktop.akonaditray") );
00438 if ( !registered )
00439 return 0;
00440
00441 QDBusInterface dbus( QLatin1String("org.freedesktop.akonaditray"), QLatin1String("/Actions"),
00442 QLatin1String("org.freedesktop.Akonadi.Tray") );
00443 QDBusMessage reply = dbus.call( QLatin1String("getWinId") );
00444
00445 if ( reply.type() == QDBusMessage::ErrorMessage )
00446 return 0;
00447
00448 WId winid = (WId)reply.arguments().at( 0 ).toLongLong();
00449 return winid;
00450 }
00451
00452 void AgentBase::quit()
00453 {
00454 Q_D( AgentBase );
00455 aboutToQuit();
00456
00457 if ( d->mSettings ) {
00458 d->mMonitor->setConfig( 0 );
00459 d->mSettings->sync();
00460 }
00461
00462 KGlobal::deref();
00463 }
00464
00465 void AgentBase::aboutToQuit()
00466 {
00467 }
00468
00469 void AgentBase::cleanup()
00470 {
00471 Q_D( AgentBase );
00472 const QString fileName = d->mSettings->fileName();
00473
00474
00475
00476
00477 d->mMonitor->setConfig( 0 );
00478 delete d->mSettings;
00479 d->mSettings = 0;
00480
00481
00482
00483
00484 QFile::remove( fileName );
00485
00486
00487
00488
00489 QString configFile = KStandardDirs::locateLocal( "config", KGlobal::config()->name() );
00490 QFile::remove( configFile );
00491
00492 QCoreApplication::quit();
00493 }
00494
00495 void AgentBase::registerObserver( Observer *observer )
00496 {
00497 kDebug() << "observer=" << (void*) observer << "this=" << (void*) this;
00498 d_ptr->mObserver = observer;
00499 }
00500
00501 QString AgentBase::identifier() const
00502 {
00503 return d_ptr->mId;
00504 }
00505
00506 void AgentBase::changeProcessed()
00507 {
00508 Q_D( AgentBase );
00509 d->changeProcessed();
00510 }
00511
00512 ChangeRecorder * AgentBase::changeRecorder() const
00513 {
00514 return d_ptr->mMonitor;
00515 }
00516
00517 void AgentBase::reconfigure()
00518 {
00519 emit reloadConfiguration();
00520 }
00521
00522 #include "agentbase.moc"
00523 #include "agentbase_p.moc"