emailuis/nmailui/src/nmeditorview.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 04 Oct 2010 00:05:37 +0300
changeset 75 47d84de1c893
parent 72 64e38f08e49c
permissions -rw-r--r--
Revision: 201037 Kit: 201039

/*
* 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";
static const char *NMUI_EDITOR_VIEW_ATTACHMENT_EXTENSION =
    "attachmentTypeToolbarExtension";

// 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");

static const QString NmMimeTypeHtml("text/html");


/*!
	\class NmEditorView
	\brief Mail editor view
*/


/*!
    Class 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),
  mTBExtnContentWidget(NULL),
  mHiddenPriorityName(NmPriorityNormal)
{
    NM_FUNCTION;

    mDocumentLoader = new NmUiDocumentLoader(mApplication.mainWindow());

    // Set the object name.
    setObjectName(QString(NMUI_EDITOR_VIEW));

    // Load the view layout.
    loadViewLayout();

    // Create the toolbar.
    createToolBar();
}


/*!
    Class 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;
    }

    if (!mTBExtnContentWidget->parent()) {
        delete mTBExtnContentWidget;
    }
}


/*!
    Loads the view layout from XML.
*/
void NmEditorView::loadViewLayout()
{
    NM_FUNCTION;
    
    mPrioritySubMenu = NULL;

    // Use the document loader to load the 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. The document loader is
    // created in the constructor.
    mDocumentLoader->setObjectTree(objectList);

    bool ok(false);
    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);
           }
       }

       // Get the toolbar extension for adding attachments.
       mTBExtnContentWidget = qobject_cast<HbListWidget *>(
           mDocumentLoader->findWidget(NMUI_EDITOR_VIEW_ATTACHMENT_EXTENSION));

       // 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) {
        setContentFullScreen(false);
        showItems(Hb::ToolBarItem);
    }
    else {
        setContentFullScreen(true);
        hideItems(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;
    NM_TIMESTAMP("Start editor.");
    
    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;
    NM_TIMESTAMP("Editor opened.");
    
    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) {
        QList<NmAddress *> toAddressList = mStartParam->mailtoAddressList();
        QList<NmAddress *> ccAddressList = mStartParam->ccAddressList();
        QList<NmAddress *> bccAddressList = mStartParam->bccAddressList();
        toAddressesString = addressListToString(toAddressList);
        ccAddressesString = addressListToString(ccAddressList);
        bccAddressesString = addressListToString(bccAddressList);
        // Also add recipients added for example from send service 
        // interface to recipient line edits.        
        mContent->header()->toEdit()->addContacts(toAddressList);
        mContent->header()->ccEdit()->addContacts(ccAddressList);
        mContent->header()->bccEdit()->addContacts(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);
    }

    if (mStartParam->bodyText().length()) {
        // If the content is not HTML, use it as plain text
        if (mStartParam->bodyMimeType().compare(NmMimeTypeHtml, Qt::CaseInsensitive)) {
			mContent->editor()->setPlainText(mStartParam->bodyText());
		}
		else {
		    mContent->editor()->setHtml(mStartParam->bodyText());
		}
    }
}


/*!
    Constructs the toolbar according to the actions received from the extension
    manager.
*/
void NmEditorView::createToolBar()
{
    NM_FUNCTION;
    
    HbToolBar *tb = toolBar();
    NmUiExtensionManager &extMngr = mApplication.extManager();

    if (!tb || !mStartParam) {
        return;
    }

    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 &&
                 mTBExtnContentWidget) {
            // Setup the toolbar extension for attachments.
            HbToolBarExtension* extension = new HbToolBarExtension();
            extension->setParent(this);
            list[i]->setToolBarExtension(extension);

            mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_photo"));
            mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_sound"));
            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);
            
            extension->setContentWidget(mTBExtnContentWidget);

            connect(mTBExtnContentWidget, SIGNAL(activated(HbListWidgetItem*)),
                    extension, SLOT(close()));

            mAttachmentPicker = new NmAttachmentPicker(this);
            
            connect(mAttachmentPicker, SIGNAL(attachmentsFetchOk(const QVariant &)),
                    this, SLOT(onAttachmentReqCompleted(const QVariant &)));
            connect(this, SIGNAL(titleChanged(QString)),
                    mAttachmentPicker, SLOT(setTitle(QString)));
            connect(mTBExtnContentWidget, SIGNAL(activated(HbListWidgetItem*)), 
                    mAttachmentPicker, SLOT (selectFetcher(HbListWidgetItem*)));
        }
    } // for ()        
}


/*!
    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_mail_reply_subject_prefix"));
        QString fwPrefix(hbTrId("txt_mail_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;
    NM_TIMESTAMP("Add attachments.");
    
    // 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;
    NM_TIMESTAMP("All attachments added.");
    
    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) {
        // Prioritize display name. Add the delimiter in the end also if
        // address list ends to display name.
        if ((*i)->displayName().length() > 0) {
            addressesString += (*i)->displayName();
            addressesString += NmDelimiter;
        }
        else {
            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 ) {
        HbMessageBox *box = NmUtilities::displayWarningNote(hbTrId("txt_mail_dialog_unable_to_open_attachment_file_ty"));
        box->setAttribute(Qt::WA_DeleteOnClose);
    }
}

/*!
   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);
                }
            }
        }
    }
}