emailuis/nmailui/src/nmeditorview.cpp
changeset 43 99bcbff212ad
parent 40 2c62ef3caffd
child 44 c2d07d913565
equal deleted inserted replaced
42:139d4b7b2938 43:99bcbff212ad
    36 */
    36 */
    37 NmEditorView::NmEditorView(
    37 NmEditorView::NmEditorView(
    38     NmApplication &application,
    38     NmApplication &application,
    39     NmUiStartParam* startParam,
    39     NmUiStartParam* startParam,
    40     NmUiEngine &uiEngine,
    40     NmUiEngine &uiEngine,
       
    41     NmAttachmentManager &attaManager,
    41     QGraphicsItem *parent)
    42     QGraphicsItem *parent)
    42     : NmBaseView(startParam, application, parent),
    43     : NmBaseView(startParam, application, parent),
    43       mApplication(application),
    44       mApplication(application),
    44       mUiEngine(uiEngine),
    45       mUiEngine(uiEngine),
       
    46       mAttaManager(attaManager),
    45       mDocumentLoader(NULL),
    47       mDocumentLoader(NULL),
    46       mScrollArea(NULL),
    48       mScrollArea(NULL),
    47       mEditWidget(NULL),
    49       mEditWidget(NULL),
    48       mHeaderWidget(NULL),
    50       mHeaderWidget(NULL),
    49       mMessage(NULL),
    51       mMessage(NULL),
    50       mContentWidget(NULL),
    52       mContentWidget(NULL),
    51       mAttachmentListContextMenu(NULL),
    53       mAttachmentListContextMenu(NULL),
    52       mMessageCreationOperation(NULL),
    54       mMessageCreationOperation(NULL),
    53       mAddAttachmentOperation(NULL),
    55       mAddAttachmentOperation(NULL),
    54       mRemoveAttachmentOperation(NULL),
    56       mRemoveAttachmentOperation(NULL),
    55       mCheckOutboxOperation(NULL),
       
    56       mWaitDialog(NULL),
    57       mWaitDialog(NULL),
    57       mQueryDialog(NULL),
    58       mQueryDialog(NULL),
    58       mAttachmentPicker(NULL),
    59       mAttachmentPicker(NULL),
    59       mCcBccFieldVisible(false)
    60       mCcBccFieldVisible(false),
    60 {
    61       mServiceSendingDialog(NULL)
       
    62 {
       
    63     NM_FUNCTION;
       
    64     
    61     mDocumentLoader	= new HbDocumentLoader();
    65     mDocumentLoader	= new HbDocumentLoader();
    62     // Set object name
    66     // Set object name
    63     setObjectName("NmEditorView");
    67     setObjectName("NmEditorView");
    64     // Set mailbox name to title pane
    68     // Set mailbox name to title pane
    65     setMailboxName();
    69     setMailboxName();
    70 /*!
    74 /*!
    71     Destructor
    75     Destructor
    72 */
    76 */
    73 NmEditorView::~NmEditorView()
    77 NmEditorView::~NmEditorView()
    74 {
    78 {
       
    79     NM_FUNCTION;
       
    80     
    75     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
    81     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
    76         mRemoveAttachmentOperation->cancelOperation();
    82         mRemoveAttachmentOperation->cancelOperation();
    77     }
    83     }
    78     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
    84     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
    79         mAddAttachmentOperation->cancelOperation();
    85         mAddAttachmentOperation->cancelOperation();
    80     }
    86     }
    81     if (mMessageCreationOperation && mMessageCreationOperation->isRunning()) {
    87     if (mMessageCreationOperation && mMessageCreationOperation->isRunning()) {
    82         mMessageCreationOperation->cancelOperation();
    88         mMessageCreationOperation->cancelOperation();
    83     }
       
    84     if (mCheckOutboxOperation && mCheckOutboxOperation->isRunning()) {
       
    85         mCheckOutboxOperation->cancelOperation();
       
    86     }
    89     }
    87     delete mMessage;
    90     delete mMessage;
    88     mWidgetList.clear();
    91     mWidgetList.clear();
    89     delete mDocumentLoader;
    92     delete mDocumentLoader;
    90     delete mContentWidget;
    93     delete mContentWidget;
    95         delete mAttachmentListContextMenu;
    98         delete mAttachmentListContextMenu;
    96     }
    99     }
    97     delete mWaitDialog;
   100     delete mWaitDialog;
    98     delete mQueryDialog;
   101     delete mQueryDialog;
    99     delete mAttachmentPicker;    
   102     delete mAttachmentPicker;    
       
   103     mAttaManager.clearObserver();
       
   104     mAttaManager.cancelFetch();
   100 }
   105 }
   101 
   106 
   102 /*!
   107 /*!
   103     View layout loading from XML
   108     View layout loading from XML
   104 */
   109 */
   105 void NmEditorView::loadViewLayout()
   110 void NmEditorView::loadViewLayout()
   106 {
   111 {
       
   112     NM_FUNCTION;
       
   113     
   107     mPrioritySubMenu = NULL;
   114     mPrioritySubMenu = NULL;
   108 
   115 
   109     // Use document loader to load the view
   116     // Use document loader to load the view
   110     bool ok = false;
   117     bool ok = false;
   111     mWidgetList = mDocumentLoader->load(NMUI_EDITOR_VIEW_XML, &ok);
   118     mWidgetList = mDocumentLoader->load(NMUI_EDITOR_VIEW_XML, &ok);
   142     Typically when view is already open and external view activation occurs
   149     Typically when view is already open and external view activation occurs
   143     for this same view
   150     for this same view
   144 */
   151 */
   145 void NmEditorView::reloadViewContents(NmUiStartParam* startParam)
   152 void NmEditorView::reloadViewContents(NmUiStartParam* startParam)
   146 {
   153 {
       
   154     NM_FUNCTION;
       
   155     
   147     // Check start parameter validity.
   156     // Check start parameter validity.
   148     if (startParam&&startParam->viewId()==NmUiViewMessageEditor) {
   157     if (startParam&&startParam->viewId()==NmUiViewMessageEditor) {
   149         // Delete existing start parameter data
   158         // Delete existing start parameter data
   150         delete mStartParam;
   159         delete mStartParam;
   151         mStartParam=NULL;
   160         mStartParam=NULL;
   153         mStartParam=startParam;
   162         mStartParam=startParam;
   154         // Store existing edited message to drafts and reload
   163         // Store existing edited message to drafts and reload
   155         // editor with new start parameters.
   164         // editor with new start parameters.
   156         // ..
   165         // ..
   157         // Reload editor with new message data
   166         // Reload editor with new message data
   158         setMessageData();
   167         fetchMessageIfNeeded();
   159     }
   168     }
   160     else {
   169     else {
   161         NMLOG("nmailui: Invalid editor start parameter");
   170         NM_ERROR(1,"nmailui: Invalid editor start parameter");
   162         // Unused start parameter needs to be deleted
   171         // Unused start parameter needs to be deleted
   163         delete startParam;
   172         delete startParam;
   164         startParam = NULL;
   173         startParam = NULL;
   165     }
   174     }
   166 }
   175 }
   170    landscape <-> portrait switch occurs because text needs to
   179    landscape <-> portrait switch occurs because text needs to
   171    be wrapped again.
   180    be wrapped again.
   172 */
   181 */
   173 void NmEditorView::orientationChanged(Qt::Orientation orientation)
   182 void NmEditorView::orientationChanged(Qt::Orientation orientation)
   174 {
   183 {
       
   184     NM_FUNCTION;
       
   185     
   175     Q_UNUSED(orientation);
   186     Q_UNUSED(orientation);
   176     // Adjust content height
   187     // Adjust content height
   177     QTimer::singleShot(NmOrientationTimer, this, SLOT(adjustViewDimensions()));
   188     QTimer::singleShot(NmOrientationTimer, this, SLOT(adjustViewDimensions()));
   178     QTimer::singleShot(NmOrientationTimer, mHeaderWidget, SLOT(sendHeaderHeightChanged()));
   189     QTimer::singleShot(NmOrientationTimer, mHeaderWidget, SLOT(sendHeaderHeightChanged()));
   179 }
   190 }
   181 /*!
   192 /*!
   182     Set new dimensions after orientation change.
   193     Set new dimensions after orientation change.
   183 */
   194 */
   184 void NmEditorView::adjustViewDimensions()
   195 void NmEditorView::adjustViewDimensions()
   185 {
   196 {
       
   197     NM_FUNCTION;
       
   198     
   186     if (mScrollAreaContents) {
   199     if (mScrollAreaContents) {
   187         const QSize reso = mApplication.screenSize();
   200         const QSize reso = mApplication.screenSize();
   188         mScrollAreaContents->setMinimumWidth(reso.width());
   201         mScrollAreaContents->setMinimumWidth(reso.width());
   189         mScrollAreaContents->setMaximumWidth(reso.width());
   202         mScrollAreaContents->setMaximumWidth(reso.width());
   190     }
   203     }
   193 /*!
   206 /*!
   194     View id
   207     View id
   195 */
   208 */
   196 NmUiViewId NmEditorView::nmailViewId() const
   209 NmUiViewId NmEditorView::nmailViewId() const
   197 {
   210 {
       
   211     NM_FUNCTION;
       
   212     
   198     return NmUiViewMessageEditor;
   213     return NmUiViewMessageEditor;
   199 }
   214 }
   200 
   215 
   201 /*!
   216 /*!
   202     ScrollArea contents
   217     ScrollArea contents
   203 */
   218 */
   204 HbWidget* NmEditorView::scrollAreaContents()
   219 HbWidget* NmEditorView::scrollAreaContents()
   205 {
   220 {
       
   221     NM_FUNCTION;
       
   222     
   206     return mScrollAreaContents;
   223     return mScrollAreaContents;
   207 }
   224 }
   208 
   225 
   209 /*
   226 /*
   210    Launch dialog for query user if we want to exit the editor
   227    Launch dialog for query user if we want to exit the editor
   211 */
   228 */
   212 void NmEditorView::okToExitView()
   229 void NmEditorView::okToExitView()
   213 {
   230 {
       
   231     NM_FUNCTION;
       
   232     
   214     NmEditorHeader *header = mContentWidget->header();
   233     NmEditorHeader *header = mContentWidget->header();
   215     
   234     
   216     bool okToExit = true;
   235     bool okToExit = true;
   217     
   236     
   218     // show the query if the message has not been sent
   237     // show the query if the message has not been sent
   219     if (mMessage && header) {
   238     if (mMessage && header) {
   220         // see if editor has any content
   239         // see if editor has any content
   221         int toTextLength = 0;
       
   222         if (header->toEdit()) {
       
   223             toTextLength = header->toEdit()->text().length();
       
   224         }
       
   225         
       
   226         int ccTextLength = 0;
       
   227         if (header->ccEdit()) {
       
   228             ccTextLength = header->ccEdit()->text().length();
       
   229         }
       
   230 
       
   231         int bccTextLength = 0;
       
   232         if (header->bccEdit()) {
       
   233             bccTextLength = header->bccEdit()->text().length();
       
   234         }
       
   235         
       
   236         int subjectLength = 0;
   240         int subjectLength = 0;
   237         if (header->subjectEdit()) {
   241         if (header->subjectEdit()) {
   238             subjectLength = header->subjectEdit()->text().length();
   242             subjectLength = header->subjectEdit()->text().length();
   239         }
   243         }
   240         
   244         
   241         QList<NmMessagePart*> attachmentList;
   245         QList<NmMessagePart*> attachmentList;
   242         mMessage->attachmentList(attachmentList);
   246         mMessage->attachmentList(attachmentList);
   243                     
   247                     
   244         okToExit = (toTextLength == 0 && ccTextLength == 0 && bccTextLength == 0 && 
   248         okToExit = (subjectLength == 0 && mContentWidget->editor()->document()->isEmpty());
   245             subjectLength == 0 && mContentWidget->editor()->document()->isEmpty() &&
       
   246             attachmentList.count() < 1);
       
   247 
   249 
   248         // content exists, verify exit from user
   250         // content exists, verify exit from user
   249         if (!okToExit) {
   251         if (!okToExit) {
   250             if (mQueryDialog) {
   252             if (mQueryDialog) {
   251                 delete mQueryDialog;
   253                 delete mQueryDialog;
   252                 mQueryDialog = 0;
   254                 mQueryDialog = 0;
   253             }
   255             }
   254             // Launch query dialog.
   256             // Launch query dialog.
   255             mQueryDialog = NmUtilities::displayQuestionNote(hbTrId("txt_mail_dialog_delete_message"),
   257             mQueryDialog = 
       
   258                 NmUtilities::displayQuestionNote(hbTrId("txt_mail_dialog_save_message_to_drafts"),
   256                                                             this,
   259                                                             this,
   257                                                             SLOT(okToExitQuery(HbAction*)));
   260                                                             SLOT(okToExitQuery(HbAction*)));
   258         }
   261         }
   259     }
   262     }
   260     
   263     
   269 /*!
   272 /*!
   270     Handle the user selection is it ok to exit.
   273     Handle the user selection is it ok to exit.
   271 */
   274 */
   272 void NmEditorView::okToExitQuery(HbAction* action)
   275 void NmEditorView::okToExitQuery(HbAction* action)
   273 {
   276 {
   274     // Check that 'Yes' button was pressed. Use loc string 'txt_mail_dialog_yes' when possible.
   277     NM_FUNCTION;
   275     if (action->text() == "Yes") {
   278     
   276         QMetaObject::invokeMethod(&mApplication,
   279     HbMessageBox *dlg = static_cast<HbMessageBox*>(sender());
   277                                   "popView",
   280     // The first action in dialogs action list is for the "Yes"-button.
   278                                   Qt::QueuedConnection);
   281     if (action == dlg->actions().at(0)) {
   279     }
   282         
       
   283         // Save message to drafts
       
   284         QList<NmOperation *> preliminaryOperations;
       
   285         if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
       
   286             preliminaryOperations.append(mAddAttachmentOperation);
       
   287         }
       
   288         if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
       
   289             preliminaryOperations.append(mRemoveAttachmentOperation);
       
   290         }
       
   291         // ownership of mMessage is transferred
       
   292         // NmOperations are automatically deleted after completion
       
   293         mUiEngine.saveDraftMessage(mMessage, preliminaryOperations);
       
   294         mMessage = NULL;
       
   295         preliminaryOperations.clear();
       
   296     }    
       
   297     
       
   298     // Close the view
       
   299     QMetaObject::invokeMethod(&mApplication,
       
   300                               "popView",
       
   301                               Qt::QueuedConnection);
   280 }
   302 }
   281 
   303 
   282 /*!
   304 /*!
   283     About to exit view. Application calls this function when user has
   305     About to exit view. Application calls this function when user has
   284     pressed back key and editor needs to delete the draft message. This is
   306     pressed back key and editor needs to delete the draft message. This is
   285     called when "auto-exiting" after a successful mail sending.
   307     called when "auto-exiting" after a successful mail sending.
   286 */
   308 */
   287 void NmEditorView::aboutToExitView()
   309 void NmEditorView::aboutToExitView()
   288 {
   310 {
   289     if (mStartParam && mStartParam->service() && mUiEngine.isSendingMessage()) {
   311     NM_FUNCTION;
   290         // The application was started as a service and is about to close.
   312     
   291         // A message is still being sent and in order to make sure that the
       
   292         // send operation is not cancelled, let us display a modal wait dialog.
       
   293 
       
   294         // When the send operation is completed, the dialog is automatically
       
   295         // closed.
       
   296         connect(&mUiEngine, SIGNAL(sendOperationCompleted()),
       
   297                 this, SLOT(handleSendOperationCompleted()));
       
   298 
       
   299         // Close and delete the previous wait dialog if one exists.
       
   300         if (mWaitDialog) {
       
   301             mWaitDialog->close();
       
   302             delete mWaitDialog;
       
   303         }
       
   304 
       
   305         // Construct and setup the wait dialog.
       
   306         mWaitDialog = new HbProgressDialog();
       
   307         mWaitDialog->setText(hbTrId("txt_mail_shareui_sending_please_wait"));
       
   308 
       
   309         if (!XQServiceUtil::isEmbedded()) {
       
   310             // Hide the application.
       
   311             XQServiceUtil::toBackground(true);
       
   312         }
       
   313 
       
   314         // Display the wait dialog.
       
   315         mWaitDialog->setModal(false);
       
   316         mWaitDialog->setBackgroundFaded(false);
       
   317         mWaitDialog->show();
       
   318         delete mWaitDialog;
       
   319         mWaitDialog = NULL;
       
   320     }
       
   321 
       
   322     // These operations need to be stopped before message can be deleted
   313     // These operations need to be stopped before message can be deleted
   323     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
   314     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
   324         mAddAttachmentOperation->cancelOperation();
   315         mAddAttachmentOperation->cancelOperation();
   325     }
   316     }
   326     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
   317     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
   327         mRemoveAttachmentOperation->cancelOperation();
   318         mRemoveAttachmentOperation->cancelOperation();
   328     }
   319     }
   329 
   320 
   330     if (mMessage) { // this is NULL if sending is started
   321     if (mMessage) { // this is NULL if sending is started
   331         // Delete message from drafts
   322         // Delete message from drafts
   332         NmId mailboxId = mMessage->envelope().mailboxId();
   323         mUiEngine.removeDraftMessage(mMessage);
   333         NmId folderId = mMessage->envelope().folderId();
   324         mMessage = NULL;
   334         NmId msgId = mMessage->envelope().messageId();
       
   335         mUiEngine.removeMessage(mailboxId, folderId, msgId);
       
   336     }
   325     }
   337 }
   326 }
   338 
   327 
   339 /*!
   328 /*!
   340     Lazy loading when view layout has been loaded
   329     Lazy loading when view layout has been loaded
   341 */
   330 */
   342 void NmEditorView::viewReady()
   331 void NmEditorView::viewReady()
   343 {
   332 {
   344     // Connect signals from background scroll area
   333     NM_FUNCTION;
   345     connect(mScrollArea, SIGNAL(handleMousePressEvent(QGraphicsSceneMouseEvent*)),
   334     
   346             this, SLOT(sendMousePressEventToScroll(QGraphicsSceneMouseEvent*)));
       
   347     connect(mScrollArea, SIGNAL(handleMouseReleaseEvent(QGraphicsSceneMouseEvent*)),
       
   348             this, SLOT(sendMouseReleaseEventToScroll(QGraphicsSceneMouseEvent*)));
       
   349     connect(mScrollArea, SIGNAL(handleMouseMoveEvent(QGraphicsSceneMouseEvent*)),
       
   350             this, SLOT(sendMouseMoveEventToScroll(QGraphicsSceneMouseEvent*)));
       
   351 
       
   352     connect(mScrollArea, SIGNAL(handleLongPressGesture(const QPointF &)),
       
   353                 this, SLOT(sendLongPressGesture(const QPointF &)));
       
   354 
       
   355     // Connect options menu about to show to create options menu function
   335     // Connect options menu about to show to create options menu function
   356     // Menu needs to be create "just-in-time"
   336     // Menu needs to be create "just-in-time"
   357     connect(menu(), SIGNAL(aboutToShow()), this, SLOT(createOptionsMenu()));
   337     connect(menu(), SIGNAL(aboutToShow()), this, SLOT(createOptionsMenu()));
   358     NmAction *dummy = new NmAction(0);
   338     NmAction *dummy = new NmAction(0);
   359     menu()->addAction(dummy);
   339     menu()->addAction(dummy);
   374     // Signal for handling the attachment list selection
   354     // Signal for handling the attachment list selection
   375     connect(mHeaderWidget, SIGNAL(attachmentLongPressed(NmId, QPointF)),
   355     connect(mHeaderWidget, SIGNAL(attachmentLongPressed(NmId, QPointF)),
   376             this, SLOT(attachmentLongPressed(NmId, QPointF)));
   356             this, SLOT(attachmentLongPressed(NmId, QPointF)));
   377     
   357     
   378     // Set message data
   358     // Set message data
   379     setMessageData();
   359     fetchMessageIfNeeded();
   380 }
   360 }
   381 
   361 
   382 /*!
   362 /*!
   383     Find message data based on start parameters.  Method is called
   363     If entering editor for forwarding or replying, use attachment manager
   384     when editor is started. If message data is found it means that
   364     to check that we have all message parts fetched. Also show dialog for
   385     operation is forward or reply message.
   365     fetching progress.
   386 */
   366 */
   387 void NmEditorView::setMessageData()
   367 void NmEditorView::fetchMessageIfNeeded()
   388 {
   368 {
   389     // Check the outbox.
   369     NM_FUNCTION;
   390     if (mCheckOutboxOperation && mCheckOutboxOperation->isRunning()) {
   370     
   391         mCheckOutboxOperation->cancelOperation();
   371     if (mStartParam->editorStartMode() == NmUiEditorForward ||
   392         NMLOG("NmEditorView::setMessageData old mCheckOutboxOperation running");
   372         mStartParam->editorStartMode() == NmUiEditorReply ||
   393     }
   373         mStartParam->editorStartMode() == NmUiEditorReplyAll) {
   394 	
   374         
   395     mCheckOutboxOperation = mUiEngine.checkOutbox(mStartParam->mailboxId());
   375         fetchProgressDialogShow();
   396     
   376         mAttaManager.clearObserver();
   397     if (mCheckOutboxOperation) {
   377         mAttaManager.setObserver(this);
   398         connect(mCheckOutboxOperation, SIGNAL(operationCompleted(int)),
   378         mAttaManager.fetchAllMessageParts(
   399                 this, SLOT(outboxChecked(int)));
   379             mStartParam->mailboxId(),
       
   380             mStartParam->folderId(),
       
   381             mStartParam->messageId());
   400     }
   382     }
   401     else {
   383     else {
   402         startMessageCreation( mStartParam->editorStartMode() );
   384         startMessageCreation(mStartParam->editorStartMode());
   403     }
   385     }
   404 }
   386 }
   405 
   387 
   406 /*!
   388 /*!
   407 */
   389     Slot. Called when attachments fetch progress changes.
       
   390 */
       
   391 void NmEditorView::progressChanged(int value)
       
   392 {
       
   393     NM_FUNCTION;
       
   394     
       
   395     Q_UNUSED(value);
       
   396 }
       
   397 
       
   398 /*!
       
   399     Slot. Called when attachments fetch is completed. We can start
       
   400     message creation. 
       
   401 */
       
   402 void NmEditorView::fetchCompleted(int result)
       
   403 {
       
   404     NM_FUNCTION;
       
   405     
       
   406     if (result == NmNoError) {
       
   407         startMessageCreation(mStartParam->editorStartMode());
       
   408     }
       
   409     else {
       
   410         mWaitDialog->close();
       
   411         QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
   412     }
       
   413 }
       
   414 
       
   415 void NmEditorView::fetchProgressDialogShow()
       
   416 {
       
   417     NM_FUNCTION;
       
   418     
       
   419     delete mWaitDialog;
       
   420     mWaitDialog = NULL;
       
   421     // Create new wait dialog and set it to me modal with dimmed background
       
   422     mWaitDialog = new HbProgressDialog(HbProgressDialog::WaitDialog);
       
   423     mWaitDialog->setModal(true);
       
   424     mWaitDialog->setBackgroundFaded(true);
       
   425     connect(mWaitDialog, SIGNAL(cancelled()), this, SLOT(fetchProgressDialogCancelled()));
       
   426     mWaitDialog->setText(hbTrId("txt_mail_dialog_loading_mail_content"));
       
   427     // Display wait dialog
       
   428     mWaitDialog->show();
       
   429 }
       
   430 
       
   431 /*!
       
   432     This is called by mFetchProgressDialog when the note is cancelled
       
   433  */
       
   434 void NmEditorView::fetchProgressDialogCancelled()
       
   435 {
       
   436     NM_FUNCTION;
       
   437     
       
   438     if (mAttaManager.isFetching()) {
       
   439         mAttaManager.cancelFetch();
       
   440         mAttaManager.clearObserver();
       
   441     }
       
   442     QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
   443 }
       
   444 
   408 void NmEditorView::startMessageCreation(NmUiEditorStartMode startMode)
   445 void NmEditorView::startMessageCreation(NmUiEditorStartMode startMode)
   409 {
   446 {
   410     NMLOG("NmEditorView::startMessageCreation ");
   447     NM_FUNCTION;
       
   448     
   411     NmId mailboxId = mStartParam->mailboxId();
   449     NmId mailboxId = mStartParam->mailboxId();
   412     NmId folderId = mStartParam->folderId();
   450     NmId folderId = mStartParam->folderId();
   413     NmId msgId = mStartParam->messageId();
   451     NmId msgId = mStartParam->messageId();
   414     
   452     
   415     if (mMessageCreationOperation && mMessageCreationOperation->isRunning()) {
   453     if (mMessageCreationOperation && mMessageCreationOperation->isRunning()) {
   441 /*!
   479 /*!
   442     Starting the message sending is handled here.
   480     Starting the message sending is handled here.
   443 */
   481 */
   444 void NmEditorView::startSending()
   482 void NmEditorView::startSending()
   445 {
   483 {
       
   484     NM_FUNCTION;
       
   485     
   446     // The message contents should be verified
   486     // The message contents should be verified
   447     updateMessageWithEditorContents();
   487     updateMessageWithEditorContents();
   448     
   488     
   449     // verify addresses before sending
   489     // verify addresses before sending
   450     QList<NmAddress> invalidAddresses;
   490     QList<NmAddress> invalidAddresses;
   477 /*!
   517 /*!
   478     Send the message after all checks have been done.
   518     Send the message after all checks have been done.
   479 */
   519 */
   480 void NmEditorView::finalizeSending()
   520 void NmEditorView::finalizeSending()
   481 {
   521 {
       
   522     NM_FUNCTION;
       
   523     
   482     QList<NmOperation *> preliminaryOperations;
   524     QList<NmOperation *> preliminaryOperations;
   483     preliminaryOperations.append(mAddAttachmentOperation);
   525     if (mAddAttachmentOperation && mAddAttachmentOperation->isRunning()) {
   484     preliminaryOperations.append(mRemoveAttachmentOperation);
   526         preliminaryOperations.append(mAddAttachmentOperation);
       
   527     }
       
   528     if (mRemoveAttachmentOperation && mRemoveAttachmentOperation->isRunning()) {
       
   529         preliminaryOperations.append(mRemoveAttachmentOperation);
       
   530     }
   485     // ownership of mMessage is transferred
   531     // ownership of mMessage is transferred
   486     // NmOperations are automatically deleted after completion
   532     // NmOperations are automatically deleted after completion
   487     mUiEngine.sendMessage(mMessage, preliminaryOperations);
   533     mUiEngine.sendMessage(mMessage, preliminaryOperations);
   488     mMessage = NULL;
   534     mMessage = NULL;
   489     preliminaryOperations.clear();
   535     preliminaryOperations.clear();
   490     // Must use delayed editor view destruction so that query dialog
   536 
   491     // (which has signaled this) gets time to complete.
   537 #ifndef NM_WINS_ENV
   492     QMetaObject::invokeMethod(&mApplication,
   538     bool service = XQServiceUtil::isService();
   493                               "popView",
   539 #else
   494                               Qt::QueuedConnection);
   540     bool service = false;
       
   541 #endif
       
   542 
       
   543     // If sending is started as a service, progress dialog needs to be shown
       
   544     // so long that sending is finished otherwise we can close pop current view.
       
   545     if (service && mUiEngine.isSendingMessage()) {
       
   546         connect(&mUiEngine, SIGNAL(sendOperationCompleted()),
       
   547             this, SLOT(handleSendOperationCompleted()), Qt::UniqueConnection);
       
   548 
       
   549         // Construct and setup the wait dialog.
       
   550         mServiceSendingDialog = new HbProgressDialog(HbProgressDialog::WaitDialog);
       
   551         mServiceSendingDialog->setAttribute(Qt::WA_DeleteOnClose);
       
   552         mServiceSendingDialog->setText(hbTrId("txt_mail_shareui_sending_please_wait"));
       
   553         connect(mServiceSendingDialog, SIGNAL(cancelled()),
       
   554             this, SLOT(sendProgressDialogCancelled()));
       
   555 
       
   556 #ifndef NM_WINS_ENV
       
   557         if (!XQServiceUtil::isEmbedded()) {
       
   558             // Hide the application.
       
   559             XQServiceUtil::toBackground(true);
       
   560         }
       
   561 #endif
       
   562          // Display the wait dialog.
       
   563          mServiceSendingDialog->setModal(true);
       
   564          mServiceSendingDialog->setBackgroundFaded(true);
       
   565          mServiceSendingDialog->show();
       
   566     } else {
       
   567         // Must use delayed editor view destruction so that query dialog
       
   568         // (which has signaled this) gets time to complete.
       
   569         QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
   570     }
   495 }
   571 }
   496 
   572 
   497 /*!
   573 /*!
   498     Handle the user selection for invalid address query which was started by startSending.
   574     Handle the user selection for invalid address query which was started by startSending.
   499 */
   575 */
   500 void NmEditorView::invalidAddressQuery(HbAction* action)
   576 void NmEditorView::invalidAddressQuery(HbAction* action)
   501 {
   577 {
   502     // Check that 'Yes' button was pressed. Use loc string 'txt_mail_dialog_yes' when possible.
   578     NM_FUNCTION;
   503     if (action->text() == "Yes") {
   579 
       
   580     HbMessageBox *dlg = static_cast<HbMessageBox*>(sender());
       
   581     // The first action in dialogs action list is for the "Yes"-button.
       
   582     if (action == dlg->actions().at(0)) {
   504         finalizeSending();
   583         finalizeSending();
   505     }
   584     }
   506 }
   585 }
   507 
   586 
   508 /*!
   587 /*!
   509     This is signalled by mMessageCreationOperation when message is created.
   588     This is signalled by mMessageCreationOperation when message is created.
   510 */
   589 */
   511 void NmEditorView::messageCreated(int result)
   590 void NmEditorView::messageCreated(int result)
   512 {
   591 {
       
   592     NM_FUNCTION;
       
   593     
   513     delete mMessage;
   594     delete mMessage;
   514     mMessage = NULL;
   595     mMessage = NULL;
   515 
   596 
       
   597     // Close wait dialog here
       
   598     if (mWaitDialog) {
       
   599         mWaitDialog->close();
       
   600     }
       
   601     
   516     if (result == NmNoError && mMessageCreationOperation) {
   602     if (result == NmNoError && mMessageCreationOperation) {
   517         NmUiEditorStartMode startMode = mStartParam->editorStartMode();
   603         NmUiEditorStartMode startMode = mStartParam->editorStartMode();
   518         
   604         
   519         // get message "again" from engine to update the message contents 
   605         // get message "again" from engine to update the message contents 
   520         mMessage = mUiEngine.message(
   606         mMessage = mUiEngine.message(
   529 /*!
   615 /*!
   530    Updates the message with the editor contents.
   616    Updates the message with the editor contents.
   531 */
   617 */
   532 void NmEditorView::updateMessageWithEditorContents()
   618 void NmEditorView::updateMessageWithEditorContents()
   533 {
   619 {
       
   620     NM_FUNCTION;
       
   621     
   534     if (mMessage) {
   622     if (mMessage) {
   535         if (mContentWidget && mContentWidget->editor()) {
   623         if (mContentWidget && mContentWidget->editor()) {
   536             NmMessagePart* bodyPart = mMessage->htmlBodyPart();
   624             NmMessagePart* bodyPart = mMessage->htmlBodyPart();
   537             if (bodyPart) {
   625             if (bodyPart) {
   538                 bodyPart->setTextContent(mContentWidget->editor()->toHtml(), NmContentTypeTextHtml);
   626                 bodyPart->setTextContent(mContentWidget->editor()->toHtml(), NmContentTypeTextHtml);
   582     Updates the message with the editor contents. Called only once when the
   670     Updates the message with the editor contents. Called only once when the
   583     editor is launched.
   671     editor is launched.
   584 */
   672 */
   585 void NmEditorView::fillEditorWithMessageContents()
   673 void NmEditorView::fillEditorWithMessageContents()
   586 {
   674 {
       
   675     NM_FUNCTION;
       
   676     
   587     if (!mMessage || !mContentWidget) {
   677     if (!mMessage || !mContentWidget) {
   588         return;
   678         return;
   589     }
   679     }
   590 
   680 
   591     NmMessageEnvelope messageEnvelope(mMessage->envelope());
   681     NmMessageEnvelope messageEnvelope(mMessage->envelope());
   634         if (subject) {
   724         if (subject) {
   635             mContentWidget->header()->subjectEdit()->setPlainText(*subject);
   725             mContentWidget->header()->subjectEdit()->setPlainText(*subject);
   636         }
   726         }
   637     }
   727     }
   638     else {
   728     else {
   639         // If a message is taken from the outbox, no subject formatting is done.
       
   640         NmId notUsed(0);
       
   641 
       
   642         if (mCheckOutboxOperation &&
       
   643             mCheckOutboxOperation->getMessageId(notUsed)) {
       
   644             editorStartMode = NmUiEditorCreateNew;
       
   645         }
       
   646 
       
   647         // Construct the subject field.
   729         // Construct the subject field.
   648         mContentWidget->header()->subjectEdit()->setPlainText(
   730         mContentWidget->header()->subjectEdit()->setPlainText(
   649             addSubjectPrefix(editorStartMode, messageEnvelope.subject()));
   731             addSubjectPrefix(editorStartMode, messageEnvelope.subject()));
   650     }
   732     }
   651 
   733 
   652     // Set priority.
   734     // Set priority.
   653     mHeaderWidget->setPriority(messageEnvelope.priority());
   735     mHeaderWidget->setPriority(messageEnvelope.priority());
   654     
   736     
   655     // Set the message body.
   737     // Set the message body.
   656     // Fetch plain text part form message store.
       
   657     NmMessagePart *plainPart = mMessage->plainTextBodyPart();
       
   658 
       
   659     if (plainPart) {
       
   660         mUiEngine.contentToMessagePart(mMessage->envelope().mailboxId(),
       
   661                                        mMessage->envelope().folderId(),
       
   662                                        mMessage->envelope().messageId(),
       
   663                                        *plainPart);
       
   664     }
       
   665 
       
   666     // Fetch html part form message store.
       
   667     NmMessagePart *htmlPart = mMessage->htmlBodyPart();
       
   668 
       
   669     if (htmlPart) {
       
   670         mUiEngine.contentToMessagePart(mMessage->envelope().mailboxId(),
       
   671                                        mMessage->envelope().folderId(),
       
   672                                        mMessage->envelope().messageId(),
       
   673                                        *htmlPart);
       
   674     }
       
   675 
       
   676     // Fetch attachment.html part form message store if such exists.
       
   677     QList<NmMessagePart*> parts;
       
   678     mMessage->attachmentList(parts);
       
   679     NmMessagePart *attachmentHtml = NULL;
       
   680 
       
   681     foreach(NmMessagePart *part, parts) {
       
   682         if (part->contentDescription().startsWith(NmContentDescrAttachmentHtml)) {
       
   683             attachmentHtml = part;
       
   684         }
       
   685     }
       
   686 
       
   687     if (attachmentHtml) {
       
   688         mUiEngine.contentToMessagePart(mMessage->envelope().mailboxId(),
       
   689                                        mMessage->envelope().folderId(),
       
   690                                        mMessage->envelope().messageId(),
       
   691                                        *attachmentHtml);
       
   692     }
       
   693 
       
   694     // Set content data
       
   695     if (editorStartMode==NmUiEditorReply||
   738     if (editorStartMode==NmUiEditorReply||
   696         editorStartMode==NmUiEditorReplyAll||
   739         editorStartMode==NmUiEditorReplyAll||
   697         editorStartMode==NmUiEditorForward){
   740         editorStartMode==NmUiEditorForward){
   698         // Pass envelope ptr only when needed for reaply header creation
   741 
       
   742         // Use the body from the original message.
   699         NmMessage *originalMessage = mUiEngine.message(mStartParam->mailboxId(), 
   743         NmMessage *originalMessage = mUiEngine.message(mStartParam->mailboxId(), 
   700                                                        mStartParam->folderId(), 
   744                                                        mStartParam->folderId(), 
   701                                                        mStartParam->messageId());
   745                                                        mStartParam->messageId());
   702         mContentWidget->setMessageData(*mMessage, &originalMessage->envelope()); 
   746 
       
   747         if (originalMessage) {
       
   748             NmMessagePart *plainPart = originalMessage->plainTextBodyPart();
       
   749 
       
   750             if (plainPart) {
       
   751                 mUiEngine.contentToMessagePart(originalMessage->envelope().mailboxId(),
       
   752                                                originalMessage->envelope().folderId(),
       
   753                                                originalMessage->envelope().messageId(),
       
   754                                                *plainPart);
       
   755             }
       
   756 
       
   757             NmMessagePart *htmlPart = originalMessage->htmlBodyPart();
       
   758 
       
   759             if (htmlPart) {
       
   760                 mUiEngine.contentToMessagePart(originalMessage->envelope().mailboxId(),
       
   761                                                originalMessage->envelope().folderId(),
       
   762                                                originalMessage->envelope().messageId(),
       
   763                                                *htmlPart);
       
   764             }
       
   765 
       
   766             mContentWidget->setMessageData(*originalMessage);
       
   767         }
       
   768 
   703         delete originalMessage;
   769         delete originalMessage;
   704     }
   770         originalMessage = NULL;
   705     else{
       
   706         // Reply header not needed, do not pass envelope ptr
       
   707         mContentWidget->setMessageData(*mMessage);     
       
   708     }
   771     }
   709     
   772     
   710     // Get list of attachments from the message and set those into UI attachment list
   773     // Get list of attachments from the message and set those into UI attachment list
   711     QList<NmMessagePart*> attachments;
   774     QList<NmMessagePart*> attachments;
   712     mMessage->attachmentList(attachments);
   775     mMessage->attachmentList(attachments);
   737     createToolBar. Function asks menu commands from extension
   800     createToolBar. Function asks menu commands from extension
   738     to be added to toolbar owned by the HbView.
   801     to be added to toolbar owned by the HbView.
   739 */
   802 */
   740 void NmEditorView::createToolBar()
   803 void NmEditorView::createToolBar()
   741 {
   804 {
       
   805     NM_FUNCTION;
       
   806     
   742     HbToolBar *tb = toolBar();
   807     HbToolBar *tb = toolBar();
   743     NmUiExtensionManager &extMngr = mApplication.extManager();
   808     NmUiExtensionManager &extMngr = mApplication.extManager();
   744     if (tb && &extMngr && mStartParam) {
   809     if (tb && &extMngr && mStartParam) {
   745         tb->clearActions();
   810         tb->clearActions();
   746         NmActionRequest request(this, NmActionToolbar, NmActionContextViewEditor,
   811         NmActionRequest request(this, NmActionToolbar, NmActionContextViewEditor,
   769                     HbAction* actionMusic = 
   834                     HbAction* actionMusic = 
   770                         extension->addAction(hbTrId("txt_mail_list_music"), extension, SLOT(close()));
   835                         extension->addAction(hbTrId("txt_mail_list_music"), extension, SLOT(close()));
   771                     connect(actionMusic, SIGNAL(triggered()), mAttachmentPicker, SLOT(fetchAudio()));
   836                     connect(actionMusic, SIGNAL(triggered()), mAttachmentPicker, SLOT(fetchAudio()));
   772                     
   837                     
   773                     HbAction* actionVideo = 
   838                     HbAction* actionVideo = 
   774                         extension->addAction(hbTrId("txt_mail_list_video"), extension, SLOT(close()));                
   839                         extension->addAction(hbTrId("txt_mail_list_video"), extension, SLOT(close()));
       
   840                     connect(actionVideo, SIGNAL(triggered()), mAttachmentPicker, SLOT(fetchVideo()));
       
   841                     
   775                     HbAction* actionOther = 
   842                     HbAction* actionOther = 
   776                         extension->addAction(hbTrId("txt_mail_list_other"), extension, SLOT(close()));
   843                         extension->addAction(hbTrId("txt_mail_list_other"), extension, SLOT(close()));
       
   844                     connect(actionOther, SIGNAL(triggered()), mAttachmentPicker, SLOT(fetchOther()));
       
   845                     
       
   846                     HbAction* actionCameraStill = 
       
   847                        extension->addAction(hbTrId("txt_mail_list_new_photo"), extension, SLOT(close()));
       
   848                     connect(actionCameraStill, SIGNAL(triggered()), mAttachmentPicker, SLOT(fetchCameraStill()));
   777             
   849             
       
   850                     HbAction* actionCameraVideo = 
       
   851                         extension->addAction(hbTrId("txt_mail_list_new_video"), extension, SLOT(close()));
       
   852                     connect(actionCameraVideo, SIGNAL(triggered()), mAttachmentPicker, SLOT(fetchCameraVideo()));
       
   853                                         
   778                     list[i]->setToolBarExtension(extension);
   854                     list[i]->setToolBarExtension(extension);
   779                 }
   855                 }
   780             }            
   856             }            
   781         }        
   857         }        
   782     }
   858     }
   786     createOptionsMenu. Functions asks menu commands from extension
   862     createOptionsMenu. Functions asks menu commands from extension
   787     to be added to options menu.
   863     to be added to options menu.
   788 */
   864 */
   789 void NmEditorView::createOptionsMenu()
   865 void NmEditorView::createOptionsMenu()
   790 {
   866 {
       
   867     NM_FUNCTION;
       
   868     
   791     menu()->clearActions();
   869     menu()->clearActions();
   792 
   870 
   793 	// Create CC/BCC options menu object
   871 	// Create CC/BCC options menu object
   794     if (mCcBccFieldVisible) {
   872     if (mCcBccFieldVisible) {
   795         menu()->addAction(hbTrId("txt_mail_opt_hide_cc_bcc"), this, SLOT(switchCcBccFieldVisibility()));
   873         menu()->addAction(hbTrId("txt_mail_opt_hide_cc_bcc"), this, SLOT(switchCcBccFieldVisibility()));
   820 /*!
   898 /*!
   821     Show or hide Cc field
   899     Show or hide Cc field
   822 */
   900 */
   823 void NmEditorView::switchCcBccFieldVisibility()
   901 void NmEditorView::switchCcBccFieldVisibility()
   824 {
   902 {
       
   903     NM_FUNCTION;
       
   904     
   825     if (mCcBccFieldVisible) {
   905     if (mCcBccFieldVisible) {
   826     	mCcBccFieldVisible = false;
   906     	mCcBccFieldVisible = false;
   827     }
   907     }
   828     else {
   908     else {
   829     	mCcBccFieldVisible = true;
   909     	mCcBccFieldVisible = true;
   837     handleActionCommand. From NmActionObserver, extension manager calls this
   917     handleActionCommand. From NmActionObserver, extension manager calls this
   838     call to handle menu command in the UI.
   918     call to handle menu command in the UI.
   839 */
   919 */
   840 void NmEditorView::handleActionCommand(NmActionResponse &actionResponse)
   920 void NmEditorView::handleActionCommand(NmActionResponse &actionResponse)
   841 {
   921 {
       
   922     NM_FUNCTION;
       
   923     
   842     NmActionResponseCommand responseCommand = actionResponse.responseCommand();
   924     NmActionResponseCommand responseCommand = actionResponse.responseCommand();
   843     
   925     
   844     // Handle options menu
   926     // Handle options menu
   845     if (actionResponse.menuType() == NmActionOptionsMenu) {
   927     if (actionResponse.menuType() == NmActionOptionsMenu) {
   846         setPriority(responseCommand);
   928         setPriority(responseCommand);
   848     else if (actionResponse.menuType() == NmActionToolbar) {
   930     else if (actionResponse.menuType() == NmActionToolbar) {
   849         switch (responseCommand) {
   931         switch (responseCommand) {
   850         case NmActionResponseCommandSendMail: {
   932         case NmActionResponseCommandSendMail: {
   851             // Just in case send mail would be somehow accessible during message creation or
   933             // Just in case send mail would be somehow accessible during message creation or
   852             // outobox checking
   934             // outobox checking
   853             if ((!mCheckOutboxOperation || !mCheckOutboxOperation->isRunning()) 
   935             if (!mMessageCreationOperation || !mMessageCreationOperation->isRunning()) {
   854                 && (!mMessageCreationOperation || !mMessageCreationOperation->isRunning())) {
       
   855                 startSending();
   936                 startSending();
   856             }
   937             }
   857             break;
   938             break;
   858         }
   939         }
   859         default:
   940         default:
   875         }
   956         }
   876     }
   957     }
   877 }
   958 }
   878 
   959 
   879 /*!
   960 /*!
   880     This function converts background scroll area coordinate point into
   961     Slot. Cancelled sending progress dialog.
   881     body text editor coordinate point.
   962 */
   882 */
   963 void NmEditorView::sendProgressDialogCancelled()
   883 QPointF NmEditorView::viewCoordinateToEditCoordinate(QPointF orgPoint)
   964 {
   884 {
   965     // Needs to be called before closing the application otherwise nmail panics
   885     QPointF contentWidgetPos = mScrollAreaContents->pos();
   966     // in destruction.
   886     qreal y = orgPoint.y() - mHeaderWidget->headerHeight();
   967     QGraphicsScene *graphicsScene = scene();
   887     y -= contentWidgetPos.y();
   968     if (graphicsScene) {
   888     qreal x = orgPoint.x() - contentWidgetPos.x();
   969         graphicsScene->clearFocus();
   889     return QPointF(x, y);
   970     }
   890 }
   971 
   891 
   972     // Must use delayed editor view destruction so that dialog
   892 /*!
   973     // gets time to complete, closes also nmail.
   893    Send mouse press event to body edit widget
   974     QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
   894 */
   975 }
   895 void NmEditorView::sendMousePressEventToScroll(QGraphicsSceneMouseEvent *event)
       
   896 {
       
   897     if (event && mEditWidget && mHeaderWidget) {
       
   898         event->setPos(viewCoordinateToEditCoordinate(event->pos()));
       
   899         event->setAccepted(true);
       
   900         mEditWidget->sendMousePressEvent(event);
       
   901     }
       
   902 }
       
   903 
       
   904 /*!
       
   905    Send mouse release event to body edit widget
       
   906 */
       
   907 void NmEditorView::sendMouseReleaseEventToScroll(QGraphicsSceneMouseEvent *event)
       
   908 {
       
   909     if (event&& mEditWidget && mHeaderWidget) {
       
   910         event->setPos(viewCoordinateToEditCoordinate(event->pos()));
       
   911         event->setAccepted(true);
       
   912         mEditWidget->sendMouseReleaseEvent(event);
       
   913     }
       
   914 }
       
   915 
       
   916 /*!
       
   917    Send mouse move event to body edit widget
       
   918 */
       
   919 void NmEditorView::sendMouseMoveEventToScroll(QGraphicsSceneMouseEvent *event)
       
   920 {
       
   921     if (event&& mEditWidget && mHeaderWidget) {
       
   922         event->setPos(viewCoordinateToEditCoordinate(event->pos()));
       
   923         event->setAccepted(true);
       
   924         mEditWidget->sendMouseMoveEvent(event);
       
   925     }
       
   926 }
       
   927 
       
   928 void NmEditorView::sendLongPressGesture(const QPointF &point)
       
   929 {
       
   930     if (mEditWidget && mHeaderWidget) {
       
   931         QPointF scenePos = mEditWidget->scenePos();
       
   932         QPointF newPoint = QPointF(point.x()-scenePos.x(), point.y()-scenePos.y());
       
   933         if(mEditWidget->contains(newPoint)) {
       
   934             mEditWidget->sendLongPressEvent(point);
       
   935         }
       
   936     }
       
   937 }
       
   938 
       
   939 
   976 
   940 /*!
   977 /*!
   941    Sets all toolbar and VKB buttons dimmed state. All actions that have the
   978    Sets all toolbar and VKB buttons dimmed state. All actions that have the
   942    availability condition NmSendable set, will be enabled/disabled.
   979    availability condition NmSendable set, will be enabled/disabled.
   943 */
   980 */
   944 void NmEditorView::setButtonsDimming(bool enabled)
   981 void NmEditorView::setButtonsDimming(bool enabled)
   945 {
   982 {
       
   983     NM_FUNCTION;
       
   984     
   946     // Set the toolbar action states
   985     // Set the toolbar action states
   947     HbToolBar *tb = toolBar();
   986     HbToolBar *tb = toolBar();
   948     if (tb) {
   987     if (tb) {
   949         QList<QAction *> toolbarList = tb->actions();
   988         QList<QAction *> toolbarList = tb->actions();
   950         int count = toolbarList.count();
   989         int count = toolbarList.count();
   974     Initialize the Virtual Keyboard to show the "Send" button
  1013     Initialize the Virtual Keyboard to show the "Send" button
   975     for all editors of the view.
  1014     for all editors of the view.
   976 */
  1015 */
   977 void NmEditorView::initializeVKB()
  1016 void NmEditorView::initializeVKB()
   978 {
  1017 {
       
  1018     NM_FUNCTION;
       
  1019     
   979     NmActionRequest request(this, NmActionVKB, NmActionContextViewEditor,
  1020     NmActionRequest request(this, NmActionVKB, NmActionContextViewEditor,
   980          NmActionContextDataNone, mStartParam->mailboxId(), mStartParam->folderId() );
  1021          NmActionContextDataNone, mStartParam->mailboxId(), mStartParam->folderId() );
   981     NmUiExtensionManager &extMngr = mApplication.extManager();
  1022     NmUiExtensionManager &extMngr = mApplication.extManager();
   982     if (&extMngr) {
  1023     if (&extMngr) {
   983         QList<NmAction *> list;
  1024         QList<NmAction *> list;
  1011 /*!
  1052 /*!
  1012     Set mailbox name to title
  1053     Set mailbox name to title
  1013 */
  1054 */
  1014 void NmEditorView::setMailboxName()
  1055 void NmEditorView::setMailboxName()
  1015 {
  1056 {
       
  1057     NM_FUNCTION;
       
  1058     
  1016     if (mStartParam){
  1059     if (mStartParam){
  1017         NmMailboxMetaData *meta = mUiEngine.mailboxById(mStartParam->mailboxId());
  1060         NmMailboxMetaData *meta = mUiEngine.mailboxById(mStartParam->mailboxId());
  1018         if (meta){
  1061         if (meta){
  1019             setTitle(meta->name());
  1062             setTitle(meta->name());
  1020         }
  1063         }
  1025    Adds a prefix to the subject for reply or forward. 
  1068    Adds a prefix to the subject for reply or forward. 
  1026    Strips other occurrences of the prefix from the beginning.
  1069    Strips other occurrences of the prefix from the beginning.
  1027 */
  1070 */
  1028 QString NmEditorView::addSubjectPrefix( NmUiEditorStartMode startMode, const QString &subject )
  1071 QString NmEditorView::addSubjectPrefix( NmUiEditorStartMode startMode, const QString &subject )
  1029 {
  1072 {
       
  1073     NM_FUNCTION;
       
  1074     
  1030     QString newSubject(subject.trimmed());
  1075     QString newSubject(subject.trimmed());
  1031     
  1076     
  1032     if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll || 
  1077     if (startMode == NmUiEditorReply || startMode == NmUiEditorReplyAll || 
  1033         startMode == NmUiEditorForward) {
  1078         startMode == NmUiEditorForward) {
  1034         QString rePrefix(hbTrId("txt_nmailui_reply_subject_prefix"));
  1079         QString rePrefix(hbTrId("txt_nmailui_reply_subject_prefix"));
  1070     This slot is called when 'attachment picker' request has been performed succesfully
  1115     This slot is called when 'attachment picker' request has been performed succesfully
  1071     Parameter 'value' contains file currently one file name but later list of the files. 
  1116     Parameter 'value' contains file currently one file name but later list of the files. 
  1072 */
  1117 */
  1073 void NmEditorView::onAttachmentReqCompleted(const QVariant &value)
  1118 void NmEditorView::onAttachmentReqCompleted(const QVariant &value)
  1074 {
  1119 {
       
  1120     NM_FUNCTION;
       
  1121     
  1075     //temporary fix for music picker back button:
  1122     //temporary fix for music picker back button:
  1076     //it shouldn't emit requestOk signal when nothing is selected
  1123     //it shouldn't emit requestOk signal when nothing is selected
  1077 	if (value.canConvert<QStringList>()) {
  1124 	if (value.canConvert<QStringList>()) {
  1078 	    QStringList list = value.toStringList();
  1125 	    QStringList list = value.toStringList();
  1079         if (!list.at(0).isEmpty()) {
  1126         if (!list.at(0).isEmpty()) {
  1080             addAttachments(list);
  1127             addAttachments(list);
  1081         }
  1128         }
  1082     }
  1129     }
  1083 }
  1130 }
  1084 
  1131 
       
  1132 /*!
       
  1133     This slot is called when 'attachment picker' request has been unsuccesfull
       
  1134     Parameter 'errorCode' is the error code returned by the service
       
  1135     Parameter 'errorMessage' is the error message returned by the service
       
  1136 */
       
  1137 void NmEditorView::onAttachmentsFetchError(int errorCode, const QString& errorMessage)
       
  1138 {
       
  1139     NM_FUNCTION;
       
  1140     NM_COMMENT(QString("Error code: %1").arg(errorCode));
       
  1141     NM_COMMENT(QString("Error message: %1").arg(errorMessage));
       
  1142 }
  1085 
  1143 
  1086 /*!
  1144 /*!
  1087     Closes the wait dialog if one exists.
  1145     Closes the wait dialog if one exists.
  1088     
  1146     
  1089     This slot is called if the mail application has been started as a service
  1147     This slot is called if the mail application has been started as a service
  1090     and is about to close. Closing the application while still sending a message
  1148     and is about to close. Closing the application while still sending a message
  1091     may cause unwanted cancelling of the operation.
  1149     may cause unwanted cancelling of the operation.
  1092 */
  1150 */
  1093 void NmEditorView::handleSendOperationCompleted()
  1151 void NmEditorView::handleSendOperationCompleted()
  1094 {
  1152 {
  1095     if (mWaitDialog) {
  1153     NM_FUNCTION;
  1096         mWaitDialog->close();
  1154 
  1097     }
  1155     if (mServiceSendingDialog) {
  1098 }
  1156         mServiceSendingDialog->close();
  1099 
  1157     }
       
  1158 
       
  1159     // Needs to be called before closing the application otherwise nmail panics
       
  1160     // in destruction.
       
  1161     QGraphicsScene *graphicsScene = scene();
       
  1162     if (graphicsScene) {
       
  1163         graphicsScene->clearFocus();
       
  1164     }
       
  1165 
       
  1166     // Must use delayed editor view destruction so that dialog
       
  1167     // gets time to complete, closes also nmail.
       
  1168     QMetaObject::invokeMethod(&mApplication, "popView", Qt::QueuedConnection);
       
  1169 }
  1100 
  1170 
  1101 /*!
  1171 /*!
  1102     Add list of attachments
  1172     Add list of attachments
  1103 */
  1173 */
  1104 void NmEditorView::addAttachments(const QStringList& fileNames) 
  1174 void NmEditorView::addAttachments(const QStringList& fileNames) 
  1105 {
  1175 {
  1106     NMLOG("NmEditorView::addAttachments");
  1176     NM_FUNCTION;
  1107 
  1177     
  1108     // Add attachment name into UI
  1178     // Add attachment name into UI
  1109     foreach (QString fileName, fileNames)  {
  1179     foreach (QString fileName, fileNames)  {
  1110         // At this phase attachment size and nmid are not known
  1180         // At this phase attachment size and nmid are not known
  1111         mHeaderWidget->addAttachment(fileName, QString("0"), NmId(0));
  1181         mHeaderWidget->addAttachment(fileName, QString("0"), NmId(0));
  1112         NMLOG(fileName);
  1182         NM_COMMENT(fileName);
  1113     }
  1183     }
  1114     //  Cancel previous operation if it's not running.
  1184     //  Cancel previous operation if it's not running.
  1115     if (mAddAttachmentOperation) {
  1185     if (mAddAttachmentOperation) {
  1116         if (!mAddAttachmentOperation->isRunning()) {
  1186         if (!mAddAttachmentOperation->isRunning()) {
  1117             mAddAttachmentOperation->cancelOperation();
  1187             mAddAttachmentOperation->cancelOperation();
  1141     This slot is called to create context menu when attachment has been selected
  1211     This slot is called to create context menu when attachment has been selected
  1142     from UI by longpress.
  1212     from UI by longpress.
  1143 */
  1213 */
  1144 void NmEditorView::attachmentLongPressed(NmId attachmentPartId, QPointF point)
  1214 void NmEditorView::attachmentLongPressed(NmId attachmentPartId, QPointF point)
  1145 {
  1215 {
       
  1216     NM_FUNCTION;
       
  1217     
  1146     // Store id of the attachment to be removed into member.
  1218     // Store id of the attachment to be removed into member.
  1147     // It is used by removeAttachmentTriggered later if 'remove' selected.
  1219     // It is used by removeAttachmentTriggered later if 'remove' selected.
  1148     mSelectedAttachment = attachmentPartId;
  1220     mSelectedAttachment = attachmentPartId;
  1149 	
  1221 	
  1150     if (!mAttachmentListContextMenu) {
  1222     if (!mAttachmentListContextMenu) {
  1173     This is signalled by mAddAttachmentOperation when the operation is
  1245     This is signalled by mAddAttachmentOperation when the operation is
  1174     completed for one attachment.
  1246     completed for one attachment.
  1175 */
  1247 */
  1176 void NmEditorView::oneAttachmentAdded(const QString &fileName, const NmId &msgPartId, int result)
  1248 void NmEditorView::oneAttachmentAdded(const QString &fileName, const NmId &msgPartId, int result)
  1177 {
  1249 {
       
  1250     NM_FUNCTION;
       
  1251     
  1178     if (result == NmNoError && mMessage) {
  1252     if (result == NmNoError && mMessage) {
  1179         // Need to get the message again because new attachment part has been added.
  1253         // Need to get the message again because new attachment part has been added.
  1180         NmId mailboxId = mMessage->envelope().mailboxId();
  1254         NmId mailboxId = mMessage->envelope().mailboxId();
  1181         NmId folderId = mMessage->envelope().folderId();
  1255         NmId folderId = mMessage->envelope().folderId();
  1182         NmId msgId = mMessage->envelope().messageId();
  1256         NmId msgId = mMessage->envelope().messageId();
  1203             }
  1277             }
  1204         }
  1278         }
  1205     }
  1279     }
  1206     else {
  1280     else {
  1207         // Attachment adding failed. Show an error note and remove from UI attachment list.
  1281         // Attachment adding failed. Show an error note and remove from UI attachment list.
  1208         NMLOG(QString("nmailui: attachment adding into message failed: %1").arg(fileName));
  1282         NM_ERROR(1,QString("nmailui: attachment adding into message failed: %1").arg(fileName));
  1209         mHeaderWidget->removeAttachment(fileName);
  1283         mHeaderWidget->removeAttachment(fileName);
  1210     }
  1284     }
  1211 }
  1285 }
  1212 
  1286 
  1213 /*!
  1287 /*!
  1214     This is signalled by mAddAttachmentOperation when the operation is
  1288     This is signalled by mAddAttachmentOperation when the operation is
  1215     completed totally.
  1289     completed totally.
  1216 */
  1290 */
  1217 void NmEditorView::allAttachmentsAdded(int result)
  1291 void NmEditorView::allAttachmentsAdded(int result)
  1218 {
  1292 {
       
  1293     NM_FUNCTION;
       
  1294     
  1219     enableToolBarAttach(true);
  1295     enableToolBarAttach(true);
  1220     if (result != NmNoError) {
  1296     if (result != NmNoError) {
  1221         NmUtilities::displayWarningNote(hbTrId("txt_mail_dialog_unable_to_add_attachment"));
  1297         NmUtilities::displayWarningNote(hbTrId("txt_mail_dialog_unable_to_add_attachment"));
  1222     }
  1298     }
  1223 }
  1299 }
  1224 
  1300 
  1225 /*!
  1301 /*!
  1226     This is signalled by mCheckOutboxOperation when the operation is complete.
       
  1227 */
       
  1228 void NmEditorView::outboxChecked(int result)
       
  1229 {
       
  1230     bool messageInOutbox = false;
       
  1231     
       
  1232     if (result == NmNoError && mCheckOutboxOperation) {
       
  1233 
       
  1234         NmId messageId;
       
  1235         messageInOutbox = mCheckOutboxOperation->getMessageId(messageId);
       
  1236         
       
  1237         if (messageInOutbox) {
       
  1238             delete mMessage;
       
  1239             mMessage = NULL;
       
  1240 
       
  1241             mMessage = mUiEngine.message(
       
  1242                 mStartParam->mailboxId(), 
       
  1243                 mUiEngine.standardFolderId(
       
  1244                     mStartParam->mailboxId(), NmFolderOutbox), 
       
  1245                 messageId);
       
  1246             
       
  1247             fillEditorWithMessageContents();
       
  1248             
       
  1249             if (mMessage) {
       
  1250                 NmUtilities::displayWarningNote(
       
  1251                     hbTrId("txt_mail_dialog_sending failed").arg(
       
  1252                         NmUtilities::truncate(
       
  1253                             mMessage->envelope().subject(), 20)));
       
  1254             }
       
  1255         }
       
  1256     }
       
  1257 
       
  1258     if (!messageInOutbox) {
       
  1259         startMessageCreation(mStartParam->editorStartMode());
       
  1260     }
       
  1261 }
       
  1262 
       
  1263 /*!
       
  1264    Sets priority for the message object that is being edited 
  1302    Sets priority for the message object that is being edited 
  1265 */
  1303 */
  1266 void NmEditorView::setPriority(NmActionResponseCommand priority)
  1304 void NmEditorView::setPriority(NmActionResponseCommand priority)
  1267 {
  1305 {
       
  1306     NM_FUNCTION;
       
  1307     
  1268     mHeaderWidget->setPriority(priority);
  1308     mHeaderWidget->setPriority(priority);
  1269 
  1309 
  1270     if (mMessage) {
  1310     if (mMessage) {
  1271         NmMessagePriority messagePriority = NmMessagePriorityNormal;
  1311         NmMessagePriority messagePriority = NmMessagePriorityNormal;
  1272         
  1312         
  1288     \param list The list containing the addresses.
  1328     \param list The list containing the addresses.
  1289     \return String containing the addresses.
  1329     \return String containing the addresses.
  1290 */
  1330 */
  1291 QString NmEditorView::addressListToString(const QList<NmAddress*> &list) const
  1331 QString NmEditorView::addressListToString(const QList<NmAddress*> &list) const
  1292 {
  1332 {
       
  1333     NM_FUNCTION;
       
  1334     
  1293     QString addressesString;
  1335     QString addressesString;
  1294     QList<NmAddress*>::const_iterator i = list.constBegin();
  1336     QList<NmAddress*>::const_iterator i = list.constBegin();
  1295     
  1337     
  1296     while (i != list.constEnd() && *i) {
  1338     while (i != list.constEnd() && *i) {
  1297         if (i > list.constBegin()) {
  1339         if (i > list.constBegin()) {
  1314     \param list The list containing the addresses.
  1356     \param list The list containing the addresses.
  1315     \return String containing the addresses.
  1357     \return String containing the addresses.
  1316 */
  1358 */
  1317 QString NmEditorView::addressListToString(const QList<NmAddress> &list) const
  1359 QString NmEditorView::addressListToString(const QList<NmAddress> &list) const
  1318 {
  1360 {
       
  1361     NM_FUNCTION;
       
  1362     
  1319     QString addressesString;
  1363     QString addressesString;
  1320     QList<NmAddress>::const_iterator i = list.constBegin();
  1364     QList<NmAddress>::const_iterator i = list.constBegin();
  1321     
  1365     
  1322     while (i != list.constEnd()) {
  1366     while (i != list.constEnd()) {
  1323         if (i > list.constBegin()) {
  1367         if (i > list.constBegin()) {
  1335 /*!
  1379 /*!
  1336     This slot is called when 'remove' is selected from attachment list context menu.
  1380     This slot is called when 'remove' is selected from attachment list context menu.
  1337 */
  1381 */
  1338 void NmEditorView::removeAttachmentTriggered()
  1382 void NmEditorView::removeAttachmentTriggered()
  1339 {
  1383 {
       
  1384     NM_FUNCTION;
       
  1385     
  1340     // Cancel will delete previous operation
  1386     // Cancel will delete previous operation
  1341     if (mRemoveAttachmentOperation) {
  1387     if (mRemoveAttachmentOperation) {
  1342         if (!mRemoveAttachmentOperation->isRunning()) {
  1388         if (!mRemoveAttachmentOperation->isRunning()) {
  1343             mRemoveAttachmentOperation->cancelOperation();
  1389             mRemoveAttachmentOperation->cancelOperation();
  1344         }
  1390         }
  1360     This slot is called by mRemoveAttachmentOperation when the operation is
  1406     This slot is called by mRemoveAttachmentOperation when the operation is
  1361     completed. There is no need to update UI because it was already updated.
  1407     completed. There is no need to update UI because it was already updated.
  1362  */
  1408  */
  1363 void NmEditorView::attachmentRemoved(int result)
  1409 void NmEditorView::attachmentRemoved(int result)
  1364 {
  1410 {
       
  1411     NM_FUNCTION;
       
  1412     
  1365     // It is not desided yet what to do if operation fails
  1413     // It is not desided yet what to do if operation fails
  1366     Q_UNUSED(result);
  1414     Q_UNUSED(result);
  1367     
  1415     
  1368     if (mMessage) {
  1416     if (mMessage) {
  1369         // Reload message because one attachment has been removed
  1417         // Reload message because one attachment has been removed
  1381 /*!
  1429 /*!
  1382     This slot is called when 'open' is selected from attachment list context menu.
  1430     This slot is called when 'open' is selected from attachment list context menu.
  1383 */
  1431 */
  1384 void NmEditorView::openAttachmentTriggered()
  1432 void NmEditorView::openAttachmentTriggered()
  1385 {
  1433 {
       
  1434     NM_FUNCTION;
       
  1435     
  1386     mHeaderWidget->launchAttachment(mSelectedAttachment);
  1436     mHeaderWidget->launchAttachment(mSelectedAttachment);
  1387 }
  1437 }
  1388 
  1438 
  1389 /*!
  1439 /*!
  1390    Enables/disables toolbar extension for attach
  1440    Enables/disables toolbar extension for attach
  1391 */
  1441 */
  1392 void NmEditorView::enableToolBarAttach(bool enable)
  1442 void NmEditorView::enableToolBarAttach(bool enable)
  1393 {
  1443 {
       
  1444     NM_FUNCTION;
       
  1445     
  1394     HbToolBar *tb = toolBar();
  1446     HbToolBar *tb = toolBar();
  1395     if (tb) {
  1447     if (tb) {
  1396         QList<QAction *> toolbarList = tb->actions();
  1448         QList<QAction *> toolbarList = tb->actions();
  1397         int count = toolbarList.count();
  1449         int count = toolbarList.count();
  1398         for (int i = 0; i < count; i++) {
  1450         for (int i = 0; i < count; i++) {