101 lines
2.9 KiB
Python
101 lines
2.9 KiB
Python
import json
|
|
import copy
|
|
from pathlib import Path
|
|
from typing import Callable
|
|
|
|
DEFAULT_CONFIG = {
|
|
"active_profile": "pc1_dp",
|
|
"profiles": [
|
|
{
|
|
"id": "pc1_dp",
|
|
"name": "PC1 \u2014 DP",
|
|
"hotkey": "ctrl+alt+1",
|
|
"monitor_inputs": [
|
|
{"monitor_index": 0, "vcp_value": 15},
|
|
{"monitor_index": 1, "vcp_value": 15}
|
|
]
|
|
},
|
|
{
|
|
"id": "pc2_hdmi",
|
|
"name": "PC2 \u2014 HDMI",
|
|
"hotkey": "ctrl+alt+2",
|
|
"monitor_inputs": [
|
|
{"monitor_index": 0, "vcp_value": 17},
|
|
{"monitor_index": 1, "vcp_value": 17}
|
|
]
|
|
}
|
|
],
|
|
"device_triggers": [
|
|
{
|
|
"name": "HP 975 keyboard",
|
|
"bt_device_id": "VID&0203F0_PID&6343",
|
|
"on_connect": "pc1_dp",
|
|
"on_disconnect": "pc2_hdmi",
|
|
"enabled": True
|
|
},
|
|
{
|
|
"name": "MX Anywhere 2S",
|
|
"bt_device_id": "VID&02046D_PID&B01A",
|
|
"on_connect": "pc1_dp",
|
|
"on_disconnect": "pc2_hdmi",
|
|
"enabled": True
|
|
}
|
|
],
|
|
"general": {
|
|
"autostart": True,
|
|
"minimize_to_tray": True,
|
|
"debounce_ms": 500
|
|
}
|
|
}
|
|
|
|
|
|
class ConfigManager:
|
|
def __init__(self, config_path=None):
|
|
if config_path is None:
|
|
config_path = Path(__file__).parent / "config.json"
|
|
self.config_path = Path(config_path)
|
|
self._config: dict = {}
|
|
self._callbacks: list[Callable] = []
|
|
self.load()
|
|
|
|
def load(self) -> None:
|
|
if self.config_path.exists():
|
|
try:
|
|
with open(self.config_path, "r", encoding="utf-8") as f:
|
|
self._config = json.load(f)
|
|
except (json.JSONDecodeError, OSError):
|
|
self._config = copy.deepcopy(DEFAULT_CONFIG)
|
|
else:
|
|
self._config = copy.deepcopy(DEFAULT_CONFIG)
|
|
self.save()
|
|
|
|
def save(self) -> None:
|
|
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
with open(self.config_path, "w", encoding="utf-8") as f:
|
|
json.dump(self._config, f, indent=2, ensure_ascii=False)
|
|
|
|
def get(self) -> dict:
|
|
return self._config
|
|
|
|
def update(self, new_config: dict) -> None:
|
|
self._config = new_config
|
|
self.save()
|
|
for cb in self._callbacks:
|
|
cb(self._config)
|
|
|
|
def on_change(self, callback: Callable) -> None:
|
|
self._callbacks.append(callback)
|
|
|
|
def get_profile(self, profile_id: str) -> dict | None:
|
|
for p in self._config.get("profiles", []):
|
|
if p["id"] == profile_id:
|
|
return p
|
|
return None
|
|
|
|
def get_active_profile_id(self) -> str:
|
|
return self._config.get("active_profile", "pc1_dp")
|
|
|
|
def set_active_profile(self, profile_id: str) -> None:
|
|
self._config["active_profile"] = profile_id
|
|
self.save()
|