aboutsummaryrefslogtreecommitdiff
path: root/src/documentstyle.cpp
diff options
context:
space:
mode:
authorFelix (xq) Queißner <git@mq32.de>2020-06-08 00:30:32 +0200
committerFelix (xq) Queißner <git@mq32.de>2020-06-08 00:30:32 +0200
commitf02ccb928fd4ed591d2efe118a571e154f5df68a (patch)
tree2fc7c4037423d074c410f4c53714ddc842d33351 /src/documentstyle.cpp
parent425f9d41cd337133d5677744eef937a8a2a61212 (diff)
downloadkristall-f02ccb928fd4ed591d2efe118a571e154f5df68a.tar.gz
Starts to implement gopher protocol and gophermap support. Heavily WIP, but you can already surf on gopherspace!
Diffstat (limited to 'src/documentstyle.cpp')
-rw-r--r--src/documentstyle.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/documentstyle.cpp b/src/documentstyle.cpp
new file mode 100644
index 0000000..6a8e8bf
--- /dev/null
+++ b/src/documentstyle.cpp
@@ -0,0 +1,290 @@
+#include "documentstyle.hpp"
+
+#include <QDebug>
+#include <QString>
+#include <QStringList>
+
+#include <QCryptographicHash>
+#include <QDebug>
+
+#include <cmath>
+
+static QString encodeCssFont (const QFont& refFont)
+{
+ //-----------------------------------------------------------------------
+ // This function assembles a CSS Font specification string from
+ // a QFont. This supports most of the QFont attributes settable in
+ // the Qt 4.8 and Qt 5.3 QFontDialog.
+ //
+ // (1) Font Family
+ // (2) Font Weight (just bold or not)
+ // (3) Font Style (possibly Italic or Oblique)
+ // (4) Font Size (in either pixels or points)
+ // (5) Decorations (possibly Underline or Strikeout)
+ //
+ // Not supported: Writing System (e.g. Latin).
+ //
+ // See the corresponding decode function, below.
+ // QFont decodeCssFontString (const QString cssFontStr)
+ //-----------------------------------------------------------------------
+
+ QStringList fields; // CSS font attribute fields
+
+ // ***************************************************
+ // *** (1) Font Family: Primary plus Substitutes ***
+ // ***************************************************
+
+ const QString family = refFont.family();
+
+ // NOTE [9-2014, Qt 4.8.6]: This isn't what I thought it was. It
+ // does not return a list of "fallback" font faces (e.g. Georgia,
+ // Serif for "Times New Roman"). In my testing, this is always
+ // returning an empty list.
+ //
+ QStringList famSubs = QFont::substitutes (family);
+
+ if (!famSubs.contains (family))
+ famSubs.prepend (family);
+
+ static const QChar DBL_QUOT ('"');
+ const int famCnt = famSubs.count();
+ QStringList famList;
+ for (int inx = 0; inx < famCnt; ++inx)
+ {
+ // Place double quotes around family names having space characters,
+ // but only if double quotes are not already there.
+ //
+ const QString fam = famSubs [inx];
+ if (fam.contains (' ') && !fam.startsWith (DBL_QUOT))
+ famList << (DBL_QUOT + fam + DBL_QUOT);
+ else
+ famList << fam;
+ }
+
+ const QString famStr = QString ("font-family: ") + famList.join (", ");
+ fields << famStr;
+
+ // **************************************
+ // *** (2) Font Weight: Bold or Not ***
+ // **************************************
+
+ const bool bold = refFont.bold();
+ if (bold)
+ fields << "font-weight: bold";
+
+ // ****************************************************
+ // *** (3) Font Style: possibly Italic or Oblique ***
+ // ****************************************************
+
+ const QFont::Style style = refFont.style();
+ switch (style)
+ {
+ case QFont::StyleNormal: break;
+ case QFont::StyleItalic: fields << "font-style: italic"; break;
+ case QFont::StyleOblique: fields << "font-style: oblique"; break;
+ }
+
+ // ************************************************
+ // *** (4) Font Size: either Pixels or Points ***
+ // ************************************************
+
+ const double sizeInPoints = refFont.pointSizeF(); // <= 0 if not defined.
+ const int sizeInPixels = refFont.pixelSize(); // <= 0 if not defined.
+ if (sizeInPoints > 0.0)
+ fields << QString ("font-size: %1pt") .arg (sizeInPoints);
+ else if (sizeInPixels > 0)
+ fields << QString ("font-size: %1px") .arg (sizeInPixels);
+
+ // ***********************************************
+ // *** (5) Decorations: Underline, Strikeout ***
+ // ***********************************************
+
+ const bool underline = refFont.underline();
+ const bool strikeOut = refFont.strikeOut();
+
+ if (underline && strikeOut)
+ fields << "text-decoration: underline line-through";
+ else if (underline)
+ fields << "text-decoration: underline";
+ else if (strikeOut)
+ fields << "text-decoration: line-through";
+
+ const QString cssFontStr = fields.join ("; ");
+ return cssFontStr;
+}
+
+DocumentStyle::DocumentStyle() : theme(Fixed),
+ standard_font(),
+ h1_font(),
+ h2_font(),
+ h3_font(),
+ preformatted_font(),
+ background_color("#edefff"),
+ standard_color(0x00, 0x00, 0x00),
+ preformatted_color(0x00, 0x00, 0x00),
+ h1_color("#022f90"),
+ h2_color("#022f90"),
+ h3_color("#022f90"),
+ internal_link_color("#0e8fff"),
+ external_link_color("#0e8fff"),
+ cross_scheme_link_color("#0960a7"),
+ internal_link_prefix("→ "),
+ external_link_prefix("⇒ "),
+ margin(55.0)
+{
+ preformatted_font.setFamily("monospace");
+ preformatted_font.setPointSizeF(10.0);
+
+ standard_font.setFamily("sans");
+ standard_font.setPointSizeF(10.0);
+
+ h1_font.setFamily("sans");
+ h1_font.setBold(true);
+ h1_font.setPointSizeF(20.0);
+
+ h2_font.setFamily("sans");
+ h2_font.setBold(true);
+ h2_font.setPointSizeF(15.0);
+
+ h3_font.setFamily("sans");
+ h3_font.setBold(true);
+ h3_font.setPointSizeF(12.0);
+}
+
+bool DocumentStyle::save(QSettings &settings) const
+{
+ settings.beginGroup("Theme");
+
+ settings.setValue("standard_font", standard_font.toString());
+ settings.setValue("h1_font", h1_font.toString());
+ settings.setValue("h2_font", h2_font.toString());
+ settings.setValue("h3_font", h3_font.toString());
+ settings.setValue("preformatted_font", preformatted_font.toString());
+
+ settings.setValue("background_color", background_color.name());
+ settings.setValue("standard_color", standard_color.name());
+ settings.setValue("preformatted_color", preformatted_color.name());
+ settings.setValue("h1_color", h1_color.name());
+ settings.setValue("h2_color", h2_color.name());
+ settings.setValue("h3_color", h3_color.name());
+ settings.setValue("internal_link_color", internal_link_color.name());
+ settings.setValue("external_link_color", external_link_color.name());
+ settings.setValue("cross_scheme_link_color", cross_scheme_link_color.name());
+
+ settings.setValue("internal_link_prefix", internal_link_prefix);
+ settings.setValue("external_link_prefix", external_link_prefix);
+
+ settings.setValue("margins", margin);
+ settings.setValue("theme", int(theme));
+
+ settings.endGroup();
+ return true;
+}
+
+bool DocumentStyle::load(QSettings &settings)
+{
+ settings.beginGroup("Theme");
+
+ if(settings.contains("standard_color"))
+ {
+ standard_font.fromString(settings.value("standard_font").toString());
+ h1_font.fromString(settings.value("h1_font").toString());
+ h2_font.fromString(settings.value("h2_font").toString());
+ h3_font.fromString(settings.value("h3_font").toString());
+ preformatted_font.fromString(settings.value("preformatted_font").toString());
+
+ background_color = QColor(settings.value("background_color").toString());
+ standard_color = QColor(settings.value("standard_color").toString());
+ preformatted_color = QColor(settings.value("preformatted_color").toString());
+ h1_color = QColor(settings.value("h1_color").toString());
+ h2_color = QColor(settings.value("h2_color").toString());
+ h3_color = QColor(settings.value("h3_color").toString());
+ internal_link_color = QColor(settings.value("internal_link_color").toString());
+ external_link_color = QColor(settings.value("external_link_color").toString());
+ cross_scheme_link_color = QColor(settings.value("cross_scheme_link_color").toString());
+
+ internal_link_prefix = settings.value("internal_link_prefix").toString();
+ external_link_prefix = settings.value("external_link_prefix").toString();
+
+ margin = settings.value("margins").toDouble();
+ theme = Theme(settings.value("theme").toInt());
+ }
+
+ settings.endGroup();
+ return true;
+}
+
+DocumentStyle DocumentStyle::derive(const QUrl &url) const
+{
+ if (this->theme == Fixed)
+ return *this;
+
+ QByteArray hash = QCryptographicHash::hash(url.host().toUtf8(), QCryptographicHash::Md5);
+
+ std::array<uint8_t, 16> items;
+ assert(items.size() == hash.size());
+ memcpy(items.data(), hash.data(), items.size());
+
+ float hue = (items[0] + items[1]) / 510.0;
+ float saturation = items[2] / 255.0;
+
+ double tmp;
+ DocumentStyle themed = *this;
+ switch (this->theme)
+ {
+ case AutoDarkTheme:
+ {
+ themed.background_color = QColor::fromHslF(hue, saturation, 0.25f);
+ themed.standard_color = QColor{0xFF, 0xFF, 0xFF};
+
+ themed.h1_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.75);
+ themed.h2_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.75);
+ themed.h3_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.75);
+
+ themed.external_link_color = QColor::fromHslF(std::modf(hue + 0.25, &tmp), 1.0, 0.75);
+ themed.internal_link_color = themed.external_link_color.lighter(110);
+ themed.cross_scheme_link_color = themed.external_link_color.darker(110);
+
+ break;
+ }
+
+ case AutoLightTheme:
+ {
+ themed.background_color = QColor::fromHslF(hue, items[2] / 255.0, 0.85);
+ themed.standard_color = QColor{0x00, 0x00, 0x00};
+
+ themed.h1_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.25);
+ themed.h2_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.25);
+ themed.h3_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.25);
+
+ themed.external_link_color = QColor::fromHslF(std::modf(hue + 0.25, &tmp), 1.0, 0.25);
+ themed.internal_link_color = themed.external_link_color.darker(110);
+ themed.cross_scheme_link_color = themed.external_link_color.lighter(110);
+
+ break;
+ }
+
+ case Fixed:
+ assert(false);
+ }
+
+ // Same for all themes
+ themed.preformatted_color = themed.standard_color;
+
+ return themed;
+}
+
+QString DocumentStyle::toStyleSheet() const
+{
+ QString css;
+
+ css += QString("p { color: %2; %1 }\n").arg(encodeCssFont (standard_font)).arg(standard_color.name());
+ css += QString("a { color: %2; %1 }\n").arg(encodeCssFont (standard_font)).arg(external_link_color.name());
+ css += QString("pre { color: %2; %1 }\n").arg(encodeCssFont (preformatted_font)).arg(preformatted_color.name());
+ css += QString("h1 { color: %2; %1 }\n").arg(encodeCssFont (h1_font)).arg(h1_color.name());
+ css += QString("h2 { color: %2; %1 }\n").arg(encodeCssFont (h2_font)).arg(h2_color.name());
+ css += QString("h3 { color: %2; %1 }\n").arg(encodeCssFont (h3_font)).arg(h3_color.name());
+
+ qDebug() << "CSS → " << css;
+ return css;
+}