--- /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