ipsservices/ipssosplugin/src/ipsplgimap4moveremoteop.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 14:51:52 +0300
changeset 18 578830873419
parent 1 12c456ceeff2
child 20 ecc8def7944a
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* 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:
            {
            // <qmail> Connected() usage
            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;        
        }    
    }