diff -r 011f79704660 -r cdd802add233 emailuis/nmailui/src/nmeditorcontent.cpp --- a/emailuis/nmailui/src/nmeditorcontent.cpp Fri Jun 11 16:23:29 2010 +0100 +++ b/emailuis/nmailui/src/nmeditorcontent.cpp Thu Jul 22 16:30:28 2010 +0100 @@ -19,46 +19,51 @@ // Layout static const char *NMUI_EDITOR_BODY = "BodyTextEdit"; +static const char *NMUI_EDITOR_SCROLL_AREA = "scrollArea"; +static const char *NMUI_EDITOR_SCROLL_AREA_CONTENTS = "scrollAreaContents"; -static const double Un = 6.66; -static const double HeaderAreaMarginsTotal = 3 * Un; - +// Regular expression for selecting img tags with "cid" in the mail. +static const char *NMUI_EDITOR_REMOVE_EMBD_IMAGES_REG = + "(\\s*|/>\\s*|>\\s*))"; + /*! Constructor */ -NmEditorContent::NmEditorContent(QGraphicsItem *parent, - NmEditorView *parentView, +NmEditorContent::NmEditorContent(QObject *parent, HbDocumentLoader *documentLoader, - QNetworkAccessManager &manager) : - HbWidget(parent), - mHeaderWidget(NULL), - mParentView(parentView), - mEditorLayout(NULL), - mMessageBodyType(PlainText), + QNetworkAccessManager &manager, + NmApplication &application) : + QObject(parent), + mHeader(NULL), + mMessageBodyType(NmPlainText), mEditorWidget(NULL), - mBackgroundScrollArea((NmBaseViewScrollArea*)parent) + mScrollArea(NULL), + mScrollAreaContents(NULL), + mApplication(application) { - mBackgroundScrollArea->setLongPressEnabled(true); + NM_FUNCTION; - // Add header area handling widget into layout - mHeaderWidget = new NmEditorHeader(documentLoader, this); + // Construct container for the header widgets + mHeader = new NmEditorHeader(this, documentLoader); // Get pointer to body text area handling widget mEditorWidget = qobject_cast(documentLoader->findWidget(NMUI_EDITOR_BODY)); - + // Set body editor to use NmEditorTextDocument NmEditorTextDocument *textDocument = new NmEditorTextDocument(manager); mEditorWidget->setDocument(textDocument); textDocument->setParent(mEditorWidget); // ownership changes - mEditorWidget->init(mBackgroundScrollArea); - // we are interested in the editor widget's height changes - connect(mEditorWidget, SIGNAL(editorContentHeightChanged()), this, - SLOT(setEditorContentHeight())); - + mScrollArea = qobject_cast + (documentLoader->findWidget(NMUI_EDITOR_SCROLL_AREA)); + mScrollArea->setScrollDirections(Qt::Vertical | Qt::Horizontal); + // Enable style picker menu item. mEditorWidget->setFormatDialog(new HbFormatDialog()); + mScrollAreaContents = + qobject_cast(documentLoader->findWidget(NMUI_EDITOR_SCROLL_AREA_CONTENTS)); + // Create signal slot connections createConnections(); } @@ -68,7 +73,7 @@ */ NmEditorContent::~NmEditorContent() { - delete mHeaderWidget; + NM_FUNCTION; } /*! @@ -76,105 +81,186 @@ present, reply header is generated and set to editor. Reply envelope ownership is not transferred here. */ -void NmEditorContent::setMessageData(const NmMessage &message, - NmMessageEnvelope *replyMsgEnvelope) +void NmEditorContent::setMessageData(const NmMessage &originalMessage, + NmUiEditorStartMode &editorStartMode) { - // Check which part is present. Html or plain text part - const NmMessagePart *htmlPart = message.htmlBodyPart(); - const NmMessagePart *plainPart = message.plainTextBodyPart(); - - QList parts; - message.attachmentList(parts); - NmMessagePart* attachmentHtml = NULL; - - foreach(NmMessagePart* part, parts) { - if (part->contentDescription().startsWith( NmContentDescrAttachmentHtml )) { - attachmentHtml = part; - } + NM_FUNCTION; + + QString bodyContent; + + // Create the "reply" header (also for forward message) + if (editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll || + editorStartMode==NmUiEditorForward) { + bodyContent.append(NmUtilities::createReplyHeader(originalMessage.envelope())); + } + + // Check which part is present. Html or plain text part. We use the original message parts. + const NmMessagePart *htmlPart = originalMessage.htmlBodyPart(); + const NmMessagePart *plainPart = originalMessage.plainTextBodyPart(); + + if (htmlPart) { + bodyContent.append(htmlPart->textContent()); + if(editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll ) { + removeEmbeddedImages(bodyContent); } - - if (htmlPart) { - // Html part was present, set it to HbTextEdit - // This will generate contentsChanged() event which is used to - // set new height for the editor widget and content. - if(attachmentHtml){ - QString htmlText = htmlPart->textContent() + attachmentHtml->textContent(); - emit setHtml(htmlText); - } - else{ - emit setHtml(htmlPart->textContent()); - } - mMessageBodyType = HTMLText; + emit setHtml(bodyContent); + mMessageBodyType = NmHTMLText; } else if (plainPart) { // Plain text part was present, set it to HbTextEdit - emit setPlainText(plainPart->textContent()); - mMessageBodyType = PlainText; - } - - // Original message text to editor content fiel - if (replyMsgEnvelope && mEditorWidget) { - QTextCursor cursor = mEditorWidget->textCursor(); - cursor.setPosition(0); - cursor.insertHtml(NmUtilities::createReplyHeader(*replyMsgEnvelope)); + bodyContent.append(plainPart->textContent()); + emit setPlainText(bodyContent); + mMessageBodyType = NmPlainText; } } /*! - This method set new height for the editor content when header or body field - height has been changed. - */ -void NmEditorContent::setEditorContentHeight() -{ - const QSizeF reso = HbDeviceProfile::current().logicalSize(); - qreal containerHeight = - mEditorWidget->contentHeight() + mHeaderWidget->headerHeight() + HeaderAreaMarginsTotal; - if (containerHeight < reso.height()) { - //Currently content height is too long because Chrome hiding is not supported. - //Fix this when Chrome works. - containerHeight = reso.height(); - qreal bodyContentHeight = - reso.height() - mHeaderWidget->headerHeight() - HeaderAreaMarginsTotal; - mEditorWidget->setPreferredHeight(bodyContentHeight); - mEditorWidget->setMaximumHeight(bodyContentHeight); - } - mParentView->scrollAreaContents()->setMinimumHeight(containerHeight); - mParentView->scrollAreaContents()->setMaximumHeight(containerHeight); - mBackgroundScrollArea->setMaximumHeight(containerHeight); -} - -/*! This method creates all needed signal-slot connections */ void NmEditorContent::createConnections() { - // Body edit widget is also interested about bg scroll position change - connect(mBackgroundScrollArea, SIGNAL(scrollPositionChanged(QPointF)), - mEditorWidget, SLOT(updateScrollPosition(QPointF))); + NM_FUNCTION; + // Signal for setting HbTextEdit widgets html content connect(this, SIGNAL(setHtml(QString)), - mEditorWidget, SLOT(setHtml(QString))); + mEditorWidget, SLOT(setHtml(QString)), Qt::QueuedConnection); + // Signal for setting HbTextEdit widgets plain text content connect(this, SIGNAL(setPlainText(QString)), - mEditorWidget, SLOT(setPlainText(QString))); + mEditorWidget, SLOT(setPlainText(QString)), Qt::QueuedConnection); + // Inform text edit widget that header height has been changed - connect(mHeaderWidget, SIGNAL(headerHeightChanged(int)), - mEditorWidget, SLOT(setHeaderHeight(int))); + connect(mHeader, SIGNAL(headerHeightChanged(int)), this, SLOT(setEditorContentHeight()), + Qt::QueuedConnection); + + // we are interested in the document's height changes + connect(mEditorWidget->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), this, + SLOT(setEditorContentHeight()), Qt::QueuedConnection); + + // We need to update the scroll position according the editor's cursor position + connect(mHeader->toEdit(), SIGNAL(cursorPositionChanged(int, int)), this, + SLOT(ensureCursorVisibility()), Qt::QueuedConnection); + connect(mHeader->ccEdit(), SIGNAL(cursorPositionChanged(int, int)), this, + SLOT(ensureCursorVisibility()), Qt::QueuedConnection); + connect(mHeader->bccEdit(), SIGNAL(cursorPositionChanged(int, int)), this, + SLOT(ensureCursorVisibility()), Qt::QueuedConnection); + connect(mHeader->subjectEdit(), SIGNAL(cursorPositionChanged(int, int)), this, + SLOT(ensureCursorVisibility()), Qt::QueuedConnection); + connect(mEditorWidget, SIGNAL(cursorPositionChanged(int, int)), this, + SLOT(ensureCursorVisibility()), Qt::QueuedConnection); + + // listen to the parent's (NmEditorView) size changes which happen eg. when VKB is opened/closed + connect(parent(), SIGNAL(sizeChanged()), this, SLOT(ensureCursorVisibility()), + Qt::QueuedConnection); } /*! Return pointer to the email body text edit widget */ -NmEditorTextEdit* NmEditorContent::editor() const +NmEditorTextEdit *NmEditorContent::editor() const { + NM_FUNCTION; + return mEditorWidget; } /*! Return pointer to the header widget */ -NmEditorHeader* NmEditorContent::header() const +NmEditorHeader *NmEditorContent::header() const +{ + NM_FUNCTION; + + return mHeader; +} + +/*! + This slot is called when header widget height has been changed. Function performs + the repositioning of the body field and resizing of the editor and content area. + */ +void NmEditorContent::setEditorContentHeight() { - return mHeaderWidget; + NM_FUNCTION; + + // the height of the margin between the title bar and the header + qreal topMargin = 0; + HbStyle().parameter("hb-param-margin-gene-top", topMargin); + + // header height + qreal headerHeight = mHeader->headerHeight(); + + // body area editor's document height with margins added + qreal documentHeightAndMargins = mEditorWidget->document()->size().height() + + (mEditorWidget->document()->documentMargin() * 2); + + // chrome height + qreal chromeHeight = 0; + HbStyle().parameter("hb-param-widget-chrome-height", chromeHeight); + + // screen height + qreal screenHeight = mApplication.screenSize().height(); + + // set min size for the body area so that at least the screen area is always filled + qreal bodyAreaMinSize = screenHeight - chromeHeight - topMargin - headerHeight; + + qreal bodyAreaSize = fmax(bodyAreaMinSize, documentHeightAndMargins); + + mScrollAreaContents->setPreferredHeight(topMargin + headerHeight + bodyAreaSize); } +/*! + This slot is called when the cursor visibility has to be ensured ie. the scroll position is + adjusted so that the cursor can be seen. +*/ +void NmEditorContent::ensureCursorVisibility() +{ + NM_FUNCTION; + + // check which of the editors has the focus and get the x/y coordinates for the cursor position + QGraphicsWidget *focused = mScrollAreaContents->focusWidget(); + + if (focused) { + QRectF localRect(0, 0, 0, 0); + bool notFound = false; + + if (focused == mHeader->toEdit()) { + localRect = mHeader->toEdit()->rectForCursorPosition(); + } + else if (focused == mHeader->ccEdit()) { + localRect = mHeader->ccEdit()->rectForCursorPosition(); + } + else if (focused == mHeader->bccEdit()) { + localRect = mHeader->bccEdit()->rectForCursorPosition(); + } + else if (focused == mHeader->subjectEdit()) { + localRect = mHeader->subjectEdit()->rectForCursorPosition(); + } + else if (focused == mEditorWidget) { + localRect = mEditorWidget->rectForCursorPosition(); + } + else { + notFound = true; + } + + if (!notFound) { + QPointF topLeftPos = focused->mapToItem(mScrollAreaContents, localRect.topLeft()); + QPointF bottomRightPos = + focused->mapToItem(mScrollAreaContents, localRect.bottomRight()); + qreal marginRight = 0; + HbStyle().parameter("hb-param-margin-gene-right", marginRight); + bottomRightPos.rx() += marginRight; + mScrollArea->ensureVisible(topLeftPos); + mScrollArea->ensureVisible(bottomRightPos); + } + } +} +/*! + Removes embedded images from the message body + */ +void NmEditorContent::removeEmbeddedImages(QString &bodyContent) +{ + NM_FUNCTION; + + QRegExp regExp(NMUI_EDITOR_REMOVE_EMBD_IMAGES_REG, Qt::CaseInsensitive); + bodyContent.remove(regExp); +}