Bug 2312 - Fix various GCCE compiler compatibility issues.
/*
* 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