• Skip to content
  • Skip to link menu
KDE 4.5 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

resourcebase.cpp

00001 /*
00002     Copyright (c) 2006 Till Adam <adam@kde.org>
00003     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or modify it
00006     under the terms of the GNU Library General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or (at your
00008     option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful, but WITHOUT
00011     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013     License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to the
00017     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018     02110-1301, USA.
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     // synchronize states
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   // FIXME: remove once the item with which we call retrieveItem() has a revision number
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       // there is no resource collection, so just ignore the request
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(); // TODO: remove, but where/how do we handle the error?
00329   job->ignorePayload(); // we only want to reset the dirty flag and update the remote id
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   // FIXME: we need at least the revision number too
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   // streaming enabled, so finalize the sync
00429   if ( d->mCollectionSyncer ) {
00430     d->mCollectionSyncer->retrievalDone();
00431   }
00432   // user did the sync himself, we are done now
00433   else {
00434     // FIXME: we need the same special case for SyncAll as in slotCollectionSyncDone here!
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   // check if this collection actually can contain anything
00478   QStringList contentTypes = currentCollection.contentMimeTypes();
00479   contentTypes.removeAll( Collection::mimeType() );
00480   if ( !contentTypes.isEmpty() || (col.rights() & (Collection::CanLinkItem)) ) { // HACK to check for virtual collections
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   // copy list of attributes to fetch
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   // streaming enabled, so finalize the sync
00528   if ( d->mItemSyncer ) {
00529     d->mItemSyncer->deliveryDone();
00530   }
00531   // user did the sync himself, we are done now
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() ); // sends the error reply and
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   // TODO: error handling
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"

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal