--- a/predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2Helper.cpp Thu Jul 15 18:22:55 2010 +0300
+++ b/predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2Helper.cpp Thu Aug 19 09:41:07 2010 +0300
@@ -16,7 +16,7 @@
*/
// INCLUDES
-#include <FindUtil.h>
+#include <PbkGlobalSettingFactory.h>
#include "FindUtilChineseECE.h"
#include "CPcsAlgorithm2.h"
#include "CPcsAlgorithm2Helper.h"
@@ -25,22 +25,11 @@
#include "CPcsCache.h"
#include "CPcsKeyMap.h"
#include "CPsData.h"
-#include "CWords.h"
#include "CPsQuery.h"
#include "CPsQueryItem.h"
#include "CPsDataPluginInterface.h"
#include "CPcsPoolElement.h"
-// Compare functions
-TBool Compare1(const TDesC& aFirst, const TDesC& aSecond)
- {
- return aFirst == aSecond;
- }
-
-TBool Compare2(const TDesC& aFirst, const TDesC& aSecond)
- {
- return CPcsAlgorithm2Utils::MyCompareC(aFirst, aSecond);
- }
// ============================== MEMBER FUNCTIONS ============================
@@ -70,6 +59,7 @@
{
PRINT ( _L("Enter CPcsAlgorithm2Helper::CPcsAlgorithm2") );
PRINT ( _L("End CPcsAlgorithm2Helper::CPcsAlgorithm2") );
+ iMaxCount = 0;
}
// ----------------------------------------------------------------------------
@@ -81,13 +71,18 @@
PRINT ( _L("Enter CPcsAlgorithm2Helper::ConstructL") );
iAlgorithm = aAlgorithm;
- keyMap = iAlgorithm->GetKeyMap();
+ iKeyMap = iAlgorithm->GetKeyMap();
+ iPbkSettings = PbkGlobalSettingFactory::CreatePersistentSettingL();
+ iPbkSettings->ConnectL( MPbkGlobalSetting::EGeneralSettingCategory );
+ iPbkSettings->RegisterObserverL( this );
+ UpdateNameOrderL();
+
PRINT ( _L("End CPcsAlgorithm2Helper::ConstructL") );
}
// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::CPcsAlgorithm2Helper
+// CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper
// Destructor
// ----------------------------------------------------------------------------
CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper()
@@ -98,798 +93,323 @@
}
// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::SearchMixedL
+// CPcsAlgorithm2Helper::SearchSingleL
// Search function for input with both ITU-T and QWERTY mode
// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::SearchMixedL(const CPsSettings& aSettings,
- CPsQuery& aPsQuery, TBool isSearchInGroup,
- RArray<TInt>& aContactsInGroup,
- RPointerArray<CPsData>& searchResults,
- RPointerArray<CPsPattern>& searchSeqs)
+void CPcsAlgorithm2Helper::SearchSingleL(const CPsSettings& aSettings,
+ CPsQuery& aPsQuery,
+ TBool aIsSearchInGroup,
+ const RArray<TInt>& aContactsInGroup,
+ RPointerArray<CPsData>& aSearchResults,
+ RPointerArray<CPsPattern>& aSearchSeqs)
{
- __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchMixedL") );
+ PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchSingleL") );
- PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchMixedL") );
+ //__LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchSingleL") );
+ iMaxCount = aSettings.MaxResults();
+
// Create filtering helper for the required sort type
TSortType sortType = aSettings.GetSortType();
CPcsAlgorithm2FilterHelper* filterHelper =
CPcsAlgorithm2FilterHelper::NewL(sortType);
+ CleanupStack::PushL( filterHelper );
+
+ // Search from cache based on first character
+ const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
+ TInt cachePoolId = iKeyMap->PoolIdForCharacter( firstCharItem.Character(), firstCharItem.Mode() );
// Reset the result set array for new search
iSearchResultsArr.ResetAndDestroy();
// Get the data stores
- RPointerArray<TDesC> aDataStores;
- aSettings.SearchUrisL(aDataStores);
+ RPointerArray<TDesC> dataStores;
+ CleanupResetAndDestroyPushL( dataStores );
+ aSettings.SearchUrisL(dataStores);
// Get the required display fields from the client
RArray<TInt> requiredDataFields;
+ CleanupClosePushL( requiredDataFields );
aSettings.DisplayFieldsL(requiredDataFields);
-
- // Search from cache based on first character
- const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
- TInt numValue = keyMap->PoolIdForCharacter( firstCharItem.Character() );
// Perform search for each required data store
RPointerArray<CPcsPoolElement> elements;
+ CleanupClosePushL( elements );
+ const TInt dataStoresCount = dataStores.Count();
- for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++)
+ for (TInt dsIndex = 0; dsIndex < dataStoresCount; dsIndex++)
{
-
- RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
- iSearchResultsArr.Append(temp);
+ RPointerArray<CPsData>* temp = new (ELeave) RPointerArray<CPsData> ();
+ CleanupStack::PushL( temp );
+ iSearchResultsArr.AppendL( temp );
+ CleanupStack::Pop( temp );
// Get the contents for this data store
- TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex]));
+ TInt arrayIndex = iAlgorithm->GetCacheIndex(*(dataStores[dsIndex]));
if (arrayIndex < 0)
{
continue;
}
CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
- cache->GetContactsForKeyL(numValue, elements);
+ cache->GetContactsForKeyL(cachePoolId, elements);
+
+ // Get the supported data fields for this data store
+ RArray<TInt> supportedDataFields;
+ CleanupClosePushL( supportedDataFields );
+ cache->GetDataFields(supportedDataFields);
+
+ // Get the filtered data fields for this data store
+ TUint8 filteredDataMatch = CPcsAlgorithm2Utils::FilterDataFieldsL(requiredDataFields,
+ supportedDataFields);
// Perform filtering
- FilterResultsMixedL(filterHelper, elements, aPsQuery,
- isSearchInGroup, aContactsInGroup);
+ FilterResultsSingleL(filterHelper,
+ elements,
+ aPsQuery,
+ filteredDataMatch,
+ aIsSearchInGroup,
+ aContactsInGroup);
- // If alphabetical sorting, get the results for this datastore
+ // If alphabetical sorting, get the results for this datastore
if (sortType == EAlphabetical)
{
filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
}
elements.Reset();
- }
-
- aDataStores.ResetAndDestroy();
- requiredDataFields.Reset();
-
- // If alphabetical sorting, merge the result sets of all datastores
- if (sortType == EAlphabetical)
- {
- // Form the complete searchResults array
- CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr,
- searchResults);
- }
- else
- {
- // Results are already sorted pattern based
- filterHelper->GetResults(searchResults);
- }
-
- // Get the sorted match sequence list
- filterHelper->GetPatternsL(searchSeqs);
-
- PRINT1 ( _L("Number of search results = %d"), searchResults.Count() );
-
- // Cleanup
- for (TInt i = 0; i < iSearchResultsArr.Count(); i++)
- {
- iSearchResultsArr[i]->Reset();
- delete iSearchResultsArr[i];
- iSearchResultsArr[i] = NULL;
+ CleanupStack::PopAndDestroy( &supportedDataFields ); // Close
}
- iSearchResultsArr.Reset();
-
- CleanupStack::PopAndDestroy(); // query
- delete filterHelper;
-
- PRINT ( _L("End CPcsAlgorithm2Helper::SearchMixedL") );
-
- __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchMixedL") );
- }
-
-// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::SearchITUL
-// Search function for ITU-T style
-// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::SearchITUL(const CPsSettings& aSettings,
- CPsQuery& aPsQuery, TBool isSearchInGroup,
- RArray<TInt>& aContactsInGroup,
- RPointerArray<CPsData>& searchResults,
- RPointerArray<CPsPattern>& searchSeqs)
- {
- __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchITUL") );
-
- PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchITUL") );
-
- // Create filtering helper for the required sort type
- TSortType sortType = aSettings.GetSortType();
- CPcsAlgorithm2FilterHelper* filterHelper =
- CPcsAlgorithm2FilterHelper::NewL(sortType);
-
- // Convert the query to string
- TPtrC queryPtr = aPsQuery.QueryAsStringLC();
-
- // Search from cache based on first character
- const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
- TInt numValue = keyMap->PoolIdForCharacter( firstCharItem.Character() );
-
- // Reset the result set array for new search
- iSearchResultsArr.ResetAndDestroy();
-
- // Get the data stores
- RPointerArray<TDesC> aDataStores;
- aSettings.SearchUrisL(aDataStores);
-
- // Get the required display fields from the client
- RArray<TInt> requiredDataFields;
- aSettings.DisplayFieldsL(requiredDataFields);
-
- // Perform search for each required data store
- RPointerArray<CPcsPoolElement> elements;
-
- for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++)
- {
- RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
- iSearchResultsArr.Append(temp);
-
- // Get the contents for this data store
- TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex]));
- if (arrayIndex < 0)
- {
- continue;
- }
- CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
- cache->GetContactsForKeyL(numValue, elements);
-
- // Perform filtering
- FilterResultsL(filterHelper, elements, queryPtr,
- isSearchInGroup, aContactsInGroup);
-
- // If alphabetical sorting, get the results for this datastore
- if (sortType == EAlphabetical)
- {
- filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
- }
-
- elements.Reset();
- }
-
- aDataStores.ResetAndDestroy();
- requiredDataFields.Reset();
-
- // If alphabetical sorting, merge the result sets of all datastores
- if (sortType == EAlphabetical)
- {
- // Merge the result sets of individual datastores alphabetically
- CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr,
- searchResults);
- }
- else
- {
- // Results are already sorted pattern based
- filterHelper->GetResults(searchResults);
- }
-
- // Get the sorted match sequence list
- filterHelper->GetPatternsL(searchSeqs);
-
- PRINT1 ( _L("Number of search results = %d"), searchResults.Count() );
-
- // Cleanup
- for (TInt i = 0; i < iSearchResultsArr.Count(); i++)
- {
- iSearchResultsArr[i]->Reset();
- delete iSearchResultsArr[i];
- iSearchResultsArr[i] = NULL;
- }
- iSearchResultsArr.Reset();
-
- CleanupStack::PopAndDestroy(); // query
- delete filterHelper;
-
- PRINT ( _L("End CPcsAlgorithm2Helper::SearchITUL") );
- __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchITUL") );
- }
-
-// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::SearchQWERTYL
-// Search function for QWERTY style
-// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::SearchQWERTYL(const CPsSettings& aSettings,
- CPsQuery& aPsQuery, TBool isSearchInGroup,
- RArray<TInt>& aContactsInGroup,
- RPointerArray<CPsData>& searchResults,
- RPointerArray<CPsPattern>& searchSeqs)
- {
- __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchQWERTYL") );
- PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchQWERTYL") );
-
- // te filtering helper for the required sort type
- TSortType sortType = aSettings.GetSortType();
- CPcsAlgorithm2FilterHelper* filterHelper =
- CPcsAlgorithm2FilterHelper::NewL(sortType);
-
- // Convert the query to string
- TPtrC queryPtr = aPsQuery.QueryAsStringLC();
-
- // Search from cache based on first character
- const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
- TInt numValue = keyMap->PoolIdForCharacter( firstCharItem.Character() );
-
- // Reset the result set array for new search
- iSearchResultsArr.ResetAndDestroy();
-
- // Get the data stores
- RPointerArray<TDesC> aDataStores;
- aSettings.SearchUrisL(aDataStores);
-
- // Get the required display fields from the client
- RArray<TInt> requiredDataFields;
- aSettings.DisplayFieldsL(requiredDataFields);
-
- // Perform search for each of the required data stores
- RPointerArray<CPcsPoolElement> elements;
-
- for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++)
- {
-
- RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
- iSearchResultsArr.Append(temp);
-
- // Get the contents for this data store
- TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex]));
- if (arrayIndex < 0)
- {
- continue;
- }
- CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
- cache->GetContactsForKeyL(numValue, elements);
-
- // Perform filtering
- FilterResultsQwertyL(filterHelper, elements, queryPtr,
- isSearchInGroup, aContactsInGroup);
-
- // If alphabetical sorting, get the results for this datastore
- if (sortType == EAlphabetical)
- {
- filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
- }
-
- elements.Reset();
- }
- aDataStores.ResetAndDestroy();
- requiredDataFields.Reset();
+ CleanupStack::PopAndDestroy( &elements ); // Close
+ CleanupStack::PopAndDestroy( &requiredDataFields ); // Close
+ CleanupStack::PopAndDestroy( &dataStores ); // ResetAndDestroy
// If alphabetical sorting, merge the result sets of all datastores
if (sortType == EAlphabetical)
{
// Form the complete searchResults array
CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr,
- searchResults);
+ aSearchResults);
}
else
{
// Results are already sorted pattern based
- filterHelper->GetResults(searchResults);
+ filterHelper->GetResults(aSearchResults);
}
// Get the sorted match sequence list
- filterHelper->GetPatternsL(searchSeqs);
+ filterHelper->GetPatternsL(aSearchSeqs);
+
+ PRINT1 ( _L("Number of search results = %d"), aSearchResults.Count() );
- PRINT1 ( _L("Number of search results = %d"), searchResults.Count() );
-
- // Cleanup
- for (TInt i = 0; i < iSearchResultsArr.Count(); i++)
+ // Cleanup
+ const TInt searchResultsArrCount = iSearchResultsArr.Count();
+ for (TInt i = 0; i < searchResultsArrCount; i++)
{
iSearchResultsArr[i]->Reset();
- delete iSearchResultsArr[i];
- iSearchResultsArr[i] = NULL;
}
- iSearchResultsArr.Reset();
+ iSearchResultsArr.ResetAndDestroy();
- CleanupStack::PopAndDestroy(); // query
- delete filterHelper;
+ CleanupStack::PopAndDestroy( filterHelper );
- PRINT ( _L("End CPcsAlgorithm2Helper::SearchQWERTYL") );
- __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchQWERTYL") );
+ //__LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchSingleL") );
+
+ PRINT ( _L("End CPcsAlgorithm2Helper::SearchSingleL") );
}
// ----------------------------------------------------------------------------
// CPcsAlgorithm2Helper::SearchMatchSeqL
-// Funciton to search matching sequences in the input text
+// Function to search matching sequences in the input text
// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::SearchMatchSeqL(HBufC* /*aQuery*/, TDesC& aData,
- RPointerArray<TDesC>& /*aMatchSet*/,
- CPsQuery& /*aPsQuery*/,
- RArray<TPsMatchLocation>& aMatchLocation)
+void CPcsAlgorithm2Helper::SearchMatchSeqL(CPsQuery& aPsQuery,
+ const TDesC& aData,
+ RPointerArray<TDesC>& aMatchSet,
+ RArray<TPsMatchLocation>& aMatchLocation )
{
PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchMatchSeqL") );
- // Convert the data into words
- TLex lex(aData);
-
- // First word
- TPtrC token = lex.NextToken();
-
- TInt beg = lex.Offset() - token.Length(); // start index of match sequence
-
- // Search thru multiple words
- while (token.Length() != 0)
+ RArray<TInt> matchPos;
+ CleanupClosePushL( matchPos );
+ RArray<TInt> matchLen;
+ CleanupClosePushL( matchLen );
+ if ( iAlgorithm->FindUtilECE()->MatchRefineL( aData, aPsQuery, matchPos, matchLen, ETrue ) )
{
- TPsMatchLocation tempLocation;
-
- // check for directionality of the text
- TBool found(EFalse);
- TBidiText::TDirectionality dir = TBidiText::TextDirectionality(token, &found);
-
- tempLocation.index = beg;
- tempLocation.length = 0;
- tempLocation.direction = dir;
-
- // Add the match location to the data structure array
- aMatchLocation.Append(tempLocation);
-
- // Next word
- token.Set(lex.NextToken());
- beg = lex.Offset() - token.Length(); // start index of next word
+ ASSERT( matchPos.Count() == matchLen.Count() );
+ const TInt matchPosCount = matchPos.Count();
+ for ( TInt i = 0 ; i < matchPosCount ; ++i )
+ {
+ TPsMatchLocation tempLocation;
+
+ // check for directionality of the text
+ TBool found(EFalse);
+ TPtrC matchingPart = aData.Mid( matchPos[i], matchLen[i] );
+ TBidiText::TDirectionality dir = TBidiText::TextDirectionality(matchingPart, &found);
+
+ tempLocation.index = matchPos[i];
+ tempLocation.length = matchLen[i];
+ tempLocation.direction = dir;
+
+ // Add the match location to the data structure array
+ aMatchLocation.Append(tempLocation);
+
+ // Add the matched sequence to set, not allowing duplicates
+ CPcsAlgorithm2Utils::AppendMatchToSeqL( aMatchSet, matchingPart );
+ }
}
+ CleanupStack::PopAndDestroy( &matchLen );
+ CleanupStack::PopAndDestroy( &matchPos );
PRINT ( _L("End CPcsAlgorithm2Helper::SearchMatchSeqL") );
}
// ----------------------------------------------------------------------------
-// CPcsAlgorithm2::FilterResultsL
+// CPcsAlgorithm2Helper::FilterResultsSingleL
// Subset search function
// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::FilterResultsL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper,
- RPointerArray<CPcsPoolElement>& searchSet,
- const TDesC& searchQuery,
- TBool isSearchInGroup,
- RArray<TInt>& aContactsInGroup)
+void CPcsAlgorithm2Helper::FilterResultsSingleL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper,
+ RPointerArray<CPcsPoolElement>& aSearchSet,
+ CPsQuery& aSearchQuery,
+ TUint8 aFilteredDataMatch,
+ TBool aIsSearchInGroup,
+ const RArray<TInt>& aContactsInGroup)
{
- __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::FilterResultsL") );
- PRINT ( _L("Enter CPcsAlgorithm2Helper::FilterResultsL") );
+ PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsSingleL") );
+
+ TInt maxcount = 0;
+ CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
- // Convert the search condition to numeric key string
- TBuf<KPsQueryMaxLen> tmpSearchQuery;
- keyMap->GetNumericKeyString(searchQuery, tmpSearchQuery);
-
- //Holds the first char of first name of a contact
- TBuf<10> firstChar;
+ // Assume that all the elements is aSearchSet are from the same database.
+ // Get firstname index and lastname index for that database.
+ // If both are found, then name fields are matched a bit differently compared
+ // to rest of the fields.
+ TInt fnIndex( KErrNotFound );
+ TInt lnIndex( KErrNotFound );
+ TBool fullNameSearch( EFalse );
+ if ( aSearchSet.Count() )
+ {
+ TInt dbUriId = aSearchSet[0]->GetPsData()->UriId();
+ CPcsCache* cache = iAlgorithm->GetCache( dbUriId );
+ fnIndex = cache->GetFirstNameIndex();
+ lnIndex = cache->GetLastNameIndex();
- PRINT2 ( _L("Numeric Key String for %S = %S"), &searchQuery, &tmpSearchQuery );
-
+ // Ensure that firstname and lastname are among the fields to be searched
+ TUint8 fnBitmask = 1 << fnIndex;
+ TUint8 lnBitmask = 1 << lnIndex;
+ if ( (aFilteredDataMatch & fnBitmask) &&
+ (aFilteredDataMatch & lnBitmask) )
+ {
+ fullNameSearch = ETrue;
+ // Remove firstname and lastname from the set of fields to search
+ // so that they will not be searched twice.
+ aFilteredDataMatch &= ~fnBitmask;
+ aFilteredDataMatch &= ~lnBitmask;
+ }
+ }
+
// Parse thru each search set elements and filter the results
- for (int index = 0; index < searchSet.Count(); index++)
+ const TInt searchSetCount = aSearchSet.Count();
+ for (TInt index = 0; index < searchSetCount; index++)
{
- CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (searchSet[index]);
+ CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (aSearchSet[index]);
CPsData* psData = poolElement->GetPsData();
psData->ClearDataMatches();
- RPointerArray<TDesC> tempMatchSeq;
- // Search thru multiple words
- TBuf<KBufferMaxLen> token;
- TBuf<KBufferMaxLen> firstName;
- TBuf<KBufferMaxLen> lastName;
- lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des());
- firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des());
+ // Skip the contact if we are doing a group search and contact doesn't belong to the group
+ if ( aIsSearchInGroup &&
+ aContactsInGroup.Find( psData->Id() ) == KErrNotFound )
+ {
+ continue;
+ }
+
+ // Buffer for matched character sequence. Currently, we don't return
+ // accurate pattern but just first character from the matching point.
+ // Current clients don't actually use this data for anything.
+ TBuf<1> matchingData;
+
+ TBool matched = EFalse;
- CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
- TBool matched = 0;
+ // Parse thru each data field and filter the results
+ // -------------------------------------------------
+
+ // Name fields are handled separately to enable searching with query like
+ // "LastnameFirstname". Searching fullname by query string
+ // only for the pool elements matching with the firstname or lastname
+ if ( fullNameSearch && ( poolElement->IsDataMatch(fnIndex) ||
+ poolElement->IsDataMatch(lnIndex) ))
+ {
+ HBufC* fullName = CreateNameBufLC( *psData, fnIndex, lnIndex );
- // If has Chinese word and the first name doesn't start with Chinese character, then should add a space
- // before the first name, otherwise intitial letter searching will not function
- if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName))
- {
- token.Append(lastName);
- if (firstName.Length())
+ // FindUtil can take care of matching queries like "Firstname", "Lastname",
+ // and "LastnameFirstname".
+ matched = pFindUtilEce->MatchRefineL( *fullName, aSearchQuery );
+ if (matched)
{
- firstChar.Zero();
- firstChar.Append(firstName[0]);
- if (!pFindUtilEce->IsChineseWord(firstChar) )
- {
- token.Append(KSpace);
- }
- token.Append(firstName);
+ matchingData = fullName->Left(1);
+ psData->SetDataMatch( fnIndex );
+ psData->SetDataMatch( lnIndex );
+ }
+
+ CleanupStack::PopAndDestroy( fullName );
+ }
+
+ // Find from the rest of the fields if no match found so far.
+ // Name fields are already removed from aFilteredDataMatch if we did separate full name search.
+ const TInt dataElementCount = psData->DataElementCount();
+ for ( TInt dataIndex = 0; dataIndex < dataElementCount && !matched ; dataIndex++ )
+ {
+ // Filter off data fields not required in search
+ TUint8 bitIndex = 1 << dataIndex;
+ TUint8 filter = bitIndex & aFilteredDataMatch;
+ if ( filter == 0x0 )
+ {
+ // Move to next data
+ continue;
}
- if (token.Length() != 0)
+ if ( poolElement->IsDataMatch(dataIndex) )
{
- matched = iAlgorithm->FindUtil()->Interface()->
- MatchRefineL(token, tmpSearchQuery, ECustomConverter, iAlgorithm);
-
+ TPtrC fieldData( *psData->Data(dataIndex) );
+ matched = pFindUtilEce->MatchRefineL( fieldData, aSearchQuery );
if (matched)
{
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
- }
- }
- }
- else
- {
- // If contact name only has western word, then should send
- // "first name","last name" and "last name + first name" to FindUtil to do the search
- const TInt lastnameLen = lastName.Length();
- const TInt firstnameLen = firstName.Length();
- if(lastnameLen)
- {
- matched = iAlgorithm->FindUtil()->Interface()->
- MatchRefineL(lastName, tmpSearchQuery, ECustomConverter, iAlgorithm);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- }
- }
-
- if(!matched && firstnameLen)
- {
- matched = iAlgorithm->FindUtil()->Interface()->
- MatchRefineL(firstName, tmpSearchQuery, ECustomConverter, iAlgorithm);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
- }
- }
-
- token.Append(lastName);
- token.Append(firstName);
- if (!matched && lastnameLen && firstnameLen)
- {
- matched = iAlgorithm->FindUtil()->Interface()->
- MatchRefineL(token, tmpSearchQuery, ECustomConverter, iAlgorithm);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
+ matchingData = fieldData.Left(1);
+ psData->SetDataMatch( dataIndex );
}
}
}
- if (matched)
+
+ // Add to results if match is found
+ if ( matched )
{
- // Extract matched character sequence, don't need to be accurate for Chinese variant
- const TInt len = 1;
- HBufC* seq = HBufC::NewLC(len);
- *seq = token.Mid(0, len);
- seq->Des().UpperCase();
-
- TIdentityRelation<TDesC> rule(Compare1);
- if (tempMatchSeq.Find(seq, rule) == KErrNotFound)
- {
- tempMatchSeq.Append(seq);
- CleanupStack::Pop();
- }
- else
- {
- CleanupStack::PopAndDestroy();
- }
-
-
- // Add the result
- if (isSearchInGroup)
- {
- if (aContactsInGroup.Find(psData->Id()) != KErrNotFound)
- {
- aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
- }
- }
- else
- {
- aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
- }
- }
-
- // Cleanup the match sequence array as
- // they are stored in pattern details structure
- tempMatchSeq.ResetAndDestroy();
- }
-
- PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsL") );
- __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::FilterResultsL") );
- }
-
-// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::FilterResultsQwertyL
-// Subset search function
-// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::FilterResultsQwertyL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper,
- RPointerArray<CPcsPoolElement>& searchSet,
- const TDesC& searchQuery,TBool isSearchInGroup,
- RArray<TInt>& aContactsInGroup)
- {
- PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsQwertyL") );
-
- TBuf<50> tmpSearchQuery = searchQuery;
- tmpSearchQuery.LowerCase();
-
- //Holds the first char of first name of a contact
- TBuf<10> firstChar;
-
- // Parse thru each search set elements and filter the results
- for (int index = 0; index < searchSet.Count(); index++)
- {
- CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (searchSet[index]);
- CPsData* psData = poolElement->GetPsData();
- psData->ClearDataMatches();
- RPointerArray<TDesC> tempMatchSeq;
+ RPointerArray<TDesC> tempMatchSeq;
+ CleanupClosePushL( tempMatchSeq );
- // Parse thru each data and filter the results
- TBuf<KBufferMaxLen> token;
- TBuf<KBufferMaxLen> firstName;
- TBuf<KBufferMaxLen> lastName;
- lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des());
- firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des());
-
- CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
- TBool matched = 0;
-
- // If has Chinese word and the first name doesn't start with Chinese character, then should add a space
- // before the first name, otherwise intitial letter searching will not function
- if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName))
- {
- token.Append(lastName);
- if (firstName.Length())
- {
- firstChar.Zero();
- firstChar.Append(firstName[0]);
- if (!pFindUtilEce->IsChineseWord(firstChar) )
- {
- token.Append(KSpace);
- }
- token.Append(firstName);
- }
-
- if (token.Length() != 0)
- {
- matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(token, tmpSearchQuery);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
- }
- }
- }
- else
- {
- // If contact name only has western word, then should send
- // "first name","last name" and "last name + first name" to FindUtil to do the search
- const TInt lastnameLen = lastName.Length();
- const TInt firstnameLen = firstName.Length();
- if(lastnameLen)
- {
- matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(lastName, tmpSearchQuery);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- }
- }
-
- if(!matched && firstnameLen)
- {
- matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(firstName, tmpSearchQuery);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
- }
- }
+ // Wrap matched character sequence to array.
+ matchingData.UpperCase();
+ tempMatchSeq.AppendL(&matchingData);
+
+ // Add the result
+ aAlgorithmFilterHelper->AddL( psData, tempMatchSeq );
+ maxcount++;
- token.Append(lastName);
- token.Append(firstName);
- if (!matched && lastnameLen && firstnameLen)
- {
- matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(token, tmpSearchQuery);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
- }
- }
+ // Cleanup the match sequence array as
+ // they are stored in pattern details structure
+ CleanupStack::PopAndDestroy( &tempMatchSeq ); // Close
+
+ // TODO: Match seqs could be extracted from actual
+ // match locations by using the other overload of
+ // CFindUtilChineseECE::MatchRefineL().
+ // Currently, match seq data is not used by clients.
}
- if (matched)
- {
- // Extract matched character sequence, don't need to be accurate for Chinese variant
- const TInt len = 1;
- HBufC* seq = HBufC::NewLC(len);
- *seq = token.Mid(0, len);
- seq->Des().UpperCase();
-
- TIdentityRelation<TDesC> rule(Compare1);
- if (tempMatchSeq.Find(seq, rule) == KErrNotFound)
- {
- tempMatchSeq.Append(seq);
- CleanupStack::Pop();
- }
- else
- {
- CleanupStack::PopAndDestroy();
- }
-
- // Add the result
- if (isSearchInGroup)
- {
- if (aContactsInGroup.Find(psData->Id()) != KErrNotFound)
- {
- aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
- }
- }
- else
- {
- aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
- }
- }
-
- // Cleanup the match sequence array as
- // they are stored in pattern details structure
- tempMatchSeq.ResetAndDestroy();
+ if ( iMaxCount != -1 && maxcount > iMaxCount )
+ {
+ return;
+ }
}
- PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsQwertyL") );
- }
-
-// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::FilterResultsMixedL
-// Subset search function
-// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::FilterResultsMixedL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper,
- RPointerArray<CPcsPoolElement>& searchSet,
- CPsQuery& searchQuery, TBool isSearchInGroup,
- RArray<TInt>& aContactsInGroup)
- {
- PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsMixedL") );
-
- // Convert the search query to alpha numeric string
- TBuf<50> tmpSearchQuery;
- ExtractQueryL(searchQuery, tmpSearchQuery);
- tmpSearchQuery.LowerCase();
- TBuf<10> firstChar;
-
- // Parse thru each search set elements and filter the results
- for (int index = 0; index < searchSet.Count(); index++)
- {
- CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (searchSet[index]);
- CPsData* psData = poolElement->GetPsData();
- psData->ClearDataMatches();
- RPointerArray<TDesC> tempMatchSeq;
-
- // Parse thru each data and filter the results
- TBuf<255> token;
- TBuf<KBufferMaxLen> firstName;
- TBuf<KBufferMaxLen> lastName;
- lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des());
- firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des());
-
- CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
- TBool matched = 0;
-
- // If has Chinese word and the first name doesn't start with Chinese character, then should add a space
- // before the first name, otherwise intitial letter searching will not function
- if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName))
- {
- token.Append(lastName);
- if (firstName.Length())
- {
- firstChar.Zero();
- firstChar.Append(firstName[0]);
- if (!pFindUtilEce->IsChineseWord(firstChar) )
- {
- token.Append(KSpace);
- }
- token.Append(firstName);
- }
-
- if (token.Length() != 0)
- {
- matched = pFindUtilEce->MatchRefineL(token, searchQuery);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
- }
- }
- }
- else
- {
- // If contact name only has western word, then should send
- // "first name","last name" and "last name + first name" to FindUtil to do the search
- const TInt lastnameLen = lastName.Length();
- const TInt firstnameLen = firstName.Length();
- if(lastnameLen)
- {
- matched = pFindUtilEce->MatchRefineL(lastName, searchQuery);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- }
- }
-
- if(!matched && firstnameLen)
- {
- matched = pFindUtilEce->MatchRefineL(firstName, searchQuery);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
- }
- }
-
- token.Append(lastName);
- token.Append(firstName);
- if (!matched && lastnameLen && firstnameLen)
- {
- matched = pFindUtilEce->MatchRefineL(token, searchQuery);
-
- if (matched)
- {
- psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
- psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
- }
- }
- }
-
- if (matched)
- {
- // Extract matched character sequence, don't need to be accurate for Chinese variant
- const TInt len = 1;
-
- HBufC* seq = HBufC::NewLC(len);
- *seq = token.Mid(0, len);
- seq->Des().UpperCase();
-
- TIdentityRelation<TDesC> rule(Compare1);
- if (tempMatchSeq.Find(seq, rule) == KErrNotFound)
- {
- tempMatchSeq.Append(seq);
- CleanupStack::Pop();
- }
- else
- {
- CleanupStack::PopAndDestroy();
- }
-
- // Add the result
- if (isSearchInGroup)
- {
- if (aContactsInGroup.Find(psData->Id()) != KErrNotFound)
- {
- aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
- }
- }
- else
- {
- aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
- }
- }
-
- // Cleanup the match sequence array as
- // they are stored in pattern details structure
- tempMatchSeq.ResetAndDestroy();
- }
-
- PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsMixedL") );
+ PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsSingleL") );
}
// ----------------------------------------------------------------------------
@@ -899,93 +419,156 @@
void CPcsAlgorithm2Helper::SortSearchSeqsL(RPointerArray<TDesC>& aSearchSeqs)
{
// Sort the search seqs
- TLinearOrder<TDesC> rule(Compare2);
+ TLinearOrder<TDesC> rule( CPcsAlgorithm2Utils::MyCompareC );
aSearchSeqs.Sort(rule);
}
-// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::ExtractQueryL()
-// Required for mixed mode search.
-// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::ExtractQueryL(CPsQuery& aQuery, TDes& aOutput)
+// ---------------------------------------------------------------------------
+// CPcsAlgorithm2Helper::CreteNameBufLC
+// Update name order according to Phonebook setting
+// ---------------------------------------------------------------------------
+HBufC* CPcsAlgorithm2Helper::CreateNameBufLC( const CPsData& aContactData,
+ TInt aFirstNameIndex, TInt aLastNameIndex ) const
{
- for (int i = 0; i < aQuery.Count(); i++)
+ const TDesC& firstName( *aContactData.Data(aFirstNameIndex) );
+ const TDesC& lastName( *aContactData.Data(aLastNameIndex) );
+ CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
+ HBufC* fullName = NULL;
+
+ if ( pFindUtilEce->IsChineseWordIncluded( lastName ) ||
+ pFindUtilEce->IsChineseWordIncluded( firstName ) )
{
- if (aQuery.GetItemAtL(i).Mode() == EItut)
+ fullName = HBufC::NewLC( lastName.Length() + firstName.Length() + 1 );
+ TPtr fullNamePtr = fullName->Des();
+
+ // Form the full name according the Phonebook name order setting. Typically,
+ // the order is always lastname-firstname in Chinese variants. However, at least
+ // currently it is possible to change this from Contacts app if UI language has
+ // been set to English.
+ if ( iNameOrder == ELastnameFirstname )
{
- TBuf<KPsQueryMaxLen> outBuf;
- keyMap->GetNumericKeyString(aQuery.QueryAsStringLC(), outBuf);
- aOutput.Append(outBuf[i]);
- CleanupStack::PopAndDestroy();
+ fullNamePtr.Append( lastName );
+ //Holds the first char of first name of a contact
+ TBuf<10> firstChar;
+ firstChar.Zero();
+
+ if(firstName.Length())
+ {
+ firstChar.Append(firstName[0]);
+ // There is no space between LastName and FirstName in Chinese Name
+ // except that the firstChar of FirstName isn't Chinese character
+ if ( !pFindUtilEce->IsChineseWordIncluded( firstChar ) )
+ {
+ fullNamePtr.Append( KSpace );
+ }
+ fullNamePtr.Append( firstName );
+ }
}
else
{
- aOutput.Append(aQuery.GetItemAtL(i).Character());
+ fullNamePtr.Append( firstName );
+ //Holds the first char of last name of a contact
+ TBuf<10> firstChar;
+ firstChar.Zero();
+
+ if(lastName.Length())
+ {
+ firstChar.Append(lastName[0]);
+ // There is no space between LastName and FirstName in Chinese Name
+ // except that the firstChar of Lastname isn't Chinese character
+ if ( !pFindUtilEce->IsChineseWordIncluded( firstChar ) )
+ {
+ fullNamePtr.Append( KSpace );
+ }
+ fullNamePtr.Append( lastName );
+ }
+ }
+ }
+ else
+ {
+ fullName = HBufC::NewLC( lastName.Length() + firstName.Length() + 1 );
+ TPtr fullNamePtr = fullName->Des();
+
+ // Form the full name according the Phonebook name order setting. Typically,
+ // the order is always lastname-firstname in Chinese variants. However, at least
+ // currently it is possible to change this from Contacts app if UI language has
+ // been set to English.
+ if ( iNameOrder == ELastnameFirstname )
+ {
+ fullNamePtr.Append( lastName );
+ fullNamePtr.Append( KSpace );
+ fullNamePtr.Append( firstName );
+ }
+ else
+ {
+ fullNamePtr.Append( firstName );
+ fullNamePtr.Append( KSpace );
+ fullNamePtr.Append( lastName );
+ }
+ }
+
+ return fullName;
+ }
+
+// ---------------------------------------------------------------------------
+// CPcsAlgorithm2Helper::UpdateNameOrderL
+// Update name order according to Phonebook setting
+// ---------------------------------------------------------------------------
+void CPcsAlgorithm2Helper::UpdateNameOrderL()
+ {
+ /*
+ * Phonebook name ordering flag, integer value, possible values:
+ * 0: name order Lastname Firstname
+ * 1: name order Firstname Lastname
+ * 2: name order undefined
+ */
+ TInt nameOrderSetting;
+ iPbkSettings->Get( MPbkGlobalSetting::ENameOrdering, nameOrderSetting );
+
+ switch ( nameOrderSetting )
+ {
+ case 0:
+ {
+ iNameOrder = ELastnameFirstname;
+ break;
+ }
+ case 1:
+ {
+ iNameOrder = EFirstnameLastname;
+ break;
+ }
+ case 2:
+ default:
+ {
+ // Decide name order based on UI language: lastname-firstname
+ // for Chinese, firstname-lastname for the rest of languages.
+ TLanguage uiLang = User::Language();
+ if ( uiLang == ELangPrcChinese ||
+ uiLang == ELangHongKongChinese ||
+ uiLang == ELangTaiwanChinese )
+ {
+ iNameOrder = ELastnameFirstname;
+ }
+ else
+ {
+ iNameOrder = EFirstnameLastname;
+ }
}
}
}
-// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::ExtractQueryL()
-// Required for mixed mode search.
-// ----------------------------------------------------------------------------
-void CPcsAlgorithm2Helper::ExtractQueryL(TDesC& aInput, CPsQuery& aQuery, TDes& aOutput)
+// ---------------------------------------------------------------------------
+// CPcsAlgorithm2Helper::SettingChangedL
+// From MPbkGlobalSettingObserver
+// ---------------------------------------------------------------------------
+void CPcsAlgorithm2Helper::SettingChangedL( MPbkGlobalSetting::TPbkGlobalSetting aKey )
{
- TInt len = -1;
-
- if (aInput.Length() > aQuery.Count())
- {
- len = aQuery.Count();
- }
- else
+ if ( aKey == MPbkGlobalSetting::ENameOrdering )
{
- len = aInput.Length();
- }
-
- for (int i = 0; i < len; i++)
- {
- if (aQuery.GetItemAtL(i).Mode() == EItut)
- {
- TBuf<KPsQueryMaxLen> outBuf;
- keyMap->GetNumericKeyString(aInput, outBuf);
- aOutput.Append(outBuf[i]);
- }
- else
- {
- aOutput.Append(aInput[i]);
- }
+ UpdateNameOrderL();
}
}
-// ----------------------------------------------------------------------------
-// CPcsAlgorithm2Helper::FilterDataFieldsL()
-// Constructs a bit pattern using the required/supported data fields
-// For example, 6, 4 and 27 are supported fields <-- 00000111
-// 6 and 4 are required fields <-- 00000011
-// Bit pattern returned is 00000011.
-// ----------------------------------------------------------------------------
-TUint8 CPcsAlgorithm2Helper::FilterDataFieldsL(RArray<TInt>& aRequiredDataFields,
- RArray<TInt>& aSupportedDataFields)
- {
- TUint8 filteredMatch = 0x0;
-
- for (int i = 0; i < aSupportedDataFields.Count(); i++)
- {
- for (int j = 0; j < aRequiredDataFields.Count(); j++)
- {
- if (aSupportedDataFields[i] == aRequiredDataFields[j])
- {
- TReal val;
- Math::Pow(val, 2, i);
-
- filteredMatch |= (TUint8) val;
- }
- }
- }
-
- return filteredMatch;
- }
-
// End of file