23 #include "collection.h"
26 #include "itemcreatejob.h"
27 #include "itemdeletejob.h"
28 #include "itemfetchjob.h"
29 #include "itemmodifyjob.h"
30 #include "transactionsequence.h"
31 #include "itemfetchscope.h"
35 #include <QtCore/QStringList>
37 using namespace Akonadi;
42 class ItemSync::Private
48 mCurrentTransaction( 0 ),
49 mTransactionJobs( 0 ),
53 mTotalItemsProcessed( 0 ),
55 mIncremental( false ),
56 mLocalListDone( false ),
57 mDeliveryDone( false ),
61 mFetchScope.fetchFullPayload();
62 mFetchScope.fetchAllAttributes();
65 void createLocalItem(
const Item &item );
67 void slotLocalListDone( KJob* );
68 void slotLocalDeleteDone( KJob* );
69 void slotLocalChangeDone( KJob* );
73 void slotTransactionResult( KJob *job );
74 Job* subjobParent()
const;
78 QHash<Item::Id, Akonadi::Item> mLocalItemsById;
79 QHash<QString, Akonadi::Item> mLocalItemsByRemoteId;
80 QSet<Akonadi::Item> mUnprocessedLocalItems;
99 int mTotalItemsProcessed;
108 void ItemSync::Private::createLocalItem(
const Item & item )
115 q->connect( create, SIGNAL(result(KJob*)), q, SLOT(slotLocalChangeDone(KJob*)) );
118 void ItemSync::Private::checkDone()
120 q->setProcessedAmount( KJob::Bytes, mProgress );
121 if ( mPendingJobs > 0 || !mDeliveryDone || mTransactionJobs > 0 )
132 d( new Private( this ) )
134 d->mSyncCollection = collection;
144 Q_ASSERT( !d->mIncremental );
145 if ( !d->mStreaming )
146 d->mDeliveryDone =
true;
147 d->mRemoteItems += items;
148 d->mTotalItemsProcessed += items.count();
149 kDebug() <<
"Received: " << items.count() <<
"In total: " << d->mTotalItemsProcessed <<
" Wanted: " << d->mTotalItems;
150 setTotalAmount( KJob::Bytes, d->mTotalItemsProcessed );
151 if ( d->mTotalItemsProcessed == d->mTotalItems )
152 d->mDeliveryDone =
true;
158 Q_ASSERT( !d->mIncremental );
159 Q_ASSERT( amount >= 0 );
162 d->mTotalItems = amount;
163 setTotalAmount( KJob::Bytes, amount );
164 if ( d->mTotalItems == 0 ) {
165 d->mDeliveryDone =
true;
172 d->mIncremental =
true;
173 if ( !d->mStreaming )
174 d->mDeliveryDone =
true;
175 d->mRemoteItems += changedItems;
176 d->mRemovedRemoteItems += removedItems;
177 d->mTotalItemsProcessed += changedItems.count() + removedItems.count();
178 setTotalAmount( KJob::Bytes, d->mTotalItemsProcessed );
179 if ( d->mTotalItemsProcessed == d->mTotalItems )
180 d->mDeliveryDone =
true;
191 return d->mFetchScope;
202 connect( job, SIGNAL(result(KJob*)), SLOT(slotLocalListDone(KJob*)) );
216 if ( d->mIncremental )
219 if ( newItem.d_func()->mClearPayload )
227 if ( storedItem.
flags() != newItem.
flags() ) {
228 kDebug() <<
"Stored flags " << storedItem.
flags()
229 <<
"new flags " << newItem.
flags();
236 if ( !missingParts.isEmpty() )
257 void ItemSync::Private::slotLocalListDone( KJob * job )
259 if ( !job->error() ) {
261 foreach (
const Item &item, list ) {
264 mLocalItemsById.insert( item.
id(), item );
265 mLocalItemsByRemoteId.insert( item.
remoteId(), item );
266 mUnprocessedLocalItems.insert( item );
270 mLocalListDone =
true;
274 void ItemSync::Private::execute()
276 if ( !mLocalListDone )
281 if ( !mDeliveryDone && mRemoteItems.isEmpty() )
284 if ( (mTransactionMode == SingleTransaction && !mCurrentTransaction) || mTransactionMode == MultipleTransactions) {
287 mCurrentTransaction->setAutomaticCommittingEnabled(
false );
288 connect( mCurrentTransaction, SIGNAL(result(KJob*)), q, SLOT(slotTransactionResult(KJob*)) );
292 if ( !mDeliveryDone ) {
293 if ( mTransactionMode == MultipleTransactions && mCurrentTransaction ) {
294 mCurrentTransaction->commit();
295 mCurrentTransaction = 0;
301 if ( !mIncremental ) {
302 mRemovedRemoteItems = mUnprocessedLocalItems.toList();
303 mUnprocessedLocalItems.clear();
306 deleteItems( mRemovedRemoteItems );
307 mLocalItemsById.clear();
308 mLocalItemsByRemoteId.clear();
309 mRemovedRemoteItems.clear();
311 if ( mCurrentTransaction ) {
312 mCurrentTransaction->commit();
313 mCurrentTransaction = 0;
319 void ItemSync::Private::processItems()
322 foreach (
Item remoteItem, mRemoteItems ) {
324 if ( remoteItem.
remoteId().isEmpty() ) {
325 kWarning() <<
"Item " << remoteItem.
id() <<
" does not have a remote identifier";
329 Item localItem = mLocalItemsById.value( remoteItem.
id() );
331 localItem = mLocalItemsByRemoteId.value( remoteItem.
remoteId() );
332 mUnprocessedLocalItems.remove( localItem );
335 createLocalItem( remoteItem );
339 if ( q->updateItem( localItem, remoteItem ) ) {
342 remoteItem.
setId( localItem.
id() );
348 q->connect( mod, SIGNAL(result(KJob*)), q, SLOT(slotLocalChangeDone(KJob*)) );
353 mRemoteItems.clear();
356 void ItemSync::Private::deleteItems(
const Item::List &items )
363 foreach (
const Item &item, items ) {
364 Item delItem( item );
366 delItem = mLocalItemsByRemoteId.value( item.
remoteId() );
369 if ( !delItem.isValid() ) {
371 kWarning() <<
"Delete item (remoteeId=" << item.
remoteId()
373 <<
") does not have a valid UID and no item with that remote ID exists either";
378 if ( delItem.remoteId().isEmpty() ) {
383 itemsToDelete.append ( delItem );
386 if ( !itemsToDelete.isEmpty() ) {
389 q->connect( job, SIGNAL(result(KJob*)), q, SLOT(slotLocalDeleteDone(KJob*)) );
401 void ItemSync::Private::slotLocalDeleteDone( KJob* )
409 void ItemSync::Private::slotLocalChangeDone( KJob * job )
418 void ItemSync::Private::slotTransactionResult( KJob *job )
421 if ( mCurrentTransaction == job )
422 mCurrentTransaction = 0;
427 Job * ItemSync::Private::subjobParent()
const
429 if ( mCurrentTransaction && mTransactionMode != NoTransaction )
430 return mCurrentTransaction;
436 d->mStreaming = enable;
441 Q_ASSERT( d->mStreaming );
442 d->mDeliveryDone =
true;
446 void ItemSync::slotResult(KJob* job)
448 if ( job->error() ) {
453 setError( job->error() );
454 setErrorText( job->errorText() );
457 Akonadi::Job::slotResult( job );
464 if ( d->mCurrentTransaction )
465 d->mCurrentTransaction->rollback();
466 d->mDeliveryDone =
true;
472 d->mTransactionMode = mode;
476 #include "moc_itemsync.cpp"