176 lines
6.7 KiB
Python
176 lines
6.7 KiB
Python
# radar_data_reader/utils/config_manager.py
|
|
|
|
"""
|
|
Configuration Manager for the application.
|
|
Handles loading and saving of application settings to a JSON file.
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Dict, Any, Optional, List
|
|
|
|
from . import logger
|
|
from ..core.export_profiles import ExportProfile, ExportField
|
|
|
|
log = logger.get_logger(__name__)
|
|
|
|
|
|
class ConfigManager:
|
|
"""Manages loading and saving configuration from/to a JSON file."""
|
|
|
|
def __init__(self, config_path: Path):
|
|
self.config_path: Path = config_path
|
|
self.config: Dict[str, Any] = {}
|
|
self.export_profiles: List[ExportProfile] = []
|
|
|
|
@staticmethod
|
|
def _get_default_config() -> Dict[str, Any]:
|
|
"""Provides the default configuration structure for the entire application."""
|
|
default_export_profile = ExportProfile(
|
|
name="Default",
|
|
fields=[
|
|
ExportField(column_name="batch_id", data_path="batch_id"),
|
|
ExportField(
|
|
column_name="timetag",
|
|
data_path="main_header.ge_header.signal_descr.ttag",
|
|
),
|
|
],
|
|
)
|
|
|
|
default_cpp_config = {
|
|
"cpp_executable_path": "C:/path/to/your/g_reconvert.exe",
|
|
"analyze_only": False,
|
|
"no_sign": False,
|
|
"use_fw_header": False,
|
|
"fix_dsp_bug": False,
|
|
"sync_signal_flows": False,
|
|
"extract_sw_only": False,
|
|
"extract_dsp_only": False,
|
|
"stop_on_discontinuity": False,
|
|
"dry_run": False,
|
|
"start_from_stby": False,
|
|
"fix_sata_date": False,
|
|
"examine_data": False,
|
|
"post_process": True,
|
|
"post_process_level": "1",
|
|
"output_format": "",
|
|
"json_config_file": "",
|
|
"max_batches": "",
|
|
"pri_number": "",
|
|
"rbin_number": "",
|
|
"video_out_to_rec": False,
|
|
"video_show": True,
|
|
"video_save": True,
|
|
"video_fix_framerate": False,
|
|
"gps_save_track": True,
|
|
"fix_hr_debug": False,
|
|
"sar_save_only": False,
|
|
"video_add_subtitles": False,
|
|
"verbose": False,
|
|
"debug_messages": False,
|
|
"quiet": False,
|
|
"mask_warnings": False,
|
|
"mask_errors": False,
|
|
"silent_overwrite": True,
|
|
}
|
|
|
|
segment_g_reconverter_options = default_cpp_config.copy()
|
|
segment_g_reconverter_options.update({
|
|
"post_process": False,
|
|
"video_show": False,
|
|
"video_save": False,
|
|
"gps_save_track": True,
|
|
"no_sign": False,
|
|
})
|
|
|
|
default_segment_export_config = {
|
|
"naming_options": {
|
|
"folder_name_template": "{Segment}_{StartBatch}-{EndBatch}",
|
|
},
|
|
"g_reconverter_options": segment_g_reconverter_options
|
|
}
|
|
|
|
return {
|
|
"last_opened_out_file": "",
|
|
"last_opened_rec_file": "",
|
|
"last_out_output_dir": "",
|
|
"last_rec_output_dir": "",
|
|
"last_flight_folder": "",
|
|
"active_out_export_profile_name": "Default",
|
|
"export_profiles": [default_export_profile.to_dict()],
|
|
"cpp_converter_config": default_cpp_config,
|
|
"segment_export_config": default_segment_export_config,
|
|
}
|
|
|
|
def load_config(self) -> None:
|
|
log.info(f"Attempting to load configuration from: {self.config_path}")
|
|
if self.config_path.is_file():
|
|
try:
|
|
with open(self.config_path, "r", encoding="utf-8") as f:
|
|
loaded_data = json.load(f)
|
|
|
|
default_conf = self._get_default_config()
|
|
|
|
self.config = default_conf
|
|
for key, value in loaded_data.items():
|
|
if isinstance(value, dict) and key in self.config:
|
|
self.config[key].update(value)
|
|
if key == "segment_export_config" and "g_reconverter_options" in self.config[key]:
|
|
main_exe_path = self.config.get("cpp_converter_config", {}).get("cpp_executable_path")
|
|
if main_exe_path:
|
|
self.config[key]["g_reconverter_options"]["cpp_executable_path"] = main_exe_path
|
|
else:
|
|
self.config[key] = value
|
|
|
|
profiles_data = self.config.get("export_profiles", [])
|
|
self.export_profiles = [ExportProfile.from_dict(p_data) for p_data in profiles_data]
|
|
|
|
if not self.export_profiles:
|
|
self._load_default_profiles()
|
|
|
|
log.info(f"Configuration loaded. Found {len(self.export_profiles)} export profiles.")
|
|
|
|
except (json.JSONDecodeError, IOError, KeyError) as e:
|
|
log.error(f"Failed to load or parse config file: {e}. Using defaults.")
|
|
self.config = self._get_default_config()
|
|
self._load_default_profiles()
|
|
else:
|
|
log.warning("Configuration file not found. Using default settings.")
|
|
self.config = self._get_default_config()
|
|
self._load_default_profiles()
|
|
|
|
def _load_default_profiles(self):
|
|
default_conf = self._get_default_config()
|
|
profiles_data = default_conf.get("export_profiles", [])
|
|
self.export_profiles = [ExportProfile.from_dict(p_data) for p_data in profiles_data]
|
|
|
|
def save_config(self) -> None:
|
|
log.info(f"Saving configuration to: {self.config_path}")
|
|
self.config["export_profiles"] = [profile.to_dict() for profile in self.export_profiles]
|
|
try:
|
|
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=4)
|
|
log.info("Configuration saved successfully.")
|
|
except IOError as e:
|
|
log.error(f"Failed to save configuration file: {e}")
|
|
|
|
def get(self, key: str, default: Optional[Any] = None) -> Any:
|
|
return self.config.get(key, default)
|
|
|
|
def set(self, key: str, value: Any) -> None:
|
|
self.config[key] = value
|
|
|
|
def get_cpp_converter_config(self) -> Dict[str, Any]:
|
|
return self.config.get("cpp_converter_config", self._get_default_config()["cpp_converter_config"])
|
|
|
|
def save_cpp_converter_config(self, new_config: Dict[str, Any]):
|
|
self.config["cpp_converter_config"] = new_config
|
|
self.save_config()
|
|
|
|
def get_export_profiles(self) -> List[ExportProfile]:
|
|
return self.export_profiles
|
|
|
|
def save_export_profiles(self, profiles: List[ExportProfile]):
|
|
self.export_profiles = profiles
|
|
self.save_config() |