phoneuis/easydialing/src/easydialingplugin.cpp
branchRCL_3
changeset 62 5266b1f337bd
child 81 c26cc2a7c548
equal deleted inserted replaced
61:41a7f70b3818 62:5266b1f337bd
       
     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 "easydialingcommands.hrh"
       
    28 #include <easydialingpluginresources.rsg>
       
    29 
       
    30 // AVKON and drawing header files
       
    31 #include <gdi.h>
       
    32 #include <aknlists.h>
       
    33 #include <AknUtils.h>
       
    34 #include <e32cmn.h>
       
    35 #include <bidivisual.h>
       
    36 
       
    37 #include <aknlayoutscalable_avkon.cdl.h>
       
    38 
       
    39 // Predictive search header files
       
    40 #include <CPsSettings.h>
       
    41 #include <CPsQuery.h>
       
    42 #include <CPsQueryItem.h>
       
    43 #include <CPsClientData.h>
       
    44 #include <CPsPattern.h>
       
    45 #include <CPsRequestHandler.h>
       
    46 
       
    47 // Virtual phonebook header files
       
    48 #include <VPbkContactStoreUris.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 #include <StringLoader.h>
       
    62 
       
    63 // CCA contactor service.
       
    64 #include "edcontactorservice.h"
       
    65 
       
    66 // Open system trace
       
    67 #include "OstTraceDefinitions.h"
       
    68 #ifdef OST_TRACE_COMPILER_IN_USE
       
    69 #include "easydialingpluginTraces.h"
       
    70 #endif
       
    71 
       
    72 #include <phoneappcommands.hrh>
       
    73 #include <bautils.h>    // for BaflUtils
       
    74 
       
    75 // Transition effects
       
    76 #include <gfxtranseffect/gfxtranseffect.h>
       
    77 
       
    78 // EXTERNAL DATA STRUCTURES
       
    79 
       
    80 // EXTERNAL FUNCTION PROTOTYPES
       
    81 
       
    82 // CONSTANTS
       
    83 const TInt KEDMaximumMatchingContactsCount = 100;
       
    84 const TInt KEasyDialingListBoxModelGranularity = 8;
       
    85 const TInt KEasyDialingMaximumMatchingParts = 10;
       
    86 const TInt KErrEasyDialingNoFirstNamePCSIndexing = -2000;
       
    87 const TInt KErrEasyDialingNoLastNamePCSIndexing = -2001;
       
    88 
       
    89 const TInt KEDFlushContactDataManagerLimit = 20;
       
    90 
       
    91 const TText KHighlightSeparatorChar = 0x1F;
       
    92 _LIT(KHighlightSeparatorCharAsLiteral,"\x1F");
       
    93 const TText KListFieldSeparatorChar = '\t';
       
    94 
       
    95 const TText KArabicAndSouthEastAsianRangeStart = 0x0600;
       
    96 const TText KArabicAndSouthEastAsianRangeEnd = 0x19FF;
       
    97 const TText KArabicPresentationFormsARangenStart = 0xFB50;
       
    98 const TText KArabicPresentationFormsARangeEnd = 0xFDFF;
       
    99 const TText KArabicPresentationFormsBRangenStart = 0xFE70;
       
   100 const TText KArabicPresentationFormsBRangeEnd = 0xFEFF;
       
   101 
       
   102 const TInt KMaxRunInfoArrayCount = 20;
       
   103 
       
   104 // Transition context_uid for dialer_list component effects
       
   105 #define KGfxContactListBoxUid TUid::Uid( 0x2000B47B )
       
   106 const TInt KGfxContactListBoxOpenEffect  = 3;
       
   107 const TInt KGfxContactListBoxCloseEffect = 4;
       
   108 
       
   109 // MACROS
       
   110 
       
   111 // LOCAL CONSTANTS AND MACROS
       
   112 _LIT(KResourceFile, "\\resource\\easydialingpluginresources.rsc");
       
   113 
       
   114 // MODULE DATA STRUCTURES
       
   115 
       
   116 // LOCAL FUNCTION PROTOTYPES
       
   117 
       
   118 TInt CompareTPsMatchLocation( const TPsMatchLocation& a1, const TPsMatchLocation& a2 );
       
   119 
       
   120 void AppendStringWithMatchDataL(
       
   121         TDes& aBuffer,
       
   122         const TDesC& aText,
       
   123         CPSRequestHandler* aPSHandler,
       
   124         const CPsQuery* aPSQuery );
       
   125 
       
   126 TBool HighlightingSupportedForText( const TDesC& aText );
       
   127 
       
   128 inline TBool HighlightingSupportedForScript( TText aChar );
       
   129 
       
   130 TBool IsStrictlyBidirectional( const TDesC& aText );
       
   131 
       
   132 static HBufC* AllocWithoutHighlightSeparatorsLC( const TDesC& aDesc );
       
   133 
       
   134 static TBool IsItuTCharacter( TChar aChar );
       
   135 
       
   136 static TInt Find( const MVPbkContactLink* aLink, const RPointerArray<MVPbkContactLink>& aArray );
       
   137 
       
   138 template <class T>
       
   139 inline void CleanupResetAndDestroyPushL( T& aRef );
       
   140 
       
   141 
       
   142 
       
   143 // -----------------------------------------------------------------------------
       
   144 // CEasyDialingPlugin
       
   145 // The default c++ constructor
       
   146 // -----------------------------------------------------------------------------
       
   147 //
       
   148 CEasyDialingPlugin::CEasyDialingPlugin() 
       
   149     : iActionToBeLaunched( ENoActionDefined )
       
   150     {
       
   151     }
       
   152 
       
   153 // -----------------------------------------------------------------------------
       
   154 // NewL
       
   155 // Create instance of concrete ECOM interface implementation.
       
   156 // -----------------------------------------------------------------------------
       
   157 //
       
   158 CEasyDialingPlugin* CEasyDialingPlugin::NewL()
       
   159     {
       
   160     OstTrace0( TRACE_NORMAL, CEASYDIALINGPLUGIN_NEWL_LOAD_PLUGIN, "Loading plugin.." );
       
   161     LOGSTRING("EasyDialingPlugin: Loading plugin..");
       
   162 
       
   163     CEasyDialingPlugin* self = new (ELeave) CEasyDialingPlugin;
       
   164     CleanupStack::PushL( self );
       
   165     self->ConstructL();
       
   166     CleanupStack::Pop( self );
       
   167 
       
   168     OstTrace0( TRACE_NORMAL, CEASYDIALINGPLUGIN_NEWL_LOAD_PLUGIN_OK, "Loading plugin completed succesfully" );
       
   169     LOGSTRING("EasyDialingPlugin: Loading plugin completed succesfully");
       
   170     return self;
       
   171     }
       
   172 
       
   173 // -----------------------------------------------------------------------------
       
   174 // ConstructL
       
   175 // Main construction handled here. Creates connection to the predictive search
       
   176 // engine and initialises all member data.
       
   177 // -----------------------------------------------------------------------------
       
   178 //
       
   179 void CEasyDialingPlugin::ConstructL()
       
   180     {
       
   181     iLongTapped = EFalse;
       
   182     // Create contact data manager.
       
   183     iContactDataManager = CEasyDialingContactDataManager::NewL();
       
   184     iContactDataManager->SetObserver( this );
       
   185 
       
   186     // Find a handle to ca launcher extension MCCAConnectionExt.
       
   187     // Easydialing has to use the extension API, because it needs function CloseAppL
       
   188     // only found in extension.
       
   189     // MCCAConnection extension has to be obtained through MCCAParameter extension,
       
   190     // since MCCAConnection is not designed to be extensible API.
       
   191     MCCAParameter* parameter = TCCAFactory::NewParameterL();
       
   192     TAny* any = parameter->CcaParameterExtension( KMCCAConnectionExtUid );
       
   193     
       
   194     // Parameter can be deallocated since "any" containing pointer to contact launcher
       
   195     // is not tied to parameter in any way.
       
   196     parameter->Close();
       
   197     
       
   198     // Cast the pointer into contact launcher object. 
       
   199     User::LeaveIfNull( any );
       
   200     iContactLauncher = static_cast<MCCAConnectionExt*>( any );
       
   201     
       
   202     iCenrepListener = CEasyDialingCenrepListener::NewL( this );
       
   203    
       
   204     iContactorService = CEDContactorService::NewL( this );
       
   205 
       
   206     // EasyDialing resource file is attempted to be read from the same directory where the
       
   207     // executed binary is located
       
   208     TFileName dllFileName;
       
   209     Dll::FileName( dllFileName );
       
   210     
       
   211     TParse parse;
       
   212     User::LeaveIfError( parse.Set(KResourceFile, &dllFileName, NULL) );
       
   213     TFileName resourceFileName( parse.FullName() );
       
   214 
       
   215     BaflUtils::NearestLanguageFile( iCoeEnv->FsSession(), resourceFileName );
       
   216     iResourceFileOffset = iCoeEnv->AddResourceFileL( resourceFileName );
       
   217   
       
   218     SetComponentsToInheritVisibility( ETrue );
       
   219     }
       
   220 
       
   221 // -----------------------------------------------------------------------------
       
   222 // ~CEasyDialingPlugin
       
   223 // The desctructor
       
   224 // -----------------------------------------------------------------------------
       
   225 //
       
   226 CEasyDialingPlugin::~CEasyDialingPlugin()
       
   227     {
       
   228     iObservers.Reset();
       
   229     
       
   230     delete iCenrepListener;
       
   231     delete iContactDataManager;
       
   232     delete iPredictiveSearchQuery;
       
   233     iContactDataStores.ResetAndDestroy();
       
   234 
       
   235     if ( iPredictiveContactSearchHandler )
       
   236         {
       
   237         iPredictiveContactSearchHandler->RemoveObserver(this);
       
   238         }
       
   239     delete iPredictiveContactSearchHandler;
       
   240 
       
   241     delete iListBoxModel;
       
   242     
       
   243     if ( iContactListBox )
       
   244         {
       
   245         GfxTransEffect::Deregister( iContactListBox );
       
   246         }
       
   247     
       
   248     delete iInfoLabelLine1;
       
   249     delete iInfoLabelLine2;
       
   250     delete iInfoLabelTextLine1;
       
   251     delete iInfoLabelTextLine2;
       
   252 
       
   253     delete iContactListBox;
       
   254 
       
   255     if ( iContactLauncher )
       
   256         {
       
   257         iContactLauncher->Close();
       
   258         }
       
   259     
       
   260     delete iContactorService;
       
   261     
       
   262     iCoeEnv->DeleteResourceFile( iResourceFileOffset );
       
   263     
       
   264     delete iInputBlocker;
       
   265     
       
   266     if ( iAsyncCallBack )
       
   267         {
       
   268         iAsyncCallBack->Cancel();
       
   269         }
       
   270     delete iAsyncCallBack;
       
   271     
       
   272     delete iContactToBeLaunched;
       
   273     delete iContactToBeLaunchedName;
       
   274     
       
   275     OstTrace0( TRACE_NORMAL, CEASYDIALINGPLUGIN_UNLOAD_PLUGIN, "Plugin unloaded" );
       
   276     LOGSTRING("EasyDialingPlugin: Plugin unloaded");
       
   277     }
       
   278 
       
   279 
       
   280 // -----------------------------------------------------------------------------
       
   281 // InitializeL
       
   282 // Initialises easy dialing.
       
   283 // -----------------------------------------------------------------------------
       
   284 //
       
   285 void CEasyDialingPlugin::InitializeL( CCoeControl& aParent )
       
   286     {
       
   287     SetContainerWindowL( aParent );
       
   288     SetMopParent( &aParent );
       
   289     
       
   290     TCallBack asyncCallBack( AsyncCallBackToLaunchAction, this );
       
   291     iAsyncCallBack = new ( ELeave ) CAsyncCallBack( asyncCallBack, 
       
   292                                                     CActive::EPriorityStandard );
       
   293 
       
   294     iContactListBox = new (ELeave) CEasyDialingListBox();
       
   295     iListBoxModel = new(ELeave) CDesCArrayFlat( KEasyDialingListBoxModelGranularity );
       
   296 
       
   297     iContactListBox->ConstructL( CEikListBox::EPaintedSelection
       
   298             | CEikListBox::ENoFirstLetterMatching
       
   299             | CEikListBox::EDisableItemSpecificMenu, 
       
   300             iContactDataManager );
       
   301     iContactListBox->SetListBoxObserver(this);
       
   302 
       
   303     iContactListBox->SetMopParent(this);
       
   304 
       
   305     CTextListBoxModel* model = iContactListBox->Model();
       
   306     model->SetItemTextArray( iListBoxModel );
       
   307     model->SetOwnershipType( ELbmDoesNotOwnItemArray );
       
   308 
       
   309     iContactListBox->MakeVisible( EFalse );
       
   310     
       
   311     SetFocus( EFalse );
       
   312     iContactListBox->ActivateL();
       
   313     
       
   314     _LIT( KEDNewLine, "\n" );
       
   315     HBufC* infoLabelText = StringLoader::LoadLC( R_QTN_EASYDIAL_ENTER_NUMBER, iCoeEnv );
       
   316     TInt newLine = infoLabelText->Find( KEDNewLine );
       
   317     if ( newLine == KErrNotFound )
       
   318         {
       
   319         iInfoLabelTextLine1 = infoLabelText;
       
   320         CleanupStack::Pop( infoLabelText );
       
   321         iInfoLabelTextLine2 = HBufC::NewL(0);
       
   322         }
       
   323     else
       
   324         {
       
   325         iInfoLabelTextLine1 = infoLabelText->Left( newLine ).AllocL();
       
   326         iInfoLabelTextLine2 = infoLabelText->Mid( newLine + 1 ).AllocL();
       
   327         CleanupStack::PopAndDestroy( infoLabelText );
       
   328         }
       
   329             
       
   330     iInfoLabelLine1 = new( ELeave ) CEikLabel;
       
   331     iInfoLabelLine1->SetContainerWindowL( *this );
       
   332     iInfoLabelLine1->SetParent( this );
       
   333     iInfoLabelLine1->SetMopParent( this ); 
       
   334     iInfoLabelLine1->SetLabelAlignment( ELayoutAlignCenter );
       
   335     iInfoLabelLine1->SetTextL( *iInfoLabelTextLine1 );
       
   336     iInfoLabelLine1->ActivateL();
       
   337 
       
   338     iInfoLabelLine2 = new( ELeave ) CEikLabel;
       
   339     iInfoLabelLine2->SetContainerWindowL( *this );
       
   340     iInfoLabelLine2->SetParent( this );
       
   341     iInfoLabelLine2->SetMopParent( this ); 
       
   342     iInfoLabelLine2->SetLabelAlignment( ELayoutAlignCenter );
       
   343     iInfoLabelLine2->SetTextL( *iInfoLabelTextLine2 );
       
   344     iInfoLabelLine2->ActivateL();
       
   345 
       
   346     SetInfoLabelColourL();
       
   347     
       
   348     GfxTransEffect::Register( iContactListBox, 
       
   349                               KGfxContactListBoxUid, EFalse );
       
   350     
       
   351     iCoeEnv->AddForegroundObserverL( *this );
       
   352     
       
   353     // Do delayed initialization of PCS. PCS constructions takes a long time.
       
   354     // On the other hand, easy dialing initialization is done in phone application
       
   355     // constructor, so it contributes the whole system boot time. These are good 
       
   356     // reasons not to construct PCS in easy dialing constructor, but do it later as
       
   357     // an asynchronous operation.
       
   358     AsyncActionLaunchL( EInitializePcs );
       
   359     }
       
   360 
       
   361 
       
   362 // -----------------------------------------------------------------------------
       
   363 // Reset
       
   364 // Resets easydialing plugin.
       
   365 // -----------------------------------------------------------------------------
       
   366 //
       
   367 void CEasyDialingPlugin::Reset()
       
   368     {
       
   369     // PCS searches completing after the Reset() call must be discarded
       
   370     iDiscardCompletingSearches = ETrue;
       
   371     
       
   372     iNewSearchNeeded = EFalse;
       
   373     iSearchString.Zero();
       
   374     iListBoxModel->Reset();
       
   375     iNumberOfNames = 0;
       
   376     iContactListBox->MakeVisible( EFalse );
       
   377     iContactDataManager->Reset();
       
   378     if ( IsFocused() )
       
   379         {
       
   380         SetFocus( EFalse );
       
   381         }
       
   382     }
       
   383 
       
   384 
       
   385 // -----------------------------------------------------------------------------
       
   386 // InitPredictiveContactSearchL
       
   387 // Initialises predictive contact search.
       
   388 // -----------------------------------------------------------------------------
       
   389 //
       
   390 void CEasyDialingPlugin::InitPredictiveContactSearchL()
       
   391     {
       
   392     iPredictiveContactSearchHandler = CPSRequestHandler::NewL();
       
   393     iPredictiveContactSearchHandler->AddObserverL(this);
       
   394 
       
   395     // Check which relevant contact fields are indexed in PCS search.
       
   396     iFirstNamePCSIndex = FindContactFieldPCSIndexL( R_VPBK_FIELD_TYPE_FIRSTNAME );
       
   397     iLastNamePCSIndex = FindContactFieldPCSIndexL( R_VPBK_FIELD_TYPE_LASTNAME );
       
   398     iCompanyNamePCSIndex = FindContactFieldPCSIndexL( R_VPBK_FIELD_TYPE_COMPANYNAME );
       
   399 
       
   400     // If first name and last name are not indexed in PCS, easy dialing plugin
       
   401     // can not function reasonably. The function leaves, which in turn causes
       
   402     // the plugin not to be initialized.
       
   403     // Company name not being indexed is not as severe case, and does not cause a leave.
       
   404     // Fields used in PCS indexing are configured in cenrep 2000B5C6.
       
   405     if ( iFirstNamePCSIndex == KErrNotFound )
       
   406         {
       
   407         OstTrace0( TRACE_ERROR, CEASYDIALINGPLUGIN_INITPREDICTIVECONTACTSEARCHL_ERROR_NO_FIRST_NAME, "ERROR, PCS does not support first name indexing!" );
       
   408         LOGSTRING("EasyDialingPlugin: PCS does not support first name indexing => Leave");
       
   409         User::Leave( KErrEasyDialingNoFirstNamePCSIndexing );
       
   410         }
       
   411     if ( iLastNamePCSIndex == KErrNotFound )
       
   412         {
       
   413         OstTrace0( TRACE_ERROR, CEASYDIALINGPLUGIN_INITPREDICTIVECONTACTSEARCHL_ERROR_NO_LAST_NAME, "ERROR, PCS does not support last name indexing!" );
       
   414         LOGSTRING("EasyDialingPlugin: PCS does not support last name indexing => Leave");
       
   415         User::Leave( KErrEasyDialingNoLastNamePCSIndexing );
       
   416         }
       
   417 
       
   418     SetupPcsSettingsL();
       
   419 
       
   420     iPredictiveSearchQuery = CPsQuery::NewL();
       
   421     }
       
   422 
       
   423 // -----------------------------------------------------------------------------
       
   424 // SetupPcsSettingsL
       
   425 // -----------------------------------------------------------------------------
       
   426 //
       
   427 void CEasyDialingPlugin::SetupPcsSettingsL()
       
   428     {
       
   429     // Get current store configuration from Phonebook settings
       
   430     iContactDataStores.ResetAndDestroy();
       
   431     iContactDataManager->GetCurrentStoreUrisL( iContactDataStores );
       
   432     
       
   433     // Put the searched contact fields into array.
       
   434     RArray<TInt> contact_fields;
       
   435     CleanupClosePushL(contact_fields);
       
   436 
       
   437     // First name, last name and company name (if supported) are used in PCS search.
       
   438     contact_fields.Append( R_VPBK_FIELD_TYPE_FIRSTNAME );
       
   439     contact_fields.Append( R_VPBK_FIELD_TYPE_LASTNAME );
       
   440     contact_fields.Append( R_VPBK_FIELD_TYPE_COMPANYNAME );
       
   441 
       
   442     // Create and fill PS settings object.
       
   443     CPsSettings* ps_settings = CPsSettings::NewL();
       
   444     CleanupStack::PushL( ps_settings );
       
   445 
       
   446     ps_settings->SetSearchUrisL( iContactDataStores );
       
   447     ps_settings->SetMaxResults( KEDMaximumMatchingContactsCount );
       
   448     ps_settings->SetSortType( EAlphabetical );
       
   449     ps_settings->SetDisplayFieldsL( contact_fields );
       
   450 
       
   451     // Set the PCS settings.
       
   452     iPredictiveContactSearchHandler->SetSearchSettingsL( *ps_settings );
       
   453 
       
   454     CleanupStack::PopAndDestroy( ps_settings );
       
   455     CleanupStack::PopAndDestroy( &contact_fields );
       
   456 
       
   457     // Set the sort order. This must happen after the contact store settings
       
   458     // are up-to-date.
       
   459     SetSortOrderL( iContactDataManager->NameOrder() );
       
   460     }
       
   461 
       
   462 // -----------------------------------------------------------------------------
       
   463 // SetSortOrderL
       
   464 // -----------------------------------------------------------------------------
       
   465 //
       
   466 void CEasyDialingPlugin::SetSortOrderL( CEasyDialingContactDataManager::TNameOrder aNameOrder )
       
   467     {
       
   468     RArray<TInt> fields;
       
   469     CleanupClosePushL( fields );
       
   470     if ( aNameOrder == CEasyDialingContactDataManager::EFirstnameLastname )
       
   471         {
       
   472         fields.AppendL( R_VPBK_FIELD_TYPE_FIRSTNAME );
       
   473         fields.AppendL( R_VPBK_FIELD_TYPE_LASTNAME );
       
   474         }
       
   475     else
       
   476         {
       
   477         fields.AppendL( R_VPBK_FIELD_TYPE_LASTNAME );
       
   478         fields.AppendL( R_VPBK_FIELD_TYPE_FIRSTNAME );
       
   479         }
       
   480     fields.AppendL( R_VPBK_FIELD_TYPE_COMPANYNAME );
       
   481     
       
   482     // Set the same order for each contact store. PCS automatically ignores
       
   483     // fields not supported by the given store.
       
   484     for ( TInt i = 0 ; i < iContactDataStores.Count() ; ++i )
       
   485         {
       
   486         iPredictiveContactSearchHandler->ChangeSortOrderL( *iContactDataStores[i], fields );
       
   487         }
       
   488     CleanupStack::PopAndDestroy( &fields );
       
   489     }
       
   490 
       
   491 // -----------------------------------------------------------------------------
       
   492 // OfferKeyEventL
       
   493 // Check the received keypad event and performs user
       
   494 // actions related to it.
       
   495 // -----------------------------------------------------------------------------
       
   496 //
       
   497 TKeyResponse CEasyDialingPlugin::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
       
   498     {
       
   499     TKeyResponse keyResponse = EKeyWasNotConsumed;
       
   500 
       
   501     if ( aType != EEventKey )
       
   502         {
       
   503         return keyResponse;
       
   504         }
       
   505 
       
   506     TInt keyCode = aKeyEvent.iCode;
       
   507     
       
   508     // Swap right and left key codes in mirrored layout.
       
   509     if ( AknLayoutUtils::LayoutMirrored() ) 
       
   510         {
       
   511         if ( keyCode == EKeyRightArrow ) keyCode = EKeyLeftArrow;
       
   512         else if ( keyCode == EKeyLeftArrow ) keyCode = EKeyRightArrow;
       
   513         }
       
   514     
       
   515 
       
   516     if ( IsFocused() )
       
   517         {
       
   518         if ( keyCode == EKeyUpArrow )
       
   519             {
       
   520             // if the focus is on the top-most item
       
   521             if ( iContactListBox->CurrentItemIndex() == 0)
       
   522                 {
       
   523                 // then focus jumps off the component.
       
   524                 SetFocus( EFalse );
       
   525                 DrawDeferred();
       
   526                 keyResponse = EKeyWasConsumed;
       
   527                 }
       
   528             else
       
   529                 {
       
   530                 keyResponse = iContactListBox->OfferKeyEventL( aKeyEvent, aType );
       
   531                 }
       
   532             }
       
   533         else if ( keyCode == EKeyDownArrow )
       
   534             {
       
   535             // if the focus is on the bottom-most item
       
   536             if ( iContactListBox->CurrentItemIndex() == (iNumberOfNames - 1) )
       
   537                 {
       
   538                 // then focus jumps off the component.
       
   539                 SetFocus( EFalse );
       
   540                 DrawDeferred();
       
   541                 keyResponse = EKeyWasConsumed;
       
   542                 }
       
   543             else
       
   544                 {
       
   545                 keyResponse = iContactListBox->OfferKeyEventL( aKeyEvent, aType );
       
   546                 }
       
   547             }
       
   548 
       
   549         else if ( keyCode == EKeyRightArrow )
       
   550             {
       
   551             iRememberFocus = ETrue;
       
   552             AsyncActionLaunchL( ELaunchCurrentContact );
       
   553             keyResponse = EKeyWasConsumed;
       
   554             }
       
   555 
       
   556         else if ( keyCode == EKeyLeftArrow )
       
   557             {
       
   558             // then focus jumps off the component.
       
   559             SetFocus( EFalse );
       
   560             DrawDeferred();
       
   561             keyResponse = EKeyWasConsumed;
       
   562             }
       
   563 
       
   564         else
       
   565             {
       
   566             // then focus jumps off the component.
       
   567             SetFocus( EFalse );
       
   568             
       
   569             // FEP hasn't had chance to handle this key event as focus was not in the editor field.
       
   570             // Give that chance now by consuming original event and simulating a new one.
       
   571             // The simulation must be asynchronous because FEP focusing state is updated
       
   572             // with high priority active object.
       
   573             // As an exception, dialer simulated keys are given directly to editor. They are
       
   574             // not handled by FEP anyway, and asynchronous handling would be problematic for
       
   575             // the * key multitapping logic of Phone.
       
   576             TBool simulatedByDialer = (aKeyEvent.iModifiers&EModifierNumLock) &&
       
   577                                       (aKeyEvent.iModifiers&EModifierKeypad);
       
   578             if ( !simulatedByDialer )
       
   579                 {
       
   580                 keyResponse = EKeyWasConsumed;
       
   581                 AsyncSimulateKeyEvent( aKeyEvent );
       
   582                 }
       
   583             }
       
   584         }
       
   585 
       
   586     else if ( iNumberOfNames > 0 ) // not in focus but there are contacts to show
       
   587         {
       
   588         if ( keyCode == EKeyUpArrow || keyCode == EKeyDownArrow )
       
   589             {
       
   590             SetFocus( ETrue );
       
   591             keyResponse = iContactListBox->SetFocusedWithKeyEventL( aKeyEvent, aType );
       
   592             }
       
   593         }
       
   594     return keyResponse;
       
   595     }
       
   596 
       
   597 
       
   598 // -----------------------------------------------------------------------------
       
   599 // CountComponentControls
       
   600 //
       
   601 // -----------------------------------------------------------------------------
       
   602 //
       
   603 TInt CEasyDialingPlugin::CountComponentControls() const
       
   604     {
       
   605     return iNumberOfNames > 0 ? 3 : 2;
       
   606     }
       
   607 
       
   608 
       
   609 // -----------------------------------------------------------------------------
       
   610 // ComponentControl
       
   611 //
       
   612 // -----------------------------------------------------------------------------
       
   613 //
       
   614 CCoeControl* CEasyDialingPlugin::ComponentControl( TInt aIndex ) const
       
   615     {
       
   616     switch ( aIndex )
       
   617         {
       
   618         case 0:
       
   619             return iInfoLabelLine1;
       
   620         case 1:
       
   621             return iInfoLabelLine2;
       
   622         case 2:
       
   623             return iContactListBox;
       
   624         default:
       
   625             return NULL;
       
   626         }
       
   627     }
       
   628 
       
   629 
       
   630 // -----------------------------------------------------------------------------
       
   631 // MakeVisible
       
   632 //
       
   633 // -----------------------------------------------------------------------------
       
   634 //
       
   635 void CEasyDialingPlugin::MakeVisible( TBool aVisible )
       
   636     {
       
   637     if ( aVisible != IsVisible() )
       
   638         {
       
   639         CCoeControl::MakeVisible( aVisible );
       
   640         
       
   641         if ( !aVisible && IsFocused() )
       
   642             {
       
   643             SetFocus( EFalse );
       
   644             }
       
   645         }
       
   646     }
       
   647 
       
   648 // -----------------------------------------------------------------------------
       
   649 // HandleResourceChange
       
   650 //
       
   651 // -----------------------------------------------------------------------------
       
   652 //
       
   653 void CEasyDialingPlugin::HandleResourceChange( TInt /*aType*/ )
       
   654     {
       
   655     TRAP_IGNORE( SetInfoLabelColourL() );
       
   656     }
       
   657 
       
   658 // -----------------------------------------------------------------------------
       
   659 // SizeChanged
       
   660 //
       
   661 // -----------------------------------------------------------------------------
       
   662 //
       
   663 void CEasyDialingPlugin::SizeChanged()
       
   664     {
       
   665     TRect rect = Rect();
       
   666     // convert rect to absolute coordinates
       
   667     rect.SetRect( PositionRelativeToScreen(), rect.Size() );
       
   668     
       
   669     iContactListBox->SetMaxRect( rect );
       
   670     iContactListBox->SetRectToNumberOfItems( iNumberOfNames );
       
   671     
       
   672     TInt itemToMakeVisible = iContactListBox->CurrentItemIndex();  
       
   673     if ( itemToMakeVisible == KErrNotFound && iNumberOfNames )
       
   674         {
       
   675         // if no current item is set, make sure that the list is then 
       
   676         // scrolled to the bottom.
       
   677         itemToMakeVisible = iNumberOfNames - 1;
       
   678         } 
       
   679     iContactListBox->ScrollToMakeItemVisible( itemToMakeVisible );
       
   680 
       
   681     // get info label locations and fonts from layout
       
   682     TRect baseRect = Rect();
       
   683     TAknTextComponentLayout labelLayoutLine1 = 
       
   684         AknLayoutScalable_Avkon::main_pane_empty_t1( 0 );
       
   685     TAknTextComponentLayout labelLayoutLine2 = 
       
   686         AknLayoutScalable_Avkon::main_pane_empty_t2( 0 );
       
   687     AknLayoutUtils::LayoutLabel( iInfoLabelLine1, baseRect, labelLayoutLine1 );
       
   688     AknLayoutUtils::LayoutLabel( iInfoLabelLine2, baseRect, labelLayoutLine2 );
       
   689     
       
   690     // the layouts used place the text too low, so center the labels vertically
       
   691     TInt labelHeight = iInfoLabelLine2->Rect().iBr.iY - iInfoLabelLine1->Rect().iTl.iY;
       
   692     TInt centeredTop = ( baseRect.Height() - labelHeight ) / 2;
       
   693     TInt offset = centeredTop - iInfoLabelLine1->Rect().iTl.iY;
       
   694     iInfoLabelLine1->SetPosition( TPoint( iInfoLabelLine1->Rect().iTl.iX,
       
   695                                           iInfoLabelLine1->Rect().iTl.iY + offset ) );
       
   696     iInfoLabelLine2->SetPosition( TPoint( iInfoLabelLine2->Rect().iTl.iX,
       
   697                                           iInfoLabelLine2->Rect().iTl.iY + offset ) );
       
   698     
       
   699     TRAP_IGNORE( SetInfoLabelColourL() );
       
   700     }
       
   701 
       
   702 
       
   703 // -----------------------------------------------------------------------------
       
   704 // FocusChanged
       
   705 //
       
   706 // -----------------------------------------------------------------------------
       
   707 //
       
   708 void CEasyDialingPlugin::FocusChanged( TDrawNow aDrawNow )
       
   709     {
       
   710     iContactListBox->SetFocus( IsFocused() );
       
   711     if ( !IsFocused() )
       
   712         {
       
   713         // To be on the safe side, cancel async callback and reset input block.
       
   714         CancelActionLaunchAndInputBlock();
       
   715         iContactListBox->View()->ItemDrawer()->ClearFlags( CListItemDrawer::ESingleClickDisabledHighlight );
       
   716         }
       
   717     CCoeControl::FocusChanged( aDrawNow );
       
   718     InformObservers( MDialingExtensionObserver::EFocusChanged );
       
   719     }
       
   720 
       
   721 
       
   722 // -----------------------------------------------------------------------------
       
   723 // SetInputL
       
   724 //
       
   725 // -----------------------------------------------------------------------------
       
   726 //
       
   727 void CEasyDialingPlugin::SetInputL( const TDesC& aSearchString )
       
   728     {
       
   729     if ( !IsEnabled() )
       
   730         {
       
   731         return;
       
   732         }
       
   733     OstTraceExt1( TRACE_NORMAL, CEASYDIALINGPLUGIN_SET_INPUT, "SetInput: '%S' ", aSearchString );
       
   734     LOGSTRING1("EasyDialingPlugin: SetInput: '%S'", &aSearchString );
       
   735     
       
   736     // Earlier here was a test if the search string is the same as the one used in previous search.
       
   737     // If it was, no search was done but function returned immediately.
       
   738     // This has now been removed. It is possible that contacts have changed, and a new search
       
   739     // may be needed even if the search string is the same. 
       
   740     
       
   741     // Check if search string is just empty space or 0-length. Decision was made that no
       
   742     // matches are shown if search string is just space (would show all contacts)
       
   743     // even if somebody might have unnamed contacts. Should be quite rare.
       
   744     // It's assumed later on in the code that string is not just empty space.
       
   745     TLex searchString( aSearchString );
       
   746     searchString.SkipSpace();
       
   747     if ( searchString.Eos() ) // the end of the string reached after skipping empty space
       
   748         {
       
   749         // It's assumed here that if we get here due to switching to call
       
   750         // handling etc, then dialer and thus ed is already set invisible
       
   751         // and effect will not be shown as listbox is already invisible.
       
   752         // However if user empties number entry, then it's feasible to show
       
   753         // effect.
       
   754         HideContactListBoxWithEffect();
       
   755         SetInfoLabelVisibleL( ETrue );
       
   756         Reset();
       
   757         }
       
   758     else // proper search string
       
   759         {
       
   760         SetInfoLabelVisibleL( EFalse );
       
   761         iSearchString.Copy( aSearchString.Left( iSearchString.MaxLength() ) );
       
   762         LaunchSearchL();
       
   763         }
       
   764     }
       
   765 
       
   766 
       
   767 // -----------------------------------------------------------------------------
       
   768 // MatchingContactCount
       
   769 //
       
   770 // -----------------------------------------------------------------------------
       
   771 //
       
   772 TInt CEasyDialingPlugin::MatchingContactCount()
       
   773     {
       
   774     return iNumberOfNames;
       
   775     }
       
   776 
       
   777 
       
   778 // -----------------------------------------------------------------------------
       
   779 // EasyDialingSettingsChanged
       
   780 // From MEasyDialingCenrepListenerObserver
       
   781 // -----------------------------------------------------------------------------
       
   782 //
       
   783 void CEasyDialingPlugin::EasyDialingSettingsChanged( TInt aValue )
       
   784     {
       
   785     if ( aValue == 0 )
       
   786         {
       
   787         Reset();
       
   788         InformObservers( MDialingExtensionObserver::EEasyDialingDisabled );
       
   789         TRAP_IGNORE( SetInfoLabelVisibleL( EFalse ) );
       
   790         }
       
   791     else if ( aValue == 1 )
       
   792         {
       
   793         InformObservers( MDialingExtensionObserver::EEasyDialingEnabled );
       
   794         if ( iSearchString.Length() == 0 )
       
   795             {
       
   796             TRAP_IGNORE( SetInfoLabelVisibleL( ETrue ) );
       
   797             }
       
   798         }
       
   799     MakeVisible( aValue );
       
   800     }
       
   801 
       
   802 // -----------------------------------------------------------------------------
       
   803 // EasyDialingContactThumbnailsSettingsChanged
       
   804 // From MEasyDialingCenrepListenerObserver
       
   805 // -----------------------------------------------------------------------------
       
   806 //
       
   807 void CEasyDialingPlugin::EasyDialingContactThumbnailsSettingsChanged( TInt aThumbnailSettingValue )
       
   808     {
       
   809     iContactDataManager->SetContactThumbnailSetting( aThumbnailSettingValue );
       
   810     iContactDataManager->Reload();
       
   811     DrawDeferred();
       
   812     }
       
   813 
       
   814 // -----------------------------------------------------------------------------
       
   815 // AllContactDataLoaded
       
   816 // From MContactDataManagerObserver
       
   817 // -----------------------------------------------------------------------------
       
   818 //
       
   819 void CEasyDialingPlugin::AllContactDataLoaded()
       
   820     {
       
   821     iContactListBox->DrawDeferred();
       
   822     }
       
   823 
       
   824 // -----------------------------------------------------------------------------
       
   825 // NameOrderChanged
       
   826 // From MContactDataManagerObserver
       
   827 // -----------------------------------------------------------------------------
       
   828 //
       
   829 void CEasyDialingPlugin::NameOrderChanged()
       
   830     {
       
   831     if ( iPredictiveContactSearchHandler )
       
   832         {
       
   833         TRAP_IGNORE( SetSortOrderL( iContactDataManager->NameOrder() ) );
       
   834         // Refresh current results if needed
       
   835         TRAP_IGNORE( DoHandleContactsChangedL() );
       
   836         }
       
   837     }
       
   838 
       
   839 // -----------------------------------------------------------------------------
       
   840 // FavouritesChanged
       
   841 // From MContactDataManagerObserver
       
   842 // -----------------------------------------------------------------------------
       
   843 //
       
   844 void CEasyDialingPlugin::FavouritesChanged()
       
   845     {
       
   846     TRAP_IGNORE( DoHandleContactsChangedL() );
       
   847     }
       
   848 
       
   849 // -----------------------------------------------------------------------------
       
   850 // StoreConfigurationChanged
       
   851 // From MContactDataManagerObserver
       
   852 // -----------------------------------------------------------------------------
       
   853 //
       
   854 void CEasyDialingPlugin::StoreConfigurationChanged()
       
   855     {
       
   856     TRAP_IGNORE( 
       
   857         // Reconfigure PCS to update its store settings
       
   858         SetupPcsSettingsL();
       
   859         // Contacts available have changed and a new search is needed if we have
       
   860         // previous results shown.
       
   861         DoHandleContactsChangedL() 
       
   862         );
       
   863     }
       
   864 
       
   865 // -----------------------------------------------------------------------------
       
   866 // InformContactorEvent
       
   867 // From MEDContactorObserver
       
   868 // -----------------------------------------------------------------------------
       
   869 //
       
   870 void CEasyDialingPlugin::InformContactorEvent( MEDContactorObserver::TEvent aEvent )
       
   871     {
       
   872     // This callback function simply propagates the events to its own listener.
       
   873     switch ( aEvent )
       
   874         {
       
   875         case MEDContactorObserver::ECommunicationStarted:
       
   876             InformObservers( MDialingExtensionObserver::ECommunicationStarted );
       
   877             break;
       
   878         case MEDContactorObserver::ECommunicationCancelled:
       
   879             InformObservers( MDialingExtensionObserver::ECommunicationCancelled );
       
   880             break;
       
   881         default:
       
   882             break;
       
   883         }
       
   884     
       
   885     // Reset focus unless it is flagged to be remembered.
       
   886     if ( !iRememberFocus )
       
   887         {
       
   888         SetFocus( EFalse );
       
   889         DrawDeferred();
       
   890         }
       
   891     
       
   892     iRememberFocus = EFalse;
       
   893     }
       
   894 
       
   895 // -----------------------------------------------------------------------------
       
   896 // Draw
       
   897 // The actual UI drawing function. Draws the easy dialing popup bubble on the
       
   898 // idle screen.
       
   899 // -----------------------------------------------------------------------------
       
   900 //
       
   901 void CEasyDialingPlugin::Draw( const TRect& /* aRect */ ) const
       
   902     {
       
   903     }
       
   904 
       
   905 
       
   906 // -----------------------------------------------------------------------------
       
   907 // LaunchSearchL
       
   908 // Initiates predictive contact search.
       
   909 // -----------------------------------------------------------------------------
       
   910 //
       
   911 void CEasyDialingPlugin::LaunchSearchL()
       
   912     {
       
   913     if ( iSearchString.Length() == 0 || !iPredictiveContactSearchHandler )
       
   914         {
       
   915         return;
       
   916         }
       
   917     
       
   918     iDiscardCompletingSearches = EFalse;
       
   919     iNewSearchNeeded = EFalse;
       
   920     
       
   921     iPredictiveSearchQuery->Reset();
       
   922 
       
   923     for ( TInt i = 0; i < iSearchString.Length(); i++ )
       
   924         {
       
   925          // Add a query item
       
   926         CPsQueryItem* item = CPsQueryItem::NewL();
       
   927         CleanupStack::PushL(item);
       
   928 
       
   929         item->SetCharacter( iSearchString[i] );
       
   930         
       
   931         // The PCS mode used with character is based on character itself,
       
   932         // not to the keyboard it is made with. While this is not strictly
       
   933         // identical to checking the used keyboard, this behaves identically
       
   934         // in most of the normal cases, and makes the logic simpler.
       
   935         // In case of hybrid mode keyboard, use always predictive default 
       
   936         // keyboard.
       
   937         if ( iKeyboardMode == EDefaultKeyboard && 
       
   938              IsItuTCharacter( iSearchString[i] ) )
       
   939             {
       
   940             item->SetMode( EPredictiveItuT );
       
   941             }
       
   942         else 
       
   943             {
       
   944             item->SetMode( EPredictiveDefaultKeyboard );
       
   945             }
       
   946         
       
   947         iPredictiveSearchQuery->AppendL(*item);
       
   948 
       
   949         // Previous CPsQuery::AppendL takes the ownership of item.
       
   950         // Do not delete item.
       
   951         CleanupStack::Pop(item);
       
   952         }
       
   953 
       
   954     // Issue the search. SearchL is asynchronous function => returns immediately.
       
   955     iPredictiveContactSearchHandler->SearchL(*iPredictiveSearchQuery);
       
   956     }
       
   957 
       
   958 
       
   959 // -----------------------------------------------------------------------------
       
   960 // HandlePsResultsUpdate from MPsResultsObserver
       
   961 // Called after predictive search has been completed.
       
   962 // -----------------------------------------------------------------------------
       
   963 //
       
   964 void CEasyDialingPlugin::HandlePsResultsUpdate( RPointerArray<CPsClientData>& aResults, RPointerArray<CPsPattern>& aSeqs )
       
   965     {
       
   966     if ( !IsEnabled() )
       
   967         {
       
   968         // Easydialing is off. We should arrive here only if user turned it off while a search was happening.
       
   969         Reset();
       
   970         return;
       
   971         }
       
   972     TRAPD( leaveError, HandlePsResultsUpdateL( aResults, aSeqs ) );
       
   973 
       
   974     if ( leaveError )
       
   975         {
       
   976         OstTrace1( TRACE_ERROR, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATE, "HandlePsResultsUpdate failed: %d", leaveError );
       
   977         LOGSTRING1("EasyDialingPlugin: HandlePsResultsUpdate failed: %d", leaveError );
       
   978         }
       
   979     }
       
   980 
       
   981 
       
   982 // -----------------------------------------------------------------------------
       
   983 // HandlePsError from MPsResultsObserver
       
   984 // Called when search error happens.
       
   985 // -----------------------------------------------------------------------------
       
   986 //
       
   987 void CEasyDialingPlugin::HandlePsError( TInt aErrorCode )
       
   988     {
       
   989     OstTrace1( TRACE_ERROR, CEASYDIALINGPLUGIN_HANDLEPSERROR, "PCS Error: %d", aErrorCode );
       
   990     LOGSTRING1("EasyDialingPlugin: PCS Error: %d", aErrorCode );
       
   991     }
       
   992 
       
   993 // -----------------------------------------------------------------------------
       
   994 // CachingStatus from MPsResultsObserver
       
   995 // Called to update caching status.
       
   996 // -----------------------------------------------------------------------------
       
   997 //
       
   998 void CEasyDialingPlugin::CachingStatus( TCachingStatus& aStatus, TInt& aError )
       
   999     {
       
  1000     OstTraceExt2( TRACE_NORMAL, CEASYDIALINGPLUGIN_CACHINGSTATUS, "PCS CachingStatus: %d, error: %d", ( TUint )( aStatus ), aError );
       
  1001     
       
  1002     switch ( aStatus )
       
  1003         {
       
  1004         case ECacheUpdateContactRemoved:
       
  1005         case ECacheUpdateContactModified:
       
  1006         case ECacheUpdateContactAdded:
       
  1007             TRAP_IGNORE( DoHandleContactsChangedL() );
       
  1008             break;
       
  1009         default:
       
  1010             break;
       
  1011         }
       
  1012     
       
  1013     LOGSTRING2("EasyDialingPlugin: PCS CachingStatus: %d, error: %d", aStatus, aError );
       
  1014     }
       
  1015 
       
  1016 
       
  1017 // -----------------------------------------------------------------------------
       
  1018 // FindContactFieldPCSIndex
       
  1019 // Searches the index that stores the given contact field.
       
  1020 // To see possible contact field numbering, see file "vpbkeng.rsg".
       
  1021 // -----------------------------------------------------------------------------
       
  1022 //
       
  1023 TInt CEasyDialingPlugin::FindContactFieldPCSIndexL( TInt aIndex )
       
  1024     {
       
  1025     RArray<TInt> fieldOrder;
       
  1026     CleanupClosePushL( fieldOrder );
       
  1027 
       
  1028     // PCS uses the same data plugin for all the Phonebook databases
       
  1029     // (i.e. phone contacts, SIM contacts, SDN contacts), and there can be only
       
  1030     // one data order per plugin. Thus, data order for all databases supported
       
  1031     // by us is the same, and it's enough to ask data order just for the default CDB.
       
  1032     const TDesC& defaultCdb = VPbkContactStoreUris::DefaultCntDbUri();
       
  1033 
       
  1034     iPredictiveContactSearchHandler->GetDataOrderL( defaultCdb, fieldOrder );
       
  1035     TInt pcsIndex = fieldOrder.Find( aIndex );
       
  1036 
       
  1037     CleanupStack::PopAndDestroy( &fieldOrder );
       
  1038     return pcsIndex;
       
  1039     }
       
  1040 
       
  1041 
       
  1042 // -----------------------------------------------------------------------------
       
  1043 // HandlePsResultsUpdateL
       
  1044 // This function does the actual callback fork, and must be trapped inside
       
  1045 // HandlePsResultsUpdateL.
       
  1046 // -----------------------------------------------------------------------------
       
  1047 //
       
  1048 void CEasyDialingPlugin::HandlePsResultsUpdateL( RPointerArray<CPsClientData>& aResults, RPointerArray<CPsPattern>& /*aSeqs*/ )
       
  1049     {
       
  1050     // If iDiscardCompletingSearches is ETrue, don't show search results but just return.
       
  1051     // If easydialing has been reset with reset function, no searches completed after that
       
  1052     // can be shown.
       
  1053     // This is done like this because there seems not to be a feasible way of cancelling all 
       
  1054     // PCS search request in PCS API. CancelRequest does not work here.
       
  1055     if ( iDiscardCompletingSearches )
       
  1056         {
       
  1057         return;
       
  1058         }
       
  1059     
       
  1060     iListBoxModel->Reset();
       
  1061     iContactListBox->HandleItemRemovalL();
       
  1062 
       
  1063     TInt numberOfPCSMatches( aResults.Count() );
       
  1064     
       
  1065     // Resetting the contactdatamanager causes the thumbnails to flicker a bit, because
       
  1066     // we need to load the thumbnails again. But if there are lots of search results, or
       
  1067     // lots of loaded thumbnails in the manager, matching the search results to the
       
  1068     // thumbnail manager contents may take too much time. If there are lots of results,
       
  1069     // it is likely that the contents of the listbox change anyway, so the flickering
       
  1070     // doesn't matter too much. This also limits the memory usage of the manager.
       
  1071     //   But if there are fewer search results, it is worth trying to match them
       
  1072     // with the contents of thumbnail manager.
       
  1073     
       
  1074     TBool matchThumbnails(ETrue);
       
  1075     if ( numberOfPCSMatches > KEDFlushContactDataManagerLimit )
       
  1076         {
       
  1077         iContactDataManager->Reset();
       
  1078         matchThumbnails = EFalse;
       
  1079         }
       
  1080 
       
  1081     OstTrace1( TRACE_NORMAL, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATEL_MATCHES, "Matching results from PCS: %d", numberOfPCSMatches );
       
  1082     LOGSTRING1("EasyDialingPlugin: Matching results from PCS: %d", numberOfPCSMatches );
       
  1083 
       
  1084     // retrieve the name order before adding
       
  1085     CEasyDialingContactDataManager::TNameOrder nameOrder = iContactDataManager->NameOrder();
       
  1086 
       
  1087     RPointerArray<MVPbkContactLink> favsFoundByPcs;
       
  1088     CleanupResetAndDestroyPushL( favsFoundByPcs );
       
  1089     
       
  1090     // Update the model
       
  1091     // ----------------
       
  1092     for ( TInt i = 0; i < numberOfPCSMatches; i++ )
       
  1093         {
       
  1094         TInt indexFromEnd = numberOfPCSMatches - i - 1;
       
  1095 
       
  1096         MVPbkContactLink* link = iPredictiveContactSearchHandler->ConvertToVpbkLinkLC(
       
  1097                 *(aResults[indexFromEnd]), iContactDataManager->ContactManager() );
       
  1098         if ( !iContactDataManager->IsFavL( link ) )
       
  1099             {
       
  1100             // handle favourites separately, in another loop
       
  1101             HBufC* contactString = CreateContactStringLC( aResults[ indexFromEnd ], nameOrder );
       
  1102             CreateListBoxContactStringL( *contactString, link, matchThumbnails, EFalse );
       
  1103             CleanupStack::PopAndDestroy( contactString );
       
  1104             CleanupStack::PopAndDestroy( link );
       
  1105             }
       
  1106         else
       
  1107             {
       
  1108             // favourites are handled later
       
  1109             favsFoundByPcs.AppendL( link );
       
  1110             CleanupStack::Pop( link );
       
  1111             }
       
  1112         
       
  1113         OstTraceExt2( TRACE_NORMAL, CEASYDIALINGPLUGIN_HANDLEPSRESULTSUPDATEL_SHOW_MATCH, "Contact #%d: '%S'", i+1, iContactStringCreationBuffer );
       
  1114         LOGSTRING2( "EasyDialingPlugin: Contact #%d: '%S'", i+1, &iContactStringCreationBuffer );
       
  1115         }
       
  1116 
       
  1117     // Search synchronously through all the favourite contacts to ensure
       
  1118     // that all favourite matches are added to bottom even when number of mathces
       
  1119     // exceeds the maximum number set to PCS
       
  1120     TInt numberOfFavs( iContactDataManager->NumberOfFavsL() );
       
  1121     TBuf<KBufferMaxLen> results;
       
  1122     for ( TInt i = numberOfFavs - 1; i >= 0; i-- )
       
  1123         {
       
  1124         HBufC* favContactString = iContactDataManager->FavContactStringLC( i, nameOrder );
       
  1125         MVPbkContactLink* link = iContactDataManager->FavLinkLC( i );
       
  1126         
       
  1127         // Check if this fav contact was returned in aResults.
       
  1128         // It's at least theoretically possible that all matches in aResults
       
  1129         // are not matched when using LookupMatchL. PCS has completely separate logics
       
  1130         // for functions SearchL and LookupMatchL and especially with Chinese variant
       
  1131         // they may return different results.
       
  1132         TBool found = ( Find( link, favsFoundByPcs ) != KErrNotFound );
       
  1133         
       
  1134         // If this fav contact was not in aResults, then use LookupMatchL
       
  1135         // to check if this contact is still a match and was excluded from aResults
       
  1136         // because maximum number of results was exceeded.
       
  1137         if ( !found )
       
  1138             {
       
  1139             results = KNullDesC;
       
  1140             iPredictiveContactSearchHandler->LookupMatchL(
       
  1141                     *iPredictiveSearchQuery, *favContactString, results );
       
  1142             found = ( results.Length() > 0 );
       
  1143             }
       
  1144 
       
  1145         if ( found )
       
  1146             {
       
  1147             // matches, add this fav to listbox.
       
  1148             CreateListBoxContactStringL( *favContactString, link, matchThumbnails, ETrue );
       
  1149             }
       
  1150 
       
  1151         CleanupStack::PopAndDestroy(); // link
       
  1152         CleanupStack::PopAndDestroy( favContactString );
       
  1153         }
       
  1154     
       
  1155     CleanupStack::PopAndDestroy( &favsFoundByPcs ); // ResetAndDestroy
       
  1156     
       
  1157     // Update the view
       
  1158     // ---------------
       
  1159     iNumberOfNames = iListBoxModel->Count();
       
  1160     if ( iNumberOfNames )
       
  1161         {
       
  1162         TInt oldRectHeight = iContactListBox->Rect().Height();
       
  1163         
       
  1164         iContactListBox->SetRectToNumberOfItems( iNumberOfNames );
       
  1165         
       
  1166         // If the window is resized (->position changes too) while it's visible, 
       
  1167         // it has to be redrawn immediately or otherwise listbox will flash
       
  1168         // in a wrong place on the screen during execution of this method
       
  1169         // HandlePsResultsUpdateL. In the worst case it'll flash on top of
       
  1170         // dialer's numeric keypad when listbox is made smaller.
       
  1171         if ( oldRectHeight != iContactListBox->Rect().Height() )
       
  1172             {
       
  1173             iContactListBox->DrawNow();
       
  1174             }
       
  1175 
       
  1176         iContactListBox->HandleItemAdditionL();
       
  1177         
       
  1178         // Scroll the list to bottom
       
  1179         iContactListBox->ScrollToMakeItemVisible( iNumberOfNames-1 );
       
  1180 
       
  1181         ShowContactListBoxWithEffect();
       
  1182         iContactListBox->View()->ItemDrawer()->ClearFlags( CListItemDrawer::ESingleClickDisabledHighlight );
       
  1183         static_cast<CEasyDialingListBoxView*>( iContactListBox->View() )->SetCurrentItemIndexToNone();
       
  1184         }
       
  1185     else
       
  1186         {  
       
  1187         HideContactListBoxWithEffect();
       
  1188         }
       
  1189 
       
  1190     if ( IsFocused() )
       
  1191         {
       
  1192         SetFocus( EFalse );
       
  1193         }
       
  1194 
       
  1195     DrawDeferred();
       
  1196 
       
  1197     InformObservers( MDialingExtensionObserver::ESearchComplete );
       
  1198     }
       
  1199 
       
  1200 
       
  1201 // -----------------------------------------------------------------------------
       
  1202 // void CCASimpleNotifyL()
       
  1203 // Implements MCCAObserver notification interface.
       
  1204 //
       
  1205 // -----------------------------------------------------------------------------
       
  1206 //
       
  1207 void CEasyDialingPlugin::CCASimpleNotifyL( TNotifyType aType, TInt aReason )
       
  1208     {
       
  1209     OstTraceExt2( TRACE_NORMAL, CEASYDIALINGPLUGIN_CCASIMPLENOTIFYL, "CCASimpleNotifyL: type: %d, reason: %d", ( TUint )( aType ), aReason );
       
  1210     LOGSTRING2("EasyDialingPlugin: CCASimpleNotifyL: type: %d, reason: %d", (TInt)aType, aReason );
       
  1211 
       
  1212     iContactLauncherActive = EFalse;
       
  1213 
       
  1214     CAknAppUi* appUi = static_cast<CAknAppUi*>( iCoeEnv->AppUi() );
       
  1215     appUi->HandleCommandL( EPhoneCmdBlockingDialogClosed );
       
  1216 
       
  1217     // Give up focus, if iRememberFocus flag is not set.
       
  1218     if ( !iRememberFocus )
       
  1219         {
       
  1220         SetFocus( EFalse );
       
  1221         DrawDeferred();
       
  1222         }    
       
  1223     iRememberFocus = EFalse;
       
  1224 
       
  1225     // Inform observers.
       
  1226     InformObservers( MDialingExtensionObserver::ECCALauncherExit );
       
  1227     }
       
  1228 
       
  1229 
       
  1230 // -----------------------------------------------------------------------------
       
  1231 // void LaunchCurrentContactL()
       
  1232 // Implements MCCAObserver notification interface.
       
  1233 //
       
  1234 // -----------------------------------------------------------------------------
       
  1235 //
       
  1236 void CEasyDialingPlugin::LaunchCurrentContactL()
       
  1237     {
       
  1238     __ASSERT_DEBUG( iNumberOfNames > 0, EasyDialingPanic( EEasyDialingPanicNoResults ) );
       
  1239     __ASSERT_DEBUG( iContactToBeLaunched, EasyDialingPanic( EEasyDialingPanicNoContactSelected ) );
       
  1240 
       
  1241     if (( iContactLauncherActive ) || ( iNumberOfNames == 0 ) || ( !iContactListBox ) || ( !iContactToBeLaunched ))
       
  1242         {
       
  1243         OstTrace0( TRACE_ERROR, CEASYDIALINGPLUGIN_LAUNCHCURRENTCONTACTL_ERROR, "LaunchCurrentContactL: Parameter error" );
       
  1244         LOGSTRING("EasyDialingPlugin: LaunchCurrentContactL - Parameter error");
       
  1245         return;
       
  1246         }
       
  1247 
       
  1248     MCCAParameter* launchParameters = TCCAFactory::NewParameterL();
       
  1249     CleanupClosePushL( *launchParameters );
       
  1250 
       
  1251     // ESoftExit flag causes that ca launcher will not close the 
       
  1252     // client application in any circumstance. 
       
  1253     // Application hosting easydialing is telephone application.
       
  1254     // It must never be closed, so we must use this flag.
       
  1255     launchParameters->SetConnectionFlag(MCCAParameter::ESoftExit);
       
  1256     
       
  1257     launchParameters->SetContactDataFlag(MCCAParameter::EContactLink);
       
  1258 
       
  1259     // Expand contact link into 16-bit descriptor because cca launcher api expects this. 
       
  1260     HBufC16* contact16 = HBufC16::NewLC( iContactToBeLaunched->Length() );
       
  1261     contact16->Des().Copy( *iContactToBeLaunched );
       
  1262 
       
  1263     launchParameters->SetContactDataL( *contact16 );
       
  1264 
       
  1265     CleanupStack::PopAndDestroy( contact16 );
       
  1266 
       
  1267     OstTraceExt1( TRACE_NORMAL, CEASYDIALINGPLUGIN_LAUNCHCURRENTCONTACTL_LAUNCH_CCA, "Launch CL for contact: '%S'", *iContactToBeLaunchedName );
       
  1268     LOGSTRING1("EasyDialingPlugin: Launch CL for contact: '%S'", iContactToBeLaunchedName );
       
  1269 
       
  1270     delete iContactToBeLaunched;
       
  1271     iContactToBeLaunched = NULL;
       
  1272     delete iContactToBeLaunchedName;
       
  1273     iContactToBeLaunchedName = NULL;    
       
  1274     
       
  1275     iContactLauncher->LaunchAppL( *launchParameters, this );
       
  1276 
       
  1277     // Ownership of parameter transferred to CCA launcher => pop but do not destroy.
       
  1278     CleanupStack::Pop( launchParameters );
       
  1279 
       
  1280     if ( !IsVisible() )
       
  1281         {
       
  1282         // MCCAConnection::LaunchAppL uses CActiveSchedulerWait to hide asynchronous
       
  1283         // opening of CCA launcher. It is possible that during opening of CCA launcher
       
  1284         // phone has moved to in-call view (at least in case of an incoming call).
       
  1285         // In that case we need to close CCA launcher again.
       
  1286         iContactLauncher->CloseAppL();
       
  1287         }
       
  1288     else
       
  1289         {
       
  1290         iContactLauncherActive = ETrue;
       
  1291         CAknAppUi* appUi = static_cast<CAknAppUi*>( iCoeEnv->AppUi() );
       
  1292         appUi->HandleCommandL( EPhoneCmdBlockingDialogLaunched );
       
  1293         }
       
  1294     }
       
  1295 
       
  1296 
       
  1297 // -----------------------------------------------------------------------------
       
  1298 // CreateListBoxContactStringL
       
  1299 //
       
  1300 // -----------------------------------------------------------------------------
       
  1301 //
       
  1302 void CEasyDialingPlugin::CreateListBoxContactStringL(
       
  1303         const TDesC& aContactString,
       
  1304         MVPbkContactLink *aLink,
       
  1305         TBool aMatchThumbnails,
       
  1306         TBool aFav )
       
  1307     {
       
  1308     // Construct the contact string for the listbox model.
       
  1309     iContactStringCreationBuffer.Zero();
       
  1310     
       
  1311     // Append contact thumbnail id.
       
  1312     HBufC* thumbnailId = iContactDataManager->GetThumbnailIdL( aLink, aMatchThumbnails, aFav );
       
  1313     iContactStringCreationBuffer.Append( *thumbnailId );
       
  1314     delete thumbnailId;
       
  1315     iContactStringCreationBuffer.Append( KListFieldSeparatorChar );
       
  1316     
       
  1317     AppendStringWithMatchDataL(
       
  1318             iContactStringCreationBuffer,
       
  1319             aContactString,
       
  1320             iPredictiveContactSearchHandler,
       
  1321             iPredictiveSearchQuery );
       
  1322     
       
  1323     // Append the whole string to listbox model.
       
  1324     iListBoxModel->AppendL( iContactStringCreationBuffer );
       
  1325     }
       
  1326 
       
  1327 // -----------------------------------------------------------------------------
       
  1328 // CreateContactStringLC
       
  1329 //
       
  1330 // -----------------------------------------------------------------------------
       
  1331 //
       
  1332 HBufC* CEasyDialingPlugin::CreateContactStringLC( CPsClientData* aResult,
       
  1333         CEasyDialingContactDataManager::TNameOrder aNameOrder )
       
  1334     {
       
  1335     TPtrC firstName = *aResult->Data( iFirstNamePCSIndex );
       
  1336     TPtrC lastName = *aResult->Data( iLastNamePCSIndex );
       
  1337     TPtrC companyName( KNullDesC );
       
  1338     
       
  1339     if ( iCompanyNamePCSIndex != KErrNotFound )
       
  1340         {
       
  1341         companyName.Set( *aResult->Data( iCompanyNamePCSIndex ) );
       
  1342         }
       
  1343     return EasyDialingUtils::CreateContactStringLC( firstName, lastName, companyName, aNameOrder );
       
  1344     }
       
  1345 
       
  1346 
       
  1347 // -----------------------------------------------------------------------------
       
  1348 // AddObserverL
       
  1349 //
       
  1350 // -----------------------------------------------------------------------------
       
  1351 //
       
  1352 void CEasyDialingPlugin::AddObserverL( MDialingExtensionObserver* aObserver )
       
  1353     {
       
  1354     if ( !aObserver )
       
  1355         {
       
  1356         return;
       
  1357         }
       
  1358     
       
  1359     iObservers.AppendL( aObserver );
       
  1360     }
       
  1361 
       
  1362 
       
  1363 // -----------------------------------------------------------------------------
       
  1364 // RemoveObserver
       
  1365 //
       
  1366 // Removes the parameter observer from observer list if found. If same observer
       
  1367 // has registered multiple times (which is unnecessary), removed just the first
       
  1368 // registration.
       
  1369 // -----------------------------------------------------------------------------
       
  1370 //
       
  1371 void CEasyDialingPlugin::RemoveObserver( MDialingExtensionObserver* aObserver )
       
  1372     {
       
  1373     for ( TInt i = 0; i < iObservers.Count(); i++ )
       
  1374         {
       
  1375         if ( iObservers[i] == aObserver)
       
  1376             {
       
  1377             iObservers.Remove( i );
       
  1378             return;
       
  1379             }
       
  1380         }
       
  1381     }
       
  1382 
       
  1383 
       
  1384 // -----------------------------------------------------------------------------
       
  1385 // InformObservers
       
  1386 // Informs all registered observers of easy dialing events.
       
  1387 // -----------------------------------------------------------------------------
       
  1388 //
       
  1389 void CEasyDialingPlugin::InformObservers( MDialingExtensionObserver::TEvent aEvent )
       
  1390     {
       
  1391     for ( TInt i = 0; i < iObservers.Count(); i++ )
       
  1392         {
       
  1393         iObservers[i]->HandleDialingExtensionEvent( aEvent );
       
  1394         }
       
  1395     }
       
  1396 
       
  1397 // -----------------------------------------------------------------------------
       
  1398 // CbaResourceId
       
  1399 // Returns EasyDialingPlugin specific CBA resource ID that
       
  1400 // Phone application can use when updating Soft Keys.
       
  1401 // -----------------------------------------------------------------------------
       
  1402 //
       
  1403 TInt CEasyDialingPlugin::CbaResourceId()
       
  1404     {
       
  1405     return R_EASYDIALING_CBA;
       
  1406     }
       
  1407 
       
  1408 
       
  1409 // -----------------------------------------------------------------------------
       
  1410 // MenuResourceId
       
  1411 // Returns EasyDialingPlugin specific menu resource ID that
       
  1412 // Phone application can use when easydialing is in focus.
       
  1413 // -----------------------------------------------------------------------------
       
  1414 //
       
  1415 TInt CEasyDialingPlugin::MenuResourceId()
       
  1416     {
       
  1417     return R_EASYDIALING_MENUBAR;
       
  1418     }
       
  1419 
       
  1420 
       
  1421 // -----------------------------------------------------------------------------
       
  1422 // InitializeMenuPaneL
       
  1423 // Initializes easy dialing menu pane. This function is meant to be called in 
       
  1424 // DynInitMenuPaneL of the application, if the application wants to use easy
       
  1425 // dialing menu.
       
  1426 // -----------------------------------------------------------------------------
       
  1427 //
       
  1428 TBool CEasyDialingPlugin::InitializeMenuPaneL( CEikMenuPane& aMenuPane, TInt aMenuResourceId )
       
  1429     {   
       
  1430     if ( aMenuResourceId == R_PHONEUIDIALER_OPTIONS_MENU )
       
  1431         {
       
  1432         TInt index( KErrNotFound );
       
  1433         // To be on the safe side - place holder was added into phoneui.rss.
       
  1434         if ( aMenuPane.MenuItemExists( EEasyDialingSettingsItemPlaceHolder, index ) )
       
  1435             {
       
  1436             // Add first menu item (= on/off submenu) after placeHolder item and 
       
  1437             // then delete that (empty) placeHolder.
       
  1438             aMenuPane.AddMenuItemsL( R_EASYDIALING_OPTIONS_ON_OFF_MENU_ITEM, 
       
  1439                                      EEasyDialingSettingsItemPlaceHolder );
       
  1440             aMenuPane.DeleteMenuItem( EEasyDialingSettingsItemPlaceHolder );
       
  1441             
       
  1442             LOGSTRING("EasyDialingPlugin::InitializeMenuPaneL: Added on/off menu into dialer's menu" );
       
  1443             }
       
  1444 
       
  1445         // Return EFalse as only one menu item was added here.
       
  1446         return EFalse; 
       
  1447         }
       
  1448     
       
  1449     else if ( aMenuResourceId == R_EASYDIALING_MENU )
       
  1450         {
       
  1451         TBool voiceCall = EFalse;
       
  1452         TBool videoCall = EFalse;
       
  1453         TBool message = EFalse;
       
  1454         
       
  1455         if ( iContactListBox->CurrentItemIndex() >= 0 ) 
       
  1456             {
       
  1457             TInt index = iContactListBox->CurrentContactDataIndex();
       
  1458             
       
  1459             voiceCall = iContactDataManager->VoiceCallAvailable( index );
       
  1460             videoCall = iContactDataManager->VideoCallAvailable( index );
       
  1461             message = iContactDataManager->UniEditorAvailable( index );
       
  1462             }
       
  1463             
       
  1464         
       
  1465         aMenuPane.SetItemDimmed( EEasyDialingVoiceCall, !voiceCall ); 
       
  1466         aMenuPane.SetItemDimmed( EEasyDialingVideoCall, !videoCall ); 
       
  1467         aMenuPane.SetItemDimmed( EEasyDialingSendMessage, !message ); 
       
  1468         
       
  1469         LOGSTRING("EasyDialingPlugin::InitializeMenuPaneL: InitializeMenuPaneL done" );
       
  1470         
       
  1471         return ETrue;  
       
  1472         }
       
  1473     
       
  1474     else if ( aMenuResourceId == R_EASYDIALING_OPTIONS_ON_OFF_CASCADE_MENU )
       
  1475         {
       
  1476         if ( IsEnabled() )
       
  1477             {
       
  1478             aMenuPane.SetItemButtonState( EEasyDialingOn, EEikMenuItemSymbolOn );
       
  1479             }
       
  1480         else
       
  1481             {
       
  1482             aMenuPane.SetItemButtonState( EEasyDialingOff, EEikMenuItemSymbolOn );
       
  1483             }
       
  1484         
       
  1485         LOGSTRING("EasyDialingPlugin::InitializeMenuPaneL: InitializeMenuPaneL for on/off submenu done" );
       
  1486         
       
  1487         return ETrue;
       
  1488         }
       
  1489     
       
  1490     else 
       
  1491         {
       
  1492         return EFalse;
       
  1493         }
       
  1494     }
       
  1495 
       
  1496 // -----------------------------------------------------------------------------
       
  1497 // HandleCommandL
       
  1498 // Method for handling EasyDialingPlugin specific commands.
       
  1499 // -----------------------------------------------------------------------------
       
  1500 //
       
  1501 TBool CEasyDialingPlugin::HandleCommandL( TInt aCommand )
       
  1502     {      
       
  1503     // Input blocker can't block controls higher on the control stack than 
       
  1504     // ECoeStackPriorityDialog so we will get HandleCommandL calls from 
       
  1505     // phoneappui (CBA) when input blocker is active (=not NULL).
       
  1506     
       
  1507     if ( iInputBlocker && aCommand != EEasyDialingCallHandlingActivated &&
       
  1508          aCommand != EEasyDialingVkbOpened && aCommand != EEasyDialingVkbClosed )
       
  1509         {
       
  1510         // Some action is already being launched since iInputBlocker exists.
       
  1511         // Only call activation command requires always action from this plugin.
       
  1512         // Vkb status flag should be updated always too (invokes no action).
       
  1513         return ETrue;
       
  1514         }
       
  1515  
       
  1516     
       
  1517     TBool ret(ETrue);
       
  1518     
       
  1519     switch ( aCommand )
       
  1520         {
       
  1521         case EEasyDialingOpenContact:
       
  1522             
       
  1523             iRememberFocus = ETrue;
       
  1524             AsyncActionLaunchL( ELaunchCurrentContact );
       
  1525             break;
       
  1526 
       
  1527         // EEasyDialingEnterKeyAction is sent when Enter key is pressed.
       
  1528         // EEasyDialingMakeCall is sent when send key or send toolbar button or send menu item is pressed.
       
  1529         case EEasyDialingVoiceCall: // fall through
       
  1530         case EEasyDialingEnterKeyAction:
       
  1531             // Make a call.
       
  1532             iRememberFocus = ETrue;
       
  1533             AsyncActionLaunchL( ECallCurrentContact );
       
  1534             break;
       
  1535             
       
  1536         // Video call is selectable only through menu.
       
  1537         case EEasyDialingVideoCall:
       
  1538             // Make a video call.
       
  1539             iRememberFocus = ETrue;
       
  1540             AsyncActionLaunchL( EVideoCallCurrentContact );
       
  1541             break;
       
  1542                 
       
  1543         // Uni-editor message is selectable only through menu.
       
  1544         case EEasyDialingSendMessage:
       
  1545             // Create a message.
       
  1546             iRememberFocus = ETrue;
       
  1547             AsyncActionLaunchL( ESendMessageCurrentContact );
       
  1548             break;
       
  1549                     
       
  1550         // EEasyDialingCallHandlingActivated is sent when the in-call-ui of telephony gets activated
       
  1551         case EEasyDialingCallHandlingActivated:
       
  1552             
       
  1553             iRememberFocus = EFalse;
       
  1554             // Stop input block and async action launch in case they are active.
       
  1555             CancelActionLaunchAndInputBlock();
       
  1556             // Close down number selection popup in case it happens to be open.
       
  1557             iContactorService->CancelService();
       
  1558             // Close down communication launcher if it's active
       
  1559             if ( iContactLauncherActive )
       
  1560                 {
       
  1561                 iNewSearchNeeded = EFalse;
       
  1562                 iContactLauncher->CloseAppL();
       
  1563                 }
       
  1564             break;
       
  1565             
       
  1566         case EEasyDialingOn:
       
  1567             
       
  1568             iCenrepListener->SetEasyDialingSettingsValue( 1 );
       
  1569             break;
       
  1570 
       
  1571         case EEasyDialingOff:
       
  1572             
       
  1573             iCenrepListener->SetEasyDialingSettingsValue( 0 );
       
  1574             break;    
       
  1575             
       
  1576         case EEasyDialingClosePopup:
       
  1577             
       
  1578             // Not only Number Entry is removed but also closes down number selection popup in case it happens to be open.
       
  1579             iContactorService->CancelService();
       
  1580             break;
       
  1581             
       
  1582         case EEasyDialingVkbOpened:
       
  1583             
       
  1584             iVirtualKeyboardOpen = ETrue;
       
  1585             break;
       
  1586                   
       
  1587         case EEasyDialingVkbClosed:
       
  1588             
       
  1589             iVirtualKeyboardOpen = EFalse;
       
  1590             HandleGainingForeground();
       
  1591             break;
       
  1592             
       
  1593         default:
       
  1594             ret = EFalse;
       
  1595             break;
       
  1596         }
       
  1597     return ret;
       
  1598     }
       
  1599 
       
  1600 // -----------------------------------------------------------------------------
       
  1601 // IsEnabled
       
  1602 // Check if Easy dialing is enabled in the settings
       
  1603 // -----------------------------------------------------------------------------
       
  1604 //
       
  1605 TBool CEasyDialingPlugin::IsEnabled() const
       
  1606     {
       
  1607     return ( iCenrepListener && iCenrepListener->Value() != 0 );
       
  1608     }
       
  1609 
       
  1610 // -----------------------------------------------------------------------------
       
  1611 // SetKeyboardMode
       
  1612 // Sets keyboard mode
       
  1613 // -----------------------------------------------------------------------------
       
  1614 //
       
  1615 void CEasyDialingPlugin::SetKeyboardMode( TKeyboardMode aMode )
       
  1616     {
       
  1617     iKeyboardMode = aMode;
       
  1618     }
       
  1619 
       
  1620 // -----------------------------------------------------------------------------
       
  1621 // AsyncSimulateKeyEvent
       
  1622 // 
       
  1623 // -----------------------------------------------------------------------------
       
  1624 //
       
  1625 void CEasyDialingPlugin::AsyncSimulateKeyEvent( const TKeyEvent& aKeyEvent )
       
  1626     {
       
  1627     // Do the simulation only if input hasn't been blocked
       
  1628     if ( !iInputBlocker )
       
  1629         {
       
  1630         iKeyEventToSimulate = aKeyEvent;
       
  1631         iActionToBeLaunched = ESimulateKeyEvent;
       
  1632         iAsyncCallBack->SetPriority( CActive::EPriorityStandard );
       
  1633         iAsyncCallBack->CallBack(); // activates callback request
       
  1634         }
       
  1635     }
       
  1636 
       
  1637 // -----------------------------------------------------------------------------
       
  1638 // AsyncActionLaunchL
       
  1639 // Use asynchronous callback to launch action. While action is being launched,
       
  1640 // input blocker is used to avoid OfferKeyEvent and HandlePointerEvent calls
       
  1641 // coming in. Both end key and application key work despite of input blocker.
       
  1642 // Input blocker can't block phoneappui's cba so extra check is needed in
       
  1643 // HandleCommandL method.
       
  1644 // -----------------------------------------------------------------------------
       
  1645 //
       
  1646 void CEasyDialingPlugin::AsyncActionLaunchL( TEasyDialingAction aAction )
       
  1647     {
       
  1648     iActionToBeLaunched = aAction;
       
  1649 
       
  1650     delete iContactToBeLaunched;
       
  1651     iContactToBeLaunched = NULL;
       
  1652     delete iContactToBeLaunchedName;
       
  1653     iContactToBeLaunchedName = NULL;
       
  1654        
       
  1655     if ( aAction == ECallCurrentContact
       
  1656             || aAction == EVideoCallCurrentContact
       
  1657             || aAction == ESendMessageCurrentContact
       
  1658             || aAction == ELaunchCurrentContact )
       
  1659         {
       
  1660         // Need to save current contact link and name. Listbox current item
       
  1661         // index might not be correct when callback is handled.
       
  1662         TRAPD( err, iContactToBeLaunched = iContactListBox->CurrentContactLinkL() );
       
  1663         if ( err || !iContactToBeLaunched )
       
  1664             {
       
  1665             // Can't find contact for the action - probably because listbox
       
  1666             // has lost the selection somehow. This shouldn't happen, but if it does
       
  1667             // return without trying to launch any action.
       
  1668             return;
       
  1669             }
       
  1670         
       
  1671         TPtrC contactString( iListBoxModel->MdcaPoint( iContactListBox->CurrentItemIndex() ) );
       
  1672         TPtrC fullNameSeparators;
       
  1673         TInt error = TextUtils::ColumnText( fullNameSeparators, 1, &contactString );
       
  1674         __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) );
       
  1675         
       
  1676         // Remove highlight separators. It is possible that some contactor API has problem with them.
       
  1677         iContactToBeLaunchedName = AllocWithoutHighlightSeparatorsLC( fullNameSeparators );
       
  1678         CleanupStack::Pop( iContactToBeLaunchedName );
       
  1679         }
       
  1680     
       
  1681     CancelActionLaunchAndInputBlock();
       
  1682     
       
  1683     if ( aAction == ELaunchSearch )
       
  1684         {
       
  1685         // Must be set as low as possible to enable PCS to update its store.
       
  1686         iAsyncCallBack->SetPriority( CActive::EPriorityIdle );
       
  1687         }
       
  1688     else
       
  1689         {
       
  1690         iAsyncCallBack->SetPriority( CActive::EPriorityStandard );
       
  1691         }
       
  1692     
       
  1693     iAsyncCallBack->CallBack(); // activates callback request
       
  1694     
       
  1695     // By defining cancel handler, we don't block all input but system is still
       
  1696     // able to deactivate the view etc.
       
  1697     iInputBlocker = CAknInputBlock::NewCancelHandlerLC( this );
       
  1698     CleanupStack::Pop( iInputBlocker );
       
  1699     
       
  1700     // This means that iInputBlocker is deleted by CAknInputBlock when
       
  1701     // it's cancelled ( we get a callback where iInputBlocker is set to NULL).
       
  1702     iInputBlocker->SetCancelDelete( iInputBlocker );
       
  1703     }
       
  1704 
       
  1705 // -----------------------------------------------------------------------------
       
  1706 // AsyncCallBackToLaunchAction
       
  1707 // Callback function for CAsyncCallBack class.
       
  1708 // -----------------------------------------------------------------------------
       
  1709 //
       
  1710 TInt CEasyDialingPlugin::AsyncCallBackToLaunchAction( TAny* aPtr )
       
  1711     {
       
  1712     CEasyDialingPlugin* plugin = static_cast<CEasyDialingPlugin*>( aPtr );
       
  1713     
       
  1714     TRAP_IGNORE( plugin->DoLaunchActionL() );
       
  1715     
       
  1716     // Stop input block if active (=not NULL).
       
  1717     if ( plugin->iInputBlocker )
       
  1718         {
       
  1719         plugin->iInputBlocker->Cancel();
       
  1720         }
       
  1721     
       
  1722     plugin->iActionToBeLaunched = ENoActionDefined;
       
  1723     
       
  1724     return KErrNone;
       
  1725     }
       
  1726     
       
  1727 // -----------------------------------------------------------------------------
       
  1728 // DoLaunchActionL
       
  1729 //
       
  1730 // -----------------------------------------------------------------------------
       
  1731 //
       
  1732 void CEasyDialingPlugin::DoLaunchActionL()
       
  1733     {
       
  1734     if ( iActionToBeLaunched == EInitializePcs )
       
  1735         {
       
  1736         PERF_MEASURE_START
       
  1737         InitPredictiveContactSearchL();
       
  1738         PERF_MEASURE_STOP
       
  1739  
       
  1740         return;
       
  1741         }
       
  1742     else if ( !IsVisible() )
       
  1743         {
       
  1744         // If ED is not visible, don't launch the action. This can happen if
       
  1745         // we get incoming call in the middle of action launching.
       
  1746         return;
       
  1747         }
       
  1748     // If ELaunchCurrentContact, then we launch cca launcher.
       
  1749     else if ( iActionToBeLaunched == ELaunchCurrentContact )
       
  1750         {
       
  1751         LaunchCurrentContactL();
       
  1752         return;
       
  1753         }
       
  1754     else if ( iActionToBeLaunched == ELaunchSearch )
       
  1755         {
       
  1756         LaunchSearchL();
       
  1757         return;
       
  1758         }
       
  1759     else if ( iActionToBeLaunched == ESimulateKeyEvent )
       
  1760         {
       
  1761         iEikonEnv->SimulateKeyEventL( iKeyEventToSimulate, EEventKey );
       
  1762         return;
       
  1763         }
       
  1764     
       
  1765     // If not for launching current contact or performing search, 
       
  1766     // the action is launching some communication method.
       
  1767     
       
  1768     if ( iContactorService->IsBusy() )
       
  1769         {
       
  1770         LOGSTRING("EasyDialingPlugin: LaunchActionL - contactor service is busy!");
       
  1771         return;
       
  1772         }
       
  1773  
       
  1774     VPbkFieldTypeSelectorFactory::TVPbkContactActionTypeSelector selector( 
       
  1775             VPbkFieldTypeSelectorFactory::EEmptySelector );
       
  1776     
       
  1777     switch ( iActionToBeLaunched ) 
       
  1778         {
       
  1779         case ECallCurrentContact:
       
  1780             {
       
  1781             // Easy Dialing provides pretty much the same functionality for big Call icon 
       
  1782             // and Send key than phonebook's contact list view by using aiw interface 
       
  1783             // in edcontactor.
       
  1784             // At this point one must however check whether to use voip or voice call selector - 
       
  1785             // otherwise correct logic is provided by aiw interface.
       
  1786             // Note that Easy Dialing ignores default numbers and addresses set for
       
  1787             // action types and shows always the number and address list if there are
       
  1788             // more than one possible number/address for some action.
       
  1789              
       
  1790             CSPSettingsVoIPUtils* sPSettings = CSPSettingsVoIPUtils::NewLC();
       
  1791             
       
  1792             if ( sPSettings->IsPreferredTelephonyVoIP() )
       
  1793                 {
       
  1794                 selector = VPbkFieldTypeSelectorFactory::EVOIPCallSelector;
       
  1795                 }
       
  1796             else
       
  1797                 {
       
  1798                 selector = VPbkFieldTypeSelectorFactory::EVoiceCallSelector;
       
  1799                 }
       
  1800             
       
  1801             CleanupStack::PopAndDestroy( sPSettings );
       
  1802             }
       
  1803             break;
       
  1804             
       
  1805         case EVideoCallCurrentContact:
       
  1806             
       
  1807             selector = VPbkFieldTypeSelectorFactory::EVideoCallSelector;
       
  1808             break;
       
  1809             
       
  1810         case ESendMessageCurrentContact:
       
  1811             
       
  1812             selector = VPbkFieldTypeSelectorFactory::EUniEditorSelector;
       
  1813             break;
       
  1814             
       
  1815         default:
       
  1816             delete iContactToBeLaunched;
       
  1817             iContactToBeLaunched = NULL;
       
  1818             delete iContactToBeLaunchedName;
       
  1819             iContactToBeLaunchedName = NULL;
       
  1820             __ASSERT_DEBUG( EFalse, EasyDialingPanic( EEasyDialingActionNotSupported ) );
       
  1821             return;
       
  1822         }
       
  1823 
       
  1824     CEDContactorService::TCSParameter param( selector, *iContactToBeLaunched, 
       
  1825                                              CEDContactorService::TCSParameter::EEnableDefaults, 
       
  1826                                              *iContactToBeLaunchedName );
       
  1827 
       
  1828     iContactorService->ExecuteServiceL( param );
       
  1829 
       
  1830     delete iContactToBeLaunched;
       
  1831     iContactToBeLaunched = NULL;
       
  1832     delete iContactToBeLaunchedName;
       
  1833     iContactToBeLaunchedName = NULL;
       
  1834     }
       
  1835 
       
  1836 
       
  1837 // -----------------------------------------------------------------------------
       
  1838 // CancelActionLaunchAndInputBlock
       
  1839 // Should be called when focus is lost or when call ui is activated.
       
  1840 // -----------------------------------------------------------------------------
       
  1841 //
       
  1842 void CEasyDialingPlugin::CancelActionLaunchAndInputBlock()
       
  1843     {
       
  1844     iAsyncCallBack->Cancel();
       
  1845     if ( iInputBlocker )
       
  1846         {
       
  1847         iInputBlocker->Cancel();
       
  1848         }
       
  1849     }
       
  1850 
       
  1851 // -----------------------------------------------------------------------------
       
  1852 // HandleListBoxEventL
       
  1853 // EasyDialerListBox calls this function when listbox events are reported
       
  1854 // to observers.
       
  1855 // -----------------------------------------------------------------------------
       
  1856 //
       
  1857 void CEasyDialingPlugin::HandleListBoxEventL( CEikListBox* /*aListBox*/, TListBoxEvent aEventType )
       
  1858     {
       
  1859     LOGSTRING1( "EasyDialingPlugin: HandleListBoxEventL( %d ) - Enter", aEventType );
       
  1860 
       
  1861     switch( aEventType )
       
  1862         {
       
  1863         case EEventItemSingleClicked:
       
  1864             // 9.2. Selecting contact initiates call
       
  1865             AsyncActionLaunchL( ECallCurrentContact );
       
  1866             break;
       
  1867 
       
  1868         case KEasyDialingContactLongTapped:
       
  1869             iLongTapped = ETrue;
       
  1870             AsyncActionLaunchL( ELaunchCurrentContact );
       
  1871             break;
       
  1872             
       
  1873         // Pause contact data manager when panning and flicking listbox.
       
  1874         // This ensures smooth and responsive listbox touch handling.
       
  1875         case EEventFlickStarted:
       
  1876         case EEventPanningStarted:
       
  1877         case KEasyDialingScrollingStarted:
       
  1878             iContactDataManager->Pause( ETrue );
       
  1879             break;
       
  1880             
       
  1881         case EEventFlickStopped:
       
  1882         case EEventPanningStopped:
       
  1883         case KEasyDialingScrollingStopped:
       
  1884             iContactListBox->View()->ItemDrawer()->ClearFlags( CListItemDrawer::ESingleClickDisabledHighlight );
       
  1885             static_cast<CEasyDialingListBoxView*>( iContactListBox->View() )->SetCurrentItemIndexToNone();
       
  1886             iContactDataManager->Pause( EFalse );
       
  1887             
       
  1888             // Touching the listbox always removes the visual focus from any list item.
       
  1889             // Move the focus away from the listbox after panning has ended to
       
  1890             // align our internal state with the visual lack of focus.
       
  1891             if ( IsFocused() && !iLongTapped )
       
  1892                 {
       
  1893                 SetFocus( EFalse );
       
  1894                 DrawDeferred();
       
  1895                 }
       
  1896             iLongTapped = EFalse;
       
  1897             break;
       
  1898             
       
  1899         // We are not interested about the other listbox events.
       
  1900         default:
       
  1901             break;
       
  1902         }
       
  1903     }
       
  1904 
       
  1905 // -----------------------------------------------------------------------------
       
  1906 // From MAknInputBlockCancelHandler.
       
  1907 // Called when input block is cancelled.
       
  1908 // -----------------------------------------------------------------------------
       
  1909 //
       
  1910 void CEasyDialingPlugin::AknInputBlockCancel()
       
  1911     {
       
  1912     LOGSTRING("EasyDialingPlugin: AknInputBlockCancel");
       
  1913     
       
  1914     // iInputBlocker will be deleted right after this callback by CAknInputBlock
       
  1915     // cause we are using CAknInputBlock::SetCancelDelete method.
       
  1916     iInputBlocker = NULL;
       
  1917     }
       
  1918 
       
  1919 // -----------------------------------------------------------------------------
       
  1920 // HandleGainingForeground
       
  1921 // From MCoeForegroundObserver.
       
  1922 // -----------------------------------------------------------------------------
       
  1923 //
       
  1924 void CEasyDialingPlugin::HandleGainingForeground()
       
  1925     {
       
  1926     if ( iNewSearchNeeded && IsEnabled() )
       
  1927         {
       
  1928         // The cached information in contact data manager may be outdated. Call to reload makes sure that when the 
       
  1929         // search is made, all data is loaded again.
       
  1930         iContactDataManager->Reload();
       
  1931         
       
  1932         TRAP_IGNORE( LaunchSearchL() );
       
  1933         }
       
  1934     }
       
  1935 
       
  1936 // -----------------------------------------------------------------------------
       
  1937 // HandleLosingForeground
       
  1938 // From MCoeForegroundObserver.
       
  1939 // -----------------------------------------------------------------------------
       
  1940 //
       
  1941 void CEasyDialingPlugin::HandleLosingForeground()
       
  1942     {
       
  1943     // Make sure contact data manager is not left in paused state when
       
  1944     // ED loses foreground while scrolling is active.
       
  1945     iContactDataManager->Pause( EFalse );
       
  1946     
       
  1947     // Simulate an EButton1Up event for scrollbar so that it will be in correct
       
  1948     // state if e.g. some popup appears while scrollbar is dragged.
       
  1949     // No need to check if scrollbar has received button1Down event or
       
  1950     // is indeed dragged currently: no harm done if button1Up is simulated 
       
  1951     // in vain.
       
  1952     CEikScrollBarFrame* scrollBarFrame = iContactListBox->ScrollBarFrame();
       
  1953     if ( scrollBarFrame )
       
  1954         {
       
  1955         CEikScrollBar* scrollBar = scrollBarFrame->VerticalScrollBar();
       
  1956         if ( scrollBar && scrollBar->IsVisible() )
       
  1957             {
       
  1958             TPointerEvent simulatedPointerEvent( TPointerEvent::EButton1Up, 0,
       
  1959                                                  TPoint(), TPoint() );
       
  1960             TRAP_IGNORE( scrollBar->HandlePointerEventL( simulatedPointerEvent ) );
       
  1961             }
       
  1962         }
       
  1963     }
       
  1964 
       
  1965 // -----------------------------------------------------------------------------
       
  1966 // CEasyDialingPlugin::DoHandleContactsChangedL
       
  1967 // -----------------------------------------------------------------------------
       
  1968 //
       
  1969 void CEasyDialingPlugin::DoHandleContactsChangedL()
       
  1970     {
       
  1971     if ( iSearchString.Length() > 0 && IsEnabled() )
       
  1972         {
       
  1973         CAknAppUi* appUi = static_cast<CAknAppUi*>( iCoeEnv->AppUi() );
       
  1974         if ( appUi->IsForeground() && !iVirtualKeyboardOpen )
       
  1975             {
       
  1976             // Do new search immediately, if contacts change while we are on the
       
  1977             // foreground. This can happen for example if view is switched to
       
  1978             // dialer while deletion of multiple contacts is still ongoing or if
       
  1979             // PCS takes so long to update the cache that view gets changed 
       
  1980             // before the update is ready.
       
  1981             iContactDataManager->Reload(); // to update thumbnails
       
  1982             AsyncActionLaunchL( ELaunchSearch );
       
  1983             }
       
  1984         else
       
  1985             {
       
  1986             // Set the flag to make a search when we come back to foreground.
       
  1987             // This way, we don't make unnecessary searches when several
       
  1988             // contacts are imported or deleted, for example.
       
  1989             iNewSearchNeeded = ETrue;
       
  1990             
       
  1991             // Hide previous results so that they won't show up before the
       
  1992             // the new search is ready.
       
  1993             iContactListBox->MakeVisible( EFalse );
       
  1994             }
       
  1995         }
       
  1996     }
       
  1997 
       
  1998 // -----------------------------------------------------------------------------
       
  1999 // CEasyDialingPlugin::ShowContactListBoxWithEffect
       
  2000 // Use appear/disappear effects when in foreground and when listbox truly
       
  2001 // changes visiblity.
       
  2002 // -----------------------------------------------------------------------------
       
  2003 //
       
  2004 void CEasyDialingPlugin::ShowContactListBoxWithEffect()
       
  2005     {
       
  2006     if ( !IsVisible() )
       
  2007         {
       
  2008         // never show listbox if easydialing is not visible
       
  2009         return;
       
  2010         }
       
  2011     // Show effect only if listbox is about to come visible.
       
  2012     else if ( !iContactListBox->IsVisible() && CanListBoxEffectBeUsed() )
       
  2013         {
       
  2014         GfxTransEffect::Begin( iContactListBox, KGfxContactListBoxOpenEffect );
       
  2015         iContactListBox->MakeVisible( ETrue );
       
  2016         GfxTransEffect::SetDemarcation( iContactListBox, iContactListBox->Rect() );
       
  2017         GfxTransEffect::End( iContactListBox );
       
  2018         }
       
  2019     else
       
  2020         {
       
  2021         iContactListBox->MakeVisible( ETrue );
       
  2022         }
       
  2023     }
       
  2024 
       
  2025 // -----------------------------------------------------------------------------
       
  2026 // CEasyDialingPlugin::HideContactListBoxWithEffect
       
  2027 // -----------------------------------------------------------------------------
       
  2028 //
       
  2029 void CEasyDialingPlugin::HideContactListBoxWithEffect()
       
  2030     {
       
  2031     // Show effect only if listbox is about to disappear from the screen.
       
  2032     if ( iContactListBox->IsVisible() && CanListBoxEffectBeUsed() )
       
  2033         {
       
  2034         GfxTransEffect::Begin( iContactListBox, KGfxContactListBoxCloseEffect );
       
  2035         iContactListBox->MakeVisible( EFalse );
       
  2036         GfxTransEffect::SetDemarcation( iContactListBox, iContactListBox->Rect() );
       
  2037         GfxTransEffect::End( iContactListBox );
       
  2038         }
       
  2039     else
       
  2040         {
       
  2041         iContactListBox->MakeVisible( EFalse );
       
  2042         }
       
  2043     }
       
  2044 
       
  2045 // -----------------------------------------------------------------------------
       
  2046 // CEasyDialingPlugin::CanListBoxEffectBeUsed
       
  2047 // -----------------------------------------------------------------------------
       
  2048 //
       
  2049 TBool CEasyDialingPlugin::CanListBoxEffectBeUsed() const
       
  2050     {
       
  2051     TBool canBeUsed( EFalse );
       
  2052     
       
  2053     CAknAppUi* appUi = static_cast<CAknAppUi*>( iCoeEnv->AppUi() );
       
  2054     
       
  2055     // Note that when vkb is open, phone still keeps foreground and focus so
       
  2056     // vkb status must be checked separately (vkb's window group has just higher
       
  2057     // priority than phone's window group).
       
  2058     if ( appUi && appUi->IsForeground() &&
       
  2059          !iVirtualKeyboardOpen &&
       
  2060          GfxTransEffect::IsEnabled() &&
       
  2061          GfxTransEffect::IsRegistered( iContactListBox ) )
       
  2062         {
       
  2063         canBeUsed = ETrue;
       
  2064         }
       
  2065     
       
  2066     return canBeUsed;
       
  2067     }
       
  2068 
       
  2069 // -----------------------------------------------------------------------------
       
  2070 // CEasyDialingPlugin::SetInfoLabelColourL
       
  2071 // -----------------------------------------------------------------------------
       
  2072 //
       
  2073 void CEasyDialingPlugin::SetInfoLabelColourL()
       
  2074     {
       
  2075     MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
  2076     TRgb skinColor;
       
  2077     TInt error = AknsUtils::GetCachedColor( skin, skinColor,
       
  2078             KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6 );
       
  2079             
       
  2080     if ( error == KErrNone )
       
  2081         {
       
  2082         iInfoLabelLine1->OverrideColorL( EColorLabelText, skinColor );
       
  2083         iInfoLabelLine2->OverrideColorL( EColorLabelText, skinColor );
       
  2084         }    
       
  2085     }
       
  2086 
       
  2087 // -----------------------------------------------------------------------------
       
  2088 // CEasyDialingPlugin::SetInfoLabelVisibleL
       
  2089 // -----------------------------------------------------------------------------
       
  2090 //
       
  2091 void CEasyDialingPlugin::SetInfoLabelVisibleL( TBool aVisible )
       
  2092     {
       
  2093     if ( aVisible )
       
  2094         {
       
  2095         iInfoLabelLine1->SetTextL( *iInfoLabelTextLine1 );
       
  2096         iInfoLabelLine2->SetTextL( *iInfoLabelTextLine2 );
       
  2097         }
       
  2098     else
       
  2099         {
       
  2100         iInfoLabelLine1->SetTextL( KNullDesC );
       
  2101         iInfoLabelLine2->SetTextL( KNullDesC );
       
  2102         }    
       
  2103     iInfoLabelLine1->DrawDeferred();
       
  2104     iInfoLabelLine2->DrawDeferred();
       
  2105     }
       
  2106 
       
  2107 
       
  2108 /*
       
  2109  * ==============================================================================
       
  2110  * 
       
  2111  * Local functions
       
  2112  * 
       
  2113  * ==============================================================================
       
  2114  */
       
  2115 
       
  2116 
       
  2117 
       
  2118 // -----------------------------------------------------------------------------
       
  2119 // CompareTPsMatchLocation
       
  2120 // Compares two TPsMatchLocation objects based on where the match 
       
  2121 // is located in the search string. This used in ordering matches
       
  2122 // based on their location.
       
  2123 // -----------------------------------------------------------------------------
       
  2124 //
       
  2125 TInt CompareTPsMatchLocation( const TPsMatchLocation& a1, const TPsMatchLocation& a2)
       
  2126     {
       
  2127     return a1.index - a2.index;
       
  2128     }
       
  2129 
       
  2130 
       
  2131 // -----------------------------------------------------------------------------
       
  2132 // AppendStringWithMatchDataL
       
  2133 // Appends a string with match data into a TDes buffer. Match data is a string 
       
  2134 // where matching and non-matching parts are separated by matching hightlight separator
       
  2135 // characters.
       
  2136 // -----------------------------------------------------------------------------
       
  2137 //
       
  2138 void AppendStringWithMatchDataL(
       
  2139         TDes& aBuffer,
       
  2140         const TDesC& aText,
       
  2141         CPSRequestHandler* aPSHandler,
       
  2142         const CPsQuery* aPSQuery )
       
  2143     {
       
  2144     if ( HighlightingSupportedForText( aText ) )
       
  2145         {
       
  2146         CDesCArrayFlat* matchingParts = new (ELeave) CDesCArrayFlat(KEasyDialingMaximumMatchingParts);
       
  2147         CleanupStack::PushL( matchingParts );
       
  2148      
       
  2149         RArray<TPsMatchLocation> matchIndices;
       
  2150         CleanupClosePushL( matchIndices );
       
  2151         
       
  2152         aPSHandler->LookupL( *aPSQuery , aText , *matchingParts, matchIndices );
       
  2153         
       
  2154         // Sort matchIndices array. Later handling assumes it to be sorted according to index field.
       
  2155         TLinearOrder<TPsMatchLocation> order( CompareTPsMatchLocation );
       
  2156         matchIndices.Sort( order );
       
  2157        
       
  2158         TInt numberOfIndices = matchIndices.Count();
       
  2159         TInt textOffset = 0;
       
  2160         
       
  2161         for ( TInt i = 0; i < numberOfIndices ; i++ )
       
  2162             {
       
  2163             TInt matchingPartStart = matchIndices[i].index;
       
  2164             TInt matchingPartLength = matchIndices[i].length;
       
  2165             
       
  2166             // Append the non-matching part (if exists) 
       
  2167             if ( matchingPartStart > textOffset )
       
  2168                 {
       
  2169                 TPtrC notMatchingPart = aText.Mid( textOffset, matchingPartStart - textOffset );
       
  2170                 aBuffer.Append( notMatchingPart );
       
  2171                 }
       
  2172             
       
  2173             // Append matching separator charactes.
       
  2174             aBuffer.Append( KHighlightSeparatorChar );
       
  2175             
       
  2176             TPtrC matchingPart = aText.Mid( matchingPartStart, matchingPartLength );
       
  2177             aBuffer.Append( matchingPart );
       
  2178             
       
  2179             // Append matching separator charactes.
       
  2180             aBuffer.Append( KHighlightSeparatorChar );
       
  2181             
       
  2182             textOffset = matchingPartStart + matchingPartLength;
       
  2183             }
       
  2184 
       
  2185         CleanupStack::PopAndDestroy( &matchIndices );
       
  2186         CleanupStack::PopAndDestroy( matchingParts );
       
  2187 
       
  2188         // Now there still may be one not matching part to be appended.
       
  2189         if ( textOffset < aText.Length() )
       
  2190             {
       
  2191             TPtrC notMatchingPart = aText.Mid( textOffset, aText.Length() - textOffset );
       
  2192             aBuffer.Append( notMatchingPart );
       
  2193             }
       
  2194         }
       
  2195     else // HighlightingSupportedForText( aText )
       
  2196         {
       
  2197         aBuffer.Append( aText );
       
  2198         }
       
  2199     }
       
  2200 
       
  2201 // -----------------------------------------------------------------------------
       
  2202 // HighlightingSupportedForText
       
  2203 // Checks if highlighting of matching text part is supported for the combination
       
  2204 // of scripts used in the given text
       
  2205 // -----------------------------------------------------------------------------
       
  2206 //
       
  2207 TBool HighlightingSupportedForText( const TDesC& aText )
       
  2208     {
       
  2209     // Highlighting for text is supported unless it contains one ore more
       
  2210     // characters written with unsupported script.
       
  2211     TBool supported = ETrue;
       
  2212     for ( TInt i = 0 ; i < aText.Length() && supported ; ++i )
       
  2213         {
       
  2214         supported = HighlightingSupportedForScript( aText[i] );
       
  2215         }
       
  2216     
       
  2217     // ... or it contains both LTR and RTL blocks
       
  2218     if ( supported )
       
  2219         {
       
  2220         supported = !IsStrictlyBidirectional( aText );
       
  2221         }
       
  2222     
       
  2223     return supported;
       
  2224     }
       
  2225 
       
  2226 // -----------------------------------------------------------------------------
       
  2227 // HighlightingSupportedForScript
       
  2228 // Checks if highlighting of matching text part is supported for the script
       
  2229 // of given character
       
  2230 // -----------------------------------------------------------------------------
       
  2231 //
       
  2232 TBool HighlightingSupportedForScript( TText aChar )
       
  2233     {
       
  2234     // For now, we don't support highlighting for any Arabic or South East Asian 
       
  2235     // script. This is because many of these scripts use rendering rules
       
  2236     // which cause problems for our simple highlighting logic designed for
       
  2237     // Latin script.
       
  2238 
       
  2239     TBool belongsToUnsupportedRange = 
       
  2240         ( aChar >= KArabicAndSouthEastAsianRangeStart && aChar <= KArabicAndSouthEastAsianRangeEnd ) ||
       
  2241         ( aChar >= KArabicPresentationFormsARangenStart && aChar <= KArabicPresentationFormsARangeEnd ) ||
       
  2242         ( aChar >= KArabicPresentationFormsBRangenStart && aChar <= KArabicPresentationFormsBRangeEnd );
       
  2243     return !belongsToUnsupportedRange;
       
  2244     }
       
  2245 
       
  2246 // -----------------------------------------------------------------------------
       
  2247 // IsStrictlyBidirectional
       
  2248 // 
       
  2249 // Returns true if argument descriptor contains both left-to-right and
       
  2250 // right-to-left blocks
       
  2251 // -----------------------------------------------------------------------------
       
  2252 //
       
  2253 TBool IsStrictlyBidirectional( const TDesC& aText )
       
  2254     {
       
  2255     TBool bothDirectionsFound = EFalse;
       
  2256     
       
  2257     // TRunInfoArray contains information of the directionalities of the different sections of the aText    
       
  2258     TBidirectionalState::TRunInfo array[ KMaxRunInfoArrayCount ];
       
  2259     
       
  2260     // Initialize the TBidiLogicalToVisual converter for making the conversion from logical to visual order
       
  2261     TBidiLogicalToVisual converter( aText, array, KMaxRunInfoArrayCount );
       
  2262     
       
  2263     // Do the reordering. Amount of different directionality sections is returned.
       
  2264     TInt blockCount = converter.Reorder();
       
  2265     if ( blockCount > KMaxRunInfoArrayCount )
       
  2266         {
       
  2267         // If there are  more directionality blocks than we are prepared to handle, then we don't
       
  2268         // know the directionality of them all. Report this as bidirectional to be on the safe side.
       
  2269         // This should be an extremely rare special case.
       
  2270         bothDirectionsFound = ETrue;
       
  2271         }
       
  2272     else if ( blockCount > 1 )
       
  2273         {
       
  2274         // If there are more than one directionality blocks, go through all of them and
       
  2275         // check if the resolved direction changes in any of the blocks.
       
  2276         TUint8 firstDirection = array[0].iDirection;
       
  2277         for ( TInt i = 1 ; i < blockCount && !bothDirectionsFound ; i++ )
       
  2278             {
       
  2279             if ( array[i].iDirection != firstDirection )
       
  2280                 {
       
  2281                 bothDirectionsFound = ETrue;
       
  2282                 }
       
  2283             }
       
  2284         }
       
  2285 
       
  2286     return bothDirectionsFound;
       
  2287     }
       
  2288 
       
  2289 
       
  2290 // -----------------------------------------------------------------------------
       
  2291 // AllocWithoutHighlightSeparatorsLC
       
  2292 // 
       
  2293 // Allocates a copy of the parameter descriptor with highlight separators 
       
  2294 // removed.
       
  2295 // -----------------------------------------------------------------------------
       
  2296 //
       
  2297 static HBufC* AllocWithoutHighlightSeparatorsLC( const TDesC& aDesc )
       
  2298     {
       
  2299     HBufC* resultDesc = aDesc.AllocLC();
       
  2300     TPtr ptr = resultDesc->Des();
       
  2301     AknTextUtils::StripCharacters( ptr, KHighlightSeparatorCharAsLiteral );
       
  2302     return resultDesc;
       
  2303     }
       
  2304 
       
  2305 
       
  2306 // -----------------------------------------------------------------------------
       
  2307 // IsItuTCharacter
       
  2308 // 
       
  2309 // Test whether parameter character is a number pad character "0123456789#*+"
       
  2310 // -----------------------------------------------------------------------------
       
  2311 //
       
  2312 static TBool IsItuTCharacter( TChar aChar )
       
  2313     {
       
  2314     return aChar.IsDigit() || 
       
  2315          aChar.GetCategory() == TChar::EArabicNumber ||
       
  2316          aChar == TChar('#') ||
       
  2317          aChar == TChar('*') ||
       
  2318          aChar == TChar('+');
       
  2319     }
       
  2320 
       
  2321 // -----------------------------------------------------------------------------
       
  2322 // Find contact link pointing to the same contact as given link
       
  2323 // -----------------------------------------------------------------------------
       
  2324 //
       
  2325 static TInt Find( const MVPbkContactLink* aLink, const RPointerArray<MVPbkContactLink>& aArray )
       
  2326     {
       
  2327     TInt idx = KErrNotFound;
       
  2328     for ( TInt i = 0 ; i < aArray.Count() ; ++i )
       
  2329         {
       
  2330         if ( aArray[i]->IsSame( *aLink ) )
       
  2331             {
       
  2332             idx = i;
       
  2333             i = aArray.Count();
       
  2334             }
       
  2335         }
       
  2336     return idx;
       
  2337     }
       
  2338 
       
  2339 // -----------------------------------------------------------------------------
       
  2340 // CleanupStack helpers for item owning RPointerArrays (etc)
       
  2341 // -----------------------------------------------------------------------------
       
  2342 //
       
  2343 template <class T>
       
  2344 class CleanupResetAndDestroy
       
  2345     {
       
  2346 public:
       
  2347     inline static void PushL( T& aRef )
       
  2348         { CleanupStack::PushL( TCleanupItem(&ResetAndDestroy,&aRef) ); }
       
  2349 private:
       
  2350     inline static void ResetAndDestroy( TAny *aPtr )
       
  2351         { static_cast<T*>(aPtr)->ResetAndDestroy(); }
       
  2352     };
       
  2353 
       
  2354 template <class T>
       
  2355 inline void CleanupResetAndDestroyPushL( T& aRef )
       
  2356     { CleanupResetAndDestroy<T>::PushL(aRef); }
       
  2357 
       
  2358 //  End of File
       
  2359