7#include "grantleeheaderformatter.h"
8#include "headerstyle_util.h"
9#include "settings/messageviewersettings.h"
10#include "utils/iconnamecache.h"
12#include <MessageCore/StringUtil>
13#include <MimeTreeParser/NodeHelper>
15#include <KMime/DateFormatter>
16#include <KMime/KMimeMessage>
18#include <KColorScheme>
20#include <KLocalizedString>
21#include <KTextTemplate/Engine>
22#include <KTextTemplate/MetaType>
24using namespace MessageCore;
26using namespace MessageViewer;
42 return StringUtil::emailAddrAsAnchor(
object, StringUtil::DisplayNameOnly);
44 return !
object->asUnicodeString().isEmpty();
46 return StringUtil::emailAddrAsAnchor(
object, StringUtil::DisplayFullAddress);
48 return object->asUnicodeString();
50 const auto &
name =
property.
mid(10);
51 const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
object,
52 MessageCore::StringUtil::DisplayFullAddress,
54 MessageCore::StringUtil::ShowLink,
55 MessageCore::StringUtil::ExpandableAddresses,
56 QStringLiteral(
"Full") + name + QStringLiteral(
"AddressList"));
70 return StringUtil::emailAddrAsAnchor(
object.data(), StringUtil::DisplayNameOnly);
72 return !
object->asUnicodeString().isEmpty();
74 return StringUtil::emailAddrAsAnchor(
object.data(), StringUtil::DisplayFullAddress);
76 return object->asUnicodeString();
78 const auto &
name =
property.
mid(10);
79 const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
object.data(),
80 MessageCore::StringUtil::DisplayFullAddress,
82 MessageCore::StringUtil::ShowLink,
83 MessageCore::StringUtil::ExpandableAddresses,
84 QStringLiteral(
"Full") + name + QStringLiteral(
"AddressList"));
97 return StringUtil::emailAddrAsAnchor(
object, StringUtil::DisplayNameOnly);
99 return !
object->asUnicodeString().isEmpty();
101 return StringUtil::emailAddrAsAnchor(
object, StringUtil::DisplayFullAddress);
103 return object->asUnicodeString();
105 const auto &
name =
property.
mid(10);
106 const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
object,
107 MessageCore::StringUtil::DisplayFullAddress,
109 MessageCore::StringUtil::ShowLink,
110 MessageCore::StringUtil::ExpandableAddresses,
111 QStringLiteral(
"Full") + name + QStringLiteral(
"AddressList"));
119 return StringUtil::emailAddrAsAnchor(
object.data(), StringUtil::DisplayNameOnly);
121 return !
object->asUnicodeString().isEmpty();
123 return StringUtil::emailAddrAsAnchor(
object.data(), StringUtil::DisplayFullAddress);
125 return object->asUnicodeString();
127 const auto &
name =
property.
mid(10);
128 const QString val = MessageCore::StringUtil::emailAddrAsAnchor(
object.data(),
129 MessageCore::StringUtil::DisplayFullAddress,
131 MessageCore::StringUtil::ShowLink,
132 MessageCore::StringUtil::ExpandableAddresses,
133 QStringLiteral(
"Full") + name + QStringLiteral(
"AddressList"));
144 return HeaderStyleUtil::dateStr(
object);
159 return HeaderStyleUtil::strToHtml(HeaderStyleUtil::dateString(
object, dateFormat));
163class Q_DECL_HIDDEN HeaderFormatter
166 virtual ~HeaderFormatter() =
default;
169 virtual QString i18nName() = 0;
172class DefaultHeaderFormatter :
public HeaderFormatter
182 if (header ==
"list-id") {
183 return i18n(
"List-Id:");
191 Q_UNUSED(showEmoticons);
199class SubjectFormatter :
public HeaderFormatter
204 return i18n(
"Subject:");
213 const auto subjectStr = nodeHelper->mailHeaderAsBase(
"subject", message)->
asUnicodeString();
215 return HeaderStyleUtil::strToHtml(subjectStr, flags);
219class DateFormatter :
public HeaderFormatter
224 return i18n(
"Date:");
229 Q_UNUSED(showEmoticons);
230 const auto value = nodeHelper->dateHeader(message);
235class MessageIdFormatter :
public HeaderFormatter
240 return i18n(
"Message-Id:");
245 const auto messageIdHeader = nodeHelper->mailHeaderAsBase(
"Message-Id", message);
246 if (messageIdHeader !=
nullptr) {
253class AddressHeaderFormatter :
public HeaderFormatter
263 if (header ==
"to") {
265 }
else if (header ==
"reply-To") {
266 return i18n(
"Reply To:");
267 }
else if (header ==
"cc") {
269 }
else if (header ==
"bcc") {
271 }
else if (header ==
"from") {
272 return i18n(
"From:");
273 }
else if (header ==
"sender") {
274 return i18n(
"Sender:");
275 }
else if (header ==
"resent-From") {
276 return i18n(
"resent from:");
277 }
else if (header ==
"resent-To") {
278 return i18n(
"resent to:");
286 Q_UNUSED(showEmoticons);
287 const auto value = nodeHelper->mailHeaderAsAddressList(header.
constData(), message);
295class MessageViewer::GrantleeHeaderFormatter::GrantleeHeaderFormatterPrivate
298 GrantleeHeaderFormatterPrivate()
301 KTextTemplate::registerMetaType<const KMime::Headers::Generics::AddressList *>();
302 KTextTemplate::registerMetaType<const KMime::Headers::Generics::MailboxList *>();
303 KTextTemplate::registerMetaType<QSharedPointer<KMime::Headers::Generics::MailboxList>>();
304 KTextTemplate::registerMetaType<QSharedPointer<KMime::Headers::Generics::AddressList>>();
305 KTextTemplate::registerMetaType<QDateTime>();
306 KTextTemplate::registerMetaType<QByteArray>();
312 addressHeaders <<
"to"
321 for (
const auto &header :
std::as_const(addressHeaders)) {
330 ~GrantleeHeaderFormatterPrivate()
337 headerFormatter[header] = formatter;
348GrantleeHeaderFormatter::GrantleeHeaderFormatter()
353GrantleeHeaderFormatter::~GrantleeHeaderFormatter() =
default;
355QString GrantleeHeaderFormatter::toHtml(
const GrantleeHeaderFormatter::GrantleeHeaderFormatterSettings &settings)
const
358 if (!settings.theme.isValid()) {
359 errorMessage =
i18n(
"Grantlee theme \"%1\" is not valid.", settings.theme.name());
362 d->templateLoader->setTemplateDirs(
QStringList() << settings.theme.absolutePath());
364 if (headerTemplate->
error()) {
368 return format(settings.theme.absolutePath(),
370 settings.theme.displayExtraVariables(),
374 settings.showEmoticons);
382 bool isPrinting)
const
384 d->templateLoader->setTemplateDirs(
QStringList() << absolutPath);
386 if (headerTemplate->
error()) {
389 return format(absolutPath, headerTemplate, displayExtraHeaders, isPrinting, style, message);
392QString GrantleeHeaderFormatter::format(
const QString &absolutePath,
398 bool showEmoticons)
const
400 QVariantHash headerObject;
401 const auto nodeHelper = style->nodeHelper();
409 headerObject.
insert(QStringLiteral(
"absoluteThemePath"), absoluteThemePath);
413 headerObject.
insert(QStringLiteral(
"subjectDir"), d->headerStyleUtil.subjectDirectionString(message));
416 defaultHeaders <<
"to"
430 for (
const auto &header :
std::as_const(defaultHeaders)) {
432 if (d->headerFormatter.contains(header)) {
433 formatter = d->headerFormatter.value(header);
437 const auto i18nName = formatter->i18nName();
439 if (nodeHelper->hasMailHeader(header.constData(), message)) {
440 const auto value = formatter->format(message, nodeHelper, showEmoticons);
441 headerObject.insert(objectName, value);
443 if (!i18nName.isEmpty()) {
444 headerObject.insert(objectName + QStringLiteral(
"i18n"), i18nName);
448 if (!nodeHelper->hasMailHeader(
"subject", message)) {
449 headerObject.insert(QStringLiteral(
"subject"),
i18n(
"No Subject"));
452 const QString spamHtml = d->headerStyleUtil.spamStatus(message);
454 headerObject.insert(QStringLiteral(
"spamstatusi18n"),
i18n(
"Spam Status:"));
455 headerObject.insert(QStringLiteral(
"spamHTML"), spamHtml);
458 if (!style->vCardName().
isEmpty()) {
459 headerObject.insert(QStringLiteral(
"vcardname"), style->vCardName());
466 headerObject.insert(QStringLiteral(
"isprinting"),
i18n(
"Printing mode"));
467 headerObject.insert(QStringLiteral(
"printmode"), QStringLiteral(
"printmode"));
469 headerObject.insert(QStringLiteral(
"screenmode"), QStringLiteral(
"screenmode"));
474 QString linkColor = QStringLiteral(
"white");
476 if (!d->activeColor.isValid()) {
479 QColor activeColorDark = d->activeColor.darker(130);
481 if (!style->isTopLevel()) {
482 activeColorDark = d->activeColor.darker(50);
484 linkColor = QStringLiteral(
"black");
488 headerObject.insert(QStringLiteral(
"activecolordark"), activeColorDark.
name());
489 headerObject.insert(QStringLiteral(
"fontcolor"), fontColor.name());
490 headerObject.insert(QStringLiteral(
"linkcolor"), linkColor);
492 MessageViewer::HeaderStyleUtil::xfaceSettings xface = d->headerStyleUtil.xface(style, message);
493 if (!xface.photoURL.
isEmpty()) {
494 headerObject.insert(QStringLiteral(
"photowidth"), xface.photoWidth);
495 headerObject.insert(QStringLiteral(
"photoheight"), xface.photoHeight);
496 headerObject.insert(QStringLiteral(
"photourl"), xface.photoURL);
499 for (
QString header :
std::as_const(displayExtraHeaders)) {
500 const QByteArray baHeader = header.toLocal8Bit();
501 if (
auto hrd = message->headerByType(baHeader.
constData())) {
504 headerObject.
insert(header, hrd->asUnicodeString());
508 headerObject.
insert(QStringLiteral(
"vcardi18n"),
i18n(
"[vcard]"));
509 headerObject.
insert(QStringLiteral(
"readOnlyMessage"), style->readOnlyMessage());
511 const QString attachmentHtml = style->attachmentHtml();
512 const bool messageHasAttachment = !attachmentHtml.
isEmpty();
513 headerObject.insert(QStringLiteral(
"hasAttachment"), messageHasAttachment);
514 headerObject.insert(QStringLiteral(
"attachmentHtml"), attachmentHtml);
515 headerObject.insert(QStringLiteral(
"attachmentI18n"),
i18n(
"Attachments:"));
517 if (messageHasAttachment) {
518 const QString iconPath = MessageViewer::IconNameCache::instance()->iconPath(QStringLiteral(
"mail-attachment"),
KIconLoader::Toolbar);
521 headerObject.
insert(QStringLiteral(
"attachmentIcon"), html);
524 const bool messageIsSigned = KMime::isSigned(message);
525 headerObject.insert(QStringLiteral(
"messageIsSigned"), messageIsSigned);
526 if (messageIsSigned) {
530 headerObject.
insert(QStringLiteral(
"signedIcon"), html);
533 const bool messageIsEncrypted = KMime::isEncrypted(message);
534 headerObject.insert(QStringLiteral(
"messageIsEncrypted"), messageIsEncrypted);
535 if (messageIsEncrypted) {
536 const QString iconPath = MessageViewer::IconNameCache::instance()->iconPath(QStringLiteral(
"mail-encrypted"),
KIconLoader::Toolbar);
539 headerObject.
insert(QStringLiteral(
"encryptedIcon"), html);
542 const bool messageHasSecurityInfo = messageIsEncrypted || messageIsSigned;
543 headerObject.insert(QStringLiteral(
"messageHasSecurityInfo"), messageHasSecurityInfo);
544 headerObject.insert(QStringLiteral(
"messageHasSecurityInfoI18n"),
i18n(
"Security:"));
546 QVariantHash mapping;
547 mapping.insert(QStringLiteral(
"header"), headerObject);
550 return headerTemplate->
render(&context);
QBrush background(BackgroundRole=NormalBackground) const
int currentSize(KIconLoader::Group group) const
static KIconLoader * global()
void addTemplateLoader(QSharedPointer< AbstractTemplateLoader > loader)
QString errorString() const
QString render(Context *c) const
QString i18n(const char *text, const TYPE &arg...)
KCALUTILS_EXPORT QString errorMessage(const KCalendarCore::Exception &exception)
QString name(StandardShortcut id)
const QColor & color() const const
const char * constData() const const
QByteArray & insert(qsizetype i, QByteArrayView data)
QByteArray & remove(qsizetype pos, qsizetype len)
QString name(NameFormat format) const const
QString arg(Args &&... args) const const
QString fromUtf8(QByteArrayView str)
QString & insert(qsizetype position, QChar ch)
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QUrl fromLocalFile(const QString &localFile)
QString url(FormattingOptions options) const const
QVariant fromValue(T &&value)