--- /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 <MVPbkContactViewObserver.h>
+#include <MVPbkFieldType.h>
+#include <VPbkError.h>
+#include <CVPbkSortOrder.h>
+#include <CVPbkAsyncCallback.h>
+#include <VPbkPrivateUid.h> // KFindPluingUID
+#include <VPbkSendEventUtility.h>
+#include <CVPbkContactViewDefinition.h>
+#include <MVPbkContactStoreProperties.h>
+
+// System includes
+#include <cntitem.h>
+
+// Debugging headers
+#include <VPbkDebug.h>
+
+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<MVPbkContactViewObserver>::NewL();
+ iFilterObsOp =
+ CVPbkAsyncObjectOperation<MFilteredViewSupportObserver>::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<MVPbkContactViewObserver>::NewL();
+ iFilterObsOp =
+ CVPbkAsyncObjectOperation<MFilteredViewSupportObserver>::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<const CContactLink&>(aContactLink);
+ result = iView->FindL(link.ContactId());
+ }
+
+ return result;
+ }
+
+// --------------------------------------------------------------------------
+// CViewBase::AddObserverL
+// --------------------------------------------------------------------------
+//
+void CViewBase::AddObserverL(MVPbkContactViewObserver& aObserver)
+ {
+ CVPbkAsyncObjectCallback<MVPbkContactViewObserver>* 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<const CContactBookmark*>(&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<MFilteredViewSupportObserver>* 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