§17.1 Preferences persistence: - Wire the previously-unused config_service; remember and restore the last-selected template and last batch mode. main_window loads config, distributes initial values, then persists on change (save-on-change). - template_panel: template_changed signal, select_template, current_template_state. queue_panel: set_batch_mode + batch_mode_changed. §17.2 Independent resets: - Replace the combined reset and 归零 with per-section 位置/尺寸/旋转 reset buttons (quiet ghost styling) that restore only their own aspect to the selected template. Size reset changes width/height only, leaving X/Y. Button de-dup: - Remove the export panel's 应用为模板 / 重置为模板 — literal duplicates of the template panel's 另存为 / 重置为模板. Template actions now live only in the template area; the export panel handles output only. Docs: PRD (6.6/6.9/9/10), architecture (4.12), UI design (7.x/10), development-rules (6, single-home actions + consistent naming), tasks.md (17). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
import json
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DEFAULT_CONFIG = {
|
|
"output_format": "PNG", # PNG or JPG
|
|
"output_quality": 95, # JPG quality 1-95
|
|
"output_dir": "", # empty = use app output/ dir
|
|
"last_garment_dir": "",
|
|
"last_print_dir": "",
|
|
"last_template": "", # name of the last-selected template
|
|
"last_batch_mode": "full_combo", # BatchMode value of the last-used mode
|
|
}
|
|
|
|
_CONFIG_FILENAME = "app_config.json"
|
|
|
|
|
|
def load_config():
|
|
"""
|
|
从 JSON 文件加载应用配置。
|
|
|
|
返回默认配置与文件配置的合并字典。如果配置文件不存在、损坏或无法读取,
|
|
函数不会抛出异常,而是记录日志并返回默认配置。
|
|
|
|
Returns:
|
|
dict: 合并后的配置字典
|
|
"""
|
|
from services.file_service import get_config_path
|
|
config_file = get_config_path(_CONFIG_FILENAME)
|
|
|
|
if not config_file.exists():
|
|
logger.info("Config file not found, using defaults: %s", config_file)
|
|
return dict(DEFAULT_CONFIG)
|
|
|
|
try:
|
|
with open(str(config_file), encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
if not isinstance(data, dict):
|
|
raise ValueError("Config root is not a JSON object")
|
|
merged = dict(DEFAULT_CONFIG)
|
|
merged.update(data)
|
|
logger.info("Config loaded from %s", config_file)
|
|
return merged
|
|
except (json.JSONDecodeError, ValueError) as exc:
|
|
logger.warning("Config file damaged (%s), using defaults: %s", exc, config_file)
|
|
return dict(DEFAULT_CONFIG)
|
|
except OSError as exc:
|
|
logger.warning("Config file unreadable (%s), using defaults: %s", exc, config_file)
|
|
return dict(DEFAULT_CONFIG)
|
|
|
|
|
|
def save_config(data):
|
|
"""Save config dict to JSON. Logs error on failure, does not raise."""
|
|
from services.file_service import get_config_path
|
|
config_file = get_config_path(_CONFIG_FILENAME)
|
|
|
|
try:
|
|
config_file.parent.mkdir(exist_ok=True)
|
|
with open(str(config_file), "w", encoding="utf-8") as f:
|
|
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
logger.info("Config saved to %s", config_file)
|
|
except OSError as exc:
|
|
logger.error("Failed to save config to %s: %s", config_file, exc)
|