diff -r 000000000000 -r e686773b3f54 logsui/AppSrc/CLogsRecentListView.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/logsui/AppSrc/CLogsRecentListView.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,1253 @@ +/* +* 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: +* Abstract base class for recent views +* +*/ + + +// INCLUDE FILES + +// System includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //KAiwCmdCall +#include //TAiwPocParameterData +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Virtual Phonebook +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//------------------------ + +#include "CLogsRecentListView.h" +#include "CLogsRecentListControlContainer.h" +#include "CLogsEngine.h" +#include "MLogsEventGetter.h" +#include "MLogsClearLog.h" +#include "MLogsStateHolder.h" +#include "MLogsSharedData.h" +#include "CLogsAppUi.h" +#include "LogsUID.h" +#include "CLogsViewGlobals.h" +#include "MLogsExtensionFactory.h" +#include "MLogsViewExtension.h" +#include "MLogsSystemAgent.h" +#include "MLogsUiControlExtension.h" +#include "LogsConstants.hrh" +#include "CLogsPrependQuery.h" + +#include "LogsDebug.h" +#include "LogsTraces.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// Panic string +_LIT( KStmRecentView, "StmRecentView" ); + +// MACROS + + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// ================= MEMBER FUNCTIONS ======================= + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::NewL +// ---------------------------------------------------------------------------- +// +CLogsRecentListView* CLogsRecentListView::NewL( TLogsModel aModel ) + { + CLogsRecentListView* self = new ( ELeave ) CLogsRecentListView( aModel ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); // self + return self; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::CLogsRecentListView +// ---------------------------------------------------------------------------- +// +CLogsRecentListView::CLogsRecentListView( TLogsModel aModel ) : + iState( EStateUndefined ), + iViewExtension( NULL ), + iEventListCurrentNoChange( KErrNotFound ) //iEventListCurrentNoChange switched off + { + iModel = aModel; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::~CLogsRecentListView +// ---------------------------------------------------------------------------- +// +CLogsRecentListView::~CLogsRecentListView() + { + delete iExitCbaButton; + delete iBackCbaButton; + iCoeEnv->RemoveForegroundObserver( *this ); + + Release( iViewExtension ); + Release( iViewGlobal ); + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ConstructL +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::ConstructL() + { + BaseConstructL( R_STM_COMMON_VIEW ); + iCoeEnv->AddForegroundObserverL( *this ); + iExitCbaButton = iCoeEnv->AllocReadResourceL( R_STM_EXIT_CBA_BUTTON ); + iBackCbaButton = iCoeEnv->AllocReadResourceL( R_STM_BACK_CBA_BUTTON ); + iViewGlobal = CLogsViewGlobals::InstanceL(); + +// Safwish VoIP changes >>> + if ( !iViewExtension ) + { + CPbkContactEngine* nullContactEngine = NULL; + iViewExtension = iViewGlobal->ExtensionFactoryL(). + CreateLogsViewExtensionL( *nullContactEngine, this ); + + iViewExtension->SetSendUi( *LogsAppUi()->SendUiL() ); + iViewExtension->SetSendUiText( SendUiTextL() ); + } +// <<< Safwish VoIP changes + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::LogsCurrentRecentViewId +// ---------------------------------------------------------------------------- +// +TLogsViewIds CLogsRecentListView::LogsCurrentRecentViewId() const + { + switch( iModel ) + { + case ELogsReceivedModel: + return EStmReceivedListViewId; + case ELogsDialledModel: + return EStmDialledListViewId; + case ELogsMissedModel: + return EStmMissedListViewId; + default: + User::Panic( KStmRecentView, KErrUnknown ); + return ELogsDummyViewId; // just to compile without error + //break; + } + } + + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::Id +// ---------------------------------------------------------------------------- +// +TUid CLogsRecentListView::Id() const + { + return TUid::Uid( LogsCurrentRecentViewId() ); + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::RecentListType +// ---------------------------------------------------------------------------- +// +TLogsModel CLogsRecentListView::RecentListType() const + { + return iModel; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ProcessKeyEventL +// +// Called by base control container when a key press happens. +// ---------------------------------------------------------------------------- +// +TBool CLogsRecentListView::ProcessKeyEventL( + const TKeyEvent& aKeyEvent, + TEventCode aType ) + { + if( MenuBar()->ItemSpecificCommandsEnabled() && aType == EEventKey ) + { + if( aKeyEvent.iCode == EKeyBackspace ) + { + HandleCommandL( ELogsCmdMenuDelete ); + return ETrue; + } + } + + const MLogsEventGetter* event( CurrentEvent() ); + + //FIXME (CLogsRecentListView and CLogsEventListView): + //The below is needed only because we get key event before the actual row + //is changed in the listbox. If/when listbox observer for changed row focus + //is available, remove code below and get correct event index from observer. + SetEventListCurrent(iContainer->ListBox()->CurrentItemIndex()); + + if( aType == EEventKey && EventListCurrent() != KErrNotFound ) + { + TInt count( CurrentModel()->Count() ); + switch (aKeyEvent.iScanCode) + { + case EStdKeyUpArrow: + //Set iEventListCurrent + jump to previous or last event depending on position in list + iEventListCurrent > 0 ? event = CurrentModel()->At( --iEventListCurrent ) : + event = CurrentModel()->At( iEventListCurrent = count - 1 ); + break; + + case EStdKeyDownArrow: + //Set iEventListCurrent + jump to next or first event depending on position in list + iEventListCurrent < count - 1 ? event = CurrentModel()->At( ++iEventListCurrent ) : + event = CurrentModel()->At( iEventListCurrent = 0 ); + break; + } + } + + + return CLogsBaseView::ProcessKeyEventEventL( aKeyEvent,aType, event ); + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ProcessPointerEventL +// +// Handler for pointer events, when the current focused item is tapped +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::ProcessPointerEventL( TInt /* aIndex */ ) + { + // Open the context sensitive menu + ProcessCommandL( EAknSoftkeyContextOptions ); + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::HandleCommandL +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::HandleCommandL( TInt aCommandId ) + { + TRACE_ENTRY_POINT; + +// Safwish VoIP changes >>> + //1. Process first the commands that may be in range interested by PECLogs exension + if ( iViewExtension->HandleCommandL( aCommandId ) ) + { + return; + } +// <<< Safwish VoIP changes + + //2. Was not a command in range intended for extension. Continue processing. + const MLogsEventGetter* event = CurrentEvent(); + + switch( aCommandId ) + { + case ELogsCmdMenuDeleteAll: + CmdClearRecentListL(); + break; + + case ELogsCmdMenuDelete: + CmdDeleteEventL(); + break; + + case ELogsCmdHandleMSK: + { + // If single click or press MSK for a log event, + // it will request directly by AiwSrvCmd. + aCommandId = ELogsCmdSingleTapCall; + } // Fall through + + default: + { + CLogsBaseView::HandleCommandEventL( aCommandId, event ); + } + } + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ChangeTitlePaneTextToDefaultL +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::ChangeTitlePaneTextToDefaultL() + { + iContainer->SetTitlePaneTextToDefaultL( LogsAppUi()->ActiveViewId() ); + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ProcessCommandL +// +// Called from FW when e.g. cba pressed +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::ProcessCommandL( TInt aCommand ) + { + TRACE_ENTRY_POINT; + + if (LogsAppUi()->ActiveViewId() != LogsCurrentRecentViewId() || !iContainer ) + { + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsRecentListView::ProcessCommandL - view already deactivated! return " )); + return; + } + + if (aCommand == EAknSoftkeyOptions) + { + // If options menu is opened call SetRefreshMenuOnUpdate which records the current event id + // which can then be used to make a decision on wether options menu needs to be refreshed + // when reading is finished. + SetRefreshMenuOnUpdate( CurrentEvent() ); + } + + CLogsBaseView::ProcessCommandL( aCommand ); + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::DynInitMenuPaneL +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::DynInitMenuPaneL( + TInt aResourceId, + CEikMenuPane* aMenuPane ) + { + //Get event. Note that event may NOT yet be available if asynch request(s) are not completed. + const MLogsEventGetter* event = CurrentEvent(); //returns NULL if no data yet available + CLogsBaseView::DynInitMenuPaneEventL( aResourceId, aMenuPane, event ); + +// Sawfish VoIP changes >>> + iViewExtension->DynInitMenuPaneL( aResourceId, aMenuPane, event ); +// <<< Sawfish VoIP changes + + } + + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::HandleClientRectChange +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::HandleClientRectChange() + { + if (iContainer) + { + iContainer->SetRect( ClientRect() ); + } + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::DrawComponents +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::DrawComponents() + { + if (iContainer) + { + iContainer->DrawNow(); + } + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ViewDeactivated +// +// This is called by framework when really losing foreground but not when losing foreground to some note etc. +// Also called by framework when switching views inside application. +// So DoDeactivate is not always called when ViewDeactivated is called. +// +// Note: there is no guarenteed order of which is called first ViewDeactivated or HandleLosingForeground +// +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::ViewDeactivated() + { + // When view is deactivated due to losing foreground we reset the list here in advance so there won't be + // flickering of the old list. Since view server introduced redraw storing the HandleGainingForeground + // comes too late and the old list will flicker before it is reseted. + // We'll skip this when Phonebook update pending - the list is going to be updated later. + // + // If we would do this in HandleLosingForeground, then the list would be emptied when for example when + // active applications list, global note etc. is shown. + // + if (CurrentModel() && iContainer && ( iFocusChangeControl != ELogsNoChange_PbkUpdPending ) ) + { + + // EJZO-7RJB3V + if (IgnoreViewDeactivatedOperation()) + { + CAknView::ViewDeactivated(); + return; + } + + if (iFocusChangeControl != ELogsOkToChange) + { + StoreEvenListCurrentFocus(); + } + + // Reset array and set dirty which means refresh requested, + // will call StateChangedL with state EStateArrayReseted and update the listbox. + CurrentModel()->DoDeactivate( MLogsModel::ESkipClearing, + MLogsModel::EResetOnlyArrayWithDirty ); + + // On gaining foreground, do a clean read of events + iResetAndRefreshOnGainingForeground = MLogsModel::EResetAndRefresh; + } + + CAknView::ViewDeactivated(); + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::DoActivateL +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::DoActivateL( + const TVwsViewId& aPrevViewId, + TUid aCustomMessageId, + const TDesC8& aCustomMessage ) + { + TRACE_ENTRY_POINT; + + CLogsBaseView::DoActivateL( aPrevViewId, aCustomMessageId, aCustomMessage ); + + //To prevent first time flicker of context menu if no ctx mnu will be displayed + Cba()->MakeCommandVisible( EAknSoftkeyContextOptions, EFalse ); + + iFocusChangeControl = ELogsOkToChange; + iEventListCurrentNoChange = KErrNotFound; + + LogsAppUi()->SetCurrentViewId( Id() ); + + //To avoid possible flicker, change the cba text to 'Exit' when going to background + //but don't draw it. Sometimes CAknView::ConstructMenuAndCbaL might draw the cba + //when we are going to background and activating dialled calls view. It is safer + //to have the cba thus set as 'Exit' + if( aCustomMessageId.iUid == ELogsViewActivationBackground && + LogsAppUi()->ExecutionMode() == ELogsInBackground_ExitOrEndPressed ) + { + ChangeCba2ToExitL( ELogsDontDraw ); + } + else if ( LogsAppUi()->ProvideOnlyRecentViews()) + { + LogsAppUi()->SetPreviousAppUid( aPrevViewId.iAppUid ); + LogsAppUi()->SetPreviousViewId( aPrevViewId.iViewUid ); + Engine()->DeleteConfig(); //Logs settings + ChangeCba2ToExitL( ELogsDrawNow ); //We must not be able to back to other Logs views, just exit + } + else + { + ChangeCba2ToBackL(); + } + + + Engine()->CreateModelL( iModel ); //Creates model only if not yet exists + + //Create the control container. + if( !iContainer ) + { + iContainer = CLogsRecentListControlContainer::NewL( this, ClientRect() ); + AppUi()->AddToViewStackL( *this,iContainer ); + } + iContainer->ListBox()->SetListBoxObserver( this ); + + //External launch has been done already, so come here + if ( ! LogsAppUi()->ProvideOnlyRecentViews() ) + { + LogsAppUi()->SetPreviousAppUid( TUid::Uid( KLogsAppUID3 ) ); + LogsAppUi()->SetPreviousViewId( aPrevViewId.iViewUid ); + } + + //Update item selection. Set always focus to top. If previous focus is to be retained, comment below two rows out + SetEventListCurrent(0); + SetEventListTop(0); + + CurrentModel()->SetObserver( this ); + + if( aCustomMessageId.iUid == ELogsViewActivationBackground && + LogsAppUi()->ExecutionMode() == ELogsInBackground_ExitOrEndPressed ) + { + // We have activated this view because we are hiding Logs into background (faking exit) + // so this view is waiting when Logs is again foregrounded. + // + // With MLogsModel::ECloseDBConnectionAndResetArray the connection to the database is + // closed and event array will be deleted. Calls StateChangedL with state EStateArrayReseted + // which will update the listbox to empty state. + CurrentModel()->DoDeactivate( MLogsModel::ENormalOperation, + MLogsModel::ECloseDBConnectionAndResetArray ); + + // Now we can enable bring-to-foreground on view activation: + AppUi()->SetCustomControl(0); + AppUi()->HideInBackground(); + // When coming back to foreground, do a clean read of events + iResetAndRefreshOnGainingForeground = MLogsModel::EResetAndRefresh; + } + else + { + // Just to make sure the inputblocker is not on + RemoveInputBlocker(); + CurrentModel()->DoActivateL( MLogsModel::EResetAndRefresh ); + + // By default on gaining foreground, just refresh the list. So when active applications list, + // keylock or some note (like when plugin in the charger) is shown the list doesn't flicker. + // When view is deactivated this is set to MLogsModel::EResetAndRefresh. + iResetAndRefreshOnGainingForeground = MLogsModel::ERefresh; + } + + + if( CurrentModel()->Count() ) + { + iContainer->ListBox()->SetTopItemIndex( EventListTop() ); + if( EventListCurrent() < 0 ) + { + SetEventListCurrent(0); + } + iContainer->ListBox()->SetCurrentItemIndex( EventListCurrent() ); + } + + ClearMissedCallNotificationsL(); //Clear cenrep new missed calls counter + notifications (however, possible missed + //list duplicate counters need to be cleared separately). + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ReadingFinished +// ---------------------------------------------------------------------------- +// +TBool CLogsRecentListView::ReadingFinished() + { + TBool finished = ( iState != EStateActive && iState != EStateUndefined && + iState != EStateInitializing && iState != EStateSemiFinished && + iState != EStateInterrupted ); + + return finished; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::IgnoreViewDeactivatedOperation +// ---------------------------------------------------------------------------- +// +TBool CLogsRecentListView::IgnoreViewDeactivatedOperation() + { + TBool ret = EFalse; + if (iIgnoreViewDeactivatedHandling) + { + // no guarenteed order of which is called first ViewDeactivated or HandleLosingForeground, + // so add the iSemiFinishViewDeactivatedOperation flag + if (iSemiFinishViewDeactivatedOperation) + { + iIgnoreViewDeactivatedHandling = EFalse; + iSemiFinishViewDeactivatedOperation = EFalse; + } + else + { + iSemiFinishViewDeactivatedOperation = ETrue; + } + + ret = ETrue; + } + + return ret; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::DoDeactivate +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::DoDeactivate() + { + TRACE_ENTRY_POINT; + + CLogsBaseView::DoDeactivate(); + + if( iContainer ) + { + SetEventListCurrent(iContainer->ListBox()->CurrentItemIndex()); + SetEventListTop(iContainer->ListBox()->TopItemIndex()); + AppUi()->RemoveFromViewStack( *this, iContainer ); + delete iContainer; + iContainer = NULL; + } + + if( iModel == ELogsMissedModel ) + { + // Below we test for reading finshed to prevent unnecessary clearing of duplicate counters, + // new missed call icons and missed call notification and the "x missed calls" text + // in the Call register view. + // + // This would otherwise be done when user reopens Logs by + // green key or from appshell after first leaving Missed calls view to background. + // + // (Missed calls view will first receive HandleGainingForeground followed by an + // immediate DoDeactivate ) + // + // FIXME: This fix is not 100% sure cause it might happen rarely that the reading has time to + // finish before framework activates the actual view that was opened (and calls DoDeactivate for + // missed calls view). No better solution found yet though. + // + if ( ReadingFinished() ) + { + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsRecentListView::DoDeactivate - ReadingFinished" )); + ClearMissedCallNotifications(); //Clear cenrep new missed calls counter + notifications + CurrentModel()->DoDeactivate( MLogsModel::ENormalOperation, + MLogsModel::ECloseDBConnection );//ETrue: disconnect from db. This helps for EMSH-6JDFBV but + //reduces user's perceived performance for other views + //(seems to keep clearing of missed duplicates process alive + // so no need for EFalse here as it would increase probability of + // EMSH-6JDFBV occurring again + + } + + else + { + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsRecentListView::DoDeactivate - Reading interrupted" )); + CurrentModel()->DoDeactivate( MLogsModel::ESkipClearing, + MLogsModel::ECloseDBConnection ); + } + } + else + { + CurrentModel()->DoDeactivate( MLogsModel::ENormalOperation, + MLogsModel::ECloseDBConnection );//ETrue: disconnect from db. This helps for EMSH-6JDFBV but + //reduces user's perceived performance for other views + //EFalse: don't disconnect from db. This keeps read data cached in Logs. + } + + //To prevent second time flicker of context menu if ctx mnu was was displayed + //but will not later be displayed + Cba()->MakeCommandVisible( EAknSoftkeyContextOptions, EFalse ); + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::CmdClearRecentListL +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::CmdClearRecentListL() + { + if( CurrentModel()->Count() ) + { + TInt resId( 0 ); + + CAknQueryDialog* queryDlg = CAknQueryDialog::NewL(); + + switch( iModel ) + { + case ELogsMissedModel: + resId = R_CLEAR_MISSED_LIST_CONFIRMATION_QUERY; + break; + + case ELogsReceivedModel: + resId = R_CLEAR_RECEIVED_LIST_CONFIRMATION_QUERY; + break; + + case ELogsDialledModel: + resId = R_CLEAR_DIALLED_LIST_CONFIRMATION_QUERY; + break; + + default: + User::Panic( KStmRecentView, KErrUnknown ); + break; + } + + if( queryDlg->ExecuteLD( resId ) ) + { + Engine()->ClearLogsL()->ClearModelL( iModel ); + SetEventListTop(0); + SetEventListCurrent(0); + + SetInputBlockerL(); + } + } + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::CmdDeleteEventL +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::CmdDeleteEventL() + { + if( CurrentModel()->Count() && iContainer->ListBox()->CurrentItemIndex() != KErrNotFound ) + { + CAknQueryDialog* queryDlg = CAknQueryDialog::NewL(); + SetEventListTop(iContainer->ListBox()->TopItemIndex()); + SetEventListCurrent(iContainer->ListBox()->CurrentItemIndex()); + + TLogId id = CurrentModel()->At( EventListCurrent() )->LogId(); + + if( queryDlg->ExecuteLD( R_DELETE_CONFIRMATION_QUERY ) ) + { + iEventListCurrentNoChange = iContainer->ListBox()->CurrentItemIndex(); + Engine()->ClearLogsL()->DeleteEventL( id ); //Delete the event from LogDb. Event from view gets + //removed when the view data is reread from db. + iFocusChangeControl = ELogsNoChange; //Prevent focus moving to top when list is reread + } + } + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ChangeCba2ToExitL +// ---------------------------------------------------------------------------- +// +TBool CLogsRecentListView::ChangeCba2ToExitL( TLogsDrawNow aDrawNow ) + { + //We must attempt to change CBA only if we have correct view in the foreground + if( LogsAppUi()->ActiveViewId() != LogsCurrentRecentViewId() ) + { + return EFalse; //There is some other view already active, so we don't have + } // our own cba's present + + TInt pos = Cba()->PositionById( EAknSoftkeyBack ); + + if( pos > 0 ) + { + Cba()->SetCommandL( pos, + ELogsCmdMenuExit, + iExitCbaButton->Des() ); + + if (aDrawNow == ELogsDrawNow) + { + Cba()->DrawNow(); + } + + return ETrue; + } + + return EFalse; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ChangeCba2ToBackL +// ---------------------------------------------------------------------------- +// +TBool CLogsRecentListView::ChangeCba2ToBackL() + { + if( LogsAppUi()->ActiveViewId() != LogsCurrentRecentViewId() ) + { + return EFalse; //There is some other view already active, so we don't have our own cba's present + } // (e.g. FSW can be brought to foreground already) + + TInt pos = Cba()->PositionById( ELogsCmdMenuExit ); + + if( pos > 0 ) + { + Cba()->SetCommandL( pos, + EAknSoftkeyBack, + iBackCbaButton->Des() ); + Cba()->DrawNow();//Needed when this view already been open and cba changed in other view + + return ETrue; + } + + return EFalse; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::HandleGainingForeground +// +// This function is called once for each already constructed Recent 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 CLogsRecentListView::HandleGainingForeground() + { + TRACE_ENTRY_POINT; + + CLogsBaseView::HandleGainingForeground(); + + //Process cba if this view is already open and then just brought to foreground + //in ProvideOnlyRecentViews mode + if( LogsAppUi()->ProvideOnlyRecentViews() ) + { + TRAPD( err, ChangeCba2ToExitL( ELogsDrawNow ) ); + if( err ) + { + iCoeEnv->HandleError( err ); + } + + // Always reset focus to the top of the list, when Logs is opened by a send key + // press from idle + if (LogsAppUi()->LogsOpenedWithSendKey() && LogsCurrentRecentViewId() == EStmDialledListViewId) + { + iFocusChangeControl = ELogsOkToChange; + iEventListCurrentNoChange = KErrNotFound; + LogsAppUi()->SetLogsOpenedWithSendKey(EFalse); // reset the send key checking + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsRecentListView::HandleGainingForeground - LogsOpenedWithSendKey: reset focus" )); + } + } + + //Activate current view's model that we deactivated in HandleLosingForeground(). + //No need to check if already active, DoActivateL() handles this. + if( LogsAppUi()->ActiveViewId() == LogsCurrentRecentViewId() && iContainer ) //Only if this object corresponds + //to current view. + { + MLogsModel* model = CurrentModel(); + + //ELogsNoChange is special case here, i.e contact just added to pbk: skip activating to avoid unwanted UI-focus change. + //We don't know in hw which is finished first, reading of entries because of gaining of foreground (EMSH-6JDFBV) here or + //re-reading of entries because change observed in db, or will the first db-read have enough time to finish before. + if( model ) + { + if( iFocusChangeControl != ELogsNoChange_PbkUpdPending) + { + //If menu is shown, we need to close it as focus is lost + if (MenuBar()->IsDisplayed()) + { + MenuBar()->StopDisplayingMenuBar(); + } + + SetEventListCurrent( KErrNotFound );//just to make sure that UI does not try to read anything from eventarray + TRAPD( err, model->DoActivateL( iResetAndRefreshOnGainingForeground ) ); + if( err ) + { + iCoeEnv->HandleError( err ); + } + + // By default on gaining foreground, just refresh the list. So when active applications list, + // keylock or some note (like when plugin in the charger) is shown the list doesn't flicker. + // When view is deactivated this is set to MLogsModel::EResetAndRefresh. + iResetAndRefreshOnGainingForeground = MLogsModel::ERefresh; + } + else + { + // Change ELogsNoChange_PbkUpdPending to ELogsNoChange now so there is no need to + // differentiate those in StateChangedL + iFocusChangeControl = ELogsNoChange; + } + } + + RemoveInputBlocker(); //just in case + } + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::StoreEvenListCurrentFocus() +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::StoreEvenListCurrentFocus() + { + // + // Check that not called from deactivated recent list view that also gets + // a notification of losin foreground. + if (!iContainer || LogsAppUi()->ActiveViewId() != LogsCurrentRecentViewId()) + { + return; + } + + // Store the current focused item. Sometimes foreground can be regained for only very briefly and + // event reading is not finished so skip those situations. + // Also there is no guarantees which is called fist, HandleLosingForeground + // or ViewDeactivated so don't change when list is already deleted. + // + if( (iContainer->ListBox()->CurrentItemIndex() != KErrNotFound) && ReadingFinished() ) + { + SetEventListCurrent(iContainer->ListBox()->CurrentItemIndex()); + + // Switch on iEventListCurrentNoChange: store the current item index to + // keep it over effects of loss and gain of foreground. + iEventListCurrentNoChange = EventListCurrent(); + SetEventListTop(iContainer->ListBox()->TopItemIndex()); + } + // + // If the list has no focus and iEventListCurrentNoChange is not set, let the focus go + // to the top of the list when events are reread. + else if ( ( iContainer->ListBox()->CurrentItemIndex() == KErrNotFound ) && + ( iEventListCurrentNoChange == KErrNotFound ) ) + { + iFocusChangeControl = ELogsOkToChange; + } + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::HandleLosingForeground +// +// This function is called once for each type of already constructed recent view (e.g.when fast swapping +// window is brought to foreground). +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::HandleLosingForeground() + { + TRACE_ENTRY_POINT; + CLogsBaseView::HandleLosingForeground(); + + TBool finished = ReadingFinished(); + TLogsViewIds currView = LogsCurrentRecentViewId(); + + + if ( iContainer && ( LogsAppUi()->ActiveViewId() == currView )) + { + // EJZO-7RJB3V + if (IgnoreViewDeactivatedOperation()) + { + TRACE_EXIT_POINT; + return; + } + + // If we are losing foreground in the middle of event reading, force empty text to the view. + // This happens for example when keys are locked EYSN-6X5DYS + if (!finished) + { + // Does not have effect if list is not empty + iContainer->ForceEmptyTextListBox(); + } + // + // If focus is to be kept (iFocusChangeControl is ELogsNoChange or + // ELogsNoChange_PbkUpdPending) store the current focused item + if ( iFocusChangeControl != ELogsOkToChange ) + { + StoreEvenListCurrentFocus(); + } + } + + // The below is additional code for tuning performance consumption. It can be removed when no need + // for this is found as the code below does not affect functionality. + // For performance consumption reasons (EMSH-6JDFBV) we need to deactivate the + // current view when we lose foreground. However, this needs to be done only for + // missed calls view as other views should not be affected by this. However we do it for dialled calls in order + // to prevent old wrong entry staying a while in top of list when redialing from dialled list. + // + // Update: apply the same for Received calls view. This is needed to to avoid inconsistency + // between the views, like in EYSN-6X5DYS + // + if( ( LogsAppUi()->ActiveViewId() == currView ) && //Only if this object corresponds to current view. + ( currView == EStmMissedListViewId || + currView == EStmDialledListViewId || + currView == EStmReceivedListViewId ) ) + { + MLogsModel* model = CurrentModel(); + if( model ) + { + // End key pressed in missed calls view: sent to background before the Dialled calls view + // is activated while in background. so need to clear duplicates now since the reader is deleted + // and they cannot be cleared in DoDeactivate anymore + if( LogsAppUi()->ExecutionMode() == ELogsInBackground_ExitOrEndPressed && currView == EStmMissedListViewId ) + { + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsRecentListView::HandleLosingForeground - clear duplicates" )); + model->DoDeactivate( MLogsModel::ENormalOperation, + MLogsModel::ECloseDBConnection ); //EFalse: don't disconnect from db + } + else + { + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsRecentListView::HandleLosingForeground - skip clearing" )); + //Other loss of foreground (call or AppKey). We'll not touch duplicate counters + model->DoDeactivate( MLogsModel::ESkipClearing, //Don't update db (for missed view) + MLogsModel::ECloseDBConnection ); //ETrue: disconnect from db in order to immediately to stop + //EFalse: don't disconnect from db + } + } + } + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::StateChangedL +// +// CLogsModel informs it has changed event array, e.g. added entry to array or reseted the array etc. +// This function is called as many times as there is new/changed row in the event array. +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::StateChangedL( MLogsStateHolder* aHolder ) + { + TRACE_ENTRY_POINT; + + if( !aHolder ) + { + return; + } + + iState = aHolder->State(); + + // When check contact link finished, call base method to check if need to + // refresh menu. + if( iState == EStateCheckContactLinkFinished ) + { + CLogsBaseView::StateChangedL(aHolder); + return; + } + + //Call Update() when related items available to show changes immediately plus when reading is finished. + const TInt KNbrShownEntries = 8; + + iState = aHolder->State(); + LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING + ( "CLogsRecentListView::StateChangedL - iState:%d iFocusChangeControl:%d viewid:%d"), + iState, iFocusChangeControl, LogsCurrentRecentViewId() ); + + // If there was some error reading events - most likely KErrNoMemory, + // display information to user and close Logs + if( iState == EStateError ) + { + iCoeEnv->HandleError(KErrNoMemory); + LogsAppUi()->CmdExit(); + } + + //A. If reader deleted (EMSH-6JDFBV), stop all processing. + if( iState == EStateReaderDeletedOrStopped ) + { + return; + } + // Special case, array is reseted so update the list to empty state. This prevents flicker + // of the old list when regaining foreground + else if ( iState == EStateArrayReseted ) + { + if( iContainer ) + { + iContainer->UpdateL(); + } + return; + } + + //B. Continue to show contents quickly and without flicker when enough events available + if( iContainer ) + { + //1. Check are we finished and set scroll bars + TInt count( iContainer->ListBox()->Model()->NumberOfItems() ); //Current count of items CLogsModel has read into item array + TBool finished = ReadingFinished(); + CEikScrollBarFrame* sbFrame = iContainer->ListBox()->ScrollBarFrame(); + + if( finished || iState == EStateSemiFinished) //To avoid scroll bar flicker don't show scroll bar until completely finished + { + sbFrame->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOn ); + } + else if (count == 0) + { + sbFrame->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOff ); + } + + //2. Update listbox when sufficiently events available + if( finished || iState == EStateSemiFinished) + { + iContainer->UpdateL(); //Calls HandleItemAdditionL (plus sets Empty text if needed) + // Fetch data for extension + iContainer->ControlExtension()->HandleAdditionalData( + *CurrentModel(), + *iContainer->ListBox() ); + ClearMissedCallNotificationsL(); + // When event reading is finished, remove inputblocker + RemoveInputBlocker(); + } + // If focus is not retained, refresh the UI when a screenful of events is read + else if( iFocusChangeControl == ELogsOkToChange && count == KNbrShownEntries ) + { + iContainer->UpdateL(); + } + + //3. Control focus changes in the list during the read of events + + //Set focus once when ok to change + if ( iFocusChangeControl == ELogsOkToChange ) + { + if( iState == EStateFinished || iState == EStateSemiFinished ) + { + //Reset iEventListCurrentNoChange and iFocusChangeControl + iEventListCurrentNoChange = KErrNotFound; + iFocusChangeControl = ELogsNoChange; + } + + if( count && //at least one entry from previous read to this view + ( iState == EStateUndefined || iState == EStateInitializing )) //we're about start reread + { + SetEventListCurrent(0); + iContainer->ListBox()->SetCurrentItemIndex( EventListCurrent() ); + } + } + + else + //No focus change when entry saved to phonebook, deleted or list updated twice. + { + if( (iState == EStateFinished && LogsCurrentRecentViewId() != EStmMissedListViewId ) || iState == EStateSemiFinished) + { + //If e.g. foreground regained, use iEventListCurrentNoChange if switched on + if( iEventListCurrentNoChange != KErrNotFound && //iEventListCurrentNoChange is switched on. + ( EventListCurrent() == KErrNotFound || + EventListCurrent() == 0) ) //No iEventListCurrent available. + { + SetEventListCurrent(iEventListCurrentNoChange); //Use iEventListCurrentNoChange + } + + if( count > 0 ) + { + //If now less rows than current item before, or if no current selection (e.g last + //row was deleted), try to set focus to last available item. Otherwise try to use + //iEventListCurrent. + if( count <= EventListCurrent() || EventListCurrent() < 0 ) + { + iContainer->ListBox()->SetCurrentItemIndex( count - 1 ); + } + else if( count > EventListCurrent() ) + { + iContainer->ListBox()->SetCurrentItemIndex( EventListCurrent() ); + // if event list top is sensible, adjust the window back to what it was + if ((EventListTop() >= 0) && (EventListTop() < count) ) + { + iContainer->ListBox()->SetTopItemIndex(EventListTop()); + } + } + } + + iFocusChangeControl = ELogsNoChange; + SetEventListCurrent( iContainer->ListBox()->CurrentItemIndex() ); + } + } + + //When reading twice (EMSH-6JDFBV), prevent setting focus again for second phase read. + if( iState == EStateSemiFinished ) + { + iFocusChangeControl = ELogsNoChange; + } + + //4. Set MSK state + if( iState == EStateFinished || iState == EStateSemiFinished ) + { + Cba()->MakeCommandVisible( + EAknSoftkeyContextOptions, + IsOkToShowContextMenu( CurrentEvent() )); + } + + //5. To improve user's perceived responsiviness we probably now have a good moment to perform + //some time consuming operations if not yet already done + if( count == KNbrShownEntries ) //if( iState == EStateFinished ) + { + ConstructDelayedL( ETrue ); //EFalse: perform immediately, ETrue: perform using idle time + } + + //6. When starting reading, call UpdateL so the informative text + // "Retrieving data" can be shown instead just the empty screen. + if (count == 0 && iState == EStateInitializing ) + { + iContainer->UpdateL(); + } + + //7. Just in case the menu was open before reading events, handle the possible menu refresh now + if (finished) + { + HandleMenuRefreshL(CurrentEvent()); + } + + } + + TRACE_EXIT_POINT; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::ExtStateChangedL +// ---------------------------------------------------------------------------- +// +void CLogsRecentListView::ExtStateChangedL() + { + if( iContainer ) + { + iContainer->UpdateL(); + } + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::State +// ---------------------------------------------------------------------------- +// +TLogsState CLogsRecentListView::State() const + { + return iState; + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::CurrentEvent +// +// Returns event relating current selection of listbox or NULL +// ---------------------------------------------------------------------------- +// +const MLogsEventGetter* CLogsRecentListView::CurrentEvent() + { + TRACE_ENTRY_POINT; + //KErrNotFound if no current selection in listbox: + if (iContainer && iContainer->ListBox()) + { + SetEventListCurrent(iContainer->ListBox()->CurrentItemIndex()); + } + else + { + TRACE_EXIT_POINT; + return NULL; + } + + //Return null if no current selection or no suitable event available + if( CurrentModel() && CurrentModel()->Count() > 0 && EventListCurrent() >= 0 ) + { + TRACE_EXIT_POINT; + return CurrentModel()->At( EventListCurrent() ); + } + else + { + TRACE_EXIT_POINT; + return NULL; + } + } + +// ---------------------------------------------------------------------------- +// CLogsRecentListView::HandleNotifyL +// +// Handle AIW-notifications (from asynch ExecuteCmdL call) +// ---------------------------------------------------------------------------- +// +TInt CLogsRecentListView::HandleNotifyL( + TInt aCmdId, + TInt aEventId, + CAiwGenericParamList& aEventParamList, + const CAiwGenericParamList& aInParamList ) + { + TInt result = CLogsBaseView::HandleNotifyL( aCmdId, aEventId, aEventParamList, aInParamList ); + return result; + } + + +// End of File