From cb82033e1cf6912dbd57c1ac47175d43f71416bb Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Wed, 15 Nov 2023 23:34:53 +0000 Subject: [PATCH] theme menu initial implementation bump to 0.5.7a1 Issue #19 --- pyproject.toml | 2 +- src/nvda_voicemeeter/builder.py | 3 +++ src/nvda_voicemeeter/configuration.py | 34 +++++++++++++++++++++++++++ src/nvda_voicemeeter/util.py | 17 ++++++++++++++ src/nvda_voicemeeter/window.py | 34 ++++++++++++++++----------- 5 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 src/nvda_voicemeeter/configuration.py diff --git a/pyproject.toml b/pyproject.toml index bff90b0..2cbc39e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "nvda_voicemeeter" -version = "0.5.6" +version = "0.5.7a1" description = "A Voicemeeter app compatible with NVDA" authors = [ { name = "onyx-and-iris", email = "code@onyxandiris.online" }, diff --git a/src/nvda_voicemeeter/builder.py b/src/nvda_voicemeeter/builder.py index bf80319..b003b13 100644 --- a/src/nvda_voicemeeter/builder.py +++ b/src/nvda_voicemeeter/builder.py @@ -92,6 +92,8 @@ class Builder: return [[menu], [tab_group]] def make_menu(self) -> psg.Menu: + themes = [f"{theme}::MENU THEME" for theme in util.get_themes_list()] + themes.append("Default::MENU THEME") menu_def = [ [ "&Voicemeeter", @@ -102,6 +104,7 @@ class Builder: "Load Settings on Startup ::MENU", ], ], + ["&Theme", themes], ] return psg.Menu(menu_def, key="menus") diff --git a/src/nvda_voicemeeter/configuration.py b/src/nvda_voicemeeter/configuration.py new file mode 100644 index 0000000..06f52c8 --- /dev/null +++ b/src/nvda_voicemeeter/configuration.py @@ -0,0 +1,34 @@ +import json +from pathlib import Path + +SETTINGS = Path.cwd() / "settings.json" + + +def config_from_json(): + data = {} + if not SETTINGS.exists(): + return data + with open(SETTINGS, "r") as f: + data = json.load(f) + return data + + +config = config_from_json() + + +def get(key, default=None): + if key in config: + return config[key] + return default + + +def set(key, value): + config[key] = value + with open(SETTINGS, "w") as f: + json.dump(config, f) + + +def delete(key): + del config[key] + with open(SETTINGS, "w") as f: + json.dump(config, f) diff --git a/src/nvda_voicemeeter/util.py b/src/nvda_voicemeeter/util.py index 1eec056..46305b9 100644 --- a/src/nvda_voicemeeter/util.py +++ b/src/nvda_voicemeeter/util.py @@ -196,3 +196,20 @@ def get_slider_modes() -> Iterable: def _get_bus_assignments(kind) -> list: return [f"A{i}" for i in range(1, kind.phys_out + 1)] + [f"B{i}" for i in range(1, kind.virt_out + 1)] + + +def get_themes_list() -> list: + return sorted( + [ + "Black", + "Dark Blue", + "Dark Blue 3", + "Reddit", + "Light Gray 1", + "Bright Colors", + "Dark Amber", + "Light Grey 5", + "Reds", + "Dark Brown 5", + ] + ) diff --git a/src/nvda_voicemeeter/window.py b/src/nvda_voicemeeter/window.py index 80e1d16..3377c2d 100644 --- a/src/nvda_voicemeeter/window.py +++ b/src/nvda_voicemeeter/window.py @@ -4,7 +4,7 @@ from pathlib import Path import PySimpleGUI as psg -from . import models, util +from . import configuration, models, util from .builder import Builder from .nvda import Nvda from .parser import Parser @@ -12,14 +12,12 @@ from .popup import Popup logger = logging.getLogger(__name__) -psg.theme("Dark Blue 3") +psg.theme(configuration.get("default_theme", "Dark Blue 3")) class NVDAVMWindow(psg.Window): """Represents the main window of the Voicemeeter NVDA application""" - SETTINGS = "settings.json" - def __init__(self, title, vm): self.vm = vm self.kind = self.vm.kind @@ -63,12 +61,10 @@ class NVDAVMWindow(psg.Window): self["tabgroup"].set_focus() def __enter__(self): - settings_path = Path.cwd() / self.SETTINGS + settings_path = configuration.SETTINGS if settings_path.exists(): try: - with open(settings_path, "r") as f: - data = json.load(f) - defaultconfig = Path(data["default_config"]) + defaultconfig = Path(configuration.get("default_config", "")) # coerce the type if defaultconfig.exists(): self.vm.set("command.load", str(defaultconfig)) self.logger.debug(f"config {defaultconfig} loaded") @@ -78,7 +74,7 @@ class NVDAVMWindow(psg.Window): f"config {defaultconfig.stem} has been loaded", ) except json.JSONDecodeError: - self.logger.debug("no data in settings.json. silently continuing...") + self.logger.debug("no default_config in settings.json. silently continuing...") self.vm.init_thread() self.vm.observer.add(self.on_pdirty) @@ -510,17 +506,27 @@ class NVDAVMWindow(psg.Window): file_types=(("XML", ".xml"),), ): filepath = Path(filepath) - with open(self.SETTINGS, "w") as f: - json.dump({"default_config": str(filepath)}, f) + configuration.set("default_settings", str(filepath)) self.TKroot.after( 200, self.nvda.speak, f"config {filepath.stem} set as default on startup", ) else: - with open(self.SETTINGS, "wb") as f: - f.truncate() - self.logger.debug("settings.json was truncated") + configuration.delete("default_settings") + self.logger.debug("default_settings removed from settings.json") + + case [theme, ["MENU", "THEME"]]: + chosen = " ".join(theme) + if chosen == "Default": + chosen = "Dark Blue 3" + configuration.set("default_theme", chosen) + self.TKroot.after( + 200, + self.nvda.speak, + f"theme {chosen} selected.", + ) + self.logger.debug(f"theme {chosen} selected") # Tabs case ["tabgroup"] | [["tabgroup"], ["FOCUS", "IN"]]: