phonebookui/Phonebook2/Application/src/CPbk2ContactInfoAppView.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 14 Sep 2010 20:54:53 +0300
branchRCL_3
changeset 21 9da50d567e3c
parent 0 e686773b3f54
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* 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 contact info application view.
*
*/

// INCLUDE FILES
#include "CPbk2ContactInfoAppView.h"

// Phonebook 2
#include "CPbk2AppUi.h"
#include "CPbk2Document.h"
#include "CPbk2StartupMonitor.h"
#include "CPbk2ViewExplorer.h"
#include "CPbk2ViewActivationTransaction.h"
#include "Pbk2InternalCommands.hrh"
#include "CPbk2ViewLoader.h"
#include <phonebook2.rsg>
#include <pbk2uicontrols.rsg>
#include <pbk2commands.rsg>
#include <CPbk2ViewState.h>
#include <MPbk2ContactNavigation.h>
#include <Pbk2NavigatorFactory.h>
#include <CPbk2ControlContainer.h>
#include <CPbk2ContactInfoControl.h>
#include <MPbk2CommandHandler.h>
#include <MPbk2ContactDetailsControl.h>
#include <CPbk2StoreConfiguration.h>
#include <CPbk2MemoryEntryContactLoader.h>
#include <Pbk2Commands.hrh>
#include <CPbk2ViewStateTransformer.h>
#include <TPbk2StoreContactAnalyzer.h>
#include <CPbk2FieldPropertyArray.h>
#include <CPbk2SortOrderManager.h>
#include <CPbk2ViewGraph.h>
#include <Pbk2UID.h>
#include <csxhelp/phob.hlp.hrh>
#include <MPbk2PointerEventInspector.h>
#include <MPbk2ApplicationServices.h>
#include <MPbk2ContactViewSupplier.h>

// Virtual Phonebook
#include <CVPbkContactManager.h>
#include <MVPbkStoreContact.h>
#include <MVPbkContactLink.h>
#include <MVPbkContactViewBase.h>
#include <MVPbkExpandable.h>
#include <CVPbkContactStoreUriArray.h>
#include <MVPbkContactStoreList.h>
#include <TVPbkContactStoreUriPtr.h>

// System includes
#include <avkon.rsg>
#include <AiwCommon.hrh>
#include <eikmenub.h>
#include <AknUtils.h>
#include <StringLoader.h>

// Debugging headers
#include <Pbk2Debug.h>
#include <Pbk2Profile.h>
#include <Pbk2Config.hrh>

/// Unnamed namespace for local definitions
namespace {

#ifdef _DEBUG
enum TPanicCode
    {
    EPanicPreCond_HandleCommandL = 1,
    EPanicPreCond_HandleCommandKeyL,
    EPanicPostCond_ConstructL,
    EPanicPreCond_DynInitMenuPaneL,
    EPanicPreCond_ContactChangedL,
    EPanicPreCond_SetNavigatorViewL,
    EPanicPreCond_GetViewSpecificMenuFilteringFlagsL,
    EPanicPreCond_NULLPointer,
    EPanicPreCond_ViewLoaded,
    EPanicLogic_LoadContactL
    };

void Panic(TPanicCode aReason)
    {
    _LIT( KPanicText, "CPbk2ContactInfoAppView" );
    User::Panic( KPanicText, aReason );
    }
#endif // _DEBUG

} /// namespace


// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::CPbk2ContactInfoAppView
// --------------------------------------------------------------------------
//
inline CPbk2ContactInfoAppView::CPbk2ContactInfoAppView
        ( CVPbkContactManager& aContactManager ) :
            iContactManager( aContactManager )
    {
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::~CPbk2ContactInfoAppView
// --------------------------------------------------------------------------
//
CPbk2ContactInfoAppView::~CPbk2ContactInfoAppView()
    {
    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
        ("CPbk2ContactInfoAppView(%x)::~CPbk2ContactInfoAppView()"), this);

    delete iViewLoader;
    delete iControlState;
    delete iViewActivationTransaction;
    delete iNavigation;
    delete iContactLoader;
    iStoreList.Reset();
    iStoreList.Close();

    if (iContainer)
        {
        AppUi()->RemoveFromViewStack(*this, iContainer);
        delete iContainer;
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::NewL
// --------------------------------------------------------------------------
//
CPbk2ContactInfoAppView* CPbk2ContactInfoAppView::NewL
        ( CVPbkContactManager& aContactManager )
    {
    CPbk2ContactInfoAppView* self =
        new ( ELeave ) CPbk2ContactInfoAppView( aContactManager );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ConstructL
// --------------------------------------------------------------------------
//
inline void CPbk2ContactInfoAppView::ConstructL()
    {
    // Init base class
    PBK2_PROFILE_START(Pbk2Profile::EContactInfoViewBaseConstruct);
    CAknView::BaseConstructL(R_PHONEBOOK2_CONTACTINFO_APPVIEW);
    PBK2_PROFILE_END(Pbk2Profile::EContactInfoViewBaseConstruct);

    iCommandHandler = Pbk2AppUi()->ApplicationServices().CommandHandlerL();
    iStoreConfiguration =  &Pbk2AppUi()->ApplicationServices().
        StoreConfiguration();

    __ASSERT_DEBUG(iCommandHandler,
        Panic(EPanicPostCond_ConstructL));
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::HandleCommandL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::HandleCommandL
        (TInt aCommandId)
    {
    __ASSERT_DEBUG(iControl,
        Panic(EPanicPreCond_HandleCommandL));

    // If this view has already been deactivated, just return
    if ( Pbk2AppUi()->ActiveView()->Id() != Phonebook2::KPbk2ContactInfoViewUid )
        {
        return;
        }

    if (EAknCmdHideInBackground == aCommandId)
        {
        // Gets a pointer to Nameslist extension view
        CAknView* pNamesListExtensionView =
                static_cast<CAknView*> (Pbk2AppUi()->View(
                        Phonebook2::KPbk2NamesListViewUid));

        // if Nameslist extension view does exists, 
        // pass EAknCmdHideInBackground to the view, in order to close the CCA.
        if (pNamesListExtensionView)
            {
            pNamesListExtensionView->HandleCommandL(aCommandId);
            }
        }

    switch (aCommandId)
        {
        case EAknSoftkeyBack:       // FALLTHROUGH
        case EPbk2CmdOpenPreviousView:
            {
            // Set the focused contact according to control state -> NULL
            ReturnToPreviousViewL( NULL );
            break;
            }
        default:
            {
            // No command handling in this class, forward to Commands
            if ( !iCommandHandler->HandleCommandL
                    ( aCommandId, *iControl, this ) )
                {
                iControl->ProcessCommandL(aCommandId);
                // Command was not handled in Pbk2Commands,
                // forward it to AppUi
                AppUi()->HandleCommandL(aCommandId);
                if ( aCommandId == EAknCmdHideInBackground )
                    {
                    DoDeactivate();
                    }
                }
            break;
            }
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::DynInitMenuPaneL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::DynInitMenuPaneL
        (TInt aResourceId, CEikMenuPane* aMenuPane)
    {
    __ASSERT_DEBUG(iControl,
        Panic(EPanicPreCond_DynInitMenuPaneL));

    // Ask the control do control specific filtering
    iControl->DynInitMenuPaneL(aResourceId, aMenuPane);

    // Phonebook 2 menu filtering happens in Commands
    iCommandHandler->DynInitMenuPaneL(
            aResourceId, aMenuPane, *this, *iControl);
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::Id
// --------------------------------------------------------------------------
//
TUid CPbk2ContactInfoAppView::Id() const
    {
    return Phonebook2::KPbk2ContactInfoViewUid;
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::HandleStatusPaneSizeChange
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::HandleStatusPaneSizeChange()
    {
    // Resize the container to fill the client rectangle
    if (iContainer)
        {
        iContainer->SetRect(ClientRect());
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::DoActivateL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::DoActivateL
        ( const TVwsViewId& aPrevViewId,
          TUid aCustomMessageId, const TDesC8& aCustomMessage )
    {
    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
        ("CPbk2ContactInfoAppView(%x)::DoActivateL()"), this);

    //NOTE: this view can be used as external,
    // DoActivateL can be called for active view
 
    // UpdateViewGraphL only for pbk2 views, 
    if ( Pbk2AppUi()->Pbk2ViewExplorer()->IsPhonebook2View(aPrevViewId) )
        {
        UpdateViewGraphL( aPrevViewId );
        }
    else if ( iContainer )
        {
        // if the view activated as an external, reset it state
        delete iControlState;
        iControlState = NULL;
        }

    iCommandHandler->RemoveMenuCommandObserver( *this );
    iCommandHandler->AddMenuCommandObserver( *this );
    
    iStoreConfiguration->RemoveObserver( *this );
    iStoreConfiguration->AddObserverL( *this );

    // Update application-wide state. UI control updates the title pane.
    delete iViewActivationTransaction;
    iViewActivationTransaction = NULL;
    TUint flags (Phonebook2::EUpdateContextPane);
    if ( !iContainer )
        {
        // don't update navipane if it's already active
        flags |= Phonebook2::EUpdateNaviPane;
        }
    iViewActivationTransaction =
        Pbk2AppUi()->Pbk2ViewExplorer()->HandleViewActivationLC
            ( Id(), aPrevViewId, NULL, NULL,
              flags );
    CleanupStack::Pop(); // iViewActivationTransaction

    if (aCustomMessageId == CPbk2ViewState::Uid() ||
        aCustomMessageId == TUid::Uid(KPbkViewStateUid))
        {
        // Handles both new and legacy view state parameters
        UpdateViewStateL(aCustomMessageId, aCustomMessage);
        }
    else
        {
        // No UI state specified, restore in previous state
        if (!iControlState)
            {
            // No previous state
            User::Leave(KErrArgument);
            }
        }

     if ( !iControlState->FocusedContact() )
        {
        User::Leave( KErrArgument );
        }
     
    //navigator is created for each DoActiveL, depends on input parameters
    //navigator is created for each DoActiveL, depends on input parameters
    ConstructNavigatorL();
    
    //if the view is active, its control is reused, only navigator is updated
    CreateControlsL();
    AttachAIWProvidersL();

    LoadContactViewL( aPrevViewId );
    iPreviousViewId = aPrevViewId;
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::DoDeactivate
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::DoDeactivate()
    {
    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
        ("CPbk2ContactInfoAppView(%x)::DoDeactivate()"), this);

    delete iViewLoader;
    iViewLoader = NULL;

    iCommandHandler->RemoveMenuCommandObserver( *this );

    iStoreConfiguration->RemoveObserver( *this );

    delete iViewActivationTransaction;
    iViewActivationTransaction = NULL;
    delete iNavigation;
    iNavigation = NULL;

    // Trash the old states
    delete iControlState;
    iControlState = NULL;

    // Reset store list
    iStoreList.Reset();

    if (iContainer)
        {
        iContainer->Control()->HideThumbnail();

        // Remove view and its control from the view stack
        AppUi()->RemoveFromViewStack(*this, iContainer);

        // Store current state, safe to ignore. There's no real harm,
        // if theres no stored state when activating this view again
        TRAP_IGNORE(StoreStateL());

        // Destroy the container control
        delete iContainer;
        iContainer = NULL;
        iControl = NULL;
        }

    delete iContactLoader;
    iContactLoader = NULL;
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::HandleForegroundEventL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::HandleForegroundEventL( TBool aForeground )
    {
    CPbk2AppView::HandleForegroundEventL(aForeground);

    // If this view is gaining foreground, then make sure that thumbnail
    // gets drawn
    if (aForeground && iContainer && iContainer->Control())
        {
        if ( iContainer->Control()->IsVisible() )
            {
            iContainer->Control()->ShowThumbnail();
            }
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ViewStateLC
// --------------------------------------------------------------------------
//
CPbk2ViewState* CPbk2ContactInfoAppView::ViewStateLC() const
    {
    __ASSERT_DEBUG( iControl ,Panic(EPanicPreCond_NULLPointer));

    CPbk2ViewState* state = iControl->ControlStateL();
    CleanupStack::PushL(state);
    return state;
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::HandleCommandKeyL
// --------------------------------------------------------------------------
//
TBool CPbk2ContactInfoAppView::HandleCommandKeyL
        (const TKeyEvent& aKeyEvent, TEventCode aType)
    {
    __ASSERT_DEBUG(iContainer && iNavigation,
        Panic(EPanicPreCond_HandleCommandKeyL));

    // Pass the key event to the strategy
    TBool ret = iNavigation->HandleCommandKeyL( aKeyEvent, aType );

    if ( !ret && aType == EEventKey )
        {
        switch ( aKeyEvent.iCode )
            {
            case EKeyEnter: // FALLTHROUGH
            case EKeyOK:
                {
                LaunchPopupMenuL( R_PHONEBOOK2_CONTACTINFO_CONTEXTBAR );
                ret = ETrue;
                break;
                }
            case EKeyBackspace:  // Clear key
                {
                HandleCommandL(EPbk2CmdDeleteMe);
                ret = ETrue;
                break;
                }
            case EKeyPhoneSend:
                {
                // If focused field is either url or email field
                // the proper context menu should be launched.
                if ( IsFocusedFieldTypeL( R_PHONEBOOK2_URL_SELECTOR )
                    || IsFocusedFieldTypeL( R_PHONEBOOK2_EMAIL_SELECTOR ) )
                    {
                    LaunchPopupMenuL( R_PHONEBOOK2_CONTACTINFO_CONTEXTBAR );
                    }
                else
                    {
                    // Use the EPbk2CmdCall id to identify that
                    // call is being launched with send key
                    HandleCommandL( EPbk2CmdCall );
                    }
                ret = ETrue;
                break;
                }
            case EKeyPoC:
                {
                // Use the EPbk2CmdPoC id to identify that
                // call is being launched with PoC key
                HandleCommandL( EPbk2CmdPoC );
                ret = ETrue;
                break;
                }
            default:
                {
                break;
                }
            }
        }
    return ret;
    }


// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::GetViewSpecificMenuFilteringFlagsL
// --------------------------------------------------------------------------
//
TInt CPbk2ContactInfoAppView::GetViewSpecificMenuFilteringFlagsL() const
    {
    __ASSERT_DEBUG( iControl,
        Panic( EPanicPreCond_GetViewSpecificMenuFilteringFlagsL ) );

    return iControl->GetMenuFilteringFlagsL();
    }


// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::PrepareForContactChangeL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::PrepareForContactChangeL()
    {
    StoreStateL();
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ContactChangedL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::ContactChangedL( MVPbkStoreContact* aContact )
    {
    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
        ("CPbk2ContactInfoAppView(%x)::ContactChangedL() begin"), this);

    if ( !iContainer )
        {
        // It is possible that this method get called before
        // the container and control get constructed.
        // In that case, ignore the given contact by deleting
        // it and do not continue the contact changed process.
        delete aContact;

        // iViewActivationTransaction should not be deleted here
        // since it is not tied to this ContactChangedL request

        PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
            ("CPbk2ContactInfoAppView(%x)::ContactChangedL() controls not ready"),
            this);
        }
    else
        {
        __ASSERT_DEBUG(iViewActivationTransaction,
            Panic(EPanicPreCond_ContactChangedL));
        __ASSERT_DEBUG(iNavigation, Panic(EPanicPreCond_ContactChangedL));

        // Update controls
        if (aContact)
            {
            CleanupDeletePushL(aContact);
            iContainer->Control()->UpdateL(aContact);
            CleanupStack::Pop(aContact);    // ownership was taken
            }

        if ( iControlState->FocusedContact() )
            {
            if ( !iControlState->FocusedContact()->RefersTo( *aContact ) )
                {
                iContainer->Control()->SetFocusedFieldIndex( KErrNotFound );
                iControlState->SetFocusedFieldIndex( KErrNotFound );
                }
            }

        SetEmptyTextL( R_QTN_PHOB_NO_ITEMS );

        iContainer->Control()->RestoreControlStateL(iControlState);

        // Commit application-wide state changes
        iViewActivationTransaction->Commit();

        // notifies startup monitor of view activation
        if (Pbk2AppUi()->Pbk2StartupMonitor())
            {
            Pbk2AppUi()->Pbk2StartupMonitor()->NotifyViewActivationL(Id());
            }
        }

    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
        ("CPbk2ContactInfoAppView(%x)::ContactChangedL() end"), this);
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ContactChangeFailed
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::ContactChangeFailed()
    {
    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
        ("CPbk2ContactInfoAppView(%x)::ContactChangeFailed()"), this);

    TInt err = KErrNone;

    TRAP( err, SetEmptyTextL( R_QTN_PHOB_NO_ITEMS ) );
    if ( err != KErrNone )
        {
        CEikonEnv::Static()->HandleError( err );
        }

    // Rollback
    if ( iViewActivationTransaction )
        {
        // Rollback by force
        TRAP( err, iViewActivationTransaction->RollbackL() );
        delete iViewActivationTransaction;
        iViewActivationTransaction = NULL;

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

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::Contact
// --------------------------------------------------------------------------
//
const MVPbkStoreContact* CPbk2ContactInfoAppView::Contact() const
    {
    const MVPbkStoreContact* result = NULL;
    if (iControl)
        {
        result = iControl->FocusedStoreContact();
        }
    return result;
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::HandleControlEventL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::HandleControlEventL
        ( MPbk2ContactUiControl& /*aControl*/,
          const TPbk2ControlEvent& aEvent )
    {
    switch (aEvent.iEventType)
        {
        case TPbk2ControlEvent::EContactDoubleTapped:
            {
            LaunchPopupMenuL( R_PHONEBOOK2_CONTACTINFO_CONTEXTBAR );
            break;
            }

        case TPbk2ControlEvent::EReady:
            {
            UpdateCbasL();
            break;
            }

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

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ConfigurationChanged
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::ConfigurationChanged()
    {
    if (iPreviousViewId.iViewUid != KNullUid)
        {
        TRAPD(err, LoadContactViewL(iPreviousViewId));
        if (err != KErrNone)
            {
            CCoeEnv::Static()->HandleError(err);
            }
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ConfigurationChangedComplete
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::ConfigurationChangedComplete()
    {
    // Do nothing
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::PreCommandExecutionL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::PreCommandExecutionL
        ( const MPbk2Command& /*aCommand*/ )
    {
    if (iContainer && iContainer->Control())
        {
        iContainer->Control()->HideThumbnail();
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::PostCommandExecutionL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::PostCommandExecutionL
        ( const MPbk2Command& /*aCommand*/ )
    {
    if (iContainer && iContainer->Control())
        {
        iContainer->Control()->ShowThumbnail();
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::CreateControlsL
// --------------------------------------------------------------------------
//
inline void CPbk2ContactInfoAppView::CreateControlsL()
    {
    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
            ("CPbk2ContactInfoAppView::CreateControlsL()"));

    // if the view is active, recreate control, in order
    // to use new iNavigation and delete old storecontact

    if ( iContainer && iControl )
        {
        iContainer->DestroyControl();
        iControl = NULL;
        }

    if (!iContainer)
        {
        // Create the container and control
        CContainer* container = CContainer::NewLC(this, this, *this);

        container->SetHelpContext( TCoeHelpContext( ApplicationUid(),
                KHLP_CCA_DETAILS ));
        
        // Add this view and container to the view stack
        AppUi()->AddToViewStackL(*this, container);
        CleanupStack::Pop(container);
        iContainer = container;
        }

    if ( !iControl )
        {
        CPbk2ContactInfoControl* control = CPbk2ContactInfoControl::NewL
            ( iContainer, iContactManager,
              Pbk2AppUi()->ApplicationServices().NameFormatter(),
              Pbk2AppUi()->ApplicationServices().FieldProperties(),
              Pbk2AppUi()->ApplicationServices().StoreProperties(),
              iNavigation );
        TRect r = ClientRect();
        iContainer->SetControl(control, r); // takes ownership
        control->AddObserverL(*this);

        iControl = control;
        
        // Assign pointer event inspector
        iPointerInspector =
            AknLayoutUtils::PenEnabled() ? control : NULL;

        iContainer->ActivateL();
        iContainer->Control()->MakeVisible( ETrue );
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::HandleNavigationEvent
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::HandleNavigationEvent
        ( const TEventType& aEventType )
    {
    if ( aEventType == MPbk2NavigationObserver::EContactDeleted )
        {
        // Contact was deleted which means that we must go back to previous
        // view. The previous view must know the contact to focus and it
        // obviously can not be the deleted contact. The navigator works
        // in a same logic as the focus in the previous view. It knows the
        // the contact after deletion.
        TRAPD( err,
            {
            MVPbkContactLink* curContact = CurrentContactInNavigatorLC();
            CleanupStack::Pop(); // curContact
            // Give ownership of curContact
            ReturnToPreviousViewL( curContact );
            });
        if ( err != KErrNone )
            {
            CCoeEnv::Static()->HandleError( err );
            }
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ViewLoaded
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::ViewLoaded( MVPbkContactViewBase& aView )
    {
    __ASSERT_DEBUG(iContactLoader && iControlState,
        Panic(EPanicPreCond_ViewLoaded));

    if ( &aView == iContactView )
        {
        TRAPD( error, HandleViewLoadedL() );
        if ( error != KErrNone )
            {
            ViewError( aView, error );
            }
        }
    delete iViewLoader;
    iViewLoader = NULL;
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ViewError
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::ViewError
        ( MVPbkContactViewBase& aView, TInt /*aError*/ )
    {
    delete iViewLoader;
    iViewLoader = NULL;

    if ( &aView == iContactView )
        {
        TRAPD( error, iViewActivationTransaction->RollbackL() );
        if ( error != KErrNone )
            {
            CCoeEnv::Static()->HandleError(error);
            }
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::UpdateViewStateL
// --------------------------------------------------------------------------
//
inline void CPbk2ContactInfoAppView::UpdateViewStateL
        ( const TUid aCustomMessageId,
          const TDesC8& aCustomMessage )
    {
    CPbk2ViewState* viewState = NULL;
    if (aCustomMessageId == TUid::Uid(KPbkViewStateUid))
        {
        // handle legacy view state
        CPbk2ViewStateTransformer* transformer =
            CPbk2ViewStateTransformer::NewLC( iContactManager );
        viewState = transformer->
                TransformLegacyViewStateToPbk2ViewStateLC( aCustomMessage );
        CleanupStack::Pop();
        CleanupStack::PopAndDestroy(transformer);
        }
    else if (aCustomMessageId == CPbk2ViewState::Uid())
        {
        // Read the desired UI state from aCustomMessage
        viewState = CPbk2ViewState::NewL(aCustomMessage);
        }
    else
        {
        // a parameter must be passed to this view
        User::Leave(KErrNotSupported);
        }

    if (iControlState)
        {
        // Merge parameter view state with the stored state
        if ( viewState->FocusedContact() &&
            !viewState->FocusedContact()->IsSame
                ( *iControlState->FocusedContact() ))
            {
            iControlState->SetFocusedContact(
                    viewState->TakeFocusedContact());
            iControlState->SetFocusedFieldIndex(KErrNotFound);
            iControlState->SetTopFieldIndex(KErrNotFound);
            }
        if (viewState->FocusedFieldIndex() >= 0)
            {
            iControlState->SetFocusedFieldIndex(
                    viewState->FocusedFieldIndex());
            }
        if (viewState->TopFieldIndex() >= 0)
            {
            iControlState->SetTopFieldIndex(
                    viewState->TopFieldIndex());
            }
        if ( viewState->ParentContact() )
            {
            iControlState->SetParentContact(
                viewState->TakeParentContact());
            }
        // Delete parameter view state
        delete viewState;
        }
    else
        {
        // No stored state, use the parameter supplied one
        iControlState = viewState;
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::SetNavigatorViewL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::SetNavigatorViewL()
    {
    __ASSERT_DEBUG(iNavigation,
        Panic(EPanicPreCond_SetNavigatorViewL));

    // Set default navigation
    iNavigation->SetScrollViewL( iContactView, EFalse );

    // Inspect if the parent contact is set and if the parent
    // contact is expandable. In that case set the navigation
    // view to the expandable view.
    const MVPbkContactLink* parentLink = iControlState->ParentContact();
    if ( parentLink )
        {
        // Find parent index in the contact view
        const TInt parentIndex =
            iContactView->IndexOfLinkL( *parentLink );
        // Get the view contact by view index
        const MVPbkViewContact& viewContact =
            iContactView->ContactAtL( parentIndex );

        // Expand the scroll view from the view contact
        MVPbkExpandable* expandable = viewContact.Expandable();
        if ( expandable )
            {
            MVPbkContactViewBase* scrollView = expandable->ExpandLC
                ( *iNavigation, Pbk2AppUi()->ApplicationServices().
                    SortOrderManager().SortOrder() );
            CleanupStack::Pop(); // scrollView

            // Set the navigation scroll view, transfer ownership
            iNavigation->SetScrollViewL( scrollView, ETrue );
            }
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::StoreStateL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::StoreStateL()
    {
    CPbk2ViewState* state = ViewStateLC();
    CleanupStack::Pop(state);

    // state should be always created, but valid state
    // has focusedContact
    if ( state && state->FocusedContact() )
        {
        delete iControlState;
        iControlState = state;
        }
    else
        {
        delete state;
        state = NULL;
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::IsFocusedFieldTypeL
// --------------------------------------------------------------------------
//
TBool CPbk2ContactInfoAppView::IsFocusedFieldTypeL( TInt aSelectorResId )
    {
    TPbk2StoreContactAnalyzer analyzer( iContactManager, NULL );
    const MVPbkBaseContactField* field = iContainer->Control()->FocusedField();

    if ( field )
        {
        return analyzer.IsFieldTypeIncludedL( *field, aSelectorResId );
        }
    else
        {
        return EFalse;
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::UpdateCbasL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::UpdateCbasL()
    {
    if ( iControl )
        {
        // Set cba command set "Options - Context Menu - Back"
        Cba()->SetCommandSetL( R_PBK2_SOFTKEYS_OPTIONS_BACK_CONTEXT );
        Cba()->DrawDeferred();
        // Set context menu
        MenuBar()->SetContextMenuTitleResourceId
            ( R_PHONEBOOK2_CONTACTINFO_CONTEXTBAR );
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::AttachAIWProvidersL
// --------------------------------------------------------------------------
//
inline void CPbk2ContactInfoAppView::AttachAIWProvidersL()
    {
        iCommandHandler->RegisterAiwInterestL
            ( KAiwCmdCall, R_PHONEBOOK2_CALL_MENU,
            R_PHONEBOOK2_CALLUI_AIW_INTEREST, ETrue );
    
        iCommandHandler->RegisterAiwInterestL
            (KAiwCmdCall, R_PHONEBOOK2_CALL_CONTEXT_MENU,
            R_PHONEBOOK2_CALLUI_AIW_INTEREST, EFalse);
    
        iCommandHandler->RegisterAiwInterestL
            ( KAiwCmdPoC, R_PHONEBOOK2_POC_MENU,
            R_PHONEBOOK2_POCUI_AIW_INTEREST, ETrue );
    
        iCommandHandler->RegisterAiwInterestL
            (KAiwCmdPoC, R_PHONEBOOK2_POC_CONTEXT_MENU,
            R_PHONEBOOK2_POCUI_AIW_INTEREST, EFalse);
    
        iCommandHandler->RegisterAiwInterestL
            (KAiwCmdInfoView, R_PHONEBOOK2_SIND_INFOVIEW_MENU,
            R_PHONEBOOK2_SIND_INFOVIEW_AIW_INTEREST, EFalse);
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::HandleLongTapEventL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::HandleLongTapEventL
        ( const TPoint& /*aPenEventLocation*/,
          const TPoint& /*aPenEventScreenLocation*/ )
    {
    // Do nothing
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::CurrentContactInNavigatorLC
// --------------------------------------------------------------------------
//
MVPbkContactLink* CPbk2ContactInfoAppView::CurrentContactInNavigatorLC()
    {
    if ( iNavigation )
        {
        return iNavigation->CurrentContactLC();
        }
    else
        {
        MVPbkContactLink* link = NULL;
        // LC semantics also in NULL case.
        CleanupStack::PushL( link );
        return link;
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ReturnToPreviousViewL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::ReturnToPreviousViewL
        ( MVPbkContactLink* aFocusedContact ) const
    {
    // Ownership of aFocusedContact is taken by this function
    CleanupDeletePushL( aFocusedContact );

    CPbk2ViewState* state = ViewStateLC();
    CleanupStack::Pop( state );

    // aFocusedContact contact overwrites the focused contact from control's
    // state.
    if ( aFocusedContact )
        {
        // state takes the ownership if aFocusedContact
        state->SetFocusedContact( aFocusedContact );
        CleanupStack::Pop(); // aFocusedContact
        }
    else
        {
        CleanupStack::PopAndDestroy(); // aFocusedContact
        }

    CleanupStack::PushL( state );

    Pbk2AppUi()->Pbk2ViewExplorer()->ActivatePreviousViewL( state );
    CleanupStack::PopAndDestroy( state );
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::LoadContactViewL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::LoadContactViewL
        ( const TVwsViewId& aPrevViewId )
    {
    delete iViewLoader;
    iViewLoader = NULL;

    if ( Pbk2AppUi()->Pbk2ViewExplorer()->
            IsPhonebook2View( aPrevViewId ) &&
            ( aPrevViewId.iViewUid == TUid::Uid
                ( EPbk2GroupMembersListViewId ) ) )
        {
        iContactView = Phonebook2::Pbk2AppUi()->ApplicationServices().
                ViewSupplier().AllGroupsViewL();
        }
    else
        {
        iContactView = Phonebook2::Pbk2AppUi()->ApplicationServices().
                ViewSupplier().AllContactsViewL();
        }

    iViewLoader = CPbk2ViewLoader::NewL( *iContactView, *this );
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::HandleViewLoadedL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::HandleViewLoadedL()
    {
    SetNavigatorViewL();
    LoadContactL();
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::LoadContactL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::LoadContactL()
    {
    const MVPbkContactLink* link = iControlState->FocusedContact();
    __ASSERT_DEBUG( link, Panic( EPanicLogic_LoadContactL ) );
    __ASSERT_DEBUG( iContactLoader, Panic( EPanicLogic_LoadContactL ) );

    //ChangeContact can delete iControlState, invalidating link
    //therefore copy link
    MVPbkContactLink* inputParameterContact = link->CloneLC();
    // Load the contact from view state, this is asynchronous
    iContactLoader->ChangeContactL( *inputParameterContact );
    CleanupStack::PopAndDestroy(); //inputParameterContact 
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::ConstructNavigatorL
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::ConstructNavigatorL()
    {
    iStoreList.Reset();
    CVPbkContactStoreUriArray* uriList =
        Pbk2AppUi()->ApplicationServices().StoreConfiguration().
            CurrentConfigurationL();
    CleanupStack::PushL( uriList );
    MVPbkContactStoreList& fullStoreList =
        iContactManager.ContactStoresL();
    for (TInt i = 0; i < uriList->Count(); ++i)
        {
        // Add all the contact stores to the store list
        TVPbkContactStoreUriPtr uri = (*uriList)[i];
        MVPbkContactStore* store = fullStoreList.Find(uri);
        iStoreList.AppendL(store);
        }
    CleanupStack::PopAndDestroy( uriList );

    /// Create contact loader and contact info scroll navigator
    delete iContactLoader;
    iContactLoader = NULL;
    iContactLoader = CPbk2MemoryEntryContactLoader::NewL( *this );

    MVPbkContactStore& storeFromState =
        iControlState->FocusedContact()->ContactStore();
    TBool storeNotInConfiguration = EFalse;
    if ( iStoreList.Find( &storeFromState ) == KErrNotFound )
        {
        storeNotInConfiguration = ETrue;
        // Do not add store into list, opening of this lone
        // store is not navigator's responsibility
        }

    delete iNavigation;
    iNavigation = NULL;
    
    if ( !storeNotInConfiguration )
        {
        iNavigation = Pbk2NavigatorFactory::CreateContactNavigatorL
            ( Id(), *this, *iContactLoader, iStoreList.Array(),
              R_QTN_PHOB_NAVI_POS_INDICATOR_CONTACT_INFO_VIEW );
        }
    else
        {
        // Store was not in configuration --> contact to be shown is not
        // included in the scroll view --> no point to use sideways
        // navigation strategy
        iNavigation = Pbk2NavigatorFactory::CreateVoidNavigatorL
            ( Id(), *this, *iContactLoader, iStoreList.Array() );
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::UpdateViewGraphL
// Sets previous view node. Previous node should be set dynamically
// because it could be some extension view.
// Default is names list view.
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::UpdateViewGraphL
        ( const TVwsViewId& aPrevViewId )
    {
    CPbk2ViewGraph& viewGraph = static_cast<CPbk2ViewExplorer*>
        ( Pbk2AppUi()->Pbk2ViewExplorer() )->ViewGraph();
    CPbk2ViewNode* prevNode =
        viewGraph.FindNodeWithViewId( aPrevViewId.iViewUid );
    if ( prevNode )
        {
        CPbk2ViewNode* thisNode = viewGraph.FindNodeWithViewId( Id() );
        if ( thisNode )
            {
            thisNode->SetPreviousNode( prevNode );
            }
        }
    }

// --------------------------------------------------------------------------
// CPbk2ContactInfoAppView::SetEmptyTextL
// Sets empty text for contact info list box from given resource id.
// --------------------------------------------------------------------------
//
void CPbk2ContactInfoAppView::SetEmptyTextL(
		TInt aResourceId )
	{
    HBufC* emptyText = StringLoader::LoadLC( aResourceId );
    iContainer->Control()->SetTextL( *emptyText );
    CleanupStack::PopAndDestroy( emptyText );
	}


// End of File