phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkTopContactOperation.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
child 68 9da50d567e3c
equal deleted inserted replaced
62:5b6f26637ad3 63:f4a778e096c2
       
     1 /*
       
     2 * Copyright (c) 2005-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:  Top Contact opeartion
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDES
       
    20 #include "CVPbkTopContactOperation.h"
       
    21 
       
    22 #include <barsc.h>
       
    23 #include <barsread.h>
       
    24 
       
    25 #include <MVPbkContactViewBase.h>
       
    26 #include <VPbkStoreUriLiterals.h>
       
    27 #include <CVPbkContactViewDefinition.h>
       
    28 #include <CVPbkContactLinkArray.h>
       
    29 #include <MVPbkContactLink.h>
       
    30 #include <MVPbkContactOperationBase.h>
       
    31 #include <MVPbkContactStoreProperties.h>
       
    32 #include <MVPbkContactStoreList.h>
       
    33 #include <CVPbkContactStoreUriArray.h>
       
    34 #include <TVPbkFieldTypeMapping.h>
       
    35 #include <MVPbkContactFieldTextData.h>
       
    36 #include <CVPbkFieldTypeSelector.h>
       
    37 #include <MVPbkFieldType.h>
       
    38 #include <CVPbkContactManager.h>
       
    39 #include <MVPbkContactStore.h>
       
    40 #include <VPbkContactViewFilterBuilder.h>
       
    41 #include <CVPbkSortOrder.h>
       
    42 #include <VPbkEng.rsg>
       
    43 #include <VPbkDataCaging.hrh>
       
    44 #include <RLocalizedResourceFile.h>
       
    45 #include <TVPbkFieldVersitProperty.h>
       
    46 
       
    47 #include "CVPbkContactEasyManager.h"
       
    48 #include "VPbkDebug.h"
       
    49 
       
    50 #include <CVPbkSortOrderAcquirer.h>
       
    51 #include <CVPbkEComImplementationsList.h>
       
    52 #include <VPbkSortOrderAcquirerUid.h>
       
    53 
       
    54 namespace
       
    55 	{
       
    56 	const TInt KFirstTopOrderIndex = 1;
       
    57     const TInt KTcFieldLength = 10;
       
    58     
       
    59     _LIT( KAllContactsSortOrderDisplayName, "AllContacts" );
       
    60 
       
    61     /**
       
    62      * Custom cleanup function.
       
    63      *
       
    64      * @param aObj  Object to clean.
       
    65      */
       
    66     void CleanupResetAndDestroy( TAny* aObj )
       
    67         {
       
    68         if ( aObj )
       
    69             {
       
    70             static_cast<RImplInfoPtrArray*>( aObj )->ResetAndDestroy();
       
    71             }
       
    72         }    
       
    73     
       
    74 #ifdef _DEBUG	
       
    75 	enum TTopErrors
       
    76 	    {
       
    77 		ETopErrorWrongLogic1,
       
    78 		ETopErrorWrongLogic2,
       
    79 		ETopErrorWrongLogic3,
       
    80 		EInvalidViewOperation,
       
    81 		EInvalidLinksOperation,
       
    82 		EInvalidTopOperation,
       
    83 		ETopErrorAlreadyHaveAStore,
       
    84 		ETopErrorAlreadyHaveAView,
       
    85 		ETopErrorNoView,
       
    86 		ETopErrorNoFieldData,
       
    87 		ETopErrorNoLinks,
       
    88 		ETopViewMissing,
       
    89 		ETopErrorBadIndex,
       
    90 		ETopErrorOldArrayExists,
       
    91 		ETopErrorNoContacts,
       
    92         ETopErrorWrongState,
       
    93         ETopErrorWrongStateRun,
       
    94 	    };
       
    95 	
       
    96 	_LIT( KPanicStrTopManagement, "VPbk_topManag");
       
    97 	
       
    98 	void Panic(TTopErrors aReason)
       
    99 	    {
       
   100 	    User::Panic(KPanicStrTopManagement,aReason);
       
   101 	    }
       
   102 #endif	
       
   103 	}
       
   104 
       
   105 ///////////////////////////////////////////////////////////////////////////////
       
   106 
       
   107 CVPbkTopContactOperation* CVPbkTopContactOperation::NewLC(
       
   108         CVPbkContactManager& aContactManager,
       
   109         MVPbkOperationErrorObserver& aErrorObserver,
       
   110         TTopOperation aOperation)
       
   111     {
       
   112     CVPbkTopContactOperation* self = new (ELeave) CVPbkTopContactOperation(
       
   113             aContactManager,
       
   114             aErrorObserver,
       
   115             aOperation );
       
   116     CleanupStack::PushL( self );
       
   117     self->ConstructL();
       
   118     return self;
       
   119     }
       
   120 
       
   121 void CVPbkTopContactOperation::ConstructL()
       
   122     {
       
   123     iContactEasyManager = CVPbkContactEasyManager::NewL( iContactManager );
       
   124     }
       
   125 
       
   126 CVPbkTopContactOperation::CVPbkTopContactOperation(
       
   127         CVPbkContactManager& aContactManager,
       
   128         MVPbkOperationErrorObserver& aErrorObserver,
       
   129         TTopOperation aOperation )
       
   130     : CActive( EPriorityStandard ),
       
   131     iCurrentOperation(aOperation),
       
   132     iNextState(EStateOpenStore),
       
   133     iContactManager(aContactManager),
       
   134     iErrorObserver(&aErrorObserver)
       
   135     {
       
   136     CActiveScheduler::Add( this );
       
   137     CompleteOurself(); //start execution right away
       
   138     }
       
   139 
       
   140 CVPbkTopContactOperation::~CVPbkTopContactOperation()
       
   141     {
       
   142     Cancel();
       
   143     delete iContactOperation;
       
   144     delete iContactEasyManager;
       
   145     iContacts.ResetAndDestroy();
       
   146     delete iInputLinks;
       
   147     delete iView;
       
   148     if ( iContactStore )
       
   149         {
       
   150         // Store is not owned by us.
       
   151         iContactStore->Close( *this );
       
   152         }
       
   153     }
       
   154 
       
   155 MVPbkContactOperationBase* CVPbkTopContactOperation::NewGetViewOperationL(
       
   156         CVPbkContactManager& aContactManager,
       
   157         MVPbkOperationResultObserver<MVPbkContactViewBase*>& aObserver,
       
   158         MVPbkOperationErrorObserver& aErrorObserver,
       
   159         TTopOperation aOperation )
       
   160     {
       
   161     __ASSERT_DEBUG( aOperation == EGetTopContacts || 
       
   162                     aOperation == EGetNonTopContacts,
       
   163                     Panic(EInvalidViewOperation) );
       
   164     
       
   165     CVPbkTopContactOperation* self = NewLC(
       
   166             aContactManager,
       
   167             aErrorObserver,
       
   168             aOperation );
       
   169     self->iViewObserver = &aObserver;
       
   170 
       
   171     CleanupStack::Pop(self);
       
   172     return self;
       
   173     }
       
   174 
       
   175 MVPbkContactOperationBase* CVPbkTopContactOperation::NewGetViewLinksOperationL(
       
   176         CVPbkContactManager& aContactManager,
       
   177         MVPbkOperationResultObserver<MVPbkContactLinkArray*>& aObserver,
       
   178         MVPbkOperationErrorObserver& aErrorObserver,
       
   179         TTopOperation aOperation )
       
   180     {
       
   181     __ASSERT_DEBUG( aOperation == EGetTopContactLinks || 
       
   182                     aOperation == EGetNonTopContactLinks,
       
   183                     Panic(EInvalidLinksOperation) );
       
   184     
       
   185     CVPbkTopContactOperation* self = NewLC(
       
   186             aContactManager,
       
   187             aErrorObserver,
       
   188             aOperation );
       
   189     self->iLinksObserver = &aObserver;
       
   190 
       
   191     CleanupStack::Pop(self);
       
   192     return self;
       
   193     }
       
   194 
       
   195 MVPbkContactOperationBase* CVPbkTopContactOperation::NewTopOperationL(
       
   196         CVPbkContactManager& aContactManager,
       
   197         const MVPbkContactLinkArray& aContactLinks,
       
   198         MVPbkOperationObserver& aObserver,
       
   199         MVPbkOperationErrorObserver& aErrorObserver,
       
   200         TTopOperation aOperation,
       
   201         MVPbkContactViewBase* aViewRef)
       
   202     {
       
   203     __ASSERT_DEBUG( aOperation == EAddToTop || aOperation == ERemoveFromTop ||
       
   204             aOperation == EReorderTop,
       
   205             Panic(EInvalidTopOperation) );
       
   206     
       
   207     CVPbkTopContactOperation* self = NewLC(
       
   208             aContactManager,
       
   209             aErrorObserver,
       
   210             aOperation );
       
   211     self->iObserver = &aObserver;
       
   212     self->iInputLinks = CloneArrayL( aContactLinks ); 
       
   213     self->iViewRef = aViewRef;
       
   214     
       
   215     CleanupStack::Pop(self);
       
   216     return self;
       
   217     }
       
   218 
       
   219 void CVPbkTopContactOperation::DoCancel()
       
   220 	{
       
   221 	delete iContactOperation;
       
   222 	iContactOperation = NULL;
       
   223 	iContactEasyManager->Cancel();
       
   224 	}
       
   225 
       
   226 void CVPbkTopContactOperation::RunL()
       
   227 	{
       
   228 	if ( iNextState == EStateAbortWithError )
       
   229 	    {
       
   230 	    NotifyError( iAbortError );
       
   231 	    }
       
   232 	else
       
   233 	    {
       
   234     	switch ( iCurrentOperation )
       
   235     	    {
       
   236     	    case EAddToTop:
       
   237     	    case ERemoveFromTop:
       
   238     	    case EReorderTop:
       
   239         		{
       
   240         		Top_RunL();
       
   241         		break;
       
   242         		}
       
   243     	    case EGetNonTopContacts:
       
   244     	    case EGetTopContacts:
       
   245     	    case EGetTopContactLinks:
       
   246     	    case EGetNonTopContactLinks:
       
   247                 {
       
   248         		GetView_RunL();
       
   249         		break;
       
   250                 }
       
   251     	    default:
       
   252     	        __ASSERT_DEBUG( EFalse,
       
   253     	                Panic( ETopErrorWrongStateRun ) );
       
   254             }
       
   255 	    }
       
   256 	}
       
   257 
       
   258 TInt CVPbkTopContactOperation::RunError( TInt aError )
       
   259 	{
       
   260 	NotifyError( aError );
       
   261 	return KErrNone;
       
   262 	}
       
   263 
       
   264 //---------------------------------------------------------------
       
   265 // These are from MVPbkContactViewObserver
       
   266 
       
   267 void CVPbkTopContactOperation::ContactViewReady(
       
   268     MVPbkContactViewBase& aView )
       
   269     {
       
   270     aView.RemoveObserver(*this);  
       
   271 	CompleteOurself();
       
   272     }
       
   273 
       
   274 void CVPbkTopContactOperation::ContactViewUnavailable(
       
   275     MVPbkContactViewBase& aView )
       
   276     {
       
   277     aView.RemoveObserver(*this);
       
   278 	AbortWithError( KErrGeneral );
       
   279     }
       
   280 
       
   281 void CVPbkTopContactOperation::ContactAddedToView(
       
   282     MVPbkContactViewBase& /*aView*/, 
       
   283     TInt /*aIndex*/, 
       
   284     const MVPbkContactLink& /*aContactLink*/ )
       
   285     {
       
   286     }
       
   287 
       
   288 void CVPbkTopContactOperation::ContactRemovedFromView(
       
   289     MVPbkContactViewBase& /*aView*/, 
       
   290     TInt /*aIndex*/, 
       
   291     const MVPbkContactLink& /*aContactLink*/ )
       
   292     {
       
   293     }
       
   294 
       
   295 void CVPbkTopContactOperation::ContactViewError(
       
   296         MVPbkContactViewBase& /*aView*/, 
       
   297         TInt aError, 
       
   298         TBool /*aErrorNotified*/ )
       
   299     {
       
   300     AbortWithError( aError );
       
   301     }
       
   302 
       
   303 
       
   304 //---------------------------------------------------------------
       
   305 // These are from MVPbkContactStoreObserver
       
   306 
       
   307 void CVPbkTopContactOperation::StoreReady(MVPbkContactStore& /*aContactStore*/)
       
   308 	{
       
   309 	CompleteOurself();
       
   310 	}
       
   311 
       
   312 void CVPbkTopContactOperation::StoreUnavailable(
       
   313 	MVPbkContactStore& /*aContactStore*/, TInt aReason)
       
   314 	{
       
   315 	AbortWithError( aReason );
       
   316 	}
       
   317 
       
   318 void CVPbkTopContactOperation::HandleStoreEventL(
       
   319     MVPbkContactStore& /*aContactStore*/, 
       
   320     TVPbkContactStoreEvent /*aStoreEvent*/)
       
   321 	{
       
   322 	}
       
   323 
       
   324 //---------------------------------------------------------------
       
   325 // These are from MVPbkBatchOperationObserver
       
   326 
       
   327 void CVPbkTopContactOperation::StepComplete( 
       
   328     MVPbkContactOperationBase& /*aOperation*/,
       
   329     TInt /*aStepSize*/ )
       
   330     {
       
   331     // Ignore.
       
   332     }
       
   333 
       
   334 TBool CVPbkTopContactOperation::StepFailed(
       
   335     MVPbkContactOperationBase& /*aOperation*/,
       
   336     TInt /*aStepSize*/, TInt aError )
       
   337     {
       
   338     AbortWithError( aError );
       
   339     delete iContactOperation;
       
   340     iContactOperation = NULL;
       
   341     return EFalse; // do not continue
       
   342     }
       
   343 
       
   344 void CVPbkTopContactOperation::OperationComplete( 
       
   345     MVPbkContactOperationBase& /*aOperation*/ )
       
   346     {
       
   347     // Committing of contacts has completed.
       
   348     delete iContactOperation;
       
   349     iContactOperation = NULL;
       
   350     iContacts.ResetAndDestroy();
       
   351     //can leave only when returning links 
       
   352     TRAP_IGNORE(NotifyResultL());
       
   353     }
       
   354 
       
   355 //---------------------------------------------------------------
       
   356 // From MVPbkContactEasyManagerObserver
       
   357 void CVPbkTopContactOperation::VPbkOperationCompleted(
       
   358         MVPbkContactOperationBase* /*aOperation*/)
       
   359     {
       
   360 
       
   361     // Retrieving and locking of contacts is now complete.
       
   362     CompleteOurself();
       
   363     // Continue processing in RunL()
       
   364     }
       
   365 
       
   366 void CVPbkTopContactOperation::VPbkOperationFailed(
       
   367         MVPbkContactOperationBase* /*aOperation*/,
       
   368         TInt aError )
       
   369     {
       
   370     AbortWithError( aError );
       
   371     }
       
   372 
       
   373 // --------------------------------------------------------------------------
       
   374 // Creates contact link array from a contact view.
       
   375 // --------------------------------------------------------------------------
       
   376 MVPbkContactLinkArray* CVPbkTopContactOperation::ViewToLinkArrayL(
       
   377         const MVPbkContactViewBase& aView )
       
   378     {
       
   379     CVPbkContactLinkArray* links = CVPbkContactLinkArray::NewLC(); 
       
   380     TInt count = aView.ContactCountL();
       
   381     for ( TInt n = 0; n  < count; ++n )
       
   382         {
       
   383         MVPbkContactLink* link = aView.CreateLinkLC( n );
       
   384         links->AppendL( link );
       
   385         CleanupStack::Pop(); // link
       
   386         }
       
   387     CleanupStack::Pop( links );
       
   388     return links;
       
   389     }
       
   390 
       
   391 // --------------------------------------------------------------------------
       
   392 // Loads and opens contact store
       
   393 // --------------------------------------------------------------------------
       
   394 void CVPbkTopContactOperation::OpenStoreL( const TVPbkContactStoreUriPtr& aUri )
       
   395     {
       
   396     // First need to open the store.
       
   397     iContactManager.LoadContactStoreL( aUri );
       
   398 
       
   399     iContactStore = iContactManager.ContactStoresL().Find( aUri );
       
   400     // Asynchronous opening call.
       
   401     iContactStore->OpenL(*this);
       
   402     }
       
   403 
       
   404 // --------------------------------------------------------------------------
       
   405 // Loads and opens default contact store
       
   406 // --------------------------------------------------------------------------
       
   407 void CVPbkTopContactOperation::OpenDefaultStoreL()
       
   408     {
       
   409     TVPbkContactStoreUriPtr uri( KVPbkDefaultCntDbURI );
       
   410     OpenStoreL( uri );
       
   411 	}
       
   412 
       
   413 // --------------------------------------------------------------------------
       
   414 // Requests a top contact view. The completion is signalled to this
       
   415 // object through MVPbkContactViewObserver. The observer callback will pass
       
   416 // the event on in a certain way that is dependent on the current iState
       
   417 // value.
       
   418 // -------------------------------------------------------------------------- 
       
   419 void CVPbkTopContactOperation::RequestTopContactsViewL()
       
   420 	{
       
   421 	__ASSERT_DEBUG( !iView, Panic(ETopErrorAlreadyHaveAView) );
       
   422 	
       
   423     CVPbkContactViewDefinition* viewDef = CVPbkContactViewDefinition::NewLC();
       
   424     viewDef->SetUriL( KVPbkDefaultCntDbURI );
       
   425     
       
   426     CVPbkFieldTypeSelector* filter = CVPbkFieldTypeSelector::NewL(
       
   427         iContactManager.FieldTypes());
       
   428     CleanupStack::PushL(filter);         
       
   429     VPbkContactViewFilterBuilder::BuildContactViewFilterL( *filter, 
       
   430         TVPbkContactViewFilter(EVPbkContactViewFilterTopContact), iContactManager );
       
   431 
       
   432     viewDef->SetFieldTypeFilterL( filter ); 
       
   433     CleanupStack::PopAndDestroy( filter );  
       
   434 
       
   435     CVPbkSortOrderAcquirer* soa = AllContactsSortOrderL();
       
   436     CleanupStack::PushL(soa);
       
   437 
       
   438     iView = iContactManager.CreateContactViewLC(
       
   439         *this, *viewDef, soa->SortOrder() );
       
   440 
       
   441     CleanupStack::Pop(); // iView
       
   442     CleanupStack::PopAndDestroy( soa );
       
   443     CleanupStack::PopAndDestroy( viewDef );
       
   444 	}
       
   445 
       
   446 // --------------------------------------------------------------------------
       
   447 // Requests a top contact view. The completion is signalled to this
       
   448 // object through MVPbkContactViewObserver. The observer callback will pass
       
   449 // the event on in a certain way that is dependent on the current iState
       
   450 // value.
       
   451 // --------------------------------------------------------------------------
       
   452 void CVPbkTopContactOperation::RequestNonTopContactsViewL()
       
   453 	{
       
   454 	__ASSERT_DEBUG( !iView, Panic(ETopErrorAlreadyHaveAView) );
       
   455 	
       
   456     CVPbkContactViewDefinition* viewDef = CVPbkContactViewDefinition::NewLC();
       
   457     viewDef->SetUriL( KVPbkDefaultCntDbURI );
       
   458     
       
   459     CVPbkSortOrderAcquirer* soa = AllContactsSortOrderL();
       
   460     CleanupStack::PushL(soa);
       
   461 
       
   462     // Add the Non-Top Contacts selector           
       
   463     // No filter (i.e. with a field x) is used
       
   464     // but a contact selector
       
   465     viewDef->SetContactSelector(this);   // ownership not transferred     
       
   466 
       
   467     iView = iContactManager.CreateContactViewLC(
       
   468         *this, *viewDef, soa->SortOrder() );
       
   469 
       
   470     CleanupStack::Pop(); // iView
       
   471     CleanupStack::PopAndDestroy( soa );
       
   472     CleanupStack::PopAndDestroy( viewDef );
       
   473 	}
       
   474 
       
   475 // --------------------------------------------------------------------------
       
   476 // The RunL handler for top operations.
       
   477 // --------------------------------------------------------------------------
       
   478 inline void CVPbkTopContactOperation::Top_RunL()
       
   479 	{
       
   480 	if ( iNextState == EStateOpenStore )
       
   481         {
       
   482         if ( iInputLinks->Count() > 0 )
       
   483             {
       
   484             // If the top view was not passed as a reference, we needed to construct
       
   485             // own instance for AddToTop operation to get next top index
       
   486             if ( iCurrentOperation == EAddToTop && !iViewRef )
       
   487                 {
       
   488                 iNextState = EStateCreateView;
       
   489                 }
       
   490             else
       
   491                 {
       
   492                 iNextState = EStateRetrieveLock;
       
   493                 }
       
   494             OpenStoreL( iInputLinks->At(0).ContactStore().StoreProperties().Uri() );
       
   495             }
       
   496         else
       
   497             {
       
   498             // Empty input array is ok do nothing
       
   499             // just signal completion right away
       
   500             iNextState = EStateNone;
       
   501             NotifyResultL();
       
   502             }
       
   503         }
       
   504 	else if ( iNextState == EStateCreateView )
       
   505 		{
       
   506 		iNextState = EStateRetrieveLock;
       
   507 		RequestTopContactsViewL();
       
   508 		// When view is ready, we come back to this function.
       
   509 		}
       
   510 	else if ( iNextState == EStateRetrieveLock )
       
   511 		{
       
   512         iNextState = EStateModifyCommit;
       
   513         iContactEasyManager->RetrieveAndLockContactsL(
       
   514             *iInputLinks, iContacts, *this, *this );
       
   515         // The contacts are placed into iContacts.
       
   516         // Completion is signalled to our callback, which
       
   517         // will complete ourself so we come back here to the next state.
       
   518 		}
       
   519     else if ( iNextState == EStateModifyCommit )
       
   520         {
       
   521         DoTopOperationL();
       
   522         
       
   523         iNextState = EStateNone;
       
   524         iContactOperation = iContactManager.CommitContactsL(
       
   525             iContacts.Array(), *this );
       
   526         // Completion is signalled to our callback, where our observer is
       
   527         // called for informing that everything is done.
       
   528         }
       
   529 	}
       
   530 
       
   531 // --------------------------------------------------------------------------
       
   532 // Perform actual contact modification, add, remove or change toppnes
       
   533 // depending on the operation
       
   534 // --------------------------------------------------------------------------
       
   535 inline void CVPbkTopContactOperation::DoTopOperationL()
       
   536     {
       
   537     switch( iCurrentOperation )
       
   538         {
       
   539         case EAddToTop:
       
   540             {
       
   541             // Get next top index, either from the provided top view or
       
   542             // from the self contsructed one. Delete the owned view right away.
       
   543             __ASSERT_DEBUG( iView || iViewRef, Panic(ETopViewMissing) );
       
   544             TInt nextTopIndex =  iViewRef ? NextTopOrderIndexL( *iViewRef ) : 
       
   545                                             NextTopOrderIndexL( *iView );
       
   546             __ASSERT_DEBUG( nextTopIndex >= 0, Panic(ETopErrorBadIndex) );
       
   547             delete iView;
       
   548             iView = NULL;
       
   549 
       
   550             SetTopOrderToContactsL( iContacts, nextTopIndex );
       
   551             break;
       
   552             }
       
   553         case ERemoveFromTop:
       
   554             {
       
   555             RemoveTopnessFromContacts( iContacts );
       
   556             break;
       
   557             }
       
   558         case EReorderTop:
       
   559             {
       
   560             ReorderContactsL( iContacts );
       
   561             break;
       
   562             }
       
   563         default:
       
   564             __ASSERT_DEBUG( EFalse, Panic(ETopErrorWrongState) );
       
   565         }   
       
   566     }
       
   567 
       
   568 // --------------------------------------------------------------------------
       
   569 // The RunL handler for get view/links operation.
       
   570 // --------------------------------------------------------------------------
       
   571 inline void CVPbkTopContactOperation::GetView_RunL()
       
   572 	{
       
   573 	if ( iNextState == EStateOpenStore )
       
   574         {
       
   575         iNextState = EStateCreateView;
       
   576         OpenDefaultStoreL();
       
   577         }
       
   578     else if ( iNextState == EStateCreateView )
       
   579 	    {
       
   580 	    iNextState = EStateNone;
       
   581 	    switch( iCurrentOperation )
       
   582 	        {
       
   583 	        case EGetTopContacts:
       
   584 	        case EGetTopContactLinks:
       
   585 	            {
       
   586 	            RequestTopContactsViewL();
       
   587 	            break;
       
   588 	            }
       
   589 	        case EGetNonTopContacts:
       
   590 	        case EGetNonTopContactLinks:
       
   591 	            {
       
   592 	            RequestNonTopContactsViewL();
       
   593 	            break;
       
   594 	            }
       
   595 	        default:
       
   596 	            __ASSERT_DEBUG( EFalse, Panic(ETopErrorWrongState) );
       
   597 	        } 	    
       
   598 	    }
       
   599 	else
       
   600 	    {
       
   601 	    __ASSERT_DEBUG( iNextState == EStateNone, Panic(ETopErrorWrongState) );
       
   602     	// The view is ready.
       
   603     	NotifyResultL();
       
   604 	    }
       
   605 	}
       
   606 
       
   607 // --------------------------------------------------------------------------
       
   608 // Finds out what is the top ordering index for new top contacts.
       
   609 // It looks at the collection of top contacts in iView which has been fetched
       
   610 // earlier.
       
   611 // @return The next top index, or KFirstTopOrderIndex if no valid data was found.
       
   612 // --------------------------------------------------------------------------
       
   613 TInt CVPbkTopContactOperation::NextTopOrderIndexL(
       
   614     const MVPbkContactViewBase& aView )
       
   615 	{
       
   616 	const TInt count = aView.ContactCountL();
       
   617 	TInt result = KFirstTopOrderIndex; // The default if no tops exist yet.
       
   618 	if ( count > 0 )
       
   619 		{
       
   620 		// Take the last contact.
       
   621 		const MVPbkViewContact& contact = aView.ContactAtL( count - 1 );
       
   622 		const TInt orderValue = TopOrder( contact );
       
   623 		// Check the validity of the stored value.
       
   624 		if ( orderValue >=  KFirstTopOrderIndex && orderValue < KMaxTInt )
       
   625 		    {
       
   626 		    // Yes the value is OK.
       
   627 		    // Offset of one from existing last top contact.
       
   628 		    result = orderValue + 1;
       
   629 		    }
       
   630 		}
       
   631 	return result;
       
   632 	}
       
   633 
       
   634 // --------------------------------------------------------------------------
       
   635 // Completes this active object.
       
   636 // --------------------------------------------------------------------------
       
   637 void CVPbkTopContactOperation::CompleteOurself()
       
   638 	{
       
   639 	if ( !IsActive() )
       
   640 		{
       
   641 		TRequestStatus* status = &iStatus;
       
   642 	    User::RequestComplete( status, KErrNone );
       
   643 	    SetActive();
       
   644 		}
       
   645 	else
       
   646 		{
       
   647 		__ASSERT_DEBUG( EFalse, Panic(ETopErrorWrongLogic3) );
       
   648 		}
       
   649 	}
       
   650 
       
   651 // --------------------------------------------------------------------------
       
   652 // Clone contact link array, used to copy input link array
       
   653 // --------------------------------------------------------------------------
       
   654 CVPbkContactLinkArray* CVPbkTopContactOperation::CloneArrayL(
       
   655 	const MVPbkContactLinkArray& aArray )
       
   656 	{
       
   657 	CVPbkContactLinkArray* newArray = CVPbkContactLinkArray::NewLC();
       
   658 	const TInt count = aArray.Count();
       
   659 	for ( TInt n = 0; n < count; ++n )
       
   660 		{
       
   661         MVPbkContactLink* link = aArray.At(n).CloneLC();
       
   662         newArray->AppendL( link );
       
   663         CleanupStack::Pop(); // link
       
   664 		}
       
   665 	CleanupStack::Pop( newArray );
       
   666 	return newArray;
       
   667 	}
       
   668 
       
   669 // --------------------------------------------------------------------------
       
   670 // Sets the top contact data to the contacts.
       
   671 // Does not commit the contacts.
       
   672 // The contacts might already have some top data. If not then
       
   673 // the data holder is created.
       
   674 // @param aContacts The contacts to be modified.
       
   675 // @param aHighestOrderIndex The value from which ordering starts. The order
       
   676 // value increases in steps of one.
       
   677 // --------------------------------------------------------------------------
       
   678 void CVPbkTopContactOperation::SetTopOrderToContactsL(
       
   679     RPointerArray<MVPbkStoreContact>& aContacts,
       
   680     TInt aHighestOrderIndex )
       
   681     {
       
   682     TInt topOrderIndex = aHighestOrderIndex; 
       
   683     const TInt count = aContacts.Count();
       
   684     for ( TInt n = 0; n < count; ++ n )
       
   685         {
       
   686         MVPbkStoreContact& contact = *aContacts[ n ];
       
   687         SetTopOrderL( contact, topOrderIndex );
       
   688         ++topOrderIndex;
       
   689         }
       
   690     }
       
   691 
       
   692 // --------------------------------------------------------------------------
       
   693 // Remove "top" field from contacts
       
   694 // --------------------------------------------------------------------------
       
   695 void CVPbkTopContactOperation::RemoveTopnessFromContacts(
       
   696     RPointerArray<MVPbkStoreContact>& aContacts )
       
   697     {
       
   698     const TInt count = aContacts.Count();
       
   699     for ( TInt n = 0; n < count; ++ n )
       
   700         {
       
   701         MVPbkStoreContact& contact = *aContacts[ n ];
       
   702         RemoveTopnessFromContact( contact );
       
   703         }
       
   704     }
       
   705 
       
   706 // --------------------------------------------------------------------------
       
   707 // Find and remove the "top" field from a contact
       
   708 // --------------------------------------------------------------------------
       
   709 void CVPbkTopContactOperation::RemoveTopnessFromContact(
       
   710     MVPbkStoreContact& aContact )
       
   711     {
       
   712     MVPbkStoreContactFieldCollection& fields = aContact.Fields();
       
   713     const TInt count = fields.FieldCount();
       
   714     for ( TInt n = 0; n < count; ++n )
       
   715         {
       
   716         TVPbkFieldVersitProperty versitProp;
       
   717         versitProp.SetName(EVPbkVersitNameTopContact);
       
   718         const MVPbkFieldType* fieldType = fields.FieldAt(n).BestMatchingFieldType();
       
   719         if ( fieldType && fieldType->Matches(versitProp, 0) )
       
   720             {
       
   721             aContact.RemoveField( n );
       
   722             break;
       
   723             }
       
   724         }
       
   725     }
       
   726 
       
   727 // --------------------------------------------------------------------------
       
   728 // Change contacts "top" field according to their relative order
       
   729 // in the input array. Reuses top values the contacts
       
   730 // --------------------------------------------------------------------------
       
   731 void CVPbkTopContactOperation::ReorderContactsL(
       
   732     RPointerArray<MVPbkStoreContact>& aContacts )
       
   733     {
       
   734     const TInt count = aContacts.Count();
       
   735     RArray<TInt> topOrders;
       
   736     RPointerArray<MVPbkStoreContact> contactsToBeReordered; // does not own
       
   737     CleanupClosePushL(topOrders);
       
   738     CleanupClosePushL(contactsToBeReordered);
       
   739     
       
   740     for ( TInt n = 0; n < count; ++n )
       
   741         {
       
   742         const MVPbkStoreContact& contact = *aContacts[ n ];
       
   743         const TInt topOrder = TopOrder( contact );
       
   744         if ( topOrder >= 0 )
       
   745             {
       
   746             // Yes it is a top contact.
       
   747             User::LeaveIfError( contactsToBeReordered.Append( &contact ) );
       
   748             topOrders.AppendL( topOrder );
       
   749             }
       
   750         }
       
   751     topOrders.Sort();
       
   752 
       
   753     // Now set the order values. Reuse the old order values, but assign them
       
   754     // now to different contacts.
       
   755     const TInt reorderCount = topOrders.Count();
       
   756     for ( TInt i = 0; i < reorderCount; ++i )
       
   757         {
       
   758         MVPbkStoreContact& contact = *contactsToBeReordered[ i ];
       
   759         SetTopOrderL( contact, topOrders[ i ] );
       
   760         }
       
   761     CleanupStack::PopAndDestroy(); //contactsToBeReordered
       
   762     CleanupStack::PopAndDestroy(); // topOrders
       
   763     }
       
   764 
       
   765 // --------------------------------------------------------------------------
       
   766 // Returns field type for the top field type
       
   767 // --------------------------------------------------------------------------
       
   768 const MVPbkFieldType& CVPbkTopContactOperation::TopContactFieldTypeL()
       
   769     {
       
   770     const MVPbkFieldType* fieldType;
       
   771     TVPbkFieldTypeMapping mapping;
       
   772     TVPbkFieldVersitProperty versitProp;
       
   773     versitProp.SetName(EVPbkVersitNameTopContact);
       
   774     mapping.SetVersitProperty(versitProp);
       
   775     fieldType = mapping.FindMatch(iContactManager.FieldTypes());
       
   776     if (!fieldType)
       
   777         {
       
   778         User::Leave(KErrNotFound);
       
   779         }
       
   780     return *fieldType;
       
   781     }
       
   782 
       
   783 
       
   784 // --------------------------------------------------------------------------
       
   785 // Gives the top contact order value.
       
   786 // If there is no valid Top Contact order value, then returns
       
   787 // KErrNotFound.
       
   788 //
       
   789 // @param aTopContact The top contact.
       
   790 // @return Order value, or KErrNotFound if there is no
       
   791 //         Top Contact data.
       
   792 // --------------------------------------------------------------------------
       
   793 TInt CVPbkTopContactOperation::TopOrder( const MVPbkBaseContact& aContact )
       
   794     {
       
   795     const MVPbkContactFieldTextData* textData = FindTopFieldTextData( aContact );
       
   796     TInt result = KErrNotFound;
       
   797     if ( textData )
       
   798         {
       
   799         TPtrC text(textData->Text());
       
   800         const TBool isEmpty = textData->IsEmpty();
       
   801         TLex lexer(text);
       
   802         
       
   803         if ( !isEmpty )
       
   804             {
       
   805             TInt topOrder;
       
   806             if(!lexer.Val(topOrder))
       
   807 	            {
       
   808 	             result=topOrder;	
       
   809 	            }
       
   810             }
       
   811         }          
       
   812     return result;
       
   813     }
       
   814 
       
   815 // --------------------------------------------------------------------------
       
   816 // From MVPbkContactSelector
       
   817 // --------------------------------------------------------------------------
       
   818 TBool CVPbkTopContactOperation::IsContactIncluded( const MVPbkBaseContact& aContact )
       
   819     {
       
   820     return (TopOrder(aContact) == KErrNotFound);
       
   821     }
       
   822 
       
   823 // --------------------------------------------------------------------------
       
   824 // Saves top index to the contact field
       
   825 // --------------------------------------------------------------------------
       
   826 void CVPbkTopContactOperation::SetTopOrderL(
       
   827     MVPbkContactFieldTextData& aTextData, TInt aTopOrderIndex )
       
   828     {
       
   829     TBuf<KTcFieldLength> text;
       
   830     text.NumFixedWidth(aTopOrderIndex, EDecimal, KTcFieldLength);
       
   831     aTextData.SetTextL( text );
       
   832     }
       
   833 
       
   834 // --------------------------------------------------------------------------
       
   835 // Adds given top index to a store contact
       
   836 // --------------------------------------------------------------------------
       
   837 void CVPbkTopContactOperation::SetTopOrderL(
       
   838     MVPbkStoreContact& aContact, TInt aTopOrderIndex )
       
   839     {
       
   840     MVPbkContactFieldTextData* textData = FindTopFieldTextData( aContact );
       
   841     if ( textData )
       
   842         {
       
   843         // The field already exists
       
   844         SetTopOrderL( *textData, aTopOrderIndex );
       
   845         }
       
   846     else
       
   847         {
       
   848         // Need to create the field.
       
   849         MVPbkStoreContactField* field = aContact.CreateFieldLC(
       
   850             TopContactFieldTypeL() );        
       
   851         MVPbkContactFieldTextData& fieldData = 
       
   852             MVPbkContactFieldTextData::Cast( field->FieldData() );        
       
   853         SetTopOrderL( fieldData, aTopOrderIndex );
       
   854         // Add VPbk Field to the contact
       
   855         aContact.AddFieldL(field);                    
       
   856         CleanupStack::Pop(); // field
       
   857         }    
       
   858     }
       
   859 
       
   860 // --------------------------------------------------------------------------
       
   861 // Retruns top field text data of a view contact
       
   862 // or NULL if aContact doesn't have top field
       
   863 // --------------------------------------------------------------------------
       
   864 const MVPbkContactFieldTextData* CVPbkTopContactOperation::FindTopFieldTextData(
       
   865     const MVPbkBaseContact& aContact )
       
   866     {
       
   867     // Loop through all VPbk fields in the contact 
       
   868     // check if a field contains top contact type.
       
   869     const MVPbkBaseContactFieldCollection& fields = aContact.Fields();
       
   870     const TInt count = fields.FieldCount();
       
   871     const MVPbkContactFieldTextData* result = NULL;
       
   872     for ( TUint i = 0; i < count && !result; ++i )
       
   873         {
       
   874         const MVPbkBaseContactField& field = fields.FieldAt(i);
       
   875         TVPbkFieldVersitProperty versitProp;
       
   876         versitProp.SetName(EVPbkVersitNameTopContact);
       
   877         const MVPbkFieldType* fieldType = field.BestMatchingFieldType();
       
   878         if ( fieldType && fieldType->Matches(versitProp, 0) )
       
   879             {
       
   880             // Contact Template has Top Contact Field, therefore
       
   881             // a newly created contact will have an empty TC field
       
   882             // So, remember to make an additional check to see if the field
       
   883             // has data or not by calling IsEmpty().
       
   884             result = &MVPbkContactFieldTextData::Cast( field.FieldData() );        
       
   885             }                   
       
   886         }
       
   887     return result;
       
   888     }
       
   889 
       
   890 // --------------------------------------------------------------------------
       
   891 // Retruns top field text data of a store contact
       
   892 // or NULL if aContact doesn't have top field
       
   893 // --------------------------------------------------------------------------
       
   894 MVPbkContactFieldTextData* CVPbkTopContactOperation::FindTopFieldTextData(
       
   895     MVPbkStoreContact& aContact )
       
   896     {
       
   897     // Loop through all VPbk fields in the contact 
       
   898     // check if a field contains top contact type.
       
   899     MVPbkStoreContactFieldCollection& fields = aContact.Fields();
       
   900     const TInt count = fields.FieldCount();
       
   901     MVPbkContactFieldTextData* result = NULL;
       
   902     for ( TUint i = 0; i < count && !result; ++i )
       
   903         {
       
   904         MVPbkStoreContactField& field = fields.FieldAt(i);
       
   905         TVPbkFieldVersitProperty versitProp;
       
   906         versitProp.SetName(EVPbkVersitNameTopContact);
       
   907         const MVPbkFieldType* fieldType = field.BestMatchingFieldType();
       
   908         if ( fieldType && fieldType->Matches(versitProp, 0) )
       
   909             {
       
   910             // Contact Template has Top Contact Field, therefore
       
   911             // a newly created contact will have an empty TC field
       
   912             // So, remember to make an additional check to see if the field
       
   913             // has data or not by calling IsEmpty().
       
   914             result = &MVPbkContactFieldTextData::Cast( field.FieldData() );        
       
   915             }                   
       
   916         }
       
   917     return result;
       
   918     }
       
   919 
       
   920 // --------------------------------------------------------------------------
       
   921 // Notifies operation observer of results
       
   922 // --------------------------------------------------------------------------
       
   923 void CVPbkTopContactOperation::NotifyResultL()
       
   924     {
       
   925     switch( iCurrentOperation )
       
   926         {
       
   927         case EGetTopContacts:
       
   928         case EGetNonTopContacts:
       
   929             {
       
   930             __ASSERT_DEBUG( iView, Panic(ETopErrorNoView) );
       
   931             MVPbkContactViewBase* view = iView;
       
   932             iView = NULL; //transfer ownership
       
   933             iViewObserver->VPbkOperationResultCompleted( this, view );
       
   934             break;
       
   935             }
       
   936         case EGetTopContactLinks:
       
   937         case EGetNonTopContactLinks:
       
   938             {
       
   939             __ASSERT_DEBUG( iView, Panic(ETopErrorNoView) );
       
   940             MVPbkContactLinkArray* links = ViewToLinkArrayL( *iView );
       
   941             iLinksObserver->VPbkOperationResultCompleted( this, links );
       
   942             break;
       
   943             }
       
   944         case EAddToTop:
       
   945         case ERemoveFromTop:
       
   946         case EReorderTop:
       
   947             {
       
   948             iObserver->VPbkOperationCompleted( this );
       
   949             break;
       
   950             }
       
   951         default:
       
   952             __ASSERT_DEBUG( EFalse, Panic(ETopErrorWrongState) );
       
   953         }
       
   954     }
       
   955 
       
   956 // --------------------------------------------------------------------------
       
   957 // Sends error notification to the error observer
       
   958 // --------------------------------------------------------------------------
       
   959 inline void CVPbkTopContactOperation::NotifyError(TInt aErr)
       
   960     {
       
   961     iErrorObserver->VPbkOperationFailed( this, aErr );
       
   962     }
       
   963 
       
   964 // --------------------------------------------------------------------------
       
   965 // Notify error async
       
   966 // --------------------------------------------------------------------------
       
   967 void CVPbkTopContactOperation::AbortWithError(TInt aErr)
       
   968     {
       
   969     iAbortError = aErr;
       
   970     iNextState = EStateAbortWithError;
       
   971     CompleteOurself();
       
   972     }
       
   973 
       
   974 // --------------------------------------------------------------------------
       
   975 // Aquire sort order from presentation layer
       
   976 // --------------------------------------------------------------------------
       
   977 CVPbkSortOrderAcquirer* CVPbkTopContactOperation::AllContactsSortOrderL() const
       
   978     {
       
   979     CVPbkSortOrderAcquirer* result = NULL;
       
   980     // Acquire group sort order
       
   981     RImplInfoPtrArray implementations;
       
   982     REComSession::ListImplementationsL
       
   983         ( TUid::Uid( KVPbkSortOrderAcquirerInterfaceUID ), implementations );
       
   984     CleanupStack::PushL( TCleanupItem
       
   985             ( CleanupResetAndDestroy, &implementations ) );
       
   986 
       
   987     TBool found = EFalse;
       
   988     const TInt count = implementations.Count();
       
   989     for ( TInt i = count - 1; i >= 0 && !found ; --i )
       
   990         {
       
   991         CImplementationInformation* implInfo = implementations[i];
       
   992 
       
   993         if ( implInfo->DisplayName().
       
   994                 CompareC( KAllContactsSortOrderDisplayName ) == 0 )
       
   995             {
       
   996             TUid implUid = implInfo->ImplementationUid();
       
   997 
       
   998             CVPbkSortOrderAcquirer::TSortOrderAcquirerParam param
       
   999                 ( iContactManager.FieldTypes() );
       
  1000 
       
  1001             result = CVPbkSortOrderAcquirer::NewL
       
  1002                 ( implUid, param );
       
  1003             found = ETrue;
       
  1004             }
       
  1005         }
       
  1006     CleanupStack::PopAndDestroy(); // implementations
       
  1007     return result;
       
  1008     }
       
  1009 
       
  1010 // end of file