emailuis/nmailui/src/nmviewerview.cpp
changeset 48 10eaf342f539
parent 47 f83bd4ae1fe3
child 51 d845db10c0d4
equal deleted inserted replaced
47:f83bd4ae1fe3 48:10eaf342f539
     9  * Initial Contributors:
     9  * Initial Contributors:
    10  * Nokia Corporation - initial contribution.
    10  * Nokia Corporation - initial contribution.
    11  *
    11  *
    12  * Contributors:
    12  * Contributors:
    13  *
    13  *
    14  * Description:
    14  * Description: Mail viewer implementation.
    15  *
    15  *
    16  */
    16  */
    17 
    17 
    18 #include "nmuiheaders.h"
    18 #include "nmuiheaders.h"
    19 
    19 
    23 static const char *NMUI_MESSAGE_VIEWER_SCROLL_AREA = "viewerScrollArea";
    23 static const char *NMUI_MESSAGE_VIEWER_SCROLL_AREA = "viewerScrollArea";
    24 static const char *NMUI_MESSAGE_VIEWER_SCROLL_AREA_CONTENTS = "viewerScrollAreaContents";
    24 static const char *NMUI_MESSAGE_VIEWER_SCROLL_AREA_CONTENTS = "viewerScrollAreaContents";
    25 static const char *NMUI_MESSAGE_VIEWER_HEADER = "viewerHeader";
    25 static const char *NMUI_MESSAGE_VIEWER_HEADER = "viewerHeader";
    26 static const char *NMUI_MESSAGE_VIEWER_ATTALIST = "viewerAttaList";
    26 static const char *NMUI_MESSAGE_VIEWER_ATTALIST = "viewerAttaList";
    27 static const char *NMUI_MESSAGE_VIEWER_SCROLL_WEB_VIEW = "viewerWebView";
    27 static const char *NMUI_MESSAGE_VIEWER_SCROLL_WEB_VIEW = "viewerWebView";
    28 
       
    29 static const int NmOrientationTimer = 100;
    28 static const int NmOrientationTimer = 100;
    30 static const int NmHeaderMargin = 3;
    29 static const int NmHeaderMargin = 3;
    31 
    30 static const int NmWhitePixmapSize = 10;
       
    31 static const int NmProgressValueComplete = 100;
    32 static const QString NmParamTextHeightSecondary = "hb-param-text-height-secondary";
    32 static const QString NmParamTextHeightSecondary = "hb-param-text-height-secondary";
       
    33 static const QString NmHttpLinkScheme = "http";
       
    34 static const QString NmHttpsLinkScheme = "https";
       
    35 static const QString NmMailtoLinkScheme = "mailto";
    33 
    36 
    34 /*!
    37 /*!
    35 	\class NmViewerView
    38 	\class NmViewerView
    36 	\brief Mail viewer class
    39 	\brief Mail viewer class
    37 */
    40 */
    60 mHeaderWidget(NULL),
    63 mHeaderWidget(NULL),
    61 mMessageFetchingOperation(NULL),
    64 mMessageFetchingOperation(NULL),
    62 mDisplayingPlainText(false),
    65 mDisplayingPlainText(false),
    63 mDocumentLoader(NULL),
    66 mDocumentLoader(NULL),
    64 mScrollAreaContents(NULL),
    67 mScrollAreaContents(NULL),
    65 mViewerHeaderContainer(NULL),
       
    66 mScreenSize(QSize(0,0)),
    68 mScreenSize(QSize(0,0)),
    67 mWaitDialog(NULL),
    69 mWaitDialog(NULL),
    68 webFrameloadingCompleted(false),
    70 webFrameloadingCompleted(false),
    69 mLatestLoadingSize(QSize(0,0)),
    71 mLatestLoadingSize(QSize(0,0)),
    70 mAttaIndexUnderFetch(NmNotFoundError),
    72 mAttaIndexUnderFetch(NmNotFoundError),
   133     NM_FUNCTION;
   135     NM_FUNCTION;
   134     
   136     
   135     // Use document loader to load the view
   137     // Use document loader to load the view
   136     bool ok(false);
   138     bool ok(false);
   137     setObjectName(QString(NMUI_MESSAGE_VIEWER_VIEW));
   139     setObjectName(QString(NMUI_MESSAGE_VIEWER_VIEW));
   138     // Pass the view to documentloader. Document loader uses this view
   140    QObjectList objectList;
   139     // when docml is parsed, instead of creating new view.
   141    objectList.append(this);
   140     // documentloader is created in constructor
   142    // Pass the view to documentloader. Document loader uses this view
   141     mWidgetList = mDocumentLoader->load(NMUI_MESSAGE_VIEWER_XML, &ok);
   143    // when docml is parsed, instead of creating new view.
   142     int widgetCount = mWidgetList.count();
   144    // documentloader is created in constructor
   143     if (ok == true && widgetCount)
   145    mDocumentLoader->setObjectTree(objectList);
   144     {
   146    mWidgetList = mDocumentLoader->load(NMUI_MESSAGE_VIEWER_XML, &ok);
       
   147 
       
   148    if (ok)
       
   149    {
   145         // Create content and content layout
   150         // Create content and content layout
   146         // qobject_cast not work in this case, using reinterpret_cast
   151         // qobject_cast not work in this case, using reinterpret_cast
   147         mViewerContent = reinterpret_cast<HbWidget *>(
   152         mViewerContent = reinterpret_cast<HbWidget *>(
   148                 mDocumentLoader->findObject(NMUI_MESSAGE_VIEWER_CONTENT));
   153                 mDocumentLoader->findObject(NMUI_MESSAGE_VIEWER_CONTENT));
   149         // Find scroll area
   154         // Find scroll area
   162                 QGraphicsLayout *layout = mScrollAreaContents->layout();
   167                 QGraphicsLayout *layout = mScrollAreaContents->layout();
   163                 if (layout){
   168                 if (layout){
   164                     layout->setContentsMargins(0,0,0,0);
   169                     layout->setContentsMargins(0,0,0,0);
   165                 }
   170                 }
   166                 // Set white pixmap to backgrounditem 
   171                 // Set white pixmap to backgrounditem 
   167                 QPixmap whitePixmap(10,10);
   172                 QPixmap whitePixmap(NmWhitePixmapSize,NmWhitePixmapSize);
   168                 whitePixmap.fill(Qt::white);
   173                 whitePixmap.fill(Qt::white);
   169                 QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem(whitePixmap);
   174                 QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem(whitePixmap);
   170                 mScrollAreaContents->setBackgroundItem(pixmapItem);
   175                 mScrollAreaContents->setBackgroundItem(pixmapItem);
   171             }
   176             }
   172 
   177 
   182 
   187 
   183             // Load webview
   188             // Load webview
   184             mWebView = reinterpret_cast<NmMailViewerWK *>(
   189             mWebView = reinterpret_cast<NmMailViewerWK *>(
   185                     mDocumentLoader->findObject(QString(NMUI_MESSAGE_VIEWER_SCROLL_WEB_VIEW)));
   190                     mDocumentLoader->findObject(QString(NMUI_MESSAGE_VIEWER_SCROLL_WEB_VIEW)));
   186             if (mWebView) {
   191             if (mWebView) {
   187                 mWebView->setParentView(this);
       
   188                 // Set auto load images and private browsing(no history) attributes
   192                 // Set auto load images and private browsing(no history) attributes
   189                 QWebSettings *settings = mWebView->settings();
   193                 QWebSettings *settings = mWebView->settings();
   190                 if (settings) {
   194                 if (settings) {
   191                     settings->setAttribute(QWebSettings::AutoLoadImages, true);
   195                     settings->setAttribute(QWebSettings::AutoLoadImages, true);
   192                     settings->setAttribute(QWebSettings::PrivateBrowsingEnabled, true);   
   196                     settings->setAttribute(QWebSettings::PrivateBrowsingEnabled, true);   
   455 
   459 
   456 */
   460 */
   457 void NmViewerView::openAttachment(int index)
   461 void NmViewerView::openAttachment(int index)
   458 {
   462 {
   459     NM_FUNCTION;
   463     NM_FUNCTION;
   460     
   464     if (index >= 0) {
   461     NmId attaId = mAttaIdList.at(index);
   465         NmId attaId = mAttaIdList.at(index);
   462     // reload message to get updates part sizes
   466         // reload message to get updates part sizes
   463     loadMessage();
   467         loadMessage();
   464     QList<NmMessagePart*> messageParts;
   468         QList<NmMessagePart*> messageParts;
   465     mMessage->attachmentList(messageParts);
   469         if (mMessage) {
   466     NmId mailboxId = mMessage->envelope().mailboxId();
   470             mMessage->attachmentList(messageParts);
   467     NmId folderId = mMessage->envelope().folderId();
   471              NmId mailboxId = mMessage->envelope().mailboxId();
   468     NmId messageId = mMessage->envelope().messageId();
   472              NmId folderId = mMessage->envelope().folderId();
   469     for (int i = 0; i < messageParts.count(); i++) {
   473              NmId messageId = mMessage->envelope().messageId();
   470         // message part found have to found
   474              for (int i = 0; i < messageParts.count(); i++) {
   471         // and its fetched size is smaller than size, then start part fetch
   475                  // message part found have to found
   472         if (messageParts[i]->partId() == attaId &&
   476                  // and its fetched size is smaller than size, then start part fetch
   473             messageParts[i]->size() > messageParts[i]->fetchedSize()) {
   477                  if (messageParts[i]->partId() == attaId &&
   474             // do not start if there's already ongoing fetch
   478                      messageParts[i]->size() > messageParts[i]->fetchedSize()) {
   475             if (mAttaIndexUnderFetch == NmNotFoundError) {
   479                      // do not start if there's already ongoing fetch
   476                 mAttaIndexUnderFetch = index;
   480                      if (mAttaIndexUnderFetch == NmNotFoundError) {
   477                 mAttaManager.fetchAttachment(mailboxId, folderId,
   481                          mAttaIndexUnderFetch = index;
   478                                              messageId, attaId);
   482                          mAttaManager.fetchAttachment(mailboxId, folderId,
   479             }
   483                                                       messageId, attaId);
   480         }
   484                      }
   481         // attachment is fetched, open file
   485                  }
   482         else if (messageParts[i]->partId() == attaId) {
   486                  // attachment is fetched, open file
   483             mAttaManager.cancelFetch();
   487                  else if (messageParts[i]->partId() == attaId) {
   484             XQSharableFile file = mUiEngine.messagePartFile(mailboxId, folderId,
   488                      mAttaManager.cancelFetch();
   485                                                             messageId, attaId);
   489                      XQSharableFile file = mUiEngine.messagePartFile(mailboxId, folderId,
   486             int error = NmUtilities::openFile(file);
   490                                                                      messageId, attaId);
   487             file.close();
   491                      int error = NmUtilities::openFile(file);
   488             if (error==NmNotFoundError){
   492                      file.close();
   489                 delete mErrorNote;
   493                      if (error==NmNotFoundError){
   490                 mErrorNote=NULL;
   494                          delete mErrorNote;
   491                 mErrorNote = NmUtilities::displayWarningNote(hbTrId("txt_mail_dialog_unable_to_open_attachment_file_ty"));
   495                          mErrorNote=NULL;
   492             }
   496                          mErrorNote = NmUtilities::displayWarningNote(
   493         }
   497                                  hbTrId("txt_mail_dialog_unable_to_open_attachment_file_ty"));
       
   498                      }
       
   499                  }
       
   500              }            
       
   501          }
   494     }
   502     }
   495 }
   503 }
   496 
   504 
   497 /*!
   505 /*!
   498     Function formats message based on actual data
   506     Function formats message based on actual data
   500 QString NmViewerView::formatMessage()
   508 QString NmViewerView::formatMessage()
   501 {
   509 {
   502     NM_FUNCTION;
   510     NM_FUNCTION;
   503     
   511     
   504     QString msg = "";
   512     QString msg = "";
   505     // null pointer check for mMessage is done before calling this function
   513     if (mMessage) {
   506     NmId mailboxId = mMessage->envelope().mailboxId();
   514         NmMessagePart *html = mMessage->htmlBodyPart();
   507     NmId folderId = mMessage->envelope().folderId();
   515         if (html) {
   508     NmId messageId = mMessage->envelope().messageId();
   516             msg += formatHtmlMessage(html);
   509     NmMessagePart *html = mMessage->htmlBodyPart();
   517         }
   510     if (html) {
   518         else {
       
   519             NmMessagePart *plain = mMessage->plainTextBodyPart();
       
   520             if (plain) {
       
   521                 msg += formatPlainTextMessage(plain);
       
   522             }
       
   523         }    
       
   524     }
       
   525     return msg;
       
   526 }
       
   527 
       
   528 /*!
       
   529     Function formats html message
       
   530 */
       
   531 QString NmViewerView::formatHtmlMessage(NmMessagePart *html)
       
   532 {    
       
   533     NM_FUNCTION;
       
   534 
       
   535     QString msg = "";
       
   536     if (html && mMessage) {
       
   537         NmId mailboxId = mMessage->envelope().mailboxId();
       
   538         NmId folderId = mMessage->envelope().folderId();
       
   539         NmId messageId = mMessage->envelope().messageId();
   511         QList<NmMessagePart*> parts;
   540         QList<NmMessagePart*> parts;
   512         mMessage->attachmentList(parts);
   541         mMessage->attachmentList(parts);
   513         for (int i=0; i < parts.count(); i++) {
   542         for (int i=0; i < parts.count(); i++) {
   514             NmMessagePart *child = parts[i];
   543             NmMessagePart *child = parts[i];
   515             // Browse through embedded image parts and add those
   544             // Browse through embedded image parts and add those
   531                 }
   560                 }
   532             }
   561             }
   533         }
   562         }
   534         int ret = mUiEngine.contentToMessagePart(mailboxId, folderId, messageId, *html);
   563         int ret = mUiEngine.contentToMessagePart(mailboxId, folderId, messageId, *html);
   535         if (ret == NmNoError) {
   564         if (ret == NmNoError) {
   536             msg = html->textContent();
   565          msg = html->textContent();
   537         }
   566         }    
   538     }
   567     }
   539     else {
   568     return msg;
   540         NmMessagePart *plain = mMessage->plainTextBodyPart();
   569 }
   541         if (plain) {
   570 
   542             int ret = mUiEngine.contentToMessagePart(mailboxId, folderId,
   571 /*!
   543                                                      messageId, *plain);
   572     Function formats plain text message message
   544             if (ret == NmNoError) {
   573 */
   545                 QTextDocument document;
   574 QString NmViewerView::formatPlainTextMessage(NmMessagePart *plain)
   546                 // set font
   575 {
   547                 QFont currentFont = document.defaultFont();
   576     NM_FUNCTION;
   548                 currentFont.setWeight(QFont::Normal);
   577       
   549                 qreal secondarySize;
   578     QString msg = "";
   550                 HbStyle myStyle;
   579     if (plain && mMessage) {
   551                 bool found = myStyle.parameter(NmParamTextHeightSecondary, secondarySize);
   580         NmId mailboxId = mMessage->envelope().mailboxId();
   552                 if (found) {
   581         NmId folderId = mMessage->envelope().folderId();
   553                     HbFontSpec fontSpec(HbFontSpec::Secondary);
   582         NmId messageId = mMessage->envelope().messageId();
   554                     fontSpec.setTextHeight(secondarySize);
   583         int ret = mUiEngine.contentToMessagePart(mailboxId, folderId,
   555                     currentFont.setPixelSize(fontSpec.font().pixelSize());
   584                                                  messageId, *plain);
       
   585         if (ret == NmNoError) {
       
   586             QTextDocument document;
       
   587             // set font
       
   588             QFont currentFont = document.defaultFont();
       
   589             currentFont.setWeight(QFont::Normal);
       
   590             qreal secondarySize;
       
   591             HbStyle myStyle;
       
   592             bool found = myStyle.parameter(NmParamTextHeightSecondary, secondarySize);
       
   593             if (found) {
       
   594                 HbFontSpec fontSpec(HbFontSpec::Secondary);
       
   595                 fontSpec.setTextHeight(secondarySize);
       
   596                 currentFont.setPixelSize(fontSpec.font().pixelSize());
       
   597             }
       
   598             document.setDefaultFont(currentFont);
       
   599             // convert to html
       
   600             document.setPlainText(plain->textContent());
       
   601             msg = document.toHtml();
       
   602     
       
   603             if (qApp->layoutDirection()==Qt::RightToLeft){
       
   604                 // add right alignment to document css section
       
   605                 QRegExp rx("(<style type=\"text/css\">)(.+)(</style>)", Qt::CaseInsensitive);
       
   606                 rx.setMinimal(true);
       
   607                 int pos = rx.indexIn(msg);
       
   608                 if (pos > -1) {
       
   609                     QString newStr = rx.cap(1);
       
   610                     newStr.append(rx.cap(2));
       
   611                     newStr.append("p { text-align: right } ");
       
   612                     newStr.append(rx.cap(3));
       
   613                     msg.replace(rx, newStr);
   556                 }
   614                 }
   557                 document.setDefaultFont(currentFont);
   615             }
   558                 // convert to html
   616         }    
   559                 document.setPlainText(plain->textContent());
   617     }
   560                 msg = document.toHtml();
   618     mDisplayingPlainText=true;  
   561 
       
   562                 if (qApp->layoutDirection()==Qt::RightToLeft){
       
   563                     // add right alignment to document css section
       
   564                     QRegExp rx("(<style type=\"text/css\">)(.+)(</style>)", Qt::CaseInsensitive);
       
   565                     rx.setMinimal(true);
       
   566                     int pos = rx.indexIn(msg);
       
   567                     if (pos > -1) {
       
   568                         QString newStr = rx.cap(1);
       
   569                         newStr.append(rx.cap(2));
       
   570                         newStr.append("p { text-align: right } ");
       
   571                         newStr.append(rx.cap(3));
       
   572                         msg.replace(rx, newStr);
       
   573                     }
       
   574                 }
       
   575             }
       
   576             mDisplayingPlainText=true;
       
   577         }
       
   578     }
       
   579     return msg;
   619     return msg;
   580 }
   620 }
   581 
   621 
   582 /*!
   622 /*!
   583     Reload view contents with new start parameters
   623     Reload view contents with new start parameters
   657     Scale web view width when loading is completed
   697     Scale web view width when loading is completed
   658 */
   698 */
   659 void NmViewerView::scaleWebViewWhenLoaded()
   699 void NmViewerView::scaleWebViewWhenLoaded()
   660 {
   700 {
   661     QRectF myGeometry = geometry();
   701     QRectF myGeometry = geometry();
   662     if (mWebView && mWebView->page()) {
   702     QWebPage *page = mWebView->page();
   663         mWebView->page()->setViewportSize(myGeometry.size().toSize());
   703     if (mWebView && page) {
   664         QSizeF contentSize = mWebView->page()->mainFrame()->contentsSize();
   704         page->setViewportSize(myGeometry.size().toSize());
       
   705         QSizeF contentSize = page->mainFrame()->contentsSize();
   665         int width = (int)contentSize.width();
   706         int width = (int)contentSize.width();
   666         int height = (int)contentSize.height();  
   707         int height = (int)contentSize.height();  
   667         mWebView->setPreferredWidth(width);
   708         mWebView->setPreferredWidth(width);
   668         mWebView->setPreferredHeight(height);
   709         mWebView->setPreferredHeight(height);
   669     }
   710     }
   709 */
   750 */
   710 void NmViewerView::linkClicked(const QUrl& link)
   751 void NmViewerView::linkClicked(const QUrl& link)
   711 {
   752 {
   712     NM_FUNCTION;
   753     NM_FUNCTION;
   713     
   754     
   714     if (link.scheme() == "http" ||
   755     if (link.scheme() == NmHttpLinkScheme ||
   715         link.scheme() == "https" ) {
   756         link.scheme() == NmHttpsLinkScheme) {
   716         mAttaManager.cancelFetch();
   757         mAttaManager.cancelFetch();
   717         QDesktopServices::openUrl(link);
   758         QDesktopServices::openUrl(link);
   718     } else if (link.scheme() == "mailto"){
   759     } else if (link.scheme() == NmMailtoLinkScheme){
   719         mAttaManager.cancelFetch();
   760         mAttaManager.cancelFetch();
   720         QList<NmAddress*> *addrList = new QList<NmAddress*>();
   761         QList<NmAddress*> *addrList = new QList<NmAddress*>();
   721         NmAddress *mailtoAddr = new NmAddress();
   762         NmAddress *mailtoAddr = new NmAddress();
   722         QString address = link.toString(QUrl::RemoveScheme);
   763         QString address = link.toString(QUrl::RemoveScheme);
   723         mailtoAddr->setAddress(address);
   764         mailtoAddr->setAddress(address);
   752     }
   793     }
   753     return ret;
   794     return ret;
   754 }
   795 }
   755 
   796 
   756 /*!
   797 /*!
   757    get function for content widget web view.
   798     Get function for content widget web view.
   758 */
   799 */
   759 NmMailViewerWK* NmViewerView::webView()
   800 NmMailViewerWK* NmViewerView::webView()
   760 {
   801 {
   761     return mWebView;
   802     return mWebView;
   762 }
   803 }
   763 
   804 
   764 /*!
   805 /*!
   765 
   806     Get function for message being viewed
   766 */
   807 */
   767 NmMessage* NmViewerView::message()
   808 NmMessage* NmViewerView::message()
   768 {
   809 {
   769     return mMessage;
   810     return mMessage;
   770 }
   811 }
   936 void NmViewerView::deleteMessage()
   977 void NmViewerView::deleteMessage()
   937 {
   978 {
   938     NM_FUNCTION;
   979     NM_FUNCTION;
   939     
   980     
   940     QList<NmId> messageList;
   981     QList<NmId> messageList;
   941     messageList.append(mStartParam->messageId());
   982     messageList.append(mStartParam->messageId());  
   942     
       
   943     int err = mUiEngine.deleteMessages(mStartParam->mailboxId(),
   983     int err = mUiEngine.deleteMessages(mStartParam->mailboxId(),
   944                                        mStartParam->folderId(),
   984                                        mStartParam->folderId(),
   945                                        messageList);
   985                                        messageList);
   946     
       
   947     messageList.clear();
   986     messageList.clear();
   948     if (NmNoError != err) {
       
   949         // Failed to delete the messages!
       
   950         NMLOG(QString("NmViewerView::handleActionCommand(): failed err=%1").arg(err));
       
   951     }
       
   952 }
   987 }
   953 
   988 
   954 
   989 
   955 /*!
   990 /*!
   956     This is called when attachment fetch progress changes
   991     This is called when attachment fetch progress changes
   970 */
  1005 */
   971 void NmViewerView::fetchCompleted(int result)
  1006 void NmViewerView::fetchCompleted(int result)
   972 {
  1007 {
   973     if (mAttaWidget && mAttaIndexUnderFetch != NmNotFoundError) {
  1008     if (mAttaWidget && mAttaIndexUnderFetch != NmNotFoundError) {
   974         if (result == NmNoError) {
  1009         if (result == NmNoError) {
   975             progressValueChanged(mAttaIndexUnderFetch, 100);
  1010             progressValueChanged(mAttaIndexUnderFetch, NmProgressValueComplete);
   976             openAttachment(mAttaIndexUnderFetch);
  1011             openAttachment(mAttaIndexUnderFetch);
   977         } else {
  1012         } else {
   978             mAttaWidget->hideProgressBar(mAttaIndexUnderFetch);
  1013             mAttaWidget->hideProgressBar(mAttaIndexUnderFetch);
   979         }
  1014         }
   980     }
  1015     }
   981     mAttaIndexUnderFetch = NmNotFoundError;
  1016     mAttaIndexUnderFetch = NmNotFoundError;
   982 }
  1017 }
   983 
  1018 
   984 /*!
  1019 /*!
   985     externalDelete. From NmMessageListModel, handles viewer shutdown when current message is deleted.
  1020     externalDelete. From NmUiEngine, handles viewer shutdown when current message is deleted.
   986 */
  1021 */
   987 void NmViewerView::messageDeleted(const NmId &mailboxId, const NmId &folderId, const NmId &messageId)
  1022 void NmViewerView::messageDeleted(const NmId &mailboxId, const NmId &folderId, const NmId &messageId)
   988 {
  1023 {
   989     if ((mStartParam->viewId() == NmUiViewMessageViewer)
  1024     if ((mStartParam->viewId() == NmUiViewMessageViewer)
   990         && (mStartParam->mailboxId()== mailboxId)
  1025         && (mStartParam->mailboxId()== mailboxId)