emailuis/emailui/src/FreestyleEmailUiCLSMatchObserverInterface.cpp
changeset 0 8466d47a6819
child 26 968773a0b6ef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/emailui/src/FreestyleEmailUiCLSMatchObserverInterface.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,492 @@
+/*
+* Copyright (c) 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:  Base class for Contact and RMU match observers
+*
+*/
+
+
+// for PCS support
+#include "emailtrace.h"
+#include <CPsQueryItem.h>
+#include <CPsRequestHandler.h>
+
+#include <aknnotewrappers.h>
+#include <AknFepInternalCRKeys.h>						// KCRUidAknFep, KAknFepPredTxtFlag
+#include <VPbkEng.rsg>
+
+#include "FreestyleEmailUiCLSListsHandler.h"			// CFSEmailUiClsListsHandler
+#include "FreestyleEMailUiCLSMatchObserverInterface.h"	// CFSEmailUiClsMatchObserver
+#include "FreestyleEmailUiUtilities.h"
+#include "FreestyleEmailUiLiterals.h"
+#include "FreestyleEmailUiCLSItem.h"
+#include "FreestyleEmailUiAppui.h"
+#include "FreestyleEmailUiLayoutHandler.h"
+
+
+// ================= MEMBER FUNCTIONS ==========================================
+
+CFSEmailUiClsMatchObserver* CFSEmailUiClsMatchObserver::NewL(CRepository& aCr,  
+		CFSEmailUiClsListsHandler& aListsHandler,
+		CPSRequestHandler& aRequestHandler,
+		CVPbkContactManager* aContactManager)
+	{
+    FUNC_LOG;
+	CFSEmailUiClsMatchObserver* api = CFSEmailUiClsMatchObserver::NewLC( aCr, aListsHandler,
+			aRequestHandler, aContactManager );
+	
+	CleanupStack::Pop( api );
+	return api;	
+	}
+
+CFSEmailUiClsMatchObserver* CFSEmailUiClsMatchObserver::NewLC(CRepository& aCr,  
+		CFSEmailUiClsListsHandler& aListsHandler,
+		CPSRequestHandler& aRequestHandler,
+		CVPbkContactManager* aContactManager )
+	{
+    FUNC_LOG;
+	CFSEmailUiClsMatchObserver* api = new (ELeave) CFSEmailUiClsMatchObserver( 
+			aCr, 
+			aListsHandler,
+			aRequestHandler,
+			aContactManager );
+	
+	CleanupStack::PushL( api );
+	api->ConstructL();
+	return api;	
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiClsMatchObserver::CFSEmailUiClsMatchObserver
+// -----------------------------------------------------------------------------
+CFSEmailUiClsMatchObserver::CFSEmailUiClsMatchObserver(
+ 								CRepository& aCr,  
+								CFSEmailUiClsListsHandler& aListsHandler,
+								CPSRequestHandler& aRequestHandler,
+								CVPbkContactManager* aContactManager ) :
+    iRequestHandler( &aRequestHandler ),
+    iAknFepCenRep( aCr ),
+    iListHandler( aListsHandler ),
+    iInputMode( EQwerty ),
+    iContactManager( aContactManager )
+	{
+    FUNC_LOG;
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiClsMatchObserver::~CFSEmailUiClsMatchObserver
+// -----------------------------------------------------------------------------
+CFSEmailUiClsMatchObserver::~CFSEmailUiClsMatchObserver()
+    {
+    FUNC_LOG;
+    delete iQuery;
+    if ( iRequestHandler )
+        {
+        iRequestHandler->RemoveObserver( this );
+        }
+    }
+
+void CFSEmailUiClsMatchObserver::ConstructL()
+	{
+    FUNC_LOG;
+	iRequestHandler->AddObserverL( this );
+	iInputMode = GetInputMode();
+	iQuery = CPsQuery::NewL();
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiClsMatchObserver::SearchMatchesL
+// -----------------------------------------------------------------------------
+void CFSEmailUiClsMatchObserver::SearchMatchesL( const TDesC& aText )
+	{
+    FUNC_LOG;
+	
+	if( iRequestHandler )
+		{
+		TInt cacheStatus = CheckCacheStatusL();
+		if ( !cacheStatus )
+			{
+			// Reset query
+			iQuery->Reset();
+			
+			// Create one queryitem for every character in the query string and append it to the query object
+			// Every queryitem is filled with two fields : 
+			//	1) a character from the query string 
+			//	2) the keyboard mode using which the query was entered
+			
+			TInt itemCount = aText.Length();
+			if ( itemCount > 50 )
+				{
+				itemCount = 50;
+				}
+			for ( TInt i = 0; i < itemCount; i++ )
+			{    
+			   // Add a query item
+			   CPsQueryItem* item = CPsQueryItem::NewL();
+			   item->SetCharacter(aText[i]);   
+			   item->SetMode(iInputMode);	 // EItut refers to numeric keypad
+			                         // Use EQwerty if QWERTY keyboard is used
+			   iQuery->AppendL(*item);
+			}
+
+			// Initiate a search request
+			iRequestHandler->SearchL(*iQuery);
+			}
+		else //Cache isn't ready
+			{
+			iListHandler.OperationErrorL( cacheStatus );
+			}
+
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiClsMatchObserver::SetInputModeL
+// -----------------------------------------------------------------------------
+void CFSEmailUiClsMatchObserver::SetInputMode( TKeyboardModes aInputMode )
+	{
+    FUNC_LOG;
+	iInputMode = aInputMode;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiClsMatchObserver::HandleMatchComplete
+// -----------------------------------------------------------------------------
+void CFSEmailUiClsMatchObserver::HandlePsResultsUpdate( 
+        RPointerArray<CPsClientData>& aSearchResults,
+        RPointerArray<CPsPattern>& searchSeqs )
+	{
+    FUNC_LOG;
+	TRAP_IGNORE( HandlePsResultsUpdateL( aSearchResults, searchSeqs) );
+	}
+// -----------------------------------------------------------------------------
+// CFSEmailUiClsMatchObserver::HandleMatchComplete
+// -----------------------------------------------------------------------------
+void CFSEmailUiClsMatchObserver::HandlePsResultsUpdateL( 
+        RPointerArray<CPsClientData>& aSearchResults,
+        RPointerArray<CPsPattern>& aSearchSeqs )
+	{
+    FUNC_LOG;
+    RPointerArray<CFSEmailUiClsItem> contacts;
+    CleanupResetAndDestroyClosePushL( contacts );
+    CleanupResetAndDestroyClosePushL( aSearchResults );
+    CleanupResetAndDestroyClosePushL( aSearchSeqs );
+    
+    // Iterate through all or maximum number of search results
+    CFreestyleEmailUiAppUi* appUi = 
+        static_cast<CFreestyleEmailUiAppUi*>( CCoeEnv::Static()->AppUi() );
+    TInt maxPcsMatches = appUi->LayoutHandler()->MaxPcsMatches();
+    
+	for ( TInt counter = 0 ; counter < aSearchResults.Count() && counter < maxPcsMatches ; counter++ )
+		{
+		// Get search result
+		CPsClientData* result = aSearchResults[counter];
+
+	    // Get the order of the data fields in result
+	    RArray<TInt> dataOrder;
+	    CleanupClosePushL( dataOrder );
+	    iRequestHandler->GetDataOrderL( *( result->Uri() ), dataOrder );
+		
+		TPtrC firstname( KNullDesC );
+		TPtrC lastname( KNullDesC );
+		RArray<TPtrC> emailFields;
+		CleanupClosePushL( emailFields );
+		// Iterate through all the data fields in the result.
+		// Collect the result and resolve which fields did match.
+		// Email fields are collected into array
+		for ( TInt dataField = 0 ; dataField < dataOrder.Count(); dataField++ )
+			{
+			switch ( dataOrder[dataField] )
+				{
+				case R_VPBK_FIELD_TYPE_FIRSTNAME:
+					firstname.Set( *(result->Data(dataField)) );
+					break;
+					
+				case R_VPBK_FIELD_TYPE_LASTNAME:
+					lastname.Set( *(result->Data(dataField)) );
+					break;
+
+				case R_VPBK_FIELD_TYPE_EMAILGEN:
+				case R_VPBK_FIELD_TYPE_EMAILHOME:					
+				case R_VPBK_FIELD_TYPE_EMAILWORK:
+					{
+					if ( result->Data( dataField ) )
+						{
+						if ( result->Data( dataField )->Length() > 0 )
+							{
+							TPtrC email( *result->Data( dataField ) );
+							ChopEmailEntriesList(email, emailFields);
+							}
+						}
+					}
+					break;
+				}
+			}
+
+
+		
+		TDesC& sourceUri = *( result->Uri() );
+		TBool isMruItem = sourceUri.Find( KDefaultMailBoxURI ) != KErrNotFound;
+
+		MVPbkContactLink* contactLink = NULL;
+		
+		if ( !isMruItem )
+			{
+			contactLink = iRequestHandler->ConvertToVpbkLinkLC( *result, *iContactManager );
+			CleanupStack::Pop( contactLink );
+			}
+		
+		HBufC* displayname;
+		
+		// Determine how many contact address to create:
+		// If there's no email fields, create one item without email address
+		if ( emailFields.Count() == 0 )
+			{
+			
+			// Use Ps engine to check if the text matches the search query
+			CDesCArray* matchSet = new (ELeave) CDesCArrayFlat(10);
+			CleanupStack::PushL( matchSet );
+			
+			// Create display name, this will be used in UI.
+			displayname = TFsEmailUiUtility::CreateDisplayNameLC( firstname, lastname, KNullDesC );
+			
+			RArray<TPsMatchLocation> matchLocation;
+			CleanupClosePushL( matchLocation );
+			iRequestHandler->LookupL( *iQuery, *displayname, *matchSet, matchLocation );
+			
+			// Create contact item and set highlighting for it
+			CFSEmailUiClsItem* contactItem = CFSEmailUiClsItem::NewLC();
+			contactItem->SetDisplayNameL( *displayname );
+			contactItem->SetHighlights( matchLocation );
+			if ( contactLink )
+				{
+				contactItem->SetContactLinkL( *contactLink );
+				}
+			contactItem->SetIsMruItem( isMruItem );
+			contacts.AppendL( contactItem );
+			CleanupStack::Pop( contactItem );
+			
+			CleanupStack::Pop( &matchLocation );
+			matchLocation.Close();
+			CleanupStack::PopAndDestroy( displayname );	
+			CleanupStack::PopAndDestroy( matchSet );
+			
+			}
+		else
+			{
+			// Iterate through all the email fields, check if they match the search criteria and
+			// create new contact item for each one that matches
+			for ( TInt fieldIndex = 0; fieldIndex < emailFields.Count(); fieldIndex++ )
+				{
+				
+				// Create display name, this will be used in UI. If the
+				// contact does not contain either firstname nor lastname,
+				// the displayname is left empty.
+				displayname = TFsEmailUiUtility::CreateDisplayNameLC(
+					firstname, lastname );
+				
+				// Create match text field, containing display field and email address
+				HBufC* matchText = HBufC::NewLC( displayname->Length() +
+								KSpace().Length() +
+								emailFields[fieldIndex].Length() );
+				
+				//This condition is for checking if there is no display name like in the case of MRU and therefore 
+                //we dont need to add displayname + KSpace(unnnecessary space) which is causing problem in drawing Underline
+				if (displayname->Length() > 0)
+				    {
+
+				matchText->Des().Copy( *displayname );
+				matchText->Des().Append( KSpace );
+
+				    }
+				
+				matchText->Des().Append( emailFields[fieldIndex] );
+				
+
+				// Use Ps engine to check if the text matches the search query
+				CDesCArray* matchSet = new (ELeave) CDesCArrayFlat(10);
+				CleanupStack::PushL( matchSet );
+				
+				RArray<TPsMatchLocation> matchLocation;
+				CleanupClosePushL( matchLocation );
+				iRequestHandler->LookupL( *iQuery, *matchText, *matchSet, matchLocation );
+				
+				if ( matchLocation.Count() > 0 )
+					{
+					// Create contact item and set highlighting for it
+					CFSEmailUiClsItem* contactItem = CFSEmailUiClsItem::NewLC();
+					contactItem->SetDisplayNameL( *displayname );
+					contactItem->SetIsMruItem( isMruItem );
+					contactItem->SetEmailAddressL( emailFields[fieldIndex] );
+					contactItem->SetHighlights( matchLocation );
+					if ( contactLink )
+						{
+						contactItem->SetContactLinkL( *contactLink );
+						}
+					if ( emailFields.Count() > 1 )
+						{
+						contactItem->SetMultipleEmails( ETrue );
+						}
+					contacts.AppendL( contactItem );	
+					CleanupStack::Pop( contactItem );					
+					}
+				
+				CleanupStack::PopAndDestroy( &matchLocation );
+				CleanupStack::PopAndDestroy( matchSet );
+				CleanupStack::PopAndDestroy( matchText );
+				CleanupStack::PopAndDestroy( displayname ); 		
+				}
+			}
+		
+		if ( !isMruItem )
+			{
+			delete contactLink;
+			}
+		
+		// Close arrays
+		CleanupStack::PopAndDestroy( &emailFields );
+        CleanupStack::PopAndDestroy( &dataOrder );
+		}
+
+	iListHandler.UpdateContactMatchListsL( contacts );
+	CleanupStack::PopAndDestroy( &aSearchSeqs );
+	CleanupStack::PopAndDestroy( &aSearchResults );
+	CleanupStack::PopAndDestroy( &contacts );
+	}
+
+void CFSEmailUiClsMatchObserver::HandlePsError(TInt aErrorCode)
+	{
+    FUNC_LOG;
+	TRAP_IGNORE( iListHandler.OperationErrorL( aErrorCode ) );
+	}
+
+void CFSEmailUiClsMatchObserver::CachingStatus( TCachingStatus& aStatus,
+    TInt& /*aError*/ )
+	{
+    FUNC_LOG;
+	TInt err = KErrNone;
+	switch ( aStatus )
+		{
+		case ECachingComplete:
+			err = KErrNone;
+			break;
+		case ECachingNotStarted:
+			err = KErrNotFound;
+			break;
+		case ECachingInProgress:
+			err = KErrNotReady;
+			break;
+		case ECachingCompleteWithErrors:
+			err = KErrCorrupt;
+			break;
+		default:
+			break;
+		}
+	
+	TRAP_IGNORE( iListHandler.OperationErrorL( err ) );
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiClsMatchObserver::IsCurrentInputModePredictive
+// -----------------------------------------------------------------------------
+TKeyboardModes CFSEmailUiClsMatchObserver::GetInputMode()
+	{
+    FUNC_LOG;
+	TInt repVal = 0;
+	// 1 = predictive, 0 = non predictive
+	iAknFepCenRep.Get( KAknFepPredTxtFlag, repVal );
+	
+	//If true, EItut (predictive)
+	if( repVal == 0 )
+		{
+		return EQwerty;
+		}
+	return EItut;
+	}
+
+TInt CFSEmailUiClsMatchObserver::CheckCacheStatusL()
+	{
+    FUNC_LOG;
+	// Get the caching status synchronously
+	// 'status' has the caching status
+	// 'err' has KErrNone or any caching errors
+	TCachingStatus status;
+	TInt err = iRequestHandler->GetCachingStatusL(status);
+	
+	switch (status)
+		{
+		case ECachingComplete:
+			return KErrNone;
+		case ECachingNotStarted:
+			return KErrNotFound;
+		case ECachingInProgress:
+			return KErrNotReady;
+		case ECachingCompleteWithErrors:
+			return KErrCorrupt;
+		default:
+			break;
+		}
+
+	return EFalse;
+	
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiClsMatchObserver::ChopEmailEntriesList
+// -----------------------------------------------------------------------------
+void CFSEmailUiClsMatchObserver::ChopEmailEntriesList(TPtrC & aEmail, RArray<
+		TPtrC> & aEmailFields)
+	{
+	FUNC_LOG;
+	const TInt KUnitSeparator = 31;
+	TInt prevSeparatorIndex = 0;
+	TInt nextSeparatorIndex = aEmail.Locate( KUnitSeparator );
+	// check if there are more than one email entry
+	if ( nextSeparatorIndex == KErrNotFound )
+		{
+		aEmailFields.Append( aEmail ); //one entry only
+		}
+	else //more then one entry
+		{
+		// loop through all but last email entries 
+		while ( nextSeparatorIndex != KErrNotFound )
+			{
+			// First entry needs a separate handling
+			if ( prevSeparatorIndex == 0 )
+				{
+				// -1 because there is a space before a separator character
+				TPtrC entry = aEmail.Mid( 0, nextSeparatorIndex - 1 ); 
+				aEmailFields.Append( entry );
+				}
+			else //Append the next entry
+				{ 
+				nextSeparatorIndex = nextSeparatorIndex + 1 + prevSeparatorIndex;				
+				TInt length = nextSeparatorIndex - prevSeparatorIndex - 1;
+				// +2 and -2 because there are a spaces before and after a separator character
+				TPtrC entry = aEmail.Mid(prevSeparatorIndex + 2, //starting pos
+						length - 2); //length 
+				aEmailFields.Append(entry);
+				}
+			// Take the part of the list skiping the entries already appended    
+			TPtrC nextEntry = aEmail.Mid(nextSeparatorIndex + 1); 
+			prevSeparatorIndex = nextSeparatorIndex;
+			nextSeparatorIndex = nextEntry.Locate(KUnitSeparator);
+			}
+		// the last element does not contain the separator so it needs to be taken here
+		if (nextSeparatorIndex == KErrNotFound && aEmail.Mid(prevSeparatorIndex + 1).Length() > 1)
+			{
+			aEmailFields.Append(aEmail.Mid(prevSeparatorIndex + 2));
+			}
+		}
+	}