phonebookui/Phonebook2/UIControls/src/cpbk2predictiveviewstack.cpp
changeset 0 e686773b3f54
child 12 5072fb0f5b46
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/UIControls/src/cpbk2predictiveviewstack.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1418 @@
+/*
+* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Phonebook 2 Predictive search view stack
+*
+*/
+
+#include "CPbk2ContactPositionInfo.h"
+#include "cpbk2predictiveviewstack.h"
+
+// Phonebook 2 / Virtual Phonebook
+#include <MVPbkContactViewFiltering.h>
+#include <CVPbkContactFindPolicy.h>
+#include <VPbkEng.rsg>
+#include <MVPbkViewContact.h>
+#include <CVPbkContactIdConverter.h>
+#include <MPbk2AppUi.h>
+#include <MPbk2ApplicationServices.h>
+#include <VPbkContactStoreUris.h>
+#include <centralrepository.h>
+#include <Phonebook2PrivateCRKeys.h>
+#include <CVPbkTopContactManager.h>
+#include "cpbk2filteredviewstack.h"
+#include <CPbk2StoreConfiguration.h>
+#include <MVPbkContactBookmarkCollection.h>
+#include <CVPbkContactIdConverter.h>
+#include "CPbk2PredictiveSearchFilter.h"
+#include <MPbk2ContactNameFormatter.h>
+#include <MPbk2ContactNameFormatter2.h>
+
+// Predictive seard engine headers 
+#include <CPsSettings.h>
+#include <CPsQueryItem.h>
+#include <CPsData.h>
+#include <CPsRequestHandler.h>
+
+// Debugging headers
+#include <Pbk2Debug.h>
+#include <bidivisual.h>
+#include <fepbase.h>
+#include "Phonebook2PrivateCRKeys.h"
+
+
+// System includes
+#include <aknsfld.h>
+#include <featmgr.h>
+// CONSTANTS
+const TInt Kspace = ' ';
+_LIT(KPsGroupDBSuffix, "?id=%d");
+
+/// Unnamed namespace for local definitions
+namespace {
+
+
+
+
+// --------------------------------------------------------------------------
+// SendEventToObservers
+// Sends events to the array of observes that take MVPbkContactViewBase.
+// as a parameter.
+//
+// @param aView         The parameter for the NotifyFunc.
+// @param aObservers    An array of MVPbkContactViewObservers.
+// @param aNotifyFunc   A member function pointer of the
+//                      MVPbkContactViewObserver.
+// --------------------------------------------------------------------------
+//
+template <class Observer, class NotifyFunc>
+void SendEventToObservers( MVPbkContactViewBase& aView,
+        RPointerArray<Observer>& aObservers,
+        NotifyFunc aNotifyFunc )
+    {
+    const TInt count = aObservers.Count();
+    for (TInt i = count-1; i >= 0 ; --i)
+        {
+        Observer* observer = aObservers[i];
+        (observer->*aNotifyFunc)(aView);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// SendEventToObservers
+// Sends events to the array of MVPbkContactViewObserver.
+// Used for MVPbkContactViewObserver functions that have two extra parameters
+// in addition to MVPbkContactViewBase.
+//
+// @param aView         The first parameter for the NotifyFunc.
+// @param aObservers    An array of MVPbkContactViewObserver.
+// @param aNotifyFunc   A member function pointer of the
+//                      MVPbkContactViewObserver.
+// @param aParam1       The second parameter for the aNotifyFunc.
+// @param aParam2       The third parameter for the aNotifyFunc.
+// --------------------------------------------------------------------------
+//
+template <class Observer, class FuncPtr, class ParamType1, class ParamType2>
+void SendEventToObservers( MVPbkContactViewBase& aView,
+        RPointerArray<Observer>& aObservers,
+        FuncPtr aNotifyFunc,
+        ParamType1 aParam1, ParamType2& aParam2)
+    {
+    const TInt count = aObservers.Count();
+    for (TInt i = count-1; i >= 0 ; --i)
+        {
+        Observer* observer = aObservers[i];
+        (observer->*aNotifyFunc)(aView, aParam1, aParam2);
+        }
+    }
+
+} /// namespace
+
+TInt CPbk2ContactPositionInfo::CompareByPosition( 
+        const CPbk2ContactPositionInfo& aFirst, 
+        const CPbk2ContactPositionInfo& aSecond )
+    {
+    if( aFirst.iPos < aSecond.iPos )
+        {
+        return -1;
+        }
+    else if( aFirst.iPos == aSecond.iPos )
+        {
+        return 0;
+        }
+    else
+        {
+        return 1;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::CPbk2PredictiveViewStack
+// --------------------------------------------------------------------------
+CPbk2PredictiveViewStack::CPbk2PredictiveViewStack( CPbk2PredictiveSearchFilter& aSearchFilter,
+        MPbk2ContactNameFormatter& aNameformatter ):
+    CActive( EPriorityStandard ), iSearchFilter( aSearchFilter ),
+    iNameformatter(aNameformatter),
+    iNonMatchedMarkedContactStartIndex(KErrNotFound),
+    iNonMatchedMarkedContactEndIndex(KErrNotFound)
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::~CPbk2PredictiveViewStack
+// --------------------------------------------------------------------------
+//
+CPbk2PredictiveViewStack::~CPbk2PredictiveViewStack()
+    {
+    Cancel();
+    iBidiPatterns.ResetAndDestroy();
+    iPatternsCollection.ResetAndDestroy();
+    iStackObservers.Reset();
+    iViewObservers.Reset();
+    delete iConverterDefaultStore;
+    delete iPsQuery;
+    delete iPsHandler;
+    delete iCurrentGroupLink;
+    if ( iBaseView )
+        {
+        iBaseView->RemoveObserver( *this );
+        }
+  
+    if( iPredictiveSearchResultContactLinkArrray )
+        {
+        iPredictiveSearchResultContactLinkArrray->ResetAndDestroy();
+        delete iPredictiveSearchResultContactLinkArrray;
+        }
+  
+    iTopContactPositionInfoArray.ResetAndDestroy();
+    iMarkedContactsPositionInfoArray.ResetAndDestroy();
+    
+    delete iTopContactManager;
+    iSearchText.Close();
+    if(iFeatureManagerInitilized)
+        {
+        FeatureManager::UnInitializeLib();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2PredictiveViewStack* CPbk2PredictiveViewStack::NewL(
+        MVPbkContactViewBase& aBaseView,
+        CPbk2PredictiveSearchFilter& aSearchFilter,
+        MPbk2ContactNameFormatter& aNameformatter )
+    {
+    CPbk2PredictiveViewStack* self = new ( ELeave ) CPbk2PredictiveViewStack( aSearchFilter,
+            aNameformatter );
+    CleanupStack::PushL( self );
+    self->ConstructL( aBaseView );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ConstructL
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::ConstructL( MVPbkContactViewBase& aBaseView )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2PredictiveViewStack::ConstructL"));
+
+    iSearchedState = EFalse;
+    iViewReady = EFalse;
+    iBaseView = &aBaseView;
+    
+    // Initialize feature manager
+    FeatureManager::InitializeLibL();
+    iFeatureManagerInitilized = ETrue;
+    // Initilize the PCS engine 
+    InitializePCSEngineL();
+
+    CVPbkContactManager& manager = Phonebook2::Pbk2AppUi()->
+        ApplicationServices().ContactManager();
+		
+    iTopContactManager = CVPbkTopContactManager::NewL( manager );
+	
+    // Arrary for holding the search result links
+    iPredictiveSearchResultContactLinkArrray = CVPbkContactLinkArray::NewL();
+
+    // Start listening view events
+    iBaseView->AddObserverL( *this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::UpdateFilterL
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::UpdateFilterL( const MDesCArray& aFindStrings,
+        const MVPbkContactBookmarkCollection* aAlwaysincluded,
+		        TBool aAlwaysIncludedChanged )
+    {
+    if ( aAlwaysIncludedChanged )
+        {
+        // iBookMarkCollection is not owned
+        iBookMarkCollection = 
+            const_cast<MVPbkContactBookmarkCollection*>( aAlwaysincluded );
+        }
+    
+    iPredictiveSearch = iSearchFilter.IsPredictiveActivated();
+    
+    TKeyboardModes pcsKeyboardMode( EItut );
+    if ( iPredictiveSearch )
+        {
+        pcsKeyboardMode = EItut;
+        }
+    else
+        {
+        pcsKeyboardMode = EQwerty;
+        }
+    
+    // During filtering if there were multitaps, Fep transacton is broken 
+    // and search box sends canceletion of last tap, we ignore this.
+    if( iPredictiveSearch && iSearchFilter.IsFiltering() )
+        {
+        return;
+        }   
+  
+    RBuf searchText;
+    iSearchFilter.GetSearchTextL( searchText );
+    CleanupClosePushL( searchText );
+    // Events go on up and down key, it is not good do search always twice 
+    TInt compareSearchText = iSearchText.Compare(searchText);
+    
+    iSearchText.Close();
+    iSearchText.CreateL(searchText.Length());
+    iSearchText = searchText;
+    
+    CleanupStack::PopAndDestroy(&searchText);
+    
+    if( compareSearchText == 0 )
+        {
+        return;
+        }
+    
+    if( !aFindStrings.MdcaCount() )
+        {
+        if( compareSearchText == 1 )
+            {
+            if( !iSearchText.Length() )
+                {
+                Reset();
+                }
+            else
+                {
+                ClearSearch();
+                }
+            }
+        return;
+        }
+    
+    // Delete the previous query
+    delete iPsQuery;
+    iPsQuery = NULL;
+    
+    // Create the new search query
+    iPsQuery = CPsQuery::NewL(); 
+    
+    // Combine the search strings and create the PCS query
+    for ( TInt j = 0; j < aFindStrings.MdcaCount(); j++ )
+        {
+        HBufC* searchString = aFindStrings.MdcaPoint(j).AllocL();
+        TPtrC searchStringPtr(*searchString);    
+        CleanupStack::PushL( searchString );
+        
+        for ( TInt i = 0; i < searchStringPtr.Length(); i++ )
+            {    
+            // Add a query item
+            CPsQueryItem* item = CPsQueryItem::NewL();
+            item->SetCharacter(searchStringPtr[i]); 
+            
+            TInt qwertyNumber = KErrCancel;
+            if( iPredictiveSearch )
+                {
+                TLex numberVal( searchStringPtr.Mid(i, 1) );
+                TInt num = 0;
+                qwertyNumber = numberVal.Val(num);
+                }
+            if( qwertyNumber == KErrNone )
+                {
+                // Set qwerty search mode (in predictive search we can tap numbers only by long tap)
+                item->SetMode( EQwerty );
+                }
+            else
+                {
+                // Set current search mode
+                item->SetMode( pcsKeyboardMode );
+                }
+            
+            iPsQuery->AppendL(*item);      
+            }
+        
+        //Add a space in between two words
+        if(aFindStrings.MdcaCount() > 1)
+            {
+            CPsQueryItem* item = CPsQueryItem::NewL();
+            item->SetCharacter(Kspace);   
+            item->SetMode(EItut);
+            iPsQuery->AppendL(*item);    
+            }
+       
+        //Cleanup
+        CleanupStack::PopAndDestroy( searchString);
+        }
+    
+    //Send the search query to the  PCS engine
+    iPsHandler->SearchL(*iPsQuery);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::Reset
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::Reset()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2PredictiveViewStack::Reset: topview(0x%x), current stack level = %d"));  
+    TRAP_IGNORE(iSearchFilter.ResetL());
+    iPsHandler->CancelSearch();
+    ClearSearch();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ClearSearch
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::ClearSearch()
+    {
+    iNonMatchedMarkedContactStartIndex = KErrNotFound;
+    iNonMatchedMarkedContactEndIndex = KErrNotFound;
+    iSearchedState = EFalse;
+    iPredictiveSearchResultContactLinkArrray->ResetAndDestroy();
+    iTopContactPositionInfoArray.ResetAndDestroy();
+    iSearchText.Close();
+    SendTopViewChangedEvent( *iBaseView );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::BaseView
+// --------------------------------------------------------------------------
+//
+MVPbkContactViewBase& CPbk2PredictiveViewStack::BaseView() const
+    {
+    return *iBaseView;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::SetNewBaseViewL
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::SetNewBaseViewL(
+        MVPbkContactViewBase& aBaseView )
+    {
+    Reset();
+    
+    // Remove observering the old base view
+    if ( iBaseView )
+        {
+        iBaseView->RemoveObserver( *this );
+        }
+
+    iBaseView = &aBaseView;
+
+    // Start listening to new base view
+    iBaseView->AddObserverL( *this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::Level
+// --------------------------------------------------------------------------
+//
+TInt CPbk2PredictiveViewStack::Level() const
+    {
+    if ( iSearchedState )
+        {
+        return 1;
+        }
+        
+    return 0;
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStack::AddStackObserverL
+// --------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::AddStackObserverL(
+        MPbk2FilteredViewStackObserver& aStackObserver )
+    {
+    iStackObservers.AppendL( &aStackObserver );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStack::RemoveStackObserver
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::RemoveStackObserver(
+        MPbk2FilteredViewStackObserver& aStackObserver )
+    {
+    TInt index = iStackObservers.Find( &aStackObserver );
+    if ( index != KErrNotFound )
+        {
+        iStackObservers.Remove( index );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::Type
+// --------------------------------------------------------------------------
+//
+TVPbkContactViewType CPbk2PredictiveViewStack::Type() const
+    {
+    return iBaseView->Type();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ChangeSortOrderL
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::ChangeSortOrderL(
+        const MVPbkFieldTypeList& aSortOrder )
+    {
+    return iBaseView->ChangeSortOrderL( aSortOrder );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::SortOrder
+// --------------------------------------------------------------------------
+//
+const MVPbkFieldTypeList& CPbk2PredictiveViewStack::SortOrder() const
+    {
+    return iBaseView->SortOrder();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::RefreshL
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::RefreshL()
+    {
+    return iBaseView->RefreshL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ContactCountL
+// --------------------------------------------------------------------------
+//
+TInt CPbk2PredictiveViewStack::ContactCountL() const
+    {
+    TInt count;
+    if ( iSearchedState )
+        {
+        count = iPredictiveSearchResultContactLinkArrray->Count();
+        }
+    else
+        {
+        count = iBaseView->ContactCountL();
+        }
+    return count;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ContactAtL
+// --------------------------------------------------------------------------
+//
+const MVPbkViewContact& CPbk2PredictiveViewStack::ContactAtL
+        ( TInt aIndex ) const
+    {
+    TInt ret = BaseViewIndex( aIndex);
+    User::LeaveIfError( ret );
+    return iBaseView->ContactAtL( ret  );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::CreateLinkLC
+// --------------------------------------------------------------------------
+//
+MVPbkContactLink* CPbk2PredictiveViewStack::CreateLinkLC( TInt aIndex ) const
+    {
+    TInt ret = BaseViewIndex( aIndex);
+    User::LeaveIfError( ret );
+    return iBaseView->CreateLinkLC( ret );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::IndexOfLinkL
+// --------------------------------------------------------------------------
+//
+TInt CPbk2PredictiveViewStack::IndexOfLinkL(
+        const MVPbkContactLink& aContactLink ) const
+    {
+    TInt ret = KErrNotFound;
+    
+    if ( iSearchedState )
+        {
+        ret = iPredictiveSearchResultContactLinkArrray->Find( aContactLink );
+        }
+    else
+        {
+        // Just return the index in the baseview
+        ret = iBaseView->IndexOfLinkL( aContactLink );
+        }
+    
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::AddObserverL
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::AddObserverL
+        ( MVPbkContactViewObserver& aObserver )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2PredictiveViewStack::AddObserverL - IN"));
+
+    if ( IsActive() )
+        {
+        Cancel();
+        }
+    
+    TRequestStatus* status = &iStatus;
+    User::RequestComplete( status, KErrNone );
+    SetActive();
+
+    // Events are sent in reverse order so insert to first position.
+    iViewObservers.InsertL( &aObserver, 0 );
+    
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2PredictiveViewStack::AddObserverL - OUT"));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::RemoveObserver
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::RemoveObserver(
+        MVPbkContactViewObserver& aObserver )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2PredictiveViewStack::RemoveObserver - IN"));
+    
+    TInt index = iViewObservers.Find( &aObserver );
+    if ( index != KErrNotFound )
+        {
+        iViewObservers.Remove( index );
+        }
+        
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2PredictiveViewStack::RemoveObserver - OUT"));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::MatchContactStore
+// --------------------------------------------------------------------------
+//
+TBool CPbk2PredictiveViewStack::MatchContactStore(
+        const TDesC& aContactStoreUri ) const
+    {
+    return iBaseView->MatchContactStore( aContactStoreUri );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::MatchContactStoreDomain
+// --------------------------------------------------------------------------
+//
+TBool CPbk2PredictiveViewStack::MatchContactStoreDomain(
+        const TDesC& aContactStoreDomain ) const
+    {
+    return iBaseView->MatchContactStoreDomain( aContactStoreDomain );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::CreateBookmarkLC
+// --------------------------------------------------------------------------
+//
+MVPbkContactBookmark* CPbk2PredictiveViewStack::CreateBookmarkLC(
+        TInt aIndex ) const
+    {
+    return iBaseView->CreateBookmarkLC( BaseViewIndex( aIndex ) );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::IndexOfBookmarkL
+// --------------------------------------------------------------------------
+//
+TInt CPbk2PredictiveViewStack::IndexOfBookmarkL(
+        const MVPbkContactBookmark& aContactBookmark ) const
+    {
+    TInt ret = KErrNotFound;
+    
+    if ( iSearchedState )
+        {
+        TInt indexInBaseView = iBaseView->IndexOfBookmarkL( aContactBookmark );
+        const MVPbkViewContact& contact = iBaseView->ContactAtL( indexInBaseView );
+        
+        TInt countInSearchedResult = iPredictiveSearchResultContactLinkArrray->Count();
+        
+        for ( TInt i = 0; i < countInSearchedResult && ret == KErrNotFound; i++ )
+            {
+            const MVPbkContactLink& link = iPredictiveSearchResultContactLinkArrray->At( i );
+            if ( link.RefersTo( contact ) )
+                {
+                ret = i;
+                }
+            }
+        }
+    else
+        {
+        ret = iBaseView->IndexOfBookmarkL( aContactBookmark );
+        }
+    
+    return ret;  
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ViewFiltering
+// --------------------------------------------------------------------------
+//
+MVPbkContactViewFiltering* CPbk2PredictiveViewStack::ViewFiltering()
+    {
+    // The stack itself doesn't support filtering
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ContactViewReady
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::ContactViewReady( MVPbkContactViewBase& /*aView*/ )
+    {
+    iViewReady = ETrue;
+    SendBaseViewChangedEvent();
+
+    SendEventToObservers( *this, iViewObservers,
+        MVPbkContactViewObserver::ContactViewReady );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ContactViewUnavailable
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::ContactViewUnavailable(
+        MVPbkContactViewBase& /*aView*/ )
+    {
+    iViewReady = EFalse;
+    SendEventToObservers( *this, iViewObservers,
+        MVPbkContactViewObserver::ContactViewUnavailable );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ContactAddedToView
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::ContactAddedToView
+        ( MVPbkContactViewBase& aView, TInt aIndex,
+          const MVPbkContactLink& aContactLink )
+    {
+    // Reset since we need to return to base view
+    // when a new contact is added
+   Reset();
+
+   //Send observer events   
+   if ( iBaseView == &aView )
+        {
+        SendEventToObservers( *this, iStackObservers,
+            MPbk2FilteredViewStackObserver::ContactAddedToBaseView, aIndex,
+            aContactLink );
+        
+        // Always forward only top view events to clients
+        SendEventToObservers( *this, iViewObservers,
+            MVPbkContactViewObserver::ContactAddedToView, aIndex,
+            aContactLink );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ContactRemovedFromView
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::ContactRemovedFromView
+        ( MVPbkContactViewBase& aView, TInt aIndex,
+          const MVPbkContactLink& aContactLink )
+    {
+    TRAP_IGNORE ( HandleContactDeletionL( aView, aIndex,aContactLink ) )
+    
+    //Send observer events  
+    if ( iBaseView == &aView )
+        {
+        // Always forward top view events to clients
+        SendEventToObservers( *this, iViewObservers,
+            MVPbkContactViewObserver::ContactRemovedFromView, aIndex,
+            aContactLink );
+         }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::ContactViewError
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::ContactViewError
+        ( MVPbkContactViewBase& aView, TInt aError, TBool aErrorNotified )
+    {
+    iViewReady = EFalse;
+    //Send observer events   
+    if ( iBaseView == &aView )
+        {
+        // Always forward only top view events to clients
+        SendEventToObservers( *this, iViewObservers,
+            MVPbkContactViewObserver::ContactViewError, aError,
+            aErrorNotified );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::HandlePsResultsUpdate
+// --------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::HandlePsResultsUpdate(
+    RPointerArray<CPsClientData>& aSearchResults,
+    RPointerArray<CPsPattern>& searchSeqs )
+    {
+    //set the searched state to indicate that
+    // predictive search view is now active
+    iSearchedState = ETrue;
+    
+    // update pattern array
+    TRAP_IGNORE( CreatePatternsL(searchSeqs) );
+        
+    //Clean up the data stored during previous search
+    iPredictiveSearchResultContactLinkArrray->ResetAndDestroy();
+    iTopContactPositionInfoArray.ResetAndDestroy();
+	
+    //Calculate the search result indexes
+    TRAPD( err, CalculateSearchResultIndexesL( aSearchResults ) );
+    if ( err != KErrNone )
+        {
+        Reset();       
+        }  
+    else
+        {
+        if ( !aSearchResults.Count() )
+            {
+            TRAP_IGNORE( SendPSNoResultsEventL() );
+            }
+        }
+    
+    SendTopViewChangedEvent( *this );
+    }
+    
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::HandlePsError
+// --------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::HandlePsError( TInt /*aErrorCode*/ )
+    {
+    Reset();
+    TRAP_IGNORE( InitializePCSEngineL() );
+    }
+    
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::CachingStatus
+// --------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::CachingStatus( TCachingStatus& /*aStatus*/,
+    TInt& /*aError*/)
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::RunL
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::RunL()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2PredictiveViewStack::RunL - IN"));
+    
+    if ( iViewReady )
+        {
+        iViewObservers[0]->ContactViewReady( *this );
+        }
+        
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2PredictiveViewStack::RunL - OUT"));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::DoCancel
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::DoCancel()
+    {
+    // Nothing to cancel
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::RunError
+// --------------------------------------------------------------------------
+//
+TInt CPbk2PredictiveViewStack::RunError( TInt aError )
+    {
+    iViewObservers[0]->ContactViewError( *this, aError, ETrue );
+    return KErrNone;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::CalculateSearchResultIndexesL
+// --------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::CalculateSearchResultIndexesL(
+    RPointerArray<CPsClientData>& aSearchResults )
+    {
+	__ASSERT_ALWAYS( iTopContactManager, User::Leave( KErrGeneral ) );
+	
+	//Holds the Matched Char Seq of the First Item in the 
+	//Nameslist View w.r.t the initiated Predictive Search
+	TBuf<KSearchFieldLength> matchSeqChr; 
+	
+	CVPbkContactManager& cntManager = Phonebook2::Pbk2AppUi()->
+        ApplicationServices().ContactManager();
+    
+    const TInt resultCount = aSearchResults.Count();
+    for( TInt n = 0 ; n < resultCount ; ++n )
+        {         
+        // Store the view index of search results
+        CPsClientData* result = aSearchResults[n];                
+        MVPbkContactLink* contactLink = iPsHandler->ConvertToVpbkLinkLC(*result,cntManager);
+        
+        //Get the index in the base view
+        // We need to check if base view contains this contact
+        TInt posInBaseView = iBaseView->IndexOfLinkL( *contactLink );
+        if ( posInBaseView != KErrNotFound )
+            {
+            const MVPbkViewContact& contact = iBaseView->ContactAtL( posInBaseView );
+            TBuf< KPsQueryMaxLen > result;
+            iSearchFilter.LookupL( contact, *this, iNameformatter, result );
+            
+            if( result.Length() <= 0 )
+                {
+                CleanupStack::Pop(); //contactLink
+                continue;
+                }
+            
+            TBool topcontact = iTopContactManager->IsTopContact( contact );
+            if ( topcontact )
+                {
+                // ownership of contactLink is transfered, CPbk2TopContactPositionInfo
+                // also keeps the contactLink' position from iBaseView
+                CPbk2ContactPositionInfo* topContactPosInfo = 
+                    CPbk2ContactPositionInfo::NewLC( contactLink, posInBaseView );
+                   
+                iTopContactPositionInfoArray.AppendL( topContactPosInfo ); 
+                CleanupStack::Pop( topContactPosInfo );
+                }
+            else
+                {
+                iPredictiveSearchResultContactLinkArrray->AppendL( contactLink );     
+                }
+            CleanupStack::Pop(); //contactLink
+            }
+        else
+            {
+            CleanupStack::PopAndDestroy(); //contactLink
+            }
+        }
+ 
+    iNonMatchedMarkedContactStartIndex = KErrNotFound;
+    iNonMatchedMarkedContactEndIndex = KErrNotFound;
+    
+    //save marked contacts info to iMarkedContactsPositionInfoArray
+    if ( iBookMarkCollection )
+        {
+        SaveBookmarkContatsInfoL();
+        SortbyPositionInMainView( iMarkedContactsPositionInfoArray );
+        iNonMatchedMarkedContactStartIndex = 0;
+        iNonMatchedMarkedContactEndIndex = iMarkedContactsPositionInfoArray.Count() - 1;
+        MoveArrayToSearchedResultTopL( iMarkedContactsPositionInfoArray );        
+        }
+    
+    // add those top contacts to top of the iPredictiveSearchResultContactLinkArrray,
+    // the order follows top contact orders in name list
+    SortbyPositionInMainView( iTopContactPositionInfoArray );
+    if ( iNonMatchedMarkedContactStartIndex != KErrNotFound )
+        {
+        iNonMatchedMarkedContactStartIndex += iTopContactPositionInfoArray.Count();
+        iNonMatchedMarkedContactEndIndex += iTopContactPositionInfoArray.Count();
+        }
+    MoveArrayToSearchedResultTopL( iTopContactPositionInfoArray );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::InitializePCSEngineL
+// --------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::InitializePCSEngineL()
+    {
+    	if(iPsHandler)
+    	  {
+    		delete iPsHandler;
+    		iPsHandler = NULL;
+    	  }	
+    // Create async request handle for predictive search engine
+    iPsHandler = CPSRequestHandler::NewL();
+    iPsHandler->AddObserverL( this );
+    
+    // If the iCurrentGroupLink is set, then no need to re-do the settings.It is already done.
+     if(iCurrentGroupLink)
+         {
+         return;  
+         }
+       
+    RPointerArray<TDesC> databases;
+    if ( iBaseView->MatchContactStore( VPbkContactStoreUris::SimGlobalFdnUri() ) )
+        {
+        //FDN view, initialize PS with FDN contacts only
+        databases.AppendL(VPbkContactStoreUris::SimGlobalFdnUri().AllocL());
+        }
+    else
+        {
+        CPbk2StoreConfiguration& config = Phonebook2::Pbk2AppUi()->ApplicationServices().StoreConfiguration();
+        CVPbkContactStoreUriArray* stores = config.SearchStoreConfigurationL();
+        CleanupStack::PushL(stores);
+        TInt count = stores->Count();
+        for ( TInt i = 0; i < count; ++i)
+            {
+            TVPbkContactStoreUriPtr uriPtr = stores->operator[](i);
+            databases.AppendL(uriPtr.UriDes().AllocL());
+            }
+        CleanupStack::PopAndDestroy(); //stores
+        }
+    
+    
+    SetPsSettingL(databases);
+   
+    databases.ResetAndDestroy();
+    
+    }
+
+// --------------------------------------------------------------------------
+// Maps from the search subset position index to base view index.
+// @param aSearchResultIndex Index within scope of search result set.
+// @return Index of the contact in base view.
+// --------------------------------------------------------------------------
+TInt CPbk2PredictiveViewStack::BaseViewIndex( TInt aSearchResultIndex ) const
+    {
+    // If search is not active, the argument is actually already a base view index.
+    TInt index = aSearchResultIndex;
+    if ( iSearchedState )
+        {
+        TRAP_IGNORE( index = 
+            iBaseView->IndexOfLinkL(
+                iPredictiveSearchResultContactLinkArrray->At( aSearchResultIndex ) ) );
+        }
+        
+    return index;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::HandleContactDeletionL
+// --------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::HandleContactDeletionL( MVPbkContactViewBase& /*aView*/,
+    TInt /*aIndex*/, const MVPbkContactLink& aContactLink )
+    {
+    
+    TInt removedContactPos = iPredictiveSearchResultContactLinkArrray->Find(aContactLink);
+    if(removedContactPos != KErrNotFound)
+        {
+        //Remove the link from iPredictiveSearchResultContactLinkArrray
+        iPredictiveSearchResultContactLinkArrray->Remove(removedContactPos);                   
+        }
+    
+    if (iPredictiveSearchResultContactLinkArrray->Count() == 0)
+        {
+        //clear patterns collection
+        iPatternsCollection.ResetAndDestroy();
+        // back to name list view
+        iSearchFilter.FindPaneResetL();
+        // Reset() must be called after iSearchFilter.FindPaneResetL()
+        // as it will make some judgment by the content of FindBox.
+        Reset();
+        }
+    
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::SendTopViewChangedEvent
+// --------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::SendTopViewChangedEvent
+        ( MVPbkContactViewBase& aOldTopView )
+    {
+    const TInt count = iStackObservers.Count();
+    for ( TInt i = count - 1; i >= 0; --i )
+        {
+        TRAPD( res, iStackObservers[i]->TopViewChangedL( aOldTopView ) );
+        if ( res != KErrNone )
+            {
+            PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+                ("CPbk2FilteredViewStack::SendTopViewChangedEvent:error %d"),
+                res );
+            iStackObservers[i]->ViewStackError( res );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStack::SendTopViewUpdatedEvent
+// --------------------------------------------------------------------------
+//
+void CPbk2PredictiveViewStack::SendTopViewUpdatedEvent()
+    {
+    const TInt count = iStackObservers.Count();
+    for ( TInt i = count - 1; i >= 0; --i )
+        {
+        TRAPD( res, iStackObservers[i]->TopViewUpdatedL() );
+        if ( res != KErrNone )
+            {
+            PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+                ("CPbk2FilteredViewStack::SendTopViewUpdatedEvent:error %d"),
+                res );
+            iStackObservers[i]->ViewStackError( res );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStack::SendBaseViewChangedEvent
+// --------------------------------------------------------------------------
+//    
+void CPbk2PredictiveViewStack::SendBaseViewChangedEvent()
+    {
+    const TInt count = iStackObservers.Count();
+    for ( TInt i = count - 1; i >= 0; --i )
+        {
+        TRAPD( res, iStackObservers[i]->BaseViewChangedL() );
+        if ( res != KErrNone )
+            {
+            PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+                ("CPbk2FilteredViewStack::SendBaseViewChangedEvent:error %d"),
+                res );
+            iStackObservers[i]->ViewStackError( res );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::LastPCSQuery
+// ---------------------------------------------------------------------------
+const CPsQuery* CPbk2PredictiveViewStack::LastPCSQuery() const
+    {
+    return iSearchedState?iPsQuery:NULL;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::PSHandler
+// ---------------------------------------------------------------------------
+CPSRequestHandler* CPbk2PredictiveViewStack::PSHandler() const
+    {
+    return iPsHandler;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::CreatePatternsL()
+// ---------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::CreatePatternsL(RPointerArray<CPsPattern>& searchSeqs)
+    {
+    iPatternsCollection.ResetAndDestroy();
+    iBidiPatterns.ResetAndDestroy();
+    TBidirectionalState::TRunInfo* runInfoArray = new (ELeave)TBidirectionalState::TRunInfo[4];
+
+    for (TInt i = 0; i < searchSeqs.Count(); i++)
+        {
+        //create standard pattern
+        TInt nIndex = searchSeqs[i]->FirstIndex();  
+        TDesC& patternText = searchSeqs[i]->Pattern();
+        CPsPattern* pattern = CPsPattern::NewL();
+        iPatternsCollection.Append(pattern);
+        pattern->SetFirstIndex( nIndex );
+        pattern->SetPatternL( patternText );
+
+        //create bidirectional pattern
+        HBufC* bidiPattern = HBufC::NewLC( patternText.Length() + TBidiLogicalToVisual::KMinCharAvailable );
+        TPtr tmpPtr2 = bidiPattern->Des();
+        TBidiLogicalToVisual converter2( patternText, runInfoArray, /*runInfoArrayMaxLength*/4 ) ;
+        converter2.Reorder();
+        converter2.GetVisualLine( tmpPtr2, 0, patternText.Length(), TChar(0xffff) );
+        iBidiPatterns.Append( bidiPattern );
+        CleanupStack::Pop( bidiPattern );
+        }
+    delete runInfoArray; 
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::GetMatchingPartsL()
+// Main assumption to use this method only for bidirectional
+// languages and patterns
+// ---------------------------------------------------------------------------
+void CPbk2PredictiveViewStack::GetMatchingPartsL( const TDesC& aSearchData,
+                      RArray<TPsMatchLocation>& aMatchLocation) const
+    {
+    // If list of mathes empty just return
+    if ( iPatternsCollection.Count() == 0 )
+        {
+        return;
+        }
+    //This method is implemented for bidirectional languages only
+    RBuf parserText;
+    parserText.CreateL(aSearchData);
+    parserText.CleanupClosePushL();
+    TLex lexParser(parserText);
+    TPtrC ptr;
+    //parse for all words in contact information
+    TInt currentPos = 0;
+    lexParser.SkipSpace();
+    currentPos = lexParser.Offset();
+    for (ptr.Set(lexParser.NextToken()); ptr.Length(); ptr.Set(lexParser.NextToken()) )
+        {
+        //loop by all patterns
+        for (TInt j = iBidiPatterns.Count() - 1; j >= 0; j--)
+            {
+            HBufC* pattern = iBidiPatterns[j];
+            TInt pos =  ptr.Find(pattern->Des());
+            if ( pos != KErrNotFound)
+                {
+                //check if pattern is in th end of the string
+                if ( (pos + pattern->Length()) == ptr.Length() ) 
+                    {
+                    // add math to output array
+                    TPsMatchLocation location;
+                    location.index = currentPos + pos;
+                    location.length = pattern->Length();
+                    location.direction = TBidiText::ELeftToRight;
+                    aMatchLocation.Append(location);
+                    break;
+                    }
+                }
+            }
+        lexParser.SkipSpace();
+        currentPos = lexParser.Offset();
+        }
+    CleanupStack::PopAndDestroy();//parserText
+    }
+	
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::SetCurrentGroupLinkL
+// --------------------------------------------------------------------------
+//   
+void CPbk2PredictiveViewStack::SetCurrentGroupLinkL( MVPbkContactLink* aGroupLinktoSet)
+    {
+    
+    //Create contactid converter instance for default store if not already exists
+    if(!iConverterDefaultStore)
+        {
+        CVPbkContactManager& manager = Phonebook2::Pbk2AppUi()->
+            ApplicationServices().ContactManager();
+        MVPbkContactStore* defaultStore = manager.ContactStoresL().Find(
+            VPbkContactStoreUris::DefaultCntDbUri() );
+        __ASSERT_DEBUG( defaultStore, User::Panic(_L("Pbk2 vstack"), 52));
+        
+        iConverterDefaultStore = CVPbkContactIdConverter::NewL( *defaultStore );
+        }
+    //Delete the existing group link 
+    if(iCurrentGroupLink)
+        {
+        delete iCurrentGroupLink;
+        iCurrentGroupLink = NULL;
+        }
+    
+    
+    iCurrentGroupLink = aGroupLinktoSet->CloneLC();
+    CleanupStack::Pop();
+        
+    if(iCurrentGroupLink)
+        {
+        RPointerArray<TDesC> databases;
+        RBuf storeUrl; 
+        //CleanupResetAndDestroyPushL( databases );
+        // Set max size for group URI
+        TInt32 maxLength = sizeof(TInt32) + KVPbkDefaultGrpDbURI().Size() + 
+                                 KPsGroupDBSuffix().Size() + 2;
+        storeUrl.CreateL(KVPbkDefaultGrpDbURI(), maxLength);
+        storeUrl.CleanupClosePushL();
+        
+        //get group id and create the url to be passed to ps engine
+        TInt32 id = iConverterDefaultStore->LinkToIdentifier(*iCurrentGroupLink);
+        storeUrl.AppendFormat(KPsGroupDBSuffix, NULL, id);
+        databases.AppendL(storeUrl.AllocL());
+        CleanupStack::PopAndDestroy(&storeUrl);
+        
+        // Perform the search settings
+        SetPsSettingL(databases);
+        
+        databases.ResetAndDestroy();
+        }
+        
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::SetPsSettingL
+// --------------------------------------------------------------------------
+//   
+void CPbk2PredictiveViewStack::SetPsSettingL( RPointerArray<TDesC>& aDatabases) 
+    {
+    // Perform search settings
+    CPsSettings* psSettings = CPsSettings::NewL();
+    CleanupStack::PushL( psSettings );    
+    psSettings->SetSearchUrisL(aDatabases);
+        
+    RArray<TInt> displayFields;
+    displayFields.AppendL(R_VPBK_FIELD_TYPE_FIRSTNAME); // Firstname
+    displayFields.AppendL(R_VPBK_FIELD_TYPE_LASTNAME); // Lastname
+    displayFields.AppendL(R_VPBK_FIELD_TYPE_COMPANYNAME);// Companyname
+   
+    psSettings->SetDisplayFieldsL(displayFields);
+
+    iPsHandler->SetSearchSettingsL(*psSettings);
+    
+    //Clean up
+    CleanupStack::PopAndDestroy(psSettings);
+    displayFields.Close();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::SaveBookmarkContatsInfoL
+// --------------------------------------------------------------------------
+//  
+void CPbk2PredictiveViewStack::SaveBookmarkContatsInfoL()
+    {
+    TInt count = iBookMarkCollection->Count();
+    
+    for ( TInt i = count-1; i >= 0; i-- )
+        {
+        const MVPbkContactBookmark& contactBookmark = 
+            iBookMarkCollection->At( i );
+        TInt indexInBaseView = iBaseView->IndexOfBookmarkL( contactBookmark );
+        
+        if ( indexInBaseView != KErrNotFound )
+            {
+            MVPbkContactLink* link = iBaseView->CreateLinkLC( indexInBaseView );
+            
+            // find from Searched result
+            TInt indexInSearchedResult = iPredictiveSearchResultContactLinkArrray->Find( *link );
+ 
+            TInt matchingTopContactIndex = MatchingTopContactFind( indexInBaseView );
+            
+            if ( indexInSearchedResult == KErrNotFound && 
+                    matchingTopContactIndex == KErrNotFound )
+                {
+                const MVPbkViewContact& contact = iBaseView->ContactAtL( indexInBaseView );
+                
+                CPbk2ContactPositionInfo* positionInfo = CPbk2ContactPositionInfo::NewLC( link, indexInBaseView );
+                CleanupStack::Pop( positionInfo );
+                CleanupStack::Pop(); // link
+                CleanupStack::PushL( positionInfo );
+                
+                // non matching marked top contacts
+                if ( iTopContactManager->IsTopContact( contact ) )
+                    {
+                    iTopContactPositionInfoArray.AppendL( positionInfo );
+                    }
+                else
+                    {
+                    // non matching marked contacts(non top)
+                    iMarkedContactsPositionInfoArray.AppendL( positionInfo );
+                    }
+                
+                CleanupStack::Pop( positionInfo );
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy(); // link
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::MoveArrayToSearchedResultTopL
+// --------------------------------------------------------------------------
+//  
+void CPbk2PredictiveViewStack::MoveArrayToSearchedResultTopL( 
+        RPointerArray<CPbk2ContactPositionInfo>& aContactInfoArray )
+    {
+    TInt posZero = 0;
+    TInt count = aContactInfoArray.Count();
+   
+    for( TInt i = count-1; i >=0; i-- )
+        {
+        CPbk2ContactPositionInfo* positionInfo = aContactInfoArray[ i ];
+ 
+        // ownership of contactLink is transferred
+        MVPbkContactLink* contactLink = positionInfo->ContactLink();
+        CleanupStack::PushL( contactLink );
+        // always insert to the top of iPredictiveSearchResultContactLinkArrray
+        iPredictiveSearchResultContactLinkArrray->InsertL( contactLink, posZero ); 
+        CleanupStack::Pop( contactLink );
+        // remove positionInfo from iTopContactPositionInfoArray
+        aContactInfoArray.Remove( i );
+        delete positionInfo;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::MatchingTopContactFind
+// --------------------------------------------------------------------------
+//  
+TInt CPbk2PredictiveViewStack::MatchingTopContactFind( const TInt aIndexInBaseView )
+    {
+    TInt ret = KErrNotFound;
+    
+    TInt topContactCount = iTopContactPositionInfoArray.Count();
+    for( TInt i = 0; i < topContactCount && ret == KErrNotFound; i++ )
+        {
+        CPbk2ContactPositionInfo* topContactPositionInfo = 
+            iTopContactPositionInfoArray[i];
+        
+        if ( aIndexInBaseView == topContactPositionInfo->Position() )
+            {
+            ret = i;
+            }
+        }
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2PredictiveViewStack::SortbyPositionInMainView
+// --------------------------------------------------------------------------
+// 
+void CPbk2PredictiveViewStack::SortbyPositionInMainView( 
+                 RPointerArray<CPbk2ContactPositionInfo>& aContactInfoArray )
+    {
+    TLinearOrder< CPbk2ContactPositionInfo > 
+    position( *CPbk2ContactPositionInfo::CompareByPosition );
+    aContactInfoArray.Sort( position );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStack::SendPSNoResultsEventL
+// --------------------------------------------------------------------------
+//  
+void CPbk2PredictiveViewStack::SendPSNoResultsEventL()
+    {
+    CPsQuery* lastQuery = const_cast<CPsQuery*> (LastPCSQuery());    
+    if ( lastQuery )
+        {        
+        TDesC& strQuery = lastQuery->QueryAsStringLC();   
+        //Send the matched char Sequence of the first item
+        //to the Search Pane filter 
+        iSearchFilter.HandlePSNoMatchL( strQuery, KNullDesC );
+        CleanupStack::PopAndDestroy(); // QueryAsStringLC
+        } 
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStack::IsNonMatchingMarkedContact
+// --------------------------------------------------------------------------
+//
+TBool CPbk2PredictiveViewStack::IsNonMatchingMarkedContact( const TInt aIndex )
+    {
+    TBool ret = EFalse;
+    
+    if ( aIndex >= iNonMatchedMarkedContactStartIndex &&
+           aIndex <= iNonMatchedMarkedContactEndIndex )
+        {
+        ret = ETrue;
+        }
+    return ret;
+    }
+
+// End of File