ipsservices/ipssosplugin/src/ipsplgimap4moveremoteop.cpp
changeset 0 8466d47a6819
child 1 12c456ceeff2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipsservices/ipssosplugin/src/ipsplgimap4moveremoteop.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,456 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*       Move a selection of messages that may or may not be complete
+*
+*/
+
+
+#include "emailtrace.h"
+#include "ipsplgheaders.h"
+
+const TInt KMoveRemoteOpPriority = CActive::EPriorityStandard;
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+CIpsPlgImap4MoveRemoteOp* CIpsPlgImap4MoveRemoteOp::NewL(
+    CMsvSession& aMsvSession,
+    TRequestStatus& aObserverRequestStatus,
+    TInt aFunctionId,
+    TMsvId aService,
+    CIpsPlgTimerOperation& aActivityTimer,
+    const TImImap4GetMailInfo& aGetMailInfo,
+    const CMsvEntrySelection& aSel,
+    TFSMailMsgId aFSMailBoxId,
+    MFSMailRequestObserver& aFSOperationObserver,
+    TInt aFSRequestId )
+    {
+    FUNC_LOG;
+    CIpsPlgImap4MoveRemoteOp* op = new (ELeave) CIpsPlgImap4MoveRemoteOp(
+        aMsvSession,
+        aObserverRequestStatus,
+        aFunctionId,
+        aService,
+        aActivityTimer,
+        aGetMailInfo,
+        aFSMailBoxId,
+        aFSOperationObserver,
+        aFSRequestId );
+        
+    CleanupStack::PushL( op );
+    op->ConstructL( aSel );
+    CleanupStack::Pop( op );
+    return op;
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+CIpsPlgImap4MoveRemoteOp::CIpsPlgImap4MoveRemoteOp(
+    CMsvSession& aMsvSession,
+    TRequestStatus& aObserverRequestStatus,
+    TInt aFunctionId,
+    TMsvId aService,
+    CIpsPlgTimerOperation& aActivityTimer,
+    const TImImap4GetMailInfo& aGetMailInfo,
+    TFSMailMsgId aFSMailBoxId,
+    MFSMailRequestObserver& aFSOperationObserver,
+    TInt aFSRequestId )
+    :
+    CIpsPlgOnlineOperation(
+    aMsvSession,
+    KMoveRemoteOpPriority,
+    aObserverRequestStatus,
+    aActivityTimer,
+    aFSMailBoxId,
+    aFSOperationObserver,
+    aFSRequestId ),
+    iFunctionId(aFunctionId),
+    iGetMailInfo(aGetMailInfo)
+    {
+    FUNC_LOG;
+    iService = aService;
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------    
+CIpsPlgImap4MoveRemoteOp::~CIpsPlgImap4MoveRemoteOp()
+    {
+    FUNC_LOG;
+    delete iLocalSel;
+    delete iRemoteSel;
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+void CIpsPlgImap4MoveRemoteOp::ConstructL( const CMsvEntrySelection& aSel )
+    {
+    FUNC_LOG;
+    BaseConstructL(KUidMsgTypeIMAP4);
+    SortMessageSelectionL( aSel );
+    DoConnectL();
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+void CIpsPlgImap4MoveRemoteOp::DoConnectL()
+    {
+    FUNC_LOG;
+    iState = EConnecting;
+    iStatus = KRequestPending;
+
+    CIpsPlgImap4ConnectOp* connOp = CIpsPlgImap4ConnectOp::NewL(
+        iMsvSession,
+        KMoveRemoteOpPriority,
+        iStatus, 
+        iService,
+        *iActivityTimer,
+        iFSMailboxId,
+        iFSOperationObserver,
+        iFSRequestId,
+        NULL, // event handler not needed whin plain connect
+        ETrue,
+        EFalse );
+        
+    delete iOperation;
+    iOperation = connOp;
+
+    SetActive();
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+const TDesC8& CIpsPlgImap4MoveRemoteOp::ProgressL()
+    {
+    FUNC_LOG;
+    if( iMoveErrorProgress && (iState == EIdle) )
+        {
+        // Completed, but with an error during move.
+        return *iMoveErrorProgress;
+        }        
+    TImap4SyncProgress progg;
+    progg.iErrorCode = KErrNone;
+    TPckgBuf<TImap4SyncProgress> param(progg);
+    iSyncProgress.Copy(param);
+    return iSyncProgress;  
+    }
+    
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------  
+const TDesC8& CIpsPlgImap4MoveRemoteOp::GetErrorProgressL(TInt aError)
+    {
+    FUNC_LOG;
+    // Called to report a leave in DoRunL()
+    if(!iProgressBuf().iGenericProgress.iErrorCode)
+        {
+        TImap4CompoundProgress& prog = iProgressBuf();
+        prog.iGenericProgress.iOperation = 
+            TImap4GenericProgress::EMoveWithinService;
+        prog.iGenericProgress.iState = TImap4GenericProgress::EMoving;
+        prog.iGenericProgress.iErrorCode = aError;
+        }
+    return iProgressBuf;
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+TFSProgress CIpsPlgImap4MoveRemoteOp::GetFSProgressL() const
+    {
+    FUNC_LOG;
+    // might not never called, but gives something reasonable if called
+    TFSProgress result = { TFSProgress::EFSStatus_Waiting, 0, 0, KErrNone };
+    if ( iState == EConnecting )
+        {
+        result.iProgressStatus = TFSProgress::EFSStatus_Connecting;
+        }
+    else
+        {
+        result.iProgressStatus = TFSProgress::EFSStatus_RequestComplete;
+        }
+    return result;
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+void CIpsPlgImap4MoveRemoteOp::RunL()
+    {
+    FUNC_LOG;
+    TRAPD(err, DoRunL());
+    if(err != KErrNone)
+        {
+        iSyncProgress().iErrorCode = err;
+        Complete();
+        }
+    }
+    
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+void CIpsPlgImap4MoveRemoteOp::DoRunL()
+    {
+    FUNC_LOG;
+    TInt err = iStatus.Int();
+    switch(iState)
+        {
+        case EConnecting:
+            {
+            TBool connected = STATIC_CAST(CIpsPlgImap4ConnectOp*, iOperation)->Connected();
+            if( !connected )
+                {
+                CompleteObserver( KErrCouldNotConnect );
+                return;
+                }
+            DoMoveLocalL();
+            }
+            break;
+        case ELocalMsgs:
+            // Local move complete
+            if( err != KErrNone )
+                {
+                // Failed to copy local messages.
+                iState = EIdle;
+                CompleteObserver( err );
+                }
+            else
+                {
+                DoMoveRemoteL();
+                }
+            break;
+        case ERemoteMsgs:
+            // Remote move complete.
+            if( err != KErrNone && iOperation )
+                {
+                iMoveErrorProgress = iOperation->ProgressL().AllocL();
+                }
+            iState = EIdle;
+            // to be considered
+            // if this fails, should we move the messages back to local 
+            // directory
+            CompleteObserver( err );
+            break;
+        case EIdle:
+        default:
+            break;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+void CIpsPlgImap4MoveRemoteOp::SortMessageSelectionL(const CMsvEntrySelection& aSel)
+    {
+    FUNC_LOG;
+    if ( aSel.Count() == 0 )
+        {
+        User::Leave( KErrNotSupported );
+        }
+    // Sort messages into complete and incomplete selections.
+    iLocalSel = new(ELeave) CMsvEntrySelection;
+    iRemoteSel = new(ELeave) CMsvEntrySelection;
+
+    TInt err;
+    TMsvId id;
+    TMsvId service;
+    TMsvEntry tEntry;
+    TInt selCount( aSel.Count() );
+    for( TInt count(0); count < selCount; count++ )
+        {
+        id = aSel[count];
+        err = iMsvSession.GetEntry( id, service, tEntry );
+        if( KErrNone == err )
+            {
+            // local move is not needed, if the message is not fetched
+            if( tEntry.Complete() )
+                {
+                if ( 0 < count )
+                    {
+                    // service id is not added to local, 
+                    // service is already
+                    // added in MoveMessagesL
+                    iLocalSel->AppendL( id );
+                    }
+                }
+                iRemoteSel->AppendL( id );
+                }
+            }
+        }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+void CIpsPlgImap4MoveRemoteOp::Complete()
+    {
+    FUNC_LOG;
+    TRequestStatus* observer = &iObserverRequestStatus;
+    User::RequestComplete( observer, KErrNone );
+    }
+    
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+void CIpsPlgImap4MoveRemoteOp::DoMoveLocalL()
+    {
+    FUNC_LOG;
+    iState = ELocalMsgs;
+    iStatus = KRequestPending;
+    if( iLocalSel->Count() )
+        {
+        // this gets the first msg to be moved
+        CMsvEntry* cEntry = iMsvSession.GetEntryL( (*iLocalSel)[0] );
+        CleanupStack::PushL( cEntry );
+        // find the parent of the moved message...
+        TMsvId parent = cEntry->Entry().Parent();
+        // and use it as a context
+        cEntry->SetEntryL( parent );
+
+        delete iOperation;
+        iOperation = NULL;
+        iOperation = cEntry->MoveL( *iLocalSel, 
+                                    iGetMailInfo.iDestinationFolder, 
+                                    iStatus );
+        CleanupStack::PopAndDestroy( cEntry ); 
+        SetActive();
+        }
+    else
+        {
+        SetActive();
+        CompleteThis();
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+void CIpsPlgImap4MoveRemoteOp::DoMoveRemoteL()
+    {
+    FUNC_LOG;
+    iState = ERemoteMsgs;
+    iStatus = KRequestPending;
+    // first element of the CMsvEntrySelection is the service which is then
+    // followed by any messages
+    if( iRemoteSel->Count() > 1 )
+        {
+        // Switch operations.
+        delete iOperation;
+        iOperation = NULL;
+    
+        // Filters are not used when performing 'move' operation, use normal 
+        // getmail info instead
+        TPckg<TImImap4GetMailInfo> param( iGetMailInfo );
+        InvokeClientMtmAsyncFunctionL( iFunctionId, *iRemoteSel, iService, param );
+        SetActive();
+        }
+    else
+        {
+        SetActive();
+        CompleteThis();
+        }
+    }
+    
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------    
+TInt CIpsPlgImap4MoveRemoteOp::GetEngineProgress( const TDesC8& aProgress )
+    {
+    FUNC_LOG;
+    if( !aProgress.Length() )
+        {
+        return KErrNone;
+        }
+    else
+        {
+        TPckgBuf<TImap4CompoundProgress> paramPack;
+        paramPack.Copy( aProgress );
+        const TImap4GenericProgress& progress = paramPack().iGenericProgress;
+
+        return progress.iErrorCode;
+        }
+    }
+
+// class CIpsPlgImap4MoveRemoteOpObserver
+//
+
+// ----------------------------------------------------------------------------
+// ---------------------------------------------------------------------------- 
+CIpsPlgImap4MoveRemoteOpObserver* CIpsPlgImap4MoveRemoteOpObserver::NewL(
+    CMsvSession& aSession, CIpsPlgEventHandler& aEventHandler,
+    const TFSMailMsgId& aSourceFolder,
+    const RArray<TFSMailMsgId>& aMessageIds )
+    {
+    FUNC_LOG;
+    CIpsPlgImap4MoveRemoteOpObserver* self
+        = new ( ELeave ) CIpsPlgImap4MoveRemoteOpObserver( aSession,
+            aEventHandler, aSourceFolder.Id() );
+    CleanupStack::PushL( self );
+    self->ConstructL( aMessageIds );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// ---------------------------------------------------------------------------- 
+CIpsPlgImap4MoveRemoteOpObserver::~CIpsPlgImap4MoveRemoteOpObserver()
+    {
+    FUNC_LOG;
+    delete iSelection;
+    }
+
+// ----------------------------------------------------------------------------
+// ---------------------------------------------------------------------------- 
+void CIpsPlgImap4MoveRemoteOpObserver::RequestResponseL( TFSProgress aEvent,
+    TInt /*aRequestId*/ )
+    {
+    FUNC_LOG;
+    if ( aEvent.iProgressStatus == TFSProgress::EFSStatus_RequestCancelled ||
+         aEvent.iError != KErrNone )
+        {
+        // Assumes that still existing entries have not been moved.
+        for ( TInt ii = iSelection->Count() - 1; ii >= 0; --ii )
+            {
+            TMsvId id = iSelection->At(ii);
+            TMsvId dummy = KMsvNullIndexEntryIdValue;
+            TMsvEntry entry;
+            if ( iSession.GetEntry( id, dummy, entry ) != KErrNone )
+                {
+                iSelection->Delete( ii );
+                }
+            }
+
+        if ( iSelection->Count() )
+            {
+            iEventHandler.HandleSessionEventL(
+                MMsvSessionObserver::EMsvEntriesMoved,
+                iSelection, &iSourceFolderId, &iSourceFolderId );
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// ---------------------------------------------------------------------------- 
+CIpsPlgImap4MoveRemoteOpObserver::CIpsPlgImap4MoveRemoteOpObserver(
+    CMsvSession& aSession, CIpsPlgEventHandler& aEventHandler,
+    TMsvId aSourceFolderId )
+    : iSession( aSession ), iEventHandler( aEventHandler ),
+    iSourceFolderId( aSourceFolderId )
+    {
+    FUNC_LOG;
+    }
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------     
+void CIpsPlgImap4MoveRemoteOpObserver::ConstructL(
+    const RArray<TFSMailMsgId>& aMessageIds )
+    {
+    FUNC_LOG;
+    TInt count = aMessageIds.Count();
+    iSelection = new ( ELeave ) CMsvEntrySelection;
+    for ( TInt ii = 0; ii < count; ++ii )
+        {
+        iSelection->AppendL( aMessageIds[ii].Id() );
+        }
+    }
+