logsui/AppSrc/CLogsEventListView.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
child 68 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/logsui/AppSrc/CLogsEventListView.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,713 @@
+/*
+* 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 "Event list" view class implementation
+*
+*/
+
+
+// INCLUDE FILES
+#include <eikmenub.h>
+#include <AknQueryDialog.h>
+#include <featmgr.h>    //FeatureManger
+#include <Logs.rsg>
+
+#include "CLogsEventListView.h"
+#include "CLogsAppUi.h"
+#include "CLogsEngine.h"
+#include "MLogsModel.h"
+#include "MLogsEventGetter.h"
+#include "MLogsClearLog.h"
+#include "CLogsEventListControlContainer.h"
+#include "CLogsReaderConfigFactory.h"
+#include "MLogsStateHolder.h"
+#include "MLogsSharedData.h"
+#include "LogsEngConsts.h"  //KLogEngWlanEventTypeUid
+#include "MLogsReader.h"
+#include "LogsUID.h"
+
+#include "LogsDebug.h"
+#include "LogsTraces.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES  
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// ==================== LOCAL FUNCTIONS ====================
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::NewL
+// ----------------------------------------------------------------------------
+//
+CLogsEventListView* CLogsEventListView::NewL()
+    {
+    CLogsEventListView* self = new( ELeave ) CLogsEventListView;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();  // self
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::~CLogsEventListView
+// ----------------------------------------------------------------------------
+//
+CLogsEventListView::~CLogsEventListView()
+    {
+    if( iContainer )
+        {
+        AppUi()->RemoveFromViewStack( *this, iContainer );
+        delete iContainer;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::CLogsEventListView
+// ----------------------------------------------------------------------------
+//
+CLogsEventListView::CLogsEventListView() :
+                iCurrentFilter( ELogsFilterAllComms ),
+                iState( EStateUndefined ),
+                iClearListInProgress(EFalse)
+{
+}
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::HandleCommandL
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::HandleCommandL( TInt aCommandId )
+    {
+    iEventListCurrent = iContainer->ListBox()->CurrentItemIndex();
+
+    const MLogsEventGetter* event = NULL;
+    event = Engine()->Model( ELogsMainModel )->At( iEventListCurrent );
+
+    switch( aCommandId )
+        {
+        case ELogsCmdMenuDetails:
+		    //if in clearlog process, ignore the request to avoid show
+			//deteiled view EJDU-7PCDKG 
+            if(!iClearListInProgress)
+            {
+            LogsAppUi()->CmdOkL( iEventListCurrent );
+            }
+            break;
+
+        case ELogsCmdMenuFilter:
+            CmdFilterL();
+            break;
+     
+        case ELogsCmdMenuClearList:
+            CmdClearListL();
+            break;
+
+        default:
+            {
+            CLogsBaseView::HandleCommandEventL( aCommandId, event );
+            }
+        }
+    }
+    
+// ----------------------------------------------------------------------------
+// CLogsEventListView::ChangeTitlePaneTextToDefaultL
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::ChangeTitlePaneTextToDefaultL()
+    {       
+    iContainer->SetTitlePaneTextToDefaultL( LogsAppUi()->ActiveViewId() );
+    } 
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::ProcessCommandL
+//
+// Called from FW when e.g. cba pressed 
+// ----------------------------------------------------------------------------
+
+void CLogsEventListView::ProcessCommandL( TInt aCommand )
+    {
+    if (LogsAppUi()->ActiveViewId() != ELogEventListViewId || !iContainer )
+           {
+           LOGS_DEBUG_PRINT(LOGS_DEBUG_STRING
+                   ( "CLogsRecentListView::ProcessCommandL - view already deactivated! return " ));  
+           return;
+           }
+    
+    if (aCommand == EAknSoftkeyOptions)
+        { 
+        TInt currentEventIndex = iContainer->ListBox()->CurrentItemIndex();
+        const MLogsEventGetter* event = NULL;
+        event = Engine()->Model( ELogsMainModel )->At( currentEventIndex );
+       
+        // 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( event );
+        }    
+    
+    CLogsBaseView::ProcessCommandL( aCommand );
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::ProcessKeyEventL
+// ----------------------------------------------------------------------------
+//
+TBool CLogsEventListView::ProcessKeyEventL( const TKeyEvent& aKeyEvent,
+                                            TEventCode aType )
+    {
+    iEventListCurrent = iContainer->ListBox()->CurrentItemIndex();
+
+    const MLogsEventGetter* event = CurrentModel()->At( iEventListCurrent );
+    
+    //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.
+    iEventListCurrent = iContainer->ListBox()->CurrentItemIndex();
+
+    if( aType == EEventKey && iEventListCurrent != 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 );        
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::Id
+// ----------------------------------------------------------------------------
+//
+TUid CLogsEventListView::Id() const
+    {
+    return TUid::Uid( ELogEventListViewId );
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::DynInitMenuPaneL
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::DynInitMenuPaneL
+    (   TInt aResourceId
+    ,   CEikMenuPane* aMenuPane
+    )
+    {
+    //First check do we have data already available. Data may not yet be available if asynch request(s) are 
+    //not yet completed
+    iEventListCurrent = iContainer->ListBox()->CurrentItemIndex();
+    const MLogsEventGetter* event = NULL;
+
+    if( Engine()->Model( ELogsMainModel )->Count() > 0 && iEventListCurrent >= 0 )    
+        {
+        event = Engine()->Model( ELogsMainModel )->At( iEventListCurrent );             
+        }
+        
+    //Process menuitems. Note that data may not yet be available.
+    if( aResourceId == R_LOGS_EVENT_LIST_MENU_CLEAR_LIST )
+        {
+        if( !event )        
+            {            
+            aMenuPane->DeleteMenuItem( ELogsCmdMenuClearList );
+            return; 
+            }
+        }
+    else if( aResourceId == R_LOGS_EVENT_LIST_MENU_FILTER )
+        {
+        if( !event )        
+            {            
+            //Remove filter option if we had broadest filter in use and still got an empty list
+            if( Engine()->Model( ELogsMainModel )->Count() == 0 && 
+                iCurrentFilter == ELogsFilterAllComms )
+                {            
+                aMenuPane->DeleteMenuItem( ELogsCmdMenuFilter );            
+                }
+            return; 
+            }
+        }
+    else if( aResourceId == R_LOGS_EVENT_LIST_MENU_DETAILS )
+        {
+        if( !event )        
+            {            
+            aMenuPane->DeleteMenuItem( ELogsCmdMenuDetails );                    
+            return; 
+            }
+        else
+            {
+            // If MSK is enabled both in the platform and in the application, the menu text 
+            // for viewing the event details is changed to conform with the MSK label
+            if( Engine()->SharedDataL()->IsMSKEnabledInPlatform() && 
+                AknLayoutUtils::MSKEnabled() )
+                {
+                aMenuPane->SetItemTextL( ELogsCmdMenuDetails, R_QTN_LOGS_CMD_VIEW);
+                }
+            }
+        }
+    else 
+        {
+        CLogsBaseView::DynInitMenuPaneEventL( aResourceId, aMenuPane, event );    
+        }
+    }
+
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::HandleClientRectChange
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::HandleClientRectChange()
+    {
+    if (iContainer)
+        {
+        iContainer->SetRect( ClientRect() );  
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::DrawComponents
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::DrawComponents()
+    {
+    if (iContainer)
+        {
+        iContainer->DrawNow();
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::DoActivateL
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::DoActivateL
+        ( const TVwsViewId& aPrevViewId, 
+          TUid aCustomMessageId,
+          const TDesC8& aCustomMessage )
+    {
+    TRACE_ENTRY_POINT;
+    CLogsBaseView::DoActivateL( aPrevViewId, aCustomMessageId, aCustomMessage );  
+    
+    
+    Engine()->CreateModelL( ELogsMainModel );   //Creates if not already exist
+
+    if( iContainer == NULL )
+        {
+        iContainer = CLogsEventListControlContainer::NewL( this, ClientRect() );
+        AppUi()->AddToViewStackL( *this, iContainer );
+        }
+    iContainer->ListBox()->SetListBoxObserver( this );
+    
+    //We reset this list when activated. Only exception is when returning from Logs Detail View
+    if( aPrevViewId.iViewUid != TUid::Uid( ELogDetailViewId  ))   
+        {
+        MLogsReaderConfig* readerConfig;
+        iCurrentFilter = ELogsFilterAllComms;                                         //reset filter selection
+        readerConfig = CLogsReaderConfigFactory::LogsReaderConfigLC( iCurrentFilter); //reread all events
+        iContainer->ListBox()->SetCurrentItemIndex( 0 );
+        Engine()->Model( ELogsMainModel )->ConfigureL( readerConfig );        
+        CleanupStack::PopAndDestroy();  //readerConfig
+        }
+
+    LogsAppUi()->SetPreviousViewId( aPrevViewId.iViewUid );
+    LogsAppUi()->SetCurrentViewId( Id() );
+    Engine()->Model( ELogsMainModel )->SetObserver( this );
+    Engine()->Model( ELogsMainModel )->DoActivateL( MLogsModel::ERefresh );
+    Engine()->StartSMSEventUpdaterL( /* MLogsReader::EPbkAndSim */ );//Starts the asynch process of reading Phonebook, 
+                                                                     //updating Logs event and eventually receiving 
+                                                                     //notification  of changed database data to view.
+    // Just to make sure the inputblocker is not on
+    iClearListInProgress = EFalse;
+    RemoveInputBlocker();
+      
+    TRACE_EXIT_POINT;
+    }                                                               
+// ----------------------------------------------------------------------------
+// CLogsEventListView::DoDeactivate
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::DoDeactivate()
+    {
+    if( iContainer )
+        {
+        iEventListCurrent = iContainer->ListBox()->CurrentItemIndex();
+        iEventListTop = iContainer->ListBox()->TopItemIndex();
+        AppUi()->RemoveFromViewStack( *this, iContainer );
+        delete iContainer;
+        iContainer = NULL;
+        }
+
+    //Deactivate model. We must keep the model connected to the database, otherwise we don't have the
+    //the same data available when we return from Detail view.
+    Engine()->Model( ELogsMainModel )->DoDeactivate( MLogsModel::ENormalOperation,
+                                                     MLogsModel::EKeepDBConnection ); //EFalse: keep connected to db
+   
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::ConstructL
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::ConstructL()
+    {
+    BaseConstructL( R_LOGS_EVENT_LIST_VIEW );
+    }
+
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::CmdClearListL
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::CmdClearListL()
+    {
+    CAknQueryDialog* queryDlg = CAknQueryDialog::NewL();
+    if( queryDlg->ExecuteLD( R_CLEAR_LIST_CONFIRMATION_QUERY ) )
+        {
+        Engine()->ClearLogsL()->ClearModelL( ELogsMainModel );
+        Engine()->SharedDataL()->NewMissedCalls( ETrue );
+        SetInputBlockerL();
+        iClearListInProgress = ETrue;
+        
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::AddOneListBoxTextLineL
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::AddOneListBoxTextLineL(
+    CDesCArrayFlat* aItems,
+    TInt aResourceText )
+    {
+    HBufC* text;
+    text = iCoeEnv->AllocReadResourceLC( aResourceText );
+    aItems->AppendL( *text );
+    CleanupStack::PopAndDestroy();  // text
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::InitFilterPopupListL
+//
+// Show Popuplist containing filtering options
+// ----------------------------------------------------------------------------
+//
+TLogsFilter CLogsEventListView::InitFilterPopupListL()
+    {
+    CDesCArrayFlat* items = new( ELeave )CDesCArrayFlat( ELogsFilterNumberOfFilters );
+    CleanupStack::PushL( items );
+    
+    //NOTE! In enum TLogsFilter does not necessarily contain same options as in created filter listbox., 
+    //Therefore we create popUpRow[] containing only the filtering options corresponding to 
+    //rows available in popuplistbox (e.g. wlan option is not present in all configurations).
+    TLogsFilter popUpRow[ELogsFilterNumberOfFilters];  //(ELogsFilterNumberOfFilters is last of enums)
+    TInt i = 0;
+    TInt setFocusInLB = KErrNotFound;   
+    TInt count( Engine()->Model( ELogsMainModel )->Count() );
+
+    //If previous choice did not give any events, then do not add it again to listbox (hide that option)
+    if( !( iCurrentFilter == ELogsFilterAllComms && count == 0 ) )  //1.Add other than current filters to list 2.Add also current filter to 
+        {                                                           //  list if it found events from db, otherwise discard current filter.
+        (iCurrentFilter == ELogsFilterAllComms && count > 0) ? setFocusInLB = i : 0; //Set focus to this line if current & found events from db.
+        AddOneListBoxTextLineL( items, R_LOGS_MF_ALL_COMMUNICATION_TEXT );
+        popUpRow[i++] = ELogsFilterAllComms;
+        }
+    if( !( iCurrentFilter == ELogsFilterOutgoing && count == 0 ) ) 
+        {
+        (iCurrentFilter == ELogsFilterOutgoing && count > 0) ? setFocusInLB = i : 0; 
+        AddOneListBoxTextLineL( items, R_LOGS_MF_OUTGOING_TEXT );
+        popUpRow[i++] = ELogsFilterOutgoing;
+        }
+    if( !( iCurrentFilter == ELogsFilterIncoming && count == 0 ) ) 
+        {
+        (iCurrentFilter == ELogsFilterIncoming && count > 0) ? setFocusInLB = i : 0; 
+        AddOneListBoxTextLineL( items, R_LOGS_MF_INCOMING_TEXT );
+        popUpRow[i++] = ELogsFilterIncoming;
+        }
+    if( !( iCurrentFilter == ELogsFilterVoice && count == 0 ) ) 
+        {
+        (iCurrentFilter == ELogsFilterVoice && count > 0) ? setFocusInLB = i : 0;         
+        if( FeatureManager::FeatureSupported( KFeatureIdCsVideoTelephony ) )
+            {
+            AddOneListBoxTextLineL( items, R_LOGS_MF_VOICEVIDEO_TEXT );  
+            }
+        else
+            {
+            AddOneListBoxTextLineL( items, R_LOGS_MF_VOICE_TEXT );  
+            }
+        popUpRow[i++] = ELogsFilterVoice;
+        }
+    if( !( iCurrentFilter == ELogsFilterMessages && count == 0 ) ) 
+        {
+        (iCurrentFilter == ELogsFilterMessages && count > 0) ? setFocusInLB = i : 0;                 
+        AddOneListBoxTextLineL( items, R_LOGS_MF_SMS_TEXT );
+        popUpRow[i++] = ELogsFilterMessages;
+        }
+    if( !( iCurrentFilter == ELogsFilterPacket && count == 0 ) ) 
+        {
+        (iCurrentFilter == ELogsFilterPacket && count > 0) ? setFocusInLB = i : 0;                         
+        AddOneListBoxTextLineL( items, R_LOGS_MF_PACKET_TEXT );
+        popUpRow[i++] = ELogsFilterPacket;
+        }
+    if( !( iCurrentFilter == ELogsFilterData && count == 0 ) ) 
+        {
+        (iCurrentFilter == ELogsFilterData && count > 0) ? setFocusInLB = i : 0;                                 
+        AddOneListBoxTextLineL( items, R_LOGS_MF_DATA_TEXT );
+        popUpRow[i++] = ELogsFilterData;
+        }
+    if( !( iCurrentFilter == ELogsFilterWlan && count == 0 ) ) 
+        {
+        if( FeatureManager::FeatureSupported( KFeatureIdProtocolWlan ) )   
+            {
+            (iCurrentFilter == ELogsFilterWlan && count > 0) ? setFocusInLB = i : 0;                                             
+            AddOneListBoxTextLineL( items, R_LOGS_MF_WLAN_TEXT );
+            popUpRow[i++] = ELogsFilterWlan;
+            }
+        }   
+    if( count > 0 && MenuBar()->ItemSpecificCommandsEnabled() )
+        {
+        const MLogsEventGetter* event = Engine()->Model( ELogsMainModel )->At( iEventListCurrent );
+        //Seletected event supported only for events that have number or remoty party available, so e.g
+        //payphones, unknowns, privates and poc group calls not supported
+        if( event->Number() || event->RemoteParty() )
+            {
+            (iCurrentFilter == ELogsFilterPerson) ? setFocusInLB = i : 0;                                                     
+            AddOneListBoxTextLineL( items, R_LOGS_MF_SELECTED_PERSON_TEXT );
+            popUpRow[i++] = ELogsFilterPerson;
+            }
+        }
+
+    //  Create popuplistbox
+    CAknSinglePopupMenuStyleListBox* popupListBox = new( ELeave ) CAknSinglePopupMenuStyleListBox;
+    CleanupStack::PushL( popupListBox );
+    CAknPopupList* popupFrame = CAknPopupList::NewL( popupListBox, 
+                                                     R_AVKON_SOFTKEYS_SELECT_CANCEL );
+    CleanupStack::PushL( popupFrame );  
+    popupListBox->ConstructL( popupFrame, CEikListBox::ELeftDownInViewRect );
+
+    //  Create the model for listbox
+    CTextListBoxModel* model = popupListBox->Model();
+    model->SetItemTextArray( items );
+    model->SetOwnershipType( ELbmDoesNotOwnItemArray ); // items in CleanupStack 
+    popupListBox->HandleItemAdditionL();
+
+    //  Create title for the Pop-Up window
+    HBufC* title;
+    title = iCoeEnv->AllocReadResourceLC( R_LOGS_MF_SHOW_TEXT );
+    popupFrame->SetTitleL( *title );
+    CleanupStack::PopAndDestroy();  // title
+
+    // Select previous filter (except for the first time or if no rows got using that filter)    
+    if( setFocusInLB != KErrNotFound )
+        {
+        popupListBox->SetCurrentItemIndex( setFocusInLB ); //Same choice as on previous filtering
+        }
+    else
+        {
+        popupListBox->SetCurrentItemIndex( 0 );            
+        }
+    
+    popupListBox->SetTopItemIndex( 0 );                 // To see as many lines as possible
+    iContainer->MakeScrollArrowsL( popupListBox );      // Activate scrollbar
+    CleanupStack::Pop( popupFrame );    
+
+    TLogsFilter newFilter;
+    
+    if( popupFrame->ExecuteLD() )
+        {
+        newFilter = popUpRow[popupListBox->CurrentItemIndex()];
+        }
+    else
+        {
+        newFilter = ELogsFilterNothing;                 //ELogsFilterNothing is last enum option
+        }
+
+    CleanupStack::PopAndDestroy( popupListBox ); 
+    CleanupStack::PopAndDestroy( items );                
+    return newFilter;
+    }
+    
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::CmdFilterL
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::CmdFilterL()
+    {
+    TLogsFilter newFilter( InitFilterPopupListL() );  //Show popuplist and get user's selection for filter option
+
+    // Start filtering procedure only if new filter is selected.
+    if( iCurrentFilter != newFilter && 
+        newFilter != ELogsFilterNothing )
+        {
+        iCurrentFilter = newFilter;
+        MLogsReaderConfig* readerConfig;
+        
+        if( iCurrentFilter == ELogsFilterPerson &&
+            Engine()->Model( ELogsMainModel )->Count() )
+            {
+            const MLogsEventGetter* event = Engine()->
+                            Model( ELogsMainModel )->At( iEventListCurrent );
+            TPtrC number(KNullDesC());
+            TPtrC remote(KNullDesC());
+            if( event->Number() )
+                {
+                number.Set( *(event->Number()) );
+                }
+            if( event->RemoteParty() )
+                {
+                remote.Set( *(event->RemoteParty()) );
+                }
+		    
+            readerConfig = CLogsReaderConfigFactory::
+                            LogsReaderConfigLC( &number, 
+                                                &remote );
+            }
+        else
+            {
+            readerConfig = CLogsReaderConfigFactory::
+                        LogsReaderConfigLC( iCurrentFilter );            
+            }
+            
+        iContainer->ListBox()->SetCurrentItemIndex( 0 );
+        Engine()->Model( ELogsMainModel )->ConfigureL( readerConfig );        
+        CleanupStack::PopAndDestroy(); //readerConfig         
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::CurrentFilter
+// ----------------------------------------------------------------------------
+//
+TLogsFilter CLogsEventListView::CurrentFilter() const
+    {
+    return iCurrentFilter;
+    }
+    
+// ----------------------------------------------------------------------------
+// CLogsEventListView::StateChangedL
+//
+// CLogsModel informs that it has changed the event array (e.g. added an entry or reseted the array etc)
+// ----------------------------------------------------------------------------
+//
+void CLogsEventListView::StateChangedL( MLogsStateHolder* aHolder )
+    {
+    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;
+        }
+    
+#ifdef _DEBUG
+_LIT(KDebugString,"Performance monitoring: Log view list item time %D");
+    if( !iCreationTimeCalculated && Engine()->Model( ELogsMainModel )->Count() > 0 )
+        {
+        iCreationTimeCalculated = ETrue;
+        TTime currentTime;
+        currentTime.UniversalTime();
+        
+        RDebug::Print( KDebugString, currentTime.MicroSecondsFrom( iCreationTime ));
+        }
+#endif
+
+    //Call Update() when related items available to show changes immediately plus when reading is finished. 
+    const TInt KNbrShownEntries = 16;
+
+    iState = aHolder->State();
+    
+    if( iContainer )
+        {
+        //Optimization: we reduce frequent calling of iContainer->UpdateL(). Although the UpdateL() can be called always when 
+        //StateChangedL is called, this slows down the performance significantly
+        
+        TBool finished = ( iState != EStateActive && iState != EStateUndefined  &&  iState != EStateInitializing);        
+        TInt count( iContainer->ListBox()->Model()->NumberOfItems() ); 
+        // TInt interval = 50;        
+        // TBool update = ( count / interval == (count+interval-1) / interval );//This may cause refreshes *above* the user's current line 
+                                                                                //when there are changes in db that affect the view. This
+                                                                                //causes unpleasant jumping in the view so no need to update.
+        
+        //Magic number KNbrShownEntries: Call Update() when first screenful of items available or when reading finished, stopped, 
+        //interrupted etc. Also call update when about to start to read (count==0) in order to show "Retrieving data".
+        if( count == 0 || count == KNbrShownEntries || finished )  // || update )  
+            {   
+            iContainer->UpdateL(); 
+            
+            //Show MSK if anything on list
+            Cba()->MakeCommandVisible( 
+                ELogsCmdMenuDetails, 
+                count );
+            
+            //Perform some time consuming operations if not yet already done
+            if( count == KNbrShownEntries || finished ) 
+                {
+                ConstructDelayedL( ETrue );   //ETrue: perform using idle time
+                iEventListCurrent = iContainer->ListBox()->CurrentItemIndex();
+                const MLogsEventGetter* event = Engine()->
+                    Model( ELogsMainModel )->At( iEventListCurrent );
+                
+                if (finished)
+                    {
+                    //Checks wheter the options menu was opened already and should it be refreshed
+                    //now that the reading is finishing                 
+                    HandleMenuRefreshL( event );
+                    // just in case inputblocker still alive
+                    iClearListInProgress = EFalse;
+                    RemoveInputBlocker();
+                    }                               
+                }
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsEventListView::State
+// ----------------------------------------------------------------------------
+//
+TLogsState CLogsEventListView::State() const
+    {
+    return iState;  
+    }
+
+//  End of File