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

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

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