phonebookengines/VirtualPhonebook/VPbkCntModel/src/CViewBase.cpp
changeset 0 e686773b3f54
child 23 5586b4d2ec3e
--- /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