diff -r ebe688cedc25 -r 7fdbb852d323 email/mail/EditorSrc/MsgMailEditorAppUi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/email/mail/EditorSrc/MsgMailEditorAppUi.cpp Wed Sep 01 12:31:54 2010 +0100 @@ -0,0 +1,2788 @@ +/* +* Copyright (c) 2002 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: Implements UI class for Mail application +* +*/ + + +// Mail includes +#include "MsgMailEditorAppUi.h" +#include "MsgMailEditorDocument.h" +#include "msgmaileditor.hrh" +#include "cmsgmailsendop.h" +#include "cmsgmaillaunchop.h" +#include "cmsgmailfetchfileop.h" +#include // Application UIDs +#include "MsgMailViewAttachmentsDlg.h" +#include // resource identifiers +#include +#include "MailLog.h" +#include "MailUtils.h" +#include "cmsgmaileditorheader.h" +#include "cmsgmailnavipaneutils.h" +#include +#include +#include + +// ui includes +#include +#include // for SupplyMopObject +#include +#include // AppShutter +#include // TResourceReader +#include +#include +#include +#include +#include +#include // CAknLocalScreenClearer +// Editor base classes: +#include +#include +#include +#include +#include +#include +#include + +#include +#include // CBaseMtmUi +#include // MUIU MTM utils +#include +#include // CEmailAccounts +#include // for StringLoader +#include "MsgMailOptionsDlg.h" +#include "CMsgAddMailHeadersDlg.h" // Additional headers dialog + +#include +#include +#include // CAknInputBlock + +// mail central repository handler +#include "CMailCRHandler.h" +#include +#include +#include + +#include + +#include // for iMsgEditorAppUiExtension +#include + +// LOCAL CONSTANTS +const TInt KMessageSizeMaxLength(15); +const TInt KMSKControlID(3); + +// ================= MEMBER FUNCTIONS ======================= + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::CMsgMailEditorAppUi() +// A default constructor +// ----------------------------------------------------------------------------- +// +CMsgMailEditorAppUi::CMsgMailEditorAppUi() + { + } + +// +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::ConstructL() +// Constructs new mail editor and calls PrepareToLaunchL +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::ConstructL() + { + LOG( "ConstructL" ); + CMsgMailAppUi::ConstructL(); + + // Screen is cleared so that user can't press softkeys before the view is + // properly constructed. Softkeys become visible again in + // DelegateFinalizeLaunch() after the editor is properly constructed. + iScreenClearer = CAknLocalScreenClearer::NewLC( EFalse ); + CleanupStack::Pop( iScreenClearer ); + +#ifdef RD_SCALABLE_UI_V2 + if ( AknLayoutUtils::PenEnabled() ) + { + //Set us as an observer for the toolbar + if ( PopupToolbar() ) + { + PopupToolbar()->SetToolbarObserver( this ); + PopupToolbar()->SetToolbarVisibility( ETrue, EFalse ); + } + } +#endif // RD_SCALABLE_UI_V2 + + // Disable task swapper from options menu during launch + MenuBar()->SetMenuType( CEikMenuBar::EMenuOptionsNoTaskSwapper ); + + MenuBar()->SetContextMenuTitleResourceId(R_MSGMAILEDITOR_CONTEXT_MENUBAR); + + iNaviPaneUtils = CMsgMailNaviPaneUtils::NewL(); + + iSendOp = CMsgMailSendOp::NewL( *Document(), *this ); + + iLaunchOp = CMsgMailLaunchOp::NewL( *Document(), *this ); + + // Dialer is always disabled in editor + SetDialerEnabled( EFalse ); + } + + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::~CMsgMailEditorAppUi() +// ----------------------------------------------------------------------------- +// +CMsgMailEditorAppUi::~CMsgMailEditorAppUi() + { + delete iCheckNames; + delete iWaitNote; + delete iMailEditorHeader; + delete iFetchFileOp; + delete iSendOp; + delete iLaunchOp; + delete iNaviPaneUtils; + delete iScreenClearer; + } + +// ----------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::LaunchViewL +// Opens a message, either a new or an old one. +// Sets send options in CMsgMailPreferences object. +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::LaunchViewL() + { + LOG( "LaunchViewL" ); + + if ( !Document()->HasModel() ) + { + // Format restarts editor without proper context + // and this extra check is needed with. + // Leave with KErrGeneral. + User::Leave( KErrGeneral ); + } + + CMsgEditorAppUi::SetCloseWithEndKey( EFalse ); + + iLaunchOp->StartOp( *this ); + + LOG( "LaunchViewL end" ); + } + + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DelegateInitLaunchL() +// Called from CMsgMailLaunchOp +// ---------------------------------------------------------------------------- +// +CMsgBodyControl& CMsgMailEditorAppUi::DelegateInitLaunchL() + { + LOG("CMsgMailEditorAppUi::DelegateInitLaunchL()"); + CMsgMailEditorDocument& doc = *Document(); + + iMessageID = doc.Entry().Id(); + + DoCreateControlsL(); + doc.SetConfirmation( ETrue ); + doc.ReadSendOptionsL(); + + // Checks which kind of the message is. + if( doc.IsForwardMessage() || doc.IsReplyMessage() ) + { + HandleSubjectL(); + } + else + { + SetSubjectL( doc.HeaderL().Subject() ); + } + + LOG("CMsgMailEditorAppUi::DelegateInitLaunchL() end"); + return *( BodyControl() ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::HandleSubjectL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::HandleSubjectL() + { + CMsgMailEditorDocument& doc = *Document(); + // base editor provides a service which removes unneeded prefixes + HBufC* newSubject = CreateSubjectPrefixStringL( + doc.HeaderL().Subject(), doc.IsReplyMessage() ); + CleanupStack::PushL( newSubject ); + SetSubjectL( *newSubject ); + CleanupStack::PopAndDestroy( newSubject ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DelegateExecuteViewL() +// Called from CMsgMailLaunchOp +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DelegateExecuteViewL() + { + LOG("CMsgMailEditorAppUi::DelegateExecuteViewL "); + DoGetRecipientsL(); + LockEntryL(); + UpdateMessageSizeL(); + iView->ExecuteL( ClientRect(), EMsgComponentIdNull ); + LOG("CMsgMailEditorAppUi::DelegateExecuteViewL end"); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DelegateFinalizeLaunchL() +// Called from CMsgMailLaunchOp +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DelegateFinalizeLaunchL() + { + LOG("CMsgMailEditorAppUi::DelegateFinalizeLaunchL"); + CMsgMailEditorDocument& doc = *Document(); + + UpdatePriorityIndicatorL(); + + // Check recipients' addresses + TBool highlight(EFalse); + + if ( doc.IsNewMessage() && !CheckRecipientsL( highlight ) ) + { + // Wrong address via Send As, CheckRecipientsL shows error note + // so don't ShowSelectedMailboxL + } + else + { + SetFocusToFirstFreeFieldL(); + ShowSelectedMailboxL(); + } + + + CImHeader& header = doc.HeaderL(); + + //Check if there is old reply to value saved. + //We don't want to write over local reply-to setting if there is one. + //If the reply-to is empty it must be replaced by the value + //in global smtp settings. + if(header.ReplyTo().Length() == 0) + { + TBool retVal = CheckGlobalReplyToSettingL(); + LOG1("CheckGlobalReplyToSettingL retVal=%d", retVal); + } + + + // Enable task swapper to options menu after launch has been completed. + MenuBar()->SetMenuType( CEikMenuBar::EMenuOptions ); + + doc.SetChanged( EFalse ); + + // Make softkeys visible again. + delete iScreenClearer; + iScreenClearer = NULL; + + LOG("CMsgMailEditorAppUi::DelegateFinalizeLaunchL end"); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::SetTitlePaneL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::SetTitlePaneL( TInt aResourceId ) + { + CAknTitlePane* titlePane = + static_cast(StatusPane()->ControlL( + TUid::Uid(EEikStatusPaneUidTitle))); + + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC( reader, aResourceId ); + titlePane->SetFromResourceL( reader ); + CleanupStack::PopAndDestroy(); // CSI: 12 # CreateResourceReaderLC + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::::DynInitMenuPaneL() +// This function is called by the framework just before it displays +// a menu pane. +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DynInitMenuPaneL( + TInt aResourceId, CEikMenuPane* aMenuPane) + { + ASSERT( aMenuPane ); + // Confirm app is running properly (needed atleast now) + if ( !Document()->IsLaunched() ) + { + // If not, hide everything and return + TInt amountOfItems = aMenuPane->NumberOfItemsInPane(); + if ( amountOfItems ) + { + aMenuPane->DeleteBetweenMenuItems( 0, amountOfItems-1 ); + } + return; + } + switch (aResourceId) + { + case R_MSGMAILEDITOR_OPTIONS_MENU1: + // FALLTHROUGH + case R_MSGMAILEDITOR_CONTEXT_MENUPANE: + + if ( Document()->MailCRHandler()->MailInsertToolBar() ) + { + aMenuPane->SetItemDimmed( + EMsgMailEditorCmdInsertMenu, EFalse ); + } + else + { + aMenuPane->SetItemDimmed( + EMsgMailEditorCmdInsertSubMenu, EFalse ); + } + break; + case R_MSGMAILEDITOR_OPTIONS_MENU2: + // Remove attachment option if no attachments + aMenuPane->SetItemDimmed( + EMsgMailEditorCmdAttachments, + (Document()->AttachmentModel().NumberOfItems() <= 0)); + break; + case R_SEND_OPTIONS_MENU: + // FALLTHROUGH + case R_MSGMAILEDITOR_OPTIONS_MENU3: + if (!(iCommonFlags & EHelpSupported)) + { + aMenuPane->DeleteMenuItem(EAknCmdHelp); + } + break; + case R_MSGMAILEDITOR_INSERT_MENU: + aMenuPane->SetItemDimmed( + EMsgMailEditorCmdInsertTemplate, + EFalse ); + break; + case R_MSGMAILEDITOR_ZOOM_SUBMENU: + { + TInt zoomLevel = KErrGeneral; + iMsgEditorAppUiExtension-> + iSettingCachePlugin.GetValue( KAknLocalZoomLayoutSwitch, zoomLevel ); + switch ( zoomLevel ) + { + case EAknUiZoomAutomatic: + aMenuPane->SetItemButtonState( EMsgDispSizeAutomatic, + EEikMenuItemSymbolOn ); + break; + case EAknUiZoomNormal: + aMenuPane->SetItemButtonState( EMsgDispSizeNormal, + EEikMenuItemSymbolOn ); + break; + case EAknUiZoomSmall: + aMenuPane->SetItemButtonState( EMsgDispSizeSmall, + EEikMenuItemSymbolOn ); + break; + case EAknUiZoomLarge: + aMenuPane->SetItemButtonState( EMsgDispSizeLarge, + EEikMenuItemSymbolOn ); + break; + default: + ASSERT(0); + break; + } + } + break; + default: + break; + } + } + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::::EditorObserver +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::EditorObserver( + TMsgEditorObserverFunc aFunc, + TAny* aArg1, + TAny* aArg2, + TAny* aArg3 ) + { + TRAP_IGNORE( EditorObserverL(aFunc, aArg1, aArg2, aArg3) ); + } + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::HandleKeyEventL() +// Handles received key events +// ----------------------------------------------------------------------------- +// +TKeyResponse CMsgMailEditorAppUi::HandleKeyEventL( + const TKeyEvent& aKeyEvent,TEventCode aType) + { + // still launching application + if (!Document()->IsLaunched()) + { + return EKeyWasConsumed; + } + TKeyResponse keyResp = CMsgEditorAppUi::HandleKeyEventL( + aKeyEvent, aType); + if (iView) + { + // By befault the send key is not functional when dialogs or menus + // are displaying. + if (!IsDisplayingMenuOrDialog()) + { + if (aKeyEvent.iCode == EKeyPhoneSend) + { + if ( AreAddressFieldsEmptyL() ) + { + DoAddRecipientL(); + } + else + { + DoSendMessageL(); + } + keyResp = EKeyWasConsumed; + } + } + if ( aKeyEvent.iCode == EKeyEnter ) + { + HandleEnterKeyL(); + keyResp = EKeyWasConsumed; + } + + switch (aKeyEvent.iScanCode) + { + case EStdKeyUpArrow: + case EStdKeyDownArrow: + { + if( aType == EEventKeyUp && + SpecialScrolling( aKeyEvent.iScanCode ) ) + { + keyResp = EKeyWasConsumed; + break; + } + // FALLTHROUGH + } + case EStdKeyLeftArrow: + case EStdKeyRightArrow: + case EStdKeyDevice0: // Options menu + case EStdKeyDevice1: // Done key + case EStdKeyDevice2: // Ok + case EStdKeyDevice3: // Ok + case EStdKeyRightShift: // Shift + case EStdKeyApplication0: // Task switching + break; + default: + { + //something is written to header or to body + if (aType == EEventKeyUp) + { + Document()->SetChanged(ETrue); + UpdateMessageSizeL(); + } + break; + } + } + } + return keyResp; + } + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::HandleCommandL(TInt aCommand) +// Processes menu selections +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::HandleCommandL(TInt aCommand) + { + MAIL_ALLOC_TEST( DoHandleCommandL( aCommand ) ); + } + + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoMsgSaveExitL() +// Because this method is inherited from MsgEditor method signature is leaving, +// but leaves are really trapped to ensure that exiting succeeds always. +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoMsgSaveExitL() + { + LOG( "CMsgMailEditorAppUi::DoMsgSaveExit" ); + +#ifdef _DEBUG + TRAPD( err, PrepereToExitL() ); + LOG1( "CMsgMailEditorAppUi::DoMsgSaveExit @ err:%d", err ); +#else + TRAP_IGNORE( PrepereToExitL() ); +#endif + + Exit(); + } + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::PrepereToExitL() +// Called by DoMsgSaveExit +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::PrepereToExitL() + { + LOG( "CMsgMailEditorAppUi::PrepereToExitL" ); + CMsgMailEditorDocument* doc = Document(); + + // Make sure that possibly running asynchronous operations are canceled. + // If their progress note isn't closed before actual destruction, then it + // will cause an access violation. + iLaunchOp->Cancel(); + iSendOp->Cancel(); + if ( iFetchFileOp ) + { + iFetchFileOp->Cancel(); + } + + LOG( "PrepereToExitL, operations cancelled" ); + + // check that document is launched and view has been created + if (doc->IsLaunched() && iView ) + { + LOG( "PrepereToExitL, has been fully launched" ); + if (IsEmptyL()) + { + LOG( "PrepereToExitL, calling DeleteCurrentEntryL" ); + DeleteCurrentEntryL(); + LOG( "PrepereToExitL, DeleteCurrentEntryL returned" ); + return; + } + + // save the document if it has been changed or if it is a new message + if (doc->HasChanged() || !doc->CurrentEntry().Entry().Visible() || + iView->IsAnyControlModified()) + { + LOG( "PrepereToExitL, check app shutter" ); + // Do this some time before starting the active sheduler + // Restarting the active scheduler will stop the app shutter, + // so record if an app is running a shutter + CAknAppUi* shuttingApp = CAknEnv::AppWithShutterRunning(); + + TBool isVisible(Document()->CurrentEntry().Entry().Visible()); + LOG( "PrepereToExitL, start wait note" ); + StartWaitNoteLC( isVisible ? + R_WAIT_SAVE_NOTE : + R_WAIT_SAVE_NEW_NOTE, + !isVisible ); + + LOG( "PrepereToExitL, saving message" ); + MsgSaveL( EFalse ); + LOG( "PrepereToExitL, saving finished" ); + CleanupStack::PopAndDestroy(); // CSI: 12 # StartWaitNoteLC + + if (shuttingApp) + { + shuttingApp->RunAppShutter(); + } + } + } + } + +// ----------------------------------------------------------------------------- +// Checks addresses of all recipients +// ----------------------------------------------------------------------------- +TBool CMsgMailEditorAppUi::CheckRecipientsL(TBool aHighlight) + { + TBool result(ETrue); + CMsgAddressControl* addressField = AddressControl(EMsgComponentIdTo); + if (addressField) + { + CheckRecipientsInFieldL(addressField, aHighlight, result); + } + + if ( result ) + { + addressField = AddressControl(EMsgComponentIdCc); + if (addressField) + { + CheckRecipientsInFieldL(addressField, aHighlight, result); + } + } + + if ( result ) + { + addressField = AddressControl(EMsgComponentIdBcc); + if (addressField) + { + CheckRecipientsInFieldL(addressField, aHighlight, result); + } + } + + return result; + } + +// ----------------------------------------------------------------------------- +// Checks addresses of all recipients in given field +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::CheckRecipientsInFieldL( + CMsgAddressControl* aAddressField, TBool& aHighLight, TBool& aResult) + { + ASSERT( aAddressField ); + CAknInputBlock::NewLC(); // block key events + aResult = ETrue; + + CMsgRecipientArray& recs = *aAddressField->GetRecipientsL(); + TInt count(recs.Count()); + + for (TInt i = 0; i < count; i++) + { + if (aResult) + { + HBufC* address = recs.At(i)->Address(); + + if ( IsValidAddress(*address) ) + { + recs.At(i)->SetValidated(ETrue); + } + + else // Not valid email address , Search from Phonebook + { + InitPhoneBookL(); + //approx 3 recipients + CMsgRecipientArray* rcptArray = + new (ELeave) CArrayPtrFlat(3); // CSI: 47 # See a comment above. + CleanupStack::PushL( rcptArray ); + if ( iCheckNames->FindAndCheckByNameL( + *address, CMsgCheckNames::EMsgTypeMail, *rcptArray, -1 ) ) //-1 add + { + LOG( "CMsgMailEditorAppUi::CheckRecipientsInFieldL" ); + } + + const TInt contacts(rcptArray->Count()); + + if ( contacts > 0) + { + // Validate addresses found from phonebook + TInt index; + for (index = 0; index < contacts; ++index) + { + HBufC* rcptAddress = rcptArray->At(index)->Address(); + if ( !IsValidAddress(*rcptAddress) ) + { + aResult = EFalse; + ShowIncorrectAddressErrorL( + *(rcptArray->At(index)->Name()), + *rcptAddress); + + // highlight only first invalid address + if (!aHighLight) + { + SearchUnverifiedStringL( + *address, aAddressField); + aAddressField->HighlightUnverifiedStringL(); + aHighLight = ETrue; + } + + } + else + { + // Valid address from phonebook + rcptArray->At(index)->SetValidated(ETrue); + rcptArray->At(index)->SetVerified(ETrue); + } + } + + // replace array only if all addresses were valid + if ( aResult && contacts > 0) + { + // Replace alias text and set flags + recs.At(i)->SetNameL( *rcptArray->At(0)->Name() ); + recs.At(i)->SetAddressL( + *rcptArray->At(0)->Address() ); + recs.At(i)->SetValidated(ETrue); + recs.At(i)->SetVerified(ETrue); + + // ownership not changed so delete + delete rcptArray->At( 0 ); + rcptArray->Delete( 0 ); + + while ( rcptArray->Count() ) + { + //Add the selected address items + i++; + count++; + // takes ownership + recs.InsertL( i, rcptArray->At( 0 )); + rcptArray->Delete( 0 ); + } + } + + } + else // incorrect address + { + aResult = EFalse; + ShowIncorrectAddressErrorL(*(recs.At(i)->Name()), + *address); + if (!aHighLight) // highlight only first invalid address + { + SearchUnverifiedStringL( *address, aAddressField); + aAddressField->HighlightUnverifiedStringL(); + aHighLight = ETrue; + } + + } + CleanupStack::PopAndDestroy( rcptArray ); + } + } + } + + if (aResult) + { + // refresh addresscontrol + User::LeaveIfError( aAddressField->RefreshL( recs )); + } + CleanupStack::PopAndDestroy(); // CSI: 12 # CAknInputBlocker + } + +// ----------------------------------------------------------------------------- +// Show invalid address error note +// ----------------------------------------------------------------------------- +void CMsgMailEditorAppUi::ShowIncorrectAddressErrorL(const TDesC& aTitle, + const TDesC& aAddress) const + { + HBufC* stringholder = NULL; + + if (aTitle.Length()) + { + // 2 for title & address + CDesCArrayFlat* strings = new(ELeave) CDesCArrayFlat(2); // CSI: 47 # See a comment above. + CleanupStack::PushL( strings ); + strings->AppendL(aAddress); + strings->AppendL(aTitle); + stringholder = StringLoader::LoadL( + R_MAIL_EDITOR_INCORRECT_ADDRESS, *strings, iEikonEnv); + CleanupStack::PopAndDestroy( strings ); // strings + CleanupStack::PushL(stringholder); + } + else + { + stringholder = StringLoader::LoadLC( + R_MAIL_EDITOR_INCORRECT_ADDRESS_NO_ALIAS, + aAddress, iEikonEnv ); + } + + // This is a waiting dialog + CAknInformationNote* note = new(ELeave) CAknInformationNote(ETrue); + note->ExecuteLD(*stringholder); + CleanupStack::PopAndDestroy( stringholder ); // stringholder + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoSendMessageL() +// Saves message to outbox and tries to send it immediately, +// if Sending schedule in Send options is +// CMsgMailPreferences::EMsgMailSchedulingNow. +// ---------------------------------------------------------------------------- +void CMsgMailEditorAppUi::DoSendMessageL() + { + CMsgMailEditorDocument* doc = Document(); + UnlockEntry(); + + // Force FEP commit the current word + BodyControl()->SetFocus( EFalse ); + iCoeEnv->SyncNotifyFocusObserversOfChangeInFocus(); + + // check that recipients are valid + TBool highlight( EFalse ); + if ( CheckRecipientsL( highlight ) ) + { + DoRemoveDuplicatesL(); + + iSendOp->StartOp( *this ); + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DelegateSaveMsgL() +// called from send operation +// ---------------------------------------------------------------------------- +void CMsgMailEditorAppUi::DelegateSaveMsgL() + { + MsgSaveL( EFalse ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DelegateMoveMsgToOutboxL() +// called from send operation +// ---------------------------------------------------------------------------- +TMsvId CMsgMailEditorAppUi::DelegateMoveMsgToOutboxL() + { + return MoveMessageEntryL( KMsvGlobalOutBoxIndexEntryId ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::HandleOpCompleted() +// ---------------------------------------------------------------------------- +void CMsgMailEditorAppUi::HandleOpCompleted( + const CMsgMailBaseOp& aOp, + TInt aResult ) + { + LOG( "CMsgMailEditorAppUi::HandleOpCompleted" ); + if ( &aOp == iSendOp ) + { + LOG1( "HandleOpCompleted, send op @ aResult:%d", aResult ); + if ( aResult == KErrNone || aResult == KErrNoMemory ) + { + Exit( EAknSoftkeyBack ); + } + // this is a special error case - mailbox wasn't found + else if ( aResult == KErrNotFound ) + { + //Try to step back + //Trapped to avoid possible problems in operation side + //and to keep function as non-leaving. + TRAPD(err, DoBackstepL() ); + + //DoBackStep can leave with KLeaveExit and since it call is trapped + //mail editor isn't closed like it should. That is why we have to make additional + //call to Exit(). + + if(err == KLeaveExit) + { + Exit( EAknSoftkeyBack ); + } + + + } + } + if ( &aOp == iFetchFileOp ) + { + LOG1( "HandleOpCompleted, fetch file op @ aResult:%d", aResult ); + // try to update message size and lock the entry + TRAP_IGNORE( LockEntryL() ); + if ( aResult == KErrNone ) + { + TRAP_IGNORE( HandleAttaAddedL() ); + } + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::HandleAttaAddedL() +// ---------------------------------------------------------------------------- +void CMsgMailEditorAppUi::HandleAttaAddedL() + { + if ( iAttachmentDlg ) + { + iAttachmentDlg->ItemAddedL(); + } + else + { + UpdateMessageSizeL(); + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::UpdateHeaderVisibilityL() +// ---------------------------------------------------------------------------- +void CMsgMailEditorAppUi::UpdateHeaderVisibilityL( + RPointerArray& aHeaders) + { + ASSERT( iMailEditorHeader ); + iMailEditorHeader->UpdateHeaderVisibilityL( aHeaders ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::UpdatePriorityIndicatorL() +// ---------------------------------------------------------------------------- +void CMsgMailEditorAppUi::UpdatePriorityIndicatorL() + { + TMsvId service; + TMsvEntry entry; + User::LeaveIfError( + Document()->Session().GetEntry( iMessageID, service, entry ) ); + iNaviPaneUtils->SetPriorityIndicator( entry.Priority() ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoSendOptionsL() +// ---------------------------------------------------------------------------- +void CMsgMailEditorAppUi::DoSendOptionsL() + { + // Enable dialer + SetDialerEnabled( ETrue ); + UnlockEntry(); + CMsgMailOptionsDlg* sendOptionsDlg + = CMsgMailOptionsDlg::NewL( + Document(), (iCommonFlags & EHelpSupported) ); + sendOptionsDlg->SetMopParent(this); + +#ifdef RD_SCALABLE_UI_V2 + //Hide toolbar + if ( PopupToolbar() ) + { + CAknToolbarExtension* extension = PopupToolbar()->ToolbarExtension(); + extension->SetShown( EFalse ); + DoHideToolbar( ETrue ); + } + +#endif // RD_SCALABLE_UI_V2 + + if (sendOptionsDlg->ExecuteLD(R_MAIL_EDITOR_SEND_OPTIONS)) + { + // exit was chosen in dialog + CAknAppUi::ProcessCommandL( EAknCmdExit ); + } + +#ifdef RD_SCALABLE_UI_V2 + //Show toolbar + if ( PopupToolbar() ) + { + DoHideToolbar( EFalse ); + } +#endif // RD_SCALABLE_UI_V2 + + ASSERT( iMailEditorHeader ); + iMailEditorHeader->UpdateReplyToControlL(); + + if ( Document()->MailCRHandler()->MailEncodingSetting() ) + { + DoCheckEncodingL(); + } + + LockEntryL(); + UpdatePriorityIndicatorL(); + // Disable dialer + SetDialerEnabled( EFalse ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::SetSubjectL() +// Sets subject text from CImHeader. +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::SetSubjectL + (const TDesC& aText) const //in: subject from CImHeader + { + CMsgExpandableControl* subjectControl = SubjectControl(); + if (subjectControl) + { + CEikRichTextEditor& subject = subjectControl->Editor(); + subject.SetTextL(&aText); + subject.SetCursorPosL(subject.TextLength(), EFalse); + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoHidetoolbar( const TBool aHide ) +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoHideToolbar( const TBool aHide ) + { + if ( PopupToolbar() ) + { +#ifdef RD_SCALABLE_UI_V2 + if ( AknLayoutUtils::PenEnabled() ) + { + PopupToolbar()->HideItemsAndDrawOnlyBackground( aHide ); + } +#endif // RD_SCALABLE_UI_V2 + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoShowSelectionListL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoShowSelectionListL() + { + TInt selection( 0 ); + + CAknListQueryDialog* dlg = new ( ELeave ) CAknListQueryDialog( &selection ); + dlg->PrepareLC( R_MAILEDITOR_INSERT_SELECTIONLIST ); + + if ( dlg->RunLD() ) + { + TInt commandId( EMsgMailFirstFreeCmdId ); + switch( selection ) + { + case 0: + commandId = EMsgMailEditorCmdInsertImage; + break; + case 1: + commandId = EMsgMailEditorCmdInsertVideo; + break; + case 2: // CSI: 47 # switch case + commandId = EMsgMailEditorCmdInsertAudio; + break; + case 3: // CSI: 47 # switch case + commandId = EMsgMailEditorCmdInsertNote; + break; + case 4: // CSI: 47 # switch case + commandId = EMsgMailEditorCmdInsertTemplate; + break; +#ifdef EMAIL_PRESENTATION_SUPPORT + case 5: // CSI: 47 # switch case + commandId = EMsgMailEditorCmdInsertPresentation; + break; + case 6: // CSI: 47 # switch case + commandId = EMsgMailEditorCmdInsertOther; + break; +#else + case 5: // CSI: 47 # switch case + commandId = EMsgMailEditorCmdInsertOther; + break; +#endif //EMAIL_PRESENTATION_SUPPORT + } + + HandleCommandL( commandId ); + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoShowExtensionToolBar() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoShowExtensionToolBar() + { + if ( PopupToolbar() ) + { +#ifdef RD_SCALABLE_UI_V2 + if ( AknLayoutUtils::PenEnabled() ) + { + CAknToolbarExtension* extension = PopupToolbar()->ToolbarExtension(); + extension->SetShown( ETrue ); + } +#endif // RD_SCALABLE_UI_V2 + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoShowToolBarOtherL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoShowToolBarOtherL() + { + TInt selection( 0 ); + + CAknListQueryDialog* dlg = + new ( ELeave ) CAknListQueryDialog( &selection ); + + if(!AknLayoutUtils::PenEnabled()) + { //For non-touch devices + dlg->PrepareLC(R_MAILEDITOR_TOOLBAR_CHOICELIST); + + if ( dlg->RunLD() ) + { + TInt command; + // See r_maileditor_toolbar_choicelist_items + command = ( selection == 0 ) ? + EMsgMailEditorCmdInsertNote : + EMsgMailEditorCmdInsertOther; + + DoFetchFileL(command); + } + } +#ifdef RD_SCALABLE_UI_V2 + //For touch devices toolbar and submenus are different. + else + { + dlg->PrepareLC( R_MAILEDITOR_TOOLBAR_TOUCH_CHOICELIST ); + + if ( dlg->RunLD() ) + { + // See r_maileditor_toolbar_choicelist_touch_items. + //Order of this switch-case is based on + //that resource array. + switch(selection) + { + case 0: + HandleCommandL( EMsgMailEditorCmdInsertTemplate ); + break; + case 1: + HandleCommandL( EMsgMailEditorCmdInsertTemplateNote ); + break; + case 2: // CSI: 47 # See a comment above. + DoFetchFileL(EMsgMailEditorCmdInsertNote); + break; +#ifdef EMAIL_PRESENTATION_SUPPORT + case 3: // CSI: 47 # See a comment above. + HandleCommandL( EMsgMailEditorCmdInsertPresentation ); + break; + case 4: // CSI: 47 # See a comment above. + DoFetchFileL(EMsgMailEditorCmdInsertOther); + break; +#else + case 3: // CSI: 47 # See a comment above. + DoFetchFileL(EMsgMailEditorCmdInsertOther); + break; + +#endif //EMAIL_PRESENTATION_SUPPORT + default: + //unknown selection + ASSERT( 0 ); + return; + } + } + } +#endif //RD_SCALABLE_UI_V2 + } + + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoShowToolBarTextL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoShowToolBarTextL() + { + TInt selection( 0 ); + CAknListQueryDialog* dlg = + new ( ELeave ) CAknListQueryDialog( &selection ); + dlg->PrepareLC( R_MAILEDITOR_TOOLBAR_TEXT_CHOICELIST ); + if ( dlg->RunLD() ) + { + TInt command; + // See r_maileditor_toolbar_choicelist_items + command = ( selection == 0 ) ? + EMsgMailEditorCmdInsertTemplate : + EMsgMailEditorCmdInsertTemplateNote; + HandleCommandL( command ); + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::DoFetchFileL() +// Fetch from other application. +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoFetchFileL( TInt aCommand ) + { + MsgAttachmentUtils::TMsgAttachmentFetchType fetchType; + switch( aCommand ) + { + case EMsgMailEditorCmdInsertImage: + fetchType = MsgAttachmentUtils::EImage; + break; + case EMsgMailEditorCmdInsertAudio: + fetchType = MsgAttachmentUtils::EAudio; + break; + case EMsgMailEditorCmdInsertVideo: + fetchType = MsgAttachmentUtils::EVideo; + break; + case EMsgMailEditorCmdInsertNote: + fetchType = MsgAttachmentUtils::ENote; + break; + case EMsgMailEditorCmdInsertPresentation: + fetchType = MsgAttachmentUtils::ESVG; + break; + + // Falltrough + case EMsgMailEditorCmdInsertOther: + // unknown + fetchType = MsgAttachmentUtils::EUnknown; + break; + default: + // not our command, just return + return; + } + + UnlockEntry(); + + delete iFetchFileOp; // re-instantiate each time with proper fetch type + iFetchFileOp = NULL; + iFetchFileOp = CMsgMailFetchFileOp::NewL( fetchType, *Document() ); + + iFetchFileOp->StartOp( *this ); + } + +// ---------------------------------------------------------------------------- +// TBool CMsgMailEditorAppUi::IsEmptyL() +// Returns ETrue if document contains no data, EFalse otherwise +// ---------------------------------------------------------------------------- +// +TBool CMsgMailEditorAppUi::IsEmptyL() const + { + if (!AreAddressFieldsEmptyL()) + { + return EFalse; + } + + if ( (SubjectControl() && SubjectControl()->TextContent().DocumentLength() > 0) || + BodyControl()->TextContent().DocumentLength() > 0 || + Document()->AttachmentModel().NumberOfItems()) + { + return EFalse; + } + + return ETrue; + } + +// ---------------------------------------------------------------------------- +// CMsgEditorAppUi::HelpContextL +// ---------------------------------------------------------------------------- +// +CArrayFix* CMsgMailEditorAppUi::HelpContextL( ) const + { + CArrayFix* help = + new( ELeave ) CArrayFixFlat( 1 ); + CleanupStack::PushL( help ); + help->AppendL( TCoeHelpContext( TUid::Uid( KUidMsgMailEditor ), + KMAIL_HLP_MAIL_EDITOR() ) ); + CleanupStack::Pop( help ); + return help; + } + +// ---------------------------------------------------------------------------- +// CMsgEditorAppUi::DynInitToolbarL +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DynInitToolbarL( TInt aResourceId, CAknToolbar* aToolbar ) + { + if ( aResourceId == R_MAILEDITOR_TOOLBAR ) + { + //Attachment dialog might have hided this so make sure it is visible + aToolbar->HideItem( EMsgMailEditorCmdInsertText, EFalse, EFalse ); + aToolbar->SetInitialFocusedItem( EMsgMailEditorCmdInsertImage ); + +#ifdef RD_SCALABLE_UI_V2 + if(AknLayoutUtils::PenEnabled()) + { + //Less items shown if touch device. +#ifdef RD_SVGT_IN_MESSAGING + aToolbar->HideItem( EMsgMailEditorCmdInsertPresentation, ETrue, EFalse ); +#endif //RD_SVGT_IN_MESSAGING + aToolbar->HideItem( EMsgMailEditorCmdInsertText, ETrue, EFalse ); + } +#endif //RD_SCALABLE_UI_V2 + + } + } + +// ---------------------------------------------------------------------------- +// CMsgEditorAppUi::OfferToolbarEventL +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::OfferToolbarEventL( TInt aCommand ) + { + if ( PopupToolbar() ) + { +#ifdef RD_SCALABLE_UI_V2 + // These commands create the list over the toolbar + // and reason of that list the toolbar must be hidden. + if ( aCommand == EMsgMailEditorCmdInsertTemplate || + aCommand == EMsgMailEditorCmdInsertOther ) + { + CAknToolbarExtension* extension = PopupToolbar()->ToolbarExtension(); + extension->SetShown( EFalse ); + } + + PopupToolbar()->SetToolbarVisibility( ETrue, EFalse ); + +#else // RD_SCALABLE_UI_V2 + PopupToolbar()->SetToolbarVisibility( EFalse ); +#endif // RD_SCALABLE_UI_V2 + } + + if ( aCommand == EMsgMailEditorCmdInsertOther ) + { + // If user chooses Cancel while selecting template text or note + // DoShowToolBarTextL leaves. This is ok so leave is catched here. + TRAPD(err, DoShowToolBarOtherL() ); + if( err != KErrCancel ) + { + User::LeaveIfError( err ); + } + + } + else if ( aCommand == EMsgMailEditorCmdInsertText ) + { + // If user chooses Cancel while selecting template text or note + // DoShowToolBarTextL leaves. This is ok so leave is catched here. + TRAPD( err, DoShowToolBarTextL() ); + if( err != KErrCancel ) + { + User::LeaveIfError( err ); + } + } + else + { + HandleCommandL( aCommand ); + + } + } + +// ---------------------------------------------------------------------------- +// CMsgEditorAppUi::DoCreateControlsL +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoCreateControlsL() + { + // Create Base view + iView = CMsgEditorView::NewL(*this, CMsgEditorView::EMsgEditorModeNormal); + ASSERT( iView ); + iMailEditorHeader = CMsgMailEditorHeader::NewL( *Document(), *iView ); + } + +// ---------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoAttachmentL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoAttachmentL() + { + HBufC* title = iCoeEnv->AllocReadResourceLC(R_TITLE_ATTACHMENTS); + + CMsgAttachmentModel& attmodel = Document()->AttachmentModel(); + + iAttachmentDlg = CMsgMailViewAttachmentsDlg::NewL(*title, + attmodel, *this, (iCommonFlags & EHelpSupported)); + iAttachmentDlg->SetMopParent(this); + + +#ifdef RD_SCALABLE_UI_V2 + //Hide toolbar + if ( PopupToolbar() ) + { + CAknToolbarExtension* extension = PopupToolbar()->ToolbarExtension(); + extension->SetShown( EFalse ); + DoHideToolbar( ETrue ); + } +#endif // RD_SCALABLE_UI_V2 + + // safe to call LD even as a member variable, since + // framework always takes care of deleting the dialog + if (iAttachmentDlg->ExecuteLD(R_MEB_VIEW_ATTACHMENT_DIALOG)) // CSI: 50 # see comment above + { + iAttachmentDlg = NULL; + // exit was chosen in dialog + CAknAppUi::ProcessCommandL( EAknCmdExit ); + } + else + { + //Attachment dialog has exited. Make sure we are the observers for toolbar + if ( PopupToolbar() ) + { + PopupToolbar()->SetToolbarObserver( this ); +#ifdef RD_SCALABLE_UI_V2 + CAknToolbarExtension* extension = PopupToolbar()->ToolbarExtension(); + extension->SetShown( EFalse ); + DoHideToolbar( EFalse ); +#endif // RD_SCALABLE_UI_V2 + } + + iAttachmentDlg = NULL; + UpdateMessageSizeL(); + } + + CleanupStack::PopAndDestroy( title ); // title + } + +// ---------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoCheckEncodingL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoCheckEncodingL() + { + CMsgMailPreferences& prefs = Document()->SendOptions(); + TUint charsetId = prefs.SendingCharacterSet().iUid; + LOG1( "CMsgMailEditorAppUi::DoCheckEncodingL CharsetId:%08x", charsetId ); + if (charsetId) + { + CCnvCharacterSetConverter* charConv = + CCnvCharacterSetConverter::NewLC(); + + TInt error = charConv->PrepareToConvertToOrFromL( + charsetId, iEikonEnv->FsSession()); + TInt unconverted(0); + if (error == CCnvCharacterSetConverter::EAvailable) + { + // Try to convert body text + CRichText& rtf = BodyControl()->TextContent(); + HBufC* buf = HBufC::NewLC(rtf.DocumentLength()); + TPtr bufPtr = buf->Des(); + rtf.Extract(bufPtr); + + HBufC8* foreing = HBufC8::NewLC(rtf.DocumentLength()); + TPtr8 ptr = foreing->Des(); + error = charConv->ConvertFromUnicode(ptr, *buf, unconverted); + CleanupStack::PopAndDestroy(2, buf); // CSI: 47,12 # buf, foreing + } + // Show note if can't convert to selected character set. + if (error != KErrNone || unconverted > 0) + { + MailUtils::ConfirmationNoteL(R_MAIL_SETTINGS_ENCODE_FALSE_NOTE); + } + + CleanupStack::PopAndDestroy( charConv ); + } + } + +// ---------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoBackstepL() +// Implements backstep functionality +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoBackstepL() + { + CMsgMailEditorDocument* doc = Document(); + + // if document contains no data, message and entry is deleted + if ( IsEmptyL() ) + { + if (doc->CurrentEntry().Entry().Visible()) + { + HBufC* text = iEikonEnv->AllocReadResourceLC( + R_MAIL_EDITOR_MESSAGE_DELETED_TEXT); + // waiting dialog, so it is not left into screen when + // application is exited + CAknInformationNote* note = new(ELeave) CAknInformationNote(ETrue); + note->ExecuteLD(*text); + CleanupStack::PopAndDestroy( text ); // text + } + DeleteAndExitL(); + return; + } + + switch ( ShowCloseQueryL() ) + { + case EMsgCloseDelete: + { + DeleteAndExitL(); + } + case EMsgCloseCancel: + { + return; + } + default: + { + // Normal save + if ( !doc->CurrentEntry().Entry().Visible() || + doc->HasChanged() || + iView->IsAnyControlModified() ) + { + const TBool newMessage( + !doc->CurrentEntry().Entry().Visible() ); + StartWaitNoteLC( newMessage ? + R_WAIT_SAVE_NEW_NOTE : + R_WAIT_SAVE_NOTE, + newMessage ); + + TRAPD( err, MsgSaveL( EFalse ) ); + + CleanupStack::PopAndDestroy(); // CSI: 12 # StartWaitNoteLC + User::LeaveIfError(err); + } + } + } + Exit( EAknSoftkeyBack ); + } + + +// ---------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoAddRecipientL() +// Fetch an address from phonebook +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoAddRecipientL() + { + TMsgControlId uiCompId = + (TMsgControlId)iView->FocusedControl()->ControlId(); + + //Remember original focused control + TMsgControlId uiOriginalCompId = uiCompId; + + // Add recipient into To field if focus is not in address field + if ( !(uiCompId == EMsgComponentIdTo || + uiCompId == EMsgComponentIdCc || + uiCompId == EMsgComponentIdBcc) ) + { + uiCompId = EMsgComponentIdTo; + } + + InitPhoneBookL(); + CMsgRecipientList* recipientList = CMsgRecipientList::NewL(); + CleanupStack::PushL( recipientList ); + + CMsgRecipientArray* recipients = + new (ELeave) CArrayPtrFlat(3); // CSI: 47 # approx 3 + CleanupStack::PushL( recipients ); + +#ifdef RD_SCALABLE_UI_V2 + //Hide toolbar + if ( PopupToolbar() ) + { + CAknToolbarExtension* extension = PopupToolbar()->ToolbarExtension(); + extension->SetShown( EFalse ); + DoHideToolbar( ETrue ); + } +#endif // RD_SCALABLE_UI_V2 + + //multiple entry fetch to get the contact + iCheckNames->FetchRecipientsL( *recipients, CMsgCheckNames::EMsgTypeMail ); + +#ifdef RD_SCALABLE_UI_V2 + DoHideToolbar( EFalse ); +#endif // RD_SCALABLE_UI_V2 + + //contacts now fetched, verify each contact + for ( TInt i(0); i < recipients->Count(); i++ ) + { + CMsgRecipientItem* recipient = (*recipients)[ i ]; + HBufC* name = recipient->Name(); + HBufC* address = recipient->Address(); + + // Don't parse away chars here so this is consistent with + // addresses that user writes "-()" are saved to draft + // but removed when sending + if ( IsValidAddress( *address ) ) + { + // add it to the list of valid addresses + recipient->SetVerified( ( name->Length() > 0 ? ETrue : EFalse ) ); + recipientList->AppendL( recipient ); + } + else + { + ShowIncorrectAddressErrorL( *address, *name ); + } + } + // if valid recipients were selected, add them to control + // and set focus to right component + if ( recipientList->Count() ) + { + //Add to control + AddressControl(uiCompId)->AddRecipientsL( *recipientList ); + + //Set focus + SetFocusAfterAddRecipientL( uiOriginalCompId ); + } + + // recipientList, recipients + CleanupStack::PopAndDestroy( 2, recipientList ); // CSI: 47,12 # See a comment above. + } +// ----------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::AreAddressFieldsEmptyL() +// ----------------------------------------------------------------------------- +// +TBool CMsgMailEditorAppUi::AreAddressFieldsEmptyL() const + { + TBool result( ETrue ); + + CMsgAddressControl* addressField = AddressControl(EMsgComponentIdTo); + if (addressField) + { + CMsgRecipientArray& recs = *addressField->GetRecipientsL(); + if( recs.Count() > 0 ) + { + result = EFalse; + } + } + + addressField = AddressControl(EMsgComponentIdCc); + if (addressField) + { + CMsgRecipientArray& recs = *addressField->GetRecipientsL(); + if( recs.Count() > 0 ) + { + result = EFalse; + } + } + + addressField = AddressControl(EMsgComponentIdBcc); + if (addressField) + { + CMsgRecipientArray& recs = *addressField->GetRecipientsL(); + if( recs.Count() > 0 ) + { + result = EFalse; + } + } + + return result; + } + +// ----------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::UpdateMessageSizeL() +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::UpdateMessageSizeL() + { + //If attachment dialog is visible we don't want to update navipane, + //because dialogs navi pane should be empty. + if(!iAttachmentDlg) + { + TInt docSize = MessageSizeL( ETrue ); // Count also attachments + LOG1( "CMsgMailEditorAppUi::UpdateMessageSizeL:%d", docSize ); + iNaviPaneUtils->SetMessageSizeIndicatorL( docSize ); + + // attachment indicator may be shown in navi pane only if local variation + // flag is enabled (by default disabled in common code). Remove this + // code and SetAttachmentIndicator() method when CR key gets obsolete. + if ( !Document()->MailCRHandler()->MailAttachmentField() ) + { + CMsgAttachmentModel& attModel = Document()->AttachmentModel(); + const TInt attCount( attModel.NumberOfItems() ); + iNaviPaneUtils->SetAttachmentIndicator( attCount > 0 ); + } + } + + } + +// ----------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoMessageInfoL() +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoMessageInfoL() + { + CMsgMailDocument* doc = Document(); + CMsvEntrySelection* sel = new (ELeave) CMsvEntrySelection; + CleanupStack::PushL(sel); + TMsvId id(doc->Entry().Id()); + sel->AppendL(id); + + // save the message so the fields in message info dialog will be up to date + // this is a "hidden" save, so we preserve values of + // preparation and visible flags + const TBool visible(doc->CurrentEntry().Entry().Visible()); + CAknWaitDialog* dlg = new(ELeave) CAknWaitDialog(NULL); + CleanupStack::PushL(dlg); + dlg->PrepareLC(R_MEB_WAIT_NOTE); + HBufC* text = StringLoaderLoadLC( R_WAIT_OPENING ); + dlg->SetTextL(*text); + CleanupStack::PopAndDestroy( text ); // text + dlg->RunLD(); + UnlockEntry(); + MsgSaveL(!visible); + CleanupStack::Pop( dlg ); // dlg + dlg->ProcessFinishedL(); + + TBuf8 infoParams(KMessageInfoEditor); + CMsvSingleOpWatcher* watch=CMsvSingleOpWatcher::NewLC(*doc); + CMsvOperation* op= doc->MtmUi().InvokeAsyncFunctionL( + KMtmUiFunctionMessageInfo, + *sel, + watch->iStatus, + infoParams + ); + // watch owns op before leave can occur + doc->AddSingleOperationL(op, watch); + CleanupStack::Pop( watch ); // watch + LockEntryL(); + + CleanupStack::PopAndDestroy( sel ); // sel + + // this is done, so message will be saved visible, + // when editor is exited + if (!visible) + { + doc->SetChanged(ETrue); + } + } + +// ----------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoAdditionalHeadersL() +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoAdditionalHeadersL() + { + // Cc field + TAdditionalHeaderStatus header_status_cc(EMsgComponentIdCc); + CMsgAddressControl* ccControl = AddressControl(EMsgComponentIdCc); + if (ccControl) + { + header_status_cc.iHasContent = ccControl->Editor().TextLength() > 0; + header_status_cc.iStatus = EHeaderVisible; + } + // Bcc field + TAdditionalHeaderStatus header_status_bcc(EMsgComponentIdBcc); + // Check if bcc field is allowed + if ( Document()->MailCRHandler()->MailAdditionalHeaders() ) + { + CMsgAddressControl* bccControl = AddressControl(EMsgComponentIdBcc); + if (bccControl) + { + header_status_bcc.iHasContent = + bccControl->Editor().TextLength() > 0; + header_status_bcc.iStatus = EHeaderVisible; + } + } + // Subject + TAdditionalHeaderStatus header_status_subject(EMsgComponentIdSubject); + CMsgExpandableControl* subjectControl = SubjectControl(); + if (subjectControl) + { + header_status_subject.iHasContent = + subjectControl->Editor().TextLength() > 0; + header_status_subject.iStatus = EHeaderVisible; + } + + RPointerArray headers; + CleanupClosePushL(headers); + + headers.Append(&header_status_cc); + // Check if bcc field is allowed + if ( Document()->MailCRHandler()->MailAdditionalHeaders() ) + { + headers.Append(&header_status_bcc); + } + headers.Append(&header_status_subject); + + CMsgAddMailHeadersDlg* addHeadersDlg = + CMsgAddMailHeadersDlg::NewLC(headers); + + if( addHeadersDlg->ExecuteDialogL() ) + { + TUint headersvalue(0); + for (TInt index(0); index < headers.Count(); ++index) + { + switch( headers[index]->iHeaderValue ) + { + case EMsgComponentIdCc: + if ( headers[index]->iStatus == EHeaderVisible ) + { + headersvalue += KBit0; + } + break; + case EMsgComponentIdBcc: + if ( headers[index]->iStatus == EHeaderVisible ) + { + headersvalue += KBit1; + } + break; + case EMsgComponentIdSubject: + if ( headers[index]->iStatus == EHeaderVisible ) + { + headersvalue += KBit2; + } + break; + default: + // Unknown header field + ASSERT( 0 ); + } + } + // remember user selection + Document()->MailCRHandler()->SetCRInt( + KCRUidMail,KMailAdditionalHeaderSettings,headersvalue); + + // set headers + UpdateHeaderVisibilityL(headers); + } + CleanupStack::PopAndDestroy(2); // CSI: 47,12 # headers, addHeadersDlg + } + +// ---------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoGetRecipientsL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoGetRecipientsL() + { + CImHeader& header = Document()->HeaderL(); + CMsgAddressControl* addressField = NULL; + + addressField = AddressControl(EMsgComponentIdTo); + AddRecipientArrayL(addressField, + header.ToRecipients()); + + addressField = AddressControl(EMsgComponentIdCc); + AddRecipientArrayL(addressField, + header.CcRecipients()); + + addressField = AddressControl(EMsgComponentIdBcc); + AddRecipientArrayL(addressField, + header.BccRecipients()); + } + +// ---------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoRemoveDuplicatesL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoRemoveDuplicatesL() + { + // Remove duplicate addresses + CMsgAddressControl* addressField(NULL); + addressField = AddressControl(EMsgComponentIdTo); + RemoveDuplicatesL(addressField); + + addressField = AddressControl(EMsgComponentIdCc); + RemoveDuplicatesL(addressField); + + addressField = AddressControl(EMsgComponentIdBcc); + RemoveDuplicatesL(addressField); + + //After each control is cleaned remove rest duplicates by comparing different controls + RemoveDuplicatesL(AddressControl(EMsgComponentIdTo), AddressControl(EMsgComponentIdCc)); + RemoveDuplicatesL(AddressControl(EMsgComponentIdTo), AddressControl(EMsgComponentIdBcc)); + RemoveDuplicatesL(AddressControl(EMsgComponentIdCc), AddressControl(EMsgComponentIdBcc)); + } + +// ----------------------------------------------------------------------------- +// CMsgEditorAppUi::RemoveDuplicatesL +// +// Compares two address controls and removes duplicate +// address from later one. +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::RemoveDuplicatesL(CMsgAddressControl* aAddressField, + CMsgAddressControl* aLaterAddressField) + { + + //Symbian also removes duplicate addresses (CImHeader::IsRecipientPresent), + //but it ignores BCC field for some reason. + + if(aAddressField && aLaterAddressField) + { + CMsgRecipientArray& recs = *aAddressField->GetRecipientsL(); + CMsgRecipientArray& laterRecs = *aLaterAddressField->GetRecipientsL(); + + TInt laterCount(laterRecs.Count()); + TInt count(recs.Count()); + + for(TInt i=0; iAddress()->FindF(*(laterRecs[j]->Address())) >= 0 ) + { + //Remove duplicate from later control + //and update count of that + delete laterRecs.At(j); + laterRecs.Delete(j); + + laterCount = laterRecs.Count(); + + //Now we can break and move to next item in aAddressField. + //Duplicates in the same row should have been removed earlier. + break; + } + } + } + + aLaterAddressField->RefreshL(laterRecs); + } + + + } + + +// ---------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::DoHandleCommandL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::DoHandleCommandL( TInt aCommand ) + { + //Still launching application. + //IsLaunched() can be true even if iView + //isn't created yet. + if( !Document()->IsLaunched() || !iView ) + { + if ( aCommand != EEikCmdExit ) + { + return; + } + } + + DoFetchFileL( aCommand ); + switch ( aCommand ) + { + case EEikCmdExit: + if( iForceDeleteDocument ) + { + DeleteAndExitL(); + } + else + { + DoMsgSaveExitL(); + } + break; + case EMsgMailEditorCmdSend: + if (AreAddressFieldsEmptyL()) + { + DoAddRecipientL(); + } + else + { + DoSendMessageL(); + } + break; + case EMsgMailEditorCmdSendingOptions: + DoSendOptionsL(); + break; + case EAknSoftkeyClose: + TRAPD(error, DoBackstepL()); + if ( error == KErrDiskFull ) + { + // No memory to save changes + if ( MailUtils::ConfirmationQueryL( + R_QTN_MAIL_CLOSE_NOSAVE, R_MAIL_EDITOR_DELETE_MESSAGE) ) + { + Exit(); + } + } + else + { + User::LeaveIfError( error ); + } + break; + case EMsgMailEditorCmdMskAddRecipient: + if(!AreAddressFieldsEmptyL() && !AllAddressValidL()) + { + CheckRecipientsL(EFalse); + } + else + { + DoAddRecipientL(); + } + break; + case EMsgMailEditorCmdAddRecipient: + DoAddRecipientL(); + break; + case EMsgMailEditorCmdAttachments: + DoAttachmentL(); + break; + case EMsgMailEditorCmdInsertMenu: + DoShowSelectionListL(); + break; + case EMsgMailEditorCmdInsertTemplate: + // If user chooses Cancel while selecting template text + // DoShowToolBarTextL leaves. This is ok so leave is catched here. + TRAPD(err, InsertTemplateL() ); + if( err != KErrCancel ) + { + User::LeaveIfError( err ); + } + UpdateMessageSizeL(); + break; + case EMsgMailEditorCmdInsertTemplateNote: + User::LeaveIfError( InsertTextMemoL() ); + UpdateMessageSizeL(); + break; + case EMsgMailEditorCmdMessageInfo: + DoMessageInfoL(); + break; + case EMsgMailEditorCmdAddHeaders: + DoAdditionalHeadersL(); + break; + // general options: + case EEikCmdEditCut: + iView->FocusedControl()->ClipboardL(EMsgCut); + UpdateMessageSizeL(); + break; + case EEikCmdEditCopy: + iView->FocusedControl()->ClipboardL(EMsgCopy); + break; + case EEikCmdEditPaste: + iView->FocusedControl()->ClipboardL(EMsgPaste); + UpdateMessageSizeL(); + break; + case EMsgMailEditorCmdExpandInsert: + break; + case EAknCmdHelp: + { + if ((iCommonFlags & EHelpSupported)) + { + // Launch help + HlpLauncher::LaunchHelpApplicationL( iEikonEnv->WsSession(), + iEikonEnv->EikAppUi()->AppHelpContextL() ); + } + break; + } + case EMsgDispSizeAutomatic: + // FALLTHROUGH + case EMsgDispSizeLarge: + // FALLTHROUGH + case EMsgDispSizeNormal: + // FALLTHROUGH + case EMsgDispSizeSmall: + HandleLocalZoomChangeL( (TMsgCommonCommands)aCommand ); + break; + default: + CMsgMailAppUi::HandleCommandL(aCommand); + break; + } + } + +// ---------------------------------------------------------------------------- +// void CMsgMailEditorAppUi::EditorObserverL() +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::EditorObserverL( + TMsgEditorObserverFunc aFunc, + TAny* aArg1, + TAny* aArg2, + TAny* /*aArg3*/ ) + { + if ( aFunc == MMsgEditorObserver::EMsgHandleFocusChange ) + { + ASSERT( aArg1 ); + ASSERT( aArg2 ); + + TMsgFocusEvent event = *(static_cast( aArg1 ) ); + TInt controlId = *(static_cast( aArg2 ) ); + + switch( event ) + { + case EMsgFocusMovingFrom: + { + if ( controlId == EMsgComponentIdAttachment ) + { + iNaviPaneUtils->EnableOwnNaviPaneL( EFalse ); + } + + // Set input mode (e.g. number mode)to other address fields too + CMsgAddressControl* ctrl = AddressControl( controlId ); + if ( ctrl ) + { + TInt mode( ctrl->Editor().AknEditorCurrentInputMode() ); + SetInputModeToAddressFields( mode ); + } + }// EMsgFocusMovingFrom + break; + case EMsgFocusMovedTo: + { + CheckFocusForMskL( controlId ); + if ( controlId == EMsgComponentIdAttachment ) + { + iNaviPaneUtils->EnableOwnNaviPaneL( ETrue ); + } + } // EMsgFocusMovingTo + break; + } // switch + } +#ifdef RD_SCALABLE_UI_V2 + else if( aFunc == MMsgEditorObserver::EMsgButtonEvent ) + { + ASSERT( aArg1 ); + + //Get the parameter + CMsgBaseControl* control = static_cast( aArg1 ); + + //Attachment handling is mostly done in pointer event branch. + //Here we tackle situation where focus is not in attachment row + //and the button is pressed. + //Also other button events go this way, but attachment handling + //is a special case. + if ( control && ( control->ControlId() != EMsgComponentIdAttachment || + iFocusedControl != control ) ) + { + //Summon touch functionality + ControlTouchedL( *control ); + } + } + else if( aFunc == MMsgEditorObserver::EMsgControlPointerEvent ) + { + if( aArg1 && aArg2 ) + { + TPointerEvent* event = static_cast( aArg2 ); + CMsgBaseControl* control = static_cast( aArg1 ); + + if ( event->iType == TPointerEvent::EButton1Down ) + { + //This is done to check if control is already focused. + //When attachment row is clicked and it has focus + //attachment dialog is opened. Otherwise row just gains focus. + iFocusedControl = control && control->IsFocused() ? control : NULL; + } + else if ( event->iType == TPointerEvent::EButton1Up ) + { + if( control && iFocusedControl == control && + control->ControlId() == EMsgComponentIdAttachment ) + { + //Summon touch functionality + ControlTouchedL( *control ); + } + } + } + } +#endif + } + +// --------------------------------------------------------------------------- +// CMsgMailEditorAppUi::CheckFocusForMSK +// --------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::CheckFocusForMskL(TInt aControl) + { + + RemoveMSKCommands(); + switch(aControl) + { + case EMsgComponentIdTo: + // FALLTHROUGH + case EMsgComponentIdCc: + // FALLTHROUGH + case EMsgComponentIdBcc: + SetMiddleSoftKeyLabelL(R_QTN_MSK_ADD, + EMsgMailEditorCmdMskAddRecipient); + break; + + case EMsgComponentIdAttachment: + SetMiddleSoftKeyLabelL(R_QTN_MSK_ATTACHMENT, + EMsgMailEditorCmdAttachments); + break; + + default: + //Change msk label back to normal (context sensitive menu icon) + SetMiddleSoftKeyLabelL(R_TEXT_SOFTKEY_OPTION, + EAknSoftkeyContextOptions); + } + + } + +// --------------------------------------------------------------------------- +// CMsgMailEditorAppUi::SetMiddleSoftKeyLabelL +// --------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::SetMiddleSoftKeyLabelL( + const TInt aResourceId, const TInt aCommandId ) + { + CEikButtonGroupContainer* cbaGroup = Cba(); + if ( cbaGroup ) + { + HBufC* middleSKText = StringLoader::LoadLC( aResourceId ); + TPtr mskPtr = middleSKText->Des(); + cbaGroup->AddCommandToStackL( + KMSKControlID, + aCommandId, + mskPtr ); + CleanupStack::PopAndDestroy( middleSKText ); + } + } + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::RemoveMSKCommands +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::RemoveMSKCommands() + { + if ( Cba() ) + { + Cba()->RemoveCommandFromStack( KMSKControlID, + EMsgMailEditorCmdMskAddRecipient); + Cba()->RemoveCommandFromStack( KMSKControlID, + EMsgMailEditorCmdAttachments ); + Cba()->RemoveCommandFromStack( KMSKControlID, + EAknSoftkeyContextOptions ); + } + } + +// ----------------------------------------------------------------------------- +// CMsgEditorAppUi::InitPhoneBookL +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::InitPhoneBookL() + { + // initialize pb + if ( !iCheckNames ) + { + TRAP_IGNORE( iCheckNames = CMsgCheckNames::NewL() ); + } + ASSERT( iCheckNames ); + } + +// ----------------------------------------------------------------------------- +// CMsgEditorAppUi::SearchUnverifiedStringL +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::SearchUnverifiedStringL( + const TDesC& aText, CMsgAddressControl* aControl ) + { + ASSERT( aControl ); + HBufC* buf = NULL; + iView->SetFocus(aControl->ControlId()); + aControl->GetFirstUnverifiedStringL(buf); + while (buf && buf->Compare(aText) != 0) + { + delete buf; + buf = NULL; + aControl->GetNextUnverifiedStringL(buf); + } + delete buf; + buf = NULL; + } + +// ----------------------------------------------------------------------------- +// CMsgEditorAppUi::AllAddressValidL +// ----------------------------------------------------------------------------- +// +TBool CMsgMailEditorAppUi::AllAddressValidL() + { + TInt i(0); + TBool ret(ETrue); + + CMsgAddressControl* addressField = AddressControl(EMsgComponentIdTo); + CMsgRecipientArray* rcpt = addressField->GetRecipientsL(); + + while (i < rcpt->Count() && ret) + { + ret = IsValidAddress (*rcpt->At(i)->Address()); + i++; + } + + if (ret) + { + addressField = AddressControl(EMsgComponentIdCc); + if(addressField) + { + rcpt = addressField->GetRecipientsL(); + i=0; + while (i < rcpt->Count() && ret) + { + ret = IsValidAddress (*rcpt->At(i)->Address()); + i++; + } + } + } + + if (ret) + { + addressField = AddressControl(EMsgComponentIdBcc); + + if(addressField) + { + rcpt = addressField->GetRecipientsL(); + i=0; + while (i < rcpt->Count() && ret) + { + ret = IsValidAddress (*rcpt->At(i)->Address()); + i++; + } + } + } + + return ret; + } + +// ----------------------------------------------------------------------------- +// CMsgEditorAppUi::SetFocusToFirstFreeFieldL +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::SetFocusToFirstFreeFieldL() + { + // Set focus at begining of the message when replying + if ( Document()->IsReplyMessage() ) + { + iView->SetFocus(EMsgComponentIdBody); + } + // set focus at first free field + else + { + if(AddressControl(EMsgComponentIdTo)) + { + if (!AddressControl(EMsgComponentIdTo)->Editor().TextLength()) + { + iView->SetFocus(EMsgComponentIdTo); + return; + } + } + if (AddressControl(EMsgComponentIdCc)) + { + if (!AddressControl(EMsgComponentIdCc)->Editor().TextLength()) + { + iView->SetFocus(EMsgComponentIdCc); + return; + } + } + if (AddressControl(EMsgComponentIdBcc)) + { + if (!AddressControl(EMsgComponentIdBcc)->Editor().TextLength()) + { + iView->SetFocus(EMsgComponentIdBcc); + return; + } + } + if (SubjectControl()) + { + if (!SubjectControl()->Editor().TextLength()) + { + iView->SetFocus(EMsgComponentIdSubject); + return; + } + } + iView->SetFocus(EMsgComponentIdBody); + CEikRichTextEditor& editor = BodyControl()->Editor(); + editor.SetCursorPosL(editor.TextLength(), EFalse); + } + } + +// ----------------------------------------------------------------------------- +// CMsgEditorAppUi::ShowSelectedMailboxL +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::ShowSelectedMailboxL() + { + const CMsgMailEditorDocument* doc = Document(); + CMsvEntry* rootEntry = doc->Session().GetEntryL(KMsvRootIndexEntryId); + CleanupStack::PushL(rootEntry); + + TInt noteResource(0); + TInt64 flags = MImumInHealthServices::EFlagSetHealthyReceiving; + + noteResource = R_MAIL_EDITOR_MAILBOX_IN_USE_TEXT; + + + // if more than one box defined, show its name + if ( Document()->GetHealthyMailboxListL( flags ).Count() > 1 ) + { + const TMsvId service(doc->SendOptions().ServiceId()); + TMsvSelectionOrdering ordering(rootEntry->SortType()); + ordering.SetShowInvisibleEntries(ETrue); + rootEntry->SetSortTypeL(ordering); + const TMsvEntry child = rootEntry->ChildDataL(service); + HBufC* stringholder = StringLoader::LoadLC( + noteResource, child.iDetails, iEikonEnv ); + + CAknInformationNote* note = new(ELeave) CAknInformationNote(ETrue); + note->ExecuteLD(*stringholder); + CleanupStack::PopAndDestroy( stringholder ); // stringholder + } + CleanupStack::PopAndDestroy( rootEntry ); // rootEntry + } + +// ----------------------------------------------------------------------------- +// CMsgEditorAppUi::RemoveDuplicatesL +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::RemoveDuplicatesL(CMsgAddressControl* aAddressField) + { + if ( aAddressField ) + { + CMsgRecipientArray& recs = *aAddressField->GetRecipientsL(); + TInt count(recs.Count()); + for (TInt i=0; i < count; i++) + { + for (TInt j = i + 1; j < count; ) + { + if (recs[i]->Address()->Compare(*(recs[j]->Address())) == 0) + { + if (recs[i]->Name()->Length()) + { + delete recs.At(j); + recs.Delete(j); + } + else + { + delete recs.At(i); + recs.Delete(i); + } + count = recs.Count(); + } + else + { + // increase j if something wasn't deleted. if j is + // increased when nothing is deleted, elements are skipped + j++; + } + } + } + aAddressField->RefreshL(recs); + } + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::MopSupplyObject(TTypeUid aId) +// Returns a pointer to popup menu. +// ---------------------------------------------------------------------------- +// +TTypeUid::Ptr CMsgMailEditorAppUi::MopSupplyObject(TTypeUid aId) + { + return SupplyMopObject(aId); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::StopWaitNote +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::StopWaitNote() + { + delete iWaitNote; + iWaitNote = NULL; + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::StartWaitNoteLC +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::StartWaitNoteLC( + TInt aStringResourceId, TBool aDelayOff ) + { + StartWaitNoteLC( aStringResourceId, aDelayOff, R_MEB_WAIT_NOTE ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::StartWaitNoteLC +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::StartWaitNoteLC( + TInt aStringResourceId, TBool aDelayOff, TInt aResouceID ) + { + StopWaitNote(); + iWaitNote = new(ELeave) CAknWaitDialog( + reinterpret_cast (&iWaitNote), aDelayOff ); + CleanupStack::PushL(TCleanupItem(CleanupWaitDialog, (TAny**)&iWaitNote)); + iWaitNote->PrepareLC( aResouceID ); + HBufC* text = StringLoaderLoadLC( aStringResourceId ); + iWaitNote->SetTextL(*text); + CleanupStack::PopAndDestroy( text ); // text + + // safe to call LD even as a member variable, since sets itself to NULL when deleting + iWaitNote->RunLD(); // CSI: 50 # see comment above + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::StringLoaderLoadLC +// ---------------------------------------------------------------------------- +// +HBufC* CMsgMailEditorAppUi::StringLoaderLoadLC( TInt aTextResource ) + { + return StringLoader::LoadLC( aTextResource, iEikonEnv ); + } + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::SpecialScrolling +// ----------------------------------------------------------------------------- +// +TBool CMsgMailEditorAppUi::SpecialScrolling( TUint aKeyCode ) + { + TBool keyConsumed( EFalse ); + if ( aKeyCode == EStdKeyUpArrow || aKeyCode == EStdKeyDownArrow ) + { + CMsgBaseControl* focusedControl = iView->FocusedControl(); + if ( focusedControl ) + { + TInt focused( focusedControl->ControlId() ); + if ( aKeyCode == EStdKeyDownArrow ) + { + // Focus on Reply-to field?? + if ( focused == EMailEditorControlReplyTo ) + { + // jump directly to atta control + LOG( "CMsgMailEditorAppUi::SpecialScrolling - Down" ); + RotateFocus( ETrue, EMailEditorControlReplyTo ); + keyConsumed = ETrue; + } + } + else + { + // scroll up, and focus is top of the body part + if ( focused == EMailEditorControlReplyTo ) + { + LOG( "CMsgMailEditorAppUi::SpecialScrolling - Up" ); + RotateFocus( EFalse, EMailEditorControlReplyTo ); + keyConsumed = ETrue; + } + } + } + } + + return keyConsumed; + } + +// ----------------------------------------------------------------------------- +// CMsgMailEditorAppUi::RotateFocus +// ----------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::RotateFocus( TBool aDirection, TInt aCurrentFocus ) + { + // Mail editor control order + const TInt TControls[] = + { + EMsgComponentIdTo, + EMsgComponentIdCc, + EMsgComponentIdBcc, + EMailEditorControlReplyTo, + EMsgComponentIdSubject, + EMsgComponentIdAttachment, + EMsgComponentIdBody + }; + + const TInt count( sizeof(TControls) / sizeof(TInt) ); + TInt index(0); // index starts from 0 + for(; index= 0 && index < count, User::Invariant() ); + + if ( aCurrentFocus == TControls[ index ] ) // CSI: 2 # This is checked above in the assert macro. + { + // locate currently focused item + break; + } + } + CMsgBaseControl* control(NULL); + while ( !control ) + { + // Then find next control for current position + aDirection ? ++index : --index; + ASSERT( index >= 0 && index < count ); + control = iView->ControlById( TControls[ index ] ); // CSI: 2 # This is checked above in the assert macro. + } + + LOG( "CMsgMailEditorAppUi::RotateFocus" ); + iView->SetFocus( control->ControlId() ); + } + +// ---------------------------------------------------------------------------- +// CMsgMailEditorAppUi::AddRecipientArrayL +// ---------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::AddRecipientArrayL(CMsgAddressControl* aControl, + const CDesCArray& aArray) + { + const TInt count(aArray.Count()); + if ( aControl && count>0 ) + { + CMsgRecipientList* recipientList = CMsgRecipientList::NewL(); + CleanupStack::PushL(recipientList); + + for ( TInt index=0; indexDes().Trim(); + + TInt found(KErrNone); + TPtrC16 aliasPtr = msgField.GetValidAlias( + aArray[index], found ); + HBufC* alias; + if ( found == KErrNone ) + { + alias = aliasPtr.AllocLC(); + aliasFound = ETrue; + } + else + { + alias = KNullDesC().AllocLC(); + } + + CMsgRecipientItem* reci = + CMsgRecipientItem::NewLC(*alias, *address); + + //verified is set according to alias found status + //as editorbase uses the alias only if verified == ETrue + reci->SetVerified( aliasFound ); + + recipientList->AppendL(reci); + // Ownership transferred just pop + CleanupStack::Pop( reci ); // reci + CleanupStack::PopAndDestroy( 2, address ); // CSI: 47,12 # alias, address + } + + if ( recipientList->Count() ) + { + aControl->AddRecipientsL(*recipientList); + } + CleanupStack::PopAndDestroy( recipientList ); // recipientList + } + } + +//--------------------------------------------------------------------------- +// CMsgMailEditorAppUi::CheckGlobalReplyToSettingL() +// Gets mailbox reply to address from smtp settings +// and adds it to mail header if address is different +// than address of mailbox. Returns ETrue if new value is +// set. +//--------------------------------------------------------------------------- +TBool CMsgMailEditorAppUi::CheckGlobalReplyToSettingL() + { + TBool retVal = EFalse; + + CMsgMailEditorDocument& doc = *Document(); + + //Get smtp account and load smtp settings + CEmailAccounts* smtpAccount = CEmailAccounts::NewLC(); + CImSmtpSettings* smtpSet=new(ELeave)CImSmtpSettings(); + CleanupStack::PushL(smtpSet); + const TMsvId smtpSetId = doc.CurrentEntry().Entry().iServiceId; + + TSmtpAccount accountParams; + smtpAccount->GetSmtpAccountL( smtpSetId, accountParams ); + smtpAccount->LoadSmtpSettingsL(accountParams, *smtpSet); + + //Check that if reply to address is same as mailbox address + //do not add "reply to" field for header. Otherwise "reply to" field + //would be always visible. + if(smtpSet->ReplyToAddress().Compare(smtpSet->EmailAddress() ) != 0) + { + CImHeader& header = doc.HeaderL(); + + header.SetReplyToL( smtpSet->ReplyToAddress() ); + + ASSERT( iMailEditorHeader ); + iMailEditorHeader->UpdateReplyToControlL(); + + retVal = ETrue; + } + else + { + retVal = EFalse; + } + + CleanupStack::PopAndDestroy(2, smtpAccount); // CSI: 47,12 # smtpSet + + return retVal; + } + +// --------------------------------------------------------- +// CMsgMailEditorAppUi::SetInputModeToAddressFields +// --------------------------------------------------------- +void CMsgMailEditorAppUi::SetInputModeToAddressFields( TInt aInputMode ) + { + CMsgAddressControl* ctrl( NULL ); + for ( TInt ctrlId( EMsgComponentIdTo ); + ctrlId <= EMsgComponentIdBcc; ctrlId++ ) + { + ctrl = AddressControl( ctrlId ); + if ( ctrl ) + { + ctrl->Editor().SetAknEditorCurrentInputMode( aInputMode ); + } + } + } + +// --------------------------------------------------------- +// CMsgMailEditorAppUi::SetFocusAfterAddRecipientL +// --------------------------------------------------------- +void CMsgMailEditorAppUi::SetFocusAfterAddRecipientL( TMsgControlId aFocusBeforeAdd ) + { + //If the cursor is in some other place than the address fields when "Add recipient" + //is selected the cursor remains in this same address field (do nothing). + if ( aFocusBeforeAdd == EMsgComponentIdTo || + aFocusBeforeAdd == EMsgComponentIdCc || + aFocusBeforeAdd == EMsgComponentIdBcc ) + { + //Set the cursor to the next empty address field if there is one. + + //From "To" to "CC" if available + if( aFocusBeforeAdd < EMsgComponentIdCc && + AddressControl(EMsgComponentIdCc) && + !AddressControl(EMsgComponentIdCc)->Editor().TextLength() ) + { + iView->SetFocus(EMsgComponentIdCc); + } + + //From "To" or "CC" to "BCC" if available + else if( aFocusBeforeAdd < EMsgComponentIdBcc && + AddressControl(EMsgComponentIdBcc) && + !AddressControl(EMsgComponentIdBcc)->Editor().TextLength() ) + { + iView->SetFocus(EMsgComponentIdBcc); + } + + //To "Subject" if CC and BCC have not been available + else if( SubjectControl() && !SubjectControl()->Editor().TextLength() ) + { + iView->SetFocus(EMsgComponentIdSubject); + } + + //In other case cursor is placed into the text body + //1) the beginning of the text body if it is empty, or + //2) the end of text body if there is text already. + else + { + iView->SetFocus(EMsgComponentIdBody); + CEikRichTextEditor& editor = BodyControl()->Editor(); + editor.SetCursorPosL(editor.TextLength(), EFalse); + } + } + } + +// --------------------------------------------------------------------------- +// CMsgMailEditorAppUi::ControlTouchedL +// +// Control has been touched. Invoke appopriate actions +// --------------------------------------------------------------------------- +// +#ifdef RD_SCALABLE_UI_V2 +void CMsgMailEditorAppUi::ControlTouchedL( const CMsgBaseControl& aControl ) + { + //Check the control id + TInt touchedControlId = aControl.ControlId(); + switch( touchedControlId ) + { + //Touch in address fields + case EMsgComponentIdTo: + case EMsgComponentIdCc: + case EMsgComponentIdBcc: + { + //Set focus to touched control (if needed) + TInt focusedControlId = iView->FocusedControl()->ControlId(); + + if ( focusedControlId != touchedControlId ) + { + iView->SetFocus( touchedControlId ); + } + + if(!AreAddressFieldsEmptyL() && !AllAddressValidL()) + { + CheckRecipientsL(EFalse); + } + else + { + DoAddRecipientL(); + } + break; + } + //Touch in attachment button + case EMsgComponentIdAttachment: + { + //Open attachment view + DoAttachmentL(); + break; + } + default: + { + LOG1( "CMsgMailEditorAppUi::ControlTouchedL - Unhandled control! id %d", touchedControlId ); + } + } // switch + } +#endif + +// -------------------------------------------------------------------------- +// CMsgMailEditorAppUi::HandleEnterKeyL +// Handles enter key events. +// -------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::HandleEnterKeyL() + { + if( iView ) + { + CMsgBaseControl* focusedCtrl = iView->FocusedControl(); + if( focusedCtrl ) + { + switch( focusedCtrl->ControlId() ) + { + case EMsgComponentIdAttachment: + { + // Open attachment view + DoAttachmentL(); + break; + } + default: + { + // event ignored for other controls. + break; + } + } + } + } + } + +// -------------------------------------------------------------------------- +// CMsgMailEditorAppUi::HandleSystemEventL +// Handles system events +// -------------------------------------------------------------------------- +// +void CMsgMailEditorAppUi::HandleSystemEventL( const TWsEvent& aEvent ) + { + TApaSystemEvent* event = ( TApaSystemEvent* )aEvent.EventData(); + if( *event == EApaSystemEventSecureShutdown ) + { + // When the user is writing a mail while the used memory drive is + // removed from the phone, the mail editor is closed and the mail is + // not saved. + iForceDeleteDocument = ETrue; + } + + CMsgMailAppUi::HandleSystemEventL( aEvent ); + } + +// End of File