From e66288b4defc680070037784aabf1613761de085 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:55:49 +0100 Subject: [PATCH] Add basic support for loading icons from a single file --- novelwriter/gui/theme.py | 58 ++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 11dd1fa8..553786c2 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -38,6 +38,7 @@ from novelwriter.common import NWConfigParser, cssCol, minmax from novelwriter.constants import nwLabels from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType from novelwriter.error import logException +from novelwriter.types import QtTransparent logger = logging.getLogger(__name__) @@ -245,6 +246,18 @@ class GuiTheme: self.themeLicenseUrl = parser.rdStr(sec, "licenseurl", "") self.themeIcons = parser.rdStr(sec, "icontheme", "") + # Icons + sec = "Icons" + if parser.has_section(sec): + self.iconCache.setIconColor("default", self._parseColour(parser, sec, "default")) + self.iconCache.setIconColor("red", self._parseColour(parser, sec, "red")) + self.iconCache.setIconColor("orange", self._parseColour(parser, sec, "orange")) + self.iconCache.setIconColor("yellow", self._parseColour(parser, sec, "yellow")) + self.iconCache.setIconColor("green", self._parseColour(parser, sec, "green")) + self.iconCache.setIconColor("aqua", self._parseColour(parser, sec, "aqua")) + self.iconCache.setIconColor("blue", self._parseColour(parser, sec, "blue")) + self.iconCache.setIconColor("purple", self._parseColour(parser, sec, "purple")) + # Palette sec = "Palette" if parser.has_section(sec): @@ -294,6 +307,7 @@ class GuiTheme: # Icons defaultIcons = "typicons_light" if backLNess >= 0.5 else "typicons_dark" self.iconCache.loadTheme(self.themeIcons or defaultIcons) + self.iconCache.loadNewTheme("") # Apply Styles QApplication.setPalette(self._guiPalette) @@ -540,6 +554,9 @@ class GuiIcons: self.mainTheme = mainTheme # Storage + self._svgData: dict[str, bytes] = {} + self._svgColours: dict[str, bytes] = {} + self._qIcons: dict[str, QIcon] = {} self._themeMap: dict[str, Path] = {} self._headerDec: list[QPixmap] = [] @@ -638,6 +655,22 @@ class GuiIcons: return True + def loadNewTheme(self, iconTheme: str) -> bool: + """Load new style theme.""" + themePath = self._iconPath / "material_outline_normal.icons" + with open(themePath, mode="r", encoding="utf-8") as icons: + for icon in icons: + key, _, svg = icon.partition(" = ") + if key and svg: + self._svgData[key.strip()] = svg.strip().encode("utf-8") + + return True + + def setIconColor(self, key: str, color: QColor) -> None: + """Set an icon colour for a named colour.""" + self._svgColours[key] = color.name(QColor.NameFormat.HexRgb).encode("utf-8") + return + ## # Access Functions ## @@ -670,13 +703,14 @@ class GuiIcons: return pixmap - def getIcon(self, name: str) -> QIcon: + def getIcon(self, name: str, color: str | None = None) -> QIcon: """Return an icon from the icon buffer, or load it.""" - if name in self._qIcons: + key = f"{name}_{color}" if color else name + if key in self._qIcons: return self._qIcons[name] else: - icon = self._loadIcon(name) - self._qIcons[name] = icon + icon = self._loadIcon(name, color) + self._qIcons[key] = icon return icon def getToggleIcon(self, name: str, size: tuple[int, int]) -> QIcon: @@ -755,13 +789,13 @@ class GuiIcons: # Internal Functions ## - def _loadIcon(self, name: str) -> QIcon: + def _loadIcon(self, name: str, color: str | None = None) -> QIcon: """Load an icon from the assets themes folder. Is guaranteed to return a QIcon. """ - if name not in self.ICON_KEYS: - logger.error("Requested unknown icon name '%s'", name) - return self._noIcon + # if name not in self.ICON_KEYS: + # logger.error("Requested unknown icon name '%s'", name) + # return self._noIcon # If we just want the app icons, return right away if name == "novelwriter": @@ -769,6 +803,14 @@ class GuiIcons: elif name == "proj_nwx": return QIcon(str(self._iconPath / "x-novelwriter-project.svg")) + if svg := self._svgData.get(name, b""): + if fill := self._svgColours.get(color or "default"): + svg = svg.replace(b"#000000", fill) + pixmap = QPixmap(24, 24) + pixmap.fill(QtTransparent) + pixmap.loadFromData(svg, "svg") + return QIcon(pixmap) + # Otherwise, we load from the theme folder if name in self._themeMap: logger.debug("Loading: %s", self._themeMap[name].name)