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>
55 #include <QtCore/QDebug>
56 #include <QtCore/QDir>
57 #include <QtCore/QHash>
58 #include <QtCore/QSettings>
59 #include <QtCore/QTimer>
60 #include <QApplication>
61 #include <QtDBus/QtDBus>
63 using namespace Akonadi;
68 Q_CLASSINFO(
"D-Bus Interface",
"org.kde.dfaure" )
75 mItemSyncFetchScope( 0 ),
76 mItemTransactionMode(
ItemSync::SingleTransaction ),
77 mCollectionSyncer( 0 ),
78 mHierarchicalRid( false ),
79 mUnemittedProgress( 0 ),
80 mAutomaticProgressReporting( true )
82 Internal::setClientType( Internal::Resource );
83 mStatusMessage = defaultReadyMessage();
84 mProgressEmissionCompressor.setInterval( 1000 );
85 mProgressEmissionCompressor.setSingleShot(
true );
88 ~ResourceBasePrivate()
90 delete mItemSyncFetchScope;
98 if ( !DBusConnectionPool::threadConnection().registerService( serviceId ) ) {
99 QString reason = DBusConnectionPool::threadConnection().lastError().message();
100 if ( reason.isEmpty() ) {
101 reason = QString::fromLatin1(
"this service is probably running already." );
103 kError() <<
"Unable to register service" << serviceId <<
"at D-Bus:" << reason;
105 if ( QThread::currentThread() == QCoreApplication::instance()->thread() )
106 QCoreApplication::instance()->exit(1);
109 AgentBasePrivate::delayedInit();
113 virtual void changeProcessed()
115 if ( m_recursiveMover ) {
116 m_recursiveMover->changeProcessed();
117 QTimer::singleShot( 0, m_recursiveMover, SLOT(replayNext()) );
122 if ( !mChangeRecorder->
isEmpty() )
123 scheduler->scheduleChangeReplay();
124 scheduler->taskDone();
127 void slotAbortRequested();
129 void slotDeliveryDone( KJob* job );
130 void slotCollectionSyncDone( KJob *job );
131 void slotLocalListDone( KJob *job );
132 void slotSynchronizeCollection(
const Collection &col );
133 void slotCollectionListDone( KJob *job );
134 void slotSynchronizeCollectionAttributes(
const Collection &col );
135 void slotCollectionListForAttributesDone( KJob *job );
136 void slotCollectionAttributesSyncDone( KJob *job );
138 void slotItemSyncDone( KJob *job );
140 void slotPercent( KJob* job,
unsigned long percent );
141 void slotDelayedEmitProgress();
142 void slotDeleteResourceCollection();
143 void slotDeleteResourceCollectionDone( KJob *job );
144 void slotCollectionDeletionDone( KJob *job );
148 void slotPrepareItemRetrieval(
const Akonadi::Item &item );
149 void slotPrepareItemRetrievalResult( KJob* job );
151 void changeCommittedResult( KJob* job );
154 void slotRecursiveMoveReplayResult( KJob *job );
156 void slotSessionReconnected()
163 void createItemSyncInstanceIfMissing()
166 Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::SyncCollection,
167 "createItemSyncInstance",
"Calling items retrieval methods although no item retrieval is in progress" );
168 if ( !mItemSyncer ) {
169 mItemSyncer =
new ItemSync( q->currentCollection() );
171 if ( mItemSyncFetchScope )
172 mItemSyncer->setFetchScope( *mItemSyncFetchScope );
173 mItemSyncer->setProperty(
"collection", QVariant::fromValue( q->currentCollection() ) );
174 connect( mItemSyncer, SIGNAL(percent(KJob*,ulong)), q, SLOT(slotPercent(KJob*,ulong)) );
175 connect( mItemSyncer, SIGNAL(result(KJob*)), q, SLOT(slotItemSyncDone(KJob*)) );
177 Q_ASSERT( mItemSyncer );
182 Q_SCRIPTABLE QString dumpToString()
const
186 QMetaObject::invokeMethod( const_cast<ResourceBase *>(q),
"dumpResourceToString", Qt::DirectConnection, Q_RETURN_ARG(QString, retVal) );
187 return scheduler->dumpToString() + QLatin1Char(
'\n') + retVal;
190 Q_SCRIPTABLE
void dump()
195 Q_SCRIPTABLE
void clear()
209 if ( collection.
remoteId().isEmpty() ) {
213 AgentBasePrivate::itemAdded( item, collection );
216 void itemChanged(
const Akonadi::Item& item,
const QSet< QByteArray >& partIdentifiers)
218 if ( item.remoteId().isEmpty() ) {
222 AgentBasePrivate::itemChanged( item, partIdentifiers );
225 void itemsFlagsChanged(
const Item::List& items,
const QSet< QByteArray >& addedFlags,
226 const QSet< QByteArray >& removedFlags)
228 if (addedFlags.isEmpty() && removedFlags.isEmpty() ) {
233 Item::List validItems;
234 foreach (
const Akonadi::Item &item, items ) {
235 if ( !item.remoteId().isEmpty() ) {
239 if ( validItems.isEmpty() ) {
244 AgentBasePrivate::itemsFlagsChanged( validItems, addedFlags, removedFlags );
250 if ( item.remoteId().isEmpty() || destination.
remoteId().isEmpty() || destination == source ) {
254 AgentBasePrivate::itemMoved( item, source, destination );
257 void itemsMoved(
const Item::List& items,
const Collection& source,
const Collection& destination)
259 if ( destination.
remoteId().isEmpty() || destination == source ) {
264 Item::List validItems;
265 foreach (
const Akonadi::Item &item, items ) {
266 if ( !item.remoteId().isEmpty() ) {
270 if ( validItems.isEmpty() ) {
275 AgentBasePrivate::itemsMoved( validItems, source, destination );
278 void itemRemoved(
const Akonadi::Item& item)
280 if ( item.remoteId().isEmpty() ) {
284 AgentBasePrivate::itemRemoved( item );
287 void itemsRemoved(
const Item::List& items)
289 Item::List validItems;
290 foreach (
const Akonadi::Item &item, items ) {
291 if ( !item.remoteId().isEmpty() ) {
295 if ( validItems.isEmpty() ) {
300 AgentBasePrivate::itemsRemoved( validItems );
305 if ( parent.
remoteId().isEmpty() ) {
309 AgentBasePrivate::collectionAdded( collection, parent );
314 if ( collection.
remoteId().isEmpty() ) {
318 AgentBasePrivate::collectionChanged( collection );
321 void collectionChanged(
const Akonadi::Collection& collection,
const QSet< QByteArray >& partIdentifiers)
323 if ( collection.
remoteId().isEmpty() ) {
327 AgentBasePrivate::collectionChanged( collection, partIdentifiers );
333 if ( destination.
remoteId().isEmpty() || source == destination ) {
341 AgentBasePrivate::collectionRemoved( collection );
343 scheduler->taskDone();
346 scheduler->scheduleMoveReplay( collection, mover );
352 if ( collection.
remoteId().isEmpty() ) {
358 AgentBasePrivate::collectionMoved( collection, source, destination );
363 if ( collection.
remoteId().isEmpty() ) {
367 AgentBasePrivate::collectionRemoved( collection );
374 ResourceScheduler *scheduler;
379 bool mHierarchicalRid;
380 QTimer mProgressEmissionCompressor;
381 int mUnemittedProgress;
382 QMap<Akonadi::Collection::Id, QVariantMap> mUnemittedAdvancedStatus;
383 bool mAutomaticProgressReporting;
384 QPointer<RecursiveMover> m_recursiveMover;
388 :
AgentBase( new ResourceBasePrivate( this ), id )
392 new Akonadi__ResourceAdaptor(
this );
394 d->scheduler =
new ResourceScheduler(
this );
396 d->mChangeRecorder->setChangeRecordingEnabled(
true );
397 d->mChangeRecorder->setCollectionMoveTranslationEnabled(
false );
398 connect( d->mChangeRecorder, SIGNAL(changesAdded()),
399 d->scheduler, SLOT(scheduleChangeReplay()) );
401 d->mChangeRecorder->setResourceMonitored( d->mId.toLatin1() );
402 d->mChangeRecorder->fetchCollection(
true );
404 connect( d->scheduler, SIGNAL(executeFullSync()),
406 connect( d->scheduler, SIGNAL(executeCollectionTreeSync()),
412 connect( d->scheduler, SIGNAL(executeItemFetch(Akonadi::Item,QSet<QByteArray>)),
413 SLOT(slotPrepareItemRetrieval(Akonadi::Item)) );
414 connect( d->scheduler, SIGNAL(executeResourceCollectionDeletion()),
415 SLOT(slotDeleteResourceCollection()) );
418 connect( d->scheduler, SIGNAL(
status(
int,QString)),
419 SIGNAL(
status(
int,QString)) );
420 connect( d->scheduler, SIGNAL(executeChangeReplay()),
421 d->mChangeRecorder, SLOT(replayNext()) );
422 connect( d->scheduler, SIGNAL(executeRecursiveMoveReplay(
RecursiveMover*)),
424 connect( d->scheduler, SIGNAL(fullSyncComplete()), SIGNAL(
synchronized()) );
426 connect( d->mChangeRecorder, SIGNAL(nothingToReplay()), d->scheduler, SLOT(
taskDone()) );
429 connect(
this, SIGNAL(
abortRequested()),
this, SLOT(slotAbortRequested()) );
430 connect(
this, SIGNAL(
synchronized()), d->scheduler, SLOT(
taskDone()) );
435 connect( &d->mProgressEmissionCompressor, SIGNAL(timeout()),
436 this, SLOT(slotDelayedEmitProgress()) );
438 d->scheduler->setOnline( d->mOnline );
439 if ( !d->mChangeRecorder->isEmpty() )
440 d->scheduler->scheduleChangeReplay();
444 connect( d->mChangeRecorder->session(), SIGNAL(reconnected()), SLOT(slotSessionReconnected()) );
453 d_func()->scheduler->scheduleFullSync();
466 QString ResourceBase::parseArguments(
int argc,
char **argv )
470 kDebug() <<
"Not enough arguments passed...";
474 for (
int i = 1; i < argc - 1; ++i ) {
475 if ( QLatin1String( argv[ i ] ) == QLatin1String(
"--identifier" ) )
476 identifier = QLatin1String( argv[ i + 1 ] );
479 if ( identifier.isEmpty() ) {
480 kDebug() <<
"Identifier argument missing";
484 const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
486 const QByteArray catalog = fi.baseName().toLatin1();
489 ki18nc(
"@title application name",
"Akonadi Resource" ), KDEPIMLIBS_VERSION,
490 ki18nc(
"@title application description",
"Akonadi Resource" ) );
492 KCmdLineOptions options;
493 options.add(
"identifier <argument>",
494 ki18nc(
"@label commandline option",
"Resource identifier" ) );
495 KCmdLineArgs::addCmdLineOptions( options );
502 QApplication::setQuitOnLastWindowClosed(
false );
503 KGlobal::locale()->insertCatalog( QLatin1String(
"libakonadi" ) );
504 int rv = kapp->exec();
509 void ResourceBasePrivate::slotAbortRequested()
513 scheduler->cancelQueues();
514 QMetaObject::invokeMethod( q,
"abortActivity" );
520 Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::FetchItem );
521 if ( !item.isValid() ) {
522 d->scheduler->currentTask().sendDBusReplies( i18nc(
"@info",
"Invalid item retrieved" ) );
523 d->scheduler->taskDone();
528 QSet<QByteArray> requestedParts = d->scheduler->currentTask().itemParts;
529 foreach (
const QByteArray &part, requestedParts ) {
530 if ( !item.loadedPayloadParts().contains( part ) ) {
531 kWarning() <<
"Item does not provide part" << part;
538 connect( job, SIGNAL(result(KJob*)), SLOT(slotDeliveryDone(KJob*)) );
541 void ResourceBasePrivate::slotDeliveryDone(KJob * job)
544 Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::FetchItem );
545 if ( job->error() ) {
546 emit q->error( i18nc(
"@info",
"Error while creating item: %1", job->errorString() ) );
548 scheduler->currentTask().sendDBusReplies( job->error() ? job->errorString() : QString() );
549 scheduler->taskDone();
555 Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
558 d->scheduler->taskDone();
563 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionAttributesSyncDone(KJob*)) );
566 void ResourceBasePrivate::slotCollectionAttributesSyncDone(KJob * job)
569 Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
570 if ( job->error() ) {
571 emit q->error( i18nc(
"@info",
"Error while updating collection: %1", job->errorString() ) );
573 emit q->attributesSynchronized( scheduler->currentTask().collection.id() );
574 scheduler->taskDone();
577 void ResourceBasePrivate::slotDeleteResourceCollection()
583 connect( job, SIGNAL(result(KJob*)), q, SLOT(slotDeleteResourceCollectionDone(KJob*)) );
586 void ResourceBasePrivate::slotDeleteResourceCollectionDone( KJob *job )
589 if ( job->error() ) {
590 emit q->error( job->errorString() );
591 scheduler->taskDone();
597 connect( job, SIGNAL(result(KJob*)), q, SLOT(slotCollectionDeletionDone(KJob*)) );
600 scheduler->taskDone();
605 void ResourceBasePrivate::slotCollectionDeletionDone( KJob *job )
608 if ( job->error() ) {
609 emit q->error( job->errorString() );
612 scheduler->taskDone();
619 connect( job, SIGNAL(result(KJob*)), scheduler, SLOT(taskDone()) );
630 job->d_func()->setClean();
633 connect( job, SIGNAL(finished(KJob*)),
this, SLOT(changeCommittedResult(KJob*)) );
639 connect( job, SIGNAL(result(KJob*)), SLOT(changeCommittedResult(KJob*)) );
642 void ResourceBasePrivate::changeCommittedResult( KJob *job )
645 if ( qobject_cast<CollectionModifyJob*>( job ) ) {
646 if ( job->error() ) {
647 emit q->error( i18nc(
"@info",
"Updating local collection failed: %1.", job->errorText() ) );
649 mChangeRecorder->d_ptr->invalidateCache( static_cast<CollectionModifyJob*>( job )->collection() );
658 bool ResourceBase::requestItemDelivery( qint64 uid,
const QString &remoteId,
659 const QString &mimeType,
const QStringList &parts )
661 return requestItemDeliveryV2( uid, remoteId, mimeType, parts ).isEmpty();
664 QString ResourceBase::requestItemDeliveryV2(qint64 uid,
const QString &remoteId,
const QString &mimeType,
const QStringList &_parts)
668 const QString errorMsg = i18nc(
"@info",
"Cannot fetch item in offline mode." );
669 emit
error( errorMsg );
673 setDelayedReply(
true );
676 item.setMimeType( mimeType );
677 item.setRemoteId( remoteId );
679 QSet<QByteArray> parts;
680 Q_FOREACH(
const QString &str, _parts )
681 parts.insert( str.toLatin1() );
683 d->scheduler->scheduleItemFetch( item, parts, message() );
692 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
693 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
694 "ResourceBase::collectionsRetrieved()",
695 "Calling collectionsRetrieved() although no collection retrieval is in progress" );
696 if ( !d->mCollectionSyncer ) {
698 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
699 connect( d->mCollectionSyncer, SIGNAL(
percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
700 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
702 d->mCollectionSyncer->setRemoteCollections( collections );
709 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
710 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
711 "ResourceBase::collectionsRetrievedIncremental()",
712 "Calling collectionsRetrievedIncremental() although no collection retrieval is in progress" );
713 if ( !d->mCollectionSyncer ) {
715 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
716 connect( d->mCollectionSyncer, SIGNAL(
percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
717 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
719 d->mCollectionSyncer->setRemoteCollections( changedCollections, removedCollections );
725 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
726 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
727 "ResourceBase::setCollectionStreamingEnabled()",
728 "Calling setCollectionStreamingEnabled() although no collection retrieval is in progress" );
729 if ( !d->mCollectionSyncer ) {
731 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
732 connect( d->mCollectionSyncer, SIGNAL(
percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
733 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
735 d->mCollectionSyncer->setStreamingEnabled( enable );
741 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
742 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
743 "ResourceBase::collectionsRetrievalDone()",
744 "Calling collectionsRetrievalDone() although no collection retrieval is in progress" );
746 if ( d->mCollectionSyncer ) {
747 d->mCollectionSyncer->retrievalDone();
752 d->scheduler->taskDone();
756 void ResourceBasePrivate::slotCollectionSyncDone( KJob * job )
759 mCollectionSyncer = 0;
760 if ( job->error() ) {
762 emit q->error( job->errorString() );
764 if ( scheduler->currentTask().type == ResourceScheduler::SyncAll ) {
766 list->
setFetchScope( q->changeRecorder()->collectionFetchScope() );
768 q->connect( list, SIGNAL(result(KJob*)), q, SLOT(slotLocalListDone(KJob*)) );
770 }
else if ( scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ) {
771 scheduler->scheduleCollectionTreeSyncCompletion();
774 scheduler->taskDone();
777 void ResourceBasePrivate::slotLocalListDone( KJob * job )
780 if ( job->error() ) {
781 emit q->error( job->errorString() );
785 scheduler->scheduleSync( col );
787 scheduler->scheduleFullSyncCompletion();
789 scheduler->taskDone();
792 void ResourceBasePrivate::slotSynchronizeCollection(
const Collection &col )
800 if ( !contentTypes.isEmpty() || col.
isVirtual() ) {
801 if ( mAutomaticProgressReporting ) {
807 scheduler->taskDone();
810 void ResourceBasePrivate::slotSynchronizeCollectionAttributes(
const Collection &col )
813 QMetaObject::invokeMethod( q,
"retrieveCollectionAttributes", Q_ARG(
Akonadi::Collection, col ) );
816 void ResourceBasePrivate::slotPrepareItemRetrieval(
const Akonadi::Item &item )
824 const QSet<QByteArray> attributes = q->changeRecorder()->itemFetchScope().attributes();
825 foreach (
const QByteArray &attribute, attributes )
828 q->connect( fetch, SIGNAL(result(KJob*)), SLOT(slotPrepareItemRetrievalResult(KJob*)) );
831 void ResourceBasePrivate::slotPrepareItemRetrievalResult( KJob* job )
834 Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::FetchItem,
835 "ResourceBasePrivate::slotPrepareItemRetrievalResult()",
836 "Preparing item retrieval although no item retrieval is in progress" );
837 if ( job->error() ) {
838 q->cancelTask( job->errorText() );
842 if ( fetch->
items().count() != 1 ) {
843 q->cancelTask( i18n(
"The requested item no longer exists" ) );
846 const Item item = fetch->
items().first();
847 const QSet<QByteArray> parts = scheduler->currentTask().itemParts;
848 if ( !q->retrieveItem( item, parts ) )
852 void ResourceBasePrivate::slotRecursiveMoveReplay(
RecursiveMover *mover )
856 Q_ASSERT( !m_recursiveMover );
857 m_recursiveMover = mover;
858 connect( mover, SIGNAL(result(KJob*)), q, SLOT(slotRecursiveMoveReplayResult(KJob*)) );
862 void ResourceBasePrivate::slotRecursiveMoveReplayResult( KJob *job )
865 m_recursiveMover = 0;
867 if ( job->error() ) {
879 if ( d->mItemSyncer ) {
880 d->mItemSyncer->deliveryDone();
884 d->scheduler->taskDone();
891 d->scheduler->scheduleResourceCollectionDeletion();
897 d->scheduler->scheduleCacheInvalidation( collection );
903 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection ,
904 "ResourceBase::currentCollection()",
905 "Trying to access current collection although no item retrieval is in progress" );
906 return d->currentCollection;
912 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::FetchItem ,
913 "ResourceBase::currentItem()",
914 "Trying to access current item although no item retrieval is in progress" );
915 return d->scheduler->currentTask().item;
920 d_func()->scheduler->scheduleCollectionTreeSync();
926 switch ( d->scheduler->currentTask().type ) {
927 case ResourceScheduler::FetchItem:
930 case ResourceScheduler::ChangeReplay:
931 d->changeProcessed();
933 case ResourceScheduler::SyncCollectionTree:
934 case ResourceScheduler::SyncAll:
935 if ( d->mCollectionSyncer )
936 d->mCollectionSyncer->rollback();
938 d->scheduler->taskDone();
940 case ResourceScheduler::SyncCollection:
941 if ( d->mItemSyncer ) {
942 d->mItemSyncer->rollback();
944 d->scheduler->taskDone();
948 d->scheduler->taskDone();
962 d->scheduler->deferTask();
967 d_func()->scheduler->setOnline( state );
980 job->setProperty(
"recursive", recursive );
981 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListDone(KJob*)) );
984 void ResourceBasePrivate::slotCollectionListDone( KJob *job )
986 if ( !job->error() ) {
988 if ( !list.isEmpty() ) {
989 if ( job->property(
"recursive" ).toBool() ) {
990 Q_FOREACH (
const Collection &collection, list ) {
991 scheduler->scheduleSync( collection );
994 scheduler->scheduleSync( list.first() );
1006 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListForAttributesDone(KJob*)) );
1009 void ResourceBasePrivate::slotCollectionListForAttributesDone( KJob *job )
1011 if ( !job->error() ) {
1013 if ( !list.isEmpty() ) {
1015 scheduler->scheduleAttributesSync( col );
1026 if ( d->mItemSyncer ) {
1027 d->mItemSyncer->setTotalItems( amount );
1034 d->createItemSyncInstanceIfMissing();
1035 if ( d->mItemSyncer ) {
1036 d->mItemSyncer->setStreamingEnabled( enable );
1043 d->createItemSyncInstanceIfMissing();
1044 if ( d->mItemSyncer ) {
1045 d->mItemSyncer->setFullSyncItems( items );
1050 const Item::List &removedItems )
1053 d->createItemSyncInstanceIfMissing();
1054 if ( d->mItemSyncer ) {
1055 d->mItemSyncer->setIncrementalSyncItems( changedItems, removedItems );
1059 void ResourceBasePrivate::slotItemSyncDone( KJob *job )
1064 emit q->error( job->errorString() );
1066 scheduler->taskDone();
1069 void ResourceBasePrivate::slotDelayedEmitProgress()
1072 if ( mAutomaticProgressReporting ) {
1073 emit q->percent( mUnemittedProgress );
1075 Q_FOREACH(
const QVariantMap &statusMap, mUnemittedAdvancedStatus ) {
1076 emit q->advancedStatus( statusMap );
1079 mUnemittedProgress = 0;
1080 mUnemittedAdvancedStatus.clear();
1083 void ResourceBasePrivate::slotPercent( KJob *job,
unsigned long percent )
1089 QVariantMap statusMap;
1090 statusMap.insert( QLatin1String(
"key" ), QString::fromLatin1(
"collectionSyncProgress" ) );
1091 statusMap.insert( QLatin1String(
"collectionId" ), collection.
id() );
1092 statusMap.insert( QLatin1String(
"percent" ), static_cast<unsigned int>( percent ) );
1094 mUnemittedAdvancedStatus[collection.
id()] = statusMap;
1097 if ( percent == 100 ) {
1098 mProgressEmissionCompressor.stop();
1099 slotDelayedEmitProgress();
1100 }
else if ( !mProgressEmissionCompressor.isActive() ) {
1101 mProgressEmissionCompressor.start();
1108 d->mHierarchicalRid = enable;
1114 d->scheduler->scheduleCustomTask( receiver, method, argument, priority );
1120 d->scheduler->taskDone();
1136 d->mItemTransactionMode = mode;
1142 if ( !d->mItemSyncFetchScope )
1144 *(d->mItemSyncFetchScope) = fetchScope;
1150 d->mAutomaticProgressReporting = enabled;
1156 return d->dumpNotificationListToString();
1162 return d->dumpToString();
1168 return d->dumpMemoryInfo();
1174 return d->dumpMemoryInfoToString();
1177 #include "resourcebase.moc"
1178 #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 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 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.
void setAgentName(const QString &name)
This method is used to set the name of the agent.
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 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.
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.
QString identifier() const
Returns the instance identifier of this agent.
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.
ChangeRecorder * changeRecorder() const
Returns the Akonadi::ChangeRecorder object used for monitoring.
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 changeProcessed()
Marks the current change as processes and replays the next change if change recording is enabled (noo...
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.
~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.
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.
QString agentName() const
Returns the name of the agent.
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.