|
56 | 56 | from pathlib import Path |
57 | 57 | from typing import Optional, List, Dict, Any |
58 | 58 | import logging |
| 59 | +from datetime import datetime |
59 | 60 |
|
60 | 61 | # Ensure project root has priority on sys.path |
61 | 62 | ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) |
|
78 | 79 | ) |
79 | 80 | logger = logging.getLogger(__name__) |
80 | 81 |
|
| 82 | +# Centralized logging for OnlyMod GUIs |
| 83 | +_ONLYMOD_LOG_HISTORY: list[str] = [] |
| 84 | + |
| 85 | + |
| 86 | +def onlymod_log(message: str, gui: Optional[object] = None) -> str: |
| 87 | + """Centralized logging for OnlyMod GUIs. |
| 88 | +
|
| 89 | + - Adds a timestamp |
| 90 | + - Appends to the GUI log widget when provided |
| 91 | + - Mirrors to the standard logger |
| 92 | + """ |
| 93 | + try: |
| 94 | + ts = datetime.now().strftime("%H:%M:%S") |
| 95 | + except Exception: |
| 96 | + ts = "" |
| 97 | + line = f"[{ts}] {message}" if ts else str(message) |
| 98 | + |
| 99 | + try: |
| 100 | + _ONLYMOD_LOG_HISTORY.append(line) |
| 101 | + except Exception: |
| 102 | + pass |
| 103 | + |
| 104 | + try: |
| 105 | + logger.info("[OnlyMod] %s", message) |
| 106 | + except Exception: |
| 107 | + pass |
| 108 | + |
| 109 | + # Push to GUI log widget if available |
| 110 | + if gui is not None: |
| 111 | + try: |
| 112 | + log_text = getattr(gui, "log_text", None) |
| 113 | + is_valid = getattr(gui, "_is_valid", None) |
| 114 | + if callable(is_valid) and not is_valid(log_text): |
| 115 | + return line |
| 116 | + if log_text is not None: |
| 117 | + log_text.append(line) |
| 118 | + scrollbar = log_text.verticalScrollBar() |
| 119 | + scrollbar.setValue(scrollbar.maximum()) |
| 120 | + except Exception: |
| 121 | + pass |
| 122 | + |
| 123 | + return line |
| 124 | + |
81 | 125 | IS_WINDOWS = os.name == "nt" or platform.system().lower().startswith("win") |
82 | 126 | IS_DARWIN = platform.system().lower().startswith("darwin") |
83 | 127 | IS_LINUX = platform.system().lower().startswith("linux") |
@@ -175,19 +219,50 @@ def _platform_log_dir() -> Path: |
175 | 219 | pass |
176 | 220 |
|
177 | 221 |
|
178 | | -def _get_icon_path() -> Optional[str]: |
179 | | - """Return the best available application icon path.""" |
| 222 | +def _get_app_icon_path() -> Optional[str]: |
| 223 | + """Return the best available application icon path (non-GUI usage).""" |
| 224 | + try: |
| 225 | + candidates = [ |
| 226 | + os.path.join(ROOT_DIR, "logo", "image-6.png"), |
| 227 | + os.path.join(ROOT_DIR, "logo", "logo2.png"), |
| 228 | + ] |
| 229 | + for path in candidates: |
| 230 | + if os.path.isfile(path): |
| 231 | + return path |
| 232 | + except Exception: |
| 233 | + pass |
| 234 | + return None |
| 235 | + |
| 236 | + |
| 237 | +def _get_window_icon_path() -> Optional[str]: |
| 238 | + """Return the best available window icon path (GUI usage).""" |
180 | 239 | try: |
181 | | - path = os.path.join(ROOT_DIR, "logo", "logo2.png") |
182 | | - return path if os.path.isfile(path) else None |
| 240 | + candidates = [ |
| 241 | + os.path.join(ROOT_DIR, "logo", "logo2.png"), |
| 242 | + os.path.join(ROOT_DIR, "logo", "logo.png"), |
| 243 | + ] |
| 244 | + for path in candidates: |
| 245 | + if os.path.isfile(path): |
| 246 | + return path |
183 | 247 | except Exception: |
184 | | - return None |
| 248 | + pass |
| 249 | + return None |
| 250 | + |
| 251 | + |
| 252 | +def _set_app_icon(target) -> None: |
| 253 | + """Set the application icon if available.""" |
| 254 | + try: |
| 255 | + icon_path = _get_app_icon_path() |
| 256 | + if icon_path: |
| 257 | + target.setWindowIcon(QIcon(icon_path)) |
| 258 | + except Exception: |
| 259 | + pass |
185 | 260 |
|
186 | 261 |
|
187 | 262 | def _set_window_icon(target) -> None: |
188 | | - """Set the window/application icon if available.""" |
| 263 | + """Set the window (GUI) icon if available.""" |
189 | 264 | try: |
190 | | - icon_path = _get_icon_path() |
| 265 | + icon_path = _get_window_icon_path() |
191 | 266 | if icon_path: |
192 | 267 | target.setWindowIcon(QIcon(icon_path)) |
193 | 268 | except Exception: |
@@ -496,7 +571,7 @@ def launch_bcasl_standalone(workspace_dir: Optional[str] = None) -> int: |
496 | 571 | app = QApplication(sys.argv) |
497 | 572 | app.setApplicationName("PyCompiler ARK++ BCASL") |
498 | 573 | app.setOrganizationName("raidos23") |
499 | | - _set_window_icon(app) |
| 574 | + _set_app_icon(app) |
500 | 575 | window = BcaslStandaloneGui(workspace_dir=workspace_dir) |
501 | 576 | _set_window_icon(window) |
502 | 577 | window.show() |
@@ -547,7 +622,7 @@ def launch_engines_only_standalone(workspace_dir: Optional[str] = None) -> int: |
547 | 622 | app = QApplication(sys.argv) |
548 | 623 | app.setApplicationName("PyCompiler ARK++ Engines") |
549 | 624 | app.setOrganizationName("raidos23") |
550 | | - _set_window_icon(app) |
| 625 | + _set_app_icon(app) |
551 | 626 | window = EnginesStandaloneGui(workspace_dir=workspace_dir) |
552 | 627 | _set_window_icon(window) |
553 | 628 |
|
@@ -582,7 +657,7 @@ def launch_main_application() -> int: |
582 | 657 | """ |
583 | 658 | try: |
584 | 659 | app = QApplication(sys.argv) |
585 | | - _set_window_icon(app) |
| 660 | + _set_app_icon(app) |
586 | 661 |
|
587 | 662 | # Splash screen: affiche l'image 'splash.*' depuis le dossier 'logo' si disponible |
588 | 663 | splash = None |
|
0 commit comments