phonebookui/Phonebook/App/src/CPbkContactInfoAppView.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook/App/src/CPbkContactInfoAppView.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1536 @@
+/*
+* Copyright (c) 2002 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: 
+*       Provides Contact Info App View class methods.
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPbkContactInfoAppView.h"  // This class' declaration
+
+#include <eikmenub.h> // CEikMenuBar
+#include <AknNoteWrappers.h>
+#include <FeatMgr.h>
+#include <StringLoader.h>
+#include <PbkUID.h>
+
+// Phonebook.app include files
+#include <Phonebook.rsg>
+#include <PbkView.rsg>
+
+// Phone include files
+#include <SpdiaControl.h>
+
+// Send UI
+#include <sendui.h>
+#include <sendnorm.rsg>
+#include <SendUiConsts.h>
+#include <CMessageData.h>
+
+// AIW
+#include <AiwCommon.hrh>
+
+// Clipboard
+#include <baclipb.h>
+
+// PbkEng.dll include files
+#include <CPbkContactEngine.h>
+#include <CPbkFieldInfo.h>
+#include <CPbkContactItem.h>
+#include <PbkCommandHandler.h>
+#include <CPbkFieldsInfo.h>
+#include <PbkFields.hrh>
+
+// PbkUi.dll include files
+#include <MPbkCommand.h>
+#include <MPbkCommandFactory.h>
+#include <CPbkAiwInterestArray.h>
+#include <MenuFilteringFlags.h>
+
+// PbkView.dll classes
+#include <CPbkContactInfoControl.h>
+#include <CPbkMemoryEntryDefaultsDlg.h>
+#include <CPbkViewState.h>
+#include <CPbkPhoneNumberSelect.h>
+#include <CPbkContactEditorDlg.h>
+#include <CPbkRingingToneFetch.h>
+#include <CPbkPrependDlg.h>
+#include <CPbkFFSCheck.h>
+
+// PbkExtension classes
+#include <CPbkExtGlobals.h>
+#include <MPbkExtensionFactory.h>
+#include <MPbkViewExtension.h>
+#include <cshelp/phob.hlp.hrh>
+
+// Postcard Uid
+#include <SendUiConsts.h>
+
+// Phonebook.app include files
+#include <CPbkControlContainer.h>
+#include "CPbkAppUi.h"
+#include "CPbkAppGlobals.h"
+#include "CPbkDocument.h"
+#include "MPbkContactInfoNavigationStrategy.h"
+#include "PbkContactInfoNavigationStrategyFactory.h"
+#include <pbkconfig.hrh>
+#include "CPbkCodImageCmd.h"
+
+// Debugging headers
+#include <pbkdebug.h>
+#include "PbkProfiling.h"
+
+/// Unnamed namespace for local definitions
+namespace {
+
+// LOCAL CONSTANTS AND MACROS
+
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    EPanicPostCond_DoActivateL = 1,
+    EPanicPostCond_DoDeactivate,
+    EPanicPreCond_HandleCommandL,
+    EPanicPreCond_ConstructL,
+    EPanicPostCond_ConstructL,
+    EPanicPreCond_CmdSpeedDialL,
+    EPanicPreCond_CmdWriteToContactL,
+    EPanicPreCond_CmdEditMeL,
+    EPanicPostCond_CmdEditMeL,
+    EPanicPreCond_CmdRemoveSpeedDialL, // 10
+    EPanicPreCond_DynInitMenuPaneL,
+    EPanicIcon_StatusPaneUpdateL,
+    EPanicPreCond_HandleCommandKeyL,
+    EPanicPreCond_CmdRemoveCodL,
+    EPanicPreCond_CmdAddCodFieldL,
+    EPanicFieldInfoNotFound_CmdAddCodFieldL,
+    EPanicImageStorageNotFound_CmdAddCodFieldL,
+    EPanicPreCond_CmdEditTextCodFieldL,
+    EPanicFieldInfoNotFound_HandleCodTextChangeL,
+    EPanicTextStorageNotFound_HandleCodTextChangeL
+    };
+#endif // _DEBUG
+
+
+// ==================== LOCAL FUNCTIONS ====================
+
+#ifdef _DEBUG
+void Panic(TPanicCode aReason)
+    {
+    _LIT(KPanicText, "CPbkContactInfoAppView");
+    User::Panic(KPanicText, aReason);
+    }
+#endif // _DEBUG
+
+}  // namespace
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+inline CPbkContactInfoAppView::CPbkContactInfoAppView()
+    {
+    }
+
+inline void CPbkContactInfoAppView::ConstructL()
+    {
+    // PreCond
+     __ASSERT_DEBUG(!iContainer && !iViewState,
+        Panic(EPanicPreCond_ConstructL));
+
+    // Init base class
+    __PBK_PROFILE_START(PbkProfiling::EViewBaseConstruct);
+    BaseConstructL(R_PBK_CONTACTINFO_APPVIEW);
+    __PBK_PROFILE_END(PbkProfiling::EViewBaseConstruct);
+
+    iExtGlobal = CPbkExtGlobals::InstanceL();
+
+    // Create AIW interest array for call
+    CreateInterestItemAndAttachL(KAiwCmdCall,
+        R_PHONEBOOK_CALL_MENU, R_PHONEBOOK_CALLUI_AIW_INTEREST, ETrue);
+    // The last parameter is false, since KAiwCmdCall is already attached
+    // to base services above
+    CreateInterestItemAndAttachL(KAiwCmdCall,
+        R_PHONEBOOK_CALL_CONTEXT_MENU, R_PHONEBOOK_CALLUI_AIW_INTEREST, EFalse);
+
+    // Create AIW interest array for PoC
+    CreateInterestItemAndAttachL(KAiwCmdPoC,
+        R_PHONEBOOK_POC_MENU, R_PHONEBOOK_POCUI_AIW_INTEREST, ETrue);
+    // The last parameter is false, since KAiwCmdPoC is already attached
+    // to base services above
+    CreateInterestItemAndAttachL(KAiwCmdPoC,
+        R_PHONEBOOK_POC_CONTEXT_MENU, R_PHONEBOOK_POCUI_AIW_INTEREST, EFalse);
+
+    // FFS checker
+    iPbkFFSCheck = CPbkFFSCheck::NewL();
+
+    // PostCond
+     __ASSERT_DEBUG(!iContainer && !iContactItem && !iViewState,
+        Panic(EPanicPostCond_ConstructL));
+    }
+
+CPbkContactInfoAppView* CPbkContactInfoAppView::NewL()
+    {
+    CPbkContactInfoAppView* self = new(ELeave) CPbkContactInfoAppView();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();  // self
+    return self;
+    }
+
+CPbkContactInfoAppView::~CPbkContactInfoAppView()
+    {
+    if (iContainer)
+        {
+        // Remove the container from the view stack
+        AppUi()->RemoveFromViewStack(*this, iContainer);
+        // Destroy the control container
+        delete iContainer;
+        }
+    delete iUpdateContact;
+    delete iContactItem;
+    delete iViewState;
+    delete iNaviStrategy;
+    Release(iViewExtension);
+    Release(iExtGlobal);
+    delete iPbkCodImageCmd;
+    delete iPbkFFSCheck;
+    }
+
+/**
+ * Command handler: Opens the context sensive menu.
+ */
+void CPbkContactInfoAppView::CmdContextMenuL()
+    {
+    LaunchPopupMenuL(R_PBK_CONTACTINFO_CONTEXTBAR);
+    }
+
+/**
+ * Command handler: Edit contact.
+ */
+void CPbkContactInfoAppView::CmdEditMeL()
+    {
+    __ASSERT_DEBUG(
+        iContainer && iContainer->Control() && iContactItem,
+        Panic(EPanicPreCond_CmdEditMeL));
+    CPbkContactInfoControl* control = iContainer->Control();
+
+    // Find focused field's index in contact item
+    const TPbkContactItemField* field = control->CurrentField();
+    const TInt fieldIndex = field ?
+        iContactItem->FindFieldIndex(*field) : KErrNotFound;
+
+    // Store the view state
+    delete iViewState;
+    iViewState = NULL;
+    iViewState = iContainer->Control()->GetStateL();
+
+    // Open contact for editing
+    CPbkContactItem* ci = Engine()->OpenContactLCX(iContactItem->Id());
+
+    // Run the editor dialog
+    CPbkContactEditorDlg* editorDlg = CPbkContactEditorDlg::NewL
+        (*Engine(), *ci, EFalse, fieldIndex);
+    editorDlg->SetExitCommandId(EPbkCmdExit);
+
+    control->HideThumbnail();
+    iSavedId = KNullContactId;
+    iContainer->SetFocusing( EFalse );
+    iContainer->CoeControl()->SetFocusing( EFalse );
+    TRAPD( err, iSavedId = editorDlg->ExecuteLD() );
+    iContainer->SetFocusing( ETrue );
+    iContainer->CoeControl()->SetFocusing( ETrue );
+    control->ShowThumbnailL();
+    User::LeaveIfError( err );
+
+    CleanupStack::PopAndDestroy(2);  // lock, ci
+
+    // delay update so that if desctruction of phonebook
+    // has caused stopping of editor execution, no update is done
+    // if this is deleted.
+    delete iUpdateContact;
+    iUpdateContact = NULL;
+    iUpdateContact = CIdle::NewL(CActive::EPriorityIdle);
+
+    TCallBack callBack( UpdateContact,this );
+    iUpdateContact->Start( callBack );
+    }
+
+TInt CPbkContactInfoAppView::UpdateContact(TAny* aPbkContactInfoAppView)
+    {
+    return static_cast<CPbkContactInfoAppView*>(aPbkContactInfoAppView)->DoUpdateContact();
+    }
+
+TInt CPbkContactInfoAppView::DoUpdateContact()
+    {
+    CPbkContactInfoControl* control = NULL;
+    if( iContainer )
+        {
+        control = iContainer->Control();
+        }
+
+    if ( !iExitInProgress && control )
+        {
+        CPbkContactInfoControl* control = iContainer->Control();
+        if (iSavedId != KNullContactId)
+            {
+            // Reload contact and update UI control. Do this manually here instead
+            // of in HandleDatabaseEventL() because editor dialog restores previous
+            // text into title pane which would be wrong in this case.
+            CPbkContactItem* ci = NULL;
+            TRAPD( err, ci = Engine()->ReadContactL(iSavedId) );
+            if ( err == KErrNone )
+                {
+                TRAP( err, control->UpdateL(ci));
+                if ( err == KErrNone )
+                    {
+                    delete iContactItem;
+                    iContactItem = ci;
+                    if ( iViewState )
+                        {
+                        // Restore UI control state, no harm done
+                        // if this fails, focus just changes
+                        TRAP_IGNORE( iContainer->Control()->RestoreStateL(iViewState) );
+                        // Delete the view state object to save memory
+                        delete iViewState;
+                        iViewState = NULL;
+                        }
+                    control->DrawNow();
+                    }
+                else
+                    {
+                    delete ci;
+                    }
+                }
+            if ( err != KErrNone )
+                {
+                iContainer->ControlEnv()->HandleError( err );
+                }
+            }
+        else
+            {
+            // It is just thumbnail, we can manage if that fails to show
+            TRAP_IGNORE( control->ShowThumbnailL() );
+            }
+
+        __ASSERT_DEBUG(
+            iContainer && iContainer->Control() && iContactItem,
+            Panic(EPanicPostCond_CmdEditMeL));
+        }
+    // Stop idle callback
+    return KErrNone;
+    }
+
+/**
+ * Command handler: Default settings.
+ */
+void CPbkContactInfoAppView::CmdDefaultSettingsL()
+    {
+    CPbkContactInfoControl* control = iContainer->Control();
+    control->HideThumbnail();
+    CPbkMemoryEntryDefaultsDlg* memoryEntryDefaultsDlg =
+        CPbkMemoryEntryDefaultsDlg::NewL(iContactItem->Id(), *Engine());
+    memoryEntryDefaultsDlg->ExecuteLD();
+    control->ShowThumbnailL();
+    }
+
+/**
+ * Command handler: Assign a speed dial to a phone number.
+ */
+void CPbkContactInfoAppView::CmdAssignSpeedDialL()
+    {
+    //PreCond:
+    __ASSERT_DEBUG(iContainer->Control()->FieldCount() > 0,
+        Panic(EPanicPreCond_CmdSpeedDialL));
+
+    TInt fieldId = iContainer->Control()->CurrentFieldIndex();
+
+    CSpdiaControl* speedDialDlg = CSpdiaControl::NewL();
+    if (speedDialDlg->ExecuteLD(iContactItem->Id(), fieldId) && !iExitInProgress)
+        {
+        // this can removed when CContactDatabase::SetSpeedDialField sends notifications
+        CPbkContactItem* ci = Engine()->ReadContactLC(iContactItem->Id());
+        // Update the UI control
+        TInt focus = iContainer->Control()->ListBox().CurrentItemIndex();
+        iContainer->Control()->UpdateL(ci);
+        if (focus > 0 && focus < iContainer->Control()->FieldCount())
+            {
+            iContainer->Control()->ListBox().SetCurrentItemIndex(focus);
+            }
+        // Update member
+        delete iContactItem;
+        CleanupStack::Pop(ci);
+        iContactItem = ci;
+        iContainer->Control()->DrawNow();
+        }
+    }
+
+/**
+ * Command handler: Removes a speed dial from a phone number.
+ */
+void CPbkContactInfoAppView::CmdRemoveSpeedDialL()
+    {
+    //PreCond:
+    __ASSERT_DEBUG(iContainer->Control()->FieldCount() > 0,
+        Panic(EPanicPreCond_CmdRemoveSpeedDialL));
+
+    CSpdiaControl* speedDialDlg = CSpdiaControl::NewL();
+    CleanupStack::PushL( speedDialDlg );
+
+    CArrayFix<TInt>* speedDialIndexes =
+        iContainer->Control()->CurrentField()->SpeedDialIndexesL();
+    if (speedDialIndexes)
+        {
+        CleanupStack::PushL(speedDialIndexes);
+        for (TInt i = 0; i < speedDialIndexes->Count(); ++i)
+            {
+            speedDialDlg->RemoveDialIndexL(
+                    speedDialDlg->Index( (*speedDialIndexes)[i] ) );
+            }
+        CleanupStack::PopAndDestroy(speedDialIndexes);
+        }
+
+    CleanupStack::PopAndDestroy( speedDialDlg );
+
+    // This can removed when CContactDatabase::RemoveSpeedDialFieldL sends notifications
+    CPbkContactItem* ci = Engine()->ReadContactLC(iContactItem->Id());
+    // Update the UI control
+    TInt focus = iContainer->Control()->ListBox().CurrentItemIndex();
+    iContainer->Control()->UpdateL(ci);
+    if (focus > 0 && focus < iContainer->Control()->FieldCount())
+        {
+        iContainer->Control()->ListBox().SetCurrentItemIndex(focus);
+        }
+    // Update member
+    delete iContactItem;
+    CleanupStack::Pop(ci);
+    iContactItem = ci;
+    iContainer->Control()->DrawNow();
+    }
+
+/**
+ * Command handler: Personal Ringing tone setting
+ */
+void CPbkContactInfoAppView::CmdPersonalRingingToneL()
+    {
+    CPbkRingingToneFetch* toneFetch = CPbkRingingToneFetch::NewL(*Engine());
+    CleanupStack::PushL(toneFetch);
+    TFileName ringingToneFile;
+    TPbkContactItemField* field =
+        iContactItem->FindField(EPbkFieldIdPersonalRingingToneIndication);
+    if (field)
+        {
+        ringingToneFile.Copy(field->Text().Left(ringingToneFile.MaxLength()));
+        }
+    if (toneFetch->FetchRingingToneL(ringingToneFile))
+        {
+        CPbkContactItem* item = Engine()->OpenContactLCX(iContactItem->Id());
+        toneFetch->SetRingingToneL(*item, ringingToneFile);
+
+        // Check disk space before assigning.
+        // If not enough memory then leaves with KErrDiskFull.
+        iPbkFFSCheck->FFSClCheckL();
+
+        Engine()->CommitContactL(*item);
+        CleanupStack::PopAndDestroy(2); // lock, item
+        }
+    CleanupStack::PopAndDestroy(); // toneFetch
+    }
+
+
+void CPbkContactInfoAppView::CmdSendContactL(TPbkSendingParams aParams)
+    {
+    TPbkContactItemField* field = iContainer->Control()->CurrentField();
+
+    // Create the send contact command object
+    MPbkCommand* cmd = CPbkAppGlobalsBase::InstanceL()->
+        CommandFactory().CreateSendContactCmdL(aParams,*Engine(),
+        CPbkAppGlobals::InstanceL()->BCardEngL(*Engine()),
+        iContactItem->Id(), field);
+    // Execute the command
+    cmd->ExecuteLD();
+    }
+
+/**
+ * Command handler: write message to contact
+ */
+void CPbkContactInfoAppView::CmdWriteToContactL(TPbkSendingParams aParams)
+    {
+    __ASSERT_DEBUG(
+        iContainer && iContainer->Control() && iContactItem,
+        Panic(EPanicPreCond_CmdWriteToContactL));
+
+    TPbkContactItemField* currentField = iContainer->Control()->CurrentField();
+
+    // Create the write message command object
+    MPbkCommand* cmd = CPbkAppGlobalsBase::InstanceL()->
+        CommandFactory().CreateSendMultipleMessageCmdL(
+        *Engine(),
+        aParams,
+        iContainer->Control()->MarkedItemsL(),
+        currentField,
+        EFalse);
+    // Execute the command
+    cmd->ExecuteLD();
+    }
+
+
+/**
+ * Command handler: go to URL command.
+ */
+void CPbkContactInfoAppView::CmdGoToURLL()
+    {
+    // Create the go to URL command object
+    MPbkCommand* cmd = CPbkAppGlobalsBase::InstanceL()->
+        CommandFactory().CreateGoToURLCmdL(*iContactItem, NULL);
+    // Execute the command
+    cmd->ExecuteLD();
+    }
+
+/**
+ * Command handler: prepend.
+ */
+void CPbkContactInfoAppView::CmdPrependL()
+    {
+    // Get the Phone number
+    RBuf number;
+    number.CreateL( iContainer->Control()->CurrentField()->FieldInfo().MaxLength() );
+    number.CleanupClosePushL();
+    iContainer->Control()->CurrentField()->GetTextL(number);
+
+    // Convert digits to foreign characters if necessary
+    AknTextUtils::DisplayTextLanguageSpecificNumberConversion(number);
+
+    CPbkPrependDlg* dlg = CPbkPrependDlg::NewL(number);
+    if (dlg->ExecuteLD(R_PBK_PREPEND_QUERY))
+        {
+        // convert digits back from foreign characters to western digits if necessary
+        AknTextUtils::ConvertDigitsTo(number, EDigitTypeWestern);
+
+        // Create a temporary contact
+        CPbkContactItem* tempContact = Engine()->CreateEmptyContactL();
+        CleanupStack::PushL(tempContact);
+
+        // Add the prepended number to it
+        TPbkContactItemField* phoneNumberField =
+            tempContact->AddOrReturnUnusedFieldL(
+                *Engine()->FieldsInfo().Find(
+                iContainer->Control()->CurrentField()->FieldInfo().FieldId()));
+
+        if (phoneNumberField)
+            {
+            phoneNumberField->TextStorage()->SetTextL(number);
+            }
+
+        // Create an array out of the temp contact
+        CContactIdArray* array = CContactIdArray::NewL();
+        CleanupStack::PushL(array);
+        array->AddL(tempContact->Id());
+
+        // Now place a call to the temp contact
+        iAiwInterestArray->HandleCommandL(
+                EPbkCmdCall,
+                *array,
+                phoneNumberField,    // "focused field" in this case
+                KAiwCmdCall);
+
+        CleanupStack::PopAndDestroy(2); // array, tempContact
+        }
+    CleanupStack::PopAndDestroy(); //number
+    }
+
+/**
+ * Command handler: copy number.
+ */
+void CPbkContactInfoAppView::CmdCopyNumberL()
+    {
+    const TInt KBeginning = 0;
+    // Construct a plain text from the number
+    RBuf number;
+    number.CreateL( iContainer->Control()->CurrentField()->FieldInfo().MaxLength() );
+    number.CleanupClosePushL();
+    iContainer->Control()->CurrentField()->GetTextL(number);
+    CPlainText* plainText = CPlainText::NewL();
+    CleanupStack::PushL(plainText);
+    plainText->InsertL(KBeginning, number);
+
+    // Copy to clipboard
+    CClipboard* cb = CClipboard::NewForWritingLC(Engine()->FsSession());
+    plainText->CopyToStoreL(cb->Store(), cb->StreamDictionary(),
+        KBeginning, plainText->DocumentLength());
+    cb->CommitL();
+
+    CleanupStack::PopAndDestroy(2); // cb, plainText
+
+    // Show a note
+    HBufC* prompt = StringLoader::LoadLC(R_QTN_LOGS_NOTE_COPY_DONE);
+    CAknInformationNote* dlg = new(ELeave) CAknInformationNote(ETrue);
+    dlg->ExecuteLD(*prompt);
+    CleanupStack::PopAndDestroy(); // prompt
+    CleanupStack::PopAndDestroy(); //number
+    }
+
+void CPbkContactInfoAppView::ContactChangedL()
+    {
+    // if end key has been pressed, do not update the contact
+    // infromation in info control.
+    if (!iExitInProgress)
+        {
+        ChangeContactL(iContactItem->Id());
+        }
+    }
+
+CPbkContactItem* CPbkContactInfoAppView::ContactItemL()
+    {
+    return iContactItem;
+    }
+
+TContactItemId CPbkContactInfoAppView::ContactItemId()
+    {
+    return iContactItem->Id();
+    }
+
+TBool CPbkContactInfoAppView::HandleCommandKeyL
+        (const TKeyEvent& aKeyEvent,
+        TEventCode aType)
+    {
+    __ASSERT_DEBUG(iContainer && iContactItem && iNaviStrategy,
+                   Panic(EPanicPreCond_HandleCommandKeyL));
+
+    // Pass the key to the strategy
+    TBool ret = iNaviStrategy->HandleCommandKeyL(aKeyEvent, aType);
+    if (!ret)
+        {
+        // Check was it send key press
+        if (aKeyEvent.iCode == EKeyPhoneSend)
+            {
+            HandleCommandL(EPbkCmdCall);
+            ret = ETrue;
+            }
+        else if (aKeyEvent.iCode == EKeyPoC)
+            {
+            HandleCommandL(EPbkCmdPoc);
+            ret = ETrue;
+            }
+        else
+            {
+            // Pass the key event to base class
+            ret = CPbkMemoryEntryAppView::HandleCommandKeyL(aKeyEvent, aType);
+            }
+        }
+    return ret;
+    }
+
+CPbkViewState* CPbkContactInfoAppView::GetViewStateLC() const
+    {
+    return iContainer ? iContainer->Control()->GetStateLC() : NULL;
+    }
+
+void CPbkContactInfoAppView::HandleCommandL
+        (TInt aCommandId)
+    {
+    // PreCond: (this is the precond for all Cmd* functions at the same time)
+    __ASSERT_DEBUG(iContainer && iContactItem && iViewExtension,
+                   Panic(EPanicPreCond_HandleCommandL));
+
+    TInt serviceCmdId = KNullHandle;
+    if (aCommandId == EPbkCmdCall)
+        {
+        serviceCmdId = KAiwCmdCall;
+        }
+    else if (aCommandId == EPbkCmdPoc)
+        {
+        serviceCmdId = KAiwCmdPoC;
+        }
+
+    // Offer the command first to AIW
+    if (iAiwInterestArray->HandleCommandL(
+            aCommandId,
+            iContainer->Control()->MarkedItemsL(),
+            iContainer->Control()->FocusedField(),
+            serviceCmdId))
+        {
+        return;
+        }
+
+
+    // And then to the extension
+    if (iViewExtension->HandleCommandL(aCommandId))
+        {
+        return;
+        }
+
+    // Process view-specific commands
+    switch (aCommandId)
+        {
+        case EPbkCmdContextMenu:
+            {
+            CmdContextMenuL();
+            break;
+            }
+
+        case EPbkCmdEditMe:
+            {
+            PbkAppUi()->FFSClCheckL(PbkCommandHandler(this,
+                &CPbkContactInfoAppView::CmdEditMeL));
+            UpdateUrlFieldInfo();
+            break;
+            }
+
+        case EPbkCmdDefaultSettings:
+            {
+            PbkAppUi()->FFSClCheckL(PbkCommandHandler(this,
+                &CPbkContactInfoAppView::CmdDefaultSettingsL));
+            break;
+            }
+
+        case EPbkCmdAssignSpeedDial:
+            {
+            PbkAppUi()->FFSClCheckL(PbkCommandHandler(this,
+                &CPbkContactInfoAppView::CmdAssignSpeedDialL));
+            break;
+            }
+
+        case EPbkCmdRemoveSpeedDial:
+            {
+            CmdRemoveSpeedDialL();
+            break;
+            }
+
+        case EPbkCmdPersonalRingingTone:
+            {
+            PbkAppUi()->FFSClCheckL(PbkCommandHandler(this,
+                &CPbkContactInfoAppView::CmdPersonalRingingToneL));
+            break;
+            }
+
+        case EPbkCmdGoToURL:
+            {
+            CmdGoToURLL();
+            break;
+            }
+
+        case EPbkCmdPrepend:
+            {
+            CmdPrependL();
+            break;
+            }
+
+        case EPbkCmdCopyNumber:
+            {
+            CmdCopyNumberL();
+            break;
+            }
+        case EPbkCmdWrite:
+            {
+            TPbkSendingParams params = CreateWriteParamsLC();
+            PbkAppUi()->FFSClCheckL(PbkCommandHandler(this,
+                &CPbkContactInfoAppView::CmdWriteToContactL,
+                params));
+            CleanupStack::PopAndDestroy(); //mtmFilter
+            break;
+            }
+        case EPbkCmdSendUICommand:
+            {
+            TPbkSendingParams params = CreateSendParamsLC();
+            CmdSendContactL(params);
+            CleanupStack::PopAndDestroy(); //mtmFilter
+            break;
+            }
+        case EPbkCmdCodRemoveObject:
+            {
+            // Only one Cod field exists at a time.
+            // By callig both functions the existing field
+            // will be deleted
+            CmdRemoveCodL( EPbkFieldIdCodTextID );
+            CmdRemoveCodL( EPbkFieldIdCodImageID );
+            break;
+            }
+        // Following methods need critical level check of memory
+        case EPbkCmdCodAddObjectText:
+        case EPbkCmdCodAddObjectImage:
+            {
+            CmdAddCodFieldL( aCommandId );
+            break;
+            }
+        case EPbkCmdCodEditText:
+            {
+            CmdEditTextCodFieldL();
+            break;
+            }
+        case EPbkCmdCodViewImage:
+            {
+            CmdViewCodImageL();
+            break;
+            }
+        case EPbkCmdCodChangeImage:
+            {
+            CmdAddCodFieldL(EPbkCmdCodAddObjectImage);
+            break;
+            }
+        case EPbkCmdCodAddObjectSubMenu:
+            {
+            break;
+            }
+        case EPbkCmdExit:
+            {
+            // Turn up the iExitInProgress flag to avoid unwanted
+            // contact redraw in exit case. This happens if the editor
+            // dialog is running while exit should be executed.
+            iExitInProgress = ETrue;
+            // fall through to default handler.
+            }
+        default:
+            {
+            CPbkMemoryEntryAppView::HandleCommandL(aCommandId);
+            break;
+            }
+        }
+    }
+
+void CPbkContactInfoAppView::DynInitMenuPaneL
+        (TInt aResourceId,
+        CEikMenuPane* aMenuPane)
+    {
+    __ASSERT_DEBUG(iContainer && iViewExtension,
+        Panic(EPanicPreCond_DynInitMenuPaneL));
+
+    TUint flags = KPbkInfoView;
+    if (iContainer->Control()->FieldCount() == 0)
+        {
+        flags |= KPbkControlEmpty;
+        }
+
+    TPbkContactItemField* currentField =
+        iContainer->Control()->CurrentField();
+
+    if (currentField && currentField->FieldInfo().IsPhoneNumberField())
+        {
+        flags |= KPbkCurrentFieldPhoneNumber;
+        }
+
+    if (currentField && currentField->FieldInfo().IsVoipField())
+        {
+        flags |= KPbkCurrentFieldVoipAddress;
+        }
+
+    // The flag KPbkCurrentFieldPoc is valid for using only
+    // in PoC context menu filtering in CPbkAiwInterestItemPoc::InitMenuPaneL
+    if ( currentField )
+        {
+        // We can't use the IsPocField() info here, since context
+        // menu filtering is more strict than that
+        const TPbkFieldId fieldId = currentField->FieldInfo().FieldId();
+        switch ( fieldId )
+            {
+            case EPbkFieldIdVOIP:                   // FALLTHROUGH
+            case EPbkFieldIdPushToTalk:             // FALLTHROUGH
+            case EPbkFieldIdShareView:              // FALLTHROUGH
+            case EPbkFieldIdSIPID:
+                {
+                flags |= KPbkCurrentFieldPoc;
+                }
+            default:
+                {
+                // Do nothing
+                }
+            }
+        }
+
+    // Offer the menu to AIW first
+    if (iAiwInterestArray->InitMenuPaneL(aResourceId, *aMenuPane, flags))
+        {
+        // No need to continue
+        return;
+        }
+
+    iViewExtension->DynInitMenuPaneL(aResourceId, aMenuPane);
+
+    switch (aResourceId)
+        {
+        case R_PBK_CONTACTINFO_OPTIONS_MENU:
+            {
+            OptionsMenuFilteringL(*aMenuPane, flags);
+            break;
+            }
+        case R_PBK_CONTACTINFO_CONTEXT_MENU:
+            {
+            ContextMenuFilteringL(*aMenuPane, flags);
+            break;
+            }
+        case R_PBK_ADD_OBJECT_SUBMENU: // Add object menu item
+            {
+            AddObjectSubPaneMenuFilteringL(*aMenuPane, flags);
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+
+    CPbkMemoryEntryAppView::DynInitMenuPaneL(aResourceId,aMenuPane);
+    }
+
+inline void CPbkContactInfoAppView::OptionsMenuFilteringL
+        (CEikMenuPane& aMenuPane,
+        TUint aFlags)
+    {
+    if ((aFlags & KPbkControlEmpty)
+        || Engine()->IsSpeedDialAssigned(*iContactItem,
+            iContainer->Control()->CurrentFieldIndex()))
+        {
+        aMenuPane.SetItemDimmed(EPbkCmdAssignSpeedDial, ETrue);
+        }
+    else if (FeatureManager::FeatureSupported(KFeatureIdCommonVoip))
+        {
+        if (!iContainer->Control()->CurrentField()->
+            FieldInfo().IsVoipField())
+            {
+            aMenuPane.SetItemDimmed(EPbkCmdAssignSpeedDial, ETrue);
+            }
+        }
+    else
+        {
+        if (!iContainer->Control()->CurrentField()->
+            FieldInfo().IsPhoneNumberField())
+            {
+            aMenuPane.SetItemDimmed(EPbkCmdAssignSpeedDial, ETrue);
+            }
+        }
+
+    if ((aFlags & KPbkControlEmpty) ||
+        !Engine()->IsSpeedDialAssigned(*iContactItem,
+            iContainer->Control()->CurrentFieldIndex()))
+        {
+        // Field is a phone number and speed dial for this field
+        aMenuPane.SetItemDimmed(EPbkCmdRemoveSpeedDial, ETrue);
+        }
+    if ((aFlags & KPbkControlEmpty) || (!iUrlFieldAvailable))
+        {
+        // URL field not present
+        aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue);
+        }
+    if ((aFlags & KPbkControlEmpty) || !(aFlags & KPbkCurrentFieldPhoneNumber))
+        {
+        // Field is not a phone number field
+        aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue);
+        }
+
+    if (aFlags & KPbkControlEmpty)
+        {
+        aMenuPane.SetItemDimmed(EPbkCmdDefaultSettings, ETrue);
+        aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue);
+        aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue);
+        aMenuPane.SetItemDimmed(EPbkCmdSendUICommand, ETrue);
+        }
+    else
+        {
+        aMenuPane.SetItemDimmed(EPbkCmdSendUICommand, EFalse);
+        }
+
+    if (FeatureManager::FeatureSupported(KFeatureIdCallImagetext))
+        {
+        // Empty contact, no fields
+        if( (aFlags & KPbkControlEmpty) )
+            {
+            aMenuPane.SetItemDimmed( EPbkCmdCodEditText, ETrue );
+            aMenuPane.SetItemDimmed( EPbkCmdCodViewImage, ETrue );
+            aMenuPane.SetItemDimmed( EPbkCmdCodChangeImage, ETrue );
+            aMenuPane.SetItemDimmed( EPbkCmdCodRemoveObject, ETrue );
+            }
+        else
+            {
+            TPbkContactItemField* field = iContainer->Control()->CurrentField();
+            const TPbkFieldId pbkFieldId( field->FieldInfo().FieldId() );
+
+            if (pbkFieldId == EPbkFieldIdCodTextID && CodTextFieldEnabled())
+                {
+                if (CodImageFieldEnabled())
+                    {
+                    // Text field contains Cod image filename
+                    aMenuPane.SetItemDimmed( EPbkCmdCodEditText, ETrue );
+                    }
+                else
+                    {
+                    // Text field is used for Cod text purposes
+                    aMenuPane.SetItemDimmed( EPbkCmdCodViewImage, ETrue );
+                    aMenuPane.SetItemDimmed( EPbkCmdCodChangeImage, ETrue );
+                    }
+                }
+            else
+                {
+                // Focus is not on the Object for call field.
+                aMenuPane.SetItemDimmed( EPbkCmdCodEditText, ETrue );
+                aMenuPane.SetItemDimmed( EPbkCmdCodViewImage, ETrue );
+                aMenuPane.SetItemDimmed( EPbkCmdCodChangeImage, ETrue );
+                aMenuPane.SetItemDimmed( EPbkCmdCodRemoveObject, ETrue );
+                }
+            }
+        }
+    else
+        {
+        // Image/text for call feature not supported.
+        // Dimm all related commands
+        aMenuPane.SetItemDimmed( EPbkCmdCodEditText, ETrue);
+        aMenuPane.SetItemDimmed( EPbkCmdCodViewImage, ETrue);
+        aMenuPane.SetItemDimmed( EPbkCmdCodChangeImage, ETrue);
+        aMenuPane.SetItemDimmed( EPbkCmdCodAddObjectSubMenu, ETrue);
+        aMenuPane.SetItemDimmed( EPbkCmdCodRemoveObject, ETrue);
+        }
+
+    }
+
+inline void CPbkContactInfoAppView::ContextMenuFilteringL
+        (CEikMenuPane& aMenuPane,
+        TUint aFlags)
+    {
+    TPbkContactItemField* field = iContainer->Control()->CurrentField();
+
+    // context sensitive menu filtering
+    if (aFlags & KPbkControlEmpty)
+        {
+        aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue);
+        aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue);
+        aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue);
+        aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue);
+        }
+    else if (field)
+        {
+        switch(field->FieldInfo().FieldId())
+            {
+            case EPbkFieldIdPhoneNumberStandard:    // FALLTHROUGH
+            case EPbkFieldIdPhoneNumberHome:        // FALLTHROUGH
+            case EPbkFieldIdPhoneNumberWork:        // FALLTHROUGH
+            case EPbkFieldIdPhoneNumberMobile:      // FALLTHROUGH
+            case EPbkFieldIdPhoneNumberVideo:       // FALLTHROUGH
+            case EPbkFieldIdFaxNumber:              // FALLTHROUGH
+            case EPbkFieldIdAssistantNumber:        // FALLTHROUGH
+            case EPbkFieldIdCarNumber:
+                {
+                aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue);
+                break;
+                }
+            case EPbkFieldIdEmailAddress:
+                {
+                aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue);
+                break;
+                }
+            case EPbkFieldIdPersonalRingingToneIndication:
+                {
+                aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdEditMe, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue);
+                break;
+                }
+            case EPbkFieldIdURL:
+                {
+                aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue);
+                break;
+                }
+            default:
+                {
+                // By default only Edit item is shown
+                aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue);
+                aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue);
+                break;
+                }
+            }
+        }
+    }
+
+TPbkSendingParams CPbkContactInfoAppView::CreateWriteParamsLC()
+    {
+    // Construct the MTM filter
+    CArrayFixFlat<TUid>* mtmFilter =
+        new(ELeave) CArrayFixFlat<TUid>(4);
+    CleanupStack::PushL(mtmFilter);
+
+    if (iContainer->Control()->FieldCount() > 0)
+        {
+        switch(iContainer->Control()->CurrentField()->FieldInfo().FieldId())
+            {
+            case EPbkFieldIdPhoneNumberStandard:    // FALLTHROUGH
+            case EPbkFieldIdPhoneNumberHome:        // FALLTHROUGH
+            case EPbkFieldIdPhoneNumberWork:        // FALLTHROUGH
+            case EPbkFieldIdPhoneNumberMobile:      // FALLTHROUGH
+            case EPbkFieldIdAssistantNumber:        // FALLTHROUGH
+            case EPbkFieldIdCarNumber:
+                {
+                mtmFilter->AppendL(KSenduiMtmSmtpUid); //Email
+                break;
+                }
+            case EPbkFieldIdEmailAddress:
+                {
+                mtmFilter->AppendL(KSenduiMtmSmsUid); //Sms
+                break;
+                }
+            default:
+                break;
+            }
+        }
+
+    TSendingCapabilities capabilities = TSendingCapabilities();
+    capabilities.iFlags = TSendingCapabilities::ESupportsEditor;
+    return TPbkSendingParams( mtmFilter, capabilities );
+    }
+
+TPbkSendingParams CPbkContactInfoAppView::CreateSendParamsLC()
+    {
+    // Construct the MTM filter
+    CArrayFixFlat<TUid>* mtmFilter =
+        new(ELeave) CArrayFixFlat<TUid>(4);
+    CleanupStack::PushL(mtmFilter);
+
+    const TUid KPostcardMtmUid = { KSenduiMtmPostcardUidValue };
+
+    mtmFilter->AppendL(KPostcardMtmUid);    // hide postcard
+    mtmFilter->AppendL(KSenduiMtmAudioMessageUid); // hide audio message
+
+    TSendingCapabilities capabilities = TSendingCapabilities();
+    capabilities.iFlags = TSendingCapabilities::ESupportsBioSending;
+    capabilities.iFlags |= TSendingCapabilities::ESupportsAttachments;
+    return TPbkSendingParams( mtmFilter, capabilities );
+    }
+
+TUid CPbkContactInfoAppView::Id() const
+    {
+    return CPbkAppUi::KPbkContactInfoViewUid;
+    }
+
+void CPbkContactInfoAppView::HandleStatusPaneSizeChange()
+    {
+    // Resize the container to fill the client rectangle
+    if (iContainer)
+        {
+        iContainer->SetRect(ClientRect());
+        }
+    }
+
+void CPbkContactInfoAppView::DoActivateL
+        (const TVwsViewId& aPrevViewId,
+         TUid aCustomMessageId,
+         const TDesC8& aCustomMessage)
+    {
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING
+        ("CPbkContactInfoAppView(%x)::DoActivateL()"), this);
+
+    // reset the exit in progress flag.
+    iExitInProgress = EFalse;
+
+    // Call base class, this must be done!
+    CPbkMemoryEntryAppView::DoActivateL(aPrevViewId,
+        aCustomMessageId, aCustomMessage);
+
+    // Update application-wide state. UI control updates the title pane.
+    CPbkAppUi::CViewActivationTransaction* viewActivationTransaction =
+        PbkAppUi()->HandleViewActivationLC
+            (Id(), aPrevViewId, NULL, NULL,
+            CPbkAppUi::EUpdateNaviPane | CPbkAppUi::EUpdateContextPane);
+
+    if (aCustomMessageId == CPbkViewState::Uid())
+        {
+        // Read the desired UI state from aCustomMessage
+        CPbkViewState* viewState = CPbkViewState::NewL(aCustomMessage);
+        if (iViewState)
+            {
+            // Merge parameter view state with the stored state
+            if (viewState->FocusedContactId() != iViewState->FocusedContactId())
+                {
+                iViewState->SetFocusedContactId(viewState->FocusedContactId());
+                iViewState->SetFocusedFieldIndex(-1);
+                iViewState->SetTopFieldIndex(-1);
+                }
+            if (viewState->FocusedFieldIndex() >= 0)
+                {
+                iViewState->SetFocusedFieldIndex(viewState->FocusedFieldIndex());
+                }
+            if (viewState->TopFieldIndex() >= 0)
+                {
+                iViewState->SetTopFieldIndex(viewState->TopFieldIndex());
+                }
+            if (viewState->ParentContactId() != iViewState->ParentContactId())
+                {
+                iViewState->SetParentContactId(viewState->ParentContactId());
+                }
+            // delete parameter view state
+            delete viewState;
+            }
+        else
+            {
+            // No stored state, use the parameter supplied one
+            iViewState = viewState;
+            }
+        }
+    else
+        {
+        // No UI state specified, restore in previous state
+        if (!iViewState)
+            {
+            // No previous state
+            User::Leave(KErrArgument);
+            }
+        }
+
+    // Read the contact
+    if (!iContactItem || iContactItem->Id() != iViewState->FocusedContactId())
+        {
+        CPbkContactItem* ci = Engine()->ReadContactLC
+            (iViewState->FocusedContactId());
+        if (iContainer && iContainer->Control())
+            {
+            // Change the contact item inside the UI control
+            iContainer->Control()->UpdateL(ci);
+            }
+        delete iContactItem;
+        CleanupStack::Pop();  // ci
+        iContactItem = ci;
+
+        //Check does the contact have an URL field
+        UpdateUrlFieldInfo();
+        }
+
+    if (!iContainer)
+        {
+        // Create the container control
+        iContainer = CContainer::NewL(this, *this);
+
+        iContainer->SetHelpContext(TCoeHelpContext(ApplicationUid(),
+            KPHOB_HLP_CONTACT_INFO_VIEW));
+
+        // Create extension
+        if (!iViewExtension)
+            {
+            iViewExtension =
+                iExtGlobal->FactoryL().CreatePbkViewExtensionL
+                    (Id(), *PbkAppUi()->PbkDocument()->Engine(), *this);
+            }
+
+        // Create the view-side UI control
+        CPbkContactInfoControl* control = CPbkContactInfoControl::NewL
+            (R_PBK_DEFAULT_CONTACTINFO_CONTROL,
+            *iContainer,
+            iContactItem,
+            Engine());
+
+        // Set up the container. iContainer takes ownership of control safely
+        iContainer->SetControl(control, ClientRect());
+        iViewExtension->SetContactUiControl(control);
+        iContainer->ActivateL();
+
+        // create navigation strategy
+        iNaviStrategy = PbkContactInfoNavigationStrategyFactory::CreateL(
+                *Engine(), *this, iViewState->ParentContactId());
+
+        // Add this view and container to the view stack
+        AppUi()->AddToViewStackL(*this, iContainer);
+        }
+
+    // Restore UI control state
+    iContainer->Control()->RestoreStateL(iViewState);
+    // Delete the view state object to save memory
+    delete iViewState;
+    iViewState = NULL;
+
+    // Commit application-wide state changes
+    viewActivationTransaction->Commit();
+    CleanupStack::PopAndDestroy();  // viewActivationTransaction
+
+    // Draw the control
+    iContainer->Control()->DrawNow();
+
+    // PostCond
+    __ASSERT_DEBUG(
+        iContainer && iContainer->Control() &&
+        iContactItem && !iViewState,
+        Panic(EPanicPostCond_DoActivateL));
+    }
+
+void CPbkContactInfoAppView::DoDeactivate()
+    {
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING
+        ("CPbkContactInfoAppView(%x)::DoDeactivate()"), this);
+
+    // Delete any previous view state
+    delete iViewState;
+    iViewState = NULL;
+
+    // delete navigation strategy
+    delete iNaviStrategy;
+    iNaviStrategy = NULL;
+
+    if (iContainer)
+        {
+        if (iContainer->Control())
+            {
+            // Store the view state for next activation
+            TRAP_IGNORE(iViewState = iContainer->Control()->GetStateL());
+            }
+        // Remove view and its control from the view stack
+        AppUi()->RemoveFromViewStack(*this, iContainer);
+        // Destroy the container control
+        delete iContainer;
+        iContainer = NULL;
+        }
+
+    if (iViewExtension)
+        {
+        iViewExtension->SetContactUiControl(NULL);
+        }
+
+    // Delete the contact item
+    delete iContactItem;
+    iContactItem = NULL;
+
+    // Call base class, this must be done!
+    CPbkMemoryEntryAppView::DoDeactivate();
+
+    // PostCond
+    __ASSERT_DEBUG(!iContainer && !iContactItem,
+        Panic(EPanicPostCond_DoDeactivate));
+    }
+
+
+void CPbkContactInfoAppView::UpdateUrlFieldInfo()
+    {
+    iUrlFieldAvailable = EFalse;
+    if (iContactItem->FindField(EPbkFieldIdURL))
+        {
+        iUrlFieldAvailable = ETrue;
+        }
+    }
+
+void CPbkContactInfoAppView::ChangeContactL
+        (TContactItemId aContactId)
+    {
+    // Load the contact
+    CPbkContactItem* ci = Engine()->ReadContactLC(aContactId);
+    // Check if the contact content has changed or the contact
+    // has changed. CPbkContactItem's == operator only compares
+    // fields, therefore the id check has to be done manually.
+    if ((aContactId != iContactItem->Id()) || (*ci != *iContactItem))
+        {
+        // Update the UI control
+        CPbkContactInfoControl* control = iContainer->Control();
+        CPbkViewState* controlState = control->GetStateLC();
+        control->UpdateL(ci);
+        control->RestoreStateL(controlState);
+        CleanupStack::PopAndDestroy(controlState);
+        // Update members
+        delete iContactItem;
+        CleanupStack::Pop(ci);
+        iContactItem = ci;
+        UpdateUrlFieldInfo();
+        control->DrawNow();
+        }
+    else
+        {
+        // Contact data not changed, no need to update
+        CleanupStack::PopAndDestroy();  // ci
+        }
+    }
+
+CEikStatusPane* CPbkContactInfoAppView::GetStatusPane() const
+    {
+    return StatusPane();
+    }
+
+TContactItemId CPbkContactInfoAppView::GetContactItemId() const
+    {
+    return iContactItem->Id();
+    }
+
+void CPbkContactInfoAppView::AddObjectSubPaneMenuFilteringL(
+    CEikMenuPane& aMenuPane, TUint
+    aFlags
+    )
+    {
+    if (FeatureManager::FeatureSupported(KFeatureIdCallImagetext))
+        {
+        // If empty contanct then no more execution needed
+        if (! (aFlags & KPbkControlEmpty) )
+            {
+            if (CodTextFieldEnabled())
+                {
+                if (CodImageFieldEnabled())
+                    {
+                    aMenuPane.SetItemDimmed( EPbkCmdCodAddObjectImage, ETrue );
+                    }
+                else
+                    {
+                    aMenuPane.SetItemDimmed( EPbkCmdCodAddObjectText, ETrue );
+                    }
+                }
+            }
+        }
+    else
+        {
+        aMenuPane.SetItemDimmed( EPbkCmdCodAddObjectImage, ETrue );
+        }
+    }
+
+/**
+ * Command handler: Removes object for call from the contact.
+ */
+void CPbkContactInfoAppView::CmdRemoveCodL(TInt aFieldType)
+    {
+    //PreCond: Field type id should be either Cod image for Cod text.
+    __ASSERT_DEBUG( ( aFieldType == EPbkFieldIdCodTextID ||
+             aFieldType == EPbkFieldIdCodImageID ),
+        Panic(EPanicPreCond_CmdRemoveCodL) );
+
+    TPbkContactItemField* field = iContactItem->FindField( aFieldType );
+    if (field && aFieldType == EPbkFieldIdCodTextID )
+        {
+        CPbkContactItem* ci = Engine()->OpenContactLCX(iContactItem->Id());
+        ci->RemoveField(iContactItem->FindFieldIndex(*field));
+        Engine()->CommitContactL(*ci);
+        // Update member
+        CleanupStack::PopAndDestroy(ci);
+        CleanupStack::PopAndDestroy(); // lock
+        // UI refresh is handled by HandleDatabaseEventL method in base class
+        }
+    else
+        {
+        PbkCodImageCmdL().RemoveImageL(iContactItem->Id());
+        }
+    }
+
+inline void CPbkContactInfoAppView::CmdAddCodFieldL( TInt aCommandId )
+    {
+    __ASSERT_DEBUG( EPbkCmdCodAddObjectImage == aCommandId ||
+        EPbkCmdCodAddObjectText == aCommandId,
+        Panic(EPanicPreCond_CmdAddCodFieldL) );
+    #ifdef _DEBUG
+    TInt fieldId(EPbkCmdCodAddObjectText==aCommandId?
+        EPbkFieldIdCodTextID:EPbkFieldIdCodImageID);
+    // Field info should be found
+    CPbkFieldInfo* fieldInfo = Engine()->FieldsInfo().Find(fieldId);
+    #endif
+    __ASSERT_DEBUG( fieldInfo,
+        Panic(EPanicFieldInfoNotFound_CmdAddCodFieldL) );
+
+    if (aCommandId==EPbkCmdCodAddObjectText)
+        {
+        // Check if Cod image exists.
+        if ( CodTextFieldEnabled() && CodImageFieldEnabled() )
+            {
+            // Reset data.
+            CmdRemoveCodL(EPbkFieldIdCodTextID);
+            CmdRemoveCodL(EPbkFieldIdCodImageID);
+            }
+        HandleCodTextChangeL(iContactItem->Id());
+        }
+    else
+        {
+        HandleCodImageChangeL(iContactItem->Id());
+        }
+    }
+
+inline TBool CPbkContactInfoAppView::HandleCodTextChangeL(TContactItemId aId) const
+    {
+    TBool ret(EFalse);
+
+    // Field info should be found
+    CPbkFieldInfo* fieldInfo = Engine()->FieldsInfo().Find(EPbkFieldIdCodTextID);
+    __ASSERT_DEBUG( fieldInfo,
+        Panic( EPanicFieldInfoNotFound_HandleCodTextChangeL ) );
+
+    CPbkContactItem* ci = Engine()->OpenContactLCX(aId);
+    // Use text field if exists
+    TPbkContactItemField* field = ci->FindField( EPbkFieldIdCodTextID );
+    if (!field)
+        {
+        // Otherwise create new field for filename purposes
+        field = ci->AddOrReturnUnusedFieldL(*fieldInfo);
+        }
+    __ASSERT_DEBUG( field->TextStorage(),
+        Panic(EPanicTextStorageNotFound_HandleCodTextChangeL) );
+
+    HBufC* textToBeModified = HBufC::NewMaxLC(KPbkCodTextMaxLength);
+    CContactTextField& contactTextField = *field->TextStorage();
+    textToBeModified->Des().Copy(contactTextField.Text().Left(KPbkCodTextMaxLength));
+    TPtr ptr = textToBeModified->Des();
+    HBufC* prompt = StringLoader::LoadLC(R_QTN_PHOB_PRTX_TEXT_FOR_CALL);
+    CAknTextQueryDialog* aknTextQueryDialog = CAknTextQueryDialog::NewL(ptr);
+    aknTextQueryDialog->SetMaxLength(KPbkCodTextMaxLength);
+    if (aknTextQueryDialog->ExecuteLD(R_PBK_EDIT_FIELD_TEXT_FOR_QUERY, *prompt))
+        {
+        // The text is set if data query not cancelled
+        contactTextField.SetTextL(*textToBeModified);
+
+        TPbkContactItemField* imageField=ci->FindField(EPbkFieldIdCodImageID);
+        if (imageField)
+            {
+            // Image can not exist if Cod text field is used.
+            ci->RemoveField(ci->FindFieldIndex(*field));
+            }
+        Engine()->CommitContactL(*ci);
+        ret = ETrue;
+        }
+    CleanupStack::PopAndDestroy(4); //textToBeModified, prompt, ci, lock
+
+    return ret;
+    }
+
+inline void CPbkContactInfoAppView::CmdEditTextCodFieldL()
+    {
+    __ASSERT_DEBUG( iContactItem->FindField(EPbkFieldIdCodTextID),
+        Panic(EPanicPreCond_CmdEditTextCodFieldL) );
+    HandleCodTextChangeL(iContactItem->Id());
+    }
+
+inline TBool CPbkContactInfoAppView::HandleCodImageChangeL(TContactItemId aId)
+    {
+    return PbkCodImageCmdL().FetchImageL(aId);
+    }
+
+CPbkCodImageCmd& CPbkContactInfoAppView::PbkCodImageCmdL()
+    {
+    if (!iPbkCodImageCmd)
+        {
+        iPbkCodImageCmd = CPbkCodImageCmd::NewL(*Engine());
+        }
+    return *iPbkCodImageCmd;
+    }
+
+inline void CPbkContactInfoAppView::CmdViewCodImageL()
+    {
+    PbkCodImageCmdL().ViewImageL(iContactItem->Id());
+    }
+
+TBool CPbkContactInfoAppView::CodTextFieldEnabled() const
+    {
+    return iContactItem->FindField(EPbkFieldIdCodTextID)?ETrue:EFalse;
+    }
+
+TBool CPbkContactInfoAppView::CodImageFieldEnabled() const
+    {
+    return iContactItem->FindField(EPbkFieldIdCodImageID)?ETrue:EFalse;
+    }
+
+//  End of File