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