--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/logsui/AppSrc/CLogsRecentListView.cpp Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,1289 @@
+/*
+* 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 <eikmenub.h>
+#include <AknQueryDialog.h>
+#include <aknnotewrappers.h>
+#include <baclipb.h>
+#include <StringLoader.h>
+#include <CMessageData.h>
+#include <sendui.h>
+#include <SendUiConsts.h>
+#include <TSendingCapabilities.h>
+#include <Sendnorm.rsg>
+#include <Logs.rsg>
+#include <AiwCommon.hrh> //KAiwCmdCall
+#include <AiwPoCParameters.h> //TAiwPocParameterData
+#include <aknViewAppUi.h>
+#include <AiwServiceHandler.h>
+#include <AiwGenericParam.h>
+#include <StringLoader.h>
+#include <aknnotewrappers.h>
+#include <AknGlobalNote.h>
+#include <AknGlobalConfirmationQuery.h>
+#include <MGFetch.h>
+#include <AiwContactSelectionDataTypes.h>
+#include <AiwContactAssignDataTypes.h>
+
+// Virtual Phonebook
+#include <RVPbkContactFieldDefaultPriorities.h>
+#include <VPbkFieldType.hrh>
+#include <TVPbkContactStoreUriPtr.h>
+#include <CVPbkContactStoreUriArray.h>
+#include <MVPbkContactStoreList.h>
+#include <CVPbkContactManager.h>
+#include <CVPbkFieldTypeSelector.h>
+#include <CVPbkContactLinkArray.h>
+#include <VPbkContactStoreUris.h>
+#include <VPbkContactViewFilterBuilder.h>
+//------------------------
+
+#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.
+ // Keep db connection.
+ CurrentModel()->DoDeactivate( MLogsModel::ESkipClearing,
+ MLogsModel::EKeepDBConnection );
+
+ }
+
+ 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.
+ // Keep db connection
+ CurrentModel()->DoDeactivate( MLogsModel::ENormalOperation,
+ MLogsModel::EKeepDBConnection );
+
+ CurrentModel()->DoActivateL( MLogsModel::EResetAndRefresh );
+ // Now we can enable bring-to-foreground on view activation:
+ AppUi()->SetCustomControl(0);
+ AppUi()->HideInBackground();
+ // If listbox needs to redraw,do it.
+ if( CurrentModel()->Count()>0 &&
+ ( iContainer->ListBox()->TopItemIndex() != EventListTop() ||
+ iContainer->ListBox()->CurrentItemIndex() != EventListCurrent()))
+ {
+ iContainer->ListBox()->DrawDeferred();
+ }
+
+ }
+ else
+ {
+ // Just to make sure the inputblocker is not on
+ RemoveInputBlocker();
+ TRAPD( err, CurrentModel()->DoActivateL( MLogsModel::EResetAndRefresh ));
+ if( err )
+ {
+ iCoeEnv->HandleError( err );
+ }
+ if( err == KErrDiskFull )
+ {
+ RWsSession& wsSession = CCoeEnv::Static()->WsSession();
+ TApaTask logsui( wsSession );
+ TInt wgId = CCoeEnv::Static()->RootWin().WindowGroupId();
+ logsui.SetWgId( wgId );
+ logsui.KillTask();
+ return;
+ }
+
+ // Avoid the flicking when transfer to foreground from background.
+ if(LogsAppUi()->IsBackground())
+ {
+ iContainer->DrawNow();
+ iEikonEnv->AppUiFactory()->StatusPane()->DrawNow();
+ LogsAppUi()->SetCustomControl(0);
+
+ CCoeEnv * env = CCoeEnv::Static();
+ env->WsSession().SetWindowGroupOrdinalPosition(env->RootWin().Identifier(),0);
+
+ }
+
+ }
+
+
+ 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
+ // Keep db connection
+ CurrentModel()->DoDeactivate( MLogsModel::ENormalOperation,
+ MLogsModel::EKeepDBConnection );//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" ));
+ // Keep db connection
+ CurrentModel()->DoDeactivate( MLogsModel::ESkipClearing,
+ MLogsModel::EKeepDBConnection );
+ }
+ }
+ else
+ {
+ CurrentModel()->DoDeactivate( MLogsModel::ENormalOperation,
+ MLogsModel::EKeepDBConnection );//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();
+ }
+ }
+ else
+ {
+ // Change ELogsNoChange_PbkUpdPending to ELogsNoChange now so there is no need to
+ // differentiate those in StateChangedL
+ iFocusChangeControl = ELogsNoChange;
+ }
+ }
+ // Sure "ClearMissedCallNotificationsL" is called.
+ ClearMissedCallNotificationsL();
+
+ 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" ));
+ // Keep db connection
+ model->DoDeactivate( MLogsModel::ENormalOperation,
+ MLogsModel::EKeepDBConnection ); //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
+ // Keep db connection
+ model->DoDeactivate( MLogsModel::ESkipClearing, //Don't update db (for missed view)
+ MLogsModel::EKeepDBConnection ); //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() );
+ // Add condition check: To avoid Missing Call Note don't display ,do not call "ClearMissedCallNotificationsL" when logs is in background.
+ if(!LogsAppUi()->IsBackground())
+ 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;
+ }
+
+void CLogsRecentListView::ViewActivatedL(const TVwsViewId& aPrevViewId,TUid aCustomMessageId,const TDesC8& aCustomMessage)
+ {
+ //To avoid the flicking when transfer to foreground from background,we control the view show manually.
+ if(LogsAppUi()->IsBackground() &&
+ LogsAppUi()->ActiveViewId() != LogsCurrentRecentViewId() )
+ {
+ LogsAppUi()->SetCustomControl(1);
+ }
+
+ CLogsBaseView::ViewActivatedL(aPrevViewId,aCustomMessageId,aCustomMessage);
+
+ }
+
+// End of File