|
3 | 3 | from typing import Optional |
4 | 4 |
|
5 | 5 | from configuration.migration.all_migration import run_all_migration |
6 | | -from constants.app_info import APP_NAME_WITH_VERSION, APP_NAME |
| 6 | +from constants.app_info import APP_NAME_WITH_VERSION, APP_NAME, TITLE_ERROR |
7 | 7 | from constants.files import LOG_FILE_NAME |
8 | 8 | from constants.log import LOG |
9 | 9 | from constants.resources import APP_ICON, UI_SAVE, UI_LOG, UI_CONFIG |
@@ -41,7 +41,7 @@ def __init__(self): |
41 | 41 | def _setup_window(self): |
42 | 42 | self._center_window() |
43 | 43 |
|
44 | | - self.protocol("WM_DELETE_WINDOW", self._on_window_closing) |
| 44 | + self.protocol("WM_DELETE_WINDOW", self.close) |
45 | 45 | self.iconbitmap(APP_ICON) |
46 | 46 | self.title(APP_NAME_WITH_VERSION) |
47 | 47 | self.minsize(*RC_WIN_SIZE) |
@@ -145,38 +145,45 @@ def _save(self): |
145 | 145 | self._update_actions_state() |
146 | 146 | return result |
147 | 147 |
|
148 | | - def _on_window_closing(self): |
| 148 | + def close(self): |
149 | 149 | has_error = self._tabs.has_error() |
150 | 150 |
|
151 | 151 | if self._tabs.has_unsaved_changes(): |
152 | 152 | if has_error: |
| 153 | + self.to_front() |
| 154 | + |
153 | 155 | message = ("There are errors in the rules, and they can't be saved. " |
154 | 156 | "Do you want to DISCARD them and exit?") |
155 | | - result = messagebox.askyesno(f"{APP_NAME_WITH_VERSION}", message) |
| 157 | + result = messagebox.askyesno(TITLE_ERROR, message) |
156 | 158 |
|
157 | 159 | if not result: |
158 | | - return |
| 160 | + return False |
159 | 161 | else: |
| 162 | + self.to_front() |
| 163 | + |
160 | 164 | message = ("There are unsaved changes. " |
161 | 165 | "Do you want to save them before exiting?") |
162 | | - result = messagebox.askyesnocancel(f"{APP_NAME_WITH_VERSION}", message) |
| 166 | + result = messagebox.askyesnocancel(APP_NAME_WITH_VERSION, message) |
163 | 167 |
|
164 | 168 | if result is None: |
165 | | - return |
| 169 | + return False |
166 | 170 |
|
167 | 171 | if result and not self._save(): |
168 | | - return |
| 172 | + return False |
169 | 173 | else: |
170 | 174 | if has_error: |
| 175 | + self.to_front() |
| 176 | + |
171 | 177 | message = ( |
172 | 178 | f"There are errors in the rules, and they must be corrected before the application can work properly. " |
173 | 179 | f"Do you still want to close the {SETTINGS_TITLE}?") |
174 | | - result = messagebox.askyesno(f"{APP_NAME_WITH_VERSION}", message) |
| 180 | + result = messagebox.askyesno(APP_NAME_WITH_VERSION, message) |
175 | 181 |
|
176 | 182 | if not result: |
177 | | - return |
| 183 | + return False |
178 | 184 |
|
179 | 185 | self.destroy() |
| 186 | + return True |
180 | 187 |
|
181 | 188 | def _update_actions_state(self, _=None): |
182 | 189 | tabs = self._tabs |
@@ -331,6 +338,12 @@ def _search_focus(self): |
331 | 338 |
|
332 | 339 | tab.actions.search.focus_set() |
333 | 340 |
|
| 341 | + def to_front(self): |
| 342 | + self.deiconify() |
| 343 | + self.lift() |
| 344 | + self.attributes('-topmost', True) |
| 345 | + self.after_idle(self.attributes, '-topmost', False) |
| 346 | + |
334 | 347 |
|
335 | 348 | class SettingsActions(ttk.Frame): |
336 | 349 | def __init__(self, *args, **kwargs): |
@@ -367,27 +380,50 @@ def _setup_btn(self): |
367 | 380 | save.pack(**RIGHT_PACK) |
368 | 381 |
|
369 | 382 |
|
| 383 | +__app: Optional[Settings] = None |
| 384 | + |
| 385 | + |
370 | 386 | def open_settings(): |
| 387 | + global __app |
| 388 | + |
| 389 | + if __app is not None: |
| 390 | + __app.after_idle(__app.to_front) |
| 391 | + return |
| 392 | + |
371 | 393 | def settings(): |
372 | 394 | try: |
373 | | - app = Settings() |
374 | | - app.mainloop() |
| 395 | + global __app |
| 396 | + |
| 397 | + try: |
| 398 | + __app = Settings() |
| 399 | + __app.mainloop() |
| 400 | + finally: |
| 401 | + __app = None |
375 | 402 | except: |
376 | 403 | LOG.exception(f"An unexpected error occurred in the {SETTINGS_TITLE} of {APP_NAME}.") |
377 | 404 | show_settings_error_message() |
378 | 405 |
|
379 | 406 | TaskScheduler.schedule_task(THREAD_SETTINGS, settings) |
380 | 407 |
|
381 | 408 |
|
| 409 | +def is_opened_settings() -> bool: |
| 410 | + global __app |
| 411 | + return __app is not None |
| 412 | + |
| 413 | + |
| 414 | +def get_settings() -> Settings: |
| 415 | + global __app |
| 416 | + return __app |
| 417 | + |
| 418 | + |
382 | 419 | def show_settings_error_message(): |
383 | | - title = f"Error Detected - {APP_NAME_WITH_VERSION}" |
384 | 420 | message = ( |
385 | 421 | f"An error has occurred in the {SETTINGS_TITLE} of {APP_NAME}.\n" |
386 | 422 | f"To troubleshoot, please check the log file `{LOG_FILE_NAME}` for details.\n\n" |
387 | 423 | f"Would you like to open the log file?" |
388 | 424 | ) |
389 | 425 |
|
390 | | - if yesno_error_box(title, message): |
| 426 | + if yesno_error_box(message): |
391 | 427 | os.startfile(LOG_FILE_NAME) |
392 | 428 |
|
393 | 429 |
|
|
0 commit comments