phonebookengines/VirtualPhonebook/VPbkSimStore/src/CFindView.cpp
changeset 0 e686773b3f54
child 32 2828b4d142c0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkSimStore/src/CFindView.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,484 @@
+/*
+* 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:  Sim store filtered contact view implementation.
+*
+*/
+
+
+#include "CFindView.h"
+
+// From VPbkSimStore
+#include "CContactStore.h"
+#include "CContactView.h"
+#include "CViewContact.h"
+#include "CContactLink.h"
+
+// VPbkEng
+#include <MVPbkSimStoreOperation.h>
+#include <MVPbkSimCntView.h>
+#include <CVPbkSimContact.h>
+#include <RVPbkStreamedIntArray.h>
+#include <MVPbkContactViewObserver.h>
+#include <MVPbkSimCntStore.h>
+#include <MVPbkContactLink.h>
+#include <CVPbkContactFindPolicy.h>
+#include <CVPbkContactNameConstructionPolicy.h>
+#include <CVPbkContactViewSortPolicy.h>
+#include <MVPbkContactBookmarkCollection.h>
+#include <RVPbkStreamedIntArray.h>
+
+// System includes
+#include <cntviewbase.h>
+#include <featmgr.h>
+
+// Debugging headers
+#include <VPbkProfile.h>
+#include <VPbkDebug.h>
+
+namespace VPbkSimStore {
+
+// --------------------------------------------------------------------------
+// CFindView::CFindView
+// --------------------------------------------------------------------------
+//
+inline CFindView::CFindView( CContactView& aAllContactsView ) :        
+        CFindViewBase( aAllContactsView, aAllContactsView, ETrue  )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::~CFindView
+// --------------------------------------------------------------------------
+//
+CFindView::~CFindView()
+    {
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStore:CFindView(%x)::~CFindView"), this );
+         
+    delete iFindOperation;
+    delete iFindPolicy;
+    iAlwaysIncluded.Close();
+    iSIMMatchedContacts.Close();
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::ConstructL
+// --------------------------------------------------------------------------
+//
+void CFindView::ConstructL( const MDesCArray& aFindStrings,
+        MVPbkContactViewObserver& aExternalViewObserver,
+        const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts,
+        RFs& aRFs )
+    {
+    CVPbkContactFindPolicy::TParam findPolicyParams(
+        iAllContactsView.Store().MasterFieldTypeList(), aRFs );
+    iFindPolicy = CVPbkContactFindPolicy::NewL( findPolicyParams );
+    BaseConstructL( aExternalViewObserver, aFindStrings, 
+        *iFindPolicy );
+    
+    SetAlwaysIncludedContactsL( aAlwaysIncludedContacts );
+    }
+    
+// --------------------------------------------------------------------------
+// CFindView::NewLC
+// --------------------------------------------------------------------------
+//
+CFindView* CFindView::NewLC(      
+        const MDesCArray& aFindStrings,
+        CContactView& aAllContactsView,
+        MVPbkContactViewObserver& aExternalViewObserver,
+        const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts,
+        RFs& aRFs )
+    {
+    CFindView* self = new ( ELeave ) CFindView( aAllContactsView );
+    CleanupStack::PushL( self );
+    self->ConstructL( aFindStrings, aExternalViewObserver,
+        aAlwaysIncludedContacts, aRFs );
+    CleanupStack::Check( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::SetAlwaysIncludedContactsL
+// --------------------------------------------------------------------------
+//    
+void CFindView::SetAlwaysIncludedContactsL( 
+        const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts )
+    {
+    iAlwaysIncluded.Reset();
+
+    if ( aAlwaysIncludedContacts )
+        {
+        MVPbkContactStore& store = ParentObject().ContactStore();
+        const TInt count = aAlwaysIncludedContacts->Count();
+        for ( TInt i = 0; i < count; ++i )
+            {
+            const CContactLink* bookmark =            
+                dynamic_cast<const CContactLink*>( 
+                    &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->SimIndex() );
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::ContactViewReady
+// --------------------------------------------------------------------------
+//    
+void CFindView::ContactViewReady( MVPbkContactViewBase& /*aView*/ )
+    {
+    // CFindView is only interested in ContactViewReadyForFiltering that
+    // will start an asynchronous native match.
+    }
+    
+// --------------------------------------------------------------------------
+// CFindView::ContactViewReadyForFiltering
+// --------------------------------------------------------------------------
+//    
+void CFindView::ContactViewReadyForFiltering(
+        MParentViewForFiltering& aView )
+    {
+    // Cancel existing match if aready active.
+    delete iFindOperation;
+    iFindOperation = NULL;
+    
+    // Parent view is ready. Start asynchronous find from native SIM view.
+    TRAPD( error,
+        {
+        iFindOperation = 
+            iAllContactsView.NativeView().ContactMatchingPrefixL(
+                FindStrings(), *this );
+        });
+    
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStore:CFindView(%x)::ContactViewReadyForFiltering:\
+        findOp(%x)"), this, iFindOperation ); 
+        
+    if ( error != KErrNone )
+        {
+        ContactViewError( aView, error, EFalse );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::MatchL
+// --------------------------------------------------------------------------
+//
+void CFindView::MatchL( RPointerArray<MVPbkSimContact>& aMatchedContacts )
+    {
+    if (iAlwaysIncluded.Count() == 0)
+        {
+        // No always included contacts. The match can be done using
+        // only the SIM view matched contacts.
+        CViewContact* viewContact = CViewContact::NewL( iAllContactsView, 
+            SortOrder() );
+        CleanupStack::PushL(viewContact);
+        MVPbkSimCntStore& simStore = iAllContactsView.Store().NativeStore();
+        const TInt count = iSIMMatchedContacts.Count();
+        for (TInt i = 0; i < count; ++i)
+            {
+            const TDesC8* cntBuf = simStore.AtL( iSIMMatchedContacts[i] );
+            if ( cntBuf )
+                {
+                CVPbkSimContact* cnt = 
+                    CVPbkSimContact::NewL( *cntBuf, simStore );
+                CleanupStack::PushL( cnt );
+                viewContact->SetSimContactL( *cnt );
+                if ( IsMatchL( *viewContact ) )
+                    {
+                    // Keep the order of the contacts same and move contact
+                    // from iContactsModelMatchContacts to aMatchedContacts
+                    aMatchedContacts.AppendL( cnt );
+                    CleanupStack::Pop( cnt );
+                    }
+                else
+                    {
+                    CleanupStack::PopAndDestroy( cnt );
+                    }
+                }
+            }   
+        CleanupStack::PopAndDestroy( viewContact );
+        }
+    else
+        {
+        // 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 );
+            }
+        }
+    
+    // Free the memory
+    iSIMMatchedContacts.Reset(); 
+    }
+        
+// --------------------------------------------------------------------------
+// CFindView::ViewFindCompleted
+// --------------------------------------------------------------------------
+//      
+void CFindView::ViewFindCompleted( 
+        MVPbkSimCntView& aSimCntView,
+        const RVPbkStreamedIntArray& aSimIndexArray )
+    {
+    TRAPD( error, ViewFindCompletedL( aSimCntView, aSimIndexArray ) );
+    VPBK_PROFILE_END(VPbkProfile::ESimStoreFind);    
+    
+    if ( error != KErrNone )
+        {
+        ContactViewError( *this, error, EFalse );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::ViewFindError
+// --------------------------------------------------------------------------
+//                  
+void CFindView::ViewFindError( 
+        MVPbkSimCntView& /*aSimCntView*/, 
+        TInt aError )
+    {
+    ContactViewError( *this, aError, EFalse );
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::UpdateFilterL
+// --------------------------------------------------------------------------
+//
+void CFindView::UpdateFilterL( 
+        const MDesCArray& aFindWords,
+        const MVPbkContactBookmarkCollection* aAlwaysIncludedContacts )
+    {
+    SetFindStringsL( aFindWords );
+    SetAlwaysIncludedContactsL( aAlwaysIncludedContacts );
+    ActivateContactMatchL();
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::IsNativeMatchingRequestActive
+// --------------------------------------------------------------------------
+//
+TBool CFindView::IsNativeMatchingRequestActive()
+    {
+    if ( iFindOperation )
+        {
+        return ETrue;
+        }
+    return EFalse;
+    }
+    
+// --------------------------------------------------------------------------
+// CFindView::IsContactAlwaysIncluded
+// --------------------------------------------------------------------------
+//
+TBool CFindView::IsContactAlwaysIncluded( const CViewContact& aContact ) const
+    {
+    return iAlwaysIncluded.Find( aContact.SimIndex() ) != KErrNotFound;
+    }
+    
+// --------------------------------------------------------------------------
+// CFindView::DoContactAddedToViewL
+// --------------------------------------------------------------------------
+//
+void CFindView::DoContactAddedToViewL(
+        MVPbkContactViewBase& aView, 
+        TInt aIndex, 
+        const MVPbkContactLink& /*aContactLink*/,
+        RPointerArray<MVPbkSimContact>& aMatchedContacts )
+    {
+    if ( &iParentView == &aView )
+        {
+        const CViewContact& viewContact = static_cast<const CViewContact&>(
+            iParentView.ContactAtL( aIndex ) );
+        if ( IsMatchL( viewContact ) )
+            {
+            MVPbkSimCntStore& simStore = 
+                iAllContactsView.Store().NativeStore();
+            const TDesC8* cntBuf = simStore.AtL( viewContact.SimIndex() );
+            if ( cntBuf )
+                {
+                CVPbkSimContact* cnt = 
+                    CVPbkSimContact::NewL( *cntBuf, simStore );
+                CleanupStack::PushL( cnt );
+                
+                // We have to insert the new contact to the correct
+                // location. VPbk sort policy is used for that.
+                CVPbkContactViewSortPolicy::TParam param(
+                    iAllContactsView.Store().MasterFieldTypeList(), SortOrder() );
+                CVPbkContactViewSortPolicy* sortPolicy = 
+                    CVPbkContactViewSortPolicy::NewL( param );
+                CleanupStack::PushL( sortPolicy );
+                sortPolicy->SortStartL();
+                CViewContact* current = 
+                    CViewContact::NewL( iAllContactsView, SortOrder() );
+                CleanupStack::PushL( current );
+                
+                const TInt count = aMatchedContacts.Count();
+                TInt index = KErrNotFound;
+                for ( TInt i = 0; i < count && index == KErrNotFound; ++i )
+                    {
+                    current->SetSimContactL( *aMatchedContacts[i] );
+                    TInt res = 
+                        sortPolicy->CompareContacts( viewContact, *current );
+                    // CompareContacts returns -1, 0 or 1.
+                    if ( res < 0 )
+                        {
+                        index = i;
+                        }
+                    }
+                sortPolicy->SortCompleted();
+                CleanupStack::PopAndDestroy( 2, sortPolicy ); // current
+                if ( index != KErrNotFound )
+                    {
+                    // Contact is inserted to matched contacts list
+                    aMatchedContacts.InsertL( cnt, index );
+                    }
+                else
+                    {
+                    // List is empty so append contact to it
+                    aMatchedContacts.AppendL( cnt );
+                    }
+                CleanupStack::Pop( cnt );
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::ViewFindCompletedL
+// --------------------------------------------------------------------------
+//  
+void CFindView::ViewFindCompletedL( 
+        MVPbkSimCntView& /*aSimCntView*/,
+        const RVPbkStreamedIntArray& aSimIndexArray )
+    {
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStore:CFindView(%x)::ViewFindCompletedL:found %d contacts"),
+         this, aSimIndexArray.Count() );
+         
+    // Native SIM view find is ready.
+    
+    // Clean the table
+    iSIMMatchedContacts.Reset();
+    
+    // Copy matched indexes
+    const TInt count( aSimIndexArray.Count() );
+    for ( TInt i(0); i < count; ++i )
+        {
+        iSIMMatchedContacts.AppendL( aSimIndexArray[i] );
+        }
+    
+    // The operation is not needed after indexes have been copied
+    delete iFindOperation;
+    iFindOperation = NULL;
+    
+    // Call base class matching function. It will send internal observer
+    // event that this view is ready for filtering.
+    MatchContactsL();
+    // Send view ready event to both internal&external observers.
+    SendViewStateEventToObservers();
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::MatchContactL
+// --------------------------------------------------------------------------
+//  
+void CFindView::MatchContactL( const CViewContact& aViewContact,
+            RPointerArray<MVPbkSimContact>& 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 ( IsSIMMatchL( aViewContact, matchArrayIndex ) )
+        {
+        // Remove from match array to save memory
+        iSIMMatchedContacts.Remove( matchArrayIndex );
+        iSIMMatchedContacts.Compress();
+        
+        if ( IsMatchL( aViewContact ) )
+            {
+            matched = ETrue;
+            }
+        }
+    
+    if ( matched )
+        {
+        // Contact matched.
+        // CFindView owns its contacts so create a copy
+        MVPbkSimCntStore& simStore = iAllContactsView.Store().NativeStore();
+        const TDesC8* cntBuf = simStore.AtL( aViewContact.SimIndex() );
+        if ( cntBuf )
+            {
+            CVPbkSimContact* cnt = 
+                CVPbkSimContact::NewL( *cntBuf, simStore );
+            CleanupStack::PushL( cnt );
+            aMatchedContacts.AppendL( cnt );
+            CleanupStack::Pop( cnt );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::RemoveFromMatchArrayIfFound
+// --------------------------------------------------------------------------
+//  
+void CFindView::RemoveFromMatchArrayIfFound( const CViewContact& aViewContact )
+    {
+    TInt index = FindFromMatchArray( aViewContact );
+    if ( index != KErrNotFound )
+        {
+        iSIMMatchedContacts.Remove( index );
+        iSIMMatchedContacts.Compress();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::IsSIMMatchL
+// --------------------------------------------------------------------------
+//  
+TBool CFindView::IsSIMMatchL( const CViewContact& aContact,
+        TInt& aMatchArrayIndex ) const
+    {
+    aMatchArrayIndex = FindFromMatchArray( aContact );
+    return aMatchArrayIndex != KErrNotFound;
+    }
+
+// --------------------------------------------------------------------------
+// CFindView::FindFromMatchArray
+// --------------------------------------------------------------------------
+//  
+TInt CFindView::FindFromMatchArray( const CViewContact& aContact ) const
+    {
+    return iSIMMatchedContacts.Find( aContact.SimIndex() );
+    }
+} // namespace VPbkSimStore 
+// End of File