phonebookui/Phonebook2/GroupExtension/src/CPguAddMembersCmd.cpp
author andy simpson <andrews@symbian.org>
Thu, 02 Sep 2010 15:35:50 +0100
branchRCL_3
changeset 64 c1e8ba0c2b16
parent 57 2666d9724c76
parent 63 f4a778e096c2
permissions -rw-r--r--
Merge after bad RCL_3 drop reverted

/*
* 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 add to group command object.
*
*/

// INCLUDE FILES
#include "CPguAddMembersCmd.h"

// Phonebook 2
#include <Pbk2GroupUIRes.rsg>
#include <Pbk2Commands.rsg>
#include <Pbk2UIControls.rsg>
#include <CPbk2FetchDlg.h>
#include <MPbk2CommandObserver.h>
#include <MPbk2ContactUiControl.h>
#include <CPbk2ContactRelocator.h>
#include <Pbk2ProcessDecoratorFactory.h>
#include <CPbk2ViewState.h>
#include <MPbk2AppUi.h>
#include <MPbk2ApplicationServices.h>
#include <MPbk2ContactViewSupplier.h>

// Virtual Phonebook
#include <CVPbkFilteredContactView.h>
#include <CVPbkContactManager.h>
#include <MVPbkContactLink.h>
#include <CVPbkContactLinkArray.h>
#include <MVPbkContactGroup.h>
#include <MVPbkContactOperationBase.h>
#include <MVPbkContactStore.h>
#include <MVPbkContactStoreProperties.h>
#include <VPbkContactStoreUris.h>

// System includes
#include <coemain.h>
#include <eikenv.h>

// Debugging headers
#include <Pbk2Debug.h>

/// Unnamed namespace for local definitions
namespace {

const TInt KOneContact = 1;
const TInt KFirstElement = 0;
// This is used in progress bar tweaking
const TInt KCertainContactAmount = 3;

#ifdef _DEBUG

enum TPanicCode
    {
    EPanicPreCond_NewL = 1,
    EPanicPreCond_ExecuteLD,
    EPanicPreCond_RelocateContactsL,
    EPanicContactNotGroup,
    EInvalidView
    };

void Panic(TPanicCode aReason)
    {
    _LIT(KPanicText, "CPguAddMembersCmd");
    User::Panic(KPanicText,aReason);
    }

#endif // _DEBUG

} /// namespace

// --------------------------------------------------------------------------
// CPguAddMembersCmd::CPguAddMembersCmd
// --------------------------------------------------------------------------
//
CPguAddMembersCmd::CPguAddMembersCmd
        ( MVPbkContactLink& aContactGroup,
          MPbk2ContactUiControl& aUiControl ) :
            CActive( CActive::EPriorityStandard ),
            iUiControl( &aUiControl ),
            iGroupLink( aContactGroup ),
            iAddedContactsCount( 0 )
    {
    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
            ("CPguAddMembersCmd::CPguAddMembersCmd(0x%x)"), this);

    CActiveScheduler::Add( this );

    if( iUiControl )
        {
        iUiControl->RegisterCommand( this );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::~CPguAddMembersCmd
// --------------------------------------------------------------------------
//
CPguAddMembersCmd::~CPguAddMembersCmd()
    {
    Cancel();
    if ( iFilteredView )
        {
        iFilteredView->RemoveObserver( *this );
        delete iFilteredView;
        }
    else
        {
        Phonebook2::Pbk2AppUi()->
            ApplicationServices().ViewSupplier().
            AllContactsViewL()->RemoveObserver( *this );
        }
    if( iUiControl )
        {
        iUiControl->RegisterCommand( NULL );
        }
    
    delete iContact;
    delete iRetrieveContactOperation;
    delete iRetrieveGroupOperation;
    delete iContactGroup;
    delete iEntriesToAdd;
    delete iEntriesToRelocate;
    delete iContactRelocator;
    delete iDecorator;
    delete iContactsInGroup;
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ConstructL
// --------------------------------------------------------------------------
//
inline void CPguAddMembersCmd::ConstructL()
    {
    iState = ERetrievingContact;
    iContactsCounter = 0;
    }
// --------------------------------------------------------------------------
// CPguAddMembersCmd::NewLC
// --------------------------------------------------------------------------
//
CPguAddMembersCmd* CPguAddMembersCmd::NewLC
        ( MVPbkContactLink& aContactGroup,
          MPbk2ContactUiControl& aUiControl )
    {
    CPguAddMembersCmd* self = new ( ELeave ) CPguAddMembersCmd
        ( aContactGroup, aUiControl );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ExecuteLD
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ExecuteLD()
    {
    __ASSERT_DEBUG( iCommandObserver, Panic( EPanicPreCond_ExecuteLD ) );

    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
        ( "CPguAddMembersCmd::ExecuteLD(0x%x)"), this );

    IssueRequest();
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::AddObserver
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::AddObserver( MPbk2CommandObserver& aObserver )
    {
    iCommandObserver = &aObserver;
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ResetUiControl
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ResetUiControl
        ( MPbk2ContactUiControl& aUiControl )
    {
    if ( iUiControl == &aUiControl )
        {
        iUiControl = NULL;
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::RunL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::RunL()
    {
    switch( iState )
        {
        case ERetrievingContact:
            {
            iRetrieveGroupOperation = Phonebook2::Pbk2AppUi()->
                ApplicationServices().ContactManager().
                    RetrieveContactL( iGroupLink, *this );
            break;
            }
        case EHandleContactLockedEvent:
            {
            HandleContactLockedEventL();
            break;
            }
        case ECheckContacts:
            {
            CheckContactsL();
            break;
            } 
        case ERelocateContacts:
            {
            BeginRelocationL();
            break;
            }            
        case EShowingProgressNote:
            {
            ShowProgressNoteL();
            break;
            }
        case EAddingContactsToGroup:
            {
            AddContactsToGroupL();
            break;
            }
        case ECommitingTransaction:
            {
            CommitTransactionL();
            break;
            }
        case EStopping:
            {
            ProcessDismissed( KErrNone );
            break;
            }

        default:
            {
            // Do nothing
            break;
            }
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::DoCancel
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::DoCancel()
    {
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::RunError
// --------------------------------------------------------------------------
//
TInt CPguAddMembersCmd::RunError( TInt aError )
    {        
    FinishCommand( aError );
    return KErrNone;
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::VPbkSingleContactOperationComplete
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::VPbkSingleContactOperationComplete
        ( MVPbkContactOperationBase& aOperation,
          MVPbkStoreContact* aContact )
    {
    TInt error = KErrNone;

    if ( &aOperation == iRetrieveGroupOperation )
        {
        delete iRetrieveGroupOperation;
        iRetrieveGroupOperation = NULL;

        iContactGroup = aContact->Group();

        __ASSERT_DEBUG( iContactGroup, Panic( EPanicContactNotGroup ) );

        TRAP( error, iContactGroup->LockL( *this ) );
        }
    else if ( &aOperation == iRetrieveContactOperation && iState == ERelocateContacts )
        {
        TRAP( error, RelocateContactL( aContact ) );
        }
    else if ( &aOperation == iRetrieveContactOperation && iState == ECheckContacts )
        {
        iContact = aContact;
        // try to lock to check if contact is being modified by another application
        TRAP( error, iContact->LockL( *this ) );
        }

    if ( error != KErrNone )
        {
        FinishCommand( error );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::VPbkSingleContactOperationFailed
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::VPbkSingleContactOperationFailed
        ( MVPbkContactOperationBase& /*aOperation*/, TInt aError )
    {
    FinishCommand( aError );
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactOperationCompleted
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ContactOperationCompleted( TContactOpResult aResult )
    {
    if ( aResult.iOpCode == MVPbkContactObserver::EContactLock && 
            iState == ERetrievingContact )
        {
        iState = EHandleContactLockedEvent;
        IssueRequest();
        }
    else if ( aResult.iOpCode == MVPbkContactObserver::EContactLock && 
            iState == ECheckContacts )
        {
        iContactsCounter++;
        // delete to release the lock of contact
        delete iContact;
        iContact = NULL;
        IssueRequest();
        }
    else if ( aResult.iOpCode == MVPbkContactObserver::EContactCommit )
        {
        FinishCommand( KErrNone );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactOperationFailed
// --------------------------------------------------------------------------
//

void CPguAddMembersCmd::ContactOperationFailed
        ( TContactOp aOpCode, TInt aErrorCode, TBool aErrorNotified )
    {
    if ( aOpCode == MVPbkContactObserver::EContactLock && 
            iState == ECheckContacts )
        {
        delete iContact;
        iContact = NULL;
        FinishCommand( aErrorCode );
        }
    else if ( !aErrorNotified )
        {
        FinishCommand( aErrorCode );
        }
    else
        {
        FinishCommand( KErrNone );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactViewReady
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ContactViewReady
        ( MVPbkContactViewBase& /*aView*/ )
    {
    // Do nothing
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactViewUnavailable
// --------------------------------------------------------------------------
//

void CPguAddMembersCmd::ContactViewUnavailable
        ( MVPbkContactViewBase& /*aView*/ )
    {
    // Do nothing
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactAddedToView
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ContactAddedToView
        ( MVPbkContactViewBase& /*aView*/, TInt /*aIndex*/,
          const MVPbkContactLink& /*aContactLink*/ )
    {
    // Do nothing
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactRemovedFromView
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ContactRemovedFromView
        ( MVPbkContactViewBase& /*aView*/, TInt /*aIndex*/,
          const MVPbkContactLink& /*aContactLink*/ )
    {
    // Do nothing
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactViewError
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ContactViewError
        ( MVPbkContactViewBase&/*aView */,
        TInt aError, TBool /*aErrorNotified*/ )
    {
    FinishCommand( aError );
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::IsContactIncluded
//
// This function should be as efficient as possible because it's called
// as many times as there are contacts in all contacts view.
// --------------------------------------------------------------------------
//
TBool CPguAddMembersCmd::IsContactIncluded
        ( const MVPbkBaseContact& aContact )
    {
    TBool result = ETrue;
    TRAPD ( err,
        {
        // Contacts that already belongs to the group are NOT included
        // to the fetch dialog.
        if ( !iContactsInGroup )
            {
            iContactsInGroup = iContactGroup->ItemsContainedLC();
            CleanupStack::Pop(); // iContactsInGroup
            }

        const TInt count( iContactsInGroup->Count() );
        for ( TInt i(0); i < count; ++i)
            {
            if ( iContactsInGroup->At( i ).RefersTo( aContact ) )
                {
                result = EFalse;
                break;
                }
            }
        });

    if ( err != KErrNone )
        {
        CCoeEnv::Static()->HandleError( err );
        }

    return result;
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::AcceptFetchSelectionL
// --------------------------------------------------------------------------
//
MPbk2FetchDlgObserver::TPbk2FetchAcceptSelection
    CPguAddMembersCmd::AcceptFetchSelectionL
        ( TInt /*aNumMarkedEntries*/,
          MVPbkContactLink& /*aLastSelection*/ )
    {
    return MPbk2FetchDlgObserver::EFetchYes;
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::FetchCompletedL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::FetchCompletedL
        ( MVPbkContactLinkArray* aMarkedEntries )
    {
    if ( aMarkedEntries )
        {
        PrepareFetchResultsL( aMarkedEntries );
        }
    else
        {
        FinishCommand( KErrNone );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::FetchCanceled
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::FetchCanceled()
    {
    FinishCommand( KErrNone );
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::FetchAborted
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::FetchAborted()
    {
    FinishCommand( KErrNone );
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::FetchOkToExit
// --------------------------------------------------------------------------
//
TBool CPguAddMembersCmd::FetchOkToExit()
    {
    return ETrue;
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactRelocatedL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ContactRelocatedL
        ( MVPbkStoreContact* aRelocatedContact )
    {
    MVPbkContactLink* contactLink = aRelocatedContact->CreateLinkLC();
    if ( contactLink )
        {
        if ( iEntriesToAdd )
            {
            CleanupStack::Pop(); // contactLink
            iEntriesToAdd->AppendL( contactLink );
            }
        else
            {
            CleanupStack::PopAndDestroy(); // contactLink
            }
        }

    delete aRelocatedContact;

    // Advance the relocation progress note
    if ( iDecorator )
        {
        iDecorator->ProcessAdvance( 1 );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactRelocationFailed
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ContactRelocationFailed
        ( TInt aReason, MVPbkStoreContact* aContact )
    {
    // Can't do much than just delete the contact we were given ownership,
    // it can not be added to the group
    delete aContact;

    if ( aReason == KErrCancel
        && iEntriesToAdd
        && iEntriesToAdd->Count() > 0 )
        {
        // Although user discards relocation we have to add other entries
        // to the group if them exists. First show the progress note.
        iState = EShowingProgressNote;
        IssueRequest();
        }
    else
        {
        FinishCommand( aReason );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ContactsRelocationFailed
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ContactsRelocationFailed
        ( TInt aReason, CVPbkContactLinkArray* aContacts )
    {
    // Can't do much than just delete the contacts we were given ownership,
    // they can not be added to the group
    delete aContacts;

    if ( aReason == KErrCancel
        && iEntriesToAdd
        && iEntriesToAdd->Count() > 0 )
        {
        // Although user discards relocation we have to add other entries
        // to the group if them exists. First show the progress note.
        iState = EShowingProgressNote;
        IssueRequest();
        }
    else
        {
        FinishCommand( aReason );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::RelocationProcessComplete
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::RelocationProcessComplete()
    {
    iState = EShowingProgressNote;
    IssueRequest();
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ProcessDismissed
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ProcessDismissed( TInt /*aCancelCode*/ )
    {
    if ( iUiControl )
        {
        iUiControl->UpdateAfterCommandExecution();
        }
    if ( iCommandObserver )
        {
        iCommandObserver->CommandFinished( *this );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::HandleContactLockedEventL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::HandleContactLockedEventL()
    {
    delete iFilteredView;
    iFilteredView = NULL;
    MPbk2ApplicationServices& appServices = Phonebook2::Pbk2AppUi()->ApplicationServices();
    TInt count = KErrNotFound;
    if ( !iContactsInGroup && iContactGroup )
        {
        iContactsInGroup = iContactGroup->ItemsContainedLC();
        CleanupStack::Pop(); // iContactsInGroup
        }
    if ( iContactsInGroup )
        {
        count = iContactsInGroup->Count();
        }
    if ( count > 0 || count == KErrNotFound )
        {
        iFilteredView = CVPbkFilteredContactView::NewL
            ( *appServices.ViewSupplier().AllContactsViewL(), *this, *this,
                    appServices.ContactManager().FieldTypes() );
        }

    DoLaunchFetchDialogL();
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::DoLaunchFetchDialogL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::DoLaunchFetchDialogL()
    {
    CPbk2FetchDlg::TParams params;
    params.iResId = R_PBK2_MULTIPLE_ENTRY_FETCH_NO_GROUPS_DLG;
    if ( iFilteredView )
        {
        // Fetch dlg uses this view instead of AllNameslistView
        params.iNamesListView = iFilteredView;
        }
    else
        {
        MVPbkContactViewBase* view = Phonebook2::Pbk2AppUi()
            ->ApplicationServices().ViewSupplier().AllContactsViewL();
        view->AddObserverL( *this );
        params.iNamesListView = view;
        }
    params.iFlags = CPbk2FetchDlg::EFetchMultiple;
    params.iNaviPaneId = R_PBK2_GROUP_MEMBER_FETCH_NAVILABEL;

    CPbk2FetchDlg* dlg = CPbk2FetchDlg::NewL( params, *this );
    // Fetch dialog is not waiting dialog, so we just launch it
    dlg->ExecuteLD();
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::PrepareFetchResultsL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::PrepareFetchResultsL
        ( MVPbkContactLinkArray* aMarkedEntries )
    {
    if ( aMarkedEntries )
        {
        const TInt count = aMarkedEntries->Count();

        delete iEntriesToAdd;
        iEntriesToAdd = NULL;
        iEntriesToAdd = CVPbkContactLinkArray::NewL();

        delete iEntriesToRelocate;
        iEntriesToRelocate = NULL;
        iEntriesToRelocate = CVPbkContactLinkArray::NewL();

        for ( TInt i = 0; i < count; ++ i )
            {
            MVPbkContactLink* contactLink =
                aMarkedEntries->At( i ).CloneLC();
            CleanupStack::Pop(); // contactLink

            TVPbkContactStoreUriPtr uri =
                    contactLink->ContactStore().StoreProperties().Uri();
            TVPbkContactStoreUriPtr phoneMemoryUri(
                    VPbkContactStoreUris::DefaultCntDbUri() );

            if ( uri.Compare( phoneMemoryUri,
                    TVPbkContactStoreUriPtr::EContactStoreUriStoreType )
                        == 0 )
                {
                // Phone memory contact can be added to group directly
                iEntriesToAdd->AppendL( contactLink );
                }
            else
                {
                // We must first relocate the contact
                iEntriesToRelocate->AppendL( contactLink );
                }
            }

        iState = ECheckContacts;
        IssueRequest();
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::RelocateContactL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::RelocateContactL( MVPbkStoreContact* aStoreContact )
    {
    delete iContactRelocator;
    iContactRelocator = NULL;
    iContactRelocator = CPbk2ContactRelocator::NewL();

    // Asynchronously relocate the contact
    // One contact doesn't need waiting note
    iContactRelocator->RelocateContactL( aStoreContact, *this,
        Pbk2ContactRelocator::EPbk2DisplayBasicQuery,
        CPbk2ContactRelocator::EPbk2RelocatorExistingContact );
    }
// --------------------------------------------------------------------------
// CPguAddMembersCmd::RelocateContactsL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::RelocateContactsL()
    {
    __ASSERT_DEBUG( iEntriesToRelocate->Count() > KOneContact,
        Panic( EPanicPreCond_RelocateContactsL ) );

    TInt count = iEntriesToRelocate->Count();
    delete iContactRelocator;
    iContactRelocator = NULL;
    iContactRelocator = CPbk2ContactRelocator::NewL();

    // Asynchronously relocate contacts
    TBool result = iContactRelocator->RelocateContactsL( iEntriesToRelocate,
        *this, Pbk2ContactRelocator::EPbk2DisplayBasicQuery );
    iEntriesToRelocate = NULL;    // Ownership was taken
    if ( result )
        {
        // User has accepted relocation, show "Retrieving" progress note
        ShowRelocationNoteL( count );
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::AddContactsToGroupL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::AddContactsToGroupL()
    { 
    if (iEntriesToAdd && 
        iAddedContactsCount < iEntriesToAdd->Count() )
        { 
        const MVPbkContactLink& contactToAdd = iEntriesToAdd->At( iAddedContactsCount );
        iAddedContactsCount++; 
        
        // If leaves, RunError called
        iContactGroup->AddContactL( contactToAdd );
      
        if ( iDecorator )
            {
            iDecorator->ProcessAdvance( 1 );
            }     
        iState = EAddingContactsToGroup;
        }
    else
        {
        iState = ECommitingTransaction;
        }
    
    IssueRequest();
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::CommitTransactionL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::CommitTransactionL()
    {
    iContactGroup->CommitL( *this );
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::FinishCommand
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::FinishCommand( TInt aResult )
    {
    if ( iUiControl )
        {
        iUiControl->SetBlank( EFalse );
        TRAPD(err, SetFocusToLastAddedL() );
        if ( KErrNone != err )
            {
            CCoeEnv::Static()->HandleError( aResult );
            }
        }

    if ( aResult != KErrNone && aResult != KErrCancel )
        {
        CCoeEnv::Static()->HandleError( aResult );
        }

    if ( iDecorator )
        {
        // iDecorator calls ProcessStopped to end this cmd
        iDecorator->ProcessStopped();
        }
    else
        {
        if ( iUiControl )
            {
            iUiControl->UpdateAfterCommandExecution();
            }
        if ( iCommandObserver )
            {
            iCommandObserver->CommandFinished( *this );
            }
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::ShowRelocationNoteL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ShowRelocationNoteL( TInt aCount )
    {
    if ( iUiControl )
        {
        iUiControl->SetBlank( ETrue );
        }

    if ( !iDecorator )
        {
        // Show relocation note only if there are enough contacts
        // You can't use here the TBool-delay switch,
        // it just doesn't progress
        if ( aCount > KCertainContactAmount )
            {
            iDecorator = Pbk2ProcessDecoratorFactory::
                CreateProgressDialogDecoratorL
                ( R_QTN_GEN_NOTE_RETRIEVING_PROGRESS, EFalse );
            iDecorator->SetObserver( *this );
            iDecorator->ProcessStartedL( aCount + 1 );
            }
        else
            {
            // There are few contacts, so omit the whole note
            iDecorator = Pbk2ProcessDecoratorFactory::
                CreateProgressDialogDecoratorL
                ( R_QTN_GEN_NOTE_RETRIEVING_PROGRESS, ETrue );
            iDecorator->SetObserver( *this );
            iDecorator->ProcessStartedL( 0 );
            }
        }
    }


// --------------------------------------------------------------------------
// CPguAddMembersCmd::ShowProgressNoteL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::ShowProgressNoteL()
    {
    if ( iUiControl )
        {
        iUiControl->SetBlank( ETrue );
        }

    if ( !iDecorator && iEntriesToAdd )
        {
        // Show relocation note only if there are enough contacts
        // You can't use here the TBool-delay switch, it just doesn't
        // progress
        if ( iEntriesToAdd->Count() > KCertainContactAmount )
            {
            iDecorator = Pbk2ProcessDecoratorFactory::
                CreateProgressDialogDecoratorL
                ( R_QTN_GEN_NOTE_RETRIEVING_PROGRESS, EFalse );
            iDecorator->SetObserver( *this );
            iDecorator->ProcessStartedL( iEntriesToAdd->Count() + 1 );
            }
        else
            {
            // There are few contacts, so omit the whole note
            iDecorator = Pbk2ProcessDecoratorFactory::
                CreateProgressDialogDecoratorL
                ( R_QTN_GEN_NOTE_RETRIEVING_PROGRESS, ETrue );
            iDecorator->SetObserver( *this );
            iDecorator->ProcessStartedL( 0 );
            }
        }
    iState = EAddingContactsToGroup;
    IssueRequest();
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::IssueRequest
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::IssueRequest()
    {
    TRequestStatus* status = &iStatus;
    User::RequestComplete( status, KErrNone );
    SetActive();
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::IssueStopRequest
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::IssueStopRequest()
    {
    iState = EStopping;
    if ( !IsActive() )
        {
        IssueRequest();
        }
    }

// --------------------------------------------------------------------------
// CPguAddMembersCmd::SetFocusToLastAddedL
// --------------------------------------------------------------------------
//
void CPguAddMembersCmd::SetFocusToLastAddedL()
    {
    if ( iUiControl && iEntriesToAdd && iEntriesToAdd->Count() )
        {
        // Sets the focus to last added contactlink
        TInt focusedIndex( iEntriesToAdd->Count() - 1 );
        CPbk2ViewState* viewState = iUiControl->ControlStateL();
        CleanupStack::PushL( viewState );

        viewState->SetFocusedContact(
            iEntriesToAdd->At( focusedIndex ).CloneLC() );
        CleanupStack::Pop(); // iEntriesToAdd->At(focusedIndex).CloneLC

        iUiControl->RestoreControlStateL( viewState );
        CleanupStack::PopAndDestroy();  // viewState
        }
    }

void CPguAddMembersCmd::BeginRelocationL()
    {
    if ( iEntriesToRelocate->Count() > KOneContact )
        {
        RelocateContactsL();
        }
    else if ( iEntriesToRelocate->Count() == KOneContact )
        {
        // We'll have to retrieve the one single contact and
        // use single contact relocator
        delete iRetrieveContactOperation;
        iRetrieveContactOperation = NULL;
        iRetrieveContactOperation =
            Phonebook2::Pbk2AppUi()->ApplicationServices().
                ContactManager().RetrieveContactL(
                    iEntriesToRelocate->At( KFirstElement ), *this );
        }
    else
        {
        // Contacts will be added to group. First show
        // the progress note.
        iState = EShowingProgressNote;
        IssueRequest();
        }
    }

void CPguAddMembersCmd::CheckContactsL()
    {
    if ( iContactsCounter < iEntriesToAdd->Count() )
        {
        delete iRetrieveContactOperation;
        iRetrieveContactOperation = NULL;
        iRetrieveContactOperation = Phonebook2::Pbk2AppUi()->ApplicationServices().
            ContactManager().RetrieveContactL( iEntriesToAdd->At( iContactsCounter ), *this );
        }
    else
        {
        iState = ERelocateContacts;
        IssueRequest();
        }
    }
// End of File