diff -r 5b6f26637ad3 -r f4a778e096c2 phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkFindView.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkFindView.cpp Wed Sep 01 12:29:52 2010 +0100 @@ -0,0 +1,670 @@ +/* +* 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: Filtered contact view +* +*/ +#include +#include "CVPbkFindView.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include + +namespace { +const TInt KObserverArrayGranularity( 4 ); +const TInt KGranularity( 2 ); + +// --------------------------------------------------------------------------- +// Event sending function for one reference parameter +// --------------------------------------------------------------------------- +// +template +void SendEventToObservers(MVPbkContactViewBase& aView, + RPointerArray& iObservers, + NotifyFunc aNotifyFunc) + { + const TInt count = iObservers.Count(); + for (TInt i = count - 1; i >= 0; --i) + { + MVPbkContactViewObserver* observer = iObservers[i]; + (observer->*aNotifyFunc)(aView); + } + } + +// --------------------------------------------------------------------------- +// Event sending functions for 3 parameters +// --------------------------------------------------------------------------- +// +template +void SendEventToObservers(MVPbkContactViewBase& aView, + RPointerArray& iObservers, + NotifyFunc aNotifyFunc, + ParamType1 aParam1, + const ParamType2& aParam2) + { + const TInt count = iObservers.Count(); + for (TInt i = count - 1; i >= 0; --i) + { + MVPbkContactViewObserver* observer = iObservers[i]; + (observer->*aNotifyFunc)(aView, aParam1, aParam2); + } + } + +} // namespace + + +// --------------------------------------------------------------------------- +// CVPbkFindView::CVPbkFindView +// --------------------------------------------------------------------------- +// +CVPbkFindView::CVPbkFindView( + MVPbkContactViewBase& aBaseView, + const MVPbkFieldTypeList* aMasterFieldTypeList ) : + iBaseView(aBaseView), + iMasterFieldTypeList( aMasterFieldTypeList ), + iObservers( KObserverArrayGranularity ) + { + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::ConstructL +// --------------------------------------------------------------------------- +// +inline void CVPbkFindView::ConstructL( + const MDesCArray& aFindWords, + const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ConstructL(0x%x)"), this); + + iAsyncOperation = new(ELeave) VPbkEngUtils::CVPbkAsyncOperation; + + iFindStrings = new(ELeave)CDesCArrayFlat( KGranularity ); + SetFindStringsL( aFindWords ); + + SetAlwaysIncludedContactsL( aAlwaysIncludedContacts ); + + + CEikonEnv* eikonEnv = CEikonEnv::Static(); + + if ( eikonEnv ) + { + CVPbkContactFindPolicy::TParam param = + CVPbkContactFindPolicy::TParam( + *iMasterFieldTypeList, + eikonEnv->FsSession() ); + + // Create contact find policy + iContactFindPolicy = CVPbkContactFindPolicy::NewL( param ); + } + + iBaseView.AddObserverL(*this); + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ConstructL(0x%x) end"), this); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::NewL +// --------------------------------------------------------------------------- +// +CVPbkFindView* CVPbkFindView::NewLC( + MVPbkContactViewBase& aBaseView, + MVPbkContactViewObserver& aObserver, + const MDesCArray& aFindWords, + const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts, + const MVPbkFieldTypeList& aMasterFieldTypeList ) + { + CVPbkFindView* self = + new(ELeave) CVPbkFindView( + aBaseView, &aMasterFieldTypeList ); + CleanupStack::PushL(self); + self->ConstructL( aFindWords, aAlwaysIncludedContacts ); + self->AddObserverL(aObserver); + return self; + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::~CVPbkFindView +// --------------------------------------------------------------------------- +// +CVPbkFindView::~CVPbkFindView() + { + iContactMapping.Reset(); + iBaseView.RemoveObserver(*this); + iObservers.Close(); + delete iFindStrings; + delete iContactFindPolicy; + delete iAsyncOperation; + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::Type +// --------------------------------------------------------------------------- +// +TVPbkContactViewType CVPbkFindView::Type() const + { + return iBaseView.Type(); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::ChangeSortOrderL +// --------------------------------------------------------------------------- +// +void CVPbkFindView::ChangeSortOrderL( + const MVPbkFieldTypeList& aSortOrder ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ChangeSortOrderL(0x%x)"), &aSortOrder); + + iBaseView.ChangeSortOrderL(aSortOrder); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::SortOrder +// --------------------------------------------------------------------------- +// +const MVPbkFieldTypeList& CVPbkFindView::SortOrder() const + { + return iBaseView.SortOrder(); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::RefreshL +// --------------------------------------------------------------------------- +// +void CVPbkFindView::RefreshL() + { + iBaseView.RefreshL(); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::ContactCountL +// --------------------------------------------------------------------------- +// +TInt CVPbkFindView::ContactCountL() const + { + return iContactMapping.Count(); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::ContactAtL +// --------------------------------------------------------------------------- +// +const MVPbkViewContact& CVPbkFindView::ContactAtL( + TInt aIndex ) const + { + __ASSERT_ALWAYS( aIndex >= 0, + VPbkError::Panic( VPbkError::EInvalidContactIndex ) ); + if ( aIndex >= iContactMapping.Count() ) + { + User::Leave( KErrArgument ); + } + + return iBaseView.ContactAtL(iContactMapping[aIndex]); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::CreateLinkLC +// --------------------------------------------------------------------------- +// +MVPbkContactLink* CVPbkFindView::CreateLinkLC( TInt aIndex ) const + { + __ASSERT_ALWAYS( aIndex >= 0, + VPbkError::Panic( VPbkError::EInvalidContactIndex ) ); + if ( aIndex >= iContactMapping.Count() ) + { + User::Leave( KErrArgument ); + } + + return iBaseView.ContactAtL(iContactMapping[aIndex]).CreateLinkLC(); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::IndexOfLinkL +// --------------------------------------------------------------------------- +// +TInt CVPbkFindView::IndexOfLinkL( + const MVPbkContactLink& aContactLink ) const + { + TInt baseIndex = iBaseView.IndexOfLinkL(aContactLink); + return iContactMapping.Find(baseIndex); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::AddObserverL +// --------------------------------------------------------------------------- +// +void CVPbkFindView::AddObserverL( + MVPbkContactViewObserver& aObserver ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::AddObserverL(0x%x)"), &aObserver); + + VPbkEngUtils::MAsyncCallback* notifyObserver = + VPbkEngUtils::CreateAsyncCallbackLC(*this, + &CVPbkFindView::DoAddObserverL, + &CVPbkFindView::AddObserverError, + aObserver); + iAsyncOperation->CallbackL(notifyObserver); + CleanupStack::Pop(notifyObserver); + + /// Insert to first position because event are send in reverse order. + /// Last inserted gets notifcation last. + iObservers.InsertL( &aObserver, 0 ); + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::AddObserverL(0x%x) end"), &aObserver); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::DoAddObserverL +// --------------------------------------------------------------------------- +// +void CVPbkFindView::DoAddObserverL( + MVPbkContactViewObserver& aObserver ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::DoAddObserverL(0x%x)"), &aObserver); + + if ( iObservers.Find( &aObserver ) != KErrNotFound ) + { + if ( iIsReady ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::DoAddObserverL(0x%x) contact view ready"), + &aObserver); + + // If this view is ready and there was no error, + // tell it to the observer + aObserver.ContactViewReady( *this ); + } + else + { + aObserver.ContactViewUnavailable( *this ); + } + } + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::DoAddObserverL(0x%x) end"), &aObserver); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::AddObserverError +// --------------------------------------------------------------------------- +// +void CVPbkFindView::AddObserverError( + MVPbkContactViewObserver& aObserver, TInt aError ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::AddObserverError(0x%x, %d)"), &aObserver, aError); + + aObserver.ContactViewError(*this, aError, EFalse); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::RemoveObserver +// --------------------------------------------------------------------------- +// +void CVPbkFindView::RemoveObserver( + MVPbkContactViewObserver& aObserver ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::RemoveObserverError(0x%x)"), &aObserver); + + const TInt index = iObservers.Find( &aObserver ); + if (index != KErrNotFound) + { + iObservers.Remove(index); + } + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::MatchContactStore +// --------------------------------------------------------------------------- +// +TBool CVPbkFindView::MatchContactStore( + const TDesC& aContactStoreUri ) const + { + return iBaseView.MatchContactStore(aContactStoreUri); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::MatchContactStoreDomain +// --------------------------------------------------------------------------- +// +TBool CVPbkFindView::MatchContactStoreDomain( + const TDesC& aContactStoreDomain ) const + { + return iBaseView.MatchContactStoreDomain(aContactStoreDomain); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::CreateBookmarkLC +// --------------------------------------------------------------------------- +// +MVPbkContactBookmark* CVPbkFindView::CreateBookmarkLC( + TInt aIndex ) const + { + return iBaseView.ContactAtL(iContactMapping[aIndex]).CreateBookmarkLC(); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::IndexOfBookmarkL +// --------------------------------------------------------------------------- +// +TInt CVPbkFindView::IndexOfBookmarkL( + const MVPbkContactBookmark& aContactBookmark ) const + { + TInt baseIndex = iBaseView.IndexOfBookmarkL(aContactBookmark); + return iContactMapping.Find(baseIndex); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::ViewFiltering +// --------------------------------------------------------------------------- +// +MVPbkContactViewFiltering* CVPbkFindView::ViewFiltering() + { + return this; + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::CreateFilteredViewLC +// --------------------------------------------------------------------------- +// +MVPbkContactViewBase* CVPbkFindView::CreateFilteredViewLC( + MVPbkContactViewObserver& aObserver, + const MDesCArray& aFindWords, + const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::CreateFilteredViewLC(0x%x)"), this); + + return CVPbkFindView::NewLC( *this, + aObserver, + aFindWords, + aAlwaysIncludedContacts, + *iMasterFieldTypeList ); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::UpdateFilterL +// --------------------------------------------------------------------------- +// +void CVPbkFindView::UpdateFilterL( + const MDesCArray& aFindWords, + const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::UpdateFilterL(0x%x)"), this); + + SetFindStringsL( aFindWords ); + SetAlwaysIncludedContactsL( aAlwaysIncludedContacts ); + + // Remove first if this called second time when updating. + iBaseView.RemoveObserver( *this ); + // This will cause an asynchrnous view event to this view from the + // parent view. + iBaseView.AddObserverL( *this ); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::BuildViewMappingL +// --------------------------------------------------------------------------- +// +void CVPbkFindView::BuildViewMappingL() + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::BuildViewMappingL(0x%x)"), this); + + iContactMapping.Reset(); + + // Append always included contact + if ( iAlwaysIncludedContacts ) + { + const TInt alwaysIncluded( iAlwaysIncludedContacts->Count() ); + for ( TInt i(0); i < alwaysIncluded; ++i ) + { + TInt index( + iBaseView.IndexOfBookmarkL( + iAlwaysIncludedContacts->At( i ) ) ); + if ( index > KErrNotFound ) + { + User::LeaveIfError( iContactMapping.InsertInOrder(index) ); + } + } + } + + // Append matched contacts + const TInt countContacts = iBaseView.ContactCountL(); + for (TInt i(0); i < countContacts; ++i) + { + const MVPbkViewContact& contact = iBaseView.ContactAtL( i ); + + TBool match( ETrue ); + + if ( iContactFindPolicy && + !iContactFindPolicy->MatchContactNameL( *iFindStrings, contact )) + { + match = EFalse; + } + + if ( match && iContactMapping.FindInOrder( i ) == KErrNotFound ) + { + User::LeaveIfError( iContactMapping.InsertInOrder( i ) ); + } + } + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::BuildViewMappingL(0x%x) end"), this); + } + +// --------------------------------------------------------------------------- +// CVPbkFindView::HandleBuildViewMapping +// --------------------------------------------------------------------------- +// +void CVPbkFindView::HandleBuildViewMapping() + { + TRAPD( res, BuildViewMappingL() ); + if ( res == KErrNone ) + { + // Mapping was succesfully built. Send ready event + SendViewEventToObservers( + &MVPbkContactViewObserver::ContactViewReady ); + } + else + { + // Building the mapping failed. Leave mappings as they are and + // send error + SendViewErrorEventToObservers( res, EFalse ); + } + } + +// --------------------------------------------------------------------------- +// From class MVPbkContactViewBase. +// CVPbkFindView::ContactViewReady +// --------------------------------------------------------------------------- +// +void CVPbkFindView::ContactViewReady( MVPbkContactViewBase& aView ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ContactViewReady(0x%x)"), &aView); + + iIsReady = ETrue; + HandleBuildViewMapping(); + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ContactViewReady(0x%x) end"), &aView); + } + +// --------------------------------------------------------------------------- +// From class MVPbkContactViewBase. +// CVPbkFindView::ContactViewUnavailable +// --------------------------------------------------------------------------- +// +void CVPbkFindView::ContactViewUnavailable( + MVPbkContactViewBase& aView ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ContactViewUnavailable(0x%x)"), &aView); + + iIsReady = EFalse; + SendViewEventToObservers( + &MVPbkContactViewObserver::ContactViewUnavailable ); + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ContactViewUnavailable(0x%x)"), &aView); + } + +// --------------------------------------------------------------------------- +// From class MVPbkContactViewBase. +// CVPbkFindView::ContactViewError +// --------------------------------------------------------------------------- +// +void CVPbkFindView::ContactViewError( MVPbkContactViewBase& aView, + TInt aError, TBool aErrorNotified ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ContactViewError(0x%x)"), &aView); + + iIsReady = EFalse; + SendViewErrorEventToObservers( aError, aErrorNotified ); + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CVPbkFindView::ContactViewError(0x%x)"), &aView); + } + +// --------------------------------------------------------------------------- +// From class MVPbkContactViewBase. +// CVPbkFindView::ContactAddedToView +// --------------------------------------------------------------------------- +// +void CVPbkFindView::ContactAddedToView + (MVPbkContactViewBase& /*aView*/, TInt aIndex, + const MVPbkContactLink& aContactLink) + { + // To keep indexes in iContactMapping up to date rebuild mappings. + TRAPD( res, BuildViewMappingL() ); + if ( res == KErrNone ) + { + // Do a binary search to mapping + TInt index = iContactMapping.FindInOrder( aIndex ); + if ( index != KErrNotFound ) + { + // Mapping was succesfully updated and the new contact + // belongs to filter. + SendEventToObservers( *this, iObservers, + &MVPbkContactViewObserver::ContactAddedToView, index, + aContactLink ); + } + } + else + { + SendViewErrorEventToObservers( res, EFalse ); + } + } + +// --------------------------------------------------------------------------- +// From class MVPbkContactViewBase. +// CVPbkFindView::ContactRemovedFromView +// --------------------------------------------------------------------------- +// +void CVPbkFindView::ContactRemovedFromView( + MVPbkContactViewBase& /*aView*/, TInt aIndex, + const MVPbkContactLink& aContactLink) + { + // Do a binary search to mapping + TInt index = iContactMapping.FindInOrder( aIndex ); + + // To keep indexes in iContactMapping up to date rebuild mappings. + TRAPD( res, BuildViewMappingL() ); + if ( res == KErrNone ) + { + if ( index != KErrNotFound ) + { + // Mapping was succesfully updated and the new contact + // belongs to filter. + SendEventToObservers( *this, iObservers, + &MVPbkContactViewObserver::ContactRemovedFromView, index, + aContactLink ); + } + } + else + { + SendViewErrorEventToObservers( res, EFalse ); + } + } + +// -------------------------------------------------------------------------- +// CVPbkFindView::SetFindStringsL +// -------------------------------------------------------------------------- +// +void CVPbkFindView::SetFindStringsL( const MDesCArray& aFindWords ) + { + iFindStrings->Reset(); + + const TInt count( aFindWords.MdcaCount() ); + for ( TInt i(0); i < count; ++i ) + { + iFindStrings->AppendL( aFindWords.MdcaPoint( i ) ); + } + } + +// -------------------------------------------------------------------------- +// CVPbkFindView::SetAlwaysIncludedContactsL +// -------------------------------------------------------------------------- +// +void CVPbkFindView::SetAlwaysIncludedContactsL( + const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts ) + { + iAlwaysIncludedContacts = aAlwaysIncludedContacts; + } + +// -------------------------------------------------------------------------- +// CVPbkFindView::SendViewEventToObservers +// -------------------------------------------------------------------------- +// +void CVPbkFindView::SendViewEventToObservers( + void( MVPbkContactViewObserver::* aObserverFunc)( MVPbkContactViewBase& ) ) + { + // Cancel async operation to avoid duplicate event sending to observers + iAsyncOperation->Purge(); + SendEventToObservers( *this, iObservers, aObserverFunc ); + } + +// -------------------------------------------------------------------------- +// CVPbkFindView::SendViewErrorEventToObservers +// -------------------------------------------------------------------------- +// +void CVPbkFindView::SendViewErrorEventToObservers( TInt aError, TBool + aErrorNotified ) + { + // Cancel async operation to avoid duplicate event sending to observers + iAsyncOperation->Purge(); + SendEventToObservers( *this, iObservers, + &MVPbkContactViewObserver::ContactViewError, + aError, aErrorNotified ); + } +// End of File