diff -r 000000000000 -r 094583676ce7 wvuing/wvuiave/AppSrc/CCAConversationsContainer.cpp --- /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 + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //cdl +#include //cdl +#include +#include +#include +#include // for EAknFepSoftkeySpell +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +//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( CEikonEnv::Static()->AppUi() ); + iAppUi->AddLayoutChangeObserver( this ); + + // This must be done first. + SetMopParent( aParent ); + + CreateWindowL(); + CCAApp* app = static_cast( + 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( 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