phoneuis/easydialing/src/easydialingplugin.cpp
branchRCL_3
changeset 5 2a26698d78ba
parent 4 24062c24fe38
child 6 38529f706030
equal deleted inserted replaced
4:24062c24fe38 5:2a26698d78ba
   126 
   126 
   127 static HBufC* AllocWithoutHighlightSeparatorsLC( TDesC& aDesc );
   127 static HBufC* AllocWithoutHighlightSeparatorsLC( TDesC& aDesc );
   128 
   128 
   129 static TBool IsItuTCharacter( TChar aChar );
   129 static TBool IsItuTCharacter( TChar aChar );
   130 
   130 
   131 // FORWARD DECLARATIONS
   131 static TInt Find( const MVPbkContactLink* aLink, const RPointerArray<MVPbkContactLink>& aArray );
   132 
   132 
   133 using namespace AknLayoutScalable_Avkon;
   133 template <class T>
       
   134 inline void CleanupResetAndDestroyPushL(T& aRef);
       
   135 
   134 
   136 
   135 
   137 
   136 // -----------------------------------------------------------------------------
   138 // -----------------------------------------------------------------------------
   137 // CEasyDialingPlugin
   139 // CEasyDialingPlugin
   138 // The default c++ constructor
   140 // The default c++ constructor
   281     LOGSTRING("EasyDialingPlugin: Plugin unloaded");
   283     LOGSTRING("EasyDialingPlugin: Plugin unloaded");
   282     }
   284     }
   283 
   285 
   284 
   286 
   285 // -----------------------------------------------------------------------------
   287 // -----------------------------------------------------------------------------
   286 // Initialize
   288 // InitializeL
   287 // Initialises easy dialing.
   289 // Initialises easy dialing.
   288 // -----------------------------------------------------------------------------
   290 // -----------------------------------------------------------------------------
   289 //
   291 //
   290 void CEasyDialingPlugin::InitializeL( CCoeControl& aParent )
   292 void CEasyDialingPlugin::InitializeL( CCoeControl& aParent )
   291     {
   293     {
   408 
   410 
   409     iPredictiveSearchQuery = CPsQuery::NewL();
   411     iPredictiveSearchQuery = CPsQuery::NewL();
   410     }
   412     }
   411 
   413 
   412 // -----------------------------------------------------------------------------
   414 // -----------------------------------------------------------------------------
   413 // GetContactFields
   415 // SetSortOrderL
   414 // -----------------------------------------------------------------------------
   416 // -----------------------------------------------------------------------------
   415 //
   417 //
   416 void CEasyDialingPlugin::SetSortOrderL( CEasyDialingContactDataManager::TNameOrder aNameOrder )
   418 void CEasyDialingPlugin::SetSortOrderL( CEasyDialingContactDataManager::TNameOrder aNameOrder )
   417     {
   419     {
   418     RArray<TInt> fields;
   420     RArray<TInt> fields;
   430     if ( iCompanyNamePCSIndex != KErrNotFound )
   432     if ( iCompanyNamePCSIndex != KErrNotFound )
   431         {
   433         {
   432         fields.Append(R_VPBK_FIELD_TYPE_COMPANYNAME);
   434         fields.Append(R_VPBK_FIELD_TYPE_COMPANYNAME);
   433         }
   435         }
   434     iPredictiveContactSearchHandler->ChangeSortOrderL( *iContactDataStores[0], fields );
   436     iPredictiveContactSearchHandler->ChangeSortOrderL( *iContactDataStores[0], fields );
   435     CleanupStack::PopAndDestroy(); //fields
   437     CleanupStack::PopAndDestroy( &fields );
   436     }
   438     }
   437 
   439 
   438 // -----------------------------------------------------------------------------
   440 // -----------------------------------------------------------------------------
   439 // OfferKeyEventL
   441 // OfferKeyEventL
   440 // Check the received keypad event and performs user
   442 // Check the received keypad event and performs user
   710                     }
   712                     }
   711                 else
   713                 else
   712                     {
   714                     {
   713                     // We get here if user e.g. leaves dialer open and goes to Contacts
   715                     // We get here if user e.g. leaves dialer open and goes to Contacts
   714                     // application and does some editing.
   716                     // application and does some editing.
       
   717                     iContactDataManager->Reload(); // to update thumbnails
   715                     AsyncActionLaunchL( ELaunchSearch );
   718                     AsyncActionLaunchL( ELaunchSearch );
   716                     }
   719                     }
   717                 }
   720                 }
   718             }
   721             }
   719             
   722             
   845     {
   848     {
   846     if ( iSearchString.Length() == 0 )
   849     if ( iSearchString.Length() == 0 )
   847         {
   850         {
   848         return;
   851         return;
   849         }
   852         }
   850    
   853     
   851     iDiscardCompletingSearches = EFalse;
   854     iDiscardCompletingSearches = EFalse;
   852     iNewSearchNeeded = EFalse;
   855     iNewSearchNeeded = EFalse;
   853     
   856     
   854     iPredictiveSearchQuery->Reset();
   857     iPredictiveSearchQuery->Reset();
   855 
   858 
   891 // Called after predictive search has been completed.
   894 // Called after predictive search has been completed.
   892 // -----------------------------------------------------------------------------
   895 // -----------------------------------------------------------------------------
   893 //
   896 //
   894 void CEasyDialingPlugin::HandlePsResultsUpdate( RPointerArray<CPsClientData>& aResults, RPointerArray<CPsPattern>& aSeqs )
   897 void CEasyDialingPlugin::HandlePsResultsUpdate( RPointerArray<CPsClientData>& aResults, RPointerArray<CPsPattern>& aSeqs )
   895     {
   898     {
   896     if (iCenrepListener && iCenrepListener->Value() == 0)
   899     if ( !IsEnabled() )
   897         {
   900         {
   898         // Easydialing is off. We should arrive here only if user turned it off while a search was happening.
   901         // Easydialing is off. We should arrive here only if user turned it off while a search was happening.
   899         Reset();
   902         Reset();
   900         return;
   903         return;
   901         }
   904         }
   902     TRAPD( leaveError, HandlePsResultsUpdateL( aResults, aSeqs ) );
   905     TRAPD( leaveError, HandlePsResultsUpdateL( aResults, aSeqs ) );
   903 
   906 
   904     if( leaveError )
   907     if ( leaveError )
   905         {
   908         {
   906         OstTrace1( TRACE_ERROR, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATE, "HandlePsResultsUpdate failed: %d", leaveError );
   909         OstTrace1( TRACE_ERROR, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATE, "HandlePsResultsUpdate failed: %d", leaveError );
   907         LOGSTRING1("EasyDialingPlugin: HandlePsResultsUpdate failed: %d", leaveError );
   910         LOGSTRING1("EasyDialingPlugin: HandlePsResultsUpdate failed: %d", leaveError );
   908         }
   911         }
   909     }
   912     }
  1005         }
  1008         }
  1006 
  1009 
  1007     OstTrace1( TRACE_NORMAL, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATEL_MATCHES, "Matching results from PCS: %d", numberOfPCSMatches );
  1010     OstTrace1( TRACE_NORMAL, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATEL_MATCHES, "Matching results from PCS: %d", numberOfPCSMatches );
  1008     LOGSTRING1("EasyDialingPlugin: Matching results from PCS: %d", numberOfPCSMatches );
  1011     LOGSTRING1("EasyDialingPlugin: Matching results from PCS: %d", numberOfPCSMatches );
  1009 
  1012 
  1010     if ( numberOfPCSMatches > 0 )
  1013     // retrieve the name order before adding
  1011         {
  1014     CEasyDialingContactDataManager::TNameOrder nameOrder = iContactDataManager->NameOrder();
  1012         // retrieve the name order before adding
  1015 
  1013         CEasyDialingContactDataManager::TNameOrder nameOrder = iContactDataManager->NameOrder();
  1016     RPointerArray<MVPbkContactLink> favsFoundByPcs;
  1014 
  1017     CleanupResetAndDestroyPushL( favsFoundByPcs );
  1015         // map results to old contact match data
  1018     
  1016         for( TInt i = 0; i < numberOfPCSMatches; i++ )
  1019     // Update the model
  1017             {
  1020     // ----------------
  1018             TInt indexFromEnd = numberOfPCSMatches - i - 1;
  1021     for ( TInt i = 0; i < numberOfPCSMatches; i++ )
  1019 
  1022         {
  1020             MVPbkContactLink* link = iPredictiveContactSearchHandler->ConvertToVpbkLinkLC(
  1023         TInt indexFromEnd = numberOfPCSMatches - i - 1;
  1021                     *(aResults[indexFromEnd]), *iContactManager );
  1024 
  1022             if ( !iContactDataManager->IsFavL( link ) )
  1025         MVPbkContactLink* link = iPredictiveContactSearchHandler->ConvertToVpbkLinkLC(
  1023                 {
  1026                 *(aResults[indexFromEnd]), *iContactManager );
  1024                 // handle favourites separately, in another loop
  1027         if ( !iContactDataManager->IsFavL( link ) )
  1025                 HBufC* contactString = CreateContactStringLC( aResults[ indexFromEnd ], nameOrder );
  1028             {
  1026                 CreateListBoxContactStringL( *contactString, link, matchThumbnails, EFalse );
  1029             // handle favourites separately, in another loop
  1027                 CleanupStack::PopAndDestroy( contactString );
  1030             HBufC* contactString = CreateContactStringLC( aResults[ indexFromEnd ], nameOrder );
  1028                 }
  1031             CreateListBoxContactStringL( *contactString, link, matchThumbnails, EFalse );
       
  1032             CleanupStack::PopAndDestroy( contactString );
  1029             CleanupStack::PopAndDestroy( link );
  1033             CleanupStack::PopAndDestroy( link );
  1030             
  1034             }
  1031             OstTraceExt2( TRACE_NORMAL, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATEL_SHOW_MATCH, "Contact #%d: '%S'", i+1, iContactStringCreationBuffer );
  1035         else
  1032             LOGSTRING2("EasyDialingPlugin: Contact #%d: '%S'", i+1, &iContactStringCreationBuffer );    
  1036             {
  1033             }
  1037             // favourites are handled later
  1034 
  1038             favsFoundByPcs.AppendL( link );
  1035         TInt numberOfFavs( iContactDataManager->NumberOfFavsL() );
  1039             CleanupStack::Pop( link );
  1036         TBuf<KBufferMaxLen> results;
  1040             }
  1037         for ( TInt i = numberOfFavs - 1; i >= 0; i-- )
  1041         
  1038             {
  1042         OstTraceExt2( TRACE_NORMAL, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATEL_SHOW_MATCH, "Contact #%d: '%S'", i+1, iContactStringCreationBuffer );
  1039             // check if this fav matches the search
  1043         LOGSTRING2( "EasyDialingPlugin: Contact #%d: '%S'", i+1, &iContactStringCreationBuffer );
  1040             HBufC* favContactString = iContactDataManager->FavContactStringLC( i, nameOrder );
  1044         }
       
  1045 
       
  1046     // Search synchronously through all the favourite contacts to ensure
       
  1047     // that all favourite matches are added to bottom even when number of mathces
       
  1048     // exceeds the maximum number set to PCS
       
  1049     TInt numberOfFavs( iContactDataManager->NumberOfFavsL() );
       
  1050     TBuf<KBufferMaxLen> results;
       
  1051     for ( TInt i = numberOfFavs - 1; i >= 0; i-- )
       
  1052         {
       
  1053         HBufC* favContactString = iContactDataManager->FavContactStringLC( i, nameOrder );
       
  1054         MVPbkContactLink* link = iContactDataManager->FavLinkLC( i );
       
  1055         
       
  1056         // Check if this fav contact was returned in aResults.
       
  1057         // It's at least theoretically possible that all matches in aResults
       
  1058         // are not matched when using LookupMatchL. PCS has completely separate logics
       
  1059         // for functions SearchL and LookupMatchL and especially with Chinese variant
       
  1060         // they may return different results.
       
  1061         TBool found = ( Find( link, favsFoundByPcs ) != KErrNotFound );
       
  1062         
       
  1063         // If this fav contact was not in aResults, then use LookupMatchL
       
  1064         // to check if this contact is still a match and was excluded from aResults
       
  1065         // because maximum number of results was exceeded.
       
  1066         if ( !found )
       
  1067             {
  1041             results = KNullDesC;
  1068             results = KNullDesC;
  1042             iPredictiveContactSearchHandler->LookupMatchL(
  1069             iPredictiveContactSearchHandler->LookupMatchL(
  1043                     *iPredictiveSearchQuery, *favContactString, results );
  1070                     *iPredictiveSearchQuery, *favContactString, results );
  1044             if ( results.Length() > 0 )
  1071             found = ( results.Length() > 0 );
  1045                 {
  1072             }
  1046                 // matches, add this fav to listbox.
  1073 
  1047                 MVPbkContactLink* link = iContactDataManager->FavLinkLC( i );
  1074         if ( found )
  1048                 CreateListBoxContactStringL( *favContactString, link, matchThumbnails, ETrue );
  1075             {
  1049                 CleanupStack::PopAndDestroy(); //link
  1076             // matches, add this fav to listbox.
  1050                 }
  1077             CreateListBoxContactStringL( *favContactString, link, matchThumbnails, ETrue );
  1051             CleanupStack::PopAndDestroy( favContactString );
  1078             }
  1052             }
  1079 
  1053         
  1080         CleanupStack::PopAndDestroy(); // link
  1054         iNumberOfNames = iListBoxModel->Count();
  1081         CleanupStack::PopAndDestroy( favContactString );
       
  1082         }
       
  1083     
       
  1084     CleanupStack::PopAndDestroy( &favsFoundByPcs ); // ResetAndDestroy
       
  1085     
       
  1086     // Update the view
       
  1087     // ---------------
       
  1088     iNumberOfNames = iListBoxModel->Count();
       
  1089     if ( iNumberOfNames )
       
  1090         {
  1055         iContactListBox->SetRectToNumberOfItems( iNumberOfNames );
  1091         iContactListBox->SetRectToNumberOfItems( iNumberOfNames );
  1056         iContactListBox->HandleItemAdditionL();
  1092         iContactListBox->HandleItemAdditionL();
  1057         // Scroll the list to bottom
  1093         // Scroll the list to bottom
  1058         iContactListBox->ScrollToMakeItemVisible( iNumberOfNames-1 );
  1094         iContactListBox->ScrollToMakeItemVisible( iNumberOfNames-1 );
  1059 
       
  1060         iContactListBox->MakeVisible( ETrue );
  1095         iContactListBox->MakeVisible( ETrue );
  1061         }
  1096         }
  1062     else
  1097     else
  1063         {
  1098         {
  1064         iNumberOfNames = 0;
       
  1065         iContactListBox->MakeVisible( EFalse );
  1099         iContactListBox->MakeVisible( EFalse );
  1066         }
  1100         }
  1067 
  1101 
  1068     if ( IsFocused() )
  1102     if ( IsFocused() )
  1069         {
  1103         {
  1331         TBool videoCall = EFalse;
  1365         TBool videoCall = EFalse;
  1332         TBool message = EFalse;
  1366         TBool message = EFalse;
  1333         
  1367         
  1334         if ( iContactListBox->CurrentItemIndex() >= 0 ) 
  1368         if ( iContactListBox->CurrentItemIndex() >= 0 ) 
  1335             {
  1369             {
  1336             TInt index = iContactListBox->CurrentContactDataIndex(); 
  1370             TInt index = iContactListBox->CurrentContactDataIndex();
  1337             
  1371             
  1338             voiceCall = iContactDataManager->VoiceCallAvailable( index );
  1372             voiceCall = iContactDataManager->VoiceCallAvailable( index );
  1339             videoCall = iContactDataManager->VideoCallAvailable( index );
  1373             videoCall = iContactDataManager->VideoCallAvailable( index );
  1340             message = iContactDataManager->UniEditorAvailable( index );
  1374             message = iContactDataManager->UniEditorAvailable( index );
  1341             }
  1375             }
  1411         }
  1445         }
  1412  
  1446  
  1413     
  1447     
  1414     TBool ret(EFalse);
  1448     TBool ret(EFalse);
  1415     
  1449     
  1416     switch( aCommand )
  1450     switch ( aCommand )
  1417         {
  1451         {
  1418         case EEasyDialingOpenContact:
  1452         case EEasyDialingOpenContact:
  1419             
  1453             
  1420             iRememberFocus = ETrue;
  1454             iRememberFocus = ETrue;
  1421             AsyncActionLaunchL( ELaunchCurrentContact );
  1455             AsyncActionLaunchL( ELaunchCurrentContact );
  1493 // -----------------------------------------------------------------------------
  1527 // -----------------------------------------------------------------------------
  1494 // IsEnabled
  1528 // IsEnabled
  1495 // Check if Easy dialing is enabled in the settings
  1529 // Check if Easy dialing is enabled in the settings
  1496 // -----------------------------------------------------------------------------
  1530 // -----------------------------------------------------------------------------
  1497 //
  1531 //
  1498 TBool CEasyDialingPlugin::IsEnabled()
  1532 TBool CEasyDialingPlugin::IsEnabled() const
  1499     {
  1533     {
  1500     return ( iCenrepListener->Value() != 0 );
  1534     return ( iCenrepListener && iCenrepListener->Value() != 0 );
  1501     }
  1535     }
  1502 
  1536 
  1503 // -----------------------------------------------------------------------------
  1537 // -----------------------------------------------------------------------------
  1504 // AsyncActionLaunchL
  1538 // AsyncActionLaunchL
  1505 // Use asynchronous callback to launch action. While action is being launched,
  1539 // Use asynchronous callback to launch action. While action is being launched,
  1532     iInputBlocker = CAknInputBlock::NewCancelHandlerLC( this );
  1566     iInputBlocker = CAknInputBlock::NewCancelHandlerLC( this );
  1533     CleanupStack::Pop( iInputBlocker );
  1567     CleanupStack::Pop( iInputBlocker );
  1534     
  1568     
  1535     // This means that iInputBlocker is deleted by CAknInputBlock when
  1569     // This means that iInputBlocker is deleted by CAknInputBlock when
  1536     // it's cancelled ( we get a callback where iInputBlocker is set to NULL).
  1570     // it's cancelled ( we get a callback where iInputBlocker is set to NULL).
  1537     iInputBlocker->SetCancelDelete( iInputBlocker );                         
  1571     iInputBlocker->SetCancelDelete( iInputBlocker );
  1538     }
  1572     }
  1539 
  1573 
  1540 // -----------------------------------------------------------------------------
  1574 // -----------------------------------------------------------------------------
  1541 // AsyncCallBackToLaunchAction
  1575 // AsyncCallBackToLaunchAction
  1542 // Callback function for CAsyncCallBack class.
  1576 // Callback function for CAsyncCallBack class.
  1598     
  1632     
  1599     // Remove highlight separators. It is possible that some contactor API has problem with them.
  1633     // Remove highlight separators. It is possible that some contactor API has problem with them.
  1600     HBufC* fullName = AllocWithoutHighlightSeparatorsLC( fullNameSeparators );
  1634     HBufC* fullName = AllocWithoutHighlightSeparatorsLC( fullNameSeparators );
  1601     
  1635     
  1602     VPbkFieldTypeSelectorFactory::TVPbkContactActionTypeSelector selector( 
  1636     VPbkFieldTypeSelectorFactory::TVPbkContactActionTypeSelector selector( 
  1603             VPbkFieldTypeSelectorFactory::EEmptySelector );   
  1637             VPbkFieldTypeSelectorFactory::EEmptySelector );
  1604     
  1638     
  1605     switch ( iActionToBeLaunched ) 
  1639     switch ( iActionToBeLaunched ) 
  1606         {
  1640         {
  1607         case ECallCurrentContact:
  1641         case ECallCurrentContact:
  1608             {
  1642             {
  1624             else
  1658             else
  1625                 {
  1659                 {
  1626                 selector = VPbkFieldTypeSelectorFactory::EVoiceCallSelector;
  1660                 selector = VPbkFieldTypeSelectorFactory::EVoiceCallSelector;
  1627                 }
  1661                 }
  1628             
  1662             
  1629             CleanupStack::PopAndDestroy( sPSettings );         
  1663             CleanupStack::PopAndDestroy( sPSettings );
  1630             }
  1664             }
  1631             break;
  1665             break;
  1632             
  1666             
  1633         case EVideoCallCurrentContact:
  1667         case EVideoCallCurrentContact:
  1634             
  1668             
  1689             AsyncActionLaunchL( ECallCurrentContact );
  1723             AsyncActionLaunchL( ECallCurrentContact );
  1690             break;
  1724             break;
  1691 
  1725 
  1692         case KEasyDialingContactLongTapped:
  1726         case KEasyDialingContactLongTapped:
  1693             AsyncActionLaunchL( ELaunchCurrentContact );
  1727             AsyncActionLaunchL( ELaunchCurrentContact );
       
  1728             break;
       
  1729             
       
  1730         // Pause contact data manager when panning and flicking listbox.
       
  1731         // This ensures smooth and responsive listbox touch handling.
       
  1732         case EEventFlickStarted:
       
  1733         case EEventPanningStarted:
       
  1734             iContactDataManager->Pause( ETrue );
       
  1735             break;
       
  1736             
       
  1737         case EEventFlickStopped:
       
  1738         case EEventPanningStopped:
       
  1739             iContactDataManager->Pause( EFalse );
  1694             break;
  1740             break;
  1695             
  1741             
  1696         // We are not interested about the other listbox events.
  1742         // We are not interested about the other listbox events.
  1697         default:
  1743         default:
  1698             break;
  1744             break;
  1928          aChar == TChar('#') ||
  1974          aChar == TChar('#') ||
  1929          aChar == TChar('*') ||
  1975          aChar == TChar('*') ||
  1930          aChar == TChar('+');
  1976          aChar == TChar('+');
  1931     }
  1977     }
  1932 
  1978 
       
  1979 // -----------------------------------------------------------------------------
       
  1980 // Find contact link pointing to the same contact as given link
       
  1981 // -----------------------------------------------------------------------------
       
  1982 //
       
  1983 static TInt Find( const MVPbkContactLink* aLink, const RPointerArray<MVPbkContactLink>& aArray )
       
  1984     {
       
  1985     TInt idx = KErrNotFound;
       
  1986     for ( TInt i = 0 ; i < aArray.Count() ; ++i )
       
  1987         {
       
  1988         if ( aArray[i]->IsSame( *aLink ) )
       
  1989             {
       
  1990             idx = i;
       
  1991             i = aArray.Count();
       
  1992             }
       
  1993         }
       
  1994     return idx;
       
  1995     }
       
  1996 
       
  1997 // -----------------------------------------------------------------------------
       
  1998 // CleanupStack helpers for item owning RPointerArrays (etc)
       
  1999 // -----------------------------------------------------------------------------
       
  2000 //
       
  2001 template <class T>
       
  2002 class CleanupResetAndDestroy
       
  2003     {
       
  2004 public:
       
  2005     inline static void PushL( T& aRef )
       
  2006         { CleanupStack::PushL( TCleanupItem(&ResetAndDestroy,&aRef) ); }
       
  2007 private:
       
  2008     inline static void ResetAndDestroy( TAny *aPtr )
       
  2009         { static_cast<T*>(aPtr)->ResetAndDestroy(); }
       
  2010     };
       
  2011 
       
  2012 template <class T>
       
  2013 inline void CleanupResetAndDestroyPushL( T& aRef )
       
  2014     { CleanupResetAndDestroy<T>::PushL(aRef); }
       
  2015 
  1933 //  End of File
  2016 //  End of File
  1934 
  2017