Add basic support for loading icons from a single file

This commit is contained in:
Veronica Berglyd Olsen
2025-01-07 17:55:49 +01:00
parent 362da679b6
commit e66288b4de
+50 -8
View File
@@ -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)