Files

138 lines
4.5 KiB
Python

"""Persist a handful of user choices to ~/HVideoTool/settings.json.
For the project-based tool this file holds the **defaults for new projects** (the
detector, model path, overlay threshold, restore engine) plus app-level state: the
last opened project, the recent-projects list, and the last directory used in file
dialogs. Per-project settings live in each project's ``project.json``, not here.
"""
from __future__ import annotations
import json
from pathlib import Path
from .config import AppConfig
_PATH = Path.home() / "HVideoTool" / "settings.json"
def _read() -> dict:
try:
return json.loads(_PATH.read_text(encoding="utf-8"))
except (OSError, ValueError):
return {}
def _write(data: dict) -> None:
_PATH.parent.mkdir(parents=True, exist_ok=True)
_PATH.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
def apply(config: AppConfig) -> None:
"""Overlay persisted settings onto ``config`` (mutates it in place)."""
data = _read()
if data.get("detector"):
config.detector = data["detector"]
if isinstance(data.get("detector_models"), list):
config.detector_models = [str(m) for m in data["detector_models"]]
if "threshold" in data:
config.default_threshold = float(data["threshold"])
if isinstance(data.get("model_thresholds"), dict):
config.model_thresholds = {
str(k): float(v) for k, v in data["model_thresholds"].items()
}
if "cross_model_nms" in data:
config.cross_model_nms = bool(data["cross_model_nms"])
if "nms_iou" in data:
config.nms_iou = float(data["nms_iou"])
if data.get("restorer"):
config.restorer = data["restorer"]
for key in ("dm_dir", "dm_model", "dm_gpu"):
if key in data:
setattr(config, key, data[key])
if "dm_feed_restored" in data:
config.dm_feed_restored = bool(data["dm_feed_restored"])
# diffusion-inpaint engine
for key in ("diff_backend", "diff_url", "diff_model", "diff_prompt", "diff_negative"):
if key in data:
setattr(config, key, data[key])
if "diff_steps" in data:
config.diff_steps = int(data["diff_steps"])
if "diff_cfg" in data:
config.diff_cfg = float(data["diff_cfg"])
if "diff_denoise" in data:
config.diff_denoise = float(data["diff_denoise"])
if "diff_seed" in data:
config.diff_seed = int(data["diff_seed"])
if "diff_mask_dilate" in data:
config.diff_mask_dilate = int(data["diff_mask_dilate"])
if "diff_mask_blur" in data:
config.diff_mask_blur = int(data["diff_mask_blur"])
def save(config: AppConfig) -> None:
"""Persist the configurable settings, preserving other keys (e.g. last_dir)."""
data = _read()
data.update(
detector=config.detector,
detector_models=list(config.detector_models),
threshold=config.default_threshold,
model_thresholds=dict(config.model_thresholds),
cross_model_nms=config.cross_model_nms,
nms_iou=config.nms_iou,
restorer=config.restorer,
dm_dir=config.dm_dir,
dm_model=config.dm_model,
dm_gpu=config.dm_gpu,
dm_feed_restored=config.dm_feed_restored,
diff_backend=config.diff_backend,
diff_url=config.diff_url,
diff_model=config.diff_model,
diff_prompt=config.diff_prompt,
diff_negative=config.diff_negative,
diff_steps=config.diff_steps,
diff_cfg=config.diff_cfg,
diff_denoise=config.diff_denoise,
diff_seed=config.diff_seed,
diff_mask_dilate=config.diff_mask_dilate,
diff_mask_blur=config.diff_mask_blur,
)
_write(data)
def last_dir() -> str | None:
return _read().get("last_dir")
def set_last_dir(path: str) -> None:
data = _read()
data["last_dir"] = path
_write(data)
def last_project() -> str | None:
return _read().get("last_project")
def set_last_project(path: str) -> None:
data = _read()
data["last_project"] = path
_write(data)
_RECENTS_CAP = 10
def recent_projects() -> list[str]:
recents = _read().get("recent_projects", [])
return [p for p in recents if isinstance(p, str)]
def add_recent_project(path: str) -> None:
"""Push ``path`` to the front of the recent-projects list (deduped, capped)."""
data = _read()
recents = [p for p in data.get("recent_projects", []) if isinstance(p, str) and p != path]
recents.insert(0, path)
data["recent_projects"] = recents[:_RECENTS_CAP]
_write(data)