diff -r 2666d9724c76 -r d4f567ce2e7c predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2Helper.cpp --- 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 +#include #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& aContactsInGroup, - RPointerArray& searchResults, - RPointerArray& searchSeqs) +void CPcsAlgorithm2Helper::SearchSingleL(const CPsSettings& aSettings, + CPsQuery& aPsQuery, + TBool aIsSearchInGroup, + const RArray& aContactsInGroup, + RPointerArray& aSearchResults, + RPointerArray& 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 aDataStores; - aSettings.SearchUrisL(aDataStores); + RPointerArray dataStores; + CleanupResetAndDestroyPushL( dataStores ); + aSettings.SearchUrisL(dataStores); // Get the required display fields from the client RArray 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 elements; + CleanupClosePushL( elements ); + const TInt dataStoresCount = dataStores.Count(); - for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++) + for (TInt dsIndex = 0; dsIndex < dataStoresCount; dsIndex++) { - - RPointerArray *temp = new (ELeave) RPointerArray (); - iSearchResultsArr.Append(temp); + RPointerArray* temp = new (ELeave) RPointerArray (); + 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 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& aContactsInGroup, - RPointerArray& searchResults, - RPointerArray& 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 aDataStores; - aSettings.SearchUrisL(aDataStores); - - // Get the required display fields from the client - RArray requiredDataFields; - aSettings.DisplayFieldsL(requiredDataFields); - - // Perform search for each required data store - RPointerArray elements; - - for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++) - { - RPointerArray *temp = new (ELeave) RPointerArray (); - 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& aContactsInGroup, - RPointerArray& searchResults, - RPointerArray& 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 aDataStores; - aSettings.SearchUrisL(aDataStores); - - // Get the required display fields from the client - RArray requiredDataFields; - aSettings.DisplayFieldsL(requiredDataFields); - - // Perform search for each of the required data stores - RPointerArray elements; - - for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++) - { - - RPointerArray *temp = new (ELeave) RPointerArray (); - 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& /*aMatchSet*/, - CPsQuery& /*aPsQuery*/, - RArray& aMatchLocation) +void CPcsAlgorithm2Helper::SearchMatchSeqL(CPsQuery& aPsQuery, + const TDesC& aData, + RPointerArray& aMatchSet, + RArray& 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 matchPos; + CleanupClosePushL( matchPos ); + RArray 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& searchSet, - const TDesC& searchQuery, - TBool isSearchInGroup, - RArray& aContactsInGroup) +void CPcsAlgorithm2Helper::FilterResultsSingleL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, + RPointerArray& aSearchSet, + CPsQuery& aSearchQuery, + TUint8 aFilteredDataMatch, + TBool aIsSearchInGroup, + const RArray& 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 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 (searchSet[index]); + CPcsPoolElement* poolElement = static_cast (aSearchSet[index]); CPsData* psData = poolElement->GetPsData(); psData->ClearDataMatches(); - RPointerArray tempMatchSeq; - // Search thru multiple words - TBuf token; - TBuf firstName; - TBuf 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 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& searchSet, - const TDesC& searchQuery,TBool isSearchInGroup, - RArray& 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 (searchSet[index]); - CPsData* psData = poolElement->GetPsData(); - psData->ClearDataMatches(); - RPointerArray tempMatchSeq; + RPointerArray tempMatchSeq; + CleanupClosePushL( tempMatchSeq ); - // Parse thru each data and filter the results - TBuf token; - TBuf firstName; - TBuf 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 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& searchSet, - CPsQuery& searchQuery, TBool isSearchInGroup, - RArray& 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 (searchSet[index]); - CPsData* psData = poolElement->GetPsData(); - psData->ClearDataMatches(); - RPointerArray tempMatchSeq; - - // Parse thru each data and filter the results - TBuf<255> token; - TBuf firstName; - TBuf 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 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& aSearchSeqs) { // Sort the search seqs - TLinearOrder rule(Compare2); + TLinearOrder 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 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 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& aRequiredDataFields, - RArray& 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