/*
* Copyright (c) 2009 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: CLS lists class implementation
*
*/
#include "emailtrace.h"
#include "cesmrclslistshandler.h"
#include <eikenv.h> // CEikonEnv
#include <centralrepository.h> // CRepository
#include <AknFepInternalCRKeys.h> // KCRUidAknFep
#include <CPbkContactEngine.h> // CPbkContactEngine
#include <CPbkContactItem.h> // CPbkContactItem, TPbkContactItemField
#include <aknnotewrappers.h> // CAknErrorNote
//<cmail>
#include "cfsmailbox.h" // cfsmailbox
//</cmail>
#include <CPsRequestHandler.h>
#include <CPsSettings.h>
#include <CPcsDefs.h>
#include <VPbkEng.rsg>
#include <e32const.h> // TLanguage
#include <CVPbkContactManager.h>
#include "mesmrclslistsobserver.h"
#include "cesmrclsmatchobserver.h"
#include "cesmrinputmodeobserver.h"
#include "esmrfieldbuilderdef.h"
// CONSTANTS
// Unnamed namespace for local definitionsm functions and templates
namespace{ // codescanner::namespace
const TInt KMaxMRUMatches = 50;
const TInt KNumDisplayFields = 6;
const TInt KMaxUriLen = 50;
template<typename T> class CleanupResetAndDestroyClose
{
public:
inline static void PushL( T& aRef );
private:
static void Close( TAny *aPtr );
};
template<typename T> inline void CleanupResetAndDestroyClosePushL( T& aRef );
template<typename T> inline void CleanupResetAndDestroyClose<T>::PushL( T& aRef )
{
CleanupStack::PushL( TCleanupItem( &Close, &aRef ) );
}
template<typename T> void CleanupResetAndDestroyClose<T>::Close( TAny *aPtr )
{
static_cast<T*>(aPtr)->ResetAndDestroy();
static_cast<T*>(aPtr)->Close();
}
template<typename T> inline void CleanupResetAndDestroyClosePushL( T& aRef )
{
CleanupResetAndDestroyClose<T>::PushL( aRef );
}
}//namespace
// ======== MEMBER FUNCTIONS ========
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::NewL
// -----------------------------------------------------------------------------
CESMRClsListsHandler* CESMRClsListsHandler::NewL( RFs& aFs, CVPbkContactManager* aContactManager )
{
FUNC_LOG;
CESMRClsListsHandler* object = CESMRClsListsHandler::NewLC( aFs, aContactManager );
CleanupStack::Pop( object );
return object;
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::NewLC
// -----------------------------------------------------------------------------
CESMRClsListsHandler* CESMRClsListsHandler::NewLC( RFs& aFs, CVPbkContactManager* aContactManager )
{
FUNC_LOG;
CESMRClsListsHandler* object = new (ELeave) CESMRClsListsHandler( aFs, aContactManager );
CleanupStack::PushL( object );
object->ConstructL();
return object;
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::~CESMRClsListsHandler
// -----------------------------------------------------------------------------
CESMRClsListsHandler::~CESMRClsListsHandler( )
{
FUNC_LOG;
delete iSearchedText;
delete iPcsMatchObserver;
iMatchingCompleteContacts.Reset();
iMatchingMRUContacts.Reset();
iMatchingMissingEmailContacts.Reset();
iMatchingCompleteContacts.Close();
iMatchingMRUContacts.Close();
iMatchingMissingEmailContacts.Close();
delete iAllMRUContacts;
delete iInputObserver;
delete iAknFepCenRep;
delete iRequestHandler;
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::UpdateContactMatchListsL
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::UpdateContactMatchListsL( const RPointerArray<CESMRClsItem>& aMatches )
{
FUNC_LOG;
for( TInt i = 0 ; i < aMatches.Count() ; ++i )
{
if( aMatches[i]->IsMruItem() )
{
// If this is MRU item, we need to check that it doesn't
// already exist in iMatchingCompleteContacts
TInt itemIndex = FindDuplicate( *aMatches[i], iMatchingCompleteContacts );
if( itemIndex != KErrNotFound )
{
// Found, no need to add this, free memory
}
else
{
// Not found, add new to MRU list
iMatchingMRUContacts.AppendL( aMatches[i] );
}
}
else if( aMatches[i]->EmailAddress().Length() > 0 )
{
// If this is Phonebook item, we need to check that it doesn't
// already exist in iMatchingMRUContacts
TInt itemIndex = FindDuplicate( *aMatches[i], iMatchingMRUContacts );
if( itemIndex != KErrNotFound )
{
// Found, this needs to be removed from the MRU list
iMatchingMRUContacts.Remove( itemIndex );
}
// Phonebook items are always added to the top of the list
iMatchingCompleteContacts.AppendL( aMatches[i] );
}
else
{
// No email, nothing to compare, so add this always to the end of the list
iMatchingMissingEmailContacts.AppendL( aMatches[i] );
}
}
RPointerArray<CESMRClsItem> allMatches = ConstructOneListL( iMatchingCompleteContacts,
iMatchingMRUContacts,
iMatchingMissingEmailContacts );
if(iClsListObserver)
{
iClsListObserver->ArrayUpdatedL( allMatches );
}
allMatches.ResetAndDestroy();
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::InputModeChangedL
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::InputModeChangedL( TKeyboardModes aNewInputMode )
{
FUNC_LOG;
iPcsMatchObserver->SetInputMode( aNewInputMode );
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::CurrentSearchText
// -----------------------------------------------------------------------------
const TDesC& CESMRClsListsHandler::CurrentSearchText( )
{
FUNC_LOG;
return *iSearchedText;
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::SearchMatchesL
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::SearchMatchesL( const TDesC& aText )
{
FUNC_LOG;
iMatchingCompleteContacts.Reset();
iMatchingMRUContacts.Reset();
iMatchingMissingEmailContacts.Reset();
delete iSearchedText;
iSearchedText = NULL;
iSearchedText = aText.AllocL();
iPcsMatchObserver->SearchMatchesL( aText );
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::CESMRClsListsHandler
// -----------------------------------------------------------------------------
CESMRClsListsHandler::CESMRClsListsHandler( RFs& aFs, CVPbkContactManager* aContactManager ) :
iContactManager( aContactManager ),
iFs( aFs )
{
FUNC_LOG;
// do nothing
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::ConstructL
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::ConstructL( )
{
FUNC_LOG;
iRequestHandler = CPSRequestHandler::NewL();
iAknFepCenRep = CRepository::NewL( KCRUidAknFep );
iPcsMatchObserver = CESMRClsMatchObserver::NewL( *iAknFepCenRep, *this, *iRequestHandler, iContactManager );
SetSearchSettingsForPcsMatchObserverL();
// Monitors inputMode changes (predictive vs. non-predictive
iInputObserver = CESMRInputModeObserver::NewL( *iAknFepCenRep, *this );
if( !iSearchedText )
iSearchedText = KNullDesC().AllocL();
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::ReadCLSInfoFromMRUListIndexL
// -----------------------------------------------------------------------------
TBool CESMRClsListsHandler::ReadCLSInfoFromMRUListIndexL(
MDesCArray& aTextArray, CESMRClsItem& aClsItem,
const TInt aCurrentMatchIndex, const TInt aPreviousMatchIndex )
{
FUNC_LOG;
TBool retVal = EFalse;
// This should be even number
TInt currentRealItemIndex = aCurrentMatchIndex - ( aCurrentMatchIndex % 2 );
// Here we need to check if match is found both from the display name and email address
if( currentRealItemIndex != aPreviousMatchIndex )
{
aClsItem.SetDisplayNameL( aTextArray.MdcaPoint( currentRealItemIndex ) );
aClsItem.SetEmailAddressL( aTextArray.MdcaPoint( currentRealItemIndex + 1 ) );
retVal = ETrue;
}
return retVal;
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::FindDuplicate
// -----------------------------------------------------------------------------
TInt CESMRClsListsHandler::FindDuplicate( const CESMRClsItem& aClsItem,
RPointerArray<CESMRClsItem>& aContacts )
{
FUNC_LOG;
// find duplicate email addresses from aContacts
const TDesC& emailAddress = aClsItem.EmailAddress();
for( TInt i = 0; i < aContacts.Count(); ++i )
{
const TDesC& currentItemEmailAddress = aContacts[i]->EmailAddress();
if( emailAddress.CompareF( currentItemEmailAddress ) == 0 )
{
return i;
}
}
return KErrNotFound;
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::ConstructOneListL
// -----------------------------------------------------------------------------
RPointerArray<CESMRClsItem> CESMRClsListsHandler::ConstructOneListL(
const RPointerArray<CESMRClsItem>& aContactMatchesWithEmail,
const RPointerArray<CESMRClsItem>& aMRUMatches,
const RPointerArray<CESMRClsItem>& aContactMatchesWithoutEmail )
{
RPointerArray<CESMRClsItem> allMatches;
CleanupResetAndDestroyClosePushL( allMatches );
// Copy all the objects from three other lists to the all matches list
TInt matchingComleteItemsCount = aContactMatchesWithEmail.Count();
for( TInt i = 0 ; i < matchingComleteItemsCount; i++ )
{
CESMRClsItem* newClsItem = CopyClsItemLC( *aContactMatchesWithEmail[i] );
allMatches.AppendL( newClsItem );
CleanupStack::Pop( newClsItem );
}
// max MRU matches count limited to 50
TInt matchingMRUItemsCount = aMRUMatches.Count();
for( TInt i = 0; i < matchingMRUItemsCount && i < KMaxMRUMatches; i++ )
{
CESMRClsItem* newClsItem = CopyClsItemLC( *aMRUMatches[i] );
allMatches.AppendL( newClsItem );
CleanupStack::Pop( newClsItem );
}
TInt mathingContactItemsWithoutEmailCount = aContactMatchesWithoutEmail.Count();
for( TInt i = 0 ; i < mathingContactItemsWithoutEmailCount ; i++ )
{
CESMRClsItem* newClsItem = CopyClsItemLC( *aContactMatchesWithoutEmail[i] );
allMatches.AppendL( newClsItem );
CleanupStack::Pop( newClsItem );
}
CleanupStack::Pop( &allMatches );
return allMatches;
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::CopyClsItemL
// -----------------------------------------------------------------------------
CESMRClsItem* CESMRClsListsHandler::CopyClsItemLC( const CESMRClsItem& aClsItem )
{
FUNC_LOG;
return aClsItem.CloneLC();
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::SetSearchSettingsForPcsMatchObserverL()
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::SetSearchSettingsForPcsMatchObserverL()
{
FUNC_LOG;
// Create predictive search settings
CPsSettings* searchSettings = CPsSettings::NewL();
CleanupStack::PushL(searchSettings);
RPointerArray<TDesC> databases;
CleanupClosePushL(databases);
HBufC* store1 = HBufC::NewLC(KMaxUriLen);
store1->Des().Copy( KVPbkDefaultCntDbURI ); // To specify phone contacts store
databases.AppendL(store1);
HBufC* store2 = NULL;
if ( iMailBox )
{
store2 = HBufC::NewLC(KMaxUriLen);
GetMruDatastoreUriFromMailbox( *iMailBox, *store2 );
databases.AppendL( store2 );
}
searchSettings->SetSearchUrisL(databases);
// Set displayfields (first name, last name, email addresses)
RArray<TInt> displayFields(KNumDisplayFields);
CleanupClosePushL(displayFields);
displayFields.AppendL(R_VPBK_FIELD_TYPE_FIRSTNAME);
displayFields.AppendL(R_VPBK_FIELD_TYPE_LASTNAME);
displayFields.AppendL(R_VPBK_FIELD_TYPE_EMAILGEN);
displayFields.AppendL(R_VPBK_FIELD_TYPE_EMAILHOME);
displayFields.AppendL(R_VPBK_FIELD_TYPE_EMAILWORK);
searchSettings->SetDisplayFieldsL(displayFields);
CleanupStack::Pop(&displayFields);
displayFields.Close();
// Set the new sort order of data fields
RArray<TInt> sortOrder;
CleanupClosePushL(sortOrder);
sortOrder.AppendL(R_VPBK_FIELD_TYPE_FIRSTNAME);
sortOrder.AppendL(R_VPBK_FIELD_TYPE_LASTNAME);
sortOrder.AppendL(R_VPBK_FIELD_TYPE_EMAILGEN);
sortOrder.AppendL(R_VPBK_FIELD_TYPE_EMAILHOME);
sortOrder.AppendL(R_VPBK_FIELD_TYPE_EMAILWORK);
iRequestHandler->ChangeSortOrderL(*store1, sortOrder);
if ( store2 )
{
iRequestHandler->ChangeSortOrderL(*store2, sortOrder);
}
CleanupStack::Pop(&sortOrder);
sortOrder.Close();
// Set the new search settings
iRequestHandler->SetSearchSettingsL(*searchSettings);
if ( store2 )
{
CleanupStack::PopAndDestroy(store2);
}
CleanupStack::PopAndDestroy(store1);
CleanupStack::Pop(&databases);
databases.Close();
CleanupStack::PopAndDestroy(searchSettings);
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::isLanguageSupportedL()
// -----------------------------------------------------------------------------
TBool CESMRClsListsHandler::IsLanguageSupportedL()
{
FUNC_LOG;
// Get the current language
TLanguage lang = User::Language();
// Check for language support
return iRequestHandler->IsLanguageSupportedL(lang);
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::GetMruDatastoreUriFromMailbox()
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::GetMruDatastoreUriFromMailbox( CFSMailBox& aMailbox, HBufC& aUri )
{
FUNC_LOG;
aUri.Des().Copy( KDefaultMailBoxURI );
aUri.Des().AppendNum( aMailbox.GetId().PluginId().iUid );
aUri.Des().Append( KDefaultMailBoxURISeparator );
aUri.Des().AppendNum( aMailbox.GetId().Id() );
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::SetObserver()
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::SetObserver( MESMRClsListsObserver* aClsListObserver )
{
FUNC_LOG;
iClsListObserver = aClsListObserver;
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::SetCurrentMailboxL()
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::SetCurrentMailboxL( CFSMailBox* aMailBox )
{
FUNC_LOG;
TFSMailMsgId currentMailboxId;
TFSMailMsgId newMailboxId;
if( iMailBox )
{
currentMailboxId = iMailBox->GetId();
}
if( aMailBox )
{
newMailboxId = aMailBox->GetId();
}
if( currentMailboxId != newMailboxId )
{
iMailBox = aMailBox;
SetSearchSettingsForPcsMatchObserverL();
}
}
// -----------------------------------------------------------------------------
// CESMRClsListsHandler::OperationErrorL()
// -----------------------------------------------------------------------------
void CESMRClsListsHandler::OperationErrorL( TInt aErrorCode )
{
FUNC_LOG;
if ( iClsListObserver )
{
iClsListObserver->OperationErrorL( aErrorCode );
}
}