VWebView: add css_color_mapping in palette file for copying HTMl

If the mapping is specified, we will replace the foreground color with
the mapping when the content is copied.
This commit is contained in:
Le Tan 2018-01-05 19:36:40 +08:00
parent 2bdad19253
commit 324d7cd444
7 changed files with 131 additions and 12 deletions

View File

@ -65,6 +65,8 @@ void VCopyTextAsHtmlDialog::setConvertedHtml(const QUrl &p_baseUrl,
m_htmlViewer->setHtml(html, p_baseUrl); m_htmlViewer->setHtml(html, p_baseUrl);
setHtmlVisible(true); setHtmlVisible(true);
VWebUtils::translateColors(html);
// Fix image source. // Fix image source.
if (g_config->getFixImageSrcInWebWhenCopied()) { if (g_config->getFixImageSrcInWebWhenCopied()) {
VWebUtils::fixImageSrcInHtml(p_baseUrl, html); VWebUtils::fixImageSrcInHtml(p_baseUrl, html);

View File

@ -7,6 +7,12 @@ mdhl_file=v_moonlight.mdhl
css_file=v_moonlight.css css_file=v_moonlight.css
codeblock_css_file=v_moonlight_codeblock.css codeblock_css_file=v_moonlight_codeblock.css
; This mapping will be used to translate colors when the content of HTML is copied
; without background. You could just specify the foreground colors mapping here.
; It is useful for dark mode theme. '#aabbcc' or 'red' formats are supported.
; col1:col1_new,col2:col2_new
css_color_mapping=#abb2bf:#363636,#282c34:#f5f5f5,#61afef:#0099ff,#98c379:#8e24aa,#2c313a:#e0e0e0,#5c6370:#666666,#373e47:#999999,#6c6c6c:#444444,#c678dd:#0000ee,#e06c75:#880000,#56b6c2:#af00d7,#e6c07b:#008700,#d19a66:#bc6060,#61aeee:#bc6060
[phony] [phony]
; Abstract color attributes. ; Abstract color attributes.
master_fg=@edit_fg master_fg=@edit_fg

View File

@ -4,6 +4,10 @@
#include <QFileInfo> #include <QFileInfo>
#include <QDebug> #include <QDebug>
#include "vpalette.h"
extern VPalette *g_palette;
VWebUtils::VWebUtils() VWebUtils::VWebUtils()
{ {
} }
@ -56,3 +60,67 @@ bool VWebUtils::fixImageSrcInHtml(const QUrl &p_baseUrl, QString &p_html)
return changed; return changed;
} }
bool VWebUtils::removeBackgroundColor(QString &p_html)
{
QRegExp reg("(<[^>]+\\sstyle=[^>]*(\\s|\"))background(-color)?:[^;]+;([^>]*>)");
int size = p_html.size();
p_html.replace(reg, "\\1\\4");
return p_html.size() != size;
}
bool VWebUtils::translateColors(QString &p_html)
{
bool changed = false;
const QHash<QString, QString> &mapping = g_palette->getColorMapping();
if (mapping.isEmpty()) {
return changed;
}
QRegExp tagReg("(<[^>]+\\sstyle=[^>]*>)");
// Won't mixed up with background-color.
QRegExp colorReg("(\\s|\")color:([^;]+);");
int pos = 0;
while (pos < p_html.size()) {
int idx = p_html.indexOf(tagReg, pos);
if (idx == -1) {
break;
}
QString styleStr = tagReg.cap(1);
QString alteredStyleStr = styleStr;
int posb = 0;
while (posb < alteredStyleStr.size()) {
int idxb = alteredStyleStr.indexOf(colorReg, posb);
if (idxb == -1) {
break;
}
QString col = colorReg.cap(2).trimmed().toLower();
auto it = mapping.find(col);
if (it == mapping.end()) {
posb = idxb + colorReg.matchedLength();
continue;
}
// Replace the color.
QString newCol = it.value();
// Add one extra space between color and :.
QString newStr = QString("%1color : %2;").arg(colorReg.cap(1)).arg(newCol);
alteredStyleStr.replace(idxb, colorReg.matchedLength(), newStr);
posb = idxb + newStr.size();
changed = true;
}
pos = idx + tagReg.matchedLength();
if (changed) {
pos = pos + alteredStyleStr.size() - styleStr.size();
p_html.replace(idx, tagReg.matchedLength(), alteredStyleStr);
}
}
return changed;
}

View File

@ -11,6 +11,12 @@ public:
// Fix <img src> in @p_html. // Fix <img src> in @p_html.
static bool fixImageSrcInHtml(const QUrl &p_baseUrl, QString &p_html); static bool fixImageSrcInHtml(const QUrl &p_baseUrl, QString &p_html);
// Remove background color style in @p_html.
static bool removeBackgroundColor(QString &p_html);
// Translate color styles in @p_html using mappings from VPalette.
static bool translateColors(QString &p_html);
private: private:
VWebUtils(); VWebUtils();
}; };

View File

@ -180,6 +180,19 @@ QMap<QString, QString> VPalette::codeBlockCssStylesFromThemes(const QList<QStrin
return styles; return styles;
} }
static QString translateColorValue(const QString &p_col)
{
QString tmp = p_col.trimmed().toLower();
if (tmp.startsWith('#')) {
QColor col(tmp);
int r, g, b;
col.getRgb(&r, &g, &b);
return QString("rgb(%1, %2, %3)").arg(r).arg(g).arg(b);
} else {
return tmp;
}
}
VPaletteMetaData VPalette::getPaletteMetaData(const QString &p_paletteFile) VPaletteMetaData VPalette::getPaletteMetaData(const QString &p_paletteFile)
{ {
VPaletteMetaData data; VPaletteMetaData data;
@ -208,6 +221,20 @@ VPaletteMetaData VPalette::getPaletteMetaData(const QString &p_paletteFile)
data.m_codeBlockCssFile = dir.filePath(val); data.m_codeBlockCssFile = dir.filePath(val);
} }
QStringList mapping = settings.value("css_color_mapping").toStringList();
if (!mapping.isEmpty()) {
for (auto const & m : mapping) {
QStringList vals = m.split(':');
if (vals.size() != 2) {
continue;
}
// Translate the #aabbcc into rgb(aa, bb, cc) format.
data.m_colorMapping.insert(translateColorValue(vals[0]),
translateColorValue(vals[1]));
}
}
settings.endGroup(); settings.endGroup();
return data; return data;

View File

@ -15,13 +15,18 @@ struct VPaletteMetaData
QString m_cssFile; QString m_cssFile;
QString m_codeBlockCssFile; QString m_codeBlockCssFile;
// Color mapping when copied.
// All lower-case.
QHash<QString, QString> m_colorMapping;
QString toString() const QString toString() const
{ {
return QString("palette metadata qss=%1 mdhl=%2 css=%3 codeBlockCss=%4") return QString("palette metadata qss=%1 mdhl=%2 css=%3 codeBlockCss=%4 colorMappingSize=%5")
.arg(m_qssFile) .arg(m_qssFile)
.arg(m_mdhlFile) .arg(m_mdhlFile)
.arg(m_cssFile) .arg(m_cssFile)
.arg(m_codeBlockCssFile); .arg(m_codeBlockCssFile)
.arg(m_colorMapping.size());
} }
}; };
@ -39,6 +44,8 @@ public:
// Fill "@xxx" in @p_text with corresponding style. // Fill "@xxx" in @p_text with corresponding style.
void fillStyle(QString &p_text) const; void fillStyle(QString &p_text) const;
const QHash<QString, QString> &getColorMapping() const;
// Read themes and return the mappings of editor styles. // Read themes and return the mappings of editor styles.
static QMap<QString, QString> editorStylesFromThemes(const QList<QString> &p_themeFiles); static QMap<QString, QString> editorStylesFromThemes(const QList<QString> &p_themeFiles);
@ -77,4 +84,9 @@ private:
VPaletteMetaData m_data; VPaletteMetaData m_data;
}; };
inline const QHash<QString, QString> &VPalette::getColorMapping() const
{
return m_data.m_colorMapping;
}
#endif // VPALETTE_H #endif // VPALETTE_H

View File

@ -229,14 +229,6 @@ void VWebView::hideUnusedActions(QMenu *p_menu)
} }
} }
static bool removeBackgroundColor(QString &p_html)
{
QRegExp reg("(<[^>]+\\sstyle=[^>]*(\\s|\"))background(-color)?:[^;]+;([^>]*>)");
int size = p_html.size();
p_html.replace(reg, "\\1\\4");
return p_html.size() != size;
}
bool VWebView::removeStyles(QString &p_html) bool VWebView::removeStyles(QString &p_html)
{ {
bool changed = false; bool changed = false;
@ -336,8 +328,14 @@ void VWebView::alterHtmlMimeData(QClipboard *p_clipboard,
} }
// Remove background color. // Remove background color.
if (p_removeBackground && removeBackgroundColor(html)) { if (p_removeBackground) {
altered = true; if (VWebUtils::removeBackgroundColor(html)) {
altered = true;
}
if (VWebUtils::translateColors(html)) {
altered = true;
}
} }
// Fix local relative images. // Fix local relative images.