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

akonadi

  • akonadi
agentbase.cpp
1 /*
2  Copyright (c) 2006 Till Adam <adam@kde.org>
3  Copyright (c) 2007 Volker Krause <vkrause@kde.org>
4  Copyright (c) 2007 Bruno Virlet <bruno.virlet@gmail.com>
5  Copyright (c) 2008 Kevin Krammer <kevin.krammer@gmx.at>
6 
7  This library is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Library General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version.
11 
12  This library is distributed in the hope that it will be useful, but WITHOUT
13  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15  License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to the
19  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  02110-1301, USA.
21 */
22 
23 #include "agentbase.h"
24 #include "agentbase_p.h"
25 
26 #include "agentmanager.h"
27 #include "changerecorder.h"
28 #include "controladaptor.h"
29 #include "dbusconnectionpool.h"
30 #include "itemfetchjob.h"
31 #include "kdepimlibs-version.h"
32 #include "monitor_p.h"
33 #include "servermanager_p.h"
34 #include "session.h"
35 #include "session_p.h"
36 #include "statusadaptor.h"
37 
38 #include <kaboutdata.h>
39 #include <kcmdlineargs.h>
40 #include <kdebug.h>
41 #include <klocale.h>
42 #include <kstandarddirs.h>
43 
44 #include <Solid/PowerManagement>
45 
46 #include <QtCore/QDir>
47 #include <QtCore/QSettings>
48 #include <QtCore/QTimer>
49 #include <QtDBus/QtDBus>
50 #include <QApplication>
51 
52 #include <signal.h>
53 #include <stdlib.h>
54 
55 
56 //#define EXPERIMENTAL_INPROCESS_AGENTS 1
57 
58 using namespace Akonadi;
59 
60 static AgentBase *sAgentBase = 0;
61 
62 AgentBase::Observer::Observer()
63 {
64 }
65 
66 AgentBase::Observer::~Observer()
67 {
68 }
69 
70 void AgentBase::Observer::itemAdded( const Item &item, const Collection &collection )
71 {
72  Q_UNUSED( item );
73  Q_UNUSED( collection );
74  if ( sAgentBase != 0 ) {
75  sAgentBase->d_ptr->changeProcessed();
76  }
77 }
78 
79 void AgentBase::Observer::itemChanged( const Item &item, const QSet<QByteArray> &partIdentifiers )
80 {
81  Q_UNUSED( item );
82  Q_UNUSED( partIdentifiers );
83  if ( sAgentBase != 0 ) {
84  sAgentBase->d_ptr->changeProcessed();
85  }
86 }
87 
88 void AgentBase::Observer::itemRemoved( const Item &item )
89 {
90  Q_UNUSED( item );
91  if ( sAgentBase != 0 ) {
92  sAgentBase->d_ptr->changeProcessed();
93  }
94 }
95 
96 void AgentBase::Observer::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
97 {
98  Q_UNUSED( collection );
99  Q_UNUSED( parent );
100  if ( sAgentBase != 0 ) {
101  sAgentBase->d_ptr->changeProcessed();
102  }
103 }
104 
105 void AgentBase::Observer::collectionChanged( const Collection &collection )
106 {
107  Q_UNUSED( collection );
108  if ( sAgentBase != 0 ) {
109  sAgentBase->d_ptr->changeProcessed();
110  }
111 }
112 
113 void AgentBase::Observer::collectionRemoved( const Collection &collection )
114 {
115  Q_UNUSED( collection );
116  if ( sAgentBase != 0 ) {
117  sAgentBase->d_ptr->changeProcessed();
118  }
119 }
120 
121 void AgentBase::ObserverV2::itemMoved( const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest )
122 {
123  Q_UNUSED( item );
124  Q_UNUSED( source );
125  Q_UNUSED( dest );
126  if ( sAgentBase != 0 ) {
127  sAgentBase->d_ptr->changeProcessed();
128  }
129 }
130 
131 void AgentBase::ObserverV2::itemLinked( const Akonadi::Item& item, const Akonadi::Collection& collection )
132 {
133  Q_UNUSED( item );
134  Q_UNUSED( collection );
135  if ( sAgentBase != 0 ) {
136  // not implementation, let's disconnect the signal to enable optimizations in Monitor
137  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
138  sAgentBase->d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
139  sAgentBase->d_ptr->changeProcessed();
140  }
141 }
142 
143 void AgentBase::ObserverV2::itemUnlinked( const Akonadi::Item& item, const Akonadi::Collection& collection )
144 {
145  Q_UNUSED( item );
146  Q_UNUSED( collection );
147  if ( sAgentBase != 0 ) {
148  // not implementation, let's disconnect the signal to enable optimizations in Monitor
149  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
150  sAgentBase->d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
151  sAgentBase->d_ptr->changeProcessed();
152  }
153 }
154 
155 void AgentBase::ObserverV2::collectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &dest )
156 {
157  Q_UNUSED( collection );
158  Q_UNUSED( source );
159  Q_UNUSED( dest );
160  if ( sAgentBase != 0 ) {
161  sAgentBase->d_ptr->changeProcessed();
162  }
163 }
164 
165 void AgentBase::ObserverV2::collectionChanged( const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes )
166 {
167  Q_UNUSED( changedAttributes );
168  collectionChanged( collection );
169 }
170 
171 //@cond PRIVATE
172 
173 AgentBasePrivate::AgentBasePrivate( AgentBase *parent )
174  : q_ptr( parent ),
175  mDBusConnection( QString() ),
176  mStatusCode( AgentBase::Idle ),
177  mProgress( 0 ),
178  mNeedsNetwork( false ),
179  mOnline( false ),
180  mDesiredOnlineState( false ),
181  mSettings( 0 ),
182  mObserver( 0 )
183 {
184 #ifdef Q_OS_WINCE
185  QThread::currentThread()->setPriority( QThread::LowPriority );
186 #endif
187  Internal::setClientType( Internal::Agent );
188 }
189 
190 AgentBasePrivate::~AgentBasePrivate()
191 {
192  mChangeRecorder->setConfig( 0 );
193  delete mSettings;
194 }
195 
196 void AgentBasePrivate::init()
197 {
198  Q_Q( AgentBase );
199 
203  SessionPrivate::createDefaultSession( mId.toLatin1() );
204 
205  if ( QThread::currentThread() != QCoreApplication::instance()->thread() ) {
206  mDBusConnection = QDBusConnection::connectToBus( QDBusConnection::SessionBus, q->identifier() );
207  Q_ASSERT( mDBusConnection.isConnected() );
208  }
209 
210  mTracer = new org::freedesktop::Akonadi::Tracer( ServerManager::serviceName( ServerManager::Server ),
211  QLatin1String( "/tracing" ),
212  DBusConnectionPool::threadConnection(), q );
213 
214  new Akonadi__ControlAdaptor( q );
215  new Akonadi__StatusAdaptor( q );
216  if ( !DBusConnectionPool::threadConnection().registerObject( QLatin1String( "/" ), q, QDBusConnection::ExportAdaptors ) )
217  q->error( i18n( "Unable to register object at dbus: %1", DBusConnectionPool::threadConnection().lastError().message() ) );
218 
219  mSettings = new QSettings( QString::fromLatin1( "%1/agent_config_%2" ).arg( Internal::xdgSaveDir( "config" ), mId ), QSettings::IniFormat );
220 
221  mChangeRecorder = new ChangeRecorder( q );
222  mChangeRecorder->ignoreSession( Session::defaultSession() );
223  mChangeRecorder->itemFetchScope().setCacheOnly( true );
224  mChangeRecorder->setConfig( mSettings );
225 
226  mDesiredOnlineState = mSettings->value( QLatin1String( "Agent/DesiredOnlineState" ), true ).toBool();
227  mOnline = mDesiredOnlineState;
228 
229  // reinitialize the status message now that online state is available
230  mStatusMessage = defaultReadyMessage();
231 
232  mName = mSettings->value( QLatin1String( "Agent/Name" ) ).toString();
233  if ( mName.isEmpty() ) {
234  mName = mSettings->value( QLatin1String( "Resource/Name" ) ).toString();
235  if ( !mName.isEmpty() ) {
236  mSettings->remove( QLatin1String( "Resource/Name" ) );
237  mSettings->setValue( QLatin1String( "Agent/Name" ), mName );
238  }
239  }
240 
241  connect( mChangeRecorder, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)),
242  SLOT(itemAdded(Akonadi::Item,Akonadi::Collection)) );
243  connect( mChangeRecorder, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)),
244  SLOT(itemChanged(Akonadi::Item,QSet<QByteArray>)) );
245  connect( mChangeRecorder, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
246  SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)) );
247  connect( mChangeRecorder, SIGNAL(itemRemoved(Akonadi::Item)),
248  SLOT(itemRemoved(Akonadi::Item)) );
249  connect( mChangeRecorder, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)),
250  SLOT(collectionAdded(Akonadi::Collection,Akonadi::Collection)) );
251  connect( mChangeRecorder, SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
252  SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
253  connect( mChangeRecorder, SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
254  SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
255  connect( mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection)),
256  SLOT(collectionChanged(Akonadi::Collection)) );
257  connect( mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>)),
258  SLOT(collectionChanged(Akonadi::Collection,QSet<QByteArray>)) );
259  connect( mChangeRecorder, SIGNAL(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)),
260  SLOT(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)) );
261  connect( mChangeRecorder, SIGNAL(collectionRemoved(Akonadi::Collection)),
262  SLOT(collectionRemoved(Akonadi::Collection)) );
263  connect( mChangeRecorder, SIGNAL(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)),
264  SLOT(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)) );
265  connect( mChangeRecorder, SIGNAL(collectionUnsubscribed(Akonadi::Collection)),
266  SLOT(collectionUnsubscribed(Akonadi::Collection)) );
267 
268  connect( q, SIGNAL(status(int,QString)), q, SLOT(slotStatus(int,QString)) );
269  connect( q, SIGNAL(percent(int)), q, SLOT(slotPercent(int)) );
270  connect( q, SIGNAL(warning(QString)), q, SLOT(slotWarning(QString)) );
271  connect( q, SIGNAL(error(QString)), q, SLOT(slotError(QString)) );
272 
273  connect( Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), q, SLOT(slotResumedFromSuspend()) );
274 
275  // Use reference counting to allow agents to finish internal jobs when the
276  // agent is stopped.
277  KGlobal::ref();
278  if ( QThread::currentThread() == QCoreApplication::instance()->thread() ) {
279  KGlobal::setAllowQuit( true );
280  }
281 
282 #ifndef Q_OS_WINCE
283  // disable session management
284  if ( KApplication::kApplication() ) {
285  KApplication::kApplication()->disableSessionManagement();
286  }
287 #endif
288 
289  mResourceTypeName = AgentManager::self()->instance( mId ).type().name();
290  setProgramName();
291 
292  QTimer::singleShot( 0, q, SLOT(delayedInit()) );
293 }
294 
295 void AgentBasePrivate::delayedInit()
296 {
297  Q_Q( AgentBase );
298  const QString serviceId = ServerManager::agentServiceName( ServerManager::Agent, mId );
299  if ( !DBusConnectionPool::threadConnection().registerService( serviceId ) ) {
300  kFatal() << "Unable to register service" << serviceId << "at dbus:" << DBusConnectionPool::threadConnection().lastError().message();
301  }
302  q->setOnlineInternal( mDesiredOnlineState );
303 }
304 
305 void AgentBasePrivate::setProgramName()
306 {
307  // ugly, really ugly, if you find another solution, change it and blame me for this code (Andras)
308  QString programName = mResourceTypeName;
309  if ( !mName.isEmpty() ) {
310  programName = i18nc( "Name and type of Akonadi resource", "%1 of type %2", mName, mResourceTypeName ) ;
311  }
312  const_cast<KAboutData*>( KGlobal::mainComponent().aboutData() )->setProgramName( ki18n( programName.toUtf8() ) );
313 }
314 
315 void AgentBasePrivate::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
316 {
317  if ( mObserver != 0 ) {
318  mObserver->itemAdded( item, collection );
319  }
320 }
321 
322 void AgentBasePrivate::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers )
323 {
324  if ( mObserver != 0 ) {
325  mObserver->itemChanged( item, partIdentifiers );
326  }
327 }
328 
329 void AgentBasePrivate::itemMoved( const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest )
330 {
331  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
332  if ( mObserver ) {
333  // inter-resource moves, requires we know which resources the source and destination are in though
334  if ( !source.resource().isEmpty() && !dest.resource().isEmpty() ) {
335  if ( source.resource() != dest.resource() ) {
336  if ( source.resource() == q_ptr->identifier() ) { // moved away from us
337  Akonadi::Item i( item );
338  i.setParentCollection( source );
339  mObserver->itemRemoved( i );
340  } else if ( dest.resource() == q_ptr->identifier() ) { // moved to us
341  mObserver->itemAdded( item, dest );
342  } else if ( observer2 ) {
343  observer2->itemMoved( item, source, dest );
344  } else {
345  // not for us, not sure if we should get here at all
346  changeProcessed();
347  }
348  return;
349  }
350  }
351  // intra-resource move
352  if ( observer2 ) {
353  observer2->itemMoved( item, source, dest );
354  } else {
355  // ### we cannot just call itemRemoved here as this will already trigger changeProcessed()
356  // so, just itemAdded() is good enough as no resource can have implemented intra-resource moves anyway
357  // without using ObserverV2
358  mObserver->itemAdded( item, dest );
359  // mObserver->itemRemoved( item );
360  }
361  }
362 }
363 
364 void AgentBasePrivate::itemRemoved( const Akonadi::Item &item )
365 {
366  if ( mObserver != 0 ) {
367  mObserver->itemRemoved( item );
368  }
369 }
370 
371 void AgentBasePrivate::itemLinked( const Akonadi::Item &item, const Akonadi::Collection &collection )
372 {
373  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
374  if ( observer2 ) {
375  observer2->itemLinked( item, collection );
376  } else {
377  changeProcessed();
378  }
379 }
380 
381 void AgentBasePrivate::itemUnlinked( const Akonadi::Item &item, const Akonadi::Collection &collection )
382 {
383  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
384  if ( observer2 ) {
385  observer2->itemUnlinked( item, collection );
386  } else {
387  changeProcessed();
388  }
389 }
390 
391 void AgentBasePrivate::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
392 {
393  if ( mObserver != 0 ) {
394  mObserver->collectionAdded( collection, parent );
395  }
396 }
397 
398 void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection )
399 {
400  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
401  if ( mObserver != 0 && observer2 == 0 ) { // For ObserverV2 we use the variant with the part identifiers
402  mObserver->collectionChanged( collection );
403  }
404 }
405 
406 void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes )
407 {
408  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
409  if ( observer2 != 0 ) {
410  observer2->collectionChanged( collection, changedAttributes );
411  }
412 }
413 
414 void AgentBasePrivate::collectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &dest )
415 {
416  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
417  if ( observer2 ) {
418  observer2->collectionMoved( collection, source, dest );
419  } else if ( mObserver ) {
420  // ### we cannot just call collectionRemoved here as this will already trigger changeProcessed()
421  // so, just collectionAdded() is good enough as no resource can have implemented intra-resource moves anyway
422  // without using ObserverV2
423  mObserver->collectionAdded( collection, dest );
424  } else {
425  changeProcessed();
426  }
427 }
428 
429 void AgentBasePrivate::collectionRemoved( const Akonadi::Collection &collection )
430 {
431  if ( mObserver != 0 ) {
432  mObserver->collectionRemoved( collection );
433  }
434 }
435 
436 void AgentBasePrivate::collectionSubscribed( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
437 {
438  Q_UNUSED( collection );
439  Q_UNUSED( parent );
440  changeProcessed();
441 }
442 
443 void AgentBasePrivate::collectionUnsubscribed( const Akonadi::Collection &collection )
444 {
445  Q_UNUSED( collection );
446  changeProcessed();
447 }
448 
449 void AgentBasePrivate::changeProcessed()
450 {
451  mChangeRecorder->changeProcessed();
452  QTimer::singleShot( 0, mChangeRecorder, SLOT(replayNext()) );
453 }
454 
455 void AgentBasePrivate::slotStatus( int status, const QString &message )
456 {
457  mStatusMessage = message;
458  mStatusCode = 0;
459 
460  switch ( status ) {
461  case AgentBase::Idle:
462  if ( mStatusMessage.isEmpty() ) {
463  mStatusMessage = defaultReadyMessage();
464  }
465 
466  mStatusCode = 0;
467  break;
468  case AgentBase::Running:
469  if ( mStatusMessage.isEmpty() ) {
470  mStatusMessage = defaultSyncingMessage();
471  }
472 
473  mStatusCode = 1;
474  break;
475  case AgentBase::Broken:
476  if ( mStatusMessage.isEmpty() ) {
477  mStatusMessage = defaultErrorMessage();
478  }
479 
480  mStatusCode = 2;
481  break;
482  default:
483  Q_ASSERT( !"Unknown status passed" );
484  break;
485  }
486 }
487 
488 void AgentBasePrivate::slotPercent( int progress )
489 {
490  mProgress = progress;
491 }
492 
493 void AgentBasePrivate::slotWarning( const QString& message )
494 {
495  mTracer->warning( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message );
496 }
497 
498 void AgentBasePrivate::slotError( const QString& message )
499 {
500  mTracer->error( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message );
501 }
502 
503 void AgentBasePrivate::slotNetworkStatusChange( Solid::Networking::Status stat )
504 {
505  Q_Q( AgentBase );
506  q->setOnlineInternal( mDesiredOnlineState && ( stat == Solid::Networking::Unknown || stat == Solid::Networking::Connected ) );
507 }
508 
509 void AgentBasePrivate::slotResumedFromSuspend()
510 {
511  if ( mNeedsNetwork ) {
512  slotNetworkStatusChange( Solid::Networking::status() );
513  }
514 }
515 
516 AgentBase::AgentBase( const QString & id )
517  : d_ptr( new AgentBasePrivate( this ) )
518 {
519  sAgentBase = this;
520  d_ptr->mId = id;
521  d_ptr->init();
522 }
523 
524 AgentBase::AgentBase( AgentBasePrivate* d, const QString &id ) :
525  d_ptr( d )
526 {
527  sAgentBase = this;
528  d_ptr->mId = id;
529  d_ptr->init();
530 }
531 
532 AgentBase::~AgentBase()
533 {
534  delete d_ptr;
535 }
536 
537 QString AgentBase::parseArguments( int argc, char **argv )
538 {
539  QString identifier;
540  if ( argc < 3 ) {
541  kDebug() << "Not enough arguments passed...";
542  exit( 1 );
543  }
544 
545  for ( int i = 1; i < argc - 1; ++i ) {
546  if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) ) {
547  identifier = QLatin1String( argv[ i + 1 ] );
548  }
549  }
550 
551  if ( identifier.isEmpty() ) {
552  kDebug() << "Identifier argument missing";
553  exit( 1 );
554  }
555 
556  const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
557  // strip off full path and possible .exe suffix
558  const QByteArray catalog = fi.baseName().toLatin1();
559 
560  KCmdLineArgs::init( argc, argv, ServerManager::addNamespace( identifier ).toLatin1(), catalog, ki18n( "Akonadi Agent" ), KDEPIMLIBS_VERSION,
561  ki18n( "Akonadi Agent" ) );
562 
563  KCmdLineOptions options;
564  options.add( "identifier <argument>", ki18n( "Agent identifier" ) );
565  KCmdLineArgs::addCmdLineOptions( options );
566 
567  return identifier;
568 }
569 
570 // @endcond
571 
572 int AgentBase::init( AgentBase *r )
573 {
574  QApplication::setQuitOnLastWindowClosed( false );
575  KGlobal::locale()->insertCatalog( QLatin1String( "libakonadi" ) );
576  int rv = kapp->exec();
577  delete r;
578  return rv;
579 }
580 
581 int AgentBase::status() const
582 {
583  Q_D( const AgentBase );
584 
585  return d->mStatusCode;
586 }
587 
588 QString AgentBase::statusMessage() const
589 {
590  Q_D( const AgentBase );
591 
592  return d->mStatusMessage;
593 }
594 
595 int AgentBase::progress() const
596 {
597  Q_D( const AgentBase );
598 
599  return d->mProgress;
600 }
601 
602 QString AgentBase::progressMessage() const
603 {
604  Q_D( const AgentBase );
605 
606  return d->mProgressMessage;
607 }
608 
609 bool AgentBase::isOnline() const
610 {
611  Q_D( const AgentBase );
612 
613  return d->mOnline;
614 }
615 
616 void AgentBase::setNeedsNetwork( bool needsNetwork )
617 {
618  Q_D( AgentBase );
619  d->mNeedsNetwork = needsNetwork;
620 
621  if ( d->mNeedsNetwork ) {
622  connect( Solid::Networking::notifier()
623  , SIGNAL(statusChanged(Solid::Networking::Status))
624  , this, SLOT(slotNetworkStatusChange(Solid::Networking::Status))
625  , Qt::UniqueConnection );
626 
627  } else {
628  disconnect( Solid::Networking::notifier(), 0, 0, 0 );
629  setOnlineInternal( d->mDesiredOnlineState );
630  }
631 }
632 
633 void AgentBase::setOnline( bool state )
634 {
635  Q_D( AgentBase );
636  d->mDesiredOnlineState = state;
637  d->mSettings->setValue( QLatin1String( "Agent/DesiredOnlineState" ), state );
638  setOnlineInternal( state );
639 }
640 
641 void AgentBase::setOnlineInternal( bool state )
642 {
643  Q_D( AgentBase );
644  d->mOnline = state;
645 
646  const QString newMessage = d->defaultReadyMessage();
647  if ( d->mStatusMessage != newMessage && d->mStatusCode != AgentBase::Broken ) {
648  emit status( d->mStatusCode, newMessage );
649  }
650 
651  doSetOnline( state );
652  emit onlineChanged( state );
653 }
654 
655 void AgentBase::doSetOnline( bool online )
656 {
657  Q_UNUSED( online );
658 }
659 
660 void AgentBase::configure( WId windowId )
661 {
662  Q_UNUSED( windowId );
663  emit configurationDialogAccepted();
664 }
665 
666 #ifdef Q_OS_WIN //krazy:exclude=cpp
667 void AgentBase::configure( qlonglong windowId )
668 {
669  configure( reinterpret_cast<WId>( windowId ) );
670 }
671 #endif
672 
673 WId AgentBase::winIdForDialogs() const
674 {
675  const bool registered = DBusConnectionPool::threadConnection().interface()->isServiceRegistered( QLatin1String( "org.freedesktop.akonaditray" ) );
676  if ( !registered ) {
677  return 0;
678  }
679 
680  QDBusInterface dbus( QLatin1String( "org.freedesktop.akonaditray" ), QLatin1String( "/Actions" ),
681  QLatin1String( "org.freedesktop.Akonadi.Tray" ) );
682  const QDBusMessage reply = dbus.call( QLatin1String( "getWinId" ) );
683 
684  if ( reply.type() == QDBusMessage::ErrorMessage ) {
685  return 0;
686  }
687 
688  const WId winid = (WId)reply.arguments().at( 0 ).toLongLong();
689 
690  return winid;
691 }
692 
693 void AgentBase::quit()
694 {
695  Q_D( AgentBase );
696  aboutToQuit();
697 
698  if ( d->mSettings ) {
699  d->mChangeRecorder->setConfig( 0 );
700  d->mSettings->sync();
701  }
702 
703  KGlobal::deref();
704 }
705 
706 void AgentBase::aboutToQuit()
707 {
708 }
709 
710 void AgentBase::cleanup()
711 {
712  Q_D( AgentBase );
713  // prevent the monitor from picking up deletion signals for our own data if we are a resource
714  // and thus avoid that we kill our own data as last act before our own death
715  d->mChangeRecorder->blockSignals( true );
716 
717  aboutToQuit();
718 
719  const QString fileName = d->mSettings->fileName();
720 
721  /*
722  * First destroy the settings object...
723  */
724  d->mChangeRecorder->setConfig( 0 );
725  delete d->mSettings;
726  d->mSettings = 0;
727 
728  /*
729  * ... then remove the file from hd.
730  */
731  QFile::remove( fileName );
732 
733  /*
734  * ... and remove the changes file from hd.
735  */
736  QFile::remove( fileName + QLatin1String( "_changes.dat" ) );
737 
738  /*
739  * ... and also remove the agent configuration file if there is one.
740  */
741  QString configFile = KStandardDirs::locateLocal( "config", config()->name() );
742  QFile::remove( configFile );
743 
744  KGlobal::deref();
745 }
746 
747 void AgentBase::registerObserver( Observer *observer )
748 {
749  // TODO in theory we should re-connect change recorder signals here that we disconnected previously
750  d_ptr->mObserver = observer;
751 }
752 
753 QString AgentBase::identifier() const
754 {
755  return d_ptr->mId;
756 }
757 
758 void AgentBase::setAgentName( const QString &name )
759 {
760  Q_D( AgentBase );
761  if ( name == d->mName ) {
762  return;
763  }
764 
765  // TODO: rename collection
766  d->mName = name;
767 
768  if ( d->mName.isEmpty() || d->mName == d->mId ) {
769  d->mSettings->remove( QLatin1String( "Resource/Name" ) );
770  d->mSettings->remove( QLatin1String( "Agent/Name" ) );
771  } else
772  d->mSettings->setValue( QLatin1String( "Agent/Name" ), d->mName );
773 
774  d->mSettings->sync();
775 
776  d->setProgramName();
777 
778  emit agentNameChanged( d->mName );
779 }
780 
781 QString AgentBase::agentName() const
782 {
783  Q_D( const AgentBase );
784  if ( d->mName.isEmpty() ) {
785  return d->mId;
786  } else {
787  return d->mName;
788  }
789 }
790 
791 void AgentBase::changeProcessed()
792 {
793  Q_D( AgentBase );
794  d->changeProcessed();
795 }
796 
797 ChangeRecorder * AgentBase::changeRecorder() const
798 {
799  return d_ptr->mChangeRecorder;
800 }
801 
802 KSharedConfigPtr AgentBase::config()
803 {
804  if ( QCoreApplication::instance()->thread() == QThread::currentThread() ) {
805  return KGlobal::config();
806  } else {
807  return componentData().config();
808  }
809 }
810 
811 void AgentBase::abort()
812 {
813  emit abortRequested();
814 }
815 
816 void AgentBase::reconfigure()
817 {
818  emit reloadConfiguration();
819 }
820 
821 extern QThreadStorage<KComponentData*> s_agentComponentDatas;
822 
823 KComponentData AgentBase::componentData()
824 {
825  if ( QThread::currentThread() == QCoreApplication::instance()->thread() ) {
826  if ( s_agentComponentDatas.hasLocalData() ) {
827  return *( s_agentComponentDatas.localData() );
828  } else {
829  return KGlobal::mainComponent();
830  }
831  }
832 
833  Q_ASSERT( s_agentComponentDatas.hasLocalData() );
834  return *( s_agentComponentDatas.localData() );
835 }
836 
837 #include "moc_agentbase.cpp"
838 #include "moc_agentbase_p.cpp"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Fri Mar 8 2013 21:49:50 by doxygen 1.8.3.1 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.10.0 API Reference

Skip menu "kdepimlibs-4.10.0 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • 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