mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Make mdi icons for Qt themeable (#2078)
* Fix create_vars_from_map not creating vars with default definition * Add white and black to vars * Replace some hard-coded SVGs with mdi equivalents * Implement function to dynamically adjust SVG icon color * Use new svg function to make Qt stylesheet icons respond to theme changes * Use svg function for sidebar tool icons * Create copy for each new color instead of modifying source file * Fix check fails * Add custom checkbox style for #2079 * Add example of how to generate svgs during build (dae) * Create arbitrary color variants for each icon with Bazel * Remove unused label (dae)
This commit is contained in:
parent
e109c62aa9
commit
bff76727fe
13 changed files with 276 additions and 296 deletions
|
@ -2,7 +2,6 @@ load("@rules_python//python:defs.bzl", "py_library")
|
||||||
load("@py_deps//:requirements.bzl", "requirement")
|
load("@py_deps//:requirements.bzl", "requirement")
|
||||||
load("@rules_python//python:packaging.bzl", "py_package", "py_wheel")
|
load("@rules_python//python:packaging.bzl", "py_package", "py_wheel")
|
||||||
load("//:defs.bzl", "anki_version")
|
load("//:defs.bzl", "anki_version")
|
||||||
|
|
||||||
load("//ts:copy.bzl", "copy_files_into_group")
|
load("//ts:copy.bzl", "copy_files_into_group")
|
||||||
load("//ts:compile_sass.bzl", "compile_sass")
|
load("//ts:compile_sass.bzl", "compile_sass")
|
||||||
|
|
||||||
|
@ -31,13 +30,22 @@ genrule(
|
||||||
srcs = [
|
srcs = [
|
||||||
"_vars.css",
|
"_vars.css",
|
||||||
],
|
],
|
||||||
outs = ["colors.py", "props.py"],
|
outs = [
|
||||||
|
"colors.py",
|
||||||
|
"props.py",
|
||||||
|
],
|
||||||
cmd = "$(location //qt:extract_sass_vars) $(SRCS) $(OUTS)",
|
cmd = "$(location //qt:extract_sass_vars) $(SRCS) $(OUTS)",
|
||||||
tools = [
|
tools = [
|
||||||
"//qt:extract_sass_vars",
|
"//qt:extract_sass_vars",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
py_library(
|
||||||
|
name = "colors",
|
||||||
|
srcs = [":colors.py"],
|
||||||
|
visibility = ["//qt:__subpackages__"],
|
||||||
|
)
|
||||||
|
|
||||||
_py_srcs = glob(
|
_py_srcs = glob(
|
||||||
[
|
[
|
||||||
"**/*.py",
|
"**/*.py",
|
||||||
|
|
|
@ -20,8 +20,16 @@ class SidebarTool(Enum):
|
||||||
|
|
||||||
class SidebarToolbar(QToolBar):
|
class SidebarToolbar(QToolBar):
|
||||||
_tools: tuple[tuple[SidebarTool, str, Callable[[], str]], ...] = (
|
_tools: tuple[tuple[SidebarTool, str, Callable[[], str]], ...] = (
|
||||||
(SidebarTool.SEARCH, "icons:magnifying_glass.svg", tr.actions_search),
|
(
|
||||||
(SidebarTool.SELECT, "icons:select.svg", tr.actions_select),
|
SidebarTool.SEARCH,
|
||||||
|
"mdi:magnify",
|
||||||
|
tr.actions_search,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SidebarTool.SELECT,
|
||||||
|
"mdi:selection-drag",
|
||||||
|
tr.actions_select,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, sidebar: aqt.browser.sidebar.SidebarTreeView) -> None:
|
def __init__(self, sidebar: aqt.browser.sidebar.SidebarTreeView) -> None:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
load("//ts:vendor.bzl", "copy_mdi_icons")
|
load("//ts:vendor.bzl", "copy_mdi_icons")
|
||||||
|
load("color_svg.bzl", "color_svg")
|
||||||
|
|
||||||
copy_mdi_icons(
|
copy_mdi_icons(
|
||||||
name = "mdi-icons",
|
name = "mdi-icons",
|
||||||
|
@ -33,6 +34,19 @@ copy_mdi_icons(
|
||||||
# tags
|
# tags
|
||||||
"tag-outline.svg",
|
"tag-outline.svg",
|
||||||
"tag-off-outline.svg",
|
"tag-off-outline.svg",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
copy_mdi_icons(
|
||||||
|
name = "mdi-themed",
|
||||||
|
icons = [
|
||||||
|
# sidebar tools
|
||||||
|
"magnify.svg",
|
||||||
|
"selection-drag.svg",
|
||||||
|
|
||||||
|
# QComboBox arrows
|
||||||
|
"chevron-up.svg",
|
||||||
|
"chevron-down.svg",
|
||||||
|
|
||||||
# QHeaderView arrows
|
# QHeaderView arrows
|
||||||
"menu-up.svg",
|
"menu-up.svg",
|
||||||
|
@ -41,12 +55,73 @@ copy_mdi_icons(
|
||||||
# drag handle
|
# drag handle
|
||||||
"drag-vertical.svg",
|
"drag-vertical.svg",
|
||||||
"drag-horizontal.svg",
|
"drag-horizontal.svg",
|
||||||
|
|
||||||
|
# checkbox
|
||||||
|
"check.svg",
|
||||||
|
"minus-thick.svg",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
py_binary(
|
||||||
|
name = "color_svg",
|
||||||
|
srcs = [
|
||||||
|
"color_svg.py",
|
||||||
|
"//qt/aqt:colors",
|
||||||
|
],
|
||||||
|
imports = ["."],
|
||||||
|
visibility = [":__subpackages__"],
|
||||||
|
)
|
||||||
|
|
||||||
|
color_svg(
|
||||||
|
name = "magnify",
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "selection-drag",
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "chevron-up",
|
||||||
|
extra_colors = ["FG_DISABLED"],
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "chevron-down",
|
||||||
|
extra_colors = ["FG_DISABLED"],
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "menu-up",
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "menu-down",
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "drag-vertical",
|
||||||
|
extra_colors = ["FG_SUBTLE"],
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "drag-horizontal",
|
||||||
|
extra_colors = ["FG_SUBTLE"],
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "check",
|
||||||
|
)
|
||||||
|
color_svg(
|
||||||
|
name = "minus-thick",
|
||||||
|
)
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "icons",
|
name = "icons",
|
||||||
srcs = ["mdi-icons"] + glob([
|
srcs = [
|
||||||
|
"mdi-icons",
|
||||||
|
"magnify",
|
||||||
|
"selection-drag",
|
||||||
|
"chevron-up",
|
||||||
|
"chevron-down",
|
||||||
|
"menu-up",
|
||||||
|
"menu-down",
|
||||||
|
"drag-vertical",
|
||||||
|
"drag-horizontal",
|
||||||
|
"check",
|
||||||
|
"minus-thick",
|
||||||
|
] + glob([
|
||||||
"*.svg",
|
"*.svg",
|
||||||
"*.png",
|
"*.png",
|
||||||
]),
|
]),
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
||||||
<path fill="#f4f4f4" d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" />
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 157 B |
|
@ -1,3 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
||||||
<path fill="#f4f4f4" d="M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z" />
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 159 B |
30
qt/aqt/data/qt/icons/color_svg.bzl
Normal file
30
qt/aqt/data/qt/icons/color_svg.bzl
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
def color_svg(name, extra_colors = [], visibility = ["//qt:__submodules__"]):
|
||||||
|
native.genrule(
|
||||||
|
name = name,
|
||||||
|
srcs = ["mdi-themed"],
|
||||||
|
outs = [
|
||||||
|
name + "-light.svg",
|
||||||
|
] + [
|
||||||
|
# additional light colors
|
||||||
|
"{}{}{}".format(
|
||||||
|
name,
|
||||||
|
"-{}".format(color),
|
||||||
|
"-light.svg"
|
||||||
|
) for color in extra_colors
|
||||||
|
] + [
|
||||||
|
name + "-dark.svg",
|
||||||
|
] + [
|
||||||
|
# additional dark colors
|
||||||
|
"{}{}{}".format(
|
||||||
|
name,
|
||||||
|
"-{}".format(color),
|
||||||
|
"-dark.svg"
|
||||||
|
) for color in extra_colors
|
||||||
|
],
|
||||||
|
cmd = "$(location color_svg) {}.svg {} $(OUTS) $(SRCS)".format(
|
||||||
|
name, ":".join(["FG"] + extra_colors)
|
||||||
|
),
|
||||||
|
tools = [
|
||||||
|
"color_svg",
|
||||||
|
],
|
||||||
|
)
|
47
qt/aqt/data/qt/icons/color_svg.py
Normal file
47
qt/aqt/data/qt/icons/color_svg.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from qt.aqt import colors
|
||||||
|
|
||||||
|
input_filename = sys.argv[1]
|
||||||
|
input_name = input_filename.replace(".svg", "")
|
||||||
|
color_names = sys.argv[2].split(":")
|
||||||
|
|
||||||
|
# two files created for each additional color
|
||||||
|
offset = len(color_names) * 2
|
||||||
|
svg_paths = sys.argv[3 : 3 + offset]
|
||||||
|
|
||||||
|
# as we've received a group of files, we need to manually join the path
|
||||||
|
input_folder = Path(sys.argv[4]).parent
|
||||||
|
input_svg = input_folder / input_filename
|
||||||
|
|
||||||
|
with open(input_svg, "r") as f:
|
||||||
|
svg_data = f.read()
|
||||||
|
|
||||||
|
for color_name in color_names:
|
||||||
|
color = getattr(colors, color_name)
|
||||||
|
light_svg = dark_svg = ""
|
||||||
|
|
||||||
|
if color_name == "FG":
|
||||||
|
prefix = input_name
|
||||||
|
else:
|
||||||
|
prefix = f"{input_name}-{color_name}"
|
||||||
|
|
||||||
|
for path in svg_paths:
|
||||||
|
if f"{prefix}-light.svg" in path:
|
||||||
|
light_svg = path
|
||||||
|
elif f"{prefix}-dark.svg" in path:
|
||||||
|
dark_svg = path
|
||||||
|
|
||||||
|
for (idx, filename) in enumerate((light_svg, dark_svg)):
|
||||||
|
data = svg_data
|
||||||
|
if "fill" in data:
|
||||||
|
data = re.sub(r"fill=\"#.+?\"", f'fill="{color[idx]}"', data)
|
||||||
|
else:
|
||||||
|
data = re.sub(r"<svg", f'<svg fill="{color[idx]}"', data, 1)
|
||||||
|
with open(filename, "w") as f:
|
||||||
|
f.write(data)
|
|
@ -1,84 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="64"
|
|
||||||
height="64"
|
|
||||||
viewBox="0 0 16.933333 16.933334"
|
|
||||||
version="1.1"
|
|
||||||
id="svg8"
|
|
||||||
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)"
|
|
||||||
sodipodi:docname="magnifying_glass.svg">
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="8"
|
|
||||||
inkscape:cx="10.039334"
|
|
||||||
inkscape:cy="35.645602"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
inkscape:document-rotation="0"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1017"
|
|
||||||
inkscape:window-x="-8"
|
|
||||||
inkscape:window-y="-8"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
gridtolerance="10000"
|
|
||||||
objecttolerance="51"
|
|
||||||
guidetolerance="51"
|
|
||||||
inkscape:snap-global="false">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid833" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata5">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Ebene 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<circle
|
|
||||||
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.38115;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
|
||||||
id="path835"
|
|
||||||
cx="5.5429349"
|
|
||||||
cy="5.5176048"
|
|
||||||
r="4.7567849" />
|
|
||||||
<g
|
|
||||||
id="path837"
|
|
||||||
style="opacity:1"
|
|
||||||
transform="translate(0.280633,0.25724692)">
|
|
||||||
<path
|
|
||||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.1866;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
|
||||||
d="m 9.270412,9.1682417 5.763677,5.8797903"
|
|
||||||
id="path3348" />
|
|
||||||
<path
|
|
||||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.997025;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
|
||||||
d="M 8.519367,8.5427531 C 7.9111727,9.1535363 7.8640343,9.5551464 8.1618931,9.8774543 l 5.8029559,6.2792797 c 0.603423,0.638261 1.591613,0.648031 2.206659,0.0218 0.614172,-0.625577 0.623586,-1.648878 0.02103,-2.286493 0,0 -6.025394,-5.3742675 -6.3649177,-5.6724746 C 9.4880962,7.9213592 9.1275613,7.9319698 8.519367,8.5427531 Z"
|
|
||||||
id="path3350"
|
|
||||||
sodipodi:nodetypes="zzccczz" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 5.3 KiB |
|
@ -1,168 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="64"
|
|
||||||
height="64"
|
|
||||||
viewBox="0 0 16.933333 16.933334"
|
|
||||||
version="1.1"
|
|
||||||
id="svg8"
|
|
||||||
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)"
|
|
||||||
sodipodi:docname="select.svg">
|
|
||||||
<defs
|
|
||||||
id="defs2">
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="powermask"
|
|
||||||
id="path-effect4000"
|
|
||||||
is_visible="true"
|
|
||||||
lpeversion="1"
|
|
||||||
uri="#mask-powermask-path-effect4000"
|
|
||||||
invert="false"
|
|
||||||
hide_mask="false"
|
|
||||||
background="true"
|
|
||||||
background_color="#ffffffff" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="powermask"
|
|
||||||
id="path-effect3981"
|
|
||||||
is_visible="true"
|
|
||||||
lpeversion="1"
|
|
||||||
uri="#mask-powermask-path-effect3981"
|
|
||||||
invert="false"
|
|
||||||
hide_mask="false"
|
|
||||||
background="true"
|
|
||||||
background_color="#ffffffff" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="powermask"
|
|
||||||
id="path-effect3966"
|
|
||||||
is_visible="true"
|
|
||||||
lpeversion="1"
|
|
||||||
uri="#mask-powermask-path-effect3966"
|
|
||||||
invert="false"
|
|
||||||
hide_mask="false"
|
|
||||||
background="true"
|
|
||||||
background_color="#ffffffff" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="powermask"
|
|
||||||
id="path-effect2895"
|
|
||||||
is_visible="true"
|
|
||||||
lpeversion="1"
|
|
||||||
uri="#mask-powermask-path-effect2895"
|
|
||||||
invert="false"
|
|
||||||
hide_mask="false"
|
|
||||||
background="true"
|
|
||||||
background_color="#ffffffff" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient866"
|
|
||||||
osb:paint="solid">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#838799;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop864" />
|
|
||||||
</linearGradient>
|
|
||||||
<marker
|
|
||||||
style="overflow:visible"
|
|
||||||
id="Arrow1Lstart"
|
|
||||||
refX="0.0"
|
|
||||||
refY="0.0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow1Lstart"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
transform="scale(0.8) translate(12.5,0)"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
|
|
||||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
|
||||||
id="path2747" />
|
|
||||||
</marker>
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 8.466667 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="16.933333 : 8.466667 : 1"
|
|
||||||
inkscape:persp3d-origin="8.4666665 : 5.6444447 : 1"
|
|
||||||
id="perspective2694" />
|
|
||||||
<filter
|
|
||||||
id="mask-powermask-path-effect4000_inverse"
|
|
||||||
inkscape:label="filtermask-powermask-path-effect4000"
|
|
||||||
style="color-interpolation-filters:sRGB"
|
|
||||||
height="100"
|
|
||||||
width="100"
|
|
||||||
x="-50"
|
|
||||||
y="-50">
|
|
||||||
<feColorMatrix
|
|
||||||
id="mask-powermask-path-effect4000_primitive1"
|
|
||||||
values="1"
|
|
||||||
type="saturate"
|
|
||||||
result="fbSourceGraphic" />
|
|
||||||
<feColorMatrix
|
|
||||||
id="mask-powermask-path-effect4000_primitive2"
|
|
||||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 "
|
|
||||||
in="fbSourceGraphic" />
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="9.1371454"
|
|
||||||
inkscape:cx="33.803843"
|
|
||||||
inkscape:cy="32.605832"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
inkscape:current-layer="layer2"
|
|
||||||
inkscape:document-rotation="0"
|
|
||||||
showgrid="true"
|
|
||||||
units="px"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1017"
|
|
||||||
inkscape:window-x="-8"
|
|
||||||
inkscape:window-y="-8"
|
|
||||||
inkscape:window-maximized="1">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid833" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata5">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer2"
|
|
||||||
inkscape:label="Back"
|
|
||||||
style="display:inline;opacity:0.997">
|
|
||||||
<path
|
|
||||||
id="rect2692"
|
|
||||||
transform="translate(0.26458378,0.26458346)"
|
|
||||||
mask="none"
|
|
||||||
d="m 7.4083329,10.847917 -6.87916626,0 V 0.52916664 H 14.022917 l 0,5.29166656"
|
|
||||||
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.165;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:2.33,2.33;stroke-dashoffset:8.621;stroke-opacity:1;paint-order:normal"
|
|
||||||
sodipodi:nodetypes="ccccc" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:label="Front"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
style="display:inline">
|
|
||||||
<path
|
|
||||||
style="opacity:1;fill:#000000;fill-opacity:0.997319;stroke:#000000;stroke-width:0.535;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="m 10.433094,5.9254024 v 8.8238546 l 2.129895,-1.217083 1.217083,3.042708 1.521355,-0.608542 -1.217083,-3.042708 h 2.434166 z"
|
|
||||||
id="path2710"
|
|
||||||
sodipodi:nodetypes="cccccccc" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 5.3 KiB |
|
@ -100,19 +100,19 @@ QComboBox:!editable:pressed {{
|
||||||
|
|
||||||
|
|
||||||
def splitter_styles(tm: ThemeManager, buf: str) -> str:
|
def splitter_styles(tm: ThemeManager, buf: str) -> str:
|
||||||
buf += """
|
buf += f"""
|
||||||
QSplitter::handle,
|
QSplitter::handle,
|
||||||
QMainWindow::separator {
|
QMainWindow::separator {{
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}}
|
||||||
QSplitter::handle:vertical,
|
QSplitter::handle:vertical,
|
||||||
QMainWindow::separator:horizontal {
|
QMainWindow::separator:horizontal {{
|
||||||
image: url(icons:drag-horizontal.svg);
|
image: url({tm.themed_icon("mdi:drag-horizontal-FG_SUBTLE")});
|
||||||
}
|
}}
|
||||||
QSplitter::handle:horizontal,
|
QSplitter::handle:horizontal,
|
||||||
QMainWindow::separator:vertical {
|
QMainWindow::separator:vertical {{
|
||||||
image: url(icons:drag-vertical.svg);
|
image: url({tm.themed_icon("mdi:drag-vertical-FG_SUBTLE")});
|
||||||
}
|
}}
|
||||||
"""
|
"""
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
|
@ -156,21 +156,21 @@ QComboBox::drop-down {{
|
||||||
border-bottom-right-radius: {tm.var(props.BORDER_RADIUS)};
|
border-bottom-right-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
}}
|
}}
|
||||||
QComboBox::down-arrow {{
|
QComboBox::down-arrow {{
|
||||||
image: url(icons:chevron-down.svg);
|
image: url({tm.themed_icon("mdi:chevron-down")});
|
||||||
}}
|
}}
|
||||||
QComboBox::drop-down {{
|
QComboBox::drop-down {{
|
||||||
background: {
|
background: {
|
||||||
button_gradient(
|
button_gradient(
|
||||||
tm.var(colors.BUTTON_PRIMARY_GRADIENT_START),
|
tm.var(colors.BUTTON_GRADIENT_START),
|
||||||
tm.var(colors.BUTTON_PRIMARY_GRADIENT_END)
|
tm.var(colors.BUTTON_GRADIENT_END)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
QComboBox::drop-down:hover {{
|
QComboBox::drop-down:hover {{
|
||||||
background: {
|
background: {
|
||||||
button_gradient(
|
button_gradient(
|
||||||
tm.var(colors.BUTTON_PRIMARY_HOVER_GRADIENT_START),
|
tm.var(colors.BUTTON_HOVER_GRADIENT_START),
|
||||||
tm.var(colors.BUTTON_PRIMARY_HOVER_GRADIENT_END)
|
tm.var(colors.BUTTON_HOVER_GRADIENT_END)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
|
@ -288,10 +288,10 @@ QHeaderView::down-arrow {{
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}}
|
}}
|
||||||
QHeaderView::up-arrow {{
|
QHeaderView::up-arrow {{
|
||||||
image: url(icons:menu-up.svg);
|
image: url({tm.themed_icon("mdi:menu-up")});
|
||||||
}}
|
}}
|
||||||
QHeaderView::down-arrow {{
|
QHeaderView::down-arrow {{
|
||||||
image: url(icons:menu-down.svg);
|
image: url({tm.themed_icon("mdi:menu-down")});
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
return buf
|
return buf
|
||||||
|
@ -306,8 +306,8 @@ QSpinBox::down-button {{
|
||||||
border: 1px solid {tm.var(colors.BUTTON_BORDER)};
|
border: 1px solid {tm.var(colors.BUTTON_BORDER)};
|
||||||
background: {
|
background: {
|
||||||
button_gradient(
|
button_gradient(
|
||||||
tm.var(colors.BUTTON_PRIMARY_GRADIENT_START),
|
tm.var(colors.BUTTON_GRADIENT_START),
|
||||||
tm.var(colors.BUTTON_PRIMARY_GRADIENT_END)
|
tm.var(colors.BUTTON_GRADIENT_END)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
|
@ -316,8 +316,8 @@ QSpinBox::down-button:pressed {{
|
||||||
border: 1px solid {tm.var(colors.BUTTON_PRESSED_BORDER)};
|
border: 1px solid {tm.var(colors.BUTTON_PRESSED_BORDER)};
|
||||||
background: {
|
background: {
|
||||||
button_pressed_gradient(
|
button_pressed_gradient(
|
||||||
tm.var(colors.BUTTON_PRIMARY_GRADIENT_START),
|
tm.var(colors.BUTTON_GRADIENT_START),
|
||||||
tm.var(colors.BUTTON_PRIMARY_GRADIENT_END),
|
tm.var(colors.BUTTON_GRADIENT_END),
|
||||||
tm.var(colors.BUTTON_PRESSED_SHADOW)
|
tm.var(colors.BUTTON_PRESSED_SHADOW)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -326,8 +326,8 @@ QSpinBox::up-button:hover,
|
||||||
QSpinBox::down-button:hover {{
|
QSpinBox::down-button:hover {{
|
||||||
background: {
|
background: {
|
||||||
button_gradient(
|
button_gradient(
|
||||||
tm.var(colors.BUTTON_PRIMARY_HOVER_GRADIENT_START),
|
tm.var(colors.BUTTON_HOVER_GRADIENT_START),
|
||||||
tm.var(colors.BUTTON_PRIMARY_HOVER_GRADIENT_END)
|
tm.var(colors.BUTTON_HOVER_GRADIENT_END)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
|
@ -342,10 +342,10 @@ QSpinBox::down-button {{
|
||||||
border-bottom-right-radius: {tm.var(props.BORDER_RADIUS)};
|
border-bottom-right-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
}}
|
}}
|
||||||
QSpinBox::up-arrow {{
|
QSpinBox::up-arrow {{
|
||||||
image: url(icons:chevron-up.svg);
|
image: url({tm.themed_icon("mdi:chevron-up")});
|
||||||
}}
|
}}
|
||||||
QSpinBox::down-arrow {{
|
QSpinBox::down-arrow {{
|
||||||
image: url(icons:chevron-down.svg);
|
image: url({tm.themed_icon("mdi:chevron-down")});
|
||||||
}}
|
}}
|
||||||
QSpinBox::up-arrow,
|
QSpinBox::up-arrow,
|
||||||
QSpinBox::down-arrow,
|
QSpinBox::down-arrow,
|
||||||
|
@ -363,7 +363,40 @@ QSpinBox::down-arrow:hover {{
|
||||||
}}
|
}}
|
||||||
QSpinBox::up-button:disabled, QSpinBox::up-button:off,
|
QSpinBox::up-button:disabled, QSpinBox::up-button:off,
|
||||||
QSpinBox::down-button:disabled, QSpinBox::down-button:off {{
|
QSpinBox::down-button:disabled, QSpinBox::down-button:off {{
|
||||||
background: {tm.var(colors.BUTTON_PRIMARY_DISABLED)};
|
background: {tm.var(colors.BUTTON_DISABLED)};
|
||||||
|
}}
|
||||||
|
QSpinBox::up-arrow:off,
|
||||||
|
QSpinBox::down-arrow:off {{
|
||||||
|
image: url({tm.themed_icon("mdi:chevron-down-FG_DISABLED")});
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
return buf
|
||||||
|
|
||||||
|
|
||||||
|
def checkbox_styles(tm: ThemeManager, buf: str) -> str:
|
||||||
|
buf += f"""
|
||||||
|
QCheckBox {{
|
||||||
|
spacing: 8px;
|
||||||
|
margin: 2px 0;
|
||||||
|
}}
|
||||||
|
QCheckBox::indicator {{
|
||||||
|
border: 1px solid {tm.var(colors.BUTTON_BORDER)};
|
||||||
|
border-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
|
background: {tm.var(colors.CANVAS_INSET)};
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}}
|
||||||
|
QCheckBox::indicator:hover,
|
||||||
|
QCheckBox::indicator:checked:hover {{
|
||||||
|
border: 2px solid {tm.var(colors.BORDER_STRONG)};
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}}
|
||||||
|
QCheckBox::indicator:checked {{
|
||||||
|
image: url({tm.themed_icon("mdi:check")});
|
||||||
|
}}
|
||||||
|
QCheckBox::indicator:indeterminate {{
|
||||||
|
image: url({tm.themed_icon("mdi:minus-thick")});
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
return buf
|
return buf
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Callable, List, Tuple
|
from typing import Callable, List, Tuple
|
||||||
|
@ -81,8 +83,21 @@ class ThemeManager:
|
||||||
|
|
||||||
night_mode = property(get_night_mode, set_night_mode)
|
night_mode = property(get_night_mode, set_night_mode)
|
||||||
|
|
||||||
|
def themed_icon(self, path: str) -> str:
|
||||||
|
"Fetch themed version of svg."
|
||||||
|
from aqt.utils import aqt_data_folder
|
||||||
|
|
||||||
|
if m := re.match(r"(?:mdi:)(.+)$", path):
|
||||||
|
name = m.group(1)
|
||||||
|
else:
|
||||||
|
return path
|
||||||
|
|
||||||
|
filename = f"{name}-{'dark' if self.night_mode else 'light'}.svg"
|
||||||
|
|
||||||
|
return os.path.join(aqt_data_folder(), "qt", "icons", filename)
|
||||||
|
|
||||||
def icon_from_resources(self, path: str | ColoredIcon) -> QIcon:
|
def icon_from_resources(self, path: str | ColoredIcon) -> QIcon:
|
||||||
"Fetch icon from Qt resources, and invert if in night mode."
|
"Fetch icon from Qt resources."
|
||||||
if self.night_mode:
|
if self.night_mode:
|
||||||
cache = self._icon_cache_light
|
cache = self._icon_cache_light
|
||||||
else:
|
else:
|
||||||
|
@ -99,6 +114,9 @@ class ThemeManager:
|
||||||
|
|
||||||
if isinstance(path, str):
|
if isinstance(path, str):
|
||||||
# default black/white
|
# default black/white
|
||||||
|
if "mdi:" in path:
|
||||||
|
icon = QIcon(self.themed_icon(path))
|
||||||
|
else:
|
||||||
icon = QIcon(path)
|
icon = QIcon(path)
|
||||||
if self.night_mode:
|
if self.night_mode:
|
||||||
img = icon.pixmap(self._icon_size, self._icon_size).toImage()
|
img = icon.pixmap(self._icon_size, self._icon_size).toImage()
|
||||||
|
@ -193,6 +211,7 @@ class ThemeManager:
|
||||||
if not is_mac:
|
if not is_mac:
|
||||||
from aqt.stylesheets import (
|
from aqt.stylesheets import (
|
||||||
button_styles,
|
button_styles,
|
||||||
|
checkbox_styles,
|
||||||
combobox_styles,
|
combobox_styles,
|
||||||
general_styles,
|
general_styles,
|
||||||
scrollbar_styles,
|
scrollbar_styles,
|
||||||
|
@ -210,6 +229,7 @@ class ThemeManager:
|
||||||
tabwidget_styles(self, buf),
|
tabwidget_styles(self, buf),
|
||||||
table_styles(self, buf),
|
table_styles(self, buf),
|
||||||
spinbox_styles(self, buf),
|
spinbox_styles(self, buf),
|
||||||
|
checkbox_styles(self, buf),
|
||||||
scrollbar_styles(self, buf),
|
scrollbar_styles(self, buf),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@else if $key == "default" {
|
||||||
|
@return map.set($output, $name, map.get($map, $key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@return $output;
|
@return $output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,12 @@ $vars: (
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
colors: (
|
colors: (
|
||||||
|
white: (
|
||||||
|
default: white,
|
||||||
|
),
|
||||||
|
black: (
|
||||||
|
default: black,
|
||||||
|
),
|
||||||
fg: (
|
fg: (
|
||||||
default: (
|
default: (
|
||||||
light: palette(darkgray, 9),
|
light: palette(darkgray, 9),
|
||||||
|
@ -28,8 +34,8 @@ $vars: (
|
||||||
dark: palette(lightgray, 3),
|
dark: palette(lightgray, 3),
|
||||||
),
|
),
|
||||||
disabled: (
|
disabled: (
|
||||||
light: palette(darkgray, 3),
|
light: palette(darkgray, 2),
|
||||||
dark: palette(lightgray, 6),
|
dark: palette(lightgray, 8),
|
||||||
),
|
),
|
||||||
faint: (
|
faint: (
|
||||||
light: palette(lightgray, 7),
|
light: palette(lightgray, 7),
|
||||||
|
@ -67,6 +73,10 @@ $vars: (
|
||||||
light: palette(lightgray, 5),
|
light: palette(lightgray, 5),
|
||||||
dark: palette(darkgray, 4),
|
dark: palette(darkgray, 4),
|
||||||
),
|
),
|
||||||
|
strong: (
|
||||||
|
light: palette(lightgray, 9),
|
||||||
|
dark: palette(darkgray, 1),
|
||||||
|
),
|
||||||
focus: (
|
focus: (
|
||||||
light: palette(blue, 5),
|
light: palette(blue, 5),
|
||||||
dark: palette(blue, 5),
|
dark: palette(blue, 5),
|
||||||
|
@ -91,6 +101,10 @@ $vars: (
|
||||||
dark: palette(darkgray, 9),
|
dark: palette(darkgray, 9),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
disabled: (
|
||||||
|
light: color.scale(palette(lightgray, 5), $alpha: -50%),
|
||||||
|
dark: color.scale(palette(darkgray, 3), $alpha: -50%),
|
||||||
|
),
|
||||||
gradient: (
|
gradient: (
|
||||||
start: (
|
start: (
|
||||||
light: white,
|
light: white,
|
||||||
|
|
Loading…
Reference in a new issue