|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #if !defined(__MSVAPI_H__) |
|
17 #include <msvapi.h> |
|
18 #endif |
|
19 |
|
20 #include "OFFOP.H" |
|
21 #include "MIUTQUE.H" |
|
22 |
|
23 #include "MIUT_ERR.H" |
|
24 #include "MIUTSET.H" // KUidMsgTypeIMAP4 |
|
25 |
|
26 |
|
27 const TUid KUidImQueuedOperationList = {0x10001794}; // 2648441492 dec. |
|
28 |
|
29 |
|
30 // |
|
31 // CImOffLineOperation |
|
32 EXPORT_C CImOffLineOperation::CImOffLineOperation() |
|
33 : iOpType(EOffLineOpNone), iMessageId(KMsvNullIndexEntryId), iTargetMessageId(KMsvNullIndexEntryId),iMtmFunctionId(0),iMtmParameters(NULL) |
|
34 { |
|
35 }; |
|
36 |
|
37 EXPORT_C TBool CImOffLineOperation::Equals(const CImOffLineOperation& aOperation) const |
|
38 { |
|
39 if (iOpType != aOperation.iOpType || |
|
40 iMessageId != aOperation.iMessageId || |
|
41 iTargetMessageId != aOperation.iTargetMessageId || |
|
42 iMtmFunctionId != aOperation.iMtmFunctionId) |
|
43 return EFalse; |
|
44 |
|
45 if (iMtmParameters) |
|
46 { |
|
47 if (!aOperation.iMtmParameters) |
|
48 return EFalse; |
|
49 if (iMtmParameters->Des().Compare(aOperation.iMtmParameters->Des())) |
|
50 return EFalse; |
|
51 } |
|
52 |
|
53 return ETrue; |
|
54 } |
|
55 |
|
56 EXPORT_C void CImOffLineOperation::CopyL(const CImOffLineOperation& aOperation) |
|
57 { |
|
58 DeleteBuffer(); |
|
59 iOpType = aOperation.iOpType; |
|
60 iMessageId = aOperation.iMessageId; |
|
61 iTargetMessageId = aOperation.iTargetMessageId; |
|
62 iMtmFunctionId = aOperation.iMtmFunctionId; |
|
63 if (aOperation.iMtmParameters) |
|
64 { |
|
65 iMtmParameters = aOperation.iMtmParameters->Des().AllocL(); |
|
66 } |
|
67 } |
|
68 |
|
69 EXPORT_C CImOffLineOperation::~CImOffLineOperation() |
|
70 { |
|
71 DeleteBuffer(); |
|
72 } |
|
73 |
|
74 EXPORT_C void CImOffLineOperation::DeleteBuffer() |
|
75 { |
|
76 delete iMtmParameters; |
|
77 iMtmParameters = NULL; |
|
78 } |
|
79 |
|
80 EXPORT_C void CImOffLineOperation::DetachMtmParameters() |
|
81 { |
|
82 iMtmParameters = NULL; |
|
83 } |
|
84 |
|
85 EXPORT_C void CImOffLineOperation::SetMtmSpecificCommandL(TMsvId aMessageId, TMsvId aTargetMessageId, TInt aMtmFunctionId, const TDesC8& aParameters) |
|
86 { |
|
87 HBufC8* parameters = aParameters.AllocL(); |
|
88 SetOperation(EOffLineOpMtmSpecific, aMessageId, aTargetMessageId, aMtmFunctionId, parameters); |
|
89 } |
|
90 |
|
91 |
|
92 EXPORT_C void CImOffLineOperation::SetOperation(TOffLineOpType aOpType, TMsvId aMessageId, TMsvId aTargetMessageId, TInt aMtmFunctionId, HBufC8* aParameters) |
|
93 { |
|
94 DeleteBuffer(); |
|
95 iOpType = aOpType; |
|
96 iMessageId = aMessageId; |
|
97 iTargetMessageId = aTargetMessageId; |
|
98 iMtmFunctionId = aMtmFunctionId; |
|
99 iMtmFunctionId = aMtmFunctionId; |
|
100 iMtmParameters = aParameters; |
|
101 } |
|
102 |
|
103 EXPORT_C void CImOffLineOperation::SetOperation(TOffLineOpType aOpType, TMsvId aMessageId, TMsvId aTargetMessageId) |
|
104 { |
|
105 DeleteBuffer(); |
|
106 iOpType = aOpType; |
|
107 iMessageId = aMessageId; |
|
108 iTargetMessageId = aTargetMessageId; |
|
109 iMtmFunctionId = 0; |
|
110 } |
|
111 |
|
112 EXPORT_C void CImOffLineOperation::ExternalizeL( RMsvWriteStream& aWriteStream ) const |
|
113 { |
|
114 aWriteStream.WriteInt32L(iOpType); |
|
115 aWriteStream.WriteInt32L(iMessageId); |
|
116 aWriteStream.WriteInt32L(iTargetMessageId); |
|
117 aWriteStream.WriteInt32L(iMtmFunctionId); |
|
118 |
|
119 if (iMtmParameters) |
|
120 { |
|
121 TInt length = iMtmParameters->Length(); |
|
122 aWriteStream.WriteInt32L(length); |
|
123 if (length > 0) |
|
124 aWriteStream << TPtrC8(*iMtmParameters); |
|
125 } |
|
126 else |
|
127 { |
|
128 aWriteStream.WriteInt32L(0); |
|
129 } |
|
130 return; |
|
131 } |
|
132 |
|
133 EXPORT_C void CImOffLineOperation::InternalizeL( RMsvReadStream& aReadStream ) |
|
134 { |
|
135 DeleteBuffer(); |
|
136 iOpType = TOffLineOpType(aReadStream.ReadInt32L()); |
|
137 iMessageId = TMsvId(aReadStream.ReadInt32L()); |
|
138 iTargetMessageId = TMsvId(aReadStream.ReadInt32L()); |
|
139 iMtmFunctionId = aReadStream.ReadInt32L(); |
|
140 |
|
141 TInt length = aReadStream.ReadInt32L(); |
|
142 |
|
143 if (length > 0) |
|
144 { |
|
145 iMtmParameters = HBufC8::NewL(aReadStream, length); |
|
146 } |
|
147 return; |
|
148 } |
|
149 |
|
150 EXPORT_C int CImOffLineOperation::operator ==(const CImOffLineOperation& otherOperation) const |
|
151 { |
|
152 TBool result; |
|
153 |
|
154 if ((iMessageId == otherOperation.iMessageId) |
|
155 && (iMtmFunctionId == otherOperation.iMtmFunctionId) |
|
156 && (iOpType == otherOperation.iOpType) |
|
157 && (iTargetMessageId == otherOperation.iTargetMessageId)) |
|
158 { |
|
159 result = ETrue; |
|
160 } |
|
161 else |
|
162 { |
|
163 result = EFalse; |
|
164 } |
|
165 |
|
166 if (iMtmParameters != otherOperation.iMtmParameters) |
|
167 { |
|
168 if ((iMtmParameters == NULL) || (otherOperation.iMtmParameters == NULL)) |
|
169 { |
|
170 result = EFalse; |
|
171 } |
|
172 else if (*iMtmParameters != *(otherOperation.iMtmParameters)) |
|
173 { |
|
174 result = EFalse; |
|
175 } |
|
176 } |
|
177 |
|
178 return result; |
|
179 } |
|
180 |
|
181 |
|
182 // |
|
183 // CImOffLineOperationArrayStore |
|
184 |
|
185 EXPORT_C void CImOffLineArrayStore::StoreL(CMsvStore& aMsvStore) const |
|
186 { |
|
187 RMsvWriteStream out; |
|
188 out.AssignLC( aMsvStore, KUidImQueuedOperationList ); |
|
189 ExternalizeL(out); |
|
190 out.CommitL(); |
|
191 CleanupStack::PopAndDestroy(); |
|
192 } |
|
193 |
|
194 |
|
195 EXPORT_C void CImOffLineArrayStore::RestoreL(const CMsvStore& aMessageStore ) |
|
196 { |
|
197 if (aMessageStore.IsPresentL(KUidImQueuedOperationList)) |
|
198 { |
|
199 RMsvReadStream in; |
|
200 in.OpenLC( aMessageStore, KUidImQueuedOperationList ); // pushes 'in' to the stack |
|
201 InternalizeL(in); |
|
202 CleanupStack::PopAndDestroy(); |
|
203 } |
|
204 } |
|
205 |
|
206 EXPORT_C void CImOffLineArrayStore::ExternalizeL(RMsvWriteStream& aWriteStream) const |
|
207 { |
|
208 TInt nr = iArray->CountOperations(); |
|
209 aWriteStream.WriteUint16L(iVersion); |
|
210 aWriteStream.WriteInt32L(nr); |
|
211 |
|
212 TInt i; |
|
213 for ( i = 0 ; i < nr ; i++) |
|
214 { |
|
215 iArray->Operation( i ).ExternalizeL(aWriteStream); |
|
216 } |
|
217 } |
|
218 |
|
219 EXPORT_C void CImOffLineArrayStore::InternalizeL(RMsvReadStream& aReadStream) |
|
220 { |
|
221 TInt nr; |
|
222 TUint16 version = aReadStream.ReadUint16L(); |
|
223 if (version > iVersion) |
|
224 return; |
|
225 |
|
226 nr = aReadStream.ReadInt32L(); |
|
227 CImOffLineOperation *operation=new(ELeave)CImOffLineOperation; |
|
228 CleanupStack::PushL(operation); |
|
229 |
|
230 TInt i; |
|
231 for (i = 0 ; i < nr ; i++) |
|
232 { |
|
233 operation->InternalizeL(aReadStream); |
|
234 iArray->AppendOperationL(*operation); |
|
235 } |
|
236 CleanupStack::PopAndDestroy();//operation |
|
237 } |
|
238 |
|
239 |
|
240 // |
|
241 // COffLineOperationArrayStore |
|
242 EXPORT_C CImOffLineOperationArray* CImOffLineOperationArray::NewL() |
|
243 { |
|
244 CImOffLineOperationArray* self = new(ELeave)CImOffLineOperationArray(); |
|
245 CleanupStack::PushL(self); |
|
246 self->ConstructL(); |
|
247 CleanupStack::Pop();//self |
|
248 return self; |
|
249 } |
|
250 |
|
251 EXPORT_C void CImOffLineOperationArray::ConstructL() |
|
252 { |
|
253 iArray = new(ELeave)CArrayFixFlat<CImOffLineOperation>(10); |
|
254 } |
|
255 |
|
256 CImOffLineOperationArray::CImOffLineOperationArray() |
|
257 { |
|
258 } |
|
259 |
|
260 EXPORT_C CImOffLineOperationArray::~CImOffLineOperationArray() |
|
261 { |
|
262 if (iArray) |
|
263 { |
|
264 TInt i; |
|
265 TInt nr = CountOperations(); |
|
266 for (i=0;i<nr;i++) |
|
267 { |
|
268 (*iArray)[i].DeleteBuffer(); |
|
269 } |
|
270 delete iArray; |
|
271 } |
|
272 } |
|
273 |
|
274 TInt CImOffLineOperationArray::CountOperations() const |
|
275 { |
|
276 return iArray->Count(); |
|
277 } |
|
278 |
|
279 const CImOffLineOperation& CImOffLineOperationArray::Operation(TInt aIndex) const |
|
280 { |
|
281 return iArray->At(aIndex); |
|
282 } |
|
283 |
|
284 void CImOffLineOperationArray::AppendOperationL(const CImOffLineOperation& aOperation) |
|
285 { |
|
286 CImOffLineOperation *operation=new(ELeave)CImOffLineOperation; |
|
287 CleanupStack::PushL(operation); |
|
288 operation->CopyL(aOperation); // Construct by hand |
|
289 iArray->AppendL(*operation); |
|
290 operation->DetachMtmParameters(); // Delete by hand |
|
291 CleanupStack::PopAndDestroy();//operation |
|
292 } |
|
293 |
|
294 EXPORT_C void CImOffLineOperationArray::InsertOperationL(CImOffLineOperation& aOperation, TInt aPosition) |
|
295 { |
|
296 CImOffLineOperation *operation=new(ELeave)CImOffLineOperation; |
|
297 CleanupStack::PushL(operation); |
|
298 operation->CopyL(aOperation); // Construct by hand |
|
299 iArray->InsertL(aPosition,*operation); |
|
300 operation->DetachMtmParameters(); // Delete by hand |
|
301 CleanupStack::PopAndDestroy();//operation |
|
302 } |
|
303 |
|
304 void CImOffLineOperationArray::Delete(TInt aIndex) |
|
305 { |
|
306 (*iArray)[aIndex].DeleteBuffer(); |
|
307 iArray->Delete(aIndex); |
|
308 } |
|
309 |
|
310 // |
|
311 // TQueuedOperation |
|
312 |
|
313 |
|
314 EXPORT_C TQueuedOperation* TQueuedOperation::NewL(TMsvId aFolderId,TInt aOperationIndex, const CImOffLineOperation& aStoredOperation) |
|
315 { |
|
316 TQueuedOperation* self = new(ELeave)TQueuedOperation(aFolderId,aOperationIndex); |
|
317 CleanupStack::PushL(self); |
|
318 self->iStoredOperation.CopyL(aStoredOperation); |
|
319 CleanupStack::Pop();//self |
|
320 return self; |
|
321 } |
|
322 |
|
323 |
|
324 TQueuedOperation::TQueuedOperation(TMsvId aFolderId,TInt aOperationIndex) |
|
325 : iFolderId(aFolderId),iOperationIndex(aOperationIndex) |
|
326 { |
|
327 } |
|
328 |
|
329 EXPORT_C TQueuedOperation::TQueuedOperation() |
|
330 : iFolderId(KMsvNullIndexEntryId), iOperationIndex(0), iStoredOperation() |
|
331 { |
|
332 } |
|
333 |
|
334 EXPORT_C void TQueuedOperation::CopyL(const TQueuedOperation& aOperation) |
|
335 { |
|
336 iFolderId = aOperation.iFolderId; |
|
337 iOperationIndex = aOperation.iOperationIndex; |
|
338 iStoredOperation.CopyL(aOperation.iStoredOperation); |
|
339 } |
|
340 |
|
341 EXPORT_C TBool TQueuedOperation::operator!=(const TQueuedOperation& aOp) |
|
342 { |
|
343 return (iFolderId != aOp.iFolderId || |
|
344 iOperationIndex != aOp.iOperationIndex || |
|
345 !iStoredOperation.Equals(aOp.iStoredOperation)); |
|
346 } |
|
347 |
|
348 // |
|
349 // CImQueuedList |
|
350 |
|
351 EXPORT_C CImQueuedList* CImQueuedList::NewL() |
|
352 { |
|
353 CImQueuedList* self = new(ELeave)CImQueuedList(); |
|
354 CleanupStack::PushL(self); |
|
355 self->iArray = new(ELeave)CArrayFixFlat<TQueuedOperation>(10); |
|
356 CleanupStack::Pop();//self |
|
357 return self; |
|
358 } |
|
359 |
|
360 CImQueuedList::CImQueuedList() |
|
361 : iFolderId(KMsvNullIndexEntryId), iLine(0) |
|
362 { |
|
363 } |
|
364 |
|
365 EXPORT_C CImQueuedList::~CImQueuedList() |
|
366 { |
|
367 if (iArray) |
|
368 { |
|
369 TInt i; |
|
370 TInt nr = CountOperations(); |
|
371 for (i=0;i<nr;i++) |
|
372 { |
|
373 (*iArray)[i].Operation().DeleteBuffer(); |
|
374 } |
|
375 delete iArray; |
|
376 } |
|
377 } |
|
378 |
|
379 EXPORT_C void CImQueuedList::SetFolder(TMsvId aFolderId) |
|
380 { |
|
381 iFolderId = aFolderId; |
|
382 } |
|
383 |
|
384 EXPORT_C void CImQueuedList::ResetLineCounter() |
|
385 { |
|
386 iLine = 0; |
|
387 } |
|
388 |
|
389 EXPORT_C TQueuedOperation& CImQueuedList::operator[](TInt anIndex) |
|
390 { |
|
391 return (*iArray)[anIndex]; |
|
392 } |
|
393 |
|
394 EXPORT_C TInt CImQueuedList::CountOperations() const |
|
395 { |
|
396 return iArray->Count(); |
|
397 } |
|
398 |
|
399 EXPORT_C const CImOffLineOperation& CImQueuedList::Operation(TInt aIndex) const |
|
400 { |
|
401 return iArray->At(aIndex).Operation(); |
|
402 } |
|
403 |
|
404 EXPORT_C void CImQueuedList::AppendOperationL(const CImOffLineOperation& aOperation) |
|
405 { |
|
406 TQueuedOperation *operation=TQueuedOperation::NewL(iFolderId, iLine, aOperation); |
|
407 CleanupStack::PushL(operation); |
|
408 iArray->AppendL(*operation); |
|
409 operation->Operation().DetachMtmParameters(); |
|
410 CleanupStack::Pop();//operation |
|
411 delete operation; |
|
412 iLine++; |
|
413 } |
|
414 |
|
415 EXPORT_C void CImQueuedList::Delete(TInt aIndex) |
|
416 { |
|
417 (*iArray)[aIndex].Operation().DeleteBuffer(); |
|
418 iArray->Delete(aIndex); |
|
419 } |
|
420 |
|
421 EXPORT_C void CImQueuedList::Reset() |
|
422 { |
|
423 TInt i; |
|
424 TInt nr = iArray->Count(); |
|
425 for (i=0;i<nr;i++) |
|
426 { |
|
427 (*iArray)[i].Operation().DeleteBuffer(); |
|
428 } |
|
429 iArray->Reset(); |
|
430 } |
|
431 |
|
432 EXPORT_C void CImQueuedList::AppendL(TQueuedOperation& aOperation) |
|
433 { |
|
434 iArray->AppendL(aOperation); |
|
435 aOperation.Operation().DetachMtmParameters(); |
|
436 } |
|
437 |
|
438 // |
|
439 // CImOperationQueueList |
|
440 // |
|
441 // definition of class CImOperationQueueList. This class is responsible for gathering all |
|
442 // the queued information of a MTM service, traversing folders to gather that |
|
443 // information. It will then give access to the queued operations in the list, allowing |
|
444 // queued elements to be deleted. |
|
445 // |
|
446 |
|
447 EXPORT_C CImOperationQueueList* CImOperationQueueList::NewL(CMsvEntry& aServiceEntry, MImUndoOffLineOperation *aImUndoOffLineOperation) |
|
448 // |
|
449 // Create new list of queued operations for service entry aServiceEntry is set to. |
|
450 // |
|
451 { |
|
452 CImOperationQueueList* self = new (ELeave) CImOperationQueueList(aServiceEntry, aImUndoOffLineOperation); |
|
453 CleanupStack::PushL(self); |
|
454 self->ConstructL(); |
|
455 CleanupStack::Pop();//self |
|
456 return self; |
|
457 } |
|
458 |
|
459 EXPORT_C CImOperationQueueList::~CImOperationQueueList() |
|
460 { |
|
461 delete iServiceEntry; |
|
462 delete iQueuedList; |
|
463 delete iDeletedList; |
|
464 } |
|
465 |
|
466 CImOperationQueueList::CImOperationQueueList(CMsvEntry& aServiceEntry, MImUndoOffLineOperation *aImUndoOffLineOperation) |
|
467 : iServiceEntry(&aServiceEntry) , iUndoOffline(aImUndoOffLineOperation) |
|
468 { |
|
469 iServiceId = iServiceEntry->Entry().Id(); |
|
470 }; |
|
471 |
|
472 void CImOperationQueueList::ProcessFoldersL() |
|
473 // |
|
474 // Usage: reset iQueuedList, set iServiceEntry to the service entry, and |
|
475 // call this function if a complete list of all queued operations stored |
|
476 // under the folders within the service is needed. |
|
477 // |
|
478 { |
|
479 __ASSERT_DEBUG( iServiceEntry->Entry().iType == KUidMsvFolderEntry || |
|
480 iServiceEntry->Entry().iType == KUidMsvServiceEntry, gPanic(EOffOpEntryShouldBeFolder)); |
|
481 CMsvEntrySelection* selection = iServiceEntry->ChildrenWithTypeL(KUidMsvFolderEntry); |
|
482 CleanupStack::PushL(selection); |
|
483 |
|
484 TInt folder; |
|
485 TInt nr = selection->Count(); |
|
486 for ( folder = 0 ; folder < nr; folder ++ ) |
|
487 { |
|
488 iServiceEntry->SetEntryL( (*selection)[ folder ] ); |
|
489 RestoreQueuedListL(*iQueuedList); |
|
490 ProcessFoldersL(); |
|
491 } |
|
492 |
|
493 CleanupStack::PopAndDestroy();//selection |
|
494 } |
|
495 |
|
496 void CImOperationQueueList::ConstructL() |
|
497 // |
|
498 // Create the list of queued operations. |
|
499 // |
|
500 { |
|
501 iQueuedList = CImQueuedList::NewL(); |
|
502 iDeletedList = CImQueuedList::NewL(); |
|
503 |
|
504 iDeletedList->Reset(); |
|
505 iQueuedList->Reset(); |
|
506 ProcessFoldersL(); |
|
507 } |
|
508 |
|
509 EXPORT_C void CImOperationQueueList::DeleteL(TInt aLine) |
|
510 // |
|
511 // Remove operation from list of queued operations locally. |
|
512 // |
|
513 { |
|
514 TQueuedOperation deletedOperation; |
|
515 deletedOperation.CopyL((*iQueuedList)[aLine]); |
|
516 iQueuedList->Delete(aLine); |
|
517 iDeletedList->AppendL(deletedOperation); |
|
518 } |
|
519 |
|
520 void CImOperationQueueList::RestoreQueuedListL(CImQueuedList &aList) |
|
521 // |
|
522 // Append contents of current entry (pointed to by iServiceEntry) |
|
523 // to aList. |
|
524 // |
|
525 { |
|
526 __ASSERT_DEBUG( iServiceEntry->Entry().iMtm == KUidMsgTypeIMAP4, gPanic(EOffOpBadMtmTypeUid)); |
|
527 __ASSERT_DEBUG( iServiceEntry->Entry().iType == KUidMsvFolderEntry || |
|
528 iServiceEntry->Entry().iType == KUidMsvServiceEntry, gPanic(EOffOpEntryShouldBeFolder)); |
|
529 |
|
530 TInt err=KErrNone; |
|
531 CMsvStore* store=NULL; |
|
532 // Leaves with KErrNotFound if no store exists. |
|
533 TRAP(err,store=iServiceEntry->ReadStoreL()); |
|
534 if (err) |
|
535 return; |
|
536 CleanupStack::PushL(store); |
|
537 |
|
538 aList.SetFolder(iServiceEntry->Entry().Id()); |
|
539 aList.ResetLineCounter(); |
|
540 |
|
541 CImOffLineArrayStore internaliser(aList); |
|
542 internaliser.RestoreL(*store); |
|
543 CleanupStack::PopAndDestroy();//store |
|
544 } |
|
545 |
|
546 void CImOperationQueueList::StoreQueuedListL(CImQueuedList &aList) |
|
547 // |
|
548 // Store contents of aList back in current entry (pointed to by iServiceEntry) |
|
549 // to aList. |
|
550 // |
|
551 { |
|
552 __ASSERT_DEBUG( iServiceEntry->Entry().iMtm == KUidMsgTypeIMAP4, gPanic(EOffOpBadMtmTypeUid)); |
|
553 __ASSERT_DEBUG( iServiceEntry->Entry().iType == KUidMsvFolderEntry || |
|
554 iServiceEntry->Entry().iType == KUidMsvServiceEntry, gPanic(EOffOpEntryShouldBeFolder)); |
|
555 CMsvStore* store = iServiceEntry->EditStoreL(); |
|
556 CleanupStack::PushL(store); |
|
557 CImOffLineArrayStore externaliser(aList); |
|
558 externaliser.StoreL(*store); |
|
559 store->CommitL(); |
|
560 CleanupStack::PopAndDestroy();//store |
|
561 } |
|
562 |
|
563 EXPORT_C void CImOperationQueueList::ExpungeDeletedOperationsL() |
|
564 // |
|
565 // Remove the queued operations that were marked as deleted from the folder stores. |
|
566 // |
|
567 { |
|
568 // First sort so that each store only has to be visited once, and queued operations |
|
569 // can be deleted back-to-front. Starting at the back leaves the other delete commands |
|
570 // valid. |
|
571 TQueuedOperationKey key(*iDeletedList); |
|
572 TQueuedOperationSwap swap(*iDeletedList); |
|
573 User::QuickSort(iDeletedList->CountOperations(),key,swap); |
|
574 |
|
575 // Current folder being updated |
|
576 TMsvId lastFolderRead = KMsvNullIndexEntryId; |
|
577 // list holds the list of queued operations for the current folder |
|
578 CImQueuedList *list = CImQueuedList::NewL(); |
|
579 CleanupStack::PushL(list); |
|
580 |
|
581 TInt line; |
|
582 |
|
583 TInt nr = iDeletedList->CountOperations(); |
|
584 for ( line = 0 ; line < nr; line ++ ) |
|
585 { |
|
586 // Get item to delete |
|
587 TQueuedOperation toDelete; |
|
588 toDelete.CopyL((*iDeletedList)[ 0 ]); |
|
589 iDeletedList->Delete(0); |
|
590 |
|
591 // See if item belongs to different folder. |
|
592 if (lastFolderRead != toDelete.FolderId()) |
|
593 { |
|
594 // Store changes to previous list |
|
595 if (lastFolderRead != KMsvNullIndexEntryId) |
|
596 { |
|
597 StoreQueuedListL(*list); |
|
598 } |
|
599 |
|
600 // go to folder to delete item from. |
|
601 iServiceEntry->SetEntryL(toDelete.FolderId()); |
|
602 __ASSERT_DEBUG( iServiceEntry->Entry().iMtm == KUidMsgTypeIMAP4, gPanic(EOffOpBadMtmTypeUid)); |
|
603 __ASSERT_DEBUG(iServiceEntry->Entry().iType == KUidMsvFolderEntry, gPanic(EOffOpEntryShouldBeFolder)); |
|
604 |
|
605 // Initialise for the next folder |
|
606 lastFolderRead = toDelete.FolderId(); |
|
607 // Get the list of queued operations |
|
608 list->Reset(); |
|
609 RestoreQueuedListL(*list); |
|
610 } |
|
611 |
|
612 // Sanity check: the data contained in toDelete should be EXACTLY the same as |
|
613 // the queued operation it refers to (as retrieved from the folder) |
|
614 if (toDelete != (*list)[ toDelete.OperationIndex() ]) |
|
615 { |
|
616 gPanic(EOffOpListOutOfSync); |
|
617 continue; |
|
618 } |
|
619 |
|
620 // Undo changes made in server to reflect the disconnected operation. |
|
621 iUndoOffline->UndoOffLineChangesL(toDelete.Operation(), toDelete.FolderId()); |
|
622 // Delete queued operation from list |
|
623 list->Delete(toDelete.OperationIndex()); |
|
624 } |
|
625 |
|
626 // Store changes to last folder. |
|
627 if (lastFolderRead != KMsvNullIndexEntryId) |
|
628 { |
|
629 StoreQueuedListL(*list); |
|
630 } |
|
631 CleanupStack::PopAndDestroy(); //list |
|
632 } |
|
633 |
|
634 // |
|
635 // TQueuedOperationSwap |
|
636 EXPORT_C TQueuedOperationSwap::TQueuedOperationSwap(CImQueuedList& aList) |
|
637 : iList(aList) |
|
638 { |
|
639 }; |
|
640 |
|
641 void TQueuedOperationSwap::Swap(TInt aLeft,TInt aRight) const |
|
642 { |
|
643 Mem::Swap(&iList[aLeft],&iList[aRight],sizeof(TQueuedOperation)); |
|
644 } |
|
645 |
|
646 // |
|
647 // TQueuedOperationKey |
|
648 EXPORT_C TQueuedOperationKey::TQueuedOperationKey(CImQueuedList& aList) |
|
649 : iList(aList) |
|
650 { |
|
651 } |
|
652 |
|
653 TInt TQueuedOperationKey::Compare(TInt aLeft,TInt aRight) const |
|
654 { |
|
655 if (aLeft == aRight) |
|
656 return 0; |
|
657 if (iList[ aLeft ].FolderId() != iList[ aRight ].FolderId()) |
|
658 return iList[ aLeft ].FolderId() - iList[ aRight ].FolderId(); |
|
659 // Sort in descending order, so last lines will be deleted first |
|
660 TInt diff = iList[ aRight ].OperationIndex() - iList[ aLeft ].OperationIndex(); |
|
661 __ASSERT_DEBUG(diff != 0, gPanic(EOffOpTwoSameLinesNotAllowed)); |
|
662 return diff; |
|
663 } |
|
664 TAny *TQueuedOperationKey::At(TInt anIndex) const |
|
665 { |
|
666 return &iList[ anIndex ]; |
|
667 } |
|
668 |
|
669 |