--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wvuing/wvuiave/AppSrc/CCAConversationsContainer.cpp Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,2056 @@
+/*
+* Copyright (c) 2006 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: Container class for conversations view
+*
+*/
+
+#include <AknSettingCache.h>
+
+#include "CAPresenceManager.h"
+#include "MCAPresence.h"
+#include "ccafetchwaiter.h"
+#include "ccasyncchecker.h"
+#include "ImpsCSPAllErrors.h"
+
+// INCLUDE FILES
+#include "CCAConversationsContainer.h"
+#include "MCAViewSwitcher.h"
+#include "CCAMessageEditor.h"
+#include "ChatDefinitions.h"
+#include "ChatDebugPrint.h"
+#include "CCAAppUi.h"
+#include "CCAContactEditor.h"
+#include "CCAStatusPaneHandler.h"
+#include "MCABlockingPC.h"
+#include "IMDialogUtils.h"
+#include "MCARecipientObserver.h"
+#include "CAExternalinterface.h"
+#include "IMNoteMapper.h"
+#include "CCABlockingUI.h"
+#include "chatngclient.hrh"
+#include "CCAApp.h"
+#include "CCAVariantFactory.h"
+#include "MCASkinVariant.h"
+#include "CCAUISessionManager.h"
+#include "CCAMessageExtensionsHandler.h"
+#include "CCAChatViewControl.h"
+#include "IMDialogUtils.h"
+
+#include "TCAChatListBoxLayout.h"
+#include "IMUtils.h"
+#include "CAUtils.h"
+#include "ccawaitnote.h"
+#include "chatdebugassert.h"
+#include "CCAPCUtils.h"
+
+#include "MCAMessageErrorInformer.h"
+#include "MCAMessageUtils.h"
+#include "MCAMessageCreator.h"
+#include "MCAMessageContainerInfo.h"
+#include "MCAMessageUtils.h"
+#include "MCAContentProcessor.h"
+#include "MCASettingsPC.h"
+#include "MCAConversationMessage.h"
+#include "MCALayoutInfo.h"
+
+
+#include "imnginternalcrkeys.h"
+#include "imprivatecrkeys.h"
+#include "imvariant.hrh"
+#include "CCAAppSettingsSAPExt.h"
+
+
+#include "MCAUiLoginCmdCB.h"
+#include "MCAConversationPC.h"
+#include "CCAEditIndicator.h"
+#include "MCAProcessManager.h"
+#include "CCAUiMessageUtils.h"
+#include "MCALoginPC.h"
+#include "MCALoginRefreshObserverPC.h"
+
+#include <finditemengine.h>
+#include <apgcli.h>
+#include <S32FILE.H>
+#include <npdapi.h>
+#include <chatNG.mbg>
+#include <chatNG.rsg>
+#include <aknnotedialog.h>
+#include <StringLoader.h>
+#include <csxhelp/imng.hlp.hrh>
+#include <impserrors.h>
+#include <txtrich.h>
+#include <gulicon.h>
+#include <AknLayout.cdl.h> //cdl
+#include <AppLayout.cdl.h> //cdl
+#include <AknsUtils.h>
+#include <AknLayoutScalable_Apps.cdl.h>
+#include <aknnotewrappers.h>
+#include <AknFepGlobalEnums.h> // for EAknFepSoftkeySpell
+#include <barsread.h>
+
+#include "CATouchUtils.h"
+
+// The Settings have been moved to Cenrep (also retained in the Resource file),
+// so the enums for keys and central repository header is added here
+#include "VariantKeys.h"
+#ifdef RD_MULTIPLE_DRIVE
+#include <centralrepository.h>
+#include <IMPSServiceSettingsUINGInternalCRKeys.h>
+#include <E32std.h>
+#include <EIKAPP.H>
+#include <eikappui.h>
+#include <eikenv.h>
+#include <eikbtgpc.h>
+#include <CAknMemorySelectionDialogMultiDrive.h>
+//CONSTANTS
+const TInt KErrNotSaved = -999;
+#endif
+
+// CONSTANTS
+// Maximum amount of lines in the editor
+const TInt KChatConvEditorMaxLines = 2;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::NewL
+// Symbian constructor can leave.
+// -----------------------------------------------------------------------------
+//
+CCAConversationsContainer* CCAConversationsContainer::NewL(
+ const TRect& aRect,
+ MCAViewSwitcher& aViewSwitcher,
+ MCAConversationPC* aCCAConversationManagerPC,
+ MCARecipientObserver& aRecipientObserver,
+ MObjectProvider* aParent,
+ CCAMessageExtensionsHandler& aMessageHandler,
+ MCATitleUpdater& aTitleUpdater,
+ MCAEditorContentStorage& aEditorContentStorage,
+ CEikButtonGroupContainer* aCba,
+ TBool aActivateFromTabSwitch,
+ TInt& aTabId )
+ {
+ CCAConversationsContainer* self = new ( ELeave ) CCAConversationsContainer(
+ aViewSwitcher, aCCAConversationManagerPC, aRecipientObserver,
+ aMessageHandler, aTitleUpdater, aEditorContentStorage, aCba, aTabId );
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aRect, aParent, aActivateFromTabSwitch );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::CCAConversationsContainer
+// Default constructor must not leave
+// -----------------------------------------------------------------------------
+//
+CCAConversationsContainer::CCAConversationsContainer(
+ MCAViewSwitcher& aViewSwitcher,
+ MCAConversationPC* aCCAConversationManagerPC,
+ MCARecipientObserver& aRecipientObserver,
+ CCAMessageExtensionsHandler& aMessageHandler,
+ MCATitleUpdater& aTitleUpdater,
+ MCAEditorContentStorage& aEditorContentStorage,
+ CEikButtonGroupContainer* aCba,
+ TInt& aTabId )
+
+ : iViewSwitcher( aViewSwitcher ),
+ iRecipientObserver( aRecipientObserver ),
+ iIsChangeToOnlineAskedOnce( EFalse ),
+ iMessageExtensionsHandler( aMessageHandler ),
+ iTitleUpdater( aTitleUpdater ),
+ iEditorContentStorage( aEditorContentStorage ),
+ iCba( aCba ),
+ iConversationPC( aCCAConversationManagerPC ),
+ iTabId( aTabId )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CCAConversationsContainer::ConstructL( const TRect& aRect,
+ MObjectProvider* aParent,
+ TBool aActivateFromTabSwitch )
+ {
+ // for getting mbm path from CCAAppUi
+ iAppUi = static_cast<CCAAppUi*>( CEikonEnv::Static()->AppUi() );
+ iAppUi->AddLayoutChangeObserver( this );
+
+ // This must be done first.
+ SetMopParent( aParent );
+
+ CreateWindowL();
+ CCAApp* app = static_cast<CCAApp*>(
+ CEikonEnv::Static()->EikAppUi()->Application() );
+ iSkinVar = app->VariantFactory()->SkinVariantL();
+
+ AknEditUtils::SAknEditorParameters editorParams;
+ editorParams.iCursorYesNo = ETrue;
+ editorParams.iAllowedToMoveInsertionPoint = ETrue;
+ editorParams.iCharacterCase = EAknEditorTextCase;
+ editorParams.iEditingSpace = IMUtils::MaxMsgLength();
+ editorParams.iEditingWindow = KChatConvEditorMaxLines;
+ editorParams.iJustification = EAknEditorAlignBidi;
+ editorParams.iOverflowYesNo = EFalse;
+
+ iEditor = new ( ELeave ) CCAMessageEditor( iMessageExtensionsHandler );
+ iEditor->SetMopParent( this );
+ AknEditUtils::ConstructEditingL( iEditor, editorParams );
+ iEditor->SetContainerWindowL( *this );
+ iEditor->SetAllowPictures( ETrue );
+
+ iEditor->SetEdwinSizeObserver( this );
+ iEditor->SetMessageEditorObserver( this );
+
+ LoadBitmapsL();
+
+ MCAMsgAddedToRichTxtCtrlObserver* observer = NULL;
+
+ if ( aActivateFromTabSwitch && !iAppUi->FocusFlag() )
+ {
+ observer = this;
+ }
+
+ iChatView = CCAChatViewControl::NewL( aRect, *this,
+ *iConversationPC,
+ *iAppUi->GetProcessManager().GetSettingsInterface(),
+ iMessageExtensionsHandler,
+ iFromMe,
+ iToMe,
+ iUnsupported,
+ iCorrupted,
+ ETrue,
+ observer );
+
+ iChatView->SetObserver( this );
+
+ iAppUi->LayoutInfo()->SetLayoutID( TChatListBoxLayout::EWithEditor );
+ iAppUi->LayoutInfo()->SetEditorVisibility( ETrue );
+
+ iEditor->SetupSkinContextL();
+ iEditor->SetCursorPosL( 0, EFalse );
+
+ if ( !aActivateFromTabSwitch )
+ {
+ iEditor->SetFocus( ETrue );
+ iAppUi->SetFocusFlag( ETrue );
+ iChatView->SetFocus( EFalse );
+ }
+ else
+ {
+ iEditor->SetFocus( EFalse );
+ iChatView->SetFocus( ETrue );
+ }
+
+ iEditor->SetObserver( this );
+
+ iBlockingUI = CCABlockingUI::NewL( iAppUi->GetProcessManager().GetBlockingInterface() );
+
+ iSendkeyInMsgList = ( IMUtils::CRKeyL( KCRUidIMVariation, KIMVariationKey )
+ & EIMFeatSendkeyInMsgList );
+
+ SetRect( aRect );
+
+ ActivateL();
+ TBool tempFlag = aActivateFromTabSwitch;
+ if ( iAppUi->FocusFlag() && aActivateFromTabSwitch )
+ {
+ tempFlag = EFalse;
+ }
+
+ ResetAfterSendL( tempFlag );
+
+ CHAT_DP( D_CHAT_LIT( "CursorPos(): %d" ), iEditor->CursorPos() );
+ CHAT_DP( D_CHAT_LIT( "TextLength(): %d" ), iEditor->TextLength() );
+
+ // Observe tap events
+ iChatView->SetTapObserver( this, EMessageList );
+ iEditor->SetTapObserver( this, EMessageEditor );
+
+ iEditIndicator = CCAEditIndicator::NewL( *iEditor ) ;
+ ifocusFlag = EFalse;
+ }
+
+// Destructor
+CCAConversationsContainer::~CCAConversationsContainer()
+ {
+
+ delete iFromMe;
+ delete iToMe;
+ delete iUnsupported;
+ delete iCorrupted;
+ delete iChatView;
+
+ delete iEditIndicator;
+ delete iEditor;
+ delete iBlockingUI;
+ if ( iAppUi )
+ {
+ if ( !iAppUi->IsUnderDestruction() )
+ {
+ iAppUi->LayoutInfo()->SetEditorVisibility( EFalse );
+ iAppUi->RemoveLayoutChangeObserver( this );
+
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::IsObjectSelected
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::IsObjectSelected( TBool& aIsOpenable , TBool& aSavePossible )
+ {
+ MCAConversationMessage* msg = iChatView->SelectedMessage();
+ if ( !msg )
+ {
+ // Nothing selected
+ return EFalse;
+ }
+
+ TBool object = EFalse;
+
+ if ( msg->ContentType() == TEnumsPC::EContentPicture ||
+ msg->ContentType() == TEnumsPC::EContentOther )
+ {
+ // We have object
+ object = ETrue;
+ }
+
+
+ switch ( msg->ContentProcessState() )
+ {
+ case TEnumsPC::EContentNotSupported:
+ case TEnumsPC::EContentCorrupted:
+ case TEnumsPC::EContentNotSupportedDrm:
+ {
+ // Not supported or corrupted, can't open
+ aIsOpenable = EFalse;
+ break;
+ }
+ case TEnumsPC::EThumbnailReady:
+ default:
+ {
+ if ( msg->ContentData().Length() == 0 )
+ {
+ // No content, don't allow opening
+ aIsOpenable = EFalse;
+ }
+ else
+ {
+ // Allow opening
+ aIsOpenable = ETrue;
+
+ //fix - refer Ui Spec Approved Version 1.0
+ //(Instant Messaging NG 001 151006.pdf)
+ //Section 10.2.10 Pg 131 -
+ //"In case user has saved the image already or sent it
+ //by himself, this option(save) is not available."
+ aSavePossible = ( ( msg->MessagerType() == TEnumsPC::EMessageSent )
+ || ( msg->IsImageSaved() ) )
+ ? EFalse : ETrue ;
+ }
+ }
+ }
+
+ return object;
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SelectedMessage
+// ---------------------------------------------------------
+//
+MCAConversationMessage* CCAConversationsContainer::SelectedMessage()
+ {
+ return iChatView->SelectedMessage();
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::FetchMessages
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::FetchMessages( TBool aFetch )
+ {
+ iChatView->FetchMessages( aFetch );
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SelectedItem()
+// ---------------------------------------------------------
+//
+HBufC* CCAConversationsContainer::SelectedItemL()
+ {
+ return iChatView->SelectedItemL();
+ }
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::SelectedItemType
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CCAConversationsContainer::SelectedItemType()
+ {
+ return iChatView->SelectedItemType();
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::IsStopped()
+// This method checks if scroll mode is on or off
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::IsStopped() const
+ {
+ return iChatView->Highlighted();
+ }
+
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::SetItemHighlightL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCAConversationsContainer::SetItemHighlightL( TBool aHighlight )
+ {
+ iChatView->SetHighlight( aHighlight );
+ iItemHighlight = aHighlight;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::StartScrollingL()
+// This method is called when scrolling is started again
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::StartScrollingL( TBool aActivateFromTabSwitch/*=EFalse*/ )
+ {
+ // disable highlight and set focus to editor
+ if ( iChatView->Highlighted() )
+ {
+ iChatView->DisableHighlightL();
+ }
+ if ( !aActivateFromTabSwitch )
+ {
+ iEditor->SetFocus( ETrue, EDrawNow );
+ iChatView->SetFocus( EFalse, EDrawNow );
+ }
+ else
+ {
+ iEditor->SetFocus( EFalse, EDrawNow );
+ iChatView->SetFocus( ETrue, EDrawNow );
+ }
+
+ iEditor->DrawDeferred();
+ UpdateCbaL();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::StopScrollingL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::StopScrollingL()
+ {
+ // unfocus editor (highlighting is enabled
+ // automatically in OfferKeyEvent of ChatView)
+ iEditor->SetFocus( EFalse, EDrawNow );
+ iChatView->SetFocus( ETrue, EDrawNow );
+ iEditor->DrawDeferred();
+ // Set editor cursor pos to end of text
+ iEditor->SetCursorPosL( iEditor->TextLength(), EFalse );
+ UpdateCbaL();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::UpdateCbaL()
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::UpdateCbaL()
+ {
+ TInt cbaRes( R_CHAT_SOFTKEYS_OPTIONS_CONTINUE__EMPTY );
+ if ( !iCba )
+ {
+ return;
+ }
+
+ if ( !iChatView->GetMessageCount() )
+ {
+ //if the message list is empty
+ if ( !iEditor->IsFocused() )
+ {
+ //if editor is not in focus then the rightSK must be "continue"
+ iCba->SetCommandSetL( cbaRes );
+ iCba->DrawNow();
+ return;
+ }
+ }
+
+ if ( iChatView->Highlighted() )
+ {
+ // focus on chatview
+ TBool ignore;
+ HBufC* item = iChatView->SelectedItemL();
+ CleanupStack::PushL( item );
+ TBool dummyArgument( EFalse );
+ if ( IsObjectSelected( ignore, dummyArgument ) )
+ {
+ // openable object selected
+ cbaRes = R_CHAT_SOFTKEYS_OPTIONS_CONTINUE__OPEN;
+ }
+ else if ( item && item->Length() > 0 )
+ {
+ // automatic find item selected
+ cbaRes = R_CHAT_SOFTKEYS_OPTIONS_CONTINUE__CONTEXTOPTIONS;
+ }
+ CleanupStack::PopAndDestroy( item );
+ }
+ else
+ {
+ // focus on editor
+ cbaRes = iEditor->TextLength() > 0 ?
+ R_CHAT_SOFTKEYS_OPTIONS_BACK__SEND :
+ R_CHAT_SOFTKEYS_OPTIONS_BACK__EMPTY;
+ }
+
+ // Check that there is not "Spell" in the left button
+ // ControlOrNull() is needed for 3.0 backport.
+ if ( !( iCba->ControlOrNull( EAknFepSoftkeySpell ) &&
+ iCba->IsCommandVisible( EAknFepSoftkeySpell ) ) )
+ {
+ iCba->SetCommandSetL( cbaRes );
+ iCba->DrawNow();
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::Editor()
+// This method returns pointer to CEikGlobalTextEditor
+// ---------------------------------------------------------
+//
+CCAMessageEditor& CCAConversationsContainer::Editor() const
+ {
+ return *iEditor;
+ }
+
+TBool CCAConversationsContainer::Sending() const
+ {
+ return iSending;
+ }
+
+void CCAConversationsContainer::ResetSending()
+ {
+ iSending = EFalse;
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::CheckBlockedL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::CheckBlockedL()
+ {
+
+ MCABlockingPC* blockinInterface = iAppUi->GetProcessManager().GetBlockingInterface();
+
+ TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+
+ // Check if target id is blocked
+ if ( blockinInterface->IsContactBlocked( wvid, ETrue ) )
+ {
+ iAppUi->ShowWaitDialogL( R_CHAT_BLOCK_REMOVING );
+ TInt errorCode = KErrNone;
+ TRAPD( err, errorCode = blockinInterface->SetTemporaryGrantL(
+ wvid, ETrue ) );
+ iAppUi->DismissWaitDialogL( err );
+ if ( errorCode == KErrNone )
+ {
+ IMDialogUtils::DisplayNoteDialogL( R_CHATCLIENT_CNOTE_UNBLOCK );
+ }
+ else
+ {
+ IMNoteMapper::ShowNoteL( errorCode );
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SendMessageL()
+// This method handles message sending to engine
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::SendMessageL()
+ {
+ if ( iAppUi->UISessionManager().IsLoggedIn() )
+ {
+ TInt textLength( iEditor->TextLength() );
+ if ( textLength == 0 )
+ {
+ return;
+ }
+
+ // Check status, and change status to "online" if it's "away"
+ MCAPresence::TPresenceStatus curStatus =
+ CAPresenceManager::InstanceL()->StatusL();
+
+ TBool statusChangeNeeded =
+ ( curStatus == MCAPresence::EAway ||
+ curStatus == MCAPresence::EBusy );
+
+ if ( statusChangeNeeded &&
+ IMUtils::IntResourceValueL(
+ RSC_CHAT_VARIATION_AUTOMATIC_STATUS_CHANGE ) )
+ {
+ CCAWaitNote* note = CCAWaitNote::ShowWaitNoteLC(
+ R_QTN_CHAT_CHANGE_STATUS_CHANGING );
+
+ TInt error = CAPresenceManager::InstanceL()->ChangeStatusL(
+ MCAPresence::EOnline, KNullDesC );
+
+ CleanupStack::PopAndDestroy(); // waitnote
+
+ if ( error == KErrNone )
+ {
+ // Change status pane icon
+ iAppUi->UISessionManager().SetStatusPaneIconsL();
+ // show information note
+ IMDialogUtils::DisplayInformationNoteL(
+ R_CHAT_STATUS_CHANGED_AUTOMATIC );
+ }
+ else
+ {
+ // change status failed
+ IMDialogUtils::DisplayErrorNoteL(
+ R_QTN_CHAT_CHANGE_STATUS_FAILED );
+ }
+ }
+
+ CheckReplyL();
+
+ HBufC* msgBuf = iMessageExtensionsHandler.ProcessMessageLC( *iEditor );
+ TPtr msgPtr( msgBuf->Des() );
+
+ // Check message if there is other than empty chars
+ TInt len( msgPtr.Length() );
+ TBool contaisOnlyEmptyChars( ETrue );
+
+ for ( TInt i( 0 ); ( i < len ) && contaisOnlyEmptyChars; ++i )
+ {
+ TPtrC c = msgPtr.Mid( i, 1 ); // next character
+ TInt position = ( KEmptyCharacters() ).FindC( c );
+
+ if ( position == KErrNotFound )
+ {
+ // c not found from empty characters --> c is not empty char
+ contaisOnlyEmptyChars = EFalse;
+ }
+ }
+
+ if ( contaisOnlyEmptyChars )
+ {
+ // message contains only empty character
+ // don't send message and setting focus back to editor window
+ iEditor->SetFocus( ETrue );
+ iChatView->SetFocus( EFalse );
+ CleanupStack::PopAndDestroy( msgBuf );
+ return;
+ }
+
+
+ // Check grant list
+ CheckBlockedL();
+
+ iConversationPC->SendMessageL( msgBuf->Des() );
+
+ TInt editorFlags = ( iEditor->AknEdwinFlags() | EAknEditorFlagNoEditIndicators );
+ iEditor->SetAknEditorFlags( editorFlags );
+
+ ResetAfterSendL();
+ CleanupStack::PopAndDestroy( msgBuf ); // msgBuf
+ }
+ else
+ {
+ // Not logged in
+ // 1. Start login procedure
+ // 2. Wait for contact list fetching to complete
+ // before proceeding with sending (unless bgfetch is enabled)
+ if ( !iLogingFlag )
+ {
+ iLogingFlag = ETrue;
+ MCALoginPC *loginPC = iAppUi->GetProcessManager().GetLogInInterface();
+ loginPC->AddObserver( this );
+
+ TBool isloggedIn = iAppUi->UISessionManager().LoginL( MCAUiLoginCmdCB::EQueryLogin );
+
+ if ( isloggedIn )
+ {
+ iWvId.Copy( iConversationPC->GetReadInterfaceId().Left(
+ iWvId.MaxLength() ) );
+ iSending = ETrue; // set the sending flag, so we don't get deleted
+ // Login
+ }
+ else
+ { // Login failed, return
+ ResetSending();
+ loginPC->RemoveObserver();
+ }
+ iLogingFlag = EFalse;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::AddToFriendsL()
+// Adds to friend
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::AddToFriendsL()
+ {
+
+ CCAStatusPaneHandler& statusPane = *iViewSwitcher.CAStatusPane();
+
+ HBufC* titleText = statusPane.Title()->AllocLC();
+
+ // creating a new contact
+ TBool contactSaved( EFalse );
+
+ CCAContactEditor* contactEditor =
+ CCAContactEditor::NewL( -1, contactSaved );
+ TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+
+ contactEditor->EditContactLD( TEnumsPC::EAddToContact, KNullDesC, wvid, KNullDesC );
+
+ statusPane.SetTitleL( *titleText );
+ CleanupStack::PopAndDestroy( titleText );
+
+ iTitleUpdater.UpdateTitleL();
+
+ statusPane.RestoreNaviPane();
+
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::BlockUserL()
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::BlockUserL()
+ {
+ TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+
+ iBlockingUI->BlockUserL( wvid );
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::IsBlocked()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::IsBlocked() const
+ {
+ TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+ return iAppUi->GetProcessManager().GetBlockingInterface()->IsContactBlocked( wvid );
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::BlockUserWVIdL()
+// ---------------------------------------------------------
+void CCAConversationsContainer::BlockUserWVIdL()
+ {
+ iBlockingUI->DisplayBlockTextQueryL();
+ }
+// ---------------------------------------------------------
+// CCAConversationsContainer::UnBlockL()
+// ---------------------------------------------------------
+void CCAConversationsContainer::UnBlockL()
+ {
+ iBlockingUI->DisplayUnblockListQueryL();
+ }
+// ---------------------------------------------------------
+// CCAConversationsContainer::DisplayBlockedListL()
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::DisplayBlockedListL()
+ {
+ iBlockingUI->DisplayBlockedListL();
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ApplicationUserSentThis()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::ApplicationUserSentThis() const
+ {
+ TBool ret( EFalse );
+ MCAConversationMessage* message = iChatView->SelectedMessage();
+ if ( message )
+ {
+ ret = ( message->MessagerType() == TEnumsPC::EMessageSent );
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SetLoggingOnL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::RecordChatL()
+ {
+ TBool isMemorySelected = ETrue;
+#ifdef RD_MULTIPLE_DRIVE // show note
+ isMemorySelected = ShowMemorySelectionDialogL();
+#endif
+ // if the location has not been set, don't do record
+ if ( !isMemorySelected )
+ {
+ return;
+ }
+
+ HBufC* logFileName = HBufC::NewLC( KMaxLogFileName );
+ TPtr logFileNamePtr( logFileName->Des() );
+
+ iConversationPC->GetLogFileName( logFileNamePtr ) ;
+
+ TInt result( IMDialogUtils::DisplayTextQueryDialogL( logFileNamePtr,
+ RSC_CHATNG_LOGDIALOG_PROMPT, R_CHATCLIENT_LOG_NAME_QUERY,
+ ETrue // T9
+ ) );
+
+ if ( result == EAknSoftkeyOk || result == EAknSoftkeyDone )
+ {
+ //CR ID : 10139730 Show warning when saving a chat
+ ShowRecordSavingWarningL() ;
+#ifdef RD_MULTIPLE_DRIVE // show note
+ TInt error = KErrNone;
+ TRAP( error , iConversationPC->RecordChatL( *logFileName ) );
+
+ if ( error != KErrNotSaved && error != KErrDiskFull )
+#else
+ iConversationPC->RecordChatL( *logFileName );
+#endif
+ {
+ IMDialogUtils::DisplayConfirmationNoteL( R_QTN_CHAT_SAVING_SAVED );
+ }
+#ifdef RD_MULTIPLE_DRIVE
+ else if ( error == KErrDiskFull )
+ {
+ TBuf< KMaxPath > defaultDrive;
+
+ CRepository* cenrep = CRepository::NewL( KWVSettingsCenRepUid );
+
+ TInt err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+
+ delete cenrep;
+ cenrep = NULL;
+
+ if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+ TInt driveNo = 0;
+ err = RFs::CharToDrive( defaultDrive[0], driveNo );
+ if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+ TDriveNumber driveNumber = TDriveNumber( driveNo );
+
+ RFs& fs = CCoeEnv::Static()->FsSession();
+
+ TDriveInfo driveInfo;
+ err = fs.Drive( driveInfo, driveNumber );
+ if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+ if ( driveInfo.iDriveAtt & KDriveAttRemovable )
+ {
+ HBufC* prompt = iEikonEnv->AllocReadResourceLC( R_CHAT_MEMLO_MMC_NOT_ENOUGH_MEMORY );
+ IMDialogUtils::DisplayErrorNoteL( *prompt, ETrue );
+ CleanupStack::PopAndDestroy( prompt );
+ }
+ else
+ {
+ HBufC* prompt = iEikonEnv->AllocReadResourceLC( R_CHAT_MEMLO_NOT_ENOUGH_MEMORY );
+ IMDialogUtils::DisplayErrorNoteL( *prompt, ETrue );
+ CleanupStack::PopAndDestroy( prompt );
+ }
+
+ }
+#endif
+ }
+ CleanupStack::PopAndDestroy( logFileName );
+ }
+
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ExtensionFits()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::ExtensionFits( TInt aLength )
+ {
+ TBool retVal( ETrue );
+ if ( iEditor->MaxLength() - iEditor->TextLength() < aLength )
+ {
+ retVal = EFalse;
+ }
+ return retVal;
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ResetAfterSendL()
+// Resets arrays, lines and nick length after send
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::ResetAfterSendL( TBool aActivateFromTabSwitch/*=EFalse*/ )
+ {
+ iEditor->ResetL();
+ iEditor->SetTextLimit( IMUtils::MaxMsgLength() );
+ iEditor->SetAknEditorCurrentCase( EAknEditorTextCase );
+ StartScrollingL( aActivateFromTabSwitch ); // Call to update CBA
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::DisplayInfoNoteL()
+// Displays info note for corresponding resource id
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::DisplayInfoNoteL( const TInt aResourceId )
+ {
+ CAknNoteDialog* infoNote = new ( ELeave ) CAknNoteDialog( CAknNoteDialog::
+ EConfirmationTone, CAknNoteDialog::EShortTimeout );
+
+ infoNote->ExecuteLD( aResourceId );
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::LayoutChangedL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::LayoutChangedL( TInt aType )
+ {
+ LoadBitmapsL();
+ TRect mainPaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPaneRect );
+ SetRect( mainPaneRect );
+
+ // Update skin context of editor
+ if ( iEditor )
+ {
+ iEditor->SetupSkinContextL( ETrue );
+ }
+
+ CCoeControl::HandleResourceChange( aType );
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleEdwinSizeEventL( CEikEdwin* aEdwin,
+// TEdwinSizeEvent aEventType, TSize aDesirableEdwinSize )
+// This method is called when editor is extended to two lines
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::HandleEdwinSizeEventL( CEikEdwin* /*aEdwin*/,
+ TEdwinSizeEvent aEventType, TSize /*aDesirableEdwinSize*/ )
+ {
+ if ( aEventType == EEventSizeChanging )
+ {
+ SizeChanged();
+
+ DrawNow();
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleTapEventL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleTapEventL( TTapEvent aEvent,
+ TUint aControlId )
+ {
+ // Handle the tap events which occur in our child controls:
+ // Message list and Message editor.
+ switch ( aControlId )
+ {
+ case EMessageList:
+ {
+ // Focused message was double tapped
+ if ( aEvent == MCATapEventObserver::EDoubleTap )
+ {
+ // Activate tapped item
+ TBool ignore;
+ TBool dummyArgument;
+ if ( IsObjectSelected( ignore , dummyArgument ) )
+ {
+ iAppUi->ProcessCommandL( EChatClientOpenObject );
+ }
+
+ }
+ // Message or item was tapped
+ else if ( aEvent == MCATapEventObserver::ESingleTap )
+ {
+ // Find objects activate with single tap
+ iRecipientObserver.ShowPopUpMenuL();
+ }
+ break;
+ }
+ case EMessageEditor:
+ {
+ // Nothing to do here ATM.
+ // Focus transition is handled in HandleControlEventL
+ break;
+ }
+ default:
+ {
+ // There is an unhandled object or the object returned wrong
+ // controlId. Check the implementation
+ __CHAT_ASSERT_DEBUG( EFalse );
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleControlEventL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleControlEventL( CCoeControl* aControl,
+ TCoeEvent aEventType )
+ {
+ if ( EEventRequestFocus == aEventType )
+ {
+ if ( aControl == ( CCoeControl* )iEditor )
+ {
+ // Focus to editor
+ StartScrollingL();
+ iAppUi->SetFocusFlag( ETrue );
+ }
+ else // aControl == iChatView
+ {
+ // Focus to messagelist
+ StopScrollingL();
+ iAppUi->SetFocusFlag( EFalse );
+ }
+ }
+
+ if ( CATouchUtils::PenEnabled() )
+ {
+
+ if ( EEventStateChanged == aEventType )
+ {
+ if ( aControl == ( CCoeControl* )iEditor )
+ {
+ // Update MSK - When using virtual keyboard
+ // on touch enabled devices, one is bound to receive
+ // EEventStateChanged. Hence handle the same
+ UpdateCbaL();
+ }
+ }
+
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SizeChanged()
+// Called by framework when the view size is changed
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::SizeChanged()
+ {
+ TInt lines( iEditor->NumberOfLines() );
+
+ if ( lines > 2 ) // ignore events for more than 2 lines
+ {
+ lines = 2;
+ }
+ lines--; // convert to index
+
+ TAknLayoutRect rp;
+ if ( lines == 1 )
+ {
+ rp.LayoutRect( Rect(), AknLayoutScalable_Apps::im_reading_pane(
+ TChatListBoxLayout::EWithEditor2Lines ) );
+ }
+ else
+ {
+ rp.LayoutRect( Rect(), AknLayoutScalable_Apps::im_reading_pane(
+ TChatListBoxLayout::EWithEditor ) );
+ }
+
+ // Set icon sizes, do this before setting the rect for
+ // chat view to prevent icon sizes from changing after chat
+ // view rect is set.
+ ResizeIcons( TextRect() );
+
+ // set rect for chat view
+ iChatView->SetRect( rp.Rect() );
+
+ // and editor
+ TAknLayoutRect wpl;
+ wpl.LayoutRect( Rect(), AknLayoutScalable_Apps::im_writing_pane( 1 - lines ) );
+
+ TAknWindowLineLayout myWPLayout( AknLayoutScalable_Apps::im_writing_pane( 1 - lines ) );
+
+ iOutLine.LayoutRect( iAppUi->LayoutInfo()->MainPaneRect(), myWPLayout );
+
+ iVertLine.LayoutRect( wpl.Rect(),
+ iAppUi->LayoutInfo()->IM_writing_field_elements_Line_1( lines ) );
+
+ iHoriline.LayoutRect( wpl.Rect(),
+ iAppUi->LayoutInfo()->IM_writing_field_elements_Line_2() );
+
+ TAknMultiLineTextLayout mlwpt =
+ iAppUi->LayoutInfo()->Multiline_IM_writing_pane_texts_Line_1( lines + 1 );
+
+ AknLayoutUtils::LayoutEdwin( iEditor, wpl.Rect(), mlwpt, EAknsCIQsnTextColorsCG25 );
+
+ FocusChanged( EDrawNow );
+
+ DrawNow();
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::CountComponentControls() const
+// ---------------------------------------------------------
+//
+TInt CCAConversationsContainer::CountComponentControls() const
+ {
+ // We have 2 controls
+ return 2;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ComponentControl(TInt aIndex) const
+// ---------------------------------------------------------
+//
+CCoeControl* CCAConversationsContainer::ComponentControl( TInt aIndex ) const
+ {
+ //returns control with aIndex
+ switch ( aIndex )
+ {
+ case 0:
+ {
+ return iChatView;
+ }
+ case 1:
+ {
+ return iEditor;
+ }
+ default:
+ {
+ return NULL;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::Draw(const TRect& aRect) const
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::Draw( const TRect& aRect ) const
+ {
+ CWindowGc& gc = SystemGc();
+
+ // Draw skinned background
+ iSkinVar->ClearChatListBoxBackGround(
+ gc, aRect,
+ iSkinVar->MainPaneBackgroundContext() );
+
+ TRect editorRect( iEditor->Rect() );
+ TRect outlineRect( iOutLine.Rect() );
+ TRect parent( Rect() );
+
+ TBool skinnedDraw = iSkinVar->DrawSkinnedEditor(
+ this, gc, parent, editorRect, outlineRect );
+
+ if ( ! skinnedDraw )
+ {
+ DrawUtils::ClearBetweenRects( gc, Rect(), iEditor->Rect() );
+
+ iOutLine.DrawOutLineRect( gc );
+ iHoriline.DrawRect( gc );
+ iVertLine.DrawRect( gc );
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent,
+// TEventCode aType )
+// Handles keyevents
+// ---------------------------------------------------------
+//
+TKeyResponse CCAConversationsContainer::OfferKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType )
+ {
+ CHAT_DP( D_CHAT_LIT( "CCAConversationsContainer::OfferKeyEventL key %d" ),
+ aKeyEvent.iCode );
+
+ if ( aKeyEvent.iScanCode == EStdKeyYes && aType != EEventKey )
+ {
+ return EKeyWasConsumed;
+ }
+
+ if ( ( IsStopped() || !iEditor->IsFocused() ) )
+ {
+ if ( aKeyEvent.iScanCode >= '0' && aKeyEvent.iScanCode <= '9' )
+ {
+ // stop the automatic scrolling and start manual
+ // if user presses any of the number keys (0-9)
+ StartScrollingL();
+ // Key event gets passed to editor after this
+ }
+ }
+
+ if ( aType == EEventKeyDown )
+ {
+ if ( ( aKeyEvent.iScanCode == KHashKey ) &&
+ ( iEditor->TextLength() == 0 ) )
+ {
+
+ if ( !iEditIndicator->IsIndicatorActive() )
+ {
+ iEditIndicator->StartTimer();
+ }
+
+ }
+ }
+ switch ( aKeyEvent.iCode )
+ {
+ // flowthrough
+ case EKeyEnter:
+ case EKeyOK:
+ case EKeyPhoneSend:
+ {
+ if ( iEditor->IsFocused() )
+ {
+ // trapping error so that focus can be returned to editor
+ TRAPD( err, SendMessageL() );
+ if ( err )
+ {
+ CActiveScheduler::Current()->Error( err );
+ }
+ iEditor->SetFocus( ETrue );
+ iChatView->SetFocus( EFalse );
+ }
+ else if ( aKeyEvent.iCode == EKeyEnter || aKeyEvent.iCode == EKeyOK
+ && iChatView->Highlighted() )
+ {
+ TBool ignore;
+ TBool dummyArgument;
+ if ( IsObjectSelected( ignore , dummyArgument ) )
+ {
+ iAppUi->ProcessCommandL( EChatClientOpenObject );
+ }
+ else
+ {
+ iRecipientObserver.ShowPopUpMenuL();
+ }
+ }
+ else if ( iSendkeyInMsgList )
+ {
+ if ( aKeyEvent.iCode == EKeyPhoneSend
+ && iChatView->Highlighted()
+ && iChatView->SelectedItemType()
+ == CFindItemEngine::EFindItemSearchPhoneNumberBin )
+ {
+ // Phone number highlighted, send key pressed -> call
+ iAppUi->ProcessCommandL( EChatClientCall );
+ }
+ }
+ return EKeyWasConsumed;
+ }
+
+ case EKeyBackspace:
+ {
+ // if bitmap is selected, it is deleted "normally" in
+ // iEditor's OfferKeyEvent
+ if ( iEditor->SelectionLength() > 0 )
+ {
+ break;
+ }
+
+ TInt cursorPos( iEditor->CursorPos() );
+ if ( cursorPos > 0 ) // at least one char in editor
+ {
+ TPtrC ptr = iEditor->RichText()->Read( ( cursorPos - 1 ), 1 );
+ // if a char to be "backspaced" is a picture
+ if ( ptr[ 0 ] == CEditableText::EPictureCharacter )
+ {
+ iMessageExtensionsHandler.DeleteExtensionL( *iEditor,
+ EMessageExtensionSmiley, cursorPos - 1 );
+ return EKeyWasConsumed;
+ }
+ }
+
+ if ( cursorPos < 2 )
+ {
+ cursorPos = 2;
+ }
+
+ CHAT_DP( D_CHAT_LIT( "CursorPos(): %d" ), cursorPos );
+ break;
+ }
+
+ // flowthrough
+ case EKeyLeftArrow:
+ case EKeyRightArrow:
+ {
+ if ( !iEditor->IsFocused() )
+ {
+ //return EKeyWasConsumed;
+ TKeyResponse res = iAppUi->OfferTabEventL( aKeyEvent, aType );
+ if ( ifocusFlag )
+ {
+ StartScrollingL();
+ ifocusFlag = EFalse;
+ }
+ else
+ {
+ iAppUi->SetFocusFlag( EFalse );
+ }
+ return res;
+ }
+ break;
+ }
+
+ case EKeyDownArrow: // flowthrough
+ case EKeyUpArrow:
+ {
+ if ( iEditor->IsFocused() )
+ {
+ // editor is focused, try to offer the key
+ if ( iEditor->OfferKeyEventL( aKeyEvent, aType )
+ == EKeyWasConsumed )
+ {
+ // editor took it
+ return EKeyWasConsumed;
+ }
+ }
+ TInt inputLang = iAvkonEnv->SettingCache().InputLanguage(); // when the editor is empty and language has candidate pane
+ if ( !iChatView->GetMessageCount() && ( ( inputLang == ELangPrcChinese )// focus should move to messagelistpane, helps in tab swithching.
+ || ( inputLang == ELangHongKongChinese )
+ || ( inputLang == ELangTaiwanChinese )
+ || ( inputLang == ELangJapanese ) ) )
+ {
+ //when message list is empty
+ if ( iEditor->IsFocused() )
+ {
+ //if editor in focus, then remove the focus from
+ // editor and move the focus to message list
+ StopScrollingL();
+ iAppUi->SetFocusFlag( EFalse );
+ }
+ else
+ {
+ //if editor not in focus, then remove the focus from
+ //msg list and move the focus to editor
+ StartScrollingL();
+ iAppUi->SetFocusFlag( ETrue );
+ }
+
+
+ return EKeyWasConsumed;
+ }
+ // offer the key to our chat control
+ TKeyResponse res = static_cast<CCoeControl*>( iChatView )
+ ->OfferKeyEventL( aKeyEvent, aType );
+
+ if ( iChatView->Highlighted() )
+ {
+ // change the cba
+ StopScrollingL();
+ iAppUi->SetFocusFlag( EFalse );
+ }
+ else
+ {
+ // change the cba
+ StartScrollingL();
+ iAppUi->SetFocusFlag( ETrue );
+ }
+ return res;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+
+ if ( iEditor->IsFocused() )
+ {
+ TKeyResponse res = iEditor->OfferKeyEventL( aKeyEvent, aType );
+
+ // Update CBA only when there is not a shift held down
+ if ( !( aKeyEvent.iModifiers & EModifierShift ) )
+ {
+ UpdateCbaL();
+ }
+ TInt inputLang = iAvkonEnv->SettingCache().InputLanguage(); // when the language has candidate
+ if ( ( inputLang != ELangPrcChinese ) && ( inputLang != ELangHongKongChinese )//pane then switching between tabs shouldnot
+ && ( inputLang != ELangTaiwanChinese ) && ( inputLang != ELangJapanese ) ) // happen,when editor is empty.
+ {
+
+ if ( res == EKeyWasNotConsumed && iEditor->TextLength() == 0
+ && aType == EEventKeyDown
+ && ( aKeyEvent.iScanCode == EStdKeyLeftArrow
+ || aKeyEvent.iScanCode == EStdKeyRightArrow )
+ )
+ {
+ StopScrollingL();
+ ifocusFlag = ETrue;
+ iAppUi->SetFocusFlag( ETrue );
+ }
+ }
+ return res;
+ }
+
+ return EKeyWasNotConsumed;
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::GetHelpContext
+// This function is called when Help application is launched
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::GetHelpContext(
+ TCoeHelpContext& aContext ) const
+ {
+ aContext.iMajor = KUidChatClient;
+ aContext.iContext = KIMNG_HLP_CONVERSATIONS ;
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::FocusChanged
+// This function is called when focus has been changed
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::FocusChanged(TDrawNow aDrawNow)
+ {
+ if ( iEditor && iAppUi->FocusFlag() )
+ {
+ iEditor->SetFocus( IsFocused() );
+ }
+
+ CCoeControl::FocusChanged( aDrawNow );
+ }
+
+// logic:
+// 1. no groups/groups not supported --> hide "to group"
+// 2. no contacts --> hide "to contact"
+// 3. 1 and 2 --> hide forward menu completely
+// 4. contacts, but no online contacts, show All contacts are Offline
+// 5. skip always the current contact we're conversing with
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::FwdContactVisible
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::FwdContactVisible()
+ {
+ // contacts
+ TInt numContacts( iConversationPC->ContactCount() );
+ TBool showFwdToContact = numContacts > 0;
+
+ // but check if the only contact is OTHER than the contact
+ // we are having a conversation with
+ if ( numContacts == 1 )
+ {
+ TPtrC wvid( iConversationPC->GetReadInterfaceId() );
+ if ( iConversationPC->FindAnyContact( wvid ) )
+ {
+ // found it, skip the current contact
+ // in list hiding logic
+ showFwdToContact = numContacts == 1 ? EFalse : ETrue;
+ }
+ }
+
+ CHAT_DP( D_CHAT_LIT( "CCAConversationsContainer::FwdContactVisible\
+ - contacts %d, show %d" ),
+ numContacts, showFwdToContact );
+
+ return showFwdToContact;
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::FwdGroupVisible
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::FwdGroupVisible()
+ {
+ // groups
+ TBool groupsSupported = iAppUi->UISessionManager().IsSupported(
+ CCAUISessionManager::EGroup );
+ TInt numGroups( 0 );
+
+ numGroups = iConversationPC->GroupCount( ETrue ) ;
+
+ // we have to have groups supported and visible to show the forward-menu
+ TBool showFwdToGroup = groupsSupported && ( numGroups > 0 );
+
+ CHAT_DP( D_CHAT_LIT( "CCAConversationsContainer::\
+ FwdGroupVisible - fwd show group: %d" ),
+ ( TInt ) showFwdToGroup );
+
+ return showFwdToGroup;
+ }
+
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::CheckReplyL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::CheckReplyL()
+ {
+
+ TPtrC wvid;
+ TBool contactInlist = ETrue;
+
+ iConversationPC->CheckReply( wvid, contactInlist );
+ if ( !contactInlist )
+ {
+ //To Remove wv and domain part from "WV User Id"
+ //if RSC_CHAT_VARIATION_HIDE_WV flag is enabled
+ HBufC* text = StringLoader::LoadLC( R_QTN_CHAT_FRIEND_ADD_UNKNOWN,
+ CCAPCUtils::DisplayId( wvid ) );
+ TInt ret = IMDialogUtils::DisplayYesNoConfirmationDialogL( *text );
+ CleanupStack::PopAndDestroy( text );
+ if ( ret == EAknSoftkeyOk || ret == EAknSoftkeyYes )
+ {
+ // Launch add contact.
+ AddToFriendsL();
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ResizeIcons
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::ResizeIcons( TRect aParentRect )
+ {
+ TSize size( aParentRect.Height(), aParentRect.Height() );
+ AknIconUtils::SetSize( iFromMe->Bitmap(), size );
+ AknIconUtils::SetSize( iToMe->Bitmap(), size );
+
+ iMessageExtensionsHandler.SizeChanged( size );
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleMessageEditorEventL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleMessageEditorEventL( TEditorEvent aEvent )
+ {
+ switch ( aEvent )
+ {
+ case EEditorContentCleared:
+ {
+ // Call StartScrollingL to update CBA if needed
+ StartScrollingL();
+ break;
+ }
+
+
+ case EEditorFirstContentAdded:
+ {
+ // Call StartScrollingL to update CBA if needed
+ if ( !iEditor->IsFocused() )
+ {
+ StartScrollingL();
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::LoadBitmapsL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::LoadBitmapsL()
+ {
+ //Removed the ownership of iConnUI from this file and made it a reference
+ //APPUI owns this connection UI instance and shares the same with this component.
+ // get user-defined colors from SAP settings
+ CCAAppSettingsSAPExt* SAPExtension = CCAAppSettingsSAPExt::NewLC( iAppUi->ConnectionUI() );
+ TInt ownCol( SAPExtension->IntValueL( KIMOwnMessageColourKey ) );
+ TInt otherCol( SAPExtension->IntValueL( KIMOthersMessageColourKey ) );
+ CleanupStack::PopAndDestroy( SAPExtension );
+
+ // These are pointers, because it has to be given as a pointer parameter
+ // to skin variant when loading icons
+ TRgb* ownRgbCol = NULL;
+ TRgb* otherRgbCol = NULL;
+
+ // check if custom color is defined for incoming messages arrow
+ TBool useCustomOtherMsgColor = EFalse;
+ if ( otherCol != KErrNotFound )
+ {
+ otherRgbCol = new ( ELeave ) TRgb( otherCol );
+ CleanupStack::PushL( otherRgbCol );
+ useCustomOtherMsgColor = ETrue;
+ }
+
+ // check if custom color is defined for outgoing messages arrow
+ TBool useCustomOwnMsgColor = EFalse;
+ if ( ownCol != KErrNotFound )
+ {
+ ownRgbCol = new ( ELeave ) TRgb( ownCol );
+ CleanupStack::PushL( ownRgbCol );
+ useCustomOwnMsgColor = ETrue;
+ }
+
+ // check resource colours
+ // The color settings is fetched directly from the REsource file, and its not part of Cenrep, that is the reason for using IntResourceValueFromRssL
+ TBool defaultColors = IMUtils::IntResourceValueFromRssL(
+ RSC_CHAT_DEFAULT_MESSAGE_COLORS );
+
+ if ( !useCustomOwnMsgColor && !defaultColors )
+ {
+ // user-defined color not defined and resource colour in use
+ TResourceReader reader;
+ CCoeEnv::Static()->CreateResourceReaderLC( reader,
+ RSC_CHAT_MESSAGE_COLOR );
+ TUint8 red( reader.ReadUint8() );
+ TUint8 green( reader.ReadUint8() );
+ TUint8 blue( reader.ReadUint8() );
+
+ CleanupStack::PopAndDestroy(); // reader
+
+ if ( !ownRgbCol )
+ {
+ ownRgbCol = new ( ELeave ) TRgb( red, green, blue );
+ CleanupStack::PushL( ownRgbCol );
+ }
+ else
+ {
+ *ownRgbCol = TRgb( red, green, blue );
+ }
+
+ useCustomOwnMsgColor = ETrue;
+ }
+
+ if ( !useCustomOtherMsgColor && !defaultColors )
+ {
+ // user-defined color not defined and resource colour in use
+ TResourceReader reader;
+ CCoeEnv::Static()->CreateResourceReaderLC( reader,
+ RSC_CHAT_OWN_MESSAGE_COLOR );
+ TUint8 red( reader.ReadUint8() );
+ TUint8 green( reader.ReadUint8() );
+ TUint8 blue( reader.ReadUint8() );
+
+ CleanupStack::PopAndDestroy(); // reader
+
+ if ( !otherRgbCol )
+ {
+ otherRgbCol = new ( ELeave ) TRgb( red, green, blue );
+ CleanupStack::PushL( otherRgbCol );
+ }
+ else
+ {
+ *otherRgbCol = TRgb( red, green, blue );
+ }
+
+ useCustomOwnMsgColor = ETrue;
+ }
+
+ TBool overrideBrand( AknLayoutUtils::LayoutMirrored() );
+
+ CGulIcon* temp;
+
+ // if custom colors are defined, use them
+ if ( useCustomOwnMsgColor )
+ {
+ temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_from,
+ EMbmChatngQgn_prop_im_from_mask,
+ iAppUi->MbmFullPath(),
+ overrideBrand, ownRgbCol );
+ }
+ else
+ {
+ temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_from,
+ EMbmChatngQgn_prop_im_from_mask,
+ iAppUi->MbmFullPath() );
+ }
+
+ CleanupStack::PushL( temp );
+ IMUtils::UpdateIcon( iFromMe, temp );
+ //iconTemp is removed from CleanupStack and does not have valid value
+
+ //it can be safely reused
+ // if custom colors are defined, use them
+ if ( useCustomOtherMsgColor )
+ {
+ temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_tome,
+ EMbmChatngQgn_prop_im_tome_mask,
+ iAppUi->MbmFullPath(),
+ overrideBrand, otherRgbCol );
+ }
+ else
+ {
+ temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_tome,
+ EMbmChatngQgn_prop_im_tome_mask,
+ iAppUi->MbmFullPath() );
+ }
+
+ CleanupStack::PushL( temp );
+ IMUtils::UpdateIcon( iToMe, temp );
+ //iconTemp is removed from CleanupStack and does not have valid value
+
+
+ //it can be safely reused
+ temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_image_corrupted,
+ EMbmChatngQgn_prop_image_corrupted_mask,
+ iAppUi->MbmFullPath() );
+ CleanupStack::PushL( temp );
+ IMUtils::UpdateIcon( iCorrupted, temp );
+ //iconTemp is removed from CleanupStack and does not have valid value
+
+ //it can be safely reused
+ temp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_unknown,
+ EMbmChatngQgn_prop_unknown_mask,
+ iAppUi->MbmFullPath() );
+ CleanupStack::PushL( temp );
+ IMUtils::UpdateIcon( iUnsupported, temp );
+ //iconTemp is removed from CleanupStack and does not have valid value
+
+ if ( useCustomOwnMsgColor )
+ {
+ CleanupStack::PopAndDestroy(); // ownRgbCol
+ }
+
+ if ( useCustomOtherMsgColor )
+ {
+ CleanupStack::PopAndDestroy(); // otherRgbCol
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::RefreshEditorL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::RefreshEditorL()
+ {
+ iEditor->RefreshEditorL();
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::IsItemHighlight
+// ---------------------------------------------------------
+//
+TBool CCAConversationsContainer::IsItemHighlight() const
+ {
+ return iItemHighlight;
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::TextRect
+// ---------------------------------------------------------
+//
+const TRect CCAConversationsContainer::TextRect() const
+ {
+ TInt lines( iEditor->NumberOfLines() );
+
+ if ( lines > 2 ) // ignore events for more than 2 lines
+ {
+ lines = 2;
+ }
+ lines--; // convert to index
+
+ TAknLayoutRect rp;
+ if ( lines == 1 )
+ {
+ rp.LayoutRect( Rect(), AknLayoutScalable_Apps::im_reading_pane( 0
+ /*TChatListBoxLayout::EWithEditor2Lines*/ ) );
+ }
+ else
+ {
+ rp.LayoutRect( Rect(), AknLayoutScalable_Apps::im_reading_pane( 1
+ /*TChatListBoxLayout::EWithEditor*/ ) );
+ }
+
+ TAknLayoutText text;
+ text.LayoutText( rp.Rect(),
+ AknLayoutScalable_Apps::im_reading_pane_t1( 1 ).LayoutLine() );
+
+ return text.TextRect();
+ }
+
+
+//added for multitab support
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::SwitchViewL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::SwitchViewL( )
+ {
+ delete iChatView;
+ //iChatView is assigned NULL as NewL may leave
+ iChatView = NULL;
+
+ //when user navigate among tab.
+ MCAMsgAddedToRichTxtCtrlObserver* observer = NULL;
+
+ if ( !iAppUi->FocusFlag() )
+ {
+ observer = this;
+ }
+
+ iChatView = CCAChatViewControl::NewL( Rect(), *this,
+ *iConversationPC,
+ *iAppUi->GetProcessManager().GetSettingsInterface(),
+ iMessageExtensionsHandler,
+ iFromMe,
+ iToMe,
+ iUnsupported,
+ iCorrupted,
+ ETrue,
+ observer );
+
+ iChatView->SetObserver( this );
+
+ UpdateCbaL();
+
+ SizeChanged();
+
+ // Observe tap events
+ iChatView->SetTapObserver( this, EMessageList );
+
+ iAppUi->LayoutInfo()->SetLayoutID( TChatListBoxLayout::EWithEditor );
+ iAppUi->LayoutInfo()->SetEditorVisibility( ETrue );
+
+ if ( iAppUi->FocusFlag() )
+ {
+ StartScrollingL();
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleLoginRefreshCompleteL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleLoginRefreshCompleteL( )
+ {
+ // Check if chat is deleted, happens when user
+ // selected to login to different server.
+ // Use case:
+ // - user was logged in to server 1
+ // - user had on going conversation with another user in server 1
+ // - user logged out from server 1
+ // - user opens the conversation and tries to send a message to the another user
+ // - user selects server 2 to login
+ // ==> all open conversations are deleted during login procedure
+ if ( iChatView->IsDeleted() )
+ {
+ iConversationPC->SetActiveConversationL( iWvId );
+
+ HBufC* msgBuf = iMessageExtensionsHandler.ProcessMessageLC( *iEditor );
+ iEditorContentStorage.StoreContent( msgBuf ); // Ownership changed
+ CleanupStack::Pop( msgBuf );
+
+ iTabId = iAppUi->CAStatusPane()->ResetAndShowCurrentTabL( TEnumsPC::EConversationItem,
+ iWvId ) ;
+ ResetSending();
+
+ SwitchViewL();
+
+ SendMessageL();
+
+ }
+ else
+ {
+ // Contacts are now available, update titlebar
+ iTitleUpdater.UpdateTitleL();
+ // Proceed with message sending
+ SendMessageL();
+ ResetSending();
+ }
+ MCALoginPC *loginPC = iAppUi->GetProcessManager().GetLogInInterface();
+ loginPC->RemoveObserver();
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ShowRecordSavingWarningL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::ShowRecordSavingWarningL() const
+ {
+ if ( IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_RECORD_WARNING ) )
+ {
+ HBufC* warningText = CCoeEnv::Static()->AllocReadResourceLC(
+ R_CHAT_RECORD_WARNING );
+
+ HBufC* warningHeading = CCoeEnv::Static()->AllocReadResourceLC(
+ R_CHAT_RECORD_WARNING_HEADING );
+
+ IMDialogUtils::DisplayMessageQueryDialogL(
+ R_CHATCLIENT_MESSAGE_QUERY_DIALOG,
+ *warningText,
+ *warningHeading
+ );
+
+ CleanupStack::PopAndDestroy( 2, warningText );
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::HandleMessageAddedL
+// ---------------------------------------------------------
+//
+void CCAConversationsContainer::HandleMessageAddedL( const TInt aMessageCount )
+ {
+ //called by tabswitch. hence set the foxus to the last message
+ if ( iConversationPC->MessageCount() == aMessageCount )
+ {
+ iChatView->MoveHighlightL( CCARichTextContainer::EPrevious );
+
+ iChatView->UnRegisterRichTxtCtrlObserver();
+
+ UpdateCbaL();
+ }
+
+ }
+
+#ifdef RD_MULTIPLE_DRIVE
+// -----------------------------------------------------------------------------
+// CCAConversationsContainer::ShowMemorySelectionDialogL
+// New actual filename for new history file.
+// -----------------------------------------------------------------------------
+//
+TBool CCAConversationsContainer::ShowMemorySelectionDialogL()
+ {
+ CHAT_DP_TXT( "CCALoggerManager::ShowMemorySelectionDialogL" );
+
+ ///////// read settings from cenrep ///////////////
+
+ TBuf< KMaxPath > defaultDrive;
+ TBuf< KMaxPath > pathTempWithoutDrive;
+ TBuf< KMaxPath > driveAndPath;
+
+ CRepository* cenrep = NULL;
+ TRAPD( err, cenrep = CRepository::NewL( KWVSettingsCenRepUid ) );
+
+ if ( err == KErrNone )
+ {
+ // creation of cenrep OK
+ CleanupStack::PushL( cenrep );
+ err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+ if ( err != KErrNone )
+ {
+ CleanupStack::PopAndDestroy( cenrep );
+ cenrep = NULL;
+ User::Leave( err );
+ }
+ // end of reading from cenrep
+
+ TInt driveNo = 0;
+ err = RFs::CharToDrive( defaultDrive[0], driveNo );
+ TDriveNumber driveNumber = TDriveNumber( driveNo );
+
+ // Check drive's media status
+ TBool isDriveOk = iAppUi->GetDriveStatusL( driveNumber );
+ if ( !isDriveOk )
+ {
+
+ // prompt the user to save into a different drive.......
+ CAknMemorySelectionDialogMultiDrive* dlg = CAknMemorySelectionDialogMultiDrive::NewL(
+ ECFDDialogTypeSave,
+ EFalse );
+
+ HBufC* rootBuffer = HBufC::NewLC( KMaxPath );
+ TPtr rootBufferPtr ( rootBuffer->Des() );
+
+ HBufC* defaultFolderBuffer = HBufC::NewLC( KMaxPath );
+ TPtr defaultFolderBufferPtr ( defaultFolderBuffer->Des() );
+
+ CleanupStack::PushL( dlg );
+ TBool ret( dlg->ExecuteL( driveNumber, &rootBufferPtr, &defaultFolderBufferPtr ) );
+ CleanupStack::PopAndDestroy( dlg );
+
+ CleanupStack::PopAndDestroy( defaultFolderBuffer );
+
+ if ( ret )
+ {
+ // update the centrep sheet also..as user changed the default folder...
+ cenrep->Set( KIMPSCRIMDefaultMemoryDrive, rootBufferPtr.Left( 3 ) );
+ driveAndPath.Append( rootBufferPtr.Left( 2 ) ); // append the drive root here with user selected drive...
+ CleanupStack::PopAndDestroy( rootBuffer );
+ CleanupStack::PopAndDestroy( cenrep );
+ cenrep = NULL;
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy( rootBuffer );
+ CleanupStack::PopAndDestroy( cenrep );
+ cenrep = NULL;
+ }
+
+ // use selected memory
+ return ret;
+ }
+ else
+
+ {
+
+ CleanupStack::PopAndDestroy( cenrep );
+
+ cenrep = NULL;
+
+ // use the default memory
+ return ETrue;
+ }
+
+ }// end of cenrep error
+
+ // cenrep create error
+ return EFalse;
+ }
+
+#endif
+
+// End of File