--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wvuing/wvuiave/AppSrc/CCAChatViewContainer.cpp Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,2747 @@
+/*
+* 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 chat group view
+ *
+*/
+#include "CCAAppSettingsSAPExt.h"
+
+// INCLUDE FILES
+#include "CCAChatViewContainer.h"
+#include "MCAGroupUtilsPC.h"
+#include "CCAAppUi.h"
+#include "CCAApp.h"
+#include "CCAVariantFactory.h"
+#include "CCAUISessionManager.h"
+#include "CCAMessageEditor.h"
+#include "CCAChatViewControl.h"
+#include "CCAInviteEditor.h"
+#include "CCAMessageExtensionsHandler.h"
+#include "CCAGroupUtils.h"
+#include "CCAPicture.h"
+#include "CCAStatusPanehandler.h"
+#include "CCAUiMessageUtils.h"
+#include "cautils.h"
+#include "CCAChatView.h"
+
+#include "MCAConversationMessage.h"
+#include "MCALayoutInfo.h"
+#include "MCASkinVariant.h"
+#include "MCARecipientObserver.h"
+#include "CCAPCUtils.h"
+#include "IMUtils.h"
+#include "IMDialogUtils.h"
+#include "IMNoteMapper.h"
+#include "CAExternalInterface.h"
+#include "chatdebugprint.h"
+#include "chatdebugassert.h"
+#include "CCAContactSelectionDialog.h"
+
+#include "chatngclient.hrh"
+#include "imnginternalcrkeys.h"
+#include "imprivatecrkeys.h"
+#include "imvariant.hrh"
+//added for showing the editing indicator
+#include "CCAEditIndicator.h"
+#include "MCAProcessManager.h"
+#include "MCAGroupPC.h"
+#include "MCAServerContactsArrayPC.h"
+#include <finditemengine.h>
+#include <chatNG.mbg>
+#include <chatNG.rsg>
+#include <csxhelp/imng.hlp.hrh>
+#include <gulicon.h>
+#include <AknBidiTextUtils.h> // KAknBidiExtraSpacePerLine
+#include <AknsUtils.h>
+#include <aknenv.h>
+#include <txtrich.h>
+#include <impsgroupprops.h>
+#include <stringloader.h>
+#include <AknQueryDialog.h>
+#include <AknsConstants.h>
+#include <AppLayout.cdl.h> //cdl
+#include <AknLayoutScalable_Apps.cdl.h>
+#include <AknFepGlobalEnums.h> // for EAknFepSoftkeySpell
+#include <barsread.h>
+
+#include "CATouchUtils.h"
+#include <AknSettingCache.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
+
+// ================= MEMBER FUNCTIONS =======================
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::CCAChatViewContainer
+// Default constructor must not leave.
+// ---------------------------------------------------------
+//
+CCAChatViewContainer::CCAChatViewContainer( MCAViewSwitcher& aViewSwitcher,
+ MCAGroupPC* aGroupPC,
+ MCARecipientObserver& aRecipientObserver,
+ CCAMessageExtensionsHandler& aMessageHandler,
+ CEikButtonGroupContainer* aCba,
+ TInt& aTabId ,
+ CCAChatView * aView )
+
+ : iRecipientObserver( aRecipientObserver ),
+ iViewSwitcher( aViewSwitcher ),
+ iGroupPC( aGroupPC ),
+ iMessageExtensionsHandler( aMessageHandler ),
+ iCba( aCba ),
+ iTabId( aTabId ),
+ iView( aView )
+ {
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::NewL
+// Symbian constructor can leave.
+// ---------------------------------------------------------
+//
+CCAChatViewContainer* CCAChatViewContainer::NewL( const TRect& aRect,
+ MCAViewSwitcher& aViewSwitcher,
+ MCAGroupPC* aGroupPC,
+ MCARecipientObserver& aRecipientObserver,
+ MObjectProvider* aParent,
+ CCAMessageExtensionsHandler& aMessageHandler,
+ CEikButtonGroupContainer* aCba,
+ const TBool aActivateFromTabSwitch, TInt& aTabId , CCAChatView * aView )
+ {
+ CCAChatViewContainer* self = new ( ELeave ) CCAChatViewContainer(
+ aViewSwitcher, aGroupPC , aRecipientObserver,
+ aMessageHandler, aCba, aTabId, aView );
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aRect, aParent, aActivateFromTabSwitch );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ConstructL
+// Symbian OS two phased constructor
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::ConstructL( const TRect& aRect,
+ MObjectProvider* aParent,
+ const TBool aActivateFromTabSwitch )
+ {
+ iAppUi = static_cast<CCAAppUi*>( iEikonEnv->AppUi() );
+
+ // This must be done first.
+ SetMopParent( aParent );
+
+ CreateWindowL();
+ CCAApp* app = static_cast<CCAApp*>(
+ iEikonEnv->EikAppUi()->Application() );
+ iSkinVar = app->VariantFactory()->SkinVariantL();
+
+ iGroupId = iGroupPC->ActiveGroupId().AllocL();
+
+ iGroupUtilsPC = iAppUi->GetProcessManager().GetGroupUtilsInterface() ;
+
+ //Get group interface
+ iIsLoggedIn = iAppUi->UISessionManager().IsLoggedIn();
+
+ AknEditUtils::SAknEditorParameters editorParams;
+ editorParams.iCursorYesNo = ETrue;
+ editorParams.iAllowedToMoveInsertionPoint = ETrue;
+ editorParams.iCharacterCase = EAknEditorTextCase;
+ editorParams.iEditingSpace = IMUtils::MaxMsgLength();
+ editorParams.iEditingWindow = KMaxLines; // max 2 lines in the editor
+ 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 );
+
+ // create chat view control
+
+
+ LoadBitmapsL();
+
+ MCAMsgAddedToRichTxtCtrlObserver* observer = NULL;
+
+ if ( aActivateFromTabSwitch && !iAppUi->FocusFlag() )
+ {
+ observer = this;
+ }
+
+ iChatView = CCAChatViewControl::NewL( aRect, *this,
+ *iGroupPC,
+ *iAppUi->GetProcessManager().GetSettingsInterface(),
+ iMessageExtensionsHandler,
+ iPrivIcon, iToMe,
+ iUnsupported,
+ iCorrupted,
+ ETrue,
+ observer
+ );
+
+ iChatView->SetObserver( this );
+
+
+ iGroupPC->SetGroupEventObserverL( this, *iGroupId );
+
+ iAppUi->LayoutInfo()->SetLayoutID( TChatListBoxLayout::EWithEditor );
+ iAppUi->LayoutInfo()->SetEditorVisibility( ETrue );
+ SetRect( aRect );
+
+ iEditor->SetupSkinContextL();
+ iEditor->SetCursorPosL( 0, EFalse );
+
+ if ( !aActivateFromTabSwitch )
+ {
+ iEditor->SetFocus( ETrue );
+ iChatView->SetFocus( EFalse );
+ iAppUi->SetFocusFlag( ETrue );
+ }
+ else
+ {
+ iEditor->SetFocus( EFalse );
+ iChatView->SetFocus( ETrue );
+ }
+
+ iEditor->SetObserver( this );
+
+ iRecipients = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+ iSentRecipients = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+
+ iIsEditorStateChanged = EFalse;
+
+ iSendkeyInMsgList = ( IMUtils::CRKeyL( KCRUidIMVariation, KIMVariationKey )
+ & EIMFeatSendkeyInMsgList );
+
+ 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() );
+ iAppUi->AddLayoutChangeObserver( this );
+
+ // Observe tap events
+ iChatView->SetTapObserver( this, EMessageList );
+ iEditor->SetTapObserver( this, EMessageEditor );
+ iEditIndicator = CCAEditIndicator::NewL( *iEditor ) ;
+ ifocusFlag = EFalse;
+ }
+
+// Destructor
+CCAChatViewContainer::~CCAChatViewContainer()
+ {
+
+ delete iEditIndicator;
+ delete iEditor;
+ delete iPrivIcon;
+ delete iToMe;
+ delete iUnsupported;
+ delete iCorrupted;
+ delete iPrivToMany;
+ delete iChatView;
+
+ if ( iRecipients )
+ {
+ iRecipients->Reset();
+ }
+ delete iRecipients;
+
+ if ( iSentRecipients )
+ {
+ iSentRecipients->Reset();
+ }
+ delete iSentRecipients;
+
+ if ( iGroupId && iGroupPC )
+ {
+ TRAP_IGNORE( iGroupPC->SetGroupEventObserverL( NULL, *iGroupId ) );
+ }
+
+ delete iGroupId;
+
+ if ( iAppUi )
+ {
+ if ( !iAppUi->IsUnderDestruction() )
+ {
+ iAppUi->LayoutInfo()->SetEditorVisibility( EFalse );
+ iAppUi->RemoveLayoutChangeObserver( this );
+
+ }
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::IsObjectSelected
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::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;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SelectedMessage
+// ---------------------------------------------------------
+//
+MCAConversationMessage* CCAChatViewContainer::SelectedMessage()
+ {
+ return iChatView->SelectedMessage();
+ }
+
+// -----------------------------------------------------------------------------
+// CCAChatViewContainer::SetItemHighlight
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCAChatViewContainer::SetItemHighlight( TBool aHighlight )
+ {
+ iChatView->SetHighlight( aHighlight );
+ iItemHighlight = aHighlight;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::FetchMessages
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::FetchMessages( TBool aFetch )
+ {
+ iChatView->FetchMessages( aFetch );
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ResizeIcons
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::ResizeIcons( TRect aParentRect )
+ {
+ TSize size( aParentRect.Height(), aParentRect.Height() );
+ AknIconUtils::SetSize( iPrivIcon->Bitmap(), size );
+ AknIconUtils::SetSize( iPrivToMany->Bitmap(), size );
+ AknIconUtils::SetSize( iToMe->Bitmap(), size );
+ iMessageExtensionsHandler.SizeChanged( size );
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SelectedItem
+// ---------------------------------------------------------
+//
+HBufC* CCAChatViewContainer::SelectedItemL()
+ {
+ return iChatView->SelectedItemL();
+ }
+
+// -----------------------------------------------------------------------------
+// CCAChatViewContainer::SelectedItemType
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CCAChatViewContainer::SelectedItemType()
+ {
+ return iChatView->SelectedItemType();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::IsInvitationAllowed
+// Checks if user can invite friends to this group
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::IsInvitationAllowed() const
+ {
+ return iGroupUtilsPC->IsJoined( *iGroupId );
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::InviteFriendsToGroupL
+// Start invite editor for current group
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::InviteFriendsToGroupL()
+ {
+
+ //hide tabs
+ iAppUi->CAStatusPane()->ClearNaviPaneL();
+
+ CCAInviteEditor* editor = CCAInviteEditor::NewLC(
+ *iGroupId );
+
+ editor->CreateAndSendInvitation( *( iAppUi->GroupUtils() ) );
+ CleanupStack::PopAndDestroy( editor );
+
+ //Show tabs
+ iAppUi->CAStatusPane()->RestoreNaviPane();
+
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::IsStopped
+// This method checks if scroll mode is on or off
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::IsStopped() const
+ {
+ return iChatView->Highlighted();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::StartScrollingL()
+// This method is called when scrolling is started again
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::StartScrollingL( const 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 CCAChatViewContainer::StopScrollingL()
+ {
+ // unfocus editor (highlighting is enabled
+ // automatically in OfferKeyEvent of ChatView)
+ iEditor->SetFocus( EFalse, EDrawNow );
+ iEditor->DrawDeferred();
+ // Set editor cursor pos to end of text
+ iEditor->SetCursorPosL( iEditor->TextLength(), EFalse );
+ iChatView->SetFocus( ETrue );
+ UpdateCbaL();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::UpdateCbaL()
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::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;
+ TBool dummyArgument( EFalse );
+ HBufC* item = iChatView->SelectedItemL();
+ CleanupStack::PushL( item );
+
+ 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();
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SetItemEmphasize( TBool aIsEmphasized )
+// This method sets the item emphasization on
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::SetItemEmphasize( const TBool aIsEmphasized )
+ {
+ iIsEmphasis = aIsEmphasized;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::IsEmphasized()
+// This method tells if item is emphasized or not
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::IsEmphasized() const
+ {
+ return iIsEmphasis;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::Editor()
+// This method returns pointer to CEikGlobalTextEditor
+// ---------------------------------------------------------
+//
+CCAMessageEditor& CCAChatViewContainer::Editor() const
+ {
+ return *iEditor;
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ForwardToGroupL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::ForwardToGroupL()
+ {
+ MCAConversationMessage* message = iChatView->SelectedMessage();
+ if ( !message )
+ {
+ // nothing selected
+ return;
+ }
+
+ MCAServerContactsArrayPC* pairsArray =
+ iGroupPC->GetGroupPairArrayLC();
+
+ HBufC* emptyText = iEikonEnv->AllocReadResourceLC(
+ R_CHAT_IBOX_FRIENDS_OFFLINE );
+ HBufC* title = iEikonEnv->AllocReadResourceLC(
+ R_PRIVATE_CHAT_FORWARD_TITLE_GROUP );
+
+ TInt selectedIndex( 0 );
+ TInt retVal( IMDialogUtils::DisplayListQueryDialogL( &selectedIndex,
+ pairsArray,
+ R_PRIVATE_CHAT_LIST_SELECT_RECIP_DLG,
+ *title,
+ *emptyText,
+ ETrue ) );
+ //Note: code scanner warning is ignored for using magic numbers
+ CleanupStack::PopAndDestroy( 2, emptyText ); // title, emptyText
+
+ if ( retVal == EAknSoftkeyOk || retVal == EAknSoftkeyDone
+ || retVal == EAknSoftkeySelect )
+ {
+
+ // Check if there is highlighted item
+ HBufC* item = SelectedItemL();
+ CleanupStack::PushL( item );
+
+ if ( item->Length() > 0 )
+ {
+ // Set forwarded message, ownership is transferred
+ message->SetForwardPartL( item );
+ }
+ else
+ {
+ // Clear previous forward message
+ message->SetForwardPartL( NULL );
+ }
+
+ CleanupStack::PopAndDestroy( item );
+
+ TInt err = iAppUi->GroupUtils()->JoinGroupL(
+ ETrue,
+ pairsArray->WVIdL( selectedIndex )->iWVID,
+ KNullDesC, message );
+
+ if ( err )
+ {
+ CActiveScheduler::Current()->Error( err );
+ }
+ if ( TEnumsPC::EUnregistered == iAppUi->RetForwardTo() )
+ {
+ iAppUi->SetResetForwardTo( TEnumsPC::ERegister );
+ iAppUi->GroupUtils()->PrepareToSwitchBackL( iGroupId->Des(),
+ KUidChatView,
+ KUidChatView );
+ }
+ else if ( TEnumsPC::ERegister == iAppUi->RetForwardTo() )
+ {
+ iAppUi->SetResetForwardTo( TEnumsPC::EAlreadyRegistered );
+ }
+ }
+ //always dont use CleanupStack::PopAndDestroy(pairsArray)
+ //because there might be a object slicing happening
+ //when the pairsArray is transferred from the creator
+ //to the caller. Hence one will end up deleting the wrong ptr.
+ //Hence it is better to use CleanupStack::PopAndDestroy(), as
+ //we dont know wat the creator has pushed onto the CleanupStack
+ CleanupStack::PopAndDestroy();//pairsArray
+ }
+
+
+// ---------------------------------------------------------
+// CCAConversationsContainer::ForwardToContactL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::ForwardToContactL()
+ {
+ MCAConversationMessage* message = iChatView->SelectedMessage();
+ if ( !message )
+ {
+ // nothing selected
+ return;
+ }
+
+ MCASkinVariant* skinVar = static_cast<CCAApp*>( iAppUi->Application() )
+ ->VariantFactory()->SkinVariantL();
+
+
+ CDesCArray* selectedContacts = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+ CleanupStack::PushL( selectedContacts );
+
+ CDesCArray* selectedIdentifications = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+ CleanupStack::PushL( selectedIdentifications );
+
+ MCASettingsPC* settingsPC = iAppUi->GetProcessManager().GetSettingsInterface();
+ MCAMainViewArrayPC* mainViewArrayPC = iAppUi->GetProcessManager().GetArrayInterface();
+
+ // show selection dialog
+ TBool contacts( CCAContactSelectionDialog::ShowDialogL( *selectedContacts,
+ *mainViewArrayPC,
+ *skinVar, *settingsPC,
+ iAppUi->MbmFullPath(),
+ TEnumsPC::ESingleSelect,
+ R_CONTACT_SELECTION_DIALOG,
+ *iAppUi->CAStatusPane(),
+ selectedIdentifications ) );
+ if ( !contacts )
+ {
+ // no contacts
+ //Note: code scanner warning is ignored for using magic numbers
+ CleanupStack::PopAndDestroy( 2, selectedContacts ); // selectedContacts, selectedIdentifications
+ return;
+ }
+
+ // allow tabs - suppose user would have received new messages
+ iAppUi->CAStatusPane()->RestoreNaviPane();
+
+ // handle selected contact (if any)
+
+
+ TInt count( selectedContacts->MdcaCount() );
+ CHAT_DP( D_CHAT_LIT( "selection count %d" ), count );
+
+ //if( selectedContacts->Count() == 1 )
+ if ( count == 1 )
+ {
+ TPtrC wvid( selectedContacts->MdcaPoint( 0 ) );
+
+ // User made selection -> set temporary identification for the wv id
+ MCAMainViewArrayPC* mainViewArrayPC =
+ iAppUi->GetProcessManager().GetArrayInterface();
+
+
+ //Add the conversation item to open chats array before switching the view
+ mainViewArrayPC->InsertConversationItemL( wvid,
+ selectedIdentifications->MdcaPoint( 0 ) );
+
+
+ // Check if there is highlighted item
+ HBufC* item = SelectedItemL();
+ CleanupStack::PushL( item );
+
+ if ( item->Length() > 0 )
+ {
+ // Set forwarded message
+ message->SetForwardPartL( item );
+ }
+ else
+ {
+ message->SetForwardPartL( NULL );
+ }
+
+ CleanupStack::PopAndDestroy( item );
+
+ // Store message, in case it gets destroyed.
+ iAppUi->SetForwardMessageL( message );
+
+ if ( TEnumsPC::EUnregistered == iAppUi->RetForwardTo() )
+ {
+ iAppUi->SetResetForwardTo( TEnumsPC::ERegister );
+ iAppUi->GroupUtils()->PrepareToSwitchBackL( iGroupId->Des(),
+ KUidChatView,
+ KUidConversationsView );
+ }
+ else if ( TEnumsPC::ERegister == iAppUi->RetForwardTo() )
+ {
+ iAppUi->SetResetForwardTo( TEnumsPC::EAlreadyRegistered );
+ }
+ TCADnlConvView dnlConView;
+ dnlConView.iWVID = wvid;
+ dnlConView.iIsForwarded = ETrue;
+ dnlConView.iForwardedMessage = iAppUi->ForwardMessage();
+ dnlConView.iSAPChanged = EFalse;
+ dnlConView.iSwitchTab = EFalse;
+
+ TCADnlConvViewBuf convMsgBuf( dnlConView );
+ CHAT_DP( D_CHAT_LIT( "**forward \"%S\" to contact %S" ),
+ &dnlConView.iForwardedMessage, &dnlConView.iWVID );
+
+ iAppUi->ActivateLocalViewL( KUidConversationsView, KUidConvViewMsgId, convMsgBuf );
+
+
+ }
+ //Note: code scanner warning is ignored
+ CleanupStack::PopAndDestroy( 2, selectedContacts ); // selectedContacts,selectedIdentifications
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SendMessageL()
+// This method handles message sending to engine
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::SendMessageL()
+ {
+ if ( iAppUi->UISessionManager().IsLoggedIn() )
+ {
+ TInt textLength( iEditor->TextLength() );
+ if ( textLength == 0 )
+ {
+ // setting focus back to editor window
+ iEditor->SetFocus( ETrue );
+ iChatView->SetFocus( EFalse );
+ return;
+ }
+
+ HBufC* msgBuf = iMessageExtensionsHandler.ProcessMessageLC( *iEditor );
+ TPtr msgPtr( msgBuf->Des() );
+ TInt offset( 0 );
+
+ // 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 if the message still is a whisper message,
+ // did the user erase the recipient
+ TBool isWhisper = ETrue;
+
+ // the pics are in different place with mirrored layout
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ offset = msgPtr.FindC( KSemicolon );
+ // the rest are privmsg header
+ if ( offset >= 0 ) // if found
+ {
+ //1 is space
+ msgPtr.Delete( 0, offset + 1 );
+ }
+ else
+ {
+ // user erased the recipient
+ isWhisper = EFalse;
+ }
+ }
+ else
+ {
+ if ( msgPtr[0] == CEditableText::EPictureCharacter &&
+ msgPtr[2] == CEditableText::EPictureCharacter )
+ {
+ offset = msgPtr.FindC( KSemicolon );
+ msgPtr.Delete( 0, offset + KPictureChar );
+ }
+ else if ( msgPtr[0] == CEditableText::EPictureCharacter )
+ {
+ offset = msgPtr.FindC( KSemicolon );
+ msgPtr.Delete( 0, offset + KPictureChar );
+ }
+ else
+ {
+ // user erased the recipient
+ isWhisper = EFalse;
+ }
+ }
+
+ // send message
+ if ( msgPtr.Length() > 0 )
+ {
+
+
+ if ( ! isWhisper )
+ {
+ // no longer a whisper message, address this message to all
+ iRecipients->Reset();
+ }
+
+
+ iGroupPC->SendMessageL( msgPtr, *iRecipients );
+
+ TInt editorFlags = ( iEditor->AknEdwinFlags() | EAknEditorFlagNoEditIndicators );
+ iEditor->SetAknEditorFlags( editorFlags );
+
+ ResetAfterSendL();
+
+
+ }
+
+ CleanupStack::PopAndDestroy( msgBuf );
+ }
+ else
+ {
+ iAppUi->UISessionManager().LoginL( MCAUiLoginCmdCB::ELogin );
+ if ( iAppUi->UISessionManager().IsLoggedIn() )
+ {
+ if ( iGroupUtilsPC->IsJoined( *iGroupId ) )
+ {
+ SendMessageL();
+ }
+ else
+ {
+ iAppUi->GroupUtils()->JoinGroupL( EFalse, *iGroupId );
+ if ( iGroupUtilsPC->IsJoined( *iGroupId ) )
+ {
+ SendMessageL();
+ }
+ }
+ }
+ }
+
+ // for some reason we're not redrawn, so force it
+ DrawNow();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SendImageL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::SendObjectL( TBool aNewFile,
+ TNewServiceFileType aFileType /*= ENewFileServiceImage */ )
+ {
+ if ( iAppUi->UISessionManager().IsLoggedIn() )
+ {
+
+
+ // get members
+ CDesCArray* members = new( ELeave )CDesCArrayFlat( 1 );
+ CleanupStack::PushL( members );
+
+
+
+ TPtrC groupid = iGroupPC->ActiveGroupId();
+ TBool isGroupFound = iGroupUtilsPC->FindGroup( groupid );
+
+ if ( isGroupFound )
+ {
+ // get joined members
+ iGroupUtilsPC->GetParticipantsL( *members, groupid );
+ }
+
+ TInt index;
+ if ( members->Find( *iAppUi->ScreenNamePtr(), index ) == KErrNone )
+ {
+ members->Delete( index );
+ members->Compress();
+ }
+
+ members->Sort( ECmpCollated );
+
+ CCAUiMessageUtils* utils = CCAUiMessageUtils::NewLC();
+
+
+ if ( aNewFile )
+ {
+ // create new
+ utils->SendNewFileL( aFileType, *iGroupPC,
+ iGroupPC->ScreenName(), members, IsWhisperAllowedL() );
+ }
+ else
+ {
+ // from photos
+ utils->SendImageL( *iGroupPC,
+ iGroupPC->ScreenName(), members, IsWhisperAllowedL() );
+ }
+ //Note: code scanner warning is ignored
+ CleanupStack::PopAndDestroy( 2, members ); // utils, members
+ }
+ else
+ {
+ iAppUi->UISessionManager().LoginL( MCAUiLoginCmdCB::ELogin );
+ if ( iAppUi->UISessionManager().IsLoggedIn() )
+ {
+ if ( iGroupUtilsPC->IsJoined( *iGroupId ) )
+ {
+ SendObjectL( aNewFile, aFileType );
+ }
+ else
+ {
+ iAppUi->GroupUtils()->JoinGroupL( EFalse, *iGroupId );
+ if ( iGroupUtilsPC->IsJoined( *iGroupId ) )
+ {
+ SendObjectL( aNewFile, aFileType );
+ }
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::InitPrivateMessageL()
+// Initialises privatemessage. Sets the icons to the editor
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::InitPrivateMessageL( const TDesC& aNickName,
+ const TBool aGroupMsg )
+ {
+ iCurrentNickInPrivMsg = aNickName;
+ iIsGroupMsgInPrivMsg = aGroupMsg;
+
+ HBufC* nickHb =
+ HBufC::NewLC( aNickName.Length() + KAknBidiExtraSpacePerLine );
+
+ TPtr nickVisPtr( nickHb->Des() );
+ nickVisPtr.Append( aNickName );
+
+ HBufC* msg = iEditor->GetTextInHBufL();
+ CleanupStack::PushL( msg );
+
+
+ if ( msg )
+ {
+ TPtr msgPtr( msg->Des() );
+ TInt scIndex( msgPtr.FindC( KSemicolon ) );
+ CHAT_DP( D_CHAT_LIT( "scIndex = %d" ), scIndex );
+ if ( scIndex >= 0 )
+ {
+ //KPictureChar is for space and icon
+ TPtrC tmpMsg( msgPtr.Mid( scIndex + KPictureChar ) );
+ CHAT_DP( D_CHAT_LIT( "tmpMsg:%S" ), &tmpMsg );
+ *msg = tmpMsg;
+ CHAT_DP( D_CHAT_LIT( "msg:%S" ), msg );
+ }
+ }
+
+ TInt textLength( iEditor->TextLength() );
+ //Read picture char from position zero to one
+ TPtrC pictureChar( iEditor->Text()->Read( 0, 1 ) );
+
+ CCAPicture* privIconPic = new ( ELeave ) CCAPicture(
+ *CCoeEnv::Static()->SystemGc().Device(),
+ iPrivIcon, -1 );
+
+ CleanupStack::PushL( privIconPic );
+
+ TPictureHeader privIconHeader;
+ privIconHeader.iPicture = TSwizzle<CPicture>( privIconPic );
+
+ if ( textLength > 0 && pictureChar[0] != CEditableText::EPictureCharacter )
+ {
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ CreatePrivMsgAHHeaderL( privIconHeader, aGroupMsg, nickVisPtr, msg );
+ }
+ else
+ {
+ CreatePrivMsgHeaderL( privIconHeader, aGroupMsg, nickVisPtr, msg );
+ }
+
+ }
+ else if ( ( pictureChar[0] == CEditableText::EPictureCharacter ) ||
+ ( textLength == 0 ) )
+ {
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ CreatePrivMsgAHHeaderL( privIconHeader, aGroupMsg,
+ nickVisPtr, msg );
+ }
+ else
+ {
+ CreatePrivMsgHeaderL( privIconHeader, aGroupMsg, nickVisPtr, msg );
+ }
+ }
+
+ // apply formatting for private message icon
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormat.iFontPresentation.iPictureAlignment =
+ TFontPresentation::EAlignCentered;
+ charFormatMask.SetAttrib( EAttFontPictureAlignment );
+ iEditor->RichText()->ApplyCharFormatL( charFormat, charFormatMask,
+ 0, iEditor->TextLength() );
+
+ iEditor->HandleTextChangedL();
+
+ TInt nickLengthInPixels( 0 );
+
+ TAknLayoutId layoutId;
+ CAknEnv::Static()->GetCurrentLayoutId( layoutId );
+
+ const CFont* font;
+ if ( layoutId == EAknLayoutIdAPAC )
+ {
+ font = ApacPlain12();
+ }
+ else
+ {
+ font = LatinPlain12();
+ }
+
+ if ( !aGroupMsg )
+ {
+ nickLengthInPixels = font->TextWidthInPixels( nickVisPtr );
+ }
+
+ nickLengthInPixels += ( font->TextWidthInPixels( KSpace ) ) +
+ font->TextWidthInPixels( KSemicolon );
+
+ iEditor->SetCursorPosL( iEditor->Text()->DocumentLength(), EFalse );
+
+ CleanupStack::Pop( privIconPic );
+ //Note: code scanner warning is ignored
+ CleanupStack::PopAndDestroy( 2, nickHb ); // msg, nickHb
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::Recipients()
+// Returns recipients array
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+CDesCArrayFlat& CCAChatViewContainer::Recipients() const
+ {
+ return *iRecipients;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SentRecipients()
+// Returns handle to sent recipients
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+CDesCArrayFlat* CCAChatViewContainer::SentRecipients() const
+ {
+ return iSentRecipients;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ResetAfterSendL()
+// Resets arrays, lines and nick length after send
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::ResetAfterSendL( const TBool aActivateFromTabSwitch/*=EFalse*/ )
+ {
+ iEditor->ResetL();
+
+ if ( !aActivateFromTabSwitch )
+ {
+ iEditor->SetFocus( ETrue, EDrawNow );
+ iChatView->SetFocus( EFalse, EDrawNow );
+ }
+ else
+ {
+ iEditor->SetFocus( EFalse, EDrawNow );
+ iChatView->SetFocus( ETrue, EDrawNow );
+ }
+
+ iIsPrivateMsgActive = EFalse;
+ iCurrentNickInPrivMsg.Zero();
+ iCurrentTextLenght = 0;
+ iNickLength = 0;
+ iRecipients->Reset();
+ iEditor->EnableCcpuSupportL( ETrue );
+ iEditor->SetTextLimit( IMUtils::MaxMsgLength() );
+ iEditor->SetAknEditorCurrentCase( EAknEditorTextCase );
+ StartScrollingL( aActivateFromTabSwitch ); // Call to update CBA
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::DisplayInfoNoteL()
+// Displays info note for corresponding resource id
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::DisplayInfoNoteL( const TInt aResourceId )
+ {
+ CAknNoteDialog* infoNote = new ( ELeave ) CAknNoteDialog( CAknNoteDialog::
+ EConfirmationTone, CAknNoteDialog::EShortTimeout );
+
+ infoNote->ExecuteLD( aResourceId );
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ClearSelectionL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::ClearSelectionL( const TInt aSelectionLength )
+ {
+ HBufC* tmpMsg = iEditor->GetTextInHBufL();
+ TPtr tmpPtr( tmpMsg->Des() );
+ CleanupStack::PushL( tmpMsg );
+ tmpPtr.Delete( 0, aSelectionLength );
+ iEditor->ResetL();
+ iEditor->SetTextL( &*tmpMsg );
+ CleanupStack::PopAndDestroy( tmpMsg );
+ iEditor->DrawNow();
+ iIsPrivateMsgActive = EFalse;
+ iNickLength = 0;
+ iRecipients->Reset();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::CreatePrivMsgHeaderL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::CreatePrivMsgHeaderL( TPictureHeader& aIconHeader,
+ const TBool& aGroupMsg,
+ TDesC& aNick,
+ HBufC* aMsg )
+ {
+ //Richtext pointer cannot be put to local variable and that's why it is used
+ //via methods
+
+ // if already exist the prefix of private message, delete it.
+ if ( iNickLength > 0 && iEditor->Text()->DocumentLength() >= iNickLength )
+ {
+ iEditor->RichText()->DeleteL( 0, iNickLength );
+ }
+
+ // reset the prefix of private message
+ TInt originalLength = iEditor->Text()->DocumentLength();
+
+ iEditor->RichText()->InsertL( 0, KSemicolon );
+
+ if ( aGroupMsg )
+ {
+ CCAPicture* privToMany = new ( ELeave ) CCAPicture(
+ *CCoeEnv::Static()->SystemGc().Device(),
+ iPrivToMany );
+
+ CleanupStack::PushL( privToMany );
+
+ TPictureHeader groupIconHeader;
+ groupIconHeader.iPicture = TSwizzle<CPicture>( privToMany );
+
+ iEditor->RichText()->InsertL( 0, groupIconHeader );
+ CleanupStack::Pop( privToMany );
+ }
+ else
+ {
+ iEditor->RichText()->InsertL( 0, aNick );
+ }
+
+ iEditor->RichText()->InsertL( 0, KSpace );
+ iEditor->RichText()->InsertL( 0, aIconHeader );
+
+ iNickLength = iEditor->Text()->DocumentLength() - originalLength;
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::CreatePrivMsgAHHeaderL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::CreatePrivMsgAHHeaderL( TPictureHeader& aIconHeader,
+ const TBool& aGroupMsg,
+ TDesC& aNick,
+ HBufC* aMsg )
+ {
+ //Richtext pointer cannot be put to local variable and that's why it is used
+ //via methods
+
+ // if already exist the prefix of private message, delete it.
+ if ( iNickLength > 0 && iEditor->Text()->DocumentLength() >= iNickLength )
+ {
+ iEditor->RichText()->DeleteL( 0, iNickLength );
+ }
+
+ // reset the prefix of private message
+ TInt originalLength = iEditor->Text()->DocumentLength();
+
+ iEditor->RichText()->InsertL( 0, KSemicolon );
+ iEditor->RichText()->InsertL( 0, KArabicSign );
+
+ if ( aGroupMsg )
+ {
+ CCAPicture* privToMany = new ( ELeave ) CCAPicture(
+ *CCoeEnv::Static()->SystemGc().Device(),
+ iPrivToMany );
+
+ CleanupStack::PushL( privToMany );
+
+ TPictureHeader groupIconHeader;
+ groupIconHeader.iPicture = TSwizzle<CPicture>( privToMany );
+
+ CleanupStack::Pop();
+ iEditor->RichText()->InsertL( 0, groupIconHeader );
+ }
+ else
+ {
+ iEditor->RichText()->InsertL( 0, KArabicSign );
+ iEditor->RichText()->InsertL( 0, aNick );
+ }
+
+ iEditor->RichText()->InsertL( 0, KSpace );
+ iEditor->RichText()->InsertL( 0, KArabicSign );
+ iEditor->RichText()->InsertL( 0, aIconHeader );
+ iEditor->RichText()->InsertL( 0, KArabicSign );
+
+ iNickLength = iEditor->Text()->DocumentLength() - originalLength;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::LoadBitmapsL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::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 );
+
+ TRgb* ownRgbCol = NULL;
+ TRgb* otherRgbCol = NULL;
+
+ TBool useCustomOtherMsgColor = EFalse;
+ if ( otherCol != KErrNotFound )
+ {
+ otherRgbCol = new ( ELeave ) TRgb( otherCol );
+ CleanupStack::PushL( otherRgbCol );
+ useCustomOtherMsgColor = ETrue;
+ }
+
+ TBool useCustomOwnMsgColor = EFalse;
+ if ( ownCol != KErrNotFound )
+ {
+ ownRgbCol = new ( ELeave ) TRgb( ownCol );
+ CleanupStack::PushL( ownRgbCol );
+ useCustomOwnMsgColor = ETrue;
+ }
+
+ // check resource colours
+ // The color settings are fetched from Resource file, and not from the Cenrep, that is the reason for using IntResourceValueFromRssL instead of IntResourceValueL
+ 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;
+ }
+
+ CGulIcon* iconTemp;
+
+ // if custom colors are defined, use them
+ if ( useCustomOwnMsgColor )
+ {
+ iconTemp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_tome,
+ EMbmChatngQgn_prop_im_tome_mask,
+ iAppUi->MbmFullPath(), EFalse, ownRgbCol );
+ }
+ else
+ {
+ iconTemp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_tome,
+ EMbmChatngQgn_prop_im_tome_mask,
+ iAppUi->MbmFullPath() );
+ }
+
+ CleanupStack::PushL( iconTemp );
+ IMUtils::UpdateIcon( iPrivIcon, iconTemp );
+ //iconTemp is removed from CleanupStack and does not have valid value
+
+ //it can be safely reused
+ iconTemp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_many,
+ EMbmChatngQgn_prop_im_many_mask,
+ iAppUi->MbmFullPath() );
+ CleanupStack::PushL( iconTemp );
+ IMUtils::UpdateIcon( iPrivToMany, iconTemp );
+ //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 )
+ {
+ iconTemp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_tome,
+ EMbmChatngQgn_prop_im_tome_mask,
+ iAppUi->MbmFullPath(), EFalse, otherRgbCol );
+ }
+ else
+ {
+ iconTemp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_im_tome,
+ EMbmChatngQgn_prop_im_tome_mask,
+ iAppUi->MbmFullPath() );
+ }
+ CleanupStack::PushL( iconTemp );
+ IMUtils::UpdateIcon( iToMe, iconTemp );
+ //iconTemp is removed from CleanupStack and does not have valid value
+
+ //it can be safely reused
+ iconTemp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_image_corrupted,
+ EMbmChatngQgn_prop_image_corrupted_mask,
+ iAppUi->MbmFullPath() );
+ CleanupStack::PushL( iconTemp );
+ IMUtils::UpdateIcon( iCorrupted, iconTemp );
+ //iconTemp is removed from CleanupStack and does not have valid value
+
+ //it can be safely reused
+ iconTemp = iSkinVar->LoadBitmapL( EMbmChatngQgn_prop_unknown,
+ EMbmChatngQgn_prop_unknown_mask,
+ iAppUi->MbmFullPath() );
+ CleanupStack::PushL( iconTemp );
+ IMUtils::UpdateIcon( iUnsupported, iconTemp );
+ //iconTemp is removed from CleanupStack and does not have valid value
+
+ if ( useCustomOwnMsgColor )
+ {
+ CleanupStack::PopAndDestroy(); // ownRgbCol
+ }
+
+ if ( useCustomOtherMsgColor )
+ {
+ CleanupStack::PopAndDestroy(); // otherRgbCol
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ApplicationUserSentThis() const
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::ApplicationUserSentThis() const
+ {
+ TBool ret( EFalse );
+ MCAConversationMessage* msg = iChatView->SelectedMessage();
+ if ( msg )
+ {
+ ret = ( msg->MessagerType() == TEnumsPC::EMessageSent );
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::Received() const
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::Received() const
+ {
+ TBool ret( EFalse );
+ MCAConversationMessage* msg = iChatView->SelectedMessage();
+ if ( msg )
+ {
+ ret = ( msg->MessagerType() == TEnumsPC::EMessageReceived );
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SaveChatL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+
+void CCAChatViewContainer::SaveChatL()
+ {
+ 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() );
+
+ logFileNamePtr.Copy( iGroupPC->GroupName().Left( KMaxLogFileName ) );
+
+ TInt result( IMDialogUtils::DisplayTextQueryDialogL( logFileNamePtr,
+ RSC_CHATNG_LOGDIALOG_PROMPT, R_CHATCLIENT_LOG_NAME_QUERY,
+ ETrue // T9
+ ) );
+
+ if ( result == EAknSoftkeyOk || result == EAknSoftkeyDone )
+ {
+#ifdef RD_MULTIPLE_DRIVE // show note
+ TInt error = KErrNone;
+ TRAP( error , iGroupPC->SaveChatL( *logFileName ) );
+
+ if ( error != KErrNotSaved && error != KErrDiskFull )
+#else
+ iGroupPC->SaveChatL( *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 );
+
+ CleanupStack::PushL( cenrep );
+ CleanupStack::PopAndDestroy( 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 );
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SetLoggingOffL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::SetLoggingOffL()
+ {
+ if ( iGroupPC->IsLoggingOn() )
+ {
+ iAppUi->ShowWaitDialogL( R_QTN_GEN_NOTE_SAVING );
+
+
+ TRAPD( err, iGroupPC->EndLoggingL() );
+
+ iAppUi->DismissWaitDialogL( err );
+ if ( err == KErrNone )
+ {
+ IMDialogUtils::DisplayNoteDialogL( R_QTN_RECORDING_ENDED );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::IsWhisperAllowedL() const
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::IsWhisperAllowedL() const
+ {
+ CHAT_DP( D_CHAT_LIT( "CCAChatViewContainer::IsWhisperAllowedL()" ) );
+
+ if ( IMUtils::IntResourceValueL( RSC_CHAT_VARIATION_GROUP_WHISPER ) )
+ {
+ return iWhisperingAllowed;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::IsUserAdminL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::IsUserAdmin() const
+ {
+ CHAT_DP( D_CHAT_LIT( "CCAChatViewContainer::IsUserAdminL()" ) );
+ return( iGroupUtilsPC->IsAdmin( *iGroupId ) || iGroupUtilsPC->IsOwnGroup( *iGroupId ) );
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::IsGroupOpen()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::IsGroupOpen() const
+ {
+
+ // In error situation let the group be closed i.e. EFalse
+ CHAT_DP( D_CHAT_LIT( "CCAChatViewContainer::IsGroupOpen()" ) );
+ CHAT_DP( D_CHAT_LIT( "%d = iChatGroup->IsOpenL()" ), iIsOpen );
+ return iIsOpen;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ExtensionFits()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::ExtensionFits( TInt aLength )
+ {
+ TBool retVal( ETrue );
+ if ( iEditor->MaxLength() - iEditor->TextLength() < aLength )
+ {
+ retVal = EFalse;
+ }
+ return retVal;
+ }
+
+// 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
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::FwdContactVisible
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::FwdContactVisible()
+ {
+ // contacts
+ TInt numContacts = iGroupPC->ContactCount();
+
+ TBool showFwdToContact = numContacts > 0;
+
+ CHAT_DP( D_CHAT_LIT(
+ "CCAChatViewContainer::FwdContactVisible - contacts %d, show %d" ),
+ numContacts, showFwdToContact );
+
+ return showFwdToContact;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::FwdGroupVisible
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::FwdGroupVisible()
+ {
+ // groups
+ TBool groupsSupported = iAppUi->UISessionManager().IsSupported( CCAUISessionManager::EGroup );
+ TInt numGroups = iGroupPC->GroupCount( ETrue );
+
+ // we have to have groups supported and visible to show the forward-menu
+ // If there is only one group we have to be in it so does not need to show menuitem.
+ TBool showFwdToGroup = groupsSupported && ( numGroups > 1 );
+
+ CHAT_DP( D_CHAT_LIT( "CCAChatViewContainer::FwdGroupVisible - fwd show group: %d" ), ( TInt ) showFwdToGroup );
+
+ return showFwdToGroup;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ReplyL()
+// Reply function
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::ReplyL()
+ {
+ MCAConversationMessage* msg = iChatView->SelectedMessage();
+ if ( msg )
+ {
+ TPtrC sender( msg->Sender() );
+ iRecipients->AppendL( sender );
+ InitPrivateMessageL( sender, EFalse );
+
+ StartScrollingL();
+ iAppUi->SetFocusFlag(ETrue);
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::EditChatGroupPropertiesL()
+// Edits chat group properties. Launches setting dialog
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::EditChatGroupPropertiesL()
+ {
+
+ TBool highlight = iChatView->Highlighted();
+
+ if ( !highlight )
+ {
+ iEditor->SetFocus( EFalse );
+ }
+
+ // Prohibit the tab group at this moment
+ //iAppUi->CAStatusPane()->ProhibitTabGroup( ETrue );
+
+ TInt result = iAppUi->GroupUtils()->EditChatGroupPropertiesL( *iGroupId );
+
+ //iAppUi->CAStatusPane()->RestoreNaviPane();
+
+ if ( !highlight && result != EAknSoftkeyExit )
+ {
+ iEditor->SetFocus( ETrue );
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::LeaveGroupL()
+// This function starts leaving procedure
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::LeaveGroupL()
+ {
+ //Save group conversation if logging is on
+ SetLoggingOffL();
+
+ iAppUi->GroupUtils()->LeaveGroupL( *iGroupId );
+
+ // Deregister group from switch back views
+ iAppUi->DeRegisterSwitchBack( KUidChatView, *iGroupId );
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::DisplayChatInfoL()
+// Displays chat info
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::DisplayChatInfoL()
+ {
+ iAppUi->GroupUtils()->DisplayChatInfoL( *iGroupId );
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::HandleEdwinSizeEventL( CEikEdwin* aEdwin,
+// TEdwinSizeEvent aEventType, TSize aDesirableEdwinSize )
+// This method is called when editor is extended to two lines
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::HandleEdwinSizeEventL( CEikEdwin* /*aEdwin*/,
+ TEdwinSizeEvent aEventType, TSize /*aDesirableEdwinSize*/ )
+ {
+ if ( aEventType == EEventSizeChanging )
+ {
+ SizeChanged();
+
+ DrawNow();
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::HandleTapEventL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::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( EFalse );
+ 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;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::CheckIfPrivateMessageL()
+// Checks if written message has private icons
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::CheckIfPrivateMessageL()
+ {
+ TInt cursosPos( iEditor->CursorPos() );
+ //KPictureChar stands for for space and ':' character
+ cursosPos -= KPictureChar;
+
+ if ( cursosPos >= 0 && cursosPos <= iNickLength )
+ {
+ TPtrC text( iEditor->Text()->Read( cursosPos, 1 ) );
+
+ if ( text[0] == KColon )
+ {
+ TInt selectionLength( iEditor->SelectionLength() );
+ if ( selectionLength > 0 )
+ {
+ ClearSelectionL( selectionLength );
+ iEditor->EnableCcpuSupportL( ETrue );
+ }
+ else
+ {
+ iEditor->SetSelectionL( iEditor->CursorPos(), 0 );
+ iEditor->EnableCcpuSupportL( EFalse );
+ }
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::DoHandleGroupPropertiesChangedL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::DoHandleGroupPropertiesChangedL()
+ {
+ TBool isGroupProps( EFalse );
+ iGroupPC->GetPropertiesL( isGroupProps );
+ if ( isGroupProps )
+ {
+ TPtrC groupName = iGroupPC->GroupName();
+ if ( groupName.Length() > 0 )
+ {
+ // use name when possible
+ iViewSwitcher.CAStatusPane()->SetTitleL( groupName );
+ }
+ else if ( iGroupId )
+ {
+ // GroupId is the second option
+ iViewSwitcher.CAStatusPane()->SetTitleL(
+ CCAPCUtils::DisplayId( *iGroupId ) );
+ }
+ iWhisperingAllowed = ( TEnumsPC::EImpsPropYes == iGroupPC->IsPrivateAllowed() );
+ iIsOpen = ( TEnumsPC::EImpsPropYes == iGroupPC->IsOpen() );
+ }
+ else
+ {
+ // We don't know the states so assume the worst
+ iWhisperingAllowed = EFalse;
+ iIsOpen = EFalse;
+ }
+
+
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::DoHandleGroupLeftL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::DoHandleGroupLeftL( TInt aReason )
+ {
+ // don't redraw the list box.otherwise we might crash after background to
+ // foreground switch
+ IMNoteMapper::ShowNoteL( aReason );
+ //SwitchView and DeleteTab is called here as there can be group leave
+ //because the creater has removed the group or banned the user from the group
+
+ iAppUi->CAStatusPane()->SynchroniseAndRemoveTabGroup();
+ iViewSwitcher.SwitchViewL( KUidFriendsListView );
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::LayoutChangedL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::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 );
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::HandleGroupLeft
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::HandleGroupLeft( TInt aReason )
+ {
+ CHAT_DP_TXT( " !! CCAChatViewContainer::HandleGroupLeft !!!" );
+ TRAPD( err, DoHandleGroupLeftL( aReason ) );
+
+ if ( err )
+ {
+ CActiveScheduler::Current()->Error( err );
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::HandleGroupPropertiesChanged()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::HandleGroupPropertiesChanged()
+ {
+ TRAPD( err, DoHandleGroupPropertiesChangedL() );
+ if ( err )
+ {
+ CActiveScheduler::Current()->Error( err );
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SizeChanged()
+// Called by framework when the view size is changed
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::SizeChanged()
+ {
+
+ TInt lines( iEditor->NumberOfLines() );
+
+ if ( lines > KMaxLines ) // 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() );
+
+
+ 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(), AppLayout::IM_writing_field_elements_Line_1( lines ) );
+
+ iHoriline.LayoutRect( wpl.Rect(), AppLayout::IM_writing_field_elements_Line_2() );
+
+ TAknMultiLineTextLayout mlwpt = AppLayout::Multiline_IM_writing_pane_texts_Line_1( lines + 1 );
+
+ AknLayoutUtils::LayoutEdwin( iEditor , wpl.Rect(), mlwpt, EAknsCIQsnTextColorsCG25 );
+
+ FocusChanged( EDrawNow );
+
+ DrawNow();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::CountComponentControls() const
+// ---------------------------------------------------------
+//
+TInt CCAChatViewContainer::CountComponentControls() const
+ {
+ //chatview, iEditor
+ return KControlCount;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::ComponentControl(TInt aIndex) const
+// ---------------------------------------------------------
+//
+CCoeControl* CCAChatViewContainer::ComponentControl( TInt aIndex ) const
+ {
+ switch ( aIndex )
+ {
+ case 0:
+ {
+ return iChatView;
+ }
+ case 1:
+ {
+ return iEditor;
+
+ }
+ default:
+ {
+ return NULL;
+
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::Draw(const TRect& aRect) const
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::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 );
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent,
+// TEventCode aType )
+// Handles keyevents
+// ---------------------------------------------------------
+//
+TKeyResponse CCAChatViewContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent,
+ TEventCode aType )
+ {
+ CHAT_DP( D_CHAT_LIT( "CCAChatViewContainer::OfferKeyEventL key %d" ), aKeyEvent.iCode );
+
+ 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 "#" is pressed start and timer and show the editing indicator
+ if ( ( aKeyEvent.iScanCode == KHashKey ) &&
+ ( iEditor->TextLength() == 0 ) )
+ {
+
+ if ( !iEditIndicator->IsIndicatorActive() )
+ {
+ iEditIndicator->StartTimer();
+ }
+
+ }
+ }
+
+ switch ( aKeyEvent.iCode )
+ {
+ // flowthrough
+ case EKeyEnter:
+ case EKeyOK:
+ case EKeyPhoneSend:
+ {
+ if ( iView->GetIfMenuPopup() )
+ {
+ return EKeyWasConsumed;
+ }
+ if ( iEditor->IsFocused() )
+ {
+ iEditor->SetFocus( EFalse );
+ // trapping error so that focus can be returned to editor
+ TRAPD( err, SendMessageL() );
+ if ( err )
+ {
+ CActiveScheduler::Current()->Error( err );
+ }
+ iEditor->SetFocus( ETrue );
+ }
+ else if ( aKeyEvent.iCode == EKeyEnter
+ || aKeyEvent.iCode == EKeyOK
+ && iChatView->Highlighted() )
+ {
+ TBool ignore;
+ TBool dummyArgument( EFalse );
+
+ 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;
+ }
+
+ if ( CheckIfPrivateMessageL() ) // if there are private icons, don't go back
+ {
+ return EKeyWasConsumed;
+ }
+ else
+ {
+ 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 cursor pos is less than 2 then it is set to 2
+ //KPictureChar for picture characters. (Two icons)
+ if ( cursorPos < KPictureChar )
+ {
+ cursorPos = 2;
+ }
+
+ CHAT_DP( D_CHAT_LIT( "CursorPos(): %d" ), cursorPos );
+ }
+ break;
+ }
+
+ case EKeyLeftArrow:
+ {
+ if ( !iEditor->IsFocused() ||
+ ( iEditor->CursorPos() <= iNickLength &&
+ iNickLength > 0 ) )
+ {
+ TKeyResponse res = iAppUi->OfferTabEventL( aKeyEvent, aType );
+ if ( ifocusFlag )
+ {
+ StartScrollingL();
+ ifocusFlag = EFalse;
+ }
+ else
+ {
+ iAppUi->SetFocusFlag( EFalse );
+ }
+ return res;
+ }
+ break;
+ }
+
+ case EKeyRightArrow:
+ {
+ if ( !iEditor->IsFocused() )
+ {
+ TKeyResponse res = iAppUi->OfferTabEventL( aKeyEvent, aType );
+ if ( ifocusFlag )
+ {
+ StartScrollingL();
+ ifocusFlag = EFalse;
+ }
+ else
+ {
+ iAppUi->SetFocusFlag( EFalse );
+ }
+ return res;
+ }
+
+ TInt cursorPos( iEditor->CursorPos() );
+
+ if ( ( cursorPos >= 0 ) &&
+ ( cursorPos < iNickLength ) &&
+ ( iNickLength > 0 ) )
+ {
+ TPtrC text( iEditor->Text()->Read( cursorPos, 1 ) );
+
+ if ( text[0] == CEditableText::EPictureCharacter )
+ {
+ iEditor->SetCursorPosL( iNickLength, EFalse );
+ return EKeyWasConsumed;
+ }
+ }
+ else if ( cursorPos == iEditor->TextLength() )
+ {
+ iEditor->SetCursorPosL( iNickLength, EFalse );
+ return EKeyWasConsumed;
+ }
+ 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;
+ }
+ }
+
+ // 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;
+ }
+ }
+
+ if ( iEditor->IsFocused() )
+ {
+ TKeyResponse resp = iEditor->OfferKeyEventL( aKeyEvent, aType );
+
+ TInt cursorPos( iEditor->CursorPos() );
+ if ( ( cursorPos >= 0 ) &&
+ ( cursorPos < iNickLength ) &&
+ ( iNickLength > 0 ) )
+ {
+ TPtrC text( iEditor->Text()->Read( cursorPos, 1 ) );
+
+ if ( text[0] == CEditableText::EPictureCharacter )
+ {
+ iEditor->SetCursorPosL( iNickLength, EFalse );
+ }
+ }
+
+ // 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 ( resp == EKeyWasNotConsumed && iEditor->TextLength() == 0
+ && aType == EEventKeyDown
+ && ( aKeyEvent.iScanCode == EStdKeyLeftArrow
+ || aKeyEvent.iScanCode == EStdKeyRightArrow ) )
+ {
+ StopScrollingL();
+ ifocusFlag = ETrue;
+ iAppUi->SetFocusFlag( ETrue );
+ }
+ }
+ return resp;
+ }
+
+ return EKeyWasNotConsumed;
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::HandleMessageEditorEventL
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::HandleMessageEditorEventL( TEditorEvent aEvent )
+ {
+ switch ( aEvent )
+ {
+ case EEditorContentCleared: // Flowthrough
+ {
+ // Call StartScrollingL to update CBA if needed
+ StartScrollingL();
+ break;
+ }
+ case EEditorFirstContentAdded:
+ {
+ if ( !iEditor->IsFocused() )
+ {
+ StartScrollingL();
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::GetHelpContext
+// This function is called when Help application is launched
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::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 CCAChatViewContainer::FocusChanged(TDrawNow aDrawNow)
+ {
+ if ( iEditor && iAppUi->FocusFlag() )
+ {
+ iEditor->SetFocus( IsFocused() );
+ }
+
+ CCoeControl::FocusChanged( aDrawNow );
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::RefreshEditorL
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::RefreshEditorL()
+ {
+ iEditor->RefreshEditorL();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::IsItemHighlight
+// ---------------------------------------------------------
+//
+TBool CCAChatViewContainer::IsItemHighlight() const
+ {
+ return iItemHighlight;
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::TextRect
+// ---------------------------------------------------------
+//
+const TRect CCAChatViewContainer::TextRect() const
+ {
+ TInt lines( iEditor->NumberOfLines() );
+
+ if ( lines > KMaxLines ) // 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();
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::HandleControlEventL
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::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();
+ }
+ }
+ }
+
+ }
+
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::SwitchTabL
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::SwitchTabL()
+ {
+
+ if ( iGroupId )
+ {
+
+ iGroupPC->SetGroupEventObserverL( NULL, *iGroupId );
+
+ delete iGroupId;
+ iGroupId = NULL;
+ }
+
+ iGroupId = iGroupPC->ActiveGroupId().AllocL();
+
+ HandleGroupPropertiesChanged();
+
+ iGroupPC->SetGroupEventObserverL( this, *iGroupId );
+
+ delete iChatView;
+ iChatView = NULL;
+
+ MCAMsgAddedToRichTxtCtrlObserver* observer = NULL;
+
+ if ( !iAppUi->FocusFlag() )
+ {
+ observer = this;
+ }
+
+ iChatView = CCAChatViewControl::NewL( Rect(), *this,
+ *iGroupPC,
+ *iAppUi->GetProcessManager().GetSettingsInterface(),
+ iMessageExtensionsHandler,
+ iPrivIcon, iToMe,
+ iUnsupported,
+ iCorrupted,
+ ETrue,
+ observer
+ );
+
+ iChatView->SetObserver( this );
+
+ SizeChanged();
+
+ // Observe tap events
+ iChatView->SetTapObserver( this, EMessageList );
+
+ iAppUi->LayoutInfo()->SetLayoutID( TChatListBoxLayout::EWithEditor );
+ iAppUi->LayoutInfo()->SetEditorVisibility( ETrue );
+
+ if ( iAppUi->FocusFlag() )
+ {
+ StartScrollingL();
+ }
+ }
+
+// ---------------------------------------------------------
+// CCAChatViewContainer::HandleMessageAddedL
+// ---------------------------------------------------------
+//
+void CCAChatViewContainer::HandleMessageAddedL( const TInt aMessageCount )
+ {
+ //called by tabswitch. hence set the foxus to the last message
+ if ( iGroupPC->MessageCount() == aMessageCount )
+ {
+ iChatView->MoveHighlightL( CCARichTextContainer::EPrevious );
+
+ iChatView->UnRegisterRichTxtCtrlObserver();
+
+ UpdateCbaL();
+ }
+
+ }
+
+#ifdef RD_MULTIPLE_DRIVE
+// -----------------------------------------------------------------------------
+// CCAChatViewContainer::ShowMemorySelectionDialogL
+// New actual filename for new history file.
+// -----------------------------------------------------------------------------
+//
+TBool CCAChatViewContainer::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;
+ }
+ }
+
+ // cenrep create error
+ return EFalse;
+ }
+
+
+#endif
+
+// End of File