21 #include "resourcebase.h"
22 #include "agentbase_p.h"
24 #include "resourceadaptor.h"
25 #include "collectiondeletejob.h"
26 #include "collectionsync_p.h"
27 #include "dbusconnectionpool.h"
29 #include "kdepimlibs-version.h"
30 #include "resourcescheduler_p.h"
31 #include "tracerinterface.h"
32 #include "xdgbasedirs_p.h"
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"
44 #include "resourceselectjob_p.h"
45 #include "monitor_p.h"
46 #include "servermanager_p.h"
47 #include "recursivemover_p.h"
49 #include <kaboutdata.h>
50 #include <kcmdlineargs.h>
52 #include <klocalizedstring.h>
54 #include <akonadi/tagmodifyjob.h>
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>
64 using namespace Akonadi;
69 Q_CLASSINFO(
"D-Bus Interface",
"org.kde.dfaure" )
76 mItemSyncFetchScope( 0 ),
77 mItemTransactionMode(
ItemSync::SingleTransaction ),
78 mCollectionSyncer( 0 ),
79 mHierarchicalRid( false ),
80 mUnemittedProgress( 0 ),
81 mAutomaticProgressReporting( true )
83 Internal::setClientType( Internal::Resource );
84 mStatusMessage = defaultReadyMessage();
85 mProgressEmissionCompressor.setInterval( 1000 );
86 mProgressEmissionCompressor.setSingleShot(
true );
89 ~ResourceBasePrivate()
91 delete mItemSyncFetchScope;
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." );
104 kError() <<
"Unable to register service" << serviceId <<
"at D-Bus:" << reason;
106 if ( QThread::currentThread() == QCoreApplication::instance()->thread() )
107 QCoreApplication::instance()->exit(1);
110 AgentBasePrivate::delayedInit();
114 virtual void changeProcessed()
116 if ( m_recursiveMover ) {
117 m_recursiveMover->changeProcessed();
118 QTimer::singleShot( 0, m_recursiveMover, SLOT(replayNext()) );
123 if ( !mChangeRecorder->
isEmpty() )
124 scheduler->scheduleChangeReplay();
125 scheduler->taskDone();
128 void slotAbortRequested();
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 );
139 void slotItemSyncDone( KJob *job );
141 void slotPercent( KJob* job,
unsigned long percent );
142 void slotDelayedEmitProgress();
143 void slotDeleteResourceCollection();
144 void slotDeleteResourceCollectionDone( KJob *job );
145 void slotCollectionDeletionDone( KJob *job );
149 void slotPrepareItemRetrieval(
const Akonadi::Item &item );
150 void slotPrepareItemRetrievalResult( KJob* job );
152 void changeCommittedResult( KJob* job );
155 void slotRecursiveMoveReplayResult( KJob *job );
157 void slotSessionReconnected()
164 void createItemSyncInstanceIfMissing()
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() );
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*)) );
178 Q_ASSERT( mItemSyncer );
183 Q_SCRIPTABLE QString dumpToString()
const
187 QMetaObject::invokeMethod( const_cast<ResourceBase *>(q),
"dumpResourceToString", Qt::DirectConnection, Q_RETURN_ARG(QString, retVal) );
188 return scheduler->dumpToString() + QLatin1Char(
'\n') + retVal;
191 Q_SCRIPTABLE
void dump()
196 Q_SCRIPTABLE
void clear()
210 if ( collection.
remoteId().isEmpty() ) {
214 AgentBasePrivate::itemAdded( item, collection );
217 void itemChanged(
const Akonadi::Item& item,
const QSet< QByteArray >& partIdentifiers)
219 if ( item.remoteId().isEmpty() ) {
223 AgentBasePrivate::itemChanged( item, partIdentifiers );
226 void itemsFlagsChanged(
const Item::List& items,
const QSet< QByteArray >& addedFlags,
227 const QSet< QByteArray >& removedFlags)
229 if (addedFlags.isEmpty() && removedFlags.isEmpty() ) {
234 Item::List validItems;
235 foreach (
const Akonadi::Item &item, items ) {
236 if ( !item.remoteId().isEmpty() ) {
240 if ( validItems.isEmpty() ) {
245 AgentBasePrivate::itemsFlagsChanged( validItems, addedFlags, removedFlags );
248 void itemsTagsChanged(
const Item::List &items,
const QSet<Tag> &addedTags,
const QSet<Tag> &removedTags )
250 if ( addedTags.isEmpty() && removedTags.isEmpty() ) {
255 Item::List validItems;
256 foreach (
const Akonadi::Item &item, items ) {
257 if ( !item.remoteId().isEmpty() ) {
261 if ( validItems.isEmpty() ) {
266 AgentBasePrivate::itemsTagsChanged( validItems, addedTags, removedTags );
272 if ( item.remoteId().isEmpty() || destination.
remoteId().isEmpty() || destination == source ) {
276 AgentBasePrivate::itemMoved( item, source, destination );
279 void itemsMoved(
const Item::List& items,
const Collection& source,
const Collection& destination)
281 if ( destination.
remoteId().isEmpty() || destination == source ) {
286 Item::List validItems;
287 foreach (
const Akonadi::Item &item, items ) {
288 if ( !item.remoteId().isEmpty() ) {
292 if ( validItems.isEmpty() ) {
297 AgentBasePrivate::itemsMoved( validItems, source, destination );
300 void itemRemoved(
const Akonadi::Item& item)
302 if ( item.remoteId().isEmpty() ) {
306 AgentBasePrivate::itemRemoved( item );
309 void itemsRemoved(
const Item::List& items)
311 Item::List validItems;
312 foreach (
const Akonadi::Item &item, items ) {
313 if ( !item.remoteId().isEmpty() ) {
317 if ( validItems.isEmpty() ) {
322 AgentBasePrivate::itemsRemoved( validItems );
327 if ( parent.
remoteId().isEmpty() ) {
331 AgentBasePrivate::collectionAdded( collection, parent );
336 if ( collection.
remoteId().isEmpty() ) {
340 AgentBasePrivate::collectionChanged( collection );
343 void collectionChanged(
const Akonadi::Collection& collection,
const QSet< QByteArray >& partIdentifiers)
345 if ( collection.
remoteId().isEmpty() ) {
349 AgentBasePrivate::collectionChanged( collection, partIdentifiers );
355 if ( destination.
remoteId().isEmpty() || source == destination ) {
363 AgentBasePrivate::collectionRemoved( collection );
365 scheduler->taskDone();
368 scheduler->scheduleMoveReplay( collection, mover );
374 if ( collection.
remoteId().isEmpty() ) {
380 AgentBasePrivate::collectionMoved( collection, source, destination );
385 if ( collection.
remoteId().isEmpty() ) {
389 AgentBasePrivate::collectionRemoved( collection );
394 if ( !tag.isValid() ) {
399 AgentBasePrivate::tagAdded( tag );
404 if ( tag.remoteId().isEmpty() ) {
409 AgentBasePrivate::tagChanged( tag );
414 if ( tag.remoteId().isEmpty() ) {
419 AgentBasePrivate::tagRemoved( tag );
426 ResourceScheduler *scheduler;
431 bool mHierarchicalRid;
432 QTimer mProgressEmissionCompressor;
433 int mUnemittedProgress;
434 QMap<Akonadi::Collection::Id, QVariantMap> mUnemittedAdvancedStatus;
435 bool mAutomaticProgressReporting;
436 QPointer<RecursiveMover> m_recursiveMover;
440 :
AgentBase( new ResourceBasePrivate( this ), id )
444 new Akonadi__ResourceAdaptor(
this );
446 d->scheduler =
new ResourceScheduler(
this );
448 d->mChangeRecorder->setChangeRecordingEnabled(
true );
449 d->mChangeRecorder->setCollectionMoveTranslationEnabled(
false );
450 connect( d->mChangeRecorder, SIGNAL(changesAdded()),
451 d->scheduler, SLOT(scheduleChangeReplay()) );
453 d->mChangeRecorder->setResourceMonitored( d->mId.toLatin1() );
454 d->mChangeRecorder->fetchCollection(
true );
456 connect( d->scheduler, SIGNAL(executeFullSync()),
458 connect( d->scheduler, SIGNAL(executeCollectionTreeSync()),
464 connect( d->scheduler, SIGNAL(executeItemFetch(Akonadi::Item,QSet<QByteArray>)),
465 SLOT(slotPrepareItemRetrieval(Akonadi::Item)) );
466 connect( d->scheduler, SIGNAL(executeResourceCollectionDeletion()),
467 SLOT(slotDeleteResourceCollection()) );
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*)),
476 connect( d->scheduler, SIGNAL(fullSyncComplete()), SIGNAL(
synchronized()) );
478 connect( d->mChangeRecorder, SIGNAL(nothingToReplay()), d->scheduler, SLOT(
taskDone()) );
481 connect(
this, SIGNAL(
abortRequested()),
this, SLOT(slotAbortRequested()) );
482 connect(
this, SIGNAL(
synchronized()), d->scheduler, SLOT(
taskDone()) );
487 connect( &d->mProgressEmissionCompressor, SIGNAL(timeout()),
488 this, SLOT(slotDelayedEmitProgress()) );
490 d->scheduler->setOnline( d->mOnline );
491 if ( !d->mChangeRecorder->isEmpty() )
492 d->scheduler->scheduleChangeReplay();
496 connect( d->mChangeRecorder->session(), SIGNAL(reconnected()), SLOT(slotSessionReconnected()) );
505 d_func()->scheduler->scheduleFullSync();
518 QString ResourceBase::parseArguments(
int argc,
char **argv )
522 kDebug() <<
"Not enough arguments passed...";
526 for (
int i = 1; i < argc - 1; ++i ) {
527 if ( QLatin1String( argv[ i ] ) == QLatin1String(
"--identifier" ) )
528 identifier = QLatin1String( argv[ i + 1 ] );
531 if ( identifier.isEmpty() ) {
532 kDebug() <<
"Identifier argument missing";
536 const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
538 const QByteArray catalog = fi.baseName().toLatin1();
541 ki18nc(
"@title application name",
"Akonadi Resource" ), KDEPIMLIBS_VERSION,
542 ki18nc(
"@title application description",
"Akonadi Resource" ) );
544 KCmdLineOptions options;
545 options.add(
"identifier <argument>",
546 ki18nc(
"@label commandline option",
"Resource identifier" ) );
547 KCmdLineArgs::addCmdLineOptions( options );
554 QApplication::setQuitOnLastWindowClosed(
false );
555 KGlobal::locale()->insertCatalog( QLatin1String(
"libakonadi" ) );
556 int rv = kapp->exec();
561 void ResourceBasePrivate::slotAbortRequested()
565 scheduler->cancelQueues();
566 QMetaObject::invokeMethod( q,
"abortActivity" );
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();
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;
588 job->d_func()->setSilent(
true );
591 connect( job, SIGNAL(result(KJob*)), SLOT(slotDeliveryDone(KJob*)) );
594 void ResourceBasePrivate::slotDeliveryDone(KJob * job)
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() ) );
601 scheduler->currentTask().sendDBusReplies( job->error() ? job->errorString() : QString() );
602 scheduler->taskDone();
608 Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
611 d->scheduler->taskDone();
616 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionAttributesSyncDone(KJob*)) );
619 void ResourceBasePrivate::slotCollectionAttributesSyncDone(KJob * job)
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() ) );
626 emit q->attributesSynchronized( scheduler->currentTask().collection.id() );
627 scheduler->taskDone();
630 void ResourceBasePrivate::slotDeleteResourceCollection()
636 connect( job, SIGNAL(result(KJob*)), q, SLOT(slotDeleteResourceCollectionDone(KJob*)) );
639 void ResourceBasePrivate::slotDeleteResourceCollectionDone( KJob *job )
642 if ( job->error() ) {
643 emit q->error( job->errorString() );
644 scheduler->taskDone();
650 connect( job, SIGNAL(result(KJob*)), q, SLOT(slotCollectionDeletionDone(KJob*)) );
653 scheduler->taskDone();
658 void ResourceBasePrivate::slotCollectionDeletionDone( KJob *job )
661 if ( job->error() ) {
662 emit q->error( job->errorString() );
665 scheduler->taskDone();
672 connect( job, SIGNAL(result(KJob*)), scheduler, SLOT(taskDone()) );
683 job->d_func()->setClean();
687 connect( job, SIGNAL(finished(KJob*)),
this, SLOT(changeCommittedResult(KJob*)) );
693 connect( job, SIGNAL(result(KJob*)), SLOT(changeCommittedResult(KJob*)) );
696 void ResourceBasePrivate::changeCommittedResult( KJob *job )
699 if ( qobject_cast<CollectionModifyJob*>( job ) ) {
700 if ( job->error() ) {
701 emit q->error( i18nc(
"@info",
"Updating local collection failed: %1.", job->errorText() ) );
703 mChangeRecorder->d_ptr->invalidateCache( static_cast<CollectionModifyJob*>( job )->collection() );
715 connect( job, SIGNAL(result(KJob*)), SLOT(changeCommittedResult(KJob*)) );
718 bool ResourceBase::requestItemDelivery( qint64 uid,
const QString &remoteId,
719 const QString &mimeType,
const QStringList &parts )
721 return requestItemDeliveryV2( uid, remoteId, mimeType, parts ).isEmpty();
724 QString ResourceBase::requestItemDeliveryV2(qint64 uid,
const QString &remoteId,
const QString &mimeType,
const QStringList &_parts)
728 const QString errorMsg = i18nc(
"@info",
"Cannot fetch item in offline mode." );
729 emit
error( errorMsg );
733 setDelayedReply(
true );
736 item.setMimeType( mimeType );
737 item.setRemoteId( remoteId );
739 QSet<QByteArray> parts;
740 Q_FOREACH(
const QString &str, _parts )
741 parts.insert( str.toLatin1() );
743 d->scheduler->scheduleItemFetch( item, parts, message() );
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 ) {
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*)) );
762 d->mCollectionSyncer->setRemoteCollections( collections );
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 ) {
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*)) );
779 d->mCollectionSyncer->setRemoteCollections( changedCollections, removedCollections );
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 ) {
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*)) );
795 d->mCollectionSyncer->setStreamingEnabled( enable );
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" );
806 if ( d->mCollectionSyncer ) {
807 d->mCollectionSyncer->retrievalDone();
812 d->scheduler->taskDone();
816 void ResourceBasePrivate::slotCollectionSyncDone( KJob * job )
819 mCollectionSyncer = 0;
820 if ( job->error() ) {
822 emit q->error( job->errorString() );
824 if ( scheduler->currentTask().type == ResourceScheduler::SyncAll ) {
826 list->
setFetchScope( q->changeRecorder()->collectionFetchScope() );
828 q->connect( list, SIGNAL(result(KJob*)), q, SLOT(slotLocalListDone(KJob*)) );
830 }
else if ( scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ) {
831 scheduler->scheduleCollectionTreeSyncCompletion();
834 scheduler->taskDone();
837 void ResourceBasePrivate::slotLocalListDone( KJob * job )
840 if ( job->error() ) {
841 emit q->error( job->errorString() );
845 scheduler->scheduleSync( col );
847 scheduler->scheduleFullSyncCompletion();
849 scheduler->taskDone();
852 void ResourceBasePrivate::slotSynchronizeCollection(
const Collection &col )
860 if ( !contentTypes.isEmpty() || col.
isVirtual() ) {
861 if ( mAutomaticProgressReporting ) {
867 scheduler->taskDone();
870 void ResourceBasePrivate::slotSynchronizeCollectionAttributes(
const Collection &col )
873 QMetaObject::invokeMethod( q,
"retrieveCollectionAttributes", Q_ARG(
Akonadi::Collection, col ) );
876 void ResourceBasePrivate::slotPrepareItemRetrieval(
const Akonadi::Item &item )
884 const QSet<QByteArray> attributes = q->changeRecorder()->itemFetchScope().attributes();
885 foreach (
const QByteArray &attribute, attributes )
888 q->connect( fetch, SIGNAL(result(KJob*)), SLOT(slotPrepareItemRetrievalResult(KJob*)) );
891 void ResourceBasePrivate::slotPrepareItemRetrievalResult( KJob* job )
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() );
902 if ( fetch->
items().count() != 1 ) {
903 q->cancelTask( i18n(
"The requested item no longer exists" ) );
906 const Item item = fetch->
items().first();
907 const QSet<QByteArray> parts = scheduler->currentTask().itemParts;
908 if ( !q->retrieveItem( item, parts ) )
912 void ResourceBasePrivate::slotRecursiveMoveReplay(
RecursiveMover *mover )
916 Q_ASSERT( !m_recursiveMover );
917 m_recursiveMover = mover;
918 connect( mover, SIGNAL(result(KJob*)), q, SLOT(slotRecursiveMoveReplayResult(KJob*)) );
922 void ResourceBasePrivate::slotRecursiveMoveReplayResult( KJob *job )
925 m_recursiveMover = 0;
927 if ( job->error() ) {
939 if ( d->mItemSyncer ) {
940 d->mItemSyncer->deliveryDone();
944 d->scheduler->taskDone();
951 d->scheduler->scheduleResourceCollectionDeletion();
957 d->scheduler->scheduleCacheInvalidation( collection );
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;
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;
980 d_func()->scheduler->scheduleCollectionTreeSync();
986 switch ( d->scheduler->currentTask().type ) {
987 case ResourceScheduler::FetchItem:
990 case ResourceScheduler::ChangeReplay:
991 d->changeProcessed();
993 case ResourceScheduler::SyncCollectionTree:
994 case ResourceScheduler::SyncAll:
995 if ( d->mCollectionSyncer )
996 d->mCollectionSyncer->rollback();
998 d->scheduler->taskDone();
1000 case ResourceScheduler::SyncCollection:
1001 if ( d->mItemSyncer ) {
1002 d->mItemSyncer->rollback();
1004 d->scheduler->taskDone();
1008 d->scheduler->taskDone();
1022 d->scheduler->deferTask();
1027 d_func()->scheduler->setOnline( state );
1040 job->setProperty(
"recursive", recursive );
1041 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListDone(KJob*)) );
1044 void ResourceBasePrivate::slotCollectionListDone( KJob *job )
1046 if ( !job->error() ) {
1048 if ( !list.isEmpty() ) {
1049 if ( job->property(
"recursive" ).toBool() ) {
1050 Q_FOREACH (
const Collection &collection, list ) {
1051 scheduler->scheduleSync( collection );
1054 scheduler->scheduleSync( list.first() );
1066 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListForAttributesDone(KJob*)) );
1069 void ResourceBasePrivate::slotCollectionListForAttributesDone( KJob *job )
1071 if ( !job->error() ) {
1073 if ( !list.isEmpty() ) {
1075 scheduler->scheduleAttributesSync( col );
1086 if ( d->mItemSyncer ) {
1087 d->mItemSyncer->setTotalItems( amount );
1094 d->createItemSyncInstanceIfMissing();
1095 if ( d->mItemSyncer ) {
1096 d->mItemSyncer->setStreamingEnabled( enable );
1103 d->createItemSyncInstanceIfMissing();
1104 if ( d->mItemSyncer ) {
1105 d->mItemSyncer->setFullSyncItems( items );
1110 const Item::List &removedItems )
1113 d->createItemSyncInstanceIfMissing();
1114 if ( d->mItemSyncer ) {
1115 d->mItemSyncer->setIncrementalSyncItems( changedItems, removedItems );
1119 void ResourceBasePrivate::slotItemSyncDone( KJob *job )
1124 emit q->error( job->errorString() );
1126 scheduler->taskDone();
1129 void ResourceBasePrivate::slotDelayedEmitProgress()
1132 if ( mAutomaticProgressReporting ) {
1133 emit q->percent( mUnemittedProgress );
1135 Q_FOREACH(
const QVariantMap &statusMap, mUnemittedAdvancedStatus ) {
1136 emit q->advancedStatus( statusMap );
1139 mUnemittedProgress = 0;
1140 mUnemittedAdvancedStatus.clear();
1143 void ResourceBasePrivate::slotPercent( KJob *job,
unsigned long percent )
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 ) );
1154 mUnemittedAdvancedStatus[collection.
id()] = statusMap;
1157 if ( percent == 100 ) {
1158 mProgressEmissionCompressor.stop();
1159 slotDelayedEmitProgress();
1160 }
else if ( !mProgressEmissionCompressor.isActive() ) {
1161 mProgressEmissionCompressor.start();
1168 d->mHierarchicalRid = enable;
1174 d->scheduler->scheduleCustomTask( receiver, method, argument, priority );
1180 d->scheduler->taskDone();
1196 d->mItemTransactionMode = mode;
1202 if ( !d->mItemSyncFetchScope )
1204 *(d->mItemSyncFetchScope) = fetchScope;
1210 d->mAutomaticProgressReporting = enabled;
1216 return d->dumpNotificationListToString();
1222 return d->dumpToString();
1228 return d->dumpMemoryInfo();
1234 return d->dumpMemoryInfoToString();
1237 #include "resourcebase.moc"
1238 #include "moc_resourcebase.cpp"
Job that modifies a collection in the Akonadi storage.
Helper class for expanding inter-resource collection moves inside ResourceBase.
void fetchAttribute(const QByteArray &type, bool fetch=true)
Sets whether the attribute of the given type should be fetched.
void retrieveCollectionAttributes(const Akonadi::Collection &collection)
Retrieve the attributes of a single collection from the backend.
void abortActivity()
Abort any activity in progress in the backend.
void disableRevisionCheck()
Disables the check of the revision number.
void percent(int progress)
This signal should be emitted whenever the progress of an action in the agent (e.g.
virtual void retrieveCollections()=0
Retrieve the collection tree from the remote server and supply it via collectionsRetrieved() or colle...
Collection::List collections() const
Returns the list of fetched collection.
void abortRequested()
Emitted when another application has remotely asked the agent to abort its current operation...
QString dumpNotificationListToString() const
Dump the contents of the current ChangeReplay.
QString displayName() const
Returns the display name (EntityDisplayAttribute::displayName()) if set, and Collection::name() other...
void attributesSynchronized(qlonglong collectionId)
Emitted when a collection attributes synchronization has been completed.
void setUpdateGid(bool update)
Sets whether the GID shall be updated either from the gid parameter or by extracting it from the payl...
ChangeRecorder * changeRecorder() const
Returns the Akonadi::ChangeRecorder object used for monitoring.
void collectionsRetrievalDone()
Call this method to indicate you finished synchronizing the collection tree.
void setAutomaticProgressReporting(bool enabled)
Enable or disable automatic progress reporting.
void setCollectionStreamingEnabled(bool enable)
Enable collection streaming, that is collections don't have to be delivered at once as result of a re...
void synchronizeCollectionAttributes(qint64 id)
This method is called whenever the collection with the given id shall have its attributes synchronize...
Only list direct sub-collections of the base collection.
CollectionFetchScope & fetchScope()
Returns the collection fetch scope.
void setResource(const QString &resource)
Sets a resource filter, that is only collections owned by the specified resource are retrieved...
Represents a collection of PIM items.
Job that fetches collections from the Akonadi storage.
void itemsRetrieved(const Item::List &items)
Call this method to supply the full collection listing from the remote server.
static QString virtualMimeType()
Returns the mimetype used for virtual collections.
void setAgentName(const QString &name)
This method is used to set the name of the agent.
void agentNameChanged(const QString &name)
This signal is emitted whenever the name of the agent has changed.
static QString mimeType()
Returns the mimetype used for collections.
void setItemSynchronizationFetchScope(const ItemFetchScope &fetchScope)
Set the fetch scope applied for item synchronization.
void synchronizeCollectionTree()
Refetches the Collections.
void setTotalItems(int amount)
Call this method when you want to use the itemsRetrieved() method in streaming mode and indicate the ...
void nameChanged(const QString &name)
This signal is emitted whenever the name of the resource has changed.
void changesCommitted(const Item::List &items)
Resets the dirty flag of all given items and updates remote ids.
Item::List items() const
Returns the fetched items.
The base class for all Akonadi agents and resources.
Only fetch the base collection.
Syncs between items known to a client (usually a resource) and the Akonadi storage.
void itemsRetrievalDone()
Call this method to indicate you finished synchronizing the current collection.
void deferTask()
Stops the execution of the current task and continues with the next one.
ItemFetchScope & fetchScope()
Returns the item fetch scope.
SchedulePriority
Describes the scheduling priority of a task that has been queued for execution.
void synchronize()
This method is called whenever the resource should start synchronize all data.
void error(const QString &message)
This signal shall be used to report errors.
virtual int status() const
This method returns the current status code of the agent.
void clearCache()
Call this method to remove all items and collections of the resource from the server cache...
void collectionAttributesRetrieved(const Collection &collection)
Call this method from retrieveCollectionAttributes() once the result is available.
QString remoteId() const
Returns the remote id of the entity.
void collectionsRetrieved(const Collection::List &collections)
Call this to supply the full folder tree retrieved from the remote server.
static Collection root()
Returns the root collection.
Item currentItem() const
Returns the item that is currently retrieved.
Job that deletes a collection in the Akonadi storage.
void itemsRetrievedIncremental(const Item::List &changedItems, const Item::List &removedItems)
Call this method to supply incrementally retrieved items from the remote server.
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...
void doSetOnline(bool online)
Inherited from AgentBase.
Id id() const
Returns the unique identifier of the entity.
void collectionTreeSynchronized()
Emitted when a collection tree synchronization has been completed.
void changeProcessed()
Marks the current change as processes and replays the next change if change recording is enabled (noo...
void setFetchScope(const CollectionFetchScope &fetchScope)
Sets the collection fetch scope.
void synchronizeCollection(qint64 id)
This method is called whenever the collection with the given id shall be synchronized.
Specifies which parts of an item should be fetched from the Akonadi storage.
QString identifier() const
Returns the instance identifier of this agent.
void setAncestorRetrieval(AncestorRetrieval ancestorDepth)
Sets how many levels of ancestor collections should be included in the retrieval. ...
void setItemTransactionMode(ItemSync::TransactionMode mode)
Set transaction mode for item sync'ing.
Helper job to invalidate item cache for an entire collection.
void setIgnorePayload(bool ignore)
Sets whether the payload of the modified item shall be omitted from transmission to the Akonadi stora...
TransactionMode
Transaction mode used by ItemSync.
void changeCommitted(const Item &item)
Resets the dirty flag of the given item and updates the remote id.
void dumpMemoryInfo() const
Dumps memory usage information to stdout.
void setHierarchicalRemoteIdentifiersEnabled(bool enable)
Indicate the use of hierarchical remote identifiers.
bool isOnline() const
Returns whether the agent is currently online.
void itemRetrieved(const Item &item)
Call this method from retrieveItem() once the result is available.
void setCollection(const Akonadi::Collection &collection, const Akonadi::Collection &parentCollection)
Set the collection that is actually moved.
Job that modifies an existing item in the Akonadi storage.
Job that fetches items from the Akonadi storage.
Job that selects a resource context for remote identifier based operations.
Job that modifies a tag in the Akonadi storage.
~ResourceBase()
Destroys the base resource.
void changeProcessed()
Removes the previously emitted change from the records.
QStringList contentMimeTypes() const
Returns a list of possible content mimetypes, e.g.
static int init(int argc, char **argv)
Use this method in the main function of your resource application to initialize your resource subclas...
void setItemStreamingEnabled(bool enable)
Enable item streaming.
QString name() const
Returns the name of the resource.
void taskDone()
Indicate that the current task is finished.
void cancelTask()
Stops the execution of the current task and continues with the next one.
bool isEmpty() const
Returns whether there are recorded changes.
Collection currentCollection() const
Returns the collection that is currently synchronized.
QString resource() const
Returns the identifier of the resource owning the collection.
QString agentName() const
Returns the name of the agent.
The user canceld this job.
ResourceBase(const QString &id)
Creates a base resource.
The agent is working on something.
bool isValid() const
Returns whether the entity is valid.
void setTransactionMode(TransactionMode mode)
Set the transaction mode to use for this sync.
void collectionsRetrievedIncremental(const Collection::List &changedCollections, const Collection::List &removedCollections)
Call this to supply incrementally retrieved collections from the remote server.
static QString addNamespace(const QString &string)
Adds the multi-instance namespace to string if required (with '_' as separator).
void setName(const QString &name)
This method is used to set the name of the resource.
List all sub-collections.
QString dumpMemoryInfoToString() const
Returns a string with memory usage information.
QList< Collection > List
Describes a list of collections.
The base class for all Akonadi resources.
bool isVirtual() const
Returns whether the collection is virtual, for example a search collection.
QString dumpSchedulerToString() const
Dump the state of the scheduler.
void scheduleCustomTask(QObject *receiver, const char *method, const QVariant &argument, SchedulePriority priority=Append)
Schedules a custom task in the internal scheduler.
void setCacheOnly(bool cacheOnly)
Sets whether payload data should be requested from remote sources or just from the local cache...
void invalidateCache(const Collection &collection)
Call this method to invalidate all cached content in collection.