[LyX/master] Adapt math and IPA panels to dark theme (#5636)

Juergen Spitzmueller spitz at lyx.org
Fri Dec 11 07:38:55 UTC 2020


commit a06cdfa0736c7ab0830a3fde51231949a5a40913
Author: Juergen Spitzmueller <spitz at lyx.org>
Date:   Fri Dec 11 09:08:41 2020 +0100

    Adapt math and IPA panels to dark theme (#5636)
---
 src/frontends/qt/GuiApplication.cpp |   82 ++++++++++++++++++++++++++++------
 src/frontends/qt/GuiApplication.h   |    8 +++
 2 files changed, 75 insertions(+), 15 deletions(-)

diff --git a/src/frontends/qt/GuiApplication.cpp b/src/frontends/qt/GuiApplication.cpp
index 9ff6d2c..8e4d48a 100644
--- a/src/frontends/qt/GuiApplication.cpp
+++ b/src/frontends/qt/GuiApplication.cpp
@@ -86,6 +86,7 @@
 #include <tuple>
 
 #include <QByteArray>
+#include <QBitmap>
 #include <QDateTime>
 #include <QDesktopWidget>
 #include <QEvent>
@@ -102,6 +103,7 @@
 #include <QMenuBar>
 #include <QMimeData>
 #include <QObject>
+#include <QPainter>
 #include <QPixmap>
 #include <QRegExp>
 #include <QSessionManager>
@@ -475,9 +477,10 @@ QString themeIconName(QString const & action)
 }
 
 
-// the returned bool is true if the icon needs to be flipped
-pair<QString,bool> iconName(FuncRequest const & f, bool unknown, bool rtl)
+IconInfo iconInfo(FuncRequest const & f, bool unknown, bool rtl)
 {
+	IconInfo res;
+
 	QStringList names;
 	QString lfunname = toqstr(lyxaction.getActionName(f.action()));
 
@@ -539,16 +542,61 @@ pair<QString,bool> iconName(FuncRequest const & f, bool unknown, bool rtl)
 			for (QString const & suffix : suffixes) {
 				QString id = imagedir;
 				FileName fname = imageLibFileSearch(id, name + suffix, "svgz,png", mode);
-				if (fname.exists())
-					return make_pair(toqstr(fname.absFileName()),
-					                 rtl && suffix.isEmpty());
+				if (fname.exists()) {
+					docstring const fpath = fname.absoluteFilePath();
+					res.filepath = toqstr(fname.absFileName());
+					// these icons are subject to inversion in dark mode
+					res.invert = (contains(fpath, from_ascii("math")) || contains(fpath, from_ascii("ert-insert"))
+						      || suffixIs(fname.onlyPath().absoluteFilePath(), from_ascii("ipa")));
+					res.swap = rtl && suffix.isEmpty();
+					return res;
+				}
 			}
 
 	LYXERR(Debug::GUI, "Cannot find icon for command \""
 			   << lyxaction.getActionName(f.action())
 			   << '(' << to_utf8(f.argument()) << ")\"");
 
-	return make_pair(QString(), false);
+	return res;
+}
+
+
+QPixmap prepareForDarkMode(QPixmap pixmap)
+{
+	QPalette palette = QPalette();
+	QColor text_color = palette.color(QPalette::Active, QPalette::WindowText);
+	QColor bg_color = palette.color(QPalette::Active, QPalette::Window);
+
+	// guess whether we are in dark mode
+	if (text_color.black() > bg_color.black())
+		// not in dark mode, do nothing
+		return pixmap;
+
+	// create a layer with black text turned to QPalette::WindowText
+	QPixmap black_overlay(pixmap.size());
+	black_overlay.fill(text_color);
+	black_overlay.setMask(pixmap.createMaskFromColor(Qt::black, Qt::MaskOutColor));
+
+	// create a layer with blue text turned to lighter blue
+	QPixmap blue_overlay(pixmap.size());
+	QColor math_blue(0, 0, 255);
+	blue_overlay.fill(math_blue.lighter());
+	blue_overlay.setMask(pixmap.createMaskFromColor(math_blue, Qt::MaskOutColor));
+
+	// create a layer with ("latex") red text turned to lighter red
+	QPixmap red_overlay(pixmap.size());
+	QColor math_red(128, 0, 0);
+	QColor math_red_light(233, 175, 175);
+	red_overlay.fill(math_red_light);
+	red_overlay.setMask(pixmap.createMaskFromColor(math_red, Qt::MaskOutColor));
+
+	// put layers on top of existing pixmap
+	QPainter painter(&pixmap);
+	painter.drawPixmap(pixmap.rect(), black_overlay);
+	painter.drawPixmap(pixmap.rect(), blue_overlay);
+	painter.drawPixmap(pixmap.rect(), red_overlay);
+
+	return pixmap;
 }
 
 
@@ -559,8 +607,11 @@ QPixmap getPixmap(QString const & path, QString const & name, QString const & ex
 	QString fpath = toqstr(fname.absFileName());
 	QPixmap pixmap = QPixmap();
 
-	if (pixmap.load(fpath))
+	if (pixmap.load(fpath)) {
+		if (fpath.contains("math") || fpath.contains("ipa"))
+			return prepareForDarkMode(pixmap);
 		return pixmap;
+	}
 
 	bool const list = ext.contains(",");
 	LYXERR(Debug::GUI, "Cannot load pixmap \""
@@ -588,20 +639,21 @@ QIcon getIcon(FuncRequest const & f, bool unknown, bool rtl)
 	}
 #endif
 
-	QString icon;
-	bool flip;
-	tie(icon, flip) = iconName(f, unknown, rtl);
-	if (icon.isEmpty())
+	IconInfo icondata = iconInfo(f, unknown, rtl);
+	if (icondata.filepath.isEmpty())
 		return QIcon();
 
 	//LYXERR(Debug::GUI, "Found icon: " << icon);
 	QPixmap pixmap = QPixmap();
-	if (!pixmap.load(icon)) {
-		LYXERR0("Cannot load icon " << icon << ".");
+	if (!pixmap.load(icondata.filepath)) {
+		LYXERR0("Cannot load icon " << icondata.filepath << ".");
 		return QIcon();
 	}
 
-	if (flip)
+	if (icondata.invert)
+		pixmap = prepareForDarkMode(pixmap);
+
+	if (icondata.swap)
 		return QIcon(pixmap.transformed(QTransform().scale(-1, 1)));
 	else
 		return QIcon(pixmap);
@@ -1129,7 +1181,7 @@ void GuiApplication::clearSession()
 
 docstring Application::iconName(FuncRequest const & f, bool unknown)
 {
-	return qstring_to_ucs4(lyx::frontend::iconName(f, unknown, false).first);
+	return qstring_to_ucs4(lyx::frontend::iconInfo(f, unknown, false).filepath);
 }
 
 
diff --git a/src/frontends/qt/GuiApplication.h b/src/frontends/qt/GuiApplication.h
index f37e252..e6a96c3 100644
--- a/src/frontends/qt/GuiApplication.h
+++ b/src/frontends/qt/GuiApplication.h
@@ -264,6 +264,14 @@ private:
 
 extern GuiApplication * guiApp;
 
+struct IconInfo {
+	/// Absolute path to icon file
+	QString filepath;
+	/// Swap the icon in RTL mode
+	bool swap;
+	/// Invert the icon in dark mode
+	bool invert;
+};
 
 /// \return the pixmap for the given path, name and extension.
 /// in case of errors a warning is produced and an empty pixmap is returned.


More information about the lyx-cvs mailing list