emailcontacts/remotecontactlookup/engine/src/cpbkxrclserviceuicontextimpl.cpp
changeset 0 8466d47a6819
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailcontacts/remotecontactlookup/engine/src/cpbkxrclserviceuicontextimpl.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1478 @@
+/*
+* Copyright (c) 2007 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:  Implementation of the class CPbkxRclServiceUiContextImpl.
+*
+*/
+
+
+#include "emailtrace.h"
+#include <pbkxrclengine.rsg>
+#include <cntfldst.h>
+#include <StringLoader.h>
+#include <CPbkContactEngine.h>
+#include <bautils.h>
+#include <textresolver.h>
+//<cmail>
+#include "fsccontactactionservicedefines.h"
+//</cmail>
+#include <data_caging_path_literals.hrh>
+#include <AknsUtils.h>
+#include <hlplch.h>
+
+#include "cpbkxrclserviceuicontextimpl.h"
+#include "pbkxremotecontactlookuppanic.h"
+#include "cpbkxremotecontactlookupprotocolsession.h"
+#include "cpbkxrclprotocolenvimpl.h"
+#include "cpbkxremotecontactlookupprotocoladapter.h"
+#include "cpbkxremotecontactlookupprotocolaccount.h"
+
+#include "cpbkxrclsearchresultdlg.h"
+#include "cpbkxrclresultinfodlg.h"
+#include "cpbkxrclqueryeditor.h"
+#include "cpbkxrclactionservicewrapper.h"
+
+#include "pbkxrclutils.h"
+#include "pbkxrclengineconstants.h"
+
+#include "engine.hrh"
+#include <aknnotewrappers.h>
+
+// own macro to handle errors in traps
+// <cmail> Do not use, produces Codescanner warnings
+//#define EXIT_IF_ERROR( xxx ) { TRAPD( err, xxx ); if ( err != KErrNone ) HandleError( err ); }
+// </cmail>
+
+/// Unnamed namespace for local definitions
+namespace {
+const TInt KTwoMinutesTimerInterval(120000000);
+} /// namespace
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::NewL
+// ---------------------------------------------------------------------------
+//
+CPbkxRclServiceUiContextImpl* CPbkxRclServiceUiContextImpl::NewL(
+    TPbkxRemoteContactLookupProtocolAccountId aId,
+    TMode aMode )
+    {
+    FUNC_LOG;
+    CPbkxRclServiceUiContextImpl* context = 
+        CPbkxRclServiceUiContextImpl::NewLC( aId, aMode );
+    CleanupStack::Pop( context );
+    return context;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::NewLC
+// ---------------------------------------------------------------------------
+//
+CPbkxRclServiceUiContextImpl* CPbkxRclServiceUiContextImpl::NewLC(
+    TPbkxRemoteContactLookupProtocolAccountId aId,
+    TMode aMode )
+    {
+    FUNC_LOG;
+    CPbkxRclServiceUiContextImpl* context = 
+        new ( ELeave ) CPbkxRclServiceUiContextImpl( aId, aMode );
+    CleanupStack::PushL( context );
+    context->ConstructL();
+    return context;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::CPbkxRclServiceUiContextImpl
+// ---------------------------------------------------------------------------
+//
+CPbkxRclServiceUiContextImpl::CPbkxRclServiceUiContextImpl(
+    TPbkxRemoteContactLookupProtocolAccountId aId,
+    TMode aMode ) : 
+    iAccountId( aId ), iMode( aMode ), iSelectedIndex( KErrNotFound )
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::~CPbkxRclServiceUiContextImpl
+// ---------------------------------------------------------------------------
+//
+CPbkxRclServiceUiContextImpl::~CPbkxRclServiceUiContextImpl()
+    {
+    FUNC_LOG;
+
+    if( iTimer )
+        {
+        iTimer->Cancel();
+        }
+    delete iTimer;
+
+    iQueryText.Close();
+    iQueryCriteria.Close();
+
+    CCoeEnv::Static()->DeleteResourceFile( iResourceFileOffset );
+
+    iContactCards.Reset();
+    iSearchResults.ResetAndDestroy();
+    iWaitObjects.ResetAndDestroy();
+    delete iContactEngine;
+
+    delete iActionServiceWrapper;
+
+    delete iAccount;
+    delete iSession;
+    delete iAdapter;
+    delete iEnvImpl;
+
+    delete iEventScheduler;
+    
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::ConstructL()
+    {
+    FUNC_LOG;
+
+    CCoeEnv* coeEnv = CCoeEnv::Static();
+
+    TFileName dllFileName;
+    Dll::FileName( dllFileName );
+      
+    TParse parse;
+    parse.Set( KResourceFile, &KDC_APP_RESOURCE_DIR, &dllFileName );
+    TFileName resourceFile = parse.FullName();
+    BaflUtils::NearestLanguageFile( coeEnv->FsSession(), resourceFile );
+
+    TRAPD( status,
+           iResourceFileOffset = coeEnv->AddResourceFileL( resourceFile ) );
+    
+    if( status != KErrNone )
+        {
+    	PbkxRclPanic( EPbkxRclPanicGeneral );		
+        }
+	else 
+        {
+        }
+
+    // create default contact engine to use to create CPbkContactItems
+    iContactEngine = CPbkContactEngine::NewL();
+
+    // create actions service wrapper used by UI views
+    iActionServiceWrapper = CPbkxRclActionServiceWrapper::NewL( *iContactEngine );
+
+    iActionServiceWrapper->SetContactSelectorMode( 
+        iMode == EModeContactSelector );
+
+    // Create objects needed for executing the search
+    iEnvImpl = CPbkxRclProtocolEnvImpl::NewL();
+    
+    iAdapter = CPbkxRemoteContactLookupProtocolAdapter::NewL( 
+        iAccountId.iProtocolUid, 
+        *iEnvImpl );
+
+    iAccount = iAdapter->NewProtocolAccountL( iAccountId );
+
+    if ( iAccount == NULL )
+        {
+        User::Leave( KErrNotFound );
+        }
+    
+    iSession = iAdapter->NewSessionL();
+    iSession->InitializeL( *this, iAccountId );
+
+    iEventScheduler = CPbkxRclEventScheduler::NewL( *this );
+    
+    iTimer = CPeriodic::NewL( CActive::EPriorityIdle );
+
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::GetSelectedContactL
+// ---------------------------------------------------------------------------
+//
+CContactItem* CPbkxRclServiceUiContextImpl::GetSelectedContactL()
+    {
+    FUNC_LOG;
+    __ASSERT_ALWAYS( iSelectedIndex >= 0 && iSelectedIndex < iContactCards.Count(),
+                     PbkxRclPanic( EPbkxRclPanicGeneral ) );
+    CContactCard* selected = iContactCards[iSelectedIndex];
+    CContactCard* copy = CContactCard::NewL( selected );
+    return copy;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::GetResultByIndex
+// ---------------------------------------------------------------------------
+//
+CPbkxRemoteContactLookupProtocolResult* 
+CPbkxRclServiceUiContextImpl::GetResultByIndex( TInt aIndex )
+    {
+    __ASSERT_ALWAYS( aIndex >= 0 && aIndex < iContactCards.Count(), 
+                     PbkxRclPanic( EPbkxRclPanicGeneral ) );
+  
+    CContactCard* card = iContactCards[aIndex];
+    CPbkxRemoteContactLookupProtocolResult* result = NULL;
+    for ( TInt i = 0; i < iSearchResults.Count(); i++ )
+        {
+        if ( card == &( iSearchResults[i]->ContactItem() ) )
+            {
+            result = iSearchResults[i];
+            break;
+            }
+        }
+
+    __ASSERT_ALWAYS( result != NULL, PbkxRclPanic( EPbkxRclPanicGeneral ) );
+
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::ExecuteL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::ExecuteL( const TDesC& aQueryText, TResult& aResult )
+    {
+    FUNC_LOG;
+
+    // set state as initial
+    ResetState();
+    SetState( EInitial );
+    iExitCode = KErrNone;
+
+    iSearchResults.ResetAndDestroy();
+
+    iQueryCriteria.Close();
+    iQueryCriteria.CreateL( KRclQueryTextMaxLength );
+    iQueryCriteria = aQueryText.Left( KRclQueryTextMaxLength );
+
+    iResult = &aResult;
+
+    TOperation op = ( iMode != EModeExistingCriteria ) ? 
+        EOpenSearchQueryDefault : EExecuteSearchWithNoQuery;
+    
+    AddOperation( op );
+        
+    StartActiveWaitL( EMainWait );
+
+    
+    HandleContextExitL();
+
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::LooseSearchCompleted
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::LooseSearchCompleted(
+    TInt aStatus,
+    RPointerArray<CPbkxRemoteContactLookupProtocolResult>& aResults )
+    {
+    FUNC_LOG;
+
+    // <cmail>
+    TRAPD( err, DoLooseSearchCompletedL( aStatus, aResults ) );
+    if ( err != KErrNone )
+        {
+        HandleError( err );
+        }
+    // </cmail>
+    
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::ContactFieldsRetrievalCompleted
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::ContactFieldsRetrievalCompleted( TInt aStatus )
+    {
+    FUNC_LOG;
+
+    // <cmail>
+    TRAPD( err, DoContactFieldsRetrievalCompletedL( aStatus ) );
+    if ( err != KErrNone )
+        {
+        HandleError( err );
+        }
+    // </cmail>
+
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::RetrieveDetailsL
+// ---------------------------------------------------------------------------
+//
+CContactCard* CPbkxRclServiceUiContextImpl::RetrieveDetailsL( 
+    TInt aContactIndex,
+    const TDesC& aWaitNoteText )
+    {
+    FUNC_LOG;
+
+    CPbkxRemoteContactLookupProtocolResult* result = GetResultByIndex( aContactIndex );
+
+    CContactCard* card = static_cast<CContactCard*>( &result->ContactItem() );
+
+    if ( !result->IsComplete() )
+        {
+        
+        RPointerArray<CPbkxRemoteContactLookupProtocolResult> array;
+        CleanupClosePushL( array );
+        array.AppendL( result );
+
+        iSession->RetrieveContactFieldsL( array );
+
+        // Start time for time out event
+        iTimer->Start(
+        		KTwoMinutesTimerInterval, KTwoMinutesTimerInterval, 
+            TCallBack(TimerCallBack, this));
+        
+        DisplayWaitDialogL( R_RCL_SEARCH_WAIT_DIALOG_CANCEL, aWaitNoteText );
+
+        // Start active wait. When contact retrieval is completed, 
+        // ContactFieldsRetrievalCompleted is called. If user cancels
+        // retrieval, DialogDismissedL is called. TimeOut is called when time is out.
+        StartActiveWaitL( EContactRetrievalWait );
+        
+        CleanupStack::PopAndDestroy( &array );
+        
+
+        // if contact retrieval was canceledor retrieval failed, 
+        // result is not yet complete
+        if ( !result->IsComplete() )
+            {
+            card = NULL;
+            }
+        
+        }
+
+    return card;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::ContactCount
+// ---------------------------------------------------------------------------
+//
+TInt CPbkxRclServiceUiContextImpl::ContactCount() const
+    {
+    FUNC_LOG;
+    return iContactCards.Count();
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::SetSelectedContact
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::SetSelectedContactL( TInt aIndex )
+    {
+    FUNC_LOG;
+    iSearchResultDialog->SetCurrentItemIndexL( aIndex );
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::EventTriggered
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::EventTriggered()
+    {
+    FUNC_LOG;
+
+    // <cmail>
+    TRAPD( err, DoHandleOperationL() );
+    if ( err != KErrNone )
+        {
+        HandleError( err );
+        }
+    // </cmail>
+
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::ProcessCommandL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::ProcessCommandL( TInt aCommandId )
+    {
+    FUNC_LOG;
+   
+    // some commands are handled the same way no matter which dialog is on top
+    TBool handled = ETrue;
+
+    switch ( aCommandId )
+        {
+        case ERclCmdVoiceCall:
+            iActionServiceWrapper->ExecuteActionL( 
+                KFscAtComCallGSM );
+            break;
+        case ERclCmdVideoCall:
+            iActionServiceWrapper->ExecuteActionL( 
+                KFscAtComCallVideo );
+            break;
+        case ERclCmdVoip:
+            iActionServiceWrapper->ExecuteActionL(
+                KFscAtComCallVoip );
+            break;
+        case ERclCmdSendMsg:
+            iActionServiceWrapper->ExecuteActionL( 
+                KFscAtComSendMsg );
+            break;
+          
+        case ERclCmdSendEmail:
+            iActionServiceWrapper->ExecuteActionL( 
+                KFscAtComSendEmail );
+            break;
+            
+        case ERclCmdSendMeetingReq:
+            iActionServiceWrapper->ExecuteActionL( 
+                KFscAtComSendCalReq );
+            break;
+        case ERclCmdSendAudioMsg:
+            iActionServiceWrapper->ExecuteActionL( 
+                KFscAtComSendAudio );
+            break;
+        case ERclCmdToContact:
+            iActionServiceWrapper->ExecuteActionL(
+                KFscAtComCallPoc );
+            break;
+        case ERclCmdHelp:
+            {
+            CCoeAppUi* appUi = CCoeEnv::Static()->AppUi();
+            CArrayFix<TCoeHelpContext>* contexts = appUi->AppHelpContextL();
+            HlpLauncher::LaunchHelpApplicationL( 
+                CCoeEnv::Static()->WsSession(), 
+                contexts );
+            }
+            break;
+        default:
+            handled = EFalse;
+            break;
+        }
+    
+    if ( !handled )
+        {
+        if ( IsStateSet( EResultDlgOnTop ) )
+            {
+            switch ( aCommandId )
+                {
+                case ERclCmdAddAsRecipient:
+                    // close the dialog, selected contact is stored in iSelectedContact
+                    AddOperation( ECloseSearchResultDlg );
+                    SetState( EReturnToCaller );
+                    SetState( EResultSelected );
+                    break;
+                case ERclCmdViewDetails:
+                    AddOperation( EOpenResultInfoDlg );
+                    break;
+                case ERclCmdNewSearch:
+                    // open empty search query
+                    AddOperation( EOpenSearchQueryEmpty );
+                    break;
+                case ERclCmdSendBusinessCard:
+                    {
+                    // first fetch details if they are not already
+                    // fetched
+                    HBufC* waitNoteText = StringLoader::LoadLC(
+                        R_QTN_RCL_RETRIEVAL_WAIT_NOTE );
+                    if ( RetrieveDetailsL(
+                             iSearchResultDialog->CurrentItemIndex(),
+                             *waitNoteText ) != NULL )
+                        {
+                        iSearchResultDialog->SendBusinessCardL();
+                        }
+                    CleanupStack::PopAndDestroy( waitNoteText );
+                    }
+                    break;
+                case ERclCmdSaveToContacts:
+                    {
+                    // first retrieve all the details
+                    HBufC* waitNoteText = StringLoader::LoadLC(
+                        R_QTN_RCL_SAVING_WAIT_NOTE );
+                    if ( RetrieveDetailsL( 
+                             iSearchResultDialog->CurrentItemIndex(),
+                             *waitNoteText ) != NULL )
+                        {
+                        
+                        iActionServiceWrapper->ExecuteActionL( 
+                            KFscAtManSaveAs );
+                        
+                        // in contact selector mode, return to the calling 
+                        // application
+                        if ( iMode == EModeContactSelector )
+                            {
+                            AddOperation( ECloseSearchResultDlg );
+                            SetState( EReturnToCaller );
+                            SetState( EResultSelected );
+                            }
+                        }
+                    CleanupStack::PopAndDestroy( waitNoteText );
+                    }
+                    break;
+                case EAknCmdExit:
+                    iResult->iExitReason = TResult::EExitApplication;
+                    AddOperation( ECloseSearchResultDlg );
+                    SetState( EReturnToCaller );
+                    break;
+                default:
+                    break;
+                }
+            }
+        else if ( IsStateSet( EInfoDlgOnTop ) )
+            {
+            switch ( aCommandId )
+                {
+                case ERclCmdAddAsRecipient:
+                    // close both dialogs, selected contact is in iSelectedContact
+                    AddOperation( ECloseResultInfoDlg );
+                    AddOperation( ECloseSearchResultDlg );
+                    SetState( EResultSelected );
+                    SetState( EReturnToCaller );
+                    break;
+                case ERclCmdSendCallbackReq:
+                    iResultInfoDialog->SendCallbackRequestL();
+                    break;
+                case ERclCmdCreateNew:
+                    iActionServiceWrapper->ExecuteActionL(
+                        KFscAtManSaveAs );
+                    // in contact selector mode, return to the calling
+                    // application
+                    if ( iMode == EModeContactSelector )
+                        {
+                        AddOperation( ECloseResultInfoDlg );
+                        AddOperation( ECloseSearchResultDlg );
+                        SetState( EReturnToCaller );
+                        SetState( EResultSelected );
+                        }
+                    break;
+                case ERclCmdUpdateExisting:
+                    {
+                    HBufC* resultText = 
+                        iResultInfoDialog->UpdateExistingContactL();
+                    if ( resultText != NULL )
+                        {
+                        CleanupStack::PushL( resultText );
+                        DisplayNoteDialogL(
+                            R_RCL_CONFIRMATION_NOTE,
+                            *resultText,
+                            ETrue );
+                        CleanupStack::PopAndDestroy( resultText );
+                        }
+                    }
+                    break;
+                case ERclCmdSendBusinessCard:
+                    iResultInfoDialog->SendBusinessCardL();
+                    break;
+                case EAknCmdExit:
+                    // again close both dialogs
+                    AddOperation( ECloseResultInfoDlg );
+                    AddOperation( ECloseSearchResultDlg );
+                    SetState( EReturnToCaller );
+                    iResult->iExitReason = TResult::EExitApplication;
+                    break;
+                default:
+                    break;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DialogDismissedL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::DialogDismissedL( TInt aButtonId )
+    {
+    FUNC_LOG;
+
+    if ( aButtonId == EAknSoftkeyCancel )
+        {
+        
+        // Action was canceled. Don't need to inform about errors
+        iExitCode = KErrNone;
+    	// cancel search or detail retrieval
+    	if (iSession)
+    		{
+    		iSession->Cancel();
+    		}
+    	
+    	// cancel time out timer
+        if (iTimer)
+    		{
+    		iTimer->Cancel();
+    		}
+        
+        // do actions based on state
+        if ( IsStateSet( EInitial ) )
+            {
+            if ( iMode != EModeExistingCriteria )
+                {
+                // show new search query dialog
+                AddOperation( EOpenSearchQueryDefault );
+                }
+            else
+                {
+                // with existing criteria, exit
+                AddOperation( EExit );
+                }
+            }
+        else if ( IsStateSet( EResultDlgOnTop ) )
+            {
+            if ( iWaitObjects.Count() == EContactRetrievalWait + 1 )
+                {
+                // contact retrieval was in progress
+                StopActiveWait( EContactRetrievalWait );
+                } // else new search was in progress, no actions needed
+            }
+        else if ( IsStateSet( EInfoDlgOnTop ) )
+            {
+            // details retrieval was in progress, stop active wait 
+            StopActiveWait( EContactRetrievalWait );
+            }
+        
+        }
+    else
+        {
+        // wait dialog closed by itself. exit now if exiting
+        if ( IsStateSet( EReturnToCaller ) &&
+                ( IsStateSet( EResultSelected ) || IsStateSet( EInitial ) ) )
+            {
+            AddOperation( EExit );
+            }
+        
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::ExecuteSearchL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::ExecuteSearchL( 
+    TBool aShowQueryDialog,
+    const TDesC& aQueryText )
+    {
+    FUNC_LOG;
+
+
+    iQueryText.Close();
+    iQueryText.CreateMaxL( KRclQueryTextMaxLength );
+    iQueryText = aQueryText;
+
+    TBool result = EFalse;
+    if ( aShowQueryDialog )
+        {
+        CPbkxRclQueryEditor* queryEditor = CPbkxRclQueryEditor::NewL( 
+            iAccount->Name(), 
+            iQueryText );
+        result = queryEditor->ExecuteDialogLD();
+        
+        // save initial query text given by user
+        if ( !IsStateSet( EResultDlgOnTop ) )
+            {
+            iQueryCriteria = iQueryText;
+            }
+        }
+    else
+        {
+        result = ETrue;
+        }
+
+    if ( result )
+        {
+        
+        // Start time for time out event
+        iTimer->Start(
+            KTwoMinutesTimerInterval, KTwoMinutesTimerInterval, 
+            TCallBack(TimerCallBack, this));
+        
+        // execute search based on query text
+        // use KMaxMatches + 1 to be able to catch "too many results error"
+        iSession->LooseSearchL( iQueryText, KMaxMatches + 1 );
+        HBufC* text = StringLoader::LoadLC( R_QTN_RCL_SEARCH_WAIT_NOTE, iQueryText );
+        DisplayWaitDialogL( R_RCL_SEARCH_WAIT_DIALOG_CANCEL, *text );
+        CleanupStack::PopAndDestroy( text );
+        }
+    else
+        {
+        if ( !IsStateSet( EResultDlgOnTop ) )
+            {
+            AddOperation( EExit );
+            } // otherwise just return to search result dlg
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DisplayWaitDialogL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::DisplayWaitDialogL(
+    TInt aDialogResourceId,
+    const TDesC& aText )
+    {
+    FUNC_LOG;
+
+    iWaitDialog = new ( ELeave ) CAknWaitDialog( NULL, ETrue );
+    iWaitDialog->SetTextL( aText );
+    iWaitDialog->SetCallback( this );
+    iWaitDialog->ExecuteLD( aDialogResourceId );
+
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DisplayNoteDialogL
+// ---------------------------------------------------------------------------
+//
+TBool CPbkxRclServiceUiContextImpl::DisplayNoteDialogL(
+    TInt aDialogResourceId, 
+    const TDesC& aText,
+    TBool aTimeout )
+    {
+    FUNC_LOG;
+    CAknNoteDialog* dialog = NULL;
+    
+    if ( aTimeout )
+        {
+        dialog = new ( ELeave ) CAknNoteDialog( 
+            CAknNoteDialog::ENoTone, 
+            CAknNoteDialog::ELongTimeout );
+        }
+    else
+        {
+        dialog = new ( ELeave ) CAknNoteDialog();
+        }
+
+    dialog->PrepareLC( aDialogResourceId );
+    dialog->SetTextL( aText );
+        
+    TBool ret = ( TBool )dialog->RunLD();
+    
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DisplayQueryDialogL
+// ---------------------------------------------------------------------------
+//
+//Fix for: EASV-7KFGG3
+TBool CPbkxRclServiceUiContextImpl::DisplayQueryDialogL(
+    TInt aDialogResourceId, 
+    const TDesC& aText )
+    {
+    FUNC_LOG;
+    CAknQueryDialog* dialog = NULL;
+    
+    dialog = new ( ELeave ) CAknQueryDialog();
+    dialog->PrepareLC( aDialogResourceId );
+    dialog->SetPromptL( aText );
+        
+    TBool ret = ( TBool )dialog->RunLD();
+    
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::CloseWaitDialogL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::CloseWaitDialogL()
+    {
+    FUNC_LOG;
+    iWaitDialog->ProcessFinishedL();
+    iWaitDialog = NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DisplaySearchResultDialogL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::DisplaySearchResultDialogL()
+    {
+    FUNC_LOG;
+
+    if ( iSearchResultDialog == NULL )
+        {
+        // no search result dialog on screen, show new one
+
+        // result array holds list box items and it is filled inside search
+        // result dialog
+        CDesCArrayFlat* resultArray = 
+            new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+        CleanupStack::PushL( resultArray );
+        
+        TBool contactSelectorEnabled = iMode == EModeContactSelector;
+        
+        iSearchResultDialog = CPbkxRclSearchResultDlg::NewL(
+            iSelectedIndex,
+            resultArray,
+            this,
+            iContactCards,
+            *iContactEngine,
+            *iActionServiceWrapper,
+            contactSelectorEnabled );
+        
+        UnsetState( EInitial );
+        SetState( EResultDlgOnTop );
+    
+        // set action service mode
+        iActionServiceWrapper->SetActionMenuMode( ETrue );
+    
+        iSearchResultDialog->ExecuteLD();
+        
+        iActionServiceWrapper->SetActionMenuMode( EFalse );
+
+
+        iSearchResultDialog = NULL;
+        
+        CleanupStack::PopAndDestroy( resultArray );
+
+        HandleSearchResultDialogExitL();
+
+        UnsetState( EResultDlgOnTop );
+        SetState( EInitial );
+        }
+    else
+        { // iSearchResultDialog != NULL
+        
+        
+        iSearchResultDialog->UpdateDialogL();
+        }
+    }
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DisplayResultInfoDialogL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::DisplayResultInfoDialogL()
+    {
+    FUNC_LOG;
+    
+    // items array holds the list box items in result info dialog and it is filled
+    // result info dialog
+    CDesCArrayFlat* items = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+    CleanupStack::PushL( items );
+    
+    TInt index = 0;
+    
+    TBool contactSelectorEnabled = iMode == EModeContactSelector;
+
+    TInt itemIndex = iSearchResultDialog->CurrentItemIndex();
+
+    // creation fails if item details cannot be retrieved or user cancels
+    // retrieval
+    iResultInfoDialog = CPbkxRclResultInfoDlg::NewL(
+        index,
+        items,
+        this,
+        this,
+        *iContactEngine,
+        *iActionServiceWrapper,
+        contactSelectorEnabled,
+        itemIndex );
+    
+    UnsetState( EResultDlgOnTop );
+    SetState( EInfoDlgOnTop );
+    
+     // set action service mode
+    iActionServiceWrapper->SetActionMenuMode( EFalse );
+    
+    //Fix for: PKAO-7NNCJ2
+    if ( iSearchResultDialog )
+        {
+        iSearchResultDialog->InfoDlgVisible( ETrue );
+        }
+    
+    iResultInfoDialog->ExecuteLD();
+    
+    // update action service since now search result dialog is on top
+    iActionServiceWrapper->SetActionMenuMode( ETrue );
+
+    if ( !IsStateSet( EReturnToCaller ) && iResult->iExitReason != TResult::EExitApplication )
+    	{
+    	iSearchResultDialog->SetCurrentContactToActionServiceL();
+    	}
+    
+    //Fix for: PKAO-7NNCJ2
+    if ( iSearchResultDialog )
+        {
+        iSearchResultDialog->InfoDlgVisible( EFalse );
+        }
+    
+    iResultInfoDialog = NULL;
+    
+    UnsetState( EInfoDlgOnTop );
+    SetState( EResultDlgOnTop );
+        
+    CleanupStack::PopAndDestroy( items );
+    
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::CreateContactCardArray
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::CreateContactCardArray()
+    {
+    FUNC_LOG;
+
+    // remove possible old contact cards
+    iContactCards.Reset();
+    
+
+    for ( TInt i = 0; i < iSearchResults.Count(); i++ )
+        {
+        CContactItem& item = iSearchResults[i]->ContactItem();
+        CContactCard* card = dynamic_cast<CContactCard*>( &item );
+        if ( card != NULL )
+            {
+            iContactCards.Append( card );
+            }
+        }
+
+
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DoLooseSearchCompletedL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::DoLooseSearchCompletedL( 
+    TInt aStatus,
+    RPointerArray<CPbkxRemoteContactLookupProtocolResult>& aResults )
+    {
+    FUNC_LOG;
+	
+    // cancel time out timer
+    if (iTimer)
+		{
+		iTimer->Cancel();
+		}
+    
+    CloseWaitDialogL();
+
+    if ( aStatus == KErrNone )
+        {
+        if ( aResults.Count() > KMaxMatches )
+            {
+            
+            HBufC* text = StringLoader::LoadLC( 
+                R_QTN_RCL_TOO_MANY_RESULTS_NOTE, 
+                KMaxMatches );
+
+            TBool ret = DisplayQueryDialogL(
+                R_RCL_CONFIRMATION_NOTE_OK_REFINE,
+                *text );
+            
+            CleanupStack::PopAndDestroy( text );
+            
+            if ( !ret )
+                {
+                // user wants new search
+                AddOperation( EOpenSearchQueryDefault );
+
+                // reset the old results
+                aResults.ResetAndDestroy();
+                return;
+                }
+            }
+        
+        // delete old results
+        iSearchResults.ResetAndDestroy();
+        TInt count = aResults.Count() <= KMaxMatches ? aResults.Count() : KMaxMatches;
+        for ( TInt i = 0; i < count; i++ )
+            {
+            iSearchResults.AppendL( aResults[i] );
+            }
+
+        // delete the extra results
+        for ( TInt j = aResults.Count() - 1; j >= KMaxMatches; j-- )
+            {
+            delete aResults[j];
+            aResults.Remove( j );
+            }
+        
+        CreateContactCardArray();
+        TLinearOrder<CContactCard> sort( CPbkxRclServiceUiContextImpl::Sort );
+        iContactCards.Sort( sort );
+        
+        AddOperation( EOpenSearchResultDlg );
+        }
+    else
+        {
+
+        // reset the array just in case
+        aResults.ResetAndDestroy();
+
+        // remote contact lookup failed, exit
+        HandleError( aStatus );
+        
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DoContactFieldsRetrievalCompletedL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::DoContactFieldsRetrievalCompletedL( TInt aStatus )
+    {
+    FUNC_LOG;
+
+	// cancel time out timer
+    if (iTimer)
+		{
+		iTimer->Cancel();
+		}
+    
+    StopActiveWait( EContactRetrievalWait );
+
+    CloseWaitDialogL();
+
+    if ( aStatus != KErrNone )
+        {
+        // error occurred, so contact is not complete. this is checked
+        // in RetrieveContactDetailsL method and it returns NULL
+        // to the caller
+
+        // exit application
+        HandleError( aStatus );
+        }
+    
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::DoHandleOperationL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::DoHandleOperationL()
+    {
+    FUNC_LOG;
+
+    if ( iOperations.Count() > 0 )
+        {
+        TOperation operation = iOperations.Pop();
+        
+        
+        switch ( operation )
+            {
+            case EOpenSearchResultDlg:
+                DisplaySearchResultDialogL();
+                break;
+            case EOpenResultInfoDlg:
+                DisplayResultInfoDialogL();
+                break;
+            case ECloseSearchResultDlg:
+                if ( iSearchResultDialog != NULL )
+                    {
+                    iSearchResultDialog->Close();
+                    }
+                break;
+            case ECloseResultInfoDlg:
+                if ( iResultInfoDialog != NULL )
+                    {
+                    iResultInfoDialog->Close();
+                    }
+                break;
+            case EOpenSearchQueryDefault:
+                ExecuteSearchL( ETrue, iQueryCriteria );
+                break;
+            case EOpenSearchQueryEmpty:
+                ExecuteSearchL( ETrue, KNullDesC );
+                break;
+            case EExecuteSearchWithNoQuery:
+                ExecuteSearchL( EFalse, iQueryCriteria );
+                break;
+            case EExit:
+                StopActiveWait( EMainWait );
+                break;
+            default:
+                PbkxRclPanic( EPbkxRclPanicGeneral );
+                break;
+            }
+        
+        if ( iOperations.Count() > 0 )
+            {
+            iEventScheduler->TriggerEvent();
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::HandleSearchResultDialogExitL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::HandleSearchResultDialogExitL()
+    {
+    FUNC_LOG;
+
+    // this flag is set if wait dialog on the screen and we cannot exit before
+    // wait dialog is closed itself
+    TBool waitDlgOnScreen = EFalse;
+    
+    if ( IsStateSet( EResultSelected ) )
+        {
+        // if contact details are not retrieved, we must do that before exiting
+        CPbkxRemoteContactLookupProtocolResult* result = GetResultByIndex( iSelectedIndex );
+        if ( !result->IsComplete() )
+            {
+            HBufC* text = StringLoader::LoadLC( R_QTN_RCL_RETRIEVAL_WAIT_NOTE );
+            RetrieveDetailsL( iSelectedIndex, *text );
+            CleanupStack::PopAndDestroy( text );
+            
+            // if wait dialog is NULL, it is closed by CloseWaitDialogL method
+            // and not by user. so it is still on the screen
+            waitDlgOnScreen = iWaitDialog == NULL;
+            
+            // make sure we succeeded in detail retrieving. if not, return nothing.
+            if ( result->IsComplete() )
+                {
+                iResult->iSelectedContactItem = GetSelectedContactL();
+                }
+            }
+        else
+            {
+            iResult->iSelectedContactItem = GetSelectedContactL();
+            }
+        }
+    
+    if ( !waitDlgOnScreen )
+        {
+        // exit
+
+        AddOperation( EExit );
+        }
+
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::HandleContextExitL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::HandleContextExitL()
+    {
+    FUNC_LOG;
+
+    // set exit reason
+    if ( iResult->iExitReason == TResult::EExitUndefined )
+        {
+        if ( iExitCode != KErrNone )
+            {
+            iResult->iExitReason = TResult::EExitError;
+            }
+        else if ( iResult->iSelectedContactItem != NULL )
+            {
+            iResult->iExitReason = TResult::EExitContactSelected;
+            }
+        else
+            {
+            iResult->iExitReason = TResult::EExitUserClosed;
+            }
+        }
+
+    if ( iExitCode != KErrNone )
+        {
+        // show error note
+        CTextResolver* resolver = CTextResolver::NewLC( *( CCoeEnv::Static() ) );
+    
+        // on return, contains information about the loaded error text
+        TUint textFlags;
+        TInt textId;
+
+        const TDesC& errorText = resolver->ResolveErrorString( 
+            iExitCode,
+            textId,
+            textFlags,
+            CTextResolver::ECtxNoCtxNoSeparator );
+        
+        if ( textFlags & EErrorResBlankErrorFlag ||
+             textFlags & ETextResolverUnknownErrorFlag )
+            {
+            // show general error message, because there was no good error 
+            // message available
+            HBufC* text = StringLoader::LoadLC( R_QTN_RCL_ERROR_NOTE );
+            DisplayNoteDialogL( R_RCL_WARNING_NOTE, *text, ETrue );
+            CleanupStack::PopAndDestroy( text );
+            }
+        else
+            {
+            DisplayNoteDialogL( R_RCL_WARNING_NOTE, errorText, ETrue );
+            }
+        CleanupStack::PopAndDestroy( resolver );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::StartActiveWaitL
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::StartActiveWaitL( TWaitObjectIndex aIndex )
+    {
+    FUNC_LOG;
+
+    if ( aIndex != iWaitObjects.Count() )
+        {
+        // wait object index invalid, panic
+        PbkxRclPanic( EPbkxRclPanicGeneral );
+        }
+    
+    // starts new active wait and appends it in the list of wait objects
+    CActiveSchedulerWait* wait = new ( ELeave ) CActiveSchedulerWait();
+    CleanupStack::PushL( wait );
+    iWaitObjects.AppendL( wait );
+    CleanupStack::Pop( wait );
+    wait->Start();
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::StopActiveWait
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::StopActiveWait( TWaitObjectIndex aIndex )
+    {
+    FUNC_LOG;
+    if ( iWaitObjects.Count() != aIndex + 1 )
+        {
+        // invalid wait object count, panic
+        PbkxRclPanic( EPbkxRclPanicGeneral );
+        }
+    
+    // stops active wait of the most recently started wait
+    CActiveSchedulerWait* wait = iWaitObjects[aIndex];
+    iWaitObjects.Remove( aIndex );
+    wait->AsyncStop();
+    delete wait;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::SetState
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::SetState( TState aState )
+    {
+    FUNC_LOG;
+    iState |= aState;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::UnsetState
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::UnsetState( TState aState )
+    {
+    FUNC_LOG;
+    iState &= ~aState;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::IsStateSet
+// ---------------------------------------------------------------------------
+//
+TBool CPbkxRclServiceUiContextImpl::IsStateSet( TState aState )
+    {
+    FUNC_LOG;
+    return ( iState & aState ) != 0;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::ResetState
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::ResetState()
+    {
+    FUNC_LOG;
+    iState = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::AddOperation
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::AddOperation( TOperation aOperation )
+    {
+    FUNC_LOG;
+    iOperations.Add( aOperation );
+    iEventScheduler->TriggerEvent();
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::HandleError
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::HandleError( TInt aError )
+    {
+    FUNC_LOG;
+    iExitCode = aError;
+    SetState( EReturnToCaller );
+    if ( IsStateSet( EInfoDlgOnTop ) )
+        {
+        AddOperation( ECloseResultInfoDlg );
+        AddOperation( ECloseSearchResultDlg );
+        }
+    else if ( IsStateSet( EResultDlgOnTop ) )
+        {
+        AddOperation( ECloseSearchResultDlg );
+        }
+    
+	// If dialog is NULL and state is EInitial & EReturnToCaller
+	// EExit operation is added in DialogDismissedL callback
+	if ( !iWaitDialog && IsStateSet( EInitial ) && IsStateSet( EReturnToCaller ) )
+        { 
+        return;
+        }
+	else 
+	    {
+	    AddOperation( EExit );
+	    }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::Sort
+// ---------------------------------------------------------------------------
+//
+TInt CPbkxRclServiceUiContextImpl::Sort( 
+    const CContactCard& aFirst, 
+    const CContactCard& aSecond )
+    {
+    FUNC_LOG;
+    
+    TPtrC lastName1 = PbkxRclUtils::FieldText( &aFirst, KUidContactFieldFamilyName );
+    TPtrC lastName2 = PbkxRclUtils::FieldText( &aSecond, KUidContactFieldFamilyName );
+
+    TInt ret = 0;
+    if ( lastName1 < lastName2 )
+        {
+        ret = -1;
+        }
+    else if ( lastName1 > lastName2 )
+        {
+        ret = 1;
+        }
+    return ret;
+    }
+
+// ----------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::TimerCallBack
+// ----------------------------------------------------------------------------
+//
+TInt CPbkxRclServiceUiContextImpl::TimerCallBack(TAny* aAny)
+	{
+    FUNC_LOG;
+	CPbkxRclServiceUiContextImpl* self = static_cast<CPbkxRclServiceUiContextImpl*>( aAny );
+	self->TimeOut();
+	return KErrNone;
+	}
+
+// ----------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::TimeOut
+// ----------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::TimeOut()
+	{
+    FUNC_LOG;
+	iTimer->Cancel();
+	
+	if (iSession)
+		{
+		iSession->Cancel();
+		}
+	
+	if (IsStateSet( EInfoDlgOnTop ) || IsStateSet( EResultDlgOnTop ))
+		{
+		StopActiveWait( EContactRetrievalWait );
+		}
+	
+	TRAP_IGNORE( CloseWaitDialogL() );	
+	HandleError( KErrTimedOut );
+	}
+
+//////////////////////////////////////////////////////////////////////////////
+// TOperationQueue class definition
+//////////////////////////////////////////////////////////////////////////////
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::TOperationQueue::TOperationQueue
+// ---------------------------------------------------------------------------
+//
+CPbkxRclServiceUiContextImpl::TOperationQueue::TOperationQueue() : 
+    iCurrent( 0 ), iCount( 0 )
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::TOperationQueue::Add
+// ---------------------------------------------------------------------------
+//
+void CPbkxRclServiceUiContextImpl::TOperationQueue::Add( TOperation aOperation )
+    {
+    FUNC_LOG;
+    if ( iCount == KMaxOperations )
+        {
+        PbkxRclPanic( EPbkxRclPanicGeneral );
+        }
+    
+    TBool exists = EFalse;
+    for ( TInt i = iCurrent, count = 0; 
+          count < iCount; 
+          ( ++i ) % KMaxOperations, count++ )
+        {
+        if ( iOperations[i] == aOperation )
+            {
+            exists = ETrue;
+            break;
+            }
+        }
+
+    if ( !exists )
+        {
+        TInt newIndex = ( iCurrent + iCount ) % KMaxOperations;
+        iOperations[newIndex] = aOperation;
+        iCount++;
+        }
+    
+    }
+
+// ---------------------------------------------------------------------------
+// CPbkxRclServiceUiContextImpl::TOperationQueue::Pop
+// ---------------------------------------------------------------------------
+//
+CPbkxRclServiceUiContextImpl::TOperation 
+CPbkxRclServiceUiContextImpl::TOperationQueue::Pop()
+    {
+    if ( iCount > 0 )
+        {
+        TOperation op = iOperations[iCurrent];
+        iOperations[iCurrent] = ENoOperation;
+        iCount--;
+        
+        if ( iCount > 0 )
+            {
+            iCurrent = ( ++iCurrent ) % KMaxOperations;
+            }
+        else
+            {
+            iCurrent = 0;
+            }
+        return op;
+        }
+    else
+        {
+        return ENoOperation;
+        }
+    }
+
+TInt CPbkxRclServiceUiContextImpl::TOperationQueue::Count() const
+    {
+    FUNC_LOG;
+    return iCount;
+    }
+
+