--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkSimStoreImpl/src/CVPbkSimContactView.cpp Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,1175 @@
+/*
+* Copyright (c) 2002-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: The contact view
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <CVPbkSimContactView.h>
+
+#include "CStoreBase.h"
+#include "CContactArray.h"
+#include "CSimCntSortUtil.h"
+#include "CContactArray.h"
+#include "VPbkSimStoreImplError.h"
+
+#include <CVPbkSimContactBuf.h>
+#include <CVPbkSimContact.h>
+#include <CVPbkSimCntField.h>
+#include <CVPbkAsyncOperation.h>
+#include <CVPbkAsyncCallback.h>
+#include <CVPbkSimFieldTypeFilter.h>
+#include <CVPbkContactFindPolicy.h>
+#include <MVPbkSimViewObserver.h>
+#include <MVPbkSimViewFindObserver.h>
+#include <MVPbkSimStoreOperation.h>
+#include <RVPbkStreamedIntArray.h>
+#include <TVPbkSimStoreProperty.h>
+#include <VPbkSimStoreTemplateFunctions.h>
+#include <VPbkDebug.h>
+
+// CONSTANTS
+
+enum TVPbkSimViewState
+ {
+ /// View has no clients. It doesn' listen to store/contact array events
+ ENotReady,
+ /// View has clients but the store is not available or the view is resorting.
+ /// It listens to store events but not contact array events.
+ EUnvavailable,
+ /// View has clients and it's ready to use.
+ EReady
+ };
+
+namespace VPbkSimStoreImpl {
+
+/**
+* An active object for contact matching
+*/
+NONSHARABLE_CLASS(CContactMatchingOperation) :
+ public CActive,
+ public MVPbkSimStoreOperation
+ {
+ public: // Construction and destruction
+ static CContactMatchingOperation* NewL(
+ const MDesCArray& aFindStrings,
+ MVPbkSimViewFindObserver& aObserver,
+ MVPbkSimCntView& aSimCntView );
+ ~CContactMatchingOperation();
+
+ public: // New functions
+ void Activate();
+
+ public: // Functions from CActive
+ void RunL();
+ void DoCancel();
+ TInt RunError( TInt aError );
+
+ private:
+ /**
+ * C++ constructor
+ */
+ CContactMatchingOperation(
+ const MDesCArray& aFindStrings,
+ MVPbkSimViewFindObserver& aObserver,
+ MVPbkSimCntView& aSimCntView );
+
+ /**
+ * By default Symbian 2nd phase constructor is private.
+ */
+ void ConstructL();
+
+ /**
+ * Contact matched
+ *
+ * @param aSimContact SIM contact to be matched
+ * @param aType SIM contact field to be matched with find string
+ * @return ETrue, if contact matched, EFalse if not
+ */
+ TBool ContactMatchedL(
+ MVPbkSimContact& aSimContact,
+ TVPbkSimCntFieldType aType );
+
+ private:
+ /// Ref: strings used in find
+ const MDesCArray& iFindStrings;
+ /// Ref: Observer that is interested in the result of the find
+ MVPbkSimViewFindObserver& iObserver;
+ /// Ref: View of SimStore to existing contacts
+ MVPbkSimCntView& iSimCntView;
+ /// Own: The result of the find
+ RVPbkStreamedIntArray iMatchingResults;
+ /// Own: Makes a string comparison
+ CVPbkContactFindPolicy* iContactFindPolicy;
+ };
+
+// ============================ MEMBER FUNCTIONS ============================
+// --------------------------------------------------------------------------
+// CContactMatchingOperation::CContactMatchingOperation
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// --------------------------------------------------------------------------
+//
+CContactMatchingOperation::CContactMatchingOperation(
+ const MDesCArray& aFindStrings,
+ MVPbkSimViewFindObserver& aObserver,
+ MVPbkSimCntView& aSimCntView )
+ : CActive( EPriorityStandard ),
+ iFindStrings( aFindStrings ),
+ iObserver( aObserver ),
+ iSimCntView( aSimCntView )
+ {
+ }
+
+// --------------------------------------------------------------------------
+// CContactMatchingOperation::ConstructL
+// Symbian 2nd phase constructor can leave.
+// --------------------------------------------------------------------------
+//
+void CContactMatchingOperation::ConstructL()
+ {
+ CActiveScheduler::Add( this );
+
+ //Create contact find policy
+ iContactFindPolicy = CVPbkContactFindPolicy::NewL();
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactViewFindOperation::NewL
+// Two-phased constructor.
+// --------------------------------------------------------------------------
+//
+CContactMatchingOperation* CContactMatchingOperation::NewL(
+ const MDesCArray& aFindStrings,
+ MVPbkSimViewFindObserver& aObserver,
+ MVPbkSimCntView& aSimCntView )
+ {
+ CContactMatchingOperation* self =
+ new( ELeave ) CContactMatchingOperation( aFindStrings, aObserver,
+ aSimCntView );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// Destructor
+CContactMatchingOperation::~CContactMatchingOperation()
+ {
+ delete iContactFindPolicy;
+ iMatchingResults.Close();
+ Cancel();
+ // iContactFindPolicy is an ECOM plugin so call FinalClose after delete.
+ REComSession::FinalClose();
+ }
+
+// --------------------------------------------------------------------------
+// CContactMatchingOperation::Activate
+// --------------------------------------------------------------------------
+//
+void CContactMatchingOperation::Activate()
+ {
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+ }
+
+// --------------------------------------------------------------------------
+// CContactMatchingOperation::ContactMatchedL
+// --------------------------------------------------------------------------
+//
+TBool CContactMatchingOperation::ContactMatchedL(
+ MVPbkSimContact& aSimContact,
+ TVPbkSimCntFieldType aType )
+ {
+ TBool result( EFalse );
+ MVPbkSimContact::TFieldLookup lookup =
+ aSimContact.FindField( aType );
+
+ if ( !lookup.EndOfLookup() )
+ {
+ const TDesC& data =
+ aSimContact.ConstFieldAt( lookup.Index() ).Data();
+
+ const TInt findCount( iFindStrings.MdcaCount() );
+ for ( TInt i(0); i < findCount; ++i )
+ {
+ // Match refine
+ if ( iContactFindPolicy->MatchRefineL(
+ data, iFindStrings.MdcaPoint( i ) ) )
+ {
+ iMatchingResults.AppendIntL( aSimContact.SimIndex() );
+ result = ETrue;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+// --------------------------------------------------------------------------
+// CContactMatchingOperation::RunL
+// --------------------------------------------------------------------------
+//
+void CContactMatchingOperation::RunL()
+ {
+ const TInt count( iSimCntView.CountL() );
+ for ( TInt i(0); i < count; ++i )
+ {
+ MVPbkSimContact& simContact = iSimCntView.ContactAtL( i );
+ MVPbkSimContact::TFieldLookup lookupSimName = simContact.FindField( EVPbkSimName );
+ //try to fetch contact with EVPbkSimName
+ if ( !lookupSimName.EndOfLookup() )
+ {
+ ContactMatchedL( simContact, EVPbkSimName );
+ }
+ //if contact without name, then try to fetch it with EVPbkSimGsmNumber
+ else
+ {
+ MVPbkSimContact::TFieldLookup lookupGsmNum = simContact.FindField( EVPbkSimGsmNumber );
+ if ( !lookupGsmNum.EndOfLookup() )
+ {
+ ContactMatchedL( simContact, EVPbkSimGsmNumber );
+ }
+ }
+ }
+ iObserver.ViewFindCompleted( iSimCntView, iMatchingResults );
+ }
+
+// --------------------------------------------------------------------------
+// CContactMatchingOperation::DoCancel
+// --------------------------------------------------------------------------
+//
+void CContactMatchingOperation::DoCancel()
+ {
+ // Operation has no handles to any services -> do nothing
+ }
+
+// --------------------------------------------------------------------------
+// CContactMatchingOperation::RunError
+// --------------------------------------------------------------------------
+//
+TInt CContactMatchingOperation::RunError( TInt aError )
+ {
+ iObserver.ViewFindError( iSimCntView, aError );
+ return KErrNone;
+ }
+
+} // namespace VPbkSimStoreImpl
+
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::CVPbkSimContactView
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// --------------------------------------------------------------------------
+//
+CVPbkSimContactView::CVPbkSimContactView( MVPbkSimCntStore& aParentStore,
+ TVPbkSimViewConstructionPolicy aConstructionPolicy )
+ : iParentStore( aParentStore ),
+ iConstructionPolicy( aConstructionPolicy ),
+ iViewState( ENotReady )
+ {
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::~CVPbkSimContactView
+// --------------------------------------------------------------------------
+//
+CVPbkSimContactView::~CVPbkSimContactView()
+ {
+ delete iIdleSort;
+ SetToNotReadyState();
+ delete iAsyncOperation;
+ iObservers.Close();
+ iSortOrder.Close();
+ delete iViewName;
+ delete iSortUtil;
+ delete iCurrentContact;
+ delete iTempContactForSorting;
+ delete iFilter;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::NewLC
+// Two-phased constructor.
+// --------------------------------------------------------------------------
+//
+EXPORT_C CVPbkSimContactView* CVPbkSimContactView::NewLC(
+ const RVPbkSimFieldTypeArray& aSortOrder,
+ TVPbkSimViewConstructionPolicy aConstructionPolicy,
+ MVPbkSimCntStore& aParentStore, const TDesC& aViewName,
+ CVPbkSimFieldTypeFilter* aFilter )
+ {
+ CVPbkSimContactView* self =
+ new ( ELeave ) CVPbkSimContactView( aParentStore,
+ aConstructionPolicy );
+ CleanupStack::PushL( self );
+ self->ConstructL( aSortOrder, aViewName );
+ self->iFilter = aFilter;
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ConstructL
+// Symbian 2nd phase constructor can leave.
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::ConstructL( const RVPbkSimFieldTypeArray& aSortOrder,
+ const TDesC& aViewName )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView(0x%x)::ConstructL name=%S"),
+ this, &aViewName );
+
+ iIdleSort = CIdle::NewL( CActive::EPriorityStandard );
+ ResetAndCopySortOrderL( aSortOrder );
+ iViewName = aViewName.AllocL();
+ iAsyncOperation =
+ CVPbkAsyncObjectOperation<MVPbkSimViewObserver>::NewL();
+ iCurrentContact = CVPbkSimContactBuf::NewL( iParentStore );
+ iTempContactForSorting = CVPbkSimContactBuf::NewL( iParentStore );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::Name
+// --------------------------------------------------------------------------
+//
+const TDesC& CVPbkSimContactView::Name() const
+ {
+ return *iViewName;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ParentStore
+// --------------------------------------------------------------------------
+//
+MVPbkSimCntStore& CVPbkSimContactView::ParentStore() const
+ {
+ return iParentStore;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::OpenL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::OpenL( MVPbkSimViewObserver& aObserver )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView(0x%x)::OpenL name=%S,aObserver=0x%x,state=%d"),
+ this, iViewName, &aObserver, iViewState );
+
+ if ( ViewStateNotReady() )
+ {
+ // Call close first to ensure store is not opened many times
+ iParentStore.Close( *this );
+ // Open a store asynchronously.
+ iParentStore.OpenL( *this );
+ }
+ else
+ {
+ void( CVPbkSimContactView::* notifyFuncPtr)( MVPbkSimViewObserver& ) =
+ &CVPbkSimContactView::DoViewOpenCallbackL;
+ if ( ViewStateUnavailable() )
+ {
+ notifyFuncPtr = &CVPbkSimContactView::DoViewUnavailableCallbackL;
+ }
+
+ CVPbkAsyncObjectCallback<MVPbkSimViewObserver>* callback =
+ VPbkEngUtils::CreateAsyncObjectCallbackLC(
+ *this,
+ notifyFuncPtr,
+ &CVPbkSimContactView::DoViewErrorCallback,
+ aObserver );
+ iAsyncOperation->CallbackL(callback);
+ CleanupStack::Pop(); // callBack
+ }
+
+ if ( iObservers.Find( &aObserver ) == KErrNotFound )
+ {
+ iObservers.AppendL( &aObserver );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::Close
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::Close( MVPbkSimViewObserver& aObserver )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::Close name=%S,aObserver=0x%x,state=%d"),
+ iViewName, &aObserver, iViewState );
+
+ iAsyncOperation->CancelCallback( &aObserver );
+
+ TInt index = iObservers.Find( &aObserver );
+ if ( index >= 0 )
+ {
+ iObservers.Remove( index );
+ if ( iObservers.Count() == 0 )
+ {
+ SetToNotReadyState();
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::CountL
+// --------------------------------------------------------------------------
+//
+TInt CVPbkSimContactView::CountL() const
+ {
+ return iViewContacts.Count();
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ContactAtL
+// --------------------------------------------------------------------------
+//
+MVPbkSimContact& CVPbkSimContactView::ContactAtL( TInt aIndex )
+ {
+ if ( aIndex < 0 || aIndex >= iViewContacts.Count() )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ const MVPbkSimContact* fullContact =
+ iParentStore.ContactAtL( iViewContacts[aIndex].iSimIndex );
+
+ // Check that view is up to date
+ __ASSERT_DEBUG( fullContact,
+ Panic( VPbkSimStoreImpl::EViewArrayNotUpToDate ) );
+ if ( !fullContact )
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ CVPbkSimContact* cnt =
+ CVPbkSimContact::NewLC( iParentStore );
+ // Copy fields that have same type as in the sortorder
+ TInt count = iSortOrder.Count();
+ for ( TInt i = 0; i < count; ++i )
+ {
+ MVPbkSimContact::TFieldLookup lookup =
+ fullContact->FindField( iSortOrder[i] );
+ if ( !lookup.EndOfLookup() )
+ {
+ CVPbkSimCntField* field = cnt->CreateFieldLC( iSortOrder[i] );
+ field->SetDataL( fullContact->ConstFieldAt( lookup.Index() ).Data() );
+ cnt->AddFieldL( field );
+ CleanupStack::Pop( field );
+ }
+ }
+
+ cnt->SetSimIndex( fullContact->SimIndex() );
+ iCurrentContact->SetL( cnt->ETelContactL() );
+ CleanupStack::PopAndDestroy( cnt );
+ return *iCurrentContact;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ChangeSortOrderL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::ChangeSortOrderL( const RVPbkSimFieldTypeArray& aSortOrder )
+ {
+ // Copy the new sort order to the view
+ ResetAndCopySortOrderL( aSortOrder );
+
+ // Change state only if the view is currently ready, Otherwise
+ // the view is already waiting sorting or store event.
+ if ( ViewStateReady() )
+ {
+ // Change to unavailable: view will be ready after sorting.
+ SetToUnavailableState();
+ // Resort view.
+ StartSorting();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::MapSimIndexToViewIndexL
+// --------------------------------------------------------------------------
+//
+TInt CVPbkSimContactView::MapSimIndexToViewIndexL( TInt aSimIndex )
+ {
+ TViewContact cnt( aSimIndex );
+ return iViewContacts.Find( cnt,
+ TIdentityRelation<TViewContact>( &CVPbkSimContactView::CompareViewContactSimIndex ) );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ContactMatchingPrefixL
+// --------------------------------------------------------------------------
+//
+MVPbkSimStoreOperation* CVPbkSimContactView::ContactMatchingPrefixL(
+ const MDesCArray& aFindStrings,
+ MVPbkSimViewFindObserver& aObserver )
+ {
+ VPbkSimStoreImpl::CContactMatchingOperation* operation =
+ VPbkSimStoreImpl::CContactMatchingOperation::NewL( aFindStrings,
+ aObserver, *this );
+ operation->Activate();
+ return operation;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::SortOrderL
+// --------------------------------------------------------------------------
+//
+const RVPbkSimFieldTypeArray& CVPbkSimContactView::SortOrderL() const
+ {
+ return iSortOrder;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::StoreReady
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::StoreReady( MVPbkSimCntStore& /*aStore*/ )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::StoreReady"));
+
+ // Store has become ready or has been updated. Update the view too.
+ StartSorting();
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::StoreReady
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::StoreError( MVPbkSimCntStore& /*aStore*/, TInt aError )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::StoreError %d"), aError);
+
+ SetToUnavailableState();
+ VPbkSimStoreImpl::SendObserverMessageRV( iObservers,
+ &MVPbkSimViewObserver::ViewError, *this, aError );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::StoreNotAvailable
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::StoreNotAvailable( MVPbkSimCntStore& /*aStore*/ )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::StoreNotAvailable"));
+
+ // Reset view until StoreReady is called again
+ SetToUnavailableState();
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::StoreContactEvent
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::StoreContactEvent( TEvent aEvent, TInt aSimIndex )
+ {
+ TRAPD( res, HandleStoreContactEventL( aEvent, aSimIndex ) );
+ if ( res != KErrNone )
+ {
+ // The view is not up to date any more.
+ SetToUnavailableState();
+ VPbkSimStoreImpl::SendObserverMessageRV( iObservers,
+ &MVPbkSimViewObserver::ViewError, *this, res );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::Sort
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::Sort()
+ {
+ TRAPD( res, SortL() );
+ if ( res != KErrNone )
+ {
+ SortError( res );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::SortL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::SortL()
+ {
+ // Get the size of the store
+ TVPbkGsmStoreProperty properties;
+ User::LeaveIfError( iParentStore. GetGsmStoreProperties( properties ) );
+ TInt lastIndex = properties.iTotalEntries;
+
+ // Loop all contacts of the store.
+ for ( TInt i = KVPbkSimStoreFirstETelIndex; i <= lastIndex; ++i )
+ {
+ const MVPbkSimContact* cnt = iParentStore.ContactAtL( i );
+ if ( cnt )
+ {
+ InsertViewContactL( *cnt );
+ }
+ }
+
+ // All contacts have been sorted and the view is ready
+ SetToReadyState();
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::SortError
+// --------------------------------------------------------------------------
+//
+TInt CVPbkSimContactView::SortError( TInt aError )
+ {
+ iAsyncOperation->Purge();
+ VPbkSimStoreImpl::SendObserverMessageRV( iObservers,
+ &MVPbkSimViewObserver::ViewError, *this, aError );
+ return KErrNone;
+ }
+
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::IsSorting
+// --------------------------------------------------------------------------
+//
+TBool CVPbkSimContactView::IsSorting() const
+ {
+ return iIdleSort->IsActive();
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::StartSorting
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::StartSorting()
+ {
+ iIdleSort->Cancel();
+ iIdleSort->Start(
+ TCallBack( CVPbkSimContactView::IdleSortCallback, this ) );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::HandleStoreContactEventL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::HandleStoreContactEventL( TEvent aEvent, TInt aSimIndex )
+ {
+ switch( aEvent )
+ {
+ case EContactAdded:
+ {
+ HandleContactAddedL( aSimIndex );
+ break;
+ }
+ case EContactDeleted:
+ {
+ HandleContactRemoved( aSimIndex );
+ break;
+ }
+ case EContactChanged:
+ {
+ HandleContactChangedL( aSimIndex );
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::HandleContactAddedL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::HandleContactAddedL( TInt aSimIndex )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::HandleContactAdded: simIndex %d"),
+ aSimIndex );
+
+ const MVPbkSimContact* addedCnt = iParentStore.ContactAtL( aSimIndex );
+ if ( addedCnt )
+ {
+ TInt viewIndex = InsertViewContactL( *addedCnt );
+ VPbkSimStoreImpl::SendObserverMessageVVV( iObservers,
+ &MVPbkSimViewObserver::ViewContactEvent,
+ MVPbkSimViewObserver::EContactAdded, viewIndex, aSimIndex );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::HandleContactRemoved
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::HandleContactRemoved( TInt aSimIndex )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::HandleContactRemoved: simIndex %d"),
+ aSimIndex );
+
+ TInt removedIndex = RemoveViewContact( aSimIndex );
+ VPbkSimStoreImpl::SendObserverMessageVVV( iObservers,
+ &MVPbkSimViewObserver::ViewContactEvent,
+ MVPbkSimViewObserver::EContactDeleted, removedIndex, aSimIndex );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::HandleContactChangedL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::HandleContactChangedL( TInt aSimIndex )
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::HandleContactChanged: simIndex %d"),
+ aSimIndex );
+
+ // Changed contact is a bit complicated from the view point of view
+ // due to case of contacts that have same name
+ // E.g the view has following contacts
+ // index 0: Jill
+ // index 1: Jill
+ // index 2: Jill
+ // Then editing any of them must not change the position of the
+ // contact in the view if the name remains same.
+
+ // Get the changed contact
+ const MVPbkSimContact* changedCnt = iParentStore.ContactAtL( aSimIndex );
+
+ if ( changedCnt )
+ {
+ // Get current position of the changed contact
+ TInt curIndex = iViewContacts.Find( aSimIndex,
+ TIdentityRelation<TViewContact>( CompareViewContactSimIndex ) );
+
+ // Remove the contact from the view
+ TInt nextContactIndex = curIndex + 1;
+
+ // Investigate if we can ignore the event from view point of i.e if
+ // the position of the contacts is still same.
+ TBool keepInSamePos = EFalse;
+ const TInt viewCntCount = iViewContacts.Count();
+ if ( PassesFilter( *changedCnt, iFilter ) &&
+ nextContactIndex >= 0 && nextContactIndex < viewCntCount )
+ {
+ // Create a temp copy of changedCnt becuase next ContactAtL will
+ // overwrite the reference.
+ CVPbkSimContactBuf* temp = CVPbkSimContactBuf::NewLC(
+ changedCnt->ETelContactL(), iParentStore );
+ // Get the next contact
+ const MVPbkSimContact* nextCnt = iParentStore.ContactAtL(
+ iViewContacts[nextContactIndex].iSimIndex );
+ // Compare names of the changed contact and the next contact
+ if ( iSortUtil->Compare( *temp, *nextCnt ) == 0 )
+ {
+ // Next contact has a same name. This means that we don't
+ // need to modify the view at all.
+ keepInSamePos = ETrue;
+ }
+ CleanupStack::PopAndDestroy( temp );
+ }
+
+ if ( keepInSamePos )
+ {
+ // Though there was no need to change anything the events must still
+ // be sent to observers.
+ VPbkSimStoreImpl::SendObserverMessageVVV( iObservers,
+ &MVPbkSimViewObserver::ViewContactEvent,
+ MVPbkSimViewObserver::EContactDeleted, curIndex, aSimIndex );
+ VPbkSimStoreImpl::SendObserverMessageVVV( iObservers,
+ &MVPbkSimViewObserver::ViewContactEvent,
+ MVPbkSimViewObserver::EContactAdded, curIndex, aSimIndex );
+ }
+ else
+ {
+ HandleContactRemoved( aSimIndex );
+ HandleContactAddedL( aSimIndex );
+ }
+ }
+ }
+
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::InsertViewContactL
+// --------------------------------------------------------------------------
+//
+TInt CVPbkSimContactView::InsertViewContactL(
+ const MVPbkSimContact& aContact )
+ {
+ TInt index = KErrNotFound;
+ if ( PassesFilter( aContact, iFilter ) )
+ {
+ // Use temp contact because Sorting uses ContactAtL
+ iTempContactForSorting->SetL( aContact.ETelContactL() );
+ if ( iConstructionPolicy == EVPbkSortedSimView )
+ {
+ index = SortedIndexL( *iTempContactForSorting );
+ }
+ else
+ {
+ index = UnsortedIndex( *iTempContactForSorting );
+ }
+ TViewContact cnt( iTempContactForSorting->SimIndex() );
+ iViewContacts.InsertL( cnt, index );
+ }
+ return index;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::SortedIndexL
+// --------------------------------------------------------------------------
+//
+TInt CVPbkSimContactView::SortedIndexL( const MVPbkSimContact& aLeft )
+ {
+ TInt first = 0;
+ TInt len = iViewContacts.Count();
+
+ while ( len > 0 )
+ {
+ TInt half = len / 2;
+ TInt middle = first + half;
+ TInt simIndex = iViewContacts[middle].iSimIndex;
+ const MVPbkSimContact* right =
+ iParentStore.ContactAtL( simIndex );
+ if ( iSortUtil->Compare( aLeft, *right ) < 0 )
+ {
+ len = half;
+ }
+ else
+ {
+ first = middle + 1;
+ len = len - half - 1;
+ }
+ }
+
+ len = iViewContacts.Count();
+ if ( first < len )
+ {
+ TInt simIndex = iViewContacts[first].iSimIndex;
+ if ( iSortUtil->Compare( aLeft,
+ *iParentStore.ContactAtL( simIndex ) ) == 0 )
+ {
+ ++first;
+ }
+ }
+
+ __ASSERT_DEBUG( first <= len,
+ Panic( VPbkSimStoreImpl::EInvalidSortedIndex ) );
+ if ( first > len )
+ {
+ first = len;
+ }
+
+ return first;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::UnsortedIndex
+// --------------------------------------------------------------------------
+//
+TInt CVPbkSimContactView::UnsortedIndex( const MVPbkSimContact& aLeft )
+ {
+ const TInt count = iViewContacts.Count();
+ for ( TInt i = 0; i < count; ++i )
+ {
+ if ( aLeft.SimIndex() < iViewContacts[i].iSimIndex )
+ {
+ return i;
+ }
+ }
+ return count;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::RemoveViewContact
+// --------------------------------------------------------------------------
+//
+TInt CVPbkSimContactView::RemoveViewContact( TInt aSimIndex )
+ {
+ TInt index = iViewContacts.Find( aSimIndex,
+ TIdentityRelation<TViewContact>( CompareViewContactSimIndex ) );
+
+ if ( index != KErrNotFound )
+ {
+ iViewContacts.Remove( index );
+ }
+
+ return index;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ResetAndCopySortOrderL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::ResetAndCopySortOrderL( const RVPbkSimFieldTypeArray& aSource )
+ {
+ // Reset old sort order
+ iSortOrder.Reset();
+ // Copy the new one
+ TInt count = aSource.Count();
+ for ( TInt i = 0; i < count; ++i )
+ {
+ iSortOrder.AppendL( aSource[i] );
+ }
+ // Recreate sort util with new sort order
+ VPbkSimStoreImpl::CSimCntSortUtil* sortUtil =
+ VPbkSimStoreImpl::CSimCntSortUtil::NewL( iSortOrder );
+ delete iSortUtil;
+ iSortUtil = sortUtil;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::Reset
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::Reset()
+ {
+ iViewContacts.Reset();
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::PassesFilter
+// --------------------------------------------------------------------------
+//
+inline TBool CVPbkSimContactView::PassesFilter( const MVPbkSimContact& aContact,
+ const CVPbkSimFieldTypeFilter* aFilter ) const
+ {
+ // Initialize to 'fail'
+ TBool ret = EFalse;
+
+ if ( aFilter )
+ {
+ // Get filtering criteria
+ TUint16 criteria = aFilter->FilteringCriteria();
+
+ if ( criteria &
+ CVPbkSimFieldTypeFilter::ESimFilterCriteriaGsmNumber )
+ {
+ MVPbkSimContact::TFieldLookup lookup =
+ aContact.FindField( EVPbkSimGsmNumber );
+ ret = !lookup.EndOfLookup();
+ }
+
+ if ( !ret && criteria &
+ CVPbkSimFieldTypeFilter::ESimFilterCriteriaAdditionalNumber )
+ {
+ MVPbkSimContact::TFieldLookup lookup =
+ aContact.FindField( EVPbkSimAdditionalNumber );
+ ret = !lookup.EndOfLookup();
+ }
+
+ if ( !ret && criteria &
+ CVPbkSimFieldTypeFilter::ESimFilterCriteriaEmailAddress )
+ {
+ MVPbkSimContact::TFieldLookup lookup =
+ aContact.FindField( EVPbkSimEMailAddress );
+ ret = !lookup.EndOfLookup();
+ }
+
+ if ( !ret && criteria &
+ CVPbkSimFieldTypeFilter::ESimFilterCriteriaName )
+ {
+ MVPbkSimContact::TFieldLookup lookup =
+ aContact.FindField( EVPbkSimName );
+ ret = !lookup.EndOfLookup();
+ }
+
+ if ( !ret && criteria &
+ CVPbkSimFieldTypeFilter::ESimFilterCriteriaSecondName )
+ {
+ MVPbkSimContact::TFieldLookup lookup =
+ aContact.FindField( EVPbkSimNickName );
+ ret = !lookup.EndOfLookup();
+ }
+
+ if ( !ret && criteria == 0 )
+ {
+ ret = ETrue;
+ }
+ }
+ else
+ {
+ ret = ETrue;
+ }
+
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::SetToReadyState
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::SetToReadyState()
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::SetToReadyState"));
+ // Cancel any async callback because event is sent to all observer
+ iAsyncOperation->Purge();
+
+ iViewState = EReady;
+ VPbkSimStoreImpl::SendObserverMessageR( iObservers,
+ &MVPbkSimViewObserver::ViewReady, *this );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::SetToNotReadyState
+// In Not Ready State the view doesn't have observer and it
+// doesn't listen to any events. It waits that a client calls OpenL.
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::SetToNotReadyState()
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::SetToNotReadyState"));
+
+ Reset();
+ iParentStore.Close( *this );
+ iViewState = ENotReady;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::SetToUnavailableState
+// In Unavailable state the view doesn' listen to contact events. It listens
+// to store event to get Store Ready event.
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::SetToUnavailableState()
+ {
+ VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+ "VPbkSimStoreImpl: CVPbkSimContactView::SetToUnavailableState"));
+
+ Reset();
+ iAsyncOperation->Purge();
+ iViewState = EUnvavailable;
+ VPbkSimStoreImpl::SendObserverMessageR( iObservers,
+ &MVPbkSimViewObserver::ViewNotAvailable, *this );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ViewStateReady
+// --------------------------------------------------------------------------
+//
+TBool CVPbkSimContactView::ViewStateReady() const
+ {
+ return iViewState == EReady;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ViewStateUnavailable
+// --------------------------------------------------------------------------
+//
+TBool CVPbkSimContactView::ViewStateUnavailable() const
+ {
+ return iViewState == EUnvavailable;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::ViewStateNotReady
+// --------------------------------------------------------------------------
+//
+TBool CVPbkSimContactView::ViewStateNotReady() const
+ {
+ return iViewState == ENotReady;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::DoViewOpenCallbackL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::DoViewOpenCallbackL( MVPbkSimViewObserver& aObserver )
+ {
+ aObserver.ViewReady( *this );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::DoViewUnavailableCallbackL
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::DoViewUnavailableCallbackL( MVPbkSimViewObserver& aObserver )
+ {
+ aObserver.ViewNotAvailable( *this );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::DoViewErrorCallback
+// --------------------------------------------------------------------------
+//
+void CVPbkSimContactView::DoViewErrorCallback( MVPbkSimViewObserver& aObserver,
+ TInt aError )
+ {
+ aObserver.ViewError( *this, aError );
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::CompareViewContactSimIndex
+// --------------------------------------------------------------------------
+//
+TBool CVPbkSimContactView::CompareViewContactSimIndex( const TViewContact& aLeft,
+ const TViewContact& aRight )
+ {
+ return aLeft.iSimIndex == aRight.iSimIndex;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::IdleSortCallback
+// --------------------------------------------------------------------------
+//
+TInt CVPbkSimContactView::IdleSortCallback( TAny* aThis )
+ {
+ static_cast<CVPbkSimContactView*>( aThis )->Sort();
+ // Don't continue idle i.e return false value
+ return 0;
+ }
+
+// --------------------------------------------------------------------------
+// CVPbkSimContactView::IsMatch
+// --------------------------------------------------------------------------
+//
+TBool CVPbkSimContactView::IsMatch(
+ const RVPbkSimFieldTypeArray& aSortOrder,
+ TVPbkSimViewConstructionPolicy aConstructionPolicy,
+ const TDesC& aViewName )
+ {
+ TBool result = EFalse;
+ if ( ( iViewName->CompareC( aViewName ) == 0 ) &&
+ ( aConstructionPolicy == iConstructionPolicy ) )
+ {
+ if ( EVPbkUnsortedSimView == aConstructionPolicy )
+ {
+ result = ETrue;
+ }
+ else if ( iSortOrder.Count() == aSortOrder.Count() )
+ {
+ result = ETrue;
+ for ( TInt i=0; i<aSortOrder.Count(); i++ )
+ {
+ if ( aSortOrder[i] != iSortOrder[i] )
+ {
+ result = EFalse;
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+// End of File