examples/ForumNokia/S60_3rd_Edition_TextMTM_Example/modules/Server/src/TXTSCPMV.CPP

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 

Generated by  doxygen 1.6.2