--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/nmailui/src/nmeditorview.cpp Fri Apr 16 14:51:52 2010 +0300
@@ -0,0 +1,1124 @@
+/*
+* 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_SCROLL_AREA = "scrollArea";
+static const char *NMUI_EDITOR_SCROLL_AREA_CONTENTS = "scrollAreaContents";
+
+static const int nmOrientationTimer=100;
+
+static const QString Delimiter("; ");
+#define IMAGE_FETCHER_INTERFACE "Image"
+#define FETCHER_OPERATION "fetch(QVariantMap,QVariant)"
+
+/*!
+ \class NmEditorView
+ \brief Mail editor view
+*/
+
+/*!
+ Constructor
+*/
+NmEditorView::NmEditorView(
+ NmApplication &application,
+ NmUiStartParam* startParam,
+ NmUiEngine &uiEngine,
+ QGraphicsItem *parent)
+: NmBaseView(startParam, parent),
+mApplication(application),
+mUiEngine(uiEngine),
+mDocumentLoader(NULL),
+mScrollArea(NULL),
+mEditWidget(NULL),
+mHeaderWidget(NULL),
+mMessage(NULL),
+mContentWidget(NULL),
+mAttachContextMenu(NULL),
+mMessageCreationOperation(NULL),
+mAddAttachmentOperation(NULL),
+mRemoveAttachmentOperation(NULL),
+mCheckOutboxOperation(NULL)
+{
+ mDocumentLoader = new HbDocumentLoader();
+ // Set object name
+ setObjectName("NmEditorView");
+ // Load view layout
+ loadViewLayout();
+ // Set mailbox name to title pane
+ setMailboxName();
+ // Set message data
+ setMessageData();
+}
+
+/*!
+ Destructor
+*/
+NmEditorView::~NmEditorView()
+{
+ delete mMessageCreationOperation;
+ delete mCheckOutboxOperation;
+
+ delete mMessage;
+
+ mWidgetList.clear();
+ delete mDocumentLoader;
+
+ delete mContentWidget;
+
+ delete mPrioritySubMenu;
+ delete mAttachContextMenu;
+}
+
+/*!
+ View layout loading from XML
+*/
+void NmEditorView::loadViewLayout()
+{
+ mPrioritySubMenu = NULL;
+
+ // Use document loader to load the view
+ bool ok = false;
+ mWidgetList = mDocumentLoader->load(NMUI_EDITOR_VIEW_XML, &ok);
+
+ if (ok == true && mWidgetList.count()) {
+ // Set view
+ QGraphicsWidget *view = mDocumentLoader->findWidget(NMUI_EDITOR_VIEW);
+ if (view){
+ setWidget(view);
+ }
+
+ mScrollArea = qobject_cast<NmBaseViewScrollArea *>
+ (mDocumentLoader->findObject(NMUI_EDITOR_SCROLL_AREA));
+ mScrollAreaContents = qobject_cast<HbWidget *>
+ (mDocumentLoader->findObject(NMUI_EDITOR_SCROLL_AREA_CONTENTS));
+
+ mContentWidget = new NmEditorContent(mScrollArea, this, mDocumentLoader);
+ mEditWidget = mContentWidget->editor();
+ mHeaderWidget = mContentWidget->header();
+
+ // Set default color for user - entered text if editor is in re/reAll/fw mode
+ NmUiEditorStartMode mode = mStartParam->editorStartMode();
+ if (mode == NmUiEditorReply || mode == NmUiEditorReplyAll || mode == NmUiEditorForward) {
+ mEditWidget->setCustomTextColor(true, Qt::blue);
+ }
+ }
+
+ // Connect signals from background scroll area
+ connect(mScrollArea, SIGNAL(handleMousePressEvent(QGraphicsSceneMouseEvent*)),
+ this, SLOT(sendMousePressEventToScroll(QGraphicsSceneMouseEvent*)));
+ connect(mScrollArea, SIGNAL(handleMouseReleaseEvent(QGraphicsSceneMouseEvent*)),
+ this, SLOT(sendMouseReleaseEventToScroll(QGraphicsSceneMouseEvent*)));
+ connect(mScrollArea, SIGNAL(handleMouseMoveEvent(QGraphicsSceneMouseEvent*)),
+ this, SLOT(sendMouseMoveEventToScroll(QGraphicsSceneMouseEvent*)));
+
+ connect(mScrollArea, SIGNAL(handleLongPressGesture(const QPointF &)),
+ this, SLOT(sendLongPressGesture(const QPointF &)));
+
+ // 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);
+
+ initializeVKB();
+ connect(mContentWidget->header(), SIGNAL(recipientFieldsHaveContent(bool)),
+ this, SLOT(setButtonsDimming(bool)) );
+
+ // call the createToolBar on load view layout
+ createToolBar();
+
+ // Set dimensions
+ adjustViewDimensions();
+
+ // 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(attachmentRemoved(const NmId)),
+ this, SLOT(removeAttachment(const NmId)));
+}
+
+/*!
+ 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)
+{
+ // 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
+ setMessageData();
+ }
+ else {
+ NMLOG("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)
+{
+ Q_UNUSED(orientation);
+ // Adjust content height
+ QTimer::singleShot(nmOrientationTimer, this, SLOT(adjustViewDimensions()));
+}
+
+/*!
+ Set new dimensions after orientation change.
+*/
+void NmEditorView::adjustViewDimensions()
+{
+ if (mScrollAreaContents) {
+ const QSize reso = mApplication.screenSize();
+ mScrollAreaContents->setMinimumWidth(reso.width());
+ mScrollAreaContents->setMaximumWidth(reso.width());
+ }
+}
+
+/*!
+ View id
+*/
+NmUiViewId NmEditorView::nmailViewId() const
+{
+ return NmUiViewMessageEditor;
+}
+
+/*!
+ ScrollArea contents
+*/
+HbWidget* NmEditorView::scrollAreaContents()
+{
+ return mScrollAreaContents;
+}
+
+/*
+ Query user if we want to exit the editor
+ */
+bool NmEditorView::okToExitView()
+{
+ bool okToExit = true;
+
+ // show the query if the message has not been sent
+ if (mMessage && mContentWidget->header()) {
+ // see if editor has any content
+ NmEditorHeader *header = mContentWidget->header();
+
+ int toTextLength = 0;
+ if (header->toField()) {
+ toTextLength = header->toField()->text().length();
+ }
+
+ int ccTextLength = 0;
+ if (header->ccField()) {
+ ccTextLength = header->ccField()->text().length();
+ }
+
+ int bccTextLength = 0;
+ if (header->bccField()) {
+ bccTextLength = header->bccField()->text().length();
+ }
+
+ int subjectLength = 0;
+ if (header->subjectField()) {
+ subjectLength = header->subjectField()->text().length();
+ }
+
+ okToExit = (toTextLength == 0 && ccTextLength == 0 && bccTextLength == 0 &&
+ subjectLength == 0 && mContentWidget->editor()->document()->isEmpty());
+
+ // content exists, verify exit from user
+ if (!okToExit) {
+ HbMessageBox *messageBox = new HbMessageBox(HbMessageBox::MessageTypeQuestion);
+ messageBox->setText(hbTrId("txt_mail_dialog_delete_message"));
+ messageBox->setTimeout(HbMessageBox::NoTimeout);
+
+ // Read user selection
+ HbAction *action = messageBox->exec();
+ okToExit = (action == messageBox->primaryAction());
+ }
+ }
+
+ return okToExit;
+}
+
+/*!
+ 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()
+{
+ // These operations need to be stopped before message can be deleted
+ delete mAddAttachmentOperation;
+ delete mRemoveAttachmentOperation;
+
+ if (mMessage) { // this is NULL if sending is started
+ // Delete message from drafts
+ NmId mailboxId = mMessage->mailboxId();
+ NmId folderId = mMessage->parentId();
+ NmId msgId = mMessage->envelope().id();
+ mUiEngine.removeMessage(mailboxId, folderId, msgId);
+ }
+}
+
+/*!
+ Find message data based on start parameters. Method is called
+ when editor is started. If message data is found it means that
+ operation is forward or reply message.
+ */
+void NmEditorView::setMessageData()
+{
+ // Check the outbox.
+ delete mCheckOutboxOperation;
+ mCheckOutboxOperation = NULL;
+
+ mCheckOutboxOperation = mUiEngine.checkOutbox(mStartParam->mailboxId());
+
+ if (mCheckOutboxOperation) {
+ connect(mCheckOutboxOperation, SIGNAL(operationCompleted(int)),
+ this, SLOT(outboxChecked(int)));
+ }
+ else {
+ startMessageCreation( mStartParam->editorStartMode() );
+ }
+}
+
+/*!
+ */
+void NmEditorView::startMessageCreation(NmUiEditorStartMode startMode)
+{
+ NmId mailboxId = mStartParam->mailboxId();
+ NmId folderId = mStartParam->folderId();
+ NmId msgId = mStartParam->messageId();
+
+ delete mMessageCreationOperation;
+ mMessageCreationOperation = NULL;
+
+ // 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 {
+ 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()
+{
+ // The message contents should be verified
+ updateMessageWithEditorContents();
+
+ // verify addresses before sending
+ QList<NmAddress> invalidAddresses;
+ NmUtilities::getRecipientsFromMessage(*mMessage, invalidAddresses, NmUtilities::InvalidAddress);
+
+ bool okToSend = true;
+ if (invalidAddresses.count() > 0) {
+
+ // invalid addresses found, verify send from user
+ HbMessageBox *messageBox = new HbMessageBox(HbMessageBox::MessageTypeQuestion);
+ QString noteText = hbTrId("txt_mail_dialog_invalid_mail_address_send");
+ // set the first failing address to the note
+ noteText = noteText.arg(invalidAddresses.at(0).address());
+ messageBox->setText(noteText);
+ messageBox->setTimeout(HbMessageBox::NoTimeout);
+
+ // Read user selection
+ HbAction *action = messageBox->exec();
+ okToSend = (action == messageBox->primaryAction());
+ }
+
+ if (okToSend) {
+ // ownership of mMessage changes
+ mUiEngine.sendMessage(mMessage);
+ mMessage = NULL;
+ // sending animation should be shown here, then exit
+ QTimer::singleShot(1000, &mApplication, SLOT(popView()));
+ }
+}
+
+/*!
+ This is signalled by mMessageCreationOperation when message is created.
+ */
+void NmEditorView::messageCreated(int result)
+{
+ delete mMessage;
+ mMessage = NULL;
+
+ if (result == NmNoError && 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()
+{
+ if (mMessage) {
+ if (mContentWidget && mContentWidget->editor()) {
+ NmMessagePart* bodyPart = mMessage->htmlBodyPart();
+ if (bodyPart) {
+ bodyPart->setTextContent(mContentWidget->editor()->toHtml(), NmContentTypeTextHtml);
+ }
+ bodyPart = mMessage->plainTextBodyPart();
+ if (bodyPart) {
+ bodyPart->setTextContent(mContentWidget->editor()->toPlainText(), NmContentTypeTextPlain);
+ }
+ }
+ if (mContentWidget && mContentWidget->header() ) {
+ if (mContentWidget->header()->subjectField()) {
+ mMessage->envelope().setSubject(
+ mContentWidget->header()->subjectField()->text());
+ }
+ if (mContentWidget->header()->toField()) {
+ QString toFieldText =
+ mContentWidget->header()->toField()->text();
+
+ // This verification of zero length string isn't needed
+ // after list of addresses
+ if (toFieldText.length() > 0) {
+ mMessage->envelope().setToRecipients(mContentWidget->header()->toField()->emailAddressList());
+ }
+ }
+ if (mContentWidget->header()->ccField()) {
+ QString ccFieldText =
+ mContentWidget->header()->ccField()->text();
+
+ if (ccFieldText.length() > 0) {
+ mMessage->envelope().setCcRecipients(mContentWidget->header()->ccField()->emailAddressList());
+ }
+ }
+ if (mContentWidget->header()->bccField()) {
+ QString bccFieldText =
+ mContentWidget->header()->bccField()->text();
+
+ if (bccFieldText.length() > 0) {
+ mMessage->envelope().setBccRecipients(mContentWidget->header()->bccField()->emailAddressList());
+ }
+ }
+ }
+ }
+}
+
+
+/*!
+ Updates the message with the editor contents. Called only once when the
+ editor is launched.
+ */
+void NmEditorView::fillEditorWithMessageContents()
+{
+ if (!mMessage || !mContentWidget) {
+ return;
+ }
+
+ NmMessageEnvelope messageEnvelope(mMessage->envelope());
+ NmUiEditorStartMode editorStartMode = NmUiEditorCreateNew;
+ bool useStartParam(false);
+
+ if (mStartParam) {
+ 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());
+ }
+
+ mContentWidget->header()->toField()->setPlainText(toAddressesString);
+ mContentWidget->header()->ccField()->setPlainText(ccAddressesString);
+ mContentWidget->header()->bccField()->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.
+ mContentWidget->header()->setGroupBoxCollapsed(false);
+ }
+
+ // Set subject.
+ if (useStartParam) {
+ QString *subject = mStartParam->subject();
+
+ if (subject) {
+ mContentWidget->header()->subjectField()->setPlainText(*subject);
+ }
+ }
+ else {
+ // If a message is taken from the outbox, no subject formatting is done.
+ NmId notUsed(0);
+
+ if (mCheckOutboxOperation &&
+ mCheckOutboxOperation->getMessageId(notUsed)) {
+ editorStartMode = NmUiEditorCreateNew;
+ }
+
+ // Construct the subject field.
+ mContentWidget->header()->subjectField()->setPlainText(
+ addSubjectPrefix(editorStartMode, messageEnvelope.subject()));
+ }
+
+ // Set priority.
+ mHeaderWidget->setPriority(messageEnvelope.priority());
+
+ // Set the message body.
+ // Fetch plain text part form message store.
+ NmMessagePart *plainPart = mMessage->plainTextBodyPart();
+
+ if (plainPart) {
+ mUiEngine.contentToMessagePart(mMessage->mailboxId(),
+ mMessage->parentId(),
+ mMessage->envelope().id(),
+ *plainPart);
+ }
+
+ // Fetch html part form message store.
+ NmMessagePart *htmlPart = mMessage->htmlBodyPart();
+
+ if (htmlPart) {
+ mUiEngine.contentToMessagePart(mMessage->mailboxId(),
+ mMessage->parentId(),
+ mMessage->envelope().id(),
+ *htmlPart);
+ }
+
+ // Fetch attachment.html part form message store if such exists.
+ QList<NmMessagePart*> parts;
+ mMessage->attachmentList(parts);
+ NmMessagePart *attachmentHtml = NULL;
+
+ foreach(NmMessagePart *part, parts) {
+ if (part->contentDescription().startsWith(NmContentDescrAttachmentHtml)) {
+ attachmentHtml = part;
+ }
+ }
+
+ if (attachmentHtml) {
+ mUiEngine.contentToMessagePart(mMessage->mailboxId(),
+ mMessage->parentId(),
+ mMessage->envelope().id(),
+ *attachmentHtml);
+ }
+
+ mContentWidget->setMessageData(mMessage);
+
+ // 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]->id());
+ }
+
+ if (mStartParam) {
+ // Attach passed files to the message.
+ QStringList *fileList = mStartParam->attachmentList();
+
+ if (fileList) {
+ addAttachments(*fileList);
+ }
+ }
+
+ // TODO Switch the following arbitrary (magic number) timeout to a
+ // meaningful constant, please!
+ QTimer::singleShot(200, mHeaderWidget, SLOT(sendHeaderHeightChanged()));
+}
+
+
+/*!
+ createToolBar. Function asks menu commands from extension
+ to be added to toolbar owned by the HbView.
+*/
+void NmEditorView::createToolBar()
+{
+ 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);
+ }
+ }
+ }
+}
+
+/*!
+ createOptionsMenu. Functions asks menu commands from extension
+ to be added to options menu.
+*/
+void NmEditorView::createOptionsMenu()
+{
+ if (!mPrioritySubMenu) {
+ mPrioritySubMenu = new HbMenu();
+ }
+ mPrioritySubMenu->clearActions();
+ menu()->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++) {
+ mPrioritySubMenu->addAction(list[i]);
+ }
+ mPrioritySubMenu->setObjectName("editorPrioritySubMenu");
+ mPrioritySubMenu->setTitle(hbTrId("txt_mail_opt_add_priority"));
+ menu()->addMenu(mPrioritySubMenu);
+}
+
+/*!
+ handleActionCommand. From NmActionObserver, extension manager calls this
+ call to handle menu command in the UI.
+*/
+void NmEditorView::handleActionCommand(NmActionResponse &actionResponse)
+{
+ NmActionResponseCommand responseCommand = actionResponse.responseCommand();
+
+ // Handle options menu
+ if (actionResponse.menuType() == NmActionOptionsMenu) {
+ setPriority(responseCommand);
+ }
+ else if (actionResponse.menuType() == NmActionToolbar) {
+ switch (responseCommand) {
+ case NmActionResponseCommandSendMail: {
+ startSending();
+ break;
+ }
+ case NmActionResponseCommandAttach : {
+ // Do nothing if previous addAttachment operation is still ongoing.
+ if(!mAddAttachmentOperation || !mAddAttachmentOperation->isRunning()) {
+ //will be replaced by toolbar extension
+ if (!mAttachContextMenu) {
+ QList<NmAction *> actionList;
+ NmAction* actionPhoto = new NmAction(0);
+ actionPhoto->setText(QObject::tr("Photo", "txt_nmailui_photo_attach"));
+ actionList.append(actionPhoto);
+ connect(actionPhoto, SIGNAL(triggered()), this, SLOT(attachImage()));
+
+ mAttachContextMenu = new HbMenu();
+ mAttachContextMenu->clearActions();
+
+ for (int i=0;i<actionList.count();i++) {
+ mAttachContextMenu->addAction(actionList[i]);
+ }
+ }
+
+ QPointF menuPos(qreal(20),qreal(520));
+ mAttachContextMenu->exec(menuPos);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+/*!
+ This function converts background scroll area coordinate point into
+ body text editor coordinate point.
+ */
+QPointF NmEditorView::viewCoordinateToEditCoordinate(QPointF orgPoint)
+{
+ QPointF contentWidgetPos = mScrollAreaContents->pos();
+ qreal y = orgPoint.y() - mHeaderWidget->headerHeight();
+ y -= contentWidgetPos.y();
+ qreal x = orgPoint.x() - contentWidgetPos.x();
+ return QPointF(x, y);
+}
+
+/*!
+ Send mouse press event to body edit widget
+*/
+void NmEditorView::sendMousePressEventToScroll(QGraphicsSceneMouseEvent *event)
+{
+ if (event && mEditWidget && mHeaderWidget) {
+ event->setPos(viewCoordinateToEditCoordinate(event->pos()));
+ event->setAccepted(true);
+ mEditWidget->sendMousePressEvent(event);
+ }
+}
+
+/*!
+ Send mouse release event to body edit widget
+*/
+void NmEditorView::sendMouseReleaseEventToScroll(QGraphicsSceneMouseEvent *event)
+{
+ if (event&& mEditWidget && mHeaderWidget) {
+ event->setPos(viewCoordinateToEditCoordinate(event->pos()));
+ event->setAccepted(true);
+ mEditWidget->sendMouseReleaseEvent(event);
+ }
+}
+
+/*!
+ Send mouse move event to body edit widget
+*/
+void NmEditorView::sendMouseMoveEventToScroll(QGraphicsSceneMouseEvent *event)
+{
+ if (event&& mEditWidget && mHeaderWidget) {
+ event->setPos(viewCoordinateToEditCoordinate(event->pos()));
+ event->setAccepted(true);
+ mEditWidget->sendMouseMoveEvent(event);
+ }
+}
+
+void NmEditorView::sendLongPressGesture(const QPointF &point)
+{
+ if (mEditWidget && mHeaderWidget) {
+ QPointF scenePos = mEditWidget->scenePos();
+ QPointF newPoint = QPointF(point.x()-scenePos.x(), point.y()-scenePos.y());
+ if(mEditWidget->contains(newPoint)) {
+ mEditWidget->sendLongPressEvent(point);
+ }
+ }
+}
+
+
+/*!
+ 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)
+{
+ // 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(mContentWidget->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()
+{
+ 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(mContentWidget->editor());
+ editorInterface.addAction(list[i]);
+ HbEditorInterface toEditorInterface(mContentWidget->header()->toField());
+ toEditorInterface.addAction(list[i]);
+ HbEditorInterface ccEditorInterface(mContentWidget->header()->ccField());
+ ccEditorInterface.addAction(list[i]);
+ HbEditorInterface bccEditorInterface(mContentWidget->header()->bccField());
+ bccEditorInterface.addAction(list[i]);
+ HbEditorInterface subjectEditorInterface(mContentWidget->header()->subjectField());
+ subjectEditorInterface.addAction(list[i]);
+ }
+ }
+}
+
+/*!
+ Set mailbox name to title
+*/
+void NmEditorView::setMailboxName()
+{
+ 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 )
+{
+ QString newSubject(subject.trimmed());
+
+ if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll ||
+ startMode == NmUiEditorForward) {
+ QString rePrefix(QObject::tr("Re:", "txt_nmailui_reply_subject_prefix"));
+ QString fwPrefix(QObject::tr("Fw:", "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;
+}
+
+#ifdef Q_OS_SYMBIAN
+
+void NmEditorView::attachImage()
+{
+ XQAiwRequest *request;
+ XQApplicationManager mAppmgr;
+ request = mAppmgr.create(IMAGE_FETCHER_INTERFACE, FETCHER_OPERATION, true);
+
+ if (request) {
+ connect(request, SIGNAL(requestOk(const QVariant&)), this, SLOT(onAttachmentReqCompleted(const QVariant&)));
+ }
+ else {
+ //create request failed
+ NMLOG("appmgr: create request failed");
+ return;
+ }
+
+ if (!(request)->send()) {
+ //sending request failed
+ NMLOG("appmgr: send request failed");
+ }
+ delete request;
+}
+
+/*!
+ 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)
+{
+ if (!value.isNull()) {
+ addAttachments(value.toStringList());
+ }
+}
+
+#endif
+
+/*!
+ Add list of attachments
+*/
+void NmEditorView::addAttachments(const QStringList& fileNames)
+{
+ NMLOG("NmEditorView::addAttachments");
+
+ // 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));
+ NMLOG(fileName);
+ }
+
+ // Start operation to attach file or list of files into mail message
+ // This will also copy files into message store
+ // Delete previous operation
+ if (mAddAttachmentOperation) {
+ if (!mAddAttachmentOperation->isRunning()) {
+ delete mAddAttachmentOperation;
+ mAddAttachmentOperation = NULL;
+ }
+ }
+ if (!mAddAttachmentOperation) {
+ mAddAttachmentOperation = mUiEngine.addAttachments(*mMessage, fileNames);
+
+ if (mAddAttachmentOperation) {
+ // 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 when attachment has been deleted from UI
+*/
+void NmEditorView::removeAttachment(const NmId attachmentPartId)
+{
+ // Delete previous operation
+ if (mRemoveAttachmentOperation) {
+ if (!mRemoveAttachmentOperation->isRunning()) {
+ delete mRemoveAttachmentOperation;
+ mRemoveAttachmentOperation = NULL;
+ }
+ }
+ if (!mRemoveAttachmentOperation) {
+ mRemoveAttachmentOperation = mUiEngine.removeAttachment(*mMessage, attachmentPartId);
+ }
+}
+
+/*!
+ This is signalled by mAddAttachmentOperation when the operation is
+ completed for one attachment.
+ */
+void NmEditorView::oneAttachmentAdded(const QString &fileName, const NmId &msgPartId, int result)
+{
+ if (result == NmNoError) {
+ // Get file size from the message when it works
+ mHeaderWidget->setAttachmentParameters(fileName, msgPartId, QString("0"), result);
+ }
+ else {
+ // Attachment adding failed. Show an error note and remove from UI attachment list.
+ NMLOG(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)
+{
+ if (result != NmNoError) {
+ HbMessageBox::warning(hbTrId("txt_mail_dialog_unable_to_add_attachment"));
+ }
+}
+
+/*!
+ This is signalled by mCheckOutboxOperation when the operation is complete.
+ */
+void NmEditorView::outboxChecked(int result)
+{
+ bool messageInOutbox = false;
+
+ if (result == NmNoError && mCheckOutboxOperation) {
+
+ NmId messageId;
+ messageInOutbox = mCheckOutboxOperation->getMessageId(messageId);
+
+ if (messageInOutbox) {
+ delete mMessage;
+ mMessage = NULL;
+
+ mMessage = mUiEngine.message(
+ mStartParam->mailboxId(),
+ mUiEngine.standardFolderId(
+ mStartParam->mailboxId(), NmFolderOutbox),
+ messageId);
+
+ fillEditorWithMessageContents();
+
+ if (mMessage) {
+ HbMessageBox::warning(
+ hbTrId("txt_mail_dialog_sending failed").arg(
+ NmUtilities::truncate(
+ mMessage->envelope().subject(), 20)));
+ }
+ }
+ }
+
+ if (!messageInOutbox) {
+ startMessageCreation(mStartParam->editorStartMode());
+ }
+}
+
+/*!
+ Sets priority for the message object that is being edited
+*/
+void NmEditorView::setPriority(NmActionResponseCommand priority)
+{
+ mHeaderWidget->setPriority(priority);
+
+ if (mMessage) {
+ NmMessagePriority messagePriority = NmMessagePriorityNormal;
+
+ if (priority == NmActionResponseCommandPriorityHigh) {
+ messagePriority = NmMessagePriorityHigh;
+ }
+ else if (priority == NmActionResponseCommandPriorityLow) {
+ messagePriority = NmMessagePriorityLow;
+ }
+ 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
+{
+ QString addressesString;
+ QList<NmAddress*>::const_iterator i = list.constBegin();
+
+ while (i != list.constEnd() && *i) {
+ if (i > list.constBegin()) {
+ // Add the delimiter.
+ addressesString += Delimiter;
+ }
+
+ 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
+{
+ QString addressesString;
+ QList<NmAddress>::const_iterator i = list.constBegin();
+
+ while (i != list.constEnd()) {
+ if (i > list.constBegin()) {
+ // Add the delimiter.
+ addressesString += Delimiter;
+ }
+
+ addressesString += (*i).address();
+ ++i;
+ }
+
+ return addressesString;
+}
+
+
+// End of file.