phonebookui/Phonebook2/USIMExtension/src/CPsu2CopyToSimCmd.cpp
changeset 0 e686773b3f54
child 18 d4f567ce2e7c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/USIMExtension/src/CPsu2CopyToSimCmd.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,896 @@
+/*
+* Copyright (c) 2005-2007 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:  Phonebook 2 USIM UI Extension copy to SIM command.
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPsu2CopyToSimCmd.h"
+
+// Phonebook 2
+#include "CPsu2CopyToSimFieldInfoArray.h"
+#include "CPsu2SimContactProcessor.h"
+#include "TPsu2SimCopyResults.h"
+#include "CPsu2ContactCopyInspector.h"
+#include <MPbk2ContactUiControl.h>
+#include <CPbk2FieldPropertyArray.h>
+#include <MPbk2ContactNameFormatter.h>
+#include <MPbk2CommandObserver.h>
+#include <Pbk2ProcessDecoratorFactory.h>
+#include <Pbk2USimUIRes.rsg>
+#include <CPbk2StorePropertyArray.h>
+#include <CPbk2StoreProperty.h>
+#include <CPbk2ApplicationServices.h>
+#include <MPbk2AppUi.h>
+#include <Pbk2CommonUi.rsg>
+
+// Virtual Phonebook
+#include <MVPbkContactStoreProperties.h>
+#include <CVPbkContactManager.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkContactLink.h>
+#include <MVPbkContactOperationBase.h>
+#include <CVPbkContactLinkArray.h>
+#include <CVPbkFieldTypeRefsList.h>
+#include <MVPbkContactStoreInfo.h>
+
+// System includes
+#include <avkon.hrh>
+#include <exterror.h>
+#include <coemain.h>
+#include <StringLoader.h>
+#include <aknnotewrappers.h>
+
+// debug
+#include <Pbk2Debug.h>
+
+/// Unnamed namespace for local definitions
+namespace {
+
+const TInt KZero = 0;
+const TInt KOne = 1;
+
+enum TNextTask
+    {
+    EStartCommand,
+    ERetrieveSourceContact,
+    ECreateSimContacts,
+    EStartCopy,
+    ECopyContact,
+    EShowResultsAndComplete,
+    EComplete
+    };
+
+enum TTargetStoreStatus
+	{
+    EStoreNotOpen,
+    EStoreOpen,
+    EStoreNotAvailable
+	};
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    ECopyToSimMenuItemMustNotBeInMenu,
+    EPreCond_CopyCurrentContactL,
+    };
+
+void Panic(TInt aReason)
+    {
+    _LIT(KPanicText, "CPsu2CopyToSimCmd");
+    User::Panic(KPanicText, aReason);
+    }
+#endif // _DEBUG
+
+} /// namespace
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::CPsu2CopyToSimCmd
+// --------------------------------------------------------------------------
+//
+CPsu2CopyToSimCmd::CPsu2CopyToSimCmd( MPbk2ContactUiControl& aUiControl,
+        MVPbkContactStore& aTargetStore ) :
+    CActive( EPriorityStandard ),
+    iUiControl( &aUiControl ),
+    iTargetStore( aTargetStore ),
+    iUpdateControl( ETrue ),
+    iIsCopiedCompletely( ETrue ),
+    iIsLastCopyFailedForSimIsFull( EFalse )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::~CPsu2CopyToSimCmd
+// --------------------------------------------------------------------------
+//
+CPsu2CopyToSimCmd::~CPsu2CopyToSimCmd()
+    {   
+    Cancel();
+    delete iContactInspector;
+    delete iDecorator;
+    delete iSimContactProcessor;
+    delete iCopyToSimTypeInfos;
+    delete iContactRetriever;
+    delete iLinkArray;
+    delete iCurrentSourceContact;
+    delete iCurrentSimContact;
+    iSimContacts.ResetAndDestroy();
+    // Deregister the observer to the target store.
+    iTargetStore.Close( *this );
+
+    Release( iAppServices );
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::NewL
+// --------------------------------------------------------------------------
+//
+CPsu2CopyToSimCmd* CPsu2CopyToSimCmd::NewL(
+        MPbk2ContactUiControl& aUiControl,
+        MVPbkContactStore& aTargetStore)
+    {
+    CPsu2CopyToSimCmd* self =
+        new( ELeave ) CPsu2CopyToSimCmd(aUiControl, aTargetStore);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ConstructL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::ConstructL()
+    {
+    iAppServices = CPbk2ApplicationServices::InstanceL();
+
+    CActiveScheduler::Add(this);
+
+    iLinkArray = CVPbkContactLinkArray::NewL();
+    iContactInspector = CPsu2ContactCopyInspector::NewL
+        ( iAppServices->NameFormatter() );
+
+    // The command can be called from the generic Copy starter
+    // or straight using Copy To SIM menu command
+    // -> iUiControl can be name list control or
+    // it can be a store list control
+    // safe since reference in contructor
+    iNameListUiControl = iUiControl->ParentControl();
+    if (!iNameListUiControl)
+        {
+        iNameListUiControl = iUiControl;
+        }
+
+    iNameListUiControl->RegisterCommand( this );
+
+    MVPbkContactLinkArray* linkArray =
+        iNameListUiControl->SelectedContactsOrFocusedContactL();
+    // There must be at least one item in the array, otherwise the menu
+    // item shouldn't be there
+    __ASSERT_DEBUG( linkArray && linkArray->Count() > 0,
+        Panic( ECopyToSimMenuItemMustNotBeInMenu ) );
+
+    CleanupDeletePushL( linkArray );
+    // Copy links that belongs to the target store
+    TVPbkContactStoreUriPtr targetUri = iTargetStore.StoreProperties().Uri();
+    const TInt count = linkArray->Count();
+    for (TInt i = 0; i < count; ++i)
+        {
+        TVPbkContactStoreUriPtr uri =
+            (*linkArray)[i].ContactStore().StoreProperties().Uri();
+        if ( targetUri.Compare(uri,
+            TVPbkContactStoreUriPtr::EContactStoreUriAllComponents) != 0)
+            {
+            iLinkArray->AppendL( (*linkArray)[i].CloneLC() );
+            CleanupStack::Pop(); // created link
+            }
+        }
+    CleanupStack::PopAndDestroy(); // linkArray
+
+    // Create source to SIM field type mapping infos
+    iCopyToSimTypeInfos = CPsu2CopyToSimFieldInfoArray::NewL(
+        iAppServices->ContactManager().FieldTypes(),
+        iAppServices->ContactManager().FsSession() );
+
+    // Create a processor that knows how to build and split contacts
+    iSimContactProcessor = CPsu2SimContactProcessor::NewL(
+        iTargetStore,
+        *iCopyToSimTypeInfos,
+        iAppServices->NameFormatter(),
+        iAppServices->ContactManager().FieldTypes(),
+        iAppServices->ContactManager().FsSession() );
+
+    iDecorator = Pbk2ProcessDecoratorFactory::CreateProgressDialogDecoratorL(
+            R_PSU2_COPY_PROGRESS_NOTE, ETrue );
+    iDecorator->SetObserver( *this );
+    
+    iTargetStoreStatus = EStoreNotOpen;
+    // Register as an observer of the store, to make sure could get the store state
+    // change notification.
+    iTargetStore.OpenL( *this );
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::RunL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::RunL()
+    {
+    switch (iNextTask)
+        {
+        case EStartCommand:
+            {
+            StartL();
+            break;
+            }
+        case ERetrieveSourceContact:
+            {
+            RetrieveSourceContactL();
+            break;
+            }
+        case ECreateSimContacts:
+            {
+            CreateSimContactsL();
+            break;
+            }
+        case EStartCopy:
+            {
+            StartCopyL();
+            break;
+            }
+        case ECopyContact:
+            {
+            CopyCurrentContactL();
+            break;
+            }
+        case EShowResultsAndComplete:
+            {
+            // If can't get the sim space here, and the former  
+            // copy is failed, just show that sim is full 
+            if ( (GetSimSpaceStatusL() == ESimSpaceUnknown) &&
+                    iIsLastCopyFailedForSimIsFull )
+                {
+                ShowSimIsFullNoteL();
+                }
+            else
+                {
+                ShowResultsNoteL();    
+                }
+            
+            CompleteL();
+            break;
+            }
+        case EComplete: // FALLTHROUGH
+        default:
+            {
+            CompleteL();
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::DoCancel
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::DoCancel()
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::RunError
+// --------------------------------------------------------------------------
+//
+TInt CPsu2CopyToSimCmd::RunError(TInt aError)
+    {
+    PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING
+        ( "CPsu2CopyToSimCmd::RunError %d" ), aError );
+    CCoeEnv::Static()->HandleError(aError);
+    if ( iCommandObserver )
+        {
+        iCommandObserver->CommandFinished(*this);
+        }
+    return KErrNone;
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ExecuteLD
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::ExecuteLD()
+    {
+    iNextTask = EStartCommand;
+    IssueRequest();
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::AddObserver
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::AddObserver(MPbk2CommandObserver& aObserver)
+    {
+    iCommandObserver = &aObserver;
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ResetUiControl
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::ResetUiControl(
+        MPbk2ContactUiControl& aUiControl)
+    {
+    if (iNameListUiControl == & aUiControl)
+        {
+        iUiControl = NULL;
+        iNameListUiControl = NULL;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::StoreReady
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::StoreReady( MVPbkContactStore& /*aContactStore*/ )
+	{
+	iTargetStoreStatus = EStoreOpen;
+	}
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::StoreUnavailable
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::StoreUnavailable( MVPbkContactStore& /*aContactStore*/, 
+        TInt /*aReason*/ )
+	{
+	iTargetStoreStatus = EStoreNotAvailable;
+	}
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::HandleStoreEventL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::HandleStoreEventL( 
+        MVPbkContactStore& /*aContactStore*/, 
+        TVPbkContactStoreEvent /*aStoreEvent*/ )
+	{
+	// do nothing.
+	}
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::VPbkSingleContactOperationComplete
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::VPbkSingleContactOperationComplete(
+    MVPbkContactOperationBase& /*aOperation*/,
+    MVPbkStoreContact* aContact)
+    {
+    PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING
+        ( "CPsu2CopyToSimCmd::VPbkSingleContactOperationComplete 0x%x" ),
+        this );
+    // This is called when a new source contact is loaded
+
+    delete iCurrentSourceContact;
+    iCurrentSourceContact = aContact;
+
+    // Create SIM contacts from the source next
+    iNextTask = ECreateSimContacts;
+    IssueRequest();
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::VPbkSingleContactOperationFailed
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::VPbkSingleContactOperationFailed(
+    MVPbkContactOperationBase& /*aOperation*/, TInt aError)
+    {
+    PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING
+        ( "CPsu2CopyToSimCmd::VPbkSingleContactOperationFailed 0x%x" ),
+        this );
+    // This is called when a new source contact loading failed
+    iDecorator->ProcessAdvance(KOne);
+    HandleError(aError);
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ContactOperationCompleted
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::ContactOperationCompleted
+        (TContactOpResult /*aResult*/)
+    {
+    PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING
+        ( "CPsu2CopyToSimCmd::ContactOperationCompleted 0x%x" ),
+        this );
+    // This called when one SIM contact has been copied
+    // ( or deleted in additional number full case )
+    iIsLastCopyFailedForSimIsFull = ETrue;
+    if (iSimContacts.Count() == 0)
+        {
+        // The source contact has been successfully copied
+        ++iCopied;
+        MoveToNextContact();
+        }
+    else
+        {
+        // The source contact was splitted and all splitted sim contacts
+        // are not yet copied
+        CopyNextSimContact();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ContactOperationFailed
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::ContactOperationFailed
+    (TContactOp /*aOpCode*/, TInt aErrorCode, TBool /*aErrorNotified*/)
+    {
+    PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING
+        ( "CPsu2CopyToSimCmd::ContactOperationFailed 0x%x ERROR: %d" ),
+        this, aErrorCode );
+
+    // This called when copying of a SIM contact failed
+    TInt res = KErrNone;
+    TInt currentSimContactDeleted( EFalse );
+    iIsLastCopyFailedForSimIsFull = ETrue;
+    if (iSimContactProcessor->HandleSimError(aErrorCode ))
+        {
+        // If the error was handled it means that the SIM contact
+        // must be splitted and resulted contacts must be copied.
+        TRAP(res, iSimContactProcessor->CreateFixedSimContactsL(
+            *iCurrentSimContact, iSimContacts));
+
+        if ( res == KErrNone && iIsCopiedCompletely )
+            {
+            iIsCopiedCompletely = !iSimContactProcessor->DetailsDropped();
+            if ( iIsCopiedCompletely )
+                {
+                // Inspect that contact was copied completely
+                // if sim contacts has created.
+                if ( iIsCopiedCompletely && iSimContacts.Count() > 0 )
+                    {
+                    iIsCopiedCompletely = iContactInspector->IsCopiedCompletelyL
+                        ( *iCurrentSimContact, iSimContacts );
+                    }
+                }
+            }
+
+        if ( res == KErrNone )
+            {
+            // Current contact is partially saved so delete it
+            // to prevent duplicate data
+            TRAP( res, iCurrentSimContact->DeleteL( *this ) );
+            currentSimContactDeleted = ETrue;
+            }
+        }
+    else
+        {
+        res = aErrorCode;
+        }
+
+    if (res != KErrNone)
+        {
+        // Stop command or move to next contact depending on the error
+        HandleError(res);
+        }
+    else if (iSimContacts.Count() > 0)
+        {
+        // if delete contact is on, this will continue in
+        // MVPbkContactObserver callback
+        if ( !currentSimContactDeleted )
+            {
+            // There are still SIM contacts to copy
+            CopyNextSimContact();
+            }
+        }
+    else
+        {
+        // Current contact has been handled, move to next contact
+        MoveToNextContact();
+        }
+
+    PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING(
+    "CPsu2CopyToSimCmd::ContactOperationFailed 0x%x IsCopiedCompletely: %d" ),
+    this, iIsCopiedCompletely );
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ProcessDismissed
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::ProcessDismissed(TInt aCancelCode)
+    {
+    if ( iNameListUiControl )
+        {
+        iNameListUiControl->SetBlank( EFalse );
+        }
+
+    if ( aCancelCode == KErrCancel || aCancelCode == EEikBidCancel )
+        {
+        Cancel();
+        HandleCanceling();
+        iNextTask = EShowResultsAndComplete;
+        }
+    IssueRequest();
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::IssueRequest
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::IssueRequest()
+    {
+    if ( !IsActive() )
+        {
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete(status, KErrNone);
+        SetActive();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::StartL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::StartL()
+    {
+    if ( GetSimSpaceStatusL() == ESimSpaceIsFull )
+        {
+        ShowSimIsFullNoteL();
+        iNextTask = EComplete;
+        IssueRequest();
+        }
+    else
+        {
+        iCurrentIndex = 0;
+        TInt contactCount = iLinkArray->Count();
+        switch ( contactCount )
+            {
+            case KZero:
+                {
+                CompleteWithResults();
+                break;
+                }
+            default:
+                {
+                iDecorator->ProcessStartedL( contactCount );
+                iNextTask = ERetrieveSourceContact;
+                IssueRequest();
+                break;
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::HandleCanceling
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::HandleCanceling()
+    {
+    delete iContactRetriever;
+    iContactRetriever = NULL;
+    delete iCurrentSimContact;
+    iCurrentSimContact = NULL;
+    iSimContacts.ResetAndDestroy();
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::RetrieveSourceContactL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::RetrieveSourceContactL()
+    {
+    if (iCurrentIndex >= iLinkArray->Count())
+        {
+        // End copying if all contacts have been read
+        CompleteWithResults();
+        }
+    else
+        {
+        delete iContactRetriever;
+        iContactRetriever = NULL;
+
+        iContactRetriever = iAppServices->ContactManager().RetrieveContactL(
+                (*iLinkArray)[iCurrentIndex], *this);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::CreateSimContactsL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::CreateSimContactsL()
+    {
+    iSimContacts.ResetAndDestroy();
+    iSimContactProcessor->CreateSimContactsL(
+        *iCurrentSourceContact, iSimContacts );
+    // Inspect that contact was copied completely
+    // if sim contacts has created.
+    if ( iIsCopiedCompletely && iSimContacts.Count() > 0 )
+        {
+        iIsCopiedCompletely = iContactInspector->IsCopiedCompletelyL
+            ( *iCurrentSourceContact, iSimContacts );
+        }
+    if ( iSimContacts.Count() == 0 )
+        {
+        MoveToNextContact();
+        }
+    else
+        {
+        iNextTask = EStartCopy;
+        IssueRequest();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::StartCopyL()
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::StartCopyL()
+    {
+    if ( iNameListUiControl )
+        {
+        // Blank UI control to avoid names list view refreshing
+        iNameListUiControl->SetBlank( ETrue );
+        }
+
+    CopyNextSimContact();
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::CopyCurrentContactL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::CopyCurrentContactL()
+    {
+    delete iCurrentSimContact;
+    iCurrentSimContact = NextSimContact();
+    
+    __ASSERT_DEBUG(iCurrentSimContact, Panic(EPreCond_CopyCurrentContactL));
+    // If the store is not open, just complete the copy process.
+    if( iTargetStoreStatus != EStoreOpen )
+    	{
+    	CompleteWithResults();
+    	}
+    else
+    	{
+    	iCurrentSimContact->CommitL(*this);
+    	}
+    }
+    
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ShowResultsNoteL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::ShowResultsNoteL()
+    {
+    if (iLinkArray->Count() == KOne)
+        {
+        if (iCurrentSourceContact)
+            {
+            HBufC* title = iAppServices->NameFormatter().
+                GetContactTitleL(iCurrentSourceContact->Fields(),
+                    MPbk2ContactNameFormatter::EPreserveLeadingSpaces);
+            CleanupStack::PushL(title);
+            TPsu2SimCopyResults results(iCopied, *title);
+            // Show partly copied note if necessary
+            if ( !iIsCopiedCompletely )
+                {
+                results.ShowPartlyCopiedNoteL();
+                }
+            else
+                {
+                results.ShowNoteL();
+                }
+            CleanupStack::PopAndDestroy(title);
+            }
+        else
+            {
+            TPsu2SimCopyResults results;
+            results.ShowErrorNoteL();
+            }
+        }
+    else
+        {
+        TPsu2SimCopyResults results(iCopied, iLinkArray->Count());
+        results.ShowNoteL();
+        // Show partly copied note if necessary
+        if ( !iIsCopiedCompletely )
+            {
+            results.ShowPartlyCopiedNoteL();
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::CompleteL
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::CompleteL()
+    {
+    if ( iUpdateControl  && iNameListUiControl )
+        {
+        iNameListUiControl->SetBlank( EFalse );
+        // Reset find due to case that if contact was not really copied
+        // (=the target contact had already all the same fields) then
+        // UI control doesn't receive any events and find text is not
+        // reset by the UI control.
+        iNameListUiControl->ResetFindL();
+        if ( iCurrentSourceContact )
+            {
+            // Maintain NamesList focus on the source contact
+            iNameListUiControl->SetFocusedContactL( *iCurrentSourceContact );
+            }
+        // If the copy has been cancelled we don't want to update control.
+        // Markings are not removed after cancel.
+        iNameListUiControl->UpdateAfterCommandExecution();
+        }
+    if ( iCommandObserver )
+        {
+        iCommandObserver->CommandFinished(*this);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::NextSimContact
+// --------------------------------------------------------------------------
+//
+MVPbkStoreContact* CPsu2CopyToSimCmd::NextSimContact()
+    {
+    if (iSimContacts.Count() > 0)
+        {
+        const TInt firstPos = 0;
+        MVPbkStoreContact* contact = iSimContacts[firstPos];
+        iSimContacts.Remove(firstPos);
+        return contact;
+        }
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::HandleError
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::HandleError(TInt aError)
+    {
+    switch (aError)
+        {
+        // Errors that can be ignored
+        case KErrGsm0707InvalidCharsInTextString:   // FALLTHROUGH
+        case KErrGsm0707TextStringTooLong:          // FALLTHROUGH
+        case KErrGsm0707DialStringTooLong:          // FALLTHROUGH
+        case KErrGsmCCUnassignedNumber:
+            {
+            MoveToNextContact();
+            break;
+            }
+        default:
+            {
+            // If the copy was failed for memory full
+            if (aError == KErrGsm0707MemoryFull)
+                {
+                iIsLastCopyFailedForSimIsFull = ETrue;
+                }
+            CompleteWithResults();
+            CCoeEnv::Static()->HandleError(aError);
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::MoveToNextContact
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::MoveToNextContact()
+    {
+    iDecorator->ProcessAdvance(KOne);
+    ++iCurrentIndex;
+    iNextTask = ERetrieveSourceContact;
+    IssueRequest();
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::CopyNextSimContact
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::CopyNextSimContact()
+    {
+    CPsu2CopyToSimCmd::TSimSpaceStatus simSpaceStatus = ESimSpaceUnknown;
+
+    // Check always before copying that there is space for a new contact
+    TRAPD( res, simSpaceStatus = GetSimSpaceStatusL() )
+    if ( res != KErrNone )
+        {
+        HandleError( res );
+        }
+    else
+        {
+        iNextTask = ECopyContact;
+        if ( simSpaceStatus == ESimSpaceIsFull )
+            {
+            CompleteWithResults();
+            }
+        else
+            {
+            IssueRequest();
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::CompleteWithResults
+// --------------------------------------------------------------------------
+//
+void CPsu2CopyToSimCmd::CompleteWithResults()
+    {
+    iNextTask = EShowResultsAndComplete;
+    if ( iDecorator )
+        {
+        // This will cause a callback to ProcessDismissed
+        iDecorator->ProcessStopped();
+        }
+    else
+        {
+        IssueRequest();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ShowNoteIfSimIsFullL
+// --------------------------------------------------------------------------
+//
+CPsu2CopyToSimCmd::TSimSpaceStatus CPsu2CopyToSimCmd::GetSimSpaceStatusL()
+    {
+    const MVPbkContactStoreInfo& info = iTargetStore.StoreInfo();
+    
+    if ( info.MaxNumberOfContactsL() <= 0 )
+        {
+        return ESimSpaceUnknown;
+        }
+    else if ( info.MaxNumberOfContactsL() == info.NumberOfContactsL() )
+        {
+        return ESimSpaceIsFull;
+        }
+    
+    return ESimSpaceIsNotFull;
+    }
+
+// --------------------------------------------------------------------------
+// CPsu2CopyToSimCmd::ShowSimIsFullNoteL
+// --------------------------------------------------------------------------
+//    
+void CPsu2CopyToSimCmd::ShowSimIsFullNoteL()
+    {
+        const CPbk2StoreProperty* storeProperty =
+            iAppServices->StoreProperties().FindProperty(
+                    iTargetStore.StoreProperties().Uri() );
+
+        // R_QTN_PHOB_NOTE_STORE_FULL is from Pbk2Commands and it's
+        // safe to use because commands resources are loaded in core pbk2
+        HBufC* fullText = StringLoader::LoadLC(
+            R_QTN_PHOB_NOTE_STORE_FULL,
+            storeProperty->StoreName() );
+
+        CAknInformationNote* noteDlg =
+            new(ELeave) CAknInformationNote( ETrue );
+        noteDlg->ExecuteLD( *fullText );
+        CleanupStack::PopAndDestroy( fullText );
+    }
+
+//  End of File