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