diff --git a/Core.py b/Core.py index 740cb95..4755a1a 100644 --- a/Core.py +++ b/Core.py @@ -14,7 +14,11 @@ import flet as ft import tomlkit AppName = "SaraSuite" -FontFamily = "Fixedsys Excelsior" +# Bundled in assets/fonts and always registered, so it works as FontFamily +# without being installed. Any other FontFamily is looked up among the +# system's installed fonts. +BundledFontFamily = "Fixedsys Excelsior" +ActiveFontFamily = BundledFontFamily # set by ApplyAppearance, read by BuildTheme Home = Path.home() ConfigHome = Home / ".config" @@ -25,6 +29,9 @@ SharedConfigDir = ConfigHome / "SaraSuite" ThemesDir = SharedConfigDir / "Themes" ConfigDir = SharedConfigDir / "SaraSuite" ConfigPath = ConfigDir / "Config.toml" +# Settings shared by every SaraSuite program (theme, font, window title bar). +# Same key names as the matching fields in each program's own Config.toml. +SharedConfigPath = SharedConfigDir / "Config.toml" # Everything SaraSuite itself keeps about installed programs. Nothing in here # is user-edited, so it's all fair game to delete when a program is removed. @@ -89,7 +96,13 @@ def ApplyTheme(ThemeName: str) -> None: @dataclass class AppConfig: + # True: Theme, FontFamily and HideWindowTitleBar come from the shared + # ~/.config/SaraSuite/Config.toml (edited in SaraFem's Settings, SaraSuite + # tab). False: SaraSuite uses its own values below instead. + UseSharedSettings: bool = True Theme: str = "CatppuccinMocha" # matches a file in ~/.config/SaraSuite/Themes/ + FontFamily: str = BundledFontFamily + HideWindowTitleBar: bool = False # Where the Sara repos live (Gitea on SpineS); manifests # use it as {GitHost}. GitHost: str = "https://git.srhtnin.garden/sarah" @@ -112,6 +125,52 @@ def LoadConfig() -> AppConfig: return AppConfig(**{Key: Value for Key, Value in Data.items() if Key in KnownFields}) +@dataclass +class SharedSettings: + """~/.config/SaraSuite/Config.toml, shared by every SaraSuite program. + Same schema and fallback rules as SaraFem's SharedSettings.""" + + Theme: str = "CatppuccinMocha" + FontFamily: str = BundledFontFamily + HideWindowTitleBar: bool = False + + def Save(self) -> None: + SharedConfigDir.mkdir(parents=True, exist_ok=True) + SharedConfigPath.write_text(tomlkit.dumps(asdict(self))) + + +def _OwnSettings(Config: AppConfig) -> SharedSettings: + return SharedSettings(Config.Theme, Config.FontFamily, Config.HideWindowTitleBar) + + +def LoadSharedSettings(Config: AppConfig) -> SharedSettings: + """The shared file, created from this program's own values if missing.""" + if not SharedConfigPath.exists(): + Shared = _OwnSettings(Config) + Shared.Save() + return Shared + Result = _OwnSettings(Config) # fallback for keys the file doesn't have + try: + Data = tomlkit.parse(SharedConfigPath.read_text()).unwrap() + except tomlkit.exceptions.TOMLKitError: + return Result + for Key in SharedSettings.__dataclass_fields__: + if Key in Data: + setattr(Result, Key, Data[Key]) + return Result + + +def EffectiveSettings(Config: AppConfig) -> SharedSettings: + return LoadSharedSettings(Config) if Config.UseSharedSettings else _OwnSettings(Config) + + +def ApplyAppearance(Settings: SharedSettings) -> None: + """Theme colours and font; must run before anything reads Palette.X.""" + global ActiveFontFamily + ApplyTheme(Settings.Theme) + ActiveFontFamily = Settings.FontFamily or BundledFontFamily + + def ChildEnvironment() -> dict[str, str]: """The environment for child processes (systemctl, pip, python3 -m venv). A PyInstaller build points LD_LIBRARY_PATH at its own bundled libraries @@ -158,7 +217,7 @@ def BuildTheme() -> ft.Theme: on_error=Palette.Crust, ) return ft.Theme( - font_family=FontFamily, + font_family=ActiveFontFamily, color_scheme=ColorScheme, use_material3=True, scaffold_bgcolor=Palette.Base, @@ -166,7 +225,7 @@ def BuildTheme() -> ft.Theme: dialog_theme=ft.DialogTheme( bgcolor=Palette.Mantle, shape=ft.RoundedRectangleBorder(radius=8, side=ft.BorderSide(1, Palette.Mauve)), - title_text_style=ft.TextStyle(color=Palette.Mauve, size=18, font_family=FontFamily), + title_text_style=ft.TextStyle(color=Palette.Mauve, size=18, font_family=ActiveFontFamily), ), ) diff --git a/Main.py b/Main.py index 071337d..026d722 100644 --- a/Main.py +++ b/Main.py @@ -10,8 +10,8 @@ from typing import Callable import flet as ft from Core import ( - AppName, ApplyTheme, AssetsDir, BuildTheme, ChipButtonStyle, DataDir, DataHome, FontFamily, - LoadConfig, Palette, + AppName, ApplyAppearance, AssetsDir, BuildTheme, BundledFontFamily, ChipButtonStyle, DataDir, + DataHome, EffectiveSettings, LoadConfig, Palette, ) from Dialogs import ShowInstallDialog, ShowRemoveDialog, ShowUpdateDialog from Installer import Apply, Fetch, GetStatus, PlanConfigs, PlanRemoval, Remove, SourceVersion @@ -38,19 +38,21 @@ def _SetMenuEntry(Enabled: bool) -> None: "[Desktop Entry]\nType=Application\nName=SaraSuite\n" "Comment=Install, update and remove Sara programs\n" f"Exec={_AppImage}\nIcon={_MenuIcon}\nTerminal=false\n" - "Categories=System;Settings;\nStartupNotify=true\n" + "Categories=System;\nStartupNotify=true\n" ) def Main(Page: ft.Page) -> None: Config = LoadConfig() - ApplyTheme(Config.Theme) # must run before anything reads Palette.X + Appearance = EffectiveSettings(Config) # shared SaraSuite settings, or SaraSuite's own + ApplyAppearance(Appearance) # must run before anything reads Palette.X Page.title = AppName Page.theme_mode = ft.ThemeMode.DARK Page.theme = BuildTheme() Page.dark_theme = BuildTheme() - Page.fonts = {FontFamily: "fonts/Fixedsys_Excelsior_Regular.ttf"} + Page.fonts = {BundledFontFamily: "fonts/Fixedsys_Excelsior_Regular.ttf"} + Page.window.title_bar_hidden = Appearance.HideWindowTitleBar Page.padding = 0 Page.bgcolor = Palette.Base Page.window.width = 960 diff --git a/Packaging/BuildAppImage.sh b/Packaging/BuildAppImage.sh index 63e7158..a156dfd 100755 --- a/Packaging/BuildAppImage.sh +++ b/Packaging/BuildAppImage.sh @@ -29,7 +29,7 @@ Comment=Install, update and remove Sara programs Exec=SaraSuite Icon=SaraSuite Terminal=false -Categories=System;Settings; +Categories=System; DESKTOP mkdir -p dist diff --git a/README.md b/README.md index 0cfcadb..2d5700b 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,23 @@ GitHost = "https://git.srhtnin.garden/sarah" The only thing a program needs from the system is `python3` (for its venv). +## Shared settings + +Settings every SaraSuite program shares live in `~/.config/SaraSuite/Config.toml`: + +```toml +Theme = "CatppuccinMocha" # a file in ~/.config/SaraSuite/Themes/ +FontFamily = "Fixedsys Excelsior" # the bundled font, or any installed font family +HideWindowTitleBar = false +``` + +Each program's own `~/.config/SaraSuite//Config.toml` has the same three keys plus +`UseSharedSettings` (default `true`). With it on, the program reads the shared file; with it +off, it uses its own values instead. SaraFem edits both in its Settings (the SaraSuite tab +for the shared file, the General tab for its own); for SaraSuite itself, edit its +`Config.toml` directly. Whichever program starts first creates the shared file from its own +values. + ## Running and building - AppImage: `Packaging/BuildAppImage.sh` builds `dist/SaraSuite-x86_64.AppImage`