|
22 | 22 | import threading |
23 | 23 | from typing import Optional |
24 | 24 |
|
25 | | -from PySide6.QtCore import QObject, QProcess, Qt, QTimer, Signal |
| 25 | +from PySide6.QtCore import QProcess, Qt |
26 | 26 | from PySide6.QtGui import QDropEvent, QPixmap |
27 | 27 | from PySide6.QtWidgets import QApplication, QFileDialog, QMessageBox, QWidget |
| 28 | + |
| 29 | +from .utils import _UiInvoker, _run_coro_async |
28 | 30 | from .dialogs import ProgressDialog, CompilationProcessDialog |
29 | 31 | from .Venv_Manager import VenvManager |
30 | 32 |
|
@@ -56,53 +58,6 @@ def get_selected_workspace() -> Optional[str]: |
56 | 58 | return None |
57 | 59 |
|
58 | 60 |
|
59 | | -class _UiInvoker(QObject): |
60 | | - _sig = Signal(object) |
61 | | - |
62 | | - def __init__(self, parent=None): |
63 | | - super().__init__(parent) |
64 | | - self._sig.connect(self._exec, Qt.QueuedConnection) |
65 | | - |
66 | | - def post(self, fn): |
67 | | - try: |
68 | | - self._sig.emit(fn) |
69 | | - except Exception: |
70 | | - pass |
71 | | - |
72 | | - def _exec(self, fn): |
73 | | - try: |
74 | | - fn() |
75 | | - except Exception: |
76 | | - pass |
77 | | - |
78 | | - |
79 | | -def _run_coro_async(coro, on_result, ui_owner=None): |
80 | | - invoker = None |
81 | | - try: |
82 | | - if ui_owner is not None and isinstance(ui_owner, QObject): |
83 | | - invoker = getattr(ui_owner, "_ui_invoker", None) |
84 | | - if invoker is None: |
85 | | - invoker = _UiInvoker(ui_owner) |
86 | | - setattr(ui_owner, "_ui_invoker", invoker) |
87 | | - except Exception: |
88 | | - invoker = None |
89 | | - |
90 | | - def _runner(): |
91 | | - try: |
92 | | - res = asyncio.run(coro) |
93 | | - except Exception as e: |
94 | | - res = e |
95 | | - try: |
96 | | - if invoker is not None: |
97 | | - invoker.post(lambda: on_result(res)) |
98 | | - else: |
99 | | - QTimer.singleShot(0, lambda: on_result(res)) |
100 | | - except Exception: |
101 | | - pass |
102 | | - |
103 | | - threading.Thread(target=_runner, daemon=True).start() |
104 | | - |
105 | | - |
106 | 61 | # Synchronous request from background threads to change workspace via GUI thread |
107 | 62 | # Ensures confirmation dialog is shown and result returned to caller |
108 | 63 | from PySide6.QtCore import QEventLoop as _QEventLoop |
@@ -1117,7 +1072,7 @@ def show_statistics(self): |
1117 | 1072 | # Internationalization using JSON language files |
1118 | 1073 | current_language = "English" |
1119 | 1074 |
|
1120 | | - def _apply_translations(self, tr: dict): |
| 1075 | + def _apply_main_app_translations(self, tr: dict): |
1121 | 1076 | # Utilitaires internes pour éviter les valeurs codées en dur |
1122 | 1077 | def _set(attr: str, key: str, method: str = "setText"): |
1123 | 1078 | try: |
@@ -1202,7 +1157,7 @@ def _on_result(res): |
1202 | 1157 | if isinstance(res, Exception): |
1203 | 1158 | return |
1204 | 1159 | code, tr = res |
1205 | | - self._apply_translations(tr) |
| 1160 | + self._apply_main_app_translations(tr) |
1206 | 1161 | # Notifier les moteurs pour rafraîchir leurs libellés (i18n) |
1207 | 1162 | try: |
1208 | 1163 | # Callback-based refresh (legacy) |
|
0 commit comments