phonebookui/Phonebook2/Commands/src/CPbk2CommandHandler.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
child 68 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/Commands/src/CPbk2CommandHandler.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,1130 @@
+/*
+* 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 command handler.
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPbk2CommandHandler.h"
+
+// Phonebook 2
+#include "CPbk2CommandFactory.h"
+#include "CPbk2CommandStore.h"
+#include "CPbk2AiwInterestArray.h"
+#include <MPbk2ViewExplorer.h>
+#include <CPbk2AppViewBase.h>
+#include <CPbk2AppUiBase.h>
+#include <CPbk2UIExtensionManager.h>
+#include <MPbk2Command.h>
+#include <Pbk2Commands.rsg>
+#include <Pbk2UIControls.rsg>
+#include <CPbk2ViewState.h>
+#include <CPbk2PhonebookInfoDlg.h>
+#include <TPbk2StoreContactAnalyzer.h>
+#include <MPbk2ContactNameFormatter.h>
+#include <CPbk2StoreProperty.h>
+#include <CPbk2StorePropertyArray.h>
+#include <CPbk2ContactRelocator.h>
+#include <MPbk2ContactLinkIterator.h>
+#include <CPbk2PresentationContact.h>
+#include <CPbk2PresentationContactFieldCollection.h>
+#include <CPbk2FieldPropertyArray.h>
+#include <cpbk2commandactivator.h>
+#include <CPbk2ApplicationServices.h>
+#include <MPbk2AppUi.h>
+
+// Virtual Phonebook
+#include <CVPbkContactManager.h>
+#include <MVPbkStoreContactField.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkContactStoreProperties.h>
+#include <MVPbkContactAttributeManager.h>
+#include <MVPbkContactLinkArray.h>
+#include <MVPbkContactLink.h>
+#include <CVPbkSpeedDialAttribute.h>
+#include <MVPbkStoreContact.h>
+#include <VPbkContactStoreUris.h>
+
+// System includes
+#include <avkon.hrh>
+#include <eikmenup.h>
+#include <featmgr.h>
+#include <hlplch.h>
+#include <akntoolbar.h>
+#include <eikmenub.h>
+
+
+/// Unnamed namespace for local definitions
+namespace {
+
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    EPanicPreCond_CmdOpenMeViewsL = 1,
+    EPanicPreCond_CmdOpenSettingsViewL,
+    EPanicPreCond_CmdOpenPreviousViewL,
+    EPanicPreCond_CmdOpenHelpL,
+    EPanicLogic_FocusedFieldMatchesFieldTypeL,
+    EPanicLogic_FocusedContactHasFieldTypeL
+    };
+
+void Panic(TPanicCode aReason)
+    {
+    _LIT(KPanicText, "CPbk2CommandHandler");
+    User::Panic(KPanicText, aReason);
+    }
+#endif //_DEBUG
+
+/**
+ * Checks if focused field is of given field type.
+ *
+ * @param aUiControl        UI control.
+ * @param aSelectorResId    Selector resource id.
+ * @param aContactManager   Virtual Phonebook contact manager.
+ * @return  ETrue if field type matches with given types.
+ */
+TBool FocusedFieldMatchesFieldTypeL(
+        MPbk2ContactUiControl& aUiControl,
+        TInt aSelectorResId,
+        CVPbkContactManager& aContactManager )
+    {
+    const MVPbkStoreContact* contact = aUiControl.FocusedStoreContact();
+    __ASSERT_DEBUG(contact, Panic
+            ( EPanicLogic_FocusedFieldMatchesFieldTypeL ) );
+
+    TPbk2StoreContactAnalyzer analyzer( aContactManager, NULL );
+    const MVPbkBaseContactField* field = aUiControl.FocusedField();
+    return field &&
+        analyzer.IsFieldTypeIncludedL( *field, aSelectorResId );
+    }
+
+/**
+ * Checks if the focused contact have a given field type.
+ *
+ * @param aUiControl        UI control
+ * @param aSelectorResId    Selector resource id.
+ * @param aContactManager   Virtual Phonebook contact manager.
+ * @return  Index of the field having the type, KErrNotFound if
+ *          the contact does not have the field type.
+ */
+ TInt FocusedContactHasFieldTypeL(
+        MPbk2ContactUiControl& aUiControl,
+        TInt aSelectorResId,
+        CVPbkContactManager& aContactManager )
+    {
+    TInt ret = KErrNotFound;
+    const MVPbkStoreContact* contact = aUiControl.FocusedStoreContact();
+    __ASSERT_DEBUG( contact,
+        Panic( EPanicLogic_FocusedContactHasFieldTypeL ) );
+
+    TPbk2StoreContactAnalyzer analyzer( aContactManager, contact );
+    ret = analyzer.HasFieldL( aSelectorResId );
+    return ret;
+    }
+
+/**
+ * Checks if command is 'exit' command.
+ *
+ * @param aCommandId    The command to check.
+ * @return  ETrue if command is an exit command, EFalse otherwise.
+ */
+TBool IsExitCommand( TInt aCommandId )
+    {
+    TBool ret = EFalse;
+
+    if ( EEikCmdExit == aCommandId || EAknSoftkeyExit == aCommandId ||
+         EAknCmdExit == aCommandId || EPbk2CmdExit == aCommandId )
+        {
+        ret = ETrue;
+        }
+
+    return ret;
+    }
+
+} /// namespace
+
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::CPbk2CommandHandler
+// --------------------------------------------------------------------------
+//
+inline CPbk2CommandHandler::CPbk2CommandHandler()
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::~CPbk2CommandHandler
+// --------------------------------------------------------------------------
+//
+CPbk2CommandHandler::~CPbk2CommandHandler()
+    {
+    delete iAiwInterestArray;
+    delete iCommandStore;
+    delete iCommandFactory;
+    delete iContactRelocator;
+    Release(iExtensionManager);
+    Release(iAppServices);
+    FeatureManager::UnInitializeLib();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::NewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C CPbk2CommandHandler* CPbk2CommandHandler::NewL()
+    {
+    CPbk2CommandHandler* self = new(ELeave) CPbk2CommandHandler();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::ConstructL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2CommandHandler::ConstructL()
+    {
+    iCommandFactory = CPbk2CommandFactory::NewL();
+    iCommandStore = CPbk2CommandStore::NewL();
+    iAiwInterestArray = CPbk2AiwInterestArray::NewL();
+    iExtensionManager = CPbk2UIExtensionManager::InstanceL();
+    iContactRelocator = CPbk2ContactRelocator::NewL();
+    iAppServices = CPbk2ApplicationServices::InstanceL();
+
+    // Initialize feature manager
+    FeatureManager::InitializeLibL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::HandleCommandL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2CommandHandler::HandleCommandL
+        ( const TInt aCommandId, MPbk2ContactUiControl& aControl,
+          const CPbk2AppViewBase* aAppView )
+    {
+    TBool ret = ETrue;
+
+    // Exit commands are forwarded right away to appui
+    // Otherwise there is possibility that
+    // 'exit' command is not handled in low memory situations
+    if ( IsExitCommand( aCommandId ) )
+        {
+        ret = EFalse;
+        }
+
+    // Offer the command to AIW unless it is exit command
+    if ( ret && !iAiwInterestArray->HandleCommandL
+            ( aCommandId, aControl, KNullHandle ) )
+        {
+        // Try generic command, this can also be a command from an extension
+        ret = CmdGenericCommandL( TPbk2CommandId( aCommandId ), aControl );
+        if ( !ret )
+            {
+            ret = ETrue;
+            switch ( aCommandId )
+                {
+                case EAknSoftkeyBack:               // FALLTHROUGH
+                case EPbk2CmdOpenPreviousView:
+                    {
+                    CmdOpenPreviousViewL( aControl, aAppView );
+                    break;
+                    }
+                case EPbk2CmdSettings:
+                    {
+                    CmdOpenSettingsViewL( aControl, aAppView,
+                        Phonebook2::KPbk2SettingsViewUid );
+                    break;
+                    }
+                case EAknCmdHelp:
+                    {
+                    CmdOpenHelpL( aControl, aAppView );
+                    break;
+                    }
+                default:
+                    {
+                    ret = EFalse;
+                    break;
+                    }
+                }
+            }
+        }
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::DynInitMenuPaneL
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::DynInitMenuPaneL(
+        TInt aResourceId,
+        CEikMenuPane* aMenuPane,
+        CPbk2AppViewBase& aViewBase,
+        MPbk2ContactUiControl& aControl )
+    {
+    // First, delegate to AIW interests.
+    // If the menu initialization is handled there,
+    // there's no need to continue here
+    if ( !iAiwInterestArray->DynInitMenuPaneL
+            ( aResourceId, *aMenuPane, aControl ) )
+        {
+        // Then call extensions
+        iExtensionManager->DynInitMenuPaneL( aResourceId, aMenuPane,
+            aViewBase, aControl );
+
+        // First perform standard menu filtering
+        PerformStandardMenuFilteringL( aResourceId, aMenuPane, aControl );
+
+        // Then perform field type based filtering
+        PerformFieldTypeBasedFilteringL( aResourceId, aMenuPane, aControl );
+
+        // Finally perform store specific filtering
+        PerformStoreSpecificFilteringL( aResourceId, aMenuPane, aControl );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::RegisterAiwInterestL
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::RegisterAiwInterestL(
+        const TInt aInterestId,
+        const TInt aMenuResourceId,
+        const TInt aInterestResourceId,
+        const TBool aAttachBaseService)
+    {
+    iAiwInterestArray->QueueInterestL(aInterestId,
+        aMenuResourceId, aInterestResourceId, aAttachBaseService);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::ServiceCmdByMenuCmd
+// --------------------------------------------------------------------------
+//
+TInt CPbk2CommandHandler::ServiceCmdByMenuCmd(
+        TInt aMenuCmdId ) const
+    {
+    return iAiwInterestArray->ServiceCmdByMenuCmd( aMenuCmdId );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::AddAndExecuteCommandL
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::AddAndExecuteCommandL(
+        MPbk2Command* aCommand)
+    {
+    iCommandStore->AddAndExecuteCommandL(aCommand);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::AddMenuCommandObserver
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::AddMenuCommandObserver(
+        MPbk2MenuCommandObserver& aObserver)
+    {
+    iCommandStore->AddMenuCommandObserver(aObserver);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::RemoveMenuCommandObserver
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::RemoveMenuCommandObserver(
+        MPbk2MenuCommandObserver& aObserver)
+    {
+    iCommandStore->RemoveMenuCommandObserver(aObserver);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::DynInitToolbarL
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::DynInitToolbarL
+        ( TInt aResourceId, CAknToolbar* aToolbar,
+          const CPbk2AppViewBase& /*aAppView*/,
+          MPbk2ContactUiControl& aControl )
+    {
+    switch ( aResourceId )
+        {
+        case R_PBK2_NAMESLIST_TOOLBAR:
+            {
+            if ( aControl.FocusedContactIndex() == KErrNotFound )
+                {
+                // If there is not focused contact (empty list or otherwise no
+                // focus) then disable calling and message writing
+                aToolbar->SetItemDimmed( EPbk2CmdCall, ETrue, ETrue );
+                aToolbar->SetItemDimmed( EPbk2CmdWriteNoQuery, ETrue, ETrue );
+                }
+            else if ( aControl.ContactsMarked() )
+                {
+                // Disable calling to many contacts
+                aToolbar->SetItemDimmed( EPbk2CmdCall, ETrue, ETrue );
+                }
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::OfferToolbarEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::OfferToolbarEventL
+        ( TInt aCommand, MPbk2ContactUiControl& aControl,
+          const CPbk2AppViewBase* aAppView )
+    {
+    if ( aAppView )
+        {
+    HandleCommandL( aCommand, aControl, aAppView );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::CmdOpenSettingsViewL
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::CmdOpenSettingsViewL
+        ( MPbk2ContactUiControl& aControl,
+          const CPbk2AppViewBase* aAppView, TUid aViewId )
+    {
+    if (aAppView)
+        {
+        // Phonebook 2 view explorer for view switching
+        MPbk2ViewExplorer* viewExplorer = Phonebook2::Pbk2AppUi()->Pbk2ViewExplorer();
+
+        __ASSERT_DEBUG( viewExplorer,
+            Panic( EPanicPreCond_CmdOpenSettingsViewL ) );
+
+        CPbk2ViewState* state = aAppView->ViewStateLC();
+        viewExplorer->ActivatePhonebook2ViewL
+            ( aViewId, state );
+        CleanupStack::PopAndDestroy( state );
+        aControl.UpdateAfterCommandExecution();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::CmdOpenPreviousViewL
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::CmdOpenPreviousViewL
+        ( MPbk2ContactUiControl& /*aControl*/,
+          const CPbk2AppViewBase* aAppView )
+    {
+    if (aAppView)
+        {
+        // Phonebook 2 view explorer for view switching
+        MPbk2ViewExplorer* viewExplorer = Phonebook2::Pbk2AppUi()->Pbk2ViewExplorer();
+
+        CPbk2ViewState* state = aAppView->ViewStateLC();
+        viewExplorer->ActivatePreviousViewL( state );
+        CleanupStack::PopAndDestroy( state );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::CmdOpenHelpL
+// --------------------------------------------------------------------------
+//
+void CPbk2CommandHandler::CmdOpenHelpL
+        ( MPbk2ContactUiControl& aControl,
+          const CPbk2AppViewBase* aAppView )
+    {
+    if ( aAppView )
+        {
+    TCoeHelpContext helpContext;
+    if ( iExtensionManager->GetHelpContextL
+            ( helpContext, *aAppView, aControl) )
+        {
+        CArrayFix<TCoeHelpContext>* helpContextArray =
+                new (ELeave) CArrayFixFlat<TCoeHelpContext>( 1 );
+        CleanupStack::PushL( helpContextArray );
+        helpContextArray->AppendL( helpContext );
+
+        // HlpLauncher destroys the help context array
+        CleanupStack::Pop( helpContextArray );
+        HlpLauncher::LaunchHelpApplicationL
+            ( CCoeEnv::Static()->WsSession(), helpContextArray );
+        }
+    else
+        {
+        HlpLauncher::LaunchHelpApplicationL
+            ( CCoeEnv::Static()->WsSession(),
+              CEikonEnv::Static()->EikAppUi()->AppHelpContextL() );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::CmdGenericCommandL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2CommandHandler::CmdGenericCommandL(
+        TPbk2CommandId aCommandId,
+        MPbk2ContactUiControl& aControl)
+    {
+    // Create the command object
+    TBool result = EFalse;
+    MPbk2Command* cmd = iCommandFactory->CreateCommandForIdL(
+            aCommandId, aControl);
+    if (cmd)
+        {
+        // If command factory was able to create the command,
+        // add it to the command store and execute it
+        iCommandStore->AddAndExecuteCommandL(cmd);
+        result = ETrue;
+        }
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::PerformStandardMenuFilteringL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2CommandHandler::PerformStandardMenuFilteringL(
+        TInt aResourceId,
+        CEikMenuPane* aMenuPane,
+        MPbk2ContactUiControl& aControl )
+    {
+    switch (aResourceId)
+        {
+        case R_PHONEBOOK2_NAMESLIST_DELETE_MENU:
+            {
+            if ( aControl.NumberOfContacts() == 0 )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdDeleteMe, ETrue );
+                }
+            break;
+            }
+        
+        case R_PHONEBOOK2_NAMELIST_CALL_CONTACT_MENU:
+            {
+            // Weed out commands not meant to be used with marked items
+            if ( aControl.ContactsMarked() )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdCall, ETrue );
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_NAMESLIST_CREATE_MENU:
+            {
+            // Weed out commands not meant to be used with marked items
+            if ( aControl.ContactsMarked() )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdCreateNew, ETrue );
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_NAMESLIST_SEND_URL_MENU:
+            {
+            // Weed out commands not meant to be used with empty list
+            if ( aControl.NumberOfContacts() == 0 )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdGoToURL, ETrue );
+                }
+
+            if ( aControl.ContactsMarked() )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdGoToURL, ETrue );
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_NAMESLIST_COPY_MENU:          // FALLTHROUGH
+        case R_PHONEBOOK2_NAMESLIST_COPY_CONTEXT_MENU:
+            {
+            // The copy menu is not shown if there are no contacts
+            TBool itemSpecCommEnabled = Phonebook2::Pbk2AppUi()->ActiveView()->MenuBar()->ItemSpecificCommandsEnabled();
+            if ( aControl.NumberOfContacts() == 0 || 
+                    ( !aControl.ContactsMarked() && !itemSpecCommEnabled ) ||
+                    ( !aControl.FocusedContactL() && itemSpecCommEnabled && 
+                            !aControl.ContactsMarked() ) )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdCopy, ETrue );
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_CONTACTINFO_EDIT_MENU:
+            {
+            // Weed out commands not meant to be used with empty contact
+            if ( aControl.NumberOfContactFields() == 0 )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdWrite, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdGoToURL, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdDefaultSettings, ETrue );
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_CONTACTINFO_EXTENDED_MENU:
+            {
+            CVPbkContactManager& manager = iAppServices->ContactManager();
+
+            // Always dim thumbnail if image/text supported or vice versa
+            if ( FeatureManager::FeatureSupported
+                    ( KFeatureIdCallImagetext ) )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdFetchThumbnail, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdRemoveThumbnail, ETrue );
+                }
+            else
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdAddImage, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdImage, ETrue );
+                }
+
+            // Weed out commands not meant to be used with empty contact
+            if ( aControl.NumberOfContactFields() == 0 )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdSend, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdAssignSpeedDial, ETrue);
+                aMenuPane->SetItemDimmed( EPbk2CmdRemoveSpeedDial, ETrue );
+                aMenuPane->SetItemDimmed
+                    ( EPbk2CmdPersonalRingingTone, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdCopy, ETrue );
+
+                if ( !FeatureManager::FeatureSupported
+                        ( KFeatureIdCallImagetext ) )
+                    {
+                    aMenuPane->SetItemDimmed
+                        ( EPbk2CmdFetchThumbnail, ETrue );
+                    aMenuPane->SetItemDimmed
+                        ( EPbk2CmdRemoveThumbnail, ETrue );
+                    }
+                else
+                    {
+                    aMenuPane->SetItemDimmed( EPbk2CmdAddImage, ETrue );
+                    aMenuPane->SetItemDimmed( EPbk2CmdImage, ETrue );
+                    }
+                }
+            else
+                {
+                // Utilise attribute manager to find out if
+                // the contact have a speed dial defined
+                TBool hasSpeedDial = HasSpeedDialL( aControl );
+
+                // Filtering is based on the speed dial existence
+                if ( !hasSpeedDial )
+                    {
+                    aMenuPane->SetItemDimmed
+                        ( EPbk2CmdRemoveSpeedDial, ETrue );
+                    }
+                else
+                    {
+                    aMenuPane->SetItemDimmed
+                        ( EPbk2CmdAssignSpeedDial, ETrue );
+                    }
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_CONTACTINFO_CONTEXT_MENU:
+            {
+            // Weed out commands not meant to be used with empty contact
+            if ( aControl.NumberOfContactFields() == 0 )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdWrite, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdGoToURL, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdPersonalRingingTone, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdUseNumber, ETrue );
+                aMenuPane->SetItemDimmed( EPbk2CmdImage, ETrue );
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_INFO_MENU:
+            {
+            // Filter memory info items when list box is empty
+            // or items are marked
+            if ( aControl.NumberOfContacts() == 0 ||
+                 aControl.ContactsMarked() )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdPhonebook2Info, ETrue );
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_SYSTEM_MENU:
+            {
+            if ( !FeatureManager::FeatureSupported( KFeatureIdHelp ) )
+                {
+                // Remove non-supported help from menu
+                aMenuPane->SetItemDimmed( EAknCmdHelp, ETrue );
+                }
+            break;
+            }
+        case R_PHONEBOOK2_MERGE_CONTACTS:
+            {
+            TBool supported = FeatureManager::FeatureSupported( KFeatureIdFfContactsMerge );
+                       
+            if ( !supported || aControl.ContactsMarked() )
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdMergeContacts, ETrue );
+                }
+            break;
+            }
+        default:
+            {
+            // Do nothing
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::PerformStoreSpecificFiltering
+// --------------------------------------------------------------------------
+//
+inline void CPbk2CommandHandler::PerformStoreSpecificFilteringL(
+            TInt aResourceId,
+            CEikMenuPane* aMenuPane,
+            MPbk2ContactUiControl& aControl )
+    {
+    switch (aResourceId)
+        {
+        case R_PHONEBOOK2_NAMESLIST_CONTEXT_MENU_MARKED_ITEMS: // FALLTHROUGH
+        case R_PHONEBOOK2_NAMESLIST_DELETE_MENU:
+            {
+            // Weed out commands not meant to be used with read only stores
+            if (AreSelectedContactsFromReadOnlyStoreL( aControl ))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdDeleteMe, ETrue);
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_CONTACTINFO_EDIT_MENU:
+            {
+            TBool phoneMemoryInConfiguration =
+                    iContactRelocator->IsPhoneMemoryInConfigurationL();
+
+            // Weed out commands not meant to be used with read only stores
+            if (AreSelectedContactsFromReadOnlyStoreL( aControl ))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdDeleteMe, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdEditMe, ETrue);
+                }
+
+            // Weed out phone memory specific commands, if there is no
+            // phone memory in configuration
+            if (!phoneMemoryInConfiguration)
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdDefaultSettings, ETrue);
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_CONTACTINFO_EXTENDED_MENU:
+            {
+            TBool phoneMemoryInConfiguration =
+                    iContactRelocator->IsPhoneMemoryInConfigurationL();
+
+            // Weed out phone memory specific commands, if there is no
+            // phone memory in configuration
+            if (!phoneMemoryInConfiguration)
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdAssignSpeedDial, ETrue);
+                if (!FeatureManager::FeatureSupported(KFeatureIdCallImagetext))
+                    {
+                    aMenuPane->SetItemDimmed(EPbk2CmdFetchThumbnail, ETrue);
+                    }
+                else
+                    {
+                    aMenuPane->SetItemDimmed(EPbk2CmdAddImage, ETrue);
+                    aMenuPane->SetItemDimmed(EPbk2CmdImage, ETrue);
+                    }
+                aMenuPane->SetItemDimmed(EPbk2CmdPersonalRingingTone, ETrue);
+                }
+
+            break;
+            }
+
+        case R_PHONEBOOK2_CONTACTINFO_CONTEXT_MENU:
+            {
+            // Weed out commands not meant to be used with read only stores
+            if (AreSelectedContactsFromReadOnlyStoreL( aControl ))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdEditMe, ETrue);
+                }
+            break;
+            }
+        case R_PHONEBOOK2_MERGE_CONTACTS:
+            {
+            TBool phoneMemoryInConfiguration =
+                    iContactRelocator->IsPhoneMemoryInConfigurationL();
+            
+            if( !phoneMemoryInConfiguration ) 
+                {
+                aMenuPane->SetItemDimmed( EPbk2CmdMergeContacts, ETrue );
+                }
+            break;
+            }
+        default:
+            {
+            // Do nothing
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::PerformFieldTypeBasedFilteringL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2CommandHandler::PerformFieldTypeBasedFilteringL(
+            TInt aResourceId,
+            CEikMenuPane* aMenuPane,
+            MPbk2ContactUiControl& aControl )
+    {
+    CVPbkContactManager& manager = iAppServices->ContactManager();
+
+    switch (aResourceId)
+        {
+        case R_PHONEBOOK2_CONTACTINFO_EDIT_MENU:
+            {
+            // Weed out commands which are not shown if currently focused field is
+            // not phone number
+            if (!FocusedFieldMatchesFieldTypeL(aControl,
+                    R_PHONEBOOK2_PHONENUMBER_SELECTOR, manager))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdUseNumber, ETrue);
+                }
+
+            // If the contact does not have URL field, there is no
+            // "Go To URL" option available
+            if (FocusedContactHasFieldTypeL(aControl,
+                    R_PHONEBOOK2_URL_SELECTOR, manager) < 0)
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdGoToURL, ETrue);
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_CONTACTINFO_EXTENDED_MENU:
+            {
+            // Speed dial menus are variated based on VoIP support
+            if( FeatureManager::FeatureSupported( KFeatureIdCommonVoip ) )
+                {
+                // Weed out commands which are not shown if currently focused field is
+                // neither phone number nor VoIP field
+                if( !FocusedFieldMatchesFieldTypeL( aControl,
+                        R_PHONEBOOK2_SIP_MSISDN_SELECTOR, manager ) )
+                    {
+                    aMenuPane->SetItemDimmed( EPbk2CmdAssignSpeedDial, ETrue );
+                    aMenuPane->SetItemDimmed( EPbk2CmdRemoveSpeedDial, ETrue );
+                    }
+                }
+            else
+                {
+                // Weed out commands which are not shown if currently focused field is
+                // not phone number
+                if( !FocusedFieldMatchesFieldTypeL( aControl,
+                        R_PHONEBOOK2_PHONENUMBER_SELECTOR, manager ) )
+                    {
+                    aMenuPane->SetItemDimmed( EPbk2CmdAssignSpeedDial, ETrue );
+                    aMenuPane->SetItemDimmed( EPbk2CmdRemoveSpeedDial, ETrue );
+                    }
+                }
+
+            // Alternate Thumbnail/Call object menus based on whether data
+            // has been added or not
+            if (!FeatureManager::FeatureSupported(KFeatureIdCallImagetext))
+                {
+                // Weed out command Remove Thumbnail if contact does not have one
+                if (FocusedContactHasFieldTypeL(aControl,
+                        R_PHONEBOOK2_THUMBNAIL_SELECTOR, manager) < 0)
+                    {
+                    aMenuPane->SetItemDimmed(EPbk2CmdRemoveThumbnail, ETrue);
+                    }
+                }
+            else
+                {
+                if ((FocusedContactHasFieldTypeL(aControl,
+                        R_PHONEBOOK2_IMAGE_SELECTOR, manager) < 0) &&
+                    (FocusedContactHasFieldTypeL(aControl,
+                        R_PHONEBOOK2_THUMBNAIL_SELECTOR, manager) < 0))
+                    {
+                    // Weed out Image submenu if contact does not have image
+                    aMenuPane->SetItemDimmed(EPbk2CmdImage, ETrue);
+                    }
+                else
+                    {
+                    // Weed out command Add Image if contact already has one
+                    aMenuPane->SetItemDimmed(EPbk2CmdAddImage, ETrue);
+                    }
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_CONTACTINFO_CONTEXT_MENU:
+            {
+            TBool filtered = EFalse;
+
+            // Telephone field
+            if (FocusedFieldMatchesFieldTypeL(aControl,
+                    R_PHONEBOOK2_PHONENUMBER_SELECTOR, manager))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdGoToURL, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdPersonalRingingTone, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdImage, ETrue);
+                filtered = ETrue;
+
+                // Further filtering of phone number fields
+                // Pager field
+                // Pager returns a match for R_PHONEBOOK2_PHONENUMBER_SELECTOR
+                // too, but it requires further filtering, which is handled here
+                if (FocusedFieldMatchesFieldTypeL(aControl,
+                        R_PHONEBOOK2_PAGER_SELECTOR, manager))
+                    {
+                    aMenuPane->SetItemDimmed(EPbk2CmdWrite, ETrue);
+                    aMenuPane->SetItemDimmed(EPbk2CmdUseNumber, ETrue );
+                    }
+
+                // VoIP
+                // VoIP returns a match for R_PHONEBOOK2_PHONENUMBER_SELECTOR
+                // too, but it requires further filtering, which is handled here
+                if (FocusedFieldMatchesFieldTypeL(aControl,
+                        R_PHONEBOOK2_VOIP_SELECTOR, manager))
+                    {
+                    aMenuPane->SetItemDimmed(EPbk2CmdWrite, ETrue);
+                    aMenuPane->SetItemDimmed(EPbk2CmdUseNumber, ETrue );
+                    }
+                } // further filtering
+
+            // Email field
+            if (FocusedFieldMatchesFieldTypeL(aControl,
+                    R_PHONEBOOK2_EMAIL_SELECTOR, manager))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdGoToURL, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdUseNumber, ETrue );
+                aMenuPane->SetItemDimmed(EPbk2CmdPersonalRingingTone, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdImage, ETrue);
+                filtered = ETrue;
+                }
+
+            // URL field
+            if (FocusedFieldMatchesFieldTypeL(aControl,
+                    R_PHONEBOOK2_URL_SELECTOR, manager))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdWrite, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdUseNumber, ETrue );
+                aMenuPane->SetItemDimmed(EPbk2CmdPersonalRingingTone, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdImage, ETrue);
+                filtered = ETrue;
+                }
+
+            // Ringing tone field
+            if (FocusedFieldMatchesFieldTypeL(aControl,
+                    R_PHONEBOOK2_RINGTONE_SELECTOR, manager))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdWrite, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdGoToURL, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdEditMe, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdUseNumber, ETrue );
+                aMenuPane->SetItemDimmed(EPbk2CmdImage, ETrue);
+                filtered = ETrue;
+                }
+
+            // Image/text context submenus
+            if( FocusedFieldMatchesFieldTypeL(aControl,
+                    R_PHONEBOOK2_IMAGE_SELECTOR, manager))
+                {
+                aMenuPane->SetItemDimmed(EPbk2CmdWrite, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdGoToURL, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdUseNumber, ETrue );
+                aMenuPane->SetItemDimmed(EPbk2CmdPersonalRingingTone, ETrue);
+                filtered = ETrue;
+                }
+
+            if (!filtered)
+                {
+                // Default filtering leaves only edit option in the menu
+                aMenuPane->SetItemDimmed(EPbk2CmdWrite, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdGoToURL, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdUseNumber, ETrue );
+                aMenuPane->SetItemDimmed(EPbk2CmdPersonalRingingTone, ETrue);
+                aMenuPane->SetItemDimmed(EPbk2CmdImage, ETrue);
+                }
+            break;
+            }
+
+        case R_PHONEBOOK2_IMAGE_SUBMENU:
+            {
+            if (FeatureManager::FeatureSupported(KFeatureIdCallImagetext))
+                {
+                if (FocusedContactHasFieldTypeL(aControl,
+                        R_PHONEBOOK2_IMAGE_SELECTOR, manager) < 0)
+                    {
+                    // Weed out Image View command if contact has no image
+                    // (it might have thumbnail from e.g. business card and
+                    // and thus other image submenu options)
+                    aMenuPane->SetItemDimmed(EPbk2CmdViewImage, ETrue);
+                    }
+                }
+            break;
+            }
+
+        default:
+            {
+            // AIW provider menus are filtered in the corresponding
+            // interest item, for example R_PHONEBOOK2_CALL_CONTEXT_MENU
+            // is filtered in CPbk2AiwInterestItemCall
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::AreSelectedContactsFromReadOnlyStoreL
+// Returns ETrue if all selected contacts are read-only.
+// --------------------------------------------------------------------------
+//
+inline TBool CPbk2CommandHandler::AreSelectedContactsFromReadOnlyStoreL(
+            MPbk2ContactUiControl& aControl)
+    {
+    // Default behavior is that selection is read-only, e.g
+    // a link can not be created for folding contact in which case
+    // the folding contact cannot be destroyed
+    TBool ret = ETrue;
+
+    MPbk2ContactLinkIterator* iterator =
+        aControl.SelectedContactsIteratorL();
+    if ( iterator )
+        {
+        CleanupDeletePushL( iterator );
+
+        while( iterator->HasNext() && ret )
+            {
+            MVPbkContactLink* link = iterator->NextL();
+
+            if ( link && !IsFromReadOnlyStore( *link ) )
+                {
+                ret = EFalse;
+                }
+
+            delete link;
+            link = NULL;
+            }
+
+        CleanupStack::PopAndDestroy(); // iterator
+        }
+    else
+        {
+        // There was no iterator so there are no selected contacts,
+        // this means we are operating with the focused contact
+        const MVPbkBaseContact* focusedContact =
+            aControl.FocusedContactL();
+        if ( focusedContact )
+            {
+            MVPbkContactLink* link = focusedContact->CreateLinkLC();
+            if ( link && !IsFromReadOnlyStore( *link ) )
+                {
+                ret = EFalse;
+                }
+            CleanupStack::PopAndDestroy(); // link
+            }
+        }
+
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::IsFromReadOnlyStore
+// --------------------------------------------------------------------------
+//
+TBool CPbk2CommandHandler::IsFromReadOnlyStore(
+        const MVPbkContactLink& aContactLink ) const
+    {
+    TBool ret = EFalse;
+
+    const MVPbkContactStore& store = aContactLink.ContactStore();
+    if ( store.StoreProperties().ReadOnly() )
+        {
+        ret = ETrue;
+        }
+
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::HasSpeedDialL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2CommandHandler::HasSpeedDialL(
+        MPbk2ContactUiControl& aControl )
+    {
+    TBool hasAttribute(EFalse);
+
+    const MVPbkStoreContact* storeContact =
+            aControl.FocusedStoreContact();
+
+    // Convert presentation index to store index.
+    TInt index( ToStoreFieldIndexL(
+                    aControl.FocusedFieldIndex(),
+                    storeContact ) );
+
+    if ( index != KErrNotFound )
+        {
+        const MVPbkStoreContactField& field =
+            storeContact->Fields().FieldAt( index );
+
+
+        hasAttribute =
+            iAppServices->ContactManager().ContactAttributeManagerL().
+            HasFieldAttributeL(
+                CVPbkSpeedDialAttribute::Uid(),
+                field );
+        }
+    return hasAttribute;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2CommandHandler::ToStoreFieldIndexL
+// --------------------------------------------------------------------------
+//
+TInt CPbk2CommandHandler::ToStoreFieldIndexL(
+        TInt aPresIndex,
+        const MVPbkStoreContact* aStoreContact )
+    {
+    // It is ok to remove const, we don't make any changes
+    MVPbkStoreContact* storeContact =
+        const_cast<MVPbkStoreContact*>( aStoreContact );
+
+    TInt index( KErrNotFound );
+    if ( aPresIndex >= 0 )
+        {
+        CPbk2PresentationContact* presentationContact =
+            CPbk2PresentationContact::NewL(
+                *storeContact,
+                iAppServices->FieldProperties() );
+        CleanupStack::PushL( presentationContact );
+
+        index = presentationContact->PresentationFields().
+                    StoreIndexOfField( aPresIndex );
+
+        CleanupStack::PopAndDestroy( presentationContact );
+        }
+    return index;
+    }
+
+// End of File