emailuis/nmailui/src/nmeditorview.cpp
branchRCL_3
changeset 63 d189ee25cf9d
equal deleted inserted replaced
61:dcf0eedfc1a3 63:d189ee25cf9d
       
     1 /*
       
     2 * Copyright (c) 2009 - 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Message editor view
       
    15 *
       
    16 */
       
    17 #include "nmuiheaders.h"
       
    18 
       
    19 // Layout file and view
       
    20 static const char *NMUI_EDITOR_VIEW_XML = ":/docml/nmeditorview.docml";
       
    21 static const char *NMUI_EDITOR_VIEW = "editorview";
       
    22 
       
    23 // extension list item frame.
       
    24 static const QString NmPopupListFrame = "qtg_fr_popup_list_normal";
       
    25 static const QString NmDelimiter("; ");
       
    26 static const QString NmPriorityLow("low");
       
    27 static const QString NmPriorityNormal("normal");
       
    28 static const QString NmPriorityHigh("high");
       
    29 
       
    30 /*!
       
    31 	\class NmEditorView
       
    32 	\brief Mail editor view
       
    33 */
       
    34 
       
    35 /*!
       
    36     Constructor
       
    37 */
       
    38 NmEditorView::NmEditorView(
       
    39     NmApplication &application,
       
    40     NmUiStartParam* startParam,
       
    41     NmUiEngine &uiEngine,
       
    42     NmAttachmentManager &attaManager,
       
    43     QGraphicsItem *parent)
       
    44     : NmBaseView(startParam, application, parent),
       
    45       mApplication(application),
       
    46       mUiEngine(uiEngine),
       
    47       mAttaManager(attaManager),
       
    48       mDocumentLoader(NULL),
       
    49       mHeaderWidget(NULL),
       
    50       mMessage(NULL),
       
    51       mContent(NULL),
       
    52       mAttachmentListContextMenu(NULL),
       
    53       mMessageCreationOperation(NULL),
       
    54       mAddAttachmentOperation(NULL),
       
    55       mRemoveAttachmentOperation(NULL),
       
    56       mWaitDialog(NULL),
       
    57       mQueryDialog(NULL),
       
    58       mAttachmentPicker(NULL),
       
    59       mCcBccFieldVisible(false),
       
    60       mServiceSendingDialog(NULL),
       
    61       mHiddenPriorityName(NmPriorityNormal)
       
    62 {
       
    63     NM_FUNCTION;
       
    64     
       
    65     mDocumentLoader	= new HbDocumentLoader();
       
    66     // Set object name
       
    67     setObjectName("NmEditorView");
       
    68     // call the createToolBar on load view layout
       
    69     createToolBar();
       
    70     // Load view layout
       
    71     loadViewLayout();
       
    72 }
       
    73 
       
    74 /*!
       
    75     Destructor
       
    76 */
       
    77 NmEditorView::~NmEditorView()
       
    78 {
       
    79     NM_FUNCTION;
       
    80     
       
    81     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
       
    82         mRemoveAttachmentOperation->cancelOperation();
       
    83     }
       
    84     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
       
    85         mAddAttachmentOperation->cancelOperation();
       
    86     }
       
    87     if (mMessageCreationOperation && mMessageCreationOperation->isRunning()) {
       
    88         mMessageCreationOperation->cancelOperation();
       
    89     }
       
    90     delete mMessage;
       
    91     mWidgetList.clear();
       
    92     delete mDocumentLoader;
       
    93     delete mPrioritySubMenu;
       
    94     
       
    95     if (mAttachmentListContextMenu) {
       
    96         mAttachmentListContextMenu->clearActions();
       
    97         delete mAttachmentListContextMenu;
       
    98     }
       
    99     delete mWaitDialog;
       
   100     delete mQueryDialog;
       
   101     delete mAttachmentPicker;    
       
   102     mAttaManager.clearObserver();
       
   103     mAttaManager.cancelFetch();
       
   104     
       
   105     // make sure virtual keyboard is closed
       
   106     QInputContext *ic = qApp->inputContext();
       
   107     if (ic) {
       
   108         QEvent *closeEvent = new QEvent(QEvent::CloseSoftwareInputPanel);
       
   109         ic->filterEvent(closeEvent);
       
   110         delete closeEvent;
       
   111     }
       
   112 }
       
   113 
       
   114 /*!
       
   115     View layout loading from XML
       
   116 */
       
   117 void NmEditorView::loadViewLayout()
       
   118 {
       
   119     NM_FUNCTION;
       
   120     
       
   121     mPrioritySubMenu = NULL;
       
   122 
       
   123     // Use document loader to load the view
       
   124     bool ok(false);
       
   125 
       
   126     setObjectName(QString(NMUI_EDITOR_VIEW));
       
   127     QObjectList objectList;
       
   128     objectList.append(this);
       
   129     // Pass the view to documentloader. Document loader uses this view
       
   130     // when docml is parsed, instead of creating new view.
       
   131     // documentloader is created in constructor
       
   132     mDocumentLoader->setObjectTree(objectList);
       
   133 
       
   134     mWidgetList = mDocumentLoader->load(NMUI_EDITOR_VIEW_XML, &ok);
       
   135 
       
   136    if (ok) {
       
   137         mContent = new NmEditorContent(this, mDocumentLoader, 
       
   138             mApplication.networkAccessManager(), mApplication);
       
   139 
       
   140         mHeaderWidget = mContent->header();
       
   141 
       
   142         // Set default color for user - entered text if editor is in re/reAll/fw mode
       
   143         if (mStartParam) {
       
   144             NmUiEditorStartMode mode = mStartParam->editorStartMode();
       
   145             if (mode == NmUiEditorReply
       
   146                 || mode == NmUiEditorReplyAll 
       
   147                 || mode == NmUiEditorForward) {
       
   148                 mContent->editor()->setCustomTextColor(true, Qt::blue);
       
   149             }
       
   150         }
       
   151 
       
   152         // the rest of the view initialization is done in viewReady()
       
   153     }
       
   154 }
       
   155 
       
   156 /*!
       
   157     Reload view contents with new start parameters
       
   158     Typically when view is already open and external view activation occurs
       
   159     for this same view
       
   160 */
       
   161 void NmEditorView::reloadViewContents(NmUiStartParam* startParam)
       
   162 {
       
   163     NM_FUNCTION;
       
   164     
       
   165     // Check start parameter validity.
       
   166     if (startParam&&startParam->viewId()==NmUiViewMessageEditor) {
       
   167         // Delete existing start parameter data
       
   168         delete mStartParam;
       
   169         mStartParam=NULL;
       
   170         // Store new start parameter data
       
   171         mStartParam=startParam;
       
   172         // Store existing edited message to drafts and reload
       
   173         // editor with new start parameters.
       
   174         // ..
       
   175         // Reload editor with new message data
       
   176         fetchMessageIfNeeded(*mStartParam);
       
   177     }
       
   178     else {
       
   179         NM_ERROR(1,"nmailui: Invalid editor start parameter");
       
   180         // Unused start parameter needs to be deleted
       
   181         delete startParam;
       
   182         startParam = NULL;
       
   183     }
       
   184 }
       
   185 
       
   186 /*!
       
   187    Screen orientation changed. Editor view needs to be scaled when
       
   188    landscape <-> portrait switch occurs because text needs to
       
   189    be wrapped again.
       
   190 */
       
   191 void NmEditorView::orientationChanged(Qt::Orientation orientation)
       
   192 {
       
   193     NM_FUNCTION;
       
   194     
       
   195     Q_UNUSED(orientation);
       
   196     
       
   197     // content widget height needs to be set according to the new orientation to get the scroll
       
   198 	// area work correctly
       
   199 	mHeaderWidget->sendDelayedHeaderHeightChanged();
       
   200 	mHeaderWidget->adjustHeaderWidth();
       
   201 }
       
   202 
       
   203 /*!
       
   204     This slot is signaled by VKB when it opens
       
   205  */
       
   206 void NmEditorView::vkbOpened()
       
   207 {
       
   208     showChrome(false);	
       
   209 }
       
   210 
       
   211 /*!
       
   212     This slot is signaled by VKB when it closes.
       
   213  */
       
   214 void NmEditorView::vkbClosed()
       
   215 {
       
   216 	showChrome(true);
       
   217 }
       
   218 
       
   219 /*!
       
   220     Hide or show chrome.
       
   221  */
       
   222 void NmEditorView::showChrome(bool show)
       
   223 {
       
   224     if (show) {
       
   225         showItems(Hb::StatusBarItem | Hb::TitleBarItem | Hb::ToolBarItem);
       
   226     }
       
   227     else {
       
   228         hideItems(Hb::StatusBarItem | Hb::TitleBarItem | Hb::ToolBarItem);
       
   229     }
       
   230 }
       
   231 
       
   232 /*!
       
   233     View id
       
   234 */
       
   235 NmUiViewId NmEditorView::nmailViewId() const
       
   236 {
       
   237     NM_FUNCTION;
       
   238     
       
   239     return NmUiViewMessageEditor;
       
   240 }
       
   241 
       
   242 /*
       
   243    Launch dialog for query user if we want to exit the editor
       
   244 */
       
   245 void NmEditorView::okToExitView()
       
   246 {
       
   247     NM_FUNCTION;
       
   248        
       
   249     bool okToExit(true);
       
   250     
       
   251     if (mContent) {
       
   252         NmEditorHeader *header = mContent->header();
       
   253         // show the query if the message has not been sent
       
   254         if (mMessage && header) {
       
   255             // see if editor has any content
       
   256             int subjectLength = 0;
       
   257             if (header->subjectEdit()) {
       
   258                 subjectLength = header->subjectEdit()->text().length();
       
   259             }
       
   260             
       
   261             QList<NmMessagePart*> attachmentList;
       
   262             mMessage->attachmentList(attachmentList);
       
   263             
       
   264             if (mContent->editor()) {
       
   265                 okToExit = (subjectLength == 0 && mContent->editor()->document()->isEmpty());            
       
   266             }
       
   267     
       
   268             // content exists, verify exit from user
       
   269             if (!okToExit) {
       
   270                 if (mQueryDialog) {
       
   271                     delete mQueryDialog;
       
   272                     mQueryDialog = 0;
       
   273                 }
       
   274                 // Launch query dialog.
       
   275                 mQueryDialog = 
       
   276                     NmUtilities::displayQuestionNote(hbTrId("txt_mail_dialog_save_message_to_drafts"),
       
   277                                                                 this,
       
   278                                                                 SLOT(okToExitQuery(HbAction*)));
       
   279             }
       
   280         }    
       
   281     }
       
   282     
       
   283     // no need to query anything, just exit.
       
   284     if(okToExit) {
       
   285         QMetaObject::invokeMethod(&mApplication,
       
   286                                   "popView",
       
   287                                   Qt::QueuedConnection);
       
   288     }
       
   289 }
       
   290 
       
   291 /*!
       
   292     Handle the user selection is it ok to exit.
       
   293 */
       
   294 void NmEditorView::okToExitQuery(HbAction *action)
       
   295 {
       
   296     NM_FUNCTION;
       
   297     
       
   298     HbMessageBox *dlg = static_cast<HbMessageBox*>(sender());
       
   299     // The first action in dialogs action list is for the "Yes"-button.
       
   300     if (action == dlg->actions().at(0)) {
       
   301         safeToDraft();
       
   302     }    
       
   303     
       
   304     // Close the view
       
   305     QMetaObject::invokeMethod(&mApplication,
       
   306                               "popView",
       
   307                               Qt::QueuedConnection);
       
   308 }
       
   309 
       
   310 /*!
       
   311     Public slot to handle draft saving.
       
   312 */
       
   313 void NmEditorView::safeToDraft()
       
   314 {
       
   315     // Update draft message with content.
       
   316     updateMessageWithEditorContents();
       
   317 
       
   318     // Save message to drafts
       
   319     QList<NmOperation *> preliminaryOperations;
       
   320     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
       
   321         preliminaryOperations.append(mAddAttachmentOperation);
       
   322     }
       
   323     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
       
   324         preliminaryOperations.append(mRemoveAttachmentOperation);
       
   325     }
       
   326     // ownership of mMessage is transferred
       
   327     // NmOperations are automatically deleted after completion
       
   328     mUiEngine.saveDraftMessage(mMessage, preliminaryOperations);
       
   329     mMessage = NULL;
       
   330     preliminaryOperations.clear();
       
   331 }
       
   332 
       
   333 /*!
       
   334     About to exit view. Application calls this function when user has
       
   335     pressed back key and editor needs to delete the draft message. This is
       
   336     called when "auto-exiting" after a successful mail sending.
       
   337 */
       
   338 void NmEditorView::aboutToExitView()
       
   339 {
       
   340     NM_FUNCTION;
       
   341     
       
   342     // These operations need to be stopped before message can be deleted
       
   343     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
       
   344         mAddAttachmentOperation->cancelOperation();
       
   345     }
       
   346     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
       
   347         mRemoveAttachmentOperation->cancelOperation();
       
   348     }
       
   349 
       
   350     if (mMessage) { // this is NULL if sending or saving is started
       
   351         // Delete message from drafts
       
   352         mUiEngine.removeDraftMessage(mMessage);
       
   353         mMessage = NULL;
       
   354     }
       
   355 }
       
   356 
       
   357 /*!
       
   358     Lazy loading when view layout has been loaded
       
   359 */
       
   360 void NmEditorView::viewReady()
       
   361 {
       
   362     NM_FUNCTION;
       
   363 
       
   364     // Set mailbox name to title pane
       
   365     setMailboxName();
       
   366     
       
   367     // Connect options menu about to show to create options menu function
       
   368     // Menu needs to be create "just-in-time"
       
   369     connect(menu(), SIGNAL(aboutToShow()), this, SLOT(createOptionsMenu()));
       
   370     NmAction *dummy = new NmAction(0);
       
   371     menu()->addAction(dummy);
       
   372 
       
   373     mVkbHost = new HbShrinkingVkbHost(this);
       
   374     
       
   375     initializeVKB();
       
   376     
       
   377     //start to listen VKB open and close signals for hiding the chrome.
       
   378     connect(mVkbHost, SIGNAL(keypadOpened()), this, SLOT(vkbOpened()));
       
   379     connect(mVkbHost, SIGNAL(keypadClosed()), this, SLOT(vkbClosed()));
       
   380     
       
   381     connect(mContent->header(), SIGNAL(recipientFieldsHaveContent(bool)),
       
   382             this, SLOT(setButtonsDimming(bool)) );
       
   383 
       
   384     // Connect to observe orientation change events
       
   385     connect(mApplication.mainWindow(), SIGNAL(orientationChanged(Qt::Orientation)),
       
   386             this, SLOT(orientationChanged(Qt::Orientation)));
       
   387     // Signal for handling the attachment list selection
       
   388     connect(mHeaderWidget, SIGNAL(attachmentShortPressed(NmId)),
       
   389             this, SLOT(openAttachmentTriggered(NmId)));
       
   390     connect(mHeaderWidget, SIGNAL(attachmentLongPressed(NmId, QPointF)),
       
   391             this, SLOT(attachmentLongPressed(NmId, QPointF)));
       
   392     
       
   393     if (mStartParam) {
       
   394         fetchMessageIfNeeded(*mStartParam);
       
   395     }
       
   396     else { // execution cannot proceed without start param 
       
   397         QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
   398     }
       
   399     
       
   400     // Adjust the header width according to the current screen width.
       
   401     mHeaderWidget->adjustHeaderWidth(); 
       
   402 }
       
   403 
       
   404 /*!
       
   405     If entering editor for forwarding or replying, use attachment manager
       
   406     to check that we have all message parts fetched. Also show dialog for
       
   407     fetching progress.
       
   408 */
       
   409 void NmEditorView::fetchMessageIfNeeded(NmUiStartParam &startParam)
       
   410 {
       
   411     NM_FUNCTION;
       
   412     
       
   413     if (startParam.editorStartMode() == NmUiEditorForward
       
   414         || startParam.editorStartMode()== NmUiEditorReply
       
   415         || startParam.editorStartMode() == NmUiEditorReplyAll) {
       
   416     
       
   417         fetchProgressDialogShow();
       
   418         mAttaManager.clearObserver();
       
   419         mAttaManager.setObserver(this);
       
   420         mAttaManager.fetchAllMessageParts(
       
   421             startParam.mailboxId(),
       
   422             startParam.folderId(),
       
   423             startParam.messageId());
       
   424     }
       
   425     else {
       
   426         startMessageCreation(startParam);
       
   427     }
       
   428 }
       
   429 
       
   430 /*!
       
   431     Slot. Called when attachments fetch progress changes.
       
   432 */
       
   433 void NmEditorView::progressChanged(int value)
       
   434 {
       
   435     NM_FUNCTION;
       
   436     
       
   437     Q_UNUSED(value);
       
   438 }
       
   439 
       
   440 /*!
       
   441     Slot. Called when attachments fetch is completed. We can start
       
   442     message creation. 
       
   443 */
       
   444 void NmEditorView::fetchCompleted(int result)
       
   445 {
       
   446     NM_FUNCTION;
       
   447     
       
   448     if (result == NmNoError && mStartParam) {
       
   449         startMessageCreation(*mStartParam);
       
   450     }
       
   451     else {
       
   452         // Close "Loading mail content" dialog
       
   453         mWaitDialog->close();
       
   454         
       
   455         // Show a fetching failed note when the failure is not caused by a Device/System failure.
       
   456         if (result != NmNoError && 
       
   457             result != NmNotFoundError &&
       
   458             result != NmGeneralError &&
       
   459             result != NmCancelError &&
       
   460             result != NmAuthenticationError &&
       
   461             result != NmServerConnectionError &&
       
   462             result != NmConnectionError) {         
       
   463             HbNotificationDialog *note = new HbNotificationDialog();            
       
   464             bool enalbeAttribute(true);
       
   465             note->setAttribute(Qt::WA_DeleteOnClose, enalbeAttribute);           
       
   466             note->setIcon(HbIcon(QLatin1String("note_warning")));        
       
   467             note->setTitle(hbTrId("txt_mail_dpopinfo_loading_failed"));
       
   468             note->setTitleTextWrapping(Hb::TextWordWrap);      
       
   469             note->setDismissPolicy(HbNotificationDialog::TapAnywhere);
       
   470             note->setTimeout(HbNotificationDialog::StandardTimeout);       
       
   471             note->setSequentialShow(true);
       
   472             note->show();
       
   473         }
       
   474         
       
   475         // Go back to Viewer view
       
   476         QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
   477     }
       
   478 }
       
   479 
       
   480 void NmEditorView::fetchProgressDialogShow()
       
   481 {
       
   482     NM_FUNCTION;
       
   483     
       
   484     delete mWaitDialog;
       
   485     mWaitDialog = NULL;
       
   486     // Create new wait dialog and set it to me modal with dimmed background
       
   487     mWaitDialog = new HbProgressDialog(HbProgressDialog::WaitDialog);
       
   488     mWaitDialog->setModal(true);
       
   489     mWaitDialog->setBackgroundFaded(true);
       
   490     connect(mWaitDialog, SIGNAL(cancelled()), this, SLOT(fetchProgressDialogCancelled()));
       
   491     mWaitDialog->setText(hbTrId("txt_mail_dialog_loading_mail_content"));
       
   492     // Display wait dialog
       
   493     mWaitDialog->show();
       
   494 }
       
   495 
       
   496 /*!
       
   497     This is called by mFetchProgressDialog when the note is cancelled
       
   498  */
       
   499 void NmEditorView::fetchProgressDialogCancelled()
       
   500 {
       
   501     NM_FUNCTION;
       
   502     
       
   503     if (mAttaManager.isFetching()) { 
       
   504         mAttaManager.cancelFetch();
       
   505         mAttaManager.clearObserver();
       
   506     }
       
   507     else {   
       
   508         // For those email has no attachment or attachment has fetched.
       
   509         // Go back to Viewer view.
       
   510         QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
   511     }
       
   512 }
       
   513 
       
   514 void NmEditorView::startMessageCreation(NmUiStartParam &startParam)
       
   515 {
       
   516     NM_FUNCTION;
       
   517     
       
   518     NmUiEditorStartMode startMode = startParam.editorStartMode();
       
   519     NmId mailboxId = startParam.mailboxId();
       
   520     NmId folderId = startParam.folderId();
       
   521     NmId msgId = startParam.messageId();
       
   522     
       
   523     if (mMessageCreationOperation && mMessageCreationOperation->isRunning()) {
       
   524         mMessageCreationOperation->cancelOperation();
       
   525     }
       
   526 	  
       
   527     // original message is now fetched so start message creation
       
   528     if (startMode == NmUiEditorForward) {
       
   529         mMessageCreationOperation = mUiEngine.createForwardMessage(mailboxId, msgId);
       
   530     }
       
   531     else if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll) {
       
   532         mMessageCreationOperation = mUiEngine.createReplyMessage(mailboxId, 
       
   533             msgId, 
       
   534             startMode == NmUiEditorReplyAll);
       
   535     }
       
   536     else if (startMode == NmUiEditorFromDrafts) {
       
   537         // Draft opened, so reload message and fill editor with message data.
       
   538         mMessage = mUiEngine.message(
       
   539             mStartParam->mailboxId(), 
       
   540             mStartParam->folderId(), 
       
   541             mStartParam->messageId());
       
   542         fillEditorWithMessageContents();
       
   543     }
       
   544     else {
       
   545         mMessageCreationOperation = mUiEngine.createNewMessage(mailboxId);
       
   546     }
       
   547     
       
   548     // operation continues in messageCreated() once it finishes ok
       
   549     if (mMessageCreationOperation) {
       
   550         connect(mMessageCreationOperation,
       
   551                 SIGNAL(operationCompleted(int)),
       
   552                 this,
       
   553                 SLOT(messageCreated(int)));
       
   554     }    
       
   555 }
       
   556 
       
   557 /*!
       
   558     Starting the message sending is handled here.
       
   559 */
       
   560 void NmEditorView::startSending()
       
   561 {
       
   562     NM_FUNCTION;
       
   563     
       
   564     // The message contents should be verified
       
   565     updateMessageWithEditorContents();
       
   566     
       
   567     // verify addresses before sending
       
   568     QList<NmAddress> invalidAddresses;
       
   569     if (mMessage) {
       
   570         NmUtilities::getRecipientsFromMessage(*mMessage, invalidAddresses, NmUtilities::NmInvalidAddress);
       
   571     }
       
   572     
       
   573     if (invalidAddresses.count() > 0) {
       
   574         
       
   575         // Invalid addresses found, verify send from user.
       
   576         // Set the first failing address to the note.
       
   577         QString noteText = 
       
   578             HbParameterLengthLimiter(
       
   579                 "txt_mail_dialog_invalid_mail_address_send"
       
   580                 ).arg(invalidAddresses.at(0).address());
       
   581         
       
   582         if (mQueryDialog) {
       
   583             delete mQueryDialog;
       
   584             mQueryDialog = 0;
       
   585         }
       
   586         // Launch query dialog. Pressing "yes" will finalize the sending.
       
   587         mQueryDialog = NmUtilities::displayQuestionNote(noteText,
       
   588                                                         this,
       
   589                                                         SLOT(invalidAddressQuery(HbAction*)));
       
   590     }
       
   591     else {
       
   592         // no need to ask anything, just send
       
   593         finalizeSending();
       
   594     }
       
   595 }
       
   596 
       
   597 /*!
       
   598     Send the message after all checks have been done.
       
   599 */
       
   600 void NmEditorView::finalizeSending()
       
   601 {
       
   602     NM_FUNCTION;
       
   603     
       
   604     QList<NmOperation *> preliminaryOperations;
       
   605     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
       
   606         preliminaryOperations.append(mAddAttachmentOperation);
       
   607     }
       
   608     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
       
   609         preliminaryOperations.append(mRemoveAttachmentOperation);
       
   610     }
       
   611     // ownership of mMessage is transferred
       
   612     // NmOperations are automatically deleted after completion
       
   613     mUiEngine.sendMessage(mMessage, preliminaryOperations);
       
   614     mMessage = NULL;
       
   615     preliminaryOperations.clear();
       
   616 
       
   617     bool service = XQServiceUtil::isService();
       
   618 
       
   619     // If sending is started as a service, progress dialog needs to be shown
       
   620     // so long that sending is finished otherwise we can close pop current view.
       
   621     if (service && mStartParam && mStartParam->service() && 
       
   622         mUiEngine.isSendingMessage()) {
       
   623         connect(&mUiEngine, SIGNAL(sendOperationCompleted()),
       
   624             this, SLOT(handleSendOperationCompleted()), Qt::UniqueConnection);
       
   625 
       
   626         // Construct and setup the wait dialog.
       
   627         mServiceSendingDialog = new HbProgressDialog(HbProgressDialog::WaitDialog);
       
   628         mServiceSendingDialog->setAttribute(Qt::WA_DeleteOnClose);
       
   629         mServiceSendingDialog->setText(hbTrId("txt_mail_shareui_sending_please_wait"));
       
   630         connect(mServiceSendingDialog, SIGNAL(cancelled()),
       
   631             this, SLOT(sendProgressDialogCancelled()));
       
   632 
       
   633         if (!XQServiceUtil::isEmbedded()) {
       
   634             // Hide the application.
       
   635             XQServiceUtil::toBackground(true);
       
   636         }
       
   637          // Display the wait dialog.
       
   638          mServiceSendingDialog->setModal(true);
       
   639          mServiceSendingDialog->setBackgroundFaded(true);
       
   640          mServiceSendingDialog->show();
       
   641     } else {
       
   642         // Must use delayed editor view destruction so that query dialog
       
   643         // (which has signaled this) gets time to complete.
       
   644         QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
   645     }
       
   646 }
       
   647 
       
   648 /*!
       
   649     Handle the user selection for invalid address query which was started by startSending.
       
   650 */
       
   651 void NmEditorView::invalidAddressQuery(HbAction* action)
       
   652 {
       
   653     NM_FUNCTION;
       
   654 
       
   655     HbMessageBox *dlg = static_cast<HbMessageBox*>(sender());
       
   656     // The first action in dialogs action list is for the "Yes"-button.
       
   657     if (action == dlg->actions().at(0)) {
       
   658         finalizeSending();
       
   659     }
       
   660 }
       
   661 
       
   662 /*!
       
   663     This is called when the view's geometry size has been changed, eg. when VKB is opened/closed.
       
   664 */
       
   665 void NmEditorView::resizeEvent(QGraphicsSceneResizeEvent *event)
       
   666 {
       
   667     NM_FUNCTION;
       
   668     
       
   669     NmBaseView::resizeEvent(event);
       
   670     
       
   671     emit sizeChanged();
       
   672 }
       
   673 
       
   674 /*!
       
   675     This is signalled by mMessageCreationOperation when message is created.
       
   676 */
       
   677 void NmEditorView::messageCreated(int result)
       
   678 {
       
   679     NM_FUNCTION;
       
   680     
       
   681     delete mMessage;
       
   682     mMessage = NULL;
       
   683 
       
   684     // Close wait dialog here
       
   685     if (mWaitDialog) {
       
   686         mWaitDialog->close();
       
   687     }
       
   688     
       
   689     if (result == NmNoError && mStartParam && mMessageCreationOperation) {
       
   690         NmUiEditorStartMode startMode = mStartParam->editorStartMode();
       
   691         
       
   692         // get message "again" from engine to update the message contents 
       
   693         mMessage = mUiEngine.message(
       
   694             mStartParam->mailboxId(), 
       
   695             mStartParam->folderId(), 
       
   696             mMessageCreationOperation->getMessageId());
       
   697         
       
   698         fillEditorWithMessageContents();       
       
   699     }
       
   700 }
       
   701 
       
   702 /*!
       
   703    Updates the message with the editor contents.
       
   704 */
       
   705 void NmEditorView::updateMessageWithEditorContents()
       
   706 {
       
   707     NM_FUNCTION;
       
   708     
       
   709     if (mMessage) {
       
   710         if (mContent && mContent->editor()) {
       
   711             NmMessagePart* bodyPart = mMessage->htmlBodyPart();
       
   712             if (bodyPart) {
       
   713                 bodyPart->setTextContent(mContent->editor()->toHtml(), NmContentTypeTextHtml);
       
   714             }
       
   715             bodyPart = mMessage->plainTextBodyPart();
       
   716             if (bodyPart) {
       
   717                 bodyPart->setTextContent(mContent->editor()->toPlainText(), NmContentTypeTextPlain);
       
   718             }
       
   719         }
       
   720         if (mContent && mContent->header() ) {
       
   721             if (mContent->header()->subjectEdit()) {
       
   722                 mMessage->envelope().setSubject(
       
   723                     mContent->header()->subjectEdit()->text());
       
   724             }
       
   725             if (mContent->header()->toEdit()) {
       
   726                 QString toFieldText =
       
   727                     mContent->header()->toEdit()->text();
       
   728 
       
   729                 // This verification of zero length string isn't needed
       
   730                 // after list of addresses
       
   731                 if (toFieldText.length() > 0) {
       
   732                     mMessage->envelope().setToRecipients(mContent->header()->toEdit()->emailAddressList());  
       
   733                 }
       
   734             }
       
   735             if (mContent->header()->ccEdit()) {
       
   736                 QString ccFieldText =
       
   737                     mContent->header()->ccEdit()->text();
       
   738 
       
   739                 if (ccFieldText.length() > 0) {
       
   740                     mMessage->envelope().setCcRecipients(mContent->header()->ccEdit()->emailAddressList());      
       
   741                 }
       
   742             }
       
   743             if (mContent->header()->bccEdit()) {
       
   744                 QString bccFieldText =
       
   745                     mContent->header()->bccEdit()->text();
       
   746 
       
   747                 if (bccFieldText.length() > 0) {
       
   748                     mMessage->envelope().setBccRecipients(mContent->header()->bccEdit()->emailAddressList());  
       
   749                 }
       
   750             }
       
   751         }
       
   752     }
       
   753 }
       
   754 
       
   755 
       
   756 /*!
       
   757     Updates the message with the editor contents. Called only once when the
       
   758     editor is launched.
       
   759 */
       
   760 void NmEditorView::fillEditorWithMessageContents()
       
   761 {
       
   762     NM_FUNCTION;
       
   763     
       
   764     if (!mStartParam || !mMessage || !mContent) {
       
   765         return;
       
   766     }
       
   767 
       
   768     NmMessageEnvelope messageEnvelope(mMessage->envelope());
       
   769     bool useStartParam(false);
       
   770 
       
   771     NmUiEditorStartMode editorStartMode = mStartParam->editorStartMode();
       
   772 
       
   773     if (editorStartMode == NmUiEditorMailto) {
       
   774         // Retrieve the message header data e.g. recipients from mStartParam.
       
   775         useStartParam = true;        
       
   776     }
       
   777     
       
   778     // Set recipients (to, cc and bcc).
       
   779     QString toAddressesString;
       
   780     QString ccAddressesString;
       
   781     QString bccAddressesString;
       
   782 
       
   783     if (useStartParam) {
       
   784         toAddressesString = addressListToString(mStartParam->mailtoAddressList());
       
   785         ccAddressesString = addressListToString(mStartParam->ccAddressList());
       
   786         bccAddressesString = addressListToString(mStartParam->bccAddressList());
       
   787     }
       
   788     else {
       
   789         toAddressesString = addressListToString(messageEnvelope.toRecipients());
       
   790         ccAddressesString = addressListToString(messageEnvelope.ccRecipients());
       
   791         bccAddressesString = addressListToString(messageEnvelope.bccRecipients());
       
   792     }
       
   793 
       
   794     mContent->header()->toEdit()->setPlainText(toAddressesString);
       
   795     mContent->header()->ccEdit()->setPlainText(ccAddressesString);
       
   796     mContent->header()->bccEdit()->setPlainText(bccAddressesString);
       
   797 
       
   798     if (ccAddressesString.length() || bccAddressesString.length()) {
       
   799         // Since cc or/and bcc recipients exist, expand the group box to display
       
   800         // the addresses by expanding the group box.
       
   801         mCcBccFieldVisible = true;
       
   802         mHeaderWidget->setFieldVisibility(mCcBccFieldVisible);
       
   803     }
       
   804 
       
   805     // Set subject.
       
   806     if (useStartParam) {
       
   807         QString *subject = mStartParam->subject();
       
   808 
       
   809         if (subject) {
       
   810             mContent->header()->subjectEdit()->setPlainText(*subject);
       
   811         }
       
   812     }
       
   813     else {
       
   814         // Construct the subject field.
       
   815         mContent->header()->subjectEdit()->setPlainText(
       
   816             addSubjectPrefix(editorStartMode, messageEnvelope.subject()));
       
   817     }
       
   818 
       
   819     // Set priority.
       
   820     if (editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll) {
       
   821         //Clear the importance flag. Replied messages dont keep the importance
       
   822         setPriority(NmActionResponseCommandNone);
       
   823     }
       
   824     mHeaderWidget->setPriority(messageEnvelope.priority());
       
   825     
       
   826     NmMessage *originalMessage = NULL;
       
   827     
       
   828     // Set the message body.
       
   829     if (editorStartMode==NmUiEditorReply||
       
   830         editorStartMode==NmUiEditorReplyAll||
       
   831         editorStartMode==NmUiEditorForward||
       
   832         editorStartMode==NmUiEditorFromDrafts){
       
   833 
       
   834         // Use the body from the original message.
       
   835         originalMessage = mUiEngine.message(mStartParam->mailboxId(), 
       
   836                                             mStartParam->folderId(), 
       
   837                                             mStartParam->messageId());
       
   838 
       
   839         if (originalMessage) {
       
   840             NmMessagePart *plainPart = originalMessage->plainTextBodyPart();
       
   841 
       
   842             if (plainPart) {
       
   843                 mUiEngine.contentToMessagePart(originalMessage->envelope().mailboxId(),
       
   844                                                originalMessage->envelope().folderId(),
       
   845                                                originalMessage->envelope().messageId(),
       
   846                                                *plainPart);
       
   847             }
       
   848 
       
   849             NmMessagePart *htmlPart = originalMessage->htmlBodyPart();
       
   850 
       
   851             if (htmlPart) {
       
   852                 mUiEngine.contentToMessagePart(originalMessage->envelope().mailboxId(),
       
   853                                                originalMessage->envelope().folderId(),
       
   854                                                originalMessage->envelope().messageId(),
       
   855                                                *htmlPart);
       
   856             }
       
   857 
       
   858         }
       
   859 
       
   860     }
       
   861     
       
   862     QString *signature = NULL;
       
   863     // return value is not relevant here
       
   864     mUiEngine.getSignature(mStartParam->mailboxId(), signature);
       
   865     
       
   866     mContent->setBodyContent(editorStartMode, originalMessage, signature);
       
   867 
       
   868     delete signature;
       
   869     signature = NULL;
       
   870 
       
   871     delete originalMessage;
       
   872     originalMessage = NULL;
       
   873 
       
   874     // Get list of attachments from the message and set those into UI attachment list
       
   875     QList<NmMessagePart*> attachments;
       
   876     mMessage->attachmentList(attachments);
       
   877 
       
   878     for (int i=0; i<attachments.count(); i++) {
       
   879         mHeaderWidget->addAttachment(
       
   880             attachments[i]->attachmentName(),
       
   881             QString::number(attachments[i]->size()),
       
   882             attachments[i]->partId());
       
   883     }
       
   884 
       
   885     // Attach passed files to the message.
       
   886     QStringList *fileList = mStartParam->attachmentList();
       
   887 
       
   888     if (fileList) {
       
   889         addAttachments(*fileList);
       
   890     }
       
   891 
       
   892 }
       
   893 
       
   894 
       
   895 /*!
       
   896     createToolBar. Function asks menu commands from extension
       
   897     to be added to toolbar owned by the HbView.
       
   898 */
       
   899 void NmEditorView::createToolBar()
       
   900 {
       
   901     NM_FUNCTION;
       
   902     
       
   903     HbToolBar *tb = toolBar();
       
   904     NmUiExtensionManager &extMngr = mApplication.extManager();
       
   905     if (tb && &extMngr && mStartParam) {
       
   906         tb->clearActions();
       
   907         NmActionRequest request(this, NmActionToolbar, NmActionContextViewEditor,
       
   908                 NmActionContextDataNone, mStartParam->mailboxId(), mStartParam->folderId() );
       
   909         QList<NmAction *> list;
       
   910         extMngr.getActions(request, list);
       
   911         for (int i = 0; i < list.count(); i++) {
       
   912             tb->addAction(list[i]);
       
   913             // If action has NmSendable condition, it is shown only when send action
       
   914             // is available, i.e. when at least one recipient field has data.
       
   915             if( list[i]->availabilityCondition() == NmAction::NmSendable ) {
       
   916                 list[i]->setEnabled(false);
       
   917             }
       
   918             else if (list[i]->availabilityCondition() == NmAction::NmAttachable) {
       
   919                 HbToolBarExtension* extension = new HbToolBarExtension();
       
   920                 mAttachmentPicker = new NmAttachmentPicker(this);
       
   921                 
       
   922                 if (extension && mAttachmentPicker) {
       
   923                     connect(mAttachmentPicker, SIGNAL(attachmentsFetchOk(const QVariant &)),
       
   924                         this, SLOT(onAttachmentReqCompleted(const QVariant &)));
       
   925                     
       
   926                     connect(this, SIGNAL(titleChanged(QString)), mAttachmentPicker,
       
   927                         SLOT(setTitle(QString)));
       
   928 
       
   929                     list[i]->setToolBarExtension(extension);
       
   930                     
       
   931                     //content widget to get the items to a list
       
   932                     mTBExtnContentWidget = new HbListWidget();
       
   933                     mTBExtnContentWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
       
   934                     
       
   935                     mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_photo"));
       
   936                     mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_music"));
       
   937                     mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_video"));
       
   938                     mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_other"));
       
   939                     mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_new_photo"));
       
   940                     mTBExtnContentWidget->addItem(hbTrId("txt_mail_list_new_video"));
       
   941                     HbListViewItem *listView = mTBExtnContentWidget->listItemPrototype();
       
   942                     HbFrameBackground frame(NmPopupListFrame, HbFrameDrawer::NinePieces);
       
   943                     listView->setDefaultFrame(frame);
       
   944                     
       
   945                     connect(mTBExtnContentWidget, SIGNAL(activated(HbListWidgetItem*)), 
       
   946                     		mAttachmentPicker, SLOT (selectFetcher(HbListWidgetItem*)));
       
   947             
       
   948                     connect(mTBExtnContentWidget, SIGNAL(activated(HbListWidgetItem*)),
       
   949                             extension, SLOT(close()));
       
   950                                         
       
   951                     extension->setContentWidget(mTBExtnContentWidget);
       
   952                 }
       
   953             }            
       
   954         }        
       
   955     }
       
   956 }
       
   957 
       
   958 /*!
       
   959     createOptionsMenu. Functions asks menu commands from extension
       
   960     to be added to options menu.
       
   961 */
       
   962 void NmEditorView::createOptionsMenu()
       
   963 {
       
   964     NM_FUNCTION;
       
   965     
       
   966     menu()->clearActions();
       
   967 
       
   968 	// Create CC/BCC options menu object
       
   969     if (mCcBccFieldVisible) {
       
   970         menu()->addAction(hbTrId("txt_mail_opt_hide_cc_bcc"), this, SLOT(switchCcBccFieldVisibility()));
       
   971     }
       
   972     else {
       
   973         menu()->addAction(hbTrId("txt_mail_opt_show_cc_bcc"), this, SLOT(switchCcBccFieldVisibility()));
       
   974     }
       
   975 
       
   976 	// Create Priority options menu object
       
   977 	if (!mPrioritySubMenu) {
       
   978         mPrioritySubMenu = new HbMenu();
       
   979     }
       
   980     mPrioritySubMenu->clearActions();
       
   981     NmActionRequest request(this, NmActionOptionsMenu, NmActionContextViewEditor,
       
   982             NmActionContextDataMessage, mStartParam->mailboxId(), mStartParam->folderId(),
       
   983             mStartParam->messageId());
       
   984     NmUiExtensionManager &extMngr = mApplication.extManager();
       
   985     QList<NmAction*> list;
       
   986     extMngr.getActions(request, list);
       
   987     for (int i = 0; i < list.count(); i++) {
       
   988         // check what priority has already been selected and hide it from options menu
       
   989         if (!list[i]->objectName().contains(mHiddenPriorityName)) {
       
   990             mPrioritySubMenu->addAction(list[i]);
       
   991         }
       
   992     }
       
   993     mPrioritySubMenu->setObjectName("editorPrioritySubMenu");
       
   994     mPrioritySubMenu->setTitle(hbTrId("txt_mail_opt_add_priority"));
       
   995     menu()->addMenu(mPrioritySubMenu);
       
   996 }
       
   997 
       
   998 /*!
       
   999     Show or hide Cc field
       
  1000 */
       
  1001 void NmEditorView::switchCcBccFieldVisibility()
       
  1002 {
       
  1003     NM_FUNCTION;
       
  1004     
       
  1005     if (mCcBccFieldVisible) {
       
  1006     	mCcBccFieldVisible = false;
       
  1007     }
       
  1008     else {
       
  1009     	mCcBccFieldVisible = true;
       
  1010     }
       
  1011     mHeaderWidget->setFieldVisibility( mCcBccFieldVisible );
       
  1012 }
       
  1013 
       
  1014 /*!
       
  1015     handleActionCommand. From NmActionObserver, extension manager calls this
       
  1016     call to handle menu command in the UI.
       
  1017 */
       
  1018 void NmEditorView::handleActionCommand(NmActionResponse &actionResponse)
       
  1019 {
       
  1020     NM_FUNCTION;
       
  1021     
       
  1022     NmActionResponseCommand responseCommand = actionResponse.responseCommand();
       
  1023     
       
  1024     // Handle options menu
       
  1025     if (actionResponse.menuType() == NmActionOptionsMenu) {
       
  1026         setPriority(responseCommand);
       
  1027     }
       
  1028     else if (actionResponse.menuType() == NmActionToolbar) {
       
  1029         switch (responseCommand) {
       
  1030         case NmActionResponseCommandSendMail: {
       
  1031             // Just in case send mail would be somehow accessible during message creation or
       
  1032             // outobox checking
       
  1033             if (!mMessageCreationOperation || !mMessageCreationOperation->isRunning()) {
       
  1034                 startSending();
       
  1035             }
       
  1036             break;
       
  1037         }
       
  1038         default:
       
  1039             break;
       
  1040         }
       
  1041     }
       
  1042     else if (actionResponse.menuType() == NmActionContextMenu) {
       
  1043         switch (responseCommand) {
       
  1044         case NmActionResponseCommandRemoveAttachment: {
       
  1045             removeAttachmentTriggered();
       
  1046             break;
       
  1047         }
       
  1048         case NmActionResponseCommandOpenAttachment: {
       
  1049             openAttachmentTriggered(mSelectedAttachment);
       
  1050             break;
       
  1051         }
       
  1052         default:
       
  1053             break;
       
  1054         }
       
  1055     }
       
  1056 }
       
  1057 
       
  1058 /*!
       
  1059     Slot. Cancelled sending progress dialog.
       
  1060 */
       
  1061 void NmEditorView::sendProgressDialogCancelled()
       
  1062 {
       
  1063     // Must use delayed editor view destruction so that dialog
       
  1064     // gets time to complete, closes also nmail.
       
  1065     QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
  1066 }
       
  1067 
       
  1068 /*!
       
  1069    Sets all toolbar and VKB buttons dimmed state. All actions that have the
       
  1070    availability condition NmSendable set, will be enabled/disabled.
       
  1071 */
       
  1072 void NmEditorView::setButtonsDimming(bool enabled)
       
  1073 {
       
  1074     NM_FUNCTION;
       
  1075     
       
  1076     // Set the toolbar action states
       
  1077     HbToolBar *tb = toolBar();
       
  1078     if (tb) {
       
  1079         QList<QAction *> toolbarList = tb->actions();
       
  1080         int count = toolbarList.count();
       
  1081         for (int i = 0; i < count; i++) {
       
  1082             NmAction *action = static_cast<NmAction *>(toolbarList[i]);
       
  1083             if (action->availabilityCondition() == NmAction::NmSendable) {
       
  1084                 action->setEnabled(enabled);
       
  1085             }
       
  1086         }
       
  1087 
       
  1088         // Set the VKB action states
       
  1089         // All editors of the view share the same action, so it is enough to set
       
  1090         // this only to one of them.
       
  1091         HbEditorInterface editorInterface(mContent->editor());
       
  1092         QList<HbAction *> vkbList = editorInterface.actions();
       
  1093         count = vkbList.count();
       
  1094         for (int i = 0; i < count; i++) {
       
  1095             NmAction *action = static_cast<NmAction *>(vkbList[i]);
       
  1096             if (action->availabilityCondition() == NmAction::NmSendable) {
       
  1097                 action->setEnabled(enabled);
       
  1098             }
       
  1099         }
       
  1100     }
       
  1101 }
       
  1102 
       
  1103 /*!
       
  1104     Initialize the Virtual Keyboard to show the "Send" button
       
  1105     for all editors of the view.
       
  1106 */
       
  1107 void NmEditorView::initializeVKB()
       
  1108 {
       
  1109     NM_FUNCTION;
       
  1110     
       
  1111     if (!mStartParam) {
       
  1112         return;
       
  1113     }
       
  1114     
       
  1115     NmActionRequest request(this, NmActionVKB, NmActionContextViewEditor,
       
  1116          NmActionContextDataNone, mStartParam->mailboxId(), mStartParam->folderId() );
       
  1117     NmUiExtensionManager &extMngr = mApplication.extManager();
       
  1118     if (&extMngr) {
       
  1119         QList<NmAction *> list;
       
  1120         extMngr.getActions(request, list);
       
  1121 
       
  1122         // VKB only supports one application key, but the responsibility of giving only one
       
  1123         // action is left to the extension plugin. The rest are still attached to the VKB, but
       
  1124         // they are not shown (unless VKB starts supporting more than one).
       
  1125         for (int i = 0; i < list.count(); i++) {
       
  1126             if( list[i]->availabilityCondition() == NmAction::NmSendable ) {
       
  1127                 list[i]->setEnabled(false);
       
  1128             }
       
  1129             list[i]->setIcon(NmIcons::getIcon(NmIcons::NmIconSend));
       
  1130 
       
  1131             // Link VKB to the action. This must be done to all
       
  1132             // editors that show the button in VKB.
       
  1133             HbEditorInterface editorInterface(mContent->editor());
       
  1134             editorInterface.addAction(list[i]);
       
  1135             HbEditorInterface toEditorInterface(mContent->header()->toEdit());
       
  1136             toEditorInterface.addAction(list[i]);
       
  1137             HbEditorInterface ccEditorInterface(mContent->header()->ccEdit());
       
  1138             ccEditorInterface.addAction(list[i]);
       
  1139             HbEditorInterface bccEditorInterface(mContent->header()->bccEdit());
       
  1140             bccEditorInterface.addAction(list[i]);
       
  1141             HbEditorInterface subjectEditorInterface(mContent->header()->subjectEdit());
       
  1142             subjectEditorInterface.addAction(list[i]);
       
  1143         }
       
  1144     }
       
  1145 }
       
  1146 
       
  1147 /*!
       
  1148     Set mailbox name to title
       
  1149 */
       
  1150 void NmEditorView::setMailboxName()
       
  1151 {
       
  1152     NM_FUNCTION;
       
  1153     
       
  1154     if (mStartParam){
       
  1155         NmMailboxMetaData *meta = mUiEngine.mailboxById(mStartParam->mailboxId());
       
  1156         if (meta){
       
  1157             setTitle(meta->name());
       
  1158         }
       
  1159     }
       
  1160 }
       
  1161 
       
  1162 /*!
       
  1163    Adds a prefix to the subject for reply or forward. 
       
  1164    Strips other occurrences of the prefix from the beginning.
       
  1165 */
       
  1166 QString NmEditorView::addSubjectPrefix( NmUiEditorStartMode startMode, const QString &subject )
       
  1167 {
       
  1168     NM_FUNCTION;
       
  1169     
       
  1170     QString newSubject(subject.trimmed());
       
  1171     
       
  1172     if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll || 
       
  1173         startMode == NmUiEditorForward) {
       
  1174         QString rePrefix(hbTrId("txt_nmailui_reply_subject_prefix"));
       
  1175         QString fwPrefix(hbTrId("txt_nmailui_forward_subject_prefix"));
       
  1176         
       
  1177         // strip extra prefixes from beginning
       
  1178         int rePrefixLength(rePrefix.length());
       
  1179         int fwPrefixLength(fwPrefix.length());
       
  1180         
       
  1181         bool startswithRe(newSubject.startsWith(rePrefix, Qt::CaseInsensitive));
       
  1182         bool startswithFw(newSubject.startsWith(fwPrefix, Qt::CaseInsensitive));
       
  1183         
       
  1184         while (startswithRe || startswithFw) {            
       
  1185             if (startswithRe) {
       
  1186                 newSubject.remove(0,rePrefixLength);
       
  1187                 newSubject = newSubject.trimmed();
       
  1188             }
       
  1189             else if (startswithFw) {
       
  1190                 newSubject.remove(0,fwPrefixLength);
       
  1191                 newSubject = newSubject.trimmed();
       
  1192             }
       
  1193             startswithRe = newSubject.startsWith(rePrefix, Qt::CaseInsensitive);
       
  1194             startswithFw = newSubject.startsWith(fwPrefix, Qt::CaseInsensitive);
       
  1195         }
       
  1196         
       
  1197         if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll) {
       
  1198             newSubject = rePrefix + " " + newSubject;
       
  1199         }
       
  1200         else if (startMode == NmUiEditorForward) {
       
  1201             newSubject = fwPrefix + " " + newSubject;
       
  1202         }
       
  1203     }
       
  1204     
       
  1205     return newSubject;
       
  1206 }
       
  1207 
       
  1208 
       
  1209 /*!
       
  1210     This slot is called when 'attachment picker' request has been performed succesfully
       
  1211     Parameter 'value' contains file currently one file name but later list of the files. 
       
  1212 */
       
  1213 void NmEditorView::onAttachmentReqCompleted(const QVariant &value)
       
  1214 {
       
  1215     NM_FUNCTION;
       
  1216     
       
  1217     //temporary fix for music picker back button:
       
  1218     //it shouldn't emit requestOk signal when nothing is selected
       
  1219 	if (value.canConvert<QStringList>()) {
       
  1220 	    QStringList list = value.toStringList();
       
  1221         if (!list.at(0).isEmpty()) {
       
  1222             addAttachments(list);
       
  1223         }
       
  1224     }
       
  1225 }
       
  1226 
       
  1227 /*!
       
  1228     This slot is called when 'attachment picker' request has been unsuccesfull
       
  1229     Parameter 'errorCode' is the error code returned by the service
       
  1230     Parameter 'errorMessage' is the error message returned by the service
       
  1231 */
       
  1232 void NmEditorView::onAttachmentsFetchError(int errorCode, const QString& errorMessage)
       
  1233 {
       
  1234     NM_FUNCTION;
       
  1235     Q_UNUSED(errorCode);
       
  1236     Q_UNUSED(errorMessage);
       
  1237     NM_COMMENT(QString("Error code: %1").arg(errorCode));
       
  1238     NM_COMMENT(QString("Error message: %1").arg(errorMessage));
       
  1239 }
       
  1240 
       
  1241 /*!
       
  1242     Closes the wait dialog if one exists.
       
  1243     
       
  1244     This slot is called if the mail application has been started as a service
       
  1245     and is about to close. Closing the application while still sending a message
       
  1246     may cause unwanted cancelling of the operation.
       
  1247 */
       
  1248 void NmEditorView::handleSendOperationCompleted()
       
  1249 {
       
  1250     NM_FUNCTION;
       
  1251 
       
  1252     if (mServiceSendingDialog) {
       
  1253         mServiceSendingDialog->close();
       
  1254     }
       
  1255     // Must use delayed editor view destruction so that dialog
       
  1256     // gets time to complete, closes also nmail.
       
  1257     QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
  1258 }
       
  1259 
       
  1260 /*!
       
  1261     Add list of attachments
       
  1262 */
       
  1263 void NmEditorView::addAttachments(const QStringList& fileNames) 
       
  1264 {
       
  1265     NM_FUNCTION;
       
  1266     
       
  1267     // Add attachment name into UI
       
  1268     foreach (QString fileName, fileNames)  {
       
  1269         // At this phase attachment size and nmid are not known
       
  1270         mHeaderWidget->addAttachment(fileName, QString("0"), NmId(0));
       
  1271         NM_COMMENT(fileName);
       
  1272     }
       
  1273     //  Cancel previous operation if it's not running.
       
  1274     if (mAddAttachmentOperation) {
       
  1275         if (!mAddAttachmentOperation->isRunning()) {
       
  1276             mAddAttachmentOperation->cancelOperation();
       
  1277         }
       
  1278     }
       
  1279     // Start operation to attach file or list of files into mail message.
       
  1280     // This will also copy files into message store.
       
  1281     mAddAttachmentOperation = mUiEngine.addAttachments(*mMessage, fileNames);
       
  1282 
       
  1283     if (mAddAttachmentOperation) {
       
  1284         enableToolBarAttach(false);
       
  1285         // Signal to inform completion of one attachment
       
  1286         connect(mAddAttachmentOperation,
       
  1287                 SIGNAL(operationPartCompleted(const QString &, const NmId &, int)),
       
  1288                 this,
       
  1289                 SLOT(oneAttachmentAdded(const QString &, const NmId &, int)));
       
  1290     
       
  1291         // Signal to inform the completion of the whole operation
       
  1292         connect(mAddAttachmentOperation,
       
  1293                 SIGNAL(operationCompleted(int)),
       
  1294                 this,
       
  1295                 SLOT(allAttachmentsAdded(int)));
       
  1296     }
       
  1297 }
       
  1298 
       
  1299 /*!
       
  1300     This slot is called to create context menu when attachment has been selected
       
  1301     from UI by longpress.
       
  1302 */
       
  1303 void NmEditorView::attachmentLongPressed(NmId attachmentPartId, QPointF point)
       
  1304 {
       
  1305     NM_FUNCTION;
       
  1306     
       
  1307     // Store id of the attachment to be removed into member.
       
  1308     // It is used by removeAttachmentTriggered later if 'remove' selected.
       
  1309     mSelectedAttachment = attachmentPartId;
       
  1310 	
       
  1311     if (!mAttachmentListContextMenu) {
       
  1312         mAttachmentListContextMenu = new HbMenu();
       
  1313     }
       
  1314     mAttachmentListContextMenu->clearActions();
       
  1315     NmActionRequest request(this, NmActionContextMenu, NmActionContextViewEditor,
       
  1316         NmActionContextDataMessage, mStartParam->mailboxId(), mStartParam->folderId(),
       
  1317         mStartParam->messageId());
       
  1318     NmUiExtensionManager &extensionManager = mApplication.extManager();
       
  1319     if (&extensionManager) {
       
  1320         QList<NmAction*> actionList;
       
  1321         extensionManager.getActions(request, actionList);
       
  1322         for (int i = 0; i < actionList.count(); ++i) {
       
  1323             mAttachmentListContextMenu->addAction(actionList[i]);
       
  1324         }
       
  1325     }
       
  1326 
       
  1327     // Add menu position check here, so that it does not go outside of the screen
       
  1328     QPointF menuPos(point.x(),point.y());
       
  1329     mAttachmentListContextMenu->setPreferredPos(menuPos);
       
  1330     mAttachmentListContextMenu->open();
       
  1331 }
       
  1332 
       
  1333 /*!
       
  1334     This is signalled by mAddAttachmentOperation when the operation is
       
  1335     completed for one attachment.
       
  1336 */
       
  1337 void NmEditorView::oneAttachmentAdded(const QString &fileName, const NmId &msgPartId, int result)
       
  1338 {
       
  1339     NM_FUNCTION;
       
  1340     
       
  1341     if (result == NmNoError && mMessage) {
       
  1342         // Need to get the message again because new attachment part has been added.
       
  1343         NmId mailboxId = mMessage->envelope().mailboxId();
       
  1344         NmId folderId = mMessage->envelope().folderId();
       
  1345         NmId msgId = mMessage->envelope().messageId();
       
  1346         NmMessagePriority messagePriority = mMessage->envelope().priority();        
       
  1347         
       
  1348         delete mMessage;
       
  1349         mMessage = NULL;
       
  1350         
       
  1351         mMessage = mUiEngine.message(mailboxId, folderId, msgId);
       
  1352 
       
  1353         if (mMessage) {
       
  1354             mMessage->envelope().setPriority(messagePriority);
       
  1355             mMessage->envelope().setHasAttachments(true);
       
  1356             // Get attachment list from the message
       
  1357             QList<NmMessagePart*> attachmentList;
       
  1358             mMessage->attachmentList(attachmentList);
       
  1359         
       
  1360             // Search newly added attachment from the list
       
  1361             for (int i=0; i<attachmentList.count(); i++) {
       
  1362                 if (attachmentList[i]->partId() == msgPartId) {
       
  1363                     // Get attachment file size and set it into UI
       
  1364                     mHeaderWidget->setAttachmentParameters(fileName,
       
  1365                         msgPartId,
       
  1366                         QString().setNum(attachmentList[i]->size()),
       
  1367                         result);
       
  1368                 }
       
  1369             }
       
  1370         }
       
  1371     }
       
  1372     else {
       
  1373         // Attachment adding failed. Show an error note and remove from UI attachment list.
       
  1374         NM_ERROR(1,QString("nmailui: attachment adding into message failed: %1").arg(fileName));
       
  1375         mHeaderWidget->removeAttachment(fileName);
       
  1376     }
       
  1377 }
       
  1378 
       
  1379 /*!
       
  1380     This is signalled by mAddAttachmentOperation when the operation is
       
  1381     completed totally.
       
  1382 */
       
  1383 void NmEditorView::allAttachmentsAdded(int result)
       
  1384 {
       
  1385     NM_FUNCTION;
       
  1386     
       
  1387     enableToolBarAttach(true);
       
  1388     if (result != NmNoError) {
       
  1389         NmUtilities::displayWarningNote(hbTrId("txt_mail_dialog_unable_to_add_attachment"));
       
  1390     }
       
  1391 }
       
  1392 
       
  1393 /*!
       
  1394    Sets priority for the message object that is being edited 
       
  1395 */
       
  1396 void NmEditorView::setPriority(NmActionResponseCommand priority)
       
  1397 {
       
  1398     NM_FUNCTION;
       
  1399     
       
  1400     mHeaderWidget->setPriority(priority);
       
  1401 
       
  1402     if (mMessage) {
       
  1403         NmMessagePriority messagePriority = NmMessagePriorityNormal;
       
  1404         mHiddenPriorityName = NmPriorityNormal;
       
  1405         
       
  1406         if (priority == NmActionResponseCommandPriorityHigh) {
       
  1407             messagePriority = NmMessagePriorityHigh;
       
  1408             mHiddenPriorityName = NmPriorityHigh;
       
  1409         }
       
  1410         else if (priority == NmActionResponseCommandPriorityLow) {
       
  1411             messagePriority = NmMessagePriorityLow;
       
  1412             mHiddenPriorityName = NmPriorityLow;
       
  1413         }
       
  1414         mMessage->envelope().setPriority(messagePriority);
       
  1415     }
       
  1416 }
       
  1417 
       
  1418 
       
  1419 /*!
       
  1420     Extracts the addresses from the given list into a string separated with a
       
  1421     delimiter.
       
  1422 
       
  1423     \param list The list containing the addresses.
       
  1424     \return String containing the addresses.
       
  1425 */
       
  1426 QString NmEditorView::addressListToString(const QList<NmAddress*> &list) const
       
  1427 {
       
  1428     NM_FUNCTION;
       
  1429     
       
  1430     QString addressesString;
       
  1431     QList<NmAddress*>::const_iterator i = list.constBegin();
       
  1432     
       
  1433     while (i != list.constEnd() && *i) {
       
  1434         if (i > list.constBegin()) {
       
  1435             // Add the delimiter.
       
  1436             addressesString += NmDelimiter;
       
  1437         }
       
  1438 
       
  1439         addressesString += (*i)->address();
       
  1440         ++i;
       
  1441     }
       
  1442 
       
  1443     return addressesString;
       
  1444 }
       
  1445 
       
  1446 
       
  1447 /*!
       
  1448     Extracts the addresses from the given list into a string separated with a
       
  1449     delimiter.
       
  1450 
       
  1451     \param list The list containing the addresses.
       
  1452     \return String containing the addresses.
       
  1453 */
       
  1454 QString NmEditorView::addressListToString(const QList<NmAddress> &list) const
       
  1455 {
       
  1456     NM_FUNCTION;
       
  1457     
       
  1458     QString addressesString;
       
  1459     QList<NmAddress>::const_iterator i = list.constBegin();
       
  1460     
       
  1461     while (i != list.constEnd()) {
       
  1462         if (i > list.constBegin()) {
       
  1463             // Add the delimiter.
       
  1464             addressesString += NmDelimiter;
       
  1465         }
       
  1466 
       
  1467         addressesString += (*i).address();
       
  1468         ++i;
       
  1469     }
       
  1470 
       
  1471     return addressesString;
       
  1472 }
       
  1473 
       
  1474 /*!
       
  1475     This slot is called when 'remove' is selected from attachment list context menu.
       
  1476 */
       
  1477 void NmEditorView::removeAttachmentTriggered()
       
  1478 {
       
  1479     NM_FUNCTION;
       
  1480     
       
  1481     // Cancel will delete previous operation
       
  1482     if (mRemoveAttachmentOperation) {
       
  1483         if (!mRemoveAttachmentOperation->isRunning()) {
       
  1484             mRemoveAttachmentOperation->cancelOperation();
       
  1485         }
       
  1486     }
       
  1487     // Remove from UI
       
  1488     mHeaderWidget->removeAttachment(mSelectedAttachment);
       
  1489     // Remove from message store
       
  1490     mRemoveAttachmentOperation = mUiEngine.removeAttachment(*mMessage, mSelectedAttachment);
       
  1491     if (mRemoveAttachmentOperation) {
       
  1492         // Signal to inform the remove operation completion
       
  1493         connect(mRemoveAttachmentOperation,
       
  1494                 SIGNAL(operationCompleted(int)),
       
  1495                 this,
       
  1496                 SLOT(attachmentRemoved(int)));
       
  1497     }
       
  1498 }
       
  1499 
       
  1500 /*!
       
  1501     This slot is called by mRemoveAttachmentOperation when the operation is
       
  1502     completed. There is no need to update UI because it was already updated.
       
  1503  */
       
  1504 void NmEditorView::attachmentRemoved(int result)
       
  1505 {
       
  1506     NM_FUNCTION;
       
  1507     
       
  1508     // It is not desided yet what to do if operation fails
       
  1509     Q_UNUSED(result);
       
  1510     
       
  1511     if (mMessage) {
       
  1512         // Reload message because one attachment has been removed
       
  1513         NmId mailboxId = mMessage->envelope().mailboxId();
       
  1514         NmId folderId = mMessage->envelope().folderId();
       
  1515         NmId msgId = mMessage->envelope().messageId();
       
  1516         NmMessagePriority messagePriority = mMessage->envelope().priority();    
       
  1517 
       
  1518         delete mMessage;
       
  1519         mMessage = NULL;
       
  1520     
       
  1521         mMessage = mUiEngine.message(mailboxId, folderId, msgId);
       
  1522         
       
  1523         if(mMessage) {
       
  1524             // Set the correct priority
       
  1525             mMessage->envelope().setPriority(messagePriority);    
       
  1526             
       
  1527             // If there is no more attachments in the message, set the correct value
       
  1528             QList<NmMessagePart*> attachmentList;
       
  1529             mMessage->attachmentList(attachmentList);
       
  1530             if(attachmentList.count() == 0) {
       
  1531                 mMessage->envelope().setHasAttachments(false);
       
  1532             }
       
  1533         }
       
  1534     }
       
  1535 }
       
  1536 
       
  1537 /*!
       
  1538     This slot is called when 'open' is selected from attachment list context menu.
       
  1539 */
       
  1540 void NmEditorView::openAttachmentTriggered(NmId attachmentId)
       
  1541 {
       
  1542     NM_FUNCTION;
       
  1543     NmId mailboxId = mMessage->envelope().mailboxId();
       
  1544     NmId folderId = mMessage->envelope().folderId();
       
  1545     NmId msgId = mMessage->envelope().messageId();
       
  1546 
       
  1547     XQSharableFile file = mUiEngine.messagePartFile(mailboxId, folderId,
       
  1548     		msgId, attachmentId);
       
  1549     int error = NmUtilities::openFile(file);
       
  1550     file.close();
       
  1551     if ( error == NmNotFoundError ) {
       
  1552         NmUtilities::displayErrorNote(hbTrId("txt_mail_dialog_unable_to_open_attachment_file_ty")); 
       
  1553     }
       
  1554 }
       
  1555 
       
  1556 /*!
       
  1557    Enables/disables toolbar extension for attach
       
  1558 */
       
  1559 void NmEditorView::enableToolBarAttach(bool enable)
       
  1560 {
       
  1561     NM_FUNCTION;
       
  1562     
       
  1563     HbToolBar *tb = toolBar();
       
  1564     if (tb) {
       
  1565         QList<QAction *> toolbarList = tb->actions();
       
  1566         int count = toolbarList.count();
       
  1567         for (int i = 0; i < count; i++) {
       
  1568             NmAction *action = static_cast<NmAction *>(toolbarList[i]);
       
  1569             if (action->availabilityCondition() == NmAction::NmAttachable) {
       
  1570                 action->setEnabled(enable);
       
  1571                 if (enable) {
       
  1572                     // For some reason 'Add attachment' toolbar button stays dimmed sometimes,
       
  1573                     // showItems will fix the situation.
       
  1574                     showItems(Hb::ToolBarItem);
       
  1575                 }
       
  1576             }
       
  1577         }
       
  1578     }
       
  1579 }