diff -r 000000000000 -r e686773b3f54 phonebookengines/VirtualPhonebook/VPbkCntModel/src/CViewBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines/VirtualPhonebook/VPbkCntModel/src/CViewBase.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,930 @@ +/* +* 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: Contacts Model store contact view implementation. +* +*/ + + +#include "CViewBase.h" + +// INCLUDES + +// VPbkCntModel +#include "CContactStore.h" +#include "CFieldFactory.h" +#include "CContact.h" +#include "CFieldTypeList.h" +#include "CContactLink.h" +#include "CContactBookmark.h" +#include "CFindView.h" +#include "VPbkCntModelRemoteViewPreferences.h" +#include "CSortOrderAcquirerList.h" + +// VPbkEng +#include +#include +#include +#include +#include +#include // KFindPluingUID +#include +#include +#include + +// System includes +#include + +// Debugging headers +#include + +namespace VPbkCntModel { + +// CONSTANTS + +const TInt KObserverArrayGranularity = 4; + +// -------------------------------------------------------------------------- +// CViewBase::CViewBase +// -------------------------------------------------------------------------- +// +CViewBase::CViewBase( CContactStore& aParentStore ) : + iObservers( KObserverArrayGranularity ), + iParentStore( aParentStore ) + { + } + +// -------------------------------------------------------------------------- +// CViewBase::~CViewBase +// -------------------------------------------------------------------------- +// +CViewBase::~CViewBase() + { + delete iObserverOp; + delete iFilterObsOp; + delete iEventLink; + if (iView) + { + iView->Close(*this); + } + delete iCurrentContact; + iObservers.Close(); + iFilteringObservers.Close(); + delete iViewDefinition; + delete iSortOrder; + iParentStore.RemoveObserver(*this); + } + +// -------------------------------------------------------------------------- +// CViewBase::ConstructL +// -------------------------------------------------------------------------- +// +void CViewBase::ConstructL( + const CVPbkContactViewDefinition& aViewDefinition, + MVPbkContactViewObserver& aObserver, + const MVPbkFieldTypeList& aSortOrder ) + { + iParentStore.AddObserverL(*this); + iSortOrder = CVPbkSortOrder::NewL(aSortOrder); + iViewDefinition = CVPbkContactViewDefinition::NewL( aViewDefinition ); + + if ( iParentStore.IsOpened() ) + { + InitializeViewL( aViewDefinition, aSortOrder ); + } + + iObserverOp = + CVPbkAsyncObjectOperation::NewL(); + iFilterObsOp = + CVPbkAsyncObjectOperation::NewL(); + + AddObserverL(aObserver); + } + +// -------------------------------------------------------------------------- +// CViewBase::ConstructL +// -------------------------------------------------------------------------- +// +void CViewBase::ConstructL( + const CVPbkContactViewDefinition& aViewDefinition, + const MVPbkFieldTypeList& aSortOrder ) + { + iParentStore.AddObserverL(*this); + iSortOrder = CVPbkSortOrder::NewL(aSortOrder); + iViewDefinition = CVPbkContactViewDefinition::NewL( aViewDefinition ); + + if ( iParentStore.IsOpened() ) + { + InitializeViewL( aViewDefinition, aSortOrder ); + } + + iObserverOp = + CVPbkAsyncObjectOperation::NewL(); + iFilterObsOp = + CVPbkAsyncObjectOperation::NewL(); + } + +// -------------------------------------------------------------------------- +// CViewBase::ChangeSortOrderL +// -------------------------------------------------------------------------- +// +void CViewBase::ChangeSortOrderL(const MVPbkFieldTypeList& aSortOrder) + { + // If this view is a remote view in Contacts server a strict policy + // must be applied for changing sortorder. Shared views are used + // widely in S60 applications so their sortorder must be controlled + // by S60 Phonebook application. + LeaveIfIncorrectSortOrderL( aSortOrder ); + + CVPbkSortOrder* newSortOrder = CVPbkSortOrder::NewL(aSortOrder); + CleanupStack::PushL(newSortOrder); + + RContactViewSortOrder viewSortOrder = CreateSortOrderL(aSortOrder); + CleanupClosePushL(viewSortOrder); + + if ( !DoChangeSortOrderL( *iViewDefinition, viewSortOrder ) ) + { + TeardownView(); + InitializeViewL( *iViewDefinition, aSortOrder ); + } + + CleanupStack::PopAndDestroy(); // viewSortOrder + CleanupStack::Pop(); // newSortOrder + + delete iSortOrder; + iSortOrder = newSortOrder; + } + +// -------------------------------------------------------------------------- +// CViewBase::SortOrder +// -------------------------------------------------------------------------- +// +const MVPbkFieldTypeList& CViewBase::SortOrder() const + { + return *iSortOrder; + } + +// -------------------------------------------------------------------------- +// CViewBase::RefreshL +// -------------------------------------------------------------------------- +// +void CViewBase::RefreshL() + { + // make the view sort itself again to refresh contents + RContactViewSortOrder viewSortOrder = CreateSortOrderL(*iSortOrder); + CleanupClosePushL(viewSortOrder); + + DoChangeSortOrderL( *iViewDefinition, viewSortOrder ); + + CleanupStack::PopAndDestroy(); // viewSortOrder + } + +// -------------------------------------------------------------------------- +// CViewBase::ContactCountL +// -------------------------------------------------------------------------- +// +TInt CViewBase::ContactCountL() const + { + TInt result = 0; + if (iViewReady) + { + result = iView->CountL(); + } + return result; + } + +// -------------------------------------------------------------------------- +// CViewBase::ContactAtL +// -------------------------------------------------------------------------- +// +const MVPbkViewContact& CViewBase::ContactAtL(TInt aIndex) const + { + __ASSERT_ALWAYS( aIndex >= 0, + VPbkError::Panic( VPbkError::EInvalidContactIndex ) ); + if ( aIndex >= ContactCountL() ) + { + User::Leave( KErrArgument ); + } + + const ::CViewContact& viewContact = iView->ContactAtL(aIndex); + iCurrentContact->SetViewContact(viewContact); + return *iCurrentContact; + } + +// -------------------------------------------------------------------------- +// CViewBase::CreateLinkLC +// -------------------------------------------------------------------------- +// +MVPbkContactLink* CViewBase::CreateLinkLC(TInt aIndex) const + { + __ASSERT_ALWAYS( aIndex >= 0, + VPbkError::Panic( VPbkError::EInvalidContactIndex ) ); + if ( aIndex >= ContactCountL() ) + { + User::Leave( KErrArgument ); + } + + TContactItemId contactId = iView->AtL(aIndex); + return CContactLink::NewLC(iParentStore, contactId); + } + +// -------------------------------------------------------------------------- +// CViewBase::IndexOfLinkL +// -------------------------------------------------------------------------- +// +TInt CViewBase::IndexOfLinkL(const MVPbkContactLink& aContactLink) const + { + TInt result = KErrNotFound; + + if (&aContactLink.ContactStore() == &ContactStore()) + { + const CContactLink& link = static_cast(aContactLink); + result = iView->FindL(link.ContactId()); + } + + return result; + } + +// -------------------------------------------------------------------------- +// CViewBase::AddObserverL +// -------------------------------------------------------------------------- +// +void CViewBase::AddObserverL(MVPbkContactViewObserver& aObserver) + { + CVPbkAsyncObjectCallback* callback = + VPbkEngUtils::CreateAsyncObjectCallbackLC( + *this, + &CViewBase::DoAddObserverL, + &CViewBase::AddObserverError, + aObserver); + iObserverOp->CallbackL( callback ); + CleanupStack::Pop( callback ); + + /// Insert to first position because event are send in reverse order. + /// Last inserted gets notifcation last. + iObservers.InsertL( &aObserver, 0 ); + } + +// -------------------------------------------------------------------------- +// CViewBase::RemoveObserver +// -------------------------------------------------------------------------- +// +void CViewBase::RemoveObserver(MVPbkContactViewObserver& aObserver) + { + iObserverOp->CancelCallback( &aObserver ); + const TInt index( iObservers.Find( &aObserver ) ); + if (index != KErrNotFound) + { + iObservers.Remove(index); + } + } + +// -------------------------------------------------------------------------- +// CViewBase::MatchContactStore +// -------------------------------------------------------------------------- +// +TBool CViewBase::MatchContactStore(const TDesC& aContactStoreUri) const + { + return iParentStore.MatchContactStore(aContactStoreUri); + } + +// -------------------------------------------------------------------------- +// CViewBase::MatchContactStoreDomain +// -------------------------------------------------------------------------- +// +TBool CViewBase::MatchContactStoreDomain + ( const TDesC& aContactStoreDomain ) const + { + return iParentStore.MatchContactStoreDomain( aContactStoreDomain ); + } + +// -------------------------------------------------------------------------- +// CViewBase::CreateBookmarkLC +// -------------------------------------------------------------------------- +// +MVPbkContactBookmark* CViewBase::CreateBookmarkLC(TInt aIndex) const + { + __ASSERT_ALWAYS( aIndex >= 0, + VPbkError::Panic( VPbkError::EInvalidContactIndex ) ); + + TContactItemId contactId = iView->AtL(aIndex); + // Link implements also the bookmark interface in this store + return CContactBookmark::NewLC( contactId, iParentStore ); + } + +// -------------------------------------------------------------------------- +// CViewBase::IndexOfBookmarkL +// -------------------------------------------------------------------------- +// +TInt CViewBase::IndexOfBookmarkL( + const MVPbkContactBookmark& aContactBookmark) const + { + TInt result = KErrNotFound; + // Bookmark is implemeted as a link in this store + const CContactBookmark* bookmark = + dynamic_cast(&aContactBookmark); + if (bookmark && + &bookmark->ContactStore() == &ContactStore() ) + { + result = iView->FindL( bookmark->ContactId() ); + } + + return result; + } + +// -------------------------------------------------------------------------- +// CViewBase::AddFilteringObserverL +// -------------------------------------------------------------------------- +// +void CViewBase::AddFilteringObserverL( + MFilteredViewSupportObserver& aObserver ) + { + // Insert observer in callback function. That ensures that the observer + // will always get the event asynchronously. + + CVPbkAsyncObjectCallback* callback = + VPbkEngUtils::CreateAsyncObjectCallbackLC( + *this, + &CViewBase::DoAddFilteringObserverL, + &CViewBase::DoAddFilteringObserverError, + aObserver); + + iFilterObsOp->CallbackL( callback ); + CleanupStack::Pop( callback ); + } + +// -------------------------------------------------------------------------- +// CViewBase::RemoveFilteringObserver +// -------------------------------------------------------------------------- +// +void CViewBase::RemoveFilteringObserver( + MFilteredViewSupportObserver& aObserver ) + { + iFilterObsOp->CancelCallback( &aObserver ); + const TInt index( iFilteringObservers.Find( &aObserver ) ); + if ( index != KErrNotFound ) + { + iFilteringObservers.Remove( index ); + } + } + +// -------------------------------------------------------------------------- +// CViewBase::ViewFiltering +// -------------------------------------------------------------------------- +// +MVPbkContactViewFiltering* CViewBase::ViewFiltering() + { + // Both contact view and group view support filtering + return this; + } + +// -------------------------------------------------------------------------- +// CViewBase::CreateFilteredViewLC +// -------------------------------------------------------------------------- +// +MVPbkContactViewBase* CViewBase::CreateFilteredViewLC( + MVPbkContactViewObserver& aObserver, + const MDesCArray& aFindWords, + const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts ) + { + CFindView* findView = CFindView::NewLC( aFindWords, *this, aObserver, + aAlwaysIncludedContacts, Store().ContactStoreDomainFsSession() ); + findView->ActivateContactMatchL(); + return findView; + } + +// -------------------------------------------------------------------------- +// CViewBase::UpdateFilterL +// -------------------------------------------------------------------------- +// +void CViewBase::UpdateFilterL( + const MDesCArray& /*aFindWords*/, + const MVPbkContactBookmarkCollection* /*aAlwaysIncludedContacts*/ ) + { + // CViewBase implementations are "all contacts" views and not itself + // filtered views. Only creating a filtered view is supported. + User::Leave( KErrNotSupported ); + } + +// -------------------------------------------------------------------------- +// CViewBase::ParentObject +// -------------------------------------------------------------------------- +// +MVPbkObjectHierarchy& CViewBase::ParentObject() const + { + return iParentStore; + } + +// -------------------------------------------------------------------------- +// CViewBase::StoreReady +// -------------------------------------------------------------------------- +// +void CViewBase::StoreReady( MVPbkContactStore& /*aContactStore*/ ) + { + if ( !iViewReady ) + { + TeardownView(); + TRAPD( error, InitializeViewL( *iViewDefinition, *iSortOrder ) ); + + if ( error != KErrNone ) + { + iViewReady = EFalse; + SendViewErrorEvent( error ); + } + } + } + +// -------------------------------------------------------------------------- +// CViewBase::StoreUnavailable +// -------------------------------------------------------------------------- +// +void CViewBase::StoreUnavailable + ( MVPbkContactStore& /*aContactStore*/, TInt /*aReason*/ ) + { + TeardownView(); + iViewReady = EFalse; + SendViewStateEvent(); + } + +// -------------------------------------------------------------------------- +// CViewBase::HandleStoreEventL +// -------------------------------------------------------------------------- +// +void CViewBase::HandleStoreEventL( + MVPbkContactStore& /*aContactStore*/, + TVPbkContactStoreEvent /*aStoreEvent*/) + { + // No need to handle this here, events are received from the view + } + +// -------------------------------------------------------------------------- +// CViewBase::HandleContactViewEvent +// -------------------------------------------------------------------------- +// +void CViewBase::HandleContactViewEvent + ( const CContactViewBase& /*aView*/, + const TContactViewEvent& aEvent ) + { + switch ( aEvent.iEventType ) + { + case TContactViewEvent::EUnavailable: + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) EUnavailable"), + this ); + + iViewReady = EFalse; + SendViewStateEvent(); + break; + } + case TContactViewEvent::EReady: + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) EReady"), + this); + + iViewReady = ETrue; + SendViewStateEvent(); + break; + } + case TContactViewEvent::EItemAdded: + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) EItemAdded\ + index %d id %d"), this, aEvent.iInt, aEvent.iContactId); + iViewReady = ETrue; + iEventLink->SetContactId(aEvent.iContactId); + VPbkEng::SendViewEventToObservers( *this, aEvent.iInt, *iEventLink, + iObservers, &MVPbkContactViewObserver::ContactAddedToView, + &MVPbkContactViewObserver::ContactViewError ); + VPbkEng::SendViewEventToObservers( *this, aEvent.iInt, *iEventLink, + iFilteringObservers, + &MVPbkContactViewObserver::ContactAddedToView, + &MVPbkContactViewObserver::ContactViewError ); + break; + } + case TContactViewEvent::EItemRemoved: + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) EItemRemoved\ + index %d id %d"), + this, aEvent.iInt, aEvent.iContactId); + + iViewReady = ETrue; + iEventLink->SetContactId( aEvent.iContactId ); + VPbkEng::SendViewEventToObservers( *this, aEvent.iInt, *iEventLink, + iObservers, + &MVPbkContactViewObserver::ContactRemovedFromView, + &MVPbkContactViewObserver::ContactViewError ); + VPbkEng::SendViewEventToObservers( *this, aEvent.iInt, *iEventLink, + iFilteringObservers, + &MVPbkContactViewObserver::ContactRemovedFromView, + &MVPbkContactViewObserver::ContactViewError ); + break; + } + case TContactViewEvent::ESortOrderChanged: + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) ESortOrderChanged"), + this); + + iViewReady = ETrue; + // Update the new sort order to the view contact + TRAPD( res, DoUpdateTypeListL() ); + if ( res != KErrNone ) + { + SendViewErrorEvent( res ); + } + else + { + SendViewStateEvent(); + } + break; + } + case TContactViewEvent::ESortError: + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) ESortError"), + this); + + iViewReady = EFalse; + SendViewErrorEvent( aEvent.iInt ); + break; + } + case TContactViewEvent::EServerError: + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) EServerError"), + this); + + iViewReady = EFalse; + SendViewErrorEvent( aEvent.iInt ); + break; + } + + case TContactViewEvent::EIndexingError: + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) EIndexingError"), + this); + + iViewReady = EFalse; + SendViewErrorEvent( aEvent.iInt ); + break; + } + case TContactViewEvent::EGroupChanged: // FALLTHROUGH + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) EGroupChanged"), + this); + + // We don't send any events because EItemRemoved and/or + // EItemAdded events are generated and those handle the UI + // refreshing. If the view is not ready we are expecting + // EReady event from CntModel to refresh the view. + } + default: + { + // Default is: do nothing + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleContactViewEvent(0x%x) eventType %d"), + this, aEvent.iEventType ); + break; + } + } + } + +// -------------------------------------------------------------------------- +// CViewBase::HandleCustomContactViewEvent +// -------------------------------------------------------------------------- +// +void CViewBase::HandleCustomContactViewEvent + ( const CContactViewBase& aView, + const TContactViewEvent& aEvent ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING + ("CViewBase::HandleCustomContactViewEvent(0x%x)"), &aView); + + // This function needs to behave like HandleContactViewEvent function + // above, but without notifying observers. The observers will be notified + // later, with the succeeding HandleContactViewEvent call. + switch ( aEvent.iEventType ) + { + case TContactViewEvent::EReady: // FALLTHROUGH + case TContactViewEvent::EItemAdded: // FALLTHROUGH + case TContactViewEvent::EItemRemoved: // FALLTHROUGH + case TContactViewEvent::ESortOrderChanged: // FALLTHROUGH + case TContactViewEvent::EGroupChanged: // FALLTHROUGH + { + iViewReady = ETrue; + break; + } + + case TContactViewEvent::EUnavailable: // FALLTHROUGH + case TContactViewEvent::ESortError: // FALLTHROUGH + case TContactViewEvent::EServerError: // FALLTHROUGH + case TContactViewEvent::EIndexingError: // FALLTHROUGH + { + iViewReady = EFalse; + break; + } + default: + { + // Do nothing + break; + } + } + } + +// -------------------------------------------------------------------------- +// CViewBase::CreateSortOrderL +// -------------------------------------------------------------------------- +// +RContactViewSortOrder CViewBase::CreateSortOrderL + ( const MVPbkFieldTypeList& aSortOrder ) + { + RContactViewSortOrder sortOrder; + CleanupClosePushL(sortOrder); + + const TInt count = aSortOrder.FieldTypeCount(); + for (TInt i = 0; i < count; ++i) + { + const MVPbkFieldType& fieldType = aSortOrder.FieldTypeAt(i); + // Ignores all field types that are not supported by this store + const CContactItemField* field = + iParentStore.FieldFactory().FindField(fieldType); + if (field) + { + sortOrder.AppendL(field->ContentType().FieldType(0)); + } + } + CleanupStack::Pop(); // sortOrder + + return sortOrder; + } + +// -------------------------------------------------------------------------- +// CViewBase::DoUpdateTypeListL +// -------------------------------------------------------------------------- +// +void CViewBase::DoUpdateTypeListL() + { + MVPbkFieldTypeList* typeList = CFieldTypeList::NewLC + (iView->SortOrderL(), iParentStore.FieldTypeMap()); + iCurrentContact->SetTypeListL(*typeList); + + CVPbkSortOrder* sortOrder = CVPbkSortOrder::NewL(*typeList); + delete iSortOrder; + iSortOrder = sortOrder; + CleanupStack::PopAndDestroy(); // typeList + } + +// -------------------------------------------------------------------------- +// CViewBase::DoAddObserverL +// -------------------------------------------------------------------------- +// +void CViewBase::DoAddObserverL(MVPbkContactViewObserver& aObserver) + { + // Check if aObserver is still observer of this view + if ( iObservers.Find( &aObserver ) != KErrNotFound ) + { + if (iViewReady) + { + // If this view is ready and there was no error, + // tell it to the observer + aObserver.ContactViewReady(*this); + } + else if (!iViewReady && !iParentStore.IsOpened()) + { + aObserver.ContactViewUnavailable(*this); + } + // If this view was not ready and there was no error, observer will + // be called back in HandleContactViewEvent + } + } + +// -------------------------------------------------------------------------- +// CViewBase::AddObserverError +// -------------------------------------------------------------------------- +// +void CViewBase::AddObserverError(MVPbkContactViewObserver& aObserver, TInt aError) + { + // Check if aObserver is still observer of this view + if ( iObservers.Find( &aObserver ) != KErrNotFound) + { + aObserver.ContactViewError(*this, aError, EFalse); + } + } + +// -------------------------------------------------------------------------- +// CViewBase::DoAddFilteringObserverL +// -------------------------------------------------------------------------- +// +void CViewBase::DoAddFilteringObserverL( + MFilteredViewSupportObserver& aObserver ) + { + /// Insert to first position because event are send in reverse order. + /// Last inserted gets notifcation last. + iFilteringObservers.InsertL( &aObserver, 0 ); + + if (iViewReady) + { + // If this view is ready and there was no error. + // Build filtered view first using the internal interface + aObserver.ContactViewReadyForFiltering( *this ); + // Then let the filtered view to send event to its external + // observers. + aObserver.ContactViewReady( *this ); + } + else if (!iViewReady && !iParentStore.IsOpened()) + { + aObserver.ContactViewUnavailableForFiltering( *this ); + aObserver.ContactViewUnavailable( *this ); + } + } + +// -------------------------------------------------------------------------- +// CViewBase::DoAddFilteringObserverError +// -------------------------------------------------------------------------- +// +void CViewBase::DoAddFilteringObserverError( + MFilteredViewSupportObserver& aObserver, TInt aError ) + { + // See DoAddFilteringObserverL. If it leaves then adding the aObserver + // failed. + aObserver.ContactViewError(*this, aError, EFalse); + } + +// -------------------------------------------------------------------------- +// CViewBase::InitializeViewL +// -------------------------------------------------------------------------- +// +void CViewBase::InitializeViewL( + const CVPbkContactViewDefinition& aViewDefinition, + const MVPbkFieldTypeList& aSortOrder ) + { + iCurrentContact = CViewContact::NewL( *this, aSortOrder ); + + RContactViewSortOrder viewSortOrder = CreateSortOrderL( aSortOrder ); + CleanupClosePushL( viewSortOrder ); + + // Let sub class create the concrete view to iView + DoInitializeViewL( aViewDefinition, viewSortOrder ); + // Update sort order because shared view can have a different + // sort order compared to aSortOrder. Creating a new remote view + // handle to Contacts Model shared view doesn't change the sort order + // in Contacts Server shared view. + if ( iView ) + { + DoUpdateTypeListL(); + + // Set find plugin uid, without this cntmodel find does not work with + // all variants. + iView->SetViewFindConfigPlugin( TUid::Uid( KFindPluginUID ) ); + } + + CleanupStack::PopAndDestroy(); // viewSortOrder + + iEventLink = CContactLink::NewLC( iParentStore, KNullContactId ); + CleanupStack::Pop( iEventLink ); + } + +// -------------------------------------------------------------------------- +// CViewBase::TeardownView +// -------------------------------------------------------------------------- +// +void CViewBase::TeardownView() + { + delete iCurrentContact; + iCurrentContact = NULL; + + if (iView) + { + iView->Close(*this); + iView = NULL; + } + + delete iEventLink; + iEventLink = NULL; + + DoTeardownView(); + } + +// -------------------------------------------------------------------------- +// CViewBase::SendViewErrorEvent +// -------------------------------------------------------------------------- +// +void CViewBase::SendViewErrorEvent( TInt aError ) + { + // Cancel async operation to avoid double message sending + // to observer in DoAddObserverL + PurgeAsyncOperations(); + + /// Then report the failure to client so that in handle it. + TBool errorIsNotified = EFalse; + VPbkEng::SendEventToObservers( *this, aError, errorIsNotified, + iObservers, &MVPbkContactViewObserver::ContactViewError ); + VPbkEng::SendEventToObservers( *this, aError, errorIsNotified, + iFilteringObservers, &MVPbkContactViewObserver::ContactViewError ); + } + +// -------------------------------------------------------------------------- +// CViewBase::SendViewStateEvent +// -------------------------------------------------------------------------- +// +void CViewBase::SendViewStateEvent() + { + // Cancel async operation to avoid double message sending + // to observer in DoAddObserverL + PurgeAsyncOperations(); + + void (MVPbkContactViewObserver::*obsNotifyFunc)( + MVPbkContactViewBase&) = + &MVPbkContactViewObserver::ContactViewReady; + void (MFilteredViewSupportObserver::*filtObsNotifyFunc)( + MParentViewForFiltering&) = + &MFilteredViewSupportObserver::ContactViewReadyForFiltering; + + if ( !iViewReady ) + { + obsNotifyFunc = &MVPbkContactViewObserver::ContactViewUnavailable; + filtObsNotifyFunc = + &MFilteredViewSupportObserver::ContactViewUnavailableForFiltering; + } + + // Due to filtered view stack it must be ensured that internal filtered + // views know first about changes because CRefineViews have pointers to + // contacts that must not be invalidated. + // On the other hand the events to external observers must come + // first from lowest view in the view stack. + // See MVPbkContactViewFiltering interface. + VPbkEng::SendViewEventToObservers( *this, iFilteringObservers, + filtObsNotifyFunc, &MVPbkContactViewObserver::ContactViewError ); + VPbkEng::SendViewEventToObservers( *this, iObservers, + obsNotifyFunc, &MVPbkContactViewObserver::ContactViewError ); + VPbkEng::SendViewEventToObservers( *this, iFilteringObservers, + obsNotifyFunc, &MVPbkContactViewObserver::ContactViewError ); + } + +// -------------------------------------------------------------------------- +// CViewBase::PurgeAsyncOperations +// -------------------------------------------------------------------------- +// +void CViewBase::PurgeAsyncOperations() + { + // Purge only iObserverOp callbacks because observers are added + // already in AddObserverL. iFilterObsOp must not be purged because + // filtering observers are added in a call back DoAddFilteringObserverL. + iObserverOp->Purge(); + } + +// -------------------------------------------------------------------------- +// CViewBase::LeaveIfIncorrectSortOrderL +// -------------------------------------------------------------------------- +// +void CViewBase::LeaveIfIncorrectSortOrderL( + const MVPbkFieldTypeList& aSortOrder ) + { + if ( RemoteViewDefinition( *iViewDefinition ) ) + { + // Get allowed sort orders via ECOM + CVPbkSortOrderAcquirer::TSortOrderAcquirerParam param( + iParentStore.MasterFieldTypeList() ); + CSortOrderAcquirerList* ecomList = + CSortOrderAcquirerList::NewLC(param); + + const TInt count = ecomList->Count(); + for ( TInt i = 0; i < count; ++i ) + { + CVPbkSortOrderAcquirer& acquirer = ecomList->At( i ); + // Sort order is incorrect if + // 1) acquirer is for this store + // 2) this is a shared view and acquirer is for the + // same named view. + // 3) aSortOrder is not same as acquirer's sort order. + if ( acquirer.ApplySortOrderToStoreL( + iParentStore.StoreProperties().Uri() ) && + ecomList->FindInfo(acquirer)->DisplayName().CompareC( + RemoteViewName( *iViewDefinition ) ) == 0 && + !VPbkFieldTypeList::IsSame( acquirer.SortOrder(), + aSortOrder) ) + { + User::Leave( KErrArgument ); + } + } + CleanupStack::PopAndDestroy( ecomList ); + } + } +} // namespace VPbkCntModel + +// End of File