diff -r 578830873419 -r ecc8def7944a emailuis/nmailui/src/nmeditorview.cpp --- a/emailuis/nmailui/src/nmeditorview.cpp Fri Apr 16 14:51:52 2010 +0300 +++ b/emailuis/nmailui/src/nmeditorview.cpp Mon May 03 12:23:15 2010 +0300 @@ -25,8 +25,6 @@ static const int nmOrientationTimer=100; static const QString Delimiter("; "); -#define IMAGE_FETCHER_INTERFACE "Image" -#define FETCHER_OPERATION "fetch(QVariantMap,QVariant)" /*! \class NmEditorView @@ -41,20 +39,22 @@ NmUiStartParam* startParam, NmUiEngine &uiEngine, QGraphicsItem *parent) -: NmBaseView(startParam, parent), -mApplication(application), -mUiEngine(uiEngine), -mDocumentLoader(NULL), -mScrollArea(NULL), -mEditWidget(NULL), -mHeaderWidget(NULL), -mMessage(NULL), -mContentWidget(NULL), -mAttachContextMenu(NULL), -mMessageCreationOperation(NULL), -mAddAttachmentOperation(NULL), -mRemoveAttachmentOperation(NULL), -mCheckOutboxOperation(NULL) + : NmBaseView(startParam, parent), + mApplication(application), + mUiEngine(uiEngine), + mDocumentLoader(NULL), + mScrollArea(NULL), + mEditWidget(NULL), + mHeaderWidget(NULL), + mMessage(NULL), + mContentWidget(NULL), + mAttachmentListContextMenu(NULL), + mMessageCreationOperation(NULL), + mAddAttachmentOperation(NULL), + mRemoveAttachmentOperation(NULL), + mCheckOutboxOperation(NULL), + mWaitDialog(NULL), + mAttachmentPicker(NULL) { mDocumentLoader = new HbDocumentLoader(); // Set object name @@ -72,18 +72,24 @@ */ NmEditorView::~NmEditorView() { + // It is clearer that the operations are not owned by parent QObject as + // they are not allocated in the constructor. + delete mRemoveAttachmentOperation; + delete mAddAttachmentOperation; delete mMessageCreationOperation; delete mCheckOutboxOperation; - delete mMessage; - mWidgetList.clear(); delete mDocumentLoader; - delete mContentWidget; - delete mPrioritySubMenu; - delete mAttachContextMenu; + + if (mAttachmentListContextMenu) { + mAttachmentListContextMenu->clearActions(); + delete mAttachmentListContextMenu; + } + delete mWaitDialog; + delete mAttachmentPicker; } /*! @@ -109,7 +115,8 @@ mScrollAreaContents = qobject_cast (mDocumentLoader->findObject(NMUI_EDITOR_SCROLL_AREA_CONTENTS)); - mContentWidget = new NmEditorContent(mScrollArea, this, mDocumentLoader); + mContentWidget = new NmEditorContent(mScrollArea, this, mDocumentLoader, + mApplication.networkAccessManager()); mEditWidget = mContentWidget->editor(); mHeaderWidget = mContentWidget->header(); @@ -151,8 +158,8 @@ connect(mApplication.mainWindow(), SIGNAL(orientationChanged(Qt::Orientation)), this, SLOT(orientationChanged(Qt::Orientation))); // Signal for handling the attachment list selection - connect(mHeaderWidget, SIGNAL(attachmentRemoved(const NmId)), - this, SLOT(removeAttachment(const NmId))); + connect(mHeaderWidget, SIGNAL(attachmentLongPressed(NmId, QPointF)), + this, SLOT(attachmentLongPressed(NmId, QPointF))); } /*! @@ -193,6 +200,7 @@ Q_UNUSED(orientation); // Adjust content height QTimer::singleShot(nmOrientationTimer, this, SLOT(adjustViewDimensions())); + QTimer::singleShot(nmOrientationTimer, mHeaderWidget, SLOT(sendHeaderHeightChanged())); } /*! @@ -225,7 +233,7 @@ /* Query user if we want to exit the editor - */ +*/ bool NmEditorView::okToExitView() { bool okToExit = true; @@ -280,9 +288,42 @@ */ void NmEditorView::aboutToExitView() { + if (mStartParam && mStartParam->service() && mUiEngine.isSendingMessage()) { + // The application was started as a service and is about to close. + // A message is still being sent and in order to make sure that the + // send operation is not cancelled, let us display a modal wait dialog. + + // When the send operation is completed, the dialog is automatically + // closed. + connect(&mUiEngine, SIGNAL(sendOperationCompleted()), + this, SLOT(handleSendOperationCompleted())); + + // Close and delete the previous wait dialog if one exists. + if (mWaitDialog) { + mWaitDialog->close(); + delete mWaitDialog; + } + + // Construct and setup the wait dialog. + mWaitDialog = new HbProgressDialog(); + mWaitDialog->setText(hbTrId("txt_mail_shareui_sending_please_wait")); + + if (!XQServiceUtil::isEmbedded()) { + // Hide the application. + XQServiceUtil::toBackground(true); + } + + // Display the wait dialog. + mWaitDialog->exec(); + delete mWaitDialog; + mWaitDialog = NULL; + } + // These operations need to be stopped before message can be deleted delete mAddAttachmentOperation; + mAddAttachmentOperation = NULL; delete mRemoveAttachmentOperation; + mRemoveAttachmentOperation = NULL; if (mMessage) { // this is NULL if sending is started // Delete message from drafts @@ -297,14 +338,14 @@ Find message data based on start parameters. Method is called when editor is started. If message data is found it means that operation is forward or reply message. - */ +*/ void NmEditorView::setMessageData() { // Check the outbox. delete mCheckOutboxOperation; - mCheckOutboxOperation = NULL; + mCheckOutboxOperation = NULL; - mCheckOutboxOperation = mUiEngine.checkOutbox(mStartParam->mailboxId()); + mCheckOutboxOperation = mUiEngine.checkOutbox(mStartParam->mailboxId()); if (mCheckOutboxOperation) { connect(mCheckOutboxOperation, SIGNAL(operationCompleted(int)), @@ -316,7 +357,7 @@ } /*! - */ +*/ void NmEditorView::startMessageCreation(NmUiEditorStartMode startMode) { NmId mailboxId = mStartParam->mailboxId(); @@ -324,9 +365,9 @@ NmId msgId = mStartParam->messageId(); delete mMessageCreationOperation; - mMessageCreationOperation = NULL; + mMessageCreationOperation = NULL; - // original message is now fetched so start message creation + // original message is now fetched so start message creation if (startMode == NmUiEditorForward) { mMessageCreationOperation = mUiEngine.createForwardMessage(mailboxId, msgId); } @@ -350,7 +391,7 @@ /*! Starting the message sending is handled here. - */ +*/ void NmEditorView::startSending() { // The message contents should be verified @@ -358,7 +399,9 @@ // verify addresses before sending QList invalidAddresses; - NmUtilities::getRecipientsFromMessage(*mMessage, invalidAddresses, NmUtilities::InvalidAddress); + if (mMessage) { + NmUtilities::getRecipientsFromMessage(*mMessage, invalidAddresses, NmUtilities::InvalidAddress); + } bool okToSend = true; if (invalidAddresses.count() > 0) { @@ -377,9 +420,16 @@ } if (okToSend) { - // ownership of mMessage changes - mUiEngine.sendMessage(mMessage); + QList preliminaryOperations; + preliminaryOperations.append(mAddAttachmentOperation); + preliminaryOperations.append(mRemoveAttachmentOperation); + // ownership of mMessage is transferred + // ownerships of NmOperations in preliminaryOperations are transferred + mUiEngine.sendMessage(mMessage, preliminaryOperations); mMessage = NULL; + mAddAttachmentOperation = NULL; + mRemoveAttachmentOperation = NULL; + preliminaryOperations.clear(); // sending animation should be shown here, then exit QTimer::singleShot(1000, &mApplication, SLOT(popView())); } @@ -387,7 +437,7 @@ /*! This is signalled by mMessageCreationOperation when message is created. - */ +*/ void NmEditorView::messageCreated(int result) { delete mMessage; @@ -408,7 +458,7 @@ /*! Updates the message with the editor contents. - */ +*/ void NmEditorView::updateMessageWithEditorContents() { if (mMessage) { @@ -461,7 +511,7 @@ /*! Updates the message with the editor contents. Called only once when the editor is launched. - */ +*/ void NmEditorView::fillEditorWithMessageContents() { if (!mMessage || !mContentWidget) { @@ -571,7 +621,21 @@ *attachmentHtml); } - mContentWidget->setMessageData(mMessage); + // Set content data + if (editorStartMode==NmUiEditorReply|| + editorStartMode==NmUiEditorReplyAll|| + editorStartMode==NmUiEditorForward){ + // Pass envelope ptr only when needed for reaply header creation + NmMessage *originalMessage = mUiEngine.message(mStartParam->mailboxId(), + mStartParam->folderId(), + mStartParam->messageId()); + mContentWidget->setMessageData(*mMessage, &originalMessage->envelope()); + delete originalMessage; + } + else{ + // Reply header not needed, do not pass envelope ptr + mContentWidget->setMessageData(*mMessage); + } // Get list of attachments from the message and set those into UI attachment list QList attachments; @@ -620,7 +684,33 @@ if( list[i]->availabilityCondition() == NmAction::NmSendable ) { list[i]->setEnabled(false); } - } + //object name set in NmBaseClientPlugin::createEditorViewCommands + //temporary solution + else if (list[i]->objectName() == "baseclientplugin_attachaction") { + HbToolBarExtension* extension = new HbToolBarExtension(); + mAttachmentPicker = new NmAttachmentPicker(this); + + if (extension && mAttachmentPicker) { + connect(mAttachmentPicker, SIGNAL(attachmentsFetchOk(const QVariant &)), + this, SLOT(onAttachmentReqCompleted(const QVariant &))); + + HbAction* actionPhoto = + extension->addAction(hbTrId("txt_mail_list_photo"), extension, SLOT(close())); + connect(actionPhoto, SIGNAL(triggered()), mAttachmentPicker, SLOT(fetchImage())); + + HbAction* actionMusic = + extension->addAction(hbTrId("txt_mail_list_music"), extension, SLOT(close())); + connect(actionMusic, SIGNAL(triggered()), mAttachmentPicker, SLOT(fetchAudio())); + + HbAction* actionVideo = + extension->addAction(hbTrId("txt_mail_list_video"), extension, SLOT(close())); + HbAction* actionOther = + extension->addAction(hbTrId("txt_mail_list_other"), extension, SLOT(close())); + + list[i]->setToolBarExtension(extension); + } + } + } } } @@ -663,36 +753,31 @@ } else if (actionResponse.menuType() == NmActionToolbar) { switch (responseCommand) { - case NmActionResponseCommandSendMail: { + case NmActionResponseCommandSendMail: { + // Just in case send mail would be somehow accessible during message creation or + // outobox checking + if (!mCheckOutboxOperation->isRunning() + && (!mMessageCreationOperation || !mMessageCreationOperation->isRunning())) { startSending(); - break; } - case NmActionResponseCommandAttach : { - // Do nothing if previous addAttachment operation is still ongoing. - if(!mAddAttachmentOperation || !mAddAttachmentOperation->isRunning()) { - //will be replaced by toolbar extension - if (!mAttachContextMenu) { - QList actionList; - NmAction* actionPhoto = new NmAction(0); - actionPhoto->setText(QObject::tr("Photo", "txt_nmailui_photo_attach")); - actionList.append(actionPhoto); - connect(actionPhoto, SIGNAL(triggered()), this, SLOT(attachImage())); - - mAttachContextMenu = new HbMenu(); - mAttachContextMenu->clearActions(); - - for (int i=0;iaddAction(actionList[i]); - } - } - - QPointF menuPos(qreal(20),qreal(520)); - mAttachContextMenu->exec(menuPos); - } - break; - } - default: - break; + break; + } + default: + break; + } + } + else if (actionResponse.menuType() == NmActionContextMenu) { + switch (responseCommand) { + case NmActionResponseCommandRemoveAttachment: { + removeAttachmentTriggered(); + break; + } + case NmActionResponseCommandOpenAttachment: { + openAttachmentTriggered(); + break; + } + default: + break; } } } @@ -700,7 +785,7 @@ /*! This function converts background scroll area coordinate point into body text editor coordinate point. - */ +*/ QPointF NmEditorView::viewCoordinateToEditCoordinate(QPointF orgPoint) { QPointF contentWidgetPos = mScrollAreaContents->pos(); @@ -845,7 +930,7 @@ /*! Adds a prefix to the subject for reply or forward. Strips other occurrences of the prefix from the beginning. - */ +*/ QString NmEditorView::addSubjectPrefix( NmUiEditorStartMode startMode, const QString &subject ) { QString newSubject(subject.trimmed()); @@ -886,29 +971,6 @@ return newSubject; } -#ifdef Q_OS_SYMBIAN - -void NmEditorView::attachImage() -{ - XQAiwRequest *request; - XQApplicationManager mAppmgr; - request = mAppmgr.create(IMAGE_FETCHER_INTERFACE, FETCHER_OPERATION, true); - - if (request) { - connect(request, SIGNAL(requestOk(const QVariant&)), this, SLOT(onAttachmentReqCompleted(const QVariant&))); - } - else { - //create request failed - NMLOG("appmgr: create request failed"); - return; - } - - if (!(request)->send()) { - //sending request failed - NMLOG("appmgr: send request failed"); - } - delete request; -} /*! This slot is called when 'attachment picker' request has been performed succesfully @@ -921,7 +983,21 @@ } } -#endif + +/*! + Closes the wait dialog if one exists. + + This slot is called if the mail application has been started as a service + and is about to close. Closing the application while still sending a message + may cause unwanted cancelling of the operation. +*/ +void NmEditorView::handleSendOperationCompleted() +{ + if (mWaitDialog) { + mWaitDialog->close(); + } +} + /*! Add list of attachments @@ -937,9 +1013,7 @@ NMLOG(fileName); } - // Start operation to attach file or list of files into mail message - // This will also copy files into message store - // Delete previous operation + // Delete previous operation if it's not running. if (mAddAttachmentOperation) { if (!mAddAttachmentOperation->isRunning()) { delete mAddAttachmentOperation; @@ -947,9 +1021,12 @@ } } if (!mAddAttachmentOperation) { + // Start operation to attach file or list of files into mail message. + // This will also copy files into message store. mAddAttachmentOperation = mUiEngine.addAttachments(*mMessage, fileNames); if (mAddAttachmentOperation) { + enableToolBarAttach(false); // Signal to inform completion of one attachment connect(mAddAttachmentOperation, SIGNAL(operationPartCompleted(const QString &, const NmId &, int)), @@ -966,31 +1043,69 @@ } /*! - This slot is called when attachment has been deleted from UI + This slot is called to create context menu when attachment has been selected + from UI by longpress. */ -void NmEditorView::removeAttachment(const NmId attachmentPartId) +void NmEditorView::attachmentLongPressed(NmId attachmentPartId, QPointF point) { - // Delete previous operation - if (mRemoveAttachmentOperation) { - if (!mRemoveAttachmentOperation->isRunning()) { - delete mRemoveAttachmentOperation; - mRemoveAttachmentOperation = NULL; + // Store id of the attachment to be removed into member. + // It is used by removeAttachmentTriggered later if 'remove' selected. + mSelectedAttachment = attachmentPartId; + + if (!mAttachmentListContextMenu) { + mAttachmentListContextMenu = new HbMenu(); + } + mAttachmentListContextMenu->clearActions(); + NmActionRequest request(this, NmActionContextMenu, NmActionContextViewEditor, + NmActionContextDataMessage, mStartParam->mailboxId(), mStartParam->folderId(), + mStartParam->messageId()); + NmUiExtensionManager &extensionManager = mApplication.extManager(); + if (&extensionManager) { + QList actionList; + extensionManager.getActions(request, actionList); + for (int i = 0; i < actionList.count(); ++i) { + mAttachmentListContextMenu->addAction(actionList[i]); } } - if (!mRemoveAttachmentOperation) { - mRemoveAttachmentOperation = mUiEngine.removeAttachment(*mMessage, attachmentPartId); - } + + // Add menu position check here, so that it does not go outside of the screen + QPointF menuPos(point.x(),point.y()); + mAttachmentListContextMenu->exec(menuPos); } /*! This is signalled by mAddAttachmentOperation when the operation is completed for one attachment. - */ +*/ void NmEditorView::oneAttachmentAdded(const QString &fileName, const NmId &msgPartId, int result) { - if (result == NmNoError) { - // Get file size from the message when it works - mHeaderWidget->setAttachmentParameters(fileName, msgPartId, QString("0"), result); + if (result == NmNoError && mMessage) { + // Need to get the message again because new attachment part has been added. + NmId mailboxId = mMessage->mailboxId(); + NmId folderId = mMessage->parentId(); + NmId msgId = mMessage->envelope().id(); + + delete mMessage; + mMessage = NULL; + + mMessage = mUiEngine.message(mailboxId, folderId, msgId); + + if (mMessage) { + // Get attachment list from the message + QList attachmentList; + mMessage->attachmentList(attachmentList); + + // Search newly added attachment from the list + for (int i=0; iid() == msgPartId) { + // Get attachment file size and set it into UI + mHeaderWidget->setAttachmentParameters(fileName, + msgPartId, + QString().setNum(attachmentList[i]->size()), + result); + } + } + } } else { // Attachment adding failed. Show an error note and remove from UI attachment list. @@ -1002,9 +1117,10 @@ /*! This is signalled by mAddAttachmentOperation when the operation is completed totally. - */ +*/ void NmEditorView::allAttachmentsAdded(int result) { + enableToolBarAttach(true); if (result != NmNoError) { HbMessageBox::warning(hbTrId("txt_mail_dialog_unable_to_add_attachment")); } @@ -1012,7 +1128,7 @@ /*! This is signalled by mCheckOutboxOperation when the operation is complete. - */ +*/ void NmEditorView::outboxChecked(int result) { bool messageInOutbox = false; @@ -1120,5 +1236,82 @@ return addressesString; } +/*! + This slot is called when 'remove' is selected from attachment list context menu. +*/ +void NmEditorView::removeAttachmentTriggered() +{ + // Delete previous operation + if (mRemoveAttachmentOperation) { + if (!mRemoveAttachmentOperation->isRunning()) { + delete mRemoveAttachmentOperation; + mRemoveAttachmentOperation = NULL; + } + } + if (!mRemoveAttachmentOperation) { + // Remove from UI + mHeaderWidget->removeAttachment(mSelectedAttachment); + // Remove from message store + mRemoveAttachmentOperation = mUiEngine.removeAttachment(*mMessage, mSelectedAttachment); + if (mRemoveAttachmentOperation) { + // Signal to inform the remove operation completion + connect(mRemoveAttachmentOperation, + SIGNAL(operationCompleted(int)), + this, + SLOT(attachmentRemoved(int))); + } + } +} + +/*! + This slot is called by mRemoveAttachmentOperation when the operation is + completed. There is no need to update UI because it was already updated. + */ +void NmEditorView::attachmentRemoved(int result) +{ + // It is not desided yet what to do if operation fails + Q_UNUSED(result); + + if (mMessage) { + // Reload message because one attachment has been removed + NmId mailboxId = mMessage->mailboxId(); + NmId folderId = mMessage->parentId(); + NmId msgId = mMessage->envelope().id(); + + delete mMessage; + mMessage = NULL; + + mMessage = mUiEngine.message(mailboxId, folderId, msgId); + } +} + +/*! + This slot is called when 'open' is selected from attachment list context menu. +*/ +void NmEditorView::openAttachmentTriggered() +{ + mHeaderWidget->launchAttachment(mSelectedAttachment); +} + +/*! + Enables/disables toolbar extension for attach +*/ +void NmEditorView::enableToolBarAttach(bool enable) +{ + HbToolBar *tb = toolBar(); + if (tb) { + QList toolbarList = tb->actions(); + int count = toolbarList.count(); + for (int i = 0; i < count; i++) { + NmAction *action = static_cast(toolbarList[i]); + //object name set in NmBaseClientPlugin::createEditorViewCommands + //temporary solution + if (action->objectName() == "baseclientplugin_attachaction") { + action->setEnabled(enable); + } + } + } +} + // End of file.