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); |
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) |