emailuis/emailui/src/FreestyleEmailUiMsgDetailsVisualiser.cpp
changeset 0 8466d47a6819
child 1 12c456ceeff2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/emailui/src/FreestyleEmailUiMsgDetailsVisualiser.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1812 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+*  Description : FreestyleEmailUi message details view implementation
+*  Version     : %version: 44 %
+*
+*/
+
+
+
+// SYSTEM INCLUDES
+#include "emailtrace.h"
+#include <AknUtils.h>
+#include <gulicon.h>
+#include <freestyleemailui.mbg>
+#include <FreestyleEmailUi.rsg>
+#include <StringLoader.h>
+#include <AknBidiTextUtils.h>
+#include <akntitle.h>
+// <cmail> SF
+#include <alf/alfdecklayout.h>
+#include <alf/alfcontrolgroup.h>
+#include <alf/alfframebrush.h>
+#include <alf/alfevent.h>
+// </cmail>
+#include <featmgr.h>
+//</cmail>
+
+//<cmail>
+#include "CFSMailMessage.h"
+#include "CFSMailClient.h"
+//</cmail>
+
+#include "FSEmailBuildFlags.h"
+//<cmail>
+#include "cfsccontactactionmenu.h"
+#include "mfsccontactactionmenumodel.h"
+//</cmail>
+
+//<cmail>
+#include "fstreelist.h"
+#include "fstreevisualizerbase.h"
+#include "fstreeplainonelinenodedata.h"
+#include "fstreeplainonelinenodevisualizer.h"
+#include "fstreeplainonelineitemdata.h"
+#include "fstreeplainonelineitemvisualizer.h"
+#include "fstreeplaintwolineitemdata.h"
+#include "fstreeplaintwolineitemvisualizer.h"
+#include <csxhelp/cmail.hlp.hrh>
+// </cmail>
+
+// INTERNAL INCLUDES
+#include "FreestyleEmailUiAppui.h"
+#include "FreestyleEmailUiMsgDetailsControl.h"
+#include "FreestyleEmailUiMsgDetailsModel.h"
+#include "FreestyleEmailUiMsgDetailsVisualiser.h"
+#include "FreestyleEmailUi.hrh"
+#include "FreestyleEmailUiLayoutHandler.h"
+#include "FreestyleEmailUiTextureManager.h"
+#include "FreestyleEmailUiUtilities.h"
+#include "FreestyleEmailUiShortcutBinding.h"
+#include "FreestyleEmailUiContactHandler.h"
+#include "FSDelayedLoader.h"
+
+
+CFSEmailUiMsgDetailsVisualiser* CFSEmailUiMsgDetailsVisualiser::NewL( CAlfEnv& aEnv,
+                                                 CAlfControlGroup& aControlGroup,
+                                                 CFreestyleEmailUiAppUi& aAppUi )
+    {
+    FUNC_LOG;
+    CFSEmailUiMsgDetailsVisualiser* self = CFSEmailUiMsgDetailsVisualiser::NewLC(aEnv, aControlGroup, aAppUi );
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CFSEmailUiMsgDetailsVisualiser* CFSEmailUiMsgDetailsVisualiser::NewLC( CAlfEnv& aEnv,
+                                                 CAlfControlGroup& aControlGroup,
+                                                 CFreestyleEmailUiAppUi& aAppUi )
+{
+    FUNC_LOG;
+    CFSEmailUiMsgDetailsVisualiser* self = new (ELeave) CFSEmailUiMsgDetailsVisualiser( aEnv, aAppUi, aControlGroup );
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+}
+
+void CFSEmailUiMsgDetailsVisualiser::ConstructL()
+	{
+    FUNC_LOG;
+
+    BaseConstructL( R_FSEMAILUI_MAIL_DETAILS_VIEW );
+
+    iFirstStartCompleted = EFalse;    
+ 
+	}
+
+// CFSEmailUiMsgDetailsVisualiser::DoFirstStartL()
+// Purpose of this function is to do first start only when msg details is
+// really needed to be shown. Implemented to make app startuo faster.
+void CFSEmailUiMsgDetailsVisualiser::DoFirstStartL()
+    {
+    FUNC_LOG;
+    iControl = CFSEmailUiMsgDetailsControl::NewL( iEnv, *this );
+    iModel = new (ELeave) CFSEmailUiMsgDetailsModel();
+
+    UpdateListSizeAttributes();
+     
+    iParentLayout = CAlfDeckLayout::AddNewL( *iControl );
+    iParentLayout->SetFlags( EAlfVisualFlagLayoutUpdateNotification );
+    iParentLayout->SetRect( iScreenRect );
+    
+    iTreeVisualizer = CFsTreeVisualizerBase::NewL(iControl, *iParentLayout);
+    iTreeVisualizer->SetItemExpansionDelay( iAppUi.LayoutHandler()->ListItemExpansionDelay() );
+    iTreeVisualizer->SetScrollTime( iAppUi.LayoutHandler()->ListScrollingTime() );
+    iTreeVisualizer->SetFadeInEffectTime( iAppUi.LayoutHandler()->ListFadeInEffectTime() );
+    iTreeVisualizer->SetFadeOutEffectTime( iAppUi.LayoutHandler()->ListFadeOutEffectTime() );
+    
+    iTreeList = CFsTreeList::NewL( *iTreeVisualizer, iEnv );
+    iTreeList->HideListL();
+    iTreeList->SetLoopingType( EFsTreeListLoopingJumpToFirstLast );
+    iTreeList->SetScrollbarVisibilityL( EFsScrollbarAuto );
+    iTreeList->SetIndentationL( 0 );
+
+    //<cmail> Compared to S60 3.2.3 in S60 5.0 Alf offers the key events in
+    // opposite order.
+    ControlGroup().AppendL( iControl );
+    ControlGroup().AppendL( iTreeList->TreeControl() ); 
+    //</cmail>
+    
+    // <cmail> Touch
+    iTreeList->AddObserverL(*this);
+    //</cmail>
+    
+    // Set page up and page down keys
+    iTreeVisualizer->AddCustomPageUpKey( EStdKeyPageUp );
+    iTreeVisualizer->AddCustomPageDownKey( EStdKeyPageDown );
+    iTreeVisualizer->SetItemsAlwaysExtendedL( ETrue );
+
+    iAppUi.LayoutHandler()->SetListMarqueeBehaviour( iTreeList );
+    
+    iFirstStartCompleted = ETrue;
+    }
+
+CFSEmailUiMsgDetailsVisualiser::CFSEmailUiMsgDetailsVisualiser( CAlfEnv& aEnv, CFreestyleEmailUiAppUi& aAppUi, CAlfControlGroup& aControlGroup  )
+  : CFsEmailUiViewBase(aControlGroup, aAppUi),
+    iEnv(aEnv),
+    iFirstViewActivation( ETrue ),
+    iExpandCollapseMode( EExpandAll ),
+    // <cmail> video call
+    iVideoCall( EFalse )
+    // </cmail>
+	{
+    FUNC_LOG;
+	}
+	
+CFSEmailUiMsgDetailsVisualiser::~CFSEmailUiMsgDetailsVisualiser()
+	{
+    FUNC_LOG;
+	delete iModel;
+	iModel = NULL;
+
+	delete iPreviousTitleText;
+	iPreviousTitleText = NULL;
+
+	delete iViewedMsg;
+	iViewedMsg = NULL;
+	
+	delete iNoDisplayNameAvailableText;
+	iNoDisplayNameAvailableText = NULL;
+	
+	delete iNoEmailAddressAvailableText;
+	iNoEmailAddressAvailableText = NULL;
+	
+	delete iTreeList;
+	iTreeList = NULL;
+	
+	iNodeIds.Close();
+	}
+
+TUid CFSEmailUiMsgDetailsVisualiser::Id() const
+	{
+    FUNC_LOG;
+	return MsgDetailsViewId;
+	}			   
+
+// <cmail> Toolbar
+/*void CFSEmailUiMsgDetailsVisualiser::DoActivateL(const TVwsViewId& aPrevViewId,
+                     TUid aCustomMessageId,
+                     const TDesC8& aCustomMessage)*/
+void CFSEmailUiMsgDetailsVisualiser::ChildDoActivateL(
+    const TVwsViewId& aPrevViewId, TUid aCustomMessageId, 
+        const TDesC8& aCustomMessage)
+// </cmail> Toolbar
+	{
+    FUNC_LOG;
+	if ( !iFirstStartCompleted )
+	    {
+	    DoFirstStartL();
+	    }
+	
+	UpdateListSizeAttributes();
+    iParentLayout->SetRect( iScreenRect );
+
+	if ( aCustomMessageId == KStartMsgDetailsReturnToPrevious )
+	    {
+	    // Fisrt handle special case where we are returning to msg details view,
+	    // so we don't need to recreate list contents, just refresh the view
+	    if ( iViewedMsg ) // Safety check
+	        {
+	        // Set title bar text to "Message/Meeting details"
+	        ChangeTitleBarTextL( ETrue );
+
+	        // Hide list and switch this view as active
+	        iTreeList->HideListL();
+
+	        // Then just refresh the list as in dynamic variant switch,
+	        // because screen orientation might have changed
+            HandleDynamicVariantSwitchL( EScreenLayoutChanged );
+	        }
+	    }
+	else
+		{
+		// This is the "normal" case, so we need to recreate the list contents
+		
+		// Store previous view ID
+		iPreviousViewUid = aPrevViewId.iViewUid;
+
+		TMsgDetailsActivationData subView;
+		TPckgBuf<TMsgDetailsActivationData> viewData( subView );
+		viewData.Copy( aCustomMessage );
+		subView = viewData();
+
+		delete iViewedMsg;
+		iViewedMsg = NULL;
+
+		iViewedMsg = iAppUi.GetMailClient()->GetMessageByUidL( subView.iMailBoxId, subView.iFolderId, subView.iMessageId, EFSMsgDataEnvelope  );
+		CFSMailBox* mailBox = iAppUi.GetMailClient()->GetMailBoxByUidL( subView.iMailBoxId );
+	    CleanupStack::PushL( mailBox );    
+	    if ( mailBox && TFsEmailUiUtility::IsRemoteLookupSupported( *mailBox ) )
+	        {
+	        iRCLSupported = ETrue;       
+	        } 
+	    else
+	        {
+	        iRCLSupported = EFalse;
+	        }
+	    CleanupStack::PopAndDestroy( mailBox );		
+
+		if( iFirstViewActivation )
+			{
+			iTreeVisualizer->SetMenuIcon( iAppUi.FsTextureManager()->TextureByIndex( EListControlMenuIcon ) );		
+		    //<cmail> S60 skin support
+		    //iTreeVisualizer->SetBackgroundTextureL( iAppUi.FsTextureManager()->TextureByIndex( EBackgroundTextureMailList ) );
+		    //</cmail>
+
+		  	CAlfBrush* selectorBrush = iAppUi.FsTextureManager()->ListSelectorBrushL();
+			iTreeVisualizer->SetSelectorPropertiesL( selectorBrush, 1.0, CFsTreeVisualizerBase::EFsSelectorMoveSmoothly );
+	  
+		    iFirstViewActivation = EFalse;
+			}
+
+	    if ( iViewedMsg ) // Safety check
+	        {
+	        // Set title bar text to "Message/Meeting details"
+	        ChangeTitleBarTextL( ETrue );
+
+	        iTreeList->HideListL();
+
+            // By default we expand all nodes, if parameters doesn't state
+            // something else
+            iExpandCollapseMode = EExpandAll;
+            if ( aCustomMessageId == KStartMsgDetailsToTo )
+                {
+                iExpandCollapseMode = ECollapseAllExceptTo;
+                }
+            else if ( aCustomMessageId == KStartMsgDetailsToCc )
+                {
+                iExpandCollapseMode = ECollapseAllExceptCc;
+                }
+            else if ( aCustomMessageId == KStartMsgDetailsToBcc )
+                {
+                iExpandCollapseMode = ECollapseAllExceptBcc;
+                }
+            
+            iParentLayout->SetRect( iScreenRect );
+            ClearMsgDetailsModelL();        
+            
+            UpdateMsgDetailsModelL();
+            iTreeList->ShowListL();
+	        }
+		}
+	// <cmail> Touch
+	iTreeList->SetFocusedL(ETrue);
+	// </cmail>
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::ChildDoDeactivate()
+	{
+    FUNC_LOG;
+    if ( !iAppUi.AppUiExitOngoing() )
+        {
+        if ( iTreeList->IsFocused() )
+            {
+            TRAP_IGNORE( { 
+                iTreeList->SetFocusedL(EFalse);
+                iTreeList->SetFocusedItemL(KFsTreeNoneID);
+                } );
+            }
+        iTreeVisualizer->NotifyControlVisibilityChange( EFalse );
+        }
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::PrepareForExit()
+    {
+    delete iViewedMsg;
+    iViewedMsg = NULL;
+    }
+
+
+void CFSEmailUiMsgDetailsVisualiser::ChangeTitleBarTextL( TBool aViewStarted )
+	{
+    FUNC_LOG;
+	if ( iFirstStartCompleted ) // Safety
+	    {
+		if ( aViewStarted )
+			{
+			// Store previous application title text
+			delete iPreviousTitleText;
+			iPreviousTitleText = NULL;
+			iPreviousTitleText = iAppUi.TitlePaneTextL().AllocL();
+			
+			HBufC* titleText = NULL;
+			if( iViewedMsg->IsFlagSet( EFSMsgFlag_CalendarMsg ) )
+				{
+				titleText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_MEETING_HEADING );
+				}
+			else
+				{
+				titleText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_HEADING );
+				}
+
+			iAppUi.SetTitlePaneTextL( *titleText );
+
+			CleanupStack::PopAndDestroy( titleText ); 
+			}
+		else
+			{
+			if ( iPreviousTitleText )
+				{
+				iAppUi.SetTitlePaneTextL( *iPreviousTitleText ); // Set application title text back			
+				}
+			}
+		}
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::LaunchActionMenuL()
+	{
+    FUNC_LOG;
+    CFSEmailUiActionMenu::RemoveAllL();
+
+    RFsEActionMenuIdList itemList;
+    itemList.AppendL(FsEActionMenuCall);
+    // <cmail> video call
+    itemList.AppendL( FsEActionMenuCallVideo );
+    // </cmail>
+    itemList.AppendL(FsEActionMenuCreateMessage);
+    itemList.AppendL(FsEActionMenuContactDetails);
+    itemList.AppendL(FsEActionMenuAddToContacts);
+    if ( iRCLSupported )
+        {
+        itemList.AppendL(FsEActionMenuRemoteLookup);
+        }     
+    CFSEmailUiActionMenu::AddCustomItemsL( itemList );
+    itemList.Close();
+    
+    // <cmail> Touch	
+    TActionMenuCustomItemId itemId = CFSEmailUiActionMenu::ExecuteL( EFscCustom, 0, this );
+    // </cmail>
+	
+   	HandleActionMenuCommandL( itemId );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::HandleActionMenuCommandL( TActionMenuCustomItemId itemId )
+	{
+    FUNC_LOG;
+	switch( itemId )
+		{
+		case FsEActionMenuCall:
+			{
+			CallToFocusedItemL();
+			}
+			break;
+        // <cmail> video call
+        case FsEActionMenuCallVideo: // Video Call
+            {
+            iVideoCall = ETrue;
+            CallToFocusedItemL();
+            }
+            break;
+        // </cmail>
+		case FsEActionMenuCreateMessage:
+			{
+			CreateMessageToFocusedItemL();
+			}
+			break;
+
+		case FsEActionMenuContactDetails:
+			{
+			ShowContactDetailsForFocusedItemL();
+			}
+			break;
+
+		case FsEActionMenuAddToContacts:
+			{
+			AddFocusedItemToContactsL();
+			}
+			break;
+
+		case FsEActionMenuRemoteLookup:
+			{
+			LaunchRemoteLookupForFocusedItemL();
+			}
+			break;
+		}
+	}
+
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::GetEmailAddressForFocusedItem
+// Returns email address of the focused list item. NULL returned if not found.
+// -----------------------------------------------------------------------------
+CFSMailAddress* CFSEmailUiMsgDetailsVisualiser::GetEmailAddressForFocusedItem() const
+	{
+    FUNC_LOG;
+	CFSMailAddress* foundEmailAddress = NULL;
+	CFSEmailUiMsgDetailsItem* item = iModel->ItemByListId( iTreeList->FocusedItem() );
+	if( item )
+		{
+		foundEmailAddress = item->iMailAddress;
+		}
+	return foundEmailAddress;
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::GetEmailAddressForFocusedItem
+// Returns email address of the focused list item. NULL returned if not found.
+// -----------------------------------------------------------------------------
+TDesC* CFSEmailUiMsgDetailsVisualiser::GetEmailAddressForFocusedItemAsTDes() const
+	{
+    FUNC_LOG;
+	TDesC* foundEmailAddress = NULL;
+	CFSMailAddress* address = GetEmailAddressForFocusedItem();
+	if( address )
+		{
+		foundEmailAddress = &address->GetEmailAddress();
+		}
+	return foundEmailAddress;
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::SendEmailToFocusedItemL
+// 
+// Open composer and set the focused item as recipient, if valid email address
+// is available. Return ETrue if valid email address was found, EFalse if not.
+// -----------------------------------------------------------------------------
+TBool CFSEmailUiMsgDetailsVisualiser::SendEmailToFocusedItemL() const
+	{
+    FUNC_LOG;
+	TBool addrFound = EFalse;
+	CFSMailAddress* address = GetEmailAddressForFocusedItem();
+	if( address )
+		{
+		iAppUi.LaunchEditorL( address );
+		addrFound = ETrue;
+		}
+	return addrFound;	
+	}
+	
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::CallToFocusedItemL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMsgDetailsVisualiser::CallToFocusedItemL()
+	{
+    FUNC_LOG;
+	TDesC* email = GetEmailAddressForFocusedItemAsTDes();
+	if( email )
+		{
+		CFSMailClient* mailClient =	iAppUi.GetMailClient();
+		CFSMailBox* mailBox = mailClient->GetMailBoxByUidL( iViewedMsg->GetMailBoxId() );
+	   	CleanupStack::PushL( mailBox );
+
+        // <cmail> video call
+        if ( iVideoCall )
+            {
+            iVideoCall = EFalse;
+            CFsDelayedLoader::InstanceL()->GetContactHandlerL()->SetVideoCall( ETrue );
+            }
+        // </cmail>
+	   	
+	   	CFsDelayedLoader::InstanceL()->GetContactHandlerL()->FindAndCallToContactByEmailL( *email, 
+	   			 iAppUi.GetActiveMailbox(), this, EFalse );
+
+	   	CleanupStack::PopAndDestroy( mailBox );
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::CreateMessageToFocusedItemL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMsgDetailsVisualiser::CreateMessageToFocusedItemL() const
+	{
+    FUNC_LOG;
+	TDesC* email = GetEmailAddressForFocusedItemAsTDes();
+	if( email )
+		{
+		CFsDelayedLoader::InstanceL()->GetContactHandlerL()->FindAndCreateMsgToContactByEmailL( *email, iAppUi.GetActiveMailbox() );
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::LaunchRemoteLookupForFocusedItemL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMsgDetailsVisualiser::LaunchRemoteLookupForFocusedItemL() const
+	{
+    FUNC_LOG;
+	CFSEmailUiMsgDetailsItem* item = iModel->ItemByListId( iTreeList->FocusedItem() );
+	if( !item )
+		{
+		return;
+		}
+	CFSMailAddress* address = item->iMailAddress;
+	if( !address )
+		{
+		return;
+		}
+	TDesC* queryString = &address->GetEmailAddress();
+	if( !queryString )
+		{
+		queryString = &address->GetDisplayName();
+		if( !queryString )
+			{
+			return;
+			}
+		}
+
+	// this method assumes that remote lookup is available with current plugin.
+	CFSMailClient* mailClient =	iAppUi.GetMailClient();
+	CFSMailBox* mailBox = mailClient->GetMailBoxByUidL( iViewedMsg->GetMailBoxId() );
+   	CleanupStack::PushL( mailBox );
+   	
+	CFsDelayedLoader::InstanceL()->GetContactHandlerL()->LaunchRemoteLookupWithQueryL( *mailBox, *queryString );
+
+   	CleanupStack::PopAndDestroy( mailBox );
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::AddFocusedItemToContactsL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMsgDetailsVisualiser::AddFocusedItemToContactsL() const
+	{
+    FUNC_LOG;
+	TDesC* email = GetEmailAddressForFocusedItemAsTDes();
+	if( email )
+		{
+		TAddToContactsType aType;
+		//Query to "update existing" or "Create new" --> EFALSE = user choosed "cancel"
+		if ( CFsDelayedLoader::InstanceL()->GetContactHandlerL()->AddtoContactsQueryL( aType ) )
+			{
+			CFsDelayedLoader::InstanceL()->GetContactHandlerL()->AddToContactL( 
+					*email, EContactUpdateEmail, aType );		
+			}						
+		}										
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::ShowContactDetailsForFocusedItemL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMsgDetailsVisualiser::ShowContactDetailsForFocusedItemL() const
+	{
+    FUNC_LOG;
+	TDesC* email = GetEmailAddressForFocusedItemAsTDes();
+	if( email )
+		{
+		CFsDelayedLoader::InstanceL()->GetContactHandlerL()->ShowContactDetailsL( 
+					*email, EContactUpdateEmail, NULL );
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CFSEmailUiMsgDetailsVisualiser::CopyFocusedItemToClipboardL
+// -----------------------------------------------------------------------------
+void CFSEmailUiMsgDetailsVisualiser::CopyFocusedItemToClipboardL() const
+	{
+    FUNC_LOG;
+	CFSEmailUiMsgDetailsItem* item = iModel->ItemByListId( iTreeList->FocusedItem() );
+	if (item)
+	    {
+    	CFSMailAddress* address = item->iMailAddress;
+    	TDesC* text = item->iText;
+    	if ( address )
+    	    {
+        	TDesC* clipBoardText = &address->GetEmailAddress();
+        	if( !clipBoardText ||
+        		(clipBoardText && clipBoardText->Length() == 0) )
+        		{
+        		clipBoardText = &address->GetDisplayName();
+        		if( !clipBoardText )
+        			{
+        			return;
+        			}
+        		}
+	       	TFsEmailUiUtility::CopyToClipboardL( *clipBoardText );
+    	    }
+    	else if( text )
+    		{
+	       	TFsEmailUiUtility::CopyToClipboardL( *text );
+    		}
+	    }		
+	}
+
+// -----------------------------------------------------------------------------
+// Action menu is available for items that has iMailAddress set in model.
+// -----------------------------------------------------------------------------
+TBool CFSEmailUiMsgDetailsVisualiser::HasFocusedItemActionMenu() const
+	{
+    FUNC_LOG;
+	CFSEmailUiMsgDetailsItem* item = iModel->ItemByListId( iTreeList->FocusedItem() );
+	if( item && item->iMailAddress )
+		{
+		const TDesC* displayName = &item->iMailAddress->GetDisplayName();
+		const TDesC* emailAddress = &item->iMailAddress->GetEmailAddress();
+
+		if ( (displayName && displayName->Length()) ||
+		     (emailAddress && emailAddress->Length()) )
+		    {
+		    return ETrue;
+		    }
+		}
+	return EFalse;
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::SetMskL()
+    {
+    FUNC_LOG;
+    if ( iFirstStartCompleted ) // Safety
+        {
+        TFsTreeItemId curId = iTreeList->FocusedItem(); 
+
+        if ( iTreeList->IsNode( curId ) )
+            {
+            if ( iTreeList->IsExpanded( curId ) )
+                {
+                ChangeMskCommandL( R_FSE_QTN_MSK_COLLAPSE );
+                } 
+            else  
+                {
+                ChangeMskCommandL( R_FSE_QTN_MSK_EXPAND );
+                }
+            }
+        else // non-node item
+            {
+            if( GetEmailAddressForFocusedItem() )
+                {
+                ChangeMskCommandL( R_FSE_QTN_MSK_COMPOSE );
+                }
+            else
+                {
+                ChangeMskCommandL( R_FSE_QTN_MSK_EMPTY );
+                }
+            }        
+        }
+    }
+
+TBool CFSEmailUiMsgDetailsVisualiser::OfferEventL(const TAlfEvent& aEvent)
+    {
+    FUNC_LOG;
+    TBool result = EFalse;
+    SetMskL();
+    if ( aEvent.IsKeyEvent() && aEvent.Code() == EEventKey )
+        {
+        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;
+            }
+        
+        switch ( scanCode )
+            {
+            case EStdKeyDevice3:	// CENTER CLICK
+            case EStdKeyEnter:		// ENTER
+            	{
+            	// Send email to focused item. Set the event as consumed if
+            	// valid email address was found and composer was opened with
+            	// that email address as recipent. If email address was not
+            	// found, offer the event to list by not consuming it.
+            	result = SendEmailToFocusedItemL();
+            	}
+            	break;
+				
+            case EStdKeyYes:
+            	{
+				CallToFocusedItemL();
+            	result = ETrue;
+            	}
+            	break;
+            
+	        case EStdKeyRightArrow:
+            	{
+            	// Show action toolbar if the item has action menu.
+            	if( HasFocusedItemActionMenu() )
+            		{
+            		LaunchActionMenuL();
+            		result = ETrue;
+            		}
+            	else
+            		{
+            		result = EFalse;
+            		}
+            	}
+				break;
+			
+			default:
+			    // Check keyboard shortcuts.
+	       	    TInt shortcutCommand = 
+	       	        iAppUi.ShortcutBinding().CommandForShortcutKey( aEvent.KeyEvent(),
+	       	                                                         CFSEmailUiShortcutBinding::EContextMailDetails );
+	       	    if ( shortcutCommand != KErrNotFound )
+	       	        {
+       	            HandleCommandL( shortcutCommand );
+	       	        result = ETrue;
+       	            }
+				break;
+            }
+        }
+    else if (aEvent.IsPointerEvent())
+        {
+        result = iTreeList->TreeControl()->OfferEventL(aEvent);
+        }
+
+	return result;
+    }
+
+// ---------------------------------------------------------------------------
+// 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 CFSEmailUiMsgDetailsVisualiser::OperationCompleteL(
+    TContactHandlerCmd /*aCmd*/, const RPointerArray<CFSEmailUiClsItem>& /*aContacts*/ )
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// From MFSEmailUiContactHandlerObserver
+// Handles error in contact handler operation.
+// ---------------------------------------------------------------------------
+//
+void CFSEmailUiMsgDetailsVisualiser::OperationErrorL( TContactHandlerCmd /*aCmd*/,
+    TInt /*aError*/ )
+    {
+    FUNC_LOG;
+    }
+
+void CFSEmailUiMsgDetailsVisualiser::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane)
+	{
+    FUNC_LOG;
+	   
+    if ( aResourceId == R_FSEMAILUI_MAILDETAILS_MENUPANE )
+        {
+        if ( FeatureManager::FeatureSupported( KFeatureIdFfCmailIntegration ) )
+    	   {
+    	   // remove help support in pf5250
+    	   aMenuPane->SetItemDimmed( EFsEmailUiCmdHelp, ETrue);      
+    	   }
+        
+        // Hide "actions" option if currently focused item doesn't have action menu
+       	aMenuPane->SetItemDimmed( EFsEmailUiCmdMailActions, !HasFocusedItemActionMenu() );
+        // Hide "copy to clipboard" option if there is nothing to copy on the focused row
+    	CFSEmailUiMsgDetailsItem* item = iModel->ItemByListId( iTreeList->FocusedItem() );
+    	if ( !item )
+    	    {
+        	aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsCopyToClipboard, ETrue );
+            }
+        aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsCollapseAll, AllNodesCollapsed() );
+        aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsExpandAll, AllNodesExpanded() );
+        }
+    
+    if ( aResourceId == R_FSEMAILUI_MAILDETAILS_SUBMENU_ACTIONS )
+        {
+        TInt pos( 0 );
+        if ( !iRCLSupported && aMenuPane->MenuItemExists( EFsEmailUiCmdActionsRemoteLookup ,pos) )
+            {
+            aMenuPane->SetItemDimmed( EFsEmailUiCmdActionsRemoteLookup, ETrue );
+            }
+        }
+    
+    // Add shortcut hints
+	iAppUi.ShortcutBinding().AppendShortcutHintsL( *aMenuPane, 
+	                           CFSEmailUiShortcutBinding::EContextMailDetails );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::HandleCommandL( TInt aCommand )
+    {
+    FUNC_LOG;
+    switch(aCommand)
+        {
+        case EAknSoftkeyBack:
+        	{
+            if ( !iAppUi.ViewSwitchingOngoing() )
+				{
+				ChangeTitleBarTextL( EFalse );
+	  	       	iAppUi.ReturnToPreviousViewL();
+				}
+     	 	}
+        	break;
+        	
+        case EFsEmailUiCmdActionsCopyToClipboard:
+		    {
+		    CopyFocusedItemToClipboardL();
+	        }
+	        break;
+        case EFsEmailUiCmdCollapse:
+			{
+            TFsTreeItemId focId1 = iTreeList->FocusedItem();
+            iTreeList->CollapseNodeL(focId1);
+            ChangeMskCommandL( R_FSE_QTN_MSK_EXPAND);
+            }
+            break;
+            
+        case EFsEmailUiCmdExpand:
+			{
+            TFsTreeItemId focId2 = iTreeList->FocusedItem();
+            iTreeList->ExpandNodeL(focId2);
+            ChangeMskCommandL( R_FSE_QTN_MSK_COLLAPSE);
+			}
+            break;
+		// Options menu commands
+        case EFsEmailUiCmdActionsCollapseAll:
+		    {
+        	TFsTreeItemId prevId = iTreeList->FocusedItem();
+        	prevId = GetRootParent( prevId );
+	    	iTreeVisualizer->CollapseAllL();
+    	    if ( prevId != KFsTreeRootID && prevId != KFsTreeNoneID )
+    	    	{
+		        iTreeVisualizer->SetFocusedItemL( prevId );
+    	    	}
+	        }
+	        break;
+
+        case EFsEmailUiCmdActionsExpandAll:
+		    {
+        	TFsTreeItemId prevId = iTreeList->FocusedItem();	
+		   	iTreeVisualizer->ExpandAllL();
+    	    if ( prevId != KFsTreeRootID && prevId != KFsTreeNoneID )
+    	    	{
+		        iTreeVisualizer->SetFocusedItemL( prevId );
+    	    	}
+	        }
+	        break;
+
+        case EFsEmailUiCmdActionsCall:
+		    {
+		    CallToFocusedItemL();
+	        }
+	        break;
+        // <cmail> video call
+        case EFsEmailUiCmdActionsCallVideo:
+            {
+            iVideoCall = ETrue;
+            CallToFocusedItemL();
+            }
+            break;
+        // </cmail>
+        case EFsEmailUiCmdActionsCreateMessage:
+		    {
+		    CreateMessageToFocusedItemL();
+	        }
+	        break;
+
+        case EFsEmailUiCmdComposeTo:
+            {
+            SendEmailToFocusedItemL();
+            }
+            break;
+            
+        case EFsEmailUiCmdActionsContactDetails:
+		    {
+		    ShowContactDetailsForFocusedItemL();
+	        }
+	        break;
+
+        case EFsEmailUiCmdActionsAddContact:
+		    {
+		    AddFocusedItemToContactsL();
+	        }
+	        break;
+
+        case EFsEmailUiCmdActionsRemoteLookup:
+		    {
+		    LaunchRemoteLookupForFocusedItemL();
+	        }
+	        break;
+
+        case EFsEmailUiCmdHelp:
+		    {
+        	TFsEmailUiUtility::LaunchHelpL( KFSE_HLP_LAUNCHER_GRID );
+	        }
+	        break;
+
+        case EFsEmailUiCmdExit:
+		    {
+		    //<cmail>
+		    iTreeList->SetFocusedL(EFalse);
+		    //</cmail>
+		    iAppUi.Exit();
+	        }
+	        break;
+        
+        case EFsEmailUiCmdActionsCollapseExpandAllToggle:
+            {
+            ShortcutCollapseExpandAllToggleL();
+            }
+            break;
+        
+        case EFsEmailUiCmdGoToTop:
+            {
+            GoToTopL();
+            }
+            break;
+            
+        case EFsEmailUiCmdGoToBottom:
+            {
+            GoToBottomL();
+            }
+            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;
+
+        default:
+        	break;
+        }
+    }
+
+
+void CFSEmailUiMsgDetailsVisualiser::ClearMsgDetailsModelL()
+	{
+    FUNC_LOG;
+	iTreeList->RemoveAllL();
+	iModel->RemoveAll();
+
+	iNodeIds.Reset();
+	iToNodeId = iCcNodeId = iBccNodeId = KFsTreeNoneID;
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::UpdateMsgDetailsModelL()
+    {
+    FUNC_LOG;
+    // If there are lots of items under some node, then the list drawing
+    // might become very slow because of scroll bar updating. So we deny
+    // the list refresh during the construction. List refresh is still
+    // allowed in case of node insert, as there aren't that many nodes,
+    // and it will keep the scroll bar roughly in the map.
+    iAllowListRefreshInInsert = ETrue;
+    iExpandAndHighlightNextNode = EFalse;
+
+	// Append lines to the model
+	AppendFromLinesL();
+	AppendSubjectLinesL();
+	
+	if( iExpandCollapseMode == ECollapseAllExceptTo )
+	    {
+	    iExpandAndHighlightNextNode = ETrue;
+	    }
+	AppendToLinesL();
+
+	if( iExpandCollapseMode == ECollapseAllExceptCc )
+        {
+        iExpandAndHighlightNextNode = ETrue;
+        }
+	AppendCcLinesL();
+
+	if( iExpandCollapseMode == ECollapseAllExceptBcc )
+        {
+        iExpandAndHighlightNextNode = ETrue;
+        }
+	AppendBccLinesL();
+	AppendSizeLinesL();
+	AppendSentLinesL();	
+	AppendPriorityLinesL();
+    // Allow list (scroll bar) refresh for last item(s)
+    //iAllowListRefreshInInsert = ETrue;
+	AppendMessageTypeLinesL();
+  	}
+
+void CFSEmailUiMsgDetailsVisualiser::CreateOneLinePlainItemLC2( const TDesC& aItemDataBuff,
+                                                       		    CFsTreePlainOneLineItemData* &aItemData,
+                                                       		    CFsTreePlainOneLineItemVisualizer* &aItemVisualizer )
+	{
+    FUNC_LOG;
+    aItemData = CFsTreePlainOneLineItemData::NewL();
+    CleanupStack::PushL( aItemData );
+    aItemData->SetDataL( aItemDataBuff );
+    
+    aItemVisualizer = CFsTreePlainOneLineItemVisualizer::NewL(*iTreeList->TreeControl());
+    CleanupStack::PushL( aItemVisualizer );
+	aItemVisualizer->SetExtendable( EFalse ); // One line items are obviously not extendable
+
+    SetItemVisualizerCommonProperties( *aItemVisualizer );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::CreateTwoLinePlainItemLC2( const TDesC& aPrimaryDataBuff,
+															    const TDesC& aSecondaryDataBuff,
+															    CFsTreePlainTwoLineItemData* &aItemData,
+															    CFsTreePlainTwoLineItemVisualizer* &aItemVisualizer )
+	{
+    FUNC_LOG;
+    aItemData = CFsTreePlainTwoLineItemData::NewL();
+    CleanupStack::PushL( aItemData );
+    aItemData->SetDataL( aPrimaryDataBuff );
+	aItemData->SetSecondaryDataL( aSecondaryDataBuff );
+
+    aItemVisualizer = CFsTreePlainTwoLineItemVisualizer::NewL(*iTreeList->TreeControl());
+    CleanupStack::PushL( aItemVisualizer );
+	aItemVisualizer->SetExtendable( ETrue ); // All two line items are extendable
+	aItemVisualizer->SetMenu( NULL );
+
+    SetItemVisualizerCommonProperties( *aItemVisualizer );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::SetItemVisualizerCommonProperties( MFsTreeItemVisualizer& aItemVisualizer )
+	{
+    FUNC_LOG;
+    aItemVisualizer.SetSize(TSize(iScreenRect.Width(), iListItemHeight));
+	aItemVisualizer.SetExtendedSize(TSize(iScreenRect.Width(), 2*iListItemHeight));
+
+  	// Set correct skin text colors for the list items  
+   	TRgb focusedColor = iAppUi.LayoutHandler()->ListFocusedStateTextSkinColor();
+   	TRgb normalColor = iAppUi.LayoutHandler()->ListNormalStateTextSkinColor();
+    aItemVisualizer.SetFocusedStateTextColor( focusedColor );
+    aItemVisualizer.SetNormalStateTextColor( normalColor );
+
+	// Set font size
+	aItemVisualizer.SetFontHeight( iAppUi.LayoutHandler()->ListItemFontHeightInTwips() );		
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::CreatePlainNodeLC2( const TDesC& aItemDataBuff,
+                                                         CFsTreePlainOneLineNodeData* &aItemData,
+                                                         CFsTreePlainOneLineNodeVisualizer* &aNodeVisualizer )
+	{
+    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(*iTreeList->TreeControl());
+    CleanupStack::PushL( aNodeVisualizer );
+    
+    SetNodeVisualizerProperties( *aNodeVisualizer );
+    
+    // Gradient background for headings    
+    CAlfBrush *titleDividerBgBrush = iAppUi.FsTextureManager()->TitleDividerBgBrushL();
+    aNodeVisualizer->SetBackgroundBrush( titleDividerBgBrush );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::SetNodeVisualizerProperties( MFsTreeItemVisualizer& aNodeVisualizer )
+	{
+    FUNC_LOG;
+    aNodeVisualizer.SetSize(TSize(iScreenRect.Width(), iListNodeHeight));
+
+  	// 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 size
+	aNodeVisualizer.SetFontHeight( iAppUi.LayoutHandler()->ListItemFontHeightInTwips() );		
+	// Set node bolded	
+	aNodeVisualizer.SetTextBold( ETrue );
+	
+	// Temporary fix for EASV-7GJFVD
+	//aNodeVisualizer.SetBackgroundColorL( iAppUi.LayoutHandler()->ListNodeBackgroundColor() );
+	
+	}
+
+TFsTreeItemId CFSEmailUiMsgDetailsVisualiser::AppendHeadingToListL( TInt aResourceId )
+	{
+    FUNC_LOG;
+    CFsTreePlainOneLineNodeData* plainNodeData;
+    CFsTreePlainOneLineNodeVisualizer* plainNodeVisualizer;
+
+ 	HBufC* headingText = StringLoader::LoadLC( aResourceId );
+
+	CreatePlainNodeLC2( *headingText, plainNodeData, plainNodeVisualizer );
+	
+    TFsTreeItemId nodeId = iTreeList->InsertNodeL( *plainNodeData, *plainNodeVisualizer, KFsTreeRootID);
+    CleanupStack::Pop( 2 ); // plainNodeData & plainNodeVisualizer
+
+    // Set the node expanded/collapsed according to the member variables
+    if( nodeId != KFsTreeNoneID ) // Safety check
+        {
+        if( iExpandCollapseMode == EExpandAll )
+            {
+            // The "normal" case, expand all and keep the first one highlighted
+            iTreeList->ExpandNodeL( nodeId );
+            }
+        else if( iExpandAndHighlightNextNode )
+            {
+            // View opened to To, Cc or Bcc field and we just added the
+            // corresponding node, so expand and focus it
+            iTreeList->ExpandNodeL( nodeId );
+            iTreeVisualizer->SetFocusedItemL( nodeId );
+            }
+        else
+            {
+            // View opened to To, Cc or Bcc field but we added some other
+            // node, so collapse it
+            iTreeList->CollapseNodeL( nodeId );
+            }
+        }
+    // Reset the node expanding and highlighting flag
+    iExpandAndHighlightNextNode = EFalse;
+    
+   	CleanupStack::PopAndDestroy(headingText);
+
+   	return nodeId;
+	}
+
+TFsTreeItemId CFSEmailUiMsgDetailsVisualiser::AppendOneLineItemToListL( const TDesC& aItemData, TFsTreeItemId aParentNode )
+	{
+    FUNC_LOG;
+    CFsTreePlainOneLineItemData* plainItemData;
+    CFsTreePlainOneLineItemVisualizer* plainItemVisualizer;
+
+    CreateOneLinePlainItemLC2( aItemData, plainItemData, plainItemVisualizer );
+
+    TFsTreeItemId itemId = iTreeList->InsertItemL( *plainItemData, *plainItemVisualizer, aParentNode, KErrNotFound, iAllowListRefreshInInsert );
+    CleanupStack::Pop( 2 ); // plainItemData & plainItemVisualizer
+
+    return itemId;
+	}
+
+TFsTreeItemId CFSEmailUiMsgDetailsVisualiser::AppendTwoLineItemToListL( const TDesC& aPrimaryDataBuff,
+															  			const TDesC& aSecondaryDataBuff,
+															  			TFsTreeItemId aParentNode,
+															  			TBool aItemHasActionMenu /*= EFalse*/ )
+	{
+    FUNC_LOG;
+    CFsTreePlainTwoLineItemData* plainItemData;
+    CFsTreePlainTwoLineItemVisualizer* plainItemVisualizer;
+
+    CreateTwoLinePlainItemLC2( aPrimaryDataBuff, aSecondaryDataBuff, plainItemData, plainItemVisualizer );
+    
+    if ( aItemHasActionMenu )
+        {
+        plainItemVisualizer->SetFlags( plainItemVisualizer->Flags() | KFsTreeListItemHasMenu );
+        }
+   
+    plainItemVisualizer->SetFlags(plainItemVisualizer->Flags() & ~KFsTreeListItemManagedLayout);  
+  
+    TFsTreeItemId itemId = iTreeList->InsertItemL( *plainItemData, *plainItemVisualizer, aParentNode, KErrNotFound, iAllowListRefreshInInsert );
+    CleanupStack::Pop( 2 ); // plainItemData & plainItemVisualizer
+
+    return itemId;
+	}
+
+TFsTreeItemId CFSEmailUiMsgDetailsVisualiser::AppendDateTimeItemToListL( const TDesC& aPrimaryDataBuff,
+															  			 const TDesC& aSecondaryDataBuff,
+															  			 const TDesC& aDateTimeDataBuff,
+															  			 TFsTreeItemId aParentNode )
+	{
+    FUNC_LOG;
+    CFsTreePlainTwoLineItemData* plainItemData;
+    CFsTreePlainTwoLineItemVisualizer* plainItemVisualizer;
+
+    CreateTwoLinePlainItemLC2( aPrimaryDataBuff, aSecondaryDataBuff, plainItemData, plainItemVisualizer );
+
+	plainItemData->SetDateTimeDataL( aDateTimeDataBuff );
+	plainItemVisualizer->SetExtendable( EFalse );
+    
+	TFsTreeItemId itemId = iTreeList->InsertItemL( *plainItemData, *plainItemVisualizer, aParentNode, KErrNotFound, iAllowListRefreshInInsert );
+    CleanupStack::Pop( 2 ); // plainItemData & plainItemVisualizer
+
+    return itemId;
+	}
+
+TBool CFSEmailUiMsgDetailsVisualiser::GetDisplayNameAndEmailAddressL( CFSMailAddress* aAddressData, TDesC* &aDisplayName, TDesC* &aEmailAddress )
+	{
+    FUNC_LOG;
+ 	aDisplayName = &aAddressData->GetDisplayName();
+ 	aEmailAddress = &aAddressData->GetEmailAddress();
+ 	TInt notFoundCount(0);
+ 	
+ 	// If display name is not set, then the plugins seem to set it to be same
+ 	// as email address. So there's no safe way to know wheter the display name
+ 	// is set or not. Best quess is that if display name is the same as email
+ 	// address, then there are no display name available.
+ 	if ( !aDisplayName || ( aDisplayName->Length() == 0 ) || ( *aDisplayName == *aEmailAddress ) )
+		{
+		// Internal variable used to store the text to avoid problems with ownership handling
+		if( !iNoDisplayNameAvailableText )
+			{
+			iNoDisplayNameAvailableText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_NO_DISPLAY_NAME );
+			}
+	
+		aDisplayName = iNoDisplayNameAvailableText;
+		notFoundCount++;
+		}
+ 	if ( !aEmailAddress || ( aEmailAddress->Length() == 0 ) )
+		{
+		// Internal variable used to store the text to avoid problems with ownership handling
+		if( !iNoEmailAddressAvailableText )
+			{
+			iNoEmailAddressAvailableText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_NO_EMAIL_ADDRESS );
+			}
+
+		aEmailAddress = iNoEmailAddressAvailableText;
+		notFoundCount++;
+		}
+
+	// If both display name and email address are empty, return EFalse
+	if( notFoundCount > 1 )
+		{
+		return EFalse;
+		}
+	else
+		{
+		return ETrue;
+		}
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::AppendFromLinesL()
+	{
+    FUNC_LOG;
+	TFsTreeItemId nodeId;
+	if( iViewedMsg->IsFlagSet( EFSMsgFlag_CalendarMsg ) )
+		{
+		nodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_ORGANIZER );
+		}
+	else
+		{
+	 	nodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_FROM );
+		}
+ 	iNodeIds.Append( nodeId );
+
+ 	CFSMailAddress* fromAddress = iViewedMsg->GetSender();
+	// If CFSMailAddress not available, show "No sender info available"
+ 	if( fromAddress == NULL )
+ 		{
+	 	HBufC* noSender = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_NO_SENDER_INFO_AVAILABLE );
+		AppendOneLineItemToListL( *noSender, nodeId );
+		CleanupStack::PopAndDestroy( noSender );
+ 		}
+ 	else
+ 		{
+		TDesC* displayName( NULL );
+		TDesC* emailAddress( NULL );
+		if( GetDisplayNameAndEmailAddressL( fromAddress, displayName, emailAddress ) )
+			{
+			TFsTreeItemId itemId = AppendTwoLineItemToListL( *displayName, *emailAddress, nodeId, ETrue );
+			iModel->AppendL( itemId, fromAddress );
+			}
+		else
+			{
+		 	HBufC* noSender = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_NO_SENDER_INFO_AVAILABLE );
+			AppendOneLineItemToListL( *noSender, nodeId );
+			CleanupStack::PopAndDestroy( noSender );
+			}
+ 		}
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::AppendSubjectLinesL()
+	{
+    FUNC_LOG;
+ 	TFsTreeItemId nodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_SUBJECT );
+ 	iNodeIds.Append( nodeId );
+
+	TDesC* subject = &iViewedMsg->GetSubject();
+	if ( subject == NULL || subject->Length() <= 0 )
+		{
+	 	HBufC* noSubject = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_NO_SUBJECT );
+		AppendOneLineItemToListL( *noSubject, nodeId );
+		CleanupStack::PopAndDestroy( noSubject );
+		}
+	else
+		{
+		HBufC* subjectText = TFsEmailUiUtility::CreateSubjectTextLC( iViewedMsg );
+		TFsTreeItemId itemId = AppendOneLineItemToListL( *subjectText, nodeId );
+		CleanupStack::PopAndDestroy( subjectText );
+		iModel->AppendL( itemId, subject );
+		}
+	}
+
+// Duplicate code in AppendToLinesL/AppendCcLinesL/AppendBccLinesL, create
+// one generic function that can be used from all of these functions
+void CFSEmailUiMsgDetailsVisualiser::AppendToLinesL()
+	{
+    FUNC_LOG;
+	if( iViewedMsg->IsFlagSet( EFSMsgFlag_CalendarMsg ) )
+		{
+		iToNodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_REQUIRED );
+		}
+	else
+		{
+	 	iToNodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_TO );
+		}
+ 	iNodeIds.Append( iToNodeId );
+ 
+ 	RPointerArray<CFSMailAddress>& toArray = iViewedMsg->GetToRecipients();
+	TInt toArrayCount = toArray.Count(); 
+	if ( toArrayCount )
+		{
+		for ( TInt i=0 ; i<toArrayCount ; i++ )
+			{
+		  	CFSMailAddress* toAddress = toArray[i];
+		  	if( toAddress )
+		  		{
+			 	TDesC* displayName( NULL );
+			 	TDesC* emailAddress( NULL );
+				TBool toNameFound = GetDisplayNameAndEmailAddressL( toAddress, displayName, emailAddress );
+
+				TFsTreeItemId itemId = AppendTwoLineItemToListL( *displayName, *emailAddress, iToNodeId, toNameFound );
+				iModel->AppendL( itemId, toAddress );
+		  		}
+			}		
+		}		
+	else
+		{
+		//Laske To- ja Cc-vastaanottajat yhteensä ja näytä tämä vain jos kumpiakaan ei ole yhtään
+	 	HBufC* noToText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_NO_VISIBLE_RECIPIENTS );
+		AppendOneLineItemToListL( *noToText, iToNodeId );
+		CleanupStack::PopAndDestroy( noToText );
+		}
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::AppendCcLinesL()
+	{
+    FUNC_LOG;
+ 	RPointerArray<CFSMailAddress>& ccArray = iViewedMsg->GetCCRecipients();
+	TInt ccArrayCount = ccArray.Count(); 
+
+	if ( ccArrayCount )
+		{
+		if( iViewedMsg->IsFlagSet( EFSMsgFlag_CalendarMsg ) )
+			{
+			iCcNodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_OPTIONAL );
+			}
+		else
+			{
+		 	iCcNodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_CC );
+			}
+	 	iNodeIds.Append( iCcNodeId );
+	 	
+		for ( TInt i=0 ; i<ccArrayCount ; i++ )
+			{
+		  	CFSMailAddress* ccAddress = ccArray[i];
+		  	if( ccAddress )
+		  		{
+			 	TDesC* displayName( NULL );
+			 	TDesC* emailAddress( NULL );
+				TBool ccNameFound = GetDisplayNameAndEmailAddressL( ccAddress, displayName, emailAddress );
+
+				TFsTreeItemId itemId = AppendTwoLineItemToListL( *displayName, *emailAddress, iCcNodeId, ccNameFound );
+				iModel->AppendL( itemId, ccAddress );
+		  		}
+			}
+		}
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::AppendBccLinesL()
+	{
+    FUNC_LOG;
+	// Get message's parent folder
+	TFSMailMsgId folderId = iViewedMsg->GetFolderId();
+	TFSMailMsgId mailboxId = iViewedMsg->GetMailBoxId();
+	CFSMailFolder* folder = iAppUi.GetMailClient()->GetFolderByUidL( mailboxId, folderId );
+	
+	// Show bcc field only if message's parent folder is some outgoing folder,
+	// so basically outbox, drafts or sent items.
+	TBool showBcc( EFalse );
+	if( folder )
+		{
+		TInt folderType = folder->GetFolderType();
+
+		switch( folderType )
+			{
+			case EFSOutbox:
+			case EFSDraftsFolder:
+			case EFSSentFolder:
+				{
+				showBcc = ETrue;
+				}
+				break;
+
+			case EFSInbox:
+			case EFSDeleted:
+			default:
+				break;
+			}
+		}
+	delete folder; 
+	
+	if( showBcc )
+		{
+	 	RPointerArray<CFSMailAddress>& bccArray = iViewedMsg->GetBCCRecipients();
+		TInt bccArrayCount = bccArray.Count(); 
+
+		if ( bccArrayCount )
+			{
+		 	iBccNodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_BCC );
+		 	iNodeIds.Append( iBccNodeId );
+		 	
+			for ( TInt i=0 ; i<bccArrayCount ; i++ )
+				{
+			  	CFSMailAddress* bccAddress = bccArray[i];
+			  	if( bccAddress )
+			  		{
+				 	TDesC* displayName( NULL );
+				 	TDesC* emailAddress( NULL );
+					TBool bccNameFound = GetDisplayNameAndEmailAddressL( bccAddress, displayName, emailAddress );
+
+					TFsTreeItemId itemId = AppendTwoLineItemToListL( *displayName, *emailAddress, iBccNodeId, bccNameFound );
+					iModel->AppendL( itemId, bccAddress );
+			  		}
+				}
+			}
+		}
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::AppendSizeLinesL()
+	{
+    FUNC_LOG;
+ 	TFsTreeItemId nodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_SIZE_HEADER );
+ 	iNodeIds.Append( nodeId );
+ 	
+ 	// Gets the full content size (in bytes)
+    TUint msgSize = iViewedMsg->ContentSize();
+
+    HBufC* sizeText = TFsEmailUiUtility::CreateSizeDescLC( msgSize, ETrue );
+
+	AppendOneLineItemToListL( *sizeText, nodeId );
+	CleanupStack::PopAndDestroy( sizeText );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::AppendSentLinesL()
+	{
+    FUNC_LOG;
+ 	TFsTreeItemId nodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_SENT );
+ 	iNodeIds.Append( nodeId );
+
+ 	HBufC* dateFromMsg = TFsEmailUiUtility::DateTextFromMsgLC( iViewedMsg );
+	HBufC* dateText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_DATE_U, *dateFromMsg );
+ 	
+	AppendOneLineItemToListL( *dateText, nodeId );
+		
+	CleanupStack::PopAndDestroy( dateText );
+ 	CleanupStack::PopAndDestroy( dateFromMsg );
+	
+	//////////////////////////
+ 	HBufC* timeFromMsg = TFsEmailUiUtility::TimeTextFromMsgLC( iViewedMsg );
+	HBufC* timeText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_TIME_U, *timeFromMsg );
+ 	
+	AppendOneLineItemToListL( *timeText, nodeId );
+	
+	CleanupStack::PopAndDestroy( timeText );
+ 	CleanupStack::PopAndDestroy( timeFromMsg );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::AppendPriorityLinesL()
+	{
+    FUNC_LOG;
+ 	TFsTreeItemId nodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_PRIORITY );
+ 	iNodeIds.Append( nodeId );
+ 	
+ 	HBufC* priorityText( NULL );
+	if ( iViewedMsg->IsFlagSet( EFSMsgFlag_Important ) )
+		{
+		priorityText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_PRIORITY_HIGH );			
+		}
+	else if ( iViewedMsg->IsFlagSet( EFSMsgFlag_Low ) )
+		{
+		priorityText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_PRIORITY_LOW );				
+		}
+	else
+		{
+		priorityText = StringLoader::LoadL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_PRIORITY_NORMAL );					
+		}
+
+	CleanupStack::PushL( priorityText );
+	AppendOneLineItemToListL( *priorityText, nodeId );
+	CleanupStack::PopAndDestroy( priorityText );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::AppendMessageTypeLinesL()
+	{
+    FUNC_LOG;
+ 	TFsTreeItemId nodeId = AppendHeadingToListL( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_MSG_TYPE );
+ 	iNodeIds.Append( nodeId );
+ 	
+ 	HBufC* msgType;
+	if( iViewedMsg->IsFlagSet( EFSMsgFlag_CalendarMsg ) )
+		{
+		msgType = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_MSG_TYPE_MEETING );
+		}
+	else
+		{
+		msgType = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_MSG_DETAILS_MSG_TYPE_EMAIL );
+		}
+		
+	AppendOneLineItemToListL( *msgType, nodeId );
+	CleanupStack::PopAndDestroy( msgType );
+	}
+
+void CFSEmailUiMsgDetailsVisualiser::HandleDynamicVariantSwitchL( CFsEmailUiViewBase::TDynamicSwitchType /*aType*/ )
+	{
+    FUNC_LOG;
+    if ( iFirstStartCompleted ) // Safety
+        {
+        iTreeList->HideListL();        
+        UpdateListSizeAttributes();
+        iParentLayout->SetRect( iScreenRect );
+        for ( TInt i = 0; i < iNodeIds.Count(); i++ )
+            {
+            MFsTreeItemVisualizer& vis = iTreeList->ItemVisualizer( iNodeIds[i] );
+            SetNodeVisualizerProperties( vis );           
+            SetChildVisualizersProperties( iNodeIds[i] );
+            }
+        iTreeList->ShowListL();        
+        }
+	}
+
+// ---------------------------------------------------------------------------
+// Sets tree item visualizer properties for all the childs of the given node
+// ---------------------------------------------------------------------------
+//
+void CFSEmailUiMsgDetailsVisualiser::SetChildVisualizersProperties( TFsTreeItemId aNodeId )
+	{
+    FUNC_LOG;
+	TUint childrenCount = iTreeList->CountChildren( aNodeId );
+	for( TInt i = 0; i < childrenCount; ++i )
+		{
+		TFsTreeItemId childId = iTreeList->Child( aNodeId, i );
+    	MFsTreeItemVisualizer& vis = iTreeList->ItemVisualizer( childId );
+	    SetItemVisualizerCommonProperties( vis );
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// Update list size members variables
+// ---------------------------------------------------------------------------
+//
+void CFSEmailUiMsgDetailsVisualiser::UpdateListSizeAttributes()
+	{
+    FUNC_LOG;
+    if ( iFirstStartCompleted ) // Safety
+        {
+        AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, iScreenRect );
+        iScreenRect.SetRect( 0, 0, iScreenRect.Width(), iScreenRect.Height() );
+
+        iListItemHeight = iAppUi.LayoutHandler()->OneLineListItemHeight();
+        iListNodeHeight = iAppUi.LayoutHandler()->OneLineListNodeHeight();        
+        }
+	}
+
+// ---------------------------------------------------------------------------
+// Collapse nodes except the specified one (used when starting the list in 
+// specific loaction)
+// ---------------------------------------------------------------------------
+//
+void CFSEmailUiMsgDetailsVisualiser::CollapseNodesExceptL( TFsTreeItemId aExcludedNode )
+	{
+    FUNC_LOG;
+	for( TInt i = 0; i < iNodeIds.Count(); i++ )
+		{
+		if( iNodeIds[i] != aExcludedNode )
+			{
+			iTreeList->CollapseNodeL( iNodeIds[i] );
+			}
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// If there is one or more expanded nodes, collapses all nodes.
+// Otherwise expands all nodes.
+// ---------------------------------------------------------------------------
+//
+void CFSEmailUiMsgDetailsVisualiser::ShortcutCollapseExpandAllToggleL()
+    {
+    FUNC_LOG;
+    TBool collapseAllNodes( EFalse );
+    for( TInt i=0 ; i<iNodeIds.Count() ; i++ )
+        {
+        if( iTreeList->IsExpanded( iNodeIds[i] ) )
+            {
+            collapseAllNodes = ETrue;
+            break;
+            }	
+        }
+
+    if( collapseAllNodes )
+        {
+        HandleCommandL( EFsEmailUiCmdActionsCollapseAll );
+        }
+    else
+        {
+        HandleCommandL( EFsEmailUiCmdActionsExpandAll );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Moves the focus to the topmost item
+// ---------------------------------------------------------------------------
+//
+void CFSEmailUiMsgDetailsVisualiser::GoToTopL()
+    {
+    FUNC_LOG;
+    if ( iNodeIds.Count() )
+        {
+        TFsTreeItemId topId = iNodeIds[0];
+        iTreeVisualizer->SetFocusedItemL( topId );            
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Moves the focus to the bottommost item
+// ---------------------------------------------------------------------------
+//
+void CFSEmailUiMsgDetailsVisualiser::GoToBottomL()
+    {
+    FUNC_LOG;
+    if ( iNodeIds.Count() )
+        {
+        TFsTreeItemId bottomId = iNodeIds[ iNodeIds.Count()-1 ];
+        TInt childCount = iTreeList->CountChildren(bottomId);
+        if ( childCount && iTreeList->IsExpanded(bottomId) )
+            {
+            // Focus the last child of the bottom node if the node is expanded.
+            bottomId = iTreeList->Child( bottomId, childCount-1 );
+            }
+        iTreeVisualizer->SetFocusedItemL( bottomId );            
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Recursive function to get the root parent of given item
+// ---------------------------------------------------------------------------
+//
+TFsTreeItemId CFSEmailUiMsgDetailsVisualiser::GetRootParent( const TFsTreeItemId aItemId ) const
+	{
+    FUNC_LOG;
+	TFsTreeItemId parentId = iTreeList->Parent( aItemId );
+	// If current item's parent is KFsTreeRootID, return its id
+	if( parentId == KFsTreeRootID || parentId == KFsTreeNoneID )
+		{
+		return aItemId;
+		}
+	else
+		{
+		// Get the root parent recursively
+		return GetRootParent( parentId );
+		}
+	}
+
+
+// ---------------------------------------------------------------------------
+// Tells if all expandable nodes are collapsed
+// ---------------------------------------------------------------------------
+//
+TBool CFSEmailUiMsgDetailsVisualiser::AllNodesCollapsed() const
+    {
+    FUNC_LOG;
+    TFsTreeItemId itemId = KFsTreeNoneID;
+    TInt count = iTreeList->CountChildren(KFsTreeRootID);
+	
+	// If top level is collapsed, then everything is collapsed. There's no need
+	// to crawl any deeper in the tree hierarchy.
+	for ( TInt i=0 ; i<count ; ++i )
+	    {
+	    itemId = iTreeList->Child( KFsTreeRootID, i );
+	    if ( iTreeList->IsNode(itemId) &&
+	         iTreeList->IsExpanded(itemId) )
+	        {
+	        return EFalse;
+	        }
+	    }
+	
+	return ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// Tells if all expandable nodes are expanded
+// ---------------------------------------------------------------------------
+//
+TBool CFSEmailUiMsgDetailsVisualiser::AllNodesExpanded( TFsTreeItemId aParentNodeId ) const
+    {
+    FUNC_LOG;
+    // We must crawl through the whole tree to see, if there are any collapsed nodes
+    // at any level. We do this with recursive depth-first-search.
+    
+    TFsTreeItemId itemId = KFsTreeNoneID;
+    TInt count = iTreeList->CountChildren(aParentNodeId);
+    
+    for ( TInt i=0 ; i<count ; ++i )
+        {
+        itemId = iTreeList->Child( aParentNodeId, i );
+        if ( iTreeList->IsNode(itemId) )
+            {
+            if ( !iTreeList->IsExpanded(itemId) ||
+                 !AllNodesExpanded(itemId) )
+                {
+                return EFalse;
+                }
+            }
+        }
+	
+	return ETrue;
+    }
+
+// <cmail> Touch
+// ---------------------------------------------------------------------------
+// Process a treelist event
+// ---------------------------------------------------------------------------
+//
+void CFSEmailUiMsgDetailsVisualiser::TreeListEventL( const TFsTreeListEvent aEvent, 
+                                    const TFsTreeItemId /*aId*/ )
+    {
+    switch (aEvent)
+        {
+        case EFsTreeListItemTouchAction:
+            {
+            if (TFsTreeItemId focId1 = iTreeList->FocusedItem())
+                {
+                if (iTreeList->IsNode(focId1))
+                    {
+                    if (iTreeList->IsExpanded(focId1))
+                        {
+                        HandleCommandL(EFsEmailUiCmdCollapse);
+                        }
+                    else
+                        {
+                        HandleCommandL(EFsEmailUiCmdExpand);
+                        }
+                    }
+                else
+                    {
+                    SendEmailToFocusedItemL();
+                    }
+                }
+            break;
+            }
+        case EFsTreeListItemTouchLongTap:
+            {
+            // Show action toolbar if the item has action menu.
+            if( HasFocusedItemActionMenu() )
+                {
+                LaunchActionMenuL();
+                }
+            break;
+            }
+        case EFsTreeListItemWillGetFocused:
+            {
+            SetMskL(); 
+            break;
+            }
+        }
+    }
+
+
+TPoint CFSEmailUiMsgDetailsVisualiser::ActionMenuPosition()
+    {
+    TAlfRealRect focusRect;
+    TFsTreeItemId listItemId = iTreeList->FocusedItem();
+    iTreeList->GetItemDisplayRectTarget(listItemId, focusRect);
+    return focusRect.iTl;
+    }
+// </cmail>
+
+void CFSEmailUiMsgDetailsVisualiser::GetParentLayoutsL( RPointerArray<CAlfVisual>& aLayoutArray ) const
+    {
+    aLayoutArray.AppendL( iParentLayout );
+    }
+