00001 // TXTSCPMV.CPP 00002 // 00003 // Copyright (c) 1999 Symbian Ltd. All rights reserved. 00004 // 00005 00006 #if !defined(__E32STD_H__) 00007 #include <e32std.h> 00008 #endif 00009 00010 #if !defined(__TXTETEXT_H__) 00011 #include <txtetext.h> 00012 #endif 00013 00014 #if !defined(__TXTRICH_H__) 00015 #include <txtrich.h> 00016 #endif 00017 00018 #if !defined(__APPARC_H__) 00019 #include <apparc.h> 00020 #endif 00021 00022 #if !defined(__MSVUIDS_H__) 00023 #include <MSVUIDS.H> 00024 #endif 00025 00026 #if !defined(__MSVIDS_H__) 00027 #include <MSVIDS.H> 00028 #endif 00029 00030 #include "txtserv.h" 00031 #include "txtscpmv.h" 00032 #include "txtspan.h" 00033 00034 // 00035 // CTxtActiveOper: base class for move, copy and delete operations 00036 // 00037 00038 CTxtActiveOper::CTxtActiveOper(RFs& aFs, CMsvServerEntry& aServerEntry) 00039 : CActive(0), iServerEntry(aServerEntry), iFs(aFs) 00040 { 00041 00042 00043 CActiveScheduler::Add(this); 00044 iFs.Connect(); 00045 } 00046 00047 CTxtActiveOper::~CTxtActiveOper() 00048 { 00049 Cancel(); 00050 } 00051 00052 void CTxtActiveOper::Start(TMsvId& aSourceId, TMsvId& aDestId, TRequestStatus& aStatus) 00053 // 00054 // Start asynchronous transfer. 00055 // 00056 { 00057 iSourceId = aSourceId; 00058 iDestId = aDestId; 00059 00060 iStatus = KRequestPending; 00061 iReportStatus = &aStatus; 00062 SetActive(); 00063 aStatus = KRequestPending; 00064 TRequestStatus *sP=&iStatus; 00065 User::RequestComplete(sP, KErrNone); 00066 } 00067 00068 void CTxtActiveOper::DoCancel() 00069 { 00070 } 00071 00072 00073 void CTxtActiveOper::RunL() 00074 // 00075 // Default operation: do nothing 00076 // 00077 { 00078 TRAPD(errorCode, DoRunL()); 00079 // Within this class, a leave is an external (service) error 00080 // This basically means the DoRunL implementation is not allowed to leave with an error 00081 // after calling User::RequestComplete 00082 if (errorCode) 00083 { 00084 iCurrentCaller->Progress().iErrorCode = errorCode; 00085 User::RequestComplete(iReportStatus, KErrNone); 00086 } 00087 } 00088 00089 // 00090 // CTxtCopyMoveBase: walks over all the items in aSource, and starts aActiveOperation 00091 // for each one of them, waiting for completion. 00092 // 00093 00094 CTxtCopyMoveBase* CTxtCopyMoveBase::NewL(CTxtActiveOper* aActiveOperation, const CMsvEntrySelection& aSource, 00095 CMsvServerEntry& aDestination, TMsvId& aServiceEntryId, TParse& aParse) 00096 { 00097 CTxtCopyMoveBase* self = new (ELeave) CTxtCopyMoveBase(aActiveOperation,aSource, 00098 aDestination, aServiceEntryId, aParse); 00099 CleanupStack::PushL(self); 00100 self->ConstructL(); 00101 CleanupStack::Pop(); 00102 return self; 00103 } 00104 00105 CTxtCopyMoveBase* CTxtCopyMoveBase::CopyConstructL(const CMsvEntrySelection& aSource) 00106 { 00107 CTxtActiveOper* newActive = iActiveOperation->CopyConstructL(); 00108 return NewL(newActive, aSource, iDestination, iServiceEntryId, iServiceDestinationpath); 00109 } 00110 00111 CTxtCopyMoveBase::CTxtCopyMoveBase(CTxtActiveOper* aActiveOperation, const CMsvEntrySelection& aSource, 00112 CMsvServerEntry& aDestination, TMsvId& aServiceEntryId, TParse& aParse) 00113 : CActive( KMsgTxtRefreshMailboxPriority ), 00114 iActiveOperation(aActiveOperation), iSource(aSource), iDestination(aDestination), 00115 iServiceEntryId(aServiceEntryId), iServiceDestinationpath(aParse) 00116 { 00117 } 00118 00119 void CTxtCopyMoveBase::ConstructL() 00120 { 00121 iDestId = iDestination.Entry().Id(); 00122 iActiveOperation->SetCurrentCaller(this); 00123 if (iActiveOperation->MoveIsToService()) 00124 { 00125 __ASSERT_ALWAYS(iDestination.Entry().iServiceId == iServiceEntryId, gPanic(ETxtsInvalidService)); 00126 } 00127 CActiveScheduler::Add(this); // Add CTxtCopyMoveBase to scheduler's queue 00128 } 00129 00130 CTxtCopyMoveBase::~CTxtCopyMoveBase() 00131 { 00132 Cancel(); 00133 delete iActiveOperation; 00134 iActiveOperation = NULL; 00135 } 00136 00137 void CTxtCopyMoveBase::DoCancel() 00138 // 00139 // Cancel any current operation 00140 // 00141 { 00142 delete iActiveOperation; 00143 iActiveOperation = NULL; 00144 iTxtCopyMoveState = ETxtFinished; 00145 } 00146 00147 void CTxtCopyMoveBase::Start(TRequestStatus& aStatus) 00148 // 00149 // Start me up 00150 // 00151 { 00152 iReportStatus = &aStatus; 00153 00154 iMsgCounter = -1; 00155 // set up progress object 00156 iProgress.iTotalMsgs=iSource.Count(); 00157 iProgress.iMsgsProcessed=0; 00158 iProgress.iErrorCode=KErrNone; 00159 00160 if(iSource.Count()) 00161 { 00162 iTxtCopyMoveState=ETxtRetrievingMessage; 00163 } 00164 else 00165 { 00166 iTxtCopyMoveState=ETxtFinished; 00167 } 00168 aStatus = KRequestPending; 00169 SetActive(); 00170 TRequestStatus *sP=&iStatus; 00171 User::RequestComplete(sP, KErrNone); 00172 } 00173 00174 00175 void CTxtCopyMoveBase::RunL() 00176 { 00177 TRAPD(errorCode, DoRunL()); 00178 // In this class a leave is an internal error 00179 // No leave is allowed after calling User::RequestComplete in DoRunL because 00180 // of this implementation 00181 if (errorCode) 00182 { 00183 User::RequestComplete(iReportStatus, errorCode); 00184 } 00185 } 00186 00187 00188 void CTxtCopyMoveBase::CheckDeleteSource() 00189 // Delete previous source message if necessary 00190 { 00191 if (iMsgCounter>=0) 00192 { 00193 if (iActiveOperation->DeleteSourceAfterwards()) 00194 { 00195 //delete the previous source 00196 iDestination.SetEntry(iSource[iMsgCounter]); 00197 TMsvId parent = iDestination.Entry().Parent(); 00198 iDestination.SetEntry(parent); 00199 iDestination.DeleteEntry(iSource[iMsgCounter]); 00200 } 00201 } 00202 } 00203 00204 00205 void CTxtCopyMoveBase::SetupNewEntryL(TMsvId& aSourceMsgId, TMsvId& aNewDestMsvId) 00206 // Create new entry index details based on source 00207 { 00208 // Get the destination path, and put it in the details 00209 // section of the message 00210 iDestination.SetEntry(aSourceMsgId); 00211 TMsvEntry entry; 00212 entry.iServiceId = iDestination.Entry().iServiceId; 00213 entry.iRelatedId = iDestination.Entry().iRelatedId; 00214 entry.iType = iDestination.Entry().iType; 00215 entry.iMtm = iDestination.Entry().iMtm; 00216 entry.iDate = iDestination.Entry().iDate; 00217 entry.iSize = iDestination.Entry().iSize; 00218 entry.iError = iDestination.Entry().iError; 00219 // entry.iWdpPortNumber = iDestination.Entry().iWdpPortNumber; 00220 entry.iMtmData1 = iDestination.Entry().iMtmData1; 00221 entry.iMtmData2 = iDestination.Entry().iMtmData2; 00222 entry.iMtmData3 = iDestination.Entry().iMtmData3; 00223 // Copy the details and description for protection 00224 TFileName name=iDestination.Entry().iDescription; 00225 TFileName path=iDestination.Entry().iDetails; 00226 entry.iDescription.Set(name); 00227 entry.iDetails.Set(path); 00228 entry.SetUnread(ETrue); 00229 entry.SetNew(ETrue); 00230 // If the move is to the service, make sure the entry is valid 00231 if (iActiveOperation->MoveIsToService()) 00232 { 00233 __ASSERT_DEBUG(name.Length()>0,gPanic(ETxtsInvalidFileName)); 00234 00235 if (name.Length()==0) 00236 User::Leave(KErrArgument); 00237 00238 00239 entry.iDetails.Set(iServiceDestinationpath.FullName()); 00240 entry.iServiceId = iServiceEntryId; 00241 } 00242 else 00243 { 00244 entry.iServiceId = KMsvLocalServiceIndexEntryId; 00245 } 00246 00247 // Create the new entry 00248 iDestination.SetEntry(iDestId); 00249 iDestination.CreateEntry(entry); 00250 00251 aNewDestMsvId=entry.Id(); 00252 iProgress.iNewId = aNewDestMsvId; 00253 } 00254 00255 void CTxtCopyMoveBase::DoRunL() 00256 { 00257 // Check if error occurred on last stage 00258 User::LeaveIfError(iStatus.Int()); // Leave if internal error has occurred. 00259 if (iProgress.iErrorCode != KErrNone) // External error occurred 00260 { 00261 User::RequestComplete(iReportStatus,KErrNone); 00262 return; 00263 } 00264 00265 // Delete previous source message if necessary 00266 CheckDeleteSource(); 00267 00268 switch (iTxtCopyMoveState) 00269 { 00270 case ETxtRetrievingMessage: 00271 // Operate on the next message 00272 { 00273 iMsgCounter++; 00274 00275 // For copy/move ops, make a new entry on the other side. 00276 TMsvId newSourceMsgId=iSource[iMsgCounter]; 00277 TMsvId newDestMsvId=KMsvNullIndexEntryId; 00278 if (iActiveOperation->CopiedHeader()) SetupNewEntryL(newSourceMsgId,newDestMsvId); 00279 00280 iProgress.iMsgsProcessed++; // Update progress info 00281 // Check if finished 00282 if(iMsgCounter == iSource.Count()-1) 00283 { 00284 iTxtCopyMoveState = ETxtFinished; 00285 } 00286 // Do the operation-specific part 00287 iActiveOperation->Start(newSourceMsgId,newDestMsvId,iStatus); 00288 SetActive(); 00289 } 00290 break; 00291 case ETxtFinished: 00292 // Have now finished this operation, so pass the completion up 00293 __ASSERT_DEBUG(iReportStatus != NULL, gPanic(ETxtsStrayRequest)); 00294 User::RequestComplete(iReportStatus,KErrNone); 00295 break; 00296 } 00297 } 00298 00299 00300 TTxtProgress& CTxtCopyMoveBase::Progress() 00301 // 00302 // Report the refreshing news back to the UI 00303 // 00304 { 00305 return iProgress; 00306 } 00307 00308 00309 // 00310 // Implementation of the several body-moving classes 00311 // 00312 00313 void CTxtCopyToLocalOp::DoRunL() 00314 // 00315 // Copy one remote entry to local, getting the source text and storing 00316 // it in the associated CMsvStore 00317 // 00318 { 00319 User::LeaveIfError(iStatus.Int()); 00320 00321 User::LeaveIfError(iServerEntry.SetEntry(iSourceId)); 00322 TMsvEntry entry = iServerEntry.Entry(); 00323 00324 // Build a new source file file name 00325 User::LeaveIfError(iServerEntry.SetEntry( iDestId )); 00326 TxtUtils::GetEntryFileNameL(iFileName, entry); 00327 00328 DoMessageCopyToLocalL(); 00329 } 00330 00331 void CTxtCopyToLocalOp::DoMessageCopyToLocalL() 00332 // Copy remote message to local: i.e. read file contents into message store 00333 { 00334 // Description of the body is the original file 00335 CMsvStore* wstore=NULL; 00336 wstore=iServerEntry.EditStoreL(); 00337 CleanupStack::PushL(wstore); 00338 User::LeaveIfNull(wstore); 00339 00340 // Read file text into rich text object 00341 CParaFormatLayer* paraLayer = CParaFormatLayer::NewL(); 00342 CleanupStack::PushL(paraLayer); 00343 CCharFormatLayer* charLayer = CCharFormatLayer::NewL(); 00344 CleanupStack::PushL(charLayer); 00345 CRichText* body = CRichText::NewL(paraLayer,charLayer, CEditableText::EFlatStorage, 70 ); 00346 CleanupStack::PushL(body); 00347 body->ImportTextFileL(0,iFileName,CPlainText::EOrganiseByLine); 00348 00349 // Store in body 00350 wstore->StoreBodyTextL(*body); 00351 wstore->CommitL(); 00352 00353 // Clean up 00354 CleanupStack::PopAndDestroy(4); //body, charLayer, paraLayer, wstore 00355 TInt err=KErrNone; 00356 if (DeleteSourceAfterwards()) 00357 err=iFs.Delete(iFileName); 00358 User::RequestComplete(iReportStatus, err); 00359 } 00360 00361 00362 void CTxtCopyFromLocalOp::DoRunL() 00363 // 00364 // Copy entries from local to remote, storing the plain text contents of 00365 // the associated rich text in a newly created file. 00366 // 00367 { 00368 // Error on previous stages 00369 User::LeaveIfError(iStatus.Int()); 00370 00371 // Get details of destination entry 00372 User::LeaveIfError(iServerEntry.SetEntry( iDestId )); 00373 TMsvEntry entry = iServerEntry.Entry(); 00374 00375 // Find file from entry details 00376 TxtUtils::GetEntryFileNameL(iFileName, entry); 00377 00378 // Check if file already exists. 00379 RFile file; 00380 if (file.Open(iFs,iFileName,EFileRead) == KErrNone) 00381 { 00382 file.Close(); 00383 // If so, create a new unique filename and update entry 00384 User::LeaveIfError(CApaApplication::GenerateFileName(iFs,iFileName)); 00385 TParse newName; 00386 newName.Set(iFileName,NULL,NULL); 00387 entry.iDescription.Set(newName.NameAndExt()); 00388 User::LeaveIfError(iServerEntry.ChangeEntry(entry)); 00389 } 00390 00391 // Set the context back 00392 User::LeaveIfError(iServerEntry.SetEntry( iSourceId )); 00393 00394 DoMessageCopyFromLocalL(entry); 00395 } 00396 00397 00398 void CTxtCopyFromLocalOp::DoMessageCopyFromLocalL(const TMsvEntry& aEntry) 00399 // Copy local message to remote service: i.e. create a file 00400 { 00401 CMsvStore* rstore=iServerEntry.ReadStoreL(); 00402 CleanupStack::PushL(rstore); 00403 00404 if (rstore->HasBodyTextL()) 00405 { 00406 // Get message text and write it to file 00407 CParaFormatLayer* paraLayer = CParaFormatLayer::NewL(); 00408 CleanupStack::PushL(paraLayer); 00409 CCharFormatLayer* charLayer = CCharFormatLayer::NewL(); 00410 CleanupStack::PushL(charLayer); 00411 CRichText* body = CRichText::NewL(paraLayer,charLayer, CEditableText::EFlatStorage, 70); 00412 CleanupStack::PushL(body); 00413 rstore->RestoreBodyTextL(*body); 00414 //User::LeaveIfError(iFs.MkDir(iFileName)); 00415 body->ExportAsTextL(iFileName,CPlainText::EOrganiseByLine,70); 00416 00417 // Change date modified to reflect what's in the TMsvEntry 00418 RFile outFile; 00419 if (outFile.Open(iFs, iFileName, EFileWrite) == KErrNone) 00420 { 00421 outFile.SetModified(aEntry.iDate); 00422 outFile.Close(); 00423 } 00424 CleanupStack::PopAndDestroy(3); //paraLayer, charLayer, body 00425 } 00426 00427 CleanupStack::PopAndDestroy(); //rstore 00428 00429 User::RequestComplete(iReportStatus, KErrNone); 00430 } 00431 00432 00433 void CTxtCopyWithinServiceOp::DoRunL() 00434 // 00435 // Copy files over within the service. 00436 // 00437 { 00438 TInt err=KErrNone; 00439 User::LeaveIfError(iStatus.Int()); 00440 00441 User::LeaveIfError(iServerEntry.SetEntry(iSourceId)); 00442 TMsvEntry sourceEntry = iServerEntry.Entry(); 00443 00444 // Source settings 00445 TFileName sourceFileName; 00446 TxtUtils::GetEntryFileNameL(sourceFileName, sourceEntry); 00447 iFileName = sourceFileName; 00448 00449 // Destination settings 00450 err = iServerEntry.SetEntry(iDestId); 00451 if (err) 00452 { 00453 User::RequestComplete(iReportStatus, err); 00454 return; 00455 } 00456 00457 DoMessageCopyWithinServiceL(); 00458 } 00459 00460 00461 void CTxtCopyWithinServiceOp::DoMessageCopyWithinServiceL() 00462 // Copy remote message to local: i.e. read file contents into message store 00463 { 00464 TMsvEntry destEntry = iServerEntry.Entry(); 00465 TFileName destFileName; 00466 TxtUtils::GetEntryFileNameL(destFileName, destEntry); 00467 00468 iFs.MkDir(destFileName); 00469 00470 RFile outFile; 00471 // Test if destination file already exists 00472 if (outFile.Open(iFs, destFileName, EFileRead) == KErrNone) 00473 { 00474 outFile.Close(); 00475 User::RequestComplete(iReportStatus, KErrAlreadyExists); 00476 return; 00477 } 00478 // Create destination file 00479 TInt err = outFile.Create(iFs, destFileName, EFileWrite); 00480 if (err) 00481 { 00482 User::RequestComplete(iReportStatus, err); 00483 return; 00484 } 00485 // Open input file 00486 RFile inFile; 00487 err = inFile.Open(iFs, iFileName, EFileRead); 00488 if (err) 00489 { 00490 inFile.Close(); 00491 User::RequestComplete(iReportStatus, err); 00492 return; 00493 } 00494 00495 // Copy the file over 00496 TFileText inTextFile; 00497 TFileText outTextFile; 00498 inTextFile.Set(inFile); 00499 outTextFile.Set(outFile); 00500 TBuf<201> buf; 00501 TInt len = 200; 00502 while (len>0) 00503 { 00504 buf.FillZ(); 00505 inTextFile.Read(buf); 00506 len=buf.Length(); 00507 outTextFile.Write(buf); 00508 } 00509 // Change date modified to reflect what's in the TMsvEntry 00510 outFile.SetModified(destEntry.iDate); 00511 00512 // Clean up 00513 inFile. Close(); 00514 outFile.Close(); 00515 if (DeleteSourceAfterwards()) 00516 err=iFs.Delete(iFileName); 00517 User::RequestComplete(iReportStatus, KErrNone); 00518 } 00519 00520 00521 void CTxtDeleteOp::DoRunL() 00522 // 00523 // Deleting files. 00524 // 00525 { 00526 TInt err=KErrNone; 00527 User::LeaveIfError(iStatus.Int()); 00528 // 00529 User::LeaveIfError(iServerEntry.SetEntry(iSourceId)); 00530 TMsvEntry entry = iServerEntry.Entry(); 00531 TxtUtils::GetEntryFileNameL(iFileName, entry); 00532 00533 err=iFs.Delete(iFileName); 00534 User::RequestComplete(iReportStatus, err); 00535 } 00536 00537 // 00538 // These CopyConstructL methods allow other classes to get an exact copy 00539 // of the class derived from CTxtActiveOper. Needed to recursively perform an 00540 // operation on a set of entries. 00541 // 00542 00543 // CTxtCopyToLocalOp 00544 00545 CTxtActiveOper* CTxtCopyToLocalOp::CopyConstructL() 00546 { 00547 return new (ELeave) CTxtCopyToLocalOp(iFs, iServerEntry); 00548 } 00549 00550 TBool CTxtCopyToLocalOp::CopiedHeader() const 00551 { 00552 return ETrue; 00553 } 00554 TBool CTxtCopyToLocalOp::DeleteSourceAfterwards() const 00555 { 00556 return EFalse; 00557 } 00558 00559 TBool CTxtCopyToLocalOp::MoveIsToService() const 00560 { 00561 return EFalse; 00562 } 00563 00564 // CTxtCopyFromLocalOp 00565 00566 CTxtActiveOper* CTxtCopyFromLocalOp::CopyConstructL() 00567 { 00568 return new (ELeave) CTxtCopyFromLocalOp(iFs, iServerEntry); 00569 } 00570 00571 TBool CTxtCopyFromLocalOp::CopiedHeader() const 00572 { 00573 return ETrue; 00574 } 00575 00576 TBool CTxtCopyFromLocalOp::DeleteSourceAfterwards() const 00577 { 00578 return EFalse; 00579 } 00580 00581 TBool CTxtCopyFromLocalOp::MoveIsToService() const 00582 { 00583 return ETrue; 00584 } 00585 00586 // CTxtCopyWithinServiceOp 00587 00588 CTxtActiveOper* CTxtCopyWithinServiceOp::CopyConstructL() 00589 { 00590 return new (ELeave) CTxtCopyWithinServiceOp(iFs, iServerEntry); 00591 } 00592 00593 TBool CTxtCopyWithinServiceOp::CopiedHeader() const 00594 { 00595 return ETrue; 00596 } 00597 00598 TBool CTxtCopyWithinServiceOp::DeleteSourceAfterwards() const 00599 { 00600 return EFalse; 00601 } 00602 00603 TBool CTxtCopyWithinServiceOp::MoveIsToService() const 00604 { 00605 return ETrue; 00606 } 00607 00608 // CTxtMoveToLocalOp 00609 00610 CTxtActiveOper* CTxtMoveToLocalOp::CopyConstructL() 00611 { 00612 return new (ELeave) CTxtMoveToLocalOp(iFs, iServerEntry); 00613 } 00614 00615 TBool CTxtMoveToLocalOp::DeleteSourceAfterwards() const 00616 { 00617 return ETrue; 00618 } 00619 00620 // CTxtMoveFromLocalOp 00621 00622 CTxtActiveOper* CTxtMoveFromLocalOp::CopyConstructL() 00623 { 00624 return new (ELeave) CTxtMoveFromLocalOp(iFs, iServerEntry); 00625 } 00626 00627 TBool CTxtMoveFromLocalOp::DeleteSourceAfterwards() const 00628 { 00629 return ETrue; 00630 } 00631 00632 // CTxtMoveWithinServiceOp 00633 00634 CTxtActiveOper* CTxtMoveWithinServiceOp::CopyConstructL() 00635 { 00636 return new (ELeave) CTxtMoveWithinServiceOp(iFs, iServerEntry); 00637 } 00638 00639 TBool CTxtMoveWithinServiceOp::DeleteSourceAfterwards() const 00640 { 00641 return ETrue; 00642 } 00643 00644 // CTxtDeleteOp 00645 00646 CTxtActiveOper* CTxtDeleteOp::CopyConstructL() 00647 { 00648 return new (ELeave) CTxtDeleteOp(iFs, iServerEntry); 00649 } 00650 00651 TBool CTxtDeleteOp::CopiedHeader() const 00652 { 00653 return EFalse; 00654 } 00655 00656 TBool CTxtDeleteOp::DeleteSourceAfterwards() const 00657 { 00658 return ETrue; 00659 } 00660 00661 TBool CTxtDeleteOp::MoveIsToService() const 00662 { 00663 return EFalse; 00664 } 00665 00666
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.