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>
54 #include <QtCore/QDebug>
55 #include <QtCore/QDir>
56 #include <QtCore/QHash>
57 #include <QtCore/QSettings>
58 #include <QtCore/QTimer>
59 #include <QtGui/QApplication>
60 #include <QtDBus/QtDBus>
62 using namespace Akonadi;
67 Q_CLASSINFO(
"D-Bus Interface",
"org.kde.dfaure" )
70 ResourceBasePrivate( ResourceBase *parent )
74 mItemSyncFetchScope( 0 ),
75 mItemTransactionMode( ItemSync::SingleTransaction ),
76 mCollectionSyncer( 0 ),
77 mHierarchicalRid( false ),
78 mUnemittedProgress( 0 ),
79 mAutomaticProgressReporting( true )
81 Internal::setClientType( Internal::Resource );
82 mStatusMessage = defaultReadyMessage();
83 mProgressEmissionCompressor.setInterval( 1000 );
84 mProgressEmissionCompressor.setSingleShot(
true );
87 ~ResourceBasePrivate()
89 delete mItemSyncFetchScope;
92 Q_DECLARE_PUBLIC( ResourceBase )
96 const QString serviceId = QLatin1String(
"org.freedesktop.Akonadi.Resource." ) + mId;
97 if ( !DBusConnectionPool::threadConnection().registerService( serviceId ) ) {
98 QString reason = DBusConnectionPool::threadConnection().lastError().message();
99 if ( reason.isEmpty() ) {
100 reason = QString::fromLatin1(
"this service is probably running already." );
102 kError() <<
"Unable to register service" << serviceId <<
"at D-Bus:" << reason;
104 if ( QThread::currentThread() == QCoreApplication::instance()->thread() )
105 QCoreApplication::instance()->exit(1);
108 AgentBasePrivate::delayedInit();
112 virtual void changeProcessed()
114 if ( m_recursiveMover ) {
115 m_recursiveMover->changeProcessed();
116 QTimer::singleShot( 0, m_recursiveMover, SLOT(replayNext()) );
120 mChangeRecorder->changeProcessed();
121 if ( !mChangeRecorder->isEmpty() )
122 scheduler->scheduleChangeReplay();
123 scheduler->taskDone();
126 void slotAbortRequested();
128 void slotDeliveryDone( KJob* job );
129 void slotCollectionSyncDone( KJob *job );
130 void slotLocalListDone( KJob *job );
131 void slotSynchronizeCollection(
const Collection &col );
132 void slotCollectionListDone( KJob *job );
133 void slotSynchronizeCollectionAttributes(
const Collection &col );
134 void slotCollectionListForAttributesDone( KJob *job );
135 void slotCollectionAttributesSyncDone( KJob *job );
137 void slotItemSyncDone( KJob *job );
139 void slotPercent( KJob* job,
unsigned long percent );
140 void slotDelayedEmitProgress();
141 void slotDeleteResourceCollection();
142 void slotDeleteResourceCollectionDone( KJob *job );
143 void slotCollectionDeletionDone( KJob *job );
145 void slotInvalidateCache(
const Akonadi::Collection &collection );
147 void slotPrepareItemRetrieval(
const Akonadi::Item &item );
148 void slotPrepareItemRetrievalResult( KJob* job );
150 void changeCommittedResult( KJob* job );
152 void slotRecursiveMoveReplay( RecursiveMover *mover );
153 void slotRecursiveMoveReplayResult( KJob *job );
155 void slotSessionReconnected()
159 new ResourceSelectJob( q->identifier() );
162 void createItemSyncInstanceIfMissing()
165 Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::SyncCollection,
166 "createItemSyncInstance",
"Calling items retrieval methods although no item retrieval is in progress" );
167 if ( !mItemSyncer ) {
168 mItemSyncer =
new ItemSync( q->currentCollection() );
169 mItemSyncer->setTransactionMode( mItemTransactionMode );
170 if ( mItemSyncFetchScope )
171 mItemSyncer->setFetchScope( *mItemSyncFetchScope );
172 mItemSyncer->setProperty(
"collection", QVariant::fromValue( q->currentCollection() ) );
173 connect( mItemSyncer, SIGNAL(percent(KJob*,ulong)), q, SLOT(slotPercent(KJob*,ulong)) );
174 connect( mItemSyncer, SIGNAL(result(KJob*)), q, SLOT(slotItemSyncDone(KJob*)) );
176 Q_ASSERT( mItemSyncer );
181 Q_SCRIPTABLE QString dumpNotificationListToString()
const
183 return mChangeRecorder->dumpNotificationListToString();
187 Q_SCRIPTABLE QString dumpToString()
const
189 Q_Q(
const ResourceBase );
191 QMetaObject::invokeMethod( const_cast<ResourceBase *>(q),
"dumpResourceToString", Qt::DirectConnection, Q_RETURN_ARG(QString, retVal) );
192 return scheduler->dumpToString() + QLatin1Char(
'\n') + retVal;
195 Q_SCRIPTABLE
void dump()
200 Q_SCRIPTABLE
void clear()
211 void itemAdded(
const Akonadi::Item& item,
const Akonadi::Collection& collection)
213 if ( collection.remoteId().isEmpty() ) {
217 AgentBasePrivate::itemAdded( item, collection );
220 void itemChanged(
const Akonadi::Item& item,
const QSet< QByteArray >& partIdentifiers)
222 if ( item.remoteId().isEmpty() ) {
226 AgentBasePrivate::itemChanged( item, partIdentifiers );
230 void itemMoved(
const Akonadi::Item &item,
const Akonadi::Collection &source,
const Akonadi::Collection &destination)
232 if ( item.remoteId().isEmpty() || destination.remoteId().isEmpty() || destination == source ) {
236 AgentBasePrivate::itemMoved( item, source, destination );
239 void itemRemoved(
const Akonadi::Item& item)
241 if ( item.remoteId().isEmpty() ) {
245 AgentBasePrivate::itemRemoved( item );
248 void collectionAdded(
const Akonadi::Collection& collection,
const Akonadi::Collection& parent)
250 if ( parent.remoteId().isEmpty() ) {
254 AgentBasePrivate::collectionAdded( collection, parent );
257 void collectionChanged(
const Akonadi::Collection& collection)
259 if ( collection.remoteId().isEmpty() ) {
263 AgentBasePrivate::collectionChanged( collection );
266 void collectionChanged(
const Akonadi::Collection& collection,
const QSet< QByteArray >& partIdentifiers)
268 if ( collection.remoteId().isEmpty() ) {
272 AgentBasePrivate::collectionChanged( collection, partIdentifiers );
275 void collectionMoved(
const Akonadi::Collection& collection,
const Akonadi::Collection& source,
const Akonadi::Collection& destination)
278 if ( destination.remoteId().isEmpty() || source == destination ) {
284 if ( !source.resource().isEmpty() && !destination.resource().isEmpty() && source.resource() != destination.resource() ) {
285 if ( source.resource() == q_ptr->identifier() ) {
286 AgentBasePrivate::collectionRemoved( collection );
287 }
else if ( destination.resource() == q_ptr->identifier() ) {
288 scheduler->taskDone();
289 RecursiveMover *mover =
new RecursiveMover(
this );
290 mover->setCollection( collection, destination );
291 scheduler->scheduleMoveReplay( collection, mover );
297 if ( collection.remoteId().isEmpty() ) {
303 AgentBasePrivate::collectionMoved( collection, source, destination );
306 void collectionRemoved(
const Akonadi::Collection& collection)
308 if ( collection.remoteId().isEmpty() ) {
312 AgentBasePrivate::collectionRemoved( collection );
317 Collection currentCollection;
319 ResourceScheduler *scheduler;
320 ItemSync *mItemSyncer;
321 ItemFetchScope *mItemSyncFetchScope;
322 ItemSync::TransactionMode mItemTransactionMode;
323 CollectionSync *mCollectionSyncer;
324 bool mHierarchicalRid;
325 QTimer mProgressEmissionCompressor;
326 int mUnemittedProgress;
327 QMap<Akonadi::Collection::Id, QVariantMap> mUnemittedAdvancedStatus;
328 bool mAutomaticProgressReporting;
329 QPointer<RecursiveMover> m_recursiveMover;
332 ResourceBase::ResourceBase(
const QString &
id )
333 :
AgentBase( new ResourceBasePrivate( this ), id )
337 new Akonadi__ResourceAdaptor(
this );
339 d->scheduler =
new ResourceScheduler(
this );
341 d->mChangeRecorder->setChangeRecordingEnabled(
true );
342 d->mChangeRecorder->setCollectionMoveTranslationEnabled(
false );
343 connect( d->mChangeRecorder, SIGNAL(changesAdded()),
344 d->scheduler, SLOT(scheduleChangeReplay()) );
346 d->mChangeRecorder->setResourceMonitored( d->mId.toLatin1() );
347 d->mChangeRecorder->fetchCollection(
true );
349 connect( d->scheduler, SIGNAL(executeFullSync()),
351 connect( d->scheduler, SIGNAL(executeCollectionTreeSync()),
353 connect( d->scheduler, SIGNAL(executeCollectionSync(Akonadi::Collection)),
354 SLOT(slotSynchronizeCollection(Akonadi::Collection)) );
355 connect( d->scheduler, SIGNAL(executeCollectionAttributesSync(Akonadi::Collection)),
356 SLOT(slotSynchronizeCollectionAttributes(Akonadi::Collection)) );
357 connect( d->scheduler, SIGNAL(executeItemFetch(Akonadi::Item,QSet<QByteArray>)),
358 SLOT(slotPrepareItemRetrieval(Akonadi::Item)) );
359 connect( d->scheduler, SIGNAL(executeResourceCollectionDeletion()),
360 SLOT(slotDeleteResourceCollection()) );
361 connect ( d->scheduler, SIGNAL(executeCacheInvalidation(Akonadi::Collection)),
362 SLOT(slotInvalidateCache(Akonadi::Collection)) );
363 connect( d->scheduler, SIGNAL(
status(
int,QString)),
364 SIGNAL(
status(
int,QString)) );
365 connect( d->scheduler, SIGNAL(executeChangeReplay()),
366 d->mChangeRecorder, SLOT(replayNext()) );
367 connect( d->scheduler, SIGNAL(executeRecursiveMoveReplay(
RecursiveMover*)),
369 connect( d->scheduler, SIGNAL(fullSyncComplete()), SIGNAL(
synchronized()) );
371 connect( d->mChangeRecorder, SIGNAL(nothingToReplay()), d->scheduler, SLOT(
taskDone()) );
372 connect( d->mChangeRecorder, SIGNAL(collectionRemoved(Akonadi::Collection)),
373 d->scheduler, SLOT(collectionRemoved(Akonadi::Collection)) );
374 connect(
this, SIGNAL(
abortRequested()),
this, SLOT(slotAbortRequested()) );
375 connect(
this, SIGNAL(
synchronized()), d->scheduler, SLOT(
taskDone()) );
380 connect( &d->mProgressEmissionCompressor, SIGNAL(timeout()),
381 this, SLOT(slotDelayedEmitProgress()) );
383 d->scheduler->setOnline( d->mOnline );
384 if ( !d->mChangeRecorder->isEmpty() )
385 d->scheduler->scheduleChangeReplay();
387 DBusConnectionPool::threadConnection().registerObject( QLatin1String(
"/Debug" ), d, QDBusConnection::ExportScriptableSlots );
391 connect( d->mChangeRecorder->session(), SIGNAL(reconnected()), SLOT(slotSessionReconnected()) );
394 ResourceBase::~ResourceBase()
398 void ResourceBase::synchronize()
400 d_func()->scheduler->scheduleFullSync();
403 void ResourceBase::setName(
const QString &name )
408 QString ResourceBase::name()
const
413 QString ResourceBase::parseArguments(
int argc,
char **argv )
417 kDebug() <<
"Not enough arguments passed...";
421 for (
int i = 1; i < argc - 1; ++i ) {
422 if ( QLatin1String( argv[ i ] ) == QLatin1String(
"--identifier" ) )
423 identifier = QLatin1String( argv[ i + 1 ] );
426 if ( identifier.isEmpty() ) {
427 kDebug() <<
"Identifier argument missing";
431 const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
433 const QByteArray catalog = fi.baseName().toLatin1();
435 KCmdLineArgs::init( argc, argv, identifier.toLatin1(), catalog,
436 ki18nc(
"@title application name",
"Akonadi Resource" ), KDEPIMLIBS_VERSION,
437 ki18nc(
"@title application description",
"Akonadi Resource" ) );
439 KCmdLineOptions options;
440 options.add(
"identifier <argument>",
441 ki18nc(
"@label commandline option",
"Resource identifier" ) );
442 KCmdLineArgs::addCmdLineOptions( options );
447 int ResourceBase::init( ResourceBase *r )
449 QApplication::setQuitOnLastWindowClosed(
false );
450 KGlobal::locale()->insertCatalog( QLatin1String(
"libakonadi" ) );
451 int rv = kapp->exec();
456 void ResourceBasePrivate::slotAbortRequested()
460 scheduler->cancelQueues();
461 QMetaObject::invokeMethod( q,
"abortActivity" );
464 void ResourceBase::itemRetrieved(
const Item &item )
467 Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::FetchItem );
469 d->scheduler->currentTask().sendDBusReplies(
false );
470 d->scheduler->taskDone();
475 QSet<QByteArray> requestedParts = d->scheduler->currentTask().itemParts;
476 foreach (
const QByteArray &part, requestedParts ) {
478 kWarning() <<
"Item does not provide part" << part;
485 connect( job, SIGNAL(result(KJob*)), SLOT(slotDeliveryDone(KJob*)) );
488 void ResourceBasePrivate::slotDeliveryDone(KJob * job)
491 Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::FetchItem );
492 if ( job->error() ) {
493 emit q->error( QLatin1String(
"Error while creating item: " ) + job->errorString() );
495 scheduler->currentTask().sendDBusReplies( !job->error() );
496 scheduler->taskDone();
499 void ResourceBase::collectionAttributesRetrieved(
const Collection &collection )
502 Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
504 emit attributesSynchronized( d->scheduler->currentTask().collection.id() );
505 d->scheduler->taskDone();
510 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionAttributesSyncDone(KJob*)) );
513 void ResourceBasePrivate::slotCollectionAttributesSyncDone(KJob * job)
516 Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
517 if ( job->error() ) {
518 emit q->error( QLatin1String(
"Error while updating collection: " ) + job->errorString() );
520 emit q->attributesSynchronized( scheduler->currentTask().collection.id() );
521 scheduler->taskDone();
524 void ResourceBasePrivate::slotDeleteResourceCollection()
528 CollectionFetchJob *job =
new CollectionFetchJob( Collection::root(), CollectionFetchJob::FirstLevel );
529 job->fetchScope().setResource( q->identifier() );
530 connect( job, SIGNAL(result(KJob*)), q, SLOT(slotDeleteResourceCollectionDone(KJob*)) );
533 void ResourceBasePrivate::slotDeleteResourceCollectionDone( KJob *job )
536 if ( job->error() ) {
537 emit q->error( job->errorString() );
538 scheduler->taskDone();
540 const CollectionFetchJob *fetchJob =
static_cast<const CollectionFetchJob*
>( job );
542 if ( !fetchJob->collections().isEmpty() ) {
543 CollectionDeleteJob *job =
new CollectionDeleteJob( fetchJob->collections().first() );
544 connect( job, SIGNAL(result(KJob*)), q, SLOT(slotCollectionDeletionDone(KJob*)) );
547 scheduler->taskDone();
552 void ResourceBasePrivate::slotCollectionDeletionDone( KJob *job )
555 if ( job->error() ) {
556 emit q->error( job->errorString() );
559 scheduler->taskDone();
562 void ResourceBasePrivate::slotInvalidateCache(
const Akonadi::Collection &collection )
565 InvalidateCacheJob *job =
new InvalidateCacheJob( collection, q );
566 connect( job, SIGNAL(result(KJob*)), scheduler, SLOT(taskDone()) );
569 void ResourceBase::changeCommitted(
const Item& item )
573 job->d_func()->setClean();
576 d->changeProcessed();
579 void ResourceBase::changeCommitted(
const Collection &collection )
582 connect( job, SIGNAL(result(KJob*)), SLOT(changeCommittedResult(KJob*)) );
585 void ResourceBasePrivate::changeCommittedResult( KJob *job )
589 emit q->error( i18nc(
"@info",
"Updating local collection failed: %1.", job->errorText() ) );
590 mChangeRecorder->d_ptr->invalidateCache( static_cast<CollectionModifyJob*>( job )->collection() );
594 bool ResourceBase::requestItemDelivery( qint64 uid,
const QString & remoteId,
595 const QString &mimeType,
const QStringList &_parts )
599 emit error( i18nc(
"@info",
"Cannot fetch item in offline mode." ) );
603 setDelayedReply(
true );
606 item.setMimeType( mimeType );
607 item.setRemoteId( remoteId );
609 QSet<QByteArray> parts;
610 Q_FOREACH(
const QString &str, _parts )
611 parts.insert( str.toLatin1() );
613 d->scheduler->scheduleItemFetch( item, parts, message().createReply() );
621 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
622 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
623 "ResourceBase::collectionsRetrieved()",
624 "Calling collectionsRetrieved() although no collection retrieval is in progress" );
625 if ( !d->mCollectionSyncer ) {
627 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
628 connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
629 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
631 d->mCollectionSyncer->setRemoteCollections( collections );
634 void ResourceBase::collectionsRetrievedIncremental(
const Collection::List & changedCollections,
638 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
639 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
640 "ResourceBase::collectionsRetrievedIncremental()",
641 "Calling collectionsRetrievedIncremental() although no collection retrieval is in progress" );
642 if ( !d->mCollectionSyncer ) {
644 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
645 connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
646 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
648 d->mCollectionSyncer->setRemoteCollections( changedCollections, removedCollections );
651 void ResourceBase::setCollectionStreamingEnabled(
bool enable )
654 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
655 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
656 "ResourceBase::setCollectionStreamingEnabled()",
657 "Calling setCollectionStreamingEnabled() although no collection retrieval is in progress" );
658 if ( !d->mCollectionSyncer ) {
660 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
661 connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
662 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
664 d->mCollectionSyncer->setStreamingEnabled( enable );
667 void ResourceBase::collectionsRetrievalDone()
670 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
671 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
672 "ResourceBase::collectionsRetrievalDone()",
673 "Calling collectionsRetrievalDone() although no collection retrieval is in progress" );
675 if ( d->mCollectionSyncer ) {
676 d->mCollectionSyncer->retrievalDone();
681 d->scheduler->taskDone();
685 void ResourceBasePrivate::slotCollectionSyncDone( KJob * job )
688 mCollectionSyncer = 0;
689 if ( job->error() ) {
690 if ( job->error() != Job::UserCanceled )
691 emit q->error( job->errorString() );
693 if ( scheduler->currentTask().type == ResourceScheduler::SyncAll ) {
694 CollectionFetchJob *list =
new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive );
695 list->setFetchScope( q->changeRecorder()->collectionFetchScope() );
696 list->fetchScope().setResource( mId );
697 q->connect( list, SIGNAL(result(KJob*)), q, SLOT(slotLocalListDone(KJob*)) );
699 }
else if ( scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ) {
700 scheduler->scheduleCollectionTreeSyncCompletion();
703 scheduler->taskDone();
706 void ResourceBasePrivate::slotLocalListDone( KJob * job )
709 if ( job->error() ) {
710 emit q->error( job->errorString() );
712 Collection::List cols =
static_cast<CollectionFetchJob*
>( job )->collections();
713 foreach (
const Collection &col, cols ) {
714 scheduler->scheduleSync( col );
716 scheduler->scheduleFullSyncCompletion();
718 scheduler->taskDone();
721 void ResourceBasePrivate::slotSynchronizeCollection(
const Collection &col )
724 currentCollection = col;
726 QStringList contentTypes = currentCollection.contentMimeTypes();
727 contentTypes.removeAll( Collection::mimeType() );
728 if ( !contentTypes.isEmpty() || (col.rights() & (Collection::CanLinkItem)) ) {
729 if ( mAutomaticProgressReporting ) {
730 emit q->status(
AgentBase::Running, i18nc(
"@info:status",
"Syncing folder '%1'", currentCollection.name() ) );
732 q->retrieveItems( currentCollection );
735 scheduler->taskDone();
738 void ResourceBasePrivate::slotSynchronizeCollectionAttributes(
const Collection &col )
741 QMetaObject::invokeMethod( q,
"retrieveCollectionAttributes", Q_ARG( Akonadi::Collection, col ) );
744 void ResourceBasePrivate::slotPrepareItemRetrieval(
const Akonadi::Item &item )
747 ItemFetchJob *fetch =
new ItemFetchJob( item,
this );
748 fetch->fetchScope().setAncestorRetrieval( q->changeRecorder()->itemFetchScope().ancestorRetrieval() );
749 fetch->fetchScope().setCacheOnly(
true );
752 const QSet<QByteArray> attributes = q->changeRecorder()->itemFetchScope().attributes();
753 foreach (
const QByteArray &attribute, attributes )
754 fetch->fetchScope().fetchAttribute( attribute );
756 q->connect( fetch, SIGNAL(result(KJob*)), SLOT(slotPrepareItemRetrievalResult(KJob*)) );
759 void ResourceBasePrivate::slotPrepareItemRetrievalResult( KJob* job )
762 Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::FetchItem,
763 "ResourceBasePrivate::slotPrepareItemRetrievalResult()",
764 "Preparing item retrieval although no item retrieval is in progress" );
765 if ( job->error() ) {
766 q->cancelTask( job->errorText() );
769 ItemFetchJob *fetch = qobject_cast<ItemFetchJob*>( job );
770 if ( fetch->items().count() != 1 ) {
771 q->cancelTask( i18n(
"The requested item no longer exists" ) );
774 const Item item = fetch->items().first();
775 const QSet<QByteArray> parts = scheduler->currentTask().itemParts;
776 if ( !q->retrieveItem( item, parts ) )
780 void ResourceBasePrivate::slotRecursiveMoveReplay( RecursiveMover *mover )
784 Q_ASSERT( !m_recursiveMover );
785 m_recursiveMover = mover;
786 connect( mover, SIGNAL(result(KJob*)), q, SLOT(slotRecursiveMoveReplayResult(KJob*)) );
790 void ResourceBasePrivate::slotRecursiveMoveReplayResult( KJob *job )
793 m_recursiveMover = 0;
795 if ( job->error() ) {
803 void ResourceBase::itemsRetrievalDone()
807 if ( d->mItemSyncer ) {
808 d->mItemSyncer->deliveryDone();
812 d->scheduler->taskDone();
816 void ResourceBase::clearCache()
819 d->scheduler->scheduleResourceCollectionDeletion();
822 void ResourceBase::invalidateCache(
const Collection& collection)
825 d->scheduler->scheduleCacheInvalidation( collection );
831 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection ,
832 "ResourceBase::currentCollection()",
833 "Trying to access current collection although no item retrieval is in progress" );
834 return d->currentCollection;
837 Item ResourceBase::currentItem()
const
840 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::FetchItem ,
841 "ResourceBase::currentItem()",
842 "Trying to access current item although no item retrieval is in progress" );
843 return d->scheduler->currentTask().item;
846 void ResourceBase::synchronizeCollectionTree()
848 d_func()->scheduler->scheduleCollectionTreeSync();
851 void ResourceBase::cancelTask()
854 switch ( d->scheduler->currentTask().type ) {
855 case ResourceScheduler::FetchItem:
856 itemRetrieved(
Item() );
858 case ResourceScheduler::ChangeReplay:
859 d->changeProcessed();
861 case ResourceScheduler::SyncCollectionTree:
862 case ResourceScheduler::SyncAll:
863 if ( d->mCollectionSyncer )
864 d->mCollectionSyncer->rollback();
866 d->scheduler->taskDone();
868 case ResourceScheduler::SyncCollection:
869 if ( d->mItemSyncer ) {
870 d->mItemSyncer->rollback();
872 d->scheduler->taskDone();
876 d->scheduler->taskDone();
880 void ResourceBase::cancelTask(
const QString &msg )
887 void ResourceBase::deferTask()
890 d->scheduler->deferTask();
893 void ResourceBase::doSetOnline(
bool state )
895 d_func()->scheduler->setOnline( state );
898 void ResourceBase::synchronizeCollection( qint64 collectionId )
900 synchronizeCollection( collectionId,
false );
903 void ResourceBase::synchronizeCollection( qint64 collectionId,
bool recursive )
905 CollectionFetchJob* job =
new CollectionFetchJob( Collection( collectionId ), recursive ? CollectionFetchJob::Recursive : CollectionFetchJob::Base );
906 job->setFetchScope( changeRecorder()->collectionFetchScope() );
907 job->fetchScope().setResource( identifier() );
908 job->setProperty(
"recursive", recursive );
909 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListDone(KJob*)) );
912 void ResourceBasePrivate::slotCollectionListDone( KJob *job )
914 if ( !job->error() ) {
915 Collection::List list =
static_cast<CollectionFetchJob*
>( job )->collections();
916 if ( !list.isEmpty() ) {
917 if ( job->property(
"recursive" ).toBool() ) {
918 Q_FOREACH (
const Collection &collection, list ) {
919 scheduler->scheduleSync( collection );
922 scheduler->scheduleSync( list.first() );
929 void ResourceBase::synchronizeCollectionAttributes( qint64 collectionId )
932 job->
setFetchScope( changeRecorder()->collectionFetchScope() );
934 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListForAttributesDone(KJob*)) );
937 void ResourceBasePrivate::slotCollectionListForAttributesDone( KJob *job )
939 if ( !job->error() ) {
941 if ( !list.isEmpty() ) {
943 scheduler->scheduleAttributesSync( col );
949 void ResourceBase::setTotalItems(
int amount )
953 setItemStreamingEnabled(
true );
954 if ( d->mItemSyncer ) {
955 d->mItemSyncer->setTotalItems( amount );
959 void ResourceBase::setItemStreamingEnabled(
bool enable )
962 d->createItemSyncInstanceIfMissing();
963 if ( d->mItemSyncer ) {
964 d->mItemSyncer->setStreamingEnabled( enable );
971 d->createItemSyncInstanceIfMissing();
972 if ( d->mItemSyncer ) {
973 d->mItemSyncer->setFullSyncItems( items );
977 void ResourceBase::itemsRetrievedIncremental(
const Item::List &changedItems,
981 d->createItemSyncInstanceIfMissing();
982 if ( d->mItemSyncer ) {
983 d->mItemSyncer->setIncrementalSyncItems( changedItems, removedItems );
987 void ResourceBasePrivate::slotItemSyncDone( KJob *job )
991 if ( job->error() && job->error() != Job::UserCanceled ) {
992 emit q->error( job->errorString() );
994 scheduler->taskDone();
998 void ResourceBasePrivate::slotDelayedEmitProgress()
1000 Q_Q( ResourceBase );
1001 if ( mAutomaticProgressReporting ) {
1002 emit q->percent( mUnemittedProgress );
1004 Q_FOREACH(
const QVariantMap &statusMap, mUnemittedAdvancedStatus ) {
1005 emit q->advancedStatus( statusMap );
1008 mUnemittedProgress = 0;
1009 mUnemittedAdvancedStatus.clear();
1012 void ResourceBasePrivate::slotPercent( KJob *job,
unsigned long percent )
1014 mUnemittedProgress = percent;
1016 const Collection collection = job->property(
"collection" ).value<Collection>();
1017 if ( collection.isValid() ) {
1018 QVariantMap statusMap;
1019 statusMap.insert( QLatin1String(
"key" ), QString::fromLatin1(
"collectionSyncProgress" ) );
1020 statusMap.insert( QLatin1String(
"collectionId" ), collection.id() );
1021 statusMap.insert( QLatin1String(
"percent" ), static_cast<unsigned int>( percent ) );
1023 mUnemittedAdvancedStatus[collection.id()] = statusMap;
1026 if ( percent == 100 ) {
1027 mProgressEmissionCompressor.stop();
1028 slotDelayedEmitProgress();
1029 }
else if ( !mProgressEmissionCompressor.isActive() ) {
1030 mProgressEmissionCompressor.start();
1034 void ResourceBase::setHierarchicalRemoteIdentifiersEnabled(
bool enable )
1037 d->mHierarchicalRid = enable;
1040 void ResourceBase::scheduleCustomTask( QObject *receiver,
const char *method,
const QVariant &argument,
SchedulePriority priority )
1043 d->scheduler->scheduleCustomTask( receiver, method, argument, priority );
1046 void ResourceBase::taskDone()
1049 d->scheduler->taskDone();
1052 void ResourceBase::retrieveCollectionAttributes(
const Collection &collection )
1054 collectionAttributesRetrieved( collection );
1065 d->mItemTransactionMode = mode;
1068 void ResourceBase::setItemSynchronizationFetchScope(
const ItemFetchScope& fetchScope)
1071 if ( !d->mItemSyncFetchScope )
1073 *(d->mItemSyncFetchScope) = fetchScope;
1076 void ResourceBase::setAutomaticProgressReporting(
bool enabled )
1079 d->mAutomaticProgressReporting = enabled;
1082 QString ResourceBase::dumpNotificationListToString()
const
1085 return d->dumpNotificationListToString();
1088 QString ResourceBase::dumpSchedulerToString()
const
1091 return d->dumpToString();
1094 #include "resourcebase.moc"
1095 #include "moc_resourcebase.cpp"