• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.13.3 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 <kglobal.h>
42 #include <klocalizedstring.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 <QApplication>
52 
53 #include <signal.h>
54 #include <stdlib.h>
55 #if defined __GLIBC__
56 # include <malloc.h> // for dumping memory information
57 #endif
58 
59 //#define EXPERIMENTAL_INPROCESS_AGENTS 1
60 
61 using namespace Akonadi;
62 
63 static AgentBase *sAgentBase = 0;
64 
65 AgentBase::Observer::Observer()
66 {
67 }
68 
69 AgentBase::Observer::~Observer()
70 {
71 }
72 
73 void AgentBase::Observer::itemAdded( const Item &item, const Collection &collection )
74 {
75  Q_UNUSED( item );
76  Q_UNUSED( collection );
77  if ( sAgentBase != 0 ) {
78  sAgentBase->d_ptr->changeProcessed();
79  }
80 }
81 
82 void AgentBase::Observer::itemChanged( const Item &item, const QSet<QByteArray> &partIdentifiers )
83 {
84  Q_UNUSED( item );
85  Q_UNUSED( partIdentifiers );
86  if ( sAgentBase != 0 ) {
87  sAgentBase->d_ptr->changeProcessed();
88  }
89 }
90 
91 void AgentBase::Observer::itemRemoved( const Item &item )
92 {
93  Q_UNUSED( item );
94  if ( sAgentBase != 0 ) {
95  sAgentBase->d_ptr->changeProcessed();
96  }
97 }
98 
99 void AgentBase::Observer::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
100 {
101  Q_UNUSED( collection );
102  Q_UNUSED( parent );
103  if ( sAgentBase != 0 ) {
104  sAgentBase->d_ptr->changeProcessed();
105  }
106 }
107 
108 void AgentBase::Observer::collectionChanged( const Collection &collection )
109 {
110  Q_UNUSED( collection );
111  if ( sAgentBase != 0 ) {
112  sAgentBase->d_ptr->changeProcessed();
113  }
114 }
115 
116 void AgentBase::Observer::collectionRemoved( const Collection &collection )
117 {
118  Q_UNUSED( collection );
119  if ( sAgentBase != 0 ) {
120  sAgentBase->d_ptr->changeProcessed();
121  }
122 }
123 
124 void AgentBase::ObserverV2::itemMoved( const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest )
125 {
126  Q_UNUSED( item );
127  Q_UNUSED( source );
128  Q_UNUSED( dest );
129  if ( sAgentBase != 0 ) {
130  sAgentBase->d_ptr->changeProcessed();
131  }
132 }
133 
134 void AgentBase::ObserverV2::itemLinked( const Akonadi::Item& item, const Akonadi::Collection& collection )
135 {
136  Q_UNUSED( item );
137  Q_UNUSED( collection );
138  if ( sAgentBase != 0 ) {
139  // not implementation, let's disconnect the signal to enable optimizations in Monitor
140  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
141  sAgentBase->d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
142  sAgentBase->d_ptr->changeProcessed();
143  }
144 }
145 
146 void AgentBase::ObserverV2::itemUnlinked( const Akonadi::Item& item, const Akonadi::Collection& collection )
147 {
148  Q_UNUSED( item );
149  Q_UNUSED( collection );
150  if ( sAgentBase != 0 ) {
151  // not implementation, let's disconnect the signal to enable optimizations in Monitor
152  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
153  sAgentBase->d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
154  sAgentBase->d_ptr->changeProcessed();
155  }
156 }
157 
158 void AgentBase::ObserverV2::collectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &dest )
159 {
160  Q_UNUSED( collection );
161  Q_UNUSED( source );
162  Q_UNUSED( dest );
163  if ( sAgentBase != 0 ) {
164  sAgentBase->d_ptr->changeProcessed();
165  }
166 }
167 
168 void AgentBase::ObserverV2::collectionChanged( const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes )
169 {
170  Q_UNUSED( changedAttributes );
171  collectionChanged( collection );
172 }
173 
174 void AgentBase::ObserverV3::itemsFlagsChanged(const Akonadi::Item::List& items, const QSet< QByteArray >& addedFlags, const QSet< QByteArray >& removedFlags)
175 {
176  Q_UNUSED( items );
177  Q_UNUSED( addedFlags );
178  Q_UNUSED( removedFlags );
179 
180  if ( sAgentBase != 0 ) {
181  // not implementation, let's disconnect the signal to enable optimizations in Monitor
182  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)),
183  sAgentBase->d_ptr, SLOT(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)) );
184  sAgentBase->d_ptr->changeProcessed();
185  }
186 }
187 
188 void AgentBase::ObserverV3::itemsMoved(const Akonadi::Item::List& items, const Collection& sourceCollection, const Collection& destinationCollection)
189 {
190  Q_UNUSED( items );
191  Q_UNUSED( sourceCollection );
192  Q_UNUSED( destinationCollection );
193 
194  if ( sAgentBase != 0 ) {
195  // not implementation, let's disconnect the signal to enable optimizations in Monitor
196  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)),
197  sAgentBase->d_ptr, SLOT(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)) );
198  sAgentBase->d_ptr->changeProcessed();
199  }
200 }
201 
202 void AgentBase::ObserverV3::itemsRemoved(const Akonadi::Item::List& items)
203 {
204  Q_UNUSED( items );
205 
206  if ( sAgentBase != 0 ) {
207  // not implementation, let's disconnect the signal to enable optimizations in Monitor
208  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemsRemoved(Akonadi::Item::List)),
209  sAgentBase->d_ptr, SLOT(itemsRemoved(Akonadi::Item::List)) );
210  sAgentBase->d_ptr->changeProcessed();
211  }
212 }
213 
214 void AgentBase::ObserverV3::itemsLinked(const Akonadi::Item::List& items, const Collection& collection)
215 {
216  Q_UNUSED( items );
217  Q_UNUSED( collection );
218 
219  if ( sAgentBase != 0 ) {
220  // not implementation, let's disconnect the signal to enable optimizations in Monitor
221  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemsLinked(Akonadi::Item::List,Akonadi::Collection)),
222  sAgentBase->d_ptr, SLOT(itemsLinked(Akonadi::Item::List,Akonadi::Collection)) );
223  sAgentBase->d_ptr->changeProcessed();
224  }
225 }
226 
227 void AgentBase::ObserverV3::itemsUnlinked(const Akonadi::Item::List& items, const Collection& collection)
228 {
229  Q_UNUSED( items );
230  Q_UNUSED( collection )
231 
232  if ( sAgentBase != 0 ) {
233  // not implementation, let's disconnect the signal to enable optimizations in Monitor
234  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)),
235  sAgentBase->d_ptr, SLOT(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)) );
236  sAgentBase->d_ptr->changeProcessed();
237  }
238 }
239 
240 void AgentBase::ObserverV4::tagAdded( const Tag &tag )
241 {
242  Q_UNUSED( tag );
243 
244  if ( sAgentBase != 0 ) {
245  // not implementation, let's disconnect the signal to enable optimization in Monitor
246  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(tagAdded(Akonadi::Tag)),
247  sAgentBase->d_ptr, SLOT(tagAdded(Akonadi::Tag)) );
248  sAgentBase->d_ptr->changeProcessed();
249  }
250 }
251 
252 void AgentBase::ObserverV4::tagChanged( const Tag &tag )
253 {
254  Q_UNUSED( tag );
255 
256  if ( sAgentBase != 0 ) {
257  // not implementation, let's disconnect the signal to enable optimization in Monitor
258  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(tagChanged(Akonadi::Tag)),
259  sAgentBase->d_ptr, SLOT(tagChanged(Akonadi::Tag)) );
260  sAgentBase->d_ptr->changeProcessed();
261  }
262 }
263 
264 void AgentBase::ObserverV4::tagRemoved( const Tag &tag )
265 {
266  Q_UNUSED( tag );
267 
268  if ( sAgentBase != 0 ) {
269  // not implementation, let's disconnect the signal to enable optimization in Monitor
270  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(tagRemoved(Akonadi::Tag)),
271  sAgentBase->d_ptr, SLOT(tagRemoved(Akonadi::Tag)) );
272  sAgentBase->d_ptr->changeProcessed();
273  }
274 }
275 
276 void AgentBase::ObserverV4::itemsTagsChanged( const Item::List &items, const QSet<Tag> &addedTags, const QSet<Tag> &removedTags )
277 {
278  Q_UNUSED( items );
279  Q_UNUSED( addedTags );
280  Q_UNUSED( removedTags );
281 
282  if ( sAgentBase != 0 ) {
283  // not implementation, let's disconnect the signal to enable optimization in Monitor
284  QObject::disconnect( sAgentBase->changeRecorder(), SIGNAL(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)),
285  sAgentBase->d_ptr, SLOT(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)) );
286  sAgentBase->d_ptr->changeProcessed();
287  }
288 }
289 
290 
291 
292 //@cond PRIVATE
293 
294 AgentBasePrivate::AgentBasePrivate( AgentBase *parent )
295  : q_ptr( parent ),
296  mDBusConnection( QString() ),
297  mStatusCode( AgentBase::Idle ),
298  mProgress( 0 ),
299  mNeedsNetwork( false ),
300  mOnline( false ),
301  mDesiredOnlineState( false ),
302  mSettings( 0 ),
303  mChangeRecorder( 0 ),
304  mTracer( 0 ),
305  mObserver(0),
306  mTemporaryOfflineTimer(0)
307 {
308  Internal::setClientType( Internal::Agent );
309 }
310 
311 AgentBasePrivate::~AgentBasePrivate()
312 {
313  mChangeRecorder->setConfig( 0 );
314  delete mSettings;
315 }
316 
317 void AgentBasePrivate::init()
318 {
319  Q_Q( AgentBase );
320 
324  SessionPrivate::createDefaultSession( mId.toLatin1() );
325 
326  if ( QThread::currentThread() != QCoreApplication::instance()->thread() ) {
327  mDBusConnection = QDBusConnection::connectToBus( QDBusConnection::SessionBus, q->identifier() );
328  Q_ASSERT( mDBusConnection.isConnected() );
329  }
330 
331  mTracer = new org::freedesktop::Akonadi::Tracer( ServerManager::serviceName( ServerManager::Server ),
332  QLatin1String( "/tracing" ),
333  DBusConnectionPool::threadConnection(), q );
334 
335  new Akonadi__ControlAdaptor( q );
336  new Akonadi__StatusAdaptor( q );
337  if ( !DBusConnectionPool::threadConnection().registerObject( QLatin1String( "/" ), q, QDBusConnection::ExportAdaptors ) )
338  q->error( i18n( "Unable to register object at dbus: %1", DBusConnectionPool::threadConnection().lastError().message() ) );
339 
340  mSettings = new QSettings( QString::fromLatin1( "%1/agent_config_%2" ).arg( Internal::xdgSaveDir( "config" ), mId ), QSettings::IniFormat );
341 
342  mChangeRecorder = new ChangeRecorder( q );
343  mChangeRecorder->ignoreSession( Session::defaultSession() );
344  mChangeRecorder->itemFetchScope().setCacheOnly( true );
345  mChangeRecorder->setConfig( mSettings );
346 
347  mDesiredOnlineState = mSettings->value( QLatin1String( "Agent/DesiredOnlineState" ), true ).toBool();
348  mOnline = mDesiredOnlineState;
349 
350  // reinitialize the status message now that online state is available
351  mStatusMessage = defaultReadyMessage();
352 
353  mName = mSettings->value( QLatin1String( "Agent/Name" ) ).toString();
354  if ( mName.isEmpty() ) {
355  mName = mSettings->value( QLatin1String( "Resource/Name" ) ).toString();
356  if ( !mName.isEmpty() ) {
357  mSettings->remove( QLatin1String( "Resource/Name" ) );
358  mSettings->setValue( QLatin1String( "Agent/Name" ), mName );
359  }
360  }
361 
362  connect( mChangeRecorder, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)),
363  SLOT(itemAdded(Akonadi::Item,Akonadi::Collection)) );
364  connect( mChangeRecorder, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)),
365  SLOT(itemChanged(Akonadi::Item,QSet<QByteArray>)) );
366  connect( mChangeRecorder, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)),
367  SLOT(collectionAdded(Akonadi::Collection,Akonadi::Collection)) );
368  connect( mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection)),
369  SLOT(collectionChanged(Akonadi::Collection)) );
370  connect( mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>)),
371  SLOT(collectionChanged(Akonadi::Collection,QSet<QByteArray>)) );
372  connect( mChangeRecorder, SIGNAL(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)),
373  SLOT(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)) );
374  connect( mChangeRecorder, SIGNAL(collectionRemoved(Akonadi::Collection)),
375  SLOT(collectionRemoved(Akonadi::Collection)) );
376  connect( mChangeRecorder, SIGNAL(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)),
377  SLOT(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)) );
378  connect( mChangeRecorder, SIGNAL(collectionUnsubscribed(Akonadi::Collection)),
379  SLOT(collectionUnsubscribed(Akonadi::Collection)) );
380 
381  connect( q, SIGNAL(status(int,QString)), q, SLOT(slotStatus(int,QString)) );
382  connect( q, SIGNAL(percent(int)), q, SLOT(slotPercent(int)) );
383  connect( q, SIGNAL(warning(QString)), q, SLOT(slotWarning(QString)) );
384  connect( q, SIGNAL(error(QString)), q, SLOT(slotError(QString)) );
385 
386  connect( Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), q, SLOT(slotResumedFromSuspend()) );
387 
388  // Use reference counting to allow agents to finish internal jobs when the
389  // agent is stopped.
390  KGlobal::ref();
391  if ( QThread::currentThread() == QCoreApplication::instance()->thread() ) {
392  KGlobal::setAllowQuit( true );
393  }
394 
395  // disable session management
396  if ( KApplication::kApplication() ) {
397  KApplication::kApplication()->disableSessionManagement();
398  }
399 
400  mResourceTypeName = AgentManager::self()->instance( mId ).type().name();
401  setProgramName();
402 
403  QTimer::singleShot( 0, q, SLOT(delayedInit()) );
404 }
405 
406 void AgentBasePrivate::delayedInit()
407 {
408  Q_Q( AgentBase );
409 
410  const QString serviceId = ServerManager::agentServiceName( ServerManager::Agent, mId );
411  if ( !DBusConnectionPool::threadConnection().registerService( serviceId ) ) {
412  kFatal() << "Unable to register service" << serviceId << "at dbus:" << DBusConnectionPool::threadConnection().lastError().message();
413  }
414  q->setOnlineInternal( mDesiredOnlineState );
415 
416  DBusConnectionPool::threadConnection().registerObject( QLatin1String( "/Debug" ), this, QDBusConnection::ExportScriptableSlots );
417 }
418 
419 void AgentBasePrivate::setProgramName()
420 {
421  // ugly, really ugly, if you find another solution, change it and blame me for this code (Andras)
422  QString programName = mResourceTypeName;
423  if ( !mName.isEmpty() ) {
424  programName = i18nc( "Name and type of Akonadi resource", "%1 of type %2", mName, mResourceTypeName ) ;
425  }
426  const_cast<KAboutData*>( KGlobal::mainComponent().aboutData() )->setProgramName( ki18n( programName.toUtf8() ) );
427 }
428 
429 void AgentBasePrivate::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
430 {
431  if ( mObserver != 0 ) {
432  mObserver->itemAdded( item, collection );
433  }
434 }
435 
436 void AgentBasePrivate::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers )
437 {
438  if ( mObserver != 0 ) {
439  mObserver->itemChanged( item, partIdentifiers );
440  }
441 }
442 
443 void AgentBasePrivate::itemMoved( const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest )
444 {
445  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
446  if ( mObserver ) {
447  // inter-resource moves, requires we know which resources the source and destination are in though
448  if ( !source.resource().isEmpty() && !dest.resource().isEmpty() ) {
449  if ( source.resource() != dest.resource() ) {
450  if ( source.resource() == q_ptr->identifier() ) { // moved away from us
451  Akonadi::Item i( item );
452  i.setParentCollection( source );
453  mObserver->itemRemoved( i );
454  } else if ( dest.resource() == q_ptr->identifier() ) { // moved to us
455  mObserver->itemAdded( item, dest );
456  } else if ( observer2 ) {
457  observer2->itemMoved( item, source, dest );
458  } else {
459  // not for us, not sure if we should get here at all
460  changeProcessed();
461  }
462  return;
463  }
464  }
465  // intra-resource move
466  if ( observer2 ) {
467  observer2->itemMoved( item, source, dest );
468  } else {
469  // ### we cannot just call itemRemoved here as this will already trigger changeProcessed()
470  // so, just itemAdded() is good enough as no resource can have implemented intra-resource moves anyway
471  // without using ObserverV2
472  mObserver->itemAdded( item, dest );
473  // mObserver->itemRemoved( item );
474  }
475  }
476 }
477 
478 void AgentBasePrivate::itemRemoved( const Akonadi::Item &item )
479 {
480  if ( mObserver != 0 ) {
481  mObserver->itemRemoved( item );
482  }
483 }
484 
485 void AgentBasePrivate::itemLinked( const Akonadi::Item &item, const Akonadi::Collection &collection )
486 {
487  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
488  if ( observer2 ) {
489  observer2->itemLinked( item, collection );
490  } else {
491  changeProcessed();
492  }
493 }
494 
495 void AgentBasePrivate::itemUnlinked( const Akonadi::Item &item, const Akonadi::Collection &collection )
496 {
497  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
498  if ( observer2 ) {
499  observer2->itemUnlinked( item, collection );
500  } else {
501  changeProcessed();
502  }
503 }
504 
505 void AgentBasePrivate::itemsFlagsChanged( const Akonadi::Item::List &items, const QSet<QByteArray> &addedFlags, const QSet<QByteArray> &removedFlags )
506 {
507  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3*>( mObserver );
508  if ( observer3 ) {
509  observer3->itemsFlagsChanged( items, addedFlags, removedFlags );
510  } else {
511  Q_ASSERT_X( false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available" );
512  }
513 }
514 
515 void AgentBasePrivate::itemsMoved( const Akonadi::Item::List &items, const Akonadi::Collection &source, const Akonadi::Collection &destination )
516 {
517  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3*>( mObserver );
518  if ( observer3 ) {
519  observer3->itemsMoved( items, source, destination );
520  } else {
521  Q_ASSERT_X( false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available" );
522  }
523 }
524 
525 void AgentBasePrivate::itemsRemoved( const Akonadi::Item::List &items )
526 {
527  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3*>( mObserver );
528  if ( observer3 ) {
529  observer3->itemsRemoved( items );
530  } else {
531  Q_ASSERT_X( false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available" );
532  }
533 }
534 
535 void AgentBasePrivate::itemsLinked( const Akonadi::Item::List &items, const Akonadi::Collection &collection )
536 {
537  if ( !mObserver ) {
538  changeProcessed();
539  return;
540  }
541 
542  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3*>( mObserver );
543  if ( observer3 ) {
544  observer3->itemsLinked( items, collection );
545  } else {
546  Q_ASSERT_X( false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available" );
547  }
548 }
549 
550 void AgentBasePrivate::itemsUnlinked( const Akonadi::Item::List &items, const Akonadi::Collection &collection )
551 {
552  if ( !mObserver ) {
553  return;
554  }
555 
556  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3*>( mObserver );
557  if ( observer3 ) {
558  observer3->itemsUnlinked( items, collection );
559  } else {
560  Q_ASSERT_X( false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available" );
561  }
562 }
563 
564 void AgentBasePrivate::tagAdded( const Akonadi::Tag &tag )
565 {
566  if ( !mObserver ) {
567  return;
568  }
569 
570  AgentBase::ObserverV4 *observer4 = dynamic_cast<AgentBase::ObserverV4*>( mObserver );
571  if ( observer4 ) {
572  observer4->tagAdded( tag );
573  } else {
574  changeProcessed();
575  }
576 }
577 
578 void AgentBasePrivate::tagChanged( const Akonadi::Tag &tag )
579 {
580  if ( !mObserver ) {
581  return;
582  }
583 
584  AgentBase::ObserverV4 *observer4 = dynamic_cast<AgentBase::ObserverV4*>( mObserver );
585  if ( observer4 ) {
586  observer4->tagChanged( tag );
587  } else {
588  changeProcessed();
589  }
590 }
591 
592 void AgentBasePrivate::tagRemoved( const Akonadi::Tag &tag )
593 {
594  if ( !mObserver ) {
595  return;
596  }
597 
598  AgentBase::ObserverV4 *observer4 = dynamic_cast<AgentBase::ObserverV4*>( mObserver );
599  if ( observer4 ) {
600  observer4->tagRemoved( tag );;
601  } else {
602  changeProcessed();
603  }
604 }
605 
606 void AgentBasePrivate::itemsTagsChanged( const Akonadi::Item::List &items, const QSet<Akonadi::Tag> &addedTags, const QSet<Akonadi::Tag> &removedTags )
607 {
608  if ( !mObserver ) {
609  return;
610  }
611 
612  AgentBase::ObserverV4 *observer4 = dynamic_cast<AgentBase::ObserverV4*>( mObserver );
613  if ( observer4 ) {
614  observer4->itemsTagsChanged( items, addedTags, removedTags );
615  } else {
616  changeProcessed();
617  }
618 }
619 
620 void AgentBasePrivate::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
621 {
622  if ( mObserver != 0 ) {
623  mObserver->collectionAdded( collection, parent );
624  }
625 }
626 
627 void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection )
628 {
629  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
630  if ( mObserver != 0 && observer2 == 0 ) { // For ObserverV2 we use the variant with the part identifiers
631  mObserver->collectionChanged( collection );
632  }
633 }
634 
635 void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes )
636 {
637  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
638  if ( observer2 != 0 ) {
639  observer2->collectionChanged( collection, changedAttributes );
640  }
641 }
642 
643 void AgentBasePrivate::collectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &dest )
644 {
645  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2*>( mObserver );
646  if ( observer2 ) {
647  observer2->collectionMoved( collection, source, dest );
648  } else if ( mObserver ) {
649  // ### we cannot just call collectionRemoved here as this will already trigger changeProcessed()
650  // so, just collectionAdded() is good enough as no resource can have implemented intra-resource moves anyway
651  // without using ObserverV2
652  mObserver->collectionAdded( collection, dest );
653  } else {
654  changeProcessed();
655  }
656 }
657 
658 void AgentBasePrivate::collectionRemoved( const Akonadi::Collection &collection )
659 {
660  if ( mObserver != 0 ) {
661  mObserver->collectionRemoved( collection );
662  }
663 }
664 
665 void AgentBasePrivate::collectionSubscribed( const Akonadi::Collection &collection, const Akonadi::Collection &parent )
666 {
667  Q_UNUSED( collection );
668  Q_UNUSED( parent );
669  changeProcessed();
670 }
671 
672 void AgentBasePrivate::collectionUnsubscribed( const Akonadi::Collection &collection )
673 {
674  Q_UNUSED( collection );
675  changeProcessed();
676 }
677 
678 void AgentBasePrivate::changeProcessed()
679 {
680  mChangeRecorder->changeProcessed();
681  QTimer::singleShot( 0, mChangeRecorder, SLOT(replayNext()) );
682 }
683 
684 void AgentBasePrivate::slotStatus( int status, const QString &message )
685 {
686  mStatusMessage = message;
687  mStatusCode = 0;
688 
689  switch ( status ) {
690  case AgentBase::Idle:
691  if ( mStatusMessage.isEmpty() ) {
692  mStatusMessage = defaultReadyMessage();
693  }
694 
695  mStatusCode = 0;
696  break;
697  case AgentBase::Running:
698  if ( mStatusMessage.isEmpty() ) {
699  mStatusMessage = defaultSyncingMessage();
700  }
701 
702  mStatusCode = 1;
703  break;
704  case AgentBase::Broken:
705  if ( mStatusMessage.isEmpty() ) {
706  mStatusMessage = defaultErrorMessage();
707  }
708 
709  mStatusCode = 2;
710  break;
711 
712  case AgentBase::NotConfigured:
713  if ( mStatusMessage.isEmpty() ) {
714  mStatusMessage = defaultUnconfiguredMessage();
715  }
716 
717  mStatusCode = 3;
718  break;
719 
720  default:
721  Q_ASSERT( !"Unknown status passed" );
722  break;
723  }
724 }
725 
726 void AgentBasePrivate::slotPercent( int progress )
727 {
728  mProgress = progress;
729 }
730 
731 void AgentBasePrivate::slotWarning( const QString& message )
732 {
733  mTracer->warning( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message );
734 }
735 
736 void AgentBasePrivate::slotError( const QString& message )
737 {
738  mTracer->error( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message );
739 }
740 
741 void AgentBasePrivate::slotNetworkStatusChange( Solid::Networking::Status stat )
742 {
743  Q_UNUSED( stat );
744  Q_Q( AgentBase );
745  q->setOnlineInternal( mDesiredOnlineState );
746 }
747 
748 void AgentBasePrivate::slotResumedFromSuspend()
749 {
750  if ( mNeedsNetwork ) {
751  slotNetworkStatusChange( Solid::Networking::status() );
752  }
753 }
754 
755 void AgentBasePrivate::slotTemporaryOfflineTimeout()
756 {
757  Q_Q(AgentBase);
758  q->setOnlineInternal(true);
759 }
760 
761 QString AgentBasePrivate::dumpNotificationListToString() const
762 {
763  return mChangeRecorder->dumpNotificationListToString();
764 }
765 
766 void AgentBasePrivate::dumpMemoryInfo() const
767 {
768  // Send it to stdout, so we can debug user problems.
769  // since you have to explicitely call this
770  // it won't flood users with release builds.
771  QTextStream stream( stdout );
772  stream << dumpMemoryInfoToString();
773 }
774 
775 QString AgentBasePrivate::dumpMemoryInfoToString() const
776 {
777  // man mallinfo for more info
778  QString str;
779 #if defined __GLIBC__
780  struct mallinfo mi;
781  mi = mallinfo();
782  QTextStream stream( &str );
783  stream
784  << "Total non-mmapped bytes (arena): " << mi.arena << '\n'
785  << "# of free chunks (ordblks): " << mi.ordblks << '\n'
786  << "# of free fastbin blocks (smblks>: " << mi.smblks << '\n'
787  << "# of mapped regions (hblks): " << mi.hblks << '\n'
788  << "Bytes in mapped regions (hblkhd): " << mi.hblkhd << '\n'
789  << "Max. total allocated space (usmblks): " << mi.usmblks << '\n'
790  << "Free bytes held in fastbins (fsmblks):" << mi.fsmblks << '\n'
791  << "Total allocated space (uordblks): " << mi.uordblks << '\n'
792  << "Total free space (fordblks): " << mi.fordblks << '\n'
793  << "Topmost releasable block (keepcost): " << mi.keepcost << '\n';
794 #else
795  str = QLatin1String( "mallinfo() not supported" );
796 #endif
797  return str;
798 }
799 
800 
801 AgentBase::AgentBase( const QString & id )
802  : d_ptr( new AgentBasePrivate( this ) )
803 {
804  sAgentBase = this;
805  d_ptr->mId = id;
806  d_ptr->init();
807 }
808 
809 AgentBase::AgentBase( AgentBasePrivate* d, const QString &id ) :
810  d_ptr( d )
811 {
812  sAgentBase = this;
813  d_ptr->mId = id;
814  d_ptr->init();
815 }
816 
817 AgentBase::~AgentBase()
818 {
819  delete d_ptr;
820 }
821 
822 QString AgentBase::parseArguments( int argc, char **argv )
823 {
824  QString identifier;
825  if ( argc < 3 ) {
826  kDebug() << "Not enough arguments passed...";
827  exit( 1 );
828  }
829 
830  for ( int i = 1; i < argc - 1; ++i ) {
831  if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) ) {
832  identifier = QLatin1String( argv[ i + 1 ] );
833  }
834  }
835 
836  if ( identifier.isEmpty() ) {
837  kDebug() << "Identifier argument missing";
838  exit( 1 );
839  }
840 
841  const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
842  // strip off full path and possible .exe suffix
843  const QByteArray catalog = fi.baseName().toLatin1();
844 
845  KCmdLineArgs::init( argc, argv, ServerManager::addNamespace( identifier ).toLatin1(), catalog, ki18n( "Akonadi Agent" ), KDEPIMLIBS_VERSION,
846  ki18n( "Akonadi Agent" ) );
847 
848  KCmdLineOptions options;
849  options.add( "identifier <argument>", ki18n( "Agent identifier" ) );
850  KCmdLineArgs::addCmdLineOptions( options );
851 
852  return identifier;
853 }
854 
855 // @endcond
856 
857 int AgentBase::init( AgentBase *r )
858 {
859  QApplication::setQuitOnLastWindowClosed( false );
860  KGlobal::locale()->insertCatalog( QLatin1String( "libakonadi" ) );
861  int rv = kapp->exec();
862  delete r;
863  return rv;
864 }
865 
866 int AgentBase::status() const
867 {
868  Q_D( const AgentBase );
869 
870  return d->mStatusCode;
871 }
872 
873 QString AgentBase::statusMessage() const
874 {
875  Q_D( const AgentBase );
876 
877  return d->mStatusMessage;
878 }
879 
880 int AgentBase::progress() const
881 {
882  Q_D( const AgentBase );
883 
884  return d->mProgress;
885 }
886 
887 QString AgentBase::progressMessage() const
888 {
889  Q_D( const AgentBase );
890 
891  return d->mProgressMessage;
892 }
893 
894 bool AgentBase::isOnline() const
895 {
896  Q_D( const AgentBase );
897 
898  return d->mOnline;
899 }
900 
901 void AgentBase::setNeedsNetwork( bool needsNetwork )
902 {
903  Q_D( AgentBase );
904  d->mNeedsNetwork = needsNetwork;
905 
906  if ( d->mNeedsNetwork ) {
907  connect( Solid::Networking::notifier()
908  , SIGNAL(statusChanged(Solid::Networking::Status))
909  , this, SLOT(slotNetworkStatusChange(Solid::Networking::Status))
910  , Qt::UniqueConnection );
911 
912  } else {
913  disconnect( Solid::Networking::notifier(), 0, 0, 0 );
914  setOnlineInternal( d->mDesiredOnlineState );
915  }
916 }
917 
918 void AgentBase::setOnline( bool state )
919 {
920  Q_D( AgentBase );
921  d->mDesiredOnlineState = state;
922  d->mSettings->setValue( QLatin1String( "Agent/DesiredOnlineState" ), state );
923  setOnlineInternal( state );
924 }
925 
926 void AgentBase::setTemporaryOffline(int makeOnlineInSeconds)
927 {
928  Q_D(AgentBase);
929 
930  // if not currently online, avoid bringing it online after the timeout
931  if (!d->mOnline) {
932  return;
933  }
934 
935  setOnlineInternal(false);
936 
937  if (!d->mTemporaryOfflineTimer) {
938  d->mTemporaryOfflineTimer = new QTimer(d);
939  d->mTemporaryOfflineTimer->setSingleShot(true);
940  connect(d->mTemporaryOfflineTimer, SIGNAL(timeout()), this, SLOT(slotTemporaryOfflineTimeout()));
941  }
942  d->mTemporaryOfflineTimer->setInterval(makeOnlineInSeconds * 1000);
943  d->mTemporaryOfflineTimer->start();
944 }
945 
946 void AgentBase::setOnlineInternal( bool state )
947 {
948  Q_D( AgentBase );
949  if (state && d->mNeedsNetwork) {
950  const Solid::Networking::Status stat = Solid::Networking::status();
951  if (stat != Solid::Networking::Unknown && stat != Solid::Networking::Connected) {
952  //Don't go online if the resource needs network but there is none
953  state = false;
954  }
955  }
956  d->mOnline = state;
957 
958  if (d->mTemporaryOfflineTimer) {
959  d->mTemporaryOfflineTimer->stop();
960  }
961 
962  const QString newMessage = d->defaultReadyMessage();
963  if ( d->mStatusMessage != newMessage && d->mStatusCode != AgentBase::Broken ) {
964  emit status( d->mStatusCode, newMessage );
965  }
966 
967  doSetOnline( state );
968  emit onlineChanged( state );
969 }
970 
971 void AgentBase::doSetOnline( bool online )
972 {
973  Q_UNUSED( online );
974 }
975 
976 void AgentBase::configure( WId windowId )
977 {
978  Q_UNUSED( windowId );
979  emit configurationDialogAccepted();
980 }
981 
982 #ifdef Q_OS_WIN //krazy:exclude=cpp
983 void AgentBase::configure( qlonglong windowId )
984 {
985  configure( reinterpret_cast<WId>( windowId ) );
986 }
987 #endif
988 
989 WId AgentBase::winIdForDialogs() const
990 {
991  const bool registered = DBusConnectionPool::threadConnection().interface()->isServiceRegistered( QLatin1String( "org.freedesktop.akonaditray" ) );
992  if ( !registered ) {
993  return 0;
994  }
995 
996  QDBusInterface dbus( QLatin1String( "org.freedesktop.akonaditray" ), QLatin1String( "/Actions" ),
997  QLatin1String( "org.freedesktop.Akonadi.Tray" ) );
998  const QDBusMessage reply = dbus.call( QLatin1String( "getWinId" ) );
999 
1000  if ( reply.type() == QDBusMessage::ErrorMessage ) {
1001  return 0;
1002  }
1003 
1004  const WId winid = (WId)reply.arguments().at( 0 ).toLongLong();
1005 
1006  return winid;
1007 }
1008 
1009 void AgentBase::quit()
1010 {
1011  Q_D( AgentBase );
1012  aboutToQuit();
1013 
1014  if ( d->mSettings ) {
1015  d->mChangeRecorder->setConfig( 0 );
1016  d->mSettings->sync();
1017  }
1018 
1019  KGlobal::deref();
1020 }
1021 
1022 void AgentBase::aboutToQuit()
1023 {
1024 }
1025 
1026 void AgentBase::cleanup()
1027 {
1028  Q_D( AgentBase );
1029  // prevent the monitor from picking up deletion signals for our own data if we are a resource
1030  // and thus avoid that we kill our own data as last act before our own death
1031  d->mChangeRecorder->blockSignals( true );
1032 
1033  aboutToQuit();
1034 
1035  const QString fileName = d->mSettings->fileName();
1036 
1037  /*
1038  * First destroy the settings object...
1039  */
1040  d->mChangeRecorder->setConfig( 0 );
1041  delete d->mSettings;
1042  d->mSettings = 0;
1043 
1044  /*
1045  * ... then remove the file from hd.
1046  */
1047  QFile::remove( fileName );
1048 
1049  /*
1050  * ... and remove the changes file from hd.
1051  */
1052  QFile::remove( fileName + QLatin1String( "_changes.dat" ) );
1053 
1054  /*
1055  * ... and also remove the agent configuration file if there is one.
1056  */
1057  QString configFile = KStandardDirs::locateLocal( "config", config()->name() );
1058  QFile::remove( configFile );
1059 
1060  KGlobal::deref();
1061 }
1062 
1063 void AgentBase::registerObserver( Observer *observer )
1064 {
1065  // TODO in theory we should re-connect change recorder signals here that we disconnected previously
1066  d_ptr->mObserver = observer;
1067 
1068  const bool hasObserverV3 = (dynamic_cast<AgentBase::ObserverV3*>(d_ptr->mObserver) != 0);
1069  const bool hasObserverV4 = (dynamic_cast<AgentBase::ObserverV4*>(d_ptr->mObserver) != 0);
1070 
1071  disconnect( d_ptr->mChangeRecorder, SIGNAL(tagAdded(Akonadi::Tag)),
1072  d_ptr, SLOT(tagAdded(Akonadi::Tag)) );
1073  disconnect( d_ptr->mChangeRecorder, SIGNAL(tagChanged(Akonadi::Tag)),
1074  d_ptr, SLOT(tagChanged(Akonadi::Tag)) );
1075  disconnect( d_ptr->mChangeRecorder, SIGNAL(tagRemoved(Akonadi::Tag)),
1076  d_ptr, SLOT(tagRemoved(Akonadi::Tag)) );
1077  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)),
1078  d_ptr, SLOT(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)) );
1079  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)),
1080  d_ptr, SLOT(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)) );
1081  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)),
1082  d_ptr, SLOT(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)) );
1083  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemsRemoved(Akonadi::Item::List)),
1084  d_ptr, SLOT(itemsRemoved(Akonadi::Item::List)) );
1085  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemsLinked(Akonadi::Item::List,Akonadi::Collection)),
1086  d_ptr, SLOT(itemsLinked(Akonadi::Item::List,Akonadi::Collection)) );
1087  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)),
1088  d_ptr, SLOT(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)) );
1089  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
1090  d_ptr, SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)) );
1091  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemRemoved(Akonadi::Item)),
1092  d_ptr, SLOT(itemRemoved(Akonadi::Item)) );
1093  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
1094  d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
1095  disconnect( d_ptr->mChangeRecorder, SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
1096  d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
1097 
1098  if ( hasObserverV4 ) {
1099  connect( d_ptr->mChangeRecorder, SIGNAL(tagAdded(Akonadi::Tag)),
1100  d_ptr, SLOT(tagAdded(Akonadi::Tag)) );
1101  connect( d_ptr->mChangeRecorder, SIGNAL(tagChanged(Akonadi::Tag)),
1102  d_ptr, SLOT(tagChanged(Akonadi::Tag)) );
1103  connect( d_ptr->mChangeRecorder, SIGNAL(tagRemoved(Akonadi::Tag)),
1104  d_ptr, SLOT(tagRemoved(Akonadi::Tag)) );
1105  connect( d_ptr->mChangeRecorder, SIGNAL(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)),
1106  d_ptr, SLOT(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)) );
1107  }
1108 
1109  if ( hasObserverV3 ) {
1110  connect( d_ptr->mChangeRecorder, SIGNAL(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)),
1111  d_ptr, SLOT(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)) );
1112  connect( d_ptr->mChangeRecorder, SIGNAL(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)),
1113  d_ptr, SLOT(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)) );
1114  connect( d_ptr->mChangeRecorder, SIGNAL(itemsRemoved(Akonadi::Item::List)),
1115  d_ptr, SLOT(itemsRemoved(Akonadi::Item::List)) );
1116  connect( d_ptr->mChangeRecorder, SIGNAL(itemsLinked(Akonadi::Item::List,Akonadi::Collection)),
1117  d_ptr, SLOT(itemsLinked(Akonadi::Item::List,Akonadi::Collection)) );
1118  connect( d_ptr->mChangeRecorder, SIGNAL(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)),
1119  d_ptr, SLOT(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)) );
1120  } else {
1121  // V2 - don't connect these if we have V3
1122  connect( d_ptr->mChangeRecorder, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
1123  d_ptr, SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)) );
1124  connect( d_ptr->mChangeRecorder, SIGNAL(itemRemoved(Akonadi::Item)),
1125  d_ptr, SLOT(itemRemoved(Akonadi::Item)) );
1126  connect( d_ptr->mChangeRecorder, SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
1127  d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
1128  connect( d_ptr->mChangeRecorder, SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
1129  d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
1130  }
1131 }
1132 
1133 QString AgentBase::identifier() const
1134 {
1135  return d_ptr->mId;
1136 }
1137 
1138 void AgentBase::setAgentName( const QString &name )
1139 {
1140  Q_D( AgentBase );
1141  if ( name == d->mName ) {
1142  return;
1143  }
1144 
1145  // TODO: rename collection
1146  d->mName = name;
1147 
1148  if ( d->mName.isEmpty() || d->mName == d->mId ) {
1149  d->mSettings->remove( QLatin1String( "Resource/Name" ) );
1150  d->mSettings->remove( QLatin1String( "Agent/Name" ) );
1151  } else
1152  d->mSettings->setValue( QLatin1String( "Agent/Name" ), d->mName );
1153 
1154  d->mSettings->sync();
1155 
1156  d->setProgramName();
1157 
1158  emit agentNameChanged( d->mName );
1159 }
1160 
1161 QString AgentBase::agentName() const
1162 {
1163  Q_D( const AgentBase );
1164  if ( d->mName.isEmpty() ) {
1165  return d->mId;
1166  } else {
1167  return d->mName;
1168  }
1169 }
1170 
1171 void AgentBase::changeProcessed()
1172 {
1173  Q_D( AgentBase );
1174  d->changeProcessed();
1175 }
1176 
1177 ChangeRecorder * AgentBase::changeRecorder() const
1178 {
1179  return d_ptr->mChangeRecorder;
1180 }
1181 
1182 KSharedConfigPtr AgentBase::config()
1183 {
1184  if ( QCoreApplication::instance()->thread() == QThread::currentThread() ) {
1185  return KGlobal::config();
1186  } else {
1187  return componentData().config();
1188  }
1189 }
1190 
1191 void AgentBase::abort()
1192 {
1193  emit abortRequested();
1194 }
1195 
1196 void AgentBase::reconfigure()
1197 {
1198  emit reloadConfiguration();
1199 }
1200 
1201 extern QThreadStorage<KComponentData*> s_agentComponentDatas;
1202 
1203 KComponentData AgentBase::componentData()
1204 {
1205  if ( QThread::currentThread() == QCoreApplication::instance()->thread() ) {
1206  if ( s_agentComponentDatas.hasLocalData() ) {
1207  return *( s_agentComponentDatas.localData() );
1208  } else {
1209  return KGlobal::mainComponent();
1210  }
1211  }
1212 
1213  Q_ASSERT( s_agentComponentDatas.hasLocalData() );
1214  return *( s_agentComponentDatas.localData() );
1215 }
1216 
1217 #include "moc_agentbase.cpp"
1218 #include "moc_agentbase_p.cpp"
Akonadi::AgentBase::winIdForDialogs
WId winIdForDialogs() const
This method returns the windows id, which should be used for dialogs.
Akonadi::AgentBase::ObserverV4::itemsTagsChanged
virtual void itemsTagsChanged(const Akonadi::Item::List &items, const QSet< Akonadi::Tag > &addedTags, const QSet< Akonadi::Tag > &removedTags)
Reimplement to handle items tagging.
Definition: agentbase.cpp:276
Akonadi::AgentBase::ObserverV3::itemsUnlinked
virtual void itemsUnlinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection)
Reimplement to handle batch notifications about items unlinking.
Definition: agentbase.cpp:227
Akonadi::AgentBase::ObserverV3::itemsMoved
virtual void itemsMoved(const Akonadi::Item::List &items, const Akonadi::Collection &sourceCollection, const Akonadi::Collection &destinationCollection)
Reimplement to handle batch notification about items move.
Definition: agentbase.cpp:188
Akonadi::AgentBase::percent
void percent(int progress)
This signal should be emitted whenever the progress of an action in the agent (e.g.
Akonadi::AgentBase::abortRequested
void abortRequested()
Emitted when another application has remotely asked the agent to abort its current operation...
Akonadi::AgentBase::NotConfigured
The agent is lacking required configuration.
Definition: agentbase.h:414
Akonadi::AgentBase::ObserverV4::tagAdded
virtual void tagAdded(const Akonadi::Tag &tag)
Reimplement to handle tags additions.
Definition: agentbase.cpp:240
Akonadi::AgentBase::AgentBase
AgentBase(const QString &id)
Creates an agent base.
Akonadi::AgentBase::ObserverV4::tagRemoved
virtual void tagRemoved(const Akonadi::Tag &tag)
Reimplement to handle tags removal.
Definition: agentbase.cpp:264
Akonadi::AgentBase::changeRecorder
ChangeRecorder * changeRecorder() const
Returns the Akonadi::ChangeRecorder object used for monitoring.
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
Akonadi::AgentInstance::type
AgentType type() const
Returns the agent type of this instance.
Definition: agentinstance.cpp:50
Akonadi::AgentBase::ObserverV2::itemMoved
virtual void itemMoved(const Akonadi::Item &item, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination)
Reimplement to handle item moves.
Definition: agentbase.cpp:124
Akonadi::AgentBase::setNeedsNetwork
void setNeedsNetwork(bool needsNetwork)
Sets whether the agent needs network or not.
Akonadi::AgentType::name
QString name() const
Returns the i18n'ed name of the agent type.
Definition: agenttype.cpp:51
Akonadi::AgentBase::setAgentName
void setAgentName(const QString &name)
This method is used to set the name of the agent.
Akonadi::AgentBase::ObserverV2::collectionMoved
virtual void collectionMoved(const Akonadi::Collection &collection, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination)
Reimplement to handle collection moves.
Definition: agentbase.cpp:158
Akonadi::AgentBase::agentNameChanged
void agentNameChanged(const QString &name)
This signal is emitted whenever the name of the agent has changed.
Akonadi::AgentBase::reloadConfiguration
void reloadConfiguration()
Emitted if another application has changed the agent's configuration remotely and called AgentInstanc...
Akonadi::SessionPrivate::createDefaultSession
static void createDefaultSession(const QByteArray &sessionId)
Creates a new default session for this thread with the given sessionId.
Definition: session.cpp:464
Akonadi::ServerManager::serviceName
static QString serviceName(ServiceType serviceType)
Returns the namespaced D-Bus service name for serviceType.
Definition: servermanager.cpp:305
Akonadi::AgentBase::componentData
static KComponentData componentData()
Returns the component data object for this agent instance.
Akonadi::AgentBase::configurationDialogAccepted
void configurationDialogAccepted()
This signal is emitted whenever the user has accepted the configuration dialog.
Akonadi::AgentBase::ObserverV2::collectionChanged
virtual void collectionChanged(const Akonadi::Collection &collection, const QSet< QByteArray > &changedAttributes)
Reimplement to handle changes to existing collections.
Definition: agentbase.cpp:168
Akonadi::Session::defaultSession
static Session * defaultSession()
Returns the default session for this thread.
Definition: session.cpp:479
Akonadi::AgentBase::~AgentBase
~AgentBase()
Destroys the agent base.
Akonadi::AgentBasePrivate
Definition: agentbase_p.h:39
Akonadi::AgentBase
The base class for all Akonadi agents and resources.
Definition: agentbase.h:80
Akonadi::AgentBase::Observer::itemChanged
virtual void itemChanged(const Akonadi::Item &item, const QSet< QByteArray > &partIdentifiers)
Reimplement to handle changes to existing items.
Definition: agentbase.cpp:82
Akonadi::AgentBase::error
void error(const QString &message)
This signal shall be used to report errors.
Akonadi::AgentBase::aboutToQuit
virtual void aboutToQuit()
This method is called whenever the agent application is about to quit.
Akonadi::AgentBase::Observer::~Observer
virtual ~Observer()
Destroys the observer instance.
Definition: agentbase.cpp:69
Akonadi::AgentBase::status
virtual int status() const
This method returns the current status code of the agent.
Akonadi::AgentBase::setOnline
void setOnline(bool state)
Sets whether the agent shall be online or not.
Akonadi::AgentBase::config
KSharedConfigPtr config()
Returns the config object for this Agent.
Akonadi::AgentBase::Observer::itemAdded
virtual void itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection)
Reimplement to handle adding of new items.
Definition: agentbase.cpp:73
Akonadi::AgentBase::ObserverV2::itemUnlinked
virtual void itemUnlinked(const Akonadi::Item &item, const Akonadi::Collection &collection)
Reimplement to handle item unlinking.
Definition: agentbase.cpp:146
Akonadi::AgentManager::instance
AgentInstance instance(const QString &identifier) const
Returns the agent instance with the given identifier or an invalid agent instance if the identifier d...
Definition: agentmanager.cpp:404
Akonadi::AgentBase::ObserverV3::itemsFlagsChanged
virtual void itemsFlagsChanged(const Akonadi::Item::List &items, const QSet< QByteArray > &addedFlags, const QSet< QByteArray > &removedFlags)
Reimplement to handle changes in flags of existing items.
Definition: agentbase.cpp:174
Akonadi::AgentBase::doSetOnline
virtual void doSetOnline(bool online)
This method is called whenever the online status has changed.
Akonadi::AgentBase::configure
virtual void configure(WId windowId)
This method is called whenever the agent shall show its configuration dialog to the user...
Akonadi::AgentBase::ObserverV2
BC extension of Observer with support for monitoring item and collection moves.
Definition: agentbase.h:244
Akonadi::AgentBase::Observer::itemRemoved
virtual void itemRemoved(const Akonadi::Item &item)
Reimplement to handle deletion of items.
Definition: agentbase.cpp:91
Akonadi::AgentBase::cleanup
virtual void cleanup()
This method is called when the agent is removed from the system, so it can do some cleanup stuff...
Akonadi::ServerManager::agentServiceName
static QString agentServiceName(ServiceAgentType agentType, const QString &identifier)
Returns the namespaced D-Bus service name for an agent of type agentType with agent identifier identi...
Definition: servermanager.cpp:317
Akonadi::AgentBase::ObserverV3
BC extension of ObserverV2 with support for batch operations.
Definition: agentbase.h:309
Akonadi::AgentBase::statusMessage
virtual QString statusMessage() const
This method returns an i18n'ed description of the current status code.
Akonadi::AgentBase::changeProcessed
void changeProcessed()
Marks the current change as processes and replays the next change if change recording is enabled (noo...
Akonadi::AgentBase::ObserverV4::tagChanged
virtual void tagChanged(const Akonadi::Tag &tag)
Reimplement to handle tags changes.
Definition: agentbase.cpp:252
Akonadi::AgentBase::identifier
QString identifier() const
Returns the instance identifier of this agent.
Akonadi::AgentBase::Observer::collectionRemoved
virtual void collectionRemoved(const Akonadi::Collection &collection)
Reimplement to handle deletion of collections.
Definition: agentbase.cpp:116
Akonadi::ChangeRecorder::setConfig
void setConfig(QSettings *settings)
Sets the QSettings object used for persistent recorded changes.
Definition: changerecorder.cpp:42
Akonadi::AgentBase::ObserverV3::itemsRemoved
virtual void itemsRemoved(const Akonadi::Item::List &items)
Reimplement to handle batch notification about items deletion.
Definition: agentbase.cpp:202
Akonadi::AgentBase::Broken
The agent encountered an error state.
Definition: agentbase.h:413
Akonadi::AgentBase::progress
virtual int progress() const
This method returns the current progress of the agent in percentage.
Akonadi::AgentBase::Observer::Observer
Observer()
Creates an observer instance.
Definition: agentbase.cpp:65
Akonadi::AgentBase::Observer::collectionChanged
virtual void collectionChanged(const Akonadi::Collection &collection)
Reimplement to handle changes to existing collections.
Definition: agentbase.cpp:108
Akonadi::AgentBase::isOnline
bool isOnline() const
Returns whether the agent is currently online.
Akonadi::AgentBase::ObserverV4
Observer that adds support for item tagging.
Definition: agentbase.h:368
Akonadi::Tag
An Akonadi Tag.
Definition: tag.h:44
Akonadi::AgentBase::ObserverV3::itemsLinked
virtual void itemsLinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection)
Reimplement to handle batch notifications about items linking.
Definition: agentbase.cpp:214
Akonadi::AgentBase::ObserverV2::itemLinked
virtual void itemLinked(const Akonadi::Item &item, const Akonadi::Collection &collection)
Reimplement to handle item linking.
Definition: agentbase.cpp:134
Akonadi::AgentBase::registerObserver
void registerObserver(Observer *observer)
Registers the given observer for reacting on monitored or recorded changes.
Akonadi::AgentManager::self
static AgentManager * self()
Returns the global instance of the agent manager.
Definition: agentmanager.cpp:380
Akonadi::AgentBase::init
static int init(int argc, char **argv)
Use this method in the main function of your agent application to initialize your agent subclass...
Definition: agentbase.h:442
Akonadi::Collection::resource
QString resource() const
Returns the identifier of the resource owning the collection.
Definition: collection.cpp:207
Akonadi::AgentBase::onlineChanged
void onlineChanged(bool online)
Emitted when the online state changed.
Akonadi::AgentBase::agentName
QString agentName() const
Returns the name of the agent.
Akonadi::AgentBase::Running
The agent is working on something.
Definition: agentbase.h:412
Akonadi::AgentBase::warning
void warning(const QString &message)
This signal shall be used to report warnings.
Akonadi::ServerManager::addNamespace
static QString addNamespace(const QString &string)
Adds the multi-instance namespace to string if required (with '_' as separator).
Definition: servermanager.cpp:331
Akonadi::AgentBase::Observer::collectionAdded
virtual void collectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &parent)
Reimplement to handle adding of new collections.
Definition: agentbase.cpp:99
Akonadi::AgentBase::progressMessage
virtual QString progressMessage() const
This method returns an i18n'ed description of the current progress.
Akonadi::AgentBase::Idle
The agent does currently nothing.
Definition: agentbase.h:411
Akonadi::ChangeRecorder
Records and replays change notification.
Definition: changerecorder.h:47
Akonadi::AgentBase::setTemporaryOffline
void setTemporaryOffline(int makeOnlineInSeconds=300)
Sets the agent offline but will make it online again after a given time.
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Mon Jul 21 2014 08:03:49 by doxygen 1.8.6 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.13.3 API Reference

Skip menu "kdepimlibs-4.13.3 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