File indexing completed on 2025-03-09 04:54:40

0001 /*
0002     csshelper.cpp
0003 
0004     This file is part of KMail, the KDE mail client.
0005     SPDX-FileCopyrightText: 2003 Marc Mutz <mutz@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "csshelperbase.h"
0011 #include "header/headerstyleplugin.h"
0012 #include "utils/iconnamecache.h"
0013 
0014 #include <QApplication>
0015 #include <QPaintDevice>
0016 #include <QPalette>
0017 #include <QUrl>
0018 
0019 namespace MessageViewer
0020 {
0021 namespace
0022 {
0023 // some QColor manipulators that hide the ugly QColor API w.r.t. HSV:
0024 inline QColor darker(const QColor &c)
0025 {
0026     int h;
0027     int s;
0028     int v;
0029     c.getHsv(&h, &s, &v);
0030     return QColor::fromHsv(h, s, v * 4 / 5);
0031 }
0032 
0033 inline QColor desaturate(const QColor &c)
0034 {
0035     int h;
0036     int s;
0037     int v;
0038     c.getHsv(&h, &s, &v);
0039     return QColor::fromHsv(h, s / 8, v);
0040 }
0041 
0042 inline QColor fixValue(const QColor &c, int newV)
0043 {
0044     int h;
0045     int s;
0046     int v;
0047     c.getHsv(&h, &s, &v);
0048     return QColor::fromHsv(h, s, newV);
0049 }
0050 
0051 inline int getValueOf(const QColor &c)
0052 {
0053     int h;
0054     int s;
0055     int v;
0056     c.getHsv(&h, &s, &v);
0057     return v;
0058 }
0059 
0060 static const struct {
0061     CSSHelperBase::InlineMessageType type;
0062     const char *cssName;
0063 } inlineMessageStyles[] = {{CSSHelperBase::Positive, "inlineMessagePositive"},
0064                            {CSSHelperBase::Information, "inlineMessageInformation"},
0065                            {CSSHelperBase::Warning, "inlineMessageWarning"},
0066                            {CSSHelperBase::Error, "inlineMessageError"}};
0067 }
0068 
0069 CSSHelperBase::CSSHelperBase(const QPaintDevice *pd)
0070     : mPaintDevice(pd)
0071 {
0072     recalculatePGPColors();
0073     const QString imgSrcShow = QStringLiteral("quicklistClosed.png");
0074     const QString imgSrcHide = QStringLiteral("quicklistOpened.png");
0075     imgShowUrl = QUrl::fromLocalFile(MessageViewer::IconNameCache::instance()->iconPathFromLocal(imgSrcShow)).url();
0076     imgHideUrl = QUrl::fromLocalFile(MessageViewer::IconNameCache::instance()->iconPathFromLocal(imgSrcHide)).url();
0077 }
0078 
0079 CSSHelperBase::~CSSHelperBase() = default;
0080 
0081 void CSSHelperBase::recalculatePGPColors()
0082 {
0083     // determine the frame and body color for PGP messages from the header color
0084     // if the header color equals the background color then the other colors are
0085     // also set to the background color (-> old style PGP message viewing)
0086     // else
0087     // the brightness of the frame is set to 4/5 of the brightness of the header
0088     // and in case of a light background color
0089     // the saturation of the body is set to 1/8 of the saturation of the header
0090     // while in case of a dark background color
0091     // the value of the body is set to the value of the background color
0092 
0093     // Check whether the user uses a light color scheme
0094     const int vBG = getValueOf(mBackgroundColor);
0095     const bool lightBG = vBG >= 128;
0096     if (cPgpOk1H == mBackgroundColor) {
0097         cPgpOk1F = mBackgroundColor;
0098         cPgpOk1B = mBackgroundColor;
0099     } else {
0100         cPgpOk1F = darker(cPgpOk1H);
0101         cPgpOk1B = lightBG ? desaturate(cPgpOk1H) : fixValue(cPgpOk1H, vBG);
0102     }
0103     if (cPgpOk0H == mBackgroundColor) {
0104         cPgpOk0F = mBackgroundColor;
0105         cPgpOk0B = mBackgroundColor;
0106     } else {
0107         cPgpOk0F = darker(cPgpOk0H);
0108         cPgpOk0B = lightBG ? desaturate(cPgpOk0H) : fixValue(cPgpOk0H, vBG);
0109     }
0110     if (cPgpWarnH == mBackgroundColor) {
0111         cPgpWarnF = mBackgroundColor;
0112         cPgpWarnB = mBackgroundColor;
0113     } else {
0114         cPgpWarnF = darker(cPgpWarnH);
0115         cPgpWarnB = lightBG ? desaturate(cPgpWarnH) : fixValue(cPgpWarnH, vBG);
0116     }
0117     if (cPgpErrH == mBackgroundColor) {
0118         cPgpErrF = mBackgroundColor;
0119         cPgpErrB = mBackgroundColor;
0120     } else {
0121         cPgpErrF = darker(cPgpErrH);
0122         cPgpErrB = lightBG ? desaturate(cPgpErrH) : fixValue(cPgpErrH, vBG);
0123     }
0124     if (cPgpEncrH == mBackgroundColor) {
0125         cPgpEncrF = mBackgroundColor;
0126         cPgpEncrB = mBackgroundColor;
0127     } else {
0128         cPgpEncrF = darker(cPgpEncrH);
0129         cPgpEncrB = lightBG ? desaturate(cPgpEncrH) : fixValue(cPgpEncrH, vBG);
0130     }
0131 }
0132 
0133 QString CSSHelperBase::addEndBlockQuote(int numberBlock) const
0134 {
0135     QString blockQuote;
0136     for (int i = 0; i < numberBlock; ++i) {
0137         blockQuote += QLatin1StringView("</blockquote>");
0138     }
0139     return blockQuote;
0140 }
0141 
0142 QString CSSHelperBase::addStartBlockQuote(int numberBlock) const
0143 {
0144     QString blockQuote;
0145     for (int i = 0; i < numberBlock; ++i) {
0146         blockQuote += QLatin1StringView("<blockquote>");
0147     }
0148     return blockQuote;
0149 }
0150 
0151 QString CSSHelperBase::extraScreenCss(const QString &headerFont) const
0152 {
0153     if (mHeaderPlugin) {
0154         return mHeaderPlugin->extraScreenCss(headerFont);
0155     }
0156     return {};
0157 }
0158 
0159 QString CSSHelperBase::extraPrintCss(const QString &headerFont) const
0160 {
0161     if (mHeaderPlugin) {
0162         return mHeaderPlugin->extraPrintCss(headerFont);
0163     }
0164     return {};
0165 }
0166 
0167 QString CSSHelperBase::extraCommonCss(const QString &headerFont) const
0168 {
0169     QString result;
0170     if (mHeaderPlugin) {
0171         result = mHeaderPlugin->extraCommonCss(headerFont);
0172     }
0173     if (result.isEmpty()) {
0174         // Add default value
0175         result = QStringLiteral(
0176             "div.header table {\n"
0177             "  width: 100% ! important;\n"
0178             "  border-width: 0px ! important;\n"
0179             "  line-height: normal;\n"
0180             "}\n\n");
0181     }
0182     return result;
0183 }
0184 
0185 QString CSSHelperBase::cssDefinitions(const HtmlHeadSettings &htmlHeadSetting) const
0186 {
0187     return commonCssDefinitions() + QLatin1StringView("@media screen {\n\n") + screenCssDefinitions(this, htmlHeadSetting)
0188         + QLatin1StringView(
0189                "}\n"
0190                "@media print {\n\n")
0191         + printCssDefinitions(htmlHeadSetting) + QLatin1StringView("}\n");
0192 }
0193 
0194 QString CSSHelperBase::htmlHead(const HtmlHeadSettings &htmlHeadSettings) const
0195 {
0196     Q_UNUSED(htmlHeadSettings)
0197     return QStringLiteral(
0198         "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
0199         "<html><head><title></title></head>\n"
0200         "<body>\n");
0201 }
0202 
0203 QString CSSHelperBase::quoteFontTag(int level) const
0204 {
0205     if (level < 0) {
0206         level = 0;
0207     }
0208     static const int numQuoteLevels = 3;
0209     const int effectiveLevel = mRecycleQuoteColors ? level % numQuoteLevels + 1 : qMin(level + 1, numQuoteLevels);
0210     if (level >= numQuoteLevels) {
0211         return QStringLiteral("<div class=\"deepquotelevel%1\">").arg(effectiveLevel);
0212     } else {
0213         return QStringLiteral("<div class=\"quotelevel%1\">").arg(effectiveLevel);
0214     }
0215 }
0216 
0217 QString CSSHelperBase::fullAddressList() const
0218 {
0219     QString css = QStringLiteral(
0220         "input[type=checkbox].addresslist_checkbox {display: none}\n"
0221         ".addresslist_label_short {border: 1px; border-radius: 5px; padding: 0px 10px 0px 10px; white-space: nowrap}\n"
0222         ".addresslist_label_full {border: 1px; border-radius: 5px; padding: 0px 10px 0px 10px; white-space: nowrap}\n");
0223     css += QStringLiteral(".addresslist_label_short {background-image:url(%1);\nbackground-repeat: no-repeat}\n").arg(imgShowUrl);
0224     css += QStringLiteral(".addresslist_label_full {background-image:url(%1);\nbackground-repeat: no-repeat}\n\n").arg(imgHideUrl);
0225     for (const QString &str : {QStringLiteral("Cc"), QStringLiteral("To"), QStringLiteral("Bcc")}) {
0226         css += QStringLiteral(
0227                    "input ~ span.fullFull%1AddressList {display: block}\n"
0228                    "input ~ span.shortFull%1AddressList {display: none}\n"
0229                    "input:checked ~ span.fullFull%1AddressList {display: none}\n"
0230                    "input:checked ~ span.shortFull%1AddressList {display: block}\n\n")
0231                    .arg(str);
0232     }
0233     return css;
0234 }
0235 
0236 QString CSSHelperBase::nonQuotedFontTag() const
0237 {
0238     return QStringLiteral("<div class=\"noquote\">");
0239 }
0240 
0241 QFont CSSHelperBase::bodyFont(bool fixed, bool print) const
0242 {
0243     return fixed ? (print ? mFixedPrintFont : mFixedFont) : (print ? mPrintFont : mBodyFont);
0244 }
0245 
0246 int CSSHelperBase::fontSize(bool fixed, bool print) const
0247 {
0248     return bodyFont(fixed, print).pointSize();
0249 }
0250 
0251 namespace
0252 {
0253 int pointsToPixel(const QPaintDevice *pd, int pointSize)
0254 {
0255     return (pointSize * pd->logicalDpiY() + 36) / 72;
0256 }
0257 }
0258 
0259 void CSSHelperBase::setHeaderPlugin(const HeaderStylePlugin *headerPlugin)
0260 {
0261     mHeaderPlugin = headerPlugin;
0262 }
0263 
0264 static const char *const quoteFontSizes[] = {"85", "80", "75"};
0265 
0266 QString CSSHelperBase::printCssDefinitions(const HtmlHeadSettings &htmlHeadSettings) const
0267 {
0268     const QString headerFont = defaultPrintHeaderFont();
0269 
0270     const QFont printFont = bodyFont(htmlHeadSettings.fixedFont, true /* print */);
0271     QString quoteCSS;
0272     if (printFont.italic()) {
0273         quoteCSS += QLatin1StringView("  font-style: italic ! important;\n");
0274     }
0275     if (printFont.bold()) {
0276         quoteCSS += QLatin1StringView("  font-weight: bold ! important;\n");
0277     }
0278     if (!quoteCSS.isEmpty()) {
0279         quoteCSS = QLatin1StringView("div.noquote {\n") + quoteCSS + QLatin1StringView("}\n\n");
0280     }
0281     quoteCSS += quoteCssDefinition();
0282 
0283     QStringList inlineMessageCss;
0284     inlineMessageCss.reserve(MESSAGE_TYPE_COUNT);
0285     for (const auto &msgStyle : inlineMessageStyles) {
0286         inlineMessageCss.push_back(QLatin1StringView("div.") + QString::fromLatin1(msgStyle.cssName));
0287     }
0288 
0289     return QStringLiteral(
0290                "body {\n"
0291                "  font-family: \"%1\" ! important;\n"
0292                "  font-size: %2pt ! important;\n"
0293                "  color: #000000 ! important;\n"
0294                "  background-color: #ffffff ! important\n"
0295                "}\n\n")
0296                .arg(printFont.family(), QString::number(printFont.pointSize()))
0297         + linkColorDefinition(htmlHeadSettings)
0298         + QStringLiteral(
0299               "tr.textAtmH,\n"
0300               "tr.signInProgressH,\n"
0301               "tr.rfc822H,\n"
0302               "tr.encrH,\n"
0303               "tr.signOkKeyOkH,\n"
0304               "tr.signOkKeyBadH,\n"
0305               "tr.signWarnH,\n"
0306               "tr.signErrH,\n"
0307               "div.header {\n"
0308               "%1"
0309               "}\n\n"
0310 
0311               "%2"
0312 
0313               "div.spamheader {\n"
0314               "  display:none ! important;\n"
0315               "}\n\n"
0316 
0317               "%3 {\n"
0318               "  display:none ! important;\n"
0319               "}\n\n"
0320 
0321               "div.senderpic{\n"
0322               "  font-size:0.8em ! important;\n"
0323               "  border:1px solid black ! important;\n"
0324               "  background-color:%2 ! important;\n"
0325               "}\n\n"
0326 
0327               "div.senderstatus{\n"
0328               "  text-align:center ! important;\n"
0329               "}\n\n"
0330 
0331               "div.noprint {\n"
0332               "  display:none ! important;\n"
0333               "}\n\n")
0334               .arg(headerFont, extraPrintCss(headerFont), inlineMessageCss.join(QLatin1StringView(", ")))
0335         + quoteCSS + fullAddressList();
0336 }
0337 
0338 QString CSSHelperBase::linkColorDefinition(const HtmlHeadSettings &htmlHeadSettings) const
0339 {
0340     const QString linkColor = mLinkColor.name();
0341     if (useBrowserColor(htmlHeadSettings)) {
0342         const QString bgColor = mBackgroundColor.name();
0343         const QString background = QStringLiteral("  background: %1 ! important;\n").arg(bgColor);
0344 
0345         return QStringLiteral(
0346                    "div#headerbox a:link {\n"
0347                    "  color: %1 ! important;\n"
0348                    "  text-decoration: none ! important;\n"
0349                    "}\n\n"
0350                    "div#header a:link {\n"
0351                    "  color: %1 ! important;\n"
0352                    "  text-decoration: none ! important;\n"
0353                    "}\n\n"
0354                    "div.header {\n"
0355                    "    %2"
0356                    "}\n\n"
0357                    "div#headerbox {\n"
0358                    "    %2"
0359                    "}\n\n")
0360             .arg(linkColor, background);
0361     } else {
0362         return QStringLiteral(
0363                    "a {\n"
0364                    "  color: %1 ! important;\n"
0365                    "  text-decoration: none ! important;\n"
0366                    "}\n\n")
0367             .arg(linkColor);
0368     }
0369 }
0370 
0371 QString CSSHelperBase::quoteCssDefinition() const
0372 {
0373     QString quoteCSS;
0374     QString blockQuote;
0375     for (int i = 0; i < 9; ++i) {
0376         blockQuote += QStringLiteral("blockquote ");
0377         quoteCSS += QStringLiteral(
0378                         "%2{\n"
0379                         "  margin: 4pt 0 4pt 0;\n"
0380                         "  padding: 0 0 0 1em;\n"
0381                         "  border-left: 2px solid %1;\n"
0382                         "  unicode-bidi: plaintext\n"
0383                         "}\n\n")
0384                         .arg(quoteColorName(i), blockQuote);
0385     }
0386     quoteCSS += QStringLiteral(
0387         ".quotemarks{\n"
0388         "  color:transparent;\n"
0389         "  font-size:0px;\n"
0390         "}\n\n");
0391     quoteCSS += QStringLiteral(
0392         ".quotemarksemptyline{\n"
0393         "  color:transparent;\n"
0394         "  font-size:0px;\n"
0395         "  line-height: 12pt;\n"
0396         "}\n\n");
0397     return quoteCSS;
0398 }
0399 
0400 QString CSSHelperBase::defaultPrintHeaderFont() const
0401 {
0402     const QString headerFont = QStringLiteral(
0403                                    "  font-family: \"%1\" ! important;\n"
0404                                    "  font-size: %2pt ! important;\n")
0405                                    .arg(mPrintFont.family())
0406                                    .arg(mPrintFont.pointSize());
0407     return headerFont;
0408 }
0409 
0410 QString CSSHelperBase::defaultScreenHeaderFont() const
0411 {
0412     const QString headerFont = QStringLiteral(
0413                                    "  font-family: \"%1\" ! important;\n"
0414                                    "  font-size: %2px ! important;\n")
0415                                    .arg(mBodyFont.family())
0416                                    .arg(pointsToPixel(mPaintDevice, mBodyFont.pointSize()));
0417     return headerFont;
0418 }
0419 
0420 bool CSSHelperBase::useBrowserColor(const HtmlHeadSettings &htmlHeadSettings) const
0421 {
0422     return mUseBrowserColor && htmlHeadSettings.htmlFormat;
0423 }
0424 
0425 QString CSSHelperBase::screenCssDefinitions(const CSSHelperBase *helper, const HtmlHeadSettings &htmlHeadSettings) const
0426 {
0427     const QString bgColor = mBackgroundColor.name();
0428     const QString headerFont = defaultScreenHeaderFont();
0429     const QString fgColor = useBrowserColor(htmlHeadSettings) ? QStringLiteral("black") : mForegroundColor.name();
0430     const QString background = useBrowserColor(htmlHeadSettings) ? QString() : QStringLiteral("  background-color: %1 ! important;\n").arg(bgColor);
0431     const QString signWarnBColorName = useBrowserColor(htmlHeadSettings) ? QStringLiteral("white") : cPgpWarnB.name();
0432     const QString cPgpErrBColorName = useBrowserColor(htmlHeadSettings) ? QStringLiteral("white") : cPgpErrB.name();
0433     const QString cPgpEncrBColorName = useBrowserColor(htmlHeadSettings) ? QStringLiteral("white") : cPgpEncrB.name();
0434     const QString cPgpOk1BColorName = useBrowserColor(htmlHeadSettings) ? QStringLiteral("white") : cPgpOk1B.name();
0435     const QString cPgpOk0BColorName = useBrowserColor(htmlHeadSettings) ? QStringLiteral("white") : cPgpOk0B.name();
0436     const QString bodyFontSize = QString::number(pointsToPixel(helper->mPaintDevice, fontSize(htmlHeadSettings.fixedFont))) + QLatin1StringView("px");
0437     const QPalette &pal = QApplication::palette();
0438 
0439     QString quoteCSS;
0440     if (bodyFont(htmlHeadSettings.fixedFont).italic()) {
0441         quoteCSS += QLatin1StringView("  font-style: italic ! important;\n");
0442     }
0443     if (bodyFont(htmlHeadSettings.fixedFont).bold()) {
0444         quoteCSS += QLatin1StringView("  font-weight: bold ! important;\n");
0445     }
0446     if (!quoteCSS.isEmpty()) {
0447         quoteCSS = QLatin1StringView("div.noquote {\n") + quoteCSS + QLatin1StringView("}\n\n");
0448     }
0449 
0450     // CSS definitions for quote levels 1-3
0451     for (int i = 0; i < 3; ++i) {
0452         quoteCSS += QStringLiteral(
0453                         "div.quotelevel%1 {\n"
0454                         "  color: %2 ! important;\n")
0455                         .arg(QString::number(i + 1), quoteColorName(i));
0456         if (mQuoteFont.italic()) {
0457             quoteCSS += QStringLiteral("  font-style: italic ! important;\n");
0458         }
0459         if (mQuoteFont.bold()) {
0460             quoteCSS += QStringLiteral("  font-weight: bold ! important;\n");
0461         }
0462         if (mShrinkQuotes) {
0463             quoteCSS += QLatin1StringView("  font-size: ") + QString::fromLatin1(quoteFontSizes[i]) + QLatin1StringView("% ! important;\n");
0464         }
0465         quoteCSS += QStringLiteral("}\n\n");
0466     }
0467 
0468     // CSS definitions for quote levels 4+
0469     for (int i = 0; i < 3; ++i) {
0470         quoteCSS += QStringLiteral(
0471                         "div.deepquotelevel%1 {\n"
0472                         "  color: %2 ! important;\n")
0473                         .arg(QString::number(i + 1), quoteColorName(i));
0474         if (mQuoteFont.italic()) {
0475             quoteCSS += QStringLiteral("  font-style: italic ! important;\n");
0476         }
0477         if (mQuoteFont.bold()) {
0478             quoteCSS += QStringLiteral("  font-weight: bold ! important;\n");
0479         }
0480         if (mShrinkQuotes) {
0481             quoteCSS += QStringLiteral("  font-size: 70% ! important;\n");
0482         }
0483         quoteCSS += QLatin1StringView("}\n\n");
0484     }
0485 
0486     quoteCSS += quoteCssDefinition();
0487 
0488     // CSS definitions for inline message boxes
0489     QString inlineMessageCss;
0490     for (const auto &msgStyle : inlineMessageStyles) {
0491         const auto c = cInlineMessage[msgStyle.type];
0492         inlineMessageCss += QStringLiteral(
0493                                 R"(
0494             div.%1 {
0495                 border: 1px solid rgba(%2, %3, %4) ! important;
0496                 border-radius: 2px;
0497                 box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.5);
0498                 background-color: rgba(%2, %3, %4, 0.2) ! important;
0499             }
0500             div.%1 a:link {
0501                 color: %5 ! important;
0502                 text-decoration: none ! important;
0503             }
0504          )")
0505                                 .arg(QString::fromLatin1(msgStyle.cssName))
0506                                 .arg(c.red())
0507                                 .arg(c.green())
0508                                 .arg(c.blue())
0509                                 .arg(mLinkColor.name());
0510     }
0511 
0512     const auto scrollBarCss = QStringLiteral(
0513         "html::-webkit-scrollbar {\n"
0514         "  /* we'll add padding as \"border\" in the thumb*/\n"
0515         "    height: 20px;\n"
0516         "    width: 20px;\n"
0517         "    background: white;\n"
0518         "    border-left: 1px solid #e5e5e5;\n"
0519         "    padding-left: 1px;\n"
0520         "}\n\n"
0521 
0522         "html::-webkit-scrollbar-track {\n"
0523         "    border-radius: 20px;\n"
0524         "    width: 6px !important;\n"
0525         "    box-sizing: content-box;\n"
0526         "}\n\n"
0527 
0528         "html::-webkit-scrollbar-thumb {\n"
0529         "    background-color: #CBCDCD;\n"
0530         "    border: 6px solid transparent;\n"
0531         "    border-radius: 20px;\n"
0532         "    background-clip: content-box;\n"
0533         "    width: 8px !important; /* 20px scrollbar - 2 * 6px border */\n"
0534         "    box-sizing: content-box;\n"
0535         "    min-height: 30px;\n"
0536         "}\n\n"
0537 
0538         "html::-webkit-scrollbar-thumb:window-inactive {\n"
0539         "   background-color: #949699; /* when window is inactive it's gray */\n"
0540         "}\n\n"
0541 
0542         "html::-webkit-scrollbar-thumb:hover {\n"
0543         "    background-color: #93CEE9; /* hovered is a lighter blue */\n"
0544         "}\n\n"
0545 
0546         "html::-webkit-scrollbar-corner {\n"
0547         "    background-color: white;\n"
0548         "}\n\n");
0549 
0550     return QStringLiteral(
0551                "body {\n"
0552                "  font-family: \"%1\" ! important;\n"
0553                "  font-size: %2 ! important;\n"
0554                "  color: %3 ! important;\n"
0555                "%4"
0556                "}\n\n")
0557                .arg(bodyFont(htmlHeadSettings.fixedFont).family(), bodyFontSize, fgColor, background)
0558         + linkColorDefinition(htmlHeadSettings)
0559         + QStringLiteral(
0560               "a.white {\n"
0561               "  color: white ! important;\n"
0562               "}\n\n"
0563 
0564               "a.black {\n"
0565               "  color: black ! important;\n"
0566               "}\n\n"
0567 
0568               "table.textAtm { background-color: %1 ! important; }\n\n"
0569 
0570               "tr.textAtmH {\n"
0571               "  background-color: %2 ! important;\n"
0572               "%3"
0573               "}\n\n"
0574 
0575               "tr.textAtmB {\n"
0576               "  background-color: %2 ! important;\n"
0577               "}\n\n"
0578 
0579               "table.signInProgress,\n"
0580               "table.rfc822 {\n"
0581               "  background-color: %2 ! important;\n"
0582               "}\n\n"
0583 
0584               "tr.signInProgressH,\n"
0585               "tr.rfc822H {\n"
0586               "%3"
0587               "}\n\n")
0588               .arg(fgColor, bgColor, headerFont)
0589         + QStringLiteral(
0590               "table.encr {\n"
0591               "  background-color: %1 ! important;\n"
0592               "}\n\n"
0593 
0594               "tr.encrH {\n"
0595               "  background-color: %2 ! important;\n"
0596               "  color: %3 ! important;\n"
0597               "%4"
0598               "}\n\n"
0599 
0600               "tr.encrB { background-color: %5 ! important; }\n\n")
0601               .arg(cPgpEncrF.name(), cPgpEncrH.name(), cPgpEncrHT.name(), headerFont, cPgpEncrBColorName)
0602         + QStringLiteral(
0603               "table.signOkKeyOk {\n"
0604               "  background-color: %1 ! important;\n"
0605               "}\n\n"
0606 
0607               "tr.signOkKeyOkH {\n"
0608               "  background-color: %2 ! important;\n"
0609               "  color: %3 ! important;\n"
0610               "%4"
0611               "}\n\n"
0612 
0613               "tr.signOkKeyOkB { background-color: %5 ! important; }\n\n")
0614               .arg(cPgpOk1F.name(), cPgpOk1H.name(), cPgpOk1HT.name(), headerFont, cPgpOk1BColorName)
0615         + QStringLiteral(
0616               "table.signOkKeyBad {\n"
0617               "  background-color: %1 ! important;\n"
0618               "}\n\n"
0619 
0620               "tr.signOkKeyBadH {\n"
0621               "  background-color: %2 ! important;\n"
0622               "  color: %3 ! important;\n"
0623               "%4"
0624               "}\n\n"
0625 
0626               "tr.signOkKeyBadB { background-color: %5 ! important; }\n\n")
0627               .arg(cPgpOk0F.name(), cPgpOk0H.name(), cPgpOk0HT.name(), headerFont, cPgpOk0BColorName)
0628         + QStringLiteral(
0629               "table.signWarn {\n"
0630               "  background-color: %1 ! important;\n"
0631               "}\n\n"
0632 
0633               "tr.signWarnH {\n"
0634               "  background-color: %2 ! important;\n"
0635               "  color: %3 ! important;\n"
0636               "%4"
0637               "}\n\n"
0638 
0639               "tr.signWarnB { background-color: %5 ! important; }\n\n")
0640               .arg(cPgpWarnF.name(), cPgpWarnH.name(), cPgpWarnHT.name(), headerFont, signWarnBColorName)
0641         + QStringLiteral(
0642               "table.signErr {\n"
0643               "  background-color: %1 ! important;\n"
0644               "}\n\n"
0645 
0646               "tr.signErrH {\n"
0647               "  background-color: %2 ! important;\n"
0648               "  color: %3 ! important;\n"
0649               "%4"
0650               "}\n\n"
0651 
0652               "tr.signErrB { background-color: %5 ! important; }\n\n")
0653               .arg(cPgpErrF.name(), cPgpErrH.name(), cPgpErrHT.name(), headerFont, cPgpErrBColorName)
0654         + inlineMessageCss
0655         + QStringLiteral(
0656               "div.header {\n"
0657               "%1"
0658               "}\n\n"
0659 
0660               "%2"
0661 
0662               "%3"
0663 
0664               "div.senderpic{\n"
0665               "  padding: 0px ! important;\n"
0666               "  font-size:0.8em ! important;\n"
0667               "  border:1px solid %5 ! important;\n"
0668               "  background-color:%4 ! important;\n"
0669               "}\n\n"
0670 
0671               "div.senderstatus{\n"
0672               "  text-align:center ! important;\n"
0673               "}\n\n")
0674 
0675               .arg(headerFont, scrollBarCss, extraScreenCss(headerFont), pal.color(QPalette::Highlight).name(), pal.color(QPalette::Window).name())
0676         + quoteCSS + fullAddressList();
0677 }
0678 
0679 QString CSSHelperBase::commonCssDefinitions() const
0680 {
0681     const QString headerFont = defaultScreenHeaderFont();
0682 
0683     QStringList inlineMessageCss;
0684     inlineMessageCss.reserve(MESSAGE_TYPE_COUNT);
0685     for (const auto &msgStyle : inlineMessageStyles) {
0686         inlineMessageCss.push_back(QLatin1StringView("div.") + QString::fromLatin1(msgStyle.cssName));
0687     }
0688     return QStringLiteral(
0689                "div.header {\n"
0690                "  margin-bottom: 10pt ! important;\n"
0691                "}\n\n"
0692 
0693                "pre.highlightattachment {\n"
0694                "  white-space: pre-wrap;\n"
0695                "}\n\n"
0696 
0697                "table.textAtm {\n"
0698                "  margin-top: 10pt ! important;\n"
0699                "  margin-bottom: 10pt ! important;\n"
0700                "}\n\n"
0701 
0702                "tr.textAtmH,\n"
0703                "tr.textAtmB,\n"
0704                "tr.rfc822B {\n"
0705                "  font-weight: normal ! important;\n"
0706                "}\n\n"
0707 
0708                "tr.signInProgressH,\n"
0709                "tr.rfc822H,\n"
0710                "tr.encrH,\n"
0711                "tr.signOkKeyOkH,\n"
0712                "tr.signOkKeyBadH,\n"
0713                "tr.signWarnH,\n"
0714                "tr.signErrH {\n"
0715                "  font-weight: bold ! important;\n"
0716                "}\n\n"
0717 
0718                "tr.textAtmH td,\n"
0719                "tr.textAtmB td {\n"
0720                "  padding: 3px ! important;\n"
0721                "}\n\n"
0722 
0723                "table.rfc822 {\n"
0724                "  width: 100% ! important;\n"
0725                "  border: solid 1px black ! important;\n"
0726                "  margin-top: 10pt ! important;\n"
0727                "  margin-bottom: 10pt ! important;\n"
0728                "}\n\n"
0729 
0730                "table.textAtm,\n"
0731                "table.encr,\n"
0732                "table.signWarn,\n"
0733                "table.signErr,\n"
0734                "table.signOkKeyBad,\n"
0735                "table.signOkKeyOk,\n"
0736                "table.signInProgress,\n"
0737 
0738                "%1"
0739 
0740                "%2 {\n"
0741                "  margin: 0px 5% 10px 5% ! important;\n"
0742                "  padding: 10px ! important;\n"
0743                "  text-align: left ! important;\n"
0744                "  line-height: normal;\n"
0745                "  min-height: %6px;\n"
0746                "}\n\n"
0747 
0748                "hr {\n"
0749                "  border: 0;\n"
0750                "  height: 0;\n"
0751                "  border-top: 1px solid rgba(%3, %4, %5, 0.3);\n"
0752                "}\n\n"
0753 
0754                "div.quotelevelmark {\n"
0755                "  position: absolute;\n"
0756                "  margin-left:-10px;\n"
0757                "}\n\n")
0758         .arg(extraCommonCss(headerFont))
0759         .arg(inlineMessageCss.join(QLatin1StringView(", ")))
0760         .arg(mForegroundColor.red())
0761         .arg(mForegroundColor.green())
0762         .arg(mForegroundColor.blue())
0763         .arg(QString::number(48));
0764 }
0765 
0766 void CSSHelperBase::setBodyFont(const QFont &font)
0767 {
0768     mBodyFont = font;
0769 }
0770 
0771 void CSSHelperBase::setPrintFont(const QFont &font)
0772 {
0773     mPrintFont = font;
0774 }
0775 
0776 QString CSSHelperBase::quoteColorName(int level) const
0777 {
0778     return quoteColor(level).name();
0779 }
0780 
0781 QColor CSSHelperBase::quoteColor(int level) const
0782 {
0783     const int actualLevel = qMax(level, 0) % 3;
0784     return mQuoteColor[actualLevel];
0785 }
0786 
0787 QColor CSSHelperBase::pgpWarnColor() const
0788 {
0789     return cPgpWarnH;
0790 }
0791 }