| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import json
- import os
- import copy
- def save_json_file(file_path, data):
- """Sauvegarde générique de données JSON."""
- try:
- os.makedirs(os.path.dirname(file_path), exist_ok=True)
- with open(file_path, 'w', encoding='utf-8') as f:
- json.dump(data, f, indent=4)
- return True, None
- except Exception as e:
- return False, str(e)
- def load_json_file(file_path):
- """Chargement générique de données JSON."""
- if not os.path.exists(file_path):
- return None, "File not found"
- try:
- with open(file_path, 'r', encoding='utf-8') as f:
- data = json.load(f)
- return data, None
- except Exception as e:
- return None, str(e)
-
- class ConfigManager:
- # Source de vérité unique pour les paramètres d'usine
- DEFAULT_CONFIG = {
- "machine_settings": {
- "theme": "Dark",
- "language": "English",
- "cmd_mode": "M67 (Analog)",
- "firing_mode": "M3/M5",
- "m67_e_num": 0,
- "ctrl_max": 1000,
- "gcode_extension": ".nc",
- "laser_latency": 0.0,
- "premove": 10.0,
- "hor_linestep": 0.1,
- "ver_linestep": 0.1,
- "enable_thumbnails": True,
- "custom_header": "",
- "custom_footer": ""
- },
- "stats": {
- "total_lines": 0,
- "total_gcodes": 0,
- "total_time_seconds": 0.0
- }
- }
- # Clés qui doivent toujours être des entiers
- _INT_KEYS = {"m67_e_num", "ctrl_max"}
- def __init__(self, config_path):
- self.config_path = config_path
- self.data = self._load_from_disk()
- self._apply_defaults()
- def _load_from_disk(self):
- """Charge le fichier JSON ou renvoie un dict vide si absent/corrompu"""
- if not os.path.exists(self.config_path):
- return {}
- try:
- with open(self.config_path, 'r', encoding='utf-8') as f:
- return json.load(f)
- except Exception:
- return {}
- def _apply_defaults(self):
- """Injecte les valeurs par défaut manquantes et corrige les types connus."""
- for section, content in self.DEFAULT_CONFIG.items():
- if section not in self.data:
- self.data[section] = copy.deepcopy(content)
- else:
- for key, val in content.items():
- if key not in self.data[section]:
- self.data[section][key] = val
- # Correction des types : m67_e_num et ctrl_max doivent être int
- ms = self.data.get("machine_settings", {})
- for key in self._INT_KEYS:
- if key in ms:
- try:
- ms[key] = int(float(str(ms[key])))
- except (ValueError, TypeError):
- ms[key] = self.DEFAULT_CONFIG["machine_settings"][key]
- def get_item(self, section, key, default=None):
- """LA MÉTHODE MANQUANTE : Récupère une valeur spécifique"""
- section_data = self.data.get(section, {})
- return section_data.get(key, default)
- def set_item(self, section, key, value):
- """
- Définit une valeur et la sauvegarde immédiatement.
- """
- if section not in self.data:
- self.data[section] = {}
- self.data[section][key] = value
- return self.save()
- def get_section(self, section_name):
- """Récupère une section entière (utile pour SettingsView)"""
- return self.data.get(section_name, {})
- def set_section(self, section_name, new_data):
- """Met à jour une section avant sauvegarde"""
- self.data[section_name] = new_data
- def save(self):
- """Sauvegarde l'état actuel sur le disque"""
- try:
- with open(self.config_path, 'w', encoding='utf-8') as f:
- json.dump(self.data, f, indent=4)
- return True
- except Exception as e:
- print(f"Erreur de sauvegarde : {e}")
- return False
- def reset_all(self):
- """Réinitialisation totale aux paramètres d'usine"""
- self.data = copy.deepcopy(self.DEFAULT_CONFIG)
- return self.save()
|