--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/msgeditor/appuisrc/MsgEditorAppUi.cpp Wed Sep 01 12:31:54 2010 +0100
@@ -0,0 +1,1816 @@
+/*
+* Copyright (c) 2002-2009 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: MsgEditorAppUi implementation
+*
+*/
+
+
+
+// ========== INCLUDE FILES ================================
+
+#include <featmgr.h> // for feature manager
+
+#include <eikenv.h> // Eikon Enviroment
+#include <txtrich.h> // Rich Text
+#include <eikrted.h> // CEikRichTextEditor
+#include <eikmenub.h> // CEikMenuBar
+#include <eikspane.h> // status panel
+
+#include <eikapp.h> // CEikApplication
+#include <eikserverapp.h>
+#include <bautils.h> // NearestLanguageFile
+#include <eikdialg.h> // CEikDialog
+#include <data_caging_path_literals.hrh>
+
+#include <msvapi.h> //
+#include <mtmuibas.h> // MTM UI
+#include <mtmuidef.hrh> // Preferences
+#include <mtmdef.h> // TMsvPartList
+
+#include <MuiuMsgEmbeddedEditorWatchingOperation.h>
+#include <MuiuMsgEditorLauncher.h> // for TEditorParameters
+#include <MuiuMessageIterator.h> // for CMessageIterator
+#include <MuiuOperationWait.h> // for CMuiuOperationWait
+#include <muiu.mbg>
+
+#include <aknenv.h>
+#include <aknnavi.h> // CAknNavigationControlContainer
+#include <aknnavide.h> // CAknNavigationDecorator
+#include <akntabgrp.h> // CAknTabGroup
+#include <akninputblock.h> // CAknInputBlock
+#include <aknnotewrappers.h>
+#include <AknIndicatorContainer.h>
+#include <akncontext.h> // For message store in MMC -indication
+#include <AknsUtils.h>
+#include <AknsConstants.h>
+#include <commonphoneparser.h> // Common phone number validity checker
+#include <apgicnfl.h> // apamasked bitmaps
+#include <ErrorUI.h> // CErrorUI - to show global error notes
+#include <StringLoader.h> // StringLoader
+#include <NpdApi.h> // Notepad API
+#include <avkon.hrh>
+#include <AknStatuspaneUtils.h>
+#include <AknSettingCache.h>
+#include <messaginginternalcrkeys.h>
+#include <MessagingSDKCRKeys.h>
+#include "MsgEditorAppUiExtension.h"
+
+#include <aknlayoutscalable_avkon.cdl.h>
+
+#include "MsgEditorShutter.h"
+
+#include "MsgEditorCommon.h"
+#include "MsgEditorAppUi.h" // class header
+#include "MsgEditorView.h" // View
+#include "MsgBodyControl.h" // Body Control
+#include "MsgSendKeyAcceptingQuery.h"
+#include "MsgEditorAppUiPanic.h" // Panics
+#include "MsgEditorFlags.h" // EditorFlags
+#include "MsgAttachmentUtils.h"
+#include <MsgEditorAppUi.rsg> // resource identifiers
+#include "MsgNaviPaneControl.h"
+
+#ifdef RD_MSG_FAST_PREV_NEXT
+#include <messaginginternalpskeys.h>
+#endif
+
+#include "MsgEditorLogging.h"
+
+// ========== EXTERNAL DATA STRUCTURES =====================
+
+// ========== EXTERNAL FUNCTION PROTOTYPES =================
+
+// ========== CONSTANTS ====================================
+
+const TInt KMsgDiskSpaceForDelete = ( 5 * 1024 ); // minimum disk space needed when deleting messages
+
+// ========== MACROS =======================================
+
+_LIT( KMsgEditorAppUiResourceFileName, "msgeditorappui.rsc" );
+_LIT( KMuiuBitmapFileName, "muiu.mbm" );
+_LIT( KMsgEditorAppUiFilterRe, "RE:" );
+_LIT( KMsgEditorAppUiFilterFw, "FW:" );
+_LIT( KMsgEditorAppUiFilterFwd, "FWD:" );
+
+// ========== LOCAL CONSTANTS AND MACROS ===================
+
+// ========== MODULE DATA STRUCTURES =======================
+
+// ========== LOCAL FUNCTION PROTOTYPES ====================
+
+// ========== LOCAL FUNCTIONS ==============================
+
+// ========== MEMBER FUNCTIONS =============================
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CMsgEditorAppUi
+//
+// Constructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgEditorAppUi::CMsgEditorAppUi() :
+ iExitMode( MApaEmbeddedDocObserver::EKeepChanges ),
+ iCloseWithEndKey( ETrue )
+ {
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::ConstructL
+//
+// 2nd phase constructor.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::ConstructL()
+ {
+ CMsgEditorBaseUi::ConstructL();
+
+ iMsgNaviDirection = KErrNotFound;
+
+ // initialize feature manager to check supported features
+ FeatureManager::InitializeLibL();
+ iMmcFeatureSupported = FeatureManager::FeatureSupported( KFeatureIdMmc );
+
+ TParse parse;
+ parse.Set( KMsgEditorAppUiResourceFileName, &KDC_RESOURCE_FILES_DIR, NULL );
+ TFileName fileName( parse.FullName() );
+
+ BaflUtils::NearestLanguageFile( iCoeEnv->FsSession(), fileName );
+ iResourceFileOffset = iEikonEnv->AddResourceFileL( fileName );
+
+ Document()->SetEditorModelObserver( this );
+
+ iFileMan = CFileMan::NewL( iEikonEnv->FsSession() );
+
+ // create msgeditor temp directory.
+ TFileName temppath;
+ MsgAttachmentUtils::GetMsgEditorTempPath( temppath );
+
+ RFs& fs = iEikonEnv->FsSession();
+ fs.MkDir( temppath );
+
+ CEikStatusPane* sp = StatusPane();
+ if ( iMmcFeatureSupported &&
+ TInt( Document()->Session().CurrentDriveL() ) == EDriveE )
+ {
+ CAknContextPane* contextPane = static_cast<CAknContextPane*>
+ ( sp->ControlL( TUid::Uid( EEikStatusPaneUidContext ) ) );
+ TParse fileParse;
+ fileParse.Set( KMuiuBitmapFileName, &KDC_APP_BITMAP_DIR, NULL );
+ CFbsBitmap* bmp = NULL;
+ CFbsBitmap* mask = NULL;
+#ifdef __SCALABLE_ICONS
+ AknsUtils::CreateIconL(
+ AknsUtils::SkinInstance(),
+ KAknsIIDQgnMenuMceMmcCxt,
+ bmp,
+ mask,
+ fileParse.FullName(),
+ EMbmMuiuQgn_menu_mce_mmc,
+ EMbmMuiuQgn_menu_mce_mmc_mask );
+#else
+ AknsUtils::CreateIconL(
+ AknsUtils::SkinInstance(),
+ KAknsIIDQgnMenuMceMmcCxt,
+ bmp,
+ mask,
+ fileParse.FullName(),
+ EMbmMuiuQgn_menu_mce_mmc_cxt,
+ EMbmMuiuQgn_menu_mce_mmc_cxt_mask );
+#endif //__SCALABLE_ICONS
+ contextPane->SetPicture( bmp, mask );
+ }
+ iOwnNaviPane = static_cast<CAknNavigationControlContainer*>
+ ( sp->ControlL( TUid::Uid( EEikStatusPaneUidNavi ) ) );
+ iCoeEnv->FsSession().ReserveDriveSpace(
+ TInt( Document()->Session().CurrentDriveL() ),
+ KMsgDiskSpaceForDelete );
+
+ CMsgEditorDocument* doc = Document();
+ iEditorShutter = CMsgEditorShutter::NewL(*doc);
+
+ iMsgEditorAppUiExtension = new(ELeave) CMsgEditorAppUiExtension( this );
+ CAknEnv* env = iAvkonEnv;
+ CAknSettingCache& cache = env->SettingCache();
+ cache.RegisterPluginL( &( iMsgEditorAppUiExtension->iSettingCachePlugin ) );
+
+ iStatusPaneRes = StatusPane()->CurrentLayoutResId();
+
+ iIterator = NULL;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::~CMsgEditorAppUi
+//
+// Destructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgEditorAppUi::~CMsgEditorAppUi()
+ {
+ delete iEditorShutter;
+
+ Document()->SetEditorModelObserver( NULL );
+
+ // remove resource file from CONE-maintained resource file list.
+ if ( iResourceFileOffset )
+ {
+ iEikonEnv->DeleteResourceFile( iResourceFileOffset );
+ }
+
+ // call NotifyExit on completion of editing of an embedded document.
+ if ( iDoorObserver )
+ {
+ MEBLOGGER_WRITEF( _L( "MEB: CMsgEditorAppUi: Closing with exit mode %d" ), iExitMode );
+ iDoorObserver->NotifyExit( iExitMode );
+ }
+
+ delete iView;
+ delete iLock;
+ delete iNaviDecorator;
+
+ // we are referring instance of nvaidecoratoir only
+ // no need to delete, alreday deleted in delete iNaviDecorator;
+ //delete iIterator;
+
+ // delete files from our temp directory.
+ if ( iFileMan )
+ {
+ TFileName temppath;
+ MsgAttachmentUtils::GetMsgEditorTempPath( temppath );
+
+ /*TInt err =*/ iFileMan->Delete( temppath /*, CFileMan::ERecurse*/ );
+ //TInt err2 = iFileMan->RmDir(temppath); // remove directory
+ }
+
+ delete iFileMan;
+
+ // Uninitialize FeatureManager and members
+ FeatureManager::UnInitializeLib();
+ if( iMsgEditorAppUiExtension )
+ {
+ CAknEnv* env = iAvkonEnv;
+ CAknSettingCache& cache = env->SettingCache();
+ cache.DeRegisterPlugin( &( iMsgEditorAppUiExtension->iSettingCachePlugin ) );
+ delete iMsgEditorAppUiExtension;
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleKeyEventL
+//
+// Route key events to view.
+// ---------------------------------------------------------
+//
+EXPORT_C TKeyResponse CMsgEditorAppUi::HandleKeyEventL(
+ const TKeyEvent& aKeyEvent, TEventCode aType )
+ {
+ if ( iView )
+ {
+ return iView->OfferKeyEventL( aKeyEvent, aType );
+ }
+ return EKeyWasNotConsumed;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleWsEventL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleWsEventL( const TWsEvent& aEvent,CCoeControl* aDestination )
+ {
+ TInt type = aEvent.Type();
+
+ if ( type == EEventKey )
+ {
+ TKeyEvent* key = aEvent.Key();
+ if ( ( key->iModifiers & EModifierShift ) &&
+ ( key->iCode == EKeyBackspace ) )
+ {
+ if ( iView )
+ {
+ CMsgBodyControl* body =
+ static_cast<CMsgBodyControl*>( iView->ControlById( EMsgComponentIdBody ) );
+
+ if ( body && body->IsReadOnly() )
+ {
+ TRAP_IGNORE( SaveBodyL( body ) );
+ }
+ }
+
+ key->iModifiers &= ~EModifierShift;
+ key->iCode = EKeyDelete;
+ }
+ }
+
+ if ( type != KAknUidValueEndKeyCloseEvent ||
+ iCloseWithEndKey )
+ {
+ CAknAppUi::HandleWsEventL( aEvent, aDestination );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::NextMessageL
+//
+// Set a specific exit code for opening next or previous message. Codes are
+// defined in MuiuMsgEmbeddedEditorWatchingOperation.h
+// and handled by MCE after msg viewer has been closed.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::NextMessageL( TBool aForward )
+ {
+ // Next is ETrue if layout is EAknLayoutIdABRW,
+ // EFalse if EAknLayoutIdELAF or EAknLayoutIdAPAC
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ aForward = !aForward;
+ }
+
+ iMsgNaviDirection = aForward;
+
+ // Check if next/previous message
+ __ASSERT_DEBUG( iIterator != NULL, Panic( ENullPointer1 ) );
+ if ( aForward )
+ {
+ iIterator->SetNextMessage();
+
+ }
+ else
+ {
+ iIterator->SetPreviousMessage();
+ }
+
+ RProperty::Set( KPSUidMuiu, KMuiuKeyNextMsg,
+ iIterator->CurrentMessage().Id() );
+
+#ifdef RD_MSG_FAST_PREV_NEXT
+ // Check if next/previous message can be fast opened by viewer
+
+ if ( CanFastOpenL( *iIterator) )
+ {
+ // Load next/previous message
+ TRAPD( err, Document()->SetEntryL( iIterator->CurrentMessage().Id() ) );
+ // If fast open fails, view is incompletely constructed
+ // Drop back to mce
+ if( err == KErrCancel )
+ {
+ /* It is a known-valid failure(quick lauch cancelled in viewers due to heterogenous messages)
+ * In that case, reset the current entry to original and exit with correct code so that message
+ * will be launched completely from MCE.
+ */
+ if ( iMsgNaviDirection )
+ {
+ iIterator->SetPreviousMessage();
+ }
+ else
+ {
+ iIterator->SetNextMessage();
+ }
+ Document()->SetEntryWithoutNotificationL( iIterator->CurrentMessage().Id() );
+ iExitMode = iMsgNaviDirection ?
+ MApaEmbeddedDocObserver::TExitMode(
+ CMsgEmbeddedEditorWatchingOperation::EMsgExitNext) :
+ MApaEmbeddedDocObserver::TExitMode(
+ CMsgEmbeddedEditorWatchingOperation::EMsgExitPrevious);
+ Exit( iExitMode );
+ }
+ else if ( err != KErrNone )
+ {
+ // Reset the KMuiuKeyNextMsg to 0
+ RProperty::Set( KPSUidMuiu, KMuiuKeyNextMsg,0 );
+ // Unknown error during quick launch.
+ iCoeEnv->HandleError( err );
+ iExitMode = MApaEmbeddedDocObserver::ENoChanges;
+ Exit( EAknSoftkeyClose );
+ }
+ }
+ else
+#endif // RD_MSG_FAST_PREV_NEXT
+ {
+ iExitMode = aForward ?
+ MApaEmbeddedDocObserver::TExitMode(
+ CMsgEmbeddedEditorWatchingOperation::EMsgExitNext) :
+ MApaEmbeddedDocObserver::TExitMode(
+ CMsgEmbeddedEditorWatchingOperation::EMsgExitPrevious);
+ Exit( iExitMode );
+ }
+ iMsgNaviDirection = KErrNotFound;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::IsNextMessageAvailableL
+//
+// Check if next or previous msg is available.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgEditorAppUi::IsNextMessageAvailableL( TBool aForward )
+ {
+ TBool ret = EFalse;
+
+ if ( iEikonEnv->StartedAsServerApp() )
+ {
+ CMsgEditorDocument* doc = Document();
+
+ //We should not create iterator here navi pane iterator
+ //will be refered in CMsgEditorAppUi
+
+
+ // Next is ETrue if layout is EAknLayoutIdABRW,
+ // EFalse if EAknLayoutIdELAF or EAknLayoutIdAPAC
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ aForward = !aForward;
+ }
+ if(iIterator)
+ {
+ if ( aForward )
+ {
+ if ( iIterator->NextMessageExists() )
+ {
+ ret = ETrue;
+ }
+ }
+ else
+ {
+ if ( iIterator->PreviousMessageExists() )
+ {
+ ret = ETrue;
+ }
+ }
+ }
+
+ }
+
+ return ret;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::MessageIndexInFolderL
+//
+// Returns index of current msg and also total number of msgs in folder.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::MessageIndexInFolderL( TInt& aCurrentIndex,
+ TInt& aMsgsInFolder )
+ {
+ if ( iEikonEnv->StartedAsServerApp() )
+ {
+ CMsgEditorDocument* doc = Document();
+ //We should not create iterator here, navi pane iterator
+ //will be refered in CMsgEditorAppUi
+ if(iIterator)
+ {
+ aCurrentIndex = iIterator->CurrentMessageIndex();
+ aMsgsInFolder = iIterator->MessagesInFolder();
+ }
+ }
+ else
+ {
+ aCurrentIndex = 0;
+ aMsgsInFolder = 0;
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::MoveMessageEntryL
+//
+// Moves an entry to another location.
+// ---------------------------------------------------------
+//
+EXPORT_C TMsvId CMsgEditorAppUi::MoveMessageEntryL( TMsvId aTarget ) const
+ {
+ TMsvEntry msvEntry = Document()->Entry();
+ TMsvId id = KMsvNullIndexEntryId;
+
+ if ( msvEntry.Parent() != aTarget )
+ {
+ CAknInputBlock::NewLC();
+
+ CMsvEntry* parentEntry = Document()->Session().GetEntryL( msvEntry.Parent() );
+ CleanupStack::PushL( parentEntry );
+
+ // -- Change sort parameters so that parentEntry->MoveL does not leave as the child is invisible.
+ TMsvSelectionOrdering sort = parentEntry->SortType();
+ sort.SetShowInvisibleEntries( ETrue );
+ parentEntry->SetSortTypeL( sort );
+
+ // Copy original from the parent to the new location.
+ CMuiuOperationWait* wait = CMuiuOperationWait::NewLC();
+
+ CMsvOperation* op = parentEntry->MoveL(
+ msvEntry.Id(), aTarget, wait->iStatus );
+ CleanupStack::PushL( op );
+ wait->Start(); // wait for asynch operation
+
+ TMsvLocalOperationProgress prog = McliUtils::GetLocalProgressL( *op );
+ User::LeaveIfError( prog.iError );
+ id = prog.iId;
+
+ CleanupStack::PopAndDestroy( 4 ); // op, wait, parentEntry, absorber
+ }
+
+ return id;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::DeleteAndExitL
+//
+// Deletes current entry and then exits.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::DeleteAndExitL()
+ {
+ DeleteCurrentEntryL();
+ Exit( EAknSoftkeyBack );
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::DeleteCurrentEntryL
+//
+// Deletes current entry.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::DeleteCurrentEntryL()
+ {
+ CMsgEditorDocument* doc = Document();
+ UnlockEntry();
+
+ TInt msgStoreDrive = TInt( doc->Session().CurrentDriveL() );
+ iCoeEnv->FsSession().GetReserveAccess( msgStoreDrive );
+
+ if ( doc->CurrentEntry().OwningService() == KMsvLocalServiceIndexEntryId )
+ {
+ const TMsvId id = doc->Entry().Id();
+ //doc->CurrentEntry().SetEntryL( doc->Entry().Parent() );
+ TRAPD(
+ err,
+ {
+ doc->CurrentEntry().SetEntryL( doc->Entry().Parent() );
+ doc->CurrentEntry().DeleteL( id );
+ }
+ );
+ if ( err != KErrNone )
+ {
+ doc->Session().RemoveEntry( id );
+ }
+ }
+ else
+ {
+ CMsvEntrySelection* sel = new ( ELeave ) CMsvEntrySelection;
+ CleanupStack::PushL( sel );
+ TMsvId id = doc->Entry().Id();
+ sel->AppendL( id );
+ doc->Mtm().SwitchCurrentEntryL( doc->Entry().Parent() );
+
+ CMuiuOperationWait* wait = CMuiuOperationWait::NewLC();
+
+ CMsvOperation* op = doc->MtmUi().DeleteFromL( *sel, wait->iStatus );
+ CleanupStack::PushL( op );
+
+ wait->Start();
+
+ const TInt err = doc->MtmUi().DisplayProgressSummary( op->ProgressL() );
+ CleanupStack::PopAndDestroy( 3, sel ); // sel, wait, op
+ if ( err == KErrCancel )
+ {
+ doc->Mtm().SwitchCurrentEntryL( id );
+ LockEntryL();
+ return ;
+ }
+ User::LeaveIfError( err );
+ }
+
+ iCoeEnv->FsSession().ReleaseReserveAccess( msgStoreDrive );
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::PrepareToExit
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::PrepareToExit()
+ {
+ CMsgEditorDocument* doc = Document();
+
+ if ( doc->HasModel() )
+ {
+ if ( doc->Entry().InPreparation() )
+ {
+ doc->Session().RemoveEntry( doc->Entry().Id() );
+ }
+ }
+
+ CEikAppUi::PrepareToExit();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::ReplyL
+//
+// Asynchronous Mtm reply command.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::ReplyL(
+ TMsvId aTarget, TBool aIncludeOriginal /*= ETrue*/ )
+ {
+ TMsvPartList parts =
+ KMsvMessagePartDescription |
+ KMsvMessagePartOriginator;
+
+ if ( aIncludeOriginal )
+ {
+ parts |= KMsvMessagePartBody;
+ }
+
+ CBaseMtmUi& mtmUi = Document()->MtmUi();
+
+ // to by-pass scanner warning about member variable being stored into
+ // cleanup stack blocker is first stored into temporary variable. Storing
+ // is allowed here as it is not owned.
+
+ CMuiuOperationWait* wait =
+ CMuiuOperationWait::NewLC( EActivePriorityWsEvents + 10 );
+
+ mtmUi.SetPreferences( mtmUi.Preferences() | EMtmUiFlagEditorPreferEmbedded );
+ CMsvOperation* oper = mtmUi.ReplyL( aTarget, parts, wait->iStatus );
+ CleanupStack::PushL( oper );
+
+ wait->Start();
+
+ CleanupStack::PopAndDestroy( 2 ); // absorber, wait, oper
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::ReplyToAllL
+//
+// Asynchronous Mtm reply all command.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::ReplyToAllL(
+ TMsvId aTarget, TBool aIncludeOriginal /*= ETrue*/ )
+ {
+ TMsvPartList parts =
+ KMsvMessagePartDescription |
+ KMsvMessagePartRecipient |
+ KMsvMessagePartOriginator ;
+
+ if ( aIncludeOriginal )
+ {
+ parts |= KMsvMessagePartBody;
+ }
+
+ CBaseMtmUi& mtmUi = Document()->MtmUi();
+
+ // to by-pass scanner warning about member variable being stored into
+ // cleanup stack blocker is first stored into temporary variable. Storing
+ // is allowed here as it is not owned.
+ CAknInputBlock* blocker = CAknInputBlock::NewCancelHandlerLC( this );
+ iInputBlocker = blocker;
+
+ CMuiuOperationWait* wait =
+ CMuiuOperationWait::NewLC( EActivePriorityWsEvents + 10 );
+
+ mtmUi.SetPreferences( mtmUi.Preferences() | EMtmUiFlagEditorPreferEmbedded );
+ CMsvOperation* oper = mtmUi.ReplyL( aTarget, parts, wait->iStatus );
+ CleanupStack::PushL( oper );
+
+ wait->Start();
+
+ CleanupStack::PopAndDestroy( 3, iInputBlocker ); // absorber, wait, oper
+ iInputBlocker = NULL;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::ForwardL
+//
+// Asynchronous Mtm forward command.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::ForwardL( TMsvId aTarget )
+ {
+ TMsvPartList parts =
+ KMsvMessagePartBody |
+ KMsvMessagePartDescription |
+ KMsvMessagePartAttachments;
+
+ CBaseMtmUi& mtmUi = Document()->MtmUi();
+ mtmUi.SetPreferences( mtmUi.Preferences() | EMtmUiFlagEditorPreferEmbedded );
+
+ // to by-pass scanner warning about member variable being stored into
+ // cleanup stack blocker is first stored into temporary variable. Storing
+ // is allowed here as it is not owned.
+ CAknInputBlock* blocker = CAknInputBlock::NewCancelHandlerLC( this );
+ iInputBlocker = blocker;
+
+ CMuiuOperationWait* wait = CMuiuOperationWait::NewLC( EActivePriorityWsEvents + 10 );
+
+ CMsvOperation* oper = mtmUi.ForwardL( aTarget, parts, wait->iStatus );
+ CleanupStack::PushL( oper );
+
+ wait->Start();
+
+ CleanupStack::PopAndDestroy( 3, iInputBlocker ); // absorber, wait, oper
+ iInputBlocker = NULL;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::InsertTemplate
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgEditorAppUi::InsertTemplateL( TInt aMaxChars /*= -1*/ )
+ {
+ __ASSERT_DEBUG( iView != NULL, Panic( ENullPointer1 ) );
+
+ // get memo content from notepad to buffer.
+ HBufC* title = iEikonEnv->AllocReadResourceLC( R_QTN_MAIL_POPUP_TEXT_SEL_TEMP );
+
+ HBufC* buf = CNotepadApi::FetchTemplateL( title );
+ CleanupStack::PushL( buf );
+
+ TInt err = DoInsertTextL( buf, aMaxChars );
+
+ CleanupStack::PopAndDestroy( 2, title ); // buf, title
+ return err;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::InsertTextMemoL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgEditorAppUi::InsertTextMemoL( TInt aMaxChars )
+ {
+ __ASSERT_DEBUG( iView != NULL, Panic( ENullPointer1 ) );
+
+ // get memo content from notepad to buffer.
+ HBufC* title = iEikonEnv->AllocReadResourceLC( R_QTN_NMAKE_FETCH_MEMO_PRMPT );
+
+ HBufC* buf = CNotepadApi::FetchMemoL( title );
+ CleanupStack::PushL( buf );
+
+ TInt err = DoInsertTextL( buf, aMaxChars );
+
+ CleanupStack::PopAndDestroy( 2, title ); // buf, title
+ return err;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::DoInsertTextL
+//
+//
+// ---------------------------------------------------------
+//
+TInt CMsgEditorAppUi::DoInsertTextL( HBufC* aBuffer, TInt aMaxChars )
+ {
+ TInt err( KErrNone );
+ if ( aBuffer )
+ {
+ TInt buflen = aBuffer->Length();
+
+ if ( aMaxChars == -1 || buflen <= aMaxChars )
+ {
+ CMsgBodyControl* body =
+ static_cast<CMsgBodyControl*>( iView->ControlById( EMsgComponentIdBody ) );
+
+ if ( body )
+ {
+ CEikRichTextEditor& editor = body->Editor();
+
+ if ( body != iView->FocusedControl() )
+ {
+ editor.SetCursorPosL( editor.TextLength(), EFalse );
+ }
+
+ body->InsertTextL( *aBuffer );
+
+ iView->SetFocus( EMsgComponentIdBody );
+
+ Document()->SetChanged( ETrue );
+ }
+ }
+ else
+ {
+ err = KErrOverflow;
+ }
+ }
+ else
+ {
+ err = KErrCancel;
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::UpdateNaviPaneL
+//
+// Updates navi pane.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::UpdateNaviPaneL(
+ const CFbsBitmap* aBitmap /*= NULL*/,
+ const CFbsBitmap* aBitmapMask /*= NULL*/ )
+ {
+ UpdateNaviPaneL( EFalse, aBitmap, aBitmapMask );
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::UpdateNaviPaneL
+//
+// Updates navi pane.
+// ---------------------------------------------------------
+//
+void CMsgEditorAppUi::UpdateNaviPaneL(
+ TBool aUpdateExisting,
+ const CFbsBitmap* aBitmap /*= NULL*/,
+ const CFbsBitmap* aBitmapMask /*= NULL*/ )
+ {
+ if ( !iOwnNaviPane )
+ {
+ return;
+ }
+ TInt index = 0;
+ TInt msgs = 0;
+ HBufC* buf;
+
+ MessageIndexInFolderL( index, msgs );
+
+ TBool prevAvailable = IsNextMessageAvailableL( EFalse );
+ TBool nextAvailable = IsNextMessageAvailableL( ETrue );
+
+ CArrayFixFlat<TInt>* array = new( ELeave ) CArrayFixFlat<TInt>( 2 );
+ CleanupStack::PushL( array );
+
+ if ( msgs )
+ {
+ array->AppendL( index + 1 );
+ array->AppendL( msgs );
+ buf = StringLoader::LoadLC( R_QTN_STAT_MSG_NUMBER, *array, iCoeEnv );
+ }
+ else
+ {
+ // if no messages make empty message label.
+ buf = HBufC::NewLC( 0 );
+ prevAvailable = nextAvailable = 0;
+ }
+
+ if ( aUpdateExisting )
+ {
+ if ( iNaviDecorator )
+ {
+ CAknTabGroup* tabGroup =
+ static_cast<CAknTabGroup*>( iNaviDecorator->DecoratedControl() );
+ tabGroup->ReplaceTabTextL( 0, *buf );
+
+ iNaviDecorator->MakeScrollButtonVisible( ETrue );
+ iNaviDecorator->SetScrollButtonDimmed(
+ CAknNavigationDecorator::ELeftButton,
+ !prevAvailable );
+ iNaviDecorator->SetScrollButtonDimmed(
+ CAknNavigationDecorator::ERightButton,
+ !nextAvailable );
+
+ iOwnNaviPane->PushL( *iNaviDecorator );
+ }
+ }
+ else
+ {
+ delete iNaviDecorator;
+ iNaviDecorator = NULL;
+ iNaviDecorator = iOwnNaviPane->CreateTabGroupL();
+
+ CAknTabGroup* tabGroup =
+ static_cast<CAknTabGroup*>( iNaviDecorator->DecoratedControl() );
+ tabGroup->AddTabL( 0, *buf );
+ tabGroup->SetActiveTabById( 0 );
+ // does not leave with one tab.
+ tabGroup->SetTabFixedWidthL( KTabWidthWithOneTab );
+
+ iNaviDecorator->MakeScrollButtonVisible( ETrue );
+ iNaviDecorator->SetScrollButtonDimmed(
+ CAknNavigationDecorator::ELeftButton,
+ !prevAvailable );
+ iNaviDecorator->SetScrollButtonDimmed(
+ CAknNavigationDecorator::ERightButton,
+ !nextAvailable );
+
+ iOwnNaviPane->PushL( *iNaviDecorator );
+
+ if ( aBitmap && aBitmapMask )
+ {
+ // replace tab with new one containing text and bitmaps.
+ // this must be done after PushL because this transfers
+ // ownership of caller's bitmaps to tab group.
+ tabGroup->ReplaceTabL( 0, *buf, aBitmap, aBitmapMask );
+ }
+ }
+ CleanupStack::PopAndDestroy( 2, array ); // buf, array
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleIteratorEventL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleIteratorEventL(
+ TMessageIteratorEvent aEvent )
+ {
+ if ( aEvent == EFolderCountChanged )
+ {
+ UpdateNaviPaneL( ETrue );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CallToSenderQueryL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgEditorAppUi::CallToSenderQueryL(
+ const TDesC& aNumber, const TDesC& aAlias )
+ {
+ CDesCArrayFlat* strings = new ( ELeave ) CDesCArrayFlat( 2 );
+ CleanupStack::PushL( strings );
+
+ strings->AppendL( aAlias ); // %0U
+ strings->AppendL( aNumber ); // %1U
+
+ HBufC* prompt = StringLoader::LoadLC(
+ R_QTN_SMS_QUEST_CALL, *strings, iCoeEnv );
+
+ CMsgSendKeyAcceptingQuery* dlg = CMsgSendKeyAcceptingQuery::NewL( *prompt );
+ TInt ret = dlg->ExecuteLD( R_MEB_CALLBACK_QUERY );
+
+ CleanupStack::PopAndDestroy( 2, strings ); // strings, prompt
+
+ return ( ret != 0 ); // No = EFalse, others = ETrue.
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::ProcessCommandParametersL
+//
+// Parses command line parameter and launch model accoring to them.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgEditorAppUi::ProcessCommandParametersL(
+ TApaCommand /*aCommand*/,
+ TFileName& /*aDocumentName*/,
+ const TDesC8& aTail )
+ {
+ CMsgEditorDocument& doc = *Document();
+
+ if ( aTail.Length() > 0 )
+ {
+ // Get the parameters passed by the launching MTMUI.
+ TPckgBuf<TEditorParameters> paramPack;
+ const TInt paramSize = sizeof( TEditorParameters );
+
+ __ASSERT_ALWAYS( aTail.Length() == paramSize, Panic( EInvalidArgument ) );
+
+ paramPack.Copy( aTail );
+ const TEditorParameters& params = paramPack();
+
+ // to by-pass scanner warning about member variable being stored into
+ // cleanup stack blocker is first stored into temporary variable. Storing
+ // is allowed here as it is not owned.
+ CAknInputBlock* blocker = CAknInputBlock::NewCancelHandlerLC( this );
+ iInputBlocker = blocker;
+
+ doc.LaunchParametersL( params );
+ doc.EntryChangedL(); // notified after is unique (and unlocked).
+ doc.PrepareToLaunchL( this );
+
+ CleanupStack::PopAndDestroy( iInputBlocker );
+ iInputBlocker = NULL;
+ }
+ else
+ {
+ // no parameters enable TestEditor launching...
+ doc.PrepareToLaunchL( this );
+ }
+
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::MenuBar
+//
+// Returns application menubar.
+// ---------------------------------------------------------
+//
+EXPORT_C CEikMenuBar* CMsgEditorAppUi::MenuBar() const
+ {
+ return iEikonEnv->AppUiFactory()->MenuBar();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::SetEmphasis
+//
+// From MEikMenuObserver (called when menu is opened).
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::SetEmphasis(
+ CCoeControl* aMenuControl, TBool aEmphasis )
+ {
+ if ( iView )
+ {
+ UpdateStackedControlFlags(
+ iView,
+ aEmphasis ? ECoeStackFlagRefusesFocus : 0,
+ ECoeStackFlagRefusesFocus );
+ }
+
+ UpdateStackedControlFlags(
+ aMenuControl,
+ aEmphasis ? 0 : ECoeStackFlagRefusesFocus,
+ ECoeStackFlagRefusesFocus );
+
+ HandleStackChanged();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleEntryChangeL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleEntryChangeL is called when the currently open message
+// has been modified by some other messaging client. The default
+// action is "do nothing", but editors can define their own event
+// processing by overriding this function.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleEntryChangeL()
+ {
+ // no action
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleEntryDeletedL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleEntryDeletedL is called when the currently open message
+// has been deleted by some other messaging client.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleEntryDeletedL()
+ {
+ // TODO: get error code from errorres.
+ ViewErrorL(-7005);
+
+ // close the application (and possible chain of viewers, editors and mce etc.).
+ ProcessCommandL( EAknCmdExit );
+ //Exit();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleEntryMovedL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleEntryMovedL is called when the currently open message
+// has been moved to some other folder, by some other messaging
+// client.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleEntryMovedL(
+ TMsvId /*aOldParent*/, TMsvId /*aNewParent*/ )
+ {
+ // refresh model content.
+ Document()->SetEntryWithoutNotificationL( Document()->Entry().Id() );
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleMtmGroupDeinstalledL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleMtmGroupDeinstalledL is called when the MTM Group used
+// by the currently open message has been removed from the device.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleMtmGroupDeinstalledL()
+ {
+ // TODO: get error code from errorres.
+ ViewErrorL( -7006 );
+
+ // close the application (and possible chain of viewers, editors and mce etc.).
+ ProcessCommandL( EAknCmdExit );
+ //Exit();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleGeneralErrorL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleGeneralErrorL is called when some unknown error has
+// happened. The aErrorCode parameter contains the error code.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleGeneralErrorL( TInt /*aErrorCode*/ )
+ {
+ // TODO: show note?
+
+ // close the application (and possible chain of viewers, editors and mce etc.).
+ ProcessCommandL( EAknCmdExit );
+ //Exit();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleCloseSessionL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleCloseSessionL is called when the messaging server wants
+// to close the session (e.g. because it's closing down and wants
+// to get rid of all messaging clients).
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleCloseSessionL()
+ {
+ // save changes and close the application.
+ DoMsgSaveExitL();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleServerFailedToStartL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleServerFailedToStartL is called when the message server
+// start-up was not successful.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleServerFailedToStartL()
+ {
+ // TODO: get error code from errorres.
+ ViewErrorL( -7007 );
+
+ // close the application (and possible chain of viewers, editors and mce etc.).
+ ProcessCommandL( EAknCmdExit );
+ //Exit();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleServerTerminatedL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleServerTerminatedL is called when the messaging server has
+// died. Application cannot use the message server session any more.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleServerTerminatedL()
+ {
+ // TODO: get error code from errorres.
+ ViewErrorL( -7008 );
+
+ // close the application (and possible chain of viewers, editors and mce etc.).
+ ProcessCommandL( EAknCmdExit );
+ //Exit();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleMediaChangedL
+//
+// Default error handling for all messaging editors and viewers.
+// HandleMediaChangedL is called when the messaging storage has
+// been moved into another disk, This means that the current
+// message entry is not valid any more. This function creates
+// new entry in the new messaging store, in order to enable saving
+// the message. The new entry is left in InPreparation state, so
+// that it will be deleted if the application (e.g. viewer) does
+// not save anything in it.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleMediaChangedL()
+ {
+ if( iMmcFeatureSupported )
+ {
+ // create new InPreparation entry in the new messaging store.
+ CMsgEditorDocument* doc = Document();
+ doc->CreateNewL( doc->DefaultMsgService(), doc->DefaultMsgFolder() );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleMediaUnavailableL
+//
+// Default error handling for all messaging editors and viewers.
+// The media state is recorded in model and default action in AppUi
+// is to display warning message to the user.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleMediaUnavailableL()
+ {
+ if( iMmcFeatureSupported )
+ {
+ ProcessCommandL( EAknCmdExit );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleMediaAvailableL
+//
+// Default error handling for all messaging editors and viewers.
+// No action made by default, the media state is recorded in model.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleMediaAvailableL()
+ {
+ // no action
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleMediaIncorrectL
+//
+// Default error handling for all messaging editors and viewers.
+// The media state is recorded in model, and warning note is displayed
+// to the user here.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleMediaIncorrectL()
+ {
+ if( iMmcFeatureSupported )
+ {
+ ViewErrorL( KMsvMediaIncorrect );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleCorruptedIndexRebuildingL
+//
+// Default error handling for all messaging editors and viewers.
+// The default action is to put busy note on the screen. The busy
+// note will be displayed while the index is being rebuilt - until
+// we get "index rebuilt" event in HandleCorruptedIndexRebuiltL().
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleCorruptedIndexRebuildingL()
+ {
+ HBufC* line = iEikonEnv->AllocReadResourceLC( R_MEB_N_IN_REBUILDING_INDEX );
+ iEikonEnv->BusyMsgL( *line );
+ CleanupStack::PopAndDestroy( line ); // line
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleCorruptedIndexRebuiltL
+//
+// Default error handling for all messaging editors and viewers.
+// The default action is to remove the busy note displayed when
+// the index rebuilding event was received.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleCorruptedIndexRebuiltL()
+ {
+ iEikonEnv->BusyMsgCancel();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CreateCustomControlL
+//
+// Default implementation is NULL since viewers do not need this.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgBaseControl* CMsgEditorAppUi::CreateCustomControlL( TInt /*aControlType*/ )
+ {
+ return NULL;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::IsLaunchedL
+//
+// Checks if document has finished launching.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgEditorAppUi::IsLaunchedL() const
+ {
+ return Document()->IsLaunched();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::EditorObserver
+//
+// Default implementation.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::EditorObserver(
+ TMsgEditorObserverFunc aFunc,
+ TAny* /*aArg1*/,
+ TAny* aArg2,
+ TAny* /*aArg3*/ )
+ {
+ switch (aFunc)
+ {
+ case EMsgDenyClipboardOperation:
+ {
+ TInt* ret = static_cast<TInt*>( aArg2 );
+ *ret = 0;
+ }
+ break;
+
+ case EMsgHandleFocusChange:
+ default:
+ break;
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::DoMtmCmdL
+//
+// Get services from mtm's and offers them to APP UI.
+// ---------------------------------------------------------
+//
+void CMsgEditorAppUi::DoMtmCmdL( const TUid& /*aQuery*/, TInt aCmd ) const
+ {
+ CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection;
+ CleanupStack::PushL( selection );
+ selection->AppendL( Document()->Entry().Id() );
+ TBuf8<1> null;
+ TMsvId origMessageId = Document()->Entry().Id();
+ Document()->MtmUi().InvokeSyncFunctionL( aCmd, *selection, null );
+ CleanupStack::PopAndDestroy( selection ); // selection
+ Document()->SetEntryL( origMessageId );
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::ViewErrorL
+//
+// Helper function for Handle... methods.
+// ---------------------------------------------------------
+//
+void CMsgEditorAppUi::ViewErrorL( TInt aTitle )
+ {
+ // TODO: check if app in foreground and show error note only then.
+ CErrorUI* errorUI = CErrorUI::NewLC( *iCoeEnv );
+ errorUI->ShowGlobalErrorNoteL( aTitle );
+ CleanupStack::PopAndDestroy( errorUI ); // errorUI
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleResourceChangeL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleResourceChangeL(TInt aType)
+ {
+ CAknAppUi::HandleResourceChangeL( aType );
+ if ( iView )
+ {
+ iView->HandleResourceChange( aType );
+ }
+
+ if ( aType == KEikDynamicLayoutVariantSwitch )
+ {
+ iStatusPaneRes = StatusPane()->CurrentLayoutResId();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::SaveBodyL
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgEditorAppUi::SaveBodyL( CMsgBodyControl* aBody )
+ {
+ CEikRichTextEditor* bodyEditor = &aBody->Editor();
+ if ( bodyEditor )
+ {
+ CRichText* richText = bodyEditor->RichText();
+ if ( richText )
+ {
+ TInt len = richText->DocumentLength();
+ if ( len )
+ {
+ HBufC* buf = HBufC::NewLC( len );
+ TPtr ptr = buf->Des();
+ richText->Extract( ptr, 0 );
+ CNotepadApi::AddContentL( ptr );
+ CleanupStack::PopAndDestroy( buf );
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::ShowCloseQueryL
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgEditorAppUi::ShowCloseQueryL()
+ {
+ TInt selectedIndex( 0 );
+ CAknListQueryDialog* dlg = new ( ELeave ) CAknListQueryDialog( &selectedIndex );
+ dlg->PrepareLC( R_MEB_CLOSE_QUERY );
+ if ( dlg->RunLD() )
+ {
+ return ( selectedIndex == 0 )
+ ? EMsgCloseSave
+ : EMsgCloseDelete;
+ }
+ else
+ {
+ return EMsgCloseCancel;
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CreateSubjectPrefixStringL
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC* CMsgEditorAppUi::CreateSubjectPrefixStringL(
+ const TDesC& aSubject,
+ TBool aReply )
+ {
+ HBufC* newSubject = NULL;
+ TInt subjectLength = aSubject.Length();
+ if ( subjectLength >= 0 )
+ {
+ TInt formatResource = aReply
+ ? R_MSG_REPLY_PREFIX
+ : R_MSG_FORWARD_PREFIX;
+
+ HBufC* subjectFormat = StringLoader::LoadLC(
+ formatResource,
+ iCoeEnv );
+
+ HBufC* filteredSubject = RemovePrefixesL( aSubject );
+ CleanupStack::PushL( filteredSubject );
+
+ if ( filteredSubject->Length() > 0 )
+ {
+ // Create a buffer large enough to hold the re-formated subject
+ newSubject = HBufC::NewL( subjectLength + subjectFormat->Length());
+
+ TPtr ptr( newSubject->Des() );
+ ptr.Append( *subjectFormat );
+ ptr.Append( *filteredSubject );
+ }
+ else
+ {
+ newSubject = HBufC::NewL( 0 );
+ }
+
+ CleanupStack::PopAndDestroy( filteredSubject );
+ CleanupStack::PopAndDestroy( subjectFormat );
+ }
+ return newSubject;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::RemovePrefixesL
+// ---------------------------------------------------------
+//
+HBufC* CMsgEditorAppUi::RemovePrefixesL( const TDesC& aSubject )
+ {
+ // filter setup
+ RPointerArray<TDesC> prefixArray;
+ CleanupClosePushL( prefixArray );
+
+ // add prefixes to remove
+ TPtrC filterRe( KMsgEditorAppUiFilterRe );
+ prefixArray.AppendL( &filterRe );
+
+ TPtrC filterFw( KMsgEditorAppUiFilterFw );
+ prefixArray.AppendL( &filterFw );
+
+ TPtrC filterFwd( KMsgEditorAppUiFilterFwd );
+ prefixArray.AppendL( &filterFwd );
+
+ // corresponding prefixes for the current language variant
+ HBufC* prefixReply = StringLoader::LoadLC( R_MSG_REPLY_PREFIX, iCoeEnv );
+ TPtr prefixReplyPtr = prefixReply->Des();
+ prefixReplyPtr.Trim();
+ prefixArray.AppendL( &prefixReplyPtr );
+
+ HBufC* prefixForward = StringLoader::LoadLC( R_MSG_FORWARD_PREFIX, iCoeEnv );
+ TPtr prefixForwardPtr = prefixForward->Des();
+ prefixForwardPtr.Trim();
+ prefixArray.AppendL( &prefixForwardPtr );
+
+ // Remove prefixes
+ HBufC* subject = aSubject.AllocL();
+ TPtr ptr( subject->Des() );
+ TBool prefixFound;
+ // Search until no prefixes found
+ do
+ {
+ // Loop all prefixes
+ prefixFound = EFalse;
+ ptr.TrimLeft();
+ for ( TInt i = 0; i < prefixArray.Count(); i++ )
+ {
+ TPtrC prefix( *prefixArray[i] );
+
+ // Remove prefixes while same prefix found at begining of subject
+ while ( ptr.FindC( prefix ) == 0 )
+ {
+ ptr.Delete( 0, prefix.Length() );
+ prefixFound = ETrue;
+ ptr.TrimLeft();
+ }
+ }
+ } while ( prefixFound );
+
+ CleanupStack::PopAndDestroy(3, &prefixArray );
+
+ return subject;
+ }
+// ---------------------------------------------------------
+// CMsgEditorAppUi::LockEntryL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::LockEntryL()
+ {
+ if ( iLock == NULL )
+ {
+ iLock = CLock::LockL( *Document() );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::UnlockEntry
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::UnlockEntry()
+ {
+ delete iLock;
+ iLock = NULL;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::IsLockedEntry
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgEditorAppUi::IsLockedEntry() const
+ {
+ return iLock != NULL;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::Exit
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::Exit( TInt aReason /*= EEikCmdExit*/ )
+ {
+#ifdef RD_MSG_FAST_PREV_NEXT
+ // Communicate message id via publish and subscribe to MCE
+ RProperty::Set( KPSUidMuiu, KMuiuKeyCurrentMsg,
+ Document()->Entry().Id() );
+#endif // RD_MSG_FAST_PREV_NEXT
+
+ CEikAppServer* server = iEikonEnv->AppServer();
+ if ( server )
+ {
+ server->NotifyServerExit( aReason );
+ }
+ CEikAppUi::Exit();
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleLocalZoomChangeL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleLocalZoomChangeL( TMsgCommonCommands aNewZoom )
+ {
+ TInt localZoom = 0;
+ TInt oldLocalZoom = EAknUiZoomAutomatic;
+ CRepository* repository = CRepository::NewL( KCRUidMessagingUiSettings );
+ TInt ret = repository->Get( KMessagingEditorLocalUiZoom, oldLocalZoom );
+ if ( ret == KErrNone )
+ {
+ switch( aNewZoom )
+ {
+ case EMsgDispSizeAutomatic:
+ {
+ localZoom = EAknUiZoomAutomatic;
+ break;
+ }
+ case EMsgDispSizeLarge:
+ {
+ localZoom = EAknUiZoomLarge;
+ break;
+ }
+ case EMsgDispSizeNormal:
+ {
+ localZoom = EAknUiZoomNormal;
+ break;
+ }
+ case EMsgDispSizeSmall:
+ {
+ localZoom = EAknUiZoomSmall;
+ break;
+ }
+ default:
+ break;
+ }
+ if( oldLocalZoom != localZoom )
+ {
+ ret = repository->Set( KMessagingEditorLocalUiZoom, localZoom );
+ __ASSERT_DEBUG( !ret, Panic( EMsgRepositorySettingFailure ) );
+ TWsEvent event;
+ event.SetType( KAknLocalZoomLayoutSwitch );
+ ret = iEikonEnv->WsSession().SendEventToAllWindowGroups( event );
+ }
+ }
+
+ delete repository;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CreateViewerNaviPaneL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::CreateViewerNaviPaneL( TTime aTime,
+ TMsgEditorMsgPriority aPriority,
+ TBool aUtcTime )
+ {
+ CAknNavigationControlContainer* naviContainer =
+ static_cast<CAknNavigationControlContainer*>( StatusPane()->ControlL(
+ TUid::Uid( EEikStatusPaneUidNavi ) ) );
+ if ( !iNaviDecorator )
+ {
+ CMsgNaviPaneControl* naviPaneControl = CMsgNaviPaneControl::NewL( naviContainer );
+ naviPaneControl->SetNavigationControlObserver( this );
+
+ // naviPaneControl ownership transferred to iNaviDecorator.
+ iNaviDecorator = CAknNavigationDecorator::NewL( naviContainer, naviPaneControl );
+
+ naviPaneControl->SetTimeIndicatorL( aTime, aUtcTime );
+ naviPaneControl->SetPriorityIndicatorL( aPriority );
+
+ CMsgEditorDocument* doc = Document();
+ naviPaneControl->SetNavigationIndicatorL( doc->Session(), doc->Entry() );
+
+ // this function will always be called when viwer is launched
+ // always navi decorater will be created.
+ // refer navi decorator iterator instance here
+ iIterator = naviPaneControl->GetMessageIterator();
+ iIterator->SetMessageIteratorObserver( this );
+
+ iNaviDecorator->SetContainerWindowL( *naviContainer );
+ iNaviDecorator->MakeScrollButtonVisible( EFalse );
+ iNaviDecorator->SetComponentsToInheritVisibility( ETrue );
+ iOwnNaviPane = NULL;
+ }
+ else
+ {
+ User::Leave( KErrAlreadyExists );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleNavigationControlEventL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleNavigationControlEventL( TMsgNaviControlEventId aEvent )
+ {
+ if ( aEvent == MMsgNaviPaneControlObserver::EMsgNaviLeftArrowPressed ||
+ aEvent == MMsgNaviPaneControlObserver::EMsgNaviRightArrowPressed )
+ {
+ if ( IsNextMessageAvailableL( aEvent == MMsgNaviPaneControlObserver::EMsgNaviRightArrowPressed ) )
+ {
+ /* no need for separate checks for right and left arrows
+ because IsNextMessageAvailableL() and NextMessageL
+ are called with the truth-value of the same comparison */
+ NextMessageL( aEvent == MMsgNaviPaneControlObserver::EMsgNaviRightArrowPressed );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CLock::LockL
+//
+//
+// ---------------------------------------------------------
+//
+CMsgEditorAppUi::CLock* CMsgEditorAppUi::CLock::LockL(
+ const CMsgEditorDocument& aDoc)
+ {
+ CLock* lock = new ( ELeave ) CLock();
+ CleanupStack::PushL( lock );
+
+ lock->iStore = aDoc.CurrentEntry().EditStoreL();
+ lock->iStream.AssignL( *( lock->iStore ), KMsvEntryRichTextBody );
+
+ CleanupStack::Pop( lock );
+ return lock;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CLock::CLock
+//
+//
+// ---------------------------------------------------------
+//
+CMsgEditorAppUi::CLock::CLock()
+ {
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CLock::~CLock
+//
+//
+// ---------------------------------------------------------
+//
+CMsgEditorAppUi::CLock::~CLock()
+ {
+ if ( iStore != NULL )
+ {
+ iStream.Release();
+ iStream.Close();
+ iStore->Revert();
+ delete iStore;
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::CanFastOpenL
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgEditorAppUi::CanFastOpenL( const CMessageIterator& /*aIterator*/ )
+ {
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::AknInputBlockCancel
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::AknInputBlockCancel()
+ {
+ if ( iInputBlocker )
+ {
+ iInputBlocker->MakeVisible( EFalse );
+ iInputBlocker->ControlEnv()->AppUi()->RemoveFromStack( iInputBlocker );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::SetTitleIconSizeL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::SetTitleIconSizeL( CFbsBitmap* aTitleBitmap )
+ {
+ TRect mainPane;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ETitlePane, mainPane );
+ TAknLayoutRect titleIconPaneLayoutRect;
+
+ if ( AknStatuspaneUtils::StaconPaneActive() )
+ {
+ titleIconPaneLayoutRect.LayoutRect( mainPane,
+ AknLayoutScalable_Avkon::title_pane_stacon_g1( 0 ).LayoutLine() );
+ }
+ else
+ {
+ titleIconPaneLayoutRect.LayoutRect( mainPane,
+ AknLayoutScalable_Avkon::title_pane_g2( 0 ).LayoutLine() );
+ }
+
+ TSize iconSize = titleIconPaneLayoutRect.Rect().Size();
+
+ User::LeaveIfError( AknIconUtils::SetSize( aTitleBitmap, iconSize, EAspectRatioPreserved ) );
+ }
+
+// ---------------------------------------------------------
+// CMsgEditorAppUi::HandleStatusPaneSizeChange
+//
+// Performs layout switch on view area if statuspane is changed to
+// same statuspane that is used by CMsgEditorAppUi. This is for
+// correcting the layout if layout switch was performed when
+// SMIL player or SMIL editor that use different statuspane
+// were displayed. Without this the layout would be shown as if
+// statuspane that SMIL components use would be used.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgEditorAppUi::HandleStatusPaneSizeChange()
+ {
+ CAknAppUi::HandleStatusPaneSizeChange();
+
+ if ( iView &&
+ iStatusPaneRes == StatusPane()->CurrentLayoutResId() )
+ {
+ iView->HandleResourceChange( KEikDynamicLayoutVariantSwitch );
+ }
+ }
+
+// End of File