email/mail/ViewerSrc/cmsgmailviewercontactmatcher.cpp
changeset 0 72b543305e3a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/email/mail/ViewerSrc/cmsgmailviewercontactmatcher.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,408 @@
+/*
+* Copyright (c) 2006 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:  Mail viewer contact finder.
+*
+*/
+
+#include "cmsgmailviewercontactmatcher.h"
+#include "MailLog.h"
+#include <MsgMailViewer.rsg>
+#include <coemain.h>
+#include <basched.h> // KLeaveExit
+#include <contactmatcher.h>
+#include <CVPbkContactManager.h>
+#include <CVPbkContactLinkArray.h>
+#include <MVPbkStoreContact.h>
+#include <CVPbkFieldTypeSelector.h>
+#include <VPbkContactViewFilterBuilder.h>
+#include <MVPbkContactFieldTextData.h>
+#include <CVPbkFieldTypeRefsList.h>
+#include <TVPbkFieldVersitProperty.h>
+#include <AiwServiceHandler.h>
+#include <finditemmenu.h>
+#include <e32base.h>
+#include <AknWaitDialog.h>
+
+// Constants 
+    
+// ---------------------------------------------------------------------------
+// CMsgMailViewerContactMatcher
+// ---------------------------------------------------------------------------
+//
+CMsgMailViewerContactMatcher::CMsgMailViewerContactMatcher(
+    CAiwServiceHandler& aServiceHandler )
+    : CActive( EPriorityStandard ),
+    iServiceHandler( aServiceHandler )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+inline void CMsgMailViewerContactMatcher::ConstructL()
+    {
+    LOG("CMsgMailViewerContactMatcher::ConstructL()");
+    iContactMatcher = CContactMatcher::NewL( 
+        &CCoeEnv::Static()->FsSession() );
+        
+    //Changed to open only default stores.
+    //Opening of all stores caused
+    //frequent jamming.
+    iContactMatcher->OpenDefaultMatchStoresL();
+    
+    iContactLinks = CVPbkContactLinkArray::NewL();
+    iChangedLinks = CVPbkContactLinkArray::NewL();
+    
+    //Idle object is needed because we can't
+    //call callback method straight from HandleNotifyL().
+    //It causes KErrInUse leave.
+    iIdle = CIdle::NewL(CActive::EPriorityIdle);
+    
+    iServiceHandler.AttachL( R_PHONENUMBER_MATCH_INTEREST );    
+    LOG("CMsgMailViewerContactMatcher::ConstructL() -> END");
+    }
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CMsgMailViewerContactMatcher* CMsgMailViewerContactMatcher::NewL(
+    CAiwServiceHandler& aServiceHandler )
+    {
+    CMsgMailViewerContactMatcher* self =
+        new( ELeave ) CMsgMailViewerContactMatcher( aServiceHandler );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// ~CMsgMailViewerContactMatcher
+// ---------------------------------------------------------------------------
+//
+CMsgMailViewerContactMatcher::~CMsgMailViewerContactMatcher()
+    {
+    Cancel();
+    // delete link arrays first to avoid access violations:
+    delete iContactLinks;   
+    delete iChangedLinks;    
+    // doesn't matter really if detaching fails
+    TRAP_IGNORE( iServiceHandler.DetachL( R_PHONENUMBER_MATCH_INTEREST ) );  
+    delete iContactMatcher;
+    delete iIdle;   
+    } 
+    
+// ----------------------------------------------------------------------------
+// FindContactL
+// ----------------------------------------------------------------------------
+//
+void CMsgMailViewerContactMatcher::FindContactL(
+    const TDesC& aMailAddress,
+    TPurpose aPurpose,
+    TCallBack aCallBack )
+    {
+    LOG1("CMsgMailViewerContactMatcher::FindContactL: %S", &aMailAddress);    
+    if ( !IsActive() )         
+        {        
+        iPurpose = aPurpose;
+        iCallBack = aCallBack;
+        // reset old data
+        iContactLinks->ResetAndDestroy();
+        iChangedLinks->ResetAndDestroy();        
+        
+        const MVPbkFieldTypeList& fieldTypes = iContactMatcher->FieldTypes();         
+        iContactMatcher->MatchDataL( aMailAddress, 
+                                     fieldTypes, 
+                                     *iContactLinks,
+                                     iStatus );  
+        SetActive();
+        
+        ASSERT( !iWaitDialog ); // should not exist!
+        // dialog sets iWaitDialog to NULL when it gets deleted
+        iWaitDialog = new( ELeave ) CAknWaitDialog(
+            ( REINTERPRET_CAST( CEikDialog**, &iWaitDialog ) ));
+		// safe to call LD even as a member variable, since sets itself to NULL when deleting
+        iWaitDialog->ExecuteLD( R_VIEWER_WAIT_MATCHING_NOTE ); // CSI: 50 # see comment above
+        }
+    }    
+    
+    
+//----------------------------------------------------------------------------
+// GetDataL()
+// Returns NULL pointer if no data is found
+//----------------------------------------------------------------------------
+HBufC* CMsgMailViewerContactMatcher::GetDataL() const
+    {
+    ASSERT( !IsActive() );
+    
+    HBufC* text( NULL );
+    if ( iChangedLinks->Count() > 0 )
+        {
+        ASSERT( iChangedLinks->Count() == 1 ); // single item fetch -> 1
+        MVPbkStoreContact* storeContact = NULL;
+        MVPbkStoreContactField* selectedField = NULL;        
+        const MVPbkContactLink& link = iChangedLinks->At( 0 );
+        iContactMatcher->GetStoreContactL( link, &storeContact ); 
+        storeContact->PushL();   
+        MVPbkStoreContactFieldCollection& fieldCollection =
+            storeContact->Fields();
+        selectedField = fieldCollection.RetrieveField( link ); 
+        if ( selectedField )
+            {
+            // Set field data
+            const MVPbkContactFieldTextData* textData =
+                &MVPbkContactFieldTextData::Cast( selectedField->FieldData() );
+            text = textData->Text().AllocL();
+            }
+        CleanupStack::PopAndDestroy( storeContact );
+        }        
+    return text;
+    }
+//----------------------------------------------------------------------------
+// GetNameL()
+// Returns NULL pointer if no data is found
+//----------------------------------------------------------------------------
+HBufC* CMsgMailViewerContactMatcher::GetNameL() const
+    {
+    MVPbkStoreContact* storeContact = NULL;
+    HBufC* name( NULL );
+    
+    ASSERT(iContactMatcher); // should exist
+    
+    if(iContactLinks->Count() > 0)
+        {
+        //We should have only one contact link.
+        iContactMatcher->GetStoreContactL( iContactLinks->At(0), &storeContact ); 
+        storeContact->PushL();   
+            
+        MVPbkStoreContactFieldCollection& fieldCollection =
+            storeContact->Fields();
+       
+        name = iContactMatcher->GetNameL(fieldCollection);
+        
+        CleanupStack::PopAndDestroy( storeContact );
+        }
+    
+    
+    return name;
+    }       
+    
+// ----------------------------------------------------------------------------
+// From CActive
+// ----------------------------------------------------------------------------
+//
+void CMsgMailViewerContactMatcher::DoCancel()
+    {
+    if ( iContactMatcher )
+        {
+        iContactMatcher->CancelOperation();
+        }
+    }
+    
+// ----------------------------------------------------------------------------
+// From CActive
+// ----------------------------------------------------------------------------
+//
+void CMsgMailViewerContactMatcher::RunL()
+    {
+    LOG1("CMsgMailViewerContactMatcher::RunL: %d", iStatus.Int());
+    
+    ASSERT( iWaitDialog ); // should exist!
+    iWaitDialog->ProcessFinishedL(); // deletes the dialog
+    
+    if(iContactLinks->Count() == 0)
+        {
+        //No matching contacts found -> no need to do fetch.
+        
+        //We can't call iCallBack straight away,
+        //because it triggers events that cause KErrInUse leave.
+        iIdle->Start(iCallBack); // CSI: 10 # 
+        }
+    else
+        {
+        // We need to delete excess matches, otherwise Fetch AIW may
+        // continue with next match when user presses Cancel.
+        DeleteExcessMatches( *iContactLinks );
+        CVPbkFieldTypeSelector* filter = CreateFilterLC( iPurpose );
+        TAiwSingleItemSelectionDataV3 selectionData = SelectionData( iPurpose,
+                                                                     *filter);        
+        ExecuteSingleItemFetchL( selectionData, *iContactLinks );    
+        CleanupStack::PopAndDestroy( filter );
+        }
+    }
+	
+// ----------------------------------------------------------------------------
+// From CActive
+// ----------------------------------------------------------------------------
+//
+TInt CMsgMailViewerContactMatcher::RunError( TInt aError )
+    {
+    LOG1("CMsgMailViewerContactMatcher::RunError: %d", aError);
+      
+    if( aError == KLeaveExit )
+        {
+        return aError;    
+        }
+    else
+        {
+        return KErrNone;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// From MAiwNotifyCallback
+// ----------------------------------------------------------------------------
+//
+TInt CMsgMailViewerContactMatcher::HandleNotifyL( // CSI: 40 # We must return 
+												  // the integer value although this 
+												  // is a leaving method.
+    TInt LOGPARAM_ONLY( aCmdId ),
+    TInt aEventId,
+    CAiwGenericParamList& aEventParamList,
+    const CAiwGenericParamList& /*aInParamList*/ )
+    {
+    LOG1("CMsgMailViewerContactMatcher::HandleNotifyL: %d", aCmdId);
+    TInt retVal( KErrNone );
+    if ( aEventId == KAiwEventCompleted )
+        {
+        TInt index( 0 );
+        const TAiwGenericParam* param =
+            aEventParamList.FindFirst( index, EGenericParamContactLinkArray );
+        if ( param )
+            {
+            TPtrC8 contactLinks = param->Value().AsData();
+            if ( contactLinks.Length() > 0 )
+                {
+                CVPbkContactLinkArray* links = CVPbkContactLinkArray::NewLC(
+                    contactLinks, iContactMatcher->GetContactStoresL() );
+                CleanupStack::Pop();//links
+                iChangedLinks->ResetAndDestroy();
+                delete iChangedLinks;
+                iChangedLinks = links;
+                LOG1("CMsgMailViewerContactMatcher::HandleNotifyL: LA %d", 
+                     iChangedLinks->Count());
+                
+                //We can't call iCallBack straight away,
+                //because it triggers events that cause KErrInUse leave.
+                iIdle->Start(iCallBack); // CSI: 10 # 
+                }
+            else
+                {
+                retVal = KErrArgument;    
+                }
+            } 
+        }
+    return retVal;
+    }
+
+//----------------------------------------------------------------------------
+//  DeleteExcessMatches()
+//----------------------------------------------------------------------------
+void CMsgMailViewerContactMatcher::DeleteExcessMatches(
+    CVPbkContactLinkArray& aLinks ) const
+    {
+    TInt i( aLinks.Count() - 1 );
+    // delete all but link at index 0
+    while ( i > 0 )
+        {
+        aLinks.Delete( i-- );
+        }
+    }
+
+//----------------------------------------------------------------------------
+//  CreateFilterLC()
+//----------------------------------------------------------------------------
+CVPbkFieldTypeSelector* CMsgMailViewerContactMatcher::CreateFilterLC(
+    TPurpose aPurpose ) const
+    {
+    CVPbkContactManager& contactMgr = iContactMatcher->GetContactManager();
+    CVPbkFieldTypeSelector* contactViewFilter =
+        CVPbkFieldTypeSelector::NewL( contactMgr.FieldTypes() );
+    CleanupStack::PushL( contactViewFilter );
+
+    ASSERT( aPurpose != EPurposeNone );
+
+    if ( aPurpose == ECallToContact ||  aPurpose == EMsgToContact )
+        {        
+        // Append the filter object with suitable criteria
+        VPbkContactViewFilterBuilder::BuildContactViewFilterL(
+            *contactViewFilter, EVPbkContactViewFilterPhoneNumber, contactMgr );
+        }
+        
+    // if message, then add also email addresses in addition to phone numbers
+    if ( aPurpose == EMsgToContact )
+        {        
+        VPbkContactViewFilterBuilder::BuildContactViewFilterL(
+            *contactViewFilter, EVPbkContactViewFilterEmail, contactMgr );
+        }
+        
+    return contactViewFilter;
+    }
+
+//----------------------------------------------------------------------------
+//  SelectionData()
+//----------------------------------------------------------------------------
+TAiwSingleItemSelectionDataV3
+CMsgMailViewerContactMatcher::SelectionData(
+    TPurpose aPurpose,
+    CVPbkFieldTypeSelector& aFilter ) const
+    {
+    TAiwAddressSelectType addressSelectType( EAiwAllItemsSelect );
+    if ( aPurpose == ECallToContact )
+        {
+        addressSelectType = EAiwPhoneNumberSelect;
+        }
+    else 
+        {        
+        ASSERT( aPurpose == EMsgToContact );
+        addressSelectType = EAiwMMSSelect;
+        }
+    TAiwSingleItemSelectionDataV3 selData;
+    selData.SetAddressSelectType( addressSelectType )
+           .SetFetchFilter( &aFilter );
+    return selData;
+    }
+
+//----------------------------------------------------------------------------
+//  ExecuteSingleItemFetchL()
+//----------------------------------------------------------------------------
+void CMsgMailViewerContactMatcher::ExecuteSingleItemFetchL( 
+    TAiwSingleItemSelectionDataV3 aData,
+    const CVPbkContactLinkArray& aLinks )
+    {
+    CAiwGenericParamList& inParamList = iServiceHandler.InParamListL();    
+    inParamList.AppendL(
+        TAiwGenericParam( EGenericParamContactSelectionData,
+        TAiwVariant( TAiwSingleItemSelectionDataV3Pckg( aData ) ) ) );
+
+    //Contacts that matched search
+    HBufC8* packedLinks = aLinks.PackLC();
+        
+    inParamList.AppendL( TAiwGenericParam( EGenericParamContactLinkArray,
+                                           TAiwVariant( *packedLinks ) ) );
+
+    iServiceHandler.ExecuteServiceCmdL( KAiwCmdSelect, 
+                                        inParamList, 
+                                        iServiceHandler.OutParamListL(),
+                                        0,
+                                        this );
+    CleanupStack::PopAndDestroy( packedLinks ); 
+    }
+
+// End of File
+