diff -r 000000000000 -r e686773b3f54 logsui/AppSrc/CLogsBaseView.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/logsui/AppSrc/CLogsBaseView.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,3056 @@ +/* +* 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: +* Logs Application view superclass +* +*/ + + +// INCLUDE FILES +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include //kaiwcmdcall +#include +#include + +#ifdef __OMA_POC +#include //cpocuiintegrationservices +#endif + +#include +#include +#include +#include +#include +#include +#include +#include // logs own icons +#include //additional event uids +#include + +#include + +#include "LogsIcons.hrh" +#include "LogsConsts.h" +#include "LogsConstants.hrh" +#include "LogsUID.h" +#include "CLogsBaseView.h" +#include "CLogsAppUi.h" +#include "CLogsEngine.h" +#include "CLogsCntLinkChecker.h" +#include "CLogsReaderConfigFactory.h" +#include "MLogsReader.h" +#include "MLogsEventGetter.h" +#include "MLogsSharedData.h" +#include "MLogsSystemAgent.h" +#include "CLogsTimer.h" +#include "aiwdialdataext.h" +#include "CPhoneNumberFormat.h" +#include "LogsDebug.h" +#include "LogsTraces.h" +#include "CLogsPrependQuery.h" + +// service table +#include +#include + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// ==================== LOCAL FUNCTIONS ==================== + +// ================= MEMBER FUNCTIONS ======================= + +// ---------------------------------------------------------------------------- +// CLogsBaseView::LogsAppUi +// ---------------------------------------------------------------------------- +// +CLogsAppUi* CLogsBaseView::LogsAppUi() + { + return static_cast( CAknView::AppUi() ); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::~CLogsBaseView +// ---------------------------------------------------------------------------- +// +CLogsBaseView::~CLogsBaseView() + { + delete iSendUiText; + delete iAddress; + delete iConstructDelayed; + delete iNumberInPbkProcessing; + delete iUriInPbkProcessing; + delete iLogsTimer; + delete iEmergencyCallAPI; + RemoveInputBlocker(); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CLogsBaseView +// ---------------------------------------------------------------------------- +// +CLogsBaseView::CLogsBaseView() : + iConstructDelayedOk( EFalse ), + iSendUiText( NULL ), + iFocusChangeControl( ELogsOkToChange ), + iEventListCurrent( 0 ), + iEventListTop( 0 ), + iRefreshMenuOnUpdate( EFalse ), + iMenuType(CEikMenuBar::EMenuOptions), + iInputBlocker(NULL), + iIsCheckedCntLinkInvaild( EFalse), + iResetAndRefreshOnHandleNotify(MLogsModel::ERefresh), + iIgnoreViewDeactivatedHandling(EFalse), + iSemiFinishViewDeactivatedOperation(EFalse) + { + //Construct CIdle object call back to finalise time consuming construction + iConstructDelayed = CIdle::New( CActive::EPriorityIdle ); + + if( iConstructDelayed ) + { + //The below seems to slow down reading of Logs entries from db so we're + //not calling it from here + //iConstructDelayed->Start( TCallBack( ConstructDelayedCallbackL, this) ); + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::BaseConstructL +// +// This is just a hook to catch BaseConstructL calls from derived classes before/ +// after call to super class's BaseConstructL if needed. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::BaseConstructL(TInt aResId ) + { + CAknView::BaseConstructL( aResId ); + + if( AknLayoutUtils::PenEnabled() && Toolbar() ) + { + //By default keep toolbar invisible + ShowToolbarOnViewActivation( EFalse ); + Toolbar()->SetToolbarObserver( this ); + } + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::Engine +// ---------------------------------------------------------------------------- +// +CLogsEngine* CLogsBaseView::Engine() + { + return LogsAppUi()->Engine(); + } + +// Safwish VoIP changes >>> +// ---------------------------------------------------------------------------- +// CLogsBaseView::SendUiTextL +// ---------------------------------------------------------------------------- +// +const TDesC& CLogsBaseView::SendUiTextL() + { + if ( !iSendUiText ) + { + iSendUiText = iCoeEnv->AllocReadResourceL( R_STM_WRITE_MSG ); + } + return *iSendUiText; + } +// <<< Safwish VoIP changes + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ConstructDelayedL +// +// Perform time consuming construction operations once. Calling this is needed +// before e.g. pressing Send key or launching a command from ui's menu. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::ConstructDelayedL( TBool aIdle ) //EFalse: immediately + { //ETrue: using idle time + if( iConstructDelayed && aIdle && !iConstructDelayed->IsActive() ) + { + iConstructDelayed->Start( TCallBack( ConstructDelayedCallbackL, this) ); + } + else + { + DoConstructDelayedL(); + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ConstructDelayedCallbackL +// +// Called from CIdle once to finish time consuming construction operations +// ---------------------------------------------------------------------------- +// +TInt CLogsBaseView::ConstructDelayedCallbackL( TAny* aContainer ) + { + CLogsBaseView* container = static_cast( aContainer ); + container->DoConstructDelayedL(); + return 0; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DoConstructDelayedL +// +// Perform time consuming construction operations once. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DoConstructDelayedL() + { + TRACE_ENTRY_POINT; + + if( iConstructDelayed ) + { + iConstructDelayed->Cancel(); + delete iConstructDelayed; + iConstructDelayed = NULL; + } + + if( iConstructDelayedOk ) + { + return; + } + + iConstructDelayedOk = ETrue; + iServHandlerRef = LogsAppUi()->CallUiL(); //ownership remains in LogsAppUi, + //this takes a lot of time. + + if ( !iSendUiText ) + { + iSendUiText = iCoeEnv->AllocReadResourceL( R_STM_WRITE_MSG ); + } + + iAddress = iCoeEnv->AllocReadResourceL(R_LOGS_ADDR_PROMPT); + iLogsTimer = CLogsTimer::NewL( CActive::EPriorityUserInput ); //EPriorityStandard EPriorityHigh + iEmergencyCallAPI = CPhCltEmergencyCall::NewL( this ); + + TRACE_EXIT_POINT + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleLogsTimerL +// +// Callback function for iLogsTimer +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleLogsTimerL( TAny* /* aPtr */ ) + { + HandleCommandL( ELogsCmdLongSendKeyCall ); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::LaunchPopupMenuL +// +// Launch a popup menu when ok-button has been pressed +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::LaunchPopupMenuL( TInt aResourceId ) + { + SetCurrentMenuType(CEikMenuBar::EMenuContext); + + TRAPD( err, DoLaunchPopupL( aResourceId ) ); + if( err ) + { + SetCurrentMenuType(CEikMenuBar::EMenuOptions); + User::Leave( err ); + } + + SetCurrentMenuType(CEikMenuBar::EMenuOptions); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DoLaunchPopupL +// +// Performs the popup menu launching +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DoLaunchPopupL( TInt aResourceId ) + { + MenuBar()->SetContextMenuTitleResourceId( aResourceId ); + MenuBar()->TryDisplayContextMenuBarL(); //TryDisplayContextMenuBarL() does not provide "Act + //apps" selection as TryDisplayMenuBarL() would. + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::FindXSPServiceSettingsLC +// Checks for stored settings for the logged service id. Returns a pointer to the +// found service table entry or NULL. If a NULL pointer is returned, the object is +// not pushed to the CleanupStack. +// ---------------------------------------------------------------------------- +// +CSPEntry* CLogsBaseView::FindXSPServiceSettingsLC(const MLogsEventGetter* aEvent) + { + CSPEntry* entry = NULL; + + // check only if the service id and sip uri stored. + if (aEvent->LogsEventData()->ServiceId() && SipUriAvailable( aEvent ) ) + { + TInt err = KErrNotFound; + entry = CSPEntry::NewLC(); + + CSPSettings* settings = CSPSettings::NewL(); + CleanupStack::PushL(settings); + err = settings->FindEntryL( aEvent->LogsEventData()->ServiceId(), *entry ); + CleanupStack::PopAndDestroy( settings ); + + if (err != KErrNone) + { + CleanupStack::PopAndDestroy( entry ); + entry = NULL; + } + } + + return entry; + } + + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdSaveToVirtualPhonebookL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdSaveToVirtualPhonebookL( + TInt aCommandId, + TBool aCalledForMenu, + const MLogsEventGetter* aEvent ) + { + TRACE_ENTRY_POINT; + + using namespace AiwContactAssign; + + CAiwGenericParamList& inParamList = iServHandlerRef->InParamListL(); + + TUint assignFlags = NULL; + + if( !aCalledForMenu ) + { + assignFlags = AiwContactAssign::ECreateNewContact; + } + + inParamList.AppendL( + TAiwGenericParam( + EGenericParamContactAssignData, //AiwGenericParam.hrh + TAiwVariant(TAiwSingleContactAssignDataV1Pckg( + TAiwSingleContactAssignDataV1().SetFlags(assignFlags))))); +// TAiwVariant(TAiwContactAttributeAssignDataV1Pckg( +// TAiwContactAttributeAssignDataV1().SetFlags(assignFlags))))); +// the above commented code also provides just one field to add to phonenbook so we must +// select between msisdn and uri in code below. + + + // Check first if there is a service id logged and there are settigs configured. + // If valid settings found for the logged service id, store to contacts as an xsp id + // + CSPEntry* entry = FindXSPServiceSettingsLC(aEvent); + if (entry) + { + TBuf xspuserid; + if ( Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), xspuserid )) + { + return; //Converting uri to unicode failed + } + else + { + _LIT(KLogsColon, ":"); + + HBufC* xspid = HBufC::NewLC( + xspuserid.Length() + + entry->GetServiceName().Length() + + KLogsColon().Length() ); + + xspid->Des().Append( entry->GetServiceName() ); + xspid->Des().Append( KLogsColon ); + xspid->Des().Append( xspuserid ); + + inParamList.AppendL( + TAiwGenericParam( + EGenericParamXSpId, + TAiwVariant( xspid->Des() ) + )); + CleanupStack::PopAndDestroy( xspid ); + CleanupStack::PopAndDestroy( entry ); + } + } + // + // If service id not found or no valid settings, store as a sip uir or phonenumber + // + else if( SipUriAvailable( aEvent ) ) + { + //inParamList allocates it's own buffer, so it's safe to hand over buf + TBuf buf; + if ( Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), buf ) ) + { + return; //Converting uri to unicode failed + } + else + { + inParamList.AppendL( + TAiwGenericParam( + EGenericParamSIPAddress, + TAiwVariant( buf ) + )); + } + } + else if( PhoneNumberAvailable( aEvent ) ) + { + inParamList.AppendL( + TAiwGenericParam( + EGenericParamPhoneNumber, + TAiwVariant( aEvent->Number() ) + )); + } + else + { + return; //Nothing to store + } + + delete iNumberInPbkProcessing; + delete iUriInPbkProcessing; + iNumberInPbkProcessing = NULL; + iUriInPbkProcessing = NULL; + + //2. If sip uri available, we prefer it over phone number (PoC or VoIP) + if( SipUriAvailable( aEvent )) + { + TBuf buf; + // Returns KErrNone if everythin ok + if ( !(Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), buf )) ) + { + iUriInPbkProcessing = buf.AllocL(); + } + } + else if( PhoneNumberAvailable( aEvent )) + { + iNumberInPbkProcessing = aEvent->Number()->AllocL(); + } + + //Add to Phonebook will call CPbk2AiwAssignProvider::HandleServiceCmdL + if ( !aCalledForMenu ) + { + iServHandlerRef->ExecuteServiceCmdL( + aCommandId, + inParamList, + iServHandlerRef->OutParamListL(), + 0, + this );//HandleNotifyL + } + else + { + iServHandlerRef->ExecuteMenuCmdL( + aCommandId, + inParamList, + iServHandlerRef->OutParamListL(), + 0, + this );//HandleNotifyL + } + + // Store AiW call parameters so that we can cancel the call later if needed. + SaveAiwCallParamsL(aCommandId, aCalledForMenu, &inParamList); + + // Set input blocker cause we don't want to have the user open menus etc + // while opening phonebook + SetInputBlockerL(); + + TRACE_EXIT_POINT; + } + + + +// -------------------------------------------------------------------------- +// CLogsBaseView::SaveAiwCallParamsL +// -------------------------------------------------------------------------- +// +void CLogsBaseView::SaveAiwCallParamsL( TInt aCommandId, + TBool aCalledForMenu, + CAiwGenericParamList* aInParamList ) + { + iAiwCommandId = aCommandId; + iAiwCalledFromMenu = aCalledForMenu; + iAiwInParamList = aInParamList; + + // To detect and cancel the aiw call early enough, we will need to observe view activation + LogsAppUi()->AddViewActivationObserverL(this); + } + +// -------------------------------------------------------------------------- +// CLogsBaseView::ClearAiwCallParams +// -------------------------------------------------------------------------- +// +void CLogsBaseView::ClearAiwCallParams() + { + iAiwCommandId = KErrNotFound; + iAiwCalledFromMenu = EFalse; + iAiwInParamList = NULL; + + // No need to observe view activation anymore. + LogsAppUi()->RemoveViewActivationObserver(this); + } + +// -------------------------------------------------------------------------- +// CLogsBaseView::CancelSaveToPbkL +// -------------------------------------------------------------------------- +// +void CLogsBaseView::CancelSaveToPbkL() + { + if (iAiwInParamList && iAiwCommandId != KErrNotFound ) + { + + iResetAndRefreshOnHandleNotify = MLogsModel::EResetAndRefresh; + + // Cancel the previously done AiW call by calling with the same parameters + // + flag KAiwOptCancel + // + if ( !iAiwCalledFromMenu ) + { + iServHandlerRef->ExecuteServiceCmdL( + iAiwCommandId, + *iAiwInParamList, + iServHandlerRef->OutParamListL(), + KAiwOptCancel, + this );//HandleNotifyL + } + else + { + iServHandlerRef->ExecuteMenuCmdL( + iAiwCommandId, + *iAiwInParamList, + iServHandlerRef->OutParamListL(), + KAiwOptCancel, + this );//HandleNotifyL + } + } + + ClearAiwCallParams(); + } + + +// -------------------------------------------------------------------------- +// CLogsBaseView::HandleViewActivation +// -------------------------------------------------------------------------- +// +void CLogsBaseView::HandleViewActivation(const TVwsViewId& aNewlyActivatedViewId,const TVwsViewId& aViewIdToBeDeactivated) + { + TInt err; + + // Do nothing if iNumberInPbkProcessing of iUriInPbkProcessing already cancelled. + // + if ( iNumberInPbkProcessing || iUriInPbkProcessing ) + { + // If another Logs view is going to be activated, cancel the save to pbk AiW command. + // + if ( aNewlyActivatedViewId.iAppUid == TUid::Uid(KLogsAppUID3) && + aNewlyActivatedViewId.iViewUid != this->Id() ) + { + TRAP(err, CancelSaveToPbkL()); + } + // + // Also if Logs has received a commandline parameter telling it to activate this view, + // like when opening Logs from Idle with send key, it is best to cancel the command so that + // the view is in "fresh" state. + // + else if ( aNewlyActivatedViewId.iAppUid == TUid::Uid(KLogsAppUID3) && + aNewlyActivatedViewId.iViewUid == this->Id() && + aViewIdToBeDeactivated.iAppUid != TUid::Uid(KLogsAppUID3) ) + { + // Reset array, will call StateChangedL with state EStateArrayReseted and update the listbox. + CurrentModel()->DoDeactivate( MLogsModel::ESkipClearing, + MLogsModel::EResetOnlyArray ); + DrawComponents(); + TRAP(err, CancelSaveToPbkL()); + } + + // If a leave happened, clear the call parameters here. + if (err != KErrNone) + { + ClearAiwCallParams(); + } + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::StateChangedL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::StateChangedL( MLogsStateHolder* aHolder ) + { + if ( !aHolder ) + { + return; + } + if ( aHolder->State() == EStateCheckContactLinkFinished ) + { + const MLogsEventGetter* event = NULL; + MLogsEventData* eventData = NULL; + + if( CurrentModel() && CurrentModel()->Count() > 0 && EventListCurrent() >= 0 ) + { + event = CurrentModel()->At( EventListCurrent() ); + eventData = event->LogsEventData(); + + // When log event is for VOIP, it needs to check if the contact link is valid. + // If it's invalid, refresh menubar in order to avoid "voice" and "video" items. + // Can't avoid flicking in this case, however, it's so rare to repro. + if ( eventData && eventData->VoIP() && SipUriAvailable( event ) ) + { + TPtrC8 ptrContactLink( KNullDesC8 ); + + if ( KErrNone == eventData->GetContactLink( ptrContactLink ) ) + { + CLogsCntLinkChecker* contactCheckerPtr = Engine()->CntLinkCheckerL(); + + if ( !contactCheckerPtr->IsCntLinkValidSync( ptrContactLink ) ) + { + iIsCheckedCntLinkInvaild = ETrue; + if ( MenuBar()->IsDisplayed() ) + { + MenuBar()->StopDisplayingMenuBar(); + + if ( CurrentMenuType() == CEikMenuBar::EMenuContext ) + { + MenuBar()->TryDisplayContextMenuBarL(); + } + else + { + MenuBar()->TryDisplayMenuBarL(); + } + } + } + } + } + } + } + } + +// -------------------------------------------------------------------------- +// CLogsBaseView::SetInputBlockerL +// -------------------------------------------------------------------------- +// +void CLogsBaseView::SetInputBlockerL() + { + if (!iInputBlocker) + { + iInputBlocker = CAknInputBlock::NewCancelHandlerLC( this ); + CleanupStack::Pop( iInputBlocker ); + iInputBlocker->SetCancelDelete( iInputBlocker ); + } + } + +// -------------------------------------------------------------------------- +// CLogsBaseView::RemoveInputBlockerL +// -------------------------------------------------------------------------- +// +void CLogsBaseView::RemoveInputBlocker() + { + if (iInputBlocker) + { + iInputBlocker->Cancel(); + } + } + +// -------------------------------------------------------------------------- +// CLogsBaseView::AknInputBlockCancel +// -------------------------------------------------------------------------- +// +void CLogsBaseView::AknInputBlockCancel() + { + iInputBlocker = NULL; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ProcessKeyEventL +// +// Called by base control container when a key press happens. +// ---------------------------------------------------------------------------- +// +TBool CLogsBaseView::ProcessKeyEventL( + const TKeyEvent& aKeyEvent, + TEventCode aType ) + { + if( aType == EEventKey ) + { + switch( aKeyEvent.iCode ) + { + case EKeyApplication0: //S60 app key pressed + iCoeEnv->Flush( KDelayMicroSeconds ); + return EFalse; + } + } + + return EFalse; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ProcessPointerEventL +// +// Default handler for pointer events, when the current focused item is tapped +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::ProcessPointerEventL( TInt aIndex) + { + // Default action when tapping the focused item is to open another view + LogsAppUi()->CmdOkL(aIndex); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::FocusChangedL +// +// Informs subclass that focus is changed in listbox (item is tapped) +// ---------------------------------------------------------------------------- +// +//void CLogsBaseView::FocusChangedL() +// { +// HandleCommandL( ELogsCmdHandleTapFocusChange ); //Calls subclass impl if available +// } + +// -------------------------------------------------------------------------- +// CLogsBaseView::DynInitToolbarL +// -------------------------------------------------------------------------- +// +void CLogsBaseView::DynInitToolbarL( + TInt /* aResourceId */, + CAknToolbar* /* aToolbar */ ) + { + } + +// -------------------------------------------------------------------------- +// CLogsBaseView::OfferToolbarEventL +// -------------------------------------------------------------------------- +// +void CLogsBaseView::OfferToolbarEventL( TInt aCommand ) + { + // Call ConstructDelayedL now incase it has not been done yet. + // One example case was ELFG-6YV99Q when there are less than a screenful of events + // (see magic number KNbrShownEntries in CLogsRecentListView::StateChangedL) + ConstructDelayedL( EFalse ); + HandleCommandL( aCommand ); //Calls subclass impl if available + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleLosingForeground +// +// This function is called once for each type of already constructed view +// (e.g.when fast swapping window is brought to foreground). +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleLosingForeground() + { + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleGainingForeground +// +// This function is called once for each already View when +// Logs is gaining foreground. No matter if a view is deactivated (i.e. is also +// called for view(s) not actually gaining foreground but just have been constructed) +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleGainingForeground() + { + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DoDeactivate +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DoDeactivate() + { + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DoActivateL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DoActivateL( + const TVwsViewId& /* aPrevViewId */, + TUid /* aCustomMessageId */, + const TDesC8& /* aCustomMessage */ ) + { + // AppUi owns the service handler refrence and it might have been deleted and recreated + // so the reference here might thus be invalid. But skip this step if delayed construction + // is still going to be done. + if (iConstructDelayedOk) + { + iServHandlerRef = LogsAppUi()->CallUiL(EFalse); //ownership remains in LogsAppUi, + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleSendKeyMenuCommandL +// +// Handles send key press when menu is open. For call commands, send key works as +// if the menu option would have been selected. Default behaviour is not to consume the +// key which causes send key to open dialler. +// ---------------------------------------------------------------------------- +// +TBool CLogsBaseView::ProcessSendKeyEventInMenuL(TEventCode aType, const MLogsEventGetter* aEvent) + { + CEikMenuPane* cascadeMenuPane = MenuBar()->MenuPane()->CascadeMenuPane(); + TInt cmdId = KErrNotFound; + TBool ret = EFalse; + + if (cascadeMenuPane && cascadeMenuPane->IsFocused()) + { + cmdId = cascadeMenuPane->MenuItemCommandId( cascadeMenuPane->SelectedItem() ); + } + + TInt srvCmd = iServHandlerRef->ServiceCmdByMenuCmd( cmdId ); + switch( srvCmd ) //AiwCommon.hrh + { + case KAiwCmdCall: + case KAiwCmdPoC: + { + if (aType == EEventKeyDown ) + { + MenuBar()->StopDisplayingMenuBar(); + CmdAiwMenuCmdL(cmdId, aEvent); + } + ret = ETrue; // consume the send key + break; + } + + case KErrNotFound: + default: + { + ret = EFalse; // send key event not consumed + break; + } + } + + return ret; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ProcessKeyEventEventL +// +// For subclasses to handle key events needing LogEvent data +// ---------------------------------------------------------------------------- +// +TBool CLogsBaseView::ProcessKeyEventEventL( + const TKeyEvent& aKeyEvent, + TEventCode aType, + const MLogsEventGetter* aEvent ) + { + //First try non-event related + TBool ret = CLogsBaseView::ProcessKeyEventL( aKeyEvent, aType ); //Don't call subclass again + + // If events not read yet or a query dialog is shown, consume the key so dialler is not opened + if ( aKeyEvent.iScanCode == EStdKeyYes && ( LogsAppUi()->IsDisplayingDialog() || !aEvent ) ) + { + return ETrue; + } + else if( ret || !aEvent ) + { + return ret; + } + + //Process Send key for cellular, voip or poc call + if( aKeyEvent.iScanCode == EStdKeyYes && + ( MenuBar()->ItemSpecificCommandsEnabled() || + LogsAppUi()->ActiveViewId() == ELogDetailViewId ) ) + { + ConstructDelayedL( EFalse ); //EFalse: perform immediately + TBool supportLongSendPress = EFalse;//FIXME: FeatureManager::FeatureSupported( ??? ) this value should be available from platform in future + + // Handle first the special case when send key is pressed while options menu is open + // default behaviour is not to consume the key and let dialler open. For some call commands + // it is better to handle the command as if the menu option had been selected. + if (MenuBar()->IsDisplayed() && MenuBar()->MenuPane() ) + { + return ProcessSendKeyEventInMenuL(aType, aEvent); + } + // + else if( aType == EEventKeyDown ) + { + if( supportLongSendPress ) + { + //Start timer to wait delay period for forced video call + const TInt delay = 600000; //0.6sec, FIXME: this value should be available from platform in future + iLogsTimer->Cancel(); + iLogsTimer->After( delay, this, const_cast(aEvent) ); + } + else + { + HandleCommandEventL( ELogsCmdSendKeyCall, aEvent ); + } + } + else if( aType == EEventKey ) + { + //nop (send key down) + } + else if( aType == EEventKeyUp ) + { + if( supportLongSendPress && iLogsTimer->IsActive() ) + { + //Not pressed long enough, make normal call + iLogsTimer->Cancel(); + HandleCommandEventL( ELogsCmdSendKeyCall, aEvent ); + } + } + return ETrue; + } + + //Process other keys + if( aType == EEventKey ) + { + switch( aKeyEvent.iCode ) + { + case EKeyApplication0: //S60 app key pressed + iCoeEnv->Flush( KDelayMicroSeconds ); + return EFalse; + +// case EKeyPhoneSend: //Send key pressed (same as EKeyYes in enum TKeyCode) +// return ETrue; + + //PoC key usage (Voice/side key) goes as follows: + //When Poc app is active, it captures the key press. If Logs window is active in foreground, + //Poc app sends EKeyPoC event to Logs. Because we don't get EKeySide event to Logs, we are dependent + //on PoC to be active app to provide it (so no need to check the EKeySide event). Therefore only + //Poc call should be provided, no voip or voice call even if the current Logs event is voice/voip + //when EKeyPoC was pressed. + + //case EKeySide: //Voice key pressed (same as EKeyDevice6 in enum TKeyCode) + case EKeyPoC: //Poc key pressed (same as EKeyApplication1 in enum TKeyCode) + if ( MenuBar()->ItemSpecificCommandsEnabled() ) + { + //First check have we already done construction fully. If not, then we first need to do it. + ConstructDelayedL( EFalse ); //EFalse: perform immediately + HandleCommandEventL( ELogsCmdDeviceCallKey, aEvent ); //Other device special key pressed e.g. + //for poc call + return ETrue; + } + } + } + + //Set MSK & toolbar state + if(( aKeyEvent.iScanCode == EStdKeyUpArrow || + aKeyEvent.iScanCode == EStdKeyDownArrow ) && + aType == EEventKey ) + { + SetToolbarItems( aEvent ); + + Cba()->MakeCommandVisible( + EAknSoftkeyContextOptions, + IsOkToShowContextMenu( aEvent )); + } + + return EFalse; + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::TabObserver +// +// ---------------------------------------------------------------------------- +// +MAknTabObserver* CLogsBaseView::TabObserver() + { + return LogsAppUi(); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleCommandL +// +// For other commands +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleCommandL( TInt aCommandId ) + { + TRACE_ENTRY_POINT; + switch( aCommandId ) + { + case ELogsCmdStartPhonebook: + LogsAppUi()->StartApplicationL( TUid::Uid(KPbk2UID3), KNullDesC8 ); + break; + + case ELogsCmdMenuSettings: + AppUi()->HandleCommandL( aCommandId ); + break; + + case EEikCmdExit: // flow-through + case ELogsCmdMenuExit: // flow-through + case EAknSoftkeyExit: + LogsAppUi()->HandleCommandL( ELogsCmdMenuExit ); + break; + + case EAknCmdHideInBackground: + { + //If phonebook update is pending, request reset of callui. Otherwise in certain + //cases pending phonebook updates end up in wrong state (ECJA-7JDD5, ECJA-7JDCZW) + if( iPreviousCommand == KAiwCmdAssign ) + { + iServHandlerRef = LogsAppUi()->CallUiL( ETrue ); + } + break; + } + + case EAknSoftkeyBack: + { + // Set inputblocker to avoid problems of fast tapping during view switch. + // View switch will then cancel the inputblokcer. + SetInputBlockerL(); + LogsAppUi()->CmdBackL(); + break; + } + + case EAknCmdHelp: + AppUi()->HandleCommandL( aCommandId ); + break; + + default: + break; + } + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleCommandEventL +// +// For event-related commands +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleCommandEventL( + TInt aCommandId, + const MLogsEventGetter* aEvent ) + { + //Try first non-event commands + CLogsBaseView::HandleCommandL( aCommandId ); //Don't call subclass again + + if( !aEvent ) + { + return; + } + + //Check event releated commands + switch( aCommandId ) + { + case ELogsCmdMenuPrependNumber: + CmdPrependCallL(ETrue, aEvent); //ETrue: prefer phone number in case sip uri also available + break; + + case ELogsCmdMenuPrependAddress: + CmdPrependCallL(EFalse, aEvent); //EFalse: prefer sip uri if available + break; + + case ELogsCmdMenuCopyNumber: + CmdCopyNumberL( aEvent ); + break; + + case ELogsCmdMenuCopyAddress: + CmdCopyAddressL( aEvent ); + break; + + case ELogsCmdDeviceCallKey: //Special device key pressed to make a call + case ELogsCmdSendKeyCall: //or Send key pressed to make a call + case ELogsCmdLongSendKeyCall: + case ELogsCmdSingleTapCall: //or touch tapping to make a call + { + // Reset focus when calling from dialled calls view. + if( iModel == ELogsDialledModel) + { + iFocusChangeControl = ELogsOkToChange; + } + CmdAiwSrvCmdL( aCommandId, aEvent ); + break; + } + + case ELogsCmdShowMyAddress: + CmdShowMyAddressL( aEvent ); + break; + + case ELogsCmdMenuSendUi: // Cmd assigned for SendUI submenu processing (SMS, MMS) + case ELogsCmdToolBarSendUi: // or toolbar send message button pressed + SendMessageCmdHandlerL( aCommandId, aEvent ); + break; + + case ELogsCmdAiwCmdAssign: + iFocusChangeControl = ELogsNoChange_PbkUpdPending; //Prevent focus moving to top when list is reread + CmdSaveToVirtualPhonebookL( KAiwCmdAssign, EFalse, aEvent ); + break; + + case ELogsCmdHandleTapFocusChange: + SetToolbarItems( aEvent ); + Cba()->MakeCommandVisible( + EAknSoftkeyContextOptions, + IsOkToShowContextMenu( aEvent )); + break; + + default: + //If commandId is in range allocated to AIW, forward it to AIW for processing. + //commandId's allocated for AIW must not overlap with the other menu ids. + //Note, that there are some command id's allocated on top of ELogsCmdLast in PECLogs extension. + //However, these commands are already handled in CLogsRecentListView ReceiViewExtension->HandleCommandL(aCommandId)), + //no extension commands left here. Therefore ELogsCmdLast is ok instead of EDpbCmdLas of extension. + if( aCommandId >= ELogsCmdLast ) + { + CmdAiwMenuCmdL( aCommandId, aEvent ); + } + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SetToolbarState +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::SetToolbarState(TLogsShowToolbar aShowToolbar, TBool aSetRect) + { + TRAPD( err, SetToolbarStateL( aShowToolbar, aSetRect ) ); + if( err ) + { + // Only possible leave cause is KErrToolbarShown if + // DisableToolbarL is called when toolbar is shown. + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SetToolbarStateL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::SetToolbarStateL(TLogsShowToolbar aShowToolbar, TBool aSetRect) + { + if (AknLayoutUtils::PenEnabled() ) + { + CAknToolbar* toolbar = Toolbar(); + if (toolbar) + { + if (aShowToolbar == ELogsToolbarOn && + iToolBarState != ELogsHideItemsAndDrawOnlyBackground && + iToolBarState != ELogsUnHideItemsAndDrawOnlyBackground ) + { + if ( toolbar->IsToolbarDisabled() && !toolbar->IsShown() ) + { + // Enable toolbar and + toolbar->DisableToolbarL(EFalse); + } + // set visibility on + toolbar->SetToolbarVisibility( ETrue, EFalse); + iToolBarState = aShowToolbar; + + if (aSetRect) + { + HandleClientRectChange(); + DrawComponents(); + } + } + else if (aShowToolbar == ELogsToolbarOff && iToolBarState != ELogsHideItemsAndDrawOnlyBackground) + { + // Set toolbar visibility off and disable toolbar + toolbar->SetToolbarVisibility( EFalse, EFalse); + toolbar->DisableToolbarL(ETrue); + iToolBarState = aShowToolbar; + } + + else if (aShowToolbar == ELogsHideItemsAndDrawOnlyBackground) + { + toolbar->HideItemsAndDrawOnlyBackground(ETrue); + iToolBarState = aShowToolbar; + } + else if (aShowToolbar == ELogsUnHideItemsAndDrawOnlyBackground) + { + toolbar->HideItemsAndDrawOnlyBackground(EFalse); + iToolBarState = aShowToolbar; + if (aSetRect) + { + HandleClientRectChange(); + DrawComponents(); + } + } + } + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleClientRectChange +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleClientRectChange() + { + // base class has no implementation. + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DrawComponents +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DrawComponents() + { + // base class has no implementation. + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ProcessCommandL +// +// Called from FW when e.g. cba pressed +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::ProcessCommandL( TInt aCommand ) + { + TRACE_ENTRY_POINT; + // Close popup menu if open + MenuBar()->StopDisplayingMenuBar(); + + //If MSK-press, convert it ELogsCmdHandleMSK in order to be forwarded to + //HandleCommandL for possible processing + if ( aCommand == EAknSoftkeyContextOptions ) + { + aCommand = ELogsCmdHandleMSK; + } + + // Call base class calls HandleCommandL + CAknView::ProcessCommandL( aCommand ); + + //Store last executed command + if( aCommand >= ELogsCmdLast && iServHandlerRef) + { + iPreviousCommand = iServHandlerRef->ServiceCmdByMenuCmd( aCommand ); + } + else + { + iPreviousCommand = aCommand; + } + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleMenuRefreshL +// +// Checks wether the options menu needs to be refreshed. This is needed when +// options menu was opened before events were populated. Called from +// CLogsRecentListView::StateChangedL and CLogsEventListView::StateChangedL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleMenuRefreshL(const MLogsEventGetter* aCurrentEvent) + { + // Will be called when reading is finished. In some scenarios could be called twice + // so to avoid flickering the flag RefreshMenuOnUpdate is used. + if (MenuBar()->IsDisplayed() && RefreshMenuOnUpdate( aCurrentEvent ) ) + { + MenuBar()->StopDisplayingMenuBar(); + MenuBar()->TryDisplayMenuBarL(); + // After the refresh, set the conditional switch off. + iRefreshMenuOnUpdate = EFalse; + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SetRefreshMenuOnUpdate +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::SetRefreshMenuOnUpdate( const MLogsEventGetter* aCurrentEvent ) + { + if (aCurrentEvent) + { + iEventUidWhenMenuOpened = aCurrentEvent->EventUid().iUid; + } + else + { + iEventUidWhenMenuOpened = KErrNotFound; + } + + iRefreshMenuOnUpdate = ETrue; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::RefreshMenuOnUpdate +// ---------------------------------------------------------------------------- +// +TBool CLogsBaseView::RefreshMenuOnUpdate(const MLogsEventGetter* aCurrentEvent) + { + TBool refreshMenu(EFalse); + + if (iRefreshMenuOnUpdate) + { + if (aCurrentEvent) + { + if (iEventUidWhenMenuOpened != aCurrentEvent->EventUid().iUid) + { + refreshMenu = ETrue; + } + } + else if (iEventUidWhenMenuOpened != KErrNotFound) + { + refreshMenu = ETrue; + } + } + + return refreshMenu; + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleListBoxEventL +// +// If touch support is on, we handle the touch related events here. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleListBoxEventL( + CEikListBox* aListBox, + TListBoxEvent aEventType) + { + TRACE_ENTRY_POINT; + + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsBaseView::HandleListBoxEventL - aEventType:%d"), aEventType); + + if( AknLayoutUtils::PenEnabled() ) + { + switch ( aEventType ) + { + case EEventItemSingleClicked: + { + ProcessPointerEventL(aListBox->CurrentItemIndex()); + break; + } + + case EEventPanningStarted: + case EEventPanningStopped: + case EEventFlickStarted: + case EEventFlickStopped: + case EEventPenDownOnItem: + case EEventItemDraggingActioned: + { + HandleCommandL( ELogsCmdHandleTapFocusChange ); //Calls subclass impl if available + break; + } + + case EEventEnterKeyPressed: + { + TInt commandId( Cba()->ButtonGroup()->CommandId( + CEikButtonGroupContainer::EMiddleSoftkeyPosition ) ); + ProcessCommandL( commandId ); + break; + } + default: + break; + } + } + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::EventListCurrent +// ---------------------------------------------------------------------------- +// +TInt CLogsBaseView::EventListCurrent() const + { + return iEventListCurrent; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::EventListTop +// ---------------------------------------------------------------------------- +// +TInt CLogsBaseView::EventListTop() const + { + return iEventListTop; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SetEventListCurrent +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::SetEventListCurrent( TInt aIndex ) + { + iEventListCurrent = aIndex; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SetEventListTop +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::SetEventListTop( TInt aIndex ) + { + iEventListTop = aIndex; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DynInitMenuPaneL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DynInitMenuPaneL( + TInt /* aResourceId */, + CEikMenuPane* aMenuPane ) + { + //First check have we already done construction fully. If not, then we first need to do it. + ConstructDelayedL( EFalse ); //EFalse: perform immediately, ETrue: perform using idle time + TInt position = -1; + + if( aMenuPane->MenuItemExists( EAknCmdHelp, position ) ) + { + if( FeatureManager::FeatureSupported( KFeatureIdHelp ) ) + { + aMenuPane->SetItemDimmed( EAknCmdHelp, EFalse ); + } + else + { + aMenuPane->SetItemDimmed( EAknCmdHelp, ETrue ); + } + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DynInitMenuPaneEventL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DynInitMenuPaneEventL( + TInt aResourceId, + CEikMenuPane* aMenuPane, + const MLogsEventGetter* aEvent ) + { + TRACE_ENTRY_POINT; + + CLogsBaseView::DynInitMenuPaneL( aResourceId, aMenuPane );//Don't call subclass again + + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsBaseView::DynInitMenuPaneEventL - iServiceHandler: 0x%x"), iServHandlerRef); + + //AIW knows its own submenu hooks, so we can return from here if AIW handled this. + if( iServHandlerRef->HandleSubmenuL(*aMenuPane) || iServHandlerRef->HandleSubmenuL(*aMenuPane) ) + { + return; + } + + //Note that aEvent may NOT yet be available if asynch request(s) are not completed. + TBool phoneNumberAvailable = PhoneNumberAvailable( aEvent ); + TBool sipUriAvailable = SipUriAvailable( aEvent ); + TBool isEmergencyCall = EFalse; + + if( aEvent && aEvent->EventType() == ETypeEmerg ) + { + isEmergencyCall = ETrue; + } + + //Intitialise menupane resources + if( aResourceId == R_COMMON_EVENT_MENU_DELETE_EVENTS ) + { + // If no event data available, remove all event dependent options and exit + if( !aEvent ) + { + aMenuPane->DeleteMenuItem( ELogsCmdMenuDelete ); + aMenuPane->DeleteMenuItem( ELogsCmdMenuDeleteAll ); + return; + } + } //R_COMMON_EVENT_MENU_DELETE_EVENTS + + else if( aResourceId == R_COMMON_EVENT_MENU_EDIT_CALLS ) //Rest of Stm main menu below CallUi and PoC parts + { + // If no event data available, remove all event dependent options and exit + if( !aEvent ) + { + aMenuPane->DeleteMenuItem( ELogsCmdMenuNumberSubMenu ); //Edit and copy phone number + aMenuPane->DeleteMenuItem( ELogsCmdMenuPocAddressSubMenu ); + aMenuPane->DeleteMenuItem( ELogsCmdMenuVoipAddressSubMenu ); + return; + } + + //We have at least one event available on the list + + //Menu item for voice calls + if( !phoneNumberAvailable ) + { + aMenuPane->DeleteMenuItem( ELogsCmdMenuNumberSubMenu ); //Edit and copy phone number + } + + /* FIXME: The below should not be needed as when both available we prefer showing/using msisdn. However, + if available, it's good to provide also possibility for user to see sip-uri in addition to msisdn + if( phoneNumberAvailable && sipUriAvailable ) + { + // If both available (Phone number and SIP uri) show use address. + aMenuPane->DeleteMenuItem( ELogsCmdMenuNumberSubMenu ); + } + */ + + //Menu items for PoC and Voip calls + if( !sipUriAvailable ) + { + aMenuPane->DeleteMenuItem( ELogsCmdMenuPocAddressSubMenu ); + aMenuPane->DeleteMenuItem( ELogsCmdMenuVoipAddressSubMenu ); + } + else + { + if( !aEvent->LogsEventData()->PoC() ) + { + aMenuPane->DeleteMenuItem( ELogsCmdMenuPocAddressSubMenu ); + } + + if( !aEvent->LogsEventData()->VoIP() ) + { + aMenuPane->DeleteMenuItem( ELogsCmdMenuVoipAddressSubMenu ); + } + } + } //R_COMMON_EVENT_MENU_EDIT_CALLS + + else if( aResourceId == R_COMMON_CALLUI_SUBMENU ) //1. CallUi menu + { + if( !aEvent || ( !phoneNumberAvailable && //If event data not (yet) read, no MSISDN or no voip-uri, + ( !aEvent->LogsEventData()->VoIP() || //provide no call option + !sipUriAvailable ))) + { + aMenuPane->DeleteMenuItem( KAiwCmdCall ); //This menuitem is provided by AIW/CallUi + } + else + { + DynInitAiwCallUiMenuPaneL( aResourceId, aMenuPane, ETrue, aEvent );//Init voice&video call option in AIW menu + } + } //R_COMMON_CALLUI_SUBMENU + + else if( aResourceId == R_COMMON_POC_SUBMENU ) //2. PoC menu + { + if( !aEvent || //If event data not (yet) read or uri for voip, + aEvent->LogsEventData()->VoIP() || //provide no Poc option. However if msisdn, poc + ( !sipUriAvailable && !phoneNumberAvailable ) || //is ok. + isEmergencyCall ) //No Poc for emergency calls even if msisdn. + { + aMenuPane->DeleteMenuItem( KAiwCmdPoC ); //This menuitem is provided by AIW/PocUi + } + else + { + DynInitAiwPocMenuPaneL( aResourceId, aMenuPane, aEvent ); //Init (or remove) PoC option in AIW menu + } + } //R_COMMON_POC_SUBMENU + + else if( aResourceId == R_COMMON_SEND_MESSAGE_SUBMENU ) //3. Send message menu + { + //Add send message item if phone number available + if( !phoneNumberAvailable || + isEmergencyCall ) //Not for emergency calls. + { + aMenuPane->DeleteMenuItem( ELogsCmdMenuSendUi ); + } + else + { + TInt pos = 0; //Add send message item to menu above position pos + aMenuPane->ItemAndPos( ELogsCmdMenuSendUi, pos ); //Returns pointer to menu item + aMenuPane->DeleteMenuItem( ELogsCmdMenuSendUi ); //Delete marker item from menu + TSendingCapabilities capabilities(0, 0, 0 ); //No need here yet to tailor subitems in SendUi menu + LogsAppUi()->SendUiL()->AddSendMenuItemL(*aMenuPane, + pos, //Position in menupane + ELogsCmdMenuSendUi, //Command id to be used for "Send" menu item + capabilities ); + aMenuPane->SetItemTextL( ELogsCmdMenuSendUi, iSendUiText->Des() ); + aMenuPane->SetItemSpecific( ELogsCmdMenuSendUi, ETrue ); + } + } + + else if( aResourceId == R_COMMON_SAVETOPBK_SUBMENU ) //4. SaveToPbk menu + { + if( (!phoneNumberAvailable && !sipUriAvailable) || + isEmergencyCall ) //Not for emergency calls. + { + //Remove Phonebook's 'Copy to phonebook' submenu + aMenuPane->DeleteMenuItem( KAiwCmdAssign ); //NEW impl + } + else + { + + //Add Phonebook's 'Copy to phonebook' submenu + DynInitAiwSaveToPbkMenuPaneL( aResourceId, aMenuPane, aEvent, phoneNumberAvailable, sipUriAvailable ); + } + } + + else if( aResourceId == R_COMMON_SHOW_MY_ADDRESS_MENU ) + { + if( !aEvent || aEvent->LogsEventData()->MyAddress().Length() <= 0 ) + { + aMenuPane->DeleteMenuItem( ELogsCmdShowMyAddress ); //User's own voip adress + } + } + + TRACE_EXIT_POINT; + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SipUriAvailable +// ---------------------------------------------------------------------------- +// +TBool CLogsBaseView::SipUriAvailable( const MLogsEventGetter* aEvent ) + { + if( !aEvent || + aEvent->LogsEventData()->Url().Length() <= 0 || + aEvent->LogsEventData()->Url().Length() > KLogsSipUriMaxLen ) //exeeds maxlen for buffers etc + { + return EFalse; //no sip uri + } + + // Sip uri exists. However, if it equals to phonenumber, and it seems to + // be a valid phonenumber we don't consider a sip uri + // to exist but prefer msisdn number. + else if (PhoneNumberAndSipAreEqual(aEvent) && + CommonPhoneParser::IsValidPhoneNumber( + aEvent->Number()->Des(), + CommonPhoneParser::EPlainPhoneNumber ) ) + { + // SIP URI and number are equal and number is a + // valid phonenumber, so consider SIP URI not to exist + return EFalse; + } + + //We have a unique sip uri + return ETrue; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::PhoneNumberAndSipAreEqual +// ---------------------------------------------------------------------------- +// +TBool CLogsBaseView::PhoneNumberAndSipAreEqual(const MLogsEventGetter* aEvent) + { + TBuf buf; + + if( Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), buf) == KErrNone && + aEvent->Number()) + { + return ( *aEvent->Number() == buf ); + } + else + { + return EFalse; + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::PhoneNumberAvailable +// ---------------------------------------------------------------------------- +// +TBool CLogsBaseView::PhoneNumberAvailable( const MLogsEventGetter* aEvent ) + { + TBool numberAvailable = ETrue; + + // First check the number exists and all normal tests are passed. + if( !aEvent || !aEvent->Number() + || aEvent->Number()->Des().Length() > KLogsPhoneNumberMaxLen + || aEvent->EventType() == ETypeUnknown + || aEvent->EventType() == ETypePrivate + || aEvent->EventType() == ETypePayphone + || aEvent->EventType() == ETypeSAT //SAT: MO call/SMS without logged phonenumber (or URL) + || aEvent->EventUid() == KLogPacketDataEventTypeUid //Just in case would wrongly contain msisdn + || aEvent->EventUid() == KLogsEngWlanEventTypeUid //Just in case would wrongly contain msisdn + || aEvent->EventUid() == KLogDataEventTypeUid //No msisdn operations for data call + || aEvent->EventUid() == KLogFaxEventTypeUid ) //No msisdn operations for fax (this may change later + { //if sending fax from sendui is provided) + numberAvailable = EFalse; + } + + // Phonenumber exists. However, if it equals to SIP URI, and it is not + // a valid phonenumber we don't consider a phonenumber to exist. + // Instead the SIP URI is preferred. + else if (PhoneNumberAndSipAreEqual(aEvent) && + !CommonPhoneParser::IsValidPhoneNumber( + aEvent->Number()->Des(), + CommonPhoneParser::EPlainPhoneNumber ) ) + { + // SIP URI and number are equal and number is not a + // valid phonenumber, so consider phonenumber not to exist + numberAvailable = EFalse; + } + + return numberAvailable; + } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DynInitAiwCallUiMenuPaneL +// +// Provide CallUI AIW functionality for making voice, video and VoIP calls +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DynInitAiwCallUiMenuPaneL( + TInt aResourceId, + CEikMenuPane* aMenuPane, + TBool aVideo, + const MLogsEventGetter* aEvent ) + { + TRACE_ENTRY_POINT; + CAiwGenericParamList& paramList = iServHandlerRef->InParamListL(); + + //Check do we provide only voice call (i.e. skip video call option) + if ( !aVideo ) + { + TAiwVariant variant; + TAiwGenericParam param( EGenericParamPhoneNumber, variant ); + paramList.AppendL( param ); + } + + //Check do we provide VoiP call option + + //FIXME: the idea of the commented if instead of the if below was to remove voip from callui when there's + //no voip activated in phone. However, in this case there wouldn't be any voip events either. + //So this would unnecessarily exclude voip calls in which both sip-uri and msisdn is available. + //if( aEvent && aEvent->LogsEventData()->VoIP() && SipUriAvailable( aEvent ) && !aEvent->Number() ) + +// Sawfish VoIP changes >>>> + TPtrC8 tempPtr( KNullDesC8 ); + TInt result; + CLogsCntLinkChecker* contactCheckerPtr; + result = aEvent->LogsEventData()->GetContactLink( tempPtr ); + + if ( KErrNone == result ) + { + contactCheckerPtr = Engine()->CntLinkCheckerL(); + contactCheckerPtr->SetObserver( this ); + if ( !contactCheckerPtr->IsSameContactLink( tempPtr ) ) + { + // If current contact link is not the last one, + // need to reconfig CntLink checker. + iIsCheckedCntLinkInvaild = EFalse; + contactCheckerPtr->Stop(); + MLogsReaderConfig* readerConfig = CLogsReaderConfigFactory:: + LogsReaderConfigLC( NULL, NULL, &tempPtr ); + contactCheckerPtr->ConfigureL( readerConfig ); + CleanupStack::PopAndDestroy(); //readerConfig + contactCheckerPtr->StartL(); + } + } + + if ( aEvent + && aEvent->LogsEventData()->VoIP() + && SipUriAvailable( aEvent ) + && ( ( KErrNotFound == aEvent->LogsEventData()->GetContactLink( tempPtr ) + && !tempPtr.Length() ) + || iIsCheckedCntLinkInvaild ) ) +// <<<< Sawfish VoIP changes + { + // If contact link is invalid, provide internet call only. + TAiwVariant variant; + TAiwGenericParam param( EGenericParamSIPAddress, variant ); + paramList.AppendL( param ); + } + + //Handle runtime variation of VIDEOCALL_MENU_VISIBILITY flag + VideoCallMenuVisibilityL(*aMenuPane); + + //Add requested menu options to menu pane + iServHandlerRef->InitializeMenuPaneL( + *aMenuPane, //Handle of menu pane to initialise + aResourceId, //MenuResourceId + KAiwCmdCall, //Base ID for the handler to generate menu IDs for placeholders + paramList ); //input parameter list for provider's parameters checking + + TRACE_EXIT_POINT; + } + +// -------------------------------------------------------------------------- +// CLogsBaseView::VideoCallMenuVisibilityL +// +// Handles runtime variation of __VIDEOCALL_MENU_VISIBILITY feature flag +// i.e. Video call and Voice call command lifted to the main menu level +// instead of a submenu. Disaples\keeps the cascade flag. +// +// See error: JKLN-76XBYX +// -------------------------------------------------------------------------- +// +void CLogsBaseView::VideoCallMenuVisibilityL( CEikMenuPane& aMenuPane ) const + { + // Set to true if context menu is opened and if VOIP support is ON. + // Avoids more than 4 entries in the context sensitive menu + TBool contextMenuWithVoip = EFalse; + + if (FeatureManager::FeatureSupported(KFeatureIdCommonVoip) && + (CurrentMenuType() == CEikMenuBar::EMenuContext) ) + { + contextMenuWithVoip = ETrue; + } + + if ( FeatureManager::FeatureSupported(KFeatureIdVideocallMenuVisibility) && + (contextMenuWithVoip == EFalse ) ) + { + TInt index = KErrNotFound; + if ( aMenuPane.MenuItemExists( KAiwCmdCall, index ) && + index != KErrNotFound ) + { + CEikMenuPaneItem::SData& itemData = + aMenuPane.ItemDataByIndexL( index ); + const TInt KDisableCascade = 0; + itemData.iCascadeId = KDisableCascade; // disable cascade menu + } + + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CurrentMenuType +// ---------------------------------------------------------------------------- +// +CEikMenuBar::TMenuType CLogsBaseView::CurrentMenuType() const + { + return iMenuType; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SetCurrentMenuType +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::SetCurrentMenuType(CEikMenuBar::TMenuType aMenuType) + { + iMenuType = aMenuType; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DynInitAiwPocMenuPaneL +// +// Let AIW initialise menu for making PoC calls +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DynInitAiwPocMenuPaneL( + TInt aResourceId, + CEikMenuPane* aMenuPane, + const MLogsEventGetter* aEvent ) + { + TRACE_ENTRY_POINT; + //Create CAiwGenericParamList for menu initialisation. + TAiwPocParameterData pocParameter; + pocParameter.iCommandId = 0;//Default, not used with menu construction. + pocParameter.iPreferredMenu = KAiwPoCMenuDataBased; + TBool isParamListForPocOk( EFalse ); + CAiwGenericParamList& paramList = GetAiwGenericParamListForPocL( aEvent, pocParameter, isParamListForPocOk ); + + // Let provider add it's menu items to menu only if we got sensible paramList contents + if( isParamListForPocOk ) + { + iServHandlerRef->InitializeMenuPaneL( + *aMenuPane, + aResourceId, + KAiwCmdPoC, + paramList ); + } + else + { + aMenuPane->DeleteMenuItem( KAiwCmdPoC ); + } + TRACE_EXIT_POINT; + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::GetAiwGenericParamListForPocL +// +// Initialises AiwGenericParamList for Poc menu and Poc call functions. This is +// used for DynInitMenuPane and AIW excecution preparations. +// ---------------------------------------------------------------------------- +// +CAiwGenericParamList& CLogsBaseView::GetAiwGenericParamListForPocL( + const MLogsEventGetter* aEvent, //In: Event containing source data + TAiwPocParameterData& aPocParameter, //In: PocParameter data + TBool& aIsParamListForPocOk, //Out: Retuns ETrue if parameter can be used + const TDesC& aOverrideUsingThis, //In: Use this number/uri preferred instead of what is in aEvent + TBool aOverrideIsNumber ) //In: Type of string in aOverrideUsingThis + { + TRACE_ENTRY_POINT; + + __ASSERT_ALWAYS( aEvent != NULL, User::Leave( KErrArgument ) ); + + TInt type( aEvent->LogsEventData()->Type() ); //PoC app uses type for selecting 1-to-1, group call etc + + if( !( type >= EPoCNoOpTypeId && type < EEndOfPoCOpTypeIdRange ) ) + { + User::Leave( KErrArgument ); + } + + CAiwGenericParamList& params = iServHandlerRef->InParamListL(); //Ownership in Service Handler + aPocParameter.iConsumerAppUid = TUid::Uid(KLogsAppUID3); + aPocParameter.iConsumerWindowGroup = CCoeEnv::Static()->RootWin().Identifier(); + aPocParameter.iLogId = aEvent->LogId(); //PoC app uses LogId to map Log db entry to it's own log data + aPocParameter.iLogOperation = TPoCOperationTypeId( type ); + + //PoC parameter data always included + TAiwGenericParam param = TAiwGenericParam( EGenericParamPoCData, + TAiwVariant( TAiwPocParameterDataPckg(aPocParameter))); + params.AppendL(param); + TAiwGenericParam addressParam; + TBuf buf; + aIsParamListForPocOk = ETrue; + + if( aOverrideUsingThis != KNullDesC ) + { + //Use provided nbr or address instead what is in aEvent + addressParam = TAiwGenericParam( + aOverrideIsNumber ? EGenericParamPhoneNumber : EGenericParamSIPAddress, + aOverrideUsingThis ); + } + else if( SipUriAvailable( aEvent ) ) + { + // We prefer sip-uri over msisdn if both are available (if is uri & msisdn, Poc has made + // "best guess" for corresponding msisdn for possible subsequent cs calls. + User::LeaveIfError( Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), buf) ); + addressParam = TAiwGenericParam( EGenericParamSIPAddress, buf ); + } + + else if( PhoneNumberAvailable( aEvent ) ) + { + // Use msisdn only if uri not available + addressParam = TAiwGenericParam( EGenericParamPhoneNumber, aEvent->Number() ); + } + else + { + //ParamListForPoc is not ok, so it cannot be used. + aIsParamListForPocOk = EFalse; + } + + params.AppendL( addressParam ); //Takes own copy of addressParam + + TRACE_EXIT_POINT; + return params; + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::DynInitAiwSaveToPbkMenuPaneL +// +// Provide SaveToPbk AIW functionality +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::DynInitAiwSaveToPbkMenuPaneL( + TInt aResourceId, + CEikMenuPane* aMenuPane, + const MLogsEventGetter* aEvent, + TBool aPhoneNumberAvailable, + TBool aSipUriAvailable ) + { + TRACE_ENTRY_POINT; + using namespace AiwContactAssign; + + CAiwGenericParamList& inParamList = iServHandlerRef->InParamListL(); + + //Set flags to zero, otherwise provides only "Assing to" menu option. + TUint assignFlags = 0; //TAssignFlags in AiwContactAssignDataTypes.h + inParamList.AppendL( + TAiwGenericParam( + EGenericParamContactAssignData, //AiwGenericParam.hrh + TAiwVariant(TAiwSingleContactAssignDataV1Pckg( + TAiwSingleContactAssignDataV1().SetFlags(assignFlags))))); + + if( aPhoneNumberAvailable ) + { + inParamList.AppendL( + TAiwGenericParam( + EGenericParamPhoneNumber, + TAiwVariant( *(aEvent->Number()) ) + )); + } + + if( aSipUriAvailable ) + { + TBuf buf; + if( Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), buf) == KErrNone ) + { + inParamList.AppendL( + TAiwGenericParam( + EGenericParamSIPAddress, + TAiwVariant( buf ) + )); + } + } + + // Let provider add it's menu items to the menu + iServHandlerRef->InitializeMenuPaneL( + *aMenuPane, + aResourceId, + KAiwCmdAssign, + inParamList); + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CurrentModel +// ---------------------------------------------------------------------------- +// +MLogsModel* CLogsBaseView::CurrentModel() + { + return Engine()->Model( iModel ); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SendMessageCmdHandlerL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::SendMessageCmdHandlerL( + TInt aCommandId , + const MLogsEventGetter* aEvent ) + { + CMessageData* messageData = CMessageData::NewL(); + CleanupStack::PushL( messageData ); + + TBool isRead = aEvent->Event()->IsRead(); + TLogId logid = aEvent->LogId(); + TInt duplicates = aEvent->Duplicates(); + + //Check that event and phone number is available + TPtrC number( KNullDesC ); + if( aEvent && aEvent->Number() ) + { + number.Set( *(aEvent->Number()) ); + } + else + { + return; + } + + TBuf nbrBuff; + CPhoneNumberFormat::DTMFStrip( number, nbrBuff ); + + //Append number and remote party (if available) to message data. + if( aEvent->RemoteParty()) + { + messageData->AppendToAddressL( nbrBuff, *(aEvent->RemoteParty()) ); //Nbr & rem party + } + else + { + messageData->AppendToAddressL( nbrBuff ); //Only nbr + } + + + //We're are interested only in msg type that support writing messages. + TSendingCapabilities capabilities(0, //Max body size + 0, //Max msg size (inc. attachments) + TSendingCapabilities::ESupportsEditor );//Flags + + CArrayFixFlat* servicesToDim = new (ELeave) CArrayFixFlat( 5 );//Five services to dim + CleanupStack::PushL( servicesToDim ); + + +//******************************************************* +// QUICK & DIRTY: +// In case there is a need to quickly fix the SendUI error for not dimming the +// 'Mail for Exchange' option, we can do that excplictly with the following uids. +// +// TInt mailForEUid = 0x102826F8; +// servicesToDim->AppendL( TUid::Uid(mailForEUid ) ); +//******************************************************* + +// In normal builds we can dim all the e-mail stuff with the +// KSenduiTechnologyMailUid flag. +//"ESupportsEditor" takes care of removing infrared and bluetooth from menu, so no need to dim them +#ifndef __IMAIL + servicesToDim->AppendL( KSenduiTechnologyMailUid ); //SendUiConsts.h + servicesToDim->AppendL( KSenduiMtmPostcardUid ); +#else +// In DCP builds we need to enable KSenduiMtmSmtpUid but +// other email MTM's should be dimmed +// FIXME: we might need to dim more services. + servicesToDim->AppendL( KSenduiMtmImap4Uid ); //SendUiConsts.h + servicesToDim->AppendL( KSenduiMtmPop3Uid ); + servicesToDim->AppendL( KSenduiMtmSyncMLEmailUid ); + servicesToDim->AppendL( KSenduiMtmPostcardUid ); +#endif + +// Sawfish VoIP changes >>>> + if ( FeatureManager::FeatureSupported(KFeatureIdCommonVoip)) + { + servicesToDim->AppendL( KSenduiTechnologyIMUid ); + } +// <<<< Sawfish VoIP changes + + // Calling ShowTypedQueryAndSendL to show the write query. Different menu options are + // be shown depending on wether the RD_UNIFIED_EDITOR flag is defined ot not, but we don't + // need care about the flag here. + TUid uid; + SetToolbarState(ELogsHideItemsAndDrawOnlyBackground, EFalse); + + TRAPD(err, + if (aCommandId == ELogsCmdMenuSendUi) // with ELogsCmdMenuSendUi show query + { + uid = LogsAppUi()->SendUiL()->ShowTypedQueryL(CSendUi::EWriteMenu, messageData, capabilities, servicesToDim ); + } + else if (aCommandId == ELogsCmdToolBarSendUi) // with ELogsCmdToolBarSendUi dont show query + { + uid = KSenduiMtmUniMessageUid; + } + LogsAppUi()->SendUiL()->CreateAndSendMessageL(uid, messageData); + ); + + SetToolbarState(ELogsUnHideItemsAndDrawOnlyBackground, ETrue); + User::LeaveIfError(err); + ChangeTitlePaneTextToDefaultL(); + + if (isRead == EFalse && uid != KNullUid && iModel == ELogsMissedModel) // If not read, the New missed icon is shown. By setting event read + { // the new missed icon is not shown when control comes back to Logs + Engine()->ClearNewMissedL()->SetNewMissedCallRead(logid, duplicates); + } + CleanupStack::PopAndDestroy( servicesToDim ); + CleanupStack::PopAndDestroy( messageData ); + + //If missed list, clear now new missed calls counter + ClearMissedCallNotificationsL(); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ChangeTitlePaneTextToDefaultL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::ChangeTitlePaneTextToDefaultL() + { + // base class has no implementation + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ClearMissedCallNotifications +// +// Clears missed call notifications for Voice and PoC +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::ClearMissedCallNotifications() + { + if( iModel == ELogsMissedModel ) + { + TInt err; + TRAP( err, ClearMissedCallNotificationsL() ); //Clear new missed calls counter + if( err ) + { + CCoeEnv::Static()->HandleError( err ); + } + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::ClearMissedCallNotificationsL +// +// Clears missed call notifications for Voice and PoC +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::ClearMissedCallNotificationsL() + { + if( iModel != ELogsMissedModel ) + { + return; + } + + //1. Reset cs and voip missed calls information + Engine()->SharedDataL()->NewMissedCalls( ETrue ); //ETrue: clears the count of missed calls. + + //2. Reset missed Poc call info + notification (needs currently be done separately, + // the ResetSoftNotificationL does not do this fully). + Engine()->SystemAgentL()->ResetNewMissedPocCalls(); + +#ifdef __OMA_POC + // Clear missed poc call soft notification (no need to check are there any missed poc calls) + TUid provUid = { KS60PoCAiwProviderImplUid }; + + CPoCUiIntegrationServices* services = CPoCUiIntegrationServices::NewLC( provUid ); + services->ResetSoftNotificationL( CPoCUiIntegrationServices::EPoCUiIntegrationMissedCall ); + // services->ResetSoftNotificationL( CPoCUiIntegrationServices::EPoCUiIntegrationCallbackRequest ); + CleanupStack::PopAndDestroy( services ); +#endif + + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdPrependCallL +// +// Provide the user option to edit the phone number or sip uri and make cellular, +// voip or poc call using this number/uri. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdPrependCallL( + TBool aPreferNumber, //if both uri and number, prefer number + const MLogsEventGetter* aEvent ) + { + TRACE_ENTRY_POINT; + if ( !aEvent ) + { + return; + } + + TInt length(0); + TBuf buf; + + CAiwDialData::TCallType callTypeForVoice( CAiwDialData::EAIWVideo ); + + //Select uri or phone number to edit according to availability & preference + if( ( aEvent->LogsEventData()->VoIP() || aEvent->LogsEventData()->PoC() ) && + SipUriAvailable( aEvent ) && !aPreferNumber ) + { + + callTypeForVoice = CAiwDialData::EAIWVoiP; + + TInt ret = Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), buf); + if( ret != KErrNone && ret != KErrOverflow ) + { + return; + } + length = buf.Length(); //Unicode characters + } + else if ( aEvent->Number() ) + { + buf = *(aEvent->Number()); + length = buf.Length() ; + } + + //Show to user for editing if proper number or uri available + if( length && + ( (length <= KLogsPhoneNumberMaxLen) || //Max length for number + (length <= KLogsSipUriMaxLen && !aPreferNumber) ) //Max length for uri + ) + { + AknTextUtils::LanguageSpecificNumberConversion( buf ); + CLogsPrependQuery* query = CLogsPrependQuery::NewL( buf ); + + CAiwGenericParamList* paramList = NULL; + TBool isParamListForPocOk( EFalse ); + + if( aPreferNumber) + { + query->PrepareLC( R_STM_USE_NUMBER_QUERY ); + } + else + { + query->PrepareLC( R_STM_USE_ADDRESS_QUERY ); + + if( aEvent->LogsEventData()->PoC() ) + { + TAiwPocParameterData pocParameter; + +// // Initialise parameter data to execute AIW command + InitPocParameterL( pocParameter, aEvent ); //Other params from aEvent except the buf + paramList = &GetAiwGenericParamListForPocL( + aEvent, + pocParameter, + isParamListForPocOk, + buf, + aPreferNumber ); + + } + } + + //Show number/address to edit it + TInt queryAction; + queryAction = query->RunLD(); + + AknTextUtils::ConvertDigitsTo( buf, EDigitTypeWestern ); + + //Refresh contents in MLogsEventGetter. Otherwise it contains wrong data of last + //event read from db done in background during execution of RunLD() + //aEvent = CurrentModel()->At( iEventListCurrent ); + + switch( queryAction ) + { + case EAknSoftkeyCall: + if( isParamListForPocOk ) + { + CmdPocCallL( KAiwCmdPoC, EFalse, *paramList ); //EFalse: Direct request + } + else + { + // EFalse: Direct request (not made from menu). + CmdCallL( + KAiwCmdCall, + EFalse, + buf, + callTypeForVoice, + aEvent + ); + } + break; + + default: + break; + } + } + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdAiwSrvCmdL +// +// Request an AIW-service from an AIW provider. The commandId relates to +// Logs own commands. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdAiwSrvCmdL( + TInt aCommandId, + const MLogsEventGetter* aEvent ) + { + TRACE_ENTRY_POINT; + + if( !aEvent ) + { + return; + } + + switch( aCommandId ) + { + case ELogsCmdSingleTapCall: //Touch tapping to make a call + case ELogsCmdSendKeyCall: //Send key pressing to make a call + case ELogsCmdLongSendKeyCall: + //For PoC events make PoC call. Exception1: If phone number available, then + //for long presses attempt cs video call instead. Exception2: Long taps cause + //always Poc calls for poc events. + if( aEvent->LogsEventData()->PoC() && + !( aCommandId == ELogsCmdLongSendKeyCall && + PhoneNumberAvailable( aEvent ) )) + { + PreparePocCallL( KAiwCmdPoC, + EFalse, //EFalse: Direct request (not made from menu) + aEvent ); + } + else + { + TBool forceVideo( EFalse ); + + //For long press or single tap prefer video call but not for emergency calls + if( (aCommandId == ELogsCmdLongSendKeyCall || + aCommandId == ELogsCmdSingleTapCall ) && + aEvent->EventType() != ETypeEmerg ) + { + forceVideo = ETrue; + } + PrepareCallL( KAiwCmdCall, + EFalse, //EFalse: Direct request (not made from menu) + aEvent, + forceVideo ); //ETrue=force video call, EFalse=show voice/video query to user: + } + break; + + case ELogsCmdDeviceCallKey: //Special device key pressed to make a call, + PreparePocCallL( KAiwCmdPoC, //only poc call is supported for this key. + EFalse, //EFalse: Direct request (not made from menu). + aEvent ); + + break; + } + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdAiwMenuCmdL +// +// Forward an AIW-menu based command to corresponding AIW-provider. The commandId relates to +// AIW's menu item already shown by AIW provider to user +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdAiwMenuCmdL( + TInt aCommandId, + const MLogsEventGetter* aEvent ) + { + TRACE_ENTRY_POINT; + + if( !aEvent || !iServHandlerRef ) + { + return; + } + + TInt srvCmd = iServHandlerRef->ServiceCmdByMenuCmd( aCommandId ); + + switch( srvCmd ) //AiwCommon.hrh + { + case KErrNotFound: + break; + + case KAiwCmdCall: + PrepareCallL( aCommandId, ETrue, aEvent ); //Try to make voice call. + break; + + case KAiwCmdPoC: + PreparePocCallL( aCommandId, ETrue, aEvent ); //Try to make PoC call. + break; + + case KAiwCmdAssign: + // prevent the model being activated twice: + // from HandleGainingForeground and HandleNotifyL + iFocusChangeControl = ELogsNoChange_PbkUpdPending; + CmdSaveToVirtualPhonebookL( aCommandId, ETrue, aEvent ); + break; + + default: + // do nothing + break; + } + + // Reset focus when calling from dialled calls view. + if( iModel == ELogsDialledModel && + ( srvCmd == KAiwCmdCall || srvCmd == KAiwCmdPoC ) ) + { + iFocusChangeControl = ELogsOkToChange; + } + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::PreparePocCallL +// +// Prepares a PoC call. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::PreparePocCallL( + TInt aCommandId, + TBool aCalledForMenu, + const MLogsEventGetter* aEvent ) + { + TBool isRead = aEvent->Event()->IsRead(); + TLogId logid = aEvent->LogId(); + TInt duplicates = aEvent->Duplicates(); + + // Initialise PocParameterData for GenericParamList to execute AIW command + TAiwPocParameterData pocParameter; + if ( aCalledForMenu ) + { + pocParameter.iCommandId = aCommandId; + } + else + { + InitPocParameterL( pocParameter, aEvent ); + } + + TBool isParamListForPocOk( EFalse ); + CAiwGenericParamList& paramList = GetAiwGenericParamListForPocL( aEvent, pocParameter, isParamListForPocOk ); + + // Let's make call only if we got sensible paramList contents + if( isParamListForPocOk ) + { + CmdPocCallL( aCommandId, aCalledForMenu, paramList ); + } + + if (isRead == EFalse && iModel == ELogsMissedModel) // If not read, the New missed icon is shown. By setting event read + { // the new missed icon is not shown when control comes back to Logs + Engine()->ClearNewMissedL()->SetNewMissedCallRead(logid, duplicates); + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::InitPocParameterL +// +// Initialise PocParameterData. +// ---------------------------------------------------------------------------- +// +TAiwPocParameterData& CLogsBaseView::InitPocParameterL( + TAiwPocParameterData& aPocParameter, + const MLogsEventGetter* aEvent ) + { + TInt type( aEvent->LogsEventData()->Type() ); //PoC app uses type for selecting 1-to-1, group call etc + + if( !( type >= EPoCNoOpTypeId && type < EEndOfPoCOpTypeIdRange ) ) + { + User::Leave( KErrArgument ); + } + + aPocParameter.iLogOperation = TPoCOperationTypeId( type ); + aPocParameter.iCommandId = 0; + + // Check the type of the logged PoC call to be able to send correct + // command to PoC AIW. This is done because the call can be made from + // menu which always has an associated command and by PTT-key which + // doesn't have a command. + switch ( type ) + { + case EPoC1to1MO: // Initiated 1-to-1 call. + case EPoC1to1MT: // Received 1-to-1 call. + { + // This must be always set also for non menu-based + // PoC AIW service requests. + aPocParameter.iCommandId = EAiwPoCCmdTalk1to1; + break; + } + case EPoCAdhocDialoutGroupMO: // Initiated dial-out call. + case EPoCPredefDialoutGroupMO: // Initiated predefined dial-out call. + { + aPocParameter.iCommandId = EAiwPoCCmdTalkMany; + break; + } + case EPoCNoOpTypeId: // When only msisdn available + { + aPocParameter.iCommandId = EAiwPoCCmdTalk1to1; + break; + } + default: + case EPoCCallbackRequestMO: + case EPoCCallbackRequestMT: + case EPoCAdhocDialoutGroupMT: + case EPoCPredefDialoutGroupMT: + case EPoCDialinGroupMO: + { + // No handling at the moment since above events are not + // stored to system log. Maybe in future in OMA PoC these + // will be used aswell. Meanwhile use the 1-to-1 as default. + aPocParameter.iCommandId = EAiwPoCCmdTalk1to1; + break; + } + } + + __ASSERT_ALWAYS( aPocParameter.iCommandId > 0, User::Leave( KErrNotFound ) ); + + return aPocParameter; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdPocCallL +// +// Perform PoC call. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdPocCallL( + TInt aCommandId, + TBool aCalledForMenu, + CAiwGenericParamList& aParamList ) + { + if ( !aCalledForMenu ) + { + // Execute direct command to PoC AIW. In this case no + // Logs PoC AIW menu is displayed; call is intiated + // using the PTT-key. + iServHandlerRef->ExecuteServiceCmdL( + aCommandId, + aParamList, + iServHandlerRef->OutParamListL(), + 0, + NULL ); // Callback is NULL as no dial results wanted. + } + else + { + // Execute Menu based command to PoC AIW. The Logs PoC AIW menu + // has already displayed to user and user has selected a command + // from the menu. + iServHandlerRef->ExecuteMenuCmdL( + aCommandId, + aParamList, + iServHandlerRef->OutParamListL(), + 0, + NULL ); // Callback is NULL as no dial results wanted. + } + + //If missed list, clear now new missed calls counter + ClearMissedCallNotificationsL(); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::PrepareCallL +// +// Perform Voice, video or VoIP call. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::PrepareCallL( + TInt aCommandId, + TBool aCalledForMenu, + const MLogsEventGetter* aEvent, + TBool aForceVideo ) //Forces video call for non-voip events + { + //Quit if no event, phone number or sip uri + if( !aEvent || (!SipUriAvailable( aEvent ) && !PhoneNumberAvailable( aEvent ) )) + { + return; + } + + TBool isRead = aEvent->Event()->IsRead(); + TLogId logid = aEvent->LogId(); + TInt duplicates = aEvent->Duplicates(); + + CAiwDialData::TCallType callType( CAiwDialData::EAIWVoice ); + + if( aEvent->LogsEventData()->VoIP() ) + { + callType = CAiwDialData::EAIWVoiP; + } + else if( aForceVideo ) + { + callType = CAiwDialData::EAIWForcedVideo; + } + else if( aEvent->LogsEventData()->VT() ) + { + callType = CAiwDialData::EAIWVideo; + } + + //Create temporary TBuf that is transferred to CmdCallL in case sip-uri. This is ok as no asynch operations in + //CmdCallL, so tmp is alive long enough. Also stack consumption should not be too big, so no need for heap allocation. + TBuf buf; + + TPtrC tmp; + + if( aEvent->LogsEventData()->VoIP() ) + { + //In VoIP we prefer primarily try to use sip uri if available + if( SipUriAvailable( aEvent ) ) + { + if( Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), buf) != KErrNone ) + { + return; + } + tmp.Set( buf ); // sip-uri + } + else + { + tmp.Set( *( aEvent->Number() ) ); + } + } + else + { + //For voice and video calls use number + tmp.Set( *( aEvent->Number() ) ); + } + CmdCallL( aCommandId, + aCalledForMenu, + tmp, // *(event->Number()) or sip-uri + callType, + aEvent + ); + + if (isRead == EFalse && iModel == ELogsMissedModel) // If not read, the New missed icon is shown. By setting event read + { // the new missed icon is not shown when control comes back to Logs + Engine()->ClearNewMissedL()->SetNewMissedCallRead(logid, duplicates); + } + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdCallL +// +// Perform Voice, video or VoIP call. +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdCallL( + TInt aCommandId, + TBool aCalledForMenu, + TPtrC aNumberOrUrl, + CAiwDialData::TCallType aCallType, + const MLogsEventGetter* aEvent + ) + { + TRACE_ENTRY_POINT; + + if( !aNumberOrUrl.Length() ) + { + return; + } + + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsBaseView::CmdCallL - iServiceHandler: 0x%x"), iServHandlerRef); + + // We have a phone number or SIP URI, so let's set the dial data + +// Sawfish VoIP changes >>>> + CAiwDialDataExt* dialData = CAiwDialDataExt::NewLC(); + dialData->SetPhoneNumberL( aNumberOrUrl ); + dialData->SetCallType( aCallType ); + + if ( FeatureManager::FeatureSupported(KFeatureIdCommonVoip)) + { + MLogsEventData* eventData = aEvent->LogsEventData(); + if ( eventData ) + { + dialData->SetServiceId( eventData->ServiceId() ); + + if ( aCalledForMenu ) + { + // When call is initiated from log's menu + // - User can select service from list + dialData->SetServiceId( NULL ); + + TPtrC8 ptrContactLink( KNullDesC8 ); + if ( KErrNone == eventData->GetContactLink( ptrContactLink ) ) + { + CLogsCntLinkChecker* contactCheckerPtr = Engine()->CntLinkCheckerL(); + + SetInputBlockerL(); + + // If contact link is valid, dialData use contack link instead of number. + if ( contactCheckerPtr->IsCntLinkValidSync( ptrContactLink ) ) + { + dialData->SetContactLinkL(ptrContactLink ); + dialData->SetPhoneNumberL( KNullDesC ); + + // EJZO-7RJB3V,the CallUI will invoke phonebook2 to show the call selector, that will + // make logs receive ViewDeactivated/Lostforeground , then ViewActivated/Foreground events + //that will cause the logs view flicking.So the hack will avoid this using the following flag + iIgnoreViewDeactivatedHandling = ETrue; + } + + RemoveInputBlocker(); + } + } + } + } +// <<<< Sawfish VoIP changes + + dialData->SetWindowGroup( AIWDialData::KAiwGoToIdle ); + CAiwGenericParamList& paramList = iServHandlerRef->InParamListL(); + dialData->FillInParamListL( paramList ); + CleanupStack::PopAndDestroy( dialData ); + + // If this is an emergency number, initiate the call through the + // new emergency call API. We need to check the number, and not to trust + // the aEventType as for example CLogsPrependQuery might change the number + //// + TBool isEmergencyNumber = EFalse; + if (aNumberOrUrl.Length() <= KPhCltEmergencyNumberSize) + { + iEmergencyCallAPI->IsEmergencyPhoneNumber(aNumberOrUrl, isEmergencyNumber); + } + + if (isEmergencyNumber) + { + // in case there is already a pending asynch request + // we just skip calling the api again to avoid leaves + if ( !iEmergencyCallAPI->IsActive()) + { + iEmergencyCallAPI->DialEmergencyCallL(aNumberOrUrl); + } + } + + // If not an emergency call, initiate call through CallUI + // CallUI should be able to handle emergency calls too, but the + // safest and preffered way is to use Emergency Call API + //// + else if( !aCalledForMenu ) + // Execute direct command (CallUI shows list query + // if needed - i.e user has pressed Send key). + { + iServHandlerRef->ExecuteServiceCmdL( + aCommandId, + paramList, + iServHandlerRef->OutParamListL(), + 0, + NULL ); //Callback is NULL as no dial results wanted. + } + else + // Execute Menu based command (we have already shown + // Logs-AIW menu to user, so no menus wanted anymore) + { + iServHandlerRef->ExecuteMenuCmdL( + aCommandId, + paramList, + iServHandlerRef->OutParamListL(), + 0, + NULL ); //Callback is NULL as no dial results wanted. + } + + //If missed list, clear now new missed calls counter + ClearMissedCallNotificationsL(); + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleEmergencyDialL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleEmergencyDialL( const TInt /*aStatus */) + { + // TODO: Show some note to user if there is error? + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdCopyNumberL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdCopyNumberL( const MLogsEventGetter* aEvent ) + { + CPlainText* plainText = CPlainText::NewL(); + CleanupStack::PushL( plainText ); + + TInt length( 0 ); + const HBufC* number = aEvent->Number(); + + if( number ) + { + length = number->Length(); + } + + if( length && length <= KLogsPhoneNumberMaxLen ) + { + TBuf buf = *(aEvent->Number()); + AknTextUtils::LanguageSpecificNumberConversion( buf ); + plainText->InsertL( 0, buf ); + } + + CClipboard* cb = CClipboard::NewForWritingLC( iCoeEnv->FsSession() ); + plainText->CopyToStoreL( cb->Store(), cb->StreamDictionary(), 0, + plainText->DocumentLength() ); + cb->CommitL(); + CleanupStack::PopAndDestroy( 2 ); // plainText, cb + + CAknNoteDialog* noteDlg = new( ELeave ) CAknNoteDialog( CAknNoteDialog::ENoTone, + CAknNoteDialog::ELongTimeout ); + noteDlg->ExecuteLD( R_NUMBER_COPIED_TO_CB_NOTE ); + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdCopyAddressL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdCopyAddressL( const MLogsEventGetter* aEvent ) + { + TBuf buf; + TInt ret = Engine()->ConvertToUnicode( aEvent->LogsEventData()->Url(), buf ); + + if( ret != KErrNone && ret != KErrOverflow ) + { + return; //Converting uri to unicode failed + } + + CPlainText* plainText = CPlainText::NewL(); + CleanupStack::PushL( plainText ); + TInt length( buf.Length() ); + + if( length && length <= KLogsSipUriMaxLen ) + { + TBuf bufConv = buf; + AknTextUtils::LanguageSpecificNumberConversion( bufConv ); + plainText->InsertL( 0, bufConv ); + } + + CClipboard* cb = CClipboard::NewForWritingLC( iCoeEnv->FsSession() ); + plainText->CopyToStoreL( cb->Store(), cb->StreamDictionary(), 0, + plainText->DocumentLength() ); + cb->CommitL(); + CleanupStack::PopAndDestroy( 2 ); // plainText, cb + + HBufC* textBuf = NULL; + + if( aEvent->LogsEventData()->VoIP() ) + { + textBuf = StringLoader::LoadLC( R_VOIP_ADDRESS_COPIED ); + } + else + { + textBuf = StringLoader::LoadLC( R_POC_ADDRESS_COPIED ); + } + + //FIXME: The CAknInformationNote seems to overwritten by toolbar even if toolbar is requested + //to be hidden (compared to CAknNoteDialog above that works ok. If not later fixedby toolbar + //itself, convert here to use CAknNoteDialogs also using note resoruces. + CAknInformationNote* noteDlg = new( ELeave ) CAknInformationNote( ); + noteDlg->ExecuteLD( *textBuf ); + CleanupStack::PopAndDestroy( textBuf ); + } + + +// ---------------------------------------------------------------------------- +// CLogsBaseView::CmdShowMyAddressL +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::CmdShowMyAddressL( const MLogsEventGetter* aEvent ) + { + TBuf buf; + TInt ret = Engine()->ConvertToUnicode( aEvent->LogsEventData()->MyAddress(), buf ); + + if( ret != KErrNone && ret != KErrOverflow ) + { + return; //Converting uri to unicode failed + } + + HBufC* textBuf = NULL; + textBuf = StringLoader::LoadLC( R_STM_MY_ADDRESS, buf ); + CAknNoteDialog* noteDlg = new ( ELeave ) CAknNoteDialog( ); + noteDlg->SetTextL( *textBuf ); + noteDlg->ExecuteLD( R_MY_ADDRESS_QUERY ); + CleanupStack::PopAndDestroy( textBuf ); + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleNotifyL +// +// Handle AIW-notifications (from asynch ExecuteCmdL call) +// ---------------------------------------------------------------------------- +// +TInt CLogsBaseView::HandleNotifyL( + TInt aCmdId, + TInt aEventId, + CAiwGenericParamList& /* aEventParamList */, + const CAiwGenericParamList& /* aInParamList */ ) + { + //Only EGenericParamContactLinkArray available in aEventParamList so we use iNumberInPbkProcessing instead + + TInt retVal = 0; + //Currently we're only interested in result of contact addition to pbk + if( aCmdId == KAiwCmdAssign ) + { + switch( aEventId ) + { + case KAiwEventStarted: + break; + + // If selecting Options->Exit KAiwEventError will result but the contact may have + // still been created so start updater + case KAiwEventError: + case KAiwEventCompleted: // Asynch req completed. Right softkey "Done" selected for contact editor + { + //Enable UI for db-originated changes (however focus needs to be kept unchanged) + CurrentModel()->DoActivateL( MLogsModel::EActivateOnly ); + + //If number was updated to pbk, update it to Logs too (number preferred over sip uri) + if( iNumberInPbkProcessing ) + { + Engine()->EventUpdaterL()->Stop(); //Stop previous updating process + MLogsReaderConfig* readerConfig = CLogsReaderConfigFactory:: + LogsReaderConfigLC( iNumberInPbkProcessing ); + Engine()->EventUpdaterL()->ConfigureL( readerConfig ); + CleanupStack::PopAndDestroy(); //readerConfig + Engine()->EventUpdaterL()->StartL();//Start asynch process of reading the name from Pbk, updating Logs event + //and eventually notification of changed db data to respective Logs view. + //Note: UI Data refresh is started in CLogsEngine::StateChangedL when event updater is finished + + } + else if( iUriInPbkProcessing ) + { + //We don't support updating URIs, so nothing done, just refresh the model. + CurrentModel()->DoActivateL( MLogsModel::ERefresh ); + } + + delete iNumberInPbkProcessing; + delete iUriInPbkProcessing; + iNumberInPbkProcessing = NULL; + iUriInPbkProcessing = NULL; + ClearAiwCallParams(); + + break; + } + + case KAiwEventQueryExit: // Contact could still be created so start updater + { + // Fix for EPZO-6YWDXY: we must return "true" for the + // phonebook to know it can exit + retVal = 1;// "ETrue" + break; + } + + case KAiwEventCanceled: //Cancel pressed in Pbk UI + { + delete iNumberInPbkProcessing; + delete iUriInPbkProcessing; + iNumberInPbkProcessing = NULL; + iUriInPbkProcessing = NULL; + ClearAiwCallParams(); + + if ( LogsAppUi()->ActiveViewId() == Id().iUid && + LogsAppUi()->ExecutionMode() == ELogsInForeground ) + { + //Refresh UI + CurrentModel()->DoActivateL( iResetAndRefreshOnHandleNotify ); + } + + iResetAndRefreshOnHandleNotify = MLogsModel::ERefresh; + break; + } + case KAiwEventOutParamCheck: + case KAiwEventInParamCheck: + case KAiwEventStopped: + + default: + { + //Refresh UI + CurrentModel()->DoActivateL( MLogsModel::ERefresh ); + break; + } + } + + // Remove inputblocker if still exists + RemoveInputBlocker(); + MenuBar()->StopDisplayingMenuBar(); + } + + return retVal; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::IsOkToShowContextMenu +// ---------------------------------------------------------------------------- +// +TBool CLogsBaseView::IsOkToShowContextMenu( const MLogsEventGetter* aEvent ) + { + //aEvent may not yet be available + if( !aEvent || aEvent->EventType() == ETypeEmerg ) + { + return EFalse; + } + + if( PhoneNumberAvailable( aEvent ) || SipUriAvailable( aEvent ) ) + { + return ETrue; + } + + return EFalse; + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::HandleControlEventL +// +// from MCoeControlObserver +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::HandleControlEventL( + CCoeControl* /* aControl */, + TCoeEvent /* aEventType */ ) + { + } + +// ---------------------------------------------------------------------------- +// CLogsBaseView::SetToolbarItems +// ---------------------------------------------------------------------------- +// +void CLogsBaseView::SetToolbarItems( + const MLogsEventGetter* aEvent ) + { + TRACE_ENTRY_POINT; + + if (AknLayoutUtils::PenEnabled() ) + { + CAknToolbar* toolbar = Toolbar(); + if( !toolbar ) + { + return; + } + + //aEvent may not yet be available, show only open pbk selection then + if( !aEvent ) + { + toolbar->SetItemDimmed( ELogsCmdSendKeyCall, ETrue, EFalse ); + toolbar->SetItemDimmed( ELogsCmdToolBarSendUi, ETrue, EFalse ); + } + else + { + TBool emerg( aEvent->EventType() == ETypeEmerg ); + TBool nbr( PhoneNumberAvailable( aEvent )); + TBool voipUri( SipUriAvailable( aEvent ) && aEvent->LogsEventData()->VoIP() ); + TBool pocUri( SipUriAvailable( aEvent ) && aEvent->LogsEventData()->PoC() ); + toolbar->SetItemDimmed( ELogsCmdSendKeyCall, !nbr && !voipUri && !pocUri, EFalse ); + toolbar->SetItemDimmed( ELogsCmdToolBarSendUi, !nbr || emerg, EFalse ); + } + + //aToolbar->DrawNow(); + toolbar->DrawDeferred(); + } + TRACE_EXIT_POINT; + } + +// End of File + +