voiceui/voiceuivoicerecognition/src/vuiccontactresultsstate.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:29:17 +0100
branchRCL_3
changeset 19 e36f3802f733
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  
*
*/


// INCLUDE FILES
#include <CPbkViewState.h>
#include <PbkUID.h>
#include <StringLoader.h>

#include <vasmbasepbkhandler.h>

#include <vuivoicerecognition.rsg>

#include "vuivoicerecognition.hrh"

#include "vuicstate.h"
#include "vuiccontactresultsstate.h"
#include "vuicplaystate.h"
#include "vuicabortstate.h"
#include "vuicerrorstate.h"
#include "vuicexitstate.h"

#include "vuicdatastorage.h"

#include "vuicvoicerecogdialogimpl.h"
#include "vuicnbestlistdialog.h"
#include "vuicttsplayer.h"
#include "vuivoiceicondefs.h"

#include "rubydebug.h"

// Constants
_LIT( KTab, "\t" );
_LIT( KStringPosition, "%U" );
    
// -----------------------------------------------------------------------------
// CContactResultsState::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CContactResultsState* CContactResultsState::NewL( CDataStorage& aDataStorage, CUiModel& aUiModel )
    {
    CContactResultsState* self = new (ELeave) CContactResultsState( aDataStorage, aUiModel );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }       
    
// Destructor       
CContactResultsState::~CContactResultsState()
    {
    RUBY_DEBUG0( "CContactResultsState::~CContactResultsState START" );
    
    DataStorage().TtsPlayer()->Stop();
    
    delete iNBestListDialog;
    
    delete iTagList; // Only copies of pointers, do not reset and destroy
    
    DataStorage().SetAdditionalTagList( NULL ); // Reset for next time
    
    delete iNssVasDbManager;
    iNssTagManager = NULL;
    
    RUBY_DEBUG0( "CContactResultsState::~CContactResultsState EXIT" );
    }
    
// ---------------------------------------------------------
// CContactResultsState::HandleEventL
// ---------------------------------------------------------
//       
void CContactResultsState::HandleEventL( TInt aEvent )
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::HandleEventL" );

    CState* nextState = NULL;

    switch( aEvent )
        {
        case KErrNone:
        
            if ( iInternalState == ENotStarted )
                {
                nextState = this;
                }
            else if ( iInternalState == EStarted )
                {
                iInternalState = EInitialized;
                nextState = this;
                }
            else if ( iInternalState == EInitialized )
                {
                iInternalState = ECompleted;
                nextState = this;
                }
            break;
            
        case EVoiceTagSoftKeySelect:
        
            nextState = CPlayState::NewL( DataStorage(), UiModel() );
            break;
            
        case EAknSoftkeyQuit:
        case EAknSoftkeyNo:
        case EVoiceTagSoftKeyQuit:
        case EEndCallKeypress:
        case ELongKeypress:
        
            nextState = CAbortState::NewL( DataStorage(), UiModel() );
            break;
        
        case EShortKeypress:
        case EUpKeypress:
        case EDownKeypress:
        case ESelectKeypress:
        case EDirectSelectKeypress:
        case EDragKeypress:
        case EScrollKeypress:
        
            iKeypress = aEvent;
            nextState = this;
            break;
            
        default:
            
            nextState = CErrorState::NewL( DataStorage(), UiModel(), aEvent );
            break;
        }

    DataStorage().VoiceRecognitionImpl()->ChangeState( nextState );
    }

// ---------------------------------------------------------
// CContactResultsState::ExecuteL
// ---------------------------------------------------------
//       
void CContactResultsState::ExecuteL()
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::ExecuteL" );

    if ( HandleKeypressL() )
        {
        iKeypress = ENoKeypress;
        }
    else if ( iInternalState == EInitialized )
        {
        // If automatic confirmation or device lock is on then start the timer
        if ( DataStorage().VerificationMode() == EAutomatic ||
             DataStorage().DeviceLockMode() )
            {
            TInt timeoutValue = DataStorage().PlayDuration().Int64();
            if ( timeoutValue < KTimeoutMicroseconds )
                {
                timeoutValue = KTimeoutMicroseconds;
                }
        
            StartTimerL( *this, timeoutValue, timeoutValue );
            }
        }
    else if ( iInternalState == ECompleted )
        {
        DataStorage().TtsPlayer()->Stop();
        }
    else
        {
        if ( !DataStorage().AdditionalTagList() )
            {
            if ( iNssTagManager->GetTagList( DataStorage().VoiceRecognitionImpl(),
                                             DataStorage().Tag()->Context(),
                                             DataStorage().Tag()->RRD()->IntArray()->At( KVasContactIdRrdLocation ),
                                             KVasContactIdRrdLocation ) != KErrNone )
                {
                HandleEventL( KErrGeneral );
                }
            }
        else
            {
            iInternalState = EStarted;
            
            TInt returnValue = KErrNoResults;

            // Get the name for the n-best list title
            HBufC* name = DataStorage().Tag()->SpeechItem()->PartialTextL( KNameTrainingIndex );
            CleanupStack::PushL( name );
            
            CreateContactInfoArrayL();
            
            if ( iTagList->Count() != KErrNone )
                {
                iNBestListDialog = CNBestListDialog::NewL();
                iNBestListDialog->CreateNBestListPopupLC( CreateItemsArrayL(), *name );
    
                PlaySelectedNameL();
                BringToForeground();
    
                iNBestListDialog->RegisterForKeyCallback( DataStorage().VoiceRecognitionImpl() );            
                returnValue = iNBestListDialog->ShowNBestListPopupL(); // Pops things pushed in CreateNBestListPopupLC
                }
            CleanupStack::PopAndDestroy( name );
            
            if ( returnValue != KErrNone )
                {
                iInternalState = ECompleted;
                
                SelectTag();
                
                HandleEventL( returnValue );
                }
            }
        }
    }

// ---------------------------------------------------------
// CContactResultsState::CContactResultsState
// ---------------------------------------------------------
//              
CContactResultsState::CContactResultsState( CDataStorage& aDataStorage, CUiModel& aUiModel )
 : CState( aDataStorage, aUiModel ), iKeypress( ENoKeypress ),
   iInternalState( ENotStarted )
    {
    }

// ---------------------------------------------------------
// CContactResultsState::ConstructL
// ---------------------------------------------------------
//           
void CContactResultsState::ConstructL()
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::ConstructL" );
    
    CState::ConstructL();
    
    iNssVasDbManager = CNssVASDBMgr::NewL();
    iNssVasDbManager->InitializeL();
    iNssTagManager = iNssVasDbManager->GetTagMgr();
   
    DataStorage().SetVerificationMode();
    }

// ---------------------------------------------------------
// CContactResultsState::DoTimedEventL
// ---------------------------------------------------------
//
void CContactResultsState::DoTimedEventL()
   {   
   SelectTag();
   
   HandleEventL( EVoiceTagSoftKeySelect );
   }

// ---------------------------------------------------------
// CContactResultsState::HandleKeypressL
// ---------------------------------------------------------
//           
TBool CContactResultsState::HandleKeypressL()
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::HandleKeypressL" );
    
    TBool handled = ETrue;
    
    if ( iKeypress == EShortKeypress )
        {       
        if ( iNBestListDialog->HandleShortKeypressL( NULL ) )
            {
            iInternalState = EStarted;
            
            PlaySelectedNameL();
            }
        else
            {
            HandleEventL( KErrNoResults );
            }
        }
    else if ( iKeypress == EUpKeypress || iKeypress == EDownKeypress ||
              iKeypress == EDragKeypress )
        {
        iInternalState = EStarted;
        
        PlaySelectedNameL();
        }
    else if ( iKeypress == EScrollKeypress )
        {
        StopTimer();
        }
    else if ( iKeypress == ESelectKeypress || iKeypress == EDirectSelectKeypress )
        {        
        if ( !DataStorage().Tag() )
            {
            SelectTag();
    
            HandleEventL( EVoiceTagSoftKeySelect );
            }
        }
    else
        {
        handled = EFalse;
        }
    
    return handled;
    }
    
// ---------------------------------------------------------------------------
// CContactResultsState::PlaySelectedNameL
// ---------------------------------------------------------------------------
//
void CContactResultsState::PlaySelectedNameL()
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::PlaySelectedNameL" );

    // if TTS is used
    if ( ( DataStorage().SynthesizerMode() != KErrNone ||
         DataStorage().DeviceLockMode() ) &&
         iTagList->Count() > 0 )
        {
        TInt index = iNBestListDialog->SelectedIndex();        
        MNssTag* tag = iTagList->At( index );
            
        if ( tag->Context()->ContextName() == KVoiceDialContext &&
             tag->RRD()->IntArray()->At( KVasExtensionRrdLocation ) == EDial )
            {
            HBufC* ttsText = StringLoader::LoadLC( R_QAN_VC_TTS_DIALLING );
            
            TInt position = ttsText->FindC( KStringPosition );
            User::LeaveIfError( position );            
            
            CleanupStack::PopAndDestroy( ttsText );
            
            ttsText = StringLoader::LoadLC( R_QAN_VC_TTS_DIALLING,
                                            tag->SpeechItem()->Text() );
                                                   
            HBufC* text = tag->SpeechItem()->PartialTextL( KNameTrainingIndex );        
            CleanupStack::PushL( text ); 
            
            DataStorage().TtsPlayer()->PlayL( *ttsText, position,
                                              tag->SpeechItem()->Text().Length() , *text );
            
            CleanupStack::PopAndDestroy( text );
            CleanupStack::PopAndDestroy( ttsText );
            }
        else if ( tag->Context()->ContextName() == KVoiceDialContext )
            {           
            HBufC* text = tag->SpeechItem()->PartialTextL( KNameTrainingIndex );        
            CleanupStack::PushL( text ); 
        
            DataStorage().TtsPlayer()->PlayL( tag->SpeechItem()->Text(), 0,
                                              tag->SpeechItem()->Text().Length(), *text );

            CleanupStack::PopAndDestroy( text );
            }
        }
    else
        {
        DataStorage().SetPlayDuration( KTimeoutMicroseconds );
        HandleEventL( KErrNone );
        }
    }
    
// ---------------------------------------------------------------------------
// CContactResultsState::CreateContactInfoArrayL
// ---------------------------------------------------------------------------
//
void CContactResultsState::CreateContactInfoArrayL()
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::CreateContactInfoArrayL" );
    
    CArrayPtrFlat<MNssTag>* completeTagList = DataStorage().CompleteTagList();
    CArrayPtrFlat<MNssTag>* additionalTags = DataStorage().AdditionalTagList();
    
    iTagList = new ( ELeave ) CArrayPtrFlat<MNssTag>( KSindMaxResults );
    
    iTagList->AppendL( DataStorage().Tag() );
    
    // Add all commands from selected contact to taglist
    for ( TInt i = 0; i < completeTagList->Count(); ++i )
        {
        MNssTag* tag = completeTagList->At( i );
        
        if ( tag->Context()->ContextName() == KVoiceDialContext &&
             ( !DataStorage().DeviceLockMode() || tag->RRD()->IntArray()->At( KVasExtensionRrdLocation ) == EDial ) &&
             tag->RRD()->IntArray()->At( KVasContactIdRrdLocation ) ==
             DataStorage().Tag()->RRD()->IntArray()->At( KVasContactIdRrdLocation ) &&
             CompareContactNamesL( tag ) )
            {
            // Add tag to list
            iTagList->AppendL( tag );
            }
        }
    
    // Add all additional commands from selected contact to taglist if not added already    
    for ( TInt i = 0; i < additionalTags->Count(); ++i )
        {
        MNssTag* tag = additionalTags->At( i );
        
        if ( !CheckIfAlreadyAdded( tag ) && CompareContactNamesL( tag ) &&
             ( !DataStorage().DeviceLockMode() || tag->RRD()->IntArray()->At( KVasExtensionRrdLocation ) == EDial ) )
            {
            // Add tag to list
            iTagList->AppendL( tag );
            }
        }
        
    // Add selected tag back to tag list
    completeTagList->AppendL( DataStorage().Tag() );
    
    // Clear selected tag    
    DataStorage().SetTag( NULL, EFalse );
    }

// ---------------------------------------------------------
// CContactResultsState::CompareContactNamesL
// ---------------------------------------------------------
//     
TBool CContactResultsState::CompareContactNamesL( MNssTag* aTag )
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::CompareContactNamesL" );
    
    TBool returnValue = EFalse;
    
    HBufC* firstName = DataStorage().Tag()->SpeechItem()->PartialTextL( KNameTrainingIndex );
    CleanupStack::PushL( firstName );
    
    HBufC* secondName = aTag->SpeechItem()->PartialTextL( KNameTrainingIndex );
    CleanupStack::PushL( secondName );
    
    returnValue = ( *firstName == *secondName );
        
    CleanupStack::PopAndDestroy( secondName );
    CleanupStack::PopAndDestroy( firstName );
    
    return returnValue;
    }

// ---------------------------------------------------------
// CContactResultsState::CheckIfAlreadyAdded
// ---------------------------------------------------------
//    
TBool CContactResultsState::CheckIfAlreadyAdded( MNssTag* aTag )
    {
    RUBY_DEBUG0( "CContactResultsState::CheckIfAlreadyAdded START" );
    
    TBool returnValue = EFalse;

    for ( TInt i = 0; i < iTagList->Count(); ++i )
        {
        if ( aTag->SpeechItem()->RawText() ==
             iTagList->At( i )->SpeechItem()->RawText() ||
             aTag->SpeechItem()->RawText() ==
             DataStorage().Tag()->SpeechItem()->RawText() )
            {
            returnValue = ETrue;
            
            break;
            }
        }
    
    RUBY_DEBUG0( "CContactResultsState::CheckIfAlreadyAdded EXIT" );
    
    return returnValue;
    }
    
// ---------------------------------------------------------------------------
// CContactResultsState::CreateItemsArrayLC
// ---------------------------------------------------------------------------
//    
CDesC16ArrayFlat* CContactResultsState::CreateItemsArrayL()
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::CreateItemsArrayL" );
        
    TInt count = iTagList->Count();
           
    CDesC16ArrayFlat* items = new ( ELeave ) CDesC16ArrayFlat( KSindMaxResults );
    CleanupStack::PushL( items );

    TFullName buffer;
    
    for ( TInt i = 0; i < count; ++i )
        {
        MNssTag* tag = iTagList->At( i );        
        
        FillDialContextBufferL( tag, buffer );
            
        items->AppendL( buffer );
        }
        
    CleanupStack::Pop( items );
    
    return items;
    }

// ---------------------------------------------------------
// CContactResultsState::FillDialContextBufferL
// ---------------------------------------------------------
//
void CContactResultsState::FillDialContextBufferL( MNssTag* aTag, TDes& aBuffer )
    {
    RUBY_DEBUG_BLOCK( "CContactResultsState::FillDialContextBufferL" );
    
    TPtrC type = KNullDesC();
    
    DataStorage().PbkHandler()->FindContactFieldL( aTag );
                           
    TBufC<KMaxFieldLength> phoneNumber = DataStorage().PbkHandler()->TextL();
    type.Set( GetContactIconType( DataStorage().PbkHandler()->FieldTypeL() ) );

    aBuffer.Zero();
    aBuffer.Append( type );
    aBuffer.Append( KTab );
    
    HBufC* label = NULL;
        
    TRAPD( error, label = aTag->SpeechItem()->PartialTextL( KExtensionTrainingIndex ) );
    if ( error == KErrNone || error == KErrNotFound )
        {
        // If there is no extension then the phonebook label is shown
        if ( label )
            {
            CleanupStack::PushL( label );
    
            aBuffer.Append( *label );
    
            CleanupStack::PopAndDestroy( label );
            }
        else
            {
            aBuffer.Append( DataStorage().PbkHandler()->LabelL() );
            }
        }
    else
        {
        User::Leave( error );
        }
        
    aBuffer.Append( KTab );
    aBuffer.Append( phoneNumber );
    }
    
// ---------------------------------------------------------
// CContactResultsState::GetContactIconType
// ---------------------------------------------------------
//
TPtrC CContactResultsState::GetContactIconType( TFieldType aFieldType )
    {
    RUBY_DEBUG0( "CContactResultsState::GetContactIconType START" );
    
    TPtrC type;
    // select a phone type
    if ( aFieldType == KUidContactFieldVCardMapVOICE )
        {
        type.Set( KIconPhone );
        }
    else if ( aFieldType == KUidContactFieldVCardMapCELL )
        {
        type.Set( KIconMobile );
        }
    else if ( aFieldType == KUidContactFieldVCardMapFAX )
        {
        type.Set( KIconFax );
        }
    else if ( aFieldType == KUidContactFieldVCardMapEMAILINTERNET )
        {
        type.Set( KIconEmail );
        }
    else if ( aFieldType == KUidContactFieldVCardMapVIDEO )
        {
        type.Set( KIconVideo );
        }
    else if ( aFieldType == KUidContactFieldVCardMapVOIP )
        {
        type.Set( KIconVoip );
        }
    else
        {
        type.Set( KIconBlank );
        }

    RUBY_DEBUG0( "CContactResultsState::GetContactIconType EXIT" );
    
    return type;
    }
    
// ---------------------------------------------------------
// CContactResultsState::SelectTag
// ---------------------------------------------------------
//   
void CContactResultsState::SelectTag()
    {
    RUBY_DEBUG0( "CContactResultsState::SelectTag START" );
    
    if ( iTagList->Count() > 0 )
        {
        DataStorage().SetTag( iTagList->At( iNBestListDialog->SelectedIndex() ), ETrue );
            
        // Remove selected item from the complete taglist
        for ( TInt i = 0; i < DataStorage().CompleteTagList()->Count(); ++i )
            {
            if ( DataStorage().CompleteTagList()->At( i ) ==
                 DataStorage().Tag() )
                {
                DataStorage().CompleteTagList()->Delete( i );
                break;
                }
            }
            
        // Remove selected item from the additional taglist
        for ( TInt i = 0; i < DataStorage().AdditionalTagList()->Count(); ++i )
            {
            if ( DataStorage().AdditionalTagList()->At( i ) ==
                 DataStorage().Tag() )
                {
                // Disable adaptation since tag is not from recognition results
                DataStorage().SetAdaptationEnabled( EFalse );
                
                DataStorage().AdditionalTagList()->Delete( i );
                break;
                }
            }
        }
        
    RUBY_DEBUG0( "CContactResultsState::SelectTag EXIT" );
    }

// End of File