vibefpmgui.window.options
The project's configuration file (vibefpmgui.build_configs.ConfigFile):
which it is, and the GUI's options and New configuration's Build options in
it (see vibefpmgui.project_options): used while the project is open,
written back (when the window closes or another project is opened, if they
changed), and applied to the window when another project is opened.
A project whose file holds options (it has one that can be read) uses them; without, the app's settings as before (nothing is written in a project only looked at). A file made while the project is open (its first configuration saved) holds its options from then on.
New configuration's Build options are one Configuration: the file's
"new_configuration", or, without options, the app's settings ("profile",
"compiler"… and the project's "features/
1"""The project's configuration file (`vibefpmgui.build_configs.ConfigFile`): 2which it is, and the GUI's options and New configuration's Build options in 3it (see `vibefpmgui.project_options`): used while the project is open, 4written back (when the window closes or another project is opened, if they 5changed), and applied to the window when another project is opened. 6 7A project whose file holds options (it has one that can be read) uses them; 8without, the app's settings as before (nothing is written in a project only 9looked at). A file made while the project is open (its first configuration 10saved) holds its options from then on. 11 12New configuration's Build options are one `Configuration`: the file's 13"new_configuration", or, without options, the app's settings ("profile", 14"compiler"… and the project's "features/<hash>"). 15""" 16 17from __future__ import annotations 18 19import hashlib 20from pathlib import Path 21 22from .. import build_configs as bc 23from .. import project_options as po 24from .. import spelling 25from ..code_editor import CodeEditor 26from ..graph_view import EDGE_STYLES, LAYOUTS, THEME_CHOICES 27 28NEW_CONFIGURATION_KEY = "new_configuration" # (for _apply_options: New configuration's Build options) 29 30 31def project_key(manifest: Path, prefix: str) -> str: 32 """The app's settings key for a project's ``prefix`` (its session, build 33 configurations, features, test durations): "prefix/" and a short hash 34 of its fpm.toml's path. (A name, not security: SHA-1 is fine.)""" 35 digest = hashlib.sha1(str(manifest).encode(), usedforsecurity=False).hexdigest()[:16] 36 return f"{prefix}/{digest}" 37 38 39class ProjectOptionsMixin: 40 """The project's configuration file and its options (a part of 41 `vibefpmgui.main_window.MainWindow`).""" 42 43 config_file: bc.ConfigFile | None = None # the open project's (it may not exist yet) 44 _config_manifest: Path | None = None # the project config_file is for 45 46 @property 47 def config_path(self) -> Path | None: 48 return self.config_file.path if self.config_file is not None else None 49 50 def _project_key(self, prefix: str) -> str: 51 """The app's settings key for this project's ``prefix`` (see `project_key`).""" 52 return project_key(self.manifest_path, prefix) 53 54 def options_in_use(self) -> bool: 55 """The project's options are its file's (not the app's settings).""" 56 return self.settings.options is not None 57 58 # ------------------------------------------------------------ the file 59 def _config_file_for(self, manifest: Path) -> bc.ConfigFile: 60 """A project's configuration file, read: the one opened for it last 61 (Build options → ⋯ → Open Configuration File…), or the one beside its fpm.toml.""" 62 remembered = self.settings.app.value(project_key(manifest, "build_config_file"), "") or "" 63 path = Path(remembered) if remembered and Path(remembered).is_file() else bc.default_path(manifest) 64 return bc.ConfigFile(path).read() 65 66 def _use_config_file(self, file: bc.ConfigFile | None, manifest: Path | None, options: dict | None = None): 67 """Use ``file`` (the project ``manifest``'s) and its options (or 68 ``options``) from now on.""" 69 self.config_file, self._config_manifest = file, manifest 70 keys = {name: project_key(manifest, name) for name in po.PER_PROJECT} if manifest is not None else {} 71 if options is None and file is not None: 72 options = file.options 73 self.settings.use(options, manifest.parent if options is not None else None, keys) 74 75 def _config_file_saved(self): 76 """A configuration was saved: a file just made holds the project's options from now on.""" 77 file = self.config_file 78 if file is not None and file.options is None: 79 file.start_options() 80 self._use_config_file(file, self._config_manifest) 81 82 def _switch_config_file(self, manifest: Path, force: bool = False): 83 """Before another project is opened (or, ``force``, another 84 configuration file of this one): this one's options written, the 85 other's used and applied. (Neither with options: nothing to do but 86 keep New configuration's, which are this project's.)""" 87 if manifest == self._config_manifest and not force: 88 return 89 file = self._config_file_for(manifest) 90 involved = self.options_in_use() or file.options is not None 91 if involved: 92 self._store_window_options() 93 self._write_config_file() 94 elif self.manifest_path is not None: 95 self._keep_free_options(self.free_options()) 96 self._use_config_file(file, manifest) 97 if involved: 98 self._apply_options() 99 100 def _write_config_file(self): 101 """Write the project's options to its file, if they changed.""" 102 file = self.config_file 103 if file is None or not self.options_in_use(): 104 return 105 try: 106 file.write_options(self.settings.complete_options(), self._saved_free_options()) 107 except (OSError, bc.ConfigError) as exc: 108 self.statusBar().showMessage(f"Couldn't save the options in {file.path.name}: {exc}", 8000) 109 110 def reload_config_file(self): 111 """The configuration file was saved in the editor: its configurations 112 read again, and the options changed there (and New configuration, if 113 it was) used and applied; the window's other options, changed since 114 it was read, stay (and the configuration shown).""" 115 file = self.config_file 116 if file is None or self.manifest_path is None: 117 return 118 changed, new_changed = file.reread() 119 if not (changed or new_changed): 120 return 121 if not self.options_in_use(): # (it couldn't be read when the project was opened: fixed now) 122 self._use_config_file(file, self._config_manifest) 123 self._apply_options() 124 return 125 options = dict(self.settings.options) 126 for key in changed: 127 if key in file.options: 128 options[key] = file.options[key] 129 else: 130 options.pop(key, None) 131 self._use_config_file(file, self._config_manifest, options) 132 self._apply_options(changed | ({NEW_CONFIGURATION_KEY} if new_changed else set())) 133 134 # ------------------------------------------------------------ New configuration 135 def _saved_free_options(self) -> bc.Configuration: 136 """New configuration's Build options as kept (not as shown: see 137 free_options): the file's, or the app's settings.""" 138 file, manifest = self.config_file, self._config_manifest # (the project the settings are for) 139 if self.options_in_use() and file is not None and file.new_configuration is not None: 140 return file.new_configuration 141 s = self.settings.app 142 features = (s.value(project_key(manifest, "features"), [], type=list) or []) if manifest else [] 143 return bc.Configuration( 144 "", profile=s.value("profile", bc.DEFAULT_PROFILE) or bc.DEFAULT_PROFILE, 145 features=[str(f) for f in features], compiler=s.value("compiler", "") or "", 146 flags=s.value("flags", "") or "", target=s.value("target", "") or "", 147 extra_args=s.value("extra", "") or "", program_args=s.value("program_args", "") or "", 148 parallel_tests=max(1, s.value("test_jobs", 1, type=int)), coverage=s.value("coverage", False, type=bool), 149 verbose=s.value("verbose", False, type=bool)) 150 151 def _keep_free_options(self, config: bc.Configuration): 152 """Keep New configuration's Build options: in the file (written with 153 the options), or the app's settings.""" 154 file = self.config_file 155 if self.options_in_use() and file is not None: 156 file.new_configuration = bc.Configuration.from_json(config.to_json(named=False), name="") 157 return 158 s = self.settings.app 159 for key, value in (("profile", config.profile), ("compiler", config.compiler), ("flags", config.flags), 160 ("extra", config.extra_args), ("target", config.target), 161 ("program_args", config.program_args), ("verbose", config.verbose), 162 ("coverage", config.coverage), ("test_jobs", config.parallel_tests)): 163 s.setValue(key, value) 164 if self._config_manifest is not None: 165 s.setValue(project_key(self._config_manifest, "features"), list(config.features)) 166 167 def _apply_build_options(self): 168 """Build options' fields: New configuration's, as kept (a saved 169 configuration shown stays: they're shown when it's left).""" 170 free = self._saved_free_options() 171 self._wanted_profile = free.profile 172 if self.config_shown(): 173 self._free_options = free 174 else: 175 self._show_options(free) 176 177 # ------------------------------------------------------------ the window 178 def _toggles(self) -> list[tuple]: 179 """(action, settings key, default) of the View menu's on/off choices.""" 180 return [(self.use_editor_action, "use_editor", True), (self.lint_action, "lint", True), 181 (self.lsp_diagnostics_action, "lsp_diagnostics", True), (self.spelling_action, "spelling", True), 182 (self.gremlins_action, "gremlins", True), (self.minimap_action, "minimap", True), 183 (self.blame_action, "git_blame", False), 184 (self.coverage_action, "show_coverage", True), (self.matches_action, "highlight_matches", True), 185 (self.word_wrap_action, "word_wrap", False), (self.fortls_action, "fortls", True), 186 (self.trim_on_save_action, "trim_on_save", True)] 187 188 def _store_window_options(self, front: list[str] | None = None): 189 """Every option as the window has it now, in the settings (the 190 project's options, or the app's), and New configuration's Build 191 options: those changed are there already, not those never changed (a 192 file's options have them all). ``front``: the panels in front of 193 their stacks (as they were before closing began: see closeEvent). 194 (Collapsed panels are opened first: a layout is saved with them open.)""" 195 s = self.settings 196 for action, key, _default in self._toggles(): 197 s.setValue(key, action.isChecked()) 198 s.setValue("spelling_language", spelling.language) 199 s.setValue("indent_width", CodeEditor.indent_width) 200 s.setValue("indent_tabs", CodeEditor.use_tabs) 201 s.setValue("tab_rows_wrap", self.tab_rows_actions[True].isChecked()) 202 for key, actions in self.graph_style_actions.items(): 203 chosen = next((value for value, action in actions.items() if action.isChecked()), None) 204 if chosen is not None: 205 s.setValue(f"graph_{key}", chosen) 206 s.setValue("graph_dependencies_dev", self.dependencies_dev_action.isChecked()) 207 s.setValue("complexity_tests", self.complexity_panel.tests_check.isChecked()) 208 s.setValue("complexity_dependencies", self.complexity_panel.dependencies_check.isChecked()) 209 s.setValue("coverage_tests", self.coverage_panel.tests_check.isChecked()) 210 for source, button in self.problems_panel.buttons.items(): 211 s.setValue(f"problems/{source}", button.isChecked()) 212 self.search_panel._save_options() 213 front = self.front_panels() if front is None else front 214 self.snap_closed.expand_all() 215 s.setValue("panels", self.saveState(self.LAYOUT_VERSION)) 216 s.setValue("panels_front", front) 217 self._keep_free_options(self.free_options()) 218 219 def _apply_options(self, only: set[str] | None = None): 220 """Options, from the settings, to the window: every one (another 221 project's: the window was made with the first's), or ``only`` those 222 (changed in the file, in the editor; NEW_CONFIGURATION_KEY: New 223 configuration's Build options).""" 224 s = self.settings 225 226 def wanted(*keys: str) -> bool: 227 return only is None or any(key in only for key in keys) 228 229 if wanted(NEW_CONFIGURATION_KEY): 230 self._apply_build_options() 231 # View 232 for action, key, default in self._toggles(): 233 if wanted(key): 234 action.setChecked(s.value(key, default, type=bool)) # (its handler applies it) 235 if wanted("spelling_language"): 236 language = str(s.value("spelling_language", "en") or "en") 237 if language != spelling.language: 238 self.set_spelling_language(language) 239 if wanted("indent_width", "indent_tabs"): 240 width = s.value("indent_width", 4, type=int) 241 use_tabs = s.value("indent_tabs", False, type=bool) 242 if (width, use_tabs) != (CodeEditor.indent_width, CodeEditor.use_tabs): 243 self.set_indentation(width, use_tabs) 244 if wanted("tab_rows_wrap"): 245 self.set_tab_rows(s.value("tab_rows_wrap", False, type=bool), save=False) 246 # Graph 247 if wanted("graph_layout"): 248 self._set_graph_layout(s.value("graph_layout", next(iter(LAYOUTS)))) 249 if wanted("graph_theme"): 250 self._set_graph_theme(s.value("graph_theme", next(iter(THEME_CHOICES)))) 251 if wanted("graph_edges"): 252 self._set_graph_edges(s.value("graph_edges", next(iter(EDGE_STYLES)))) 253 if wanted("graph_dependencies_dev"): 254 dev = s.value("graph_dependencies_dev", False, type=bool) 255 if only is None: # (another project: it's loaded next anyway) 256 self.dependencies_dev_action.blockSignals(True) 257 self.dependencies_dev_action.setChecked(dev) 258 self.dependencies_dev_action.blockSignals(False) 259 # Panels' own choices 260 if wanted("complexity_tests"): 261 self.complexity_panel.tests_check.setChecked(s.value("complexity_tests", False, type=bool)) 262 if wanted("complexity_dependencies"): 263 self.complexity_panel.dependencies_check.setChecked(s.value("complexity_dependencies", False, type=bool)) 264 if wanted("coverage_tests"): 265 self.coverage_panel.tests_check.setChecked(s.value("coverage_tests", False, type=bool)) 266 for source, button in self.problems_panel.buttons.items(): 267 if wanted(f"problems/{source}"): 268 button.setChecked(s.value(f"problems/{source}", True, type=bool)) 269 if any(wanted(key) for key in po.OPTIONS if key.startswith("search/")): 270 self.search_panel._restore_options() 271 if wanted("panels", "panels_front"): 272 layout = s.value("panels") 273 if layout: 274 self.restore_layout(layout, s.value("panels_front", [], type=list) or []) 275 if only is not None and "build_configuration" in only and not self._editing: 276 # (Changed in the file. Another project's: chosen when its configurations are listed.) 277 self.select_configuration(s.value("build_configuration", "") or "")
32def project_key(manifest: Path, prefix: str) -> str: 33 """The app's settings key for a project's ``prefix`` (its session, build 34 configurations, features, test durations): "prefix/" and a short hash 35 of its fpm.toml's path. (A name, not security: SHA-1 is fine.)""" 36 digest = hashlib.sha1(str(manifest).encode(), usedforsecurity=False).hexdigest()[:16] 37 return f"{prefix}/{digest}"
The app's settings key for a project's prefix (its session, build
configurations, features, test durations): "prefix/" and a short hash
of its fpm.toml's path. (A name, not security: SHA-1 is fine.)
40class ProjectOptionsMixin: 41 """The project's configuration file and its options (a part of 42 `vibefpmgui.main_window.MainWindow`).""" 43 44 config_file: bc.ConfigFile | None = None # the open project's (it may not exist yet) 45 _config_manifest: Path | None = None # the project config_file is for 46 47 @property 48 def config_path(self) -> Path | None: 49 return self.config_file.path if self.config_file is not None else None 50 51 def _project_key(self, prefix: str) -> str: 52 """The app's settings key for this project's ``prefix`` (see `project_key`).""" 53 return project_key(self.manifest_path, prefix) 54 55 def options_in_use(self) -> bool: 56 """The project's options are its file's (not the app's settings).""" 57 return self.settings.options is not None 58 59 # ------------------------------------------------------------ the file 60 def _config_file_for(self, manifest: Path) -> bc.ConfigFile: 61 """A project's configuration file, read: the one opened for it last 62 (Build options → ⋯ → Open Configuration File…), or the one beside its fpm.toml.""" 63 remembered = self.settings.app.value(project_key(manifest, "build_config_file"), "") or "" 64 path = Path(remembered) if remembered and Path(remembered).is_file() else bc.default_path(manifest) 65 return bc.ConfigFile(path).read() 66 67 def _use_config_file(self, file: bc.ConfigFile | None, manifest: Path | None, options: dict | None = None): 68 """Use ``file`` (the project ``manifest``'s) and its options (or 69 ``options``) from now on.""" 70 self.config_file, self._config_manifest = file, manifest 71 keys = {name: project_key(manifest, name) for name in po.PER_PROJECT} if manifest is not None else {} 72 if options is None and file is not None: 73 options = file.options 74 self.settings.use(options, manifest.parent if options is not None else None, keys) 75 76 def _config_file_saved(self): 77 """A configuration was saved: a file just made holds the project's options from now on.""" 78 file = self.config_file 79 if file is not None and file.options is None: 80 file.start_options() 81 self._use_config_file(file, self._config_manifest) 82 83 def _switch_config_file(self, manifest: Path, force: bool = False): 84 """Before another project is opened (or, ``force``, another 85 configuration file of this one): this one's options written, the 86 other's used and applied. (Neither with options: nothing to do but 87 keep New configuration's, which are this project's.)""" 88 if manifest == self._config_manifest and not force: 89 return 90 file = self._config_file_for(manifest) 91 involved = self.options_in_use() or file.options is not None 92 if involved: 93 self._store_window_options() 94 self._write_config_file() 95 elif self.manifest_path is not None: 96 self._keep_free_options(self.free_options()) 97 self._use_config_file(file, manifest) 98 if involved: 99 self._apply_options() 100 101 def _write_config_file(self): 102 """Write the project's options to its file, if they changed.""" 103 file = self.config_file 104 if file is None or not self.options_in_use(): 105 return 106 try: 107 file.write_options(self.settings.complete_options(), self._saved_free_options()) 108 except (OSError, bc.ConfigError) as exc: 109 self.statusBar().showMessage(f"Couldn't save the options in {file.path.name}: {exc}", 8000) 110 111 def reload_config_file(self): 112 """The configuration file was saved in the editor: its configurations 113 read again, and the options changed there (and New configuration, if 114 it was) used and applied; the window's other options, changed since 115 it was read, stay (and the configuration shown).""" 116 file = self.config_file 117 if file is None or self.manifest_path is None: 118 return 119 changed, new_changed = file.reread() 120 if not (changed or new_changed): 121 return 122 if not self.options_in_use(): # (it couldn't be read when the project was opened: fixed now) 123 self._use_config_file(file, self._config_manifest) 124 self._apply_options() 125 return 126 options = dict(self.settings.options) 127 for key in changed: 128 if key in file.options: 129 options[key] = file.options[key] 130 else: 131 options.pop(key, None) 132 self._use_config_file(file, self._config_manifest, options) 133 self._apply_options(changed | ({NEW_CONFIGURATION_KEY} if new_changed else set())) 134 135 # ------------------------------------------------------------ New configuration 136 def _saved_free_options(self) -> bc.Configuration: 137 """New configuration's Build options as kept (not as shown: see 138 free_options): the file's, or the app's settings.""" 139 file, manifest = self.config_file, self._config_manifest # (the project the settings are for) 140 if self.options_in_use() and file is not None and file.new_configuration is not None: 141 return file.new_configuration 142 s = self.settings.app 143 features = (s.value(project_key(manifest, "features"), [], type=list) or []) if manifest else [] 144 return bc.Configuration( 145 "", profile=s.value("profile", bc.DEFAULT_PROFILE) or bc.DEFAULT_PROFILE, 146 features=[str(f) for f in features], compiler=s.value("compiler", "") or "", 147 flags=s.value("flags", "") or "", target=s.value("target", "") or "", 148 extra_args=s.value("extra", "") or "", program_args=s.value("program_args", "") or "", 149 parallel_tests=max(1, s.value("test_jobs", 1, type=int)), coverage=s.value("coverage", False, type=bool), 150 verbose=s.value("verbose", False, type=bool)) 151 152 def _keep_free_options(self, config: bc.Configuration): 153 """Keep New configuration's Build options: in the file (written with 154 the options), or the app's settings.""" 155 file = self.config_file 156 if self.options_in_use() and file is not None: 157 file.new_configuration = bc.Configuration.from_json(config.to_json(named=False), name="") 158 return 159 s = self.settings.app 160 for key, value in (("profile", config.profile), ("compiler", config.compiler), ("flags", config.flags), 161 ("extra", config.extra_args), ("target", config.target), 162 ("program_args", config.program_args), ("verbose", config.verbose), 163 ("coverage", config.coverage), ("test_jobs", config.parallel_tests)): 164 s.setValue(key, value) 165 if self._config_manifest is not None: 166 s.setValue(project_key(self._config_manifest, "features"), list(config.features)) 167 168 def _apply_build_options(self): 169 """Build options' fields: New configuration's, as kept (a saved 170 configuration shown stays: they're shown when it's left).""" 171 free = self._saved_free_options() 172 self._wanted_profile = free.profile 173 if self.config_shown(): 174 self._free_options = free 175 else: 176 self._show_options(free) 177 178 # ------------------------------------------------------------ the window 179 def _toggles(self) -> list[tuple]: 180 """(action, settings key, default) of the View menu's on/off choices.""" 181 return [(self.use_editor_action, "use_editor", True), (self.lint_action, "lint", True), 182 (self.lsp_diagnostics_action, "lsp_diagnostics", True), (self.spelling_action, "spelling", True), 183 (self.gremlins_action, "gremlins", True), (self.minimap_action, "minimap", True), 184 (self.blame_action, "git_blame", False), 185 (self.coverage_action, "show_coverage", True), (self.matches_action, "highlight_matches", True), 186 (self.word_wrap_action, "word_wrap", False), (self.fortls_action, "fortls", True), 187 (self.trim_on_save_action, "trim_on_save", True)] 188 189 def _store_window_options(self, front: list[str] | None = None): 190 """Every option as the window has it now, in the settings (the 191 project's options, or the app's), and New configuration's Build 192 options: those changed are there already, not those never changed (a 193 file's options have them all). ``front``: the panels in front of 194 their stacks (as they were before closing began: see closeEvent). 195 (Collapsed panels are opened first: a layout is saved with them open.)""" 196 s = self.settings 197 for action, key, _default in self._toggles(): 198 s.setValue(key, action.isChecked()) 199 s.setValue("spelling_language", spelling.language) 200 s.setValue("indent_width", CodeEditor.indent_width) 201 s.setValue("indent_tabs", CodeEditor.use_tabs) 202 s.setValue("tab_rows_wrap", self.tab_rows_actions[True].isChecked()) 203 for key, actions in self.graph_style_actions.items(): 204 chosen = next((value for value, action in actions.items() if action.isChecked()), None) 205 if chosen is not None: 206 s.setValue(f"graph_{key}", chosen) 207 s.setValue("graph_dependencies_dev", self.dependencies_dev_action.isChecked()) 208 s.setValue("complexity_tests", self.complexity_panel.tests_check.isChecked()) 209 s.setValue("complexity_dependencies", self.complexity_panel.dependencies_check.isChecked()) 210 s.setValue("coverage_tests", self.coverage_panel.tests_check.isChecked()) 211 for source, button in self.problems_panel.buttons.items(): 212 s.setValue(f"problems/{source}", button.isChecked()) 213 self.search_panel._save_options() 214 front = self.front_panels() if front is None else front 215 self.snap_closed.expand_all() 216 s.setValue("panels", self.saveState(self.LAYOUT_VERSION)) 217 s.setValue("panels_front", front) 218 self._keep_free_options(self.free_options()) 219 220 def _apply_options(self, only: set[str] | None = None): 221 """Options, from the settings, to the window: every one (another 222 project's: the window was made with the first's), or ``only`` those 223 (changed in the file, in the editor; NEW_CONFIGURATION_KEY: New 224 configuration's Build options).""" 225 s = self.settings 226 227 def wanted(*keys: str) -> bool: 228 return only is None or any(key in only for key in keys) 229 230 if wanted(NEW_CONFIGURATION_KEY): 231 self._apply_build_options() 232 # View 233 for action, key, default in self._toggles(): 234 if wanted(key): 235 action.setChecked(s.value(key, default, type=bool)) # (its handler applies it) 236 if wanted("spelling_language"): 237 language = str(s.value("spelling_language", "en") or "en") 238 if language != spelling.language: 239 self.set_spelling_language(language) 240 if wanted("indent_width", "indent_tabs"): 241 width = s.value("indent_width", 4, type=int) 242 use_tabs = s.value("indent_tabs", False, type=bool) 243 if (width, use_tabs) != (CodeEditor.indent_width, CodeEditor.use_tabs): 244 self.set_indentation(width, use_tabs) 245 if wanted("tab_rows_wrap"): 246 self.set_tab_rows(s.value("tab_rows_wrap", False, type=bool), save=False) 247 # Graph 248 if wanted("graph_layout"): 249 self._set_graph_layout(s.value("graph_layout", next(iter(LAYOUTS)))) 250 if wanted("graph_theme"): 251 self._set_graph_theme(s.value("graph_theme", next(iter(THEME_CHOICES)))) 252 if wanted("graph_edges"): 253 self._set_graph_edges(s.value("graph_edges", next(iter(EDGE_STYLES)))) 254 if wanted("graph_dependencies_dev"): 255 dev = s.value("graph_dependencies_dev", False, type=bool) 256 if only is None: # (another project: it's loaded next anyway) 257 self.dependencies_dev_action.blockSignals(True) 258 self.dependencies_dev_action.setChecked(dev) 259 self.dependencies_dev_action.blockSignals(False) 260 # Panels' own choices 261 if wanted("complexity_tests"): 262 self.complexity_panel.tests_check.setChecked(s.value("complexity_tests", False, type=bool)) 263 if wanted("complexity_dependencies"): 264 self.complexity_panel.dependencies_check.setChecked(s.value("complexity_dependencies", False, type=bool)) 265 if wanted("coverage_tests"): 266 self.coverage_panel.tests_check.setChecked(s.value("coverage_tests", False, type=bool)) 267 for source, button in self.problems_panel.buttons.items(): 268 if wanted(f"problems/{source}"): 269 button.setChecked(s.value(f"problems/{source}", True, type=bool)) 270 if any(wanted(key) for key in po.OPTIONS if key.startswith("search/")): 271 self.search_panel._restore_options() 272 if wanted("panels", "panels_front"): 273 layout = s.value("panels") 274 if layout: 275 self.restore_layout(layout, s.value("panels_front", [], type=list) or []) 276 if only is not None and "build_configuration" in only and not self._editing: 277 # (Changed in the file. Another project's: chosen when its configurations are listed.) 278 self.select_configuration(s.value("build_configuration", "") or "")
The project's configuration file and its options (a part of
vibefpmgui.main_window.MainWindow).
55 def options_in_use(self) -> bool: 56 """The project's options are its file's (not the app's settings).""" 57 return self.settings.options is not None
The project's options are its file's (not the app's settings).
111 def reload_config_file(self): 112 """The configuration file was saved in the editor: its configurations 113 read again, and the options changed there (and New configuration, if 114 it was) used and applied; the window's other options, changed since 115 it was read, stay (and the configuration shown).""" 116 file = self.config_file 117 if file is None or self.manifest_path is None: 118 return 119 changed, new_changed = file.reread() 120 if not (changed or new_changed): 121 return 122 if not self.options_in_use(): # (it couldn't be read when the project was opened: fixed now) 123 self._use_config_file(file, self._config_manifest) 124 self._apply_options() 125 return 126 options = dict(self.settings.options) 127 for key in changed: 128 if key in file.options: 129 options[key] = file.options[key] 130 else: 131 options.pop(key, None) 132 self._use_config_file(file, self._config_manifest, options) 133 self._apply_options(changed | ({NEW_CONFIGURATION_KEY} if new_changed else set()))
The configuration file was saved in the editor: its configurations read again, and the options changed there (and New configuration, if it was) used and applied; the window's other options, changed since it was read, stay (and the configuration shown).