aboutsummaryrefslogtreecommitdiffstats
path: root/src/htmlbuilder.h
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-07 12:12:18 +0200
committerDanilo M. <danix@danix.xyz>2026-08-07 12:12:18 +0200
commit3826759d5167fb7a6f9449f9a39814c75771f449 (patch)
tree9fb1bc09bb89bd2c77a7c8c46247c577d8666cfd /src/htmlbuilder.h
parent5a4d8f5f021dc98b2a7cc471125aa3040c02675c (diff)
downloadqtmaildir-3826759d5167fb7a6f9449f9a39814c75771f449.tar.gz
qtmaildir-3826759d5167fb7a6f9449f9a39814c75771f449.zip
fix(ui): the message pane follows the desktop theme
The stylesheet hardcoded #bbb, #555, #000, #666, #ddd and #4a6f8a, and set no background at all, so on a dark desktop plain-text mail rendered as black on white inside a dark window and the web view's own default showed through. The colours now come from a Palette struct derived from QPalette, and are passed into the builder rather than read from qApp inside it, so the stylesheet can be tested against a known palette with no running application. Base and Text rather than Window and WindowText: the pane is a content surface like a text edit, and on many themes those differ. The secondary colours are blends of text and background, not fixed greys. That is the part that makes it work both ways round, since a #555 chosen to read as subtle on white is nearly invisible on #2b2b2b. The quote colour keeps its hue, because "this is quoted" is carried by being a different colour rather than a dimmer one, but is pulled toward the background so it stays readable instead of glowing on dark. A sender's own HTML is deliberately left alone, and a test asserts that so it cannot drift: rewriting a sender's styling would break layouts that depend on it, and a newsletter setting a white background is entitled to stay white. This themes the plain-text render and the chrome around messages, nothing more. MessageView passes its own widget palette rather than the application's, since a style sheet or a themed parent can give the pane different colours from qApp, and re-renders on PaletteChange: the document's colours are baked into its stylesheet at build time, so unlike a widget it does not restyle itself when the desktop theme changes. The load-bearing test asserts the negative, that no hex colour appears in the style block which the palette did not supply. A test checking only that the palette's colours are present passes with a leftover literal still there, and one leftover literal is the whole defect. Confirmed by mutation. Closes item 12. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/htmlbuilder.h')
-rw-r--r--src/htmlbuilder.h40
1 files changed, 39 insertions, 1 deletions
diff --git a/src/htmlbuilder.h b/src/htmlbuilder.h
index 6e306dd..75fd1f8 100644
--- a/src/htmlbuilder.h
+++ b/src/htmlbuilder.h
@@ -18,7 +18,9 @@
#pragma once
+#include <QColor>
#include <QList>
+#include <QPalette>
#include "mimeparser.h"
@@ -60,11 +62,46 @@ public:
ForcePlain, ///< Always render the plain part, escaped.
};
+ /// The colours the document's own stylesheet uses.
+ ///
+ /// Passed in rather than read from qApp inside the builder, so the CSS can
+ /// be tested against a known palette without a running application, and so
+ /// nothing here depends on widget state.
+ ///
+ /// **Scope.** These style the chrome around messages and the plain-text
+ /// render. A message that brings its own HTML brings its own colours, and
+ /// those are deliberately left alone: rewriting a sender's styling would
+ /// break layouts that depend on it, and a newsletter that sets a white
+ /// background is entitled to stay white.
+ struct Palette {
+ QColor background; ///< The pane itself.
+ QColor text; ///< Body text.
+ QColor dim; ///< Headers and stubs: present but secondary.
+ QColor border; ///< Rules between messages.
+ QColor quote; ///< Quoted lines in plain text.
+ };
+
+ /// Derives the document palette from a widget palette.
+ ///
+ /// The dim and border colours are blends rather than fixed greys, which is
+ /// what makes this work on a dark theme: a hardcoded #555 that reads as
+ /// "subtle" on white is nearly invisible on near-black.
+ static Palette paletteFrom(const QPalette &palette);
+
+ /// The palette used when a caller supplies none: the running application's.
+ /// Falls back to a light default with no QApplication, which only happens
+ /// in a test that did not ask for a palette.
+ static Palette defaultPalette();
+
/// Single message, used for the error card and for tests.
static QString build(const ParsedMessage &message, Mode mode);
+ static QString build(const ParsedMessage &message, Mode mode,
+ const Palette &palette);
/// The whole thread, oldest first.
static QString buildThread(const QList<ThreadRenderItem> &items, Mode mode);
+ static QString buildThread(const QList<ThreadRenderItem> &items, Mode mode,
+ const Palette &palette);
/// Rewrites cid: URLs in an HTML body to their namespaced form.
static QString namespaceCids(const QString &html, const QString &prefix);
@@ -73,5 +110,6 @@ private:
static QString renderPlain(const QString &text);
static QString renderBody(const ThreadRenderItem &item, Mode mode);
static QString renderStub(const ParsedMessage &message);
- static QString document(const QString &bodyHtml);
+ static QString document(const QString &bodyHtml, const Palette &palette);
+ static QString styleSheet(const Palette &palette);
};