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

akonadi

  • akonadi
resourcebase.cpp
1 /*
2  Copyright (c) 2006 Till Adam <adam@kde.org>
3  Copyright (c) 2007 Volker Krause <vkrause@kde.org>
4 
5  This library is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or (at your
8  option) any later version.
9 
10  This library is distributed in the hope that it will be useful, but WITHOUT
11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13  License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  02110-1301, USA.
19 */
20 
21 #include "resourcebase.h"
22 #include "agentbase_p.h"
23 
24 #include "resourceadaptor.h"
25 #include "collectiondeletejob.h"
26 #include "collectionsync_p.h"
27 #include "dbusconnectionpool.h"
28 #include "itemsync.h"
29 #include "kdepimlibs-version.h"
30 #include "resourcescheduler_p.h"
31 #include "tracerinterface.h"
32 #include "xdgbasedirs_p.h"
33 
34 #include "changerecorder.h"
35 #include "collectionfetchjob.h"
36 #include "collectionfetchscope.h"
37 #include "collectionmodifyjob.h"
38 #include "invalidatecachejob_p.h"
39 #include "itemfetchjob.h"
40 #include "itemfetchscope.h"
41 #include "itemmodifyjob.h"
42 #include "itemmodifyjob_p.h"
43 #include "session.h"
44 #include "resourceselectjob_p.h"
45 #include "monitor_p.h"
46 #include "servermanager_p.h"
47 #include "recursivemover_p.h"
48 
49 #include <kaboutdata.h>
50 #include <kcmdlineargs.h>
51 #include <kdebug.h>
52 #include <klocalizedstring.h>
53 #include <kglobal.h>
54 
55 #include <QtCore/QDebug>
56 #include <QtCore/QDir>
57 #include <QtCore/QHash>
58 #include <QtCore/QSettings>
59 #include <QtCore/QTimer>
60 #include <QApplication>
61 #include <QtDBus/QtDBus>
62 
63 #if defined __GLIBC__
64 # include <malloc.h> // for dumping memory information
65 #endif
66 
67 using namespace Akonadi;
68 
69 class Akonadi::ResourceBasePrivate : public AgentBasePrivate
70 {
71  Q_OBJECT
72  Q_CLASSINFO( "D-Bus Interface", "org.kde.dfaure" )
73 
74  public:
75  ResourceBasePrivate( ResourceBase *parent )
76  : AgentBasePrivate( parent ),
77  scheduler( 0 ),
78  mItemSyncer( 0 ),
79  mItemSyncFetchScope( 0 ),
80  mItemTransactionMode( ItemSync::SingleTransaction ),
81  mCollectionSyncer( 0 ),
82  mHierarchicalRid( false ),
83  mUnemittedProgress( 0 ),
84  mAutomaticProgressReporting( true )
85  {
86  Internal::setClientType( Internal::Resource );
87  mStatusMessage = defaultReadyMessage();
88  mProgressEmissionCompressor.setInterval( 1000 );
89  mProgressEmissionCompressor.setSingleShot( true );
90  }
91 
92  ~ResourceBasePrivate()
93  {
94  delete mItemSyncFetchScope;
95  }
96 
97  Q_DECLARE_PUBLIC( ResourceBase )
98 
99  void delayedInit()
100  {
101  const QString serviceId = ServerManager::agentServiceName( ServerManager::Resource, mId );
102  if ( !DBusConnectionPool::threadConnection().registerService( serviceId ) ) {
103  QString reason = DBusConnectionPool::threadConnection().lastError().message();
104  if ( reason.isEmpty() ) {
105  reason = QString::fromLatin1( "this service is probably running already." );
106  }
107  kError() << "Unable to register service" << serviceId << "at D-Bus:" << reason;
108 
109  if ( QThread::currentThread() == QCoreApplication::instance()->thread() )
110  QCoreApplication::instance()->exit(1);
111 
112  } else {
113  AgentBasePrivate::delayedInit();
114  }
115  }
116 
117  virtual void changeProcessed()
118  {
119  if ( m_recursiveMover ) {
120  m_recursiveMover->changeProcessed();
121  QTimer::singleShot( 0, m_recursiveMover, SLOT(replayNext()) );
122  return;
123  }
124 
125  mChangeRecorder->changeProcessed();
126  if ( !mChangeRecorder->isEmpty() )
127  scheduler->scheduleChangeReplay();
128  scheduler->taskDone();
129  }
130 
131  void slotAbortRequested();
132 
133  void slotDeliveryDone( KJob* job );
134  void slotCollectionSyncDone( KJob *job );
135  void slotLocalListDone( KJob *job );
136  void slotSynchronizeCollection( const Collection &col );
137  void slotCollectionListDone( KJob *job );
138  void slotSynchronizeCollectionAttributes( const Collection &col );
139  void slotCollectionListForAttributesDone( KJob *job );
140  void slotCollectionAttributesSyncDone( KJob *job );
141 
142  void slotItemSyncDone( KJob *job );
143 
144  void slotPercent( KJob* job, unsigned long percent );
145  void slotDelayedEmitProgress();
146  void slotDeleteResourceCollection();
147  void slotDeleteResourceCollectionDone( KJob *job );
148  void slotCollectionDeletionDone( KJob *job );
149 
150  void slotInvalidateCache( const Akonadi::Collection &collection );
151 
152  void slotPrepareItemRetrieval( const Akonadi::Item &item );
153  void slotPrepareItemRetrievalResult( KJob* job );
154 
155  void changeCommittedResult( KJob* job );
156 
157  void slotRecursiveMoveReplay( RecursiveMover *mover );
158  void slotRecursiveMoveReplayResult( KJob *job );
159 
160  void slotSessionReconnected()
161  {
162  Q_Q( ResourceBase );
163 
164  new ResourceSelectJob( q->identifier() );
165  }
166 
167  void createItemSyncInstanceIfMissing()
168  {
169  Q_Q( ResourceBase );
170  Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::SyncCollection,
171  "createItemSyncInstance", "Calling items retrieval methods although no item retrieval is in progress" );
172  if ( !mItemSyncer ) {
173  mItemSyncer = new ItemSync( q->currentCollection() );
174  mItemSyncer->setTransactionMode( mItemTransactionMode );
175  if ( mItemSyncFetchScope )
176  mItemSyncer->setFetchScope( *mItemSyncFetchScope );
177  mItemSyncer->setProperty( "collection", QVariant::fromValue( q->currentCollection() ) );
178  connect( mItemSyncer, SIGNAL(percent(KJob*,ulong)), q, SLOT(slotPercent(KJob*,ulong)) );
179  connect( mItemSyncer, SIGNAL(result(KJob*)), q, SLOT(slotItemSyncDone(KJob*)) );
180  }
181  Q_ASSERT( mItemSyncer );
182  }
183 
184  public Q_SLOTS:
185  // Dump the contents of the current ChangeReplay
186  Q_SCRIPTABLE QString dumpNotificationListToString() const
187  {
188  return mChangeRecorder->dumpNotificationListToString();
189  }
190 
191  // Dump the state of the scheduler
192  Q_SCRIPTABLE QString dumpToString() const
193  {
194  Q_Q( const ResourceBase );
195  QString retVal;
196  QMetaObject::invokeMethod( const_cast<ResourceBase *>(q), "dumpResourceToString", Qt::DirectConnection, Q_RETURN_ARG(QString, retVal) );
197  return scheduler->dumpToString() + QLatin1Char('\n') + retVal;
198  }
199 
200  Q_SCRIPTABLE void dump()
201  {
202  scheduler->dump();
203  }
204 
205  Q_SCRIPTABLE void clear()
206  {
207  scheduler->clear();
208  }
209 
210  Q_SCRIPTABLE void dumpMemoryInfo() const
211  {
212  // Send it to stdout, so we can debug user problems.
213  // since you have to explicitely call this
214  // it won't flood users with release builds.
215  QTextStream stream( stdout );
216  stream << dumpMemoryInfoToString();
217  }
218 
219  Q_SCRIPTABLE QString dumpMemoryInfoToString() const
220  {
221  // man mallinfo for more info
222  QString str;
223 #if defined __GLIBC__
224  struct mallinfo mi;
225  mi = mallinfo();
226  QTextStream stream( &str );
227  stream << "Total non-mmapped bytes (arena): " << mi.arena << '\n'
228  << "# of free chunks (ordblks): " << mi.ordblks << '\n'
229  << "# of free fastbin blocks (smblks>: " << mi.smblks << '\n'
230  << "# of mapped regions (hblks): " << mi.hblks << '\n'
231  << "Bytes in mapped regions (hblkhd): " << mi.hblkhd << '\n'
232  << "Max. total allocated space (usmblks): " << mi.usmblks << '\n'
233  << "Free bytes held in fastbins (fsmblks):" << mi.fsmblks << '\n'
234  << "Total allocated space (uordblks): " << mi.uordblks << '\n'
235  << "Total free space (fordblks): " << mi.fordblks << '\n'
236  << "Topmost releasable block (keepcost): " << mi.keepcost << '\n';
237 #else
238  str = QLatin1String( "mallinfo() not supported" );
239 #endif
240  return str;
241  }
242 
243  protected Q_SLOTS:
244  // reimplementations from AgentbBasePrivate, containing sanity checks that only apply to resources
245  // such as making sure that RIDs are present as well as translations of cross-resource moves
246  // TODO: we could possibly add recovery code for no-RID notifications by re-enquing those to the change recorder
247  // as the corresponding Add notifications, although that contains a risk of endless fail/retry loops
248 
249  void itemAdded(const Akonadi::Item& item, const Akonadi::Collection& collection)
250  {
251  if ( collection.remoteId().isEmpty() ) {
252  changeProcessed();
253  return;
254  }
255  AgentBasePrivate::itemAdded( item, collection );
256  }
257 
258  void itemChanged(const Akonadi::Item& item, const QSet< QByteArray >& partIdentifiers)
259  {
260  if ( item.remoteId().isEmpty() ) {
261  changeProcessed();
262  return;
263  }
264  AgentBasePrivate::itemChanged( item, partIdentifiers );
265  }
266 
267  void itemsFlagsChanged(const Item::List& items, const QSet< QByteArray >& addedFlags,
268  const QSet< QByteArray >& removedFlags)
269  {
270  if (addedFlags.isEmpty() && removedFlags.isEmpty() ) {
271  changeProcessed();
272  return;
273  }
274 
275  Item::List validItems;
276  foreach ( const Akonadi::Item &item, items ) {
277  if ( !item.remoteId().isEmpty() ) {
278  validItems << item;
279  }
280  }
281  if ( validItems.isEmpty() ) {
282  changeProcessed();
283  return;
284  }
285 
286  AgentBasePrivate::itemsFlagsChanged( validItems, addedFlags, removedFlags );
287  }
288 
289  // TODO move the move translation code from AgentBasePrivate here, it's wrong for agents
290  void itemMoved(const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &destination)
291  {
292  if ( item.remoteId().isEmpty() || destination.remoteId().isEmpty() || destination == source ) {
293  changeProcessed();
294  return;
295  }
296  AgentBasePrivate::itemMoved( item, source, destination );
297  }
298 
299  void itemsMoved(const Item::List& items, const Collection& source, const Collection& destination)
300  {
301  if ( destination.remoteId().isEmpty() || destination == source ) {
302  changeProcessed();
303  return;
304  }
305 
306  Item::List validItems;
307  foreach ( const Akonadi::Item &item, items ) {
308  if ( !item.remoteId().isEmpty() ) {
309  validItems << item;
310  }
311  }
312  if ( validItems.isEmpty() ) {
313  changeProcessed();
314  return;
315  }
316 
317  AgentBasePrivate::itemsMoved( validItems, source, destination );
318  }
319 
320  void itemRemoved(const Akonadi::Item& item)
321  {
322  if ( item.remoteId().isEmpty() ) {
323  changeProcessed();
324  return;
325  }
326  AgentBasePrivate::itemRemoved( item );
327  }
328 
329  void itemsRemoved(const Item::List& items)
330  {
331  Item::List validItems;
332  foreach ( const Akonadi::Item &item, items ) {
333  if ( !item.remoteId().isEmpty() ) {
334  validItems << item;
335  }
336  }
337  if ( validItems.isEmpty() ) {
338  changeProcessed();
339  return;
340  }
341 
342  AgentBasePrivate::itemsRemoved( validItems );
343  }
344 
345  void collectionAdded(const Akonadi::Collection& collection, const Akonadi::Collection& parent)
346  {
347  if ( parent.remoteId().isEmpty() ) {
348  changeProcessed();
349  return;
350  }
351  AgentBasePrivate::collectionAdded( collection, parent );
352  }
353 
354  void collectionChanged(const Akonadi::Collection& collection)
355  {
356  if ( collection.remoteId().isEmpty() ) {
357  changeProcessed();
358  return;
359  }
360  AgentBasePrivate::collectionChanged( collection );
361  }
362 
363  void collectionChanged(const Akonadi::Collection& collection, const QSet< QByteArray >& partIdentifiers)
364  {
365  if ( collection.remoteId().isEmpty() ) {
366  changeProcessed();
367  return;
368  }
369  AgentBasePrivate::collectionChanged( collection, partIdentifiers );
370  }
371 
372  void collectionMoved(const Akonadi::Collection& collection, const Akonadi::Collection& source, const Akonadi::Collection& destination)
373  {
374  // unknown destination or source == destination means we can't do/don't have to do anything
375  if ( destination.remoteId().isEmpty() || source == destination ) {
376  changeProcessed();
377  return;
378  }
379 
380  // inter-resource moves, requires we know which resources the source and destination are in though
381  if ( !source.resource().isEmpty() && !destination.resource().isEmpty() && source.resource() != destination.resource() ) {
382  if ( source.resource() == q_ptr->identifier() ) { // moved away from us
383  AgentBasePrivate::collectionRemoved( collection );
384  } else if ( destination.resource() == q_ptr->identifier() ) { // moved to us
385  scheduler->taskDone(); // stop change replay for now
386  RecursiveMover *mover = new RecursiveMover( this );
387  mover->setCollection( collection, destination );
388  scheduler->scheduleMoveReplay( collection, mover );
389  }
390  return;
391  }
392 
393  // intra-resource move, requires the moved collection to have a valid id though
394  if ( collection.remoteId().isEmpty() ) {
395  changeProcessed();
396  return;
397  }
398 
399  // intra-resource move, ie. something we can handle internally
400  AgentBasePrivate::collectionMoved( collection, source, destination );
401  }
402 
403  void collectionRemoved(const Akonadi::Collection& collection)
404  {
405  if ( collection.remoteId().isEmpty() ) {
406  changeProcessed();
407  return;
408  }
409  AgentBasePrivate::collectionRemoved( collection );
410  }
411 
412  public:
413  // synchronize states
414  Collection currentCollection;
415 
416  ResourceScheduler *scheduler;
417  ItemSync *mItemSyncer;
418  ItemFetchScope *mItemSyncFetchScope;
419  ItemSync::TransactionMode mItemTransactionMode;
420  CollectionSync *mCollectionSyncer;
421  bool mHierarchicalRid;
422  QTimer mProgressEmissionCompressor;
423  int mUnemittedProgress;
424  QMap<Akonadi::Collection::Id, QVariantMap> mUnemittedAdvancedStatus;
425  bool mAutomaticProgressReporting;
426  QPointer<RecursiveMover> m_recursiveMover;
427 };
428 
429 ResourceBase::ResourceBase( const QString & id )
430  : AgentBase( new ResourceBasePrivate( this ), id )
431 {
432  Q_D( ResourceBase );
433 
434  new Akonadi__ResourceAdaptor( this );
435 
436  d->scheduler = new ResourceScheduler( this );
437 
438  d->mChangeRecorder->setChangeRecordingEnabled( true );
439  d->mChangeRecorder->setCollectionMoveTranslationEnabled( false ); // we deal with this ourselves
440  connect( d->mChangeRecorder, SIGNAL(changesAdded()),
441  d->scheduler, SLOT(scheduleChangeReplay()) );
442 
443  d->mChangeRecorder->setResourceMonitored( d->mId.toLatin1() );
444  d->mChangeRecorder->fetchCollection( true );
445 
446  connect( d->scheduler, SIGNAL(executeFullSync()),
447  SLOT(retrieveCollections()) );
448  connect( d->scheduler, SIGNAL(executeCollectionTreeSync()),
449  SLOT(retrieveCollections()) );
450  connect( d->scheduler, SIGNAL(executeCollectionSync(Akonadi::Collection)),
451  SLOT(slotSynchronizeCollection(Akonadi::Collection)) );
452  connect( d->scheduler, SIGNAL(executeCollectionAttributesSync(Akonadi::Collection)),
453  SLOT(slotSynchronizeCollectionAttributes(Akonadi::Collection)) );
454  connect( d->scheduler, SIGNAL(executeItemFetch(Akonadi::Item,QSet<QByteArray>)),
455  SLOT(slotPrepareItemRetrieval(Akonadi::Item)) );
456  connect( d->scheduler, SIGNAL(executeResourceCollectionDeletion()),
457  SLOT(slotDeleteResourceCollection()) );
458  connect ( d->scheduler, SIGNAL(executeCacheInvalidation(Akonadi::Collection)),
459  SLOT(slotInvalidateCache(Akonadi::Collection)) );
460  connect( d->scheduler, SIGNAL(status(int,QString)),
461  SIGNAL(status(int,QString)) );
462  connect( d->scheduler, SIGNAL(executeChangeReplay()),
463  d->mChangeRecorder, SLOT(replayNext()) );
464  connect( d->scheduler, SIGNAL(executeRecursiveMoveReplay(RecursiveMover*)),
465  SLOT(slotRecursiveMoveReplay(RecursiveMover*)) );
466  connect( d->scheduler, SIGNAL(fullSyncComplete()), SIGNAL(synchronized()) );
467  connect( d->scheduler, SIGNAL(collectionTreeSyncComplete()), SIGNAL(collectionTreeSynchronized()) );
468  connect( d->mChangeRecorder, SIGNAL(nothingToReplay()), d->scheduler, SLOT(taskDone()) );
469  connect( d->mChangeRecorder, SIGNAL(collectionRemoved(Akonadi::Collection)),
470  d->scheduler, SLOT(collectionRemoved(Akonadi::Collection)) );
471  connect( this, SIGNAL(abortRequested()), this, SLOT(slotAbortRequested()) );
472  connect( this, SIGNAL(synchronized()), d->scheduler, SLOT(taskDone()) );
473  connect( this, SIGNAL(collectionTreeSynchronized()), d->scheduler, SLOT(taskDone()) );
474  connect( this, SIGNAL(agentNameChanged(QString)),
475  this, SIGNAL(nameChanged(QString)) );
476 
477  connect( &d->mProgressEmissionCompressor, SIGNAL(timeout()),
478  this, SLOT(slotDelayedEmitProgress()) );
479 
480  d->scheduler->setOnline( d->mOnline );
481  if ( !d->mChangeRecorder->isEmpty() )
482  d->scheduler->scheduleChangeReplay();
483 
484  DBusConnectionPool::threadConnection().registerObject( QLatin1String( "/Debug" ), d, QDBusConnection::ExportScriptableSlots );
485 
486  new ResourceSelectJob( identifier() );
487 
488  connect( d->mChangeRecorder->session(), SIGNAL(reconnected()), SLOT(slotSessionReconnected()) );
489 }
490 
491 ResourceBase::~ResourceBase()
492 {
493 }
494 
495 void ResourceBase::synchronize()
496 {
497  d_func()->scheduler->scheduleFullSync();
498 }
499 
500 void ResourceBase::setName( const QString &name )
501 {
502  AgentBase::setAgentName( name );
503 }
504 
505 QString ResourceBase::name() const
506 {
507  return AgentBase::agentName();
508 }
509 
510 QString ResourceBase::parseArguments( int argc, char **argv )
511 {
512  QString identifier;
513  if ( argc < 3 ) {
514  kDebug() << "Not enough arguments passed...";
515  exit( 1 );
516  }
517 
518  for ( int i = 1; i < argc - 1; ++i ) {
519  if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) )
520  identifier = QLatin1String( argv[ i + 1 ] );
521  }
522 
523  if ( identifier.isEmpty() ) {
524  kDebug() << "Identifier argument missing";
525  exit( 1 );
526  }
527 
528  const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
529  // strip off full path and possible .exe suffix
530  const QByteArray catalog = fi.baseName().toLatin1();
531 
532  KCmdLineArgs::init( argc, argv, ServerManager::addNamespace( identifier ).toLatin1(), catalog,
533  ki18nc( "@title application name", "Akonadi Resource" ), KDEPIMLIBS_VERSION,
534  ki18nc( "@title application description", "Akonadi Resource" ) );
535 
536  KCmdLineOptions options;
537  options.add( "identifier <argument>",
538  ki18nc( "@label commandline option", "Resource identifier" ) );
539  KCmdLineArgs::addCmdLineOptions( options );
540 
541  return identifier;
542 }
543 
544 int ResourceBase::init( ResourceBase *r )
545 {
546  QApplication::setQuitOnLastWindowClosed( false );
547  KGlobal::locale()->insertCatalog( QLatin1String( "libakonadi" ) );
548  int rv = kapp->exec();
549  delete r;
550  return rv;
551 }
552 
553 void ResourceBasePrivate::slotAbortRequested()
554 {
555  Q_Q( ResourceBase );
556 
557  scheduler->cancelQueues();
558  QMetaObject::invokeMethod( q, "abortActivity" );
559 }
560 
561 void ResourceBase::itemRetrieved( const Item &item )
562 {
563  Q_D( ResourceBase );
564  Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::FetchItem );
565  if ( !item.isValid() ) {
566  d->scheduler->currentTask().sendDBusReplies( i18nc( "@info", "Invalid item retrieved" ) );
567  d->scheduler->taskDone();
568  return;
569  }
570 
571  Item i( item );
572  QSet<QByteArray> requestedParts = d->scheduler->currentTask().itemParts;
573  foreach ( const QByteArray &part, requestedParts ) {
574  if ( !item.loadedPayloadParts().contains( part ) ) {
575  kWarning() << "Item does not provide part" << part;
576  }
577  }
578 
579  ItemModifyJob *job = new ItemModifyJob( i );
580  // FIXME: remove once the item with which we call retrieveItem() has a revision number
581  job->disableRevisionCheck();
582  connect( job, SIGNAL(result(KJob*)), SLOT(slotDeliveryDone(KJob*)) );
583 }
584 
585 void ResourceBasePrivate::slotDeliveryDone(KJob * job)
586 {
587  Q_Q( ResourceBase );
588  Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::FetchItem );
589  if ( job->error() ) {
590  emit q->error( i18nc( "@info", "Error while creating item: %1", job->errorString() ) );
591  }
592  scheduler->currentTask().sendDBusReplies( job->error() ? job->errorString() : QString() );
593  scheduler->taskDone();
594 }
595 
596 void ResourceBase::collectionAttributesRetrieved( const Collection &collection )
597 {
598  Q_D( ResourceBase );
599  Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
600  if ( !collection.isValid() ) {
601  emit attributesSynchronized( d->scheduler->currentTask().collection.id() );
602  d->scheduler->taskDone();
603  return;
604  }
605 
606  CollectionModifyJob *job = new CollectionModifyJob( collection );
607  connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionAttributesSyncDone(KJob*)) );
608 }
609 
610 void ResourceBasePrivate::slotCollectionAttributesSyncDone(KJob * job)
611 {
612  Q_Q( ResourceBase );
613  Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
614  if ( job->error() ) {
615  emit q->error( i18nc( "@info", "Error while updating collection: %1", job->errorString() ) );
616  }
617  emit q->attributesSynchronized( scheduler->currentTask().collection.id() );
618  scheduler->taskDone();
619 }
620 
621 void ResourceBasePrivate::slotDeleteResourceCollection()
622 {
623  Q_Q( ResourceBase );
624 
625  CollectionFetchJob *job = new CollectionFetchJob( Collection::root(), CollectionFetchJob::FirstLevel );
626  job->fetchScope().setResource( q->identifier() );
627  connect( job, SIGNAL(result(KJob*)), q, SLOT(slotDeleteResourceCollectionDone(KJob*)) );
628 }
629 
630 void ResourceBasePrivate::slotDeleteResourceCollectionDone( KJob *job )
631 {
632  Q_Q( ResourceBase );
633  if ( job->error() ) {
634  emit q->error( job->errorString() );
635  scheduler->taskDone();
636  } else {
637  const CollectionFetchJob *fetchJob = static_cast<const CollectionFetchJob*>( job );
638 
639  if ( !fetchJob->collections().isEmpty() ) {
640  CollectionDeleteJob *job = new CollectionDeleteJob( fetchJob->collections().first() );
641  connect( job, SIGNAL(result(KJob*)), q, SLOT(slotCollectionDeletionDone(KJob*)) );
642  } else {
643  // there is no resource collection, so just ignore the request
644  scheduler->taskDone();
645  }
646  }
647 }
648 
649 void ResourceBasePrivate::slotCollectionDeletionDone( KJob *job )
650 {
651  Q_Q( ResourceBase );
652  if ( job->error() ) {
653  emit q->error( job->errorString() );
654  }
655 
656  scheduler->taskDone();
657 }
658 
659 void ResourceBasePrivate::slotInvalidateCache( const Akonadi::Collection &collection )
660 {
661  Q_Q( ResourceBase );
662  InvalidateCacheJob *job = new InvalidateCacheJob( collection, q );
663  connect( job, SIGNAL(result(KJob*)), scheduler, SLOT(taskDone()) );
664 }
665 
666 void ResourceBase::changeCommitted( const Item& item )
667 {
668  changesCommitted( Item::List() << item );
669 }
670 
671 void ResourceBase::changesCommitted(const Item::List& items)
672 {
673  ItemModifyJob *job = new ItemModifyJob( items );
674  job->d_func()->setClean();
675  job->disableRevisionCheck(); // TODO: remove, but where/how do we handle the error?
676  job->setIgnorePayload( true ); // we only want to reset the dirty flag and update the remote id
677  connect( job, SIGNAL(finished(KJob*)), this, SLOT(changeCommittedResult(KJob*)) );
678 }
679 
680 void ResourceBase::changeCommitted( const Collection &collection )
681 {
682  CollectionModifyJob *job = new CollectionModifyJob( collection );
683  connect( job, SIGNAL(result(KJob*)), SLOT(changeCommittedResult(KJob*)) );
684 }
685 
686 void ResourceBasePrivate::changeCommittedResult( KJob *job )
687 {
688  Q_Q( ResourceBase );
689  if ( qobject_cast<CollectionModifyJob*>( job ) ) {
690  if ( job->error() ) {
691  emit q->error( i18nc( "@info", "Updating local collection failed: %1.", job->errorText() ) );
692  }
693  mChangeRecorder->d_ptr->invalidateCache( static_cast<CollectionModifyJob*>( job )->collection() );
694  } else {
695  // TODO: Error handling for item changes?
696  // Item cache is invalidated by ItemModifyJob
697  }
698 
699  changeProcessed();
700 }
701 
702 bool ResourceBase::requestItemDelivery( qint64 uid, const QString &remoteId,
703  const QString &mimeType, const QStringList &parts )
704 {
705  return requestItemDeliveryV2( uid, remoteId, mimeType, parts ).isEmpty();
706 }
707 
708 QString ResourceBase::requestItemDeliveryV2(qint64 uid, const QString &remoteId, const QString &mimeType, const QStringList &_parts)
709 {
710  Q_D( ResourceBase );
711  if ( !isOnline() ) {
712  const QString errorMsg = i18nc( "@info", "Cannot fetch item in offline mode." );
713  emit error( errorMsg );
714  return errorMsg;
715  }
716 
717  setDelayedReply( true );
718  // FIXME: we need at least the revision number too
719  Item item( uid );
720  item.setMimeType( mimeType );
721  item.setRemoteId( remoteId );
722 
723  QSet<QByteArray> parts;
724  Q_FOREACH( const QString &str, _parts )
725  parts.insert( str.toLatin1() );
726 
727  d->scheduler->scheduleItemFetch( item, parts, message() );
728 
729  return QString();
730 
731 }
732 
733 void ResourceBase::collectionsRetrieved( const Collection::List & collections )
734 {
735  Q_D( ResourceBase );
736  Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
737  d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
738  "ResourceBase::collectionsRetrieved()",
739  "Calling collectionsRetrieved() although no collection retrieval is in progress" );
740  if ( !d->mCollectionSyncer ) {
741  d->mCollectionSyncer = new CollectionSync( identifier() );
742  d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
743  connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
744  connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
745  }
746  d->mCollectionSyncer->setRemoteCollections( collections );
747 }
748 
749 void ResourceBase::collectionsRetrievedIncremental( const Collection::List & changedCollections,
750  const Collection::List & removedCollections )
751 {
752  Q_D( ResourceBase );
753  Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
754  d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
755  "ResourceBase::collectionsRetrievedIncremental()",
756  "Calling collectionsRetrievedIncremental() although no collection retrieval is in progress" );
757  if ( !d->mCollectionSyncer ) {
758  d->mCollectionSyncer = new CollectionSync( identifier() );
759  d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
760  connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
761  connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
762  }
763  d->mCollectionSyncer->setRemoteCollections( changedCollections, removedCollections );
764 }
765 
766 void ResourceBase::setCollectionStreamingEnabled( bool enable )
767 {
768  Q_D( ResourceBase );
769  Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
770  d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
771  "ResourceBase::setCollectionStreamingEnabled()",
772  "Calling setCollectionStreamingEnabled() although no collection retrieval is in progress" );
773  if ( !d->mCollectionSyncer ) {
774  d->mCollectionSyncer = new CollectionSync( identifier() );
775  d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
776  connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
777  connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
778  }
779  d->mCollectionSyncer->setStreamingEnabled( enable );
780 }
781 
782 void ResourceBase::collectionsRetrievalDone()
783 {
784  Q_D( ResourceBase );
785  Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
786  d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
787  "ResourceBase::collectionsRetrievalDone()",
788  "Calling collectionsRetrievalDone() although no collection retrieval is in progress" );
789  // streaming enabled, so finalize the sync
790  if ( d->mCollectionSyncer ) {
791  d->mCollectionSyncer->retrievalDone();
792  }
793  // user did the sync himself, we are done now
794  else {
795  // FIXME: we need the same special case for SyncAll as in slotCollectionSyncDone here!
796  d->scheduler->taskDone();
797  }
798 }
799 
800 void ResourceBasePrivate::slotCollectionSyncDone( KJob * job )
801 {
802  Q_Q( ResourceBase );
803  mCollectionSyncer = 0;
804  if ( job->error() ) {
805  if ( job->error() != Job::UserCanceled )
806  emit q->error( job->errorString() );
807  } else {
808  if ( scheduler->currentTask().type == ResourceScheduler::SyncAll ) {
809  CollectionFetchJob *list = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive );
810  list->setFetchScope( q->changeRecorder()->collectionFetchScope() );
811  list->fetchScope().setResource( mId );
812  q->connect( list, SIGNAL(result(KJob*)), q, SLOT(slotLocalListDone(KJob*)) );
813  return;
814  } else if ( scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ) {
815  scheduler->scheduleCollectionTreeSyncCompletion();
816  }
817  }
818  scheduler->taskDone();
819 }
820 
821 void ResourceBasePrivate::slotLocalListDone( KJob * job )
822 {
823  Q_Q( ResourceBase );
824  if ( job->error() ) {
825  emit q->error( job->errorString() );
826  } else {
827  Collection::List cols = static_cast<CollectionFetchJob*>( job )->collections();
828  foreach ( const Collection &col, cols ) {
829  scheduler->scheduleSync( col );
830  }
831  scheduler->scheduleFullSyncCompletion();
832  }
833  scheduler->taskDone();
834 }
835 
836 void ResourceBasePrivate::slotSynchronizeCollection( const Collection &col )
837 {
838  Q_Q( ResourceBase );
839  currentCollection = col;
840  // check if this collection actually can contain anything
841  QStringList contentTypes = currentCollection.contentMimeTypes();
842  contentTypes.removeAll( Collection::mimeType() );
843  contentTypes.removeAll( Collection::virtualMimeType() );
844  if ( !contentTypes.isEmpty() || col.isVirtual() ) {
845  if ( mAutomaticProgressReporting ) {
846  emit q->status( AgentBase::Running, i18nc( "@info:status", "Syncing folder '%1'", currentCollection.displayName() ) );
847  }
848  q->retrieveItems( currentCollection );
849  return;
850  }
851  scheduler->taskDone();
852 }
853 
854 void ResourceBasePrivate::slotSynchronizeCollectionAttributes( const Collection &col )
855 {
856  Q_Q( ResourceBase );
857  QMetaObject::invokeMethod( q, "retrieveCollectionAttributes", Q_ARG( Akonadi::Collection, col ) );
858 }
859 
860 void ResourceBasePrivate::slotPrepareItemRetrieval( const Akonadi::Item &item )
861 {
862  Q_Q( ResourceBase );
863  ItemFetchJob *fetch = new ItemFetchJob( item, this );
864  fetch->fetchScope().setAncestorRetrieval( q->changeRecorder()->itemFetchScope().ancestorRetrieval() );
865  fetch->fetchScope().setCacheOnly( true );
866 
867  // copy list of attributes to fetch
868  const QSet<QByteArray> attributes = q->changeRecorder()->itemFetchScope().attributes();
869  foreach ( const QByteArray &attribute, attributes )
870  fetch->fetchScope().fetchAttribute( attribute );
871 
872  q->connect( fetch, SIGNAL(result(KJob*)), SLOT(slotPrepareItemRetrievalResult(KJob*)) );
873 }
874 
875 void ResourceBasePrivate::slotPrepareItemRetrievalResult( KJob* job )
876 {
877  Q_Q( ResourceBase );
878  Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::FetchItem,
879  "ResourceBasePrivate::slotPrepareItemRetrievalResult()",
880  "Preparing item retrieval although no item retrieval is in progress" );
881  if ( job->error() ) {
882  q->cancelTask( job->errorText() );
883  return;
884  }
885  ItemFetchJob *fetch = qobject_cast<ItemFetchJob*>( job );
886  if ( fetch->items().count() != 1 ) {
887  q->cancelTask( i18n( "The requested item no longer exists" ) );
888  return;
889  }
890  const Item item = fetch->items().first();
891  const QSet<QByteArray> parts = scheduler->currentTask().itemParts;
892  if ( !q->retrieveItem( item, parts ) )
893  q->cancelTask();
894 }
895 
896 void ResourceBasePrivate::slotRecursiveMoveReplay( RecursiveMover *mover )
897 {
898  Q_Q( ResourceBase );
899  Q_ASSERT( mover );
900  Q_ASSERT( !m_recursiveMover );
901  m_recursiveMover = mover;
902  connect( mover, SIGNAL(result(KJob*)), q, SLOT(slotRecursiveMoveReplayResult(KJob*)) );
903  mover->start();
904 }
905 
906 void ResourceBasePrivate::slotRecursiveMoveReplayResult( KJob *job )
907 {
908  Q_Q( ResourceBase );
909  m_recursiveMover = 0;
910 
911  if ( job->error() ) {
912  q->deferTask();
913  return;
914  }
915 
916  changeProcessed();
917 }
918 
919 void ResourceBase::itemsRetrievalDone()
920 {
921  Q_D( ResourceBase );
922  // streaming enabled, so finalize the sync
923  if ( d->mItemSyncer ) {
924  d->mItemSyncer->deliveryDone();
925  }
926  // user did the sync himself, we are done now
927  else {
928  d->scheduler->taskDone();
929  }
930 }
931 
932 void ResourceBase::clearCache()
933 {
934  Q_D( ResourceBase );
935  d->scheduler->scheduleResourceCollectionDeletion();
936 }
937 
938 void ResourceBase::invalidateCache(const Collection& collection)
939 {
940  Q_D( ResourceBase );
941  d->scheduler->scheduleCacheInvalidation( collection );
942 }
943 
944 Collection ResourceBase::currentCollection() const
945 {
946  Q_D( const ResourceBase );
947  Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection ,
948  "ResourceBase::currentCollection()",
949  "Trying to access current collection although no item retrieval is in progress" );
950  return d->currentCollection;
951 }
952 
953 Item ResourceBase::currentItem() const
954 {
955  Q_D( const ResourceBase );
956  Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::FetchItem ,
957  "ResourceBase::currentItem()",
958  "Trying to access current item although no item retrieval is in progress" );
959  return d->scheduler->currentTask().item;
960 }
961 
962 void ResourceBase::synchronizeCollectionTree()
963 {
964  d_func()->scheduler->scheduleCollectionTreeSync();
965 }
966 
967 void ResourceBase::cancelTask()
968 {
969  Q_D( ResourceBase );
970  switch ( d->scheduler->currentTask().type ) {
971  case ResourceScheduler::FetchItem:
972  itemRetrieved( Item() ); // sends the error reply and
973  break;
974  case ResourceScheduler::ChangeReplay:
975  d->changeProcessed();
976  break;
977  case ResourceScheduler::SyncCollectionTree:
978  case ResourceScheduler::SyncAll:
979  if ( d->mCollectionSyncer )
980  d->mCollectionSyncer->rollback();
981  else
982  d->scheduler->taskDone();
983  break;
984  case ResourceScheduler::SyncCollection:
985  if ( d->mItemSyncer ) {
986  d->mItemSyncer->rollback();
987  } else {
988  d->scheduler->taskDone();
989  }
990  break;
991  default:
992  d->scheduler->taskDone();
993  }
994 }
995 
996 void ResourceBase::cancelTask( const QString &msg )
997 {
998  cancelTask();
999 
1000  emit error( msg );
1001 }
1002 
1003 void ResourceBase::deferTask()
1004 {
1005  Q_D( ResourceBase );
1006  d->scheduler->deferTask();
1007 }
1008 
1009 void ResourceBase::doSetOnline( bool state )
1010 {
1011  d_func()->scheduler->setOnline( state );
1012 }
1013 
1014 void ResourceBase::synchronizeCollection( qint64 collectionId )
1015 {
1016  synchronizeCollection( collectionId, false );
1017 }
1018 
1019 void ResourceBase::synchronizeCollection( qint64 collectionId, bool recursive )
1020 {
1021  CollectionFetchJob* job = new CollectionFetchJob( Collection( collectionId ), recursive ? CollectionFetchJob::Recursive : CollectionFetchJob::Base );
1022  job->setFetchScope( changeRecorder()->collectionFetchScope() );
1023  job->fetchScope().setResource( identifier() );
1024  job->setProperty( "recursive", recursive );
1025  connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListDone(KJob*)) );
1026 }
1027 
1028 void ResourceBasePrivate::slotCollectionListDone( KJob *job )
1029 {
1030  if ( !job->error() ) {
1031  Collection::List list = static_cast<CollectionFetchJob*>( job )->collections();
1032  if ( !list.isEmpty() ) {
1033  if ( job->property( "recursive" ).toBool() ) {
1034  Q_FOREACH ( const Collection &collection, list ) {
1035  scheduler->scheduleSync( collection );
1036  }
1037  } else {
1038  scheduler->scheduleSync( list.first() );
1039  }
1040  }
1041  }
1042  // TODO: error handling
1043 }
1044 
1045 void ResourceBase::synchronizeCollectionAttributes( qint64 collectionId )
1046 {
1047  CollectionFetchJob* job = new CollectionFetchJob( Collection( collectionId ), CollectionFetchJob::Base );
1048  job->setFetchScope( changeRecorder()->collectionFetchScope() );
1049  job->fetchScope().setResource( identifier() );
1050  connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListForAttributesDone(KJob*)) );
1051 }
1052 
1053 void ResourceBasePrivate::slotCollectionListForAttributesDone( KJob *job )
1054 {
1055  if ( !job->error() ) {
1056  Collection::List list = static_cast<CollectionFetchJob*>( job )->collections();
1057  if ( !list.isEmpty() ) {
1058  Collection col = list.first();
1059  scheduler->scheduleAttributesSync( col );
1060  }
1061  }
1062  // TODO: error handling
1063 }
1064 
1065 void ResourceBase::setTotalItems( int amount )
1066 {
1067  kDebug() << amount;
1068  Q_D( ResourceBase );
1069  setItemStreamingEnabled( true );
1070  if ( d->mItemSyncer ) {
1071  d->mItemSyncer->setTotalItems( amount );
1072  }
1073 }
1074 
1075 void ResourceBase::setItemStreamingEnabled( bool enable )
1076 {
1077  Q_D( ResourceBase );
1078  d->createItemSyncInstanceIfMissing();
1079  if ( d->mItemSyncer ) {
1080  d->mItemSyncer->setStreamingEnabled( enable );
1081  }
1082 }
1083 
1084 void ResourceBase::itemsRetrieved( const Item::List &items )
1085 {
1086  Q_D( ResourceBase );
1087  d->createItemSyncInstanceIfMissing();
1088  if ( d->mItemSyncer ) {
1089  d->mItemSyncer->setFullSyncItems( items );
1090  }
1091 }
1092 
1093 void ResourceBase::itemsRetrievedIncremental( const Item::List &changedItems,
1094  const Item::List &removedItems )
1095 {
1096  Q_D( ResourceBase );
1097  d->createItemSyncInstanceIfMissing();
1098  if ( d->mItemSyncer ) {
1099  d->mItemSyncer->setIncrementalSyncItems( changedItems, removedItems );
1100  }
1101 }
1102 
1103 void ResourceBasePrivate::slotItemSyncDone( KJob *job )
1104 {
1105  mItemSyncer = 0;
1106  Q_Q( ResourceBase );
1107  if ( job->error() && job->error() != Job::UserCanceled ) {
1108  emit q->error( job->errorString() );
1109  }
1110  scheduler->taskDone();
1111 }
1112 
1113 
1114 void ResourceBasePrivate::slotDelayedEmitProgress()
1115 {
1116  Q_Q( ResourceBase );
1117  if ( mAutomaticProgressReporting ) {
1118  emit q->percent( mUnemittedProgress );
1119 
1120  Q_FOREACH( const QVariantMap &statusMap, mUnemittedAdvancedStatus ) {
1121  emit q->advancedStatus( statusMap );
1122  }
1123  }
1124  mUnemittedProgress = 0;
1125  mUnemittedAdvancedStatus.clear();
1126 }
1127 
1128 void ResourceBasePrivate::slotPercent( KJob *job, unsigned long percent )
1129 {
1130  mUnemittedProgress = percent;
1131 
1132  const Collection collection = job->property( "collection" ).value<Collection>();
1133  if ( collection.isValid() ) {
1134  QVariantMap statusMap;
1135  statusMap.insert( QLatin1String( "key" ), QString::fromLatin1( "collectionSyncProgress" ) );
1136  statusMap.insert( QLatin1String( "collectionId" ), collection.id() );
1137  statusMap.insert( QLatin1String( "percent" ), static_cast<unsigned int>( percent ) );
1138 
1139  mUnemittedAdvancedStatus[collection.id()] = statusMap;
1140  }
1141  // deliver completion right away, intermediate progress at 1s intervals
1142  if ( percent == 100 ) {
1143  mProgressEmissionCompressor.stop();
1144  slotDelayedEmitProgress();
1145  } else if ( !mProgressEmissionCompressor.isActive() ) {
1146  mProgressEmissionCompressor.start();
1147  }
1148 }
1149 
1150 void ResourceBase::setHierarchicalRemoteIdentifiersEnabled( bool enable )
1151 {
1152  Q_D( ResourceBase );
1153  d->mHierarchicalRid = enable;
1154 }
1155 
1156 void ResourceBase::scheduleCustomTask( QObject *receiver, const char *method, const QVariant &argument, SchedulePriority priority )
1157 {
1158  Q_D( ResourceBase );
1159  d->scheduler->scheduleCustomTask( receiver, method, argument, priority );
1160 }
1161 
1162 void ResourceBase::taskDone()
1163 {
1164  Q_D( ResourceBase );
1165  d->scheduler->taskDone();
1166 }
1167 
1168 void ResourceBase::retrieveCollectionAttributes( const Collection &collection )
1169 {
1170  collectionAttributesRetrieved( collection );
1171 }
1172 
1173 void Akonadi::ResourceBase::abortActivity()
1174 {
1175 
1176 }
1177 
1178 void ResourceBase::setItemTransactionMode(ItemSync::TransactionMode mode)
1179 {
1180  Q_D( ResourceBase );
1181  d->mItemTransactionMode = mode;
1182 }
1183 
1184 void ResourceBase::setItemSynchronizationFetchScope(const ItemFetchScope& fetchScope)
1185 {
1186  Q_D( ResourceBase );
1187  if ( !d->mItemSyncFetchScope )
1188  d->mItemSyncFetchScope = new ItemFetchScope;
1189  *(d->mItemSyncFetchScope) = fetchScope;
1190 }
1191 
1192 void ResourceBase::setAutomaticProgressReporting( bool enabled )
1193 {
1194  Q_D( ResourceBase );
1195  d->mAutomaticProgressReporting = enabled;
1196 }
1197 
1198 QString ResourceBase::dumpNotificationListToString() const
1199 {
1200  Q_D( const ResourceBase );
1201  return d->dumpNotificationListToString();
1202 }
1203 
1204 QString ResourceBase::dumpSchedulerToString() const
1205 {
1206  Q_D( const ResourceBase );
1207  return d->dumpToString();
1208 }
1209 
1210 void ResourceBase::dumpMemoryInfo() const
1211 {
1212  Q_D( const ResourceBase );
1213  return d->dumpMemoryInfo();
1214 }
1215 
1216 QString ResourceBase::dumpMemoryInfoToString() const
1217 {
1218  Q_D( const ResourceBase );
1219  return d->dumpMemoryInfoToString();
1220 }
1221 
1222 #include "resourcebase.moc"
1223 #include "moc_resourcebase.cpp"
Akonadi::CollectionModifyJob
Job that modifies a collection in the Akonadi storage.
Definition: collectionmodifyjob.h:82
Akonadi::RecursiveMover
Helper class for expanding inter-resource collection moves inside ResourceBase.
Definition: recursivemover_p.h:37
Akonadi::ItemFetchScope::fetchAttribute
void fetchAttribute(const QByteArray &type, bool fetch=true)
Sets whether the attribute of the given type should be fetched.
Definition: itemfetchscope.cpp:78
Akonadi::ResourceBase::retrieveCollectionAttributes
void retrieveCollectionAttributes(const Akonadi::Collection &collection)
Retrieve the attributes of a single collection from the backend.
Definition: resourcebase.cpp:1168
Akonadi::ResourceBase::abortActivity
void abortActivity()
Abort any activity in progress in the backend.
Definition: resourcebase.cpp:1173
Akonadi::ItemModifyJob::disableRevisionCheck
void disableRevisionCheck()
Disables the check of the revision number.
Definition: itemmodifyjob.cpp:352
Akonadi::AgentBase::percent
void percent(int progress)
This signal should be emitted whenever the progress of an action in the agent (e.g.
Akonadi::ResourceBase::retrieveCollections
virtual void retrieveCollections()=0
Retrieve the collection tree from the remote server and supply it via collectionsRetrieved() or colle...
Akonadi::CollectionFetchJob::collections
Collection::List collections() const
Returns the list of fetched collection.
Definition: collectionfetchjob.cpp:175
Akonadi::AgentBase::abortRequested
void abortRequested()
Emitted when another application has remotely asked the agent to abort its current operation...
Akonadi::ResourceBase::dumpNotificationListToString
QString dumpNotificationListToString() const
Dump the contents of the current ChangeReplay.
Definition: resourcebase.cpp:1198
Akonadi::Collection::displayName
QString displayName() const
Returns the display name (EntityDisplayAttribute::displayName()) if set, and Collection::name() other...
Definition: collection.cpp:86
Akonadi::ResourceBase::attributesSynchronized
void attributesSynchronized(qlonglong collectionId)
Emitted when a collection attributes synchronization has been completed.
Akonadi::ResourceBase::collectionsRetrievalDone
void collectionsRetrievalDone()
Call this method to indicate you finished synchronizing the collection tree.
Definition: resourcebase.cpp:782
Akonadi::ResourceBase::setAutomaticProgressReporting
void setAutomaticProgressReporting(bool enabled)
Enable or disable automatic progress reporting.
Definition: resourcebase.cpp:1192
Akonadi::ResourceBase::setCollectionStreamingEnabled
void setCollectionStreamingEnabled(bool enable)
Enable collection streaming, that is collections don&#39;t have to be delivered at once as result of a re...
Definition: resourcebase.cpp:766
Akonadi::ResourceBase::synchronizeCollectionAttributes
void synchronizeCollectionAttributes(qint64 id)
This method is called whenever the collection with the given id shall have its attributes synchronize...
Definition: resourcebase.cpp:1045
Akonadi::CollectionFetchJob::FirstLevel
Only list direct sub-collections of the base collection.
Definition: collectionfetchjob.h:63
Akonadi::CollectionFetchJob::fetchScope
CollectionFetchScope & fetchScope()
Returns the collection fetch scope.
Definition: collectionfetchjob.cpp:437
Akonadi::CollectionFetchScope::setResource
void setResource(const QString &resource)
Sets a resource filter, that is only collections owned by the specified resource are retrieved...
Definition: collectionfetchscope.cpp:114
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
Akonadi::CollectionFetchJob
Job that fetches collections from the Akonadi storage.
Definition: collectionfetchjob.h:53
Akonadi::ResourceBase::itemsRetrieved
void itemsRetrieved(const Item::List &items)
Call this method to supply the full collection listing from the remote server.
Definition: resourcebase.cpp:1084
Akonadi::Collection::virtualMimeType
static QString virtualMimeType()
Returns the mimetype used for virtual collections.
Definition: collection.cpp:202
Akonadi::AgentBase::agentNameChanged
void agentNameChanged(const QString &name)
This signal is emitted whenever the name of the agent has changed.
Akonadi::Collection::mimeType
static QString mimeType()
Returns the mimetype used for collections.
Definition: collection.cpp:197
Akonadi::ResourceBase::setItemSynchronizationFetchScope
void setItemSynchronizationFetchScope(const ItemFetchScope &fetchScope)
Set the fetch scope applied for item synchronization.
Definition: resourcebase.cpp:1184
Akonadi::ResourceBase::synchronizeCollectionTree
void synchronizeCollectionTree()
Refetches the Collections.
Definition: resourcebase.cpp:962
Akonadi::ResourceBase::setTotalItems
void setTotalItems(int amount)
Call this method when you want to use the itemsRetrieved() method in streaming mode and indicate the ...
Definition: resourcebase.cpp:1065
Akonadi::ResourceBase::nameChanged
void nameChanged(const QString &name)
This signal is emitted whenever the name of the resource has changed.
Akonadi::AgentBasePrivate
Definition: agentbase_p.h:38
Akonadi::ResourceBase::changesCommitted
void changesCommitted(const Item::List &items)
Resets the dirty flag of all given items and updates remote ids.
Definition: resourcebase.cpp:671
Akonadi::ItemFetchJob::items
Item::List items() const
Returns the fetched item.
Definition: itemfetchjob.cpp:227
Akonadi::AgentBase
The base class for all Akonadi agents and resources.
Definition: agentbase.h:80
Akonadi::CollectionFetchJob::Base
Only fetch the base collection.
Definition: collectionfetchjob.h:62
Akonadi::ItemSync
Syncs between items known to a client (usually a resource) and the Akonadi storage.
Definition: itemsync.h:53
Akonadi::ResourceBase::itemsRetrievalDone
void itemsRetrievalDone()
Call this method to indicate you finished synchronizing the current collection.
Definition: resourcebase.cpp:919
Akonadi::ResourceBase::deferTask
void deferTask()
Stops the execution of the current task and continues with the next one.
Definition: resourcebase.cpp:1003
Akonadi::ItemFetchJob::fetchScope
ItemFetchScope & fetchScope()
Returns the item fetch scope.
Definition: itemfetchjob.cpp:248
Akonadi::AgentBase::setAgentName
void setAgentName(const QString &name)
This method is used to set the name of the agent.
Definition: agentbase.cpp:931
Akonadi::ResourceBase::SchedulePriority
SchedulePriority
Describes the scheduling priority of a task that has been queued for execution.
Definition: resourcebase.h:602
Akonadi::ResourceBase::synchronize
void synchronize()
This method is called whenever the resource should start synchronize all data.
Definition: resourcebase.cpp:495
Akonadi::AgentBase::error
void error(const QString &message)
This signal shall be used to report errors.
Akonadi::AgentBase::status
virtual int status() const
This method returns the current status code of the agent.
Akonadi::ResourceBase::clearCache
void clearCache()
Call this method to remove all items and collections of the resource from the server cache...
Definition: resourcebase.cpp:932
Akonadi::ResourceBase::collectionAttributesRetrieved
void collectionAttributesRetrieved(const Collection &collection)
Call this method from retrieveCollectionAttributes() once the result is available.
Definition: resourcebase.cpp:596
Akonadi::Entity::remoteId
QString remoteId() const
Returns the remote id of the entity.
Definition: entity.cpp:82
Akonadi::ResourceBase::collectionsRetrieved
void collectionsRetrieved(const Collection::List &collections)
Call this to supply the full folder tree retrieved from the remote server.
Definition: resourcebase.cpp:733
Akonadi::Collection::root
static Collection root()
Returns the root collection.
Definition: collection.cpp:192
Akonadi::ResourceBase::currentItem
Item currentItem() const
Returns the item that is currently retrieved.
Definition: resourcebase.cpp:953
Akonadi::CollectionDeleteJob
Job that deletes a collection in the Akonadi storage.
Definition: collectiondeletejob.h:63
Akonadi::ResourceBase::itemsRetrievedIncremental
void itemsRetrievedIncremental(const Item::List &changedItems, const Item::List &removedItems)
Call this method to supply incrementally retrieved items from the remote server.
Definition: resourcebase.cpp:1093
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:307
Akonadi::ResourceBase::doSetOnline
void doSetOnline(bool online)
Inherited from AgentBase.
Definition: resourcebase.cpp:1009
Akonadi::Entity::id
Id id() const
Returns the unique identifier of the entity.
Definition: entity.cpp:72
Akonadi::ResourceBase::collectionTreeSynchronized
void collectionTreeSynchronized()
Emitted when a collection tree synchronization has been completed.
Akonadi::CollectionFetchJob::setFetchScope
void setFetchScope(const CollectionFetchScope &fetchScope)
Sets the collection fetch scope.
Definition: collectionfetchjob.cpp:431
Akonadi::ResourceBase::synchronizeCollection
void synchronizeCollection(qint64 id)
This method is called whenever the collection with the given id shall be synchronized.
Definition: resourcebase.cpp:1014
Akonadi::ItemFetchScope
Specifies which parts of an item should be fetched from the Akonadi storage.
Definition: itemfetchscope.h:68
Akonadi::ItemFetchScope::setAncestorRetrieval
void setAncestorRetrieval(AncestorRetrieval ancestorDepth)
Sets how many levels of ancestor collections should be included in the retrieval. ...
Definition: itemfetchscope.cpp:129
Akonadi::ResourceBase::setItemTransactionMode
void setItemTransactionMode(ItemSync::TransactionMode mode)
Set transaction mode for item sync&#39;ing.
Definition: resourcebase.cpp:1178
Akonadi::InvalidateCacheJob
Helper job to invalidate item cache for an entire collection.
Definition: invalidatecachejob_p.h:34
Akonadi::AgentBase::identifier
QString identifier() const
Returns the instance identifier of this agent.
Definition: agentbase.cpp:926
Akonadi::ItemModifyJob::setIgnorePayload
void setIgnorePayload(bool ignore)
Sets whether the payload of the modified item shall be omitted from transmission to the Akonadi stora...
Definition: itemmodifyjob.cpp:329
Akonadi::ItemSync::TransactionMode
TransactionMode
Transaction mode used by ItemSync.
Definition: itemsync.h:158
Akonadi::ResourceBase::changeCommitted
void changeCommitted(const Item &item)
Resets the dirty flag of the given item and updates the remote id.
Definition: resourcebase.cpp:666
Akonadi::AgentBase::changeRecorder
ChangeRecorder * changeRecorder() const
Returns the Akonadi::ChangeRecorder object used for monitoring.
Definition: agentbase.cpp:970
Akonadi::ResourceBase::dumpMemoryInfo
void dumpMemoryInfo() const
Dumps memory usage information to stdout.
Definition: resourcebase.cpp:1210
Akonadi::ResourceBase::setHierarchicalRemoteIdentifiersEnabled
void setHierarchicalRemoteIdentifiersEnabled(bool enable)
Indicate the use of hierarchical remote identifiers.
Definition: resourcebase.cpp:1150
Akonadi::CollectionSync
Definition: collectionsync_p.h:53
Akonadi::AgentBase::isOnline
bool isOnline() const
Returns whether the agent is currently online.
Akonadi::ResourceBase::itemRetrieved
void itemRetrieved(const Item &item)
Call this method from retrieveItem() once the result is available.
Definition: resourcebase.cpp:561
Akonadi::AgentBase::changeProcessed
void changeProcessed()
Marks the current change as processes and replays the next change if change recording is enabled (noo...
Definition: agentbase.cpp:964
Akonadi::RecursiveMover::setCollection
void setCollection(const Akonadi::Collection &collection, const Akonadi::Collection &parentCollection)
Set the collection that is actually moved.
Definition: recursivemover.cpp:43
Akonadi::ItemModifyJob
Job that modifies an existing item in the Akonadi storage.
Definition: itemmodifyjob.h:97
Akonadi::ItemFetchJob
Job that fetches items from the Akonadi storage.
Definition: itemfetchjob.h:82
Akonadi::ResourceSelectJob
Job that selects a resource context for remote identifier based operations.
Definition: resourceselectjob_p.h:82
Akonadi::ResourceBase::~ResourceBase
~ResourceBase()
Destroys the base resource.
Definition: resourcebase.cpp:491
Akonadi::Collection::contentMimeTypes
QStringList contentMimeTypes() const
Returns a list of possible content mimetypes, e.g.
Definition: collection.cpp:115
Akonadi::ResourceBase::init
static int init(int argc, char **argv)
Use this method in the main function of your resource application to initialize your resource subclas...
Definition: resourcebase.h:180
Akonadi::ResourceBase::setItemStreamingEnabled
void setItemStreamingEnabled(bool enable)
Enable item streaming.
Definition: resourcebase.cpp:1075
Akonadi::ResourceBase::name
QString name() const
Returns the name of the resource.
Definition: resourcebase.cpp:505
Akonadi::ResourceBase::taskDone
void taskDone()
Indicate that the current task is finished.
Definition: resourcebase.cpp:1162
Akonadi::ResourceBase::cancelTask
void cancelTask()
Stops the execution of the current task and continues with the next one.
Definition: resourcebase.cpp:967
Akonadi::ResourceBase::currentCollection
Collection currentCollection() const
Returns the collection that is currently synchronized.
Definition: resourcebase.cpp:944
Akonadi::Collection::resource
QString resource() const
Returns the identifier of the resource owning the collection.
Definition: collection.cpp:207
Akonadi::Job::UserCanceled
The user canceld this job.
Definition: job.h:108
Akonadi::ResourceBase::ResourceBase
ResourceBase(const QString &id)
Creates a base resource.
Definition: resourcebase.cpp:429
Akonadi::AgentBase::Running
The agent is working on something.
Definition: agentbase.h:365
Akonadi::Entity::isValid
bool isValid() const
Returns whether the entity is valid.
Definition: entity.cpp:97
Akonadi::ItemSync::setTransactionMode
void setTransactionMode(TransactionMode mode)
Set the transaction mode to use for this sync.
Definition: itemsync.cpp:470
Akonadi::ResourceBase::collectionsRetrievedIncremental
void collectionsRetrievedIncremental(const Collection::List &changedCollections, const Collection::List &removedCollections)
Call this to supply incrementally retrieved collections from the remote server.
Definition: resourcebase.cpp:749
Akonadi::ServerManager::addNamespace
static QString addNamespace(const QString &string)
Adds the multi-instance namespace to string if required (with &#39;_&#39; as separator).
Definition: servermanager.cpp:321
Akonadi::ResourceBase::setName
void setName(const QString &name)
This method is used to set the name of the resource.
Definition: resourcebase.cpp:500
Akonadi::CollectionFetchJob::Recursive
List all sub-collections.
Definition: collectionfetchjob.h:64
Akonadi::ResourceBase::dumpMemoryInfoToString
QString dumpMemoryInfoToString() const
Returns a string with memory usage information.
Definition: resourcebase.cpp:1216
Akonadi::Collection::List
QList< Collection > List
Describes a list of collections.
Definition: collection.h:81
Akonadi::AgentBase::agentName
QString agentName() const
Returns the name of the agent.
Definition: agentbase.cpp:954
Akonadi::ResourceBase
The base class for all Akonadi resources.
Definition: resourcebase.h:147
Akonadi::Collection::isVirtual
bool isVirtual() const
Returns whether the collection is virtual, for example a search collection.
Definition: collection.cpp:261
Akonadi::ResourceBase::dumpSchedulerToString
QString dumpSchedulerToString() const
Dump the state of the scheduler.
Definition: resourcebase.cpp:1204
Akonadi::ResourceBase::scheduleCustomTask
void scheduleCustomTask(QObject *receiver, const char *method, const QVariant &argument, SchedulePriority priority=Append)
Schedules a custom task in the internal scheduler.
Definition: resourcebase.cpp:1156
Akonadi::ItemFetchScope::setCacheOnly
void setCacheOnly(bool cacheOnly)
Sets whether payload data should be requested from remote sources or just from the local cache...
Definition: itemfetchscope.cpp:106
Akonadi::ResourceBase::invalidateCache
void invalidateCache(const Collection &collection)
Call this method to invalidate all cached content in collection.
Definition: resourcebase.cpp:938
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Nov 26 2013 09:03:18 by doxygen 1.8.5 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.11.3 API Reference

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