phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkCompositeContactView.cpp
changeset 0 e686773b3f54
child 15 e8e3147d53eb
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 /*
       
     2 * Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Composite contact view.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "CVPbkCompositeContactView.h"
       
    20 #include <MVPbkFieldType.h>
       
    21 #include <CVPbkSortOrder.h>
       
    22 #include <CVPbkAsyncCallback.h>
       
    23 #include <MVPbkContactLink.h>
       
    24 #include "CVPbkEventArrayItem.h"
       
    25 #include <VPbkError.h>
       
    26 
       
    27 // Debugging headers
       
    28 #include <VPbkProfile.h>
       
    29 #include <VPbkDebug.h>
       
    30 
       
    31 /// Unnamed namespace for local definitions
       
    32 namespace {
       
    33 
       
    34 #ifdef _DEBUG
       
    35     enum TPanic
       
    36         {
       
    37         EPanicLogic_CreateBookmarkLC = 3
       
    38         };
       
    39         
       
    40     void Panic(TPanic aPanic)
       
    41         {
       
    42         _LIT(KPanicCat, "CVPbkCompositeContactView");
       
    43         User::Panic(KPanicCat, aPanic);
       
    44         }
       
    45 #endif // _DEBUG
       
    46 
       
    47 /// Observer granulatiry
       
    48 const TInt KObserverArrayGranularity = 4;
       
    49 
       
    50 /////////////////////////////////////////////////////////////////////////////
       
    51 // Event sending functions for different amount of parameters
       
    52 //
       
    53 
       
    54 // --------------------------------------------------------------------------
       
    55 // SendEventToObservers
       
    56 // --------------------------------------------------------------------------
       
    57 //
       
    58 template <class NotifyFunc>
       
    59 void SendEventToObservers( MVPbkContactViewBase& aView, 
       
    60         RPointerArray<MVPbkContactViewObserver>& aObservers,
       
    61         NotifyFunc aNotifyFunc )
       
    62     {
       
    63     const TInt count = aObservers.Count();
       
    64     for (TInt i = count - 1; i >= 0; --i)
       
    65         {
       
    66         MVPbkContactViewObserver* observer = aObservers[i];
       
    67         (observer->*aNotifyFunc)(aView);
       
    68         }
       
    69     }
       
    70 
       
    71 // --------------------------------------------------------------------------
       
    72 // SendEventToObservers
       
    73 // --------------------------------------------------------------------------
       
    74 //
       
    75 template <class NotifyFunc, class ParamType1, class ParamType2>
       
    76 void SendEventToObservers( MVPbkContactViewBase& aView, 
       
    77         RPointerArray<MVPbkContactViewObserver>& aObservers,
       
    78         NotifyFunc aNotifyFunc, ParamType1 aParam1, const ParamType2& aParam2 )
       
    79     {
       
    80     const TInt count = aObservers.Count();
       
    81     for (TInt i = count - 1; i >= 0; --i)
       
    82         {
       
    83         MVPbkContactViewObserver* observer = aObservers[i];
       
    84         (observer->*aNotifyFunc)(aView, aParam1, aParam2);
       
    85         }
       
    86     }
       
    87 
       
    88 } /// namespace
       
    89 
       
    90 // --------------------------------------------------------------------------
       
    91 // CVPbkCompositeContactView::CSubViewData::~CSubViewData
       
    92 // --------------------------------------------------------------------------
       
    93 //
       
    94 CVPbkCompositeContactView::CSubViewData::~CSubViewData()
       
    95     {
       
    96     delete iView;
       
    97     }
       
    98 
       
    99 // --------------------------------------------------------------------------
       
   100 // CVPbkCompositeContactView::CVPbkCompositeContactView
       
   101 // --------------------------------------------------------------------------
       
   102 //
       
   103 CVPbkCompositeContactView::CVPbkCompositeContactView() :
       
   104         iAsyncOperation( CActive::EPriorityStandard ),
       
   105         iObservers( KObserverArrayGranularity )
       
   106     {
       
   107     }
       
   108 
       
   109 // --------------------------------------------------------------------------
       
   110 // CVPbkCompositeContactView::~CVPbkCompositeContactView
       
   111 // --------------------------------------------------------------------------
       
   112 //
       
   113 CVPbkCompositeContactView::~CVPbkCompositeContactView()
       
   114     {    
       
   115     delete iCompositePolicy;
       
   116     delete iSortOrder;
       
   117     iSubViews.ResetAndDestroy();
       
   118     iObservers.Close();
       
   119     iContactMapping.Reset();
       
   120     }
       
   121 
       
   122 // --------------------------------------------------------------------------
       
   123 // CVPbkCompositeContactView::BaseConstructL
       
   124 // --------------------------------------------------------------------------
       
   125 //
       
   126 void CVPbkCompositeContactView::BaseConstructL
       
   127         (const MVPbkFieldTypeList& aSortOrder)
       
   128     {
       
   129     // Create sort order
       
   130     iSortOrder = CVPbkSortOrder::NewL(aSortOrder);
       
   131 
       
   132     // Always apply internal policy
       
   133     iCompositePolicy = 
       
   134             CVPbkInternalCompositeViewPolicy::NewL( *this, iObservers );
       
   135 
       
   136     // External policy's view event buffering mechanism does not work when
       
   137     // native contact views reside in a separate process, therefore we
       
   138     // always apply internal policy.
       
   139     }
       
   140 
       
   141 // --------------------------------------------------------------------------
       
   142 // CVPbkCompositeContactView::AddSubViewL
       
   143 // Adds subview to this composite view.
       
   144 // --------------------------------------------------------------------------
       
   145 //
       
   146 void CVPbkCompositeContactView::AddSubViewL(MVPbkContactViewBase* aSubView, TInt  aViewId)
       
   147     {
       
   148     CSubViewData* subViewData =
       
   149         new(ELeave) CSubViewData(CSubViewData::ENotKnown);
       
   150     CleanupStack::PushL(subViewData);
       
   151     User::LeaveIfError(iSubViews.Append(subViewData));
       
   152     CleanupStack::Pop(subViewData);
       
   153 
       
   154     subViewData->iView = aSubView;
       
   155     subViewData->iViewId = aViewId;
       
   156     }
       
   157         
       
   158 // --------------------------------------------------------------------------
       
   159 // CVPbkCompositeContactView::ActualContactCountL
       
   160 // --------------------------------------------------------------------------
       
   161 //        
       
   162 TInt CVPbkCompositeContactView::ActualContactCountL() const
       
   163     {
       
   164     const TInt subViewCount = iSubViews.Count();
       
   165     TInt contactCount = 0;
       
   166     for (TInt i = 0; i < subViewCount; ++i)
       
   167         {
       
   168         if ( iSubViews[i]->iState == CSubViewData::EReady )
       
   169             {
       
   170             if ( iSubViews[i]->iView->Type() == EVPbkCompositeView )
       
   171                 {
       
   172                 // The view can be safely casted because
       
   173                 // CVPbkCompositeContactView is VPbkEng internal
       
   174                 // and EVPbkCompositeView type view is always
       
   175                 // derived from CVPbkCompositeContactView.
       
   176                 contactCount += static_cast<CVPbkCompositeContactView*>( 
       
   177                     iSubViews[i]->iView )->ActualContactCountL();
       
   178                 }
       
   179             else
       
   180                 {
       
   181                 contactCount += iSubViews[i]->iView->ContactCountL();
       
   182                 }
       
   183             }
       
   184         }
       
   185     return contactCount;
       
   186     }
       
   187 
       
   188 // --------------------------------------------------------------------------
       
   189 // CVPbkCompositeContactView::ApplyInternalCompositePolicyL
       
   190 // --------------------------------------------------------------------------
       
   191 //        
       
   192 void CVPbkCompositeContactView::ApplyInternalCompositePolicyL()
       
   193     {
       
   194     if ( !iCompositePolicy || !iCompositePolicy->InternalPolicy() )
       
   195         {
       
   196         MVPbkCompositeContactViewPolicy* newPolicy = 
       
   197                 CVPbkInternalCompositeViewPolicy::NewL( *this, iObservers );
       
   198         delete iCompositePolicy;
       
   199         iCompositePolicy = newPolicy;
       
   200         }
       
   201     }
       
   202     
       
   203 // --------------------------------------------------------------------------
       
   204 // CVPbkCompositeContactView::Type
       
   205 // Returns view type.
       
   206 // --------------------------------------------------------------------------
       
   207 //
       
   208 TVPbkContactViewType CVPbkCompositeContactView::Type() const
       
   209     {
       
   210     return EVPbkCompositeView;
       
   211     }
       
   212 
       
   213 // --------------------------------------------------------------------------
       
   214 // CVPbkCompositeContactView::ChangeSortOrderL
       
   215 // Changes sort order.
       
   216 // --------------------------------------------------------------------------
       
   217 //
       
   218 void CVPbkCompositeContactView::ChangeSortOrderL
       
   219         (const MVPbkFieldTypeList& aSortOrder)
       
   220     {
       
   221     const TInt subViewCount = iSubViews.Count();
       
   222     for (TInt i = 0; i < subViewCount; ++i)
       
   223         {
       
   224         // All ready subviews go to unknown state because
       
   225         // they need to be re-sorted.
       
   226         // State is known again when an event comes.
       
   227         if (iSubViews[i]->iState == CSubViewData::EReady)
       
   228             {
       
   229             iSubViews[i]->iState = CSubViewData::ENotKnown;
       
   230             iSubViews[i]->iView->ChangeSortOrderL(aSortOrder);
       
   231             }
       
   232         }
       
   233     
       
   234     // Create new sort order and take it in use
       
   235     MVPbkFieldTypeList* sortOrder = CVPbkSortOrder::NewL(aSortOrder);
       
   236     delete iSortOrder;
       
   237     iSortOrder = sortOrder;
       
   238     }
       
   239 
       
   240 // --------------------------------------------------------------------------
       
   241 // CVPbkCompositeContactView::SortOrder
       
   242 // Returns current sort order.
       
   243 // --------------------------------------------------------------------------
       
   244 //
       
   245 const MVPbkFieldTypeList& CVPbkCompositeContactView::SortOrder() const
       
   246     {
       
   247     return *iSortOrder;
       
   248     }
       
   249 
       
   250 // --------------------------------------------------------------------------
       
   251 // CVPbkCompositeContactView::RefreshL
       
   252 // Refreshes all subviews
       
   253 // --------------------------------------------------------------------------
       
   254 //
       
   255 void CVPbkCompositeContactView::RefreshL()
       
   256     {
       
   257     const TInt subViewCount = iSubViews.Count();
       
   258     for (TInt i = 0; i < subViewCount; ++i)
       
   259         {
       
   260         iSubViews[i]->iView->RefreshL();
       
   261         }
       
   262     }
       
   263 
       
   264 // --------------------------------------------------------------------------
       
   265 // CVPbkCompositeContactView::ContactCountL
       
   266 // Returns contact count.
       
   267 // --------------------------------------------------------------------------
       
   268 //
       
   269 TInt CVPbkCompositeContactView::ContactCountL() const
       
   270     {
       
   271     return iCompositePolicy->ContactCountL();
       
   272     }
       
   273 
       
   274 // --------------------------------------------------------------------------
       
   275 // CVPbkCompositeContactView::ContactAtL
       
   276 // Returns contact at aIndex.
       
   277 // --------------------------------------------------------------------------
       
   278 //
       
   279 const MVPbkViewContact& CVPbkCompositeContactView::ContactAtL
       
   280         (TInt aIndex) const
       
   281     {
       
   282     __ASSERT_ALWAYS(
       
   283         aIndex >= 0, VPbkError::Panic( VPbkError::EInvalidContactIndex ) );
       
   284     if ( aIndex >= iContactMapping.Count() )
       
   285         {
       
   286         User::Leave( KErrArgument );
       
   287         }
       
   288 
       
   289     const TContactMapping& mapping = iContactMapping[aIndex];
       
   290     MVPbkContactViewBase* view = iSubViews[mapping.iViewIndex]->iView;
       
   291     return view->ContactAtL( mapping.iContactIndex );
       
   292     }
       
   293 
       
   294 // --------------------------------------------------------------------------
       
   295 // CVPbkCompositeContactView::CreateLinkLC
       
   296 // Creates link from a contact at aIndex.
       
   297 // --------------------------------------------------------------------------
       
   298 //
       
   299 MVPbkContactLink* CVPbkCompositeContactView::CreateLinkLC(TInt aIndex) const
       
   300     {
       
   301     __ASSERT_ALWAYS(
       
   302         aIndex >= 0, VPbkError::Panic( VPbkError::EInvalidContactIndex ) );
       
   303     if ( aIndex >= iContactMapping.Count() )
       
   304         {
       
   305         User::Leave( KErrArgument );
       
   306         }
       
   307 
       
   308     const TContactMapping& mapping = iContactMapping[aIndex];
       
   309     MVPbkContactViewBase* view = iSubViews[mapping.iViewIndex]->iView;
       
   310     return view->CreateLinkLC( mapping.iContactIndex );
       
   311     }
       
   312 
       
   313 // --------------------------------------------------------------------------
       
   314 // CVPbkCompositeContactView::IndexOfLinkL
       
   315 // Returns index of aContactLink.
       
   316 // --------------------------------------------------------------------------
       
   317 //
       
   318 TInt CVPbkCompositeContactView::IndexOfLinkL
       
   319         (const MVPbkContactLink& aContactLink) const
       
   320     {
       
   321     TIdentityRelation<TContactMapping> comparisonOperator
       
   322         (&CVPbkCompositeContactView::CompareMappings);
       
   323     TInt result = KErrNotFound;
       
   324 
       
   325     // Search the link from all the subviews
       
   326     const TInt subViewCount = iSubViews.Count();
       
   327     for (TInt i = 0; i < subViewCount; ++i)
       
   328         {
       
   329         // Check that the view is ready before using it.
       
   330         TInt index = KErrNotFound;
       
   331         if (iSubViews[i]->iState == CSubViewData::EReady)
       
   332             {
       
   333             index = iSubViews[i]->iView->IndexOfLinkL(aContactLink);        
       
   334             }        
       
   335             
       
   336         if (index != KErrNotFound)
       
   337             {
       
   338             // Establish contact mapping for view and contact index
       
   339             TContactMapping mapping;
       
   340             mapping.iViewIndex = i;
       
   341             mapping.iContactIndex = index;
       
   342             // Find the composite index by comparing the two mappings
       
   343             result = iContactMapping.Find(mapping, comparisonOperator);
       
   344             break;
       
   345             }
       
   346         }
       
   347     return result;
       
   348     }
       
   349 
       
   350 // --------------------------------------------------------------------------
       
   351 // CVPbkCompositeContactView::AddObserverL
       
   352 // --------------------------------------------------------------------------
       
   353 //
       
   354 void CVPbkCompositeContactView::AddObserverL
       
   355         (MVPbkContactViewObserver& aObserver)
       
   356     {
       
   357     // Add the observer only if it is not already added
       
   358     TInt err( iObservers.InsertInAddressOrder(&aObserver) );
       
   359     if ( err != KErrNone && err != KErrAlreadyExists)
       
   360         {
       
   361         User::Leave( err );
       
   362         }
       
   363 
       
   364     TRAP(err, 
       
   365         {
       
   366         VPbkEngUtils::MAsyncCallback* notifyObserver =
       
   367             VPbkEngUtils::CreateAsyncCallbackLC(
       
   368                 *this, 
       
   369                 &CVPbkCompositeContactView::DoAddObserverL, 
       
   370                 &CVPbkCompositeContactView::AddObserverError, 
       
   371                 aObserver);
       
   372         iAsyncOperation.CallbackL(notifyObserver);
       
   373         CleanupStack::Pop(notifyObserver);
       
   374         });
       
   375 
       
   376     if (err != KErrNone)
       
   377         {
       
   378         RemoveObserver(aObserver);
       
   379         User::Leave(err);
       
   380         }
       
   381     }
       
   382 
       
   383 // --------------------------------------------------------------------------
       
   384 // CVPbkCompositeContactView::RemoveObserver
       
   385 // --------------------------------------------------------------------------
       
   386 //
       
   387 void CVPbkCompositeContactView::RemoveObserver
       
   388         (MVPbkContactViewObserver& aObserver)
       
   389     {
       
   390     const TInt index = iObservers.FindInAddressOrder( &aObserver );
       
   391     if (index != KErrNotFound)
       
   392         {
       
   393         iObservers.Remove(index);
       
   394         }
       
   395     }
       
   396 
       
   397 // --------------------------------------------------------------------------
       
   398 // CVPbkCompositeContactView::MatchContactStore
       
   399 // Check does any of the subviews match given contact store.
       
   400 // --------------------------------------------------------------------------
       
   401 //
       
   402 TBool CVPbkCompositeContactView::MatchContactStore
       
   403         (const TDesC& aContactStoreUri) const
       
   404     {
       
   405     const TInt count = iSubViews.Count();
       
   406     TBool result = EFalse;
       
   407     for (TInt i = 0; i < count && !result; ++i)
       
   408         {
       
   409         result = iSubViews[i]->iView->MatchContactStore(aContactStoreUri);
       
   410         }
       
   411     return result;
       
   412     }
       
   413     
       
   414 // --------------------------------------------------------------------------
       
   415 // CVPbkCompositeContactView::MatchContactStoreDomain
       
   416 // Check does any of the subviews match given contact store domain.
       
   417 // --------------------------------------------------------------------------
       
   418 //
       
   419 
       
   420  TBool CVPbkCompositeContactView::MatchContactStoreDomain
       
   421         (const TDesC& aContactStoreDomain) const
       
   422     {
       
   423     const TInt count = iSubViews.Count();
       
   424     TBool result = EFalse;
       
   425     for (TInt i = 0; i < count && !result; ++i)
       
   426         {
       
   427         result = iSubViews[i]->iView->MatchContactStoreDomain
       
   428             (aContactStoreDomain);
       
   429         }
       
   430     return result;
       
   431     }
       
   432 
       
   433 // --------------------------------------------------------------------------
       
   434 // CVPbkCompositeContactView::CreateBookmarkLC
       
   435 // Creates a bookmark for given index.
       
   436 // --------------------------------------------------------------------------
       
   437 //
       
   438 MVPbkContactBookmark* CVPbkCompositeContactView::CreateBookmarkLC
       
   439         (TInt aIndex) const
       
   440     {
       
   441     __ASSERT_ALWAYS( aIndex >= 0, 
       
   442         VPbkError::Panic( VPbkError::EInvalidContactIndex ) );
       
   443     __ASSERT_DEBUG(ContactCountL() > aIndex, 
       
   444             Panic(EPanicLogic_CreateBookmarkLC));
       
   445 
       
   446     const TContactMapping& mapping = iContactMapping[aIndex];
       
   447     MVPbkContactViewBase* view = iSubViews[mapping.iViewIndex]->iView;
       
   448     return view->CreateBookmarkLC( mapping.iContactIndex );
       
   449     }
       
   450 
       
   451 // --------------------------------------------------------------------------
       
   452 // CVPbkCompositeContactView::IndexOfBookmarkL
       
   453 // Returns the index of given bookmark.
       
   454 // --------------------------------------------------------------------------
       
   455 //
       
   456 TInt CVPbkCompositeContactView::IndexOfBookmarkL
       
   457         (const MVPbkContactBookmark& aContactBookmark) const
       
   458     {
       
   459     TIdentityRelation<TContactMapping> comparisonOperator(
       
   460         &CVPbkCompositeContactView::CompareMappings);
       
   461     TInt result = KErrNotFound;
       
   462     
       
   463     // Search the bookmark from all the subviews
       
   464     const TInt subViewCount = iSubViews.Count();
       
   465     for (TInt i = 0; i < subViewCount; ++i)
       
   466         {
       
   467         // Check that the view is ready before using it.
       
   468         TInt index(KErrNotFound);
       
   469         if (iSubViews[i]->iState == CSubViewData::EReady)
       
   470             {
       
   471             index = iSubViews[i]->iView->IndexOfBookmarkL(aContactBookmark);
       
   472             }
       
   473             
       
   474         if (index != KErrNotFound)
       
   475             {
       
   476             // Establish contact mapping for view and contact index
       
   477             TContactMapping mapping;
       
   478             mapping.iViewIndex = i;
       
   479             mapping.iContactIndex = index;
       
   480             // Find the composite index by comparing the two mappings
       
   481             result = iContactMapping.Find(mapping, comparisonOperator);
       
   482             break;
       
   483             }
       
   484         }
       
   485     return result;
       
   486     }
       
   487 
       
   488 // --------------------------------------------------------------------------
       
   489 // CVPbkCompositeContactView::ViewFiltering
       
   490 // --------------------------------------------------------------------------
       
   491 //
       
   492 MVPbkContactViewFiltering* CVPbkCompositeContactView::ViewFiltering()
       
   493     {
       
   494     // Composite views support filtering and is also a filtered view.
       
   495     // The subclass must implement the interface.
       
   496     return this;
       
   497     }
       
   498 
       
   499 TAny* CVPbkCompositeContactView::ContactViewBaseExtension(TUid aExtensionUid)
       
   500     {
       
   501     MVPbkContactViewBaseChildAccessExtension* extChild = NULL;
       
   502     if ( aExtensionUid == TUid::Uid(KVPbkViewBaseExtChildAccess) )
       
   503         {
       
   504         extChild = this;
       
   505         }
       
   506     return extChild;
       
   507     }
       
   508 
       
   509 // --------------------------------------------------------------------------
       
   510 // CVPbkCompositeContactView::ContactViewReady
       
   511 // --------------------------------------------------------------------------
       
   512 //
       
   513 void CVPbkCompositeContactView::ContactViewReady(MVPbkContactViewBase& aView)
       
   514     {
       
   515     TRAPD( res, HandleContactViewReadyL( aView ) );
       
   516     if ( res != KErrNone )
       
   517         {
       
   518         // There was an error when building a composite. Reset composite
       
   519         // inform client that this view unavailable and there is an error
       
   520         ResetContactMapping();
       
   521         SendViewUnavailableEvent();
       
   522         SendViewErrorEvent( res, EFalse );
       
   523         }
       
   524     }
       
   525 
       
   526 // --------------------------------------------------------------------------
       
   527 // CVPbkCompositeContactView::ContactViewUnavailable
       
   528 // --------------------------------------------------------------------------
       
   529 //
       
   530 void CVPbkCompositeContactView::ContactViewUnavailable
       
   531         (MVPbkContactViewBase& aView)
       
   532     {
       
   533     TRAPD( res, HandleContactViewUnavailableL( aView ) );
       
   534     if ( res != KErrNone )
       
   535         {
       
   536         // There was an error when building a composite. Reset composite
       
   537         // inform client that this view unavailable and there is an error
       
   538         ResetContactMapping();
       
   539         SendViewUnavailableEvent();
       
   540         SendViewErrorEvent( res, EFalse );
       
   541         }
       
   542     }
       
   543 
       
   544 // --------------------------------------------------------------------------
       
   545 // CVPbkCompositeContactView::ContactAddedToView
       
   546 // --------------------------------------------------------------------------
       
   547 //
       
   548 void CVPbkCompositeContactView::ContactAddedToView
       
   549         (MVPbkContactViewBase& aView, TInt aIndex,
       
   550         const MVPbkContactLink& aContactLink)
       
   551     {
       
   552     TInt compositeIndex = HandleContactAddition(aView, aIndex);
       
   553 
       
   554     TRAPD( error, iCompositePolicy->HandleViewEventsL( 
       
   555         CVPbkEventArrayItem::EAdded, aView, compositeIndex, aContactLink ) );
       
   556     if ( error != KErrNone )
       
   557         {
       
   558         // If error occurs reset policy
       
   559         iCompositePolicy->Reset();
       
   560         SendViewErrorEvent( error, EFalse );
       
   561         }
       
   562     }
       
   563 
       
   564 // --------------------------------------------------------------------------
       
   565 // CVPbkCompositeContactView::ContactRemovedFromView
       
   566 // --------------------------------------------------------------------------
       
   567 //
       
   568 void CVPbkCompositeContactView::ContactRemovedFromView
       
   569         (MVPbkContactViewBase& aView, TInt aIndex,
       
   570         const MVPbkContactLink& aContactLink)
       
   571     {
       
   572     TInt compositeIndex( KErrNotFound );
       
   573     compositeIndex = HandleContactRemoval(aView, aIndex);
       
   574     TRAPD( error, iCompositePolicy->HandleViewEventsL( 
       
   575         CVPbkEventArrayItem::ERemoved, aView, compositeIndex, 
       
   576             aContactLink ) );
       
   577     if ( error != KErrNone )
       
   578         {
       
   579         // If error occurs reset policy
       
   580         iCompositePolicy->Reset();
       
   581         SendViewErrorEvent( error, EFalse );
       
   582         }
       
   583     }
       
   584 
       
   585 // --------------------------------------------------------------------------
       
   586 // CVPbkCompositeContactView::ContactViewError
       
   587 // --------------------------------------------------------------------------
       
   588 //
       
   589 void CVPbkCompositeContactView::ContactViewError
       
   590         (MVPbkContactViewBase& /*aView*/, TInt aError, TBool aErrorNotified)
       
   591     {
       
   592     SendViewErrorEvent( aError, aErrorNotified );
       
   593     }
       
   594 
       
   595 // --------------------------------------------------------------------------
       
   596 // CVPbkCompositeContactView::UpdateFilterL
       
   597 // --------------------------------------------------------------------------
       
   598 //    
       
   599 void CVPbkCompositeContactView::UpdateFilterL( 
       
   600         const MDesCArray& aFindWords,
       
   601         const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts )
       
   602     {
       
   603     const TInt count = iSubViews.Count();
       
   604     for( TInt i = 0; i < count; ++i )
       
   605         {
       
   606         MVPbkContactViewFiltering* filtering = 
       
   607             iSubViews[i]->iView->ViewFiltering();
       
   608         // Check if the subview supports filtering.
       
   609         if ( filtering )
       
   610             {
       
   611             // Filtering supported
       
   612             filtering->UpdateFilterL( aFindWords, aAlwaysIncludedContacts );
       
   613             // Set state to unknown. NOTE: this set so that the composite
       
   614             // becomes ready state when all subviews have notified something.
       
   615             // Otherwise the composite would notify its own observers every
       
   616             // time a subview notifies composite. This is not wanted because
       
   617             // client must get only one notification after update.
       
   618             // On the other hand a client can still use this view while it's
       
   619             // updating itself so in that point of view the composite is not
       
   620             // in unknown state but in update state.
       
   621             iSubViews[i]->iState = CSubViewData::ENotKnown;            
       
   622             }
       
   623         }
       
   624     }
       
   625 
       
   626 TInt CVPbkCompositeContactView::ChildViewCount() const
       
   627     {
       
   628     return iSubViews.Count();
       
   629     }
       
   630 
       
   631 MVPbkContactViewBase& CVPbkCompositeContactView::ChildViewAt( TInt aIndex )
       
   632     {
       
   633     return *iSubViews[aIndex]->iView;
       
   634     }
       
   635 
       
   636 MVPbkContactViewBase* CVPbkCompositeContactView::GetChildViewById( TInt aId)
       
   637     {
       
   638     MVPbkContactViewBase* view = NULL;
       
   639     const TInt count = iSubViews.Count();
       
   640     for (TInt i = 0; i < count; ++i)
       
   641         {
       
   642         view=iSubViews[i]->iView; 
       
   643         if (iSubViews[i]->iViewId == aId)
       
   644            {
       
   645            return view;
       
   646            }
       
   647         }
       
   648     return NULL;
       
   649     }
       
   650 
       
   651 TInt CVPbkCompositeContactView::GetViewId()
       
   652     {
       
   653      return iViewId;
       
   654     }
       
   655 // --------------------------------------------------------------------------
       
   656 // CVPbkCompositeContactView::SendViewReadyEvent
       
   657 // --------------------------------------------------------------------------
       
   658 //         
       
   659 void CVPbkCompositeContactView::SendViewReadyEvent()
       
   660     {
       
   661     VPBK_DEBUG_PRINT( VPBK_DEBUG_STRING(
       
   662         "CVPbkCompositeContactView::SendViewReadyEvent(0x%x)"), this );
       
   663     // Cancel operation to avoid unnecessary event sending in DoAddObserverL
       
   664     iAsyncOperation.Purge();
       
   665     SendEventToObservers( *this, iObservers,
       
   666         &MVPbkContactViewObserver::ContactViewReady );
       
   667     }
       
   668 
       
   669 // --------------------------------------------------------------------------
       
   670 // CVPbkCompositeContactView::SendViewUnavailableEvent
       
   671 // --------------------------------------------------------------------------
       
   672 //        
       
   673 void CVPbkCompositeContactView::SendViewUnavailableEvent()
       
   674     {
       
   675     VPBK_DEBUG_PRINT( VPBK_DEBUG_STRING(
       
   676         "CVPbkCompositeContactView::SendViewUnavailableEvent(0x%x)"), this );
       
   677     // Cancel operation to avoid unnecessary event sending in DoAddObserverL
       
   678     iAsyncOperation.Purge();
       
   679     SendEventToObservers( *this, iObservers,
       
   680         &MVPbkContactViewObserver::ContactViewUnavailable );
       
   681     }
       
   682 
       
   683 // --------------------------------------------------------------------------
       
   684 // CVPbkCompositeContactView::SendViewErrorEvent
       
   685 // --------------------------------------------------------------------------
       
   686 //
       
   687 void CVPbkCompositeContactView::SendViewErrorEvent( TInt aError, 
       
   688         TBool aErrorNotified )
       
   689     {
       
   690     SendEventToObservers(*this, iObservers, 
       
   691         &MVPbkContactViewObserver::ContactViewError, aError, aErrorNotified);
       
   692     }
       
   693     
       
   694 // --------------------------------------------------------------------------
       
   695 // CVPbkCompositeContactView::CompareMappings
       
   696 // --------------------------------------------------------------------------
       
   697 //
       
   698 TBool CVPbkCompositeContactView::CompareMappings
       
   699         (const TContactMapping& aLhs, const TContactMapping& aRhs)
       
   700     {
       
   701     // Mappings match if both the contact index and the view index match
       
   702     return (aLhs.iContactIndex == aRhs.iContactIndex &&
       
   703             aLhs.iViewIndex == aRhs.iViewIndex);
       
   704     }
       
   705 
       
   706 // --------------------------------------------------------------------------
       
   707 // CVPbkCompositeContactView::IsCompositeReady
       
   708 // --------------------------------------------------------------------------
       
   709 //
       
   710 TBool CVPbkCompositeContactView::IsCompositeReady() const
       
   711     {
       
   712     // Composite view is ready if states of all sub views are known and
       
   713     // at least one of them is ready.
       
   714     return AllSubViewsKnown() && AnySubViewReady();
       
   715     }
       
   716 
       
   717 // --------------------------------------------------------------------------
       
   718 // CVPbkCompositeContactView::CompositePolicy
       
   719 // --------------------------------------------------------------------------
       
   720 //        
       
   721 MVPbkCompositeContactViewPolicy& 
       
   722         CVPbkCompositeContactView::CompositePolicy() const
       
   723     {
       
   724     return *iCompositePolicy;
       
   725     }
       
   726 
       
   727 // --------------------------------------------------------------------------
       
   728 // CVPbkCompositeContactView::FindSubViewIndex
       
   729 // --------------------------------------------------------------------------
       
   730 //
       
   731 TInt CVPbkCompositeContactView::FindSubViewIndex
       
   732         (MVPbkContactViewBase& aView) const
       
   733     {
       
   734     TInt result = KErrNotFound;
       
   735     const TInt count = iSubViews.Count();
       
   736     for (TInt i = 0; i < count; ++i)
       
   737         {
       
   738         if (iSubViews[i]->iView == &aView)
       
   739             {
       
   740             result = i;
       
   741             break;
       
   742             }
       
   743         }
       
   744     return result;
       
   745     }
       
   746 
       
   747 // --------------------------------------------------------------------------
       
   748 // CVPbkCompositeContactView::AllSubViewsKnown
       
   749 // Returns true if all the subviews are known.
       
   750 // --------------------------------------------------------------------------
       
   751 //
       
   752 TBool CVPbkCompositeContactView::AllSubViewsKnown() const
       
   753     {
       
   754     TBool ret = ETrue;
       
   755     const TInt count = iSubViews.Count();
       
   756     for (TInt i = 0; i < count; ++i)
       
   757         {
       
   758         if (iSubViews[i]->iState == CSubViewData::ENotKnown)
       
   759             {
       
   760             ret = EFalse;
       
   761             break;
       
   762             }
       
   763         }
       
   764     return ret;
       
   765     }
       
   766 
       
   767 // --------------------------------------------------------------------------
       
   768 // CVPbkCompositeContactView::AnySubViewReady
       
   769 // Returns true if any of the subviews is ready.
       
   770 // --------------------------------------------------------------------------
       
   771 //
       
   772 TBool CVPbkCompositeContactView::AnySubViewReady() const
       
   773     {
       
   774     TBool ret = EFalse;
       
   775     const TInt count = iSubViews.Count();
       
   776     for (TInt i = 0; i < count; ++i)
       
   777         {
       
   778         if (iSubViews[i]->iState == CSubViewData::EReady)
       
   779             {
       
   780             ret = ETrue;
       
   781             break;
       
   782             }
       
   783         }
       
   784 
       
   785     return ret;
       
   786     }
       
   787 
       
   788 // --------------------------------------------------------------------------
       
   789 // CVPbkCompositeContactView::ResetContactMapping
       
   790 // --------------------------------------------------------------------------
       
   791 //    
       
   792 void CVPbkCompositeContactView::ResetContactMapping()
       
   793     {
       
   794     iContactMapping.Reset();
       
   795     }
       
   796 
       
   797 // --------------------------------------------------------------------------
       
   798 // CVPbkCompositeContactView::RemoveContactMappingsFromView
       
   799 // --------------------------------------------------------------------------
       
   800 //
       
   801 void CVPbkCompositeContactView::RemoveContactMappingsFromView( 
       
   802         MVPbkContactViewBase& aView )
       
   803     {
       
   804     TInt subviewIndex = FindSubViewIndex( aView );
       
   805     if ( subviewIndex != KErrNotFound )
       
   806         {
       
   807         const TInt count = iContactMapping.Count();
       
   808         for ( TInt i = count - 1; i >= 0; --i )
       
   809             {
       
   810             if ( iContactMapping[i].iViewIndex == subviewIndex )
       
   811                 {
       
   812                 iContactMapping.Remove( i );
       
   813                 }
       
   814             }
       
   815         }
       
   816     }
       
   817 
       
   818 // --------------------------------------------------------------------------
       
   819 // CVPbkCompositeContactView::HandleContactViewReadyL
       
   820 // --------------------------------------------------------------------------
       
   821 //
       
   822 void CVPbkCompositeContactView::HandleContactViewReadyL( 
       
   823         MVPbkContactViewBase& aView )
       
   824     {
       
   825     VPBK_DEBUG_PRINT( VPBK_DEBUG_STRING(
       
   826         "CVPbkCompositeContactView::HandleContactViewReadyL(0x%x)"), this );
       
   827     
       
   828     // Find matching subview and set its state to ready
       
   829     TInt subViewIndex = FindSubViewIndex(aView);
       
   830     if (subViewIndex != KErrNotFound)
       
   831         {
       
   832         iSubViews[subViewIndex]->iState = CSubViewData::EReady;
       
   833         }
       
   834 
       
   835     // Check that composite's sort order up to date with subviews.
       
   836     UpdateSortOrderL();
       
   837     
       
   838     // If composite is ready, build view mapping and notify observers
       
   839     if ( IsCompositeReady() )
       
   840         {
       
   841         VPBK_PROFILE_START(VPbkProfile::ECompositeContactViewMapping);
       
   842         DoBuildContactMappingL();
       
   843         VPBK_PROFILE_END(VPbkProfile::ECompositeContactViewMapping);
       
   844         SendViewReadyEvent();
       
   845         }    
       
   846     }
       
   847 
       
   848 // --------------------------------------------------------------------------
       
   849 // CVPbkCompositeContactView::HandleContactViewUnavailableL
       
   850 // --------------------------------------------------------------------------
       
   851 //
       
   852 void CVPbkCompositeContactView::HandleContactViewUnavailableL( 
       
   853         MVPbkContactViewBase& aView )
       
   854     {
       
   855     VPBK_DEBUG_PRINT( VPBK_DEBUG_STRING(
       
   856         "CVPbkCompositeContactView::ContactViewUnavailable(0x%x)"), this );
       
   857     
       
   858     // Find matching subview and set its state
       
   859     TInt subViewIndex = FindSubViewIndex(aView);
       
   860     if (subViewIndex != KErrNotFound)
       
   861         {
       
   862         iSubViews[subViewIndex]->iState = CSubViewData::EUnavailable;
       
   863         }
       
   864 
       
   865     if ( IsCompositeReady() )
       
   866         {
       
   867         // Composite is still in ready state. The mapping must be updated
       
   868         // because one of the subviews became unavailable.
       
   869         DoBuildContactMappingL();
       
   870         // Call observers so that they know about update.
       
   871         SendViewReadyEvent();
       
   872         }
       
   873     else
       
   874         {
       
   875         if ( AllSubViewsKnown() )
       
   876             {
       
   877             // Composite is unavailable. Notify observers.
       
   878             ResetContactMapping();
       
   879             SendViewUnavailableEvent();
       
   880             }
       
   881         else
       
   882             {
       
   883             // Composite is still under construction.
       
   884             
       
   885             // Dont't send event here because the state of the composite is
       
   886             // not yet known and sending event can cause problems for client
       
   887             // e.g unwanted changes in the UI state.
       
   888             RemoveContactMappingsFromView( aView );
       
   889             }
       
   890         }
       
   891     }
       
   892     
       
   893 // --------------------------------------------------------------------------
       
   894 // CVPbkCompositeContactView::CVPbkCompositeContactView
       
   895 // --------------------------------------------------------------------------
       
   896 //
       
   897 TInt CVPbkCompositeContactView::HandleContactRemoval
       
   898         ( MVPbkContactViewBase& aView, TInt aIndex )
       
   899     {
       
   900     TInt index = KErrNotFound;
       
   901     
       
   902     // Find correct subview
       
   903     TInt subViewIndex = FindSubViewIndex( aView );
       
   904     if ( subViewIndex != KErrNotFound )
       
   905         {
       
   906         TIdentityRelation<TContactMapping> comparisonOperator
       
   907             ( &CVPbkCompositeContactView::CompareMappings );
       
   908         // Establish contact mapping for view and contact index
       
   909         TContactMapping mapping;
       
   910         mapping.iViewIndex = subViewIndex;
       
   911         mapping.iContactIndex = aIndex;
       
   912         // Find the composite index by comparing the two mappings
       
   913         index = iContactMapping.Find( mapping, comparisonOperator );
       
   914         
       
   915         if ( index > KErrNotFound )
       
   916             {            
       
   917             // Loop through the rest of the contacts of the subview
       
   918             // and modify their global contact mapping information
       
   919             for (TInt i = index; i < iContactMapping.Count(); ++i)
       
   920                 {
       
   921                 if (iContactMapping[i].iViewIndex == subViewIndex)
       
   922                     {
       
   923                     // Subtract one because one contact was deleted
       
   924                     // from the list before the current index
       
   925                     --iContactMapping[i].iContactIndex;
       
   926                     }
       
   927                 }
       
   928             // Finally remove the deleted index from global mapping
       
   929             iContactMapping.Remove( index );
       
   930             }
       
   931         else
       
   932             {
       
   933             // mapping inconsistent with the underlying view, rebuild it
       
   934             DoBuildContactMappingL();
       
   935             }
       
   936         }
       
   937     return index;
       
   938     }
       
   939         
       
   940 // --------------------------------------------------------------------------
       
   941 // CVPbkCompositeContactView::HandleContactAddition
       
   942 // --------------------------------------------------------------------------
       
   943 //
       
   944 TInt CVPbkCompositeContactView::HandleContactAddition
       
   945         (MVPbkContactViewBase& aView, TInt aIndex)
       
   946     {
       
   947     TInt index = KErrNotFound;
       
   948     
       
   949     // Find correct subview
       
   950     TInt subViewIndex = FindSubViewIndex(aView);
       
   951     if (subViewIndex != KErrNotFound)
       
   952         {
       
   953         TRAPD( err, index = DoHandleContactAdditionL
       
   954             ( subViewIndex, aIndex ) );
       
   955         if (err != KErrNone)
       
   956             {
       
   957             index = err;
       
   958             }
       
   959         else 
       
   960         	{
       
   961         	// We have to fix the indexes of all the succeeding
       
   962             // contacts in the view where the contact addition took place
       
   963             for ( TInt i = index + 1; i < iContactMapping.Count(); ++i )
       
   964                 {
       
   965                 if (iContactMapping[i].iViewIndex == subViewIndex)
       
   966                     {
       
   967                     ++iContactMapping[i].iContactIndex;
       
   968                     }
       
   969                 }
       
   970         	}
       
   971         }
       
   972     return index;
       
   973     }
       
   974     
       
   975 // --------------------------------------------------------------------------
       
   976 // CVPbkCompositeContactView::DoAddObserverL
       
   977 // Notifies composite view readiness to observer.
       
   978 // --------------------------------------------------------------------------
       
   979 //
       
   980 void CVPbkCompositeContactView::DoAddObserverL
       
   981         (MVPbkContactViewObserver& aObserver)
       
   982     {
       
   983     // Check if aObserver is still observer of this view and the view is ready.
       
   984     // View is considered to be ready if all subviews are ready (iIsReady)
       
   985     // or if there are no subviews
       
   986     if ( iObservers.FindInAddressOrder( &aObserver ) != KErrNotFound )
       
   987         {
       
   988         if( IsCompositeReady() )
       
   989             {            
       
   990             // If this view is ready and there was no error tell it to the observer            
       
   991             aObserver.ContactViewReady(*this);            
       
   992             }
       
   993         else if ( AllSubViewsKnown() )
       
   994             {
       
   995             // All subviews are known but the composite is not ready ->
       
   996             // view is unavailable.
       
   997             aObserver.ContactViewUnavailable( *this );
       
   998             }
       
   999         // If this view was not ready and there was no error, observer will
       
  1000         // be called back in HandleContactViewEvent
       
  1001         }
       
  1002     }
       
  1003 
       
  1004 // --------------------------------------------------------------------------
       
  1005 // CVPbkCompositeContactView::AddObserverError
       
  1006 // Notifies composite view problems to observer.
       
  1007 // --------------------------------------------------------------------------
       
  1008 //
       
  1009 void CVPbkCompositeContactView::AddObserverError
       
  1010         (MVPbkContactViewObserver& aObserver, TInt aError)
       
  1011     {
       
  1012     // Check if aObserver is still observer of this view
       
  1013     if (iObservers.FindInAddressOrder( &aObserver ) != KErrNotFound)
       
  1014         {
       
  1015         aObserver.ContactViewError(*this, aError, EFalse);
       
  1016         }
       
  1017     }
       
  1018 
       
  1019 // --------------------------------------------------------------------------
       
  1020 // CVPbkCompositeContactView::UpdateSortOrderL
       
  1021 // --------------------------------------------------------------------------
       
  1022 //
       
  1023 void CVPbkCompositeContactView::UpdateSortOrderL()
       
  1024     {
       
  1025     const MVPbkFieldTypeList* sortOrder = NULL;
       
  1026     
       
  1027     // Inspect the sort order of subviews. If all ready subviews have
       
  1028     // same sort order then update composite's sort order.
       
  1029     // This is done because subviews can be shared views whose sort order
       
  1030     // is not changed to client's sort order when a new handle is created.
       
  1031     TBool subViewsHaveSameOrder = ETrue;
       
  1032     const TInt count = iSubViews.Count();
       
  1033     for ( TInt i = 0; i < count && subViewsHaveSameOrder; ++i )
       
  1034         {
       
  1035         if ( iSubViews[i]->iState == CSubViewData::EReady )
       
  1036             {
       
  1037             const MVPbkFieldTypeList& curViewsOrder = 
       
  1038                     iSubViews[i]->iView->SortOrder();
       
  1039             if ( sortOrder )
       
  1040                 {
       
  1041                 subViewsHaveSameOrder = 
       
  1042                     VPbkFieldTypeList::IsSame( *sortOrder, curViewsOrder );
       
  1043                 }
       
  1044             sortOrder = &curViewsOrder;
       
  1045             }
       
  1046         }
       
  1047         
       
  1048     if ( subViewsHaveSameOrder && sortOrder && 
       
  1049          !VPbkFieldTypeList::IsSame( *sortOrder, *iSortOrder ) )
       
  1050         {
       
  1051         CVPbkSortOrder* newOrder = CVPbkSortOrder::NewL( *sortOrder );
       
  1052         delete iSortOrder;
       
  1053         iSortOrder = newOrder;
       
  1054         }
       
  1055     }
       
  1056     
       
  1057 void CVPbkCompositeContactView::SetViewId(TInt aViewId)
       
  1058     {
       
  1059     iViewId = aViewId;
       
  1060     }   
       
  1061 // --------------------------------------------------------------------------
       
  1062 // CVPbkExternalCompositeViewPolicy::CVPbkExternalCompositeViewPolicy
       
  1063 // --------------------------------------------------------------------------
       
  1064 //
       
  1065 CVPbkExternalCompositeViewPolicy::CVPbkExternalCompositeViewPolicy( 
       
  1066         CVPbkCompositeContactView& aCompositeView,
       
  1067         RPointerArray<MVPbkContactViewObserver>& aObservers )
       
  1068         :   iCompositeView( aCompositeView ),
       
  1069             iObservers( aObservers )
       
  1070     {
       
  1071     }
       
  1072     
       
  1073 // --------------------------------------------------------------------------
       
  1074 // CVPbkExternalCompositeViewPolicy::NewL
       
  1075 // --------------------------------------------------------------------------
       
  1076 //
       
  1077 CVPbkExternalCompositeViewPolicy* CVPbkExternalCompositeViewPolicy::NewL(
       
  1078         CVPbkCompositeContactView& aCompositeView,
       
  1079         RPointerArray<MVPbkContactViewObserver>& aObservers )
       
  1080     {
       
  1081     CVPbkExternalCompositeViewPolicy* self = 
       
  1082         new ( ELeave ) CVPbkExternalCompositeViewPolicy( aCompositeView, 
       
  1083             aObservers );
       
  1084     return self;
       
  1085     }
       
  1086 
       
  1087 // --------------------------------------------------------------------------
       
  1088 // CVPbkExternalCompositeViewPolicy::~CVPbkExternalCompositeViewPolicy
       
  1089 // --------------------------------------------------------------------------
       
  1090 //    
       
  1091 CVPbkExternalCompositeViewPolicy::~CVPbkExternalCompositeViewPolicy()
       
  1092     {
       
  1093     iEventArray.ResetAndDestroy();
       
  1094     }
       
  1095 
       
  1096 // --------------------------------------------------------------------------
       
  1097 // CVPbkExternalCompositeViewPolicy::HandleViewEventsL
       
  1098 // --------------------------------------------------------------------------
       
  1099 //    
       
  1100 void CVPbkExternalCompositeViewPolicy::HandleViewEventsL( 
       
  1101         CVPbkEventArrayItem::TViewEventType aEvent,
       
  1102         MVPbkContactViewBase& /*aSubview*/,
       
  1103         TInt aIndex, const 
       
  1104         MVPbkContactLink& aContactLink )
       
  1105     {        
       
  1106     // Append all view events to proper event array.
       
  1107     CVPbkEventArrayItem* item = 
       
  1108         CVPbkEventArrayItem::NewLC( aIndex, aContactLink, aEvent );
       
  1109             
       
  1110     iEventArray.AppendL( item );
       
  1111     CleanupStack::Pop(); // item
       
  1112     
       
  1113     // Check if the composite is up to date. Note that if the underlying
       
  1114     // native store view resides in a separate process or thread,
       
  1115     // this check may "accidentally" pass whilst the native view is still
       
  1116     // updating itself. This means that the composite might fall out of sync
       
  1117     // anytime after this check and it will then mean severe problems to the
       
  1118     // client, since if it asks for ContactCountL the answer will
       
  1119     // be zero, as the sync check is implemented in
       
  1120     // CVPbkExternalCompositeViewPolicy::ContactCountL too.
       
  1121     // The count of zero might be in severe contradiction with the
       
  1122     // view events the client just received.
       
  1123     // If the native view resides in the  same process, there are no risks.
       
  1124     if (iCompositeView.CompositeContactCountL() == 
       
  1125             iCompositeView.ActualContactCountL() )
       
  1126         {
       
  1127         // Composite mapping is valid according to contact counts. Flush
       
  1128         // the event cache.
       
  1129         TInt eventCount( iEventArray.Count() );
       
  1130                           
       
  1131         for( TInt i = 0; i < eventCount; ++i )
       
  1132             {
       
  1133             if ( iEventArray[ i ]->Event() == CVPbkEventArrayItem::ERemoved )
       
  1134                 {
       
  1135                 SendEventToObservers( iCompositeView, iObservers,
       
  1136                     &MVPbkContactViewObserver::ContactRemovedFromView,
       
  1137                     iEventArray[ i ]->Index(), 
       
  1138                     *iEventArray[ i ]->Link() ); 
       
  1139                 }
       
  1140             else
       
  1141                 {
       
  1142                 SendEventToObservers( iCompositeView, iObservers,
       
  1143                     &MVPbkContactViewObserver::ContactAddedToView,
       
  1144                     iEventArray[ i ]->Index(), 
       
  1145                     *iEventArray[ i ]->Link() );                                                
       
  1146                 }            
       
  1147             }                   
       
  1148         iEventArray.ResetAndDestroy();
       
  1149         }
       
  1150     }
       
  1151 
       
  1152 // --------------------------------------------------------------------------
       
  1153 // CVPbkExternalCompositeViewPolicy::Reset
       
  1154 // --------------------------------------------------------------------------
       
  1155 //    
       
  1156 void CVPbkExternalCompositeViewPolicy::Reset()
       
  1157     {
       
  1158     iEventArray.ResetAndDestroy();
       
  1159     }
       
  1160 
       
  1161 // --------------------------------------------------------------------------
       
  1162 // CVPbkExternalCompositeViewPolicy::ContactCountL
       
  1163 // --------------------------------------------------------------------------
       
  1164 //    
       
  1165 TInt CVPbkExternalCompositeViewPolicy::ContactCountL() const
       
  1166     {
       
  1167     TInt compositeCount = iCompositeView.CompositeContactCountL();
       
  1168     
       
  1169     if ( compositeCount != iCompositeView.ActualContactCountL() )
       
  1170         {
       
  1171         // If composite count is different as the contact count in subviews
       
  1172         // it means that composite hasn't got all view events yet and its
       
  1173         // contact mapping is not in valid state. It's too heavy to build
       
  1174         // the whole mapping so zero is returned to inform client that
       
  1175         // it must not call ContactAtL because it can panic.
       
  1176         compositeCount = 0;
       
  1177         }
       
  1178     return compositeCount;
       
  1179     }
       
  1180 
       
  1181 // --------------------------------------------------------------------------
       
  1182 // CVPbkExternalCompositeViewPolicy::InternalPolicy
       
  1183 // --------------------------------------------------------------------------
       
  1184 //    
       
  1185 TBool CVPbkExternalCompositeViewPolicy::InternalPolicy() const
       
  1186     {
       
  1187     return EFalse;
       
  1188     }
       
  1189 
       
  1190 // --------------------------------------------------------------------------
       
  1191 // CVPbkInternalCompositeViewPolicy::CVPbkInternalCompositeViewPolicy
       
  1192 // --------------------------------------------------------------------------
       
  1193 //
       
  1194 CVPbkInternalCompositeViewPolicy::CVPbkInternalCompositeViewPolicy( 
       
  1195         CVPbkCompositeContactView& aCompositeView,
       
  1196         RPointerArray<MVPbkContactViewObserver>& aObservers )
       
  1197         :   iCompositeView( aCompositeView ),
       
  1198             iObservers( aObservers )
       
  1199     {
       
  1200     }
       
  1201     
       
  1202 // --------------------------------------------------------------------------
       
  1203 // CVPbkInternalCompositeViewPolicy::NewL
       
  1204 // --------------------------------------------------------------------------
       
  1205 //
       
  1206 CVPbkInternalCompositeViewPolicy* CVPbkInternalCompositeViewPolicy::NewL(
       
  1207         CVPbkCompositeContactView& aCompositeView,
       
  1208         RPointerArray<MVPbkContactViewObserver>& aObservers )
       
  1209     {
       
  1210     CVPbkInternalCompositeViewPolicy* self = 
       
  1211         new ( ELeave ) CVPbkInternalCompositeViewPolicy( aCompositeView, 
       
  1212             aObservers );
       
  1213     return self;
       
  1214     }
       
  1215 
       
  1216 // --------------------------------------------------------------------------
       
  1217 // CVPbkInternalCompositeViewPolicy::HandleViewEventsL
       
  1218 // --------------------------------------------------------------------------
       
  1219 //
       
  1220 void CVPbkInternalCompositeViewPolicy::HandleViewEventsL( 
       
  1221         CVPbkEventArrayItem::TViewEventType aEvent,
       
  1222         MVPbkContactViewBase& /*aSubview*/,
       
  1223         TInt aIndex, const 
       
  1224         MVPbkContactLink& aContactLink )
       
  1225     {
       
  1226     if ( aEvent == CVPbkEventArrayItem::ERemoved )
       
  1227         {
       
  1228         SendEventToObservers( iCompositeView, iObservers,
       
  1229             &MVPbkContactViewObserver::ContactRemovedFromView,
       
  1230             aIndex, 
       
  1231             aContactLink ); 
       
  1232         }
       
  1233     else
       
  1234         {
       
  1235         SendEventToObservers( iCompositeView, iObservers,
       
  1236             &MVPbkContactViewObserver::ContactAddedToView,
       
  1237             aIndex, 
       
  1238             aContactLink ); 
       
  1239         }            
       
  1240     }
       
  1241 
       
  1242 // --------------------------------------------------------------------------
       
  1243 // CVPbkInternalCompositeViewPolicy::Reset
       
  1244 // --------------------------------------------------------------------------
       
  1245 //    
       
  1246 void CVPbkInternalCompositeViewPolicy::Reset()
       
  1247     {
       
  1248     // No cached data to reset
       
  1249     }
       
  1250     
       
  1251 // --------------------------------------------------------------------------
       
  1252 // CVPbkInternalCompositeViewPolicy::ContactCountL
       
  1253 // --------------------------------------------------------------------------
       
  1254 //    
       
  1255 TInt CVPbkInternalCompositeViewPolicy::ContactCountL() const
       
  1256     {
       
  1257     return iCompositeView.CompositeContactCountL();
       
  1258     }
       
  1259 
       
  1260 // --------------------------------------------------------------------------
       
  1261 // CVPbkInternalCompositeViewPolicy::InternalPolicy
       
  1262 // --------------------------------------------------------------------------
       
  1263 //    
       
  1264 TBool CVPbkInternalCompositeViewPolicy::InternalPolicy() const
       
  1265     {
       
  1266     return ETrue;
       
  1267     }
       
  1268     
       
  1269 // End of File