phoneuis/easydialing/src/easydialingplugin.cpp
branchRCL_3
changeset 9 8871b09be73b
child 14 24062c24fe38
equal deleted inserted replaced
4:c84cf270c54f 9:8871b09be73b
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Easy dialing plugin.
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 
       
    20 #include "easydialingplugin.h"
       
    21 #include "easydialinglistbox.h"
       
    22 #include "easydialinglogger.h"
       
    23 #include "easydialingpanics.h"
       
    24 #include "easydialingcenreplistener.h"
       
    25 #include "easydialingcontactdatamanager.h"
       
    26 #include "easydialingutils.h"
       
    27 #include <easydialingpluginresources.rsg>
       
    28 
       
    29 // AVKON and drawing header files
       
    30 #include <gdi.h>
       
    31 #include <aknlists.h>
       
    32 #include <AknUtils.h>
       
    33 #include <e32cmn.h>
       
    34 #include <bidivisual.h>
       
    35 
       
    36 // Predictive search header files
       
    37 #include <CPsSettings.h>
       
    38 #include <CPsQuery.h>
       
    39 #include <CPsQueryItem.h>
       
    40 #include <CPsClientData.h>
       
    41 #include <CPsPattern.h>
       
    42 #include <CPsRequestHandler.h>
       
    43 
       
    44 // Virtual phonebook header files
       
    45 #include <VPbkContactStoreUris.h>
       
    46 #include <CVPbkContactStoreUriArray.h>
       
    47 #include <TVPbkContactStoreUriPtr.h>
       
    48 #include <CVPbkContactLinkArray.h>
       
    49 #include <VPbkEng.rsg> // contains virtual phonebook data fields
       
    50 #include <phoneui.rsg> 
       
    51 
       
    52 // CCA Launcher header files.
       
    53 #include <ccafactory.h>
       
    54 #include <mccaparameter.h>
       
    55 #include <mccaconnection.h>
       
    56 #include <mccaconnectionext.h> 
       
    57 
       
    58 // Service provider settings api
       
    59 #include <spsettingsvoiputils.h>
       
    60 
       
    61 // AIW header files
       
    62 #include <AiwContactAssignDataTypes.h>
       
    63 #include <AiwContactSelectionDataTypes.h>
       
    64 
       
    65 // CCA contactor service.
       
    66 #include "edcontactorservice.h"
       
    67 
       
    68 // Open system trace
       
    69 #include "OstTraceDefinitions.h"
       
    70 #ifdef OST_TRACE_COMPILER_IN_USE
       
    71 #include "easydialingpluginTraces.h"
       
    72 #endif
       
    73 
       
    74 #include <phoneappcommands.hrh>
       
    75 #include <bautils.h>    // for BaflUtils
       
    76 
       
    77 // EXTERNAL DATA STRUCTURES
       
    78 
       
    79 // EXTERNAL FUNCTION PROTOTYPES
       
    80 
       
    81 // CONSTANTS
       
    82 const TInt KEDMaximumMatchingContactsCount = 100;
       
    83 const TInt KEasyDialingListBoxModelGranularity = 8;
       
    84 const TInt KEasyDialingMaximumMatchingParts = 10;
       
    85 const TInt KErrEasyDialingNoFirstNamePCSIndexing = -2000;
       
    86 const TInt KErrEasyDialingNoLastNamePCSIndexing = -2001;
       
    87 
       
    88 const TInt KEDFlushContactDataManagerLimit = 20;
       
    89 
       
    90 const TText KHighlightSeparatorChar = 0x1F;
       
    91 _LIT(KHighlightSeparatorCharAsLiteral,"\x1F");
       
    92 const TText KListFieldSeparatorChar = '\t';
       
    93 
       
    94 const TText KArabicAndSouthEastAsianRangeStart = 0x0600;
       
    95 const TText KArabicAndSouthEastAsianRangeEnd = 0x19FF;
       
    96 const TText KArabicPresentationFormsARangenStart = 0xFB50;
       
    97 const TText KArabicPresentationFormsARangeEnd = 0xFDFF;
       
    98 const TText KArabicPresentationFormsBRangenStart = 0xFE70;
       
    99 const TText KArabicPresentationFormsBRangeEnd = 0xFEFF;
       
   100 
       
   101 const TInt KMaxRunInfoArrayCount = 20;
       
   102 
       
   103 // MACROS
       
   104 
       
   105 // LOCAL CONSTANTS AND MACROS
       
   106 _LIT(KResourceFile, "\\resource\\easydialingpluginresources.rsc");
       
   107 
       
   108 // MODULE DATA STRUCTURES
       
   109 
       
   110 // LOCAL FUNCTION PROTOTYPES
       
   111 
       
   112 TInt CompareTPsMatchLocation( const TPsMatchLocation& a1, const TPsMatchLocation& a2);
       
   113 
       
   114 void AppendStringWithMatchDataL(
       
   115         TDes& aBuffer,
       
   116         const TDesC& aText,
       
   117         CPSRequestHandler* aPSHandler,
       
   118         const CPsQuery* aPSQuery );
       
   119 
       
   120 TBool HighlightingSupportedForText( const TDesC& aText );
       
   121 
       
   122 inline TBool HighlightingSupportedForScript( TText aChar );
       
   123 
       
   124 TBool IsStrictlyBidirectional( const TDesC& aText );
       
   125 
       
   126 static HBufC* AllocWithoutHighlightSeparatorsLC( TDesC& aDesc );
       
   127 
       
   128 static TBool IsItuTCharacter( TChar aChar );
       
   129 
       
   130 // FORWARD DECLARATIONS
       
   131 
       
   132 using namespace AknLayoutScalable_Avkon;
       
   133 
       
   134 
       
   135 // -----------------------------------------------------------------------------
       
   136 // CEasyDialingPlugin
       
   137 // The default c++ constructor
       
   138 // -----------------------------------------------------------------------------
       
   139 //
       
   140 CEasyDialingPlugin::CEasyDialingPlugin() 
       
   141     : iActionToBeLaunched( ENoActionDefined )
       
   142     {
       
   143     }
       
   144 
       
   145 // -----------------------------------------------------------------------------
       
   146 // NewL
       
   147 // Create instance of concrete ECOM interface implementation.
       
   148 // -----------------------------------------------------------------------------
       
   149 //
       
   150 CEasyDialingPlugin* CEasyDialingPlugin::NewL()
       
   151     {
       
   152     OstTrace0( TRACE_NORMAL, CEASYDIALINGPLUGIN_NEWL_LOAD_PLUGIN, "Loading plugin.." );
       
   153     LOGSTRING("EasyDialingPlugin: Loading plugin..");
       
   154 
       
   155     CEasyDialingPlugin* self = new (ELeave) CEasyDialingPlugin;
       
   156     CleanupStack::PushL( self );
       
   157     self->ConstructL();
       
   158     CleanupStack::Pop( self );
       
   159 
       
   160     OstTrace0( TRACE_NORMAL, CEASYDIALINGPLUGIN_NEWL_LOAD_PLUGIN_OK, "Loading plugin completed succesfully" );
       
   161     LOGSTRING("EasyDialingPlugin: Loading plugin completed succesfully");
       
   162     return self;
       
   163     }
       
   164 
       
   165 // -----------------------------------------------------------------------------
       
   166 // ConstructL
       
   167 // Main construction handled here. Creates connection to the predictive search
       
   168 // engine and initialises all member data.
       
   169 // -----------------------------------------------------------------------------
       
   170 //
       
   171 void CEasyDialingPlugin::ConstructL()
       
   172     {
       
   173     // Create a contact store array.
       
   174     HBufC* defaultCdb = VPbkContactStoreUris::DefaultCntDbUri().AllocLC();
       
   175     iContactDataStores.AppendL( defaultCdb );
       
   176     CleanupStack::Pop( defaultCdb );
       
   177 
       
   178     // Create a contact manager instance.
       
   179     iContactStoreUriArray = CVPbkContactStoreUriArray::NewL();
       
   180     iContactStoreUriArray->AppendL( TVPbkContactStoreUriPtr( VPbkContactStoreUris::DefaultCntDbUri() ) );
       
   181     iContactManager = CVPbkContactManager::NewL( *iContactStoreUriArray );
       
   182     
       
   183     // Set contact store observer to listen to contact store events.
       
   184     iContactManager->ContactStoresL().OpenAllL( *this );
       
   185     
       
   186     PERF_MEASURE_START
       
   187 
       
   188     InitPredictiveContactSearchL();
       
   189 
       
   190     PERF_MEASURE_STOP
       
   191  
       
   192     // Find a handle to ca launcher extension MCCAConnectionExt.
       
   193     // Easydialing has to use the extension API, because it needs function CloseAppL
       
   194     // only found in extension.
       
   195     // MCCAConnection extension has to be obtained through MCCAParameter extension,
       
   196     // since MCCAConnection is not designed to be extensible API.
       
   197     MCCAParameter* parameter = TCCAFactory::NewParameterL();    
       
   198     TAny* any = parameter->CcaParameterExtension( KMCCAConnectionExtUid );
       
   199     
       
   200     // Parameter can be deallocated since "any" containing pointer to contact launcher
       
   201     // is not tied to parameter in any way.
       
   202     parameter->Close();
       
   203     
       
   204     // Cast the pointer into contact launcher object. 
       
   205     User::LeaveIfNull( any );
       
   206     iContactLauncher = static_cast<MCCAConnectionExt*>( any );
       
   207     
       
   208     iCenrepListener = CEasyDialingCenrepListener::NewL(this);
       
   209     
       
   210     iContactDataManager = new (ELeave) CEasyDialingContactDataManager(iContactManager);
       
   211     iContactDataManager->ConstructL();
       
   212     iContactDataManager->SetObserver(this);
       
   213    
       
   214     iContactorService = CEDContactorService::NewL( this );
       
   215 
       
   216     // EasyDialing resource file is attempted to be read from the same directory where the
       
   217     // executed binary is located
       
   218     TFileName dllFileName;
       
   219     Dll::FileName( dllFileName );
       
   220     
       
   221     TParse parse;
       
   222     User::LeaveIfError( parse.Set(KResourceFile, &dllFileName, NULL) );
       
   223     TFileName resourceFileName( parse.FullName() );
       
   224 
       
   225     BaflUtils::NearestLanguageFile( iCoeEnv->FsSession(), resourceFileName );
       
   226     iResourceFileOffset = iCoeEnv->AddResourceFileL( resourceFileName );
       
   227   
       
   228     SetComponentsToInheritVisibility( ETrue );
       
   229     }
       
   230 
       
   231 // ---------------------------------------------------------
       
   232 // ~CEasyDialingPlugin
       
   233 // The desctructor
       
   234 // ---------------------------------------------------------
       
   235 //
       
   236 CEasyDialingPlugin::~CEasyDialingPlugin()
       
   237     {
       
   238     iObservers.Reset();
       
   239     
       
   240     if ( iContactManager )
       
   241         {
       
   242         TRAP_IGNORE( iContactManager->ContactStoresL().CloseAll( *this ) );
       
   243         }
       
   244 
       
   245     delete iCenrepListener;
       
   246     delete iContactDataManager;
       
   247     delete iPredictiveSearchQuery;
       
   248     delete iContactManager;
       
   249     delete iContactStoreUriArray;
       
   250     iContactDataStores.ResetAndDestroy();
       
   251 
       
   252     if (iPredictiveContactSearchHandler)
       
   253         {
       
   254         iPredictiveContactSearchHandler->RemoveObserver(this);
       
   255         }
       
   256     delete iPredictiveContactSearchHandler;
       
   257 
       
   258     delete iListBoxModel;
       
   259     
       
   260     delete iContactListBox;
       
   261 
       
   262     if (iContactLauncher)
       
   263         {
       
   264         iContactLauncher->Close();
       
   265         }
       
   266     
       
   267     delete iContactorService;
       
   268     
       
   269     iCoeEnv->DeleteResourceFile( iResourceFileOffset );
       
   270     
       
   271     delete iInputBlocker;
       
   272     
       
   273     if ( iAsyncCallBack )
       
   274         {
       
   275         iAsyncCallBack->Cancel();
       
   276         }
       
   277     delete iAsyncCallBack;
       
   278     
       
   279     OstTrace0( TRACE_NORMAL, CEASYDIALINGPLUGIN_UNLOAD_PLUGIN, "Plugin unloaded" );
       
   280     LOGSTRING("EasyDialingPlugin: Plugin unloaded");
       
   281     }
       
   282 
       
   283 
       
   284 // -----------------------------------------------------------------------------
       
   285 // Initialize
       
   286 // Initialises easy dialing.
       
   287 // -----------------------------------------------------------------------------
       
   288 //
       
   289 void CEasyDialingPlugin::InitializeL( CCoeControl& aParent )
       
   290     {
       
   291     SetContainerWindowL( aParent );
       
   292     SetMopParent( &aParent );
       
   293     
       
   294     TCallBack asyncCallBack( AsyncCallBackToLaunchAction, this );
       
   295     iAsyncCallBack = new ( ELeave ) CAsyncCallBack( asyncCallBack, 
       
   296                                                     CActive::EPriorityStandard );
       
   297 
       
   298     iContactListBox = new (ELeave) CEasyDialingListBox();
       
   299     iListBoxModel = new(ELeave) CDesCArrayFlat( KEasyDialingListBoxModelGranularity );
       
   300 
       
   301     iContactListBox->ConstructL( CEikListBox::EPaintedSelection
       
   302             | CEikListBox::ENoFirstLetterMatching
       
   303             | CEikListBox::EDisableItemSpecificMenu, 
       
   304             iContactDataManager );
       
   305     iContactListBox->SetListBoxObserver(this);
       
   306 
       
   307     iContactListBox->SetMopParent(this);
       
   308 
       
   309     CTextListBoxModel* model = iContactListBox->Model();
       
   310     model->SetItemTextArray( iListBoxModel );
       
   311     model->SetOwnershipType( ELbmDoesNotOwnItemArray );
       
   312 
       
   313 
       
   314     iContactListBox->MakeVisible( EFalse );
       
   315     
       
   316     SetFocus( EFalse );    
       
   317     iContactListBox->ActivateL();
       
   318 
       
   319     }
       
   320 
       
   321 
       
   322 // -----------------------------------------------------------------------------
       
   323 // Reset
       
   324 // Resets easydialing plugin.
       
   325 // -----------------------------------------------------------------------------
       
   326 //
       
   327 void CEasyDialingPlugin::Reset()
       
   328     {
       
   329     // PCS searches completing must be discarded, if the complete
       
   330     // after Reset() -call.    
       
   331     iDiscardCompletingSearches = ETrue;
       
   332     
       
   333     iNewSearchNeeded = EFalse;
       
   334     iSearchString.Zero();
       
   335     iListBoxModel->Reset();
       
   336     iNumberOfNames = 0;
       
   337     iContactListBox->MakeVisible( EFalse );
       
   338     iContactDataManager->Reset();
       
   339     if ( IsFocused() )
       
   340         {
       
   341         SetFocus( EFalse );
       
   342         }
       
   343     }
       
   344 
       
   345 
       
   346 // -----------------------------------------------------------------------------
       
   347 // InitPredictiveContactSearchL
       
   348 // Initialises predictive contact search.
       
   349 // -----------------------------------------------------------------------------
       
   350 //
       
   351 void CEasyDialingPlugin::InitPredictiveContactSearchL()
       
   352     {
       
   353     iPredictiveContactSearchHandler = CPSRequestHandler::NewL();
       
   354     iPredictiveContactSearchHandler->AddObserverL(this);
       
   355 
       
   356     // Put the searched contact fields into array.
       
   357     RArray<TInt> contact_fields;
       
   358     CleanupClosePushL(contact_fields);
       
   359 
       
   360     // Check which relevant contact fields are indexed in PCS search.
       
   361     iFirstNamePCSIndex = FindContactFieldPCSIndexL( R_VPBK_FIELD_TYPE_FIRSTNAME );
       
   362     iLastNamePCSIndex = FindContactFieldPCSIndexL( R_VPBK_FIELD_TYPE_LASTNAME );
       
   363     iCompanyNamePCSIndex = FindContactFieldPCSIndexL( R_VPBK_FIELD_TYPE_COMPANYNAME );
       
   364 
       
   365     // If first name and last name are not indexed in PCS, easy dialing plugin
       
   366     // can not function reasonably. The function leaves, which in turn causes
       
   367     // the plugin not to be initialized.
       
   368     // Company name not being indexed is not as severe case, and does not cause a leave.
       
   369     // Fields used in PCS indexing are configured in cenrep 2000B5C6.
       
   370     if ( iFirstNamePCSIndex == KErrNotFound )
       
   371         {
       
   372         OstTrace0( TRACE_ERROR, CEASYDIALINGPLUGIN_INITPREDICTIVECONTACTSEARCHL_ERROR_NO_FIRST_NAME, "ERROR, PCS does not support first name indexing!" );
       
   373         LOGSTRING("EasyDialingPlugin: PCS does not support first name indexing => Leave");
       
   374         User::Leave( KErrEasyDialingNoFirstNamePCSIndexing );
       
   375         }
       
   376     if ( iLastNamePCSIndex == KErrNotFound )
       
   377         {
       
   378         OstTrace0( TRACE_ERROR, CEASYDIALINGPLUGIN_INITPREDICTIVECONTACTSEARCHL_ERROR_NO_LAST_NAME, "ERROR, PCS does not support last name indexing!" );
       
   379         LOGSTRING("EasyDialingPlugin: PCS does not support last name indexing => Leave");
       
   380         User::Leave( KErrEasyDialingNoLastNamePCSIndexing );
       
   381         }
       
   382 
       
   383     // First name, last name and company name (if supported) are used in PCS search.
       
   384     contact_fields.Append(R_VPBK_FIELD_TYPE_FIRSTNAME);
       
   385     contact_fields.Append(R_VPBK_FIELD_TYPE_LASTNAME);
       
   386     if ( iCompanyNamePCSIndex != KErrNotFound )
       
   387         {
       
   388         contact_fields.Append(R_VPBK_FIELD_TYPE_COMPANYNAME);
       
   389         }
       
   390 
       
   391     // Create and fill ps settings object.
       
   392     CPsSettings* ps_settings = CPsSettings::NewL();
       
   393     CleanupStack::PushL(ps_settings);
       
   394 
       
   395     ps_settings->SetSearchUrisL(iContactDataStores);
       
   396     ps_settings->SetMaxResults(KEDMaximumMatchingContactsCount);
       
   397     ps_settings->SetSortType(EAlphabetical);
       
   398     ps_settings->SetDisplayFieldsL(contact_fields);
       
   399 
       
   400     // Set the PCS settings.
       
   401     iPredictiveContactSearchHandler->SetSearchSettingsL(*ps_settings);
       
   402 
       
   403     CleanupStack::PopAndDestroy(ps_settings);
       
   404     CleanupStack::PopAndDestroy(&contact_fields);
       
   405 
       
   406     iPredictiveSearchQuery = CPsQuery::NewL();
       
   407     }
       
   408 
       
   409 // -----------------------------------------------------------------------------
       
   410 // OfferKeyEventL
       
   411 // Check the received keypad event and performs user
       
   412 // actions related to it.
       
   413 // -----------------------------------------------------------------------------
       
   414 //
       
   415 TKeyResponse CEasyDialingPlugin::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
       
   416     {
       
   417     TKeyResponse keyResponse = EKeyWasNotConsumed;
       
   418 
       
   419     if ( aKeyEvent.iCode == 0 && aKeyEvent.iScanCode != EStdKeyDevice3)
       
   420         {
       
   421         return keyResponse;
       
   422         }
       
   423 
       
   424     TInt keyCode = aKeyEvent.iCode;
       
   425     
       
   426     // Swap right and left key codes in mirrored layout. This needs to be done
       
   427     // also for action menu grid as CAknGrid handles arrow keys like this:
       
   428     // left key = next column (not item!) and right is previous column and
       
   429     // grid layout (LtR/RtL) is not taken into account when movement is done
       
   430     // in columns (always like in LtR layout). So if right key should move
       
   431     // focus to the right also in mirroded layout, key codes must be switched.
       
   432     // This kind of approach is used also e.g. in application grid.
       
   433     if ( AknLayoutUtils::LayoutMirrored() ) 
       
   434         {
       
   435         if ( keyCode == EKeyRightArrow ) keyCode = EKeyLeftArrow;
       
   436         else if ( keyCode == EKeyLeftArrow ) keyCode = EKeyRightArrow;
       
   437         }
       
   438     
       
   439 
       
   440     if ( IsFocused() )
       
   441         {
       
   442         if ( keyCode == EKeyUpArrow )
       
   443             {
       
   444             // if the focus is on the top-most item
       
   445             if ( iContactListBox->CurrentItemIndex() == 0)
       
   446                 {
       
   447                 // then focus jumps off the component.
       
   448                 SetFocus( EFalse );
       
   449                 DrawDeferred();
       
   450                 keyResponse = EKeyWasConsumed;
       
   451                 }
       
   452             else
       
   453                 {
       
   454                 keyResponse = iContactListBox->OfferKeyEventL( aKeyEvent, aType );
       
   455                 }
       
   456             }
       
   457         else if ( keyCode == EKeyDownArrow )
       
   458             {
       
   459             // if the focus is on the bottom-most item
       
   460             if ( iContactListBox->CurrentItemIndex() == (iNumberOfNames - 1) )
       
   461                 {
       
   462                 // then focus jumps off the component.
       
   463                 SetFocus( EFalse );
       
   464                 DrawDeferred();
       
   465                 keyResponse = EKeyWasConsumed;
       
   466                 }
       
   467             else
       
   468                 {
       
   469                 keyResponse = iContactListBox->OfferKeyEventL( aKeyEvent, aType );
       
   470                 }
       
   471             }
       
   472 
       
   473         else if ( keyCode == EKeyRightArrow )
       
   474             {
       
   475             iRememberFocus = ETrue;
       
   476             AsyncActionLaunchL( ELaunchCurrentContact );
       
   477             keyResponse = EKeyWasConsumed;
       
   478             }
       
   479 
       
   480         else if ( keyCode == EKeyLeftArrow )
       
   481             {
       
   482             // then focus jumps off the component.
       
   483             SetFocus( EFalse );
       
   484             DrawDeferred();
       
   485             keyResponse = EKeyWasConsumed;
       
   486             }
       
   487 
       
   488         else
       
   489             {
       
   490             // then focus jumps off the component.
       
   491             SetFocus( EFalse );
       
   492             }
       
   493         }
       
   494 
       
   495     else if ( iNumberOfNames > 0 ) // not in focus but there are contacts to show
       
   496         {
       
   497         if ( keyCode == EKeyUpArrow || keyCode == EKeyDownArrow )
       
   498             {
       
   499             SetFocus( ETrue );
       
   500             keyResponse = iContactListBox->SetFocusedWithKeyEventL( aKeyEvent, aType );
       
   501             }
       
   502         }
       
   503     return keyResponse;
       
   504     }
       
   505 
       
   506 
       
   507 // -----------------------------------------------------------------------------
       
   508 // CountComponentControls
       
   509 //
       
   510 // -----------------------------------------------------------------------------
       
   511 //
       
   512 TInt CEasyDialingPlugin::CountComponentControls() const
       
   513     {
       
   514     return iNumberOfNames > 0 ? 1 : 0;
       
   515     }
       
   516 
       
   517 
       
   518 // -----------------------------------------------------------------------------
       
   519 // ComponentControl
       
   520 //
       
   521 // -----------------------------------------------------------------------------
       
   522 //
       
   523 CCoeControl* CEasyDialingPlugin::ComponentControl( TInt aIndex ) const
       
   524     {
       
   525     return aIndex == 0 ? iContactListBox : NULL;
       
   526     }
       
   527 
       
   528 
       
   529 // -----------------------------------------------------------------------------
       
   530 // MakeVisible
       
   531 //
       
   532 // -----------------------------------------------------------------------------
       
   533 //
       
   534 void CEasyDialingPlugin::MakeVisible( TBool aVisible )
       
   535     {
       
   536     if ( aVisible != IsVisible() )
       
   537         {
       
   538         CCoeControl::MakeVisible( aVisible );
       
   539         
       
   540         if ( !aVisible && IsFocused() )
       
   541             {
       
   542             SetFocus( EFalse );
       
   543             }
       
   544         }
       
   545     }
       
   546 
       
   547 
       
   548 // -----------------------------------------------------------------------------
       
   549 // SizeChanged
       
   550 //
       
   551 // -----------------------------------------------------------------------------
       
   552 //
       
   553 void CEasyDialingPlugin::SizeChanged()
       
   554     {
       
   555     TRect rect = Rect();
       
   556     // convert rect to absolute coordinates
       
   557     rect.SetRect( PositionRelativeToScreen(), rect.Size() );
       
   558     
       
   559     iContactListBox->SetMaxRect( rect );
       
   560     iContactListBox->SetRectToNumberOfItems( iNumberOfNames );
       
   561     }
       
   562 
       
   563 
       
   564 // -----------------------------------------------------------------------------
       
   565 // FocusChanged
       
   566 //
       
   567 // -----------------------------------------------------------------------------
       
   568 //
       
   569 void CEasyDialingPlugin::FocusChanged( TDrawNow aDrawNow )
       
   570     {
       
   571     iContactListBox->SetFocus( IsFocused() );
       
   572     if( !IsFocused() )
       
   573         {
       
   574         // To be on the safe side, cancel async callback and reset input block.
       
   575         CancelActionLaunchAndInputBlock();
       
   576         }
       
   577     CCoeControl::FocusChanged( aDrawNow );
       
   578     InformObservers( MDialingExtensionObserver::EFocusChanged );
       
   579     }
       
   580 
       
   581 
       
   582 // -----------------------------------------------------------------------------
       
   583 // SetInputL
       
   584 //
       
   585 // -----------------------------------------------------------------------------
       
   586 //
       
   587 void CEasyDialingPlugin::SetInputL( const TDesC& aSearchString )
       
   588     {
       
   589     if ( !IsEnabled() )
       
   590         {
       
   591         return;
       
   592         }
       
   593     OstTraceExt1( TRACE_NORMAL, CEASYDIALINGPLUGIN_SET_INPUT, "SetInput: '%S' ", aSearchString );
       
   594     LOGSTRING1("EasyDialingPlugin: SetInput: '%S'", &aSearchString );
       
   595     
       
   596     // Earlier here was a test if the search string is the same as the one used in previous search.
       
   597     // If it was, no search was done but function returned immediately.
       
   598     // This has now been removed. It is possible that contacts have changed, and a new search
       
   599     // may be needed even if the search string is the same. 
       
   600     
       
   601     // Check if search string is just empty space or 0-length. Decision was made that no
       
   602     // matches are shown if search string is just space (would show all contacts)
       
   603     // even if somebody might have unnamed contacts. Should be quite rare.
       
   604     // It's assumed later on in the code that string is not just empty space.
       
   605     TLex searchString( aSearchString );
       
   606     searchString.SkipSpace();
       
   607     if ( searchString.Eos() )
       
   608         {
       
   609         // the end of the string reached after skipping empty space
       
   610         Reset();
       
   611         }
       
   612     else // proper search string
       
   613         {
       
   614         iSearchString.Copy( aSearchString.Left( iSearchString.MaxLength() ) );
       
   615         LaunchSearchL();
       
   616         }
       
   617     }
       
   618 
       
   619 
       
   620 // -----------------------------------------------------------------------------
       
   621 // MatchingContactCount
       
   622 //
       
   623 // -----------------------------------------------------------------------------
       
   624 //
       
   625 TInt CEasyDialingPlugin::MatchingContactCount()
       
   626     {
       
   627     return iNumberOfNames;
       
   628     }
       
   629 
       
   630 
       
   631 // -----------------------------------------------------------------------------
       
   632 // CEasyDialingPlugin::StoreReady
       
   633 // From MVPbkContactStoreListObserver.
       
   634 //
       
   635 // -----------------------------------------------------------------------------
       
   636 //
       
   637 void CEasyDialingPlugin::StoreReady(MVPbkContactStore& /* aContactStore */)
       
   638     {
       
   639     
       
   640     }
       
   641 
       
   642 
       
   643 // -----------------------------------------------------------------------------
       
   644 // CEasyDialingPlugin::StoreUnavailable
       
   645 // From MVPbkContactStoreListObserver.
       
   646 //
       
   647 // -----------------------------------------------------------------------------
       
   648 //
       
   649 void CEasyDialingPlugin::StoreUnavailable(MVPbkContactStore& /* aContactStore */, TInt /* aReason */)
       
   650     {
       
   651     
       
   652     }
       
   653 
       
   654 
       
   655 // -----------------------------------------------------------------------------
       
   656 // CEasyDialingPlugin::HandleStoreEventL
       
   657 // From MVPbkContactStoreListObserver.
       
   658 //
       
   659 // -----------------------------------------------------------------------------
       
   660 //
       
   661 void CEasyDialingPlugin::HandleStoreEventL( MVPbkContactStore& /* aContactStore */, 
       
   662                         TVPbkContactStoreEvent aStoreEvent)
       
   663     {
       
   664     // Store's observers are informed one by one using active object so one shouldn't
       
   665     // perform search syncronously as one must try to ensure that PCS has had a
       
   666     // chance to update its store. However there seems to be no way to be
       
   667     // 100% sure that PCS is up-to-date when search is launched: telephony app
       
   668     // has such a high priority and there are no APIs to query PCS' status.
       
   669     switch ( aStoreEvent.iEventType )
       
   670         {
       
   671         case TVPbkContactStoreEvent::EContactAdded:
       
   672         case TVPbkContactStoreEvent::EContactDeleted:
       
   673         case TVPbkContactStoreEvent::EContactChanged:
       
   674             {
       
   675             if ( iSearchString.Length() > 0 )
       
   676                 {
       
   677                 if ( iContactLauncherActive )
       
   678                     {
       
   679                     // Set the flag to make a search when communication launcher exits.
       
   680                     iNewSearchNeeded = ETrue;                   
       
   681                     }
       
   682                 else
       
   683                     {
       
   684                     // We get here if user e.g. leaves dialer open and goes to Contacts
       
   685                     // application and does some editing.
       
   686                     AsyncActionLaunchL( ELaunchSearch );
       
   687                     }
       
   688                 }
       
   689             }
       
   690             
       
   691             break;
       
   692        
       
   693         default:
       
   694             
       
   695             break;
       
   696         }
       
   697     
       
   698 
       
   699     
       
   700     }
       
   701 
       
   702 
       
   703 // -----------------------------------------------------------------------------
       
   704 // CEasyDialingPlugin::OpenComplete
       
   705 // From MVPbkContactStoreListObserver.
       
   706 //
       
   707 // -----------------------------------------------------------------------------
       
   708 //
       
   709 void CEasyDialingPlugin::OpenComplete()
       
   710     {
       
   711     }
       
   712 
       
   713 // -----------------------------------------------------------------------------
       
   714 // EasyDialingSettingsChanged
       
   715 // From MEasyDialingCenrepListenerObserver
       
   716 // -----------------------------------------------------------------------------
       
   717 //
       
   718 void CEasyDialingPlugin::EasyDialingSettingsChanged( TInt aValue )
       
   719     {
       
   720     if ( aValue == 0 )
       
   721         {
       
   722         Reset();
       
   723         InformObservers( MDialingExtensionObserver::EEasyDialingDisabled );
       
   724         }
       
   725     else if ( aValue == 1 )
       
   726         {
       
   727         InformObservers( MDialingExtensionObserver::EEasyDialingEnabled );
       
   728         }
       
   729     MakeVisible( aValue );
       
   730     }
       
   731 
       
   732 // -----------------------------------------------------------------------------
       
   733 // EasyDialingContactThumbnailsSettingsChanged
       
   734 // From MEasyDialingCenrepListenerObserver
       
   735 // -----------------------------------------------------------------------------
       
   736 //
       
   737 void CEasyDialingPlugin::EasyDialingContactThumbnailsSettingsChanged( TInt aThumbnailSettingValue )
       
   738     {
       
   739     iContactDataManager->SetContactThumbnailSetting( aThumbnailSettingValue );
       
   740     iContactDataManager->Reload();
       
   741     DrawDeferred();
       
   742     }
       
   743 
       
   744 // -----------------------------------------------------------------------------
       
   745 // AllContactDataLoaded
       
   746 // From MContactDataManagerObserver
       
   747 // -----------------------------------------------------------------------------
       
   748 //
       
   749 void CEasyDialingPlugin::AllContactDataLoaded()
       
   750     {
       
   751     iContactListBox->DrawDeferred();
       
   752     }
       
   753 
       
   754 // -----------------------------------------------------------------------------
       
   755 // InformContactorEvent
       
   756 // From MEDContactorObserver
       
   757 // -----------------------------------------------------------------------------
       
   758 //
       
   759 void CEasyDialingPlugin::InformContactorEvent( MEDContactorObserver::TEvent aEvent )
       
   760     {
       
   761 
       
   762     // This callback function simply propagates the events to its own listener.
       
   763     switch ( aEvent )
       
   764         {
       
   765         case MEDContactorObserver::ECommunicationStarted:
       
   766             InformObservers( MDialingExtensionObserver::ECommunicationStarted );
       
   767             break;
       
   768         case MEDContactorObserver::ECommunicationCancelled:
       
   769             InformObservers( MDialingExtensionObserver::ECommunicationCancelled );
       
   770             break;
       
   771         default:
       
   772             break;
       
   773         }
       
   774     
       
   775     // Reset focus unless it is flagged to be remembered.
       
   776     if ( ! iRememberFocus )
       
   777         {
       
   778         SetFocus( EFalse );
       
   779         DrawDeferred();
       
   780         }
       
   781     
       
   782     iRememberFocus = EFalse;
       
   783     }
       
   784 
       
   785 // -----------------------------------------------------------------------------
       
   786 // Draw
       
   787 // The actual UI drawing function. Draws the easy dialing popup bubble on the
       
   788 // idle screen.
       
   789 // -----------------------------------------------------------------------------
       
   790 //
       
   791 void CEasyDialingPlugin::Draw( const TRect& /* aRect */ ) const
       
   792     {
       
   793     return;
       
   794     }
       
   795 
       
   796 
       
   797 // -----------------------------------------------------------------------------
       
   798 // LaunchSearchL
       
   799 // Initiates predictive contact search.
       
   800 // -----------------------------------------------------------------------------
       
   801 //
       
   802 void CEasyDialingPlugin::LaunchSearchL()
       
   803     {
       
   804     if ( iSearchString.Length() == 0 )
       
   805         {
       
   806         return;
       
   807         }
       
   808     
       
   809     iDiscardCompletingSearches = EFalse;
       
   810     iNewSearchNeeded = EFalse;
       
   811     
       
   812     iPredictiveSearchQuery->Reset();
       
   813 
       
   814     for ( TInt i = 0; i < iSearchString.Length(); i++ )
       
   815         {
       
   816          // Add a query item
       
   817         CPsQueryItem* item = CPsQueryItem::NewL();
       
   818         CleanupStack::PushL(item);
       
   819 
       
   820         item->SetCharacter( iSearchString[i] );
       
   821         
       
   822         // The PCS mode used with character is based on character itself,
       
   823         // not to the keyboard it is made with. While this is not strictly
       
   824         // identical to checking the used keyboard, this behaves identically
       
   825         // in most of the normal cases, and makes the logic simpler.
       
   826         if ( IsItuTCharacter( iSearchString[i] ) )
       
   827             {
       
   828             item->SetMode( EItut );
       
   829             }
       
   830         else 
       
   831             {
       
   832             item->SetMode( EQwerty );
       
   833             }
       
   834         
       
   835         iPredictiveSearchQuery->AppendL(*item);
       
   836 
       
   837         // Previous CPsQuery::AppendL takes the ownership of item.
       
   838         // Do not delete item.
       
   839         CleanupStack::Pop(item);
       
   840         }
       
   841 
       
   842     // Issue the search. SearchL is asynchronous function => returns immediately.
       
   843     iPredictiveContactSearchHandler->SearchL(*iPredictiveSearchQuery);
       
   844     }
       
   845 
       
   846 
       
   847 // -----------------------------------------------------------------------------
       
   848 // HandlePsResultsUpdate from MPsResultsObserver
       
   849 // Called after predictive search has been completed.
       
   850 // -----------------------------------------------------------------------------
       
   851 //
       
   852 void CEasyDialingPlugin::HandlePsResultsUpdate( RPointerArray<CPsClientData>& aResults, RPointerArray<CPsPattern>& aSeqs )
       
   853     {
       
   854     if (iCenrepListener && iCenrepListener->Value() == 0)
       
   855         {
       
   856         // Easydialing is off. We should arrive here only if user turned it off while a search was happening.
       
   857         Reset();
       
   858         return;
       
   859         }
       
   860     TRAPD( leaveError, HandlePsResultsUpdateL( aResults, aSeqs ) );
       
   861 
       
   862     if( leaveError )
       
   863         {
       
   864         OstTrace1( TRACE_ERROR, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATE, "HandlePsResultsUpdate failed: %d", leaveError );
       
   865         LOGSTRING1("EasyDialingPlugin: HandlePsResultsUpdate failed: %d", leaveError );
       
   866         }
       
   867     }
       
   868 
       
   869 
       
   870 // -----------------------------------------------------------------------------
       
   871 // HandlePsError from MPsResultsObserver
       
   872 // Called when search error happens.
       
   873 // -----------------------------------------------------------------------------
       
   874 //
       
   875 void CEasyDialingPlugin::HandlePsError( TInt aErrorCode )
       
   876     {
       
   877     OstTrace1( TRACE_ERROR, CEASYDIALINGPLUGIN_HANDLEPSERROR, "PCS Error: %d", aErrorCode );
       
   878     LOGSTRING1("EasyDialingPlugin: PCS Error: %d", aErrorCode );
       
   879     }
       
   880 
       
   881 // -----------------------------------------------------------------------------
       
   882 // CachingStatus from MPsResultsObserver
       
   883 // Called to update caching status.
       
   884 // -----------------------------------------------------------------------------
       
   885 //
       
   886 void CEasyDialingPlugin::CachingStatus( TCachingStatus& aStatus, TInt& aError )
       
   887     {
       
   888     OstTraceExt2( TRACE_NORMAL, CEASYDIALINGPLUGIN_CACHINGSTATUS, "PCS CachingStatus: %d, error: %d", ( TUint )( aStatus ), aError );
       
   889     LOGSTRING2("EasyDialingPlugin: PCS CachingStatus: %d, error: %d", aStatus, aError );
       
   890     }
       
   891 
       
   892 
       
   893 // -----------------------------------------------------------------------------
       
   894 // FindContactFieldPCSIndex
       
   895 // Searches the index that stores the given contact field.
       
   896 // To see possible contact field numbering, see file "vpbkeng.rsg".
       
   897 // -----------------------------------------------------------------------------
       
   898 //
       
   899 TInt CEasyDialingPlugin::FindContactFieldPCSIndexL( TInt aIndex )
       
   900     {
       
   901     RArray<TInt> fieldOrder;
       
   902     CleanupClosePushL( fieldOrder );
       
   903 
       
   904     // Current implementation searches only from default database.
       
   905     // Later this may be expanded to search SIM contacts as well.
       
   906     HBufC* default_cdb = VPbkContactStoreUris::DefaultCntDbUri().AllocLC();
       
   907 
       
   908     iPredictiveContactSearchHandler->GetDataOrderL( *default_cdb, fieldOrder );
       
   909 
       
   910     for ( TInt i = 0; i < fieldOrder.Count(); i++)
       
   911         {
       
   912         if ( fieldOrder[i] == aIndex )
       
   913             {
       
   914             CleanupStack::PopAndDestroy( default_cdb );
       
   915             CleanupStack::PopAndDestroy( &fieldOrder );
       
   916             return i;
       
   917             }
       
   918         }
       
   919 
       
   920     CleanupStack::PopAndDestroy( default_cdb );
       
   921     CleanupStack::PopAndDestroy( &fieldOrder );
       
   922     return KErrNotFound;
       
   923     }
       
   924 
       
   925 
       
   926 // -----------------------------------------------------------------------------
       
   927 // HandlePsResultsUpdateL
       
   928 // This function does the actual callback fork, and must be trapped inside
       
   929 // HandlePsResultsUpdateL.
       
   930 // -----------------------------------------------------------------------------
       
   931 //
       
   932 void CEasyDialingPlugin::HandlePsResultsUpdateL( RPointerArray<CPsClientData>& aResults, RPointerArray<CPsPattern>& /*aSeqs*/ )
       
   933     {
       
   934     // If iDiscardCompletingSearches is ETrue, don't show search results but just return.
       
   935     // If easydialing has been reset with reset function, no searches completed after that
       
   936     // can be shown.
       
   937     // This is done like this because there seems not to be a feasible way of cancelling all 
       
   938     // PCS search request in PCS API. CancelRequest does not work here.
       
   939     if ( iDiscardCompletingSearches )
       
   940         {
       
   941         return;
       
   942         }
       
   943     
       
   944     iListBoxModel->Reset();
       
   945     iContactListBox->HandleItemRemovalL();
       
   946 
       
   947     TInt numberOfPCSMatches( aResults.Count() );
       
   948     
       
   949     // Resetting the contactdatamanager causes the thumbnails to flicker a bit, because
       
   950     // we need to load the thumbnails again. But if there are lots of search results, or
       
   951     // lots of loaded thumbnails in the manager, matching the search results to the
       
   952     // thumbnail manager contents may take too much time. If there are lots of results,
       
   953     // it is likely that the contents of the listbox change anyway, so the flickering
       
   954     // doesn't matter too much. This also limits the memory usage of the manager.
       
   955     //   But if there are fewer search results, it is worth trying to match them
       
   956     // with the contents of thumbnail manager.
       
   957     
       
   958     TBool matchThumbnails(ETrue);
       
   959     if ( numberOfPCSMatches > KEDFlushContactDataManagerLimit )
       
   960         {
       
   961         iContactDataManager->Reset();
       
   962         matchThumbnails = EFalse;
       
   963         }
       
   964 
       
   965     OstTrace1( TRACE_NORMAL, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATEL_MATCHES, "Matching results from PCS: %d", numberOfPCSMatches );
       
   966     LOGSTRING1("EasyDialingPlugin: Matching results from PCS: %d", numberOfPCSMatches );
       
   967 
       
   968     if ( numberOfPCSMatches > 0 )
       
   969         {
       
   970         // retrieve the name order before adding
       
   971         CPbkContactEngine* pbkEngine = CPbkContactEngine::NewL();
       
   972         CleanupStack::PushL( pbkEngine );
       
   973         CPbkContactEngine::TPbkNameOrder nameOrder = pbkEngine->NameDisplayOrderL();
       
   974         CleanupStack::PopAndDestroy( pbkEngine );
       
   975 
       
   976         // map results to old contact match data
       
   977         for( TInt i = 0; i < numberOfPCSMatches; i++ )
       
   978             {
       
   979             TInt indexFromEnd = numberOfPCSMatches - i - 1;
       
   980 
       
   981             MVPbkContactLink* link = iPredictiveContactSearchHandler->ConvertToVpbkLinkLC(
       
   982                     *(aResults[indexFromEnd]), *iContactManager );
       
   983             if ( !iContactDataManager->IsFavL( link ) )
       
   984                 {
       
   985                 // handle favourites separately, in another loop
       
   986                 HBufC* contactString = CreateContactStringLC( aResults[ indexFromEnd ], nameOrder );
       
   987                 CreateListBoxContactStringL( *contactString, link, matchThumbnails, EFalse );
       
   988                 CleanupStack::PopAndDestroy( contactString );
       
   989                 }
       
   990             CleanupStack::PopAndDestroy( link );
       
   991             
       
   992             OstTraceExt2( TRACE_NORMAL, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATEL_SHOW_MATCH, "Contact #%d: '%S'", i+1, iContactStringCreationBuffer );
       
   993             LOGSTRING2("EasyDialingPlugin: Contact #%d: '%S'", i+1, &iContactStringCreationBuffer );    
       
   994             }
       
   995 
       
   996         TInt numberOfFavs( iContactDataManager->NumberOfFavsL() );
       
   997         TBuf<KBufferMaxLen> results;
       
   998         for ( TInt i = 0; i < numberOfFavs; i++ )
       
   999             {
       
  1000             // check if this fav matches the search
       
  1001             HBufC* favContactString = iContactDataManager->FavContactStringLC( i, nameOrder );
       
  1002             results = KNullDesC;
       
  1003             iPredictiveContactSearchHandler->LookupMatchL(
       
  1004                     *iPredictiveSearchQuery, *favContactString, results );
       
  1005             if ( results.Length() > 0 )
       
  1006                 {
       
  1007                 // matches, add this fav to listbox.
       
  1008                 MVPbkContactLink* link = iContactDataManager->FavLinkLC( i );
       
  1009                 CreateListBoxContactStringL( *favContactString, link, matchThumbnails, ETrue );
       
  1010                 CleanupStack::PopAndDestroy(); //link
       
  1011                 }
       
  1012             CleanupStack::PopAndDestroy( favContactString );
       
  1013             }
       
  1014         
       
  1015         iNumberOfNames = iListBoxModel->Count();
       
  1016         iContactListBox->SetRectToNumberOfItems( iNumberOfNames );
       
  1017         iContactListBox->HandleItemAdditionL();
       
  1018         // Scroll the list to bottom
       
  1019         iContactListBox->ScrollToMakeItemVisible( iNumberOfNames-1 );
       
  1020 
       
  1021         iContactListBox->MakeVisible( ETrue );
       
  1022         }
       
  1023     else
       
  1024         {
       
  1025         iNumberOfNames = 0;
       
  1026         iContactListBox->MakeVisible( EFalse );
       
  1027         }
       
  1028 
       
  1029     if ( IsFocused() )
       
  1030         {
       
  1031         SetFocus( EFalse );
       
  1032         }
       
  1033 
       
  1034     DrawDeferred();
       
  1035 
       
  1036     InformObservers( MDialingExtensionObserver::ESearchComplete );
       
  1037     }
       
  1038 
       
  1039 
       
  1040 // -----------------------------------------------------------------------------
       
  1041 // void CCASimpleNotifyL()
       
  1042 // Implements MCCAObserver notification interface.
       
  1043 //
       
  1044 // -----------------------------------------------------------------------------
       
  1045 //
       
  1046 void CEasyDialingPlugin::CCASimpleNotifyL( TNotifyType aType, TInt aReason )
       
  1047     {
       
  1048     OstTraceExt2( TRACE_NORMAL, CEASYDIALINGPLUGIN_CCASIMPLENOTIFYL, "CCASimpleNotifyL: type: %d, reason: %d", ( TUint )( aType ), aReason );
       
  1049     LOGSTRING2("EasyDialingPlugin: CCASimpleNotifyL: type: %d, reason: %d", (TInt)aType, aReason );
       
  1050 
       
  1051     iContactLauncherActive = EFalse;
       
  1052 
       
  1053     CAknAppUi* appUi = static_cast<CAknAppUi*>( iCoeEnv->AppUi() );
       
  1054     appUi->HandleCommandL( EPhoneCmdBlockingDialogClosed );
       
  1055     
       
  1056     // If contacts have been edited during contact launcher being open, a new search
       
  1057     // needs to be done.
       
  1058     if ( iNewSearchNeeded )
       
  1059         {
       
  1060         // The cached information in contact data manager may be outdated. Call to reload makes sure that when the 
       
  1061         // search is made, all data is loaded again.
       
  1062         iContactDataManager->Reload();
       
  1063         
       
  1064         LaunchSearchL();
       
  1065         }
       
  1066 
       
  1067     // Give up focus, if iRememberFocus flag is not set.
       
  1068     if ( ! iRememberFocus )
       
  1069         {
       
  1070         SetFocus( EFalse );
       
  1071         DrawDeferred();
       
  1072         }    
       
  1073     iRememberFocus = EFalse;
       
  1074 
       
  1075     // Inform observers.
       
  1076     InformObservers( MDialingExtensionObserver::ECCALauncherExit );
       
  1077     }
       
  1078 
       
  1079 
       
  1080 // -----------------------------------------------------------------------------
       
  1081 // void LaunchCurrentContactL()
       
  1082 // Implements MCCAObserver notification interface.
       
  1083 //
       
  1084 // -----------------------------------------------------------------------------
       
  1085 //
       
  1086 void CEasyDialingPlugin::LaunchCurrentContactL()
       
  1087     {
       
  1088     __ASSERT_DEBUG( iNumberOfNames > 0, EasyDialingPanic( EEasyDialingPanicNoResults ) );
       
  1089     __ASSERT_DEBUG( iContactListBox->CurrentItemIndex() >= 0, EasyDialingPanic( EEasyDialingPanicNoContactSelected ) );
       
  1090 
       
  1091     if (( iContactLauncherActive ) || ( iNumberOfNames == 0 ) || ( !iContactListBox ) || ( iContactListBox->CurrentItemIndex() < 0 ))
       
  1092         {
       
  1093         OstTrace0( TRACE_ERROR, CEASYDIALINGPLUGIN_LAUNCHCURRENTCONTACTL_ERROR, "LaunchCurrentContactL: Parameter error" );
       
  1094         LOGSTRING("EasyDialingPlugin: LaunchCurrentContactL - Parameter error");
       
  1095         return;
       
  1096         }
       
  1097 
       
  1098     MCCAParameter* launchParameters = TCCAFactory::NewParameterL();
       
  1099     CleanupClosePushL( *launchParameters );
       
  1100 
       
  1101     // ESoftExit flag causes that ca launcher will not close the 
       
  1102     // client application in any circumstance. 
       
  1103     // Application hosting easydialing is telephone application.
       
  1104     // It must never be closed, so we must use this flag.
       
  1105     launchParameters->SetConnectionFlag(MCCAParameter::ESoftExit);
       
  1106     
       
  1107     launchParameters->SetContactDataFlag(MCCAParameter::EContactLink);
       
  1108 
       
  1109     // Get the contact link of the current contact item.
       
  1110     HBufC8* contact8 = iContactListBox->CurrentContactLinkLC();
       
  1111     
       
  1112     // Expand it into 16-bit descriptor because cca launcher api expects this. 
       
  1113     HBufC16* contact16 = HBufC16::NewLC( contact8->Length() );
       
  1114     contact16->Des().Copy( *contact8 );
       
  1115 
       
  1116     launchParameters->SetContactDataL( *contact16 );
       
  1117 
       
  1118     CleanupStack::PopAndDestroy( contact16 );
       
  1119     CleanupStack::PopAndDestroy( contact8 );
       
  1120 
       
  1121     TPtrC selectedName = iListBoxModel->MdcaPoint( iContactListBox->CurrentItemIndex() );
       
  1122     OstTraceExt1( TRACE_NORMAL, CEASYDIALINGPLUGIN_LAUNCHCURRENTCONTACTL_LAUNCH_CCA, "Launch CL for contact: '%S'", selectedName );
       
  1123     LOGSTRING1("EasyDialingPlugin: Launch CL for contact: '%S'", &selectedName );
       
  1124 
       
  1125     iContactLauncher->LaunchAppL( *launchParameters, this );
       
  1126 
       
  1127     // Ownership of parameter transferred to CCA launcher => pop but do not destroy.
       
  1128     CleanupStack::Pop( launchParameters );
       
  1129 
       
  1130 
       
  1131     iContactLauncherActive = ETrue;
       
  1132     CAknAppUi* appUi = static_cast<CAknAppUi*>( iCoeEnv->AppUi() );
       
  1133     appUi->HandleCommandL( EPhoneCmdBlockingDialogLaunched );
       
  1134     }
       
  1135 
       
  1136 
       
  1137 // -----------------------------------------------------------------------------
       
  1138 // CreateListBoxContactStringL
       
  1139 //
       
  1140 // -----------------------------------------------------------------------------
       
  1141 //
       
  1142 void CEasyDialingPlugin::CreateListBoxContactStringL(
       
  1143         const TDesC& aContactString,
       
  1144         MVPbkContactLink *aLink,
       
  1145         TBool aMatchThumbnails,
       
  1146         TBool aFav )
       
  1147     {
       
  1148     // Construct the contact string for the listbox model.
       
  1149     iContactStringCreationBuffer.Zero();
       
  1150     
       
  1151     // Append contact thumbnail id.
       
  1152     HBufC* thumbnailId = iContactDataManager->GetThumbnailIdL( aLink, aMatchThumbnails, aFav );
       
  1153     iContactStringCreationBuffer.Append( *thumbnailId );
       
  1154     delete thumbnailId;
       
  1155     iContactStringCreationBuffer.Append( KListFieldSeparatorChar );
       
  1156     
       
  1157     AppendStringWithMatchDataL(
       
  1158             iContactStringCreationBuffer,
       
  1159             aContactString,
       
  1160             iPredictiveContactSearchHandler,
       
  1161             iPredictiveSearchQuery );
       
  1162     
       
  1163     // Append the whole string to listbox model.
       
  1164     iListBoxModel->AppendL( iContactStringCreationBuffer );
       
  1165     }
       
  1166 
       
  1167 // -----------------------------------------------------------------------------
       
  1168 // CreateContactStringLC
       
  1169 //
       
  1170 // -----------------------------------------------------------------------------
       
  1171 //
       
  1172 HBufC* CEasyDialingPlugin::CreateContactStringLC( CPsClientData* aResult, CPbkContactEngine::TPbkNameOrder aNameOrder )
       
  1173     {
       
  1174     TPtr firstName = aResult->Data( iFirstNamePCSIndex )->Des();
       
  1175     TPtr lastName = aResult->Data( iLastNamePCSIndex )->Des();
       
  1176     TPtr companyName( NULL, 0 );
       
  1177     
       
  1178     if ( iCompanyNamePCSIndex != KErrNotFound )
       
  1179         {
       
  1180         companyName.Set( aResult->Data( iCompanyNamePCSIndex )->Des() );
       
  1181         }
       
  1182     return EasyDialingUtils::CreateContactStringLC( firstName, lastName, companyName, aNameOrder );
       
  1183     }
       
  1184 
       
  1185 
       
  1186 // -----------------------------------------------------------------------------
       
  1187 // AddObserverL
       
  1188 //
       
  1189 // -----------------------------------------------------------------------------
       
  1190 //
       
  1191 void CEasyDialingPlugin::AddObserverL( MDialingExtensionObserver* aObserver )
       
  1192     {
       
  1193     if ( !aObserver )
       
  1194         {
       
  1195         return;
       
  1196         }
       
  1197     
       
  1198     User::LeaveIfError( iObservers.Append( aObserver ) );
       
  1199     }
       
  1200 
       
  1201 
       
  1202 // -----------------------------------------------------------------------------
       
  1203 // RemoveObserver
       
  1204 //
       
  1205 // Removes the parameter observer from observer list if found. If same observer
       
  1206 // has registered multiple times (which is unnecessary), removed just the first
       
  1207 // registration.
       
  1208 // -----------------------------------------------------------------------------
       
  1209 //
       
  1210 void CEasyDialingPlugin::RemoveObserver( MDialingExtensionObserver* aObserver )
       
  1211     {
       
  1212     for ( TInt i = 0; i < iObservers.Count(); i++ )
       
  1213         {
       
  1214         if ( iObservers[i] == aObserver)
       
  1215             {
       
  1216             iObservers.Remove( i );
       
  1217             return;
       
  1218             }
       
  1219         }
       
  1220     }
       
  1221 
       
  1222 
       
  1223 // -----------------------------------------------------------------------------
       
  1224 // InformObservers
       
  1225 // Informs all registered observers of easy dialing events.
       
  1226 // -----------------------------------------------------------------------------
       
  1227 //
       
  1228 void CEasyDialingPlugin::InformObservers( MDialingExtensionObserver::TEvent aEvent )
       
  1229     {
       
  1230     for ( TInt i = 0; i < iObservers.Count(); i++ )
       
  1231         {
       
  1232         iObservers[i]->HandleDialingExtensionEvent( aEvent );
       
  1233         }
       
  1234     }
       
  1235 
       
  1236 // -----------------------------------------------------------------------------
       
  1237 // CbaResourceId
       
  1238 // Returns EasyDialingPlugin specific CBA resource ID that
       
  1239 // Phone application can use when updating Soft Keys.
       
  1240 // -----------------------------------------------------------------------------
       
  1241 //
       
  1242 TInt CEasyDialingPlugin::CbaResourceId()
       
  1243     {
       
  1244     return R_EASYDIALING_CBA;
       
  1245     }
       
  1246 
       
  1247 
       
  1248 // -----------------------------------------------------------------------------
       
  1249 // MenuResourceId
       
  1250 // Returns EasyDialingPlugin specific menu resource ID that
       
  1251 // Phone application can use when easydialing is in focus.
       
  1252 // -----------------------------------------------------------------------------
       
  1253 //
       
  1254 TInt CEasyDialingPlugin::MenuResourceId()
       
  1255     {
       
  1256     return R_EASYDIALING_MENUBAR;
       
  1257     }
       
  1258 
       
  1259 
       
  1260 // -----------------------------------------------------------------------------
       
  1261 // InitializeMenuPaneL
       
  1262 // Initializes easy dialing menu pane. This function is meant to be called in 
       
  1263 // DynInitMenuPaneL of the application, if the application wants to use easy
       
  1264 // dialing menu.
       
  1265 // -----------------------------------------------------------------------------
       
  1266 //
       
  1267 TBool CEasyDialingPlugin::InitializeMenuPaneL( CEikMenuPane& aMenuPane, TInt aMenuResourceId )
       
  1268     {   
       
  1269     if ( aMenuResourceId == R_PHONEUIDIALER_OPTIONS_MENU )
       
  1270         {
       
  1271         TInt index( KErrNotFound );
       
  1272         // To be on the safe side - place holder was added into phoneui.rss.
       
  1273         if ( aMenuPane.MenuItemExists( EEasyDialingSettingsItemPlaceHolder, index ) )
       
  1274             {
       
  1275             // Add first menu item (= on/off submenu) after placeHolder item and 
       
  1276             // then delete that (empty) placeHolder.
       
  1277             aMenuPane.AddMenuItemsL( R_EASYDIALING_OPTIONS_ON_OFF_MENU_ITEM, 
       
  1278                                      EEasyDialingSettingsItemPlaceHolder );
       
  1279             aMenuPane.DeleteMenuItem( EEasyDialingSettingsItemPlaceHolder );
       
  1280             
       
  1281             LOGSTRING("EasyDialingPlugin::InitializeMenuPaneL: Added on/off menu into dialer's menu" );
       
  1282             }
       
  1283 
       
  1284         // Return EFalse as only one menu item was added here.
       
  1285         return EFalse; 
       
  1286         }
       
  1287     
       
  1288     else if ( aMenuResourceId == R_EASYDIALING_MENU )
       
  1289         {
       
  1290         TBool voiceCall = EFalse;
       
  1291         TBool videoCall = EFalse;
       
  1292         TBool message = EFalse;
       
  1293         
       
  1294         if ( iContactListBox->CurrentItemIndex() >= 0 ) 
       
  1295             {
       
  1296             TInt index = iContactListBox->CurrentContactDataIndex(); 
       
  1297             
       
  1298             voiceCall = iContactDataManager->VoiceCallAvailable( index );
       
  1299             videoCall = iContactDataManager->VideoCallAvailable( index );
       
  1300             message = iContactDataManager->UniEditorAvailable( index );
       
  1301             }
       
  1302             
       
  1303         // Call menu item is not show if neither voice call nor video call are possible. 
       
  1304         aMenuPane.SetItemDimmed( EEasyDialingVoiceCall, !voiceCall && !videoCall ); 
       
  1305         aMenuPane.SetItemDimmed( EEasyDialingSendMessage, !message ); 
       
  1306         
       
  1307         LOGSTRING("EasyDialingPlugin::InitializeMenuPaneL: InitializeMenuPaneL done" );
       
  1308         
       
  1309         return ETrue;  
       
  1310         }
       
  1311     
       
  1312     else if ( aMenuResourceId == R_EASYDIALING_OPTIONS_CALL_MENU )
       
  1313         {
       
  1314         TBool voiceCall = EFalse;
       
  1315         TBool videoCall = EFalse;
       
  1316         
       
  1317         if ( iContactListBox->CurrentItemIndex() >= 0 ) 
       
  1318             {
       
  1319             TInt index = iContactListBox->CurrentContactDataIndex();
       
  1320             
       
  1321             voiceCall = iContactDataManager->VoiceCallAvailable( index );
       
  1322             videoCall = iContactDataManager->VideoCallAvailable( index );
       
  1323             }
       
  1324         
       
  1325         aMenuPane.SetItemDimmed( EEasyDialingVoiceCall, !voiceCall ); 
       
  1326         aMenuPane.SetItemDimmed( EEasyDialingVideoCall, !videoCall ); 
       
  1327 
       
  1328         LOGSTRING("EasyDialingPlugin::InitializeMenuPaneL: InitializeMenuPaneL for call submenu done" );
       
  1329         
       
  1330         return ETrue;
       
  1331         }
       
  1332     
       
  1333     else if ( aMenuResourceId == R_EASYDIALING_OPTIONS_ON_OFF_CASCADE_MENU )
       
  1334         {
       
  1335         if ( IsEnabled() )
       
  1336             {
       
  1337             aMenuPane.SetItemButtonState( EEasyDialingOn, EEikMenuItemSymbolOn );      
       
  1338             }
       
  1339         else
       
  1340             {
       
  1341             aMenuPane.SetItemButtonState( EEasyDialingOff, EEikMenuItemSymbolOn );
       
  1342             }
       
  1343         
       
  1344         LOGSTRING("EasyDialingPlugin::InitializeMenuPaneL: InitializeMenuPaneL for on/off submenu done" );
       
  1345         
       
  1346         return ETrue;
       
  1347         }
       
  1348     
       
  1349     else 
       
  1350         {
       
  1351         return EFalse;
       
  1352         }
       
  1353     }
       
  1354 
       
  1355 // -----------------------------------------------------------------------------
       
  1356 // HandleCommandL
       
  1357 // Method for handling EasyDialingPlugin specific commands.
       
  1358 // -----------------------------------------------------------------------------
       
  1359 //
       
  1360 TBool CEasyDialingPlugin::HandleCommandL( TInt aCommand )
       
  1361     {      
       
  1362     // Input blocker can't block controls higher on the control stack than 
       
  1363     // ECoeStackPriorityDialog so we will get HandleCommandL calls from 
       
  1364     // phoneappui (CBA) when input blocker is active (=not NULL).
       
  1365     
       
  1366     if ( iInputBlocker && aCommand != EEasyDialingCallHandlingActivated )
       
  1367         {
       
  1368         // Some action is already being launched since iInputBlocker exists.
       
  1369         // Only call activation command requires always action from this plugin.
       
  1370         return ETrue;
       
  1371         }
       
  1372  
       
  1373     
       
  1374     TBool ret(EFalse);
       
  1375     
       
  1376     switch( aCommand )
       
  1377         {
       
  1378         case EEasyDialingOpenContact:
       
  1379             
       
  1380             iRememberFocus = ETrue;
       
  1381             AsyncActionLaunchL( ELaunchCurrentContact );
       
  1382             ret = ETrue;
       
  1383             break;
       
  1384 
       
  1385         // EEasyDialingEnterKeyAction is sent when Enter key is pressed.
       
  1386         // EEasyDialingMakeCall is sent when send key or send toolbar button or send menu item is pressed.
       
  1387         case EEasyDialingVoiceCall: // fall through
       
  1388         case EEasyDialingEnterKeyAction:
       
  1389             // Make a call.
       
  1390             iRememberFocus = ETrue;
       
  1391             AsyncActionLaunchL( ECallCurrentContact );
       
  1392             ret = ETrue;
       
  1393             break;
       
  1394             
       
  1395         // Video call is selectable only through menu.
       
  1396         case EEasyDialingVideoCall:
       
  1397             // Make a video call.
       
  1398             iRememberFocus = ETrue;
       
  1399             AsyncActionLaunchL( EVideoCallCurrentContact );
       
  1400             ret = ETrue;
       
  1401             break;
       
  1402                 
       
  1403         // Uni-editor message is selectable only through menu.
       
  1404         case EEasyDialingSendMessage:
       
  1405             // Create a message.
       
  1406             iRememberFocus = ETrue;
       
  1407             AsyncActionLaunchL( ESendMessageCurrentContact );
       
  1408             ret = ETrue;
       
  1409             break;
       
  1410                     
       
  1411         // EEasyDialingCallHandlingActivated is sent when the in-call-ui of telephony gets activated
       
  1412         case EEasyDialingCallHandlingActivated:
       
  1413             
       
  1414             iRememberFocus = EFalse;
       
  1415             // Stop input block and async action launch in case they are active.
       
  1416             CancelActionLaunchAndInputBlock();
       
  1417             // Close down number selection popup in case it happens to be open.
       
  1418             iContactorService->CancelService();
       
  1419             // Close down communication launcher if it's active
       
  1420             if ( iContactLauncherActive )
       
  1421                 {
       
  1422                 iNewSearchNeeded = EFalse;
       
  1423                 iContactLauncher->CloseAppL();
       
  1424                 }
       
  1425             ret = ETrue;
       
  1426             break;
       
  1427             
       
  1428         case EEasyDialingOn:
       
  1429             
       
  1430             iCenrepListener->SetEasyDialingSettingsValue( 1 );
       
  1431             ret = ETrue;
       
  1432             break;
       
  1433 
       
  1434         case EEasyDialingOff:
       
  1435             
       
  1436             iCenrepListener->SetEasyDialingSettingsValue( 0 );
       
  1437             ret = ETrue;
       
  1438             break;    
       
  1439             
       
  1440         case EEasyDialingClosePopup:
       
  1441             
       
  1442             // Not only Number Entry is removed but also closes down number selection popup in case it happens to be open.
       
  1443             iContactorService->CancelService();
       
  1444 			ret = ETrue;
       
  1445             break;
       
  1446             
       
  1447         default:
       
  1448             break;
       
  1449         }
       
  1450     return ret;
       
  1451     }
       
  1452 
       
  1453 // -----------------------------------------------------------------------------
       
  1454 // IsEnabled
       
  1455 // Check if Easy dialing is enabled in the settings
       
  1456 // -----------------------------------------------------------------------------
       
  1457 //
       
  1458 TBool CEasyDialingPlugin::IsEnabled()
       
  1459     {
       
  1460     return ( iCenrepListener->Value() != 0 );
       
  1461     }
       
  1462 
       
  1463 // -----------------------------------------------------------------------------
       
  1464 // AsyncActionLaunchL
       
  1465 // Use asynchronous callback to launch action. While action is being launched,
       
  1466 // input blocker is used to avoid OfferKeyEvent and HandlePointerEvent calls
       
  1467 // coming in. Both end key and application key work despite of input blocker.
       
  1468 // Input blocker can't block phoneappui's cba so extra check is needed in
       
  1469 // HandleCommandL method.
       
  1470 // -----------------------------------------------------------------------------
       
  1471 //
       
  1472 void CEasyDialingPlugin::AsyncActionLaunchL( const TEasyDialingAction aAction )
       
  1473     {
       
  1474     iActionToBeLaunched = aAction;
       
  1475     
       
  1476     CancelActionLaunchAndInputBlock();
       
  1477     
       
  1478     if ( aAction == ELaunchSearch )
       
  1479         {
       
  1480         // Must be set as low as possible to enable PCS to update its store.
       
  1481         iAsyncCallBack->SetPriority( CActive::EPriorityIdle );
       
  1482         }
       
  1483     else
       
  1484         {
       
  1485         iAsyncCallBack->SetPriority( CActive::EPriorityStandard );
       
  1486         }
       
  1487     
       
  1488     iAsyncCallBack->CallBack(); // activates callback request
       
  1489     
       
  1490     // By defining cancel handler, we don't block all input but system is still
       
  1491     // able to deactivate the view etc.
       
  1492     iInputBlocker = CAknInputBlock::NewCancelHandlerLC( this );
       
  1493     CleanupStack::Pop( iInputBlocker );
       
  1494     
       
  1495     // This means that iInputBlocker is deleted by CAknInputBlock when
       
  1496     // it's cancelled ( we get a callback where iInputBlocker is set to NULL).
       
  1497     iInputBlocker->SetCancelDelete( iInputBlocker );                         
       
  1498     }
       
  1499 
       
  1500 // -----------------------------------------------------------------------------
       
  1501 // AsyncCallBackToLaunchAction
       
  1502 // Callback function for CAsyncCallBack class.
       
  1503 // -----------------------------------------------------------------------------
       
  1504 //
       
  1505 TInt CEasyDialingPlugin::AsyncCallBackToLaunchAction( TAny* aPtr )
       
  1506     {
       
  1507     CEasyDialingPlugin* plugin = static_cast<CEasyDialingPlugin*>( aPtr );
       
  1508     
       
  1509     TRAP_IGNORE( plugin->DoLaunchActionL() );
       
  1510     
       
  1511     // Stop input block if active (=not NULL).
       
  1512     if ( plugin->iInputBlocker )
       
  1513         {
       
  1514         plugin->iInputBlocker->Cancel();
       
  1515         }
       
  1516     
       
  1517     plugin->iActionToBeLaunched = ENoActionDefined;
       
  1518     
       
  1519     return KErrNone;
       
  1520     }
       
  1521     
       
  1522 // -----------------------------------------------------------------------------
       
  1523 // DoLaunchActionL
       
  1524 //
       
  1525 // -----------------------------------------------------------------------------
       
  1526 //
       
  1527 void CEasyDialingPlugin::DoLaunchActionL( )
       
  1528     {
       
  1529     // If ELaunchCurrentContact, then we launch cca launcher.
       
  1530     if ( iActionToBeLaunched == ELaunchCurrentContact )
       
  1531         {
       
  1532         LaunchCurrentContactL();
       
  1533         return;
       
  1534         }
       
  1535     else if ( iActionToBeLaunched == ELaunchSearch )
       
  1536         {
       
  1537         LaunchSearchL();
       
  1538         return;
       
  1539         }
       
  1540     
       
  1541     // If not for launching current contact or performing search, 
       
  1542     // the action is launching some communication method.
       
  1543     
       
  1544     if ( iContactorService->IsBusy() )
       
  1545         {
       
  1546         LOGSTRING("EasyDialingPlugin: LaunchActionL - contactor service is busy!");
       
  1547         return;
       
  1548         }
       
  1549  
       
  1550     // Get current contact link.
       
  1551     HBufC8* contact8 = iContactListBox->CurrentContactLinkLC();
       
  1552     
       
  1553     TPtrC contactString( iListBoxModel->MdcaPoint( iContactListBox->CurrentItemIndex() ) );
       
  1554     
       
  1555     TPtrC fullNameSeparators;
       
  1556     TInt error = TextUtils::ColumnText( fullNameSeparators , 1, &contactString );
       
  1557     __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) );
       
  1558     
       
  1559     // Remove highlight separators. It is possible that some contactor API has problem with them.
       
  1560     HBufC* fullName = AllocWithoutHighlightSeparatorsLC( fullNameSeparators );
       
  1561     
       
  1562     VPbkFieldTypeSelectorFactory::TVPbkContactActionTypeSelector selector( 
       
  1563             VPbkFieldTypeSelectorFactory::EEmptySelector );   
       
  1564     
       
  1565     switch ( iActionToBeLaunched ) 
       
  1566         {
       
  1567         case ECallCurrentContact:
       
  1568             {
       
  1569             // Easy Dialing provides pretty much the same functionality for big Call icon 
       
  1570             // and Send key than phonebook's contact list view by using aiw interface 
       
  1571             // in edcontactor.
       
  1572             // At this point one must however check whether to use voip or voice call selector - 
       
  1573             // otherwise correct logic is provided by aiw interface.
       
  1574             // Note that Easy Dialing ignores default numbers and addresses set for
       
  1575             // action types and shows always the number and address list if there are
       
  1576             // more than one possible number/address for some action.
       
  1577              
       
  1578             CSPSettingsVoIPUtils* sPSettings = CSPSettingsVoIPUtils::NewLC();
       
  1579             
       
  1580             if ( sPSettings->IsPreferredTelephonyVoIP() )
       
  1581                 {
       
  1582                 selector = VPbkFieldTypeSelectorFactory::EVOIPCallSelector;
       
  1583                 }
       
  1584             else
       
  1585                 {
       
  1586                 selector = VPbkFieldTypeSelectorFactory::EVoiceCallSelector;
       
  1587                 }
       
  1588             
       
  1589             CleanupStack::PopAndDestroy( sPSettings );         
       
  1590             }
       
  1591             break;
       
  1592             
       
  1593         case EVideoCallCurrentContact:
       
  1594             
       
  1595             selector = VPbkFieldTypeSelectorFactory::EVideoCallSelector;
       
  1596             break;
       
  1597             
       
  1598         case ESendMessageCurrentContact:
       
  1599             
       
  1600             selector = VPbkFieldTypeSelectorFactory::EUniEditorSelector;
       
  1601             break;
       
  1602             
       
  1603         default:
       
  1604             CleanupStack::PopAndDestroy( fullName );           
       
  1605             CleanupStack::PopAndDestroy( contact8 );
       
  1606             __ASSERT_DEBUG( EFalse, EasyDialingPanic( EEasyDialingActionNotSupported ) );
       
  1607             return;
       
  1608         }
       
  1609 
       
  1610     CEDContactorService::TCSParameter param( selector, *contact8, 0, *fullName );
       
  1611 
       
  1612     iContactorService->ExecuteServiceL( param );
       
  1613 
       
  1614     CleanupStack::PopAndDestroy( fullName );
       
  1615     CleanupStack::PopAndDestroy( contact8 );
       
  1616     }
       
  1617 
       
  1618 
       
  1619 // -----------------------------------------------------------------------------
       
  1620 // CancelActionLaunchAndInputBlock
       
  1621 // Should be called when focus is lost or when call ui is activated.
       
  1622 // -----------------------------------------------------------------------------
       
  1623 //
       
  1624 void CEasyDialingPlugin::CancelActionLaunchAndInputBlock()
       
  1625     {
       
  1626     iAsyncCallBack->Cancel();
       
  1627     if ( iInputBlocker )
       
  1628         {
       
  1629         iInputBlocker->Cancel();
       
  1630         }
       
  1631     }
       
  1632 
       
  1633 // -----------------------------------------------------------------------------
       
  1634 // HandleListBoxEventL
       
  1635 // EasyDialerListBox calls this function when listbox events are reported
       
  1636 // to observers.
       
  1637 // -----------------------------------------------------------------------------
       
  1638 //
       
  1639 void CEasyDialingPlugin::HandleListBoxEventL( CEikListBox* /*aListBox*/, TListBoxEvent aEventType )
       
  1640     {
       
  1641     LOGSTRING1( "EasyDialingPlugin: HandleListBoxEventL( %d ) - Enter", aEventType );
       
  1642 
       
  1643     switch( aEventType )
       
  1644         {
       
  1645         case EEventItemSingleClicked:
       
  1646             // 9.2. Selecting contact initiates call
       
  1647             AsyncActionLaunchL( ECallCurrentContact );
       
  1648             break;
       
  1649 
       
  1650         case KEasyDialingContactLongTapped:
       
  1651             AsyncActionLaunchL( ELaunchCurrentContact );
       
  1652             break;
       
  1653             
       
  1654         // We are not interested about the other listbox events.
       
  1655         default:
       
  1656             break;
       
  1657         }
       
  1658     }
       
  1659 
       
  1660 // -----------------------------------------------------------------------------
       
  1661 // From MAknInputBlockCancelHandler.
       
  1662 // Called when input block is cancelled.
       
  1663 // -----------------------------------------------------------------------------
       
  1664 //
       
  1665  void CEasyDialingPlugin::AknInputBlockCancel()
       
  1666      {
       
  1667      LOGSTRING("EasyDialingPlugin: AknInputBlockCancel");
       
  1668      
       
  1669      // iInputBlocker will be deleted right after this callback by CAknInputBlock
       
  1670      // cause we are using CAknInputBlock::SetCancelDelete method.
       
  1671      iInputBlocker = NULL;
       
  1672      }
       
  1673 
       
  1674 /*
       
  1675  * ==============================================================================
       
  1676  * 
       
  1677  * Local functions
       
  1678  * 
       
  1679  * ==============================================================================
       
  1680  */
       
  1681 
       
  1682 
       
  1683 
       
  1684 // -----------------------------------------------------------------------------
       
  1685 // CompareTPsMatchLocation
       
  1686 // Compares two TPsMatchLocation objects based on where the match 
       
  1687 // is located in the search string. This used in ordering matches
       
  1688 // based on their location.
       
  1689 // -----------------------------------------------------------------------------
       
  1690 //
       
  1691 TInt CompareTPsMatchLocation( const TPsMatchLocation& a1, const TPsMatchLocation& a2)
       
  1692     {
       
  1693     if ( a1.index == a2.index )
       
  1694         {
       
  1695         return 0;
       
  1696         }
       
  1697     return ( a1.index > a2.index ) ? 1 : -1;
       
  1698     }
       
  1699 
       
  1700 
       
  1701 // -----------------------------------------------------------------------------
       
  1702 // AppendStringWithMatchDataL
       
  1703 // Appends a string with match data into a TDes buffer. Match data is a string 
       
  1704 // where matching and non-matching parts are separated by matching hightlight separator
       
  1705 // characters.
       
  1706 // -----------------------------------------------------------------------------
       
  1707 //
       
  1708 void AppendStringWithMatchDataL(
       
  1709         TDes& aBuffer,
       
  1710         const TDesC& aText,
       
  1711         CPSRequestHandler* aPSHandler,
       
  1712         const CPsQuery* aPSQuery )
       
  1713     {
       
  1714     if ( HighlightingSupportedForText( aText ) )
       
  1715         {
       
  1716         CDesCArrayFlat* matchingParts = new (ELeave) CDesCArrayFlat(KEasyDialingMaximumMatchingParts);
       
  1717         CleanupStack::PushL( matchingParts );
       
  1718      
       
  1719         RArray<TPsMatchLocation> matchIndices;
       
  1720         CleanupClosePushL( matchIndices );
       
  1721         
       
  1722         aPSHandler->LookupL( *aPSQuery , aText , *matchingParts, matchIndices );
       
  1723         
       
  1724         // Sort matchIndices array. Later handling assumes it to be sorted according to index field.
       
  1725         TLinearOrder<TPsMatchLocation> order( CompareTPsMatchLocation );
       
  1726         matchIndices.Sort( order );
       
  1727        
       
  1728         TInt numberOfIndices = matchIndices.Count();
       
  1729         TInt textOffset = 0;
       
  1730         
       
  1731         for (TInt i = 0; i < numberOfIndices ; i++ )
       
  1732             {
       
  1733             TInt matchingPartStart = matchIndices[i].index;
       
  1734             TInt matchingPartLength = matchIndices[i].length;
       
  1735             
       
  1736             // Append the non-matching part (if exists) 
       
  1737             if ( matchingPartStart > textOffset )
       
  1738                 {
       
  1739                 TPtrC notMatchingPart = aText.Mid( textOffset, matchingPartStart - textOffset );
       
  1740                 aBuffer.Append( notMatchingPart );
       
  1741                 }
       
  1742             
       
  1743             // Append matching separator charactes.
       
  1744             aBuffer.Append( KHighlightSeparatorChar );
       
  1745             
       
  1746             TPtrC matchingPart = aText.Mid( matchingPartStart, matchingPartLength );
       
  1747             aBuffer.Append( matchingPart );
       
  1748     
       
  1749             // Append matching separator charactes.
       
  1750             aBuffer.Append( KHighlightSeparatorChar );
       
  1751                     
       
  1752             textOffset = matchingPartStart + matchingPartLength;
       
  1753             }
       
  1754 
       
  1755         CleanupStack::PopAndDestroy( &matchIndices );
       
  1756         CleanupStack::PopAndDestroy( matchingParts );
       
  1757 
       
  1758         // Now there still may be one not matching part to be appended.
       
  1759         if ( textOffset < aText.Length() )
       
  1760             {
       
  1761             TPtrC notMatchingPart = aText.Mid( textOffset, aText.Length() - textOffset );
       
  1762             aBuffer.Append( notMatchingPart );
       
  1763             }
       
  1764         }
       
  1765     else // HighlightingSupportedForText( aText )
       
  1766         {
       
  1767         aBuffer.Append( aText );
       
  1768         }
       
  1769     }
       
  1770 
       
  1771 // -----------------------------------------------------------------------------
       
  1772 // HighlightingSupportedForText
       
  1773 // Checks if highlighting of matching text part is supported for the combination
       
  1774 // of scripts used in the given text
       
  1775 // -----------------------------------------------------------------------------
       
  1776 //
       
  1777 TBool HighlightingSupportedForText( const TDesC& aText )
       
  1778     {
       
  1779     // Highlighting for text is supported unless it contains one ore more
       
  1780     // characters written with unsupported script.
       
  1781     TBool supported = ETrue;
       
  1782     for ( TInt i = 0 ; i < aText.Length() && supported ; ++i )
       
  1783         {
       
  1784         supported = HighlightingSupportedForScript( aText[i] );
       
  1785         }
       
  1786     
       
  1787     // ... or it contains both LTR and RTL blocks
       
  1788     if ( supported )
       
  1789         {
       
  1790         supported = !IsStrictlyBidirectional( aText );
       
  1791         }
       
  1792     
       
  1793     return supported;
       
  1794     }
       
  1795 
       
  1796 // -----------------------------------------------------------------------------
       
  1797 // HighlightingSupportedForScript
       
  1798 // Checks if highlighting of matching text part is supported for the script
       
  1799 // of given character
       
  1800 // -----------------------------------------------------------------------------
       
  1801 //
       
  1802 TBool HighlightingSupportedForScript( TText aChar )
       
  1803     {
       
  1804     // For now, we don't support highlighting for any Arabic or South East Asian 
       
  1805     // script. This is because many of these scripts use rendering rules
       
  1806     // which cause problems for our simple highlighting logic designed for
       
  1807     // Latin script.
       
  1808 
       
  1809     TBool belongsToUnsupportedRange = 
       
  1810         ( aChar >= KArabicAndSouthEastAsianRangeStart && aChar <= KArabicAndSouthEastAsianRangeEnd ) ||
       
  1811         ( aChar >= KArabicPresentationFormsARangenStart && aChar <= KArabicPresentationFormsARangeEnd ) ||
       
  1812         ( aChar >= KArabicPresentationFormsBRangenStart && aChar <= KArabicPresentationFormsBRangeEnd );
       
  1813     return !belongsToUnsupportedRange;
       
  1814     }
       
  1815 
       
  1816 // -----------------------------------------------------------------------------
       
  1817 // IsStrictlyBidirectional
       
  1818 // 
       
  1819 // Returns true if argument descriptor contains both left-to-right and
       
  1820 // right-to-left blocks
       
  1821 // -----------------------------------------------------------------------------
       
  1822 //
       
  1823 TBool IsStrictlyBidirectional( const TDesC& aText )
       
  1824     {
       
  1825     TBool bothDirectionsFound = EFalse;
       
  1826     
       
  1827     // TRunInfoArray contains information of the directionalities of the different sections of the aText    
       
  1828     TBidirectionalState::TRunInfo array[ KMaxRunInfoArrayCount ];
       
  1829     
       
  1830     // Initialize the TBidiLogicalToVisual converter for making the conversion from logical to visual order
       
  1831     TBidiLogicalToVisual converter( aText, array, KMaxRunInfoArrayCount );
       
  1832     
       
  1833     // Do the reordering. Amount of different directionality sections is returned.
       
  1834     TInt blockCount = converter.Reorder();
       
  1835     if ( blockCount > KMaxRunInfoArrayCount )
       
  1836         {
       
  1837         // If there are  more directionality blocks than we are prepared to handle, then we don't
       
  1838         // know the directionality of them all. Report this as bidirectional to be on the safe side.
       
  1839         // This should be an extremely rare special case.
       
  1840         bothDirectionsFound = ETrue;
       
  1841         }
       
  1842     else if ( blockCount > 1 )
       
  1843         {
       
  1844         // If there are more than one directionality blocks, go through all of them and
       
  1845         // check if the resolved direction changes in any of the blocks.
       
  1846         TUint8 firstDirection = array[0].iDirection;
       
  1847         for ( TInt i = 1 ; i < blockCount && !bothDirectionsFound ; i++ )
       
  1848             {
       
  1849             if ( array[i].iDirection != firstDirection )
       
  1850                 {
       
  1851                 bothDirectionsFound = ETrue;
       
  1852                 }
       
  1853             }
       
  1854         }
       
  1855 
       
  1856     return bothDirectionsFound;
       
  1857     }
       
  1858 
       
  1859 
       
  1860 // -----------------------------------------------------------------------------
       
  1861 // AllocWithoutHighlightSeparatorsLC
       
  1862 // 
       
  1863 // Allocates a copy of the parameter descriptor with highlight separators 
       
  1864 // removed.
       
  1865 // -----------------------------------------------------------------------------
       
  1866 //
       
  1867 static HBufC* AllocWithoutHighlightSeparatorsLC( TDesC& aDesc )
       
  1868     {
       
  1869     HBufC* resultDesc = aDesc.AllocLC();
       
  1870     TPtr ptr = resultDesc->Des();
       
  1871     AknTextUtils::StripCharacters( ptr, KHighlightSeparatorCharAsLiteral );
       
  1872     return resultDesc;
       
  1873     }
       
  1874 
       
  1875 
       
  1876 // -----------------------------------------------------------------------------
       
  1877 // IsItuTCharacter
       
  1878 // 
       
  1879 // Test whether parameter character is a number pad character "0123456789#*+"
       
  1880 // -----------------------------------------------------------------------------
       
  1881 //
       
  1882 static TBool IsItuTCharacter( TChar aChar )
       
  1883     {
       
  1884     return aChar.IsDigit() || 
       
  1885          aChar.GetCategory() == TChar::EArabicNumber ||
       
  1886          aChar == TChar('#') ||
       
  1887          aChar == TChar('*') ||
       
  1888          aChar == TChar('+');
       
  1889     }
       
  1890 
       
  1891 //  End of File
       
  1892