diff --git a/messageviewer/src/messagepartthemes/default/autotests/testcsshelper.cpp b/messageviewer/src/messagepartthemes/default/autotests/testcsshelper.cpp index b83f8257..e5e0acd9 100644 --- a/messageviewer/src/messagepartthemes/default/autotests/testcsshelper.cpp +++ b/messageviewer/src/messagepartthemes/default/autotests/testcsshelper.cpp @@ -1,87 +1,91 @@ /* Copyright (c) 2013 Sandro Knauß 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 "testcsshelper.h" #include #include #include #include using namespace MessageViewer::Test; TestCSSHelper::TestCSSHelper(const QPaintDevice *pd) : MessageViewer::CSSHelper(pd) { mRecycleQuoteColors = false; mBackgroundColor = QColor(0xff, 0xff, 0xff); mForegroundColor = QColor(0x1f, 0x1c, 0x1b); mLinkColor = QColor(0x00, 0x57, 0xae); cPgpEncrH = QColor(0x00, 0x80, 0xff); cPgpOk1H = QColor(0x40, 0xff, 0x40); cPgpOk0H = QColor(0xff, 0xff, 0x40); cPgpWarnH = QColor(0xff, 0xff, 0x40); cPgpErrH = QColor(0xff, 0x00, 0x00); cPgpEncrHT = QColor(0xff, 0xff, 0xff); cPgpOk1HT = QColor(0x27, 0xae, 0x60); cPgpOk0HT = QColor(0xf6, 0x74, 0x00); cPgpWarnHT = QColor(0xf6, 0x74, 0x00); cPgpErrHT = QColor(0xda, 0x44, 0x53); - cHtmlWarning = QColor(0xff, 0x40, 0x40); + cInlineMessage[Positive] = QColor(0, 255, 0); + cInlineMessage[Information] = QColor(0, 0, 255); + cInlineMessage[Warning] = QColor(255, 255, 0); + cInlineMessage[Error] = QColor(255, 0, 0); + for (int i = 0; i < 3; ++i) { mQuoteColor[i] = QColor(0x00, 0x80 - i * 0x10, 0x00); } QFont defaultFont = QFont(QStringLiteral("Sans Serif"), 9); mBodyFont = defaultFont; mPrintFont = defaultFont; mFixedFont = defaultFont; mFixedPrintFont = defaultFont; defaultFont.setItalic(true); mQuoteFont = defaultFont; mShrinkQuotes = false; QPalette pal; pal.setColor(QPalette::Window, QColor(0xd6, 0xd2, 0xd0)); pal.setColor(QPalette::WindowText, QColor(0x22, 0x1f, 0x1e)); pal.setColor(QPalette::Highlight, QColor(0x43, 0xac, 0xe8)); pal.setColor(QPalette::HighlightedText, QColor(0xff, 0xff, 0xff)); pal.setColor(QPalette::Mid, QColor(0xb3, 0xab, 0xa7)); QApplication::setPalette(pal); recalculatePGPColors(); } TestCSSHelper::~TestCSSHelper() { } QString TestCSSHelper::htmlHead(bool fixed) const { Q_UNUSED(fixed); return QStringLiteral("\n" "\n" "\n"); } diff --git a/messageviewer/src/messagepartthemes/default/templates/htmlmessagepart.html b/messageviewer/src/messagepartthemes/default/templates/htmlmessagepart.html index f10c856d..5248d665 100644 --- a/messageviewer/src/messagepartthemes/default/templates/htmlmessagepart.html +++ b/messageviewer/src/messagepartthemes/default/templates/htmlmessagepart.html @@ -1,22 +1,22 @@ {% if not block.isPrinting %} {% if not block.htmlMail or not block.loadExternal and block.containsExternalReferences %} -
+
{% if not block.htmlMail %} {% i18n_var "Note: This is an HTML message. For security reasons, only the raw HTML code is shown. If you trust the sender of this message then you can activate formatted HTML display for this message by clicking here." as msg %} {% elif not block.loadExternal and block.containsExternalReferences %} {% i18n_var "Note: This HTML message may contain external references to images etc. For security/privacy reasons external references are not loaded. If you trust the sender of this message then you can load the external references for this message by clicking here." as msg %} {% endif %} {{ msg|safe }}


{% endif %} {% endif %} {% if not block.htmlMail %} {{ plaintext|safe }} {% else %}
{{ content|safe }}
{% endif %} diff --git a/messageviewer/src/viewer/csshelper.cpp b/messageviewer/src/viewer/csshelper.cpp index 67a85211..6d7382a3 100644 --- a/messageviewer/src/viewer/csshelper.cpp +++ b/messageviewer/src/viewer/csshelper.cpp @@ -1,141 +1,153 @@ /* csshelper.cpp This file is part of KMail, the KDE mail client. Copyright (c) 2003 Marc Mutz KMail is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KMail 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA In addition, as a special exception, the copyright holders give permission to link the code of this program with any edition of the Qt library by Trolltech AS, Norway (or with modified versions of Qt that use the same license as Qt), and distribute linked combinations including the two. You must obey the GNU General Public License in all respects for all of the code used other than Qt. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ #include "csshelper.h" #include "settings/messageviewersettings.h" #include "MessageCore/MessageCoreSettings" #include #include #include #include #include #include #include #include using namespace MessageViewer; +static const struct { + CSSHelperBase::InlineMessageType type; + KColorScheme::ForegroundRole role; +} inlineMessageColors[] = { + { CSSHelperBase::Positive, KColorScheme::PositiveText }, + { CSSHelperBase::Information, KColorScheme::ActiveText }, + { CSSHelperBase::Warning, KColorScheme::NeutralText }, + { CSSHelperBase::Error, KColorScheme::NegativeText } +}; + CSSHelper::CSSHelper(const QPaintDevice *pd) : CSSHelperBase(pd) { // initialize with defaults - should match the corresponding application defaults mForegroundColor = QApplication::palette().color(QPalette::Text); mLinkColor = MessageCore::ColorUtil::self()->linkColor(); mBackgroundColor = QApplication::palette().color(QPalette::Base); - cHtmlWarning = QColor(0xFF, 0x40, 0x40); // warning frame color: light red + for (const auto &msgColor : inlineMessageColors) { + cInlineMessage[msgColor.type] = KColorScheme(QPalette::Active).foreground(msgColor.role).color(); + } cPgpEncrH = MessageCore::ColorUtil::self()->pgpEncryptedMessageColor(); cPgpEncrHT = MessageCore::ColorUtil::self()->pgpEncryptedTextColor(); cPgpOk1H = MessageCore::ColorUtil::self()->pgpSignedTrustedMessageColor(); cPgpOk1HT = MessageCore::ColorUtil::self()->pgpSignedTrustedTextColor(); cPgpOk0H = MessageCore::ColorUtil::self()->pgpSignedUntrustedMessageColor(); cPgpOk0HT = MessageCore::ColorUtil::self()->pgpSignedUntrustedTextColor(); cPgpWarnH = MessageCore::ColorUtil::self()->pgpSignedUntrustedMessageColor(); cPgpWarnHT = MessageCore::ColorUtil::self()->pgpSignedUntrustedTextColor(); cPgpErrH = MessageCore::ColorUtil::self()->pgpSignedBadMessageColor(); cPgpErrHT = MessageCore::ColorUtil::self()->pgpSignedBadTextColor(); mRecycleQuoteColors = false; QFont defaultFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); QFont defaultFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); mBodyFont = MessageCore::MessageCoreSettings::self()->useDefaultFonts() ? defaultFont : MessageViewer :: MessageViewerSettings::self()->bodyFont(); mPrintFont = MessageCore::MessageCoreSettings::self()->useDefaultFonts() ? defaultFont : MessageViewer :: MessageViewerSettings::self()->printFont(); mFixedFont = mFixedPrintFont = defaultFixedFont; defaultFont.setItalic(true); mQuoteFont = defaultFont; KConfig *config = MessageViewer::MessageViewerSettings::self()->config(); KConfigGroup reader(config, "Reader"); KConfigGroup fonts(config, "Fonts"); mRecycleQuoteColors = reader.readEntry("RecycleQuoteColors", false); mForegroundColor = KColorScheme(QPalette::Active).foreground().color(); if (MessageCore::MessageCoreSettings::self()->useDefaultColors()) { mQuoteColor[0] = MessageCore::ColorUtil::self()->quoteLevel1DefaultTextColor(); mQuoteColor[1] = MessageCore::ColorUtil::self()->quoteLevel2DefaultTextColor(); mQuoteColor[2] = MessageCore::ColorUtil::self()->quoteLevel3DefaultTextColor(); } else { mLinkColor = reader.readEntry("LinkColor", mLinkColor); cPgpEncrH = reader.readEntry("PGPMessageEncr", cPgpEncrH); cPgpOk1H = reader.readEntry("PGPMessageOkKeyOk", cPgpOk1H); cPgpOk0H = reader.readEntry("PGPMessageOkKeyBad", cPgpOk0H); cPgpWarnH = reader.readEntry("PGPMessageWarn", cPgpWarnH); cPgpErrH = reader.readEntry("PGPMessageErr", cPgpErrH); mQuoteColor[0] = MessageCore::MessageCoreSettings::self()->quotedText1(); mQuoteColor[1] = MessageCore::MessageCoreSettings::self()->quotedText2(); mQuoteColor[2] = MessageCore::MessageCoreSettings::self()->quotedText3(); } if (!MessageCore::MessageCoreSettings::self()->useDefaultFonts()) { mBodyFont = fonts.readEntry("body-font", mBodyFont); mPrintFont = fonts.readEntry("print-font", mPrintFont); mFixedFont = fonts.readEntry("fixed-font", mFixedFont); mFixedPrintFont = mFixedFont; } mShrinkQuotes = MessageViewer::MessageViewerSettings::self()->shrinkQuotes(); mUseBrowserColor = MessageCore::MessageCoreSettings::self()->useRealHtmlMailColor(); recalculatePGPColors(); } CSSHelper::~CSSHelper() { } QString CSSHelper::htmlHead(bool fixed) const { return QLatin1String("\n" "\n" "\n"); } diff --git a/messageviewer/src/viewer/csshelperbase.cpp b/messageviewer/src/viewer/csshelperbase.cpp index ba0e196e..0e720a56 100644 --- a/messageviewer/src/viewer/csshelperbase.cpp +++ b/messageviewer/src/viewer/csshelperbase.cpp @@ -1,759 +1,795 @@ /* csshelper.cpp This file is part of KMail, the KDE mail client. Copyright (c) 2003 Marc Mutz KMail is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KMail 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA In addition, as a special exception, the copyright holders give permission to link the code of this program with any edition of the Qt library by Trolltech AS, Norway (or with modified versions of Qt that use the same license as Qt), and distribute linked combinations including the two. You must obey the GNU General Public License in all respects for all of the code used other than Qt. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ #include "csshelperbase.h" #include "header/headerstyleplugin.h" #include "utils/iconnamecache.h" #include #include #include #include #define USE_HTML_STYLE_COLOR 1 namespace MessageViewer { namespace { // some QColor manipulators that hide the ugly QColor API w.r.t. HSV: inline QColor darker(const QColor &c) { int h, s, v; c.getHsv(&h, &s, &v); return QColor::fromHsv(h, s, v * 4 / 5); } inline QColor desaturate(const QColor &c) { int h, s, v; c.getHsv(&h, &s, &v); return QColor::fromHsv(h, s / 8, v); } inline QColor fixValue(const QColor &c, int newV) { int h, s, v; c.getHsv(&h, &s, &v); return QColor::fromHsv(h, s, newV); } inline int getValueOf(const QColor &c) { int h, s, v; c.getHsv(&h, &s, &v); return v; } + +static const struct { + CSSHelperBase::InlineMessageType type; + const char *cssName; +} inlineMessageStyles[] = { + { CSSHelperBase::Positive, "inlineMessagePositive" }, + { CSSHelperBase::Information, "inlineMessageInformation" }, + { CSSHelperBase::Warning, "inlineMessageWarning" }, + { CSSHelperBase::Error, "inlineMessageError" } +}; + } CSSHelperBase::CSSHelperBase(const QPaintDevice *pd) : mRecycleQuoteColors(false) , mShrinkQuotes(false) - , cHtmlWarning(QColor(0xFF, 0x40, 0x40)) , mPaintDevice(pd) { recalculatePGPColors(); const QString imgSrcShow = QStringLiteral("quicklistClosed.png"); const QString imgSrcHide = QStringLiteral("quicklistOpened.png"); imgShowUrl = QUrl::fromLocalFile(MessageViewer::IconNameCache::instance()->iconPathFromLocal(imgSrcShow)).url(); imgHideUrl = QUrl::fromLocalFile(MessageViewer::IconNameCache::instance()->iconPathFromLocal(imgSrcHide)).url(); } CSSHelperBase::~CSSHelperBase() { } void CSSHelperBase::recalculatePGPColors() { // determine the frame and body color for PGP messages from the header color // if the header color equals the background color then the other colors are // also set to the background color (-> old style PGP message viewing) // else // the brightness of the frame is set to 4/5 of the brightness of the header // and in case of a light background color // the saturation of the body is set to 1/8 of the saturation of the header // while in case of a dark background color // the value of the body is set to the value of the background color // Check whether the user uses a light color scheme const int vBG = getValueOf(mBackgroundColor); const bool lightBG = vBG >= 128; if (cPgpOk1H == mBackgroundColor) { cPgpOk1F = mBackgroundColor; cPgpOk1B = mBackgroundColor; } else { cPgpOk1F = darker(cPgpOk1H); cPgpOk1B = lightBG ? desaturate(cPgpOk1H) : fixValue(cPgpOk1H, vBG); } if (cPgpOk0H == mBackgroundColor) { cPgpOk0F = mBackgroundColor; cPgpOk0B = mBackgroundColor; } else { cPgpOk0F = darker(cPgpOk0H); cPgpOk0B = lightBG ? desaturate(cPgpOk0H) : fixValue(cPgpOk0H, vBG); } if (cPgpWarnH == mBackgroundColor) { cPgpWarnF = mBackgroundColor; cPgpWarnB = mBackgroundColor; } else { cPgpWarnF = darker(cPgpWarnH); cPgpWarnB = lightBG ? desaturate(cPgpWarnH) : fixValue(cPgpWarnH, vBG); } if (cPgpErrH == mBackgroundColor) { cPgpErrF = mBackgroundColor; cPgpErrB = mBackgroundColor; } else { cPgpErrF = darker(cPgpErrH); cPgpErrB = lightBG ? desaturate(cPgpErrH) : fixValue(cPgpErrH, vBG); } if (cPgpEncrH == mBackgroundColor) { cPgpEncrF = mBackgroundColor; cPgpEncrB = mBackgroundColor; } else { cPgpEncrF = darker(cPgpEncrH); cPgpEncrB = lightBG ? desaturate(cPgpEncrH) : fixValue(cPgpEncrH, vBG); } } QString CSSHelperBase::addEndBlockQuote(int numberBlock) const { QString blockQuote; for (int i = 0; i < numberBlock; ++i) { blockQuote += QLatin1String(""); } return blockQuote; } QString CSSHelperBase::addStartBlockQuote(int numberBlock) const { QString blockQuote; for (int i = 0; i < numberBlock; ++i) { blockQuote += QLatin1String("
"); } return blockQuote; } QString CSSHelperBase::extraScreenCss(const QString &headerFont) const { if (mHeaderPlugin) { return mHeaderPlugin->extraScreenCss(headerFont); } return {}; } QString CSSHelperBase::extraPrintCss(const QString &headerFont) const { if (mHeaderPlugin) { return mHeaderPlugin->extraPrintCss(headerFont); } return {}; } QString CSSHelperBase::extraCommonCss(const QString &headerFont) const { QString result; if (mHeaderPlugin) { result = mHeaderPlugin->extraCommonCss(headerFont); if (result.isEmpty()) { //Add default value result = QStringLiteral("div.header table {\n" " width: 100% ! important;\n" " border-width: 0px ! important;\n" " line-height: normal;\n" "}\n\n"); } } return result; } QString CSSHelperBase::cssDefinitions(bool fixed) const { return commonCssDefinitions() + QLatin1String("@media screen {\n\n") + screenCssDefinitions(this, fixed) + QLatin1String("}\n" "@media print {\n\n") + printCssDefinitions(fixed) + QLatin1String("}\n"); } QString CSSHelperBase::htmlHead(bool fixedFont) const { Q_UNUSED(fixedFont); return QStringLiteral("\n" "\n" "\n"); } QString CSSHelperBase::quoteFontTag(int level) const { if (level < 0) { level = 0; } static const int numQuoteLevels = 3; const int effectiveLevel = mRecycleQuoteColors ? level % numQuoteLevels + 1 : qMin(level + 1, numQuoteLevels); if (level >= numQuoteLevels) { return QStringLiteral("
").arg(effectiveLevel); } else { return QStringLiteral("
").arg(effectiveLevel); } } QString CSSHelperBase::fullAddressList() const { QString css = QStringLiteral("input[type=checkbox].addresslist_checkbox {display: none}\n" ".addresslist_label_short {border: 1px; border-radius: 5px; padding: 0px 10px 0px 10px; white-space: nowrap}\n" ".addresslist_label_full {border: 1px; border-radius: 5px; padding: 0px 10px 0px 10px; white-space: nowrap}\n"); css += QStringLiteral(".addresslist_label_short {background-image:url(%1);\nbackground-repeat: no-repeat}\n").arg(imgShowUrl); css += QStringLiteral(".addresslist_label_full {background-image:url(%1);\nbackground-repeat: no-repeat}\n\n").arg(imgHideUrl); for (const QString &str : {QStringLiteral("Cc"), QStringLiteral("To"), QStringLiteral("Bcc")}) { css += QStringLiteral("input ~ span.fullFull%1AddressList {display: block}\n" "input ~ span.shortFull%1AddressList {display: none}\n" "input:checked ~ span.fullFull%1AddressList {display: none}\n" "input:checked ~ span.shortFull%1AddressList {display: block}\n\n").arg(str); } return css; } QString CSSHelperBase::nonQuotedFontTag() const { return QStringLiteral("
"); } QFont CSSHelperBase::bodyFont(bool fixed, bool print) const { return fixed ? (print ? mFixedPrintFont : mFixedFont) : (print ? mPrintFont : mBodyFont); } int CSSHelperBase::fontSize(bool fixed, bool print) const { return bodyFont(fixed, print).pointSize(); } namespace { int pointsToPixel(const QPaintDevice *pd, int pointSize) { return (pointSize * pd->logicalDpiY() + 36) / 72; } } void CSSHelperBase::setHeaderPlugin(const HeaderStylePlugin *headerPlugin) { mHeaderPlugin = headerPlugin; } static const char *const quoteFontSizes[] = { "85", "80", "75" }; QString CSSHelperBase::printCssDefinitions(bool fixed) const { const QString headerFont = defaultPrintHeaderFont(); const QFont printFont = bodyFont(fixed, true /* print */); QString quoteCSS; if (printFont.italic()) { quoteCSS += QLatin1String(" font-style: italic ! important;\n"); } if (printFont.bold()) { quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); } if (!quoteCSS.isEmpty()) { quoteCSS = QLatin1String("div.noquote {\n") + quoteCSS + QLatin1String("}\n\n"); } quoteCSS += quoteCssDefinition(); + QStringList inlineMessageCss; + inlineMessageCss.reserve(MESSAGE_TYPE_COUNT); + for (const auto &msgStyle : inlineMessageStyles) { + inlineMessageCss.push_back(QLatin1String("div.") + QString::fromLatin1(msgStyle.cssName)); + } + return QStringLiteral("body {\n" " font-family: \"%1\" ! important;\n" " font-size: %2pt ! important;\n" " color: #000000 ! important;\n" " background-color: #ffffff ! important\n" "}\n\n") .arg(printFont.family(), QString::number(printFont.pointSize())) + linkColorDefinition() +QStringLiteral( "tr.textAtmH,\n" "tr.signInProgressH,\n" "tr.rfc822H,\n" "tr.encrH,\n" "tr.signOkKeyOkH,\n" "tr.signOkKeyBadH,\n" "tr.signWarnH,\n" "tr.signErrH,\n" "div.header {\n" "%1" "}\n\n" "%2" "div.spamheader {\n" " display:none ! important;\n" "}\n\n" - "div.htmlWarn {\n" + "%3 {\n" " border: 2px solid #ffffff ! important;\n" " line-height: normal;\n" "}\n\n" "div.senderpic{\n" " font-size:0.8em ! important;\n" " border:1px solid black ! important;\n" " background-color:%2 ! important;\n" "}\n\n" "div.senderstatus{\n" " text-align:center ! important;\n" "}\n\n" "div.noprint {\n" " display:none ! important;\n" "}\n\n" ) - .arg(headerFont, extraPrintCss(headerFont)) + .arg(headerFont, extraPrintCss(headerFont), inlineMessageCss.join(QLatin1String(", "))) + quoteCSS + fullAddressList(); } QString CSSHelperBase::linkColorDefinition() const { const QString linkColor = mLinkColor.name(); if (mUseBrowserColor) { #ifdef USE_HTML_STYLE_COLOR const QString bgColor = mBackgroundColor.name(); const QString background = QStringLiteral(" background: %1 ! important;\n").arg(bgColor); return QStringLiteral("div#headerbox a:link {\n" - " color: %1 ! important;\n" - " text-decoration: none ! important;\n" - "}\n\n" - "div.htmlWarn a:link {\n" " color: %1 ! important;\n" " text-decoration: none ! important;\n" "}\n\n" "div#header a:link {\n" " color: %1 ! important;\n" " text-decoration: none ! important;\n" "}\n\n" "div.header {\n" " %2" "}\n\n" "div#headerbox {\n" " %2" "}\n\n").arg(linkColor, background); #else return QStringLiteral("div#headerbox a:link {\n" - " color: %1 ! important;\n" - " text-decoration: none ! important;\n" - "}\n\n" - "div.htmlWarn a:link {\n" " color: %1 ! important;\n" " text-decoration: none ! important;\n" "}\n\n" "div#header a:link {\n" " color: %1 ! important;\n" " text-decoration: none ! important;\n" "}\n\n").arg(linkColor); #endif } else { return QStringLiteral("a {\n" " color: %1 ! important;\n" " text-decoration: none ! important;\n" "}\n\n").arg(linkColor); } } QString CSSHelperBase::quoteCssDefinition() const { QString quoteCSS; QString blockQuote; for (int i = 0; i < 9; ++i) { blockQuote += QStringLiteral("blockquote "); quoteCSS += QStringLiteral("%2{\n" " margin: 4pt 0 4pt 0;\n" " padding: 0 0 0 1em;\n" " border-left: 2px solid %1;\n" " unicode-bidi: -webkit-plaintext\n" "}\n\n").arg(quoteColorName(i), blockQuote); } quoteCSS += QStringLiteral(".quotemarks{\n" " color:transparent;\n" " font-size:0px;\n" "}\n\n"); quoteCSS += QStringLiteral(".quotemarksemptyline{\n" " color:transparent;\n" " font-size:0px;\n" " line-height: 12pt;\n" "}\n\n"); return quoteCSS; } QString CSSHelperBase::defaultPrintHeaderFont() const { const QString headerFont = QStringLiteral(" font-family: \"%1\" ! important;\n" " font-size: %2pt ! important;\n") .arg(mPrintFont.family()) .arg(mPrintFont.pointSize()); return headerFont; } QString CSSHelperBase::defaultScreenHeaderFont() const { const QString headerFont = QStringLiteral(" font-family: \"%1\" ! important;\n" " font-size: %2px ! important;\n") .arg(mBodyFont.family()) .arg(pointsToPixel(this->mPaintDevice, mBodyFont.pointSize())); return headerFont; } QString CSSHelperBase::screenCssDefinitions(const CSSHelperBase *helper, bool fixed) const { const QString bgColor = mBackgroundColor.name(); const QString headerFont = defaultScreenHeaderFont(); #ifdef USE_HTML_STYLE_COLOR const QString fgColor = mUseBrowserColor ? QStringLiteral("black") : mForegroundColor.name(); const QString background = mUseBrowserColor ? QString() : QStringLiteral(" background-color: %1 ! important;\n").arg(bgColor); const QString signWarnBColorName = mUseBrowserColor ? QStringLiteral("white") : cPgpWarnB.name(); const QString cPgpErrBColorName = mUseBrowserColor ? QStringLiteral("white") : cPgpErrB.name(); const QString cPgpEncrBColorName = mUseBrowserColor ? QStringLiteral("white") : cPgpEncrB.name(); const QString cPgpOk1BColorName = mUseBrowserColor ? QStringLiteral("white") : cPgpOk1B.name(); const QString cPgpOk0BColorName = mUseBrowserColor ? QStringLiteral("white") : cPgpOk0B.name(); #else const QString fgColor = mForegroundColor.name(); const QString background = QStringLiteral(" background-color: %1 ! important;\n").arg(bgColor); const QString signWarnBColorName = cPgpWarnB.name(); const QString cPgpErrBColorName = cPgpErrB.name(); const QString cPgpEncrBColorName = cPgpEncrB.name(); const QString cPgpOk1BColorName = cPgpOk1B.name(); const QString cPgpOk0BColorName = cPgpOk0B.name(); #endif const QString bodyFontSize = QString::number(pointsToPixel(helper->mPaintDevice, fontSize( fixed))) + QLatin1String("px"); const QPalette &pal = QApplication::palette(); QString quoteCSS; if (bodyFont(fixed).italic()) { quoteCSS += QLatin1String(" font-style: italic ! important;\n"); } if (bodyFont(fixed).bold()) { quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); } if (!quoteCSS.isEmpty()) { quoteCSS = QLatin1String("div.noquote {\n") + quoteCSS + QLatin1String("}\n\n"); } // CSS definitions for quote levels 1-3 for (int i = 0; i < 3; ++i) { quoteCSS += QStringLiteral("div.quotelevel%1 {\n" " color: %2 ! important;\n") .arg(QString::number(i + 1), quoteColorName(i)); if (mQuoteFont.italic()) { quoteCSS += QStringLiteral(" font-style: italic ! important;\n"); } if (mQuoteFont.bold()) { quoteCSS += QStringLiteral(" font-weight: bold ! important;\n"); } if (mShrinkQuotes) { quoteCSS += QLatin1String(" font-size: ") + QString::fromLatin1(quoteFontSizes[i]) + QLatin1String("% ! important;\n"); } quoteCSS += QStringLiteral("}\n\n"); } // CSS definitions for quote levels 4+ for (int i = 0; i < 3; ++i) { quoteCSS += QStringLiteral("div.deepquotelevel%1 {\n" " color: %2 ! important;\n") .arg(QString::number(i + 1), quoteColorName(i)); if (mQuoteFont.italic()) { quoteCSS += QStringLiteral(" font-style: italic ! important;\n"); } if (mQuoteFont.bold()) { quoteCSS += QStringLiteral(" font-weight: bold ! important;\n"); } if (mShrinkQuotes) { quoteCSS += QStringLiteral(" font-size: 70% ! important;\n"); } quoteCSS += QLatin1String("}\n\n"); } quoteCSS += quoteCssDefinition(); + + // CSS definitions for inline message boxes + QString inlineMessageCss; + for (const auto &msgStyle : inlineMessageStyles) { + const auto c = cInlineMessage[msgStyle.type]; + inlineMessageCss += QStringLiteral(R"( + div.%1 { + border: 1px solid rgba(%2, %3, %4) ! important; + border-radius: 2px; + box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.5); + background-color: rgba(%2, %3, %4, 0.2) ! important; + } + div.%1 a:link { + color: %5 ! important; + text-decoration: none ! important; + } + )").arg(QString::fromLatin1(msgStyle.cssName)).arg(c.red()).arg(c.green()).arg(c.blue()).arg(mLinkColor.name()); + } + return QStringLiteral("body {\n" " font-family: \"%1\" ! important;\n" " font-size: %2 ! important;\n" " color: %3 ! important;\n" "%4" "}\n\n") .arg(bodyFont(fixed).family(), bodyFontSize, fgColor, background) + linkColorDefinition() + QStringLiteral("a.white {\n" " color: white ! important;\n" "}\n\n" "a.black {\n" " color: black ! important;\n" "}\n\n" "table.textAtm { background-color: %1 ! important; }\n\n" "tr.textAtmH {\n" " background-color: %2 ! important;\n" "%3" "}\n\n" "tr.textAtmB {\n" " background-color: %2 ! important;\n" "}\n\n" "table.signInProgress,\n" "table.rfc822 {\n" " background-color: %2 ! important;\n" "}\n\n" "tr.signInProgressH,\n" "tr.rfc822H {\n" "%3" "}\n\n").arg(fgColor, bgColor, headerFont) + QStringLiteral("table.encr {\n" " background-color: %1 ! important;\n" "}\n\n" "tr.encrH {\n" " background-color: %2 ! important;\n" " color: %3 ! important;\n" "%4" "}\n\n" "tr.encrB { background-color: %5 ! important; }\n\n") .arg(cPgpEncrF.name(), cPgpEncrH.name(), cPgpEncrHT.name(), headerFont, cPgpEncrBColorName) + QStringLiteral("table.signOkKeyOk {\n" " background-color: %1 ! important;\n" "}\n\n" "tr.signOkKeyOkH {\n" " background-color: %2 ! important;\n" " color: %3 ! important;\n" "%4" "}\n\n" "tr.signOkKeyOkB { background-color: %5 ! important; }\n\n") .arg(cPgpOk1F.name(), cPgpOk1H.name(), cPgpOk1HT.name(), headerFont, cPgpOk1BColorName) + QStringLiteral("table.signOkKeyBad {\n" " background-color: %1 ! important;\n" "}\n\n" "tr.signOkKeyBadH {\n" " background-color: %2 ! important;\n" " color: %3 ! important;\n" "%4" "}\n\n" "tr.signOkKeyBadB { background-color: %5 ! important; }\n\n") .arg(cPgpOk0F.name(), cPgpOk0H.name(), cPgpOk0HT.name(), headerFont, cPgpOk0BColorName) + QStringLiteral("table.signWarn {\n" " background-color: %1 ! important;\n" "}\n\n" "tr.signWarnH {\n" " background-color: %2 ! important;\n" " color: %3 ! important;\n" "%4" "}\n\n" "tr.signWarnB { background-color: %5 ! important; }\n\n") .arg(cPgpWarnF.name(), cPgpWarnH.name(), cPgpWarnHT.name(), headerFont, signWarnBColorName) + QStringLiteral("table.signErr {\n" " background-color: %1 ! important;\n" "}\n\n" "tr.signErrH {\n" " background-color: %2 ! important;\n" " color: %3 ! important;\n" "%4" "}\n\n" "tr.signErrB { background-color: %5 ! important; }\n\n") .arg(cPgpErrF.name(), cPgpErrH.name(), cPgpErrHT.name(), headerFont, cPgpErrBColorName) + - QStringLiteral("div.htmlWarn {\n" - " border: 2px solid %1 ! important;\n" - " line-height: normal;\n" - "}\n\n") - .arg(cHtmlWarning.name()) + inlineMessageCss + QStringLiteral("div.header {\n" "%1" "}\n\n" "%2" "div.senderpic{\n" " padding: 0px ! important;\n" " font-size:0.8em ! important;\n" " border:1px solid %4 ! important;\n" " background-color:%3 ! important;\n" "}\n\n" "div.senderstatus{\n" " text-align:center ! important;\n" "}\n\n" ) .arg(headerFont, extraScreenCss(headerFont), pal.color(QPalette::Highlight).name(), pal.color(QPalette::Window).name()) + quoteCSS + fullAddressList(); } QString CSSHelperBase::commonCssDefinitions() const { const QString headerFont = defaultScreenHeaderFont(); + QStringList inlineMessageCss; + inlineMessageCss.reserve(MESSAGE_TYPE_COUNT); + for (const auto &msgStyle : inlineMessageStyles) { + inlineMessageCss.push_back(QLatin1String("div.") + QString::fromLatin1(msgStyle.cssName)); + } + return QStringLiteral("div.header {\n" " margin-bottom: 10pt ! important;\n" "}\n\n" "pre.highlightattachment {\n" " white-space: pre-wrap;\n" "}\n\n" "table.textAtm {\n" " margin-top: 10pt ! important;\n" " margin-bottom: 10pt ! important;\n" "}\n\n" "tr.textAtmH,\n" "tr.textAtmB,\n" "tr.rfc822B {\n" " font-weight: normal ! important;\n" "}\n\n" "tr.signInProgressH,\n" "tr.rfc822H,\n" "tr.encrH,\n" "tr.signOkKeyOkH,\n" "tr.signOkKeyBadH,\n" "tr.signWarnH,\n" "tr.signErrH {\n" " font-weight: bold ! important;\n" "}\n\n" "tr.textAtmH td,\n" "tr.textAtmB td {\n" " padding: 3px ! important;\n" "}\n\n" "table.rfc822 {\n" " width: 100% ! important;\n" " border: solid 1px black ! important;\n" " margin-top: 10pt ! important;\n" " margin-bottom: 10pt ! important;\n" "}\n\n" "table.textAtm,\n" "table.encr,\n" "table.signWarn,\n" "table.signErr,\n" "table.signOkKeyBad,\n" "table.signOkKeyOk,\n" "table.signInProgress,\n" "%1" - "div.htmlWarn {\n" - " margin: 0px 5% ! important;\n" + "%2 {\n" + " margin: 0px 5% 10px 5% ! important;\n" " padding: 10px ! important;\n" " text-align: left ! important;\n" " line-height: normal;\n" "}\n\n" + "hr {\n" + " border: 0;\n" + " height: 0;\n" + " border-top: 1px solid rgba(%3, %4, %5, 0.3);\n" + "}\n\n" + "div.quotelevelmark {\n" " position: absolute;\n" " margin-left:-10px;\n" - "}\n\n").arg(extraCommonCss(headerFont)); + "}\n\n").arg(extraCommonCss(headerFont), inlineMessageCss.join(QLatin1String(", "))) + .arg(mForegroundColor.red()).arg(mForegroundColor.green()).arg(mForegroundColor.blue()); } void CSSHelperBase::setBodyFont(const QFont &font) { mBodyFont = font; } void CSSHelperBase::setPrintFont(const QFont &font) { mPrintFont = font; } QString CSSHelperBase::quoteColorName(int level) const { return quoteColor(level).name(); } QColor CSSHelperBase::quoteColor(int level) const { const int actualLevel = qMax(level, 0) % 3; return mQuoteColor[actualLevel]; } QColor CSSHelperBase::pgpWarnColor() const { return cPgpWarnH; } } diff --git a/messageviewer/src/viewer/csshelperbase.h b/messageviewer/src/viewer/csshelperbase.h index 0565c6cb..3219b760 100644 --- a/messageviewer/src/viewer/csshelperbase.h +++ b/messageviewer/src/viewer/csshelperbase.h @@ -1,154 +1,163 @@ /* -*- c++ -*- csshelper.h This file is part of KMail, the KDE mail client. Copyright (c) 2003 Marc Mutz KMail is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KMail 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA In addition, as a special exception, the copyright holders give permission to link the code of this program with any edition of the Qt library by Trolltech AS, Norway (or with modified versions of Qt that use the same license as Qt), and distribute linked combinations including the two. You must obey the GNU General Public License in all respects for all of the code used other than Qt. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ #ifndef MIMETREEPARSER_CSSHELPERBASE_H #define MIMETREEPARSER_CSSHELPERBASE_H #include "messageviewer_export.h" #include #include class QString; class QPaintDevice; namespace MessageViewer { class HeaderStylePlugin; class MESSAGEVIEWER_EXPORT CSSHelperBase { public: /** Construct a CSSHelper object and set its font and color settings to default values. Sub-Classes should put their config loading here. */ explicit CSSHelperBase(const QPaintDevice *pd); virtual ~CSSHelperBase(); /** @return HTML head including style sheet definitions and the >body< tag */ virtual QString htmlHead(bool fixedFont = false) const; /** @return The collected CSS definitions as a string */ Q_REQUIRED_RESULT QString cssDefinitions(bool fixedFont = false) const; /** @return a <div> start tag with embedded style information suitable for quoted text with quote level @p level */ Q_REQUIRED_RESULT QString quoteFontTag(int level) const; /** @return a <div> start tag with embedded style information suitable for non-quoted text */ Q_REQUIRED_RESULT QString nonQuotedFontTag() const; Q_REQUIRED_RESULT QFont bodyFont(bool fixedFont = false, bool printing = false) const; void setBodyFont(const QFont &font); void setPrintFont(const QFont &font); /** @return the quote color for the given level, where level ranges from 0 to 2 **/ Q_REQUIRED_RESULT QColor quoteColor(int level) const; Q_REQUIRED_RESULT QString quoteColorName(int level) const; Q_REQUIRED_RESULT QColor pgpWarnColor() const; Q_REQUIRED_RESULT QString addEndBlockQuote(int numberBlock) const; Q_REQUIRED_RESULT QString addStartBlockQuote(int numberBlock) const; virtual Q_REQUIRED_RESULT QString extraScreenCss(const QString &headerFont) const; virtual Q_REQUIRED_RESULT QString extraPrintCss(const QString &headerFont) const; virtual Q_REQUIRED_RESULT QString extraCommonCss(const QString &headerFont) const; void setHeaderPlugin(const HeaderStylePlugin *headerPlugin); + enum InlineMessageType { + Positive, + Information, + Warning, + Error, + MESSAGE_TYPE_COUNT + }; + protected: /** Recalculate PGP frame and body colors (should be called after changing color settings) */ void recalculatePGPColors(); protected: QFont mBodyFont; QFont mPrintFont; QFont mFixedFont; QFont mFixedPrintFont; QFont mQuoteFont; QColor mQuoteColor[3]; bool mRecycleQuoteColors; bool mShrinkQuotes; bool mUseBrowserColor = false; QColor mForegroundColor; QColor mLinkColor; QColor mBackgroundColor; // colors for PGP (Frame, Header, HeaderText, Body) QColor cPgpOk1F; QColor cPgpOk1H; QColor cPgpOk1HT; QColor cPgpOk1B; QColor cPgpOk0F; QColor cPgpOk0H; QColor cPgpOk0HT; QColor cPgpOk0B; QColor cPgpWarnF; QColor cPgpWarnH; QColor cPgpWarnHT; QColor cPgpWarnB; QColor cPgpErrF; QColor cPgpErrH; QColor cPgpErrHT; QColor cPgpErrB; QColor cPgpEncrF; QColor cPgpEncrH; QColor cPgpEncrHT; QColor cPgpEncrB; - // color of frame of warning preceding the source of HTML messages - QColor cHtmlWarning; + + // colors for inline message boxes, see KMessageWidget or Kirigami::InlineMessage + QColor cInlineMessage[MESSAGE_TYPE_COUNT]; QString imgShowUrl; QString imgHideUrl; private: QString quoteCssDefinition() const; int fontSize(bool fixed, bool print = false) const; // returns CSS rules specific to the print media type QString printCssDefinitions(bool fixed) const; // returns CSS rules specific to the screen media type QString screenCssDefinitions(const CSSHelperBase *helper, bool fixed) const; // returns CSS rules common to both screen and print media types QString commonCssDefinitions() const; QString fullAddressList() const; QString linkColorDefinition() const; QString defaultScreenHeaderFont() const; QString defaultPrintHeaderFont() const; const QPaintDevice *mPaintDevice = nullptr; const HeaderStylePlugin *mHeaderPlugin = nullptr; }; } #endif