def load_cfg_from_path(self, cfg_path: Path): # Bind GUI to dummy config, in case loading cfg_path raises Exception. if self.model is None: self.load_cfg(template_config(), None) assert cfg_path.is_file() self.pref.file_dir = str(cfg_path.parent.resolve()) # Raises YAML structural exceptions cfg = yaml.load(cfg_path) try: # Raises color getter exceptions self.load_cfg(cfg, cfg_path) except Exception as e: # FIXME if error halfway, clear "file path" and load empty model. TracebackDialog(self).showMessage(format_stack_trace(e)) return
def excepthook(exc_type, exc_val, exc_tb): TracebackDialog(window).showMessage(format_stack_trace(exc_val))
def on_play_thread_error(self, stack_trace: str): TracebackDialog(self).showMessage(stack_trace)
def __init__(self, cfg_or_path: Union[Config, Path]): super().__init__() # Load settings. prefs_error = None try: self.pref = gp.load_prefs() if not isinstance(self.pref, gp.GlobalPrefs): raise TypeError( f"prefs.yaml contains wrong type {type(self.pref)}") except Exception as e: prefs_error = e self.pref = gp.GlobalPrefs() # Load UI. self.setupUi(self) # sets windowTitle # Bind UI buttons, etc. Functions block main thread, avoiding race conditions. self.master_audio_browse.clicked.connect(self.on_master_audio_browse) self.channelUp.add_shortcut(self.channelsGroup, "ctrl+shift+up") self.channelDown.add_shortcut(self.channelsGroup, "ctrl+shift+down") self.channelUp.clicked.connect(self.channel_view.on_channel_up) self.channelDown.clicked.connect(self.channel_view.on_channel_down) self.channelAdd.clicked.connect(self.on_channel_add) self.channelDelete.clicked.connect(self.on_channel_delete) # Bind actions. self.action_separate_render_dir.setChecked( self.pref.separate_render_dir) self.action_separate_render_dir.toggled.connect( self.on_separate_render_dir_toggled) self.action_open_config_dir.triggered.connect(self.on_open_config_dir) self.actionNew.triggered.connect(self.on_action_new) self.actionOpen.triggered.connect(self.on_action_open) self.actionSave.triggered.connect(self.on_action_save) self.actionSaveAs.triggered.connect(self.on_action_save_as) self.actionPreview.triggered.connect(self.on_action_preview) self.actionRender.triggered.connect(self.on_action_render) self.actionWebsite.triggered.connect(self.on_action_website) self.actionHelp.triggered.connect(self.on_action_help) self.actionExit.triggered.connect(qw.QApplication.closeAllWindows) # Initialize CorrScope-thread attribute. self.corr_thread: Optional[CorrThread] = None # Setup UI. self.model = ConfigModel(template_config()) self.model.edited.connect(self.on_model_edited) # Calls self.on_gui_edited() whenever GUI widgets change. map_gui(self, self.model) self.model.update_widget["render_stereo"].append( self.on_render_stereo_changed) # Bind config to UI. if isinstance(cfg_or_path, Config): self.load_cfg(cfg_or_path, None) save_dir = self.compute_save_dir(self.cfg) if save_dir: self.pref.file_dir = save_dir elif isinstance(cfg_or_path, Path): self.load_cfg_from_path(cfg_or_path) else: raise TypeError( f"argument cfg={cfg_or_path} has invalid type {obj_name(cfg_or_path)}" ) self.show() if prefs_error is not None: TracebackDialog(self).showMessage( "Warning: failed to load global preferences, resetting to default.\n" + format_stack_trace(prefs_error))