diff -r 000000000000 -r 8466d47a6819 emailuis/emailui/src/FreestyleEmailUiMailListVisualiser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emailuis/emailui/src/FreestyleEmailUiMailListVisualiser.cpp Thu Dec 17 08:39:21 2009 +0200 @@ -0,0 +1,7391 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Symbian Foundation License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: This file implements classes CFSEmailUiMailListVisualiser, CMailListUpdater, CMsgMovedNoteTimer, CDateChangeTimer. +* +*/ + + +// SYSTEM INCLUDES +#include "emailtrace.h" +#include +#include +#include +#include +#include +// +#include +// +#include "CFSMailClient.h" +#include "CFSMailBox.h" +#include "CFSMailFolder.h" +#include "fscontrolbar.h" +#include "fscontrolbuttoninterface.h" +#include "fstreelist.h" +#include "fstreevisualizerbase.h" +#include "fstreeplainonelinenodedata.h" +#include "fstreeplainonelinenodevisualizer.h" +#include "fstreeplaintwolineitemdata.h" +#include "fstreeplaintwolineitemvisualizer.h" +#include "CFSMailCommon.h" +#include "ceuiemaillisttouchmanager.h" +// +#include "FSEmailBuildFlags.h" +// +#include "cfsccontactactionmenu.h" +#include "mfsccontactactionmenumodel.h" +// + +#include +#include +// SF +#include +#include +#include +#include +#include +// + +#include +#include +#include +// +#include "ESMailSettingsPluginUids.hrh" +#include "ESMailSettingsPlugin.h" +#include "MFSMailBrandManager.h" +// +#include +// +#include +#include +#include +// +// Meeting request +#include +// +#include "cesmricalviewer.h" +// +#include + +// INTERNAL INCLUDES +#include "FreestyleEmailUiUtilities.h" +#include "FreestyleEmailUiLiterals.h" +#include "FreestyleEmailUiLayoutHandler.h" +#include "FreestyleEmailUiMailListModel.h" +#include "FreestyleEmailUiMailListVisualiser.h" +#include "FreestyleEmailUiFileSystemInfo.h" +#include "FreestyleEmailUiAppui.h" +#include "FreestyleEmailUi.hrh" +#include "FreestyleEmailUiTextureManager.h" +#include "FreestyleEmailUiMailListControl.h" +#include "FreestyleEmailUiMailViewerVisualiser.h" +#include "FreestyleEmailUiStatusIndicator.h" +#include "FreestyleEmailCenRepHandler.h" +#include "FreestyleEmailUiFolderListVisualiser.h" +#include "FreestyleEmailUiShortcutBinding.h" +#include "FreestyleEmailUiMsgDetailsVisualiser.h" +#include "FreestyleEmailDownloadInformationMediator.h" +#include "FreestyleEmailUiContactHandler.h" +#include "FreestyleEmailUiLauncherGridVisualiser.h" +#include "FreestyleEmailUiHtmlViewerView.h" +#include "FSDelayedLoader.h" +#include "FSEmail.pan" + +// CONST VALUES +const TInt KControlBarTransitionTime = 250; +// +//const TInt KFirstButtonStartPosX = 25; +//const TInt KControlBarMailboxIconWidth = 20; +//const TInt KControlButtonPosY = 3; +//const TInt KControlButtonSeparation = 10; +// +const TInt KMaxPreviewPaneLength = 60; +//const TInt KInitialPreviewUpdate = 5; +//const TInt KSyncIconTimerDelay = 18000; +const TInt KMsgUpdaterTimerDelay = 2500000; // Time to update list, 2,5sec +static const TInt KMsgDeletionWaitNoteAmount = 5; +_LIT( KMissingPreviewDataMarker, "..." ); + +static const TInt KMaxItemsFethed = 1000; +static const TInt KCMsgBlock = 100; + +// --------------------------------------------------------------------------- +// Static constructor. +// --------------------------------------------------------------------------- +// +CFSEmailUiMailListVisualiser* CFSEmailUiMailListVisualiser::NewL(CAlfEnv& aEnv, + CFreestyleEmailUiAppUi* aAppUi, + CAlfControlGroup& aMailListControlGroup ) + { + FUNC_LOG; + CFSEmailUiMailListVisualiser* self = CFSEmailUiMailListVisualiser::NewLC(aEnv, aAppUi, aMailListControlGroup ); + CleanupStack::Pop(self); + return self; + } + +// --------------------------------------------------------------------------- +// Static constructor. +// --------------------------------------------------------------------------- +// +CFSEmailUiMailListVisualiser* CFSEmailUiMailListVisualiser::NewLC(CAlfEnv& aEnv, + CFreestyleEmailUiAppUi* aAppUi, + CAlfControlGroup& aMailListControlGroup) + { + FUNC_LOG; + CFSEmailUiMailListVisualiser* self = + new (ELeave) CFSEmailUiMailListVisualiser( aEnv, aAppUi, aMailListControlGroup ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- +// Second phase constructor. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::ConstructL() + { + FUNC_LOG; + + BaseConstructL( R_FSEMAILUI_MAIL_LIST_VIEW ); + + // Don't construct this anywhere else than here. + // Don't delete this until in the destructor to avoid NULL checks. + iModel = CFSEmailUiMailListModel::NewL( &iAppUi ); + + // Set list as initial focused control + iFocusedControl = EMailListComponent; + iThisViewActive = EFalse; + iSkinChanged = EFalse; + + iFirstStartCompleted = EFalse; + + iAsyncCallback = new (ELeave) CAsyncCallBack( CActive::EPriorityStandard ); + iAsyncRedrawer = new (ELeave) CAsyncCallBack( CActive::EPriorityLow ); + } + +// CFSEmailUiMailListVisualiser::DoFirstStartL() +// Purpose of this function is to do first start things only when list is +// really needed to be shown. Implemented to make app startuo faster. +void CFSEmailUiMailListVisualiser::DoFirstStartL() + { + FUNC_LOG; + // Create mail list updater timer + iMailListUpdater = CMailListUpdater::NewL( this ); + + // Set initial sort criteria + iCurrentSortCriteria.iField = EFSMailSortByDate; + iCurrentSortCriteria.iOrder = EFSMailDescending; + + // Create screen control and anchor layout + iMailListControl = CFreestyleEmailUiMailListControl::NewL( iEnv, this ); + iScreenAnchorLayout = CAlfAnchorLayout::AddNewL( *iMailListControl ); + iScreenAnchorLayout->SetFlags(EAlfVisualFlagAutomaticLocaleMirroringEnabled); + + // + iTouchManager = CEUiEmailListTouchManager::NewL(*this); + // + + // Create control bar control and append to control group and anchor layout + iControlBarControl = CFsControlBar::NewL( iEnv ); + iControlBarControl->AddObserverL( *this ); + // + iControlBarControl->AddObserverL( *iTouchManager ); + // + + CreateControlBarLayoutL(); + SetMailListLayoutAnchors(); + + iControlBarControl->SetSelectorTransitionTimeL( KControlBarTransitionTime ); + iControlBarControl->ClearBackgroundColor(); + iControlBarLayout = CAlfDeckLayout::AddNewL( *iControlBarControl, iScreenAnchorLayout ); + iControlBarVisual = iControlBarControl->Visual(); + + // Create list and append to control group and anchor layout + + iListLayout = CAlfDeckLayout::AddNewL( *iMailListControl, iScreenAnchorLayout ); + iMailTreeListVisualizer = CFsTreeVisualizerBase::NewL(iMailListControl, *iListLayout); + iMailTreeListVisualizer->SetFlipState( iKeyboardFlipOpen ); + iMailTreeListVisualizer->SetFocusVisibility( iFocusVisible ); + iMailList = CFsTreeList::NewL(*iMailTreeListVisualizer, iEnv ); + + // Set mark type and icon + iMailList->SetMarkTypeL( CFsTreeList::EFsTreeListMultiMarkable ); + iMailList->SetIndentationL(0); + + // Compared to S60 3.2.3 in S60 5.0 Alf offers the key events in + // opposite order. + ControlGroup().AppendL( iMailListControl ); + ControlGroup().AppendL( iControlBarControl ); + ControlGroup().AppendL( iMailList->TreeControl() ); + // + + iTreeItemArray.Reset(); + + // Set empty text + HBufC* emptyText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_EMPTY_MSG_LIST_TEXT ); + iMailTreeListVisualizer->SetEmptyListTextL( *emptyText ); + CleanupStack::PopAndDestroy( emptyText ); + + TRgb normalColor = iAppUi.LayoutHandler()->ListNormalStateTextSkinColor(); + iMailTreeListVisualizer->RootNodeVisualizer()->SetNormalStateTextColor( normalColor ); + + // Set page up and page down keys + iMailTreeListVisualizer->AddCustomPageUpKey( EStdKeyPageUp ); + iMailTreeListVisualizer->AddCustomPageDownKey( EStdKeyPageDown ); + + // Set selector brushes + CAlfBrush* listSelectorBrush = iAppUi.FsTextureManager()->ListSelectorBrushL(); // not owned + iMailTreeListVisualizer->SetSelectorPropertiesL( listSelectorBrush, 1.0, CFsTreeVisualizerBase::EFsSelectorMoveSmoothly ); + + CAlfBrush* cbSelectorBrush = iAppUi.FsTextureManager()->NewCtrlBarSelectorBrushLC(); + iControlBarControl->SetSelectorImageL( cbSelectorBrush ); + CleanupStack::Pop( cbSelectorBrush ); // ownership transferred to control bar + + // Set menu, mark and background icons + iMailTreeListVisualizer->SetMarkIcon( iAppUi.FsTextureManager()->TextureByIndex( EListControlMarkIcon ) ); + iMailTreeListVisualizer->SetMenuIcon( iAppUi.FsTextureManager()->TextureByIndex( EListControlMenuIcon ) ); + // s60 skin support + //iMailTreeListVisualizer->SetBackgroundTextureL( iAppUi.FsTextureManager()->TextureByIndex( EBackgroundTextureMailList ) ); + // + iMailList->AddObserverL( *this ); + // + iMailList->AddObserverL( *iTouchManager ); + // + // Initializing the default stylus long tap popup menu + if( !iStylusPopUpMenu ) + { + TPoint point( 0, 0 ); + iStylusPopUpMenu = CAknStylusPopUpMenu::NewL( this , point ); + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC( reader, + R_STYLUS_POPUP_MENU_MESSAGE_LIST_VIEW ); + iStylusPopUpMenu->ConstructFromResourceL( reader ); + CleanupStack::PopAndDestroy(); + } + + iAppUi.LayoutHandler()->SetListMarqueeBehaviour( iMailList ); + + iDateChangeTimer = CDateChangeTimer::NewL( *this ); + iDateChangeTimer->Start(); + + UpdateMailListSettingsL(); + + iMailList->SetIndentationL(0); + iMailList->SetLoopingType( EFsTreeListLoopingDisabled ); + iMailTreeListVisualizer->SetItemExpansionDelay( iAppUi.LayoutHandler()->ListItemExpansionDelay() ); + iMailList->SetScrollTime( iAppUi.LayoutHandler()->ListScrollingTime(), 0.5 ); + + iFirstStartCompleted = ETrue; + } + + +// --------------------------------------------------------------------------- +// Constructor. +// --------------------------------------------------------------------------- +// +CFSEmailUiMailListVisualiser::CFSEmailUiMailListVisualiser( CAlfEnv& aEnv, + CFreestyleEmailUiAppUi* aAppUi, CAlfControlGroup& aMailListControlGroup ) + : CFsEmailUiViewBase( aMailListControlGroup, *aAppUi ), + iEnv( aEnv ), + iListMarkItemsState( ETrue ), //Initlly list has no markings + iMoveToFolderOngoing( EFalse ) + { + FUNC_LOG; + } + +// --------------------------------------------------------------------------- +// Destructor. +// --------------------------------------------------------------------------- +// +CFSEmailUiMailListVisualiser::~CFSEmailUiMailListVisualiser() + { + FUNC_LOG; + // + if ( iMailFolder ) + { + delete iMailFolder; + iMailFolder = NULL; + } + + delete iTouchManager; + delete iStylusPopUpMenu; + // + delete iMailList; + + // Don't construct this anywhere else than in constructor. + // Don't delete anywhere else thatn here to avoid NULL checks. + delete iModel; + } + +void CFSEmailUiMailListVisualiser::PrepareForExit() + { + FUNC_LOG; + if ( iMsgNoteTimer ) + { + iMsgNoteTimer->Cancel(); + delete iMsgNoteTimer; + iMsgNoteTimer = NULL; + } + if ( iDateChangeTimer ) + { + iDateChangeTimer->Cancel(); + delete iDateChangeTimer; + iDateChangeTimer = NULL; + } + if ( iMailListUpdater ) + { + iMailListUpdater->Stop(); + delete iMailListUpdater; + iMailListUpdater = NULL; + } + if ( iAsyncRedrawer ) + { + iAsyncRedrawer->Cancel(); + delete iAsyncRedrawer; + iAsyncRedrawer = NULL; + } + if ( iAsyncCallback ) + { + iAsyncCallback->Cancel(); + delete iAsyncCallback; + iAsyncCallback = NULL; + } + if ( iMailList ) + { + iMailList->RemoveObserver( *this ); + } + if ( iControlBarControl ) + { + iControlBarControl->RemoveObserver( *this ); + } + // + iTreeItemArray.Reset(); + if ( iMailFolder ) + { + delete iMailFolder; + iMailFolder = NULL; + } + // Reset, not delete to avoid NULL checks. + iModel->Reset(); + // + } + +// --------------------------------------------------------------------------- +// Returns reference to mail list. +// --------------------------------------------------------------------------- +// +CFsTreeList& CFSEmailUiMailListVisualiser::GetMailList() + { + FUNC_LOG; + return *iMailList; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdateMailListModelL() + { + FUNC_LOG; + // Reset model with each update + iModel->Reset(); + + if ( iMailFolder ) + { + // Update folder if provided, otherwise use current folder + RPointerArray folderMessages( KCMsgBlock ); + CleanupClosePushL( folderMessages ); + + RPointerArray tempFolderMessages( KCMsgBlock ); + CleanupClosePushL( tempFolderMessages ); + + TFSMailDetails details( EFSMsgDataEnvelope ); + RArray sorting; + CleanupClosePushL( sorting ); + sorting.Append( iCurrentSortCriteria ); + if ( iCurrentSortCriteria.iField != EFSMailSortByDate ) + { + // Add date+descending as secondary sort criteria if primary field is something else than date + TFSMailSortCriteria secondarySortCriteria; + secondarySortCriteria.iField = EFSMailSortByDate; + secondarySortCriteria.iOrder = EFSMailDescending; + sorting.Append( secondarySortCriteria ); + } + + // List all or maximum number of messages + MFSMailIterator* iterator = iMailFolder->ListMessagesL( details, sorting ); + CleanupDeletePushL( iterator ); // standard CleanupStack::PushL does not work with non-C-class pointer + + // Use iterator to get messages in peaces of KCMsgBlock to avoid OOM in FSStore + TFSMailMsgId dummy; + TBool moreMessagesToFollow = iterator->NextL( dummy, KCMsgBlock, folderMessages ); + for ( TInt i = KCMsgBlock; i < KMaxItemsFethed && moreMessagesToFollow ; i += KCMsgBlock ) + { + tempFolderMessages.Reset(); + moreMessagesToFollow = iterator->NextL( folderMessages[i-1]->GetMessageId(), KCMsgBlock, tempFolderMessages ); + for ( TInt a=0 ; a& aMessages ) + { + FUNC_LOG; + // New Items + CFSEmailUiMailListModelItem* newItem(NULL); + + // Draw first separator if there are messages. + if ( aMessages.Count() && iNodesInUse == EListControlSeparatorEnabled ) + { + newItem = CreateSeparatorModelItemLC( *aMessages[0] ); + iModel->AppendL( newItem ); + CleanupStack::Pop( newItem ); + } + + // Start appending items + for (int i = 0; i < aMessages.Count(); i++) + { + CFSMailMessage* curMessage = aMessages[i]; + if ( curMessage ) + { + newItem = CFSEmailUiMailListModelItem::NewL( curMessage, ETypeMailItem ); + CleanupStack::PushL( newItem ); + iModel->AppendL( newItem ); + CleanupStack::Pop( newItem ); + + // Append new separator if needed + if ( i != aMessages.Count()-1 && iNodesInUse == EListControlSeparatorEnabled ) + { + CFSMailMessage* nextMessage = aMessages[i+1]; // This msg is next in the list + + if ( nextMessage ) + { + TBool needANewDivider = + !MessagesBelongUnderSameSeparatorL( *curMessage, *nextMessage ); + if ( needANewDivider ) + { + newItem = CreateSeparatorModelItemLC( *nextMessage ); + iModel->AppendL( newItem ); + CleanupStack::Pop( newItem ); + } + } + } + } + } + } + +// --------------------------------------------------------------------------- +// CreateSeparatorModelItemLC +// Create separator model item for the given message. Separator text depends +// on active sorting mode. +// --------------------------------------------------------------------------- +// +CFSEmailUiMailListModelItem* CFSEmailUiMailListVisualiser::CreateSeparatorModelItemLC( CFSMailMessage& aMessage ) const + { + FUNC_LOG; + CFSEmailUiMailListModelItem* separator = + CFSEmailUiMailListModelItem::NewL( &aMessage, ETypeSeparator ); + CleanupStack::PushL( separator ); + + HBufC* separatorText = NULL; + + switch ( iCurrentSortCriteria.iField ) + { + case EFSMailSortByFlagStatus: + { + if ( aMessage.IsFlagSet( EFSMsgFlag_FollowUp ) ) + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_FOLLOW_UP ); + } + else if ( aMessage.IsFlagSet( EFSMsgFlag_FollowUpComplete ) ) + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_FLAG_COMPLETE ); + } + else + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_NO_FLAG ); + } + } + break; + case EFSMailSortByPriority: + { + if ( aMessage.IsFlagSet( EFSMsgFlag_Important ) ) + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_PRIO_HIGH ); + } + else if ( aMessage.IsFlagSet( EFSMsgFlag_Low ) ) + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_PRIO_LOW ); + } + else + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_PRIO_NORMAL ); + } + } + break; + case EFSMailSortByRecipient: + case EFSMailSortBySender: + { + TInt folderType(EFSInbox); + if( iMailFolder ) + { + folderType = iMailFolder->GetFolderType(); + } + TBool useRecipient = ( folderType == EFSSentFolder || + folderType == EFSDraftsFolder || + folderType == EFSOutbox ); + + CFSMailAddress* fromAddress(0); + // Check address based on whether we are using recipient or sender sort + if ( useRecipient ) + { + RPointerArray& toArray = aMessage.GetToRecipients(); + if ( toArray.Count() ) + { + fromAddress = toArray[0]; + } + } + else + { + fromAddress = aMessage.GetSender(); + } + TDesC* diplayName(0); + if ( fromAddress ) + { + diplayName = &fromAddress->GetDisplayName(); + } + + if ( fromAddress && diplayName && diplayName->Length() != 0 ) + { + separatorText = diplayName->AllocLC(); + } + else if ( fromAddress && fromAddress->GetEmailAddress().Length() != 0 ) + { + separatorText = fromAddress->GetEmailAddress().AllocLC(); + } + else + { + if ( useRecipient ) + { + separatorText = KNullDesC().AllocLC(); + } + else + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_NO_SENDER_INFO_AVAILABLE ); + } + } + // Get rid of possible unwanted characters in display name + if ( separatorText ) + { + TFsEmailUiUtility::StripDisplayName( *separatorText ); + } + } + break; + case EFSMailSortByAttachment: + { + if ( aMessage.IsFlagSet( EFSMsgFlag_Attachments ) ) + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_ATTACHMENTS ); + } + else + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_NO_ATTACHMENTS ); + } + } + break; + case EFSMailSortByUnread: + { + if ( aMessage.IsFlagSet( EFSMsgFlag_Read ) ) + { + separatorText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SEPARATOR_READ_MSGS ); + } + else + { + separatorText = StringLoader::LoadLC(R_FREESTYLE_EMAIL_UI_SEPARATOR_UNREAD_MSGS); + } + } + break; + case EFSMailSortBySubject: + { + separatorText = TFsEmailUiUtility::CreateSubjectWithoutLocalisedPrefixLC( &aMessage ); + } + break; + case EFSMailSortByDate: + { + TBool eventToday = EFalse; + TBool eventYesterday = EFalse; + HBufC* weekDay = TFsEmailUiUtility::WeekDayTextFromMsgLC( &aMessage, ETrue, EFalse, eventToday, eventYesterday ); + if ( eventToday || eventYesterday ) + { + separatorText = weekDay; + } + else + { + HBufC* dateTextFromMsg = TFsEmailUiUtility::DateTextFromMsgLC( &aMessage ); + separatorText = HBufC::NewL( weekDay->Length() + + KSpace().Length() + + dateTextFromMsg->Length() ); + separatorText->Des().Append( *weekDay ); + separatorText->Des().Append( KSpace ); + separatorText->Des().Append( *dateTextFromMsg ); + CleanupStack::PopAndDestroy( dateTextFromMsg ); + CleanupStack::PopAndDestroy( weekDay ); + CleanupStack::PushL( separatorText ); + } + } + break; + default: + { + separatorText = KNullDesC().AllocLC(); + } + break; + } + + separator->SetSeparatorTextL( *separatorText ); + CleanupStack::PopAndDestroy( separatorText ); + + return separator; + } + +// --------------------------------------------------------------------------- +// MessagesBelongUnderSameSeparatorL +// Checks if the given messages belong under the same title divider. This +// depends on the currect sorting mode. +// --------------------------------------------------------------------------- +// +TBool CFSEmailUiMailListVisualiser::MessagesBelongUnderSameSeparatorL( + const CFSMailMessage& aMessage1, + const CFSMailMessage& aMessage2 ) const + { + FUNC_LOG; + return CFSEmailUiMailListModel::MessagesBelongUnderSameSeparatorL( aMessage1, + aMessage2, + iCurrentSortCriteria.iField ); + } + +// --------------------------------------------------------------------------- +// InsertNewMessagesL +// Gets new message items from the framework using the given IDs and inserts +// them in the correct place within the mail list. Both model and tree list +// are updated during this function. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::InsertNewMessagesL( const RArray& aMessages ) + { + FUNC_LOG; + iModel->SetSortCriteria( iCurrentSortCriteria ); + + // Do complete refresh in case the list is not currently correctly ordered + // (alternatively, we could first reorder the existing items and then insert + // the new ones) + if ( iListOrderMayBeOutOfDate ) + { + if ( iMailListUpdater ) + { + if ( iMailListUpdater->IsActive() ) + { + iMailListUpdater->Stop(); + } + iMailListUpdater->StartL(); + } + } + // Otherwise, just add the new items to correct places. + else + { + // Set extended status before inserting messages + SetMailListItemsExtendedL(); + TInt count(0); + count = aMessages.Count(); + for ( TInt i = 0 ; i < count ; ++i ) + { + // Make sure we don't add duplicate items. + TInt existingIdx = ItemIndexFromMessageId( aMessages[i] ); + if ( existingIdx < 0 ) + { + CFSMailMessage* msgPtr = iAppUi.GetMailClient()->GetMessageByUidL( iAppUi.GetActiveMailboxId(), + iMailFolder->GetFolderId(), + aMessages[i] , + EFSMsgDataEnvelope ); + if (msgPtr == NULL) + { + User::Leave(KErrNotFound); + } + CleanupStack::PushL( msgPtr ); + //first item - show scrollbar + //last item - updete scrollbar + TBool allowRefresh = ( i == 0 || i == count - 1 ); + InsertNewMessageL( msgPtr, allowRefresh ); + CleanupStack::Pop( msgPtr ); // ownership transferred to model + } + } + } + } + +// --------------------------------------------------------------------------- +// InsertNewMessageL +// Creates a single new message item to the model and tree list from the given +// message pointer. Ownership of the message is transferred. Also new +// separator item is created if necessary. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::InsertNewMessageL( CFSMailMessage* aNewMessage, const TBool aAllowRefresh ) + { + FUNC_LOG; + // Use simple heuristic rule: if the first item is highlighted before the new + // item is added, the highlight is forced to remain on the (possibly new) first + // item. Otherwise the highligh stays on the same item as before. + TBool firstItemWasFocused = + ( iTreeItemArray.Count() && iTreeItemArray[0].iListItemId == iMailList->FocusedItem() ); + + CFSEmailUiMailListModelItem* newItem = + CFSEmailUiMailListModelItem::NewLC( aNewMessage, ETypeMailItem ); + TInt idx = KErrNotFound; + TFsTreeItemId parentId = KFsTreeRootID; + TInt childIdx = KErrNotFound; + + if ( !iNodesInUse ) + { + // Simple case: nodes are not in use. Just insert to correct place under root node. + idx = iModel->GetInsertionPointL( *newItem ); + childIdx = idx; + } + else + { + // More complicated case: nodes are in use. + TInt parentIdx = KErrNotFound; + idx = iModel->GetInsertionPointL( *newItem, childIdx, parentIdx ); + + CFSEmailUiMailListModelItem* parentNode = NULL; + if ( parentIdx < 0 ) + { + // Suitable parent node for the new item was not found and has to be created. + parentNode = CreateSeparatorModelItemLC( *aNewMessage ); + iModel->InsertL( parentNode, idx ); + CleanupStack::Pop( parentNode ); + idx++; // The originally found index was used for the new node and the new item will reside in the next index + + // To insert the node item to the tree list, we need to figure out the index of the + // new node under the root node. If the new item is not the last item in the list, + // then the insertion location currently contains the node in front of which the new + // node is inserted. + if ( idx == iModel->Count() ) + { + InsertNodeItemL( idx-1, KErrNotFound, aAllowRefresh ); // append + } + else + { + CFSEmailUiMailListModelItem* nextNode = + static_cast( iModel->Item(idx) ); + TFsTreeItemId nextNodeId = nextNode->CorrespondingListId(); + TInt nodeIdxUnderRoot = iMailList->ChildIndex( KFsTreeRootID, nextNodeId ); + InsertNodeItemL( idx-1, nodeIdxUnderRoot, aAllowRefresh ); + } + } + else + { + // Suitable parent node exists and was found + parentNode = static_cast( iModel->Item(parentIdx) ); + } + parentId = parentNode->CorrespondingListId(); + } + + // Insert the model item + iModel->InsertL( newItem, idx ); + CleanupStack::Pop( newItem ); + + // Insert the tree list item + InsertListItemL( idx, parentId, childIdx, aAllowRefresh ); + + // Move focus after insertion if necessary + if ( firstItemWasFocused ) + { + TFsTreeItemId firstItemId = iMailList->Child( KFsTreeRootID, 0 ); + TFsTreeItemId focusedId = iMailList->FocusedItem(); + + if ( firstItemId != focusedId ) + { + // Set the first item as focused and set + // list/ctrl bar focus according iFocusedControl + // + //iMailList->SetFocusedItemL( firstItemId ); + iMailTreeListVisualizer->SetFocusedItemL( firstItemId, EFalse ); + // + SetListAndCtrlBarFocusL(); + } + } + } + +// --------------------------------------------------------------------------- +// HighlightedIndex +// This function return highlighted inxed +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::HighlightedIndex() const + { + FUNC_LOG; + TFsTreeItemId focusedId = static_cast( iMailList->FocusedItem() ); + // Map id to the index in model + TInt ret( KErrNotFound ); + if ( focusedId != KFsTreeNoneID ) + { + for ( TInt i=0; i= 0 ) + { + iMailTreeListVisualizer->SetFocusedItemL( iTreeItemArray[aWantedIndex].iListItemId ); + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::NewEmailsInModelL() const + { + FUNC_LOG; + // + TInt newCount(0); + for ( TInt i=0; iCount();i++) + { + CFSEmailUiMailListModelItem* item = + static_cast(iModel->Item(i)); + if ( item->ModelItemType() == ETypeMailItem ) + { + if ( !item->MessagePtr().IsFlagSet(EFSMsgFlag_Read) ) + { + newCount++; + } + } + } + return newCount; + // + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::EmailsInModelL() const + { + FUNC_LOG; + // + TInt ret(0); + for ( TInt i=0; iCount(); i++ ) + { + CFSEmailUiMailListModelItem* item = + static_cast(iModel->Item(i)); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + ret++; + } + } + return ret; + // + } + + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TUid CFSEmailUiMailListVisualiser::Id() const + { + FUNC_LOG; + return MailListId; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +// Toolbar +/*void CFSEmailUiMailListVisualiser::DoActivateL(const TVwsViewId& aPrevViewId, + TUid aCustomMessageId, + const TDesC8& aCustomMessage)*/ +// Toolbar +void CFSEmailUiMailListVisualiser::ChildDoActivateL(const TVwsViewId& aPrevViewId, + TUid aCustomMessageId, + const TDesC8& aCustomMessage) + { + FUNC_LOG; + iShowReplyAll = EFalse; + + if ( !iFirstStartCompleted ) + { + DoFirstStartL(); + } + + // Make sure that pending popup is not displayd + if ( iAppUi.FolderList().IsPopupShown() ) + { + iAppUi.FolderList().HidePopupL(); + } + + // inform baseView if view entered with forward navigation + TBool forwardNavigation = EFalse; + if ( aCustomMessageId != KStartListReturnToPreviousFolder && + aCustomMessageId != TUid::Uid(KMailSettingsReturnFromPluginSettings) ) + { + ViewEntered( aPrevViewId ); + forwardNavigation = ETrue; + } + + // Set control bar and list layout size always in activation + TRect clientRect = iAppUi.ClientRect(); + iScreenAnchorLayout->SetSize( clientRect.Size() ); + SetMailListLayoutAnchors(); + TInt listHeight = clientRect.Height() - iAppUi.LayoutHandler()->ControlBarHeight(); + iListLayout->SetSize( TSize( clientRect.Width(), listHeight ) ); // needs to be set separately to avoid layout problems in some special cases + ScaleControlBarL(); + SetListAndCtrlBarFocusL(); + + // Update mail list settings and date formats, is done every time + // the user might have changed these in settings, so the list needs to refresh + // Store previous modes + TInt prevListMode = iListMode; + TInt prevNodesmode = iNodesInUse; + TAknUiZoom prevZoomLevel = iCurrentZoomLevel; + STimeDateFormats prevDateFormats = MailListTimeDateSettings(); + + // Get new settings and list drawing modes + CAknEnv::Static()->GetCurrentGlobalUiZoom( iCurrentZoomLevel ); + UpdateMailListSettingsL(); + UpdateMailListTimeDateSettings(); + + // Check for changed settings, in that case a complete list refresh is needed + TBool refreshNeeded(EFalse); + if ( iSkinChanged + || iDateChanged + || iListMode != prevListMode + || iNodesInUse != prevNodesmode + || iCurrentZoomLevel != prevZoomLevel + || prevDateFormats.iDateFormat != iDateFormats.iDateFormat + || prevDateFormats.iTimeFormat != iDateFormats.iTimeFormat + || prevDateFormats.iAmPmPosition != iDateFormats.iAmPmPosition + || prevDateFormats.iDateSeparator != iDateFormats.iDateSeparator + || prevDateFormats.iTimeSeparator != iDateFormats.iTimeSeparator ) + { + refreshNeeded = ETrue; + iSkinChanged = EFalse; + iDateChanged = EFalse; + } + + // Store previously used mailbox and folder IDs + TFSMailMsgId prevMailBoxId = iAppUi.GetActiveMailboxId(); + TFSMailMsgId prevFolderId = FolderId(); + + CFSMailClient* mailClient = iAppUi.GetMailClient(); + User::LeaveIfNull( mailClient ); // we can't go on if no mail client is available + + // FIGURE OUT WHICH FOLDER TO ACTIVATE + TMailListActivationData activationData; + + // Opening folder given in custom message + if ( aCustomMessage.Length() ) + { + TPckgBuf viewData; + viewData.Copy( aCustomMessage ); + activationData = viewData(); + } + + // Returning to previous folder + if ( aCustomMessageId == KStartListReturnToPreviousFolder || + aCustomMessageId == TUid::Uid(KMailSettingsReturnFromPluginSettings) ) + { + activationData.iMailBoxId = prevMailBoxId; + activationData.iFolderId = prevFolderId; + } + + // Proper mailbox ID is not given in custom message. Try using MSV session. + if ( activationData.iMailBoxId.IsNullId() ) + { + CMsvSession* msvSession = iAppUi.GetMsvSession(); + CFSMailBox* mailBox = NULL; + + if ( msvSession ) + { + // MSV id is passed to us in aCustomMessageId when activation happens by email key + if ( aCustomMessageId != TUid::Null() ) + { + // + TInt error = KErrNone; + TRAP( error, mailBox = TFsEmailUiUtility::GetMailboxForMtmIdL( *mailClient, *msvSession, aCustomMessageId.iUid ) ); + // + if ( mailBox ) + { + activationData.iMailBoxId = mailBox->GetId(); + delete mailBox; + mailBox = NULL; + } + } + + // Try to get MCE default mailbox if we still haven't got any other box + if ( activationData.iMailBoxId.IsNullId() ) + { + // + TInt error = KErrNone; + TRAP( error, mailBox = TFsEmailUiUtility::GetMceDefaultMailboxL( *mailClient, *msvSession ) ); + // + if ( mailBox ) + { + activationData.iMailBoxId = mailBox->GetId(); + delete mailBox; + mailBox = NULL; + } + } + } + + } + + // If still no mailbox then use first from the list of the framework + if ( activationData.iMailBoxId.IsNullId() ) + { + TFSMailMsgId id; + RPointerArray mailboxes; + CleanupResetAndDestroyClosePushL( mailboxes ); + mailClient->ListMailBoxes( id, mailboxes ); + if ( mailboxes.Count() > 0 ) + { + activationData.iMailBoxId = mailboxes[0]->GetId(); + } + CleanupStack::PopAndDestroy( &mailboxes ); + } + + + // Check if we got any mailbox + if ( activationData.iMailBoxId.IsNullId() ) + { + // could not get mailbox so leave + User::Leave( KErrGeneral ); + } + else + { + // Set the active mailbox of AppUi. Do this also when mailbox hasn't actually + // changed to do the autoconnect when necessary and to verify that the previously + // active mailbox is still valid. + // Leave is caused if mailbox is no longer available, and BaseView will take care + // of the error handling. + iAppUi.SetActiveMailboxL( activationData.iMailBoxId, forwardNavigation ); + + // we got mailbox but no folder has been given => use Inbox + if ( activationData.iFolderId.IsNullId() || + activationData.iFolderId.Id() == 0 ) + { + activationData.iFolderId = iAppUi.GetActiveBoxInboxId(); + } + } + + // NOW WE HAVE A VALID MAILBOX AND FOLDER ID. + + // CHECK IF MODEL NEEDS TO BE UPDATED + if ( activationData.iMailBoxId != prevMailBoxId || + activationData.iFolderId != prevFolderId || + activationData.iRequestRefresh ) + { + // Set initial sort criteria when folder is changed + iCurrentSortCriteria.iField = EFSMailSortByDate; + iCurrentSortCriteria.iOrder = EFSMailDescending; + SetSortButtonTextAndIconL(); + + delete iMailFolder; + iMailFolder = NULL; + TRAP_IGNORE( iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( + activationData.iMailBoxId, activationData.iFolderId ) ); + if ( !iMailFolder ) + { + // Safety, try to revert back to standard folder inbox + TFSMailMsgId inboxId = iAppUi.GetActiveMailbox()->GetStandardFolderId( EFSInbox ); + iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( activationData.iMailBoxId, inboxId ); + } + HBufC* newFolderName = CreateFolderNameLC( iMailFolder ); + iFolderListButton->SetTextL( *newFolderName ); + CleanupStack::PopAndDestroy( newFolderName ); + iMailList->SetFocusedItemL( KFsTreeNoneID ); + refreshNeeded = ETrue; + } + + // Set mailbox name to status pane + SetMailboxNameToStatusPaneL(); + + // Set branded watermark and mailbox icon + SetBrandedListWatermarkL(); + SetBrandedMailBoxIconL(); + + // Check sync icon timer and sync status + ConnectionIconHandling(); + +// + iMailList->HideListL(); + iMailList->ShowListL(); +// + // REBUILD TREE LIST IF NECESSARY + if ( refreshNeeded ) + { + // Try to maintain previously active item if possible. + // This is of course not possible if folder has changed. + TFSMailMsgId focused = MsgIdFromListId( iMailList->FocusedItem() ); + + // Clear any previous items from the screen and then make the view visible + iMailList->RemoveAllL(); + iTreeItemArray.Reset(); + UpdateMailListModelL(); + RefreshDeferred( &focused ); + } + + // THE CORRECT FOLDER IS ALREADY OPEN. CHECK IF SOME PARTIAL UPDATE IS NEEDED. + else + { + // hide & show list to force it to adept to changed screen size + // + /*if ( iCurrentClientRect != clientRect ) + { + iMailList->HideListL(); + iMailList->ShowListL(); */ + SetListAndCtrlBarFocusL(); // ShowListL() makes list focused and this may need to be reverted +// } + // + UnmarkAllItemsL(); + + if ( aCustomMessageId == TUid::Uid(KMailSettingsReturnFromPluginSettings) ) + { + // Better to refresh launcher grid view because mailbox branding might be changed. + iAppUi.LauncherGrid().SetRefreshNeeded(); + } + + // Check the validity of focused message, it may be deleted or + // reply/forward, read/unread status might have changed in editor or viewer + UpdateItemAtIndexL( HighlightedIndex() ); + SetMskL(); + } + + iCurrentClientRect = clientRect; + iThisViewActive = ETrue; + + // Set email indicator off.. user has checked the new emails + TFsEmailUiUtility::ToggleEmailIconL(EFalse); + + iShiftDepressed = EFalse; // clear state just in case + + // Inform MR observer if needed, special MR case, returning from attachment list + iAppUi.MailViewer().CompletePendingMrCommand(); +// + //Make sure that correct component is set to focused. + if ( iFocusedControl == EMailListComponent ) + SetTreeListFocusedL(); + else + SetControlBarFocusedL(); +// + + iAppUi.ShowTitlePaneConnectionStatus(); + } + +// --------------------------------------------------------------------------- +// Sets status bar layout +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SetStatusBarLayout() + { + if ( StatusPane()->CurrentLayoutResId() != R_AVKON_STATUS_PANE_LAYOUT_IDLE_FLAT ) + { + TRAP_IGNORE( + StatusPane()->SwitchLayoutL( R_AVKON_STATUS_PANE_LAYOUT_IDLE_FLAT )); + } + } + + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::ChildDoDeactivate() + { + FUNC_LOG; + if ( !iAppUi.AppUiExitOngoing() ) + { + TRAP_IGNORE( { + iMailList->SetFocusedL( EFalse ); + } ); + iMailTreeListVisualizer->NotifyControlVisibilityChange( EFalse ); + } + iThisViewActive = EFalse; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +CFSEmailUiMailListModel* CFSEmailUiMailListVisualiser::Model() + { + FUNC_LOG; + return iModel; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TFSMailMsgId CFSEmailUiMailListVisualiser::FolderId() + { + FUNC_LOG; + TFSMailMsgId folderId; // constructs null ID + if ( iMailFolder ) + { + folderId = iMailFolder->GetFolderId(); + } + return folderId; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane) + { + FUNC_LOG; + CompletePendingRefresh(); + + // Get the list of items which will be targetted by the actions menu commands + RFsTreeItemIdList targetEntries; + CleanupClosePushL( targetEntries ); + GetActionsTargetEntriesL( targetEntries ); + + TBool supportsMoving = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaMoveToFolder ); + TBool supportsFlag = TFsEmailUiUtility::IsFollowUpSupported( *iAppUi.GetActiveMailbox() ); + + TInt currentFolderType = KErrNotFound; + if ( iMailFolder ) + { + currentFolderType = iMailFolder->GetFolderType(); + } + + // MAIN MENU *************************************************************************** + if ( aResourceId == R_FSEMAILUI_MAILLIST_MENUPANE ) + { + if (FeatureManager::FeatureSupported( KFeatureIdFfCmailIntegration )) + { + // remove help support in pf5250 + aMenuPane->SetItemDimmed( EFsEmailUiCmdHelp, ETrue); + } + + // Checks if a device has a keyboard or not. + if( !iKeyboardFlipOpen ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsOpen, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdMailActions, ETrue); + aMenuPane->SetItemDimmed( EFsEmailUiCmdReadEmail, ETrue ); + } + + // OFFLINE/ONLINE MENU SELECTION + TFSMailBoxStatus onlineStatus = iAppUi.GetActiveMailbox()->GetMailBoxStatus(); + aMenuPane->SetItemDimmed( EFsEmailUiCmdGoOnline, onlineStatus == EFSMailBoxOnline ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdGoOffline, onlineStatus == EFSMailBoxOffline ); + + // Sync/cancel sync + TBool supportsSync = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaSupportsSync ); + if ( !supportsSync ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdCancelSync, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdSync, ETrue ); + } + else if ( GetLatestSyncState() ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdSync, ETrue ); + } + else + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdCancelSync, ETrue ); + } + + //MESSAGEREADER MENU SELECTION + if ( iAppUi.MessageReaderSupportsFreestyle() ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdReadEmail, EFalse ); + } + else + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdReadEmail, ETrue ); + } + // Disable read in outbox and drafts + if ( currentFolderType == EFSDraftsFolder || + currentFolderType == EFSOutbox ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdReadEmail, ETrue ); + } + + // EMPTY LIST, MOST OPTIONS ARE HIDDEN + if ( !iModel->Count() || !iMailFolder ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsOpen, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdMailActions, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdMore, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdSearch, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdReadEmail, ETrue ); + } + + // NO TARGET ITEMS, E.G FOCUS ON DIVIDER AND NO MARKED ITEMS, ITEM RELATED OPTIONS ARE HIDDEN + else if ( !targetEntries.Count() ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdMailActions, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdReadEmail, ETrue ); + } + + // Open command is available only if there's exactly one target item + if ( targetEntries.Count() != 1 ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsOpen, ETrue ); + } + + // FOLDER SPECIFIC COMMAND HIDING + // In the outbox folder, Open command is inavailable in any case + if ( currentFolderType == EFSOutbox ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsOpen, ETrue ); + } + + // "Clear deleted folder" command is available only in Deleted folder + if ( currentFolderType != EFSDeleted || !iModel->Count() ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsEmptyDeleted, ETrue ); + } + } + // MAIN MENU *************************************************************************** + + + // ACTIONS SUBMENU ********************************************************************* + if ( aResourceId == R_FSEMAILUI_MAILLIST_SUBMENU_MAIL_ACTIONS ) + { + // Actions menu should never be available when there's no marked or focused item(s) + __ASSERT_DEBUG( targetEntries.Count(), Panic(EFSEmailUiUnexpectedValue) ); + + CFSMailMessage* targetMessage = NULL; + if ( targetEntries.Count() == 1 ) + { + targetMessage = &MsgPtrFromListIdL( targetEntries[0] ); + } + + // Meeting request mode is in use when there's exactly one target item and it's a + // calendar message and MRUI is available. + TBool showMrActions = EFalse; + + if ( targetMessage && targetMessage->IsFlagSet( EFSMsgFlag_CalendarMsg ) && + iAppUi.MrViewerInstanceL() && + iAppUi.MrViewerInstanceL()->CanViewMessage( *targetMessage ) && + currentFolderType != EFSOutbox && + currentFolderType != EFSDraftsFolder ) + { + showMrActions = ETrue; + } + + // CALENDAR EVENT ACTIONS SUBMENU + if ( showMrActions ) + { + // Hide all the normal email message specific actions + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsReply, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsReplyAll, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsForward, ETrue ); + + // Hide the irrelevant MR actions + TESMRMeetingRequestMethod mrMethod( EESMRMeetingRequestMethodUnknown ); + if ( iAppUi.MrViewerInstanceL() ) + { + TRAP_IGNORE( mrMethod = iAppUi.MrViewerInstanceL()->ResolveMeetingRequestMethodL( *targetMessage ) ); + } + switch ( mrMethod ) + { + case EESMRMeetingRequestMethodRequest: + { + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalRemoveFromCalendar, ETrue); + } + break; + case EESMRMeetingRequestMethodCancellation: + { + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalActionsAccept, ETrue); + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalActionsTentative, ETrue); + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalActionsDecline, ETrue); + + TBool supportsRemove = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaRemoveFromCalendar ); + if( !supportsRemove ) + { + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalRemoveFromCalendar, ETrue); + } + } + break; + case EESMRMeetingRequestMethodResponse: + case EESMRMeetingRequestMethodUnknown: + { + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalRemoveFromCalendar, ETrue); + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalActionsAccept, ETrue); + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalActionsTentative, ETrue); + aMenuPane->SetItemDimmed(EFsEmailUiCmdCalActionsDecline, ETrue); + } + break; + default: + break; + } + } + + // MAIL MESSAGE ACTIONS SUBMENU + else + { + // Hide all the calendar event options + aMenuPane->SetItemDimmed( EFsEmailUiCmdCalActionsAccept, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdCalActionsTentative, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdCalActionsDecline, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdCalRemoveFromCalendar, ETrue ); + + // Hide the irrelevant reply / reply all / forward commands + TInt numRecipients(0); + if ( targetMessage ) + { + //Get # of recipients + numRecipients = TFsEmailUiUtility::CountRecipientsSmart( iAppUi, targetMessage ); + } + // All reply/forward options are hidden when multiple marked messages or folder is outbox or drafts + if ( targetEntries.Count() > 1 || + currentFolderType == EFSOutbox || + currentFolderType == EFSDraftsFolder ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsReply, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsReplyAll, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsForward, ETrue ); + } + + // Reply all is hidden also when the single target message has multiple recipients + else if ( !targetMessage || numRecipients <= 1 ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsReplyAll, ETrue ); + } + } + + // COMMON PART OF ACTIONS SUBMENU + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkAsRead, !IsMarkAsReadAvailableL() ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkAsUnread, !IsMarkAsUnreadAvailableL() ); + + if ( !supportsMoving || !iMailFolder ) // Hide move from actions if not supported + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsMove, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsMoveToDrafts, ETrue ); + } + else + { + // Moving supported, show/hide moving options depending on the current folder + // First check deleted items case, IMS does not support deleted sync + if ( currentFolderType == EFSDeleted ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsMoveToDrafts, ETrue ); // Dim in deleted + } + // Then check for outbox case, move to drafts is allowed, other moves not + else if ( currentFolderType == EFSOutbox ) + { + // move from outbox to drafts is allowed + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsMoveToDrafts, EFalse ); // Allow in outbox + // moving from outbox is not allowed otherwise + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsMove, ETrue ); + } + // Handle rest of the folders + else + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsMoveToDrafts, ETrue ); // Dim in other folders + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsMove, EFalse ); + } + } + } + // ACTIONS SUBMENU ********************************************************************* + + + // MORE SUBMENU ************************************************************************ + if ( aResourceId == R_FSEMAILUI_MAILLIST_SUBMENU_MORE ) + { + TInt markedCount = CountMarkedItemsL(); + + // Checks if a device has a keyboard or not. + if( !iKeyboardFlipOpen ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkMark, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsCallSender, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsAddContact, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdMessageDetails, ETrue ); + } + + // Hide expand/collapse all when not applicable + if ( iNodesInUse == EListControlSeparatorDisabled || !iModel->Count() ) + { + aMenuPane->SetItemDimmed(EFsEmailUiCmdActionsCollapseAll, ETrue); + aMenuPane->SetItemDimmed(EFsEmailUiCmdActionsExpandAll, ETrue); + } + else + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsCollapseAll, AllNodesCollapsed() ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsExpandAll, AllNodesExpanded() ); + } + + // Some commands are available only when there's exactly one target message + if ( targetEntries.Count() != 1 ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsCallSender, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsAddContact, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdMessageDetails, ETrue ); + } + + // Hide mark/unmark all when not applicable + if ( markedCount == EmailsInModelL() ) // Hide mark all + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkMarkAll, ETrue ); + //aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkUnmarkAll, EFalse ); + } + else if ( !markedCount ) // hide unmark all + { + //aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkMarkAll, EFalse ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkUnmarkAll, ETrue ); + } + + // Hide followup flagging if not applicable + if ( !supportsFlag || !targetEntries.Count() ) + { + aMenuPane->SetItemDimmed(EFsEmailUiCmdActionsFlag, ETrue); + } + + // Hide Download Manager if no downloads present +// Prevent Download Manager opening with attachments +// if ( !iAppUi.DownloadInfoMediator() || !iAppUi.DownloadInfoMediator()->IsAnyAttachmentDownloads() ) +// { +// aMenuPane->SetItemDimmed(EFsEmailUiCmdDownloadManager, ETrue); +// } +// + + // Availability of the mark/unmark commands depends only on the focused item + if ( !iMailList || iMailList->FocusedItem() == KFsTreeNoneID || + iMailList->IsNode( iMailList->FocusedItem() ) ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkMark, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkUnmark, ETrue ); + } + else if ( iMailList->IsMarked( iMailList->FocusedItem() ) ) // Item was already marked + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkMark, ETrue ); + } + else + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdMarkUnmark, ETrue ); + } + + // Some commands are hidden in the outbox and drafts folders + if ( currentFolderType == EFSOutbox || + currentFolderType == EFSDraftsFolder ) + { + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsCallSender, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsAddContact, ETrue ); + aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsFlag, ETrue ); + } + } + // MORE SUBMENU ************************************************************************ + + + // SETTINGS SUBMENU ******************************************************************** + if ( aResourceId == R_FSEMAILUI_MAILLIST_SUBMENU_MAIL_SETTINGS ) + { + TUid pluginUid = iAppUi.GetActiveMailbox()->GetSettingsUid(); + + CESMailSettingsPlugin* settingsPlugin = + static_cast( iAppUi.View( pluginUid ) ); + + if ( !settingsPlugin ) + { + settingsPlugin = CESMailSettingsPlugin::NewL( pluginUid ); + CleanupStack::PushL( settingsPlugin ); + iAppUi.AddViewL( settingsPlugin ); + CleanupStack::Pop( settingsPlugin ); // ownership transferred + } + TInt count( settingsPlugin->MailSettingsSubviewCount() ); + if ( count > 0 ) + { + TInt index = 0; + while ( index < count ) + { + CEikMenuPaneItem::SData newMenuItem; + newMenuItem.iCommandId = EFsEmailUiCmdSettingsBaseCommandId + index; + newMenuItem.iCascadeId = 0; + newMenuItem.iFlags = 0; + newMenuItem.iText = settingsPlugin->MailSettingsSubviewCaption( + iAppUi.GetActiveMailboxId(), + index, + EFalse + ); + aMenuPane->InsertMenuItemL( + newMenuItem, + aMenuPane->NumberOfItemsInPane() ); + ++index; + } + } + else + { + // POP/IMAP mailbox settings + HBufC* ipsText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_SETTINGS_IPS_TEXT ); + CEikMenuPaneItem::SData newMenuItem; + newMenuItem.iCommandId = EFsEmailUiCmdSettingsBaseCommandId; + newMenuItem.iCascadeId = 0; + newMenuItem.iFlags = 0; + newMenuItem.iText = *ipsText; + aMenuPane->InsertMenuItemL( + newMenuItem, + aMenuPane->NumberOfItemsInPane() ); + CleanupStack::PopAndDestroy( ipsText ); + } + } + // SETTINGS SUBMENU ******************************************************************** + + CleanupStack::PopAndDestroy( &targetEntries ); + + // Add shortcut hints + iAppUi.ShortcutBinding().AppendShortcutHintsL( *aMenuPane, + CFSEmailUiShortcutBinding::EContextMailList ); + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::MarkAllItemsL() + { + FUNC_LOG; + if ( iTreeItemArray.Count() ) + { + for ( TInt i=0;iIsNode(iTreeItemArray[i].iListItemId ) ) + { + iMailList->MarkItemL( iTreeItemArray[i].iListItemId, ETrue ); + } + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UnmarkAllItemsL() + { + FUNC_LOG; + for ( TInt i=0 ; iIsNode(iTreeItemArray[i].iListItemId) ) + { + iMailList->MarkItemL( iTreeItemArray[i].iListItemId, EFalse ); + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::CountMarkedItemsL() + { + FUNC_LOG; + RFsTreeItemIdList markedEntries; + CleanupClosePushL( markedEntries ); + iMailList->GetMarkedItemsL( markedEntries ); + TInt count = markedEntries.Count(); + CleanupStack::PopAndDestroy( &markedEntries ); + return count; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::GetMarkedMessagesL( RArray& aMessageIDs ) const + { + FUNC_LOG; + aMessageIDs.Reset(); + + RFsTreeItemIdList markedEntries; + CleanupClosePushL( markedEntries ); + iMailList->GetMarkedItemsL( markedEntries ); + + for ( TInt i=0 ; i& aMessageIDs ) + { + FUNC_LOG; + for ( TInt i=0 ; i= 0 ) + { + iMailList->MarkItemL( iTreeItemArray[index].iListItemId, ETrue ); + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::RefreshL( TFSMailMsgId* aFocusToMessage ) + { + FUNC_LOG; + iMailList->RemoveAllL(); + iTreeItemArray.Reset(); + + RefreshListItemsL(); + + if ( !iModel->Count() ) + { + iFocusedControl = EControlBarComponent; + // If focus is not visible, hide selector + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + } + else + { + // Try to keep the previous list item if focused message ptr is given, + // and it's not NULL id + if ( aFocusToMessage && !aFocusToMessage->IsNullId() ) + { + TInt idx = ItemIndexFromMessageId( *aFocusToMessage ); + if ( idx >= 0 ) + { + iMailList->SetFocusedItemL( iTreeItemArray[idx].iListItemId ); + } + } + } + + SetListAndCtrlBarFocusL(); + SetMskL(); + + iListOrderMayBeOutOfDate = EFalse; + } + +void CFSEmailUiMailListVisualiser::RefreshOrderL() + { + FUNC_LOG; + if ( iTreeItemArray.Count() ) + { + TInt itemIdxUnderNode = -1; + TInt nodeIdx = -1; + TFsTreeItemId parentNodeId = KFsTreeRootID; + + //iMailList->HideListL( EFalse, EFalse ); + TFsTreeItemId prevFocus = iMailList->FocusedItem(); + iMailList->SetFocusedItemL( iTreeItemArray[0].iListItemId ); // Try to prevent over indexing in generic list + + // iTreeItemArray is recreated on reordering. + iTreeItemArray.Reset(); + SMailListItem mailListItem; + + for ( TInt i = 0 ; i < iModel->Count() ; ++i ) + { + CFSEmailUiMailListModelItem* item = static_cast( iModel->Item(i) ); + TFsTreeItemId itemId = item->CorrespondingListId(); + + if ( item->ModelItemType() == ETypeSeparator ) + { + nodeIdx++; + itemIdxUnderNode = -1; + parentNodeId = itemId; + if ( iMailList->ChildIndex( itemId, KFsTreeRootID ) != nodeIdx ) + { + iMailList->MoveItemL( itemId, KFsTreeRootID, nodeIdx ); + } + } + else + { + itemIdxUnderNode++; + if ( iMailList->Parent(itemId) != parentNodeId || + iMailList->ChildIndex( parentNodeId, itemId ) != itemIdxUnderNode ) + { + iMailList->MoveItemL( itemId, parentNodeId, itemIdxUnderNode ); + } + } + + mailListItem.iListItemId = itemId; + mailListItem.iTreeItemData = &iMailList->ItemData(itemId); + mailListItem.iTreeItemVisualiser = &iMailList->ItemVisualizer(itemId); + iTreeItemArray.AppendL( mailListItem ); + } + + iMailList->SetFocusedItemL( prevFocus ); + //iMailList->ShowListL( EFalse, EFalse ); + } + iListOrderMayBeOutOfDate = EFalse; + } + +// --------------------------------------------------------------------------- +// Start refresh list items asynchronously +// +// --------------------------------------------------------------------------- +// +// +void CFSEmailUiMailListVisualiser::RefreshDeferred( TFSMailMsgId* aFocusToMessage /*= NULL*/ ) + { + FUNC_LOG; + if ( aFocusToMessage ) + { + iMsgToFocusAfterRedraw = *aFocusToMessage; + } + else + { + // SetNullId sets just the null id flag, + // so we need to null the actual id manually + iMsgToFocusAfterRedraw.SetId( 0 ); + iMsgToFocusAfterRedraw.SetNullId(); + } + // + if ( iAsyncRedrawer ) + { + TCallBack asyncRefresh( DoRefresh, this ); + iAsyncRedrawer->Cancel(); + iAsyncRedrawer->Set( asyncRefresh ); + iAsyncRedrawer->CallBack(); + } + // + } + +// --------------------------------------------------------------------------- +// Static wrapper function for RefreshL() to enable asynchronous calling +// +// --------------------------------------------------------------------------- +// +// +TInt CFSEmailUiMailListVisualiser::DoRefresh( TAny* aSelfPtr ) + { + FUNC_LOG; + CFSEmailUiMailListVisualiser* self = + static_cast< CFSEmailUiMailListVisualiser* >( aSelfPtr ); + TRAPD( err, self->RefreshL( &self->iMsgToFocusAfterRedraw ) ); + return err; + } + +// --------------------------------------------------------------------------- +// Force any pending refresh event to be completed immediately +// +// --------------------------------------------------------------------------- +// +// +void CFSEmailUiMailListVisualiser::CompletePendingRefresh() + { + FUNC_LOG; + + if ( iAsyncRedrawer && iAsyncRedrawer->IsActive() ) // + { + iAsyncRedrawer->Cancel(); + DoRefresh( this ); + } + + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::RefreshListItemsL() + { + FUNC_LOG; + // IMPLEMENTATION OF FILLING UP THE LIST + TFsTreeItemId latestNodeId = KFsTreeRootID; // items will go under root node if no other nodes found in the model + CFSEmailUiMailListModelItem* item( NULL ); + SetMailListItemsExtendedL(); + + TBool allowRefresh(EFalse); + TInt count(0); + count = iModel->Count(); + for ( TInt i=0; i < count; i++ ) + { + item = static_cast(iModel->Item(i)); + + if ( i == 0 || i == count - 1 ) + {//first item - show scrollbar + //last item - update scrollbar + allowRefresh = ETrue; + } + else + {//rest of the messages - insert without updating + allowRefresh = EFalse; + } + + // Append separator item text into the list + if ( item && item->ModelItemType() == ETypeSeparator ) + { + latestNodeId = InsertNodeItemL( i, KErrNotFound, allowRefresh ); + } + // Append mail item into the list + else if ( item && item->ModelItemType() == ETypeMailItem ) + { + InsertListItemL( i, latestNodeId, KErrNotFound, allowRefresh ); + } + } + } + + +void CFSEmailUiMailListVisualiser::SetMailListItemsExtendedL() + { + FUNC_LOG; + // Set items always extended in double line preview on mode. + if ( iListMode == EListControlTypeDoubleLinePreviewOn || + iListMode == EListControlTypeDoubleLinePreviewOff ) + { + if ( iMailTreeListVisualizer ) + { + iMailTreeListVisualizer->SetItemsAlwaysExtendedL( ETrue ); + } + } + else + { + // Set the extendedability and extended size + if ( iMailTreeListVisualizer ) + { + iMailTreeListVisualizer->SetItemsAlwaysExtendedL( EFalse ); + } + } + } + + +// --------------------------------------------------------------------------- +// Create and insert one list node item according to given model item. +// Omitting the argument aChildIdx causes the new node to be appended as last +// child of the root node. +// --------------------------------------------------------------------------- +// +TFsTreeItemId CFSEmailUiMailListVisualiser::InsertNodeItemL( TInt aModelIndex, + TInt aChildIndex, + const TBool aAllowRefresh ) + { + FUNC_LOG; + TFsTreeItemId nodeId; + CFsTreePlainOneLineNodeData* plainNodeData(0); + CFsTreePlainOneLineNodeVisualizer* plainNodeVisualizer(0); + + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(aModelIndex) ); + + CreatePlainNodeL( item->SeparatorText(), plainNodeData, plainNodeVisualizer ); + CleanupStack::PushL( plainNodeData ); + CleanupStack::PushL( plainNodeVisualizer ); + // Set text aling for western or A&H layout + plainNodeVisualizer->SetTextAlign( EAlfAlignHLocale ); + //new node is expanded + plainNodeVisualizer->SetExpanded( ETrue ); + + // In mail list, scrollbar does not need to be updated after node, since node is always followed by item + if ( aChildIndex >= 0 ) + { + nodeId = iMailList->InsertNodeL( *plainNodeData, *plainNodeVisualizer, KFsTreeRootID, aChildIndex, aAllowRefresh ); + } + else + { + nodeId = iMailList->InsertNodeL( *plainNodeData, *plainNodeVisualizer, KFsTreeRootID, KErrNotFound, aAllowRefresh ); + } + + CleanupStack::Pop( 2, plainNodeData ); + + SMailListItem mailListItem; + mailListItem.iListItemId = nodeId; + mailListItem.iTreeItemData = plainNodeData; + mailListItem.iTreeItemVisualiser = plainNodeVisualizer; + iTreeItemArray.InsertL( mailListItem, aModelIndex ); + item->AddCorrespondingListId( nodeId ); + + return nodeId; + } + +// --------------------------------------------------------------------------- +// Create and insert one list item according the given model item. The item is +// added under the given node. Omitting the argument aChildIdx causes the new +// item to be appended as last child of the node. +// --------------------------------------------------------------------------- +// +TFsTreeItemId CFSEmailUiMailListVisualiser::InsertListItemL( TInt aModelIndex, + TFsTreeItemId aParentNodeId, + TInt aChildIdx, /*= KErrNotFound*/ + TBool aAllowRefresh ) + { + FUNC_LOG; + TRect screenRect = iAppUi.ClientRect(); + CFsTreePlainTwoLineItemData* itemData(0); + CFsTreePlainTwoLineItemVisualizer* itemVisualizer(0); + TRgb focusedColor = iAppUi.LayoutHandler()->ListFocusedStateTextSkinColor(); + TRgb normalColor = iAppUi.LayoutHandler()->ListNormalStateTextSkinColor(); + + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(aModelIndex) ); + + // Create data + itemData = CFsTreePlainTwoLineItemData::NewL(); + CleanupStack::PushL(itemData); + + // Read the data from the message + UpdateItemDataL( itemData, &item->MessagePtr() ); + + // Set placeholder for body preview + itemData->SetPreviewPaneDataL( KMissingPreviewDataMarker ); + + // Create item visualiser + itemVisualizer = CFsTreePlainTwoLineItemVisualizer::NewL(*iMailList->TreeControl()); + CleanupStack::PushL( itemVisualizer ); + + // Enable menu icon + itemVisualizer->SetFlags( itemVisualizer->Flags() | KFsTreeListItemHasMenu ); + + itemVisualizer->SetTextAlign( EAlfAlignHLocale ); + + TBool previewOn = ( iListMode == EListControlTypeDoubleLinePreviewOn || + iListMode == EListControlTypeSingleLinePreviewOn ); + itemVisualizer->SetPreviewPaneOn( previewOn ); + itemVisualizer->SetExtendable( ETrue ); + + itemVisualizer->SetFocusedStateTextColor( focusedColor ); + itemVisualizer->SetNormalStateTextColor( normalColor ); + + // Set font height + itemVisualizer->SetFontHeight( iAppUi.LayoutHandler()->ListItemFontHeightInTwips() ); + + //Update icons and text bolding + //DOES NOT update the item - will be drawn automatically (if needed) during InsertItemL + UpdateMsgIconAndBoldingL( itemData, itemVisualizer, &item->MessagePtr() ); + + // Insert or append under the given node + TFsTreeItemId itemId(0); + itemId = iMailList->InsertItemL( *itemData, *itemVisualizer, aParentNodeId, aChildIdx, aAllowRefresh ); + + // The visualizer and data are now owned by the iMailList and should be removed from + // the cleanup stack + CleanupStack::Pop( itemVisualizer ); + CleanupStack::Pop( itemData ); + + // Insert corresponding item to iTreeItemArray + SMailListItem mailListItem; + mailListItem.iListItemId = itemId; + mailListItem.iTreeItemData = itemData; + mailListItem.iTreeItemVisualiser = itemVisualizer; + iTreeItemArray.InsertL( mailListItem, aModelIndex ); + item->AddCorrespondingListId( itemId ); + + // Updating the preview pane must be handled separately in this case; + // generic logic in TreeListEvent handler doesn't work while we are + // still in the middle of adding the item. + if ( iMailList->FocusedItem() == itemId ) + { + UpdatePreviewPaneTextIfNecessaryL( itemId, ETrue ); + } + + return itemId; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +HBufC* CFSEmailUiMailListVisualiser::GetListFirstTextLineL( const CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + HBufC* ret( NULL ); + + TDesC* displayName( NULL ); + TDesC* emailAddress( NULL ); + + TInt folderType( EFSInbox ); + if( iMailFolder ) + { + folderType = iMailFolder->GetFolderType(); + } + + // Use sender in all other folders than outbox, sent, and drafts + if ( folderType != EFSOutbox && + folderType != EFSSentFolder && + folderType != EFSDraftsFolder ) + { + CFSMailAddress* fromAddress = aMsgPtr->GetSender(); + if ( fromAddress ) + { + displayName = &fromAddress->GetDisplayName(); + emailAddress = &fromAddress->GetEmailAddress(); + + if ( displayName && displayName->Length() != 0 ) + { + ret = displayName->AllocL(); + } + else if ( emailAddress && emailAddress->Length() != 0 ) + { + ret = emailAddress->AllocL(); + } + } + else // no fromAddress in that case we show "(No sender info available)", + // in case sender sends MR to himself/herself + { + ret = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_NO_SENDER_INFO_AVAILABLE); + } + } + // Use first recipient in case of outgoing folders + else // folderType == EFSOutbox || folderType == EFSSentFolder || folderType == EFSDraftsFolder + { + CFSMailMessage* msgPtr = const_cast( aMsgPtr ); // there's no const function in FW to get recipient data + RPointerArray& toArray = msgPtr->GetToRecipients(); + if ( toArray.Count() ) + { + CFSMailAddress* toAddress = toArray[0]; // Use first + if ( toAddress ) + { + displayName = &toAddress->GetDisplayName(); + emailAddress = &toAddress->GetEmailAddress(); + + if ( displayName && displayName->Length() ) + { + ret = displayName->AllocL(); + } + else if ( emailAddress && emailAddress->Length() ) + { + ret = emailAddress->AllocL(); + } + } + } + } + + // Allocate empty string if everything else fails + if ( !ret ) + { + ret = KNullDesC().AllocL(); + } + + // Drop out unwanted characters from display name such as <> and "" + TFsEmailUiUtility::StripDisplayName( *ret ); + + return ret; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdateItemDataL( CFsTreePlainTwoLineItemData* aData, const CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + // Set first line of data + HBufC* firstLineText = GetListFirstTextLineL( aMsgPtr ); + if ( firstLineText ) + { + CleanupStack::PushL( firstLineText ); + aData->SetDataL( *firstLineText ); + CleanupStack::PopAndDestroy( firstLineText ); + } + else + { + aData->SetDataL( KNullDesC ); + } + + // Set second line of data + HBufC* subjectText = TFsEmailUiUtility::CreateSubjectTextLC( aMsgPtr ); + aData->SetSecondaryDataL( *subjectText ); + CleanupStack::PopAndDestroy( subjectText ); + + // Set time item in mail + HBufC* timeText = NULL; + if ( iCurrentSortCriteria.iField == EFSMailSortByDate ) + { + timeText = TFsEmailUiUtility::ListMsgTimeTextFromMsgLC( aMsgPtr, iNodesInUse ); + } + else + { + // Use dates also in other sort criterias that sort by date. + timeText = TFsEmailUiUtility::ListMsgTimeTextFromMsgLC( aMsgPtr, EFalse ); + } + aData->SetDateTimeDataL( *timeText ); + CleanupStack::PopAndDestroy( timeText ); + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdatePreviewPaneTextForItemL( TInt aListItemId, CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + if ( aMsgPtr && ( iListMode == EListControlTypeSingleLinePreviewOn || + iListMode == EListControlTypeDoubleLinePreviewOn ) ) + { + CFsTreePlainTwoLineItemData* twoLineItemData = static_cast( ItemDataFromItemId( aListItemId ) ); + UpdatePreviewPaneTextForItemL( twoLineItemData, aMsgPtr ); + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdatePreviewPaneTextForItemL( + CFsTreePlainTwoLineItemData* aTwoLineItemData, CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + // Preview pane data update + if ( aTwoLineItemData && aMsgPtr && ( iListMode == EListControlTypeSingleLinePreviewOn || + iListMode == EListControlTypeDoubleLinePreviewOn ) ) + { + TBool previewSet = EFalse; + CFSMailMessagePart* textPart = aMsgPtr->PlainTextBodyPartL(); + CleanupStack::PushL( textPart ); + if ( textPart && ( textPart->FetchLoadState() == EFSPartial || + textPart->FetchLoadState() == EFSFull ) ) + { + TInt previewSize = Min( KMaxPreviewPaneLength, textPart->FetchedContentSize() ); + HBufC* plainTextData16 = HBufC::NewLC( previewSize ); + TPtr textPtr = plainTextData16->Des(); + + // Getting the content needs to be trapped as it seems to leave in some error cases + // at least with IMAP + TRAP_IGNORE( textPart->GetContentToBufferL( textPtr, 0 ) ); // Zero is start offset + // Crop out line feed, paragraph break, and tabulator + TFsEmailUiUtility::FilterListItemTextL( textPtr ); + + if ( textPtr.Length() ) + { + aTwoLineItemData->SetPreviewPaneDataL( *plainTextData16 ); + previewSet = ETrue; + } + + CleanupStack::PopAndDestroy( plainTextData16 ); + } + + // Display message size in preview pane if we got no body content + if ( !previewSet ) + { + TUint contentSize = aMsgPtr->ContentSize(); + HBufC* sizeDesc = TFsEmailUiUtility::CreateSizeDescLC( contentSize ); + HBufC* msgSizeText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_PREV_PANE_MSG_SIZE, *sizeDesc ); + aTwoLineItemData->SetPreviewPaneDataL( *msgSizeText ); + CleanupStack::PopAndDestroy( msgSizeText ); + CleanupStack::PopAndDestroy( sizeDesc ); + } + CleanupStack::PopAndDestroy( textPart ); + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdatePreviewPaneTextIfNecessaryL( TFsTreeItemId aListItemId, TBool aUpdateItem ) + { + FUNC_LOG; + if ( iFirstStartCompleted && aListItemId != KFsTreeNoneID ) + { + if ( iListMode == EListControlTypeSingleLinePreviewOn || + iListMode == EListControlTypeDoubleLinePreviewOn ) + { + if ( !iMailList->IsNode( aListItemId ) ) + { + TInt idx = ModelIndexFromListId( aListItemId ); + if ( idx != KErrNotFound ) + { + CFsTreePlainTwoLineItemData* data = + static_cast( iTreeItemArray[idx].iTreeItemData ); + if ( data->PreviewPaneData() == KMissingPreviewDataMarker ) + { + CFSEmailUiMailListModelItem* modelItem = + static_cast( iModel->Item(idx) ); + CFSMailMessage& msgRef = modelItem->MessagePtr(); + UpdatePreviewPaneTextForItemL( aListItemId, &msgRef ); + if ( aUpdateItem ) + { + iMailTreeListVisualizer->UpdateItemL( aListItemId ); + } + } + } + } + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::CreatePlainNodeL( const TDesC* aItemDataBuff, + CFsTreePlainOneLineNodeData* &aItemData, + CFsTreePlainOneLineNodeVisualizer* &aNodeVisualizer ) const + { + FUNC_LOG; + aItemData = CFsTreePlainOneLineNodeData::NewL(); + CleanupStack::PushL( aItemData ); + + aItemData->SetDataL( *aItemDataBuff ); + aItemData->SetIconExpanded( iAppUi.FsTextureManager()->TextureByIndex( EListTextureNodeExpanded )); + aItemData->SetIconCollapsed( iAppUi.FsTextureManager()->TextureByIndex( EListTextureNodeCollapsed )); + aNodeVisualizer = CFsTreePlainOneLineNodeVisualizer::NewL(*iMailList->TreeControl()); + CleanupStack::PushL( aNodeVisualizer ); + TRect screenRect = iAppUi.ClientRect(); + TInt nodeHeight = iAppUi.LayoutHandler()->OneLineListNodeHeight(); + aNodeVisualizer->SetSize( TSize(screenRect.Width(), nodeHeight) ); + aNodeVisualizer->SetExtendable(EFalse); + // Set correct skin text colors for the list items + TRgb focusedColor = iAppUi.LayoutHandler()->ListFocusedStateTextSkinColor(); + TRgb normalColor = iAppUi.LayoutHandler()->ListNodeTextColor(); + aNodeVisualizer->SetFocusedStateTextColor( focusedColor ); + aNodeVisualizer->SetNormalStateTextColor( normalColor ); + // Set font height + aNodeVisualizer->SetFontHeight( iAppUi.LayoutHandler()->ListItemFontHeightInTwips() ); + // Set font always bolded in nodes + aNodeVisualizer->SetTextBold( ETrue ); + + // + CAlfBrush* titleDividerBgBrush = + iAppUi.FsTextureManager()->TitleDividerBgBrushL(); + // ownership is not transfered + aNodeVisualizer->SetBackgroundBrush( titleDividerBgBrush ); + // + + CleanupStack::Pop( aNodeVisualizer ); + CleanupStack::Pop( aItemData ); + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::HandleDynamicVariantSwitchL( CFsEmailUiViewBase::TDynamicSwitchType aType ) + { + FUNC_LOG; + CFsEmailUiViewBase::HandleDynamicVariantSwitchL( aType ); + + if ( iFirstStartCompleted ) // Safety + { + if ( aType == ESkinChanged ) + { + iSkinChanged = ETrue; + } + else + { + iMailTreeListVisualizer->HideList(); + // screen layout changed + iCurrentClientRect = iAppUi.ClientRect(); + iScreenAnchorLayout->SetSize( iCurrentClientRect.Size() ); + SetMailListLayoutAnchors(); + // Set branded watermark + SetBrandedListWatermarkL(); + iMailTreeListVisualizer->ShowListL(); + + ScaleControlBarL(); + SetBrandedMailBoxIconL(); + } + // Update the folder/sort popup layout in case it happened to be open + if ( iAppUi.FolderList().IsPopupShown() ) + { + iAppUi.FolderList().HandleDynamicVariantSwitchL( aType ); + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::HandleDynamicVariantSwitchOnBackgroundL( CFsEmailUiViewBase::TDynamicSwitchType aType ) + { + FUNC_LOG; + CFsEmailUiViewBase::HandleDynamicVariantSwitchOnBackgroundL( aType ); + if ( aType == ESkinChanged ) + { + iSkinChanged = ETrue; + } + } + +// --------------------------------------------------------------------------- +// HandleForegroundEventL +// Function checks in foregroundevent that whether settings have changed and +// If there is a need to refresh the list. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::HandleForegroundEventL() + { + FUNC_LOG; + if ( iFirstStartCompleted ) // Safety + { + // Update mail list settings and date formats, is done every time + // the user might have changed these in settings, so the list needs to refresh + // Store previous modes + TInt prevListMode = iListMode; + TInt prevNodesmode = iNodesInUse; + TAknUiZoom prevZoomLevel = iCurrentZoomLevel; + STimeDateFormats prevDateFormats = MailListTimeDateSettings(); + + // Get new settings and list drawing modes + CAknEnv::Static()->GetCurrentGlobalUiZoom( iCurrentZoomLevel ); + UpdateMailListSettingsL(); + UpdateMailListTimeDateSettings(); + + // Check sync icon timer and sync status + ConnectionIconHandling(); + + // Updates the folder list's size after the screensaver + iAppUi.FolderList().HandleForegroundEventL(); + + // Check for changed settings, in that case a complete list refresh is needed + if ( iSkinChanged + || iDateChanged + || iListMode != prevListMode + || iNodesInUse != prevNodesmode + || iCurrentZoomLevel != prevZoomLevel + || prevDateFormats.iDateFormat != iDateFormats.iDateFormat + || prevDateFormats.iTimeFormat != iDateFormats.iTimeFormat + || prevDateFormats.iAmPmPosition != iDateFormats.iAmPmPosition + || prevDateFormats.iDateSeparator != iDateFormats.iDateSeparator + || prevDateFormats.iTimeSeparator != iDateFormats.iTimeSeparator ) + { + // Store the list of marked items. The markings are erased when the list + // is repopulated and, hence, the markings need to be reset after the + // refreshing is done. The marked items must be identified by the message + // ID rather than with the list ID because refreshing may change the list IDs. + RArray markedMessages; + CleanupClosePushL( markedMessages ); + GetMarkedMessagesL( markedMessages ); + // Store the message ID of the focused item + TFSMailMsgId msgIdBeforeRefresh = MsgIdFromListId( iMailList->FocusedItem() ); + TFsTreeItemId firstVisibleListId = iMailTreeListVisualizer->FirstVisibleItem(); + TInt modelFirstIndexBeforeUpdate = ModelIndexFromListId( firstVisibleListId ); + TInt highlightedIndexBeforeUpdate = HighlightedIndex(); + TInt modelCountBeforeUpdate = iModel->Count(); + + UpdateMailListModelL(); + if ( markedMessages.Count() ) + { + RefreshL( &msgIdBeforeRefresh ); + // Restore the marking status + MarkMessagesIfFoundL( markedMessages ); + } + else + { + RefreshDeferred( &msgIdBeforeRefresh ); + } + CleanupStack::PopAndDestroy( &markedMessages ); + iSkinChanged = EFalse; // Toggle handled + iDateChanged = EFalse; // Toggle handled + } + } + } + + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::HandleCommandL( TInt aCommand ) + { + FUNC_LOG; + CompletePendingRefresh(); + + // custom command handling for launching plugin settings + if ( EFsEmailUiCmdSettingsBaseCommandId <= aCommand + && EFsEmailUiCmdSettingsBaseCommandIdMax > aCommand ) + { + CESMailSettingsPlugin::TSubViewActivationData activationData; + activationData.iAccount = iAppUi.GetActiveMailbox()->GetId(); + // which settings plugin subview will be activated + TInt selectedCommand = aCommand - EFsEmailUiCmdSettingsBaseCommandId; + activationData.iSubviewId = selectedCommand; + + TUid pluginUid = iAppUi.GetActiveMailbox()->GetSettingsUid(); + + // If plugin view does not exist, create and register it to app ui. + if ( !iAppUi.View( pluginUid ) ) + { + CESMailSettingsPlugin* plugin = CESMailSettingsPlugin::NewL( pluginUid ); + CleanupStack::PushL( plugin ); + iAppUi.AddViewL( plugin ); // Ownership is transferred. + CleanupStack::Pop( plugin ); + } + TUid messageId = TUid::Uid( CESMailSettingsPlugin::EActivateMailSettingsSubview ); + const TPckgBuf pluginMessagePkg( activationData ); + + StatusPane()->SwitchLayoutL( R_AVKON_STATUS_PANE_LAYOUT_USUAL ); + iAppUi.EnterPluginSettingsViewL( pluginUid, messageId, pluginMessagePkg ); + } + + // Many commands may be targetted either to the focused item or to the marked item(s). + // Get list of marked or focused items. + RFsTreeItemIdList actionTargetItems; + CleanupClosePushL( actionTargetItems ); + GetActionsTargetEntriesL( actionTargetItems ); + + switch(aCommand) + { + case EAknSoftkeyOpen: + { + if (!iAppUi.IsTimerFocusShown()) + { + iAppUi.StartFocusRemovalTimer(); + break; + } + } + case EAknSoftkeySelect: + { + if ( iFocusedControl == EMailListComponent ) + { + CFSEmailUiMailListModelItem* item = dynamic_cast(iModel->Item(HighlightedIndex())); + // MAIL ITEM; OPEN MAIL + if ( item && item->ModelItemType() == ETypeMailItem ) + { + CFSMailMessage* messagePtr = &item->MessagePtr(); + if ( messagePtr ) + { + OpenHighlightedMailL(); + } + } + } + } + break; + case EAknSoftkeyChange: + { + if (!iAppUi.IsTimerFocusShown()) + { + iAppUi.StartFocusRemovalTimer(); + break; + } + if ( iFocusedControl == EControlBarComponent ) + { + TInt focusedButtonId = iControlBarControl->GetFocusedButton()->Id(); + if ( focusedButtonId == iFolderListButtonId ) + { + // + //Set touchmanager not active for preventing getting events. + DisableMailList(ETrue); + // + iAppUi.ShowFolderListInPopupL( FolderId(), this, iFolderListButton ); + } + else if ( focusedButtonId == iSortButtonId ) + { + TFSFolderType folderType; + if( iMailFolder ) + { + folderType = iMailFolder->GetFolderType(); + } + else + { + folderType = EFSInbox; + } + // Sorting set possible even for empty mailbox + // Show sort if model has data. + //if ( iModel->Count() ) + // { + // + // + //Set touchmanager not active for preventing getting events. + DisableMailList(ETrue); + // + iAppUi.ShowSortListInPopupL( iCurrentSortCriteria.iField, folderType, this, iSortButton ); + // + // } + // + } + } + } + break; + case EAknSoftkeyBack: + if ( !iAppUi.ViewSwitchingOngoing() ) + { + NavigateBackL(); + } + break; + case EEikCmdExit: + case EAknSoftkeyExit: + case EFsEmailUiCmdExit: + iAppUi.Exit(); + break; + case EFsEmailUiCmdCalActionsReplyAsMail: + case EFsEmailUiCmdActionsReply: + { + ReplyL( NULL ); // Function will check marked/highlighted msg + } + break; + case EFsEmailUiCmdActionsReplyAll: + { + ReplyAllL( NULL ); // Function will check marked/highlighted msg + } + break; + case EFsEmailUiCmdCalActionsForwardAsMail: + case EFsEmailUiCmdActionsForward: + { + ForwardL( NULL ); // Function will check marked/highlighted msg + } + break; + case EFsEmailUiCmdActionsCallSender: + { + if ( !iAppUi.ViewSwitchingOngoing() ) + { + if ( iMailFolder && iMailFolder->GetFolderType() != EFSOutbox && + iMailFolder->GetFolderType() != EFSDraftsFolder ) + { + // Calling can happen only when there's exactly one message marked or in focus + if ( actionTargetItems.Count() == 1 ) + { + CFSMailMessage& message = MsgPtrFromListIdL( actionTargetItems[0] ); + CFSMailAddress* fromAddress = message.GetSender(); + TDesC* mailAddress(0); + if ( fromAddress ) + { + mailAddress = &fromAddress->GetEmailAddress(); + } + if ( mailAddress && mailAddress->Length() ) + { + if ( iMailFolder->GetFolderType() == EFSSentFolder ) + { + CFsDelayedLoader::InstanceL()->GetContactHandlerL()->FindAndCallToContactByEmailL( + *mailAddress, iAppUi.GetActiveMailbox(), this, EFalse ); + } + else + { + CFsDelayedLoader::InstanceL()->GetContactHandlerL()->FindAndCallToContactByEmailL( + *mailAddress, iAppUi.GetActiveMailbox(), this, ETrue ); + } + } + } + } + } + } + break; + case EFsEmailUiCmdMarkAsRead: + { + // Change status of marked or highlighted + if ( CountMarkedItemsL() ) + { + ChangeReadStatusOfMarkedL( ETrue ); + } + else + { + ChangeReadStatusOfHighlightedL( ETrue ); + } + } + break; + case EFsEmailUiCmdMarkAsUnread: + { + // Change status of marked or highlighted + if ( CountMarkedItemsL() ) + { + ChangeReadStatusOfMarkedL( EFalse ); + } + else + { + ChangeReadStatusOfHighlightedL( EFalse ); + } + } + break; + case EFsEmailUiCmdGoToTop: + { + // Safety check, ignore command if the list is empty + if( iTreeItemArray.Count() ) + { + if ( iFocusedControl != EMailListComponent ) + { + iFocusedControl = EMailListComponent; + iMailList->SetFocusedL( ETrue ); + iControlBarControl->SetFocusL( EFalse ); + } + // No need to check for nodes as in move to bottom. + iMailTreeListVisualizer->SetFocusedItemL( iTreeItemArray[0].iListItemId ); + } + } + break; + case EFsEmailUiCmdGoToBottom: + { + // Safety check, ignore command if the list is empty + if( iTreeItemArray.Count() ) + { + if ( iFocusedControl != EMailListComponent ) + { + iFocusedControl = EMailListComponent; + iMailList->SetFocusedL( ETrue ); + iControlBarControl->SetFocusL( EFalse ); + } + + TFsTreeItemId bottomItem = iTreeItemArray[iTreeItemArray.Count()-1].iListItemId; + TFsTreeItemId parentItem = ParentNode( bottomItem ); // parent node of the bottom item + + // Check whether the parent is node and is collapsed + if ( parentItem>0 && !iMailList->IsExpanded( parentItem ) ) + { + bottomItem = parentItem; + } + iMailTreeListVisualizer->SetFocusedItemL( bottomItem ); + } + } + break; + case EFsEmailUiCmdPageUp: + { + TKeyEvent simEvent = { EKeyPageUp, EStdKeyPageUp, 0, 0 }; + iCoeEnv->SimulateKeyEventL( simEvent, EEventKey ); + } + break; + case EFsEmailUiCmdPageDown: + { + TKeyEvent simEvent = { EKeyPageDown, EStdKeyPageDown, 0, 0 }; + iCoeEnv->SimulateKeyEventL( simEvent, EEventKey ); + } + break; + case EFsEmailUiCmdActionsDeleteCalEvent: + case EFsEmailUiCmdActionsDelete: + { + TInt index = HighlightedIndex(); + CFSEmailUiMailListModelItem* item = + dynamic_cast( + iModel->Item( index ) ); + + // If selected item is separator (divider) mark/unmark all messages + // under it. + if ( item && item->ModelItemType() == ETypeSeparator ) + { + MarkItemsUnderSeparatorL( ETrue, index ); + } + + // Delete message only if mail list component is focused + // or if there are some marked items + TInt markedItems( CountMarkedItemsL() ); + + if ( iFocusedControl == EMailListComponent || markedItems ) + { + DeleteMessagesL(); + } + UnmarkAllItemsL(); + } + break; + case EFsEmailUiCmdCompose: + { + CreateNewMsgL(); + } + break; + case EFsEmailUiCmdMessageDetails: + { + // Message details can be viewed only when there's exactly one message marked or in focus + if ( actionTargetItems.Count() == 1 ) + { + CFSMailMessage& message = MsgPtrFromListIdL( actionTargetItems[0] ); + TMsgDetailsActivationData msgDetailsData; + msgDetailsData.iMailBoxId = iAppUi.GetActiveMailboxId(); + msgDetailsData.iFolderId = FolderId(); + msgDetailsData.iMessageId = message.GetMessageId(); + const TPckgBuf pkgOut( msgDetailsData ); + iAppUi.EnterFsEmailViewL( MsgDetailsViewId, KStartMsgDetailsToBeginning, pkgOut ); + } + } + break; + case EFsEmailUiCmdSettingsGlobal: + { + iAppUi.EnterFsEmailViewL( GlobalSettingsViewId ); + } + break; + case EFsEmailUiCmdSettingsService: + case EFsEmailUiCmdSettingsMailbox: + { + CESMailSettingsPlugin::TSubViewActivationData activationData; + activationData.iAccount = iAppUi.GetActiveMailbox()->GetId(); + activationData.iSubviewId = 0; + if ( EFsEmailUiCmdSettingsService == aCommand ) + { + activationData.iSubviewId = 1; + } + + TUid pluginUid = iAppUi.GetActiveMailbox()->GetSettingsUid(); + // register plugin view if not exists so that activation can be made + if ( !iAppUi.View( pluginUid ) ) + { + CESMailSettingsPlugin* plugin = CESMailSettingsPlugin::NewL( pluginUid ); + CleanupStack::PushL( plugin ); + iAppUi.AddViewL( plugin ); + CleanupStack::Pop( plugin ); + } + TUid messageId = TUid::Uid( CESMailSettingsPlugin::EActivateMailSettingsSubview ); + const TPckgBuf pluginMessagePkg( activationData ); + iAppUi.EnterPluginSettingsViewL( pluginUid, messageId, pluginMessagePkg ); + } + break; + case EFsEmailUiCmdOpen: + case EFsEmailUiCmdActionsOpen: + { + if ( iFocusedControl == EMailListComponent ) + { + // Opening can happen only when there's exactly one message marked or in focus + if ( actionTargetItems.Count() == 1 ) + { + OpenMailItemL( actionTargetItems[0] ); + } + } + } + break; + case EFsEmailUiCmdActionsFlag: + { + SetMessageFollowupFlagL(); + } + break; + case EFsEmailUiCmdActionsCollapseAll: + // Safety check, ignore command if the list is empty + if( iMailList->Count() ) + { + CollapseAllNodesL(); + } + break; + case EFsEmailUiCmdActionsExpandAll: + // Safety check, ignore command if the list is empty + if( iMailList->Count() ) + { + ExpandAllNodesL(); + } + break; + case EFsEmailUiCmdCollapse: + if (!iAppUi.IsTimerFocusShown()) + { + iAppUi.StartFocusRemovalTimer(); + break; + } + // Safety check, ignore command if the list is empty + if( iMailList->Count() ) + { + ExpandOrCollapseL(); + } + break; + case EFsEmailUiCmdExpand: + if (!iAppUi.IsTimerFocusShown()) + { + iAppUi.StartFocusRemovalTimer(); + break; + } + // Safety check, ignore command if the list is empty + if( iMailList->Count() ) + { + ExpandOrCollapseL(); + } + break; + case EFsEmailUiCmdSearch: + { + TSearchListActivationData tmp; + tmp.iMailBoxId = iAppUi.GetActiveMailbox()->GetId(); + const TPckgBuf pkgOut( tmp ); + iAppUi.EnterFsEmailViewL( SearchListViewId, KStartNewSearch, pkgOut ); + } + break; +// Prevent Download Manager opening with attachments +// case EFsEmailUiCmdDownloadManager: +// iAppUi.EnterFsEmailViewL( DownloadManagerViewId ); +// break; +// + case EFsEmailUiCmdMarkMark: + { + iListMarkItemsState = ETrue; // shift-scrolling does marking after one item is marked + iMailList->MarkItemL( iMailList->FocusedItem(), ETrue ); + } + break; + case EFsEmailUiCmdMarkMarkAll: + { + MarkAllItemsL(); + } + break; + case EFsEmailUiCmdMarkUnmark: + { + iListMarkItemsState = EFalse; // shift-scrolling does unmarking after one item is unmarked + iMailList->MarkItemL( iMailList->FocusedItem(), EFalse ); + } + break; + case EFsEmailUiCmdMarkUnmarkAll: + { + UnmarkAllItemsL(); + } + break; + case EFsEmailUiCmdReadEmail: + { + iAppUi.StartReadingEmailsL(); + } + break; + case EFsEmailUiCmdSync: + { + TBool supportsSync = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaSupportsSync ); + if ( supportsSync ) + { + //If synchronizing is ongoing and a new sync is started we ignore it + if(!GetLatestSyncState()) + { + iAppUi.SyncActiveMailBoxL(); + // Sync was started by the user + ManualMailBoxSync(ETrue); + iAppUi.ManualMailBoxSync( ETrue ); + } + } + } + break; + case EFsEmailUiCmdCancelSync: + { + TBool supportsSync = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaSupportsSync ); + if ( supportsSync ) + { + iAppUi.StopActiveMailBoxSyncL(); + CFSMailBox* mb = iAppUi.GetActiveMailbox(); + TDesC* mbName = &mb->GetName(); + } + } + break; + case EFsEmailUiCmdGoOffline: + { + iAppUi.GetActiveMailbox()->GoOfflineL(); + } + break; + case EFsEmailUiCmdGoOnline: + { + CFSMailBox* mb = iAppUi.GetActiveMailbox(); + TDesC* mbName = &mb->GetName(); + iAppUi.ManualMailBoxSync( ETrue ); + mb->GoOnlineL(); + } + break; + case EFsEmailUiCmdHelp: + { + + TFsEmailUiUtility::LaunchHelpL( KFSE_HLP_LAUNCHER_GRID ); + } + break; + + + case EFsEmailUiCmdActionsAddContact: + { + // contact can be got from message only when there's exactly one target message + if ( actionTargetItems.Count() == 1 && iMailFolder ) + { + CFSMailMessage& message = MsgPtrFromListIdL( actionTargetItems[0] ); + + CFSMailAddress* addressToBeStored(0); + TInt folderType = iMailFolder->GetFolderType(); + // Use first to recepient in outbox, drafts and sent if found. + if ( folderType == EFSOutbox || folderType == EFSDraftsFolder || folderType == EFSSentFolder ) + { + RPointerArray& toArray = message.GetToRecipients(); + if ( toArray.Count() ) + { + addressToBeStored = toArray[0]; + } + } + // Use sender in all other "normal" folders + else + { + addressToBeStored = message.GetSender(); + } + TDesC* emailAddressText(0); + if ( addressToBeStored ) + { + emailAddressText = &addressToBeStored->GetEmailAddress(); + } + if ( emailAddressText && emailAddressText->Length() ) + { + TAddToContactsType type; + //Query to "update existing" or "Create new" --> EFALSE = user choosed "cancel" + if ( CFsDelayedLoader::InstanceL()->GetContactHandlerL()->AddtoContactsQueryL( type ) ) + { + CFsDelayedLoader::InstanceL()->GetContactHandlerL()->AddToContactL( + *emailAddressText, EContactUpdateEmail, type, this ); + } + } + } + } + break; + case EFsEmailUiCmdActionsMove: + case EFsEmailUiCmdActionsMoveMessage: + { + TFSMailMsgId folderID; + folderID.SetNullId(); // Selection is popped up with NULL + MoveMsgsToFolderL( folderID ); + } + break; + case EFsEmailUiCmdActionsMoveToDrafts: + { + MoveMessagesToDraftsL(); + } + break; + case EFsEmailUiCmdActionsCopyMessage: + { + } + break; + case EFsEmailUiCmdActionsCollapseExpandAllToggle: + { + ShortcutCollapseExpandAllToggleL(); + } + break; + case EFsEmailUiCmdMarkAsReadUnreadToggle: + { + ShortcutReadUnreadToggleL(); + } + break; + case EFsEmailUiCmdMarkUnmarkToggle: + { + TInt focusedItem = iMailList->FocusedItem(); + if ( focusedItem > 0 && iFocusedControl == EMailListComponent ) + { + CFSEmailUiMailListModelItem* item = dynamic_cast(iModel->Item(HighlightedIndex())); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + if ( iMailList->IsMarked( focusedItem ) ) + { + HandleCommandL(EFsEmailUiCmdMarkUnmark); + } + else + { + HandleCommandL(EFsEmailUiCmdMarkMark); + } + } + else if ( item->ModelItemType() == ETypeSeparator ) + { + // Mark items. + MarkItemsUnderSeparatorL( ETrue, HighlightedIndex() ); + iListMarkItemsState = ETrue; // Enable mark mode + } + } + } + break; + case EFsEmailUiCmdGoToSwitchFolder: + { + iControlBarControl->SetFocusByIdL( iFolderListButtonId ); + iFocusedControl = EControlBarComponent; + iMailList->SetFocusedL( EFalse ); + } + break; + case EFsEmailUiCmdGoToSwitchSorting: + { + iControlBarControl->SetFocusByIdL( iSortButtonId ); + iFocusedControl = EControlBarComponent; + iMailList->SetFocusedL( EFalse ); + } + break; + case EFsEmailUiCmdCalActionsAccept: + case EFsEmailUiCmdCalActionsTentative: + case EFsEmailUiCmdCalActionsDecline: + case EFsEmailUiCmdCalRemoveFromCalendar: + { + if ( actionTargetItems.Count() == 1 ) + { + TInt mrItemIdx = ModelIndexFromListId( actionTargetItems[0] ); + CFSEmailUiMailListModelItem* item = + dynamic_cast( iModel->Item(mrItemIdx) ); + if ( item && item->MessagePtr().IsFlagSet( EFSMsgFlag_CalendarMsg ) ) + { + // Respond to meeting request + if ( iAppUi.MrViewerInstanceL() && iAppUi.MrViewerInstanceL()->CanViewMessage( item->MessagePtr() ) ) + { + ChangeReadStatusOfHighlightedL( ETrue ); + iAppUi.MailViewer().HandleMrCommandL( aCommand, + iAppUi.GetActiveMailbox()->GetId(), + FolderId(), + item->MessagePtr().GetMessageId() ); + } + } + } + } + break; + case EFsEmailUiCmdActionsEmptyDeleted: + { + // + if ( iMailFolder && iMailFolder->GetFolderType() == EFSDeleted && + iModel->Count() != 0 ) + // + { + TBool okToDelete( EFalse ); + HBufC* msg = StringLoader::LoadLC( R_FREESTYLE_EMAIL_QUERY_NOTE_PERMANENTLY_DELETE ); + CAknQueryDialog *queryNote = new ( ELeave ) CAknQueryDialog(); + CleanupStack::PushL( queryNote ); + queryNote->SetPromptL( *msg ); + CleanupStack::Pop( queryNote ); + CleanupStack::PopAndDestroy( msg ); + okToDelete = queryNote->ExecuteLD( R_FSEMAIL_QUERY_DIALOG ); + if ( okToDelete ) + { + // Empty deleted items folder + RArray msgIds; + CleanupClosePushL( msgIds ); + for ( TInt i=0 ; iCount();i++ ) + { + CFSEmailUiMailListModelItem* item = + static_cast(iModel->Item(i)); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + msgIds.Append( item->MessagePtr().GetMessageId() ); + } + } + TFSMailMsgId folderId = FolderId(); + TFSMailMsgId mailBox = iAppUi.GetActiveMailbox()->GetId(); + iAppUi.GetMailClient()->DeleteMessagesByUidL( mailBox, folderId, msgIds ); + RemoveMsgItemsFromListIfFoundL( msgIds ); + CleanupStack::PopAndDestroy( &msgIds ); + } + } + } + break; + default: + break; + } + CleanupStack::PopAndDestroy( &actionTargetItems ); + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::MoveMsgsToFolderL( const TFSMailMsgId& aDestinationFolderId ) + { + FUNC_LOG; + TInt ret(KErrGeneral); + RFsTreeItemIdList targetEntries; + CleanupClosePushL( targetEntries ); + GetActionsTargetEntriesL( targetEntries ); + TBool supportsMove = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaMoveToFolder ); + // Moving is not possible, if there are no items or the focus is on separator and + // there are no marked items. In outbox, moving is allowed only to the drafts folder; + // folder selection popup is not allowed. + // These have to be checked before launching the folder view. + if ( targetEntries.Count() && supportsMove ) + { + TBool outbox = (iMailFolder && iMailFolder->GetFolderType() == EFSOutbox); + + if ( !(outbox && aDestinationFolderId.IsNullId()) ) + { + // If destination folder is not set, it needs to be asked messages are moved after callbak + if ( aDestinationFolderId.IsNullId() ) + { + // Activate folder selection view and handle moving after callback gets destination + iMoveToFolderOngoing = ETrue; + TFolderListActivationData folderListData; + folderListData.iCallback = this; + folderListData.iSourceFolderType = iMailFolder->GetFolderType(); + const TPckgBuf pkgOut( folderListData ); + if ( targetEntries.Count() == 1 ) + { + iAppUi.EnterFsEmailViewL( FolderListId, KFolderListMoveMessage, pkgOut ); + } + else + { + iAppUi.EnterFsEmailViewL( FolderListId, KFolderListMoveMessages, pkgOut ); + } + ret = KErrNotReady; + } + // Destination folder is set, move message(s) immediately + else + { + iMoveToFolderOngoing = EFalse; + // Get message IDs from target list IDs + RArray msgIds; + CleanupClosePushL( msgIds ); + for ( TInt i = 0 ; i < targetEntries.Count() ; i++) + { + msgIds.Append( MsgIdFromListId( targetEntries[i] ) ); + } + + if ( iMailFolder && msgIds.Count() ) // Something to move + { + // check that source and destination are different + if( iMailFolder->GetFolderId() != aDestinationFolderId ) + { + // Trap is needed because protocol might return KErrNotSupported + // If move away from current folder is not supprted + TRAPD( errMove, iAppUi.GetActiveMailbox()->MoveMessagesL( msgIds, iMailFolder->GetFolderId(), aDestinationFolderId ) ); + if ( errMove != KErrNotSupported ) + { + if ( errMove == KErrNone ) + { + RemoveMsgItemsFromListIfFoundL( msgIds ); + if ( !iMsgNoteTimer ) + { + iMsgNoteTimer = CMsgMovedNoteTimer::NewL( &iAppUi, this ); + } + iMsgNoteTimer->Cancel(); + iMsgNoteTimer->Start( msgIds.Count(), aDestinationFolderId ); + ret = KErrNone; + } + else + { + User::Leave(errMove); + } + } + } + } + CleanupStack::PopAndDestroy( &msgIds ); + } + } + } + CleanupStack::PopAndDestroy( &targetEntries ); + return ret; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::MoveMessagesToDraftsL() + { + FUNC_LOG; + if ( iMailFolder && iMailFolder->GetFolderType() == EFSOutbox ) // Move to drafts should only be available from outbox, safety + { + MoveMsgsToFolderL( iAppUi.GetActiveMailbox()->GetStandardFolderId( EFSDraftsFolder ) ); + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::CollapseAllNodesL() + { + FUNC_LOG; + // Safety check, ignore command if the list is empty + if ( iMailList->Count() ) + { + iMailTreeListVisualizer->CollapseAllL(); + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::ExpandAllNodesL() + { + FUNC_LOG; + // Safety check, ignore command if the list is empty + if ( iMailList->Count() ) + { + TFsTreeItemId prevId = iMailList->FocusedItem(); + iMailTreeListVisualizer->ExpandAllL(); + iMailTreeListVisualizer->SetFocusedItemL( prevId ); + } + } + +void CFSEmailUiMailListVisualiser::ExpandOrCollapseL() + { + FUNC_LOG; + CFSEmailUiMailListModelItem* item = + dynamic_cast( iModel->Item( HighlightedIndex() ) ); + if ( item && item->ModelItemType() == ETypeSeparator ) + { + if ( iMailList->IsExpanded( iMailList->FocusedItem() ) ) + { + //ChangeMskCommandL( R_FSE_QTN_MSK_COLLAPSE ); + iMailList->CollapseNodeL( iMailList->FocusedItem() ); + } + else + { + //ChangeMskCommandL( R_FSE_QTN_MSK_EXPAND ); + iMailList->ExpandNodeL( iMailList->FocusedItem() ); + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SetMessageFollowupFlagL() + { + FUNC_LOG; + if ( TFsEmailUiUtility::IsFollowUpSupported( *iAppUi.GetActiveMailbox() ) ) + { + RFsTreeItemIdList targetItems; + CleanupClosePushL( targetItems ); + GetActionsTargetEntriesL( targetItems ); + + // If there are marked or focused item(s) + if ( targetItems.Count() ) + { + // Convert list IDs to message IDs because it's possible that list refresh + // causes list IDs to change while the flag dialog is open + RArray< TFSMailMsgId > targetMsgIds; + CleanupClosePushL( targetMsgIds ); + for ( TInt i = 0 ; i < targetItems.Count() ; ++i ) + { + TFSMailMsgId msgId = MsgIdFromIndex( ModelIndexFromListId( targetItems[i] ) ); + targetMsgIds.AppendL( msgId ); + } + + TFollowUpNewState newFollowUpState = EFollowUpNoChanges; + if ( TFsEmailUiUtility::RunFollowUpListDialogL( newFollowUpState ) ) + { + // Update the target messages + for ( TInt i = 0 ; i < targetMsgIds.Count() ; ++i ) + { + // Confirm that message is still in the list after selection has closed + TInt itemIndex = ItemIndexFromMessageId( targetMsgIds[i] ); + CFSEmailUiMailListModelItem* modelItem = + static_cast( iModel->Item( itemIndex ) ); + CFSMailMessage* confirmedPtr = NULL; // owned by the model + if ( modelItem ) + { + confirmedPtr = &modelItem->MessagePtr(); + } + if ( confirmedPtr ) + { + // Store flags to confirmed pointer for saving + TInt currentFlags = confirmedPtr->GetFlags(); + switch ( newFollowUpState ) + { + case EFollowUp: + { + confirmedPtr->SetFlag( EFSMsgFlag_FollowUp ); + confirmedPtr->ResetFlag( EFSMsgFlag_FollowUpComplete ); + } + break; + case EFollowUpComplete: + { + confirmedPtr->SetFlag( EFSMsgFlag_FollowUpComplete ); + confirmedPtr->ResetFlag( EFSMsgFlag_FollowUp ); + } + break; + case EFollowUpClear: + { + confirmedPtr->ResetFlag( EFSMsgFlag_FollowUp | EFSMsgFlag_FollowUpComplete ); + } + break; + } + + TInt newFlags = confirmedPtr->GetFlags(); + if ( newFlags != currentFlags ) + { + // Save confirmed message + confirmedPtr->SaveMessageL(); + + // Update flag icon + UpdateMsgIconAndBoldingL( itemIndex ); + + // In case we are in flag sort mode, resetting the flag may cause the list order to be out of date. + if ( iCurrentSortCriteria.iField == EFSMailSortByFlagStatus ) + { + iListOrderMayBeOutOfDate = ETrue; + } + } + } + } + } + CleanupStack::PopAndDestroy( &targetMsgIds ); + } + CleanupStack::PopAndDestroy( &targetItems ); + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SetViewSoftkeysL( TInt aResourceId ) + { + FUNC_LOG; + Cba()->SetCommandSetL( aResourceId ); + Cba()->DrawDeferred(); + } + +// --------------------------------------------------------------------------- +// Method to set Middle SoftKey +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SetMskL() + { + FUNC_LOG; + // Get the mail list count + TInt listCount(0); + if ( iMailList ) + { + listCount = iMailList->Count(); + } + + if ( iFocusedControl == EControlBarComponent ) + { +/* Sorting enabled also for empty list + // Sort menu can't be opened if mail list is empty. Hide MSK label in that case. + if ( !listCount && iControlBarControl->GetFocusedButton() == iSortButton ) + { + ChangeMskCommandL( R_FSE_QTN_MSK_EMPTY ); + } + else + */ + { + ChangeMskCommandL( R_FSE_QTN_MSK_CHANGE ); + } + } + else if ( iFocusedControl == EMailListComponent ) + { + if ( listCount ) // Safety check + { + CFSEmailUiMailListModelItem* item = + dynamic_cast( iModel->Item(HighlightedIndex()) ); + // SHIFT DEPRESSED. SELECTION KEY DOES MARK/UNMARK + if ( iShiftDepressed ) + { + // Nodes may not be marked + if ( iMailList->IsNode( iMailList->FocusedItem() ) ) + { + ChangeMskCommandL( R_FSE_QTN_MSK_EMPTY ); + } + else + { + if ( iMailList->IsMarked( iMailList->FocusedItem() ) ) + { + ChangeMskCommandL( R_FSE_QTN_MSK_UNMARK ); + } + else + { + ChangeMskCommandL( R_FSE_QTN_MSK_MARK ); + } + } + } + else + { + // MAIL ITEM; OPEN MAIL + if ( item && item->ModelItemType() == ETypeMailItem ) + { + CFSMailMessage* messagePtr = &item->MessagePtr(); + if ( messagePtr ) + { + if ( iMailFolder && iMailFolder->GetFolderType() == EFSOutbox ) + { + ChangeMskCommandL( R_FSE_QTN_MSK_OPEN_BLOCKED ); + } + else + { + ChangeMskCommandL( R_FSE_QTN_MSK_OPEN ); + } + } + } + + // SEPARAOR ITEM; COLLAPSE / EXPAND NODE + else if ( item && item->ModelItemType() == ETypeSeparator ) + { + if( iMailList->IsNode( iMailList->FocusedItem() ) ) + { + if ( iMailList->IsExpanded( iMailList->FocusedItem() ) ) + { + ChangeMskCommandL( R_FSE_QTN_MSK_COLLAPSE ); + } + else + { + ChangeMskCommandL( R_FSE_QTN_MSK_EXPAND ); + } + } + } + } + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TBool CFSEmailUiMailListVisualiser::OfferEventL(const TAlfEvent& aEvent) + { + FUNC_LOG; + TBool result( EFalse ); + + if ( !aEvent.IsKeyEvent() ) + { + // Only handle key events + if ( aEvent.IsPointerEvent() ) + { + switch( iFocusedControl ) + { + case EMailListComponent: + { + result = iMailList->TreeControl()->OfferEventL( aEvent ); + break; + } + case EControlBarComponent: + { + result = static_cast( + iControlBarControl )->OfferEventL( aEvent ); + break; + } + default: + { + break; + } + } + } + return result; + } + + TInt scanCode = aEvent.KeyEvent().iScanCode; + // Swap right and left controls in mirrored layout + if ( AknLayoutUtils::LayoutMirrored() ) + { + if ( scanCode == EStdKeyRightArrow ) scanCode = EStdKeyLeftArrow; + else if ( scanCode == EStdKeyLeftArrow ) scanCode = EStdKeyRightArrow; + } + + // Toggle mark items state when shift key is pressed or released + if ( iFocusedControl == EMailListComponent && + ( scanCode == EStdKeyLeftShift || + scanCode == EStdKeyRightShift || + scanCode == EStdKeyHash ) ) + { + if ( aEvent.Code() == EEventKeyDown ) + { + iShiftDepressed = ETrue; + iOtherKeyPressedWhileShiftDepressed = EFalse; + if ( iModel->Count() && iMailList->IsMarked( iMailList->FocusedItem() ) ) + { + iListMarkItemsState = EFalse; // Unmark state + } + else + { + iListMarkItemsState = ETrue; // Mark items state + } + } + else if ( aEvent.Code() == EEventKeyUp ) + { + iShiftDepressed = EFalse; + } + } + + // If any other key event is gained while hash is depressed, the hash key is used only + // as shift and not as individual key. + if ( iShiftDepressed && scanCode && + scanCode != EStdKeyHash && scanCode != EStdKeyLeftShift && scanCode != EStdKeyRightShift ) + { + iOtherKeyPressedWhileShiftDepressed = ETrue; + } + + // MSK label can now be updated when shift key has been handled + SetMskL(); + + if ( aEvent.IsKeyEvent() && aEvent.Code() == EEventKey ) + { + TBool shiftState = (aEvent.KeyEvent().iModifiers & EModifierShift ); + + // Do the (un)marking if in shift state and suitable key is received + if ( shiftState ) + { + switch ( aEvent.KeyEvent().iScanCode ) + { + case EStdKeyDownArrow: + case EStdKeyUpArrow: + { + DoScrollMarkUnmarkL(); + result = EFalse; // event is not consumed yet, because it must also move the cursor + } + break; + case EStdKeyEnter: + case EStdKeyDevice3: + { + if ( !aEvent.KeyEvent().iRepeats ) // no repeated (un)marking by holding selection key depressed + { + // The selection key always toggles the marking state of the current item. + // It also toggles the scroll marking/unmarking state. + if ( iModel->Count() ) + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item( HighlightedIndex() ) ); + + if ( item->ModelItemType() == ETypeMailItem ) // Separators are not markable + { + if ( iMailList->IsMarked( iMailList->FocusedItem() ) ) + { + iMailList->MarkItemL( iMailList->FocusedItem(), EFalse ); + iListMarkItemsState = EFalse; + } + else + { + iMailList->MarkItemL( iMailList->FocusedItem(), ETrue ); + iListMarkItemsState = ETrue; + } + } + } + } + result = ETrue; // shift + selection is always consumed + } + break; + default: + break; + } + + } + + // If event not handled by now + if ( !result ) + { + // Handle possible focus visibility change + if ((scanCode == EStdKeyRightArrow) + || (scanCode == EStdKeyLeftArrow) + || (scanCode == EStdKeyUpArrow) + || (scanCode == EStdKeyDownArrow) + || (scanCode == EStdKeyEnter) + || (scanCode == EStdKeyDeviceA) + || (scanCode ==EStdKeyDevice3)) + { + TBool wasActive = iAppUi.StartFocusRemovalTimer(); + + // If the focus was not active already, ignore the key press + if( !wasActive ) + { + return ETrue; + } + } + + switch ( scanCode ) + { + case EStdKeyDevice3: // CENTER CLICK + case EStdKeyEnter: // ENTER EITHER SELECTS ITEM IN TOOLBAR OR OPENS MAIL + case EStdKeyNkpEnter: + case EAknSoftkeySelect: + { + SetMskL(); + if ( iFocusedControl == EMailListComponent ) + { + TInt modelCount(0); + // + modelCount = iModel->Count(); + // + if ( modelCount ) // Safety check + { + CFSEmailUiMailListModelItem* item = + dynamic_cast( iModel->Item( HighlightedIndex() ) ); + // MAIL ITEM; OPEN MAIL + if ( item && item->ModelItemType() == ETypeMailItem ) + { + CFSMailMessage* messagePtr = &item->MessagePtr(); + if ( messagePtr ) + { + OpenHighlightedMailL(); + return EKeyWasConsumed; + } + } + // SEPARAOR ITEM; COLLAPSE / EXPAND NODE + else if ( item && item->ModelItemType() == ETypeSeparator ) + { + if ( iMailList->IsExpanded( iMailList->FocusedItem()) ) + { + ExpandOrCollapseL(); + } + else + { + ExpandOrCollapseL(); + } + return EKeyWasConsumed; + } + } + } + else + { + TInt focusedButtonId = iControlBarControl->GetFocusedButton()->Id(); + if ( focusedButtonId == iNewEmailButtonId ) + { + HandleCommandL(EFsEmailUiCmdCompose); + } + else if ( focusedButtonId == iFolderListButtonId ) + { + // + //Set touchmanager not active for preventing getting events. + DisableMailList(ETrue); + // + iAppUi.ShowFolderListInPopupL( FolderId(), this, iFolderListButton ); + } + else if ( focusedButtonId == iSortButtonId ) + { + TFSFolderType folderType; + if( iMailFolder ) + { + folderType = iMailFolder->GetFolderType(); + } + else + { + folderType = EFSInbox; + } + // Show sort if model has data. + if ( iModel->Count() ) + { + // + //Set touchmanager not active for preventing getting events. + DisableMailList(ETrue); + // + iAppUi.ShowSortListInPopupL( iCurrentSortCriteria.iField, folderType, this, iSortButton ); + } + else + { + // hide selector focus if popup is not opened + // and selection was not made via HW-keys + iControlBarControl->MakeSelectorVisible( + IsFocusShown() ); + } + } + return ETrue;//iControlBar->OfferEventL( aEvent ); + } + } + break; + case EStdKeyLeftArrow: + { + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + if( iControlBarControl && iFocusedControl == EMailListComponent ) + { + HandleCommandL( EFsEmailUiCmdGoToSwitchSorting ); + result = ETrue; + } + else if( ( iControlBarControl ) && + ( iFocusedControl == EControlBarComponent ) ) + { + + TInt focusedButtonId = iControlBarControl->GetFocusedButton()->Id(); + if ( focusedButtonId == iFolderListButtonId ) + { + if ( iModel->Count() ) + { + iFocusedControl = EMailListComponent; + result = EFalse; + } + else + { + iFocusedControl = EControlBarComponent; + result = ETrue; // Do not set focus to empty list + } + } + else + { + iFocusedControl = EControlBarComponent; + result = EFalse; + } + } + else + { + iFocusedControl = EMailListComponent; + result = EFalse; + } + SetMskL(); + } + break; + case EStdKeyRightArrow: + { + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + // Show toolbar if there is data on the list + // + if ( iFocusedControl == EMailListComponent && iModel->Count() ) + // + { + RFsTreeItemIdList targetEntries; + CleanupClosePushL( targetEntries ); + GetActionsTargetEntriesL( targetEntries ); + TInt targetCount = targetEntries.Count(); + CleanupStack::PopAndDestroy( &targetEntries ); + + if ( targetCount ) + { + LaunchStylusPopupMenuL(); + result = ETrue; + } + } + else if( ( iControlBarControl ) && + ( iFocusedControl == EControlBarComponent ) ) + { + TInt focusedButtonId = iControlBarControl->GetFocusedButton()->Id(); + if ( focusedButtonId == iFolderListButtonId ) + { + iFocusedControl = EControlBarComponent; + result = EFalse; + } + else + { + if ( iModel->Count() ) // Check for empty folder + { + iFocusedControl = EMailListComponent; + result = EFalse; + } + else + { + iFocusedControl = EControlBarComponent; + result = ETrue; // Do not set focus to empty list + } + } ; + } + else + { + iFocusedControl = EMailListComponent; + result = EFalse; + } + SetMskL(); + } + break; + case EStdKeyDownArrow: + { + if ( iFocusedControl == EMailListComponent ) + { + result = iMailList->TreeControl()->OfferEventL(aEvent); + if ( shiftState ) + { + DoScrollMarkUnmarkL(); // marking is done after moving the cursor + } + } + // + else if ( iFocusedControl == EControlBarComponent && iModel->Count() == 0 ) + { + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + result = ETrue; // Do not set focus to empty list + } + else if ( iFocusedControl == EControlBarComponent && iModel->Count() != 0 ) + // + { + iFocusedControl = EMailListComponent; + + result = iMailList->TreeControl()->OfferEventL(aEvent); + if ( shiftState ) + { + DoScrollMarkUnmarkL(); // marking is done after moving the cursor + } + } + else + { + result = EFalse; + } + SetMskL(); + } + break; + case EStdKeyUpArrow: + { + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + if ( iFocusedControl == EMailListComponent ) + { + if ( HighlightedIndex() == 0 ) + { + HandleCommandL( EFsEmailUiCmdGoToSwitchFolder ); + result = ETrue; + } + else + { + result = iMailList->TreeControl()->OfferEventL(aEvent); + if ( shiftState ) + { + DoScrollMarkUnmarkL(); // marking is done after moving the cursor + } + SetMskL(); + } + } + else if (iFocusedControl == EControlBarComponent) + { + result = ETrue; + } + else + { + result = EFalse; + } + } + break; + case EStdKeyYes: + { + if ( !iAppUi.ViewSwitchingOngoing() ) + { + if ( iMailFolder && iMailFolder->GetFolderType() != EFSOutbox && + iMailFolder->GetFolderType() != EFSDraftsFolder ) + { + TInt modelCount = iModel->Count(); + if ( modelCount ) // Safety check + { + CFSEmailUiMailListModelItem* item = + dynamic_cast( iModel->Item( HighlightedIndex() ) ); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + CFSMailAddress* fromAddress = item->MessagePtr().GetSender(); + TDesC* mailAddress(0); + if ( fromAddress ) + { + mailAddress = &fromAddress->GetEmailAddress(); + } + if ( mailAddress && mailAddress->Length() ) + { + if ( iMailFolder->GetFolderType() == EFSSentFolder ) + { + CFsDelayedLoader::InstanceL()->GetContactHandlerL()->FindAndCallToContactByEmailL( + *mailAddress, iAppUi.GetActiveMailbox(), this, EFalse ); + } + else + { + CFsDelayedLoader::InstanceL()->GetContactHandlerL()->FindAndCallToContactByEmailL( + *mailAddress, iAppUi.GetActiveMailbox(), this, ETrue ); + } + } + } + } + } + } + } + break; + case EStdKeyHash: + { + // Consume hash key events before they go to our shortcut framework. We do not want + // to react to those until the in the key up event. There hash key works as mark/unmark shortcut only + // if it hasn't been used as shift modifier. + result = ETrue; + } + break; + // + // Backspace (C key) must be handled on Key-Down instead of Key-Up + // ( this was the reason that deleted two emails from opened mail in viewer ) + case EStdKeyBackspace: + { + TInt shortcutCommand = iAppUi.ShortcutBinding().CommandForShortcutKey( aEvent.KeyEvent(), + CFSEmailUiShortcutBinding::EContextMailList ); + + if ( shortcutCommand != KErrNotFound ) + { + HandleCommandL( shortcutCommand ); + result = ETrue; + } + else result = EFalse; + } + break; + // + default: + { + if ( iFocusedControl == EMailListComponent ) + { + result = iMailList->TreeControl()->OfferEventL(aEvent); + } + else + { + result = EFalse; + } + } + break; + } + } + } + else if ( aEvent.IsKeyEvent() && aEvent.Code() == EEventKeyUp ) + { + // Check keyboard shortcuts on key up events. These can't be checked on key event + // because half-QWERTY keyboad has shortcuts also on shift and chr keys which do + // no send any key events, only key down and key up. + TInt shortcutCommand = + iAppUi.ShortcutBinding().CommandForShortcutKey( aEvent.KeyEvent(), + CFSEmailUiShortcutBinding::EContextMailList ); + // Hash/shift key of ITU-T and half-QWERTY keyboards is an exception case to other + // shortcuts: it is handled only if it hasn't been used as shift modifier + if ( (scanCode == EStdKeyHash || scanCode == EStdKeyLeftShift || scanCode == EStdKeyRightShift) && + iOtherKeyPressedWhileShiftDepressed ) + { + shortcutCommand = KErrNotFound; + } + + // // block Backspace (C key) handle on Key-Up + if ( scanCode == EStdKeyBackspace) shortcutCommand = KErrNotFound; // handled on Key-Down, see above + // + + if ( shortcutCommand != KErrNotFound ) + { + HandleCommandL( shortcutCommand ); + result = ETrue; + } + else + { + result = EFalse; + } + } + + return result; + } + +// +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::DoHandleListItemOpenL +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DoHandleListItemOpenL() + { + FUNC_LOG; + if ( 0 < iModel->Count() ) // Safety check + { + CFSEmailUiMailListModelItem* item = + dynamic_cast( iModel->Item( HighlightedIndex() ) ); + // MAIL ITEM; OPEN MAIL + if ( item && item->ModelItemType() == ETypeMailItem ) + { + CFSMailMessage* messagePtr = &item->MessagePtr(); + if ( messagePtr ) + { + OpenHighlightedMailL(); + } + } + // SEPARATOR ITEM; COLLAPSE / EXPAND NODE + else if ( item && item->ModelItemType() == ETypeSeparator ) + { + ExpandOrCollapseL(); + SetMskL(); + } + } + } + +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::DoHandleControlBarOpenL +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DoHandleControlBarOpenL( TInt aControlBarButtonId ) + { + FUNC_LOG; + + if ( aControlBarButtonId == iNewEmailButtonId ) + { + HandleCommandL(EFsEmailUiCmdCompose); + } + else if ( aControlBarButtonId == iFolderListButtonId ) + { + //FOLDERLIST + //Set touchmanager not active for preventing getting events. + DisableMailList(ETrue); + iAppUi.ShowFolderListInPopupL( FolderId(), this, iFolderListButton ); + } + else if ( aControlBarButtonId == iSortButtonId ) + { + //SORTLIST + TFSFolderType folderType; + if ( iMailFolder ) + { + folderType = iMailFolder->GetFolderType(); + } + else + { + folderType = EFSInbox; + } + if ( iModel->Count() ) + { + //Set touchmanager not active for preventing getting events. + DisableMailList(ETrue); + iAppUi.ShowSortListInPopupL( iCurrentSortCriteria.iField, folderType, this, iSortButton ); + } + else + { + // hide selector focus if popup is not opened and selection was not + // made via HW-keys + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + } + } + } + +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::DoHandleListItemLongTapL +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DoHandleListItemLongTapL() + { + FUNC_LOG; + + if ( 0 < iModel->Count() ) // Safety check + { + RFsTreeItemIdList markedEntries; + iMailList->GetMarkedItemsL( markedEntries ); + if ( markedEntries.Count() >= 0 ) + { + LaunchStylusPopupMenuL(); + } + } + } + +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::GetFocusedControl +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::GetFocusedControl() const + { + FUNC_LOG; + return iFocusedControl; + } + +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::SetControlBarFocusedL +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SetControlBarFocusedL() + { + FUNC_LOG; + iFocusedControl = EControlBarComponent; + iMailList->SetFocusedL( EFalse ); + SetMskL(); + } + +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::SetTreeListFocusedL +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SetTreeListFocusedL() + { + FUNC_LOG; + iFocusedControl = EMailListComponent; + iMailList->SetFocusedL( ETrue ); + iControlBarControl->SetFocusL( EFalse ); + SetMskL(); + } + +// ----------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::FlipStateChangedL +// ----------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::FlipStateChangedL( TBool aKeyboardFlipOpen ) + { + FUNC_LOG; + CFsEmailUiViewBase::FlipStateChangedL( aKeyboardFlipOpen ); + iMailTreeListVisualizer->SetFlipState( iKeyboardFlipOpen ); + } + +// ----------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::HandleTimerFocusStateChange +// ----------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::HandleTimerFocusStateChange( TBool aShow ) + { + FUNC_LOG; + CFsEmailUiViewBase::HandleTimerFocusStateChange( aShow ); + if( iFocusedControl == EControlBarComponent ) + { + iControlBarControl->MakeSelectorVisible( aShow ); + } + iMailTreeListVisualizer->SetFocusVisibility( aShow ); + } + +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::DisableMailList +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DisableMailList( TBool aValue ) + { + FUNC_LOG; + iTouchManager->SetDisabled( aValue ); + iControlBarControl->EnableTouch( (aValue) ? EFalse : ETrue ); + } +// + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::ShortcutCollapseExpandAllToggleL() + { + FUNC_LOG; + if ( !AllNodesCollapsed() ) + { + CollapseAllNodesL(); + } + else + { + ExpandAllNodesL(); + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TBool CFSEmailUiMailListVisualiser::AllNodesCollapsed() const + { + FUNC_LOG; + for ( TInt i=0;iIsNode( iTreeItemArray[i].iListItemId ) ) + { + if ( iMailList->IsExpanded( iTreeItemArray[i].iListItemId ) ) + { + return EFalse; + } + } + } + + return ETrue; + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +TBool CFSEmailUiMailListVisualiser::AllNodesExpanded() const + { + FUNC_LOG; + for ( TInt i=0;iIsNode( iTreeItemArray[i].iListItemId ) ) + { + if ( !iMailList->IsExpanded( iTreeItemArray[i].iListItemId ) ) + { + return EFalse; + } + } + } + + return ETrue; + } + +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::IsMarkAsReadAvailableL() +// Function checks if mark as read option should be available for user +// --------------------------------------------------------------------------- +// +TBool CFSEmailUiMailListVisualiser::IsMarkAsReadAvailableL() const + { + FUNC_LOG; + TBool available = EFalse; + + // In outbox the mark as read is always inavailable + if ( iMailFolder && iMailFolder->GetFolderType() != EFSOutbox ) + { + RFsTreeItemIdList targetEntries; + CleanupClosePushL( targetEntries ); + GetActionsTargetEntriesL( targetEntries ); + + // Mark as read is available if at least one of the target entries is unread + for ( TInt i = 0 ; i < targetEntries.Count() ; ++i ) + { + const CFSMailMessage& message = MsgPtrFromListIdL( targetEntries[i] ); + if ( !message.IsFlagSet(EFSMsgFlag_Read) ) + { + available = ETrue; + break; + } + } + + CleanupStack::PopAndDestroy( &targetEntries ); + } + + return available; + } + +// --------------------------------------------------------------------------- +// CFSEmailUiMailListVisualiser::IsMarkAsUnreadAvailableL() +// Function checks if mark as unread option should be available for user +// --------------------------------------------------------------------------- +// +TBool CFSEmailUiMailListVisualiser::IsMarkAsUnreadAvailableL() const + { + FUNC_LOG; + TBool available = EFalse; + + // In outbox the mark as unread is always inavailable + if ( iMailFolder && iMailFolder->GetFolderType() != EFSOutbox ) + { + RFsTreeItemIdList targetEntries; + CleanupClosePushL( targetEntries ); + GetActionsTargetEntriesL( targetEntries ); + + // Mark as unread is available if at least one of the target entries is read + for ( TInt i = 0 ; i < targetEntries.Count() ; ++i ) + { + const CFSMailMessage& message = MsgPtrFromListIdL( targetEntries[i] ); + if ( message.IsFlagSet(EFSMsgFlag_Read) ) + { + available = ETrue; + break; + } + } + + CleanupStack::PopAndDestroy( &targetEntries ); + } + + return available; + } + +// --------------------------------------------------------------------------- +// Utility function to get list of entries which will be targeted by the +// Actions menu commands. The list contains either marked entries or the +// focused message entry or is empty. +// --------------------------------------------------------------------------- +void CFSEmailUiMailListVisualiser::GetActionsTargetEntriesL( RFsTreeItemIdList& aListItems ) const + { + FUNC_LOG; + if ( iMailList ) + { + iMailList->GetMarkedItemsL( aListItems ); + + // If there are no marked entries the command target is the focused item. + if ( !aListItems.Count() ) + { + TFsTreeItemId focusedId = iMailList->FocusedItem(); + if ( iFocusedControl == EMailListComponent && + focusedId != KFsTreeNoneID && + !iMailList->IsNode( focusedId ) ) + { + aListItems.AppendL( focusedId ); + } + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::ShortcutReadUnreadToggleL() + { + FUNC_LOG; + // Setting the read status is not possible in outbox + // + if ( iModel->Count() && iMailFolder && iMailFolder->GetFolderType() != EFSOutbox ) + // + { + RFsTreeItemIdList targetEntries; + CleanupClosePushL( targetEntries ); + GetActionsTargetEntriesL( targetEntries ); + TInt targetCount = targetEntries.Count(); + + // figure out are we marking items as read or unread + TBool toggleAsRead(ETrue); + for ( TInt i=0 ; iSetFocusedL( ETrue ) ); + } + else if ( aEvent == EEventFocusGained ) + { + } + else if ( aEvent == EEventButtonPressed ) + { + // Handle 2 control buttons + if ( aData == iFolderListButtonId ) + { + } + else if ( aData == iSortButtonId ) + { + } + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::CreateControlBarLayoutL() + { + FUNC_LOG; + TRect screenRect = iAppUi.ClientRect(); + iControlBarControl->SetWidthL( screenRect.Width() ); + // ?? + //TInt normalButtonWidth = ( screenRect.Width() - KFirstButtonStartPosX*2 - 10 ) / 2; + // + // Mailbox icon + iImageButtonId = iControlBarControl->AddButtonL( ECBTypeIconOnly ); + iIconButton = iControlBarControl->ButtonById( iImageButtonId ); +// Use layout data instead of hardcoded values + const TRect iconButtonRect( iAppUi.LayoutHandler()->GetControlBarMailboxIconRect() ); + iIconButton->SetPos( iconButtonRect.iTl ); + iIconButton->SetSize( iconButtonRect.Size() ); + ControlGroup().AppendL(iIconButton->AsAlfControl()); +// + + // Folder list button + iFolderListButtonId = iControlBarControl->AddButtonL( ECBTypeOneLineLabelIconB ); + iFolderListButton = iControlBarControl->ButtonById( iFolderListButtonId ); +// Use layout data instead of hardcoded values + const TRect folderButtonRect( iAppUi.LayoutHandler()->GetControlBarFolderListButtonRect() ); + iFolderListButton->SetPos( folderButtonRect.iTl ); + iFolderListButton->SetSize( folderButtonRect.Size() ); + ControlGroup().AppendL(iFolderListButton->AsAlfControl()); +// + + // Sort order button + iSortButtonId = iControlBarControl->AddButtonL( ECBTypeOneLineLabelIconB ); + iSortButton = iControlBarControl->ButtonById( iSortButtonId ); +// Use layout data instead of hardcoded values + const TRect sortButtonRect( iAppUi.LayoutHandler()->GetControlBarSortButtonRect() ); + iSortButton->SetPos( sortButtonRect.iTl ); + iSortButton->SetSize( sortButtonRect.Size() ); + ControlGroup().AppendL(iSortButton->AsAlfControl()); +// + + // Set the text alignment according the layout + TAlfAlignHorizontal horizontalAlign = EAlfAlignHLeft; + if ( AknLayoutUtils::LayoutMirrored() ) + { + horizontalAlign = EAlfAlignHRight; + } + iFolderListButton->SetElemAlignL( + ECBElemLabelFirstLine, + horizontalAlign, + EAlfAlignVCenter ); + iSortButton->SetElemAlignL( + ECBElemLabelFirstLine, + horizontalAlign, + EAlfAlignVCenter ); + + // Show the buttons + iIconButton->ClearBackgroundColor(); + iIconButton->SetDimmed(); + iFolderListButton->ShowButtonL(); + iSortButton->ShowButtonL(); + + // Button background images + iFolderListButton->ClearBackgroundColor(); + iSortButton->ClearBackgroundColor(); + + // Icons and sort button text + iIconButton->SetIconL( iAppUi.FsTextureManager()->TextureByIndex( EListControlBarMailboxDefaultIcon ) ); + SetSortButtonTextAndIconL(); + + //iControlBarControl->SetSelectorBorders(-2,-2,-2,-2 ); // CHECKLATER - commented out 'cause fixing things is hard - check later to replace (?) it + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::ScaleControlBarL() + { + FUNC_LOG; + TRect screenRect = iAppUi.ClientRect(); + + // First set widht and height + iControlBarControl->SetHeightL( iAppUi.LayoutHandler()->ControlBarHeight() ); + iControlBarControl->SetWidthL( screenRect.Width() ); + + const TRect iconButtonRect( iAppUi.LayoutHandler()->GetControlBarMailboxIconRect() ); + iIconButton->SetPos( iconButtonRect.iTl ); + iIconButton->SetSize( iconButtonRect.Size() ); + + const TRect folderButtonRect( iAppUi.LayoutHandler()->GetControlBarFolderListButtonRect() ); + iFolderListButton->SetPos( folderButtonRect.iTl ); + iFolderListButton->SetSize( folderButtonRect.Size() ); + + const TRect sortButtonRect( iAppUi.LayoutHandler()->GetControlBarSortButtonRect() ); + iSortButton->SetPos( sortButtonRect.iTl ); + iSortButton->SetSize( sortButtonRect.Size() ); + + // Bar background + CAlfTexture& barBg = iAppUi.FsTextureManager()->TextureByIndex( EMailListBarBgIcon ); + TSize cbBgSize; + cbBgSize.SetSize( screenRect.Width(), iAppUi.LayoutHandler()->ControlBarHeight() ); + barBg.Size().SetSize( cbBgSize.iWidth, cbBgSize.iHeight ); + // S60 Skin support + //iControlBarControl->SetBackgroundImageL( barBg ); + // + + // Button background + CAlfTexture& buttonBg = iAppUi.FsTextureManager()->TextureByIndex( EListTextureControlButton ); + // + buttonBg.Size().SetSize( iAppUi.LayoutHandler()->GetControlBarFolderListButtonSize().iWidth, iAppUi.LayoutHandler()->GetControlBarFolderListButtonSize().iHeight ); + // + + // construct main text display window +// Use layout data instead of hard-coded values +// const CFont* font = iEikonEnv->NormalFont(); +// TFontSpec fontSpec = font->FontSpecInTwips(); + //fontSpec.iHeight = iAppUi.LayoutHandler()->ControlBarTextHeight(); + + TInt var = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0; + TAknLayoutText textLayout; + textLayout.LayoutText(TRect(0,0,0,0), AknLayoutScalable_Apps::main_sp_fs_ctrlbar_ddmenu_pane_t1(var)); + iFolderListButton->SetTextFontL( textLayout.Font()->FontSpecInTwips() ); + iSortButton->SetTextFontL( textLayout.Font()->FontSpecInTwips() ); +// + + TRgb normalStateButtonTextColor( KRgbBlack ); + AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), + normalStateButtonTextColor, KAknsIIDFsTextColors, EAknsCIFsTextColorsCG6 ); + + iFolderListButton->SetNormalTextColor( normalStateButtonTextColor ); + iFolderListButton->SetFocusedTextColor( iAppUi.LayoutHandler()->ListFocusedStateTextSkinColor() ); + + iSortButton->SetNormalTextColor( normalStateButtonTextColor ); + iSortButton->SetFocusedTextColor( iAppUi.LayoutHandler()->ListFocusedStateTextSkinColor() ); + + CAlfImageBrush* folderBtnBrush = iAppUi.FsTextureManager()->NewControlBarButtonBgBrushLC(); + iFolderListButton->SetBackgroundImageL( folderBtnBrush ); + CleanupStack::Pop( folderBtnBrush ); + + CAlfImageBrush* sortBtnBrush = iAppUi.FsTextureManager()->NewControlBarButtonBgBrushLC(); + iSortButton->SetBackgroundImageL( sortBtnBrush ); + CleanupStack::Pop( sortBtnBrush ); + + iIconButton->ShowButtonL(); + iFolderListButton->ShowButtonL(); + iSortButton->ShowButtonL(); + + iFolderListButton->SetIconL( iAppUi.FsTextureManager()->TextureByIndex( EControlBarDescendingArrowTexture ), ECBElemIconB ); + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SetSortButtonTextAndIconL() + { + FUNC_LOG; + HBufC* buttonText(0); + switch ( iCurrentSortCriteria.iField ) + { + case EFSMailSortBySubject: + { + buttonText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_SORT_BY_SUBJECT ); + } + break; + case EFSMailSortByAttachment: + { + buttonText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_SORT_BY_ATTACHMENT ); + } + break; + case EFSMailSortByFlagStatus: + { + buttonText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_SORT_BY_FLAG ); + } + break; + case EFSMailSortByRecipient: + case EFSMailSortBySender: + { + TFSFolderType folderType( EFSInbox ); + if( iMailFolder ) + { + folderType = iMailFolder->GetFolderType(); + } + switch( folderType ) + { + case EFSSentFolder: + case EFSDraftsFolder: + case EFSOutbox: + { + buttonText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_SORT_BY_RECIPIENT ); + } + break; + default: + buttonText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_SORT_BY_SENDER ); + break; + } + } + break; + case EFSMailSortByPriority: + { + buttonText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_SORT_BY_PRIORITY ); + } + break; + case EFSMailSortByUnread: + { + buttonText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_SORT_BY_UNREAD ); + } + break; + case EFSMailSortByDate: + default: + { + buttonText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_SORT_BY_DATE ); + } + break; + + } + if ( buttonText ) + { + CleanupStack::PushL( buttonText ); + iSortButton->SetTextL( *buttonText ); + CleanupStack::PopAndDestroy( buttonText ); + } + if ( iCurrentSortCriteria.iOrder == EFSMailAscending ) + { + iSortButton->SetIconL( iAppUi.FsTextureManager()->TextureByIndex( EControlBarAscendingArrowTexture ), ECBElemIconB ); + } + else + { + iSortButton->SetIconL( iAppUi.FsTextureManager()->TextureByIndex( EControlBarDescendingArrowTexture ), ECBElemIconB ); + } + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SetMailListLayoutAnchors() + { + FUNC_LOG; + // Set anchors so that list leaves space for control bar + iScreenAnchorLayout->SetAnchor(EAlfAnchorTopLeft, 0, + EAlfAnchorOriginLeft, EAlfAnchorOriginTop, + EAlfAnchorMetricRelativeToSize, EAlfAnchorMetricRelativeToSize, + TAlfTimedPoint(0, 0 )); + iScreenAnchorLayout->SetAnchor(EAlfAnchorBottomRight, 0, + EAlfAnchorOriginLeft, EAlfAnchorOriginTop, + EAlfAnchorMetricRelativeToSize, EAlfAnchorMetricAbsolute, + TAlfTimedPoint(1, iAppUi.LayoutHandler()->ControlBarHeight() )); + + // Platform layout changes + TRect listRect = iAppUi.LayoutHandler()->GetListRect(); + // Set anchors so that list leaves space for control bar + iScreenAnchorLayout->SetAnchor(EAlfAnchorTopLeft, 1, + EAlfAnchorOriginLeft, EAlfAnchorOriginTop, + EAlfAnchorMetricAbsolute, EAlfAnchorMetricAbsolute, + TAlfTimedPoint(listRect.iTl.iX, listRect.iTl.iY)); + iScreenAnchorLayout->SetAnchor(EAlfAnchorBottomRight, 1, + EAlfAnchorOriginLeft, EAlfAnchorOriginTop, + EAlfAnchorMetricAbsolute, EAlfAnchorMetricAbsolute, + TAlfTimedPoint(listRect.iBr.iX, listRect.iBr.iY)); + // Platform layout changes + + // Set anchors for connection icon + + // Platform layout changes + TRect connectionIconRect( iAppUi.LayoutHandler()->GetControlBarConnectionIconRect() ); + const TPoint& tl( connectionIconRect.iTl ); + iScreenAnchorLayout->SetAnchor(EAlfAnchorTopLeft, 2, + EAlfAnchorOriginLeft, EAlfAnchorOriginTop, + EAlfAnchorMetricAbsolute, EAlfAnchorMetricAbsolute, + TAlfTimedPoint( tl.iX, tl.iY )); + const TPoint& br( connectionIconRect.iBr ); + iScreenAnchorLayout->SetAnchor(EAlfAnchorBottomRight, 2, + EAlfAnchorOriginLeft, EAlfAnchorOriginTop, + EAlfAnchorMetricAbsolute, EAlfAnchorMetricAbsolute, + TAlfTimedPoint( br.iX, br.iY )); + // Platform layout changes + + iScreenAnchorLayout->UpdateChildrenLayout(); + } + +// --------------------------------------------------------------------------- +// +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::ChangeReadStatusOfHighlightedL( TBool aRead ) + { + FUNC_LOG; + ChangeReadStatusOfIndexL( aRead, HighlightedIndex() ); + } + +// --------------------------------------------------------------------------- +// ChangeReadStatusOfMarkedL +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::ChangeReadStatusOfMarkedL( TBool aRead ) + { + FUNC_LOG; + RFsTreeItemIdList markedEntries; + CleanupClosePushL( markedEntries ); + iMailList->GetMarkedItemsL( markedEntries ); + for ( TInt i=0; i + if ( iModel->Count() ) + // + { + CFSEmailUiMailListModelItem* selectedItem = + static_cast( iModel->Item( aIndex )); + CFSMailMessage& msgPtr = selectedItem->MessagePtr(); + TBool msgWasReadBefore = msgPtr.IsFlagSet( EFSMsgFlag_Read ); + if ( aRead != msgWasReadBefore ) + { + if ( aRead ) + { + // Send flags, local and server + msgPtr.SetFlag( EFSMsgFlag_Read ); + } + else + { + // Send flags, local and server + msgPtr.ResetFlag( EFSMsgFlag_Read ); + } + msgPtr.SaveMessageL(); // Save flag + + // Switch icon to correct one + UpdateMsgIconAndBoldingL( aIndex ); + + if ( iCurrentSortCriteria.iField == EFSMailSortByUnread ) + { + // Attribute affecting the current sorting order has been changed. + // Thus, the list order may now be incorrect. + iListOrderMayBeOutOfDate = ETrue; + } + } + } + } + +// --------------------------------------------------------------------------- +// DeleteMessagesL +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DeleteMessagesL() + { + FUNC_LOG; + TInt markedCount = CountMarkedItemsL(); + + // Delete either marked items or the focused one + if ( markedCount ) + { + DeleteMarkedMessagesL(); + } + else + { + DeleteFocusedMessageL(); + } + + // Set highlight to control bar if no items after delete + // + if ( iModel->Count() == 0 ) + // + { + iFocusedControl = EControlBarComponent; + iMailList->SetFocusedL( EFalse ); + iControlBarControl->SetFocusL(); + } + } + +// --------------------------------------------------------------------------- +// UpdateItemAtIndexL +// Reload message pointer from mail client and update list item contents to +// match it. Item is removed if it isn't valid anymore. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdateItemAtIndexL( TInt aIndex ) + { + FUNC_LOG; + // + + if ( aIndex >= 0 && aIndex < iModel->Count() ) + // + { + CFSEmailUiMailListModelItem* modelItem = + static_cast( Model()->Item( aIndex ) ); + if ( modelItem->ModelItemType() == ETypeMailItem ) + { + // This is beacause message deleted event migh have occured. + CFSMailMessage* confirmedMsgPtr = NULL; + TRAP_IGNORE( confirmedMsgPtr = iAppUi.GetMailClient()->GetMessageByUidL( iAppUi.GetActiveMailboxId(), + iMailFolder->GetFolderId(), + modelItem->MessagePtr().GetMessageId() , + EFSMsgDataEnvelope ) ); + if ( confirmedMsgPtr ) + { + // Replace message pointer in model with newly fetched one + Model()->ReplaceMessagePtr( aIndex, confirmedMsgPtr ); + + const SMailListItem& item = iTreeItemArray[aIndex]; + + // Update the list item contents and formating to match the message pointer + CFsTreePlainTwoLineItemData* itemData = + static_cast( item.iTreeItemData ); + CFsTreePlainTwoLineItemVisualizer* itemVis = + static_cast( item.iTreeItemVisualiser ); + + UpdateItemDataL( itemData, confirmedMsgPtr ); + UpdatePreviewPaneTextForItemL( itemData, confirmedMsgPtr ); + UpdateMsgIconAndBoldingL( itemData, itemVis, confirmedMsgPtr ); + iMailTreeListVisualizer->UpdateItemL( item.iListItemId ); + } + else + { + // No confirmed message for highlighted, remove from list also + iMailList->RemoveL( iTreeItemArray[aIndex].iListItemId ); // remove from list + iTreeItemArray.Remove( aIndex ); // remove from internal array. + iModel->RemoveAndDestroy( aIndex ); // Remove from model + if ( iNodesInUse ) + { + RemoveUnnecessaryNodesL(); + } + } + } + } + } + +// --------------------------------------------------------------------------- +// CheckValidityOfHighlightedMsgL +// Check validity of highlighted msg, and remove from list if needed +// Typically called after view is returned from editot or viewer. +// --------------------------------------------------------------------------- +// +TBool CFSEmailUiMailListVisualiser::CheckValidityOfHighlightedMsgL() + { + FUNC_LOG; + TBool ret(EFalse); + // + if ( iModel->Count() ) + // + { + CFSEmailUiMailListModelItem* item = + static_cast( Model()->Item( HighlightedIndex() ) ); + if ( item->ModelItemType() == ETypeMailItem ) + { + // This is beacause message deleted event migh have occured. + CFSMailMessage* confirmedMsgPtr = NULL; + TRAP_IGNORE( confirmedMsgPtr = iAppUi.GetMailClient()->GetMessageByUidL( iAppUi.GetActiveMailboxId(), + iMailFolder->GetFolderId(), + item->MessagePtr().GetMessageId() , + EFSMsgDataEnvelope ) ); + if ( confirmedMsgPtr ) + { + ret = ETrue; + delete confirmedMsgPtr; + confirmedMsgPtr = NULL; + } + else + { + // No confirmed message for highlighted, remove from list also + ret = EFalse; + SMailListItem item; + item.iListItemId = iMailList->FocusedItem(); + TInt IndexToBeDestroyed = iTreeItemArray.Find( item ); + iTreeItemArray.Remove( IndexToBeDestroyed ); // remove from internal array. + iModel->RemoveAndDestroy( IndexToBeDestroyed ); // Remove from model + iMailList->RemoveL( iMailList->FocusedItem() ); // remove from list + if ( iNodesInUse ) + { + RemoveUnnecessaryNodesL(); + } + } + } + } + return ret; + } + +// --------------------------------------------------------------------------- +// UpdateMsgIconAndBoldingL +// Updates our own message object with the data from a given message object. +// The messages are matched with the message ID. +// --------------------------------------------------------------------------- +void CFSEmailUiMailListVisualiser::UpdateMsgIconAndBoldingL( CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + // + if ( aMsgPtr && iModel->Count() ) + // + { + TInt mailItemIdx = ItemIndexFromMessageId( aMsgPtr->GetMessageId() ); + if ( mailItemIdx >= 0 ) + { + CFSEmailUiMailListModelItem* item = + static_cast( Model()->Item( mailItemIdx ) ); + + // Update all flags + TUint32 prevFlags = item->MessagePtr().GetFlags(); + TUint32 newFlags = aMsgPtr->GetFlags(); + if ( prevFlags != newFlags ) + { + item->MessagePtr().ResetFlag( prevFlags ); + item->MessagePtr().SetFlag( newFlags ); + + // Save changed flags in internal model array + item->MessagePtr().SaveMessageL(); + } + + // Update the list item graphics + UpdateMsgIconAndBoldingL( mailItemIdx ); + } + } + } + +// --------------------------------------------------------------------------- +// UpdateMsgIconAndBoldingL +// Updates list item at given index to match the state of the message object +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdateMsgIconAndBoldingL( TInt aListIndex, TBool aRefreshItem ) + { + FUNC_LOG; + CFSEmailUiMailListModelItem* item = + static_cast( Model()->Item(aListIndex) ); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + CFSMailMessage* msgPtr = &item->MessagePtr(); + CFsTreePlainTwoLineItemData* itemData = + static_cast( iTreeItemArray[aListIndex].iTreeItemData ); + CFsTreePlainTwoLineItemVisualizer* itemVis = + static_cast( iTreeItemArray[aListIndex].iTreeItemVisualiser ); + + UpdateMsgIconAndBoldingL( itemData, itemVis, msgPtr ); + + //refresh item if requested + if ( aRefreshItem ) + { + iMailTreeListVisualizer->UpdateItemL( iTreeItemArray[aListIndex].iListItemId ); + } + } + } + +// --------------------------------------------------------------------------- +// UpdateMsgIconAndBoldingL +// Updates list item at given index to match the state of the message object +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdateMsgIconAndBoldingL( CFsTreePlainTwoLineItemData* aItemData, + CFsTreePlainTwoLineItemVisualizer* aItemVis, + CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + + if ( aItemData && aItemVis && aMsgPtr ) + { + CAlfTexture* itemTexture = &TFsEmailUiUtility::GetMsgIcon( aMsgPtr, *iAppUi.FsTextureManager() ); + + aItemData->SetIcon( *itemTexture ); + + // Set font according the read status + if ( aMsgPtr->IsFlagSet( EFSMsgFlag_Read ) ) + { + CAlfTextStyle* textStyle = iAppUi.LayoutHandler()->FSTextStyleFromIdL( EFSFontTypeSmall ); + aItemVis->SetTextStyleId ( textStyle->Id() ); + aItemVis->SetTextBold( EFalse ); + } + else + { + CAlfTextStyle* textStyle = iAppUi.LayoutHandler()->FSTextStyleFromIdL( EFSFontTypeSmallBold ); + aItemVis->SetTextStyleId ( textStyle->Id() ); + aItemVis->SetTextBold( ETrue ); + } + + // Set follow up flag icon + if ( aMsgPtr->IsFlagSet( EFSMsgFlag_FollowUp ) ) + { + aItemData->SetFlagIcon( iAppUi.FsTextureManager()->TextureByIndex( EFollowUpFlagList ) ); + aItemVis->SetFlagIconVisible( ETrue ); + } + else if ( aMsgPtr->IsFlagSet( EFSMsgFlag_FollowUpComplete ) ) + { + aItemData->SetFlagIcon( iAppUi.FsTextureManager()->TextureByIndex( EFollowUpFlagCompleteList ) ); + aItemVis->SetFlagIconVisible( ETrue ); + } + else + { + aItemVis->SetFlagIconVisible( EFalse ); + } + } + } + +// --------------------------------------------------------------------------- +// RemoveMsgItemsFromListIfFoundL +// Message removing from list if found. Does not panic or return found status. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::RemoveMsgItemsFromListIfFoundL( const RArray& aEntryIds ) + { + FUNC_LOG; + for ( TInt i=0 ; i= 0 ) + { + iMailList->RemoveL( iTreeItemArray[idx].iListItemId ); // remove from list + iTreeItemArray.Remove( idx ); // remove from internal array. + iModel->RemoveAndDestroy( idx ); // Remove from model + } + } + } + if ( iNodesInUse ) + { + RemoveUnnecessaryNodesL(); + } + + // Set highligh to control bar if no items left after + // deleted items have been revoved from the list + // Otherwise mail list takes care of highlight + // + if ( iModel->Count() == 0 ) + // + { + iFocusedControl = EControlBarComponent; + iMailList->SetFocusedL( EFalse ); + iControlBarControl->SetFocusL(); + } + } + +// --------------------------------------------------------------------------- +// DeleteFocusedMessageL +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DeleteFocusedMessageL() + { + FUNC_LOG; + TInt currentItemIndex = HighlightedIndex(); + if ( Model()->Count() ) + { + CFSEmailUiMailListModelItem* item = + static_cast( Model()->Item(currentItemIndex) ); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + CFSMailMessage& messagePtr = item->MessagePtr(); + + TInt okToDelete(ETrue); + if ( iAppUi.GetCRHandler()->WarnBeforeDelete() ) + { + TInt queryTextId(0); + if ( messagePtr.IsFlagSet( EFSMsgFlag_CalendarMsg )) + { + queryTextId = R_FREESTYLE_EMAIL_DELETE_CALEVENT_NOTE; + } + else + { + queryTextId = R_FREESTYLE_EMAIL_DELETE_MAIL_NOTE; + } + HBufC* msgSubject = TFsEmailUiUtility::CreateSubjectTextLC( &messagePtr ); + + okToDelete = TFsEmailUiUtility::ShowConfirmationQueryL( queryTextId, *msgSubject ); + + CleanupStack::PopAndDestroy( msgSubject ); + } + + if ( okToDelete ) + { + // Delete message from framework, and perform internal housekeeping + TFSMailMsgId msgId = messagePtr.GetMessageId(); + RArray msgIds; + CleanupClosePushL( msgIds ); + msgIds.Append( msgId ); + TFSMailMsgId folderId = FolderId(); + TFSMailMsgId mailBox = iAppUi.GetActiveMailbox()->GetId(); + iAppUi.GetMailClient()->DeleteMessagesByUidL( mailBox, folderId, msgIds ); + RemoveMsgItemsFromListIfFoundL( msgIds ); + CleanupStack::PopAndDestroy( &msgIds ); + } + } + } + } + +// --------------------------------------------------------------------------- +// DeleteMarkedMessagesL +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DeleteMarkedMessagesL() + { + FUNC_LOG; + RFsTreeItemIdList markedEntries; + CleanupClosePushL( markedEntries ); + iMailList->GetMarkedItemsL( markedEntries ); + TInt okToDelete( ETrue ); + + if ( iAppUi.GetCRHandler()->WarnBeforeDelete() ) + { + HBufC* noteText( NULL ); + // The note depends on the amount and type of message(s) + if ( markedEntries.Count() == 1 ) + { + CFSMailMessage& msgPtr = MsgPtrFromListIdL( markedEntries[0] ); + + HBufC* msgSubject = TFsEmailUiUtility::CreateSubjectTextLC( &msgPtr ); + if ( msgPtr.IsFlagSet( EFSMsgFlag_CalendarMsg )) + { + noteText = StringLoader::LoadL( R_FREESTYLE_EMAIL_DELETE_CALEVENT_NOTE, *msgSubject ); + } + else + { + noteText = StringLoader::LoadL( R_FREESTYLE_EMAIL_DELETE_MAIL_NOTE, *msgSubject ); + } + CleanupStack::PopAndDestroy( msgSubject ); + CleanupStack::PushL( noteText ); + } + else // markedEntries.Count() > 1 + { + noteText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_DELETE_N_MAILS_NOTE, markedEntries.Count() ); + } + + // Show the note + okToDelete = TFsEmailUiUtility::ShowConfirmationQueryL( *noteText ); + CleanupStack::PopAndDestroy( noteText ); + } + + if ( okToDelete ) + { + if ( markedEntries.Count() > KMsgDeletionWaitNoteAmount ) + { + TFsEmailUiUtility::ShowWaitNoteL( iDeletingWaitNote, R_FSE_WAIT_DELETING_TEXT, EFalse, ETrue ); + } + + // + if ( iAsyncCallback ) + { + // Call actual deletion asynchronously because we must give wait + // note time to show up before deletion begins. + iAsyncCallback->Cancel(); + iAsyncCallback->Set( TCallBack(DoDeleteMarkedMessages, this) ); + iAsyncCallback->CallBack(); + } + // + } + + CleanupStack::PopAndDestroy( &markedEntries ); + } + +// --------------------------------------------------------------------------- +// DoDeleteMarkedMessages +// +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::DoDeleteMarkedMessages( TAny* aSelfPtr ) + { + FUNC_LOG; + CFSEmailUiMailListVisualiser* self = + static_cast( aSelfPtr ); + + TRAPD( err, + RFsTreeItemIdList markedEntries; + CleanupClosePushL( markedEntries ); + self->iMailList->GetMarkedItemsL( markedEntries ); + + // Delete from FW first + RArray msgIds; + CleanupClosePushL( msgIds ); + for ( TInt i=0 ; iMsgIdFromListId( markedEntries[i] ) ); + } + TFSMailMsgId folderId = self->FolderId(); + TFSMailMsgId mailBox = self->iAppUi.GetActiveMailboxId(); + self->iAppUi.GetMailClient()->DeleteMessagesByUidL( mailBox, folderId, msgIds ); + + // Remove from mail list if not already removed by mailbox events + self->RemoveMsgItemsFromListIfFoundL( msgIds ); + + CleanupStack::PopAndDestroy( &msgIds ); + CleanupStack::PopAndDestroy( &markedEntries ); + ); + + // Close wait note if it was used + if ( self->iDeletingWaitNote ) + { + TRAP_IGNORE( self->iDeletingWaitNote->ProcessFinishedL() ); + } + + return err; + } + +// --------------------------------------------------------------------------- +// RemoveUnnecessaryNodesL +// +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::RemoveUnnecessaryNodesL() + { + FUNC_LOG; + RArray nodesToBeRemoved; + CleanupClosePushL( nodesToBeRemoved ); + for ( TInt i=0;iIsNode( iTreeItemArray[i].iListItemId ) ) + { + if ( iMailList->CountChildren( iTreeItemArray[i].iListItemId ) == 0) + { + nodesToBeRemoved.Append( iTreeItemArray[i].iListItemId ); + } + } + } + // Remove from the list itself and from iTreeItemArray + for ( TInt a = 0; a < nodesToBeRemoved.Count(); a++ ) + { + iMailList->RemoveL( nodesToBeRemoved[a] ); + SMailListItem item; + item.iListItemId = nodesToBeRemoved[a]; + TInt IndexToBeDestroyed = iTreeItemArray.Find( item ); + iTreeItemArray.Remove( IndexToBeDestroyed ); // remove from internal array. + // Remove from model + iModel->RemoveAndDestroy( IndexToBeDestroyed ); + } + CleanupStack::PopAndDestroy( &nodesToBeRemoved ); + } + +// --------------------------------------------------------------------------- +// MsgIdFromIndex +// Helper function to get message id from list index +// --------------------------------------------------------------------------- +// +TFSMailMsgId CFSEmailUiMailListVisualiser::MsgIdFromIndex( TInt aItemIdx ) const + { + FUNC_LOG; + TFSMailMsgId msgId; // constructs null ID + // + if ( 0 <= aItemIdx && aItemIdx < iModel->Count() ) + // + { + CFSEmailUiMailListModelItem* item = + static_cast(iModel->Item(aItemIdx)); + if ( item->ModelItemType() == ETypeMailItem ) + { + msgId = item->MessagePtr().GetMessageId(); + } + } + + return msgId; + } + +// --------------------------------------------------------------------------- +// MsgIdFromListId +// Get message ID corresponding given list ID. If the list ID is for a node, +// the message ID of its first child is returned +// --------------------------------------------------------------------------- +// +TFSMailMsgId CFSEmailUiMailListVisualiser::MsgIdFromListId( TFsTreeItemId aListId ) const + { + FUNC_LOG; + TFSMailMsgId msgId; // constructs null ID + + if ( aListId != KFsTreeNoneID ) + { + // Substitute node ID with ID of its first child + if ( iMailList->IsNode( aListId ) && iMailList->CountChildren( aListId ) ) + { + aListId = iMailList->Child( aListId, 0 ); + } + + // Find corresponding message from the model + for ( TInt i=0 ; iCount() ; i++ ) + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(i) ); + if ( item->ModelItemType() == ETypeMailItem && + aListId == item->CorrespondingListId() ) + { + msgId = item->MessagePtr().GetMessageId(); + break; + } + } + } + + return msgId; + } + +// --------------------------------------------------------------------------- +// MsgPtrFromListIdL +// +// --------------------------------------------------------------------------- +// +CFSMailMessage& CFSEmailUiMailListVisualiser::MsgPtrFromListIdL( TFsTreeItemId aListId ) + { + FUNC_LOG; + TInt index = ModelIndexFromListId( aListId ); + if ( index >= 0 ) + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(index) ); + return item->MessagePtr(); + } + else + { + // Leave if no message found. As the function returns a reference, it is not + // possible to return any meaningful null value. + User::Leave( KErrNotFound ); + } + + CFSMailMessage* dummy = NULL; + return *dummy; // to surpress warning about missing return value; this is not really ever run + } + +// --------------------------------------------------------------------------- +// MsgPtrFromListIdL +// +// --------------------------------------------------------------------------- +// +const CFSMailMessage& CFSEmailUiMailListVisualiser::MsgPtrFromListIdL( TFsTreeItemId aListId ) const + { + FUNC_LOG; + TInt index = ModelIndexFromListId( aListId ); + if ( index >= 0 ) + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(index) ); + return item->MessagePtr(); + } + else + { + // Leave if no message found. As the function returns a reference, it is not + // possible to return any meaningful null value. + User::Leave( KErrNotFound ); + } + + const CFSMailMessage* dummy = NULL; + return *dummy; // to surpress warning about missing return value; this is not really ever run + } + +// --------------------------------------------------------------------------- +// ItemDataFromItemId +// Function returns a valid pointer to list item data based on item id +// --------------------------------------------------------------------------- +// +MFsTreeItemData* CFSEmailUiMailListVisualiser::ItemDataFromItemId( TFsTreeItemId aItemId ) + { + FUNC_LOG; + MFsTreeItemData* itemData = NULL; + if ( aItemId != KFsTreeNoneID ) + { + itemData = &iMailList->ItemData( aItemId ); + } + return itemData; + } + +// --------------------------------------------------------------------------- +// ItemVisualiserFromItemId +// Function returns a valid pointer to list item visualiser based on item id +// --------------------------------------------------------------------------- +// +MFsTreeItemVisualizer* CFSEmailUiMailListVisualiser::ItemVisualiserFromItemId( TFsTreeItemId aItemId ) + { + FUNC_LOG; + MFsTreeItemVisualizer* itemVis = NULL; + if ( aItemId != KFsTreeNoneID ) + { + itemVis = &iMailList->ItemVisualizer( aItemId ); + } + return itemVis; + } + +// --------------------------------------------------------------------------- +// ItemIndexFromMessageId +// Function returns list index based on message pointer. KErrNotFound if +// ID is not included in the list +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::ItemIndexFromMessageId( const TFSMailMsgId& aMessageId ) const + { + FUNC_LOG; + TInt idx = KErrNotFound; + + // Check first the special case; if searched id is null id, there's no + // point to loop the whole list. There shouldn't be any null id's in + // the model anyway. There is currently also an error in FW's equality + // operator implementation; it doesn't check the iNullId flag at all. + if( !aMessageId.IsNullId() ) + { + for ( TInt i=0; iCount() ; i++ ) + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(i) ); + if ( item->ModelItemType() == ETypeMailItem && + aMessageId == item->MessagePtr().GetMessageId() ) + { + idx = i; + break; + } + } + } + return idx; + } + +// --------------------------------------------------------------------------- +// NextMessageIndex +// Function returns next message index from highlighted index +// KErrNotFound if there is no next message +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::NextMessageIndex( TInt aCurMsgIdx ) const + { + FUNC_LOG; + TInt idx = KErrNotFound; + for ( TInt i=aCurMsgIdx+1 ; iCount() ; i++ ) + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(i) ); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + idx = i; + break; + } + } + + return idx; + } + +// --------------------------------------------------------------------------- +// PreviousMessageIndex +// Function returns previous message index from highlighted index +// KErrNotFound if there is no previous message +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::PreviousMessageIndex( TInt aCurMsgIdx ) const + { + FUNC_LOG; + TInt idx( KErrNotFound ); + if ( aCurMsgIdx < iModel->Count() ) + { + for ( TInt i=aCurMsgIdx-1 ; i>=0 ; i-- ) + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(i) ); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + idx = i; + break; + } + } + } + return idx; + } + +// --------------------------------------------------------------------------- +// ModelIndexFromListId +// Function returns a model index corresponding the given tree list item ID +// --------------------------------------------------------------------------- +// +TInt CFSEmailUiMailListVisualiser::ModelIndexFromListId( TFsTreeItemId aItemId ) const + { + FUNC_LOG; + TInt ret = KErrNotFound; + const TInt count = iModel->Count(); + for ( TInt i=0; i < count; i++ ) + { + const CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item(i) ); + if ( aItemId == item->CorrespondingListId() ) + { + ret = i; + break; + } + } + return ret; + } + +// --------------------------------------------------------------------------- +// FolderSelectedL +// Folder list selection callback. Function updates list when folder is changed +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::FolderSelectedL( + TFSMailMsgId aSelectedFolderId, + TFSEmailUiCtrlBarResponse aResponse ) + { + FUNC_LOG; + // hide selector if keys are not pressed + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + if ( iMoveToFolderOngoing ) + { + iMoveToFolderOngoing = EFalse; + switch ( aResponse ) + { + case EFSEmailUiCtrlBarResponseCancel: + SetMskL(); + return; + case EFSEmailUiCtrlBarResponseSelect: + { + MoveMsgsToFolderL( aSelectedFolderId ); + SetMskL(); + } + break; + default: + break; + } + } + else + { + // Ignore if cancel selected + switch ( aResponse ) + { + case EFSEmailUiCtrlBarResponseSwitchList: + { + TFSFolderType folderType; + if ( iMailFolder ) + { + folderType = iMailFolder->GetFolderType(); + } + else + { + folderType = EFSInbox; + } + iControlBarControl->SetFocusByIdL( iSortButtonId ); + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); +/* Sorting empty list enabled + // Show sort list only if maiil list is not empty + if ( iModel->Count() ) + */ + { + iAppUi.ShowSortListInPopupL( iCurrentSortCriteria.iField, folderType, this, iSortButton ); + } + } + return; + case EFSEmailUiCtrlBarResponseCancel: + SetMskL(); + // Touch + //Set touchmanager back to active + DisableMailList(EFalse); + // + return; + case EFSEmailUiCtrlBarResponseSelect: + SetMskL(); + // Touch + //Set touchmanager back to active + DisableMailList(EFalse); + // + default: + break; + } + + if ( !iMailFolder || ( iMailFolder && iMailFolder->GetFolderId() != aSelectedFolderId ) ) + { + delete iMailFolder; + iMailFolder = NULL; + iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( iAppUi.GetActiveMailboxId(), aSelectedFolderId ); + + if ( !iMailFolder ) + { + // Do nothing if can't get the folder object + return; + } + + // Set new text to folder button in control bar + HBufC* newFolderName = CreateFolderNameLC( iMailFolder ); + iFolderListButton->SetTextL( *newFolderName ); + CleanupStack::PopAndDestroy( newFolderName ); + + // Set initial sort criteria when folder has changed + iCurrentSortCriteria.iField = EFSMailSortByDate; + iCurrentSortCriteria.iOrder = EFSMailDescending; + // reload node state because in file sort mode this is disabled even when globally enabled + iNodesInUse = iAppUi.GetCRHandler()->TitleDividers(); + SetSortButtonTextAndIconL(); + + // Update the mail list contents + UpdateMailListModelL(); + RefreshL(); + } + iFocusedControl = EControlBarComponent; + SetListAndCtrlBarFocusL(); + iMoveToFolderOngoing = EFalse; + } + SetMskL(); + } + +// --------------------------------------------------------------------------- +// MailboxSelectedL +// Mailbox selection callback. Function updates list when mailbox is changed +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::MailboxSelectedL( TFSMailMsgId aSelectedMailboxId ) + { + FUNC_LOG; + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + //Set touchmanager back to active + DisableMailList(EFalse); + iAppUi.SetActiveMailboxL( aSelectedMailboxId ); + delete iMailFolder; + iMailFolder = NULL; + iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( iAppUi.GetActiveMailboxId(), iAppUi.GetActiveBoxInboxId() ); + + // Set initial sort criteria when folder has changed + iCurrentSortCriteria.iField = EFSMailSortByDate; + iCurrentSortCriteria.iOrder = EFSMailDescending; + // reload node state because in file sort mode this is disabled even when globally enabled + iNodesInUse = iAppUi.GetCRHandler()->TitleDividers(); + SetSortButtonTextAndIconL(); + + // Set folder name to the control bar button + HBufC* newFolderName = CreateFolderNameLC( iMailFolder ); + iFolderListButton->SetTextL( *newFolderName ); + CleanupStack::PopAndDestroy( newFolderName ); + + // Set mailbox name and icons + SetMailboxNameToStatusPaneL(); + SetBrandedListWatermarkL(); + SetBrandedMailBoxIconL(); + + // Update model + UpdateMailListModelL(); + iMailList->RemoveAllL(); + RefreshDeferred(); + + // Check sync icon timer and sync status + ConnectionIconHandling(); + iFocusedControl = EControlBarComponent; + } + +// --------------------------------------------------------------------------- +// FolderButtonRect +// Getter for folder button rectangle. Folder popup needs to get this +// information when screen layout changes. +// --------------------------------------------------------------------------- +// +TRect CFSEmailUiMailListVisualiser::FolderButtonRect() + { + FUNC_LOG; + const TPoint& buttonPos = iFolderListButton->Pos().Target(); + const TPoint& buttonSize = iFolderListButton->Size().Target(); + TRect buttonRect( buttonPos, buttonSize.AsSize() ); + return buttonRect; + } + +// --------------------------------------------------------------------------- +// SortOrderChangedL +// Sort order selection callback. Function updates list when sorting is changed +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::SortOrderChangedL( + TFSMailSortField aSortField, TFSEmailUiCtrlBarResponse aResponse ) + { + FUNC_LOG; + // Ignore if cancel selected + switch( aResponse ) + { + case EFSEmailUiCtrlBarResponseSwitchList: + { + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + iControlBarControl->SetFocusByIdL( iFolderListButtonId ); + iAppUi.ShowFolderListInPopupL( FolderId(), this, iFolderListButton ); + } + return; + case EFSEmailUiCtrlBarResponseCancel: + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + SetMskL(); + // Touch + //Set touchmanager back to active + DisableMailList(EFalse); + return; + + case EFSEmailUiCtrlBarResponseSelect: + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + //Set touchmanager back to active + DisableMailList(EFalse); + // + default: + break; + } + + // Check is the selected sort field same as the previous one + if( iCurrentSortCriteria.iField == aSortField ) + { + // If same sort field selected, switch the sorting order + if( iCurrentSortCriteria.iOrder == EFSMailAscending ) + { + iCurrentSortCriteria.iOrder = EFSMailDescending; + } + else + { + iCurrentSortCriteria.iOrder = EFSMailAscending; + } + } + else if ( aSortField == EFSMailSortBySubject || + aSortField == EFSMailSortBySender || + aSortField == EFSMailSortByUnread || // + aSortField == EFSMailSortByRecipient ) + { + iCurrentSortCriteria.iOrder = EFSMailAscending; + } + else + { + iCurrentSortCriteria.iOrder = EFSMailDescending; + } + + iCurrentSortCriteria.iField = aSortField; + + // Size sorting does not use nodes, so disable those, otherwise check from CR + iNodesInUse = iAppUi.GetCRHandler()->TitleDividers(); + SetSortButtonTextAndIconL(); + + iFocusedControl = EControlBarComponent; + iMailList->SetFocusedL( EFalse ); + iControlBarControl->SetFocusByIdL( iSortButtonId ); + + // + if ( iMailListUpdater ) + { + // Start updating mail list with sorting parameter. + iMailListUpdater->StartL( ETrue ); + } + // + SetMskL(); + } + +// --------------------------------------------------------------------------- +// SortButtonRect +// Getter for sort button rectangle. Sort popup needs to get this +// information when screen layout changes. +// --------------------------------------------------------------------------- +// +TRect CFSEmailUiMailListVisualiser::SortButtonRect() + { + FUNC_LOG; + const TPoint& buttonPos = iSortButton->Pos().Target(); + const TPoint& buttonSize = iSortButton->Size().Target(); + TRect buttonRect( buttonPos, buttonSize.AsSize() ); + return buttonRect; + } + +// --------------------------------------------------------------------------- +// OpenHighlightedMailL +// Function opens highlighted mail either to internal viewer or to mrui if +// message type is meeting +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::OpenHighlightedMailL() + { + FUNC_LOG; + OpenMailItemL( iMailList->FocusedItem() ); + } + +// --------------------------------------------------------------------------- +// OpenHighlightedMailL +// Function opens given mail item either to internal viewer or to mrui if +// message type is meeting +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::OpenMailItemL( TFsTreeItemId aMailItem ) + { + FUNC_LOG; + TInt idx = ModelIndexFromListId( aMailItem ); + if ( idx >= 0 ) + { + CFSEmailUiMailListModelItem* item = + static_cast( Model()->Item(idx) ); + if ( item->ModelItemType() == ETypeMailItem ) + { + // First make sure that the highlighted message really exists in the store + // Get confirmed msg ptr + CFSMailMessage* confirmedMsgPtr(0); + confirmedMsgPtr = iAppUi.GetMailClient()->GetMessageByUidL(iAppUi.GetActiveMailboxId(), + iMailFolder->GetFolderId(), item->MessagePtr().GetMessageId(), EFSMsgDataEnvelope ); + if ( confirmedMsgPtr ) + { + ChangeMskCommandL( R_FSE_QTN_MSK_EMPTY ); + // Pointer confirmed, store Id and delete not needed anymore + TFSMailMsgId confirmedId = confirmedMsgPtr->GetMessageId(); + TBool isCalMessage = confirmedMsgPtr->IsFlagSet( EFSMsgFlag_CalendarMsg ); + TBool isReadMessage = confirmedMsgPtr->IsFlagSet( EFSMsgFlag_Read ); + delete confirmedMsgPtr; + // Open to editor from drafts + if ( iMailFolder->GetFolderType() == EFSDraftsFolder ) + { + if ( !isCalMessage ) // Open only normal messages for now + { + TEditorLaunchParams params; + params.iMailboxId = iAppUi.GetActiveMailboxId(); + params.iActivatedExternally = EFalse; + params.iMsgId = confirmedId; + params.iFolderId = iMailFolder->GetFolderId(); + iAppUi.LaunchEditorL( KEditorCmdOpen, params ); + } + else + { + //Try to open to editor if support for that is needed + } + } + else if ( iMailFolder->GetFolderType() == EFSOutbox ) + { + TFsEmailUiUtility::ShowErrorNoteL( R_FREESTYLE_EMAIL_UI_OPEN_FROM_OUTBOX_NOTE, ETrue ); + } + else + { + THtmlViewerActivationData htmlData; + htmlData.iActivationDataType = THtmlViewerActivationData::EMailMessage; + htmlData.iMailBoxId = iAppUi.GetActiveMailbox()->GetId(); + htmlData.iFolderId = FolderId(); + htmlData.iMessageId = confirmedId; + TPckgBuf pckgData( htmlData ); + + // Change read status only if needed + if ( !isReadMessage ) + { + ChangeReadStatusOfHighlightedL( ETrue ); + } + + // Opening viewer seems to take more time than other views, + // so we do longer fade out in this case + SetNextTransitionOutLong( ETrue ); + + iAppUi.EnterFsEmailViewL( HtmlViewerId, KHtmlViewerOpenNew, pckgData ); + } + } + } + } + } + +// --------------------------------------------------------------------------- +// From MFSEmailUiContactHandlerObserver +// The ownership of the CLS items in the contacts array is transferred to the +// observer, and they must be deleted by the observer. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::OperationCompleteL( + TContactHandlerCmd /*aCmd*/, const RPointerArray& /*aContacts*/ ) + { + FUNC_LOG; + } + +// --------------------------------------------------------------------------- +// From MFSEmailUiContactHandlerObserver +// Handles error in contact handler operation. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::OperationErrorL( TContactHandlerCmd /*aCmd*/, + TInt /*aError*/ ) + { + FUNC_LOG; + } + +// --------------------------------------------------------------------------- +// NotifyDateChangedL +// Called when CDateChangeTimer completes. This happens when either when date +// changes or when user alters the system time. Redraws the list to ensure +// that time stamp texts in emails and nodes are up-to-date. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::NotifyDateChangedL() + { + FUNC_LOG; + iDateChanged = ETrue; + if ( iAppUi.IsForeground() ) + { + HandleForegroundEventL(); + } + } + +// --------------------------------------------------------------------------- +// CreateFolderNameLC +// Creates folder name from folder ptr. Localised if standard folder. +// --------------------------------------------------------------------------- +// +HBufC* CFSEmailUiMailListVisualiser::CreateFolderNameLC( const CFSMailFolder* aFolder ) const + { + FUNC_LOG; + TInt resourceId(0); + HBufC* ret(0); + if ( !aFolder || aFolder->GetFolderId().IsNullId() ) + { + // INBOX FOR NULL ID + resourceId = R_FREESTYLE_EMAIL_UI_DROPDOWN_LIST_INBOX; + } + else + { + TInt folderType = aFolder->GetFolderType(); + switch ( folderType ) + { + case EFSInbox: + { + resourceId = R_FREESTYLE_EMAIL_UI_DROPDOWN_LIST_INBOX; + } + break; + case EFSOutbox: + { + resourceId = R_FREESTYLE_EMAIL_UI_DROPDOWN_LIST_OUTBOX; + } + break; + case EFSDraftsFolder: + { + resourceId = R_FREESTYLE_EMAIL_UI_DROPDOWN_LIST_DRAFTS; + } + break; + case EFSSentFolder: + { + resourceId = R_FREESTYLE_EMAIL_UI_DROPDOWN_LIST_SENT; + } + break; + case EFSDeleted: + { + resourceId = R_FREESTYLE_EMAIL_UI_DROPDOWN_LIST_DELETED; + } + break; + default: + // Not a standard folder + break; + } + } + if ( resourceId ) + { + ret = StringLoader::LoadLC( resourceId ); + } + else + { + ret = aFolder->GetFolderName().AllocLC(); + } + return ret; + } + +// --------------------------------------------------------------------------- +// LaunchActionMenuL +// Function launches action menu based on the highlighted or marked messages +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::LaunchActionMenuL() + { + FUNC_LOG; + // Get marked entries + RFsTreeItemIdList markedEntries; + CleanupClosePushL( markedEntries ); + iMailList->GetMarkedItemsL( markedEntries ); + TInt markedCount = markedEntries.Count(); + + // Remove old items from action menu + CFSEmailUiActionMenu::RemoveAllL(); + // Construct item list + RFsEActionMenuIdList itemList; + CleanupClosePushL( itemList ); + // Check support for object mail iten moving + TBool supportsMoving = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaMoveToFolder ); + + if ( markedCount == 0 || markedCount == 1 ) // Action menu for a single item + { + // Get pointer to the single message we are dealing with + TFsTreeItemId listItemId; + if ( markedCount == 0 ) + { + listItemId = iMailList->FocusedItem(); + } + else // ( markedCount == 1) + { + listItemId = markedEntries[0]; + } + CFSMailMessage* msgPtr = &MsgPtrFromListIdL( listItemId ); + + if ( iMailFolder->GetFolderType() == EFSOutbox ) + { + if ( supportsMoving ) + { + itemList.AppendL( FsEActionMenuMoveToDrafts ); + } + } + else if( iMailFolder->GetFolderType() == EFSDraftsFolder ) + { + // Create mark unread / mark read flag + if ( msgPtr->IsFlagSet( EFSMsgFlag_Read ) ) + { + itemList.AppendL( FsEActionMenuMarkUnread ); + } + else + { + itemList.AppendL( FsEActionMenuMarkRead ); + } + // Add Move message item if applicable + if ( supportsMoving ) + { + itemList.AppendL( FsEActionMenuMove ); + } + } + else + { + // Construct menu for calendar message based on resolved mr object + // and whether the MRUI object is available + if ( msgPtr->IsFlagSet( EFSMsgFlag_CalendarMsg ) && iAppUi.MrViewerInstanceL() ) + { + TESMRMeetingRequestMethod mrMethod( EESMRMeetingRequestMethodUnknown ); + TRAP_IGNORE( mrMethod = iAppUi.MrViewerInstanceL()->ResolveMeetingRequestMethodL( *msgPtr ) ); + switch ( mrMethod ) + { + case EESMRMeetingRequestMethodRequest: + { + if ( iMailFolder && iMailFolder->GetFolderType() != EFSOutbox && + iMailFolder->GetFolderType() != EFSDraftsFolder ) + { + // No choices in outbox in outbox or drafts + itemList.AppendL( FsEActionMenuAccept ); + itemList.AppendL( FsEActionMenuTentative ); + itemList.AppendL( FsEActionMenuDecline ); + } + } + break; + case EESMRMeetingRequestMethodCancellation: + { + // No "remove from calendar" in outbox or drafts + if ( iMailFolder && iMailFolder->GetFolderType() != EFSOutbox && + iMailFolder->GetFolderType() != EFSDraftsFolder ) + { + TBool supportsRemove = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaRemoveFromCalendar ); + if( supportsRemove ) + { + itemList.AppendL( FsEActionMenuRemoveFormCal ); + } + } + } + break; + case EESMRMeetingRequestMethodUnknown: + case EESMRMeetingRequestMethodResponse: + default: + { + // Only "Open" options is available for responses and when MR method + // cannot be resolved without opening the message (this is the case with IMAP) + itemList.AppendL( FsEActionMenuOpenCalendarEvent ); + } + break; + } + } + // No mrui object or message is typical mail + // Append normal menu commands + else + { + itemList.AppendL( FsEActionMenuReply ); + // Show ReplyAll if more than 1 recepient + TInt numRecipients(0); + if ( msgPtr ) + { + //Get # of recipients + numRecipients =TFsEmailUiUtility::CountRecepients( msgPtr ); + if ( numRecipients == 1 ) + { + //check if the malbox ownmailaddress is same as the recipients email address. If not, then assume that the + //email is a distribution list and we need to inc num of Recipients so that "Reply ALL" option appears in UI. + if ( msgPtr->GetToRecipients().Count() ) + { + if( iAppUi.GetActiveMailbox()->OwnMailAddress().GetEmailAddress().Compare(msgPtr->GetToRecipients()[0]->GetEmailAddress()) ) + { + numRecipients++; + } + } + if ( msgPtr->GetCCRecipients().Count() ) + { + if ( iAppUi.GetActiveMailbox()->OwnMailAddress().GetEmailAddress().Compare(msgPtr->GetCCRecipients()[0]->GetEmailAddress()) ) + { + numRecipients++; + } + } + if( msgPtr->GetBCCRecipients().Count() ) + { + if ( iAppUi.GetActiveMailbox()->OwnMailAddress().GetEmailAddress().Compare(msgPtr->GetBCCRecipients()[0]->GetEmailAddress()) ) + { + numRecipients++; + } + } + } + } + + if ( numRecipients > 1 ) + { + itemList.AppendL( FsEActionMenuReplyAll ); + } + itemList.AppendL( FsEActionMenuForward ); + } + + // Add mark as read/unread options + if ( IsMarkAsUnreadAvailableL() ) + { + itemList.AppendL( FsEActionMenuMarkUnread ); + } + if ( IsMarkAsReadAvailableL() ) + { + itemList.AppendL( FsEActionMenuMarkRead ); + } + + // Add Move message item if applicable + if ( supportsMoving ) + { + itemList.AppendL( FsEActionMenuMove ); + } + } + itemList.AppendL( FsEActionMenuDelete ); + + // Execute action list and handle the menu command + TFSMailMsgId oldMsgId = msgPtr->GetMessageId(); + +// Touch + TActionMenuCustomItemId itemId = CFSEmailUiActionMenu::ExecuteL( itemList, EFscCustom, 0, this ); +// + + // Make sure that focus or marking is still on the same item as when Action menu was launched. + // This is beacause message added/deleted event migh have occured and deleted the original meessage or + // resulted in complete redraw of the message list. + TInt newItemIdx = ItemIndexFromMessageId( oldMsgId ); + if ( newItemIdx >= 0 ) // items still exists + { + TFsTreeItemId newItemListId = iTreeItemArray[ newItemIdx ].iListItemId; + if ( markedCount ) + { + // Item was marked. Make sure it's marked now. + iMailList->MarkItemL( newItemListId, ETrue ); + } + else + { + // No items were marked. Make sure the focus is on the same item as before. + if ( iMailList->FocusedItem() != newItemListId ) + { + iMailList->SetFocusedItemL( newItemListId ); + } + } + HandleActionMenuCommandL( itemId ); + } + } + else // Multiple items marked + { + // Add mark as read/unread options + if ( IsMarkAsUnreadAvailableL() ) + { + itemList.AppendL( FsEActionMenuMarkUnread ); + } + if ( IsMarkAsReadAvailableL() ) + { + itemList.AppendL( FsEActionMenuMarkRead ); + } + + if ( iMailFolder->GetFolderType() == EFSOutbox ) // Append move to drafts in outbox + { + if ( supportsMoving ) + { + itemList.AppendL( FsEActionMenuMoveToDrafts ); + } + } + else // Append move in any other cases dirtectly if supported + { + if ( supportsMoving ) + { + itemList.AppendL( FsEActionMenuMove ); + } + } + itemList.AppendL( FsEActionMenuDelete ); + TActionMenuCustomItemId itemId = CFSEmailUiActionMenu::ExecuteL( itemList ); + iMailList->GetMarkedItemsL( markedEntries ); + if ( markedEntries.Count() ) // Safety check + { + HandleActionMenuCommandL( itemId ); + } + } + CleanupStack::PopAndDestroy( &itemList ); + CleanupStack::PopAndDestroy( &markedEntries ); + } + +// --------------------------------------------------------------------------- +// HandleActionMenuCommandL +// Action menu command callback handler +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::HandleActionMenuCommandL( TActionMenuCustomItemId itemId ) + { + FUNC_LOG; + // Map each Action Menu ID to correcponding command ID. + TInt commandId = KErrNotFound; + + switch( itemId ) + { + case FsEActionMenuOpenCalendarEvent: + case FsEActionMenuOpen: + commandId = EFsEmailUiCmdOpen; + break; + case FsEActionMenuAccept: + commandId = EFsEmailUiCmdCalActionsAccept; + break; + case FsEActionMenuTentative: + commandId = EFsEmailUiCmdCalActionsTentative; + break; + case FsEActionMenuDecline: + commandId = EFsEmailUiCmdCalActionsDecline; + break; + case FsEActionMenuRemoveFormCal: + commandId = EFsEmailUiCmdCalRemoveFromCalendar; + break; + case FsEActionMenuMarkRead: + commandId = EFsEmailUiCmdMarkAsRead; + break; + case FsEActionMenuMarkUnread: + commandId = EFsEmailUiCmdMarkAsUnread; + break; + case FsEActionMenuDelete: + commandId = EFsEmailUiCmdActionsDelete; + break; + case FsEActionMenuReply: + commandId = EFsEmailUiCmdActionsReply; + break; + case FsEActionMenuReplyAll: + commandId = EFsEmailUiCmdActionsReplyAll; + break; + case FsEActionMenuForward: + commandId = EFsEmailUiCmdActionsForward; + break; + case FsEActionMenuMove: + commandId = EFsEmailUiCmdActionsMoveMessage; + break; + case FsEActionMenuMoveToDrafts: + commandId = EFsEmailUiCmdActionsMoveToDrafts; + break; + case FsEActionMenuDismissed: + commandId = KErrCancel; + break; + default: + __ASSERT_DEBUG( EFalse, Panic(EFSEmailUiUnexpectedValue) ); + break; + } + + if ( commandId >= 0 ) + { + HandleCommandL( commandId ); + } + } + +// --------------------------------------------------------------------------- +// LaunchStylusPopupMenuL +// Function launches avkon stylus popup menu based on the selected message item/items +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::LaunchStylusPopupMenuL() + { + // Irrelevant items for focused mail list item get dimmed at runtime + + // Check mail list item's type + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item( HighlightedIndex() ) ); + if ( item && item->ModelItemType() == ETypeMailItem ) + { + // Add mark as read / unread options + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdMarkAsUnread, !IsMarkAsUnreadAvailableL() ); + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdMarkAsRead, !IsMarkAsReadAvailableL() ); + + // Check support for object mail iten moving + TBool supportsMoving = iAppUi.GetActiveMailbox()->HasCapability( EFSMBoxCapaMoveToFolder ); + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsMoveMessage, !supportsMoving ); + + // Hide / show follow up + TBool supportsFlag = TFsEmailUiUtility::IsFollowUpSupported( *iAppUi.GetActiveMailbox() ); + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsFlag, !supportsFlag ); + + // Hide mark if applicable + if ( iMailList->IsMarked( iMailList->FocusedItem() ) ) + { + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdMark, ETrue ); + } + + // Hide collapse / expand all + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsCollapseAll, ETrue ); + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsExpandAll, ETrue ); + } + else if ( item->ModelItemType() == ETypeSeparator ) + { + // Hide mark as read / unread options + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdMarkAsUnread, ETrue ); + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdMarkAsRead, ETrue ); + + // Hide move & follow up + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsMoveMessage, ETrue ); + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsFlag, ETrue ); + + // Hide collapse / expand all when applicable + if ( iNodesInUse == EListControlSeparatorDisabled || !iModel->Count() ) + { + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsCollapseAll, ETrue ); + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsExpandAll, ETrue ); + } + else + { + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsCollapseAll, AllNodesCollapsed() ); + iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdActionsExpandAll, AllNodesExpanded() ); + } + } + + // Set the position for the popup + iStylusPopUpMenu->SetPosition( ActionMenuPosition() ); + + // Display the popup + iStylusPopUpMenu->ShowMenu(); + } + +// --------------------------------------------------------------------------- +// CreateNewMsgL +// Launches editor. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::CreateNewMsgL() + { + FUNC_LOG; + TEditorLaunchParams params; + params.iMailboxId = iAppUi.GetActiveMailboxId(); + params.iActivatedExternally = EFalse; + iAppUi.LaunchEditorL( KEditorCmdCreateNew, params ); + } + +void CFSEmailUiMailListVisualiser::ReplyL( CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + DoReplyForwardL( KEditorCmdReply, aMsgPtr ); + } + +void CFSEmailUiMailListVisualiser::ReplyAllL( CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + DoReplyForwardL( KEditorCmdReplyAll, aMsgPtr ); + } + +void CFSEmailUiMailListVisualiser::ForwardL( CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + DoReplyForwardL( KEditorCmdForward, aMsgPtr ); + } + +// --------------------------------------------------------------------------- +// DoReplyForwardL +// Launches editor with either reply all forward command +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::DoReplyForwardL( TEditorLaunchMode aMode, CFSMailMessage* aMsgPtr ) + { + FUNC_LOG; + // Reply, reply all, and forward commands are inavailable in the outbox + // + if ( iModel->Count() && iMailFolder && iMailFolder->GetFolderType() != EFSOutbox ) + // + { + CFSMailMessage* messagePointer = aMsgPtr; + if ( !messagePointer ) + { + RFsTreeItemIdList targetEntries; + CleanupClosePushL( targetEntries ); + GetActionsTargetEntriesL( targetEntries ); + // action is possible only when there's exactly one marked or focused mail item + if ( targetEntries.Count() == 1 ) + { + messagePointer = &MsgPtrFromListIdL( targetEntries[0] ); + } + CleanupStack::PopAndDestroy( &targetEntries ); + } + if ( messagePointer ) + { + // Opening editor is slower than opening most other views. + // Use longer transition effect to mask this. + SetNextTransitionOutLong( ETrue ); + + TEditorLaunchParams params; + params.iMailboxId = iAppUi.GetActiveMailboxId(); + params.iActivatedExternally = EFalse; + params.iMsgId = messagePointer->GetMessageId(); + iAppUi.LaunchEditorL( aMode, params ); + } + } + } + +// --------------------------------------------------------------------------- +// HandleMailBoxEventL +// Mailbox event handler, responds to events sent by the plugin. +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::HandleMailBoxEventL( TFSMailEvent aEvent, + TFSMailMsgId aMailboxId, TAny* aParam1, TAny* aParam2, TAny* aParam3 ) + { + FUNC_LOG; + + // Complete any pending asynchronous redrawing before handling the event + // to make sure that all the arrays are in consistent state + CompletePendingRefresh(); + + // Handle the event + if ( iFirstStartCompleted && + aMailboxId == iAppUi.GetActiveMailboxId() ) // Safety, in list events that only concern active mailbox are handled + { + if ( aEvent == TFSEventFoldersDeleted ) + { + // Check whether the current folder gets deleted + // Change mail item icon or read status + RArray* removedEntries = static_cast*>( aParam1 ); + if ( iMailFolder && removedEntries && removedEntries->Count() ) + { + TFSMailMsgId currentFolderId = iMailFolder->GetFolderId(); + for ( TInt i = 0; i < removedEntries->Count(); i++ ) + { + TFSMailMsgId entryId = (*removedEntries)[i]; + if ( entryId == currentFolderId ) + { + // Current folder deleted, try to revert back to standard folder inbox. + delete iMailFolder; + iMailFolder = NULL; + TFSMailMsgId inboxId = iAppUi.GetActiveMailbox()->GetStandardFolderId( EFSInbox ); + if ( !inboxId.IsNullId() ) + { + iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( aMailboxId, inboxId ); + UpdateMailListModelL(); + RefreshL(); + HBufC* newFolderName = CreateFolderNameLC( iMailFolder ); + iFolderListButton->SetTextL( *newFolderName ); + CleanupStack::PopAndDestroy( newFolderName ); + } + else + { + // No standard folder inbox, go back to grid as a last option + HandleCommandL( EAknSoftkeyBack ); + } + break; + } + } + } + } + else if ( aEvent == TFSEventMailboxRenamed ) + { + if ( iThisViewActive ) + { + SetMailboxNameToStatusPaneL(); + } + } + else if ( aEvent == TFSEventMailDeleted && iMailFolder ) // Added iMailFolder null safety check + { + // Change mail item icon or read status + RArray* removedEntries = static_cast*>(aParam1); + if ( removedEntries && removedEntries->Count() ) + { + TFSMailMsgId* parentFolderId = static_cast( aParam2 ); + TFSMailMsgId currentFolderId = iMailFolder->GetFolderId(); + if ( parentFolderId && ( *parentFolderId == currentFolderId ) ) + { + // Refresh mailfolder to get correct actual data + delete iMailFolder; + iMailFolder = NULL; + iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( aMailboxId, currentFolderId ); + RemoveMsgItemsFromListIfFoundL( *removedEntries ); + } + } + } + else if ( aEvent == TFSEventNewMail ) + { + // Switch to standardfolder inbox if we have null folderid. + // This is usually the case with first time sync. + if ( FolderId().IsNullId() ) + { + // Refresh mailfolder to standard folder inbox in case of zero id + delete iMailFolder; + iMailFolder = NULL; + TFSMailMsgId inboxId = iAppUi.GetActiveMailbox()->GetStandardFolderId( EFSInbox ); + if ( !inboxId.IsNullId() ) + { + iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( aMailboxId, inboxId ); + // Check that mailfolder fetching succeeded + if ( iMailFolder ) + { + HBufC* newFolderName = CreateFolderNameLC( iMailFolder ); + iFolderListButton->SetTextL( *newFolderName ); + CleanupStack::PopAndDestroy( newFolderName ); + } + } + } + // Null pointer check is needed here because of special cases such as new mail + // creation in POP/IMAP before first sync where folder does not exists + if ( iMailFolder ) + { + RArray* newMessages = static_cast< RArray* >( aParam1 ); + TFSMailMsgId* parentFolderId = static_cast( aParam2 ); + TFSMailMsgId currentFolderId = iMailFolder->GetFolderId(); + // Update the mail list only if the event is related to the currently open folder + if ( *parentFolderId == currentFolderId ) + { + InsertNewMessagesL( *newMessages ); + } + } + } + else if ( aEvent == TFSEventMailMoved && iMailFolder ) // Added iMailFolder null safety check + { + // If message was moved FROM this folder, just remove the entry from the list. + // If message is moved TO this folder, update the list completely. + // Otherwise, the event does not have an influence on the current folder. + RArray* entries = static_cast< RArray* >( aParam1 ); + TFSMailMsgId* toFolderId = static_cast( aParam2 ); + TFSMailMsgId* fromFolderId = static_cast( aParam3 ); + TFSMailMsgId currentFolderId = iMailFolder->GetFolderId(); + + if ( toFolderId && ( currentFolderId == *toFolderId ) ) + { + InsertNewMessagesL( *entries ); + } + else if ( fromFolderId && ( currentFolderId == *fromFolderId ) ) + { + // Refresh mailfolder to get correct actual data + delete iMailFolder; + iMailFolder = NULL; + iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( aMailboxId, currentFolderId ); + RemoveMsgItemsFromListIfFoundL( *entries ); + } + else + { + // event is not related to the current folder => do nothing + } + } + else if ( aEvent == TFSEventMailChanged && iMailFolder ) // Added iMailFolder null safety check + { + // Change mail item icon or read status + RArray* entries = static_cast*>( aParam1 ); + TFSMailMsgId* parentFolderId = static_cast( aParam2 ); + TFSMailMsgId currentFolderId = iMailFolder->GetFolderId(); + if ( *parentFolderId == currentFolderId ) + { + // Refresh mailfolder to get correct actual data + delete iMailFolder; + iMailFolder = NULL; + iMailFolder = iAppUi.GetMailClient()->GetFolderByUidL( aMailboxId, currentFolderId ); + for ( TInt i=0 ; iCount() ; i++ ) + { + TFSMailMsgId msgId = (*entries)[i]; + TInt idx = ItemIndexFromMessageId( msgId ); + if ( idx >= 0 ) + { + UpdateItemAtIndexL( idx ); + } + } + } + } + else if ( aEvent == TFSEventMailboxSyncStateChanged ) + { + TSSMailSyncState* newSyncState = static_cast( aParam1 ); + if ( newSyncState != 0 && *newSyncState != 0 ) + { + switch ( *newSyncState ) + { + case StartingSync: + { + //If sync was started by user, show the synchronisation indicator + if ( iManualMailBoxSync ) + { + CFSMailBox* mb = iAppUi.GetActiveMailbox(); + TDesC* mbName = &mb->GetName(); + ManualMailBoxSync(EFalse); + } + } + break; + } + } + } + } + } + +void CFSEmailUiMailListVisualiser::TreeListEventL( const TFsTreeListEvent aEvent, const TFsTreeItemId aId ) + { + FUNC_LOG; + if ( aEvent == MFsTreeListObserver::EFsTreeListItemWillGetFocused && aId != KFsTreeNoneID ) + {//EFalse - do not call UpdateItem directly, new text will be drawn when item gets focus + UpdatePreviewPaneTextIfNecessaryL( aId, EFalse ); + } + else if ( aEvent == MFsTreeListObserver::EFsTreeListItemTouchFocused ) + { + + } + } + +// --------------------------------------------------------------------------- +// UpdateMailListSettingsL +// Function reads and updates mail list specific settings from the cen rep +// --------------------------------------------------------------------------- +// +void CFSEmailUiMailListVisualiser::UpdateMailListSettingsL() + { + FUNC_LOG; + if ( iAppUi.GetCRHandler() ) + { + iNodesInUse = iAppUi.GetCRHandler()->TitleDividers(); + TInt lineValue = iAppUi.GetCRHandler()->MessageListLayout(); + TInt bodyPreviewValue = iAppUi.GetCRHandler()->BodyPreview(); + if ( lineValue == 1 ) // 1-line layouts + { + if ( bodyPreviewValue == 0 ) + { + iListMode = EListControlTypeSingleLinePreviewOff; + } + else + { + iListMode = EListControlTypeSingleLinePreviewOn; + } + } + else // + { + if ( bodyPreviewValue == 0 ) + { + iListMode = EListControlTypeDoubleLinePreviewOff; + } + else + { + iListMode = EListControlTypeDoubleLinePreviewOn; + } + } + } + else + { + iNodesInUse = EListControlSeparatorDisabled; + iListMode = EListControlTypeDoubleLinePreviewOff; + } + } + +void CFSEmailUiMailListVisualiser::UpdateMailListTimeDateSettings() + { + FUNC_LOG; + TLocale currentLocaleSettings; + iDateFormats.iTimeFormat = currentLocaleSettings.TimeFormat(); + iDateFormats.iDateFormat = currentLocaleSettings.DateFormat(); + iDateFormats.iAmPmPosition = currentLocaleSettings.AmPmSymbolPosition(); + // Second time separartor + iDateFormats.iTimeSeparator = currentLocaleSettings.TimeSeparator( 1 ); + // Second date separartor + iDateFormats.iDateSeparator = currentLocaleSettings.DateSeparator( 1 ); + } + +STimeDateFormats CFSEmailUiMailListVisualiser::MailListTimeDateSettings() + { + FUNC_LOG; + return iDateFormats; + } + + +void CFSEmailUiMailListVisualiser::SetMailboxNameToStatusPaneL() + { + FUNC_LOG; + iAppUi.SetActiveMailboxNameToStatusPaneL(); + } + +void CFSEmailUiMailListVisualiser::SetBrandedMailBoxIconL() + { + FUNC_LOG; + // Get and draw branded mailbox icon + MFSMailBrandManager& brandManager = iAppUi.GetMailClient()->GetBrandManagerL(); + CGulIcon* mailBoxIcon(0); + TRAPD( err, mailBoxIcon = brandManager.GetGraphicL( EFSMailboxIcon, iAppUi.GetActiveMailboxId() ) ); + if ( err == KErrNone && mailBoxIcon ) + { + CleanupStack::PushL( mailBoxIcon ); + // + TSize defaultIconSize(iAppUi.LayoutHandler()->GetControlBarMailboxIconSize()); + // + AknIconUtils::SetSize(mailBoxIcon->Bitmap(), defaultIconSize); + AknIconUtils::SetSize(mailBoxIcon->Mask(), defaultIconSize); + // Create texture into TextureManager, If not already existing + iAppUi.FsTextureManager()->CreateBrandedMailboxTexture( mailBoxIcon, + iAppUi.GetActiveMailboxId().PluginId(), + iAppUi.GetActiveMailboxId().Id(), + defaultIconSize ); + // Get branded mailbox icon + iMailBoxIconTexture = &iAppUi.FsTextureManager()->TextureByMailboxIdL( iAppUi.GetActiveMailboxId().PluginId(), + iAppUi.GetActiveMailboxId().Id(), + defaultIconSize ); + iIconButton->SetIconL( *iMailBoxIconTexture ); + CleanupStack::PopAndDestroy( mailBoxIcon ); + } + else + { + iIconButton->SetIconL( iAppUi.FsTextureManager()->TextureByIndex( EListControlBarMailboxDefaultIcon ) ); + } + } + + +void CFSEmailUiMailListVisualiser::SetBrandedListWatermarkL() + { + FUNC_LOG; + MFSMailBrandManager& brandManager = iAppUi.GetMailClient()->GetBrandManagerL(); + CGulIcon* mailBoxWatermarkIcon(0); + TRAPD( err, mailBoxWatermarkIcon = brandManager.GetGraphicL( EFSWatermark, iAppUi.GetActiveMailboxId() ) ); + if ( err == KErrNone && mailBoxWatermarkIcon ) + { + CleanupStack::PushL( mailBoxWatermarkIcon ); + TRect mainPaneRect; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPaneRect ); + TInt xPos = mainPaneRect.iBr.iX/100*40; // 40% of main pane width + TInt yPos = mainPaneRect.iBr.iY/100*40; // 40% of main pane height + TSize defaultWaterMarkSize(xPos,yPos); + AknIconUtils::SetSize(mailBoxWatermarkIcon->Bitmap(), defaultWaterMarkSize); + AknIconUtils::SetSize(mailBoxWatermarkIcon->Mask(), defaultWaterMarkSize); + if ( !iMailBoxWatermarkTexture ) + { + // iMailBoxWatermarkTexture = CAlfTexture::NewL( *iEnv, Id() ); // DOLATER - Replaced by line below, creates blank texture until UploadL's replaced by something + iMailBoxWatermarkTexture = &CAlfStatic::Env().TextureManager().BlankTexture(); + } + // DOLATER - Gone from Alfred, needs to be replaced with something + //iMailBoxWatermarkTexture->UploadL( *mailBoxWatermarkIcon->Bitmap(), mailBoxWatermarkIcon->Mask() ); + CleanupStack::PopAndDestroy( mailBoxWatermarkIcon ); + TPoint watermarkPosition( mainPaneRect.iBr.iX-xPos-20, mainPaneRect.iBr.iY-yPos-20 ); + iMailTreeListVisualizer->SetWatermarkPos( watermarkPosition ); + iMailTreeListVisualizer->SetWatermarkSize( defaultWaterMarkSize ); + iMailTreeListVisualizer->SetWatermarkOpacity( 0.3 ); + iMailTreeListVisualizer->SetWatermarkL( iMailBoxWatermarkTexture ); + } + else + { + // Not found, hide watermark + iMailTreeListVisualizer->SetWatermarkOpacity( 0 ); + } + } + +TFsTreeItemId CFSEmailUiMailListVisualiser::ParentNode( TFsTreeItemId aItemId ) const + { + FUNC_LOG; + if ( iNodesInUse ) + { + TFsTreeItemId parentNodeId = iMailList->Parent( aItemId ); + if ( iMailList->IsNode( parentNodeId ) ) + { + return parentNodeId; + } + } + return KErrNotFound; + } + +TBool CFSEmailUiMailListVisualiser::DoScrollMarkUnmarkL() + { + FUNC_LOG; + TBool ret = EFalse; + + // + if ( iFocusedControl == EMailListComponent && iModel->Count() ) + // + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item( HighlightedIndex() ) ); + + if ( item->ModelItemType() == ETypeMailItem ) // Separators are not markable + { + if ( !iListMarkItemsState ) + { + iMailList->MarkItemL( iMailList->FocusedItem(), EFalse ); + } + else + { + iMailList->MarkItemL( iMailList->FocusedItem(), ETrue ); + } + ret = ETrue; + } + } + + return ret; + } + +// Mark / unmark all items under current separator +void CFSEmailUiMailListVisualiser::MarkItemsUnderSeparatorL( TBool aMarked, TInt aSeparatorId ) + { + FUNC_LOG; + + if ( iTreeItemArray.Count() ) + { + // Find all items under wanted separator. + for ( TInt i = aSeparatorId + 1; i < iTreeItemArray.Count(); i++ ) + { + CFSEmailUiMailListModelItem* item = + static_cast( iModel->Item( i ) ); + + // Mark / unmark mail items. + if ( item && + item->ModelItemType() == ETypeMailItem && + !iMailList->IsNode( iTreeItemArray[i].iListItemId ) ) + { + iMailList->MarkItemL( iTreeItemArray[i].iListItemId, aMarked ); + } + else + { + // Stop iteration since another iterator was reached. + break; + } + } + } + } +// Navigation functions, used mainly from viewer +TBool CFSEmailUiMailListVisualiser::IsNextMsgAvailable( TFSMailMsgId aCurrentMsgId, + TFSMailMsgId& aFoundNextMsgId, + TFSMailMsgId& aFoundNextMsgFolder ) const + { + FUNC_LOG; + TBool ret(EFalse); + TInt curIdx = ItemIndexFromMessageId( aCurrentMsgId ); + if ( curIdx >= 0 ) + { + TInt nextIdx = NextMessageIndex(curIdx); + if ( nextIdx >= 0 ) + { + ret = ETrue; + aFoundNextMsgId = MsgIdFromIndex(nextIdx); + aFoundNextMsgFolder = iMailFolder->GetFolderId(); + } + } + + return ret; + } + +TBool CFSEmailUiMailListVisualiser::IsPreviousMsgAvailable( TFSMailMsgId aCurrentMsgId, + TFSMailMsgId& aFoundPreviousMsgId, + TFSMailMsgId& aFoundPrevMsgFolder ) const + { + FUNC_LOG; + TBool ret(EFalse); + TInt curIdx = ItemIndexFromMessageId( aCurrentMsgId ); + if ( curIdx >= 0 ) + { + TInt prevIdx = PreviousMessageIndex(curIdx); + if ( prevIdx >= 0 ) + { + ret = ETrue; + aFoundPreviousMsgId = MsgIdFromIndex(prevIdx); + aFoundPrevMsgFolder = iMailFolder->GetFolderId(); + } + } + + return ret; + } + +TInt CFSEmailUiMailListVisualiser::MoveToNextMsgL( TFSMailMsgId aCurrentMsgId, TFSMailMsgId& aFoundNextMsgId ) + { + FUNC_LOG; + TInt ret(KErrNotFound); + + TInt curIdx = ItemIndexFromMessageId( aCurrentMsgId ); + TInt nextIdx = NextMessageIndex( curIdx ); + + if ( curIdx >= 0 && nextIdx >= 0 ) + { + // Focus the new message + // + iMailTreeListVisualizer->SetFocusedItemL( iTreeItemArray[nextIdx].iListItemId, EFalse ); + // + ChangeReadStatusOfHighlightedL( ETrue ); + + aFoundNextMsgId = MsgIdFromIndex( nextIdx ); + ret = KErrNone; + } + if ( ret == KErrNone ) + { + OpenHighlightedMailL(); + } + return ret; + } + +TInt CFSEmailUiMailListVisualiser::MoveToPreviousMsgL( TFSMailMsgId aCurrentMsgId, TFSMailMsgId& aFoundPreviousMsgId ) + { + FUNC_LOG; + TInt ret(KErrNotFound); + + TInt curIdx = ItemIndexFromMessageId( aCurrentMsgId ); + TInt prevIdx = PreviousMessageIndex( curIdx ); + + if ( curIdx >= 0 && prevIdx >= 0 ) + { + // Focus the new message + // + iMailTreeListVisualizer->SetFocusedItemL( iTreeItemArray[prevIdx].iListItemId, EFalse ); + // + ChangeReadStatusOfHighlightedL( ETrue ); + aFoundPreviousMsgId = MsgIdFromIndex( prevIdx ); + ret = KErrNone; + } + if ( ret == KErrNone ) + { + OpenHighlightedMailL(); + } + return ret; + } + + +void CFSEmailUiMailListVisualiser::ManualMailBoxSync( TBool aManualMailBoxSync ) + { + FUNC_LOG; + iManualMailBoxSync = aManualMailBoxSync; + } + +TBool CFSEmailUiMailListVisualiser::GetLatestSyncState() + { + FUNC_LOG; + CFSMailBox* activeMailbox = iAppUi.GetActiveMailbox(); + + TBool ret = EFalse; + + if ( activeMailbox ) + { + TSSMailSyncState latestSyncstate = activeMailbox->CurrentSyncState(); + if(latestSyncstate == InboxSyncing || + latestSyncstate == StartingSync || + latestSyncstate == EmailSyncing || + latestSyncstate == OutboxSyncing || + latestSyncstate == SentItemsSyncing || + latestSyncstate == DraftsSyncing || + latestSyncstate == CalendarSyncing || + latestSyncstate == ContactsSyncing || + latestSyncstate == TasksSyncing || + latestSyncstate == NotesSyncing || + latestSyncstate == FilesSyncing || + latestSyncstate == DataSyncStarting ) + { + ret = ETrue; + } + } + + return ret; + } + +void CFSEmailUiMailListVisualiser::ConnectionIconHandling() + { + FUNC_LOG; + iAppUi.UpdateTitlePaneConnectionStatus(); + } + +void CFSEmailUiMailListVisualiser::SetListAndCtrlBarFocusL() + { + FUNC_LOG; + if ( iFocusedControl == EMailListComponent ) + { + iMailList->SetFocusedL( ETrue ); + iControlBarControl->SetFocusL( EFalse ); + } + else + { + iMailList->SetFocusedL( EFalse ); + TInt focusedBtnId = KErrNotFound; + MFsControlButtonInterface* focusedBtn = iControlBarControl->GetFocusedButton(); + if ( focusedBtn ) + { + focusedBtnId = focusedBtn->Id(); + } + iControlBarControl->MakeSelectorVisible( IsFocusShown() ); + iControlBarControl->SetFocusL( ETrue ); + if ( focusedBtnId != KErrNotFound ) + { + iControlBarControl->SetFocusByIdL( focusedBtnId ); + } + } + } + +// +// --------------------------------------------------------------------------- +// ActionMenuPosition +// --------------------------------------------------------------------------- +// +TPoint CFSEmailUiMailListVisualiser::ActionMenuPosition() + { + RFsTreeItemIdList markedEntries; + TRAP_IGNORE(iMailList->GetMarkedItemsL( markedEntries )); + TInt markedCount = markedEntries.Count(); + TFsTreeItemId listItemId; + if ( markedCount == 0 ) + { + listItemId = iMailList->FocusedItem(); + } + else // ( markedCount == 1) + { + listItemId = markedEntries[0]; + } + TAlfRealRect focusRect; + iMailList->GetItemDisplayRectTarget(listItemId, focusRect); + markedEntries.Close(); + return focusRect.iTl; + } +// + +void CFSEmailUiMailListVisualiser::GetParentLayoutsL( RPointerArray& aLayoutArray ) const + { + aLayoutArray.AppendL( iScreenAnchorLayout ); + aLayoutArray.AppendL( iControlBarControl->Visual() ); + } + + +////////////////////////////////////////////////////////////////// +// Class implementation CMailListUpdater +/////////////////////////////////////////////////////////////////// + + +// ----------------------------------------------------------------------------- +// CMailListUpdater::NewL +// NewL function. Returns timer object. +// ----------------------------------------------------------------------------- +// +CMailListUpdater* CMailListUpdater::NewL( CFSEmailUiMailListVisualiser* aMailListVisualiser ) + { + FUNC_LOG; + CMailListUpdater* self = new (ELeave) CMailListUpdater( aMailListVisualiser ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CMailListUpdater::~CMailListUpdater +// D'tor +// ----------------------------------------------------------------------------- +// +CMailListUpdater::~CMailListUpdater() + { + FUNC_LOG; + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CMailListUpdater::CMailListUpdater +// C'tor +// ----------------------------------------------------------------------------- +// +CMailListUpdater::CMailListUpdater( CFSEmailUiMailListVisualiser* aMailListVisualiser ) + : CTimer( EPriorityStandard ), + iMailListVisualiser( aMailListVisualiser ) + { + FUNC_LOG; + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CMailListUpdater::RunL +// Timer trigger function. +// ----------------------------------------------------------------------------- +// +void CMailListUpdater::RunL() + { + FUNC_LOG; + if ( iIsSorting ) + { + iMailListVisualiser->UpdateMailListModelL(); + iMailListVisualiser->RefreshL(); + // Sorting is completed + iIsSorting = EFalse; + // Dismiss wait note. + if ( iWaitNote ) + { + iWaitNote->ProcessFinishedL(); + } + } + else + { + // Store the list of marked items. The markings are erased when the list + // is repopulated and, hence, the markings need to be reset after the + // refreshing is done. The marked items must be identified by the message + // ID rather than with the list ID because refreshing may change the list IDs. + RArray markedMessages; + CleanupClosePushL( markedMessages ); + iMailListVisualiser->GetMarkedMessagesL( markedMessages ); + + // Store the message ID of the focused item + TFSMailMsgId msgIdBeforeRefresh; + TFsTreeItemId firstVisibleListId = iMailListVisualiser->iMailTreeListVisualizer->FirstVisibleItem(); + TInt modelFirstIndexBeforeUpdate = iMailListVisualiser->ModelIndexFromListId( firstVisibleListId ); + TInt highlightedIndexBeforeUpdate = iMailListVisualiser->HighlightedIndex(); + TInt modelCountBeforeUpdate = iMailListVisualiser->iModel->Count(); + if ( iMailListVisualiser->iModel->Count() ) + { + CFSEmailUiMailListModelItem* item = + static_cast(iMailListVisualiser->iModel->Item( highlightedIndexBeforeUpdate ) ); + if ( item->ModelItemType() == ETypeMailItem ) + { + msgIdBeforeRefresh = item->MessagePtr().GetMessageId(); + } + } + + iMailListVisualiser->UpdateMailListModelL(); + iMailListVisualiser->RefreshL( &msgIdBeforeRefresh ); + + // Focus is set to last focused item. After this, try to keep the same first item that previous + // Check how many messages have been added + TInt modelIndexDifference = highlightedIndexBeforeUpdate-modelFirstIndexBeforeUpdate; // 0 or more + if ( modelIndexDifference < 0 ) + { + modelIndexDifference = 0; // safety + } + TInt toBeFirstIdx = iMailListVisualiser->HighlightedIndex() - modelIndexDifference; + CFSEmailUiMailListModelItem* toBeFirstVisItem = + static_cast( iMailListVisualiser->iModel->Item(toBeFirstIdx) ); + if ( toBeFirstVisItem ) + { + // + iMailListVisualiser->iMailTreeListVisualizer->SetFirstVisibleItemL( toBeFirstVisItem->CorrespondingListId() ); + // + } + + // Restore the marking status + iMailListVisualiser->MarkMessagesIfFoundL( markedMessages ); + CleanupStack::PopAndDestroy( &markedMessages ); + } + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CMailListUpdater::Start +// Timer starting function. +// ----------------------------------------------------------------------------- +// +void CMailListUpdater::StartL( TBool aIsSorting ) + { + FUNC_LOG; + if ( iWaitNote ) + { + iWaitNote->ProcessFinishedL(); + } + + iIsSorting = aIsSorting; + Cancel(); + if ( iIsSorting ) + { + // Start wait note + TFsEmailUiUtility::ShowWaitNoteL( iWaitNote, R_FSE_WAIT_SORTING_TEXT, EFalse, ETrue ); + After( 10 ); // Update shortly after selection has been made. + } + else + { + // Mail added update + After( KMsgUpdaterTimerDelay ); // Update after 1,5 seconds + } + } + +// ----------------------------------------------------------------------------- +// CMailListUpdater::Stop +// Timer stopping function +// ----------------------------------------------------------------------------- +// +void CMailListUpdater::Stop() + { + FUNC_LOG; + Cancel(); + } + + + +////////////////////////////////////////////////////////////////// +// Class implementation CMsgMovedNoteTimer +/////////////////////////////////////////////////////////////////// + + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::NewL +// NewL function. Returns timer object. +// ----------------------------------------------------------------------------- +// +CMsgMovedNoteTimer* CMsgMovedNoteTimer::NewL( CFreestyleEmailUiAppUi* aAppUi, CFSEmailUiMailListVisualiser* aMailListVisualiser ) + { + FUNC_LOG; + CMsgMovedNoteTimer* self = new (ELeave) CMsgMovedNoteTimer( aAppUi, aMailListVisualiser ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::CMsgMovedNoteTimer +// D'tor +// ----------------------------------------------------------------------------- +// +CMsgMovedNoteTimer::~CMsgMovedNoteTimer() + { + FUNC_LOG; + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CMailListUpdater::CMailListUpdater +// C'tor +// ----------------------------------------------------------------------------- +// +CMsgMovedNoteTimer::CMsgMovedNoteTimer( CFreestyleEmailUiAppUi* aAppUi, CFSEmailUiMailListVisualiser* aMailListVisualiser ) + : CTimer( EPriorityStandard ), + iAppUi( aAppUi), + iMailListVisualiser( aMailListVisualiser ) + { + FUNC_LOG; + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::RunL +// Timer trigger function. +// ----------------------------------------------------------------------------- +// +void CMsgMovedNoteTimer::RunL() + { + FUNC_LOG; + TFsEmailUiUtility::DisplayMsgsMovedNoteL( iMsgCount, iDestinationFolderId, EFalse ); + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::Start +// Timer starting function. +// ----------------------------------------------------------------------------- +// +void CMsgMovedNoteTimer::Start( TInt aMsgCount, const TFSMailMsgId aDestinationFolderId ) + { + FUNC_LOG; + Cancel(); + iMsgCount = aMsgCount, + iDestinationFolderId = aDestinationFolderId; + TInt viewSlideinTime = iAppUi->LayoutHandler()->ViewSlideEffectTime(); + if ( viewSlideinTime == 0 ) + { + viewSlideinTime = 100; + } + After( viewSlideinTime ); + } + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::Stop +// Timer stopping function +// ----------------------------------------------------------------------------- +// +void CMsgMovedNoteTimer::Stop() + { + FUNC_LOG; + Cancel(); + } + + +////////////////////////////////////////////////////////////////// +// Class implementation CDateChnageTimer +/////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::NewL +// Two phased constructor +// ----------------------------------------------------------------------------- +// +CDateChangeTimer* CDateChangeTimer::NewL( CFSEmailUiMailListVisualiser& aMailListVisualiser ) + { + FUNC_LOG; + CDateChangeTimer* self = new ( ELeave ) CDateChangeTimer( aMailListVisualiser ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::CDateChangeTimer +// First phase constructor +// ----------------------------------------------------------------------------- +// +CDateChangeTimer::CDateChangeTimer( CFSEmailUiMailListVisualiser& aMailListVisualiser ) + : CTimer( EPriorityStandard ), iMailListVisualiser( aMailListVisualiser ) + { + FUNC_LOG; + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::~CDateChangeTimer +// Destructor +// ----------------------------------------------------------------------------- +// +CDateChangeTimer::~CDateChangeTimer() + { + FUNC_LOG; + // no implementation needed + } + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::Start +// Request event at 00:00 tomorrow +// ----------------------------------------------------------------------------- +// +void CDateChangeTimer::Start() + { + FUNC_LOG; + TTime now; + now.HomeTime(); + + // Construct target time + TTime eventTime = now + TTimeIntervalDays( 1 ); + TDateTime eventDateTime = eventTime.DateTime(); + eventDateTime.SetHour(0); + eventDateTime.SetMinute(0); + eventDateTime.SetSecond(0); + eventDateTime.SetMicroSecond(0); + eventTime = TTime( eventDateTime ); + + // Issue the request + At( eventTime ); + } + +// ----------------------------------------------------------------------------- +// CMsgMovedNoteTimer::RunL +// Function gets called when system time reaches the 00:00 in the next day or +// when the system time has been changed by the user. Both cases can be handled +// in the same way. +// ----------------------------------------------------------------------------- +// +void CDateChangeTimer::RunL() + { + FUNC_LOG; + // Update mail list and reissue the request for timer event + iMailListVisualiser.NotifyDateChangedL(); + Start(); + }