emailuis/nmailui/src/nmeditorview.cpp
branchRCL_3
changeset 63 d189ee25cf9d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/nmailui/src/nmeditorview.cpp	Tue Aug 31 15:04:17 2010 +0300
@@ -0,0 +1,1579 @@
+/*
+* Copyright (c) 2009 - 2010 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: Message editor view
+*
+*/
+#include "nmuiheaders.h"
+
+// Layout file and view
+static const char *NMUI_EDITOR_VIEW_XML = ":/docml/nmeditorview.docml";
+static const char *NMUI_EDITOR_VIEW = "editorview";
+
+// extension list item frame.
+static const QString NmPopupListFrame = "qtg_fr_popup_list_normal";
+static const QString NmDelimiter("; ");
+static const QString NmPriorityLow("low");
+static const QString NmPriorityNormal("normal");
+static const QString NmPriorityHigh("high");
+
+/*!
+	\class NmEditorView
+	\brief Mail editor view
+*/
+
+/*!
+    Constructor
+*/
+NmEditorView::NmEditorView(
+    NmApplication &application,
+    NmUiStartParam* startParam,
+    NmUiEngine &uiEngine,
+    NmAttachmentManager &attaManager,
+    QGraphicsItem *parent)
+    : NmBaseView(startParam, application, parent),
+      mApplication(application),
+      mUiEngine(uiEngine),
+      mAttaManager(attaManager),
+      mDocumentLoader(NULL),
+      mHeaderWidget(NULL),
+      mMessage(NULL),
+      mContent(NULL),
+      mAttachmentListContextMenu(NULL),
+      mMessageCreationOperation(NULL),
+      mAddAttachmentOperation(NULL),
+      mRemoveAttachmentOperation(NULL),
+      mWaitDialog(NULL),
+      mQueryDialog(NULL),
+      mAttachmentPicker(NULL),
+      mCcBccFieldVisible(false),
+      mServiceSendingDialog(NULL),
+      mHiddenPriorityName(NmPriorityNormal)
+{
+    NM_FUNCTION;
+    
+    mDocumentLoader	= new HbDocumentLoader();
+    // Set object name
+    setObjectName("NmEditorView");
+    // call the createToolBar on load view layout
+    createToolBar();
+    // Load view layout
+    loadViewLayout();
+}
+
+/*!
+    Destructor
+*/
+NmEditorView::~NmEditorView()
+{
+    NM_FUNCTION;
+    
+    if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
+        mRemoveAttachmentOperation->cancelOperation();
+    }
+    if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
+        mAddAttachmentOperation->cancelOperation();
+    }
+    if (mMessageCreationOperation && mMessageCreationOperation->isRunning()) {
+        mMessageCreationOperation->cancelOperation();
+    }
+    delete mMessage;
+    mWidgetList.clear();
+    delete mDocumentLoader;
+    delete mPrioritySubMenu;
+    
+    if (mAttachmentListContextMenu) {
+        mAttachmentListContextMenu->clearActions();
+        delete mAttachmentListContextMenu;
+    }
+    delete mWaitDialog;
+    delete mQueryDialog;
+    delete mAttachmentPicker;    
+    mAttaManager.clearObserver();
+    mAttaManager.cancelFetch();
+    
+    // make sure virtual keyboard is closed
+    QInputContext *ic = qApp->inputContext();
+    if (ic) {
+        QEvent *closeEvent = new QEvent(QEvent::CloseSoftwareInputPanel);
+        ic->filterEvent(closeEvent);
+        delete closeEvent;
+    }
+}
+
+/*!
+    View layout loading from XML
+*/
+void NmEditorView::loadViewLayout()
+{
+    NM_FUNCTION;
+    
+    mPrioritySubMenu = NULL;
+
+    // Use document loader to load the view
+    bool ok(false);
+
+    setObjectName(QString(NMUI_EDITOR_VIEW));
+    QObjectList objectList;
+    objectList.append(this);
+    // Pass the view to documentloader. Document loader uses this view
+    // when docml is parsed, instead of creating new view.
+    // documentloader is created in constructor
+    mDocumentLoader->setObjectTree(objectList);
+
+    mWidgetList = mDocumentLoader->load(NMUI_EDITOR_VIEW_XML, &ok);
+
+   if (ok) {
+        mContent = new NmEditorContent(this, mDocumentLoader, 
+            mApplication.networkAccessManager(), mApplication);
+
+        mHeaderWidget = mContent->header();
+
+        // Set default color for user - entered text if editor is in re/reAll/fw mode
+        if (mStartParam) {
+            NmUiEditorStartMode mode = mStartParam->editorStartMode();
+            if (mode == NmUiEditorReply
+                || mode == NmUiEditorReplyAll 
+                || mode == NmUiEditorForward) {
+                mContent->editor()->setCustomTextColor(true, Qt::blue);
+            }
+        }
+
+        // the rest of the view initialization is done in viewReady()
+    }
+}
+
+/*!
+    Reload view contents with new start parameters
+    Typically when view is already open and external view activation occurs
+    for this same view
+*/
+void NmEditorView::reloadViewContents(NmUiStartParam* startParam)
+{
+    NM_FUNCTION;
+    
+    // Check start parameter validity.
+    if (startParam&&startParam->viewId()==NmUiViewMessageEditor) {
+        // Delete existing start parameter data
+        delete mStartParam;
+        mStartParam=NULL;
+        // Store new start parameter data
+        mStartParam=startParam;
+        // Store existing edited message to drafts and reload
+        // editor with new start parameters.
+        // ..
+        // Reload editor with new message data
+        fetchMessageIfNeeded(*mStartParam);
+    }
+    else {
+        NM_ERROR(1,"nmailui: Invalid editor start parameter");
+        // Unused start parameter needs to be deleted
+        delete startParam;
+        startParam = NULL;
+    }
+}
+
+/*!
+   Screen orientation changed. Editor view needs to be scaled when
+   landscape <-> portrait switch occurs because text needs to
+   be wrapped again.
+*/
+void NmEditorView::orientationChanged(Qt::Orientation orientation)
+{
+    NM_FUNCTION;
+    
+    Q_UNUSED(orientation);
+    
+    // content widget height needs to be set according to the new orientation to get the scroll
+	// area work correctly
+	mHeaderWidget->sendDelayedHeaderHeightChanged();
+	mHeaderWidget->adjustHeaderWidth();
+}
+
+/*!
+    This slot is signaled by VKB when it opens
+ */
+void NmEditorView::vkbOpened()
+{
+    showChrome(false);	
+}
+
+/*!
+    This slot is signaled by VKB when it closes.
+ */
+void NmEditorView::vkbClosed()
+{
+	showChrome(true);
+}
+
+/*!
+    Hide or show chrome.
+ */
+void NmEditorView::showChrome(bool show)
+{
+    if (show) {
+        showItems(Hb::StatusBarItem | Hb::TitleBarItem | Hb::ToolBarItem);
+    }
+    else {
+        hideItems(Hb::StatusBarItem | Hb::TitleBarItem | Hb::ToolBarItem);
+    }
+}
+
+/*!
+    View id
+*/
+NmUiViewId NmEditorView::nmailViewId() const
+{
+    NM_FUNCTION;
+    
+    return NmUiViewMessageEditor;
+}
+
+/*
+   Launch dialog for query user if we want to exit the editor
+*/
+void NmEditorView::okToExitView()
+{
+    NM_FUNCTION;
+       
+    bool okToExit(true);
+    
+    if (mContent) {
+        NmEditorHeader *header = mContent->header();
+        // show the query if the message has not been sent
+        if (mMessage && header) {
+            // see if editor has any content
+            int subjectLength = 0;
+            if (header->subjectEdit()) {
+                subjectLength = header->subjectEdit()->text().length();
+            }
+            
+            QList<NmMessagePart*> attachmentList;
+            mMessage->attachmentList(attachmentList);
+            
+            if (mContent->editor()) {
+                okToExit = (subjectLength == 0 && mContent->editor()->document()->isEmpty());            
+            }
+    
+            // content exists, verify exit from user
+            if (!okToExit) {
+                if (mQueryDialog) {
+                    delete mQueryDialog;
+                    mQueryDialog = 0;
+                }
+                // Launch query dialog.
+                mQueryDialog = 
+                    NmUtilities::displayQuestionNote(hbTrId("txt_mail_dialog_save_message_to_drafts"),
+                                                                this,
+                                                                SLOT(okToExitQuery(HbAction*)));
+            }
+        }    
+    }
+    
+    // no need to query anything, just exit.
+    if(okToExit) {
+        QMetaObject::invokeMethod(&mApplication,
+                                  "popView",
+                                  Qt::QueuedConnection);
+    }
+}
+
+/*!
+    Handle the user selection is it ok to exit.
+*/
+void NmEditorView::okToExitQuery(HbAction *action)
+{
+    NM_FUNCTION;
+    
+    HbMessageBox *dlg = static_cast<HbMessageBox*>(sender());
+    // The first action in dialogs action list is for the "Yes"-button.
+    if (action == dlg->actions().at(0)) {
+        safeToDraft();
+    }    
+    
+    // Close the view
+    QMetaObject::invokeMethod(&mApplication,
+                              "popView",
+                              Qt::QueuedConnection);
+}
+
+/*!
+    Public slot to handle draft saving.
+*/
+void NmEditorView::safeToDraft()
+{
+    // Update draft message with content.
+    updateMessageWithEditorContents();
+
+    // Save message to drafts
+    QList<NmOperation *> preliminaryOperations;
+    if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
+        preliminaryOperations.append(mAddAttachmentOperation);
+    }
+    if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
+        preliminaryOperations.append(mRemoveAttachmentOperation);
+    }
+    // ownership of mMessage is transferred
+    // NmOperations are automatically deleted after completion
+    mUiEngine.saveDraftMessage(mMessage, preliminaryOperations);
+    mMessage = NULL;
+    preliminaryOperations.clear();
+}
+
+/*!
+    About to exit view. Application calls this function when user has
+    pressed back key and editor needs to delete the draft message. This is
+    called when "auto-exiting" after a successful mail sending.
+*/
+void NmEditorView::aboutToExitView()
+{
+    NM_FUNCTION;
+    
+    // These operations need to be stopped before message can be deleted
+    if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
+        mAddAttachmentOperation->cancelOperation();
+    }
+    if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
+        mRemoveAttachmentOperation->cancelOperation();
+    }
+
+    if (mMessage) { // this is NULL if sending or saving is started
+        // Delete message from drafts
+        mUiEngine.removeDraftMessage(mMessage);
+        mMessage = NULL;
+    }
+}
+
+/*!
+    Lazy loading when view layout has been loaded
+*/
+void NmEditorView::viewReady()
+{
+    NM_FUNCTION;
+
+    // Set mailbox name to title pane
+    setMailboxName();
+    
+    // Connect options menu about to show to create options menu function
+    // Menu needs to be create "just-in-time"
+    connect(menu(), SIGNAL(aboutToShow()), this, SLOT(createOptionsMenu()));
+    NmAction *dummy = new NmAction(0);
+    menu()->addAction(dummy);
+
+    mVkbHost = new HbShrinkingVkbHost(this);
+    
+    initializeVKB();
+    
+    //start to listen VKB open and close signals for hiding the chrome.
+    connect(mVkbHost, SIGNAL(keypadOpened()), this, SLOT(vkbOpened()));
+    connect(mVkbHost, SIGNAL(keypadClosed()), this, SLOT(vkbClosed()));
+    
+    connect(mContent->header(), SIGNAL(recipientFieldsHaveContent(bool)),
+            this, SLOT(setButtonsDimming(bool)) );
+
+    // Connect to observe orientation change events
+    connect(mApplication.mainWindow(), SIGNAL(orientationChanged(Qt::Orientation)),
+            this, SLOT(orientationChanged(Qt::Orientation)));
+    // Signal for handling the attachment list selection
+    connect(mHeaderWidget, SIGNAL(attachmentShortPressed(NmId)),
+            this, SLOT(openAttachmentTriggered(NmId)));
+    connect(mHeaderWidget, SIGNAL(attachmentLongPressed(NmId, QPointF)),
+            this, SLOT(attachmentLongPressed(NmId, QPointF)));
+    
+    if (mStartParam) {
+        fetchMessageIfNeeded(*mStartParam);
+    }
+    else { // execution cannot proceed without start param 
+        QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
+    }
+    
+    // Adjust the header width according to the current screen width.
+    mHeaderWidget->adjustHeaderWidth(); 
+}
+
+/*!
+    If entering editor for forwarding or replying, use attachment manager
+    to check that we have all message parts fetched. Also show dialog for
+    fetching progress.
+*/
+void NmEditorView::fetchMessageIfNeeded(NmUiStartParam &startParam)
+{
+    NM_FUNCTION;
+    
+    if (startParam.editorStartMode() == NmUiEditorForward
+        || startParam.editorStartMode()== NmUiEditorReply
+        || startParam.editorStartMode() == NmUiEditorReplyAll) {
+    
+        fetchProgressDialogShow();
+        mAttaManager.clearObserver();
+        mAttaManager.setObserver(this);
+        mAttaManager.fetchAllMessageParts(
+            startParam.mailboxId(),
+            startParam.folderId(),
+            startParam.messageId());
+    }
+    else {
+        startMessageCreation(startParam);
+    }
+}
+
+/*!
+    Slot. Called when attachments fetch progress changes.
+*/
+void NmEditorView::progressChanged(int value)
+{
+    NM_FUNCTION;
+    
+    Q_UNUSED(value);
+}
+
+/*!
+    Slot. Called when attachments fetch is completed. We can start
+    message creation. 
+*/
+void NmEditorView::fetchCompleted(int result)
+{
+    NM_FUNCTION;
+    
+    if (result == NmNoError && mStartParam) {
+        startMessageCreation(*mStartParam);
+    }
+    else {
+        // Close "Loading mail content" dialog
+        mWaitDialog->close();
+        
+        // Show a fetching failed note when the failure is not caused by a Device/System failure.
+        if (result != NmNoError && 
+            result != NmNotFoundError &&
+            result != NmGeneralError &&
+            result != NmCancelError &&
+            result != NmAuthenticationError &&
+            result != NmServerConnectionError &&
+            result != NmConnectionError) {         
+            HbNotificationDialog *note = new HbNotificationDialog();            
+            bool enalbeAttribute(true);
+            note->setAttribute(Qt::WA_DeleteOnClose, enalbeAttribute);           
+            note->setIcon(HbIcon(QLatin1String("note_warning")));        
+            note->setTitle(hbTrId("txt_mail_dpopinfo_loading_failed"));
+            note->setTitleTextWrapping(Hb::TextWordWrap);      
+            note->setDismissPolicy(HbNotificationDialog::TapAnywhere);
+            note->setTimeout(HbNotificationDialog::StandardTimeout);       
+            note->setSequentialShow(true);
+            note->show();
+        }
+        
+        // Go back to Viewer view
+        QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
+    }
+}
+
+void NmEditorView::fetchProgressDialogShow()
+{
+    NM_FUNCTION;
+    
+    delete mWaitDialog;
+    mWaitDialog = NULL;
+    // Create new wait dialog and set it to me modal with dimmed background
+    mWaitDialog = new HbProgressDialog(HbProgressDialog::WaitDialog);
+    mWaitDialog->setModal(true);
+    mWaitDialog->setBackgroundFaded(true);
+    connect(mWaitDialog, SIGNAL(cancelled()), this, SLOT(fetchProgressDialogCancelled()));
+    mWaitDialog->setText(hbTrId("txt_mail_dialog_loading_mail_content"));
+    // Display wait dialog
+    mWaitDialog->show();
+}
+
+/*!
+    This is called by mFetchProgressDialog when the note is cancelled
+ */
+void NmEditorView::fetchProgressDialogCancelled()
+{
+    NM_FUNCTION;
+    
+    if (mAttaManager.isFetching()) { 
+        mAttaManager.cancelFetch();
+        mAttaManager.clearObserver();
+    }
+    else {   
+        // For those email has no attachment or attachment has fetched.
+        // Go back to Viewer view.
+        QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
+    }
+}
+
+void NmEditorView::startMessageCreation(NmUiStartParam &startParam)
+{
+    NM_FUNCTION;
+    
+    NmUiEditorStartMode startMode = startParam.editorStartMode();
+    NmId mailboxId = startParam.mailboxId();
+    NmId folderId = startParam.folderId();
+    NmId msgId = startParam.messageId();
+    
+    if (mMessageCreationOperation && mMessageCreationOperation->isRunning()) {
+        mMessageCreationOperation->cancelOperation();
+    }
+	  
+    // original message is now fetched so start message creation
+    if (startMode == NmUiEditorForward) {
+        mMessageCreationOperation = mUiEngine.createForwardMessage(mailboxId, msgId);
+    }
+    else if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll) {
+        mMessageCreationOperation = mUiEngine.createReplyMessage(mailboxId, 
+            msgId, 
+            startMode == NmUiEditorReplyAll);
+    }
+    else if (startMode == NmUiEditorFromDrafts) {
+        // Draft opened, so reload message and fill editor with message data.
+        mMessage = mUiEngine.message(
+            mStartParam->mailboxId(), 
+            mStartParam->folderId(), 
+            mStartParam->messageId());
+        fillEditorWithMessageContents();
+    }
+    else {
+        mMessageCreationOperation = mUiEngine.createNewMessage(mailboxId);
+    }
+    
+    // operation continues in messageCreated() once it finishes ok
+    if (mMessageCreationOperation) {
+        connect(mMessageCreationOperation,
+                SIGNAL(operationCompleted(int)),
+                this,
+                SLOT(messageCreated(int)));
+    }    
+}
+
+/*!
+    Starting the message sending is handled here.
+*/
+void NmEditorView::startSending()
+{
+    NM_FUNCTION;
+    
+    // The message contents should be verified
+    updateMessageWithEditorContents();
+    
+    // verify addresses before sending
+    QList<NmAddress> invalidAddresses;
+    if (mMessage) {
+        NmUtilities::getRecipientsFromMessage(*mMessage, invalidAddresses, NmUtilities::NmInvalidAddress);
+    }
+    
+    if (invalidAddresses.count() > 0) {
+        
+        // Invalid addresses found, verify send from user.
+        // Set the first failing address to the note.
+        QString noteText = 
+            HbParameterLengthLimiter(
+                "txt_mail_dialog_invalid_mail_address_send"
+                ).arg(invalidAddresses.at(0).address());
+        
+        if (mQueryDialog) {
+            delete mQueryDialog;
+            mQueryDialog = 0;
+        }
+        // Launch query dialog. Pressing "yes" will finalize the sending.
+        mQueryDialog = NmUtilities::displayQuestionNote(noteText,
+                                                        this,
+                                                        SLOT(invalidAddressQuery(HbAction*)));
+    }
+    else {
+        // no need to ask anything, just send
+        finalizeSending();
+    }
+}
+
+/*!
+    Send the message after all checks have been done.
+*/
+void NmEditorView::finalizeSending()
+{
+    NM_FUNCTION;
+    
+    QList<NmOperation *> preliminaryOperations;
+    if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
+        preliminaryOperations.append(mAddAttachmentOperation);
+    }
+    if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
+        preliminaryOperations.append(mRemoveAttachmentOperation);
+    }
+    // ownership of mMessage is transferred
+    // NmOperations are automatically deleted after completion
+    mUiEngine.sendMessage(mMessage, preliminaryOperations);
+    mMessage = NULL;
+    preliminaryOperations.clear();
+
+    bool service = XQServiceUtil::isService();
+
+    // If sending is started as a service, progress dialog needs to be shown
+    // so long that sending is finished otherwise we can close pop current view.
+    if (service && mStartParam && mStartParam->service() && 
+        mUiEngine.isSendingMessage()) {
+        connect(&mUiEngine, SIGNAL(sendOperationCompleted()),
+            this, SLOT(handleSendOperationCompleted()), Qt::UniqueConnection);
+
+        // Construct and setup the wait dialog.
+        mServiceSendingDialog = new HbProgressDialog(HbProgressDialog::WaitDialog);
+        mServiceSendingDialog->setAttribute(Qt::WA_DeleteOnClose);
+        mServiceSendingDialog->setText(hbTrId("txt_mail_shareui_sending_please_wait"));
+        connect(mServiceSendingDialog, SIGNAL(cancelled()),
+            this, SLOT(sendProgressDialogCancelled()));
+
+        if (!XQServiceUtil::isEmbedded()) {
+            // Hide the application.
+            XQServiceUtil::toBackground(true);
+        }
+         // Display the wait dialog.
+         mServiceSendingDialog->setModal(true);
+         mServiceSendingDialog->setBackgroundFaded(true);
+         mServiceSendingDialog->show();
+    } else {
+        // Must use delayed editor view destruction so that query dialog
+        // (which has signaled this) gets time to complete.
+        QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
+    }
+}
+
+/*!
+    Handle the user selection for invalid address query which was started by startSending.
+*/
+void NmEditorView::invalidAddressQuery(HbAction* action)
+{
+    NM_FUNCTION;
+
+    HbMessageBox *dlg = static_cast<HbMessageBox*>(sender());
+    // The first action in dialogs action list is for the "Yes"-button.
+    if (action == dlg->actions().at(0)) {
+        finalizeSending();
+    }
+}
+
+/*!
+    This is called when the view's geometry size has been changed, eg. when VKB is opened/closed.
+*/
+void NmEditorView::resizeEvent(QGraphicsSceneResizeEvent *event)
+{
+    NM_FUNCTION;
+    
+    NmBaseView::resizeEvent(event);
+    
+    emit sizeChanged();
+}
+
+/*!
+    This is signalled by mMessageCreationOperation when message is created.
+*/
+void NmEditorView::messageCreated(int result)
+{
+    NM_FUNCTION;
+    
+    delete mMessage;
+    mMessage = NULL;
+
+    // Close wait dialog here
+    if (mWaitDialog) {
+        mWaitDialog->close();
+    }
+    
+    if (result == NmNoError && mStartParam && mMessageCreationOperation) {
+        NmUiEditorStartMode startMode = mStartParam->editorStartMode();
+        
+        // get message "again" from engine to update the message contents 
+        mMessage = mUiEngine.message(
+            mStartParam->mailboxId(), 
+            mStartParam->folderId(), 
+            mMessageCreationOperation->getMessageId());
+        
+        fillEditorWithMessageContents();       
+    }
+}
+
+/*!
+   Updates the message with the editor contents.
+*/
+void NmEditorView::updateMessageWithEditorContents()
+{
+    NM_FUNCTION;
+    
+    if (mMessage) {
+        if (mContent && mContent->editor()) {
+            NmMessagePart* bodyPart = mMessage->htmlBodyPart();
+            if (bodyPart) {
+                bodyPart->setTextContent(mContent->editor()->toHtml(), NmContentTypeTextHtml);
+            }
+            bodyPart = mMessage->plainTextBodyPart();
+            if (bodyPart) {
+                bodyPart->setTextContent(mContent->editor()->toPlainText(), NmContentTypeTextPlain);
+            }
+        }
+        if (mContent && mContent->header() ) {
+            if (mContent->header()->subjectEdit()) {
+                mMessage->envelope().setSubject(
+                    mContent->header()->subjectEdit()->text());
+            }
+            if (mContent->header()->toEdit()) {
+                QString toFieldText =
+                    mContent->header()->toEdit()->text();
+
+                // This verification of zero length string isn't needed
+                // after list of addresses
+                if (toFieldText.length() > 0) {
+                    mMessage->envelope().setToRecipients(mContent->header()->toEdit()->emailAddressList());  
+                }
+            }
+            if (mContent->header()->ccEdit()) {
+                QString ccFieldText =
+                    mContent->header()->ccEdit()->text();
+
+                if (ccFieldText.length() > 0) {
+                    mMessage->envelope().setCcRecipients(mContent->header()->ccEdit()->emailAddressList());      
+                }
+            }
+            if (mContent->header()->bccEdit()) {
+                QString bccFieldText =
+                    mContent->header()->bccEdit()->text();
+
+                if (bccFieldText.length() > 0) {
+                    mMessage->envelope().setBccRecipients(mContent->header()->bccEdit()->emailAddressList());  
+                }
+            }
+        }
+    }
+}
+
+
+/*!
+    Updates the message with the editor contents. Called only once when the
+    editor is launched.
+*/
+void NmEditorView::fillEditorWithMessageContents()
+{
+    NM_FUNCTION;
+    
+    if (!mStartParam || !mMessage || !mContent) {
+        return;
+    }
+
+    NmMessageEnvelope messageEnvelope(mMessage->envelope());
+    bool useStartParam(false);
+
+    NmUiEditorStartMode editorStartMode = mStartParam->editorStartMode();
+
+    if (editorStartMode == NmUiEditorMailto) {
+        // Retrieve the message header data e.g. recipients from mStartParam.
+        useStartParam = true;        
+    }
+    
+    // Set recipients (to, cc and bcc).
+    QString toAddressesString;
+    QString ccAddressesString;
+    QString bccAddressesString;
+
+    if (useStartParam) {
+        toAddressesString = addressListToString(mStartParam->mailtoAddressList());
+        ccAddressesString = addressListToString(mStartParam->ccAddressList());
+        bccAddressesString = addressListToString(mStartParam->bccAddressList());
+    }
+    else {
+        toAddressesString = addressListToString(messageEnvelope.toRecipients());
+        ccAddressesString = addressListToString(messageEnvelope.ccRecipients());
+        bccAddressesString = addressListToString(messageEnvelope.bccRecipients());
+    }
+
+    mContent->header()->toEdit()->setPlainText(toAddressesString);
+    mContent->header()->ccEdit()->setPlainText(ccAddressesString);
+    mContent->header()->bccEdit()->setPlainText(bccAddressesString);
+
+    if (ccAddressesString.length() || bccAddressesString.length()) {
+        // Since cc or/and bcc recipients exist, expand the group box to display
+        // the addresses by expanding the group box.
+        mCcBccFieldVisible = true;
+        mHeaderWidget->setFieldVisibility(mCcBccFieldVisible);
+    }
+
+    // Set subject.
+    if (useStartParam) {
+        QString *subject = mStartParam->subject();
+
+        if (subject) {
+            mContent->header()->subjectEdit()->setPlainText(*subject);
+        }
+    }
+    else {
+        // Construct the subject field.
+        mContent->header()->subjectEdit()->setPlainText(
+            addSubjectPrefix(editorStartMode, messageEnvelope.subject()));
+    }
+
+    // Set priority.
+    if (editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll) {
+        //Clear the importance flag. Replied messages dont keep the importance
+        setPriority(NmActionResponseCommandNone);
+    }
+    mHeaderWidget->setPriority(messageEnvelope.priority());
+    
+    NmMessage *originalMessage = NULL;
+    
+    // Set the message body.
+    if (editorStartMode==NmUiEditorReply||
+        editorStartMode==NmUiEditorReplyAll||
+        editorStartMode==NmUiEditorForward||
+        editorStartMode==NmUiEditorFromDrafts){
+
+        // Use the body from the original message.
+        originalMessage = mUiEngine.message(mStartParam->mailboxId(), 
+                                            mStartParam->folderId(), 
+                                            mStartParam->messageId());
+
+        if (originalMessage) {
+            NmMessagePart *plainPart = originalMessage->plainTextBodyPart();
+
+            if (plainPart) {
+                mUiEngine.contentToMessagePart(originalMessage->envelope().mailboxId(),
+                                               originalMessage->envelope().folderId(),
+                                               originalMessage->envelope().messageId(),
+                                               *plainPart);
+            }
+
+            NmMessagePart *htmlPart = originalMessage->htmlBodyPart();
+
+            if (htmlPart) {
+                mUiEngine.contentToMessagePart(originalMessage->envelope().mailboxId(),
+                                               originalMessage->envelope().folderId(),
+                                               originalMessage->envelope().messageId(),
+                                               *htmlPart);
+            }
+
+        }
+
+    }
+    
+    QString *signature = NULL;
+    // return value is not relevant here
+    mUiEngine.getSignature(mStartParam->mailboxId(), signature);
+    
+    mContent->setBodyContent(editorStartMode, originalMessage, signature);
+
+    delete signature;
+    signature = NULL;
+
+    delete originalMessage;
+    originalMessage = NULL;
+
+    // Get list of attachments from the message and set those into UI attachment list
+    QList<NmMessagePart*> attachments;
+    mMessage->attachmentList(attachments);
+
+    for (int i=0; i<attachments.count(); i++) {
+        mHeaderWidget->addAttachment(
+            attachments[i]->attachmentName(),
+            QString::number(attachments[i]->size()),
+            attachments[i]->partId());
+    }
+
+    // Attach passed files to the message.
+    QStringList *fileList = mStartParam->attachmentList();
+
+    if (fileList) {
+        addAttachments(*fileList);
+    }
+
+}
+
+
+/*!
+    createToolBar. Function asks menu commands from extension
+    to be added to toolbar owned by the HbView.
+*/
+void NmEditorView::createToolBar()
+{
+    NM_FUNCTION;
+    
+    HbToolBar *tb = toolBar();
+    NmUiExtensionManager &extMngr = mApplication.extManager();
+    if (tb && &extMngr && mStartParam) {
+        tb->clearActions();
+        NmActionRequest request(this, NmActionToolbar, NmActionContextViewEditor,
+                NmActionContextDataNone, mStartParam->mailboxId(), mStartParam->folderId() );
+        QList<NmAction *> list;
+        extMngr.getActions(request, list);
+        for (int i = 0; i < list.count(); i++) {
+            tb->addAction(list[i]);
+            // If action has NmSendable condition, it is shown only when send action
+            // is available, i.e. when at least one recipient field has data.
+            if( list[i]->availabilityCondition() == NmAction::NmSendable ) {
+                list[i]->setEnabled(false);
+            }
+            else if (list[i]->availabilityCondition() == NmAction::NmAttachable) {
+                HbToolBarExtension* extension = new HbToolBarExtension();
+                mAttachmentPicker = new NmAttachmentPicker(this);
+                
+                if (extension && mAttachmentPicker) {
+                    connect(mAttachmentPicker, SIGNAL(attachmentsFetchOk(const QVariant &)),
+                        this, SLOT(onAttachmentReqCompleted(const QVariant &)));
+                    
+                    connect(this, SIGNAL(titleChanged(QString)), mAttachmentPicker,
+                        SLOT(setTitle(QString)));
+
+                    list[i]->setToolBarExtension(extension);
+                    
+                    //content widget to get the items to a list
+                    mTBExtnContentWidget = new HbListWidget();
+                    mTBExtnContentWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+                    
+                    mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_photo"));
+                    mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_music"));
+                    mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_video"));
+                    mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_other"));
+                    mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_new_photo"));
+                    mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_new_video"));
+                    HbListViewItem *listView = mTBExtnContentWidget->listItemPrototype();
+                    HbFrameBackground frame(NmPopupListFrame, HbFrameDrawer::NinePieces);
+                    listView->setDefaultFrame(frame);
+                    
+                    connect(mTBExtnContentWidget, SIGNAL(activated(HbListWidgetItem*)), 
+                    		mAttachmentPicker, SLOT (selectFetcher(HbListWidgetItem*)));
+            
+                    connect(mTBExtnContentWidget, SIGNAL(activated(HbListWidgetItem*)),
+                            extension, SLOT(close()));
+                                        
+                    extension->setContentWidget(mTBExtnContentWidget);
+                }
+            }            
+        }        
+    }
+}
+
+/*!
+    createOptionsMenu. Functions asks menu commands from extension
+    to be added to options menu.
+*/
+void NmEditorView::createOptionsMenu()
+{
+    NM_FUNCTION;
+    
+    menu()->clearActions();
+
+	// Create CC/BCC options menu object
+    if (mCcBccFieldVisible) {
+        menu()->addAction(hbTrId("txt_mail_opt_hide_cc_bcc"), this, SLOT(switchCcBccFieldVisibility()));
+    }
+    else {
+        menu()->addAction(hbTrId("txt_mail_opt_show_cc_bcc"), this, SLOT(switchCcBccFieldVisibility()));
+    }
+
+	// Create Priority options menu object
+	if (!mPrioritySubMenu) {
+        mPrioritySubMenu = new HbMenu();
+    }
+    mPrioritySubMenu->clearActions();
+    NmActionRequest request(this, NmActionOptionsMenu, NmActionContextViewEditor,
+            NmActionContextDataMessage, mStartParam->mailboxId(), mStartParam->folderId(),
+            mStartParam->messageId());
+    NmUiExtensionManager &extMngr = mApplication.extManager();
+    QList<NmAction*> list;
+    extMngr.getActions(request, list);
+    for (int i = 0; i < list.count(); i++) {
+        // check what priority has already been selected and hide it from options menu
+        if (!list[i]->objectName().contains(mHiddenPriorityName)) {
+            mPrioritySubMenu->addAction(list[i]);
+        }
+    }
+    mPrioritySubMenu->setObjectName("editorPrioritySubMenu");
+    mPrioritySubMenu->setTitle(hbTrId("txt_mail_opt_add_priority"));
+    menu()->addMenu(mPrioritySubMenu);
+}
+
+/*!
+    Show or hide Cc field
+*/
+void NmEditorView::switchCcBccFieldVisibility()
+{
+    NM_FUNCTION;
+    
+    if (mCcBccFieldVisible) {
+    	mCcBccFieldVisible = false;
+    }
+    else {
+    	mCcBccFieldVisible = true;
+    }
+    mHeaderWidget->setFieldVisibility( mCcBccFieldVisible );
+}
+
+/*!
+    handleActionCommand. From NmActionObserver, extension manager calls this
+    call to handle menu command in the UI.
+*/
+void NmEditorView::handleActionCommand(NmActionResponse &actionResponse)
+{
+    NM_FUNCTION;
+    
+    NmActionResponseCommand responseCommand = actionResponse.responseCommand();
+    
+    // Handle options menu
+    if (actionResponse.menuType() == NmActionOptionsMenu) {
+        setPriority(responseCommand);
+    }
+    else if (actionResponse.menuType() == NmActionToolbar) {
+        switch (responseCommand) {
+        case NmActionResponseCommandSendMail: {
+            // Just in case send mail would be somehow accessible during message creation or
+            // outobox checking
+            if (!mMessageCreationOperation || !mMessageCreationOperation->isRunning()) {
+                startSending();
+            }
+            break;
+        }
+        default:
+            break;
+        }
+    }
+    else if (actionResponse.menuType() == NmActionContextMenu) {
+        switch (responseCommand) {
+        case NmActionResponseCommandRemoveAttachment: {
+            removeAttachmentTriggered();
+            break;
+        }
+        case NmActionResponseCommandOpenAttachment: {
+            openAttachmentTriggered(mSelectedAttachment);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+}
+
+/*!
+    Slot. Cancelled sending progress dialog.
+*/
+void NmEditorView::sendProgressDialogCancelled()
+{
+    // Must use delayed editor view destruction so that dialog
+    // gets time to complete, closes also nmail.
+    QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
+}
+
+/*!
+   Sets all toolbar and VKB buttons dimmed state. All actions that have the
+   availability condition NmSendable set, will be enabled/disabled.
+*/
+void NmEditorView::setButtonsDimming(bool enabled)
+{
+    NM_FUNCTION;
+    
+    // Set the toolbar action states
+    HbToolBar *tb = toolBar();
+    if (tb) {
+        QList<QAction *> toolbarList = tb->actions();
+        int count = toolbarList.count();
+        for (int i = 0; i < count; i++) {
+            NmAction *action = static_cast<NmAction *>(toolbarList[i]);
+            if (action->availabilityCondition() == NmAction::NmSendable) {
+                action->setEnabled(enabled);
+            }
+        }
+
+        // Set the VKB action states
+        // All editors of the view share the same action, so it is enough to set
+        // this only to one of them.
+        HbEditorInterface editorInterface(mContent->editor());
+        QList<HbAction *> vkbList = editorInterface.actions();
+        count = vkbList.count();
+        for (int i = 0; i < count; i++) {
+            NmAction *action = static_cast<NmAction *>(vkbList[i]);
+            if (action->availabilityCondition() == NmAction::NmSendable) {
+                action->setEnabled(enabled);
+            }
+        }
+    }
+}
+
+/*!
+    Initialize the Virtual Keyboard to show the "Send" button
+    for all editors of the view.
+*/
+void NmEditorView::initializeVKB()
+{
+    NM_FUNCTION;
+    
+    if (!mStartParam) {
+        return;
+    }
+    
+    NmActionRequest request(this, NmActionVKB, NmActionContextViewEditor,
+         NmActionContextDataNone, mStartParam->mailboxId(), mStartParam->folderId() );
+    NmUiExtensionManager &extMngr = mApplication.extManager();
+    if (&extMngr) {
+        QList<NmAction *> list;
+        extMngr.getActions(request, list);
+
+        // VKB only supports one application key, but the responsibility of giving only one
+        // action is left to the extension plugin. The rest are still attached to the VKB, but
+        // they are not shown (unless VKB starts supporting more than one).
+        for (int i = 0; i < list.count(); i++) {
+            if( list[i]->availabilityCondition() == NmAction::NmSendable ) {
+                list[i]->setEnabled(false);
+            }
+            list[i]->setIcon(NmIcons::getIcon(NmIcons::NmIconSend));
+
+            // Link VKB to the action. This must be done to all
+            // editors that show the button in VKB.
+            HbEditorInterface editorInterface(mContent->editor());
+            editorInterface.addAction(list[i]);
+            HbEditorInterface toEditorInterface(mContent->header()->toEdit());
+            toEditorInterface.addAction(list[i]);
+            HbEditorInterface ccEditorInterface(mContent->header()->ccEdit());
+            ccEditorInterface.addAction(list[i]);
+            HbEditorInterface bccEditorInterface(mContent->header()->bccEdit());
+            bccEditorInterface.addAction(list[i]);
+            HbEditorInterface subjectEditorInterface(mContent->header()->subjectEdit());
+            subjectEditorInterface.addAction(list[i]);
+        }
+    }
+}
+
+/*!
+    Set mailbox name to title
+*/
+void NmEditorView::setMailboxName()
+{
+    NM_FUNCTION;
+    
+    if (mStartParam){
+        NmMailboxMetaData *meta = mUiEngine.mailboxById(mStartParam->mailboxId());
+        if (meta){
+            setTitle(meta->name());
+        }
+    }
+}
+
+/*!
+   Adds a prefix to the subject for reply or forward. 
+   Strips other occurrences of the prefix from the beginning.
+*/
+QString NmEditorView::addSubjectPrefix( NmUiEditorStartMode startMode, const QString &subject )
+{
+    NM_FUNCTION;
+    
+    QString newSubject(subject.trimmed());
+    
+    if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll || 
+        startMode == NmUiEditorForward) {
+        QString rePrefix(hbTrId("txt_nmailui_reply_subject_prefix"));
+        QString fwPrefix(hbTrId("txt_nmailui_forward_subject_prefix"));
+        
+        // strip extra prefixes from beginning
+        int rePrefixLength(rePrefix.length());
+        int fwPrefixLength(fwPrefix.length());
+        
+        bool startswithRe(newSubject.startsWith(rePrefix, Qt::CaseInsensitive));
+        bool startswithFw(newSubject.startsWith(fwPrefix, Qt::CaseInsensitive));
+        
+        while (startswithRe || startswithFw) {            
+            if (startswithRe) {
+                newSubject.remove(0,rePrefixLength);
+                newSubject = newSubject.trimmed();
+            }
+            else if (startswithFw) {
+                newSubject.remove(0,fwPrefixLength);
+                newSubject = newSubject.trimmed();
+            }
+            startswithRe = newSubject.startsWith(rePrefix, Qt::CaseInsensitive);
+            startswithFw = newSubject.startsWith(fwPrefix, Qt::CaseInsensitive);
+        }
+        
+        if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll) {
+            newSubject = rePrefix + " " + newSubject;
+        }
+        else if (startMode == NmUiEditorForward) {
+            newSubject = fwPrefix + " " + newSubject;
+        }
+    }
+    
+    return newSubject;
+}
+
+
+/*!
+    This slot is called when 'attachment picker' request has been performed succesfully
+    Parameter 'value' contains file currently one file name but later list of the files. 
+*/
+void NmEditorView::onAttachmentReqCompleted(const QVariant &value)
+{
+    NM_FUNCTION;
+    
+    //temporary fix for music picker back button:
+    //it shouldn't emit requestOk signal when nothing is selected
+	if (value.canConvert<QStringList>()) {
+	    QStringList list = value.toStringList();
+        if (!list.at(0).isEmpty()) {
+            addAttachments(list);
+        }
+    }
+}
+
+/*!
+    This slot is called when 'attachment picker' request has been unsuccesfull
+    Parameter 'errorCode' is the error code returned by the service
+    Parameter 'errorMessage' is the error message returned by the service
+*/
+void NmEditorView::onAttachmentsFetchError(int errorCode, const QString& errorMessage)
+{
+    NM_FUNCTION;
+    Q_UNUSED(errorCode);
+    Q_UNUSED(errorMessage);
+    NM_COMMENT(QString("Error code: %1").arg(errorCode));
+    NM_COMMENT(QString("Error message: %1").arg(errorMessage));
+}
+
+/*!
+    Closes the wait dialog if one exists.
+    
+    This slot is called if the mail application has been started as a service
+    and is about to close. Closing the application while still sending a message
+    may cause unwanted cancelling of the operation.
+*/
+void NmEditorView::handleSendOperationCompleted()
+{
+    NM_FUNCTION;
+
+    if (mServiceSendingDialog) {
+        mServiceSendingDialog->close();
+    }
+    // Must use delayed editor view destruction so that dialog
+    // gets time to complete, closes also nmail.
+    QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
+}
+
+/*!
+    Add list of attachments
+*/
+void NmEditorView::addAttachments(const QStringList& fileNames) 
+{
+    NM_FUNCTION;
+    
+    // Add attachment name into UI
+    foreach (QString fileName, fileNames)  {
+        // At this phase attachment size and nmid are not known
+        mHeaderWidget->addAttachment(fileName, QString("0"), NmId(0));
+        NM_COMMENT(fileName);
+    }
+    //  Cancel previous operation if it's not running.
+    if (mAddAttachmentOperation) {
+        if (!mAddAttachmentOperation->isRunning()) {
+            mAddAttachmentOperation->cancelOperation();
+        }
+    }
+    // Start operation to attach file or list of files into mail message.
+    // This will also copy files into message store.
+    mAddAttachmentOperation = mUiEngine.addAttachments(*mMessage, fileNames);
+
+    if (mAddAttachmentOperation) {
+        enableToolBarAttach(false);
+        // Signal to inform completion of one attachment
+        connect(mAddAttachmentOperation,
+                SIGNAL(operationPartCompleted(const QString &, const NmId &, int)),
+                this,
+                SLOT(oneAttachmentAdded(const QString &, const NmId &, int)));
+    
+        // Signal to inform the completion of the whole operation
+        connect(mAddAttachmentOperation,
+                SIGNAL(operationCompleted(int)),
+                this,
+                SLOT(allAttachmentsAdded(int)));
+    }
+}
+
+/*!
+    This slot is called to create context menu when attachment has been selected
+    from UI by longpress.
+*/
+void NmEditorView::attachmentLongPressed(NmId attachmentPartId, QPointF point)
+{
+    NM_FUNCTION;
+    
+    // Store id of the attachment to be removed into member.
+    // It is used by removeAttachmentTriggered later if 'remove' selected.
+    mSelectedAttachment = attachmentPartId;
+	
+    if (!mAttachmentListContextMenu) {
+        mAttachmentListContextMenu = new HbMenu();
+    }
+    mAttachmentListContextMenu->clearActions();
+    NmActionRequest request(this, NmActionContextMenu, NmActionContextViewEditor,
+        NmActionContextDataMessage, mStartParam->mailboxId(), mStartParam->folderId(),
+        mStartParam->messageId());
+    NmUiExtensionManager &extensionManager = mApplication.extManager();
+    if (&extensionManager) {
+        QList<NmAction*> actionList;
+        extensionManager.getActions(request, actionList);
+        for (int i = 0; i < actionList.count(); ++i) {
+            mAttachmentListContextMenu->addAction(actionList[i]);
+        }
+    }
+
+    // Add menu position check here, so that it does not go outside of the screen
+    QPointF menuPos(point.x(),point.y());
+    mAttachmentListContextMenu->setPreferredPos(menuPos);
+    mAttachmentListContextMenu->open();
+}
+
+/*!
+    This is signalled by mAddAttachmentOperation when the operation is
+    completed for one attachment.
+*/
+void NmEditorView::oneAttachmentAdded(const QString &fileName, const NmId &msgPartId, int result)
+{
+    NM_FUNCTION;
+    
+    if (result == NmNoError && mMessage) {
+        // Need to get the message again because new attachment part has been added.
+        NmId mailboxId = mMessage->envelope().mailboxId();
+        NmId folderId = mMessage->envelope().folderId();
+        NmId msgId = mMessage->envelope().messageId();
+        NmMessagePriority messagePriority = mMessage->envelope().priority();        
+        
+        delete mMessage;
+        mMessage = NULL;
+        
+        mMessage = mUiEngine.message(mailboxId, folderId, msgId);
+
+        if (mMessage) {
+            mMessage->envelope().setPriority(messagePriority);
+            mMessage->envelope().setHasAttachments(true);
+            // Get attachment list from the message
+            QList<NmMessagePart*> attachmentList;
+            mMessage->attachmentList(attachmentList);
+        
+            // Search newly added attachment from the list
+            for (int i=0; i<attachmentList.count(); i++) {
+                if (attachmentList[i]->partId() == msgPartId) {
+                    // Get attachment file size and set it into UI
+                    mHeaderWidget->setAttachmentParameters(fileName,
+                        msgPartId,
+                        QString().setNum(attachmentList[i]->size()),
+                        result);
+                }
+            }
+        }
+    }
+    else {
+        // Attachment adding failed. Show an error note and remove from UI attachment list.
+        NM_ERROR(1,QString("nmailui: attachment adding into message failed: %1").arg(fileName));
+        mHeaderWidget->removeAttachment(fileName);
+    }
+}
+
+/*!
+    This is signalled by mAddAttachmentOperation when the operation is
+    completed totally.
+*/
+void NmEditorView::allAttachmentsAdded(int result)
+{
+    NM_FUNCTION;
+    
+    enableToolBarAttach(true);
+    if (result != NmNoError) {
+        NmUtilities::displayWarningNote(hbTrId("txt_mail_dialog_unable_to_add_attachment"));
+    }
+}
+
+/*!
+   Sets priority for the message object that is being edited 
+*/
+void NmEditorView::setPriority(NmActionResponseCommand priority)
+{
+    NM_FUNCTION;
+    
+    mHeaderWidget->setPriority(priority);
+
+    if (mMessage) {
+        NmMessagePriority messagePriority = NmMessagePriorityNormal;
+        mHiddenPriorityName = NmPriorityNormal;
+        
+        if (priority == NmActionResponseCommandPriorityHigh) {
+            messagePriority = NmMessagePriorityHigh;
+            mHiddenPriorityName = NmPriorityHigh;
+        }
+        else if (priority == NmActionResponseCommandPriorityLow) {
+            messagePriority = NmMessagePriorityLow;
+            mHiddenPriorityName = NmPriorityLow;
+        }
+        mMessage->envelope().setPriority(messagePriority);
+    }
+}
+
+
+/*!
+    Extracts the addresses from the given list into a string separated with a
+    delimiter.
+
+    \param list The list containing the addresses.
+    \return String containing the addresses.
+*/
+QString NmEditorView::addressListToString(const QList<NmAddress*> &list) const
+{
+    NM_FUNCTION;
+    
+    QString addressesString;
+    QList<NmAddress*>::const_iterator i = list.constBegin();
+    
+    while (i != list.constEnd() && *i) {
+        if (i > list.constBegin()) {
+            // Add the delimiter.
+            addressesString += NmDelimiter;
+        }
+
+        addressesString += (*i)->address();
+        ++i;
+    }
+
+    return addressesString;
+}
+
+
+/*!
+    Extracts the addresses from the given list into a string separated with a
+    delimiter.
+
+    \param list The list containing the addresses.
+    \return String containing the addresses.
+*/
+QString NmEditorView::addressListToString(const QList<NmAddress> &list) const
+{
+    NM_FUNCTION;
+    
+    QString addressesString;
+    QList<NmAddress>::const_iterator i = list.constBegin();
+    
+    while (i != list.constEnd()) {
+        if (i > list.constBegin()) {
+            // Add the delimiter.
+            addressesString += NmDelimiter;
+        }
+
+        addressesString += (*i).address();
+        ++i;
+    }
+
+    return addressesString;
+}
+
+/*!
+    This slot is called when 'remove' is selected from attachment list context menu.
+*/
+void NmEditorView::removeAttachmentTriggered()
+{
+    NM_FUNCTION;
+    
+    // Cancel will delete previous operation
+    if (mRemoveAttachmentOperation) {
+        if (!mRemoveAttachmentOperation->isRunning()) {
+            mRemoveAttachmentOperation->cancelOperation();
+        }
+    }
+    // Remove from UI
+    mHeaderWidget->removeAttachment(mSelectedAttachment);
+    // Remove from message store
+    mRemoveAttachmentOperation = mUiEngine.removeAttachment(*mMessage, mSelectedAttachment);
+    if (mRemoveAttachmentOperation) {
+        // Signal to inform the remove operation completion
+        connect(mRemoveAttachmentOperation,
+                SIGNAL(operationCompleted(int)),
+                this,
+                SLOT(attachmentRemoved(int)));
+    }
+}
+
+/*!
+    This slot is called by mRemoveAttachmentOperation when the operation is
+    completed. There is no need to update UI because it was already updated.
+ */
+void NmEditorView::attachmentRemoved(int result)
+{
+    NM_FUNCTION;
+    
+    // It is not desided yet what to do if operation fails
+    Q_UNUSED(result);
+    
+    if (mMessage) {
+        // Reload message because one attachment has been removed
+        NmId mailboxId = mMessage->envelope().mailboxId();
+        NmId folderId = mMessage->envelope().folderId();
+        NmId msgId = mMessage->envelope().messageId();
+        NmMessagePriority messagePriority = mMessage->envelope().priority();    
+
+        delete mMessage;
+        mMessage = NULL;
+    
+        mMessage = mUiEngine.message(mailboxId, folderId, msgId);
+        
+        if(mMessage) {
+            // Set the correct priority
+            mMessage->envelope().setPriority(messagePriority);    
+            
+            // If there is no more attachments in the message, set the correct value
+            QList<NmMessagePart*> attachmentList;
+            mMessage->attachmentList(attachmentList);
+            if(attachmentList.count() == 0) {
+                mMessage->envelope().setHasAttachments(false);
+            }
+        }
+    }
+}
+
+/*!
+    This slot is called when 'open' is selected from attachment list context menu.
+*/
+void NmEditorView::openAttachmentTriggered(NmId attachmentId)
+{
+    NM_FUNCTION;
+    NmId mailboxId = mMessage->envelope().mailboxId();
+    NmId folderId = mMessage->envelope().folderId();
+    NmId msgId = mMessage->envelope().messageId();
+
+    XQSharableFile file = mUiEngine.messagePartFile(mailboxId, folderId,
+    		msgId, attachmentId);
+    int error = NmUtilities::openFile(file);
+    file.close();
+    if ( error == NmNotFoundError ) {
+        NmUtilities::displayErrorNote(hbTrId("txt_mail_dialog_unable_to_open_attachment_file_ty")); 
+    }
+}
+
+/*!
+   Enables/disables toolbar extension for attach
+*/
+void NmEditorView::enableToolBarAttach(bool enable)
+{
+    NM_FUNCTION;
+    
+    HbToolBar *tb = toolBar();
+    if (tb) {
+        QList<QAction *> toolbarList = tb->actions();
+        int count = toolbarList.count();
+        for (int i = 0; i < count; i++) {
+            NmAction *action = static_cast<NmAction *>(toolbarList[i]);
+            if (action->availabilityCondition() == NmAction::NmAttachable) {
+                action->setEnabled(enable);
+                if (enable) {
+                    // For some reason 'Add attachment' toolbar button stays dimmed sometimes,
+                    // showItems will fix the situation.
+                    showItems(Hb::ToolBarItem);
+                }
+            }
+        }
+    }
+}