Messagelib

grantleeheaderformatter.cpp
1 /*
2  SPDX-FileCopyrightText: 2013-2023 Laurent Montel <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "grantleeheaderformatter.h"
8 #include "config-messageviewer.h"
9 #include "headerstyle_util.h"
10 #include "settings/messageviewersettings.h"
11 #include "utils/iconnamecache.h"
12 
13 #include <MessageCore/StringUtil>
14 #include <MimeTreeParser/NodeHelper>
15 
16 #include <KMime/DateFormatter>
17 #include <KMime/KMimeMessage>
18 
19 #include <KColorScheme>
20 #include <KIconLoader>
21 #include <KLocalizedString>
22 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
23 #include <grantlee/engine.h>
24 #include <grantlee/metatype.h>
25 #else
26 #include <KTextTemplate/Engine>
27 #include <KTextTemplate/MetaType>
28 #endif
29 
30 using namespace MessageCore;
31 
32 using namespace MessageViewer;
33 
34 Q_DECLARE_METATYPE(const KMime::Headers::Generics::AddressList *)
36 Q_DECLARE_METATYPE(const KMime::Headers::Generics::MailboxList *)
38 Q_DECLARE_METATYPE(QDateTime)
39 
40 // Read-only introspection of KMime::Headers::Generics::AddressList object.
41 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
42 namespace Grantlee
43 #else
44 namespace KTextTemplate
45 #endif
46 {
47 template<>
48 inline QVariant TypeAccessor<const KMime::Headers::Generics::AddressList *>::lookUp(const KMime::Headers::Generics::AddressList *const object,
49  const QString &property)
50 {
51  if (property == QLatin1String("nameOnly")) {
52  return StringUtil::emailAddrAsAnchor(object, StringUtil::DisplayNameOnly);
53  } else if (property == QLatin1String("isSet")) {
54  return !object->asUnicodeString().isEmpty();
55  } else if (property == QLatin1String("fullAddress")) {
56  return StringUtil::emailAddrAsAnchor(object, StringUtil::DisplayFullAddress);
57  } else if (property == QLatin1String("str")) {
58  return object->asUnicodeString();
59  } else if (property.startsWith(QLatin1String("expandable"))) {
60  const auto &name = property.mid(10);
62  MessageCore::StringUtil::DisplayFullAddress,
63  QString(),
64  MessageCore::StringUtil::ShowLink,
65  MessageCore::StringUtil::ExpandableAddresses,
66  QStringLiteral("Full") + name + QStringLiteral("AddressList"));
67  return val;
68  }
69  return {};
70 }
71 }
72 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
74 #else
76 #endif
77 if (property == QLatin1String("nameOnly")) {
78  return StringUtil::emailAddrAsAnchor(object.data(), StringUtil::DisplayNameOnly);
79 } else if (property == QLatin1String("isSet")) {
80  return !object->asUnicodeString().isEmpty();
81 } else if (property == QLatin1String("fullAddress")) {
82  return StringUtil::emailAddrAsAnchor(object.data(), StringUtil::DisplayFullAddress);
83 } else if (property == QLatin1String("str")) {
84  return object->asUnicodeString();
85 } else if (property.startsWith(QLatin1String("expandable"))) {
86  const auto &name = property.mid(10);
87  const QString val = MessageCore::StringUtil::emailAddrAsAnchor(object.data(),
88  MessageCore::StringUtil::DisplayFullAddress,
89  QString(),
90  MessageCore::StringUtil::ShowLink,
91  MessageCore::StringUtil::ExpandableAddresses,
92  QStringLiteral("Full") + name + QStringLiteral("AddressList"));
93  return val;
94 }
95 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
96 GRANTLEE_END_LOOKUP
97 #else
99 #endif
100 
101 // Read-only introspection of KMime::Headers::Generics::MailboxList object.
102 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
103 namespace Grantlee
104 #else
105 namespace KTextTemplate
106 #endif
107 {
108 template<>
109 inline QVariant TypeAccessor<const KMime::Headers::Generics::MailboxList *>::lookUp(const KMime::Headers::Generics::MailboxList *const object,
110  const QString &property)
111 {
112  if (property == QLatin1String("nameOnly")) {
113  return StringUtil::emailAddrAsAnchor(object, StringUtil::DisplayNameOnly);
114  } else if (property == QLatin1String("isSet")) {
115  return !object->asUnicodeString().isEmpty();
116  } else if (property == QLatin1String("fullAddress")) {
117  return StringUtil::emailAddrAsAnchor(object, StringUtil::DisplayFullAddress);
118  } else if (property == QLatin1String("str")) {
119  return object->asUnicodeString();
120  } else if (property.startsWith(QLatin1String("expandable"))) {
121  const auto &name = property.mid(10);
123  MessageCore::StringUtil::DisplayFullAddress,
124  QString(),
125  MessageCore::StringUtil::ShowLink,
126  MessageCore::StringUtil::ExpandableAddresses,
127  QStringLiteral("Full") + name + QStringLiteral("AddressList"));
128  return val;
129  }
130  return {};
131 }
132 }
133 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
135 #else
137 #endif
138 if (property == QLatin1String("nameOnly")) {
139  return StringUtil::emailAddrAsAnchor(object.data(), StringUtil::DisplayNameOnly);
140 } else if (property == QLatin1String("isSet")) {
141  return !object->asUnicodeString().isEmpty();
142 } else if (property == QLatin1String("fullAddress")) {
143  return StringUtil::emailAddrAsAnchor(object.data(), StringUtil::DisplayFullAddress);
144 } else if (property == QLatin1String("str")) {
145  return object->asUnicodeString();
146 } else if (property.startsWith(QLatin1String("expandable"))) {
147  const auto &name = property.mid(10);
148  const QString val = MessageCore::StringUtil::emailAddrAsAnchor(object.data(),
149  MessageCore::StringUtil::DisplayFullAddress,
150  QString(),
151  MessageCore::StringUtil::ShowLink,
152  MessageCore::StringUtil::ExpandableAddresses,
153  QStringLiteral("Full") + name + QStringLiteral("AddressList"));
154  return val;
155 }
156 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
157 GRANTLEE_END_LOOKUP
158 #else
160 #endif
161 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
162 namespace Grantlee
163 #else
164 namespace KTextTemplate
165 #endif
166 {
167 template<>
168 inline QVariant TypeAccessor<QDateTime &>::lookUp(const QDateTime &object, const QString &property)
169 {
171  if (property == QLatin1String("str")) {
172  return HeaderStyleUtil::dateStr(object);
173  } else if (property == QLatin1String("short")) {
175  } else if (property == QLatin1String("long")) {
177  } else if (property == QLatin1String("fancylong")) {
179  } else if (property == QLatin1String("fancyshort")) {
181  } else if (property == QLatin1String("localelong")) {
183  } else {
184  return {};
185  }
186 
187  return HeaderStyleUtil::strToHtml(HeaderStyleUtil::dateString(object, dateFormat));
188 }
189 }
190 
191 class Q_DECL_HIDDEN HeaderFormatter
192 {
193 public:
194  virtual ~HeaderFormatter() = default;
195 
196  virtual QVariant format(KMime::Message *message, MimeTreeParser::NodeHelper *nodeHelper, bool showEmoticons) = 0;
197  virtual QString i18nName() = 0;
198 };
199 
200 class DefaultHeaderFormatter : public HeaderFormatter
201 {
202 public:
203  DefaultHeaderFormatter(const QByteArray &h)
204  : header(h)
205  {
206  }
207 
208  QString i18nName() override
209  {
210  if (header == "list-id") {
211  return i18n("List-Id:");
212  } else {
213  return {};
214  }
215  }
216 
217  QVariant format(KMime::Message *message, MimeTreeParser::NodeHelper *nodeHelper, bool showEmoticons) override
218  {
219  Q_UNUSED(showEmoticons);
220  return nodeHelper->mailHeaderAsBase(header.constData(), message)->asUnicodeString();
221  }
222 
223 private:
224  QByteArray header;
225 };
226 
227 class SubjectFormatter : public HeaderFormatter
228 {
229 public:
230  QString i18nName() override
231  {
232  return i18n("Subject:");
233  }
234 
235  QVariant format(KMime::Message *message, MimeTreeParser::NodeHelper *nodeHelper, bool showEmoticons) override
236  {
238  if (showEmoticons) {
240  }
241  const auto subjectStr = nodeHelper->mailHeaderAsBase("subject", message)->asUnicodeString();
242 
243  return HeaderStyleUtil::strToHtml(subjectStr, flags);
244  }
245 };
246 
247 class DateFormatter : public HeaderFormatter
248 {
249 public:
250  QString i18nName() override
251  {
252  return i18n("Date:");
253  }
254 
255  QVariant format(KMime::Message *message, MimeTreeParser::NodeHelper *nodeHelper, bool showEmoticons) override
256  {
257  Q_UNUSED(showEmoticons);
258  const auto value = nodeHelper->dateHeader(message);
259  return value;
260  }
261 };
262 
263 class AddressHeaderFormatter : public HeaderFormatter
264 {
265 public:
266  AddressHeaderFormatter(const QByteArray &h)
267  : header(h)
268  {
269  }
270 
271  QString i18nName() override
272  {
273  if (header == "to") {
274  return i18n("To:");
275  } else if (header == "reply-To") {
276  return i18n("Reply To:");
277  } else if (header == "cc") {
278  return i18n("CC:");
279  } else if (header == "bcc") {
280  return i18n("BCC:");
281  } else if (header == "from") {
282  return i18n("From:");
283  } else if (header == "sender") {
284  return i18n("Sender:");
285  } else if (header == "resent-From") {
286  return i18n("resent from:");
287  } else if (header == "resent-To") {
288  return i18n("resent to:");
289  } else {
290  return {};
291  }
292  }
293 
294  QVariant format(KMime::Message *message, MimeTreeParser::NodeHelper *nodeHelper, bool showEmoticons) override
295  {
296  Q_UNUSED(showEmoticons);
297  const auto value = nodeHelper->mailHeaderAsAddressList(header.constData(), message);
298  return QVariant::fromValue(value);
299  }
300 
301 protected:
302  QByteArray header;
303 };
304 
305 class MessageViewer::GrantleeHeaderFormatter::GrantleeHeaderFormatterPrivate
306 {
307 public:
308  GrantleeHeaderFormatterPrivate()
309 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
310  : engine(new Grantlee::Engine)
311 #else
312  : engine(new KTextTemplate::Engine)
313 #endif
314  {
315 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
316  Grantlee::registerMetaType<const KMime::Headers::Generics::AddressList *>();
317  Grantlee::registerMetaType<const KMime::Headers::Generics::MailboxList *>();
318  Grantlee::registerMetaType<QSharedPointer<KMime::Headers::Generics::MailboxList>>();
319  Grantlee::registerMetaType<QSharedPointer<KMime::Headers::Generics::AddressList>>();
320  Grantlee::registerMetaType<QDateTime>();
321 #else
322  KTextTemplate::registerMetaType<const KMime::Headers::Generics::AddressList *>();
323  KTextTemplate::registerMetaType<const KMime::Headers::Generics::MailboxList *>();
324  KTextTemplate::registerMetaType<QSharedPointer<KMime::Headers::Generics::MailboxList>>();
325  KTextTemplate::registerMetaType<QSharedPointer<KMime::Headers::Generics::AddressList>>();
326  KTextTemplate::registerMetaType<QDateTime>();
327 #endif
329 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
330  templateLoader = QSharedPointer<Grantlee::FileSystemTemplateLoader>(new Grantlee::FileSystemTemplateLoader);
331 #else
333 #endif
334  engine->addTemplateLoader(templateLoader);
335 
336  QVector<QByteArray> addressHeaders;
337  addressHeaders << "to"
338  << "reply-To"
339  << "cc"
340  << "bcc"
341  << "from"
342  << "sender"
343  << "resent-From"
344  << "resent-To";
345 
346  for (const auto &header : std::as_const(addressHeaders)) {
347  registerHeaderFormatter(header, QSharedPointer<HeaderFormatter>(new AddressHeaderFormatter(header)));
348  }
349 
350  registerHeaderFormatter("subject", QSharedPointer<HeaderFormatter>(new SubjectFormatter()));
351  registerHeaderFormatter("date", QSharedPointer<HeaderFormatter>(new DateFormatter()));
352  }
353 
354  ~GrantleeHeaderFormatterPrivate()
355  {
356  delete engine;
357  }
358 
359  void registerHeaderFormatter(const QByteArray &header, QSharedPointer<HeaderFormatter> formatter)
360  {
361  headerFormatter[header] = formatter;
362  }
363 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
365  Grantlee::Engine *const engine;
366 #else
368  KTextTemplate::Engine *const engine;
369 #endif
371  MessageViewer::HeaderStyleUtil headerStyleUtil;
372  QColor activeColor;
373 
374  int iconSize;
375 };
376 
377 GrantleeHeaderFormatter::GrantleeHeaderFormatter()
378  : d(new GrantleeHeaderFormatter::GrantleeHeaderFormatterPrivate)
379 {
380 }
381 
382 GrantleeHeaderFormatter::~GrantleeHeaderFormatter() = default;
383 
384 QString GrantleeHeaderFormatter::toHtml(const GrantleeHeaderFormatter::GrantleeHeaderFormatterSettings &settings) const
385 {
387  if (!settings.theme.isValid()) {
388  errorMessage = i18n("Grantlee theme \"%1\" is not valid.", settings.theme.name());
389  return errorMessage;
390  }
391  d->templateLoader->setTemplateDirs(QStringList() << settings.theme.absolutePath());
392 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
393  Grantlee::Template headerTemplate = d->engine->loadByName(settings.theme.themeFilename());
394 #else
395  KTextTemplate::Template headerTemplate = d->engine->loadByName(settings.theme.themeFilename());
396 #endif
397  if (headerTemplate->error()) {
398  errorMessage = headerTemplate->errorString();
399  return errorMessage;
400  }
401  return format(settings.theme.absolutePath(),
402  headerTemplate,
403  settings.theme.displayExtraVariables(),
404  settings.isPrinting,
405  settings.style,
406  settings.message,
407  settings.showEmoticons);
408 }
409 
410 QString GrantleeHeaderFormatter::toHtml(const QStringList &displayExtraHeaders,
411  const QString &absolutPath,
412  const QString &filename,
413  const MessageViewer::HeaderStyle *style,
415  bool isPrinting) const
416 {
417  d->templateLoader->setTemplateDirs(QStringList() << absolutPath);
418 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
419  Grantlee::Template headerTemplate = d->engine->loadByName(filename);
420 #else
421  KTextTemplate::Template headerTemplate = d->engine->loadByName(filename);
422 #endif
423  if (headerTemplate->error()) {
424  return headerTemplate->errorString();
425  }
426  return format(absolutPath, headerTemplate, displayExtraHeaders, isPrinting, style, message);
427 }
428 
429 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
430 QString GrantleeHeaderFormatter::format(const QString &absolutePath,
431  const Grantlee::Template &headerTemplate,
432  const QStringList &displayExtraHeaders,
433  bool isPrinting,
434  const MessageViewer::HeaderStyle *style,
436  bool showEmoticons) const
437 #else
438 QString GrantleeHeaderFormatter::format(const QString &absolutePath,
439  const KTextTemplate::Template &headerTemplate,
440  const QStringList &displayExtraHeaders,
441  bool isPrinting,
442  const MessageViewer::HeaderStyle *style,
444  bool showEmoticons) const
445 #endif
446 {
447  QVariantHash headerObject;
448  const auto nodeHelper = style->nodeHelper();
449 
450  // However, the direction of the message subject within the header is
451  // determined according to the contents of the subject itself. Since
452  // the "Re:" and "Fwd:" prefixes would always cause the subject to be
453  // considered left-to-right, they are ignored when determining its
454  // direction.
455  const QString absoluteThemePath = QUrl::fromLocalFile(absolutePath + QLatin1Char('/')).url();
456  headerObject.insert(QStringLiteral("absoluteThemePath"), absoluteThemePath);
457  headerObject.insert(QStringLiteral("applicationDir"), QApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr"));
458 
459  // TODO: use correct subject from nodeHelper->mailHeader
460  headerObject.insert(QStringLiteral("subjectDir"), d->headerStyleUtil.subjectDirectionString(message));
461 
462  QVector<QByteArray> defaultHeaders;
463  defaultHeaders << "to"
464  << "reply-To"
465  << "cc"
466  << "bcc"
467  << "from"
468  << "sender"
469  << "resent-From"
470  << "resent-To"
471  << "subject"
472  << "organization"
473  << "list-id"
474  << "date";
475 
476  for (const auto &header : std::as_const(defaultHeaders)) {
478  if (d->headerFormatter.contains(header)) {
479  formatter = d->headerFormatter.value(header);
480  } else {
481  formatter = QSharedPointer<HeaderFormatter>(new DefaultHeaderFormatter(header));
482  }
483  const auto i18nName = formatter->i18nName();
484  const auto objectName = QString::fromUtf8(header).remove(QLatin1Char('-'));
485  if (nodeHelper->hasMailHeader(header.constData(), message)) {
486  const auto value = formatter->format(message, nodeHelper, showEmoticons);
487  headerObject.insert(objectName, value);
488  }
489  if (!i18nName.isEmpty()) {
490  headerObject.insert(objectName + QStringLiteral("i18n"), i18nName);
491  }
492  }
493 
494  if (!nodeHelper->hasMailHeader("subject", message)) {
495  headerObject.insert(QStringLiteral("subject"), i18n("No Subject"));
496  }
497 
498  const QString spamHtml = d->headerStyleUtil.spamStatus(message);
499  if (!spamHtml.isEmpty()) {
500  headerObject.insert(QStringLiteral("spamstatusi18n"), i18n("Spam Status:"));
501  headerObject.insert(QStringLiteral("spamHTML"), spamHtml);
502  }
503 
504  if (!style->vCardName().isEmpty()) {
505  headerObject.insert(QStringLiteral("vcardname"), style->vCardName());
506  }
507 
508  if (isPrinting) {
509  // provide a bit more left padding when printing
510  // kolab/issue3254 (printed mail cut at the left side)
511  // Use it just for testing if we are in printing mode
512  headerObject.insert(QStringLiteral("isprinting"), i18n("Printing mode"));
513  headerObject.insert(QStringLiteral("printmode"), QStringLiteral("printmode"));
514  } else {
515  headerObject.insert(QStringLiteral("screenmode"), QStringLiteral("screenmode"));
516  }
517 
518  // colors depend on if it is encapsulated or not
519  QColor fontColor(Qt::white);
520  QString linkColor = QStringLiteral("white");
521 
522  if (!d->activeColor.isValid()) {
524  }
525  QColor activeColorDark = d->activeColor.darker(130);
526  // reverse colors for encapsulated
527  if (!style->isTopLevel()) {
528  activeColorDark = d->activeColor.darker(50);
529  fontColor = QColor(Qt::black);
530  linkColor = QStringLiteral("black");
531  }
532 
533  // 3D borders
534  headerObject.insert(QStringLiteral("activecolordark"), activeColorDark.name());
535  headerObject.insert(QStringLiteral("fontcolor"), fontColor.name());
536  headerObject.insert(QStringLiteral("linkcolor"), linkColor);
537 
538  MessageViewer::HeaderStyleUtil::xfaceSettings xface = d->headerStyleUtil.xface(style, message);
539  if (!xface.photoURL.isEmpty()) {
540  headerObject.insert(QStringLiteral("photowidth"), xface.photoWidth);
541  headerObject.insert(QStringLiteral("photoheight"), xface.photoHeight);
542  headerObject.insert(QStringLiteral("photourl"), xface.photoURL);
543  }
544 
545  for (QString header : std::as_const(displayExtraHeaders)) {
546  const QByteArray baHeader = header.toLocal8Bit();
547  if (auto hrd = message->headerByType(baHeader.constData())) {
548  // Grantlee doesn't support '-' in variable name => remove it.
549  header.remove(QLatin1Char('-'));
550  headerObject.insert(header, hrd->asUnicodeString());
551  }
552  }
553 
554  headerObject.insert(QStringLiteral("vcardi18n"), i18n("[vcard]"));
555  headerObject.insert(QStringLiteral("readOnlyMessage"), style->readOnlyMessage());
556 
557  const QString attachmentHtml = style->attachmentHtml();
558  const bool messageHasAttachment = KMime::hasAttachment(message) && !attachmentHtml.isEmpty();
559  headerObject.insert(QStringLiteral("hasAttachment"), messageHasAttachment);
560  headerObject.insert(QStringLiteral("attachmentHtml"), attachmentHtml);
561  headerObject.insert(QStringLiteral("attachmentI18n"), i18n("Attachments:"));
562 
563  if (messageHasAttachment) {
564  const QString iconPath = MessageViewer::IconNameCache::instance()->iconPath(QStringLiteral("mail-attachment"), KIconLoader::Toolbar);
565  const QString html =
566  QStringLiteral("<img height=\"%2\" width=\"%2\" src=\"%1\"></a>").arg(QUrl::fromLocalFile(iconPath).url(), QString::number(d->iconSize));
567  headerObject.insert(QStringLiteral("attachmentIcon"), html);
568  }
569 
570  const bool messageIsSigned = KMime::isSigned(message);
571  headerObject.insert(QStringLiteral("messageIsSigned"), messageIsSigned);
572  if (messageIsSigned) {
573  const QString iconPath = MessageViewer::IconNameCache::instance()->iconPath(QStringLiteral("mail-signed"), KIconLoader::Toolbar);
574  const QString html =
575  QStringLiteral("<img height=\"%2\" width=\"%2\" src=\"%1\"></a>").arg(QUrl::fromLocalFile(iconPath).url(), QString::number(d->iconSize));
576  headerObject.insert(QStringLiteral("signedIcon"), html);
577  }
578 
579  const bool messageIsEncrypted = KMime::isEncrypted(message);
580  headerObject.insert(QStringLiteral("messageIsEncrypted"), messageIsEncrypted);
581  if (messageIsEncrypted) {
582  const QString iconPath = MessageViewer::IconNameCache::instance()->iconPath(QStringLiteral("mail-encrypted"), KIconLoader::Toolbar);
583  const QString html =
584  QStringLiteral("<img height=\"%2\" width=\"%2\" src=\"%1\"></a>").arg(QUrl::fromLocalFile(iconPath).url(), QString::number(d->iconSize));
585  headerObject.insert(QStringLiteral("encryptedIcon"), html);
586  }
587 
588  const bool messageHasSecurityInfo = messageIsEncrypted || messageIsSigned;
589  headerObject.insert(QStringLiteral("messageHasSecurityInfo"), messageHasSecurityInfo);
590  headerObject.insert(QStringLiteral("messageHasSecurityInfoI18n"), i18n("Security:"));
591 
592  QVariantHash mapping;
593  mapping.insert(QStringLiteral("header"), headerObject);
594 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
595  Grantlee::Context context(mapping);
596 #else
597  KTextTemplate::Context context(mapping);
598 #endif
599 
600  return headerTemplate->render(&context);
601 }
@ FancyLongDate
Same as LongDate for dates a week or more ago.
The GrantleeHeaderFormatter class.
const QColor & color() const const
const Engine * engine() const
QString number(int n, int base)
QString fromUtf8(const char *str, int size)
QVariant fromValue(const T &value)
@ LongDate
Locale Long date format, e.g.
QString url(QUrl::FormattingOptions options) const const
QString name() const const
QBrush background(BackgroundRole=NormalBackground) const
@ FancyShortDate
Same as ShortDate for dates a week or more ago.
KCALUTILS_EXPORT QString errorMessage(const KCalendarCore::Exception &exception)
QByteArray & remove(int pos, int len)
QString i18n(const char *text, const TYPE &arg...)
Template loadByName(const QString &name) const
This class encapsulates the visual appearance of message headers.
Definition: headerstyle.h:46
bool isEmpty() const const
QUrl fromLocalFile(const QString &localFile)
static KIconLoader * global()
#define KTEXTTEMPLATE_BEGIN_LOOKUP(Type)
#define KTEXTTEMPLATE_END_LOOKUP
QColor darker(int factor) const const
bool isRightToLeft()
int currentSize(KIconLoader::Group group) const
QString & remove(int position, int n)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString errorString() const
@ ShortDate
Locale Short date format, e.g.
const char * constData() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString & insert(int position, QChar ch)
const char * name(StandardAction id)
MESSAGECORE_EXPORT QString emailAddrAsAnchor(const QVector< KMime::Types::Mailbox > &mailboxList, Display display=DisplayNameOnly, const QString &cssStyle=QString(), Link link=ShowLink, AddressMode expandable=FullAddresses, const QString &fieldName=QString(), int collapseNumber=4)
Same as the above, only for Mailbox::List types.
virtual QString asUnicodeString() const=0
QString render(Context *c) const
The HeaderStyleUtil class.
QString message
QByteArray & insert(int i, char ch)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:08:17 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.