phonebookengines/VirtualPhonebook/VPbkCntModel/src/CFindView.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
equal deleted inserted replaced
62:5b6f26637ad3 63:f4a778e096c2
       
     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:  Contacts Model store filtered contact view implementation.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDES
       
    20 #include "CFindView.h"
       
    21 
       
    22 // VPbkCntModel
       
    23 #include "CRefineView.h"
       
    24 #include "CViewBase.h"
       
    25 #include "CContactBookmark.h"
       
    26 #include "CContactStore.h"
       
    27 
       
    28 // From Virtual Phonebook
       
    29 #include <CVPbkContactNameConstructionPolicy.h>
       
    30 #include <CVPbkContactFindPolicy.h>
       
    31 #include <MVPbkContactBookmarkCollection.h>
       
    32 
       
    33 // System includes
       
    34 #include <cntdef.h>
       
    35 
       
    36 // Debugging headers
       
    37 #include <VPbkProfile.h>
       
    38 
       
    39 namespace VPbkCntModel {
       
    40 
       
    41 // --------------------------------------------------------------------------
       
    42 // CFindView::CFindView
       
    43 // --------------------------------------------------------------------------
       
    44 //
       
    45 inline CFindView::CFindView( CViewBase& aBaseView )
       
    46     :   CFindViewBase( aBaseView, aBaseView, ETrue )
       
    47     {
       
    48     }
       
    49 
       
    50 // --------------------------------------------------------------------------
       
    51 // CFindView::ConstructL
       
    52 // --------------------------------------------------------------------------
       
    53 //
       
    54 void CFindView::ConstructL( const MDesCArray& aFindStrings,
       
    55         const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts,
       
    56         MVPbkContactViewObserver& aExternalViewObserver, RFs& aRFs )
       
    57     {
       
    58     CVPbkContactFindPolicy::TParam findPolicyParams(
       
    59         iBaseView.Store().MasterFieldTypeList(), aRFs );
       
    60     iFindPolicy = CVPbkContactFindPolicy::NewL( findPolicyParams );
       
    61     BaseConstructL( aFindStrings, *iFindPolicy,
       
    62         aExternalViewObserver );
       
    63     SetAlwaysIncludedContactsL( aAlwaysIncludedContacts );
       
    64     }
       
    65 
       
    66 // --------------------------------------------------------------------------
       
    67 // CFindView::NewLC
       
    68 // --------------------------------------------------------------------------
       
    69 //
       
    70 CFindView* CFindView::NewLC(
       
    71         const MDesCArray& aFindStrings,
       
    72         CViewBase& aParentView,
       
    73         MVPbkContactViewObserver& aExternalViewObserver,
       
    74         const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts,
       
    75         RFs& aRFs )
       
    76     {
       
    77     CFindView* self =
       
    78         new ( ELeave ) CFindView( aParentView );
       
    79     CleanupStack::PushL( self );
       
    80     self->ConstructL( aFindStrings, aAlwaysIncludedContacts,
       
    81         aExternalViewObserver, aRFs );
       
    82     return self;
       
    83     }
       
    84 
       
    85 // --------------------------------------------------------------------------
       
    86 // CFindView::~CFindView
       
    87 // --------------------------------------------------------------------------
       
    88 //
       
    89 CFindView::~CFindView()
       
    90     {
       
    91     delete iFindPolicy;
       
    92     iAlwaysIncluded.Close();
       
    93     iContactsModelMatchContacts.ResetAndDestroy();
       
    94     }
       
    95 
       
    96 // --------------------------------------------------------------------------
       
    97 // CFindView::SetAlwaysIncludedContactsL
       
    98 // --------------------------------------------------------------------------
       
    99 //
       
   100 void CFindView::SetAlwaysIncludedContactsL(
       
   101         const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts )
       
   102     {
       
   103     // Destroy old ids
       
   104     iAlwaysIncluded.Reset();
       
   105 
       
   106     if ( aAlwaysIncludedContacts )
       
   107         {
       
   108         MVPbkContactStore& store = ParentObject().ContactStore();
       
   109         const TInt count = aAlwaysIncludedContacts->Count();
       
   110         for ( TInt i = 0; i < count; ++i )
       
   111             {
       
   112             const CContactBookmark* bookmark =
       
   113                 dynamic_cast<const CContactBookmark*>(
       
   114                     &aAlwaysIncludedContacts->At( i ) );
       
   115             // If bookmark was from VPbkCntModel and if it's from same store
       
   116             // as this view then it's added to array.
       
   117             if ( bookmark &&
       
   118                  &bookmark->ContactStore() == &store )
       
   119                 {
       
   120                 iAlwaysIncluded.AppendL( bookmark->ContactId() );
       
   121                 }
       
   122             }
       
   123         }
       
   124     }
       
   125 
       
   126 // --------------------------------------------------------------------------
       
   127 // CFindView::MatchL
       
   128 // --------------------------------------------------------------------------
       
   129 //
       
   130 void CFindView::MatchL(
       
   131         RPointerArray<CCntModelViewContact>& aMatchedContacts )
       
   132     {
       
   133     CleanupClosePushL( aMatchedContacts );
       
   134     iContactsModelMatchContacts.ResetAndDestroy();
       
   135 
       
   136     VPBK_PROFILE_START(VPbkProfile::ECntModelFind);
       
   137     // Get matches from Contacts Model
       
   138     iBaseView.NativeView().ContactsMatchingPrefixL(
       
   139         FindStrings(), iContactsModelMatchContacts );
       
   140     VPBK_PROFILE_END(VPbkProfile::ECntModelFind);
       
   141 
       
   142     if (iAlwaysIncluded.Count() == 0)
       
   143         {
       
   144         // No always included contacts. The match can be done using
       
   145         // only the Contacts Model matched contacts.
       
   146         CViewContact* viewContact = CViewContact::NewL( iBaseView, SortOrder() );
       
   147         CleanupStack::PushL(viewContact);
       
   148         const TInt count = iContactsModelMatchContacts.Count();
       
   149         for (TInt i = 0; i < count; ++i)
       
   150             {
       
   151             viewContact->SetViewContact( *iContactsModelMatchContacts[i] );
       
   152             if ( IsMatchL( *viewContact ) )
       
   153                 {
       
   154                 // Keep the order of the contacts same and move contact
       
   155                 // from iContactsModelMatchContacts to aMatchedContacts
       
   156                 aMatchedContacts.AppendL(iContactsModelMatchContacts[i]);
       
   157                 // Don't remove the contact to keep indexes correct.
       
   158                 // Set to NULL so that ResetAndDestroy doesn't crash in
       
   159                 // destructor
       
   160                 iContactsModelMatchContacts[i] = NULL;
       
   161                 }
       
   162             }
       
   163         CleanupStack::PopAndDestroy( viewContact );
       
   164         }
       
   165     else
       
   166         {
       
   167         // Sort the matched contacts again with the CCompareView::CompareFieldsL
       
   168         // compare function. Mark sure the result of binary search is correct in
       
   169         // function FindFromMatchArray().
       
   170         // See defect ou1cimx1#333760 
       
   171         // Title: "Adding contacts (add recipent) issue while creating new message"
       
   172         // Root cause: When contact's first or last name contain blank spaces, 
       
   173         // the comparison result may be different between CCompareView::CompareFieldsL
       
   174         // and CntSortPlugin. e.g. "AB" and "A khan"
       
   175         HeapSortL( iContactsModelMatchContacts );
       
   176 		
       
   177         // Do it slowly by looping all the parent view contacts.
       
   178         const TInt contactCount = iParentView.ContactCountL();
       
   179         for ( TInt i = 0; i < contactCount; ++i )
       
   180             {
       
   181             // iParentView is always VPbkCntModel view and the contacts type
       
   182             // is CViewContact
       
   183             const CViewContact& candidate = static_cast<const CViewContact&>(
       
   184                 iParentView.ContactAtL( i ) );
       
   185             MatchContactL( candidate, aMatchedContacts );
       
   186             }
       
   187         }
       
   188 
       
   189     iContactsModelMatchContacts.ResetAndDestroy();
       
   190     CleanupStack::Pop();
       
   191     }
       
   192 
       
   193 // --------------------------------------------------------------------------
       
   194 // CFindView::DoContactAddedToViewL
       
   195 // --------------------------------------------------------------------------
       
   196 //
       
   197 void CFindView::DoContactAddedToViewL( MVPbkContactViewBase& aView,
       
   198         TInt aIndex, const MVPbkContactLink& /*aContactLink*/,
       
   199         RPointerArray<CCntModelViewContact>& aMatchedContacts )
       
   200     {
       
   201     if ( &iParentView == &aView )
       
   202         {
       
   203         const CViewContact& viewContact = static_cast<const CViewContact&>(
       
   204             iParentView.ContactAtL( aIndex ) );
       
   205         if ( IsMatchL( viewContact ) )
       
   206             {
       
   207             CCntModelViewContact* cnt =
       
   208                 CCntModelViewContact::NewL( *viewContact.NativeContact() );
       
   209             CleanupStack::PushL( cnt );
       
   210             aMatchedContacts.InsertInOrderAllowRepeatsL( cnt,
       
   211                 TLinearOrder<CCntModelViewContact>(
       
   212                     CCompareView::CompareFieldsL ) );
       
   213             CleanupStack::Pop( cnt );
       
   214             }
       
   215         }
       
   216     }
       
   217 
       
   218 // --------------------------------------------------------------------------
       
   219 // CFindView::UpdateFilterL
       
   220 // --------------------------------------------------------------------------
       
   221 //
       
   222 void CFindView::UpdateFilterL(
       
   223         const MDesCArray& aFindWords,
       
   224         const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts )
       
   225     {
       
   226     SetFindStringsL( aFindWords );
       
   227     SetAlwaysIncludedContactsL( aAlwaysIncludedContacts );
       
   228     ActivateContactMatchL();
       
   229     }
       
   230 
       
   231 // --------------------------------------------------------------------------
       
   232 // CFindView::MatchContactL
       
   233 // --------------------------------------------------------------------------
       
   234 //
       
   235 void CFindView::MatchContactL( const CViewContact& aViewContact,
       
   236         RPointerArray<CCntModelViewContact>& aMatchedContacts )
       
   237     {
       
   238     CleanupResetAndDestroyPushL( aMatchedContacts );
       
   239     // aContact matches if it's one of the always included contacts OR
       
   240     // if it's one of Contacts Model matched contacts AND it also
       
   241     // passes our own match.
       
   242     TInt matchArrayIndex = KErrNotFound;
       
   243     TBool matched = EFalse;
       
   244     if ( IsContactAlwaysIncluded( aViewContact ) )
       
   245         {
       
   246         // Remove from match array to save memory
       
   247         RemoveFromMatchArrayIfFound( aViewContact );
       
   248         matched = ETrue;
       
   249         }
       
   250     else if ( IsContactsModelMatchL( aViewContact, matchArrayIndex ) )
       
   251         {
       
   252         // Remove from match array to save memory
       
   253         delete iContactsModelMatchContacts[matchArrayIndex];
       
   254         iContactsModelMatchContacts.Remove( matchArrayIndex );
       
   255 
       
   256         if ( IsMatchL( aViewContact ) )
       
   257             {
       
   258             matched = ETrue;
       
   259             }
       
   260         }
       
   261 
       
   262     if ( matched )
       
   263         {
       
   264         // Contact matched.
       
   265         // CFindView owns its contacts so create a copy
       
   266         CCntModelViewContact* cnt =
       
   267             CCntModelViewContact::NewL( *aViewContact.NativeContact() );
       
   268         CleanupStack::PushL( cnt );
       
   269         aMatchedContacts.AppendL( cnt );
       
   270         CleanupStack::Pop( cnt );
       
   271         }
       
   272     CleanupStack::Pop( &aMatchedContacts );
       
   273     }
       
   274 
       
   275 // --------------------------------------------------------------------------
       
   276 // CFindView::IsContactAlwaysIncluded
       
   277 // --------------------------------------------------------------------------
       
   278 //
       
   279 TBool CFindView::IsContactAlwaysIncluded(
       
   280         const CViewContact& aContact ) const
       
   281     {
       
   282     return iAlwaysIncluded.Find( aContact.Id() ) != KErrNotFound;
       
   283     }
       
   284 
       
   285 // --------------------------------------------------------------------------
       
   286 // CFindView::IsContactsModelMatchL
       
   287 // --------------------------------------------------------------------------
       
   288 //
       
   289 TBool CFindView::IsContactsModelMatchL( const CViewContact& aContact,
       
   290         TInt& aMatchArrayIndex ) const
       
   291     {
       
   292     // Contacts are in order in iContactsModelMatchContacts. Use binary
       
   293     // search to check if aContact is can be found from the array.
       
   294     aMatchArrayIndex = FindFromMatchArray( aContact );
       
   295     return aMatchArrayIndex != KErrNotFound;
       
   296     }
       
   297 
       
   298 // --------------------------------------------------------------------------
       
   299 // CFindView::RemoveFromMatchArrayIfFound
       
   300 // --------------------------------------------------------------------------
       
   301 //
       
   302 void CFindView::RemoveFromMatchArrayIfFound( const CViewContact& aContact )
       
   303     {
       
   304     TInt index = FindFromMatchArray( aContact );
       
   305     if ( index != KErrNotFound )
       
   306         {
       
   307         delete iContactsModelMatchContacts[index];
       
   308         iContactsModelMatchContacts.Remove(index);
       
   309         }
       
   310     }
       
   311 
       
   312 // --------------------------------------------------------------------------
       
   313 // CFindView::FindFromMatchArray
       
   314 // --------------------------------------------------------------------------
       
   315 //
       
   316 TInt CFindView::FindFromMatchArray( const CViewContact& aContact ) const
       
   317     {
       
   318     return iContactsModelMatchContacts.FindInOrder(
       
   319         aContact.NativeContact(),
       
   320         TLinearOrder<CCntModelViewContact>( CCompareView::CompareFieldsL ) );
       
   321     }
       
   322 
       
   323 /** 
       
   324 Heap sort the give view contacts array.
       
   325 
       
   326 This function only be called one time when some contacts be marked and we input
       
   327 the first letter to the FindBox for searching.
       
   328 
       
   329 @param  aContacts the array of view contacts to be sorted.
       
   330 @leave  leave errors from CCompareView::CompareFieldsL
       
   331 */
       
   332 void CFindView::HeapSortL(RPointerArray<CCntModelViewContact> aContacts)
       
   333     {
       
   334     // HeapSort (copied from RPointerArrayBase)
       
   335     TInt ss = aContacts.Count();
       
   336     if ( ss>1 )
       
   337         {
       
   338         TInt sh = ss>>1;
       
   339         FOREVER
       
   340             {
       
   341             CCntModelViewContact* si;
       
   342             if (sh != 0)
       
   343                 {
       
   344                 // make heap
       
   345                 --sh;
       
   346                 si = aContacts[sh];
       
   347                 }
       
   348             else
       
   349                 {
       
   350                 // sort heap
       
   351                 --ss;
       
   352                 si = aContacts[ss];
       
   353                 aContacts[ss] = aContacts[0];
       
   354                 if (ss == 1)
       
   355                     {
       
   356                     aContacts[0] = si;
       
   357                     break;
       
   358                     }
       
   359                 }
       
   360 
       
   361             // sift down
       
   362             TInt ii = sh;
       
   363             TInt jj = sh;
       
   364             FOREVER
       
   365                 {
       
   366                 jj = (jj+1)<<1;
       
   367                 if ((jj >= ss) || (CCompareView::CompareFieldsL(*(aContacts[jj-1]),*(aContacts[jj])) > 0))
       
   368                     {
       
   369                     --jj;
       
   370                     }
       
   371 					
       
   372                 if ((jj >= ss) || (CCompareView::CompareFieldsL(*(aContacts[jj]),*si) <= 0))
       
   373                     {
       
   374                     break;
       
   375                     }
       
   376 					
       
   377                 aContacts[ii] = aContacts[jj];
       
   378                 ii = jj;
       
   379                 } //FOREVER
       
   380 				
       
   381             aContacts[ii] = si;
       
   382             } //FOREVER
       
   383         } //if (ss > 1)
       
   384     }
       
   385 } // namespace VPbkCntModel
       
   386 // End of File