EyeTrackVR/EyeTrackApp/settings/BaseSettings.py

94 lines
3.9 KiB
Python

from datetime import datetime, timedelta
from typing import Iterable
import PySimpleGUI as sg
from colorama import Fore
from threading import Event
from eye import EyeId
from config import EyeTrackConfig, EyeTrackSettingsConfig
class BaseSettingsWidget:
def __init__(self, widget_id: EyeId, main_config: EyeTrackConfig, settings_modules: Iterable):
self.widget_id = widget_id
self.main_config = main_config
self.config = main_config.settings
self.last_error_printout = datetime.now() - timedelta(seconds=20)
self.error_printout_timeout = 2
self.reset_button_key = f"RESET_SETTINGS{widget_id}"
self.is_saving = False
self.initialized_modules = self._initialize_modules(settings_modules=settings_modules, widget_id=widget_id)
self.cancellation_event = Event()
self.cancellation_event.set()
def started(self):
return not self.cancellation_event.is_set()
def start(self):
if not self.cancellation_event.is_set():
return
self.cancellation_event.clear()
def stop(self):
if self.cancellation_event.is_set():
return
self.cancellation_event.set()
def _update_and_save_config(self, validated_data: dict):
self.main_config.update(validated_data, save=True)
self.is_saving = False
def _handle_errors(self, errors):
now = datetime.now()
elapsed_seconds = (datetime.now() - self.last_error_printout).seconds
if elapsed_seconds > self.error_printout_timeout:
self.last_error_printout = now
messages = [f"{Fore.RED}[ERROR]{Fore.RESET} {error['msg']} \n" for module_errors in errors for error in module_errors]
print("".join(messages))
def render(self, window, event, values):
validated_data, errors = {}, []
for module in self.initialized_modules:
module_validated_data = module.validate(values)
if module_validated_data.changes:
validated_data.update(module_validated_data.changes)
if module_validated_data.errors:
errors.append(module_validated_data.errors)
if not errors and validated_data and not self.is_saving:
self.is_saving = True
self._update_and_save_config(validated_data)
if errors:
self._handle_errors(errors)
self.handle_events(event, window)
def _initialize_modules(self, settings_modules, widget_id):
return [module(config=self.config, settings=self.main_config, widget_id=widget_id) for module in settings_modules]
def get_layout(self) -> Iterable:
general_settings_layout = []
for module in self.initialized_modules:
general_settings_layout.extend(module.get_layout())
widget_layout = [
[sg.Column(general_settings_layout, key=f"-GENERALSETTINGSLAYOUT{self.widget_id}-", background_color="#424042")],
[sg.Text("", background_color="#424042")],
[sg.Button("Reset settings to default", key=self.reset_button_key, button_color="#c40e23")]
]
return widget_layout
def handle_events(self, event, window):
if event == "__TIMEOUT__":
return
if event == self.reset_button_key:
self.reset_config(window)
def reset_config(self, window):
default_values = {}
base_settings = EyeTrackSettingsConfig()
print(f"\033[92m[INFO] Resetting config to defaults\033[0m")
for module in self.initialized_modules:
for key in module.get_key_for_panel_defaults():
default_val = getattr(base_settings, key)
widget_key = getattr(module, key)
default_values[key] = default_val
window[widget_key].update(default_val)
print(f"\033[92m[INFO] Config reset, saving\033[0m")
self._update_and_save_config(default_values)