emailuis/nmailui/src/nmeditorcontent.cpp
branchGCC_SURGE
changeset 55 cdd802add233
parent 54 997a02608b3a
child 59 16ed8d08d0b1
equal deleted inserted replaced
28:011f79704660 55:cdd802add233
    17 
    17 
    18 #include "nmuiheaders.h"
    18 #include "nmuiheaders.h"
    19 
    19 
    20 // Layout
    20 // Layout
    21 static const char *NMUI_EDITOR_BODY = "BodyTextEdit";
    21 static const char *NMUI_EDITOR_BODY = "BodyTextEdit";
    22 
    22 static const char *NMUI_EDITOR_SCROLL_AREA = "scrollArea";
    23 static const double Un = 6.66;
    23 static const char *NMUI_EDITOR_SCROLL_AREA_CONTENTS = "scrollAreaContents";
    24 static const double HeaderAreaMarginsTotal = 3 * Un;
    24 
    25 
    25 // Regular expression for selecting img tags with "cid" in the mail.
       
    26 static const char *NMUI_EDITOR_REMOVE_EMBD_IMAGES_REG = 
       
    27     "(<img[^<]+(src\\s*=\\s*)(.{0,1}cid)([^<]+)(>\\s*|/>\\s*|></img>\\s*))";
       
    28 	
    26 /*!
    29 /*!
    27     Constructor
    30     Constructor
    28 */
    31 */
    29 NmEditorContent::NmEditorContent(QGraphicsItem *parent,
    32 NmEditorContent::NmEditorContent(QObject *parent,
    30                                  NmEditorView *parentView,
       
    31                                  HbDocumentLoader *documentLoader,
    33                                  HbDocumentLoader *documentLoader,
    32                                  QNetworkAccessManager &manager) :
    34                                  QNetworkAccessManager &manager,
    33     HbWidget(parent),
    35                                  NmApplication &application) :
    34     mHeaderWidget(NULL),
    36     QObject(parent),
    35     mParentView(parentView),
    37     mHeader(NULL),
    36     mEditorLayout(NULL),
    38     mMessageBodyType(NmPlainText),
    37     mMessageBodyType(PlainText),
       
    38     mEditorWidget(NULL),
    39     mEditorWidget(NULL),
    39     mBackgroundScrollArea((NmBaseViewScrollArea*)parent)
    40     mScrollArea(NULL),
    40 {
    41     mScrollAreaContents(NULL),
    41     mBackgroundScrollArea->setLongPressEnabled(true);
    42     mApplication(application)
    42 
    43 {
    43     // Add header area handling widget into layout
    44     NM_FUNCTION;
    44     mHeaderWidget = new NmEditorHeader(documentLoader, this);
    45 
       
    46     // Construct container for the header widgets
       
    47     mHeader = new NmEditorHeader(this, documentLoader);
    45 
    48 
    46     // Get pointer to body text area handling widget
    49     // Get pointer to body text area handling widget
    47     mEditorWidget = qobject_cast<NmEditorTextEdit *>(documentLoader->findWidget(NMUI_EDITOR_BODY));
    50     mEditorWidget = qobject_cast<NmEditorTextEdit *>(documentLoader->findWidget(NMUI_EDITOR_BODY));
    48 
    51     
    49     // Set body editor to use NmEditorTextDocument
    52     // Set body editor to use NmEditorTextDocument
    50     NmEditorTextDocument *textDocument = new NmEditorTextDocument(manager);
    53     NmEditorTextDocument *textDocument = new NmEditorTextDocument(manager);
    51     mEditorWidget->setDocument(textDocument); 
    54     mEditorWidget->setDocument(textDocument); 
    52     textDocument->setParent(mEditorWidget); // ownership changes
    55     textDocument->setParent(mEditorWidget); // ownership changes
    53 
    56 
    54     mEditorWidget->init(mBackgroundScrollArea);
    57     mScrollArea = qobject_cast<NmBaseViewScrollArea *>
    55     // we are interested in the editor widget's height changes
    58         (documentLoader->findWidget(NMUI_EDITOR_SCROLL_AREA));
    56     connect(mEditorWidget, SIGNAL(editorContentHeightChanged()), this,
    59     mScrollArea->setScrollDirections(Qt::Vertical | Qt::Horizontal);
    57         SLOT(setEditorContentHeight()));
    60     
    58 
       
    59     // Enable style picker menu item.
    61     // Enable style picker menu item.
    60     mEditorWidget->setFormatDialog(new HbFormatDialog());
    62     mEditorWidget->setFormatDialog(new HbFormatDialog());
    61 
    63 
       
    64     mScrollAreaContents =
       
    65         qobject_cast<HbWidget *>(documentLoader->findWidget(NMUI_EDITOR_SCROLL_AREA_CONTENTS));
       
    66     
    62     // Create signal slot connections
    67     // Create signal slot connections
    63     createConnections();
    68     createConnections();
    64 }
    69 }
    65 
    70 
    66 /*!
    71 /*!
    67     Destructor
    72     Destructor
    68 */
    73 */
    69 NmEditorContent::~NmEditorContent()
    74 NmEditorContent::~NmEditorContent()
    70 {
    75 {
    71    delete mHeaderWidget;
    76     NM_FUNCTION;
    72 }
    77 }
    73 
    78 
    74 /*!
    79 /*!
    75     Fill message data into header and body fileds. If reply envelopw is
    80     Fill message data into header and body fileds. If reply envelopw is
    76     present, reply header is generated and set to editor. Reply
    81     present, reply header is generated and set to editor. Reply
    77     envelope ownership is not transferred here.
    82     envelope ownership is not transferred here.
    78  */
    83  */
    79 void NmEditorContent::setMessageData(const NmMessage &message,
    84 void NmEditorContent::setMessageData(const NmMessage &originalMessage, 
    80                                      NmMessageEnvelope *replyMsgEnvelope)
    85                                      NmUiEditorStartMode &editorStartMode)
    81 {
    86 {
    82     // Check which part is present. Html or plain text part
    87     NM_FUNCTION;
    83     const NmMessagePart *htmlPart = message.htmlBodyPart();
    88     
    84     const NmMessagePart *plainPart = message.plainTextBodyPart();
    89     QString bodyContent;
    85 
    90     
    86     QList<NmMessagePart*> parts;
    91     // Create the "reply" header (also for forward message)
    87     message.attachmentList(parts);
    92     if (editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll || 
    88     NmMessagePart* attachmentHtml = NULL;
    93         editorStartMode==NmUiEditorForward) {
    89 
    94         bodyContent.append(NmUtilities::createReplyHeader(originalMessage.envelope()));
    90     foreach(NmMessagePart* part, parts) {
    95     }
    91         if (part->contentDescription().startsWith( NmContentDescrAttachmentHtml )) {
    96     
    92                 attachmentHtml = part;
    97     // Check which part is present. Html or plain text part. We use the original message parts.
    93             }
    98     const NmMessagePart *htmlPart = originalMessage.htmlBodyPart();
    94         }
    99     const NmMessagePart *plainPart = originalMessage.plainTextBodyPart();
    95     
   100  
    96     if (htmlPart) {	    
   101     if (htmlPart) {
    97         // Html part was present, set it to HbTextEdit
   102         bodyContent.append(htmlPart->textContent());
    98         // This will generate contentsChanged() event which is used to
   103         if(editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll ) {
    99         // set new height for the editor widget and content.
   104             removeEmbeddedImages(bodyContent);
   100         if(attachmentHtml){
   105         }
   101             QString htmlText = htmlPart->textContent() + attachmentHtml->textContent();
   106         emit setHtml(bodyContent);
   102             emit setHtml(htmlText);
   107         mMessageBodyType = NmHTMLText;
   103         } 
       
   104         else{
       
   105             emit setHtml(htmlPart->textContent());    
       
   106         }
       
   107         mMessageBodyType = HTMLText;
       
   108     }
   108     }
   109     else if (plainPart) {
   109     else if (plainPart) {
   110         // Plain text part was present, set it to HbTextEdit
   110         // Plain text part was present, set it to HbTextEdit
   111         emit setPlainText(plainPart->textContent());
   111         bodyContent.append(plainPart->textContent());
   112         mMessageBodyType = PlainText;
   112         emit setPlainText(bodyContent);
   113     }
   113         mMessageBodyType = NmPlainText;
   114     
       
   115     // Original message text to editor content fiel
       
   116     if (replyMsgEnvelope && mEditorWidget) {          
       
   117         QTextCursor cursor = mEditorWidget->textCursor();
       
   118         cursor.setPosition(0);
       
   119         cursor.insertHtml(NmUtilities::createReplyHeader(*replyMsgEnvelope));
       
   120     }
   114     }
   121 }  
   115 }  
   122 
   116 
   123 /*!
   117 /*!
   124    This method set new height for the editor content when header or body field
       
   125    height has been changed.
       
   126  */
       
   127 void NmEditorContent::setEditorContentHeight()
       
   128 {
       
   129 	const QSizeF reso = HbDeviceProfile::current().logicalSize();
       
   130     qreal containerHeight =
       
   131         mEditorWidget->contentHeight() + mHeaderWidget->headerHeight() + HeaderAreaMarginsTotal;
       
   132     if (containerHeight < reso.height()) {
       
   133         //Currently content height is too long because Chrome hiding is not supported.
       
   134         //Fix this when Chrome works.
       
   135         containerHeight = reso.height();
       
   136         qreal bodyContentHeight =
       
   137             reso.height() - mHeaderWidget->headerHeight() - HeaderAreaMarginsTotal;
       
   138         mEditorWidget->setPreferredHeight(bodyContentHeight);
       
   139         mEditorWidget->setMaximumHeight(bodyContentHeight);
       
   140     }
       
   141     mParentView->scrollAreaContents()->setMinimumHeight(containerHeight);
       
   142     mParentView->scrollAreaContents()->setMaximumHeight(containerHeight);
       
   143     mBackgroundScrollArea->setMaximumHeight(containerHeight);
       
   144 }
       
   145 
       
   146 /*!
       
   147    This method creates all needed signal-slot connections
   118    This method creates all needed signal-slot connections
   148  */
   119  */
   149 void NmEditorContent::createConnections()
   120 void NmEditorContent::createConnections()
   150 {
   121 {
   151     // Body edit widget is also interested about bg scroll position change
   122     NM_FUNCTION;
   152     connect(mBackgroundScrollArea, SIGNAL(scrollPositionChanged(QPointF)),
   123     
   153             mEditorWidget, SLOT(updateScrollPosition(QPointF)));
       
   154     // Signal for setting HbTextEdit widgets html content
   124     // Signal for setting HbTextEdit widgets html content
   155     connect(this, SIGNAL(setHtml(QString)),
   125     connect(this, SIGNAL(setHtml(QString)),
   156             mEditorWidget, SLOT(setHtml(QString)));
   126             mEditorWidget, SLOT(setHtml(QString)), Qt::QueuedConnection);
       
   127 
   157     // Signal for setting HbTextEdit widgets plain text content
   128     // Signal for setting HbTextEdit widgets plain text content
   158     connect(this, SIGNAL(setPlainText(QString)),
   129     connect(this, SIGNAL(setPlainText(QString)),
   159             mEditorWidget, SLOT(setPlainText(QString)));
   130             mEditorWidget, SLOT(setPlainText(QString)), Qt::QueuedConnection);
       
   131 
   160     // Inform text edit widget that header height has been changed
   132     // Inform text edit widget that header height has been changed
   161     connect(mHeaderWidget, SIGNAL(headerHeightChanged(int)),
   133     connect(mHeader, SIGNAL(headerHeightChanged(int)), this, SLOT(setEditorContentHeight()),
   162             mEditorWidget, SLOT(setHeaderHeight(int)));
   134         Qt::QueuedConnection);
       
   135 
       
   136     // we are interested in the document's height changes
       
   137     connect(mEditorWidget->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), this,
       
   138         SLOT(setEditorContentHeight()), Qt::QueuedConnection);
       
   139 
       
   140     // We need to update the scroll position according the editor's cursor position
       
   141     connect(mHeader->toEdit(), SIGNAL(cursorPositionChanged(int, int)), this, 
       
   142         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
       
   143     connect(mHeader->ccEdit(), SIGNAL(cursorPositionChanged(int, int)), this, 
       
   144         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
       
   145     connect(mHeader->bccEdit(), SIGNAL(cursorPositionChanged(int, int)), this, 
       
   146         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
       
   147     connect(mHeader->subjectEdit(), SIGNAL(cursorPositionChanged(int, int)), this, 
       
   148         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
       
   149     connect(mEditorWidget, SIGNAL(cursorPositionChanged(int, int)), this, 
       
   150         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
       
   151 
       
   152     // listen to the parent's (NmEditorView) size changes which happen eg. when VKB is opened/closed
       
   153     connect(parent(), SIGNAL(sizeChanged()), this, SLOT(ensureCursorVisibility()),
       
   154         Qt::QueuedConnection);
   163 }
   155 }
   164 
   156 
   165 /*!
   157 /*!
   166     Return pointer to the email body text edit widget
   158     Return pointer to the email body text edit widget
   167  */
   159  */
   168 NmEditorTextEdit* NmEditorContent::editor() const
   160 NmEditorTextEdit *NmEditorContent::editor() const
   169 {
   161 {
       
   162     NM_FUNCTION;
       
   163     
   170     return mEditorWidget;
   164     return mEditorWidget;
   171 }
   165 }
   172 
   166 
   173 /*!
   167 /*!
   174     Return pointer to the header widget
   168     Return pointer to the header widget
   175  */
   169  */
   176 NmEditorHeader* NmEditorContent::header() const
   170 NmEditorHeader *NmEditorContent::header() const
   177 {
   171 {
   178     return mHeaderWidget;
   172     NM_FUNCTION;
   179 }
   173     
   180 
   174     return mHeader;
       
   175 }
       
   176 
       
   177 /*!
       
   178     This slot is called when header widget height has been changed. Function performs
       
   179     the repositioning of the body field and resizing of the editor and content area.
       
   180  */
       
   181 void NmEditorContent::setEditorContentHeight()
       
   182 {
       
   183     NM_FUNCTION;
       
   184     
       
   185     // the height of the margin between the title bar and the header
       
   186     qreal topMargin = 0;
       
   187     HbStyle().parameter("hb-param-margin-gene-top", topMargin);
       
   188     
       
   189     // header height
       
   190     qreal headerHeight = mHeader->headerHeight();
       
   191 
       
   192     // body area editor's document height with margins added
       
   193     qreal documentHeightAndMargins = mEditorWidget->document()->size().height() +
       
   194         (mEditorWidget->document()->documentMargin() * 2);
       
   195 
       
   196     // chrome height
       
   197     qreal chromeHeight = 0;
       
   198     HbStyle().parameter("hb-param-widget-chrome-height", chromeHeight);
       
   199     
       
   200     // screen height
       
   201     qreal screenHeight = mApplication.screenSize().height();
       
   202 
       
   203     // set min size for the body area so that at least the screen area is always filled
       
   204     qreal bodyAreaMinSize = screenHeight - chromeHeight - topMargin - headerHeight;
       
   205     
       
   206     qreal bodyAreaSize = fmax(bodyAreaMinSize, documentHeightAndMargins);
       
   207 
       
   208     mScrollAreaContents->setPreferredHeight(topMargin + headerHeight + bodyAreaSize);
       
   209 }
       
   210 
       
   211 /*!
       
   212     This slot is called when the cursor visibility has to be ensured ie. the scroll position is 
       
   213     adjusted so that the cursor can be seen.
       
   214 */
       
   215 void NmEditorContent::ensureCursorVisibility()
       
   216 {
       
   217     NM_FUNCTION;
       
   218 
       
   219     // check which of the editors has the focus and get the x/y coordinates for the cursor position
       
   220     QGraphicsWidget *focused = mScrollAreaContents->focusWidget();
       
   221     
       
   222     if (focused) {
       
   223         QRectF localRect(0, 0, 0, 0);
       
   224         bool notFound = false;
       
   225         
       
   226         if (focused == mHeader->toEdit()) {
       
   227             localRect = mHeader->toEdit()->rectForCursorPosition();
       
   228         }
       
   229         else if (focused == mHeader->ccEdit()) {
       
   230             localRect = mHeader->ccEdit()->rectForCursorPosition();
       
   231         }
       
   232         else if (focused == mHeader->bccEdit()) {
       
   233             localRect = mHeader->bccEdit()->rectForCursorPosition();
       
   234         }
       
   235         else if (focused == mHeader->subjectEdit()) {
       
   236             localRect = mHeader->subjectEdit()->rectForCursorPosition();
       
   237         }
       
   238         else if (focused == mEditorWidget) {
       
   239             localRect = mEditorWidget->rectForCursorPosition();
       
   240         }
       
   241         else {
       
   242             notFound = true;
       
   243         }
       
   244 
       
   245         if (!notFound) {
       
   246             QPointF topLeftPos = focused->mapToItem(mScrollAreaContents, localRect.topLeft());
       
   247             QPointF bottomRightPos =
       
   248                 focused->mapToItem(mScrollAreaContents, localRect.bottomRight());
       
   249             qreal marginRight = 0;
       
   250             HbStyle().parameter("hb-param-margin-gene-right", marginRight);
       
   251             bottomRightPos.rx() += marginRight;
       
   252             mScrollArea->ensureVisible(topLeftPos);
       
   253             mScrollArea->ensureVisible(bottomRightPos);
       
   254         }
       
   255     }
       
   256 }
       
   257 /*!
       
   258     Removes embedded images from the message body
       
   259  */
       
   260 void NmEditorContent::removeEmbeddedImages(QString &bodyContent)
       
   261 {
       
   262     NM_FUNCTION;
       
   263  
       
   264     QRegExp regExp(NMUI_EDITOR_REMOVE_EMBD_IMAGES_REG, Qt::CaseInsensitive);
       
   265     bodyContent.remove(regExp);
       
   266 }