diff -r 000000000000 -r 72b543305e3a messagingappbase/msgavkon/muiu_internal/servicesinternal/src/MuiuContactAddressMatcher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingappbase/msgavkon/muiu_internal/servicesinternal/src/MuiuContactAddressMatcher.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,462 @@ +/* +* 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: Searches contact using email address as search filter from address books. +* +*/ + + +#include "MuiuContactAddressMatcher.h" +#include // KDC_RESOURCE_FILES_DIR +#include // R_MUIU_PHONENUMBER_MATCH_INTEREST +#include +#include +#include // KLeaveExit +#include // BaflUtils +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // CAknInformationNote +#include + +#include "MuiuMsvUiServiceUtilities.h" + + + +// Constants +// Resource file +_LIT( KMuiuInternalResourceFileName, "muiu_internal.rsc" ); + + +// --------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::NewL +// --------------------------------------------------------------------------- +// +CMuiuContactAddressMatcher* CMuiuContactAddressMatcher::NewL( + CEikonEnv& aEikonEnv ) + { + CMuiuContactAddressMatcher* self = + new( ELeave ) CMuiuContactAddressMatcher( aEikonEnv ); + CleanupStack::PushL( self ); + self->ConstructL(); + + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::CMuiuContactAddressMatcher +// --------------------------------------------------------------------------- +// +CMuiuContactAddressMatcher::CMuiuContactAddressMatcher( + CEikonEnv& aEikonEnv ): + CActive( EPriorityStandard ), + iEikEnv( aEikonEnv ), + iResourceOffset( KErrNotFound ) + { + CActiveScheduler::Add( this ); + } + +// --------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::ConstructL +// --------------------------------------------------------------------------- +// +inline void CMuiuContactAddressMatcher::ConstructL() + { + iServiceHandler = CAiwServiceHandler::NewL(); + + iContactMatcher = CContactMatcher::NewL( &iEikEnv.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); + + if ( !iEikEnv.IsResourceAvailableL( R_MUIU_PHONENUMBER_MATCH_INTEREST ) ) + { + TFileName fileName; + TParse parse; + parse.Set( KMuiuInternalResourceFileName, &KDC_RESOURCE_FILES_DIR, NULL ); + fileName = parse.FullName(); + BaflUtils::NearestLanguageFile( iEikEnv.FsSession(), fileName ); + iResourceOffset = iEikEnv.AddResourceFileL( fileName ); + } + + iServiceHandler->AttachL( R_MUIU_PHONENUMBER_MATCH_INTEREST ); + } + + +// --------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::~CMuiuContactAddressMatcher +// --------------------------------------------------------------------------- +// +CMuiuContactAddressMatcher::~CMuiuContactAddressMatcher() + { + Cancel(); + // delete link arrays first to avoid access violations: + delete iContactLinks; + delete iChangedLinks; + // doesn't matter really if detaching fails + if( iServiceHandler ) + { + TRAP_IGNORE( iServiceHandler->DetachL( R_MUIU_PHONENUMBER_MATCH_INTEREST ) ); + } + delete iContactMatcher; + delete iIdle; + delete iServiceHandler; + if ( iResourceOffset != KErrNotFound ) + { + iEikEnv.DeleteResourceFile( iResourceOffset ); + } + } + +// ---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::FindContactL +// ---------------------------------------------------------------------------- +// +TBool CMuiuContactAddressMatcher::FindContactL( + const TDesC& aMailAddress, + TCallBack aCallBack ) + { + if ( !MsvUiServiceUtilities::IsValidEmailAddressL( aMailAddress ) ) + { + return EFalse; + } + + if ( !IsActive() ) + { + iCallBack = aCallBack; + // reset old data + iContactLinks->ResetAndDestroy(); + iChangedLinks->ResetAndDestroy(); + + const MVPbkFieldTypeList& fieldTypes = iContactMatcher->FieldTypes(); + iContactMatcher->MatchDataL( aMailAddress, + fieldTypes, + *iContactLinks, + iStatus ); + SetActive(); + + // dialog sets iWaitDialog to NULL when it gets deleted + if (!iWaitDialog ) + { + iWaitDialog = new( ELeave ) CAknWaitDialog( + ( REINTERPRET_CAST( CEikDialog**, &iWaitDialog ) ), ETrue ); + } + iWaitDialog->ExecuteLD( R_MUIU_MATCHING_ADDRESS_WAIT_NOTE ); + } + else + { + User::Leave( KErrInUse ); + } + return ETrue; + } + + +//---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::GetAddressL() +// Returns NULL pointer if no data is found +//---------------------------------------------------------------------------- +HBufC* CMuiuContactAddressMatcher::GetAddressL() 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 ); + } + iChangedLinks->ResetAndDestroy(); + return text; + } +//---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::GetNameL() +// Returns NULL pointer if no data is found +//---------------------------------------------------------------------------- +HBufC* CMuiuContactAddressMatcher::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 ); + } + iContactLinks->ResetAndDestroy(); + return name; + } + +// ---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::DoCancel() +// From CActive +// ---------------------------------------------------------------------------- +// +void CMuiuContactAddressMatcher::DoCancel() + { + if ( iContactMatcher ) + { + iContactMatcher->CancelOperation(); + } + } + +// ---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::RunL() +// From CActive +// ---------------------------------------------------------------------------- +// +void CMuiuContactAddressMatcher::RunL() + { + // We need to delete excess matches, otherwise Fetch AIW may + // continue with next match when user presses Cancel. + DeleteExcessMatchesL( *iContactLinks ); + if( iContactLinks->Count() == 0) + { + HBufC* string = StringLoader::LoadLC( R_MUIU_QTN_PHOB_NOTE_NO_NUMBER, &iEikEnv ); + CAknInformationNote* note = new ( ELeave ) CAknInformationNote( ETrue ); + note->ExecuteLD( *string ); + CleanupStack::PopAndDestroy( string ); + // Deleting wait dialog in the beginning of the function causes + // info note to flicker + if ( iWaitDialog ) + { + iWaitDialog->ProcessFinishedL(); // deletes the dialog + } + + //We can't call iCallBack straight away, + //because it triggers events that cause KErrInUse leave. + iIdle->Start(iCallBack); + } + else + { + if ( iWaitDialog ) + { + iWaitDialog->ProcessFinishedL(); // deletes the dialog + } + CVPbkFieldTypeSelector* filter = CreateFilterLC( ); + TAiwSingleItemSelectionDataV3 selectionData = SelectionData( *filter); + ExecuteSingleItemFetchL( selectionData, *iContactLinks ); + CleanupStack::PopAndDestroy( filter ); + } + } + +// ---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::RunError +// From CActive +// ---------------------------------------------------------------------------- +// +TInt CMuiuContactAddressMatcher::RunError( TInt aError ) + { + if( aError == KLeaveExit ) + { + return aError; + } + else + { + return KErrNone; + } + } + +// ---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::HandleNotifyL +// From MAiwNotifyCallback +// ---------------------------------------------------------------------------- +// +TInt CMuiuContactAddressMatcher::HandleNotifyL( + TInt /*aCmdId*/, + TInt aEventId, + CAiwGenericParamList& aEventParamList, + const CAiwGenericParamList& /*aInParamList*/ ) + { + 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; + } + else + { + retVal = KErrArgument; + } + } + } + //Notify waiter always, even if error. + //We can't call iCallBack straight away, + //because it triggers events that cause KErrInUse leave. + iIdle->Start(iCallBack); + return retVal; + } + +//---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::DeleteExcessMatches() +//---------------------------------------------------------------------------- +void CMuiuContactAddressMatcher::DeleteExcessMatchesL( + CVPbkContactLinkArray& aLinks ) const + { + // It may be that first contact has not phone number but others has. + TInt count = aLinks.Count(); + // Search for first contact that has phone number + for (TInt i=0 ; i < count ; i++ ) + { + MVPbkStoreContact* storeContact = NULL; + const MVPbkContactLink& link = aLinks.At( i ); + iContactMatcher->GetStoreContactL( link, &storeContact ); + storeContact->PushL(); + if ( storeContact + && iContactMatcher->ContactHasFieldOfTypeL( EAiwPhoneNumberSelect, *storeContact ) == KErrNotFound ) + { + aLinks.Delete( i-- ); + count = aLinks.Count(); + } + else if ( !storeContact ) + { + // is this possible? + aLinks.Delete( i-- ); + count = aLinks.Count(); + } + else + { + CleanupStack::PopAndDestroy( storeContact ); + break; + } + CleanupStack::PopAndDestroy( storeContact ); + } + + TInt k( aLinks.Count() - 1 ); + // delete all but link at index 0 + while ( k > 0 ) + { + aLinks.Delete( k-- ); + } + } + +//---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::CreateFilterLC() +//---------------------------------------------------------------------------- +CVPbkFieldTypeSelector* CMuiuContactAddressMatcher::CreateFilterLC( ) const + { + CVPbkContactManager& contactMgr = iContactMatcher->GetContactManager(); + CVPbkFieldTypeSelector* contactViewFilter = + CVPbkFieldTypeSelector::NewL( contactMgr.FieldTypes() ); + CleanupStack::PushL( contactViewFilter ); + + // Append the filter object with suitable criteria + VPbkContactViewFilterBuilder::BuildContactViewFilterL( + *contactViewFilter, EVPbkContactViewFilterPhoneNumber, contactMgr ); + + //VPbkContactViewFilterBuilder::BuildContactViewFilterL( + // *contactViewFilter, EVPbkContactViewFilterEmail, contactMgr ); + + return contactViewFilter; + } + +//---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::SelectionData() +//---------------------------------------------------------------------------- +TAiwSingleItemSelectionDataV3 +CMuiuContactAddressMatcher::SelectionData( + CVPbkFieldTypeSelector& aFilter ) const + { + TAiwAddressSelectType addressSelectType( EAiwAllItemsSelect ); + addressSelectType = EAiwPhoneNumberSelect; + + TAiwSingleItemSelectionDataV3 selData; + selData.SetAddressSelectType( addressSelectType ) + .SetFetchFilter( &aFilter ); + return selData; + } + +//---------------------------------------------------------------------------- +// CMuiuContactAddressMatcher::ExecuteSingleItemFetchL() +//---------------------------------------------------------------------------- +void CMuiuContactAddressMatcher::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 +