/*
* 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 <MsgMailUIDs.h> // Application UIDs
#include "MsgMailViewAttachmentsDlg.h"
#include <MsgEditorAppUi.rsg> // resource identifiers
#include <MsgMailEditor.rsg>
#include "MailLog.h"
#include "MailUtils.h"
#include "cmsgmaileditorheader.h"
#include "cmsgmailnavipaneutils.h"
#include <hlplch.h>
#include <csxhelp/mail.hlp.hrh>
#include <bldvariant.hrh>
// ui includes
#include <avkon.hrh>
#include <eikmop.h> // for SupplyMopObject
#include <eikrted.h>
#include <aknenv.h> // AppShutter
#include <barsread.h> // TResourceReader
#include <aknnotewrappers.h>
#include <AknWaitDialog.h>
#include <akntitle.h>
#include <akntoolbar.h>
#include <akntoolbarextension.h>
#include <aknclearer.h> // CAknLocalScreenClearer
// Editor base classes:
#include <MsgAttachmentInfo.h>
#include <MsgAttachmentModel.h>
#include <MsgEditorView.h>
#include <MsgBodyControl.h>
#include <MsgExpandableControl.h>
#include <MsgAddressControl.h>
#include <MsgCheckNames.h>
#include <Muiumsginfo.hrh>
#include <mtmuibas.h> // CBaseMtmUi
#include <MuiuMsvUiServiceUtilities.h> // MUIU MTM utils
#include <MtmExtendedCapabilities.hrh>
#include <cemailaccounts.h> // CEmailAccounts
#include <StringLoader.h> // for StringLoader
#include "MsgMailOptionsDlg.h"
#include "CMsgAddMailHeadersDlg.h" // Additional headers dialog
#include <fepbase.h>
#include <aknedsts.h>
#include <akninputblock.h> // CAknInputBlock
// mail central repository handler
#include "CMailCRHandler.h"
#include <MailInternalCRKeys.h>
#include <ImumInHealthServices.h>
#include <ImumInMailboxServices.h>
#include <SendUiConsts.h>
#include <MsgEditorAppUiExtension.h>// for iMsgEditorAppUiExtension
#include <MsgEditorSettingCacheUpdatePlugin.h>
// 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<CAknTitlePane *>(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<CMsgRecipientItem>(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<TAdditionalHeaderStatus>& 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<TCoeHelpContext>* CMsgMailEditorAppUi::HelpContextL( ) const
{
CArrayFix<TCoeHelpContext>* help =
new( ELeave ) CArrayFixFlat<TCoeHelpContext>( 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<CMsgRecipientItem>(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<KMessageSizeMaxLength> 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<TAdditionalHeaderStatus> 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; i<count; i++)
{
for(TInt j=0; j<laterCount; j++)
{
if( recs[i]->Address()->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<TMsgFocusEvent*>( aArg1 ) );
TInt controlId = *(static_cast<TInt*>( 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<CMsgBaseControl*>( 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<TPointerEvent*>( aArg2 );
CMsgBaseControl* control = static_cast<CMsgBaseControl*>( 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 <CEikDialog**>(&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<count; ++index)
{
__ASSERT_DEBUG( 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; index<count; ++index )
{
TBool aliasFound( EFalse );
TImMessageField msgField;
HBufC* address = msgField.GetValidInternetEmailAddressFromString(
aArray[index]).AllocLC();
address->Des().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