emailuis/nmailui/src/nmeditorcontent.cpp
changeset 47 f83bd4ae1fe3
parent 44 c2d07d913565
child 48 10eaf342f539
--- a/emailuis/nmailui/src/nmeditorcontent.cpp	Fri Jun 11 16:42:02 2010 +0300
+++ b/emailuis/nmailui/src/nmeditorcontent.cpp	Thu Jun 24 14:32:18 2010 +0300
@@ -19,26 +19,32 @@
 
 // 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";
 
+// Regular expression for selecting img tags with "cid" in the mail.
+static const char *NMUI_EDITOR_REMOVE_EMBD_IMAGES_REG = 
+    "(<img (src\\s*=\\s*)(.{0,1}cid)([^<]+)(>\\s*|/>\\s*|></img>\\s*))";
+	
 /*!
     Constructor
 */
-NmEditorContent::NmEditorContent(QGraphicsItem *parent,
-                                 NmEditorView *parentView,
+NmEditorContent::NmEditorContent(QObject *parent,
                                  HbDocumentLoader *documentLoader,
-                                 QNetworkAccessManager &manager) :
-    HbWidget(parent),
+                                 QNetworkAccessManager &manager,
+                                 NmApplication &application) :
+    QObject(parent),
     mHeaderWidget(NULL),
-    mParentView(parentView),
-    mEditorLayout(NULL),
-    mMessageBodyType(PlainText),
+    mMessageBodyType(NmPlainText),
     mEditorWidget(NULL),
-    mBackgroundScrollArea((NmBaseViewScrollArea*)parent)
+    mScrollArea(NULL),
+    mScrollAreaContents(NULL),
+    mApplication(application)
 {
     NM_FUNCTION;
 
-    // Add header area handling widget into layout
-    mHeaderWidget = new NmEditorHeader(documentLoader);
+    // Construct container for the header widgets
+    mHeaderWidget = new NmEditorHeader(this, documentLoader);
 
     // Get pointer to body text area handling widget
     mEditorWidget = qobject_cast<NmEditorTextEdit *>(documentLoader->findWidget(NMUI_EDITOR_BODY));
@@ -48,14 +54,15 @@
     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<NmBaseViewScrollArea *>
+        (documentLoader->findObject(NMUI_EDITOR_SCROLL_AREA));
 
     // Enable style picker menu item.
     mEditorWidget->setFormatDialog(new HbFormatDialog());
 
+    mScrollAreaContents =
+        qobject_cast<HbWidget *>(documentLoader->findWidget(NMUI_EDITOR_SCROLL_AREA_CONTENTS));
+    
     // Create signal slot connections
     createConnections();
 }
@@ -66,8 +73,6 @@
 NmEditorContent::~NmEditorContent()
 {
     NM_FUNCTION;
-    
-   delete mHeaderWidget;
 }
 
 /*!
@@ -75,88 +80,76 @@
     present, reply header is generated and set to editor. Reply
     envelope ownership is not transferred here.
  */
-void NmEditorContent::setMessageData(const NmMessage &originalMessage,
-                                     bool createReplyHeader)
+void NmEditorContent::setMessageData(const NmMessage &originalMessage, 
+                                     NmUiEditorStartMode &editorStartMode)
 {
     NM_FUNCTION;
     
     QString bodyContent;
     
-    // We create the "reply" header (also for forward message), but not to draft message.
-    if (mEditorWidget && createReplyHeader) {          
-        QTextCursor cursor = mEditorWidget->textCursor();
-        cursor.setPosition(0);
-        cursor.insertHtml(NmUtilities::createReplyHeader(originalMessage.envelope()));
+    // Create the "reply" header (also for forward message)
+    if (editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll || 
+        editorStartMode==NmUiEditorForward) {
+        bodyContent.append(NmUtilities::createReplyHeader(originalMessage.envelope()));
     }
-    // Take reply header as html format.
-    bodyContent.append(mEditorWidget->toHtml());
     
     // 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 && mEditorWidget) {
+    if (htmlPart) {
         bodyContent.append(htmlPart->textContent());
+        if(editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll ) {
+            removeEmbeddedImages(bodyContent);
+        }
         emit setHtml(bodyContent);
-        mMessageBodyType = HTMLText;
+        mMessageBodyType = NmHTMLText;
     }
     else if (plainPart) {
         // Plain text part was present, set it to HbTextEdit
         bodyContent.append(plainPart->textContent());
         emit setPlainText(bodyContent);
-        mMessageBodyType = PlainText;
+        mMessageBodyType = NmPlainText;
     }
 }  
 
 /*!
-   This method set new height for the editor content when header or body field
-   height has been changed.
- */
-void NmEditorContent::setEditorContentHeight()
-{
-    NM_FUNCTION;
-    
-	const QSizeF reso = HbDeviceProfile::current().logicalSize();
-    qreal containerHeight = mEditorWidget->contentHeight() + mHeaderWidget->headerHeight();
-    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();
-        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()
 {
     NM_FUNCTION;
     
-    // Body edit widget is also interested about bg scroll position change
-    connect(mBackgroundScrollArea, SIGNAL(scrollPositionChanged(QPointF)),
-            mEditorWidget, SLOT(updateScrollPosition(QPointF)));
     // Signal for setting HbTextEdit widgets html content
     connect(this, SIGNAL(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)), Qt::QueuedConnection);
+
     // Inform text edit widget that header height has been changed
-    connect(mHeaderWidget, SIGNAL(headerHeightChanged(int)),
-            mEditorWidget, SLOT(setHeaderHeight(int)));
+    connect(mHeaderWidget, 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 cursor position
+    connect(mEditorWidget, SIGNAL(cursorPositionChanged(int, int)), this, 
+        SLOT(setScrollPosition(int, int)), Qt::QueuedConnection);
+    
+    // We need to know the scroll area's current position for calculating the new position in
+	// setScrollPosition
+    connect(mScrollArea, SIGNAL(scrollPositionChanged(QPointF)), this, 
+        SLOT(updateScrollPosition(QPointF)), Qt::QueuedConnection);
 }
 
 /*!
     Return pointer to the email body text edit widget
  */
-NmEditorTextEdit* NmEditorContent::editor() const
+NmEditorTextEdit *NmEditorContent::editor() const
 {
     NM_FUNCTION;
     
@@ -166,10 +159,116 @@
 /*!
     Return pointer to the header widget
  */
-NmEditorHeader* NmEditorContent::header() const
+NmEditorHeader *NmEditorContent::header() const
 {
     NM_FUNCTION;
     
     return mHeaderWidget;
 }
 
+/*!
+    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()
+{
+    NM_FUNCTION;
+    
+    qreal topMargin = 0;
+    HbStyle().parameter("hb-param-margin-gene-top", topMargin);
+    
+    // header height
+    qreal headerHeight = mHeaderWidget->headerHeight();
+
+    // body area editor's document height with margins added
+    qreal documentHeightAndMargins = mEditorWidget->document()->size().height() +
+        (mEditorWidget->document()->documentMargin() * 2);
+
+    // get the chrome height
+    qreal chromeHeight = 0;
+    HbStyle().parameter("hb-param-widget-chrome-height", chromeHeight);
+    
+    qreal toolbarHeight = 0;
+    HbStyle().parameter("hb-param-widget-toolbar-height", toolbarHeight);
+
+    // 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 cursor position is changed in body area using
+    'pointing stick' or keyboard. Function will update the scroll position
+    of the content so that cursor does not go outside of the screen or
+    behind the virtual keyboard.
+ */
+void NmEditorContent::setScrollPosition(int oldPos, int newPos)
+{
+    NM_FUNCTION;
+    
+    Q_UNUSED(oldPos);
+
+    qreal chromeHeight = 0;
+    HbStyle().parameter("hb-param-widget-chrome-height", chromeHeight);
+    
+    const QSizeF screenReso = mApplication.screenSize();
+    qreal maxHeight = screenReso.height() - chromeHeight;
+
+    // Get cursor position coordinates
+    QRectF cursorPosPix = mEditorWidget->rectForPosition(newPos);
+    
+    // Calculate the screen top and bottom boundaries, this means the part of the
+    // background scroll area which is currently visible.
+    qreal visibleRectTopBoundary;
+    qreal visibleRectBottomBoundary;
+    
+    qreal headerHeight = mHeaderWidget->headerHeight();
+
+    if (mScrollPosition.y() < headerHeight) {
+        // Header is completely or partially visible
+        visibleRectTopBoundary = headerHeight - mScrollPosition.y();
+        visibleRectBottomBoundary = maxHeight - visibleRectTopBoundary;
+    }
+    else {
+        // Header is not visible
+        visibleRectTopBoundary = mScrollPosition.y() - headerHeight;
+        visibleRectBottomBoundary = visibleRectTopBoundary + maxHeight;
+    }
+
+    // Do scrolling if cursor is out of the screen boundaries
+    if (cursorPosPix.y() > visibleRectBottomBoundary) {
+        // Do scroll forward
+        mScrollArea->scrollContentsTo(QPointF(0, cursorPosPix.y() - maxHeight + headerHeight));
+    }
+    else if (cursorPosPix.y() + headerHeight < mScrollPosition.y()) {
+        // Do scroll backward
+        mScrollArea->scrollContentsTo(QPointF(0, cursorPosPix.y() + headerHeight));
+    }
+}
+
+/*!
+    This slot is called when background scroll areas scroll position has been shanged.
+*/
+void NmEditorContent::updateScrollPosition(const QPointF &newPosition)
+{
+    NM_FUNCTION;
+    
+    mScrollPosition = newPosition;
+}
+
+/*!
+    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);
+}
\ No newline at end of file