emailuis/nmailui/src/nmeditorcontent.cpp
changeset 75 47d84de1c893
parent 72 64e38f08e49c
equal deleted inserted replaced
72:64e38f08e49c 75:47d84de1c893
   123         htmlPart = originalMessage->htmlBodyPart();
   123         htmlPart = originalMessage->htmlBodyPart();
   124         plainPart = originalMessage->plainTextBodyPart();
   124         plainPart = originalMessage->plainTextBodyPart();
   125     }
   125     }
   126  
   126  
   127     if (htmlPart) {
   127     if (htmlPart) {
   128         bodyContent.append(htmlPart->textContent());
   128         QString bodyText(htmlPart->textContent());
       
   129         if (editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll || 
       
   130                 editorStartMode==NmUiEditorForward) {
       
   131             convertBodyStylesToDivision(bodyText);
       
   132         }
       
   133         
   129         if(editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll ) {
   134         if(editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll ) {
   130             removeEmbeddedImages(bodyContent);
   135             removeEmbeddedImages(bodyText);
   131         }
   136         }
       
   137         
       
   138         bodyContent.append(bodyText);
       
   139         cursor.insertHtml(bodyContent);
   132     }
   140     }
   133     else if (plainPart) {
   141     else if (plainPart) {
   134         // Plain text part was present, set it to HbTextEdit as HTML
   142         // Plain text part was present, set it to HbTextEdit as HTML
   135         bodyContent.append(QString("<html><body><p>"));
   143         bodyContent.append(QString("<html><body><p>"));
   136         bodyContent.append(plainPart->textContent());
   144         bodyContent.append(plainPart->textContent());
   271     adjusted so that the cursor can be seen.
   279     adjusted so that the cursor can be seen.
   272 */
   280 */
   273 void NmEditorContent::ensureCursorVisibility()
   281 void NmEditorContent::ensureCursorVisibility()
   274 {
   282 {
   275     NM_FUNCTION;
   283     NM_FUNCTION;
   276 
   284     
   277     // check which of the editors has the focus and get the x/y coordinates for the cursor position
   285     QGraphicsItem *focused = NULL;
   278     QGraphicsWidget *focused = mScrollAreaContents->focusWidget();
   286     QRectF localRect; // set to empty
   279     
   287     
   280     if (focused) {
   288     // find out which widget has the input focus and get the cursor position ractangle
   281         QRectF localRect(0, 0, 0, 0);
   289     if (mHeader->toEdit() && mHeader->toEdit()->hasInputFocus()) {
   282         bool notFound = false;
   290         focused = mHeader->toEdit();
   283         
   291         localRect = mHeader->toEdit()->rectForCursorPosition();
   284         if (focused == mHeader->toEdit()) {
   292     }
   285             localRect = mHeader->toEdit()->rectForCursorPosition();
   293     else if (mHeader->ccEdit() && mHeader->ccEdit()->hasInputFocus()) {
       
   294         focused = mHeader->ccEdit();
       
   295         localRect = mHeader->ccEdit()->rectForCursorPosition();
       
   296     }
       
   297     else if (mHeader->bccEdit() && mHeader->bccEdit()->hasInputFocus()) {
       
   298         focused = mHeader->bccEdit();
       
   299         localRect = mHeader->bccEdit()->rectForCursorPosition();
       
   300     }
       
   301     else if (mHeader->subjectEdit() && mHeader->subjectEdit()->hasInputFocus()) {
       
   302         focused = mHeader->subjectEdit();
       
   303         localRect = mHeader->subjectEdit()->rectForCursorPosition();
       
   304     }
       
   305     else if (mEditorWidget->hasInputFocus()) {
       
   306         focused = mEditorWidget;
       
   307         localRect = mEditorWidget->rectForCursorPosition();
       
   308     }
       
   309 
       
   310     // ensure that the cursor position is visible
       
   311     if (focused && !localRect.isEmpty()) {
       
   312         QPointF topLeftPos = focused->mapToItem(mScrollAreaContents, localRect.topLeft());
       
   313         QPointF bottomRightPos =
       
   314             focused->mapToItem(mScrollAreaContents, localRect.bottomRight());
       
   315         qreal marginRight = 0;
       
   316         if (mScrollArea->style()) {
       
   317             mScrollArea->style()->parameter("hb-param-margin-gene-right", marginRight);
   286         }
   318         }
   287         else if (focused == mHeader->ccEdit()) {
   319         bottomRightPos.rx() += marginRight;
   288             localRect = mHeader->ccEdit()->rectForCursorPosition();
   320 
   289         }
   321         mScrollArea->ensureVisible(topLeftPos);
   290         else if (focused == mHeader->bccEdit()) {
   322         mScrollArea->ensureVisible(bottomRightPos);
   291             localRect = mHeader->bccEdit()->rectForCursorPosition();
       
   292         }
       
   293         else if (focused == mHeader->subjectEdit()) {
       
   294             localRect = mHeader->subjectEdit()->rectForCursorPosition();
       
   295         }
       
   296         else if (focused == mEditorWidget) {
       
   297             localRect = mEditorWidget->rectForCursorPosition();
       
   298         }
       
   299         else {
       
   300             notFound = true;
       
   301         }
       
   302 
       
   303         if (!notFound) {
       
   304             QPointF topLeftPos = focused->mapToItem(mScrollAreaContents, localRect.topLeft());
       
   305             QPointF bottomRightPos =
       
   306                 focused->mapToItem(mScrollAreaContents, localRect.bottomRight());
       
   307             qreal marginRight = 0;
       
   308             mScrollArea->style()->parameter("hb-param-margin-gene-right", marginRight);
       
   309             bottomRightPos.rx() += marginRight;
       
   310             mScrollArea->ensureVisible(topLeftPos);
       
   311             mScrollArea->ensureVisible(bottomRightPos);
       
   312         }
       
   313     }
   323     }
   314 }
   324 }
   315 /*!
   325 /*!
   316     Removes embedded images from the message body
   326     Removes embedded images from the message body
   317  */
   327  */
   357     }
   367     }
   358     // Call header to perform the translation which moves hader to new position.
   368     // Call header to perform the translation which moves hader to new position.
   359     mHeader->repositHeader(tr);
   369     mHeader->repositHeader(tr);
   360 }
   370 }
   361 
   371 
       
   372 /*!
       
   373     Removes body bgcolor tag from content and creates DIV from it.
       
   374  */
       
   375 void NmEditorContent::convertBodyStylesToDivision(QString &bodyContent)
       
   376 {
       
   377     NM_FUNCTION;
       
   378     convertBGColorToStyle(bodyContent);
       
   379   
       
   380     // Make division from the head style body tag
       
   381     createDivisionFromHead(bodyContent);
       
   382 }
       
   383 
       
   384 /*!
       
   385  *  Creates div.reply from the html header styles (if there is any) and applies this 
       
   386  *  style to the message by surrounding the message with the div.reply element.
       
   387  *  
       
   388  *  Example:
       
   389  *  <html><head>
       
   390  *  <style type="text/css">
       
   391  *  body {
       
   392  *  color: #FF0000;
       
   393  *  background-color: #ffffff }
       
   394  *  h3{ color: blue }
       
   395  *  </style></head>
       
   396  *  <body>
       
   397  *  <h3>This is bigger text.</h3>
       
   398  *  This is the body text.
       
   399  *  </body></html>
       
   400  *  
       
   401  *      ---->
       
   402  *      
       
   403  *  <html><head>
       
   404  *  <style type="text/css">
       
   405  *  div.reply {
       
   406  *  color: #FF0000;
       
   407  *  background-color: #ffffff }
       
   408  *  h3 { color: blue }
       
   409  *  </style></head>
       
   410  *  <body>
       
   411  *  <div class="reply">
       
   412  *  <h3>This is bigger text.</h3>
       
   413  *  This is the body text.
       
   414  *  </div></body></html> 
       
   415  *  
       
   416  */
       
   417 void NmEditorContent::createDivisionFromHead(QString &bodyContent)
       
   418 {
       
   419     NM_FUNCTION;
       
   420     
       
   421     // Regular expression string for searching <head> part that contains <style>
       
   422     QString bodyStyleDefined(
       
   423         "<head"
       
   424         "(\\s)*"    // 0-* white spaces, browsers seem to accept this too.
       
   425         ">"
       
   426         "(.)*"      // 0-* any characters
       
   427         "<style"
       
   428         "(.)*"      // 0-* any characters
       
   429         "</head"
       
   430         "(\\s)*"    // 0-* white spaces
       
   431         ">");
       
   432     QRegExp bodyStyleDefinedRegExp(bodyStyleDefined, Qt::CaseInsensitive);
       
   433     bodyStyleDefinedRegExp.setMinimal(true);
       
   434     
       
   435     QString bodyStartReplacement("<body>\n<div");
       
   436     
       
   437     if(bodyContent.contains(bodyStyleDefinedRegExp)) {
       
   438         QString headPartString = bodyStyleDefinedRegExp.cap(0);
       
   439         QString headBodyStyleString("body(\\s)*");
       
   440         QRegExp bodyStyleReplacementRegExp(headBodyStyleString, Qt::CaseInsensitive);
       
   441         
       
   442         if(headPartString.contains(bodyStyleReplacementRegExp)) {
       
   443             headPartString.replace(bodyStyleReplacementRegExp, "div.reply ");
       
   444             bodyContent.replace(bodyStyleDefinedRegExp, headPartString);
       
   445             
       
   446             bodyStartReplacement = "<body>\n<div class=\"reply\"";
       
   447         }
       
   448     }
       
   449     
       
   450     convertBodyToDiv(bodyContent, bodyStartReplacement);
       
   451 }
       
   452 
       
   453 /*!
       
   454  *  Renames <body...></body> to <div...></div> and creates new <body> element.
       
   455  *  
       
   456  *  Example:
       
   457  *  <body style="background: #00ff00; color: red; border: solid">
       
   458  *  This is the body text.
       
   459  *  </body>
       
   460  *
       
   461  *      ---->
       
   462  *  
       
   463  *  <body>    
       
   464  *  <div style="background: #00ff00; color: red; border: solid">
       
   465  *  This is the body text.
       
   466  *  </div>
       
   467  *  </body>
       
   468  *  
       
   469  *  TODO: Tämä tapahtuu toistaiseksi riippumatta siitä onko bodyssa style-määrittelyä.
       
   470  *  TODO: Entä jos dokumentissa on määritelty useampi <body>? 
       
   471  */
       
   472 void NmEditorContent::convertBodyToDiv(QString &bodyContent, const QString &replacementString)
       
   473 {
       
   474     NM_FUNCTION;
       
   475     
       
   476     QString bodyStart("<body");
       
   477     QString bodyEnd("</body>");
       
   478     QString bodyEndReplacement("</div></body>");
       
   479     QRegExp bodyStartRegExp(bodyStart, Qt::CaseInsensitive);
       
   480     QRegExp bodyEndRegExp(bodyEnd, Qt::CaseInsensitive);
       
   481     
       
   482     bodyContent.replace(bodyStartRegExp, replacementString);
       
   483     bodyContent.replace(bodyEndRegExp, bodyEndReplacement);    
       
   484 }
       
   485 
       
   486 /*!
       
   487  *  Converts "body bgcolor=#color" attribute to "body style=background: #color".
       
   488  *  
       
   489  *  Example:
       
   490  *  <body bgcolor="blue"></body> 
       
   491  *  
       
   492  *              ----->
       
   493  *  
       
   494  *  <body style="background:blue"></div></body>
       
   495  */
       
   496 void NmEditorContent::convertBGColorToStyle(QString &bodyContent)
       
   497 {
       
   498     NM_FUNCTION;
       
   499     
       
   500     QString bgColorInBodyFetchString("<body[^<]+(bgcolor(\\s|)=(\\s|)(\"|)(#|))*>");
       
   501     QRegExp bgColorInBodyRegExp(bgColorInBodyFetchString, Qt::CaseInsensitive);
       
   502     
       
   503     if(bodyContent.contains(bgColorInBodyRegExp)) {
       
   504         // There can be only one meaningful bgcolor, the first one.
       
   505         QString bgColorString = bgColorInBodyRegExp.cap(0);
       
   506         
       
   507         // Extract the color code from the string
       
   508         QString colorCode(bgColorString);
       
   509         QRegExp removeBeginningRegExp(
       
   510             "<body"
       
   511             "[^<]+"         // 1...* any character except '<'
       
   512             "bgcolor"
       
   513             "(\\s|)"        // White space or nothing
       
   514             "="
       
   515             "(\\s|)"        // White space or nothing
       
   516             "(\"|)"         // '"' or nothing
       
   517             "(#|)",         // '#' or nothing
       
   518             Qt::CaseInsensitive);
       
   519         colorCode.remove(removeBeginningRegExp);
       
   520         
       
   521         QRegExp removeEndRegExp(""
       
   522             "((\"|\\s)"     // '"' or white space
       
   523             "([^<]*)"       // 0...* any characters except '<'
       
   524             ">)"            // '>'           
       
   525             "|>");          // ... or nothing before this, just '>'
       
   526         colorCode.remove(removeEndRegExp);
       
   527         
       
   528         QString plainBgColorFetchString("bgcolor(\\s|)*=(\\s|)*[^\\s]+(\\s|(?=>))");
       
   529         QString bgColorReplacement("style=\"background: #"+colorCode+"\" ");
       
   530         QRegExp plainBgColorFetchRegExp(plainBgColorFetchString, Qt::CaseInsensitive);
       
   531         
       
   532         // Create temporary string for bgcolor
       
   533         bgColorString.replace(plainBgColorFetchRegExp, bgColorReplacement);
       
   534         
       
   535         // Copy the contents of the temporary string to the message
       
   536         bodyContent.replace(bgColorInBodyRegExp, bgColorString);
       
   537     }    
       
   538 }