00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "resourcebase.h"
00022 #include "agentbase_p.h"
00023
00024 #include "resourceadaptor.h"
00025 #include "collectiondeletejob.h"
00026 #include "collectionsync_p.h"
00027 #include "itemsync.h"
00028 #include "resourcescheduler_p.h"
00029 #include "tracerinterface.h"
00030 #include "xdgbasedirs_p.h"
00031
00032 #include "changerecorder.h"
00033 #include "collectionfetchjob.h"
00034 #include "collectionfetchscope.h"
00035 #include "collectionmodifyjob.h"
00036 #include "itemfetchjob.h"
00037 #include "itemfetchscope.h"
00038 #include "itemmodifyjob.h"
00039 #include "itemmodifyjob_p.h"
00040 #include "session.h"
00041 #include "resourceselectjob_p.h"
00042 #include "monitor_p.h"
00043 #include "servermanager_p.h"
00044
00045 #include <kaboutdata.h>
00046 #include <kcmdlineargs.h>
00047 #include <kdebug.h>
00048 #include <klocale.h>
00049
00050 #include <QtCore/QDebug>
00051 #include <QtCore/QDir>
00052 #include <QtCore/QHash>
00053 #include <QtCore/QSettings>
00054 #include <QtCore/QTimer>
00055 #include <QtGui/QApplication>
00056 #include <QtDBus/QtDBus>
00057
00058 using namespace Akonadi;
00059
00060 class Akonadi::ResourceBasePrivate : public AgentBasePrivate
00061 {
00062 Q_OBJECT
00063 Q_CLASSINFO( "D-Bus Interface", "org.kde.dfaure" )
00064
00065 public:
00066 ResourceBasePrivate( ResourceBase *parent )
00067 : AgentBasePrivate( parent ),
00068 scheduler( 0 ),
00069 mItemSyncer( 0 ),
00070 mCollectionSyncer( 0 ),
00071 mHierarchicalRid( false )
00072 {
00073 Internal::setClientType( Internal::Resource );
00074 mStatusMessage = defaultReadyMessage();
00075
00076 QDBusConnection::sessionBus().registerObject( QLatin1String( "/Debug" ), this, QDBusConnection::ExportScriptableSlots );
00077 }
00078
00079 Q_DECLARE_PUBLIC( ResourceBase )
00080
00081 void delayedInit()
00082 {
00083 if ( !QDBusConnection::sessionBus().registerService( QLatin1String( "org.freedesktop.Akonadi.Resource." ) + mId ) ) {
00084 QString reason = QDBusConnection::sessionBus().lastError().message();
00085 if ( reason.isEmpty() ) {
00086 reason = QString::fromLatin1( "this service is probably running already." );
00087 }
00088 kError() << "Unable to register service at D-Bus: " << reason;
00089 QCoreApplication::instance()->exit(1);
00090 } else {
00091 AgentBasePrivate::delayedInit();
00092 }
00093 }
00094
00095 virtual void changeProcessed()
00096 {
00097 mChangeRecorder->changeProcessed();
00098 if ( !mChangeRecorder->isEmpty() )
00099 scheduler->scheduleChangeReplay();
00100 scheduler->taskDone();
00101 }
00102
00103 void slotDeliveryDone( KJob* job );
00104 void slotCollectionSyncDone( KJob *job );
00105 void slotLocalListDone( KJob *job );
00106 void slotSynchronizeCollection( const Collection &col );
00107 void slotCollectionListDone( KJob *job );
00108
00109 void slotItemSyncDone( KJob *job );
00110
00111 void slotPercent( KJob* job, unsigned long percent );
00112 void slotDeleteResourceCollection();
00113 void slotDeleteResourceCollectionDone( KJob *job );
00114 void slotCollectionDeletionDone( KJob *job );
00115
00116 void slotPrepareItemRetrieval( const Akonadi::Item &item );
00117 void slotPrepareItemRetrievalResult( KJob* job );
00118
00119 void changeCommittedResult( KJob* job );
00120
00121 public Q_SLOTS:
00122 Q_SCRIPTABLE void dump()
00123 {
00124 scheduler->dump();
00125 }
00126
00127 Q_SCRIPTABLE void clear()
00128 {
00129 scheduler->clear();
00130 }
00131
00132 public:
00133
00134 Collection currentCollection;
00135
00136 ResourceScheduler *scheduler;
00137 ItemSync *mItemSyncer;
00138 CollectionSync *mCollectionSyncer;
00139 bool mHierarchicalRid;
00140 };
00141
00142 ResourceBase::ResourceBase( const QString & id )
00143 : AgentBase( new ResourceBasePrivate( this ), id )
00144 {
00145 Q_D( ResourceBase );
00146
00147 new Akonadi__ResourceAdaptor( this );
00148
00149 d->scheduler = new ResourceScheduler( this );
00150
00151 d->mChangeRecorder->setChangeRecordingEnabled( true );
00152 connect( d->mChangeRecorder, SIGNAL( changesAdded() ),
00153 d->scheduler, SLOT( scheduleChangeReplay() ) );
00154
00155 d->mChangeRecorder->setResourceMonitored( d->mId.toLatin1() );
00156
00157 connect( d->scheduler, SIGNAL( executeFullSync() ),
00158 SLOT( retrieveCollections() ) );
00159 connect( d->scheduler, SIGNAL( executeCollectionTreeSync() ),
00160 SLOT( retrieveCollections() ) );
00161 connect( d->scheduler, SIGNAL( executeCollectionSync( const Akonadi::Collection& ) ),
00162 SLOT( slotSynchronizeCollection( const Akonadi::Collection& ) ) );
00163 connect( d->scheduler, SIGNAL( executeItemFetch( const Akonadi::Item&, const QSet<QByteArray>& ) ),
00164 SLOT( slotPrepareItemRetrieval(Akonadi::Item)) );
00165 connect( d->scheduler, SIGNAL( executeResourceCollectionDeletion() ),
00166 SLOT( slotDeleteResourceCollection() ) );
00167 connect( d->scheduler, SIGNAL( status( int, const QString& ) ),
00168 SIGNAL( status( int, const QString& ) ) );
00169 connect( d->scheduler, SIGNAL( executeChangeReplay() ),
00170 d->mChangeRecorder, SLOT( replayNext() ) );
00171 connect( d->scheduler, SIGNAL( fullSyncComplete() ), SIGNAL( synchronized() ) );
00172 connect( d->mChangeRecorder, SIGNAL( nothingToReplay() ), d->scheduler, SLOT( taskDone() ) );
00173 connect( d->mChangeRecorder, SIGNAL( collectionRemoved( const Akonadi::Collection& ) ),
00174 d->scheduler, SLOT( collectionRemoved( const Akonadi::Collection& ) ) );
00175 connect( this, SIGNAL( synchronized() ), d->scheduler, SLOT( taskDone() ) );
00176 connect( this, SIGNAL( agentNameChanged( const QString& ) ),
00177 this, SIGNAL( nameChanged( const QString& ) ) );
00178
00179 d->scheduler->setOnline( d->mOnline );
00180 if ( !d->mChangeRecorder->isEmpty() )
00181 d->scheduler->scheduleChangeReplay();
00182
00183 new ResourceSelectJob( identifier() );
00184 }
00185
00186 ResourceBase::~ResourceBase()
00187 {
00188 }
00189
00190 void ResourceBase::synchronize()
00191 {
00192 d_func()->scheduler->scheduleFullSync();
00193 }
00194
00195 void ResourceBase::setName( const QString &name )
00196 {
00197 AgentBase::setAgentName( name );
00198 }
00199
00200 QString ResourceBase::name() const
00201 {
00202 return AgentBase::agentName();
00203 }
00204
00205 QString ResourceBase::parseArguments( int argc, char **argv )
00206 {
00207 QString identifier;
00208 if ( argc < 3 ) {
00209 kDebug() << "Not enough arguments passed...";
00210 exit( 1 );
00211 }
00212
00213 for ( int i = 1; i < argc - 1; ++i ) {
00214 if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) )
00215 identifier = QLatin1String( argv[ i + 1 ] );
00216 }
00217
00218 if ( identifier.isEmpty() ) {
00219 kDebug() << "Identifier argument missing";
00220 exit( 1 );
00221 }
00222
00223 QByteArray catalog;
00224 char *p = strrchr( argv[0], '/' );
00225 if ( p )
00226 catalog = QByteArray( p + 1 );
00227 else
00228 catalog = QByteArray( argv[0] );
00229
00230 KCmdLineArgs::init( argc, argv, identifier.toLatin1(), catalog,
00231 ki18nc( "@title application name", "Akonadi Resource" ), "0.1",
00232 ki18nc( "@title application description", "Akonadi Resource" ) );
00233
00234 KCmdLineOptions options;
00235 options.add( "identifier <argument>",
00236 ki18nc( "@label commandline option", "Resource identifier" ) );
00237 KCmdLineArgs::addCmdLineOptions( options );
00238
00239 return identifier;
00240 }
00241
00242 int ResourceBase::init( ResourceBase *r )
00243 {
00244 QApplication::setQuitOnLastWindowClosed( false );
00245 int rv = kapp->exec();
00246 delete r;
00247 return rv;
00248 }
00249
00250 void ResourceBase::itemRetrieved( const Item &item )
00251 {
00252 Q_D( ResourceBase );
00253 Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::FetchItem );
00254 if ( !item.isValid() ) {
00255 d->scheduler->currentTask().sendDBusReplies( false );
00256 d->scheduler->taskDone();
00257 return;
00258 }
00259
00260 Item i( item );
00261 QSet<QByteArray> requestedParts = d->scheduler->currentTask().itemParts;
00262 foreach ( const QByteArray &part, requestedParts ) {
00263 if ( !item.loadedPayloadParts().contains( part ) ) {
00264 kWarning() << "Item does not provide part" << part;
00265 }
00266 }
00267
00268 ItemModifyJob *job = new ItemModifyJob( i );
00269
00270 job->disableRevisionCheck();
00271 connect( job, SIGNAL( result( KJob* ) ), SLOT( slotDeliveryDone( KJob* ) ) );
00272 }
00273
00274 void ResourceBasePrivate::slotDeliveryDone(KJob * job)
00275 {
00276 Q_Q( ResourceBase );
00277 Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::FetchItem );
00278 if ( job->error() ) {
00279 emit q->error( QLatin1String( "Error while creating item: " ) + job->errorString() );
00280 }
00281 scheduler->currentTask().sendDBusReplies( !job->error() );
00282 scheduler->taskDone();
00283 }
00284
00285 void ResourceBasePrivate::slotDeleteResourceCollection()
00286 {
00287 Q_Q( ResourceBase );
00288
00289 CollectionFetchJob *job = new CollectionFetchJob( Collection::root(), CollectionFetchJob::FirstLevel );
00290 job->fetchScope().setResource( q->identifier() );
00291 connect( job, SIGNAL( result( KJob* ) ), q, SLOT( slotDeleteResourceCollectionDone( KJob* ) ) );
00292 }
00293
00294 void ResourceBasePrivate::slotDeleteResourceCollectionDone( KJob *job )
00295 {
00296 Q_Q( ResourceBase );
00297 if ( job->error() ) {
00298 emit q->error( job->errorString() );
00299 scheduler->taskDone();
00300 } else {
00301 const CollectionFetchJob *fetchJob = static_cast<const CollectionFetchJob*>( job );
00302
00303 if ( !fetchJob->collections().isEmpty() ) {
00304 CollectionDeleteJob *job = new CollectionDeleteJob( fetchJob->collections().first() );
00305 connect( job, SIGNAL( result( KJob* ) ), q, SLOT( slotCollectionDeletionDone( KJob* ) ) );
00306 } else {
00307
00308 scheduler->taskDone();
00309 }
00310 }
00311 }
00312
00313 void ResourceBasePrivate::slotCollectionDeletionDone( KJob *job )
00314 {
00315 Q_Q( ResourceBase );
00316 if ( job->error() ) {
00317 emit q->error( job->errorString() );
00318 }
00319
00320 scheduler->taskDone();
00321 }
00322
00323 void ResourceBase::changeCommitted( const Item& item )
00324 {
00325 Q_D( ResourceBase );
00326 ItemModifyJob *job = new ItemModifyJob( item );
00327 job->d_func()->setClean();
00328 job->disableRevisionCheck();
00329 job->ignorePayload();
00330 d->changeProcessed();
00331 }
00332
00333 void ResourceBase::changeCommitted( const Collection &collection )
00334 {
00335 CollectionModifyJob *job = new CollectionModifyJob( collection );
00336 connect( job, SIGNAL( result( KJob* ) ), SLOT( changeCommittedResult( KJob* ) ) );
00337 }
00338
00339 void ResourceBasePrivate::changeCommittedResult( KJob *job )
00340 {
00341 Q_Q( ResourceBase );
00342 if ( job->error() )
00343 emit q->error( i18nc( "@info", "Updating local collection failed: %1.", job->errorText() ) );
00344 mChangeRecorder->d_ptr->invalidateCache( static_cast<CollectionModifyJob*>( job )->collection() );
00345 changeProcessed();
00346 }
00347
00348 bool ResourceBase::requestItemDelivery( qint64 uid, const QString & remoteId,
00349 const QString &mimeType, const QStringList &_parts )
00350 {
00351 Q_D( ResourceBase );
00352 if ( !isOnline() ) {
00353 emit error( i18nc( "@info", "Cannot fetch item in offline mode." ) );
00354 return false;
00355 }
00356
00357 setDelayedReply( true );
00358
00359 Item item( uid );
00360 item.setMimeType( mimeType );
00361 item.setRemoteId( remoteId );
00362
00363 QSet<QByteArray> parts;
00364 Q_FOREACH( const QString &str, _parts )
00365 parts.insert( str.toLatin1() );
00366
00367 d->scheduler->scheduleItemFetch( item, parts, message().createReply() );
00368
00369 return true;
00370 }
00371
00372 void ResourceBase::collectionsRetrieved( const Collection::List & collections )
00373 {
00374 Q_D( ResourceBase );
00375 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
00376 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
00377 "ResourceBase::collectionsRetrieved()",
00378 "Calling collectionsRetrieved() although no collection retrieval is in progress" );
00379 if ( !d->mCollectionSyncer ) {
00380 d->mCollectionSyncer = new CollectionSync( identifier() );
00381 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
00382 connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
00383 connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) );
00384 }
00385 d->mCollectionSyncer->setRemoteCollections( collections );
00386 }
00387
00388 void ResourceBase::collectionsRetrievedIncremental( const Collection::List & changedCollections,
00389 const Collection::List & removedCollections )
00390 {
00391 Q_D( ResourceBase );
00392 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
00393 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
00394 "ResourceBase::collectionsRetrievedIncremental()",
00395 "Calling collectionsRetrievedIncremental() although no collection retrieval is in progress" );
00396 if ( !d->mCollectionSyncer ) {
00397 d->mCollectionSyncer = new CollectionSync( identifier() );
00398 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
00399 connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
00400 connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) );
00401 }
00402 d->mCollectionSyncer->setRemoteCollections( changedCollections, removedCollections );
00403 }
00404
00405 void ResourceBase::setCollectionStreamingEnabled( bool enable )
00406 {
00407 Q_D( ResourceBase );
00408 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
00409 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
00410 "ResourceBase::setCollectionStreamingEnabled()",
00411 "Calling setCollectionStreamingEnabled() although no collection retrieval is in progress" );
00412 if ( !d->mCollectionSyncer ) {
00413 d->mCollectionSyncer = new CollectionSync( identifier() );
00414 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
00415 connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
00416 connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) );
00417 }
00418 d->mCollectionSyncer->setStreamingEnabled( enable );
00419 }
00420
00421 void ResourceBase::collectionsRetrievalDone()
00422 {
00423 Q_D( ResourceBase );
00424 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
00425 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
00426 "ResourceBase::collectionsRetrievalDone()",
00427 "Calling collectionsRetrievalDone() although no collection retrieval is in progress" );
00428
00429 if ( d->mCollectionSyncer ) {
00430 d->mCollectionSyncer->retrievalDone();
00431 }
00432
00433 else {
00434
00435 d->scheduler->taskDone();
00436 }
00437 }
00438
00439 void ResourceBasePrivate::slotCollectionSyncDone( KJob * job )
00440 {
00441 Q_Q( ResourceBase );
00442 mCollectionSyncer = 0;
00443 if ( job->error() ) {
00444 if ( job->error() != Job::UserCanceled )
00445 emit q->error( job->errorString() );
00446 } else {
00447 if ( scheduler->currentTask().type == ResourceScheduler::SyncAll ) {
00448 CollectionFetchJob *list = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive );
00449 list->setFetchScope( q->changeRecorder()->collectionFetchScope() );
00450 list->fetchScope().setResource( mId );
00451 q->connect( list, SIGNAL( result( KJob* ) ), q, SLOT( slotLocalListDone( KJob* ) ) );
00452 return;
00453 }
00454 }
00455 scheduler->taskDone();
00456 }
00457
00458 void ResourceBasePrivate::slotLocalListDone( KJob * job )
00459 {
00460 Q_Q( ResourceBase );
00461 if ( job->error() ) {
00462 emit q->error( job->errorString() );
00463 } else {
00464 Collection::List cols = static_cast<CollectionFetchJob*>( job )->collections();
00465 foreach ( const Collection &col, cols ) {
00466 scheduler->scheduleSync( col );
00467 }
00468 scheduler->scheduleFullSyncCompletion();
00469 }
00470 scheduler->taskDone();
00471 }
00472
00473 void ResourceBasePrivate::slotSynchronizeCollection( const Collection &col )
00474 {
00475 Q_Q( ResourceBase );
00476 currentCollection = col;
00477
00478 QStringList contentTypes = currentCollection.contentMimeTypes();
00479 contentTypes.removeAll( Collection::mimeType() );
00480 if ( !contentTypes.isEmpty() || (col.rights() & (Collection::CanLinkItem)) ) {
00481 emit q->status( AgentBase::Running, i18nc( "@info:status", "Syncing collection '%1'", currentCollection.name() ) );
00482 q->retrieveItems( currentCollection );
00483 return;
00484 }
00485 scheduler->taskDone();
00486 }
00487
00488 void ResourceBasePrivate::slotPrepareItemRetrieval( const Akonadi::Item &item )
00489 {
00490 Q_Q( ResourceBase );
00491 ItemFetchJob *fetch = new ItemFetchJob( item, this );
00492 fetch->fetchScope().setAncestorRetrieval( q->changeRecorder()->itemFetchScope().ancestorRetrieval() );
00493 fetch->fetchScope().setCacheOnly( true );
00494
00495
00496 const QSet<QByteArray> attributes = q->changeRecorder()->itemFetchScope().attributes();
00497 foreach ( const QByteArray &attribute, attributes )
00498 fetch->fetchScope().fetchAttribute( attribute );
00499
00500 q->connect( fetch, SIGNAL( result( KJob* ) ), SLOT( slotPrepareItemRetrievalResult( KJob* ) ) );
00501 }
00502
00503 void ResourceBasePrivate::slotPrepareItemRetrievalResult( KJob* job )
00504 {
00505 Q_Q( ResourceBase );
00506 Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::FetchItem,
00507 "ResourceBasePrivate::slotPrepareItemRetrievalResult()",
00508 "Preparing item retrieval although no item retrieval is in progress" );
00509 if ( job->error() ) {
00510 q->cancelTask( job->errorText() );
00511 return;
00512 }
00513 ItemFetchJob *fetch = qobject_cast<ItemFetchJob*>( job );
00514 if ( fetch->items().count() != 1 ) {
00515 q->cancelTask( i18n( "The requested item no longer exists" ) );
00516 return;
00517 }
00518 const Item item = fetch->items().first();
00519 const QSet<QByteArray> parts = scheduler->currentTask().itemParts;
00520 if ( !q->retrieveItem( item, parts ) )
00521 q->cancelTask();
00522 }
00523
00524 void ResourceBase::itemsRetrievalDone()
00525 {
00526 Q_D( ResourceBase );
00527
00528 if ( d->mItemSyncer ) {
00529 d->mItemSyncer->deliveryDone();
00530 }
00531
00532 else {
00533 d->scheduler->taskDone();
00534 }
00535 }
00536
00537 void ResourceBase::clearCache()
00538 {
00539 Q_D( ResourceBase );
00540 d->scheduler->scheduleResourceCollectionDeletion();
00541 }
00542
00543 Collection ResourceBase::currentCollection() const
00544 {
00545 Q_D( const ResourceBase );
00546 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection ,
00547 "ResourceBase::currentCollection()",
00548 "Trying to access current collection although no item retrieval is in progress" );
00549 return d->currentCollection;
00550 }
00551
00552 Item ResourceBase::currentItem() const
00553 {
00554 Q_D( const ResourceBase );
00555 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::FetchItem ,
00556 "ResourceBase::currentItem()",
00557 "Trying to access current item although no item retrieval is in progress" );
00558 return d->scheduler->currentTask().item;
00559 }
00560
00561 void ResourceBase::synchronizeCollectionTree()
00562 {
00563 d_func()->scheduler->scheduleCollectionTreeSync();
00564 }
00565
00566 void ResourceBase::cancelTask()
00567 {
00568 Q_D( ResourceBase );
00569 switch ( d->scheduler->currentTask().type ) {
00570 case ResourceScheduler::FetchItem:
00571 itemRetrieved( Item() );
00572 break;
00573 case ResourceScheduler::ChangeReplay:
00574 d->changeProcessed();
00575 break;
00576 case ResourceScheduler::SyncCollectionTree:
00577 case ResourceScheduler::SyncAll:
00578 if ( d->mCollectionSyncer )
00579 d->mCollectionSyncer->rollback();
00580 else
00581 d->scheduler->taskDone();
00582 break;
00583 case ResourceScheduler::SyncCollection:
00584 if ( d->mItemSyncer )
00585 d->mItemSyncer->rollback();
00586 else
00587 d->scheduler->taskDone();
00588 break;
00589 default:
00590 d->scheduler->taskDone();
00591 }
00592 }
00593
00594 void ResourceBase::cancelTask( const QString &msg )
00595 {
00596 cancelTask();
00597
00598 emit error( msg );
00599 }
00600
00601 void ResourceBase::deferTask()
00602 {
00603 Q_D( ResourceBase );
00604 d->scheduler->deferTask();
00605 }
00606
00607 void ResourceBase::doSetOnline( bool state )
00608 {
00609 d_func()->scheduler->setOnline( state );
00610 }
00611
00612 void ResourceBase::synchronizeCollection( qint64 collectionId )
00613 {
00614 CollectionFetchJob* job = new CollectionFetchJob( Collection( collectionId ), CollectionFetchJob::Base );
00615 job->setFetchScope( changeRecorder()->collectionFetchScope() );
00616 job->fetchScope().setResource( identifier() );
00617 connect( job, SIGNAL( result( KJob* ) ), SLOT( slotCollectionListDone( KJob* ) ) );
00618 }
00619
00620 void ResourceBasePrivate::slotCollectionListDone( KJob *job )
00621 {
00622 if ( !job->error() ) {
00623 Collection::List list = static_cast<CollectionFetchJob*>( job )->collections();
00624 if ( !list.isEmpty() ) {
00625 Collection col = list.first();
00626 scheduler->scheduleSync( col );
00627 }
00628 }
00629
00630 }
00631
00632 void ResourceBase::setTotalItems( int amount )
00633 {
00634 kDebug() << amount;
00635 Q_D( ResourceBase );
00636 setItemStreamingEnabled( true );
00637 d->mItemSyncer->setTotalItems( amount );
00638 }
00639
00640 void ResourceBase::setItemStreamingEnabled( bool enable )
00641 {
00642 Q_D( ResourceBase );
00643 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection,
00644 "ResourceBase::setItemStreamingEnabled()",
00645 "Calling setItemStreamingEnabled() although no item retrieval is in progress" );
00646 if ( !d->mItemSyncer ) {
00647 d->mItemSyncer = new ItemSync( currentCollection() );
00648 connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
00649 connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) );
00650 }
00651 d->mItemSyncer->setStreamingEnabled( enable );
00652 }
00653
00654 void ResourceBase::itemsRetrieved( const Item::List &items )
00655 {
00656 Q_D( ResourceBase );
00657 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection,
00658 "ResourceBase::itemsRetrieved()",
00659 "Calling itemsRetrieved() although no item retrieval is in progress" );
00660 if ( !d->mItemSyncer ) {
00661 d->mItemSyncer = new ItemSync( currentCollection() );
00662 connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
00663 connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) );
00664 }
00665 d->mItemSyncer->setFullSyncItems( items );
00666 }
00667
00668 void ResourceBase::itemsRetrievedIncremental( const Item::List &changedItems, const Item::List &removedItems )
00669 {
00670 Q_D( ResourceBase );
00671 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection,
00672 "ResourceBase::itemsRetrievedIncremental()",
00673 "Calling itemsRetrievedIncremental() although no item retrieval is in progress" );
00674 if ( !d->mItemSyncer ) {
00675 d->mItemSyncer = new ItemSync( currentCollection() );
00676 connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) );
00677 connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) );
00678 }
00679 d->mItemSyncer->setIncrementalSyncItems( changedItems, removedItems );
00680 }
00681
00682 void ResourceBasePrivate::slotItemSyncDone( KJob *job )
00683 {
00684 mItemSyncer = 0;
00685 Q_Q( ResourceBase );
00686 if ( job->error() && job->error() != Job::UserCanceled ) {
00687 emit q->error( job->errorString() );
00688 }
00689 scheduler->taskDone();
00690 }
00691
00692 void ResourceBasePrivate::slotPercent( KJob *job, unsigned long percent )
00693 {
00694 Q_Q( ResourceBase );
00695 Q_UNUSED( job );
00696 emit q->percent( percent );
00697 }
00698
00699 void ResourceBase::setHierarchicalRemoteIdentifiersEnabled( bool enable )
00700 {
00701 Q_D( ResourceBase );
00702 d->mHierarchicalRid = enable;
00703 }
00704
00705 void ResourceBase::scheduleCustomTask( QObject *receiver, const char *method, const QVariant &argument, SchedulePriority priority )
00706 {
00707 Q_D( ResourceBase );
00708 d->scheduler->scheduleCustomTask( receiver, method, argument, priority );
00709 }
00710
00711 void ResourceBase::taskDone()
00712 {
00713 Q_D( ResourceBase );
00714 d->scheduler->taskDone();
00715 }
00716
00717 #include "resourcebase.moc"
00718 #include "moc_resourcebase.cpp"