|
1 |
|
2 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 // All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Nokia Corporation - initial contribution. |
|
11 // |
|
12 // Contributors: |
|
13 // |
|
14 // Description: |
|
15 // |
|
16 |
|
17 #include <msventry.h> |
|
18 #include <offop.h> |
|
19 #include "POPSOFFL.H" |
|
20 #include "popstran.h" |
|
21 #include "POPS.PAN" |
|
22 |
|
23 // API |
|
24 // === |
|
25 // The CImPop3OfflineOperationFinder class is used to find and order offline |
|
26 // operations. It can also be used to obtain progress information eg. the |
|
27 // number of operations queued of a particular type. |
|
28 |
|
29 // Offline operations are retrieved by first calling the asynchronous |
|
30 // FindFirstL function. After completetion call the OperationFound function |
|
31 // to find out whether or not an offline operation has been found, if it has |
|
32 // then the OfflineOperation function should be called to retrive it. |
|
33 // |
|
34 // The FindNextL function should be called to find other offline operations |
|
35 // (in conjunction with the OperationFound and OfflineOperations functions.) |
|
36 // It should be noted that the FindNextL function is synchronous. |
|
37 |
|
38 // The DeleteCurrentOperationL() function deletes the current entry from the |
|
39 // message store. |
|
40 |
|
41 // OperationDetails returns TOperationDetails which can be used for providing |
|
42 // progress information. |
|
43 |
|
44 |
|
45 // Implementaiton |
|
46 // ============== |
|
47 // The asynchronous FindFirstL function builds up a list of |
|
48 // CImOffLineOperationArray objects, each array holds a list of operations |
|
49 // of a particular type. |
|
50 |
|
51 // The operations are stored this way to facilitate easy ordering based on |
|
52 // operation type as well as being useful for generating progress |
|
53 // information. |
|
54 |
|
55 // The operations are retrieved by first visiting each message under the |
|
56 // service, this potentially slow operation is handled by the asynchronous |
|
57 // function. |
|
58 |
|
59 CImPop3OfflineOperationFinder* CImPop3OfflineOperationFinder::NewL(CMsvServerEntry& aEntry) |
|
60 { |
|
61 CImPop3OfflineOperationFinder* self = NewLC(aEntry); |
|
62 CleanupStack::Pop(); // self |
|
63 return self; |
|
64 } |
|
65 |
|
66 CImPop3OfflineOperationFinder* CImPop3OfflineOperationFinder::NewLC(CMsvServerEntry& aEntry) |
|
67 { |
|
68 CImPop3OfflineOperationFinder* self = new (ELeave) CImPop3OfflineOperationFinder(aEntry); |
|
69 CleanupStack::PushL(self); |
|
70 self->ConstructL(); |
|
71 return self; |
|
72 } |
|
73 |
|
74 void CImPop3OfflineOperationFinder::FindFirstL(TMsvId aServiceId, TBool aQuitting, TRequestStatus &aStatus) |
|
75 // Asynchronous function for finding all the offline operations and setting |
|
76 // the current operation (iOperationArrayIndex and iOperationIndex) to point |
|
77 // to the first one. |
|
78 |
|
79 // Use OperationFound(), OfflineOperation() and OperationDetails() to access |
|
80 // the results of this search. |
|
81 { |
|
82 TInt index = 0; |
|
83 // Delete each of the CImOffLineOperationArrays |
|
84 while (index < iOfflineOperations->Count()) |
|
85 { |
|
86 delete (*iOfflineOperations)[index]; |
|
87 index++; |
|
88 } |
|
89 iOfflineOperations->Reset(); |
|
90 |
|
91 iServiceId = aServiceId; |
|
92 iState = EPopsOffOpLookingForMessages; |
|
93 iQuitting = aQuitting; |
|
94 |
|
95 if (iChildMessages) |
|
96 { |
|
97 delete iChildMessages; |
|
98 iChildMessages = 0; |
|
99 } |
|
100 |
|
101 iChildMessages = new (ELeave) CMsvEntrySelection(); |
|
102 |
|
103 User::LeaveIfError(iEntry.GetChildren(*iChildMessages)); |
|
104 iMessageIndex = 0; |
|
105 Queue(aStatus); |
|
106 if (iChildMessages->Count()) |
|
107 { |
|
108 // Check the first message for offline operations. |
|
109 CheckNextChildMessageL(); |
|
110 } |
|
111 else |
|
112 { |
|
113 // There are no messages found so complete and stop searching here. |
|
114 delete iChildMessages; |
|
115 iChildMessages = 0; |
|
116 Complete(KErrNone); |
|
117 } |
|
118 } |
|
119 |
|
120 void CImPop3OfflineOperationFinder::CheckNextChildMessageL() |
|
121 // Check the current message (iMessageIndex) and append any offline operations |
|
122 // to the offline operations list. |
|
123 { |
|
124 if (iMessageIndex < iChildMessages->Count()) |
|
125 { |
|
126 iEntry.SetEntry((*iChildMessages)[iMessageIndex]); |
|
127 TMsvEmailEntry entry = iEntry.Entry(); |
|
128 if (entry.DisconnectedOperation() != ENoDisconnectedOperations) |
|
129 // If the entry has offline operations queued then add it to the list. |
|
130 { |
|
131 AppendOfflineOpsL(); |
|
132 } |
|
133 } |
|
134 |
|
135 SetActive(); |
|
136 TRequestStatus* status = &iStatus; |
|
137 User::RequestComplete(status, KErrNone); |
|
138 } |
|
139 |
|
140 void CImPop3OfflineOperationFinder::AppendOfflineOpsL() |
|
141 // This private help function appends the offline operations associated with the |
|
142 // current message to the appropriate offline operations array. |
|
143 // The array to which it is added depends on the operation type. If there |
|
144 // is currently no array for this operation type then one is created. |
|
145 { |
|
146 // Get the offline operations for the current message. |
|
147 CImOffLineOperationArray* localOfflineOpArray = CImOffLineOperationArray::NewL(); |
|
148 CleanupStack::PushL(localOfflineOpArray); |
|
149 CImOffLineArrayStore* offlineArrayStore = new (ELeave) CImOffLineArrayStore(*localOfflineOpArray); |
|
150 CleanupStack::PushL(offlineArrayStore); |
|
151 CMsvStore* messageStore = iEntry.ReadStoreL(); |
|
152 CleanupStack::PushL(messageStore); |
|
153 offlineArrayStore->RestoreL(*messageStore); |
|
154 |
|
155 // Append the local offline operations to the correct operations list. |
|
156 TInt opCounter; |
|
157 TInt offlineOps = localOfflineOpArray->CountOperations(); |
|
158 const CImOffLineOperation* newOperation; |
|
159 for (opCounter = 0; opCounter < offlineOps; opCounter++) |
|
160 { |
|
161 newOperation = &localOfflineOpArray->Operation(opCounter); |
|
162 // Append newOperation to the correct list as each list holds a different operation type. |
|
163 |
|
164 // Find the appropriate offline operation list. |
|
165 CImOffLineOperationArray* operationArray = 0; |
|
166 if (iOfflineOperations->Count() == 0) |
|
167 { |
|
168 // If there are no arrays then create the first one. |
|
169 operationArray = CImOffLineOperationArray::NewL(); |
|
170 CleanupStack::PushL(operationArray); |
|
171 iOfflineOperations->AppendL(operationArray, sizeof(void*)); |
|
172 CleanupStack::Pop(operationArray); |
|
173 } |
|
174 else |
|
175 { |
|
176 TBool found = EFalse; |
|
177 TInt index = 0; |
|
178 // Search the different arrays for one that contains the correct operation types. |
|
179 while ((!found) && (index < iOfflineOperations->Count())) |
|
180 { |
|
181 if ((*iOfflineOperations)[index]->CountOperations()) |
|
182 { |
|
183 if (((*iOfflineOperations)[index]->Operation(0)).OpType() == newOperation->OpType()) |
|
184 { |
|
185 found = ETrue; |
|
186 operationArray = (*iOfflineOperations)[index]; |
|
187 } |
|
188 } |
|
189 index++; |
|
190 } |
|
191 |
|
192 if (!found) |
|
193 { |
|
194 // If there are no appropriate arrays then create a new one. |
|
195 operationArray = CImOffLineOperationArray::NewL(); |
|
196 CleanupStack::PushL(operationArray); |
|
197 iOfflineOperations->AppendL(operationArray, sizeof(void*)); |
|
198 CleanupStack::Pop(operationArray); |
|
199 } |
|
200 } |
|
201 |
|
202 operationArray->AppendOperationL(*newOperation); |
|
203 } |
|
204 |
|
205 CleanupStack::PopAndDestroy(3); // offlineArrayStore, messageStore, localOfflineOperationArray |
|
206 } |
|
207 |
|
208 |
|
209 TBool CImPop3OfflineOperationFinder::AppropriateOperation(const CImOffLineOperation& aOperation) const |
|
210 { |
|
211 // Returns true if the operation should be run at this point. |
|
212 // Delete operations should be run at the end of the session, all others at the start. |
|
213 return (aOperation.OpType()==CImOffLineOperation::EOffLineOpDelete) ? iQuitting : (!iQuitting); |
|
214 } |
|
215 |
|
216 |
|
217 void CImPop3OfflineOperationFinder::FindNext() |
|
218 // Finds the next offline operations. |
|
219 // The results of this function call are valid as soon as the function returns. |
|
220 { |
|
221 TBool go = ETrue; |
|
222 |
|
223 CImOffLineOperationArray* operationArray = 0; |
|
224 iOperationIndex++; |
|
225 while (go) |
|
226 { |
|
227 go = ETrue; |
|
228 |
|
229 if (iOfflineOperations->Count()) |
|
230 { |
|
231 operationArray = (*iOfflineOperations)[iOperationArrayIndex]; |
|
232 } |
|
233 else |
|
234 { |
|
235 operationArray = 0; |
|
236 } |
|
237 |
|
238 if (operationArray == 0) |
|
239 { |
|
240 go = EFalse; |
|
241 } |
|
242 else if (iOperationIndex == operationArray->CountOperations()) |
|
243 // If there are no more operations in this array then move on to the next one. |
|
244 { |
|
245 iOperationArrayIndex++; |
|
246 iOperationIndex = 0; |
|
247 } |
|
248 else if (!AppropriateOperation(operationArray->Operation(0))) |
|
249 // If the operations in this array aren't of an appropriate type then move on to the next one. |
|
250 { |
|
251 iOperationArrayIndex++; |
|
252 iOperationIndex = 0; |
|
253 } |
|
254 else |
|
255 // An appropriate operation has been found. |
|
256 { |
|
257 go = EFalse; |
|
258 } |
|
259 |
|
260 if (iOperationArrayIndex == iOfflineOperations->Count()) |
|
261 // If there are no more operation arrays then don't carry on looking. |
|
262 { |
|
263 go = EFalse; |
|
264 } |
|
265 } |
|
266 |
|
267 // Set the operaitons details for later. |
|
268 if (OperationFound()) |
|
269 { |
|
270 iOperationDetails.iOpType = OfflineOperation().OpType(); |
|
271 iOperationDetails.iOperationNumber = iOperationIndex; |
|
272 iOperationDetails.iOperationsOfType = ((*iOfflineOperations)[iOperationArrayIndex])->CountOperations(); |
|
273 } |
|
274 else |
|
275 { |
|
276 iOperationDetails.iOpType = CImOffLineOperation::EOffLineOpNone; |
|
277 } |
|
278 } |
|
279 |
|
280 TBool CImPop3OfflineOperationFinder::OperationFound() const |
|
281 // Returns true if an operation has been found. |
|
282 { |
|
283 return (iOperationArrayIndex < (iOfflineOperations->Count())); |
|
284 } |
|
285 |
|
286 const CImOffLineOperation& CImPop3OfflineOperationFinder::OfflineOperation() const |
|
287 // Returns the current offline operations. |
|
288 { |
|
289 return ((*iOfflineOperations)[iOperationArrayIndex])->Operation(iOperationIndex); |
|
290 } |
|
291 |
|
292 const CImPop3OfflineOperationFinder::TOperationDetails& CImPop3OfflineOperationFinder::OperationDetails() const |
|
293 // Returns the details for the current operation. |
|
294 { |
|
295 return iOperationDetails; |
|
296 } |
|
297 |
|
298 CImPop3OfflineOperationFinder::~CImPop3OfflineOperationFinder() |
|
299 { |
|
300 delete iChildMessages; |
|
301 TInt index = 0; |
|
302 if (iOfflineOperations) |
|
303 { |
|
304 // Delete each of the CImOffLineOperationArrays |
|
305 while (index < iOfflineOperations->Count()) |
|
306 { |
|
307 delete (*iOfflineOperations)[index]; |
|
308 index++; |
|
309 } |
|
310 delete iOfflineOperations; |
|
311 } |
|
312 } |
|
313 |
|
314 void CImPop3OfflineOperationFinder::DoRunL() |
|
315 { |
|
316 ++iMessageIndex; |
|
317 if (iMessageIndex < iChildMessages->Count()) |
|
318 // If there are more messages then check them for offline operations. |
|
319 { |
|
320 CheckNextChildMessageL(); |
|
321 } |
|
322 else |
|
323 // If there are no more messages then go back and find all the offline operations. |
|
324 { |
|
325 delete iChildMessages; |
|
326 iChildMessages = 0; |
|
327 |
|
328 // Move the offline copy opertion array to the front of the list. |
|
329 TInt index = 0; |
|
330 TBool go = ETrue; |
|
331 while ((index < iOfflineOperations->Count()) |
|
332 && go) |
|
333 { |
|
334 CImOffLineOperation::TOffLineOpType opType = ((*iOfflineOperations)[index]->Operation(0)).OpType(); |
|
335 if (opType == CImOffLineOperation::EOffLineOpCopyToLocal) |
|
336 { |
|
337 // Move the offline copy operation array to the front of the list. |
|
338 go = EFalse; |
|
339 CImOffLineOperationArray* populateOperationList = (*iOfflineOperations)[index]; |
|
340 iOfflineOperations->Delete(index); |
|
341 iOfflineOperations->InsertL(index, populateOperationList, sizeof(void*)); |
|
342 } |
|
343 else |
|
344 { |
|
345 index++; |
|
346 } |
|
347 } |
|
348 |
|
349 // Move the offline populate opertion array to the front of the list. |
|
350 index = 0; |
|
351 go = ETrue; |
|
352 while ((index < iOfflineOperations->Count()) |
|
353 && go) |
|
354 { |
|
355 CImOffLineOperation::TOffLineOpType opType = ((*iOfflineOperations)[index]->Operation(0)).OpType(); |
|
356 if (opType == CImOffLineOperation::EOffLineOpCopyWithinService) |
|
357 { |
|
358 // Move the offline populate operation array to the front of the list. |
|
359 go = EFalse; |
|
360 CImOffLineOperationArray* populateOperationList = (*iOfflineOperations)[index]; |
|
361 iOfflineOperations->Delete(index); |
|
362 iOfflineOperations->InsertL(index, populateOperationList, sizeof(void*)); |
|
363 } |
|
364 else |
|
365 { |
|
366 index++; |
|
367 } |
|
368 } |
|
369 |
|
370 // Set the iOperationIndex to the first appropriate operation. |
|
371 iOperationArrayIndex = 0; |
|
372 iOperationIndex = -1; |
|
373 FindNext(); |
|
374 |
|
375 Complete(KErrNone); |
|
376 } |
|
377 } |
|
378 |
|
379 void CImPop3OfflineOperationFinder::DoCancel() |
|
380 { |
|
381 CMsgActive::DoCancel(); |
|
382 } |
|
383 |
|
384 void CImPop3OfflineOperationFinder::DoComplete() |
|
385 { |
|
386 |
|
387 } |
|
388 |
|
389 void CImPop3OfflineOperationFinder::ConstructL() |
|
390 { |
|
391 CActiveScheduler::Add(this); |
|
392 iOfflineOperations = new (ELeave) CArrayVarFlat<CImOffLineOperationArray*>(3); |
|
393 } |
|
394 |
|
395 CImPop3OfflineOperationFinder::CImPop3OfflineOperationFinder(CMsvServerEntry& aEntry) : CMsgActive(EPriorityStandard), iEntry(aEntry) |
|
396 { |
|
397 |
|
398 } |
|
399 |
|
400 |
|
401 |
|
402 |
|
403 |
|
404 |
|
405 // API |
|
406 // === |
|
407 // The CImPop3SetOfflineOps class provides a means of asynchronously adding |
|
408 // offline operations to the message stores of the appropriate messages. |
|
409 |
|
410 // Use the AddOfflineOperationL to add the offline operations. |
|
411 |
|
412 |
|
413 CImPop3SetOfflineOps* CImPop3SetOfflineOps::NewL(CMsvServerEntry& aEntry) |
|
414 { |
|
415 CImPop3SetOfflineOps* self = NewLC(aEntry); |
|
416 CleanupStack::Pop(); // self |
|
417 return self; |
|
418 } |
|
419 |
|
420 CImPop3SetOfflineOps* CImPop3SetOfflineOps::NewLC(CMsvServerEntry& aEntry) |
|
421 { |
|
422 CImPop3SetOfflineOps* self = new (ELeave) CImPop3SetOfflineOps(aEntry); |
|
423 CleanupStack::PushL(self); |
|
424 self->ConstructL(); |
|
425 CActiveScheduler::Add(self); |
|
426 // ConstructL(); |
|
427 return self; |
|
428 } |
|
429 |
|
430 void CImPop3SetOfflineOps::AddOfflineOperationL(const CMsvEntrySelection *aMessageSelection, |
|
431 CImOffLineOperation::TOffLineOpType aOperationType, |
|
432 TMsvId aTargetFolderId, |
|
433 TRequestStatus& aStatus) |
|
434 // Adds the aOperationType operation to each message in aMessageSelection. |
|
435 // The aTargetFolderId is not used for some operation types, eg. deleting. |
|
436 { |
|
437 iState = EAddingOfflineOperations; |
|
438 |
|
439 iMessageCounter = 0; |
|
440 iOperationType = aOperationType; |
|
441 iDestinationEntryId = aTargetFolderId; |
|
442 |
|
443 delete iSourceMessages; |
|
444 iSourceMessages = 0; |
|
445 |
|
446 delete iMessagesToCopyLocally; |
|
447 iMessagesToCopyLocally = new (ELeave) CMsvEntrySelection; |
|
448 |
|
449 iSourceMessages = aMessageSelection->CopyL(); |
|
450 |
|
451 TInt count = iSourceMessages->Count(); |
|
452 iOfflineOperationArrayFlag.Reset(); |
|
453 |
|
454 for(TInt i=0; i< count; ++i ) |
|
455 { |
|
456 iOfflineOperationArrayFlag.AppendL(EFalse); |
|
457 } |
|
458 |
|
459 |
|
460 Queue(aStatus); |
|
461 |
|
462 AddOfflineOperationL(); |
|
463 } |
|
464 |
|
465 |
|
466 void CImPop3SetOfflineOps::CancelOfflineOperationsL(const CMsvEntrySelection& aSelection, TRequestStatus& aStatus) |
|
467 // Cancel all pending operations on each message in aSelection. |
|
468 { |
|
469 iState = ECancellingOfflineOperations; |
|
470 iMessageCounter = 0; |
|
471 |
|
472 delete iSourceMessages; |
|
473 iSourceMessages = 0; |
|
474 |
|
475 iSourceMessages = aSelection.CopyL(); |
|
476 Queue(aStatus); |
|
477 |
|
478 CancelOfflineOperationL(); |
|
479 } |
|
480 |
|
481 // Resumes a cancelled "Cancel Offline Operations" operation. |
|
482 void CImPop3SetOfflineOps::ResumeCancelOfflineOperationsL(TRequestStatus& aStatus) |
|
483 { |
|
484 Queue(aStatus); |
|
485 CancelOfflineOperationL(); |
|
486 } |
|
487 |
|
488 void CImPop3SetOfflineOps::AddOfflineOperationL() |
|
489 { |
|
490 // Set the current entry, ready for the operation to be attached to it. |
|
491 User::LeaveIfError(iEntry.SetEntry((*iSourceMessages)[iMessageCounter])); |
|
492 |
|
493 iModifiedOperationType = iOperationType; |
|
494 |
|
495 if ((iEntry.Entry()).Complete()) |
|
496 // Any messages that have already been populated can be copied locally without |
|
497 // the need to be online. |
|
498 // This is done after any offline operations have been added but they are |
|
499 // saved for later here: |
|
500 { |
|
501 if (iOperationType == CImOffLineOperation::EOffLineOpCopyToLocal) |
|
502 { |
|
503 iMessagesToCopyLocally->AppendL(iEntry.Entry().Id()); |
|
504 iModifiedOperationType = CImOffLineOperation::EOffLineOpNone; |
|
505 } |
|
506 |
|
507 if (iOperationType == CImOffLineOperation::EOffLineOpMoveToLocal) |
|
508 { |
|
509 iMessagesToCopyLocally->AppendL(iEntry.Entry().Id()); |
|
510 iModifiedOperationType = CImOffLineOperation::EOffLineOpDelete; |
|
511 } |
|
512 } |
|
513 |
|
514 if (iModifiedOperationType == CImOffLineOperation::EOffLineOpNone) |
|
515 { |
|
516 iStatus = KRequestPending; |
|
517 SetActive(); |
|
518 TRequestStatus* status = &iStatus; |
|
519 User::RequestComplete(status, KErrNone); |
|
520 return; |
|
521 } |
|
522 |
|
523 CImOffLineOperationArray* operationArray = CImOffLineOperationArray::NewL(); |
|
524 CleanupStack::PushL(operationArray); |
|
525 CImOffLineArrayStore* operationStore = new (ELeave) CImOffLineArrayStore(*operationArray); |
|
526 CleanupStack::PushL(operationStore); |
|
527 CMsvStore* messageStore = iEntry.EditStoreL(); |
|
528 CleanupStack::PushL(messageStore); |
|
529 |
|
530 // Get the array of operations currently attached to the message. |
|
531 operationStore->RestoreL(*messageStore); |
|
532 |
|
533 // If the operation is a move or delete then ensure that it doesn't interfere with any existing operations. |
|
534 if ((iModifiedOperationType == CImOffLineOperation::EOffLineOpMoveToLocal) |
|
535 || (iModifiedOperationType == CImOffLineOperation::EOffLineOpDelete)) |
|
536 { |
|
537 // Find out if there is a move or a delete operation already pending on the message. |
|
538 TBool moveOrDeleteAlreadyPending = EFalse; |
|
539 CImOffLineOperation::TOffLineOpType opType; |
|
540 TInt counter = operationArray->CountOperations(); |
|
541 |
|
542 while (counter > 0) |
|
543 { |
|
544 counter--; |
|
545 opType = (operationArray->Operation(counter)).OpType(); |
|
546 if ((opType == CImOffLineOperation::EOffLineOpMoveToLocal) |
|
547 || (opType == CImOffLineOperation::EOffLineOpDelete)) |
|
548 { |
|
549 moveOrDeleteAlreadyPending = ETrue; |
|
550 counter = 0; |
|
551 } |
|
552 } |
|
553 |
|
554 if (moveOrDeleteAlreadyPending) |
|
555 { |
|
556 if (iModifiedOperationType == CImOffLineOperation::EOffLineOpMoveToLocal) |
|
557 { |
|
558 // Change the move operation to a copy, it will be deleted by the existing move or delete. |
|
559 iModifiedOperationType = CImOffLineOperation::EOffLineOpCopyToLocal; |
|
560 } |
|
561 |
|
562 if (iModifiedOperationType == CImOffLineOperation::EOffLineOpDelete) |
|
563 { |
|
564 // No need to append this delete operation as it will be delete be the existing move or delete. |
|
565 iModifiedOperationType = CImOffLineOperation::EOffLineOpNone; |
|
566 } |
|
567 } |
|
568 } |
|
569 |
|
570 CImOffLineOperation* operation = new (ELeave) CImOffLineOperation(); |
|
571 CleanupStack::PushL(operation); |
|
572 |
|
573 TMsvEmailEntry entry = iEntry.Entry(); |
|
574 |
|
575 switch (iModifiedOperationType) |
|
576 { |
|
577 case CImOffLineOperation::EOffLineOpCopyFromLocal: |
|
578 case CImOffLineOperation::EOffLineOpMoveFromLocal: |
|
579 case CImOffLineOperation::EOffLineOpMoveWithinService: |
|
580 case CImOffLineOperation::EOffLineOpChange: |
|
581 case CImOffLineOperation::EOffLineOpCreate: |
|
582 case CImOffLineOperation::EOffLineOpMtmSpecific: |
|
583 User::Leave(KErrNotSupported); |
|
584 |
|
585 case CImOffLineOperation::EOffLineOpCopyToLocal: |
|
586 operation->SetCopyToLocal((*iSourceMessages)[iMessageCounter], iDestinationEntryId); |
|
587 break; |
|
588 |
|
589 case CImOffLineOperation::EOffLineOpDelete: |
|
590 operation->SetDelete((*iSourceMessages)[iMessageCounter]); |
|
591 break; |
|
592 |
|
593 case CImOffLineOperation::EOffLineOpCopyWithinService: |
|
594 operation->SetCopyWithinService((*iSourceMessages)[iMessageCounter], iDestinationEntryId); |
|
595 break; |
|
596 |
|
597 case CImOffLineOperation::EOffLineOpMoveToLocal: |
|
598 operation->SetMoveToLocal((*iSourceMessages)[iMessageCounter], iDestinationEntryId); |
|
599 break; |
|
600 |
|
601 case CImOffLineOperation::EOffLineOpNone: |
|
602 break; |
|
603 |
|
604 default: |
|
605 User::Leave(KErrNotSupported); |
|
606 } |
|
607 |
|
608 |
|
609 if (iModifiedOperationType != CImOffLineOperation::EOffLineOpNone) |
|
610 { |
|
611 operationArray->AppendOperationL(*operation); |
|
612 entry.SetOperation(ETrue); |
|
613 iOfflineOperationArrayFlag[iMessageCounter] = ETrue; |
|
614 } |
|
615 |
|
616 CImPop3OfflineUtilities::SetOfflineFlags(*operationArray, entry); |
|
617 |
|
618 operationStore->StoreL(*messageStore); |
|
619 iEntry.ChangeEntry(entry); |
|
620 messageStore->CommitL(); |
|
621 CleanupStack::PopAndDestroy(4); // operation, messageStore, operationStore, operationArray |
|
622 iStatus = KRequestPending; |
|
623 SetActive(); |
|
624 TRequestStatus* status = &iStatus; |
|
625 User::RequestComplete(status, KErrNone); |
|
626 } |
|
627 |
|
628 void CImPop3SetOfflineOps::CancelOfflineOperationL() |
|
629 { |
|
630 SetActive(); |
|
631 |
|
632 // Set the current entry, ready for the operation to be attached to it. |
|
633 User::LeaveIfError(iEntry.SetEntry((*iSourceMessages)[iMessageCounter])); |
|
634 TMsvEmailEntry entry = iEntry.Entry(); |
|
635 CImOffLineOperationArray* operationArray = CImOffLineOperationArray::NewL(); |
|
636 CleanupStack::PushL(operationArray); |
|
637 CImOffLineArrayStore* operationStore = new (ELeave) CImOffLineArrayStore(*operationArray); |
|
638 CleanupStack::PushL(operationStore); |
|
639 CMsvStore* messageStore = iEntry.EditStoreL(); |
|
640 CleanupStack::PushL(messageStore); |
|
641 |
|
642 // Get the array of operations currently attached to the message. |
|
643 operationStore->RestoreL(*messageStore); |
|
644 |
|
645 TInt counter = operationArray->CountOperations(); |
|
646 while (counter > 0) |
|
647 { |
|
648 counter--; |
|
649 operationArray->Delete(counter); |
|
650 } |
|
651 |
|
652 operationStore->StoreL(*messageStore); |
|
653 messageStore->CommitL(); |
|
654 entry.SetOperation(EFalse); |
|
655 entry.SetDisconnectedOperation(ENoDisconnectedOperations); |
|
656 iEntry.ChangeEntry(entry); |
|
657 CleanupStack::PopAndDestroy(3); // messageStore, operationStore, operationArray |
|
658 TRequestStatus* status = &iStatus; |
|
659 User::RequestComplete(status, KErrNone); |
|
660 } |
|
661 |
|
662 void CImPop3SetOfflineOps::CopyLocalMessageL() |
|
663 // Copy the current local message. |
|
664 { |
|
665 User::LeaveIfError(iEntry.SetEntry((*iSourceMessages)[iMessageCounter])); |
|
666 User::LeaveIfError(iEntry.SetEntry(iEntry.Entry().Parent())); |
|
667 |
|
668 iStatus = KRequestPending; |
|
669 iTransfer->StartL((*iSourceMessages)[iMessageCounter], iDestinationEntryId, CImPop3TransferMessage::EImPop3CopyTransfer, iStatus); |
|
670 |
|
671 SetActive(); |
|
672 } |
|
673 |
|
674 CImPop3SetOfflineOps::~CImPop3SetOfflineOps() |
|
675 { |
|
676 Cancel(); |
|
677 delete iSourceMessages; |
|
678 delete iMessagesToCopyLocally; |
|
679 delete iTransfer; |
|
680 iOfflineOperationArrayFlag.Close(); |
|
681 } |
|
682 |
|
683 void CImPop3SetOfflineOps::Progress(TPop3Progress& rPop3Progress) const |
|
684 { |
|
685 // It is only necessary to report the progress when it is in the |
|
686 // ECopyingLocalEntries state. All other states should be near-instantaneous |
|
687 // and a 0 filled progress will do. |
|
688 |
|
689 switch (iState) |
|
690 { |
|
691 case ECopyingLocalEntries: |
|
692 if (iOperationType == CImOffLineOperation::EOffLineOpMoveToLocal) |
|
693 { |
|
694 rPop3Progress.iPop3Progress = TPop3Progress::EPopMoving; |
|
695 rPop3Progress.iPop3SubStateProgress = TPop3Progress::EPopMoving; |
|
696 } |
|
697 else |
|
698 { |
|
699 rPop3Progress.iPop3Progress = TPop3Progress::EPopCopying; |
|
700 rPop3Progress.iPop3SubStateProgress = TPop3Progress::EPopCopying; |
|
701 } |
|
702 rPop3Progress.iTotalMsgs = iMessagesToCopyLocally->Count(); |
|
703 rPop3Progress.iMsgsToProcess = rPop3Progress.iTotalMsgs - iMessageCounter; |
|
704 rPop3Progress.iBytesDone = 0; |
|
705 rPop3Progress.iTotalBytes = 0; |
|
706 rPop3Progress.iErrorCode = 0; |
|
707 break; |
|
708 |
|
709 case EAddingOfflineOperations: |
|
710 if (iOperationType == CImOffLineOperation::EOffLineOpDelete) |
|
711 { |
|
712 rPop3Progress.iPop3Progress = TPop3Progress::EPopDeleting; |
|
713 rPop3Progress.iTotalMsgs = iSourceMessages->Count(); |
|
714 rPop3Progress.iMsgsToProcess = rPop3Progress.iTotalMsgs - iMessageCounter; |
|
715 rPop3Progress.iBytesDone = 0; |
|
716 rPop3Progress.iTotalBytes = 0; |
|
717 rPop3Progress.iErrorCode = 0; |
|
718 rPop3Progress.iPop3SubStateProgress = TPop3Progress::EPopDeleting; |
|
719 } |
|
720 else if (iOperationType == CImOffLineOperation::EOffLineOpMoveToLocal) |
|
721 { |
|
722 rPop3Progress.iPop3Progress = TPop3Progress::EPopMoving; |
|
723 rPop3Progress.iTotalMsgs = iSourceMessages->Count(); |
|
724 rPop3Progress.iMsgsToProcess = rPop3Progress.iTotalMsgs - iMessageCounter; |
|
725 rPop3Progress.iBytesDone = 0; |
|
726 rPop3Progress.iTotalBytes = 0; |
|
727 if(rPop3Progress.iErrorCode != KErrDisconnected) |
|
728 { |
|
729 rPop3Progress.iErrorCode = 0; |
|
730 } |
|
731 rPop3Progress.iPop3SubStateProgress = TPop3Progress::EPopMoving; |
|
732 } |
|
733 else if ((iOperationType == CImOffLineOperation::EOffLineOpCopyToLocal) || |
|
734 (iOperationType == CImOffLineOperation::EOffLineOpCopyWithinService)) |
|
735 { |
|
736 rPop3Progress.iPop3Progress = TPop3Progress::EPopCopying; |
|
737 rPop3Progress.iTotalMsgs = iSourceMessages->Count(); |
|
738 rPop3Progress.iMsgsToProcess = rPop3Progress.iTotalMsgs - iMessageCounter; |
|
739 rPop3Progress.iBytesDone = 0; |
|
740 rPop3Progress.iTotalBytes = 0; |
|
741 if(rPop3Progress.iErrorCode != KErrDisconnected) |
|
742 { |
|
743 rPop3Progress.iErrorCode = 0; |
|
744 } |
|
745 rPop3Progress.iPop3SubStateProgress = TPop3Progress::EPopCopying; |
|
746 } |
|
747 break; |
|
748 |
|
749 case ECancellingOfflineOperations: |
|
750 rPop3Progress.iPop3Progress = TPop3Progress::EPopCancellingOfflineOps; |
|
751 rPop3Progress.iTotalMsgs = iSourceMessages->Count(); |
|
752 rPop3Progress.iMsgsToProcess = rPop3Progress.iTotalMsgs - iMessageCounter; |
|
753 rPop3Progress.iBytesDone = 0; |
|
754 rPop3Progress.iTotalBytes = 0; |
|
755 rPop3Progress.iErrorCode = 0; |
|
756 rPop3Progress.iPop3SubStateProgress = TPop3Progress::EPopCancellingOfflineOps; |
|
757 break; |
|
758 |
|
759 default: |
|
760 { |
|
761 _LIT(KPop3Session,"Pop3 session"); |
|
762 __ASSERT_DEBUG(EFalse, User::Panic(KPop3Session, EPopInvalidState)); |
|
763 } |
|
764 break; |
|
765 } |
|
766 } |
|
767 |
|
768 //private: |
|
769 void CImPop3SetOfflineOps::DoRunL() |
|
770 { |
|
771 // Create the ghost destination entry if one is required. |
|
772 switch (iState) |
|
773 { |
|
774 case EAddingOfflineOperations: |
|
775 if ((iModifiedOperationType == CImOffLineOperation::EOffLineOpCopyToLocal) |
|
776 || (iModifiedOperationType == CImOffLineOperation::EOffLineOpMoveToLocal)) |
|
777 { |
|
778 User::LeaveIfError(iEntry.SetEntry((*iSourceMessages)[iMessageCounter])); |
|
779 TMsvEntry ghostEntry = iEntry.Entry(); |
|
780 ghostEntry.iRelatedId = iEntry.Entry().Id(); |
|
781 ghostEntry.SetComplete(EFalse); |
|
782 User::LeaveIfError(iEntry.SetEntry(iDestinationEntryId)); |
|
783 iEntry.CreateEntry(ghostEntry); |
|
784 } |
|
785 |
|
786 iMessageCounter++; |
|
787 if (iMessageCounter < iSourceMessages->Count()) |
|
788 { |
|
789 AddOfflineOperationL(); |
|
790 } |
|
791 else |
|
792 { |
|
793 iMessageCounter = 0; |
|
794 if (iMessageCounter < iMessagesToCopyLocally->Count()) |
|
795 { |
|
796 iState = ECopyingLocalEntries; |
|
797 CopyLocalMessageL(); |
|
798 } |
|
799 } |
|
800 break; |
|
801 |
|
802 case ECancellingOfflineOperations: |
|
803 iMessageCounter++; |
|
804 if (iMessageCounter < iSourceMessages->Count()) |
|
805 { |
|
806 CancelOfflineOperationL(); |
|
807 } |
|
808 break; |
|
809 |
|
810 case ECopyingLocalEntries: |
|
811 iMessageCounter++; |
|
812 if (iMessageCounter < iMessagesToCopyLocally->Count()) |
|
813 { |
|
814 CopyLocalMessageL(); |
|
815 } |
|
816 break; |
|
817 } |
|
818 } |
|
819 |
|
820 void CImPop3SetOfflineOps::DoCancel() |
|
821 { |
|
822 iTransfer->Cancel(); |
|
823 |
|
824 switch(iState) |
|
825 { |
|
826 case ECopyingLocalEntries: |
|
827 { |
|
828 TInt messageCounter = iMessageCounter; |
|
829 |
|
830 // Loop to delete all the operations attached to the messages in iSourceMessages. |
|
831 for(TInt i = iSourceMessages->Count() - messageCounter; i > 0; -- i) |
|
832 { |
|
833 DeleteOfflineOperationL(messageCounter); |
|
834 messageCounter++; |
|
835 } |
|
836 break; |
|
837 } |
|
838 |
|
839 case EAddingOfflineOperations: |
|
840 { |
|
841 // Loop to delete all the operations attached to the messages in iSourceMessages. |
|
842 for(TInt count = 0; count <= iMessageCounter; ++count) |
|
843 { |
|
844 DeleteOfflineOperationL(count); |
|
845 } |
|
846 break; |
|
847 } |
|
848 |
|
849 case ECancellingOfflineOperations: |
|
850 default: |
|
851 { |
|
852 // Nothing to be done here. |
|
853 break; |
|
854 } |
|
855 } |
|
856 iOfflineOperationArrayFlag.Reset(); |
|
857 CMsgActive::DoCancel(); |
|
858 } |
|
859 |
|
860 |
|
861 void CImPop3SetOfflineOps::DeleteOfflineOperationL(TInt aMessageCounter) |
|
862 { |
|
863 // Set the current entry, ready for the operation to be attached to it. |
|
864 User::LeaveIfError(iEntry.SetEntry((*iSourceMessages)[aMessageCounter])); |
|
865 TMsvEmailEntry entry = iEntry.Entry(); |
|
866 |
|
867 if(iOfflineOperationArrayFlag[aMessageCounter]) |
|
868 { |
|
869 CImOffLineOperationArray* operationArray = CImOffLineOperationArray::NewL(); |
|
870 CleanupStack::PushL(operationArray); |
|
871 CImOffLineArrayStore* operationStore = new (ELeave) CImOffLineArrayStore(*operationArray); |
|
872 CleanupStack::PushL(operationStore); |
|
873 CMsvStore* messageStore = iEntry.EditStoreL(); |
|
874 CleanupStack::PushL(messageStore); |
|
875 |
|
876 // Get the array of operations currently attached to the message. |
|
877 operationStore->RestoreL(*messageStore); |
|
878 |
|
879 TInt counter = operationArray->CountOperations(); |
|
880 if (counter > 0) |
|
881 { |
|
882 counter--; |
|
883 operationArray->Delete(counter); |
|
884 } |
|
885 |
|
886 operationStore->StoreL(*messageStore); |
|
887 messageStore->CommitL(); |
|
888 |
|
889 if(counter == 0) |
|
890 { |
|
891 entry.SetOperation(EFalse); |
|
892 entry.SetDisconnectedOperation(ENoDisconnectedOperations); |
|
893 } |
|
894 else |
|
895 { |
|
896 CImPop3OfflineUtilities::SetOfflineFlags(*operationArray, entry); |
|
897 } |
|
898 iEntry.ChangeEntry(entry); |
|
899 CleanupStack::PopAndDestroy(3); // messageStore, operationStore, operationArray |
|
900 } |
|
901 } |
|
902 |
|
903 |
|
904 void CImPop3SetOfflineOps::DoComplete(TInt& /*status*/) |
|
905 { |
|
906 |
|
907 } |
|
908 |
|
909 CImPop3SetOfflineOps::CImPop3SetOfflineOps(CMsvServerEntry& aEntry) : CMsgActive(EPriorityStandard), iEntry(aEntry) |
|
910 { |
|
911 |
|
912 } |
|
913 |
|
914 void CImPop3SetOfflineOps::ConstructL() |
|
915 { |
|
916 iTransfer = CImPop3TransferMessage::NewL(iEntry); |
|
917 } |
|
918 |
|
919 |
|
920 |
|
921 void CImPop3OfflineUtilities::DeleteL(const CImOffLineOperation& aOperation, CMsvServerEntry& aEntry) |
|
922 // Finds the specified operation in the message tree and then deletes it. |
|
923 { |
|
924 aEntry.SetEntry(aOperation.MessageId()); |
|
925 CImOffLineOperationArray* localOperationArray = CImOffLineOperationArray::NewL(); |
|
926 CleanupStack::PushL(localOperationArray); |
|
927 CImOffLineArrayStore* operationStore = new (ELeave) CImOffLineArrayStore(*localOperationArray); |
|
928 CleanupStack::PushL(operationStore); |
|
929 CMsvStore* messageStore = aEntry.EditStoreL(); |
|
930 CleanupStack::PushL(messageStore); |
|
931 |
|
932 // Get the array of operations currently attached to the message. |
|
933 operationStore->RestoreL(*messageStore); |
|
934 |
|
935 // Look for the offline operation |
|
936 TBool found = EFalse; |
|
937 TInt index = 0; |
|
938 while ((!found) && (index < localOperationArray->CountOperations())) |
|
939 { |
|
940 if (aOperation == localOperationArray->Operation(index)) |
|
941 { |
|
942 found = ETrue; |
|
943 } |
|
944 else |
|
945 { |
|
946 index++; |
|
947 } |
|
948 } |
|
949 |
|
950 if (found) |
|
951 { |
|
952 // Remove the entry from the list |
|
953 localOperationArray->Delete(index); |
|
954 |
|
955 // Write out the list to the stream |
|
956 operationStore->StoreL(*messageStore); |
|
957 messageStore->CommitL(); |
|
958 |
|
959 // Set the TMsvEmailEntry details |
|
960 TMsvEmailEntry entry = aEntry.Entry(); |
|
961 SetOfflineFlags(*localOperationArray, entry); |
|
962 aEntry.ChangeEntry(entry); |
|
963 } |
|
964 |
|
965 CleanupStack::PopAndDestroy(3); // messageStore, operationStore, operationArray |
|
966 } |
|
967 |
|
968 void CImPop3OfflineUtilities::SetOfflineFlags(const CImOffLineOperationArray& aOperationArray, TMsvEmailEntry& aEntry) |
|
969 { |
|
970 // Sets the DisconnectedOperation flag on the given TMsvEmailEntry. |
|
971 // Note that it is NOT commited to the index. |
|
972 TImDisconnectedOperationType operationType = ENoDisconnectedOperations; |
|
973 TInt index = 0; |
|
974 while (index < aOperationArray.CountOperations()) |
|
975 { |
|
976 if (operationType != ENoDisconnectedOperations) |
|
977 { |
|
978 operationType = EDisconnectedMultipleOperation; |
|
979 } |
|
980 else |
|
981 { |
|
982 switch (aOperationArray.Operation(index).OpType()) |
|
983 { |
|
984 case CImOffLineOperation::EOffLineOpCopyToLocal: |
|
985 operationType = EDisconnectedCopyToOperation; |
|
986 break; |
|
987 case CImOffLineOperation::EOffLineOpCopyFromLocal: |
|
988 operationType = EDisconnectedCopyFromOperation; |
|
989 break; |
|
990 case CImOffLineOperation::EOffLineOpCopyWithinService: |
|
991 operationType = EDisconnectedCopyWithinServiceOperation; |
|
992 break; |
|
993 case CImOffLineOperation::EOffLineOpMoveToLocal: |
|
994 operationType = EDisconnectedMoveToOperation; |
|
995 break; |
|
996 case CImOffLineOperation::EOffLineOpMoveFromLocal: |
|
997 operationType = EDisconnectedMoveFromOperation; |
|
998 break; |
|
999 case CImOffLineOperation::EOffLineOpMoveWithinService: |
|
1000 operationType = EDisconnectedMoveWithinServiceOperation; |
|
1001 break; |
|
1002 case CImOffLineOperation::EOffLineOpDelete: |
|
1003 operationType = EDisconnectedDeleteOperation; |
|
1004 break; |
|
1005 case CImOffLineOperation::EOffLineOpChange: |
|
1006 operationType = EDisconnectedChangeOperation; |
|
1007 break; |
|
1008 case CImOffLineOperation::EOffLineOpCreate: |
|
1009 operationType = EDisconnectedCreateOperation; |
|
1010 break; |
|
1011 case CImOffLineOperation::EOffLineOpMtmSpecific: |
|
1012 operationType = EDisconnectedSpecialOperation; |
|
1013 break; |
|
1014 default: |
|
1015 operationType = EDisconnectedUnknownOperation; |
|
1016 break; |
|
1017 } |
|
1018 } |
|
1019 index++; |
|
1020 } |
|
1021 aEntry.SetDisconnectedOperation(operationType); |
|
1022 } |
|
1023 |
|
1024 |