Messagelib

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

KDE's Doxygen guidelines are available online.