Allow adjusting lighter and darker as well in theme files

This commit is contained in:
Veronica Berglyd Olsen
2025-06-04 21:09:35 +02:00
parent 8ce6c678aa
commit 0ab33e1843
2 changed files with 58 additions and 42 deletions
+32 -27
View File
@@ -244,32 +244,6 @@ class GuiTheme:
window = palette.window().color() window = palette.window().color()
return text.lightnessF() > window.lightnessF() return text.lightnessF() > window.lightnessF()
def parseColor(self, value: str, default: QColor = QtBlack) -> QColor:
"""Parse a string as a colour value."""
if value in self._qColors:
# Named colour
return self._qColors[value]
elif value.startswith("#") and len(value) == 7:
# Assume #RRGGBB
return QColor.fromString(value)
elif value.startswith("#") and len(value) == 9:
# Assume #RRGGBBAA and convert to #AARRGGBB
return QColor.fromString(f"#{value[7:9]}{value[1:7]}")
elif ":" in value:
# Colour name and alpha
name, _, alpha = value.partition(":")
color = QColor(self._qColors.get(name.strip(), default))
color.setAlpha(checkInt(alpha, 255))
return color
elif "," in value:
# Integer red, green, blue, alpha
data = value.split(",")
result = [0, 0, 0, 255]
for i in range(min(len(data), 4)):
result[i] = checkInt(data[i].strip(), result[i])
return QColor(*result)
return default
def loadTheme(self, force: bool = False) -> bool: def loadTheme(self, force: bool = False) -> bool:
"""Load the currently specified GUI theme. The boolean return """Load the currently specified GUI theme. The boolean return
can be used to determine if the GUI needs refreshing. can be used to determine if the GUI needs refreshing.
@@ -489,6 +463,37 @@ class GuiTheme:
# Internal Functions # Internal Functions
## ##
def _parseColor(self, value: str, default: QColor = QtBlack) -> QColor:
"""Parse a string as a colour value."""
if value in self._qColors:
# Named colour
return self._qColors[value]
elif value.startswith("#") and len(value) == 7:
# Assume #RRGGBB
return QColor.fromString(value)
elif value.startswith("#") and len(value) == 9:
# Assume #RRGGBBAA and convert to #AARRGGBB
return QColor.fromString(f"#{value[7:9]}{value[1:7]}")
elif ":" in value:
# Colour name and alpha
name, _, adjust = value.partition(":")
color = QColor(self._qColors.get(name.strip(), default))
if adjust.startswith("L"):
color = color.lighter(checkInt(adjust[1:], 100))
elif adjust.startswith("D"):
color = color.darker(checkInt(adjust[1:], 100))
else:
color.setAlpha(checkInt(adjust, 255))
return color
elif "," in value:
# Integer red, green, blue, alpha
data = value.split(",")
result = [0, 0, 0, 255]
for i in range(min(len(data), 4)):
result[i] = checkInt(data[i].strip(), result[i])
return QColor(*result)
return default
def _setBaseColor(self, key: str, color: QColor) -> None: def _setBaseColor(self, key: str, color: QColor) -> None:
"""Set the colour for a named colour.""" """Set the colour for a named colour."""
self._qColors[key] = QColor(color) self._qColors[key] = QColor(color)
@@ -544,7 +549,7 @@ class GuiTheme:
def _readColor(self, parser: ConfigParser, section: str, name: str) -> QColor: def _readColor(self, parser: ConfigParser, section: str, name: str) -> QColor:
"""Parse a colour value from a config string.""" """Parse a colour value from a config string."""
return self.parseColor(parser.get(section, name, fallback="default")) return self._parseColor(parser.get(section, name, fallback="default"))
def _setPalette( def _setPalette(
self, parser: ConfigParser, section: str, name: str, value: QPalette.ColorRole self, parser: ConfigParser, section: str, name: str, value: QPalette.ColorRole
+26 -15
View File
@@ -52,29 +52,40 @@ def testGuiTheme_ParseColor():
theme._qColors["red"] = QColor(255, 0, 0) theme._qColors["red"] = QColor(255, 0, 0)
theme._qColors["green"] = QColor(0, 255, 0) theme._qColors["green"] = QColor(0, 255, 0)
theme._qColors["blue"] = QColor(0, 0, 255) theme._qColors["blue"] = QColor(0, 0, 255)
theme._qColors["grey"] = QColor(127, 127, 127)
# By Name # By Name
assert theme.parseColor("red").getRgb() == (255, 0, 0, 255) assert theme._parseColor("red").getRgb() == (255, 0, 0, 255)
assert theme.parseColor("green").getRgb() == (0, 255, 0, 255) assert theme._parseColor("green").getRgb() == (0, 255, 0, 255)
assert theme.parseColor("blue").getRgb() == (0, 0, 255, 255) assert theme._parseColor("blue").getRgb() == (0, 0, 255, 255)
assert theme.parseColor("bob").getRgb() == (0, 0, 0, 255) assert theme._parseColor("bob").getRgb() == (0, 0, 0, 255)
# CSS Format # CSS Format
assert theme.parseColor("#ff0000").getRgb() == (255, 0, 0, 255) assert theme._parseColor("#ff0000").getRgb() == (255, 0, 0, 255)
assert theme.parseColor("#ff00007f").getRgb() == (255, 0, 0, 127) assert theme._parseColor("#ff00007f").getRgb() == (255, 0, 0, 127)
assert theme.parseColor("#ff00").getRgb() == (0, 0, 0, 255) # Too short -> ignored assert theme._parseColor("#ff00").getRgb() == (0, 0, 0, 255) # Too short -> ignored
assert theme.parseColor("#ff00007f15").getRgb() == (0, 0, 0, 255) # Too long -> ignored assert theme._parseColor("#ff00007f15").getRgb() == (0, 0, 0, 255) # Too long -> ignored
# Name + Alpha # Name + Alpha
assert theme.parseColor("red:255").getRgb() == (255, 0, 0, 255) assert theme._parseColor("red:255").getRgb() == (255, 0, 0, 255)
assert theme.parseColor("red:127").getRgb() == (255, 0, 0, 127) assert theme._parseColor("red:127").getRgb() == (255, 0, 0, 127)
assert theme.parseColor("red:512").getRgb() == (255, 0, 0, 255) # Value truncated assert theme._parseColor("red:512").getRgb() == (255, 0, 0, 255) # Value truncated
# Name + Lighter
assert theme._parseColor("grey:L100").getRgb() == (127, 127, 127, 255)
assert theme._parseColor("grey:L150").getRgb() == (190, 190, 190, 255)
assert theme._parseColor("grey:L50").getRgb() == (63, 63, 63, 255)
# Name + Darker
assert theme._parseColor("grey:D100").getRgb() == (127, 127, 127, 255)
assert theme._parseColor("grey:D150").getRgb() == (85, 85, 85, 255)
assert theme._parseColor("grey:D50").getRgb() == (254, 254, 254, 255)
# Values # Values
assert theme.parseColor("255, 0, 0").getRgb() == (255, 0, 0, 255) assert theme._parseColor("255, 0, 0").getRgb() == (255, 0, 0, 255)
assert theme.parseColor("255, 0, 0, 255").getRgb() == (255, 0, 0, 255) assert theme._parseColor("255, 0, 0, 255").getRgb() == (255, 0, 0, 255)
assert theme.parseColor("255, 0, 0, 127").getRgb() == (255, 0, 0, 127) assert theme._parseColor("255, 0, 0, 127").getRgb() == (255, 0, 0, 127)
assert theme.parseColor("255, 0, 0, 127, 42").getRgb() == (255, 0, 0, 127) # Truncated assert theme._parseColor("255, 0, 0, 127, 42").getRgb() == (255, 0, 0, 127) # Truncated
@pytest.mark.gui @pytest.mark.gui