phonebookengines/VirtualPhonebook/VPbkCntModel/src/CFindView.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkCntModel/src/CFindView.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,386 @@
+/*
+* Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Contacts Model store filtered contact view implementation.
+*
+*/
+
+
+// INCLUDES
+#include "CFindView.h"
+
+// VPbkCntModel
+#include "CRefineView.h"
+#include "CViewBase.h"
+#include "CContactBookmark.h"
+#include "CContactStore.h"
+
+// From Virtual Phonebook
+#include <CVPbkContactNameConstructionPolicy.h>
+#include <CVPbkContactFindPolicy.h>
+#include <MVPbkContactBookmarkCollection.h>
+
+// System includes
+#include <cntdef.h>
+
+// Debugging headers
+#include <VPbkProfile.h>
+
+namespace VPbkCntModel {
+
+// --------------------------------------------------------------------------
+// CFindView::CFindView
+// --------------------------------------------------------------------------
+//
+inline CFindView::CFindView( CViewBase& aBaseView )
+    :   CFindViewBase( aBaseView, aBaseView, ETrue )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::ConstructL
+// --------------------------------------------------------------------------
+//
+void CFindView::ConstructL( const MDesCArray& aFindStrings,
+        const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts,
+        MVPbkContactViewObserver& aExternalViewObserver, RFs& aRFs )
+    {
+    CVPbkContactFindPolicy::TParam findPolicyParams(
+        iBaseView.Store().MasterFieldTypeList(), aRFs );
+    iFindPolicy = CVPbkContactFindPolicy::NewL( findPolicyParams );
+    BaseConstructL( aFindStrings, *iFindPolicy,
+        aExternalViewObserver );
+    SetAlwaysIncludedContactsL( aAlwaysIncludedContacts );
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::NewLC
+// --------------------------------------------------------------------------
+//
+CFindView* CFindView::NewLC(
+        const MDesCArray& aFindStrings,
+        CViewBase& aParentView,
+        MVPbkContactViewObserver& aExternalViewObserver,
+        const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts,
+        RFs& aRFs )
+    {
+    CFindView* self =
+        new ( ELeave ) CFindView( aParentView );
+    CleanupStack::PushL( self );
+    self->ConstructL( aFindStrings, aAlwaysIncludedContacts,
+        aExternalViewObserver, aRFs );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::~CFindView
+// --------------------------------------------------------------------------
+//
+CFindView::~CFindView()
+    {
+    delete iFindPolicy;
+    iAlwaysIncluded.Close();
+    iContactsModelMatchContacts.ResetAndDestroy();
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::SetAlwaysIncludedContactsL
+// --------------------------------------------------------------------------
+//
+void CFindView::SetAlwaysIncludedContactsL(
+        const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts )
+    {
+    // Destroy old ids
+    iAlwaysIncluded.Reset();
+
+    if ( aAlwaysIncludedContacts )
+        {
+        MVPbkContactStore& store = ParentObject().ContactStore();
+        const TInt count = aAlwaysIncludedContacts->Count();
+        for ( TInt i = 0; i < count; ++i )
+            {
+            const CContactBookmark* bookmark =
+                dynamic_cast<const CContactBookmark*>(
+                    &aAlwaysIncludedContacts->At( i ) );
+            // If bookmark was from VPbkCntModel and if it's from same store
+            // as this view then it's added to array.
+            if ( bookmark &&
+                 &bookmark->ContactStore() == &store )
+                {
+                iAlwaysIncluded.AppendL( bookmark->ContactId() );
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::MatchL
+// --------------------------------------------------------------------------
+//
+void CFindView::MatchL(
+        RPointerArray<CCntModelViewContact>& aMatchedContacts )
+    {
+    CleanupClosePushL( aMatchedContacts );
+    iContactsModelMatchContacts.ResetAndDestroy();
+
+    VPBK_PROFILE_START(VPbkProfile::ECntModelFind);
+    // Get matches from Contacts Model
+    iBaseView.NativeView().ContactsMatchingPrefixL(
+        FindStrings(), iContactsModelMatchContacts );
+    VPBK_PROFILE_END(VPbkProfile::ECntModelFind);
+
+    if (iAlwaysIncluded.Count() == 0)
+        {
+        // No always included contacts. The match can be done using
+        // only the Contacts Model matched contacts.
+        CViewContact* viewContact = CViewContact::NewL( iBaseView, SortOrder() );
+        CleanupStack::PushL(viewContact);
+        const TInt count = iContactsModelMatchContacts.Count();
+        for (TInt i = 0; i < count; ++i)
+            {
+            viewContact->SetViewContact( *iContactsModelMatchContacts[i] );
+            if ( IsMatchL( *viewContact ) )
+                {
+                // Keep the order of the contacts same and move contact
+                // from iContactsModelMatchContacts to aMatchedContacts
+                aMatchedContacts.AppendL(iContactsModelMatchContacts[i]);
+                // Don't remove the contact to keep indexes correct.
+                // Set to NULL so that ResetAndDestroy doesn't crash in
+                // destructor
+                iContactsModelMatchContacts[i] = NULL;
+                }
+            }
+        CleanupStack::PopAndDestroy( viewContact );
+        }
+    else
+        {
+        // Sort the matched contacts again with the CCompareView::CompareFieldsL
+        // compare function. Mark sure the result of binary search is correct in
+        // function FindFromMatchArray().
+        // See defect ou1cimx1#333760 
+        // Title: "Adding contacts (add recipent) issue while creating new message"
+        // Root cause: When contact's first or last name contain blank spaces, 
+        // the comparison result may be different between CCompareView::CompareFieldsL
+        // and CntSortPlugin. e.g. "AB" and "A khan"
+        HeapSortL( iContactsModelMatchContacts );
+		
+        // Do it slowly by looping all the parent view contacts.
+        const TInt contactCount = iParentView.ContactCountL();
+        for ( TInt i = 0; i < contactCount; ++i )
+            {
+            // iParentView is always VPbkCntModel view and the contacts type
+            // is CViewContact
+            const CViewContact& candidate = static_cast<const CViewContact&>(
+                iParentView.ContactAtL( i ) );
+            MatchContactL( candidate, aMatchedContacts );
+            }
+        }
+
+    iContactsModelMatchContacts.ResetAndDestroy();
+    CleanupStack::Pop();
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::DoContactAddedToViewL
+// --------------------------------------------------------------------------
+//
+void CFindView::DoContactAddedToViewL( MVPbkContactViewBase& aView,
+        TInt aIndex, const MVPbkContactLink& /*aContactLink*/,
+        RPointerArray<CCntModelViewContact>& aMatchedContacts )
+    {
+    if ( &iParentView == &aView )
+        {
+        const CViewContact& viewContact = static_cast<const CViewContact&>(
+            iParentView.ContactAtL( aIndex ) );
+        if ( IsMatchL( viewContact ) )
+            {
+            CCntModelViewContact* cnt =
+                CCntModelViewContact::NewL( *viewContact.NativeContact() );
+            CleanupStack::PushL( cnt );
+            aMatchedContacts.InsertInOrderAllowRepeatsL( cnt,
+                TLinearOrder<CCntModelViewContact>(
+                    CCompareView::CompareFieldsL ) );
+            CleanupStack::Pop( cnt );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::UpdateFilterL
+// --------------------------------------------------------------------------
+//
+void CFindView::UpdateFilterL(
+        const MDesCArray& aFindWords,
+        const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts )
+    {
+    SetFindStringsL( aFindWords );
+    SetAlwaysIncludedContactsL( aAlwaysIncludedContacts );
+    ActivateContactMatchL();
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::MatchContactL
+// --------------------------------------------------------------------------
+//
+void CFindView::MatchContactL( const CViewContact& aViewContact,
+        RPointerArray<CCntModelViewContact>& aMatchedContacts )
+    {
+    CleanupResetAndDestroyPushL( aMatchedContacts );
+    // aContact matches if it's one of the always included contacts OR
+    // if it's one of Contacts Model matched contacts AND it also
+    // passes our own match.
+    TInt matchArrayIndex = KErrNotFound;
+    TBool matched = EFalse;
+    if ( IsContactAlwaysIncluded( aViewContact ) )
+        {
+        // Remove from match array to save memory
+        RemoveFromMatchArrayIfFound( aViewContact );
+        matched = ETrue;
+        }
+    else if ( IsContactsModelMatchL( aViewContact, matchArrayIndex ) )
+        {
+        // Remove from match array to save memory
+        delete iContactsModelMatchContacts[matchArrayIndex];
+        iContactsModelMatchContacts.Remove( matchArrayIndex );
+
+        if ( IsMatchL( aViewContact ) )
+            {
+            matched = ETrue;
+            }
+        }
+
+    if ( matched )
+        {
+        // Contact matched.
+        // CFindView owns its contacts so create a copy
+        CCntModelViewContact* cnt =
+            CCntModelViewContact::NewL( *aViewContact.NativeContact() );
+        CleanupStack::PushL( cnt );
+        aMatchedContacts.AppendL( cnt );
+        CleanupStack::Pop( cnt );
+        }
+    CleanupStack::Pop( &aMatchedContacts );
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::IsContactAlwaysIncluded
+// --------------------------------------------------------------------------
+//
+TBool CFindView::IsContactAlwaysIncluded(
+        const CViewContact& aContact ) const
+    {
+    return iAlwaysIncluded.Find( aContact.Id() ) != KErrNotFound;
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::IsContactsModelMatchL
+// --------------------------------------------------------------------------
+//
+TBool CFindView::IsContactsModelMatchL( const CViewContact& aContact,
+        TInt& aMatchArrayIndex ) const
+    {
+    // Contacts are in order in iContactsModelMatchContacts. Use binary
+    // search to check if aContact is can be found from the array.
+    aMatchArrayIndex = FindFromMatchArray( aContact );
+    return aMatchArrayIndex != KErrNotFound;
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::RemoveFromMatchArrayIfFound
+// --------------------------------------------------------------------------
+//
+void CFindView::RemoveFromMatchArrayIfFound( const CViewContact& aContact )
+    {
+    TInt index = FindFromMatchArray( aContact );
+    if ( index != KErrNotFound )
+        {
+        delete iContactsModelMatchContacts[index];
+        iContactsModelMatchContacts.Remove(index);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::FindFromMatchArray
+// --------------------------------------------------------------------------
+//
+TInt CFindView::FindFromMatchArray( const CViewContact& aContact ) const
+    {
+    return iContactsModelMatchContacts.FindInOrder(
+        aContact.NativeContact(),
+        TLinearOrder<CCntModelViewContact>( CCompareView::CompareFieldsL ) );
+    }
+
+/** 
+Heap sort the give view contacts array.
+
+This function only be called one time when some contacts be marked and we input
+the first letter to the FindBox for searching.
+
+@param  aContacts the array of view contacts to be sorted.
+@leave  leave errors from CCompareView::CompareFieldsL
+*/
+void CFindView::HeapSortL(RPointerArray<CCntModelViewContact> aContacts)
+    {
+    // HeapSort (copied from RPointerArrayBase)
+    TInt ss = aContacts.Count();
+    if ( ss>1 )
+        {
+        TInt sh = ss>>1;
+        FOREVER
+            {
+            CCntModelViewContact* si;
+            if (sh != 0)
+                {
+                // make heap
+                --sh;
+                si = aContacts[sh];
+                }
+            else
+                {
+                // sort heap
+                --ss;
+                si = aContacts[ss];
+                aContacts[ss] = aContacts[0];
+                if (ss == 1)
+                    {
+                    aContacts[0] = si;
+                    break;
+                    }
+                }
+
+            // sift down
+            TInt ii = sh;
+            TInt jj = sh;
+            FOREVER
+                {
+                jj = (jj+1)<<1;
+                if ((jj >= ss) || (CCompareView::CompareFieldsL(*(aContacts[jj-1]),*(aContacts[jj])) > 0))
+                    {
+                    --jj;
+                    }
+					
+                if ((jj >= ss) || (CCompareView::CompareFieldsL(*(aContacts[jj]),*si) <= 0))
+                    {
+                    break;
+                    }
+					
+                aContacts[ii] = aContacts[jj];
+                ii = jj;
+                } //FOREVER
+				
+            aContacts[ii] = si;
+            } //FOREVER
+        } //if (ss > 1)
+    }
+} // namespace VPbkCntModel
+// End of File