diff --git a/messageviewer/src/header/autotests/data/bcctest.tmpl b/messageviewer/src/header/autotests/data/bcctest.tmpl
index a2d107f1..f003675c 100644
--- a/messageviewer/src/header/autotests/data/bcctest.tmpl
+++ b/messageviewer/src/header/autotests/data/bcctest.tmpl
@@ -1,7 +1,7 @@
-
nameOnly: {{ header.bccNameOnly|safe }}
+nameOnly: {{ header.bcc.nameOnly|safe }}
isSet: {{ header.bcc.isSet|safe }}
-fullAddress: {{ header.bcc|safe }}
-str: {{ header.bccStr }}
-expandable: {{ header.bccExpandableCc|safe }}
-expandableTO: {{ header.bcc.expandableCC|safe }}
+fullAddress: {{ header.bcc.fullAddress|safe }}
+str: {{ header.bcc.str }}
+expandable: {{ header.bcc.expandableBc|safe }}
+expandableTO: {{ header.bcc.expandableBCC|safe }}
invalid: {{ header.bcc.invalid|safe }}
diff --git a/messageviewer/src/header/autotests/data/bcctest.tmpl.html b/messageviewer/src/header/autotests/data/bcctest.tmpl.html
index 316a4ff8..50346d2b 100644
--- a/messageviewer/src/header/autotests/data/bcctest.tmpl.html
+++ b/messageviewer/src/header/autotests/data/bcctest.tmpl.html
@@ -1,17 +1,17 @@
-
isSet:
+
isSet: true
str: blind copy recipient1 <bccspam1@example.org>, blind copy recipient2 <bccspam2@example.org>, blind copy recipient3 <bccspam3@example.org>, blind copy recipient4 <bccspam4@example.org>, blind copy recipient5 <bccspam5@example.org>, blind copy recipient6 <bccspam6@example.org>
-
expandable:
-
expandableTO:
+
+
invalid:
diff --git a/messageviewer/src/header/autotests/data/cctest.tmpl b/messageviewer/src/header/autotests/data/cctest.tmpl
index 990fd840..417b92b6 100644
--- a/messageviewer/src/header/autotests/data/cctest.tmpl
+++ b/messageviewer/src/header/autotests/data/cctest.tmpl
@@ -1,7 +1,7 @@
-nameOnly: {{ header.ccNameOnly|safe }}
+nameOnly: {{ header.cc.nameOnly|safe }}
isSet: {{ header.cc.isSet|safe }}
-fullAddress: {{ header.cc|safe }}
-str: {{ header.ccStr }}
-expandable: {{ header.ccExpandable|safe }}
-expandableTO: {{ header.cc.expandableTO|safe }}
+fullAddress: {{ header.cc.fullAddress|safe }}
+str: {{ header.cc.str }}
+expandable: {{ header.cc.expandableCc|safe }}
+expandableTO: {{ header.cc.expandableCC|safe }}
invalid: {{ header.cc.invalid|safe }}
diff --git a/messageviewer/src/header/autotests/data/cctest.tmpl.html b/messageviewer/src/header/autotests/data/cctest.tmpl.html
index 4e48ca46..b08cdcf3 100644
--- a/messageviewer/src/header/autotests/data/cctest.tmpl.html
+++ b/messageviewer/src/header/autotests/data/cctest.tmpl.html
@@ -1,17 +1,17 @@
-
isSet:
+
isSet: true
str: copy recipient1 <ccspam1@example.org>, copy recipient2 <ccspam2@example.org>, copy recipient3 <ccspam3@example.org>, copy recipient4 <ccspam4@example.org>, copy recipient5 <ccspam5@example.org>, copy recipient6 <ccspam6@example.org>
-
expandableTO:
+
invalid:
diff --git a/messageviewer/src/header/autotests/data/datetest.tmpl b/messageviewer/src/header/autotests/data/datetest.tmpl
index f7b1113f..1cbb6756 100644
--- a/messageviewer/src/header/autotests/data/datetest.tmpl
+++ b/messageviewer/src/header/autotests/data/datetest.tmpl
@@ -1,7 +1,7 @@
-str: {{ header.date|safe }}
-short: {{ header.dateshort|safe }}
-long: {{ header.datelong|safe }}
-fancylong: {{ header.datefancylong|safe }}
-fancyshort: {{ header.datefancyshort|safe }}
-localelong: {{ header.datelocalelong|safe }}
+str: {{ header.date.str|safe }}
+short: {{ header.date.short|safe }}
+long: {{ header.date.long|safe }}
+fancylong: {{ header.date.fancylong|safe }}
+fancyshort: {{ header.date.fancyshort|safe }}
+localelong: {{ header.date.localelong|safe }}
invalid: {{ header.date.invalid|safe }}
diff --git a/messageviewer/src/header/autotests/data/fromtest.tmpl b/messageviewer/src/header/autotests/data/fromtest.tmpl
index a579b89d..c730c382 100644
--- a/messageviewer/src/header/autotests/data/fromtest.tmpl
+++ b/messageviewer/src/header/autotests/data/fromtest.tmpl
@@ -1,7 +1,7 @@
-nameOnly: {{ header.fromNameOnly|safe }}
+nameOnly: {{ header.from.nameOnly|safe }}
isSet: {{ header.from.isSet|safe }}
-fullAddress: {{ header.from|safe }}
-str: {{ header.fromStr }}
-expandable: {{ header.fromExpandable|safe }}
+fullAddress: {{ header.from.fullAddress|safe }}
+str: {{ header.from.str }}
+expandable: {{ header.from.expandableFrom|safe }}
expandableTO: {{ header.fromexpandableTO|safe }}
invalid: {{ header.from.invalid|safe }}
diff --git a/messageviewer/src/header/autotests/data/fromtest.tmpl.html b/messageviewer/src/header/autotests/data/fromtest.tmpl.html
index 7540fc2e..82cfe255 100644
--- a/messageviewer/src/header/autotests/data/fromtest.tmpl.html
+++ b/messageviewer/src/header/autotests/data/fromtest.tmpl.html
@@ -1,17 +1,17 @@
-
nameOnly:
-
isSet:
+
+
isSet: true
str: admin <admin@ssrr.link>, from2 <from2@example.org>, from3 <from3@example.org>, from4 <from4@example.org>, from5 <from5@example.org>, from6 <from6@example.org>
-
expandable:
+
expandableTO:
invalid:
diff --git a/messageviewer/src/header/autotests/data/replyTotest.tmpl b/messageviewer/src/header/autotests/data/replyTotest.tmpl
index eb2e325b..105a54a2 100644
--- a/messageviewer/src/header/autotests/data/replyTotest.tmpl
+++ b/messageviewer/src/header/autotests/data/replyTotest.tmpl
@@ -1,7 +1,7 @@
-nameOnly: {{ header.replyToNameOnly|safe }}
+nameOnly: {{ header.replyTo.nameOnly|safe }}
isSet: {{ header.replyTo.isSet|safe }}
-fullAddress: {{ header.replyTo|safe }}
-str: {{ header.replyToStr }}
-expandable: {{ header.replyToExpandable|safe }}
-expandableTO: {{ header.replyToexpandableTO|safe }}
+fullAddress: {{ header.replyTo.fullAddress|safe }}
+str: {{ header.replyTo.str }}
+expandable: {{ header.replyTo.expandable|safe }}
+expandableTO: {{ header.replyTo.expandableTO|safe }}
invalid: {{ header.replyTo.invalid|safe }}
diff --git a/messageviewer/src/header/autotests/data/replyTotest.tmpl.html b/messageviewer/src/header/autotests/data/replyTotest.tmpl.html
index d10b9c6a..62b24c17 100644
--- a/messageviewer/src/header/autotests/data/replyTotest.tmpl.html
+++ b/messageviewer/src/header/autotests/data/replyTotest.tmpl.html
@@ -1,17 +1,17 @@
-
isSet:
+
isSet: true
str: me <reply-to@example.org>, me3 <reply-to3@example.org>, me3 <reply-to3@example.org>, me4 <reply-to4@example.org>, me5 <reply-to5@example.org>, me6 <reply-to6@example.org>
-
expandable:
-
expandableTO:
+
+
invalid:
diff --git a/messageviewer/src/header/autotests/data/resentfromtest.tmpl b/messageviewer/src/header/autotests/data/resentfromtest.tmpl
index 7fc2f22b..adc29419 100644
--- a/messageviewer/src/header/autotests/data/resentfromtest.tmpl
+++ b/messageviewer/src/header/autotests/data/resentfromtest.tmpl
@@ -1,7 +1,7 @@
-nameOnly: {{ header.resentfromNameOnly|safe }}
+nameOnly: {{ header.resentfrom.nameOnly|safe }}
isSet: {{ header.resentfrom.isSet|safe }}
-fullAddress: {{ header.resentfrom|safe }}
-str: {{ header.resentfromStr }}
-expandable: {{ header.resentfromExpandable|safe }}
-expandableTO: {{ header.resentfromexpandableTO|safe }}
+fullAddress: {{ header.resentfrom.fullAddress|safe }}
+str: {{ header.resentfrom.str }}
+expandable: {{ header.resentfrom.expandableResentFrom|safe }}
+expandableTO: {{ header.resentfrom.expandableTO|safe }}
invalid: {{ header.resentfrom.invalid|safe }}
diff --git a/messageviewer/src/header/autotests/data/resentfromtest.tmpl.html b/messageviewer/src/header/autotests/data/resentfromtest.tmpl.html
index 14c61926..ce60dc84 100644
--- a/messageviewer/src/header/autotests/data/resentfromtest.tmpl.html
+++ b/messageviewer/src/header/autotests/data/resentfromtest.tmpl.html
@@ -1,17 +1,17 @@
-
nameOnly:
-
isSet:
+
+
isSet: true
-
str:
-
expandable:
-
expandableTO:
+
str: resent-from@example.org, resent-from2@example.org, resent-from3@example.org, resent-from4@example.org, resent-to5@example.org, resent-to6@example.org
+
+
invalid:
diff --git a/messageviewer/src/header/autotests/data/resenttotest.tmpl b/messageviewer/src/header/autotests/data/resenttotest.tmpl
index 4e9bc6e2..6786a71a 100644
--- a/messageviewer/src/header/autotests/data/resenttotest.tmpl
+++ b/messageviewer/src/header/autotests/data/resenttotest.tmpl
@@ -1,7 +1,7 @@
-nameOnly: {{ header.resenttoNameOnly|safe }}
+nameOnly: {{ header.resentto.nameOnly|safe }}
isSet: {{ header.resentto.isSet|safe }}
-fullAddress: {{ header.resentto|safe }}
-str: {{ header.resenttoStr }}
-expandable: {{ header.resenttoExpandable|safe }}
-expandableTO: {{ header.resenttoexpandableTO|safe }}
+fullAddress: {{ header.resentto.fullAddress|safe }}
+str: {{ header.resentto.str }}
+expandable: {{ header.resentto.expandableResentto|safe }}
+expandableTO: {{ header.resentto.expandableTO|safe }}
invalid: {{ header.resentto.invalid|safe }}
diff --git a/messageviewer/src/header/autotests/data/resenttotest.tmpl.html b/messageviewer/src/header/autotests/data/resenttotest.tmpl.html
index 4d2c8d8c..0816fad4 100644
--- a/messageviewer/src/header/autotests/data/resenttotest.tmpl.html
+++ b/messageviewer/src/header/autotests/data/resenttotest.tmpl.html
@@ -1,17 +1,17 @@
-
nameOnly:
-
isSet:
+
+
isSet: true
-
str:
-
expandable:
-
expandableTO:
+
str: resent-to@example.org, resent-to2@example.org, resent-to3@example.org, resent-to4@example.org, resent-to5@example.org, resent-to6@example.org
+
+
invalid:
diff --git a/messageviewer/src/header/autotests/data/totest.tmpl b/messageviewer/src/header/autotests/data/totest.tmpl
index 329f4fb7..30f41389 100644
--- a/messageviewer/src/header/autotests/data/totest.tmpl
+++ b/messageviewer/src/header/autotests/data/totest.tmpl
@@ -1,7 +1,7 @@
-nameOnly: {{ header.toNameOnly|safe }}
+nameOnly: {{ header.to.nameOnly|safe }}
isSet: {{ header.to.isSet|safe }}
-fullAddress: {{ header.to|safe }}
-str: {{ header.toStr}}
-expandable: {{ header.toExpandable|safe }}
+fullAddress: {{ header.to.fullAddress|safe }}
+str: {{ header.to.str}}
+expandable: {{ header.to.expandableTo|safe }}
expandableTO: {{ header.to.expandableTO|safe }}
invalid: {{ header.to.invalid|safe }}
diff --git a/messageviewer/src/header/autotests/data/totest.tmpl.html b/messageviewer/src/header/autotests/data/totest.tmpl.html
index 8f2f32a6..ba617a99 100644
--- a/messageviewer/src/header/autotests/data/totest.tmpl.html
+++ b/messageviewer/src/header/autotests/data/totest.tmpl.html
@@ -1,17 +1,17 @@
-
isSet:
+
isSet: true
str: direct recipient1 <tospam1@example.org>, direct recipient2 <tospam2@example.org>, direct recipient3 <tospam3@example.org>, direct recipient4 <tospam4@example.org>, direct recipient5 <tospam5@example.org>, direct recipient6 <tospam6@example.org>
-
expandableTO:
+
invalid:
diff --git a/messageviewer/src/header/grantleeheaderformatter.cpp b/messageviewer/src/header/grantleeheaderformatter.cpp
index 5d69582d..76669e6d 100644
--- a/messageviewer/src/header/grantleeheaderformatter.cpp
+++ b/messageviewer/src/header/grantleeheaderformatter.cpp
@@ -1,370 +1,402 @@
/*
Copyright (C) 2013-2018 Laurent Montel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "grantleeheaderformatter.h"
#include "headerstyle_util.h"
#include "grantleetheme/grantleetheme.h"
#include "settings/messageviewersettings.h"
#include "utils/iconnamecache.h"
#include "config-messageviewer.h"
#include
#include
#include
#include
#include
#include
-#include
#include
+#include
+#include
using namespace MessageCore;
using namespace MessageViewer;
+Q_DECLARE_METATYPE(const KMime::Headers::Generics::AddressList *)
+Q_DECLARE_METATYPE(const KMime::Headers::Generics::MailboxList *)
+Q_DECLARE_METATYPE(QSharedPointer)
+Q_DECLARE_METATYPE(const KMime::Headers::Date *)
+
+// Read-only introspection of KMime::Headers::Generics::AddressList object.
+namespace Grantlee {
+template<>
+inline QVariant TypeAccessor::lookUp(const KMime::Headers::Generics::AddressList *const object, const QString &property)
+{
+ if (property == QStringLiteral("nameOnly")) {
+ return StringUtil::emailAddrAsAnchor(object, StringUtil::DisplayNameOnly);
+ } else if (property == QStringLiteral("isSet")) {
+ return !object->asUnicodeString().isEmpty();
+ } else if (property == QStringLiteral("fullAddress")) {
+ return StringUtil::emailAddrAsAnchor(object, StringUtil::DisplayFullAddress);
+ } else if (property == QStringLiteral("str")) {
+ return object->asUnicodeString();
+ } else if (property.startsWith(QStringLiteral("expandable"))) {
+ const auto &name = property.mid(10);
+ const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
+ object, MessageCore::StringUtil::DisplayFullAddress,
+ QString(), MessageCore::StringUtil::ShowLink,
+ MessageCore::StringUtil::ExpandableAddresses,
+ QStringLiteral("Full") + name + QStringLiteral("AddressList"));
+ return val;
+ }
+ return QVariant();
+}
+}
+
+// Read-only introspection of KMime::Headers::Generics::MailboxList object.
+namespace Grantlee {
+template<>
+inline QVariant TypeAccessor::lookUp(const KMime::Headers::Generics::MailboxList *const object, const QString &property)
+{
+ if (property == QStringLiteral("nameOnly")) {
+ return StringUtil::emailAddrAsAnchor(object, StringUtil::DisplayNameOnly);
+ } else if (property == QStringLiteral("isSet")) {
+ return !object->asUnicodeString().isEmpty();
+ } else if (property == QStringLiteral("fullAddress")) {
+ return StringUtil::emailAddrAsAnchor(object, StringUtil::DisplayFullAddress);
+ } else if (property == QStringLiteral("str")) {
+ return object->asUnicodeString();
+ } else if (property.startsWith(QStringLiteral("expandable"))) {
+ const auto &name = property.mid(10);
+ const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
+ object, MessageCore::StringUtil::DisplayFullAddress,
+ QString(), MessageCore::StringUtil::ShowLink,
+ MessageCore::StringUtil::ExpandableAddresses,
+ QStringLiteral("Full") + name + QStringLiteral("AddressList"));
+ return val;
+ }
+ return QVariant();
+}
+}
+
+GRANTLEE_BEGIN_LOOKUP(QSharedPointer)
+ if (property == QStringLiteral("nameOnly")) {
+ return StringUtil::emailAddrAsAnchor(object.data(), StringUtil::DisplayNameOnly);
+ } else if (property == QStringLiteral("isSet")) {
+ return !object->asUnicodeString().isEmpty();
+ } else if (property == QStringLiteral("fullAddress")) {
+ return StringUtil::emailAddrAsAnchor(object.data(), StringUtil::DisplayFullAddress);
+ } else if (property == QStringLiteral("str")) {
+ return object->asUnicodeString();
+ } else if (property.startsWith(QStringLiteral("expandable"))) {
+ const auto &name = property.mid(10);
+ const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
+ object.data(), MessageCore::StringUtil::DisplayFullAddress,
+ QString(), MessageCore::StringUtil::ShowLink,
+ MessageCore::StringUtil::ExpandableAddresses,
+ QStringLiteral("Full") + name + QStringLiteral("AddressList"));
+ return val;
+ }
+GRANTLEE_END_LOOKUP
+
+
+namespace Grantlee {
+template<>
+inline QVariant TypeAccessor::lookUp(const KMime::Headers::Date *const object, const QString &property)
+{
+ MessageViewer::HeaderStyleUtil::HeaderStyleUtilDateFormat dateFormat;
+ if (property == QStringLiteral("str")) {
+ return HeaderStyleUtil::dateStr(object->dateTime());
+ } else if (property == QStringLiteral("short")) {
+ dateFormat = MessageViewer::HeaderStyleUtil::ShortDate;
+ } else if (property == QStringLiteral("long")) {
+ dateFormat = MessageViewer::HeaderStyleUtil::CustomDate;
+ } else if (property == QStringLiteral("fancylong")) {
+ dateFormat = MessageViewer::HeaderStyleUtil::FancyLongDate;
+ } else if (property == QStringLiteral("fancyshort")) {
+ dateFormat = MessageViewer::HeaderStyleUtil::FancyShortDate;
+ } else if(property == QStringLiteral("localelong")){
+ dateFormat = MessageViewer::HeaderStyleUtil::LongDate;
+ } else {
+ return QVariant();
+ }
+
+ return HeaderStyleUtil::strToHtml(HeaderStyleUtil::dateString(object, dateFormat));
+}
+}
+
+
class Q_DECL_HIDDEN MessageViewer::GrantleeHeaderFormatter::Private
{
public:
Private()
{
+ Grantlee::registerMetaType();
+ Grantlee::registerMetaType();
+ Grantlee::registerMetaType>();
+ Grantlee::registerMetaType();
iconSize = KIconLoader::global()->currentSize(KIconLoader::Toolbar);
engine = new Grantlee::Engine;
templateLoader = QSharedPointer(
new Grantlee::FileSystemTemplateLoader);
engine->addTemplateLoader(templateLoader);
}
~Private()
{
delete engine;
}
QSharedPointer templateLoader;
Grantlee::Engine *engine = nullptr;
MessageViewer::HeaderStyleUtil headerStyleUtil;
int iconSize;
};
GrantleeHeaderFormatter::GrantleeHeaderFormatter()
: d(new GrantleeHeaderFormatter::Private)
{
}
GrantleeHeaderFormatter::~GrantleeHeaderFormatter()
{
delete d;
}
QString GrantleeHeaderFormatter::toHtml(
const GrantleeHeaderFormatter::GrantleeHeaderFormatterSettings &settings) const
{
QString errorMessage;
if (!settings.theme.isValid()) {
errorMessage = i18n("Grantlee theme \"%1\" is not valid.", settings.theme.name());
return errorMessage;
}
d->templateLoader->setTemplateDirs(QStringList() << settings.theme.absolutePath());
Grantlee::Template headerTemplate = d->engine->loadByName(settings.theme.themeFilename());
if (headerTemplate->error()) {
errorMessage = headerTemplate->errorString();
return errorMessage;
}
return format(
settings.theme.absolutePath(), headerTemplate,
settings.theme.displayExtraVariables(), settings.isPrinting, settings.style, settings.message,
settings.showEmoticons);
}
QString GrantleeHeaderFormatter::toHtml(const QStringList &displayExtraHeaders, const QString &absolutPath, const QString &filename, const MessageViewer::HeaderStyle *style, KMime::Message *message,
bool isPrinting) const
{
d->templateLoader->setTemplateDirs(QStringList() << absolutPath);
Grantlee::Template headerTemplate = d->engine->loadByName(filename);
if (headerTemplate->error()) {
return headerTemplate->errorString();
}
return format(absolutPath, headerTemplate, displayExtraHeaders, isPrinting, style, message);
}
QString GrantleeHeaderFormatter::format(const QString &absolutePath, const Grantlee::Template &headerTemplate, const QStringList &displayExtraHeaders, bool isPrinting,
const MessageViewer::HeaderStyle *style, KMime::Message *message, bool showEmoticons) const
{
QVariantHash headerObject;
// However, the direction of the message subject within the header is
// determined according to the contents of the subject itself. Since
// the "Re:" and "Fwd:" prefixes would always cause the subject to be
// considered left-to-right, they are ignored when determining its
// direction.
const QString absoluteThemePath = QUrl::fromLocalFile(absolutePath + QLatin1Char('/')).url();
headerObject.insert(QStringLiteral("absoluteThemePath"), absoluteThemePath);
headerObject.insert(QStringLiteral("applicationDir"),
QApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral(
"ltr"));
headerObject.insert(QStringLiteral("subjectDir"),
d->headerStyleUtil.subjectDirectionString(message));
headerObject.insert(QStringLiteral("subjecti18n"), i18n("Subject:"));
KTextToHTML::Options flags = KTextToHTML::PreserveSpaces;
if (showEmoticons) {
flags |= KTextToHTML::ReplaceSmileys;
}
headerObject.insert(QStringLiteral("subject"),
d->headerStyleUtil.subjectString(message, flags));
if (message->to(false)) {
headerObject.insert(QStringLiteral("toi18n"), i18n("To:"));
- headerObject.insert(QStringLiteral("to"),
- StringUtil::emailAddrAsAnchor(message->to(),
- StringUtil::DisplayFullAddress));
- headerObject.insert(QStringLiteral("toNameOnly"),
- StringUtil::emailAddrAsAnchor(
- message->to(), StringUtil::DisplayNameOnly));
- headerObject.insert(QStringLiteral("toStr"), message->to()->asUnicodeString());
- const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
- message->to(), MessageCore::StringUtil::DisplayFullAddress,
- QString(), MessageCore::StringUtil::ShowLink,
- MessageCore::StringUtil::ExpandableAddresses,
- QStringLiteral("FullToAddressList"));
- headerObject.insert(QStringLiteral("toExpandable"), val);
- headerObject.insert(QStringLiteral("toMailbox"), QVariant::fromValue(message->to()));
+ headerObject.insert(QStringLiteral("to"), QVariant::fromValue(static_cast(message->to())));
}
if (message->replyTo(false)) {
headerObject.insert(QStringLiteral("replyToi18n"), i18n("Reply to:"));
- headerObject.insert(QStringLiteral("replyTo"),
- StringUtil::emailAddrAsAnchor(message->replyTo(),
- StringUtil::DisplayFullAddress));
- headerObject.insert(QStringLiteral("replyToStr"), message->replyTo()->asUnicodeString());
- headerObject.insert(QStringLiteral("replyToNameOnly"),
- StringUtil::emailAddrAsAnchor(message->replyTo(),
- StringUtil::DisplayNameOnly));
+ headerObject.insert(QStringLiteral("replyTo"), QVariant::fromValue(static_cast(message->replyTo())));
}
if (message->cc(false)) {
headerObject.insert(QStringLiteral("cci18n"), i18n("CC:"));
- headerObject.insert(QStringLiteral("cc"),
- StringUtil::emailAddrAsAnchor(message->cc(),
- StringUtil::DisplayFullAddress));
- headerObject.insert(QStringLiteral("ccStr"), message->cc()->asUnicodeString());
- headerObject.insert(QStringLiteral("ccNameOnly"),
- StringUtil::emailAddrAsAnchor(
- message->cc(), StringUtil::DisplayNameOnly));
- headerObject.insert(QStringLiteral("ccMailbox"), QVariant::fromValue(message->cc()));
- const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
- message->cc(), MessageCore::StringUtil::DisplayFullAddress,
- QString(), MessageCore::StringUtil::ShowLink,
- MessageCore::StringUtil::ExpandableAddresses,
- QStringLiteral("FullCcAddressList"));
- headerObject.insert(QStringLiteral("ccExpandable"), val);
+ headerObject.insert(QStringLiteral("cc"), QVariant::fromValue(static_cast(message->cc())));
}
if (message->bcc(false)) {
headerObject.insert(QStringLiteral("bcci18n"), i18n("BCC:"));
- headerObject.insert(QStringLiteral("bcc"),
- StringUtil::emailAddrAsAnchor(message->bcc(),
- StringUtil::DisplayFullAddress));
- headerObject.insert(QStringLiteral("bccNameOnly"),
- StringUtil::emailAddrAsAnchor(message->bcc(),
- StringUtil::DisplayNameOnly));
- headerObject.insert(QStringLiteral("bccStr"), message->bcc()->asUnicodeString());
- headerObject.insert(QStringLiteral("bccMailbox"), QVariant::fromValue(message->bcc()));
+ headerObject.insert(QStringLiteral("bcc"), QVariant::fromValue(static_cast(message->bcc())));
}
headerObject.insert(QStringLiteral("fromi18n"), i18n("From:"));
- headerObject.insert(QStringLiteral("from"),
- StringUtil::emailAddrAsAnchor(message->from(),
- StringUtil::DisplayFullAddress));
- headerObject.insert(QStringLiteral("fromStr"), message->from()->asUnicodeString());
+ headerObject.insert(QStringLiteral("from"), QVariant::fromValue(static_cast(message->from())));
//Sender
+ headerObject.insert(QStringLiteral("senderi18n"), i18n("Sender:"));
headerObject.insert(QStringLiteral("sender"),
d->headerStyleUtil.strToHtml(message->sender()->asUnicodeString()));
- headerObject.insert(QStringLiteral("senderi18n"), i18n("Sender:"));
headerObject.insert(QStringLiteral("listidi18n"), i18n("List-Id:"));
if (auto hrd = message->headerByType("List-Id")) {
headerObject.insert(QStringLiteral("listid"), hrd->asUnicodeString());
}
const QString spamHtml = d->headerStyleUtil.spamStatus(message);
if (!spamHtml.isEmpty()) {
headerObject.insert(QStringLiteral("spamstatusi18n"), i18n("Spam Status:"));
headerObject.insert(QStringLiteral("spamHTML"), spamHtml);
}
- headerObject.insert(QStringLiteral("datei18n"), i18n("Date:"));
- headerObject.insert(QStringLiteral("dateshort"),
- d->headerStyleUtil.strToHtml(d->headerStyleUtil.dateString(message,
- isPrinting,
- MessageViewer::
- HeaderStyleUtil::
- ShortDate)));
- headerObject.insert(QStringLiteral("datelong"),
- d->headerStyleUtil.strToHtml(d->headerStyleUtil.dateString(message,
- isPrinting,
- MessageViewer::
- HeaderStyleUtil::
- CustomDate)));
- headerObject.insert(QStringLiteral("date"),
- d->headerStyleUtil.dateStr(message->date()->dateTime()));
- headerObject.insert(QStringLiteral("datefancylong"),
- d->headerStyleUtil.strToHtml(d->headerStyleUtil.dateString(message,
- isPrinting,
- MessageViewer::
- HeaderStyleUtil::
- FancyLongDate)));
- headerObject.insert(QStringLiteral("datefancyshort"),
- d->headerStyleUtil.strToHtml(d->headerStyleUtil.dateString(message,
- isPrinting,
- MessageViewer::
- HeaderStyleUtil::
- FancyShortDate)));
- headerObject.insert(QStringLiteral("datelocalelong"),
- d->headerStyleUtil.strToHtml(d->headerStyleUtil.dateString(message,
- isPrinting,
- MessageViewer::
- HeaderStyleUtil::
- LongDate)));
+ headerObject.insert(QStringLiteral("datei18n"), i18n("Date:"));
+ headerObject.insert(QStringLiteral("date"), QVariant::fromValue(static_cast(message->date())));
if (message->hasHeader("Resent-From")) {
headerObject.insert(QStringLiteral("resentfromi18n"), i18n("resent from"));
- const QVector resentFrom
- = d->headerStyleUtil.resentFromList(message);
headerObject.insert(QStringLiteral("resentfrom"),
- StringUtil::emailAddrAsAnchor(resentFrom,
- StringUtil::DisplayFullAddress));
+ QVariant::fromValue(HeaderStyleUtil::resentFromList(message)));
}
if (message->hasHeader("Resent-To")) {
- const QVector resentTo = d->headerStyleUtil.resentToList(message);
+ auto resentTo = HeaderStyleUtil::resentToList(message);
headerObject.insert(QStringLiteral("resenttoi18n"),
- i18np("receiver was", "receivers were", resentTo.count()));
+ i18np("receiver was", "receivers were", resentTo->mailboxes().count()));
headerObject.insert(QStringLiteral("resentto"),
- StringUtil::emailAddrAsAnchor(resentTo,
- StringUtil::DisplayFullAddress));
+ QVariant::fromValue(HeaderStyleUtil::resentToList(message)));
}
if (auto organization = message->organization(false)) {
headerObject.insert(QStringLiteral("organization"),
d->headerStyleUtil.strToHtml(organization->asUnicodeString()));
}
if (!style->vCardName().isEmpty()) {
headerObject.insert(QStringLiteral("vcardname"), style->vCardName());
}
if (!style->collectionName().isEmpty()) {
headerObject.insert(QStringLiteral("collectionname"), style->collectionName());
}
if (isPrinting) {
//provide a bit more left padding when printing
//kolab/issue3254 (printed mail cut at the left side)
//Use it just for testing if we are in printing mode
headerObject.insert(QStringLiteral("isprinting"), i18n("Printing mode"));
headerObject.insert(QStringLiteral("printmode"), QStringLiteral("printmode"));
} else {
headerObject.insert(QStringLiteral("screenmode"), QStringLiteral("screenmode"));
}
// colors depend on if it is encapsulated or not
QColor fontColor(Qt::white);
QString linkColor = QStringLiteral("white");
const QColor activeColor
= KColorScheme(QPalette::Active, KColorScheme::Selection).background().color();
QColor activeColorDark = activeColor.darker(130);
// reverse colors for encapsulated
if (!style->isTopLevel()) {
activeColorDark = activeColor.darker(50);
fontColor = QColor(Qt::black);
linkColor = QStringLiteral("black");
}
// 3D borders
headerObject.insert(QStringLiteral("activecolordark"), activeColorDark.name());
headerObject.insert(QStringLiteral("fontcolor"), fontColor.name());
headerObject.insert(QStringLiteral("linkcolor"), linkColor);
MessageViewer::HeaderStyleUtil::xfaceSettings xface = d->headerStyleUtil.xface(style, message);
if (!xface.photoURL.isEmpty()) {
headerObject.insert(QStringLiteral("photowidth"), xface.photoWidth);
headerObject.insert(QStringLiteral("photoheight"), xface.photoHeight);
headerObject.insert(QStringLiteral("photourl"), xface.photoURL);
}
for (QString header : qAsConst(displayExtraHeaders)) {
const QByteArray baHeader = header.toLocal8Bit();
if (auto hrd = message->headerByType(baHeader.constData())) {
//Grantlee doesn't support '-' in variable name => remove it.
header = header.remove(QLatin1Char('-'));
headerObject.insert(header, hrd->asUnicodeString());
}
}
headerObject.insert(QStringLiteral("vcardi18n"), i18n("[vcard]"));
headerObject.insert(QStringLiteral("readOnlyMessage"), style->readOnlyMessage());
const bool messageHasAttachment = KMime::hasAttachment(message);
headerObject.insert(QStringLiteral("hasAttachment"), messageHasAttachment);
headerObject.insert(QStringLiteral("attachmentHtml"), style->attachmentHtml());
if (messageHasAttachment) {
const QString iconPath
= MessageViewer::IconNameCache::instance()->iconPath(QStringLiteral(
"mail-attachment"),
KIconLoader::Toolbar);
const QString html = QStringLiteral(" ").arg(QUrl::fromLocalFile(iconPath).url(), QString::number(d->iconSize));
headerObject.insert(QStringLiteral("attachmentIcon"), html);
}
const bool messageIsSigned = KMime::isSigned(message);
headerObject.insert(QStringLiteral("messageIsSigned"), messageIsSigned);
if (messageIsSigned) {
const QString iconPath
= MessageViewer::IconNameCache::instance()->iconPath(QStringLiteral(
"mail-signed"),
KIconLoader::Toolbar);
const QString html = QStringLiteral(" ").arg(QUrl::fromLocalFile(iconPath).url(), QString::number(d->iconSize));
headerObject.insert(QStringLiteral("signedIcon"), html);
}
const bool messageIsEncrypted = KMime::isEncrypted(message);
headerObject.insert(QStringLiteral("messageIsEncrypted"), messageIsEncrypted);
if (messageIsEncrypted) {
const QString iconPath
= MessageViewer::IconNameCache::instance()->iconPath(QStringLiteral(
"mail-encrypted"),
KIconLoader::Toolbar);
const QString html = QStringLiteral(" ").arg(QUrl::fromLocalFile(iconPath).url(), QString::number(d->iconSize));
headerObject.insert(QStringLiteral("encryptedIcon"), html);
}
const bool messageHasSecurityInfo = messageIsEncrypted || messageIsSigned;
headerObject.insert(QStringLiteral("messageHasSecurityInfo"), messageHasSecurityInfo);
headerObject.insert(QStringLiteral("messageHasSecurityInfoI18n"), i18n("Security:"));
QVariantHash mapping;
mapping.insert(QStringLiteral("header"), headerObject);
Grantlee::Context context(mapping);
return headerTemplate->render(&context);
}
diff --git a/messageviewer/src/header/headerstyle_util.cpp b/messageviewer/src/header/headerstyle_util.cpp
index b42c2dc3..56009fdd 100644
--- a/messageviewer/src/header/headerstyle_util.cpp
+++ b/messageviewer/src/header/headerstyle_util.cpp
@@ -1,413 +1,400 @@
/*
Copyright (C) 2013-2018 Laurent Montel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "headerstyle_util.h"
#include "messageviewer_debug.h"
#include "contactdisplaymessagememento.h"
#include "kxface.h"
#include "header/headerstyle.h"
#include "utils/iconnamecache.h"
#include "settings/messageviewersettings.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace MessageCore;
using namespace MessageViewer;
//
// Convenience functions:
//
HeaderStyleUtil::HeaderStyleUtil()
{
}
QString HeaderStyleUtil::directionOf(const QString &str) const
{
return str.isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr");
}
-QString HeaderStyleUtil::strToHtml(const QString &str, KTextToHTML::Options flags) const
+QString HeaderStyleUtil::strToHtml(const QString &str, KTextToHTML::Options flags)
{
return KTextToHTML::convertToHtml(str, flags, 4096, 512);
}
-// Prepare the date string (when printing always use the localized date)
-QString HeaderStyleUtil::dateString(KMime::Message *message, bool printing, HeaderStyleUtilDateFormat dateFormat) const
+// Prepare the date string
+QString HeaderStyleUtil::dateString(KMime::Message *message, HeaderStyleUtilDateFormat dateFormat)
{
- const QDateTime dateTime = message->date()->dateTime();
+ return dateString(message->date(), dateFormat);
+}
+
+QString HeaderStyleUtil::dateString(const KMime::Headers::Date *date, HeaderStyleUtilDateFormat dateFormat)
+{
+ const QDateTime dateTime = date->dateTime();
if (!dateTime.isValid()) {
qCDebug(MESSAGEVIEWER_LOG) << "Unable to parse date";
return i18nc("Unknown date", "Unknown");
}
- const time_t unixTime = dateTime.toSecsSinceEpoch();
- if (printing) {
+ const time_t unixTime = dateTime.toTime_t();
+ switch (dateFormat) {
+ case ShortDate:
return KMime::DateFormatter::formatDate(KMime::DateFormatter::Localized, unixTime);
- } else {
- switch (dateFormat) {
- case ShortDate:
- return KMime::DateFormatter::formatDate(KMime::DateFormatter::Localized, unixTime);
- case LongDate:
- return KMime::DateFormatter::formatDate(KMime::DateFormatter::CTime, unixTime);
- case FancyShortDate:
- return KMime::DateFormatter::formatDate(KMime::DateFormatter::Fancy, unixTime);
- case FancyLongDate:
- //Laurent fix me
- //TODO return QLocale::system().toString(dateTime, QLocale::LongFormat);
- case CustomDate:
- default:
- return dateStr(dateTime);
- }
+ case LongDate:
+ return KMime::DateFormatter::formatDate(KMime::DateFormatter::CTime, unixTime);
+ case FancyShortDate:
+ return KMime::DateFormatter::formatDate(KMime::DateFormatter::Fancy, unixTime);
+ case FancyLongDate:
+ //Laurent fix me
+ //TODO return QLocale::system().toString(dateTime, QLocale::LongFormat);
+ case CustomDate:
+ default:
+ return dateStr(dateTime);
}
}
QString HeaderStyleUtil::subjectString(KMime::Message *message, KTextToHTML::Options flags) const
{
QString subjectStr;
const KMime::Headers::Subject *const subject = message->subject(false);
if (subject) {
subjectStr = subject->asUnicodeString();
if (subjectStr.isEmpty()) {
subjectStr = i18n("No Subject");
} else {
subjectStr = strToHtml(subjectStr, flags);
}
} else {
subjectStr = i18n("No Subject");
}
return subjectStr;
}
QString HeaderStyleUtil::subjectDirectionString(KMime::Message *message) const
{
QString subjectDir;
if (message->subject(false)) {
subjectDir = directionOf(MessageCore::StringUtil::cleanSubject(message));
} else {
subjectDir = directionOf(i18n("No Subject"));
}
return subjectDir;
}
QString HeaderStyleUtil::spamStatus(KMime::Message *message) const
{
QString spamHTML;
const SpamScores scores = SpamHeaderAnalyzer::getSpamScores(message);
for (SpamScores::const_iterator it = scores.constBegin(), end = scores.constEnd(); it != end;
++it) {
spamHTML += (*it).agent() + QLatin1Char(' ')
+drawSpamMeter((*it).error(), (*it).score(),
(*it).confidence(), (*it).spamHeader(),
(*it).confidenceHeader());
}
return spamHTML;
}
QString HeaderStyleUtil::drawSpamMeter(SpamError spamError, double percent, double confidence, const QString &filterHeader, const QString &confidenceHeader) const
{
static const int meterWidth = 20;
static const int meterHeight = 5;
QImage meterBar(meterWidth, 1, QImage::Format_Indexed8 /*QImage::Format_RGB32*/);
meterBar.setColorCount(24);
meterBar.setColor(meterWidth + 1, qRgb(255, 255, 255));
meterBar.setColor(meterWidth + 2, qRgb(170, 170, 170));
if (spamError != noError) { // grey is for errors
meterBar.fill(meterWidth + 2);
} else {
static const unsigned short gradient[meterWidth][3] = {
{ 0, 255, 0 },
{ 27, 254, 0 },
{ 54, 252, 0 },
{ 80, 250, 0 },
{ 107, 249, 0 },
{ 135, 247, 0 },
{ 161, 246, 0 },
{ 187, 244, 0 },
{ 214, 242, 0 },
{ 241, 241, 0 },
{ 255, 228, 0 },
{ 255, 202, 0 },
{ 255, 177, 0 },
{ 255, 151, 0 },
{ 255, 126, 0 },
{ 255, 101, 0 },
{ 255, 76, 0 },
{ 255, 51, 0 },
{ 255, 25, 0 },
{ 255, 0, 0 }
};
meterBar.fill(meterWidth + 1);
const int max = qMin(meterWidth, static_cast(percent) / 5);
for (int i = 0; i < max; ++i) {
meterBar.setColor(i + 1, qRgb(gradient[i][0], gradient[i][1],
gradient[i][2]));
meterBar.setPixel(i, 0, i + 1);
}
}
QString titleText;
QString confidenceString;
if (spamError == noError) {
if (confidence >= 0) {
confidenceString = QString::number(confidence) + QLatin1String("% ");
titleText = i18n("%1% probability of being spam with confidence %3%.\n\n"
"Full report:\nProbability=%2\nConfidence=%4",
QString::number(percent, 'f',
2), filterHeader, confidence, confidenceHeader);
} else { // do not show negative confidence
confidenceString = QString() + QLatin1String(" ");
titleText = i18n("%1% probability of being spam.\n\n"
"Full report:\nProbability=%2",
QString::number(percent, 'f', 2), filterHeader);
}
} else {
QString errorMsg;
switch (spamError) {
case errorExtractingAgentString:
errorMsg = i18n("No Spam agent");
break;
case couldNotConverScoreToFloat:
errorMsg = i18n("Spam filter score not a number");
break;
case couldNotConvertThresholdToFloatOrThresholdIsNegative:
errorMsg = i18n("Threshold not a valid number");
break;
case couldNotFindTheScoreField:
errorMsg = i18n("Spam filter score could not be extracted from header");
break;
case couldNotFindTheThresholdField:
errorMsg = i18n("Threshold could not be extracted from header");
break;
default:
errorMsg = i18n("Error evaluating spam score");
break;
}
// report the error in the spam filter
titleText = i18n("%1.\n\n"
"Full report:\n%2",
errorMsg, filterHeader);
}
return QStringLiteral(
" ")
.arg(imgToDataUrl(meterBar), QString::number(meterWidth),
QString::number(meterHeight), titleText) + confidenceString;
}
QString HeaderStyleUtil::imgToDataUrl(const QImage &image) const
{
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
return QStringLiteral("data:image/%1;base64,%2").arg(QStringLiteral("PNG"),
QString::fromLatin1(ba.toBase64()));
}
-QString HeaderStyleUtil::dateStr(const QDateTime &dateTime) const
+QString HeaderStyleUtil::dateStr(const QDateTime &dateTime)
{
const time_t unixTime = dateTime.toSecsSinceEpoch();
return KMime::DateFormatter::formatDate(
static_cast(
MessageCore::MessageCoreSettings::self()->dateFormat()),
unixTime, MessageCore::MessageCoreSettings::self()->customDateFormat());
}
-QString HeaderStyleUtil::dateShortStr(const QDateTime &dateTime) const
+QString HeaderStyleUtil::dateShortStr(const QDateTime &dateTime)
{
KMime::DateFormatter formatter(KMime::DateFormatter::Fancy);
return formatter.dateString(dateTime);
}
-QVector HeaderStyleUtil::resentFromList(KMime::Message *message) const
+QSharedPointer mailboxesFromHeader(const KMime::Headers::Base *hrd)
+{
+ QSharedPointer mailboxList(new KMime::Headers::Generics::MailboxList());
+ const QByteArray &data = hrd->as7BitString(false);
+ mailboxList->from7BitString(data);
+ return mailboxList;
+}
+
+QSharedPointer HeaderStyleUtil::resentFromList(KMime::Message *message)
{
- // Get the resent-from header into a Mailbox
- QVector resentFrom;
if (auto hrd = message->headerByType("Resent-From")) {
- const QByteArray data = hrd->as7BitString(false);
- const char *start = data.data();
- const char *end = start + data.length();
- KMime::Types::AddressList addressList;
- KMime::HeaderParsing::parseAddressList(start, end, addressList);
- for (const KMime::Types::Address &addr : qAsConst(addressList)) {
- for (const KMime::Types::Mailbox &mbox : qAsConst(addr.mailboxList)) {
- resentFrom.append(mbox);
- }
- }
+ return mailboxesFromHeader(hrd);
}
- return resentFrom;
+ return nullptr;
}
-QVector HeaderStyleUtil::resentToList(KMime::Message *message) const
+QSharedPointer HeaderStyleUtil::resentToList(KMime::Message *message)
{
- // Get the resent-from header into a Mailbox
- QVector resentTo;
if (auto hrd = message->headerByType("Resent-To")) {
- const QByteArray data = hrd->as7BitString(false);
- const char *start = data.data();
- const char *end = start + data.length();
- KMime::Types::AddressList addressList;
- KMime::HeaderParsing::parseAddressList(start, end, addressList);
- for (const KMime::Types::Address &addr : qAsConst(addressList)) {
- for (const KMime::Types::Mailbox &mbox : qAsConst(addr.mailboxList)) {
- resentTo.append(mbox);
- }
- }
+ return mailboxesFromHeader(hrd);
}
- return resentTo;
+ return nullptr;
}
void HeaderStyleUtil::updateXFaceSettings(QImage photo, xfaceSettings &settings) const
{
if (!photo.isNull()) {
settings.photoWidth = photo.width();
settings.photoHeight = photo.height();
// scale below 60, otherwise it can get way too large
if (settings.photoHeight > 60) {
double ratio = (double)settings.photoHeight / (double)settings.photoWidth;
settings.photoHeight = 60;
settings.photoWidth = (int)(60 / ratio);
photo = photo.scaled(settings.photoWidth, settings.photoHeight, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
}
settings.photoURL = MessageViewer::HeaderStyleUtil::imgToDataUrl(photo);
}
}
HeaderStyleUtil::xfaceSettings HeaderStyleUtil::xface(const MessageViewer::HeaderStyle *style, KMime::Message *message) const
{
xfaceSettings settings;
bool useOtherPhotoSources = false;
if (style->allowAsync()) {
Q_ASSERT(style->nodeHelper());
Q_ASSERT(style->sourceObject());
ContactDisplayMessageMemento *photoMemento
= dynamic_cast(style->nodeHelper()->bodyPartMemento(
message, "contactphoto"));
if (!photoMemento) {
const QString email
= QString::fromLatin1(KEmailAddress::firstEmailAddress(message->from()->as7BitString(
false)));
photoMemento = new ContactDisplayMessageMemento(email);
style->nodeHelper()->setBodyPartMemento(message, "contactphoto", photoMemento);
QObject::connect(photoMemento, SIGNAL(update(MimeTreeParser::UpdateMode)),
style->sourceObject(), SLOT(update(MimeTreeParser::UpdateMode)));
QObject::connect(photoMemento,
SIGNAL(changeDisplayMail(Viewer::DisplayFormatMessage,bool)),
style->sourceObject(),
SIGNAL(changeDisplayMail(Viewer::DisplayFormatMessage,bool)));
}
if (photoMemento->finished()) {
useOtherPhotoSources = true;
if (photoMemento->photo().isIntern()) {
// get photo data and convert to data: url
const QImage photo = photoMemento->photo().data();
updateXFaceSettings(photo, settings);
} else if (!photoMemento->imageFromUrl().isNull()) {
updateXFaceSettings(photoMemento->imageFromUrl(), settings);
} else if (!photoMemento->photo().url().isEmpty()) {
settings.photoURL = photoMemento->photo().url();
if (settings.photoURL.startsWith(QLatin1Char('/'))) {
settings.photoURL.prepend(QLatin1String("file:"));
}
} else if (!photoMemento->gravatarPixmap().isNull()) {
const QImage photo = photoMemento->gravatarPixmap().toImage();
updateXFaceSettings(photo, settings);
}
} else {
// if the memento is not finished yet, use other photo sources instead
useOtherPhotoSources = true;
}
} else {
useOtherPhotoSources = true;
}
if (settings.photoURL.isEmpty() && useOtherPhotoSources) {
if (auto hrd = message->headerByType("Face")) {
// no photo, look for a Face header
const QString faceheader = hrd->asUnicodeString();
if (!faceheader.isEmpty()) {
qCDebug(MESSAGEVIEWER_LOG) << "Found Face: header";
const QByteArray facestring = faceheader.toUtf8();
// Spec says header should be less than 998 bytes
// Face: is 5 characters
if (facestring.length() < 993) {
const QByteArray facearray = QByteArray::fromBase64(facestring);
QImage faceimage;
if (faceimage.loadFromData(facearray, "png")) {
// Spec says image must be 48x48 pixels
if ((48 == faceimage.width()) && (48 == faceimage.height())) {
settings.photoURL = MessageViewer::HeaderStyleUtil::imgToDataUrl(
faceimage);
settings.photoWidth = 48;
settings.photoHeight = 48;
} else {
qCDebug(MESSAGEVIEWER_LOG) << "Face: header image is"
<< faceimage.width() << "by"
<< faceimage.height() << "not 48x48 Pixels";
}
} else {
qCDebug(MESSAGEVIEWER_LOG)
<< "Failed to load decoded png from Face: header";
}
} else {
qCDebug(MESSAGEVIEWER_LOG) << "Face: header too long at" << facestring.length();
}
}
}
}
if (settings.photoURL.isEmpty() && useOtherPhotoSources) {
if (auto hrd = message->headerByType("X-Face")) {
// no photo, look for a X-Face header
const QString xfhead = hrd->asUnicodeString();
if (!xfhead.isEmpty()) {
MessageViewer::KXFace xf;
settings.photoURL
= MessageViewer::HeaderStyleUtil::imgToDataUrl(xf.toImage(xfhead));
settings.photoWidth = 48;
settings.photoHeight = 48;
}
}
}
return settings;
}
diff --git a/messageviewer/src/header/headerstyle_util.h b/messageviewer/src/header/headerstyle_util.h
index 6e276eb9..e2b8a566 100644
--- a/messageviewer/src/header/headerstyle_util.h
+++ b/messageviewer/src/header/headerstyle_util.h
@@ -1,89 +1,90 @@
/*
Copyright (C) 2013-2018 Laurent Montel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef HEADERSTYLE_UTIL_H
#define HEADERSTYLE_UTIL_H
#include
#include
#include
#include
#include
#include "messageviewer/spamheaderanalyzer.h"
#include "messageviewer/headerstyle.h"
#include "messageviewer/viewer.h"
#include "messageviewer_export.h"
namespace MessageViewer {
class MESSAGEVIEWER_EXPORT HeaderStyleUtil
{
public:
HeaderStyleUtil();
struct xfaceSettings {
xfaceSettings()
: photoWidth(60)
, photoHeight(60)
{
}
QString photoURL;
int photoWidth;
int photoHeight;
};
enum HeaderStyleUtilDateFormat {
ShortDate, /**< Locale Short date format, e.g. 08-04-2007 */
LongDate, /**< Locale Long date format, e.g. Sunday 08 April 2007 */
FancyShortDate, /**< Same as ShortDate for dates a week or more ago. For more
recent dates, it is represented as Today, Yesterday, or
the weekday name. */
FancyLongDate, /**< Same as LongDate for dates a week or more ago. For more
recent dates, it is represented as Today, Yesterday, or
the weekday name. */
CustomDate
};
Q_REQUIRED_RESULT QString directionOf(const QString &str) const;
- Q_REQUIRED_RESULT QString strToHtml(const QString &str, KTextToHTML::Options flags = KTextToHTML::PreserveSpaces) const;
+ static Q_REQUIRED_RESULT QString strToHtml(const QString &str, KTextToHTML::Options flags = KTextToHTML::PreserveSpaces);
+ static Q_REQUIRED_RESULT QString dateString(KMime::Message *message, HeaderStyleUtilDateFormat dateFormat);
+ static Q_REQUIRED_RESULT QString dateString(const KMime::Headers::Date *date, HeaderStyleUtilDateFormat dateFormat);
- Q_REQUIRED_RESULT QString dateString(KMime::Message *message, bool printing, HeaderStyleUtilDateFormat dateFormat) const;
Q_REQUIRED_RESULT QString subjectString(KMime::Message *message, KTextToHTML::Options flags = KTextToHTML::PreserveSpaces) const;
Q_REQUIRED_RESULT QString subjectDirectionString(KMime::Message *message) const;
Q_REQUIRED_RESULT QString spamStatus(KMime::Message *message) const;
- Q_REQUIRED_RESULT QString dateStr(const QDateTime &dateTime) const;
+ static Q_REQUIRED_RESULT QString dateStr(const QDateTime &dateTime);
- Q_REQUIRED_RESULT QString dateShortStr(const QDateTime &dateTime) const;
+ static Q_REQUIRED_RESULT QString dateShortStr(const QDateTime &dateTime);
+ static Q_REQUIRED_RESULT QSharedPointer resentFromList(KMime::Message *message);
- Q_REQUIRED_RESULT QVector resentFromList(KMime::Message *message) const;
- Q_REQUIRED_RESULT QVector resentToList(KMime::Message *message) const;
+ static Q_REQUIRED_RESULT QSharedPointer resentToList(KMime::Message *message);
Q_REQUIRED_RESULT xfaceSettings xface(const HeaderStyle *style, KMime::Message *message) const;
private:
void updateXFaceSettings(QImage photo, xfaceSettings &settings) const;
QString drawSpamMeter(SpamError spamError, double percent, double confidence, const QString &filterHeader, const QString &confidenceHeader) const;
QString imgToDataUrl(const QImage &image) const;
};
}
#endif // HEADERSTYLE_UTIL_H
diff --git a/messageviewer/src/header/plainheaderstyle.cpp b/messageviewer/src/header/plainheaderstyle.cpp
index 8e7d47a0..3b89bb94 100644
--- a/messageviewer/src/header/plainheaderstyle.cpp
+++ b/messageviewer/src/header/plainheaderstyle.cpp
@@ -1,194 +1,190 @@
/*
Copyright (C) 2013-2018 Laurent Montel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "plainheaderstyle.h"
#include "messageviewer/messageviewersettings.h"
#include "header/headerstyle_util.h"
#include "header/headerstrategy.h"
#include
#include
#include
#include
using namespace MessageCore;
using namespace MessageViewer;
class MessageViewer::PlainHeaderStylePrivate
{
public:
PlainHeaderStylePrivate()
{
}
QString formatAllMessageHeaders(KMime::Message *message) const;
MessageViewer::HeaderStyleUtil mHeaderStyleUtil;
};
QString PlainHeaderStylePrivate::formatAllMessageHeaders(KMime::Message *message) const
{
QByteArray head = message->head();
KMime::Headers::Base *header = KMime::HeaderParsing::extractFirstHeader(head);
QString result;
while (header) {
result += mHeaderStyleUtil.strToHtml(QLatin1String(header->type()) + QLatin1String(
": ") + header->asUnicodeString());
result += QLatin1String(" \n");
delete header;
header = KMime::HeaderParsing::extractFirstHeader(head);
}
return result;
}
PlainHeaderStyle::PlainHeaderStyle()
: HeaderStyle()
, d(new MessageViewer::PlainHeaderStylePrivate)
{
}
PlainHeaderStyle::~PlainHeaderStyle()
{
delete d;
}
//
// PlainHeaderStyle:
// show every header field on a line by itself,
// show subject larger
//
QString PlainHeaderStyle::format(KMime::Message *message) const
{
if (!message) {
return QString();
}
const HeaderStrategy *strategy = headerStrategy();
// The direction of the header is determined according to the direction
// of the application layout.
const QString dir
= QApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr");
// However, the direction of the message subject within the header is
// determined according to the contents of the subject itself. Since
// the "Re:" and "Fwd:" prefixes would always cause the subject to be
// considered left-to-right, they are ignored when determining its
// direction.
const QString subjectDir = d->mHeaderStyleUtil.subjectDirectionString(message);
QString headerStr;
if (strategy->headersToDisplay().isEmpty()
&& strategy->defaultPolicy() == HeaderStrategy::Display) {
// crude way to emulate "all" headers - Note: no strings have
// i18n(), so direction should always be ltr.
headerStr = QStringLiteral("");
}
headerStr = QStringLiteral("\n");
return headerStr;
}
const char *MessageViewer::PlainHeaderStyle::name() const
{
return "plain";
}
diff --git a/messageviewer/src/messageviewerheaderplugins/defaultgrantleeheaderstyleplugin/theme/5.2/header.html b/messageviewer/src/messageviewerheaderplugins/defaultgrantleeheaderstyleplugin/theme/5.2/header.html
index 83d99826..c4f0806f 100644
--- a/messageviewer/src/messageviewerheaderplugins/defaultgrantleeheaderstyleplugin/theme/5.2/header.html
+++ b/messageviewer/src/messageviewerheaderplugins/defaultgrantleeheaderstyleplugin/theme/5.2/header.html
@@ -1,87 +1,87 @@