phonebookui/Phonebook2/UIPolicy/src/CPbk2ContactFindPolicy.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/UIPolicy/src/CPbk2ContactFindPolicy.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,377 @@
+/*
+* 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:  Phonebook 2 contact find policy.
+*
+*/
+
+
+#include "CPbk2ContactFindPolicy.h"
+
+// Phonebook2 includes
+#include <CPbk2SortOrderManager.h>
+#include <MPbk2ContactNameFormatter.h>
+#include <MPbk2ContactNameFormatter2.h>
+#include <Pbk2ContactNameFormatterFactory.h>
+
+// Virtual phonebook includes
+#include <MVPbkBaseContact.h>
+#include <CVPbkFieldTypeRefsList.h>
+#include <CVPbkContactFieldIterator.h>
+#include <MVPbkContactFieldTextData.h>
+#include <VPbkContactStoreUris.h>
+#include <VPbkEng.rsg>
+#include <MVPbkContactFieldTextData.h>
+#include <MVPbkBaseContactFieldCollection.h>
+
+// System includes
+#include <FindUtil.h>
+#include <featmgr.h>
+
+// Constants
+const TInt KCountOfWords = 1;
+const TInt KMaxLengthOfTwoNameFields = 100;
+const TInt KDefaultTitleFormatting =
+        MPbk2ContactNameFormatter::EPreserveLeadingSpaces;
+
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    EPanicNullArray = 1
+    };
+
+void Panic( TPanicCode aReason )
+    {
+    _LIT( KPanicText, "CPbk2ContactFindPolicy" );
+    User::Panic( KPanicText, aReason );
+    }
+#endif // _DEBUG
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::CPbk2ContactFindPolicy
+// --------------------------------------------------------------------------
+//
+CPbk2ContactFindPolicy::CPbk2ContactFindPolicy()
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::~CPbk2ContactFindPolicy
+// --------------------------------------------------------------------------
+//
+CPbk2ContactFindPolicy::~CPbk2ContactFindPolicy()
+    {
+    delete iFindUtil;
+    delete iSortOrderManager;
+    delete iNameFormatter;
+    delete iFieldTypeRefsList;
+    FeatureManager::UnInitializeLib();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2ContactFindPolicy* CPbk2ContactFindPolicy::NewL( TParam* aParam )
+    {
+    CPbk2ContactFindPolicy* self = new ( ELeave ) CPbk2ContactFindPolicy();
+    CleanupStack::PushL( self );
+    self->ConstructL( aParam );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::ConstructL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2ContactFindPolicy::ConstructL( TParam* aParam )
+    {
+    iFindUtil = CFindUtil::NewL();
+    
+    if ( aParam )
+        {
+        // Create sort order manager
+        iSortOrderManager = CPbk2SortOrderManager::NewL(
+            aParam->iFieldTypeList, &aParam->iRFs );
+        
+        // Create contact name formatter
+        iNameFormatter = Pbk2ContactNameFormatterFactory::CreateL(
+            aParam->iFieldTypeList, *iSortOrderManager, &aParam->iRFs );
+            
+        //Create field type list
+        iFieldTypeRefsList = CVPbkFieldTypeRefsList::NewL();
+        }
+    FeatureManager::InitializeLibL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::Match
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactFindPolicy::Match
+        ( const TDesC& aText, const TDesC& aSearchString )
+    {
+    return iFindUtil->Interface()->Match( aText, aSearchString );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::MatchContactNameL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactFindPolicy::MatchContactNameL( 
+    const MDesCArray& aFindWords,
+    const MVPbkBaseContact& aContact )
+    {
+    // This class constructed without aParam, so iNameFormatter
+    // doesn't exist. Let's leave.
+    if ( !iNameFormatter )
+        {
+        User::Leave( KErrNotSupported );
+        }
+    
+    TBool match( ETrue );
+    TInt findWordsCount = aFindWords.MdcaCount();
+    const TInt KGranularity = 4; 
+    CDesCArrayFlat* allNamesArray = new ( ELeave ) CDesCArrayFlat
+        ( KGranularity );
+    CleanupStack::PushL( allNamesArray );
+
+    HBufC* title = NULL;
+    if( FeatureManager::FeatureSupported(KFeatureIdFfContactsCompanyNames) )
+        {
+        MPbk2ContactNameFormatter2* nameformatterExtension =
+            reinterpret_cast<MPbk2ContactNameFormatter2*>(iNameFormatter->
+                    ContactNameFormatterExtension( MPbk2ContactNameFormatterExtension2Uid ) );
+        title = nameformatterExtension->GetContactTitleWithCompanyNameL( aContact.Fields(),
+                KDefaultTitleFormatting );
+        } 
+    else
+        {
+        title = iNameFormatter->GetContactTitleL( aContact.Fields(), 
+                KDefaultTitleFormatting );
+        }
+
+    CleanupStack::PushL( title );
+        
+    if ( title->Length() )
+    	{
+    	SplitContactFieldTextIntoArrayL( allNamesArray, *title );
+    	}
+    else 
+    	{
+    	//If FDN contact, no name, use phonenumber as title if exists
+    	GetTitleFromFDNNumberL( aContact, *allNamesArray );
+    	}   
+
+    CleanupStack::PopAndDestroy( title );
+
+    // Match every search word in contact's fields. 
+    if ( findWordsCount <= allNamesArray->MdcaCount() )
+        {
+        for ( TInt i = 0; i < findWordsCount && match; ++i )
+            {
+            for ( TInt j = 0; j < allNamesArray->MdcaCount(); ++j )   
+                {
+                // Match refine
+                if ( !MatchRefineL( allNamesArray->MdcaPoint( j ), 
+                        aFindWords.MdcaPoint( i ) ) )
+                    {
+                    match = EFalse;
+                    }
+                else
+                    {
+                    // Match is found, delete it from array to prevent 
+                    // matching with the same word again
+                    match = ETrue;
+                    allNamesArray->Delete( j );
+                    break;
+                    }  
+                }            
+            }   
+        }
+    else
+        {
+        // More search words than name fields, can't match
+        match = EFalse;
+        }
+    
+        
+    // Special case when searching names in China variant:
+    // Last and first names are merged and search must find
+    // names without typing space between them.
+    if ( findWordsCount == KCountOfWords && !match )
+        {
+        FeatureManager::InitializeLibL();
+        TBool chinese = FeatureManager::FeatureSupported( KFeatureIdChinese );
+        FeatureManager::UnInitializeLib();
+        
+        TBool korean = (User::Language() == ELangKorean);
+
+        if ( chinese || korean )
+            {
+            match = MatchChineseContactNameL( aFindWords, aContact );
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( allNamesArray );
+    return match;
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::MatchChineseContactNameL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactFindPolicy::MatchChineseContactNameL( 
+    const MDesCArray& aFindWords,
+    const MVPbkBaseContact& aContact )
+    {
+    HBufC* nameFields = HBufC::NewLC( KMaxLengthOfTwoNameFields );
+    TPtr nameFieldsPtr = nameFields->Des();
+    TBool match;
+    
+    // Create iterator
+    MVPbkBaseContactFieldIterator* iterator = iNameFormatter->
+    ActualTitleFieldsLC( *iFieldTypeRefsList, aContact.Fields() );
+    
+    // Loop iterator
+    while ( iterator->HasNext() )
+        {
+        const MVPbkBaseContactField* field = iterator->Next();
+
+        // Check field's type
+        if ( field->FieldData().DataType() == EVPbkFieldStorageTypeText )
+            {
+            const MVPbkContactFieldTextData& data =
+                MVPbkContactFieldTextData::Cast( field->FieldData() );
+            // Catenate contact's name fields
+            nameFieldsPtr.Append( data.Text() );
+            }
+        }
+    // Match refine
+    if ( !MatchRefineL( nameFieldsPtr, aFindWords.MdcaPoint( 0 ) ) )
+        {
+        match = EFalse;
+        }
+    else
+        {
+        match = ETrue;
+        }
+    CleanupStack::PopAndDestroy(); // iterator
+    CleanupStack::PopAndDestroy( nameFields );
+    
+    return match;
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::MatchRefineL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactFindPolicy::MatchRefineL
+        ( const TDesC& aText, const TDesC &aSearchString )
+    {
+    TBool ret = iFindUtil->Interface()->MatchRefineL( aText, aSearchString );
+
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::IsWordValidForMatching
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactFindPolicy::IsWordValidForMatching
+        ( const TDesC& aWord )
+    {
+    return iFindUtil->Interface()->IsWordValidForMatching(aWord);
+    }
+
+//----------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::SplitContactFieldTextIntoArrayL
+//----------------------------------------------------------------------------
+//
+void CPbk2ContactFindPolicy::SplitContactFieldTextIntoArrayL(
+		CDesCArray* aArray,
+        const TDesC& aText )
+    {
+    __ASSERT_DEBUG( aArray, Panic( EPanicNullArray ) );
+
+    TBool firstWord = ETrue; // To avoid ignoring space from first word in contact field
+    const TInt textLength = aText.Length();
+    for ( TInt beg = 0; beg < textLength; ++beg )
+        {
+        // Skip separators before next word
+        if ( !iNameFormatter->IsFindSeparatorChar( aText[beg] ) )
+            {
+            // Scan the end of the word
+            TInt end = beg;
+            for (; end < textLength &&
+                   !iNameFormatter->IsFindSeparatorChar( aText[end] );
+                ++end )
+                {
+                }
+            const TInt len = end - beg;
+            // Append found word to the array
+            if (firstWord)
+	            {
+	            aArray->AppendL( aText.Mid( 0,end ) );
+	            firstWord = EFalse;
+	            }
+            else
+            	{
+            	aArray->AppendL( aText.Mid( beg,len ) );
+            	}
+            // Scan for next word
+            beg = end;
+            }
+        }
+
+    if ( aArray->MdcaCount() == 0 && textLength > 0 )
+        {
+        // aText is all word separator characters
+        // -> make a "word" out of those
+        aArray->AppendL( aText );
+        }
+    }
+
+//----------------------------------------------------------------------------
+// CPbk2ContactFindPolicy::GetTitleFromFDNNumber
+//----------------------------------------------------------------------------
+//
+void CPbk2ContactFindPolicy::GetTitleFromFDNNumberL( const MVPbkBaseContact& aContact, CDesC16Array& aAllNamesArray )
+	{    
+    //Check if it's a SIM FDN contact
+    if( aContact.MatchContactStore( VPbkContactStoreUris::SimGlobalFdnUri() ) )
+        {
+        const MVPbkBaseContactFieldCollection& fieldCollection = aContact.Fields(); 
+        
+        for(TInt i = 0; i < fieldCollection.FieldCount(); i++ )
+            {
+            const MVPbkBaseContactField& contactField = fieldCollection.FieldAt( i );
+            const MVPbkFieldType* fieldType = contactField.BestMatchingFieldType();
+            
+            //Check if mobile number is used in the view
+            if( fieldType->FieldTypeResId() == R_VPBK_FIELD_TYPE_MOBILEPHONEGEN )
+                {
+                const MVPbkContactFieldTextData* textData =
+                                               &MVPbkContactFieldTextData::Cast
+                                                   ( contactField.FieldData() );
+                aAllNamesArray.AppendL( textData->Text() );
+                break;
+                }
+            }
+        }    
+	}
+    
+// End of File