mirror of
https://github.com/Cheviiot/Vual.git
synced 2026-08-03 15:57:25 +00:00
140 lines
6.1 KiB
Python
140 lines
6.1 KiB
Python
"""Configuration management for Vual.
|
|
|
|
Stores settings in ~/.config/vual/config.json
|
|
"""
|
|
|
|
import json
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
|
|
_DEFAULT_PROTONHAX = str(Path.home() / ".local" / "share" / "vual" / "bin" / "protonhax")
|
|
_DEFAULT_TEMPLATE = f"{_DEFAULT_PROTONHAX} init %COMMAND%"
|
|
_DEFAULT_EXCLUDED = ["^Proton", "^Steam Linux Runtime"]
|
|
|
|
# Config file location
|
|
CONFIG_PATH = Path.home() / ".config" / "vual" / "config.json"
|
|
|
|
|
|
# Tile size presets: small=120, medium=150, large=180
|
|
TILE_SIZES = {"small": 120, "medium": 150, "large": 180}
|
|
|
|
|
|
@dataclass
|
|
class Config:
|
|
"""Application configuration.
|
|
|
|
Attributes:
|
|
ce_executable: Path to Cheat Engine executable.
|
|
steam_path: Path to Steam installation directory.
|
|
lookup_enabled: Whether to look up game info.
|
|
launch_options_template: Template for Steam launch options.
|
|
excluded_app_patterns: Regex patterns to exclude apps.
|
|
window_width: Main window width.
|
|
window_height: Main window height.
|
|
color_scheme: Color scheme ("system", "light", "dark").
|
|
tile_size: Tile size preset ("small", "medium", "large").
|
|
sort_by: Sort order ("name", "status").
|
|
ce_language: CE language ("system", "ru_RU").
|
|
wine_theme: Wine color theme ("system", "dark", "light").
|
|
app_language: Application UI language ("system", "en", "ru").
|
|
transparent_window: Enable semi-transparent window background.
|
|
guide_shown: Whether the startup guide has been shown.
|
|
"""
|
|
|
|
ce_executable: str = "~/.local/share/vual/cheatengine/cheatengine-x86_64.exe"
|
|
steam_path: str = "~/.local/share/Steam"
|
|
lookup_enabled: bool = True
|
|
launch_options_template: str = field(default_factory=lambda: _DEFAULT_TEMPLATE)
|
|
excluded_app_patterns: list[str] = field(default_factory=lambda: _DEFAULT_EXCLUDED.copy())
|
|
window_width: int = 1000
|
|
window_height: int = 700
|
|
color_scheme: str = "system"
|
|
tile_size: str = "medium"
|
|
sort_by: str = "name"
|
|
ce_language: str = "system"
|
|
wine_theme: str = "system"
|
|
app_language: str = "system"
|
|
transparent_window: bool = False
|
|
guide_shown: bool = False
|
|
|
|
# ════════════════════════════════════════════════════════════════
|
|
# Load / Save
|
|
# ════════════════════════════════════════════════════════════════
|
|
|
|
@classmethod
|
|
def load(cls) -> "Config":
|
|
"""Load configuration from JSON file.
|
|
|
|
Returns:
|
|
Config instance with loaded or default values.
|
|
"""
|
|
if CONFIG_PATH.exists():
|
|
try:
|
|
data = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
|
|
return cls(
|
|
ce_executable=data.get("ce_executable", cls.ce_executable),
|
|
steam_path=data.get("steam_path", cls.steam_path),
|
|
lookup_enabled=data.get("lookup_enabled", cls.lookup_enabled),
|
|
launch_options_template=data.get("launch_options_template", _DEFAULT_TEMPLATE),
|
|
excluded_app_patterns=data.get("excluded_app_patterns", _DEFAULT_EXCLUDED.copy()),
|
|
window_width=data.get("window_width", cls.window_width),
|
|
window_height=data.get("window_height", cls.window_height),
|
|
color_scheme=data.get("color_scheme", cls.color_scheme),
|
|
tile_size=data.get("tile_size", cls.tile_size),
|
|
sort_by=data.get("sort_by", cls.sort_by),
|
|
ce_language=data.get("ce_language", cls.ce_language),
|
|
wine_theme=data.get("wine_theme", cls.wine_theme),
|
|
app_language=data.get("app_language", cls.app_language),
|
|
transparent_window=data.get("transparent_window", cls.transparent_window),
|
|
guide_shown=data.get("guide_shown", cls.guide_shown),
|
|
)
|
|
except (json.JSONDecodeError, OSError):
|
|
pass
|
|
return cls()
|
|
|
|
def save(self) -> Path:
|
|
"""Save configuration to JSON file.
|
|
|
|
Returns:
|
|
Path to the saved config file.
|
|
"""
|
|
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
data = {
|
|
"ce_executable": self.ce_executable,
|
|
"steam_path": self.steam_path,
|
|
"lookup_enabled": self.lookup_enabled,
|
|
"launch_options_template": self.launch_options_template,
|
|
"excluded_app_patterns": self.excluded_app_patterns,
|
|
"window_width": self.window_width,
|
|
"window_height": self.window_height,
|
|
"color_scheme": self.color_scheme,
|
|
"tile_size": self.tile_size,
|
|
"sort_by": self.sort_by,
|
|
"ce_language": self.ce_language,
|
|
"wine_theme": self.wine_theme,
|
|
"app_language": self.app_language,
|
|
"transparent_window": self.transparent_window,
|
|
"guide_shown": self.guide_shown,
|
|
}
|
|
CONFIG_PATH.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
return CONFIG_PATH
|
|
|
|
# ════════════════════════════════════════════════════════════════
|
|
# Derived Paths
|
|
# ════════════════════════════════════════════════════════════════
|
|
|
|
@property
|
|
def steamapps_path(self) -> Path:
|
|
"""Path to Steam's steamapps directory."""
|
|
return Path(self.steam_path).expanduser() / "steamapps"
|
|
|
|
@property
|
|
def ce_executable_path(self) -> Path:
|
|
"""Expanded path to CE executable."""
|
|
return Path(self.ce_executable).expanduser()
|
|
|
|
@property
|
|
def ce_exists(self) -> bool:
|
|
"""Check if CE executable exists."""
|
|
return self.ce_executable_path.is_file()
|