"""Có dùng được QtWebEngine hay không — R08-T14. Cờ khả năng, tách riêng vì cả ``structure_graph_view.py`` lẫn ``graph_render.py`` đều phải hỏi. Để ở một trong hai thì file kia import ngược lại — vòng import. WebEngine là add-on tuỳ chọn của PySide6, và bản đóng gói one-file của PyInstaller không chạy được nó; những trường hợp đó rơi về khung nhìn Qt. """ from __future__ import annotations import sys from pathlib import Path def _frozen_onefile() -> bool: """True only for a PyInstaller ONEFILE build. Onefile extracts itself to a temp dir (sys._MEIPASS under %TEMP%), where the QtWebEngine helper process can't run — creating a QWebEngineView hard-crashes the app (reported as "click the graph tab → app closes"). A ONEDIR build keeps _MEIPASS as the ``_internal`` folder right next to the exe, where WebEngine works fine, so it keeps the full embedded D3 view.""" if not getattr(sys, "frozen", False): return False meipass = getattr(sys, "_MEIPASS", "") if not meipass: return False try: return Path(meipass).resolve().parent != Path(sys.executable).resolve().parent except OSError: # can't tell → play safe: use the native fallback return True try: # WebEngine + WebChannel are optional PySide6 add-ons from PySide6.QtWebEngineWidgets import QWebEngineView from PySide6.QtWebChannel import QWebChannel _HAS_WEB = not _frozen_onefile() except Exception: # pragma: no cover _HAS_WEB = False