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