Skip to content

Commit 6cf7398

Browse files
author
PyCompiler ARK++
committed
refactor: Enhance UI loading process and improve error handling in BCASLStudioWindow
1 parent 66f21b6 commit 6cf7398

1 file changed

Lines changed: 92 additions & 55 deletions

File tree

bcasl/only_mod/widgets/main_window.py

Lines changed: 92 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ def run(self):
8080
class BCASLStudioWindow(QMainWindow):
8181
def __init__(self):
8282
super().__init__()
83-
self.setWindowTitle("BCASL Studio (Standalone)")
84-
self.resize(1400, 900)
8583
self.workspace: Optional[Path] = None
8684
self.plugins_dir: Optional[Path] = None
8785
self.cfg = None
@@ -90,69 +88,95 @@ def __init__(self):
9088

9189
self._load_ui_from_designer()
9290
self._wire_menu_from_ui()
93-
self._normalize_tab_positions()
9491
self._wire_logic()
9592

9693
# ---------- UI loading from Designer ----------
9794
def _load_ui_from_designer(self):
95+
# Load the .ui into a temporary QMainWindow, then copy its full state/layout into this subclass instance.
9896
loader = QUiLoader()
9997
ui_path = Path(__file__).resolve().parents[1] / "ui" / "studio.ui"
10098
f = QFile(str(ui_path))
10199
if not f.open(QFile.ReadOnly):
102100
raise RuntimeError(f"Cannot open UI file: {ui_path}")
103-
# Load without parenting to avoid premature deletions; keep strong ref
104-
w = loader.load(f)
105-
f.close()
106-
if w is None:
107-
raise RuntimeError("Failed to load UI")
108-
self._ui_loaded = w # keep strong reference to prevent GC/deletion
109-
# Adopt menubar/statusbar/central widget and docks
110101
try:
111-
from PySide6.QtWidgets import QMenuBar, QStatusBar
112-
mb = w.findChild(QMenuBar, "menubar")
113-
if mb:
114-
self.setMenuBar(mb)
115-
sb = w.findChild(QStatusBar, "statusbar")
116-
if sb:
117-
self.setStatusBar(sb)
118-
except Exception:
119-
pass
120-
cw = w.findChild(QWidget, "centralwidget")
121-
if cw:
122-
self.setCentralWidget(cw)
123-
# Docks by name (reparent into this main window)
124-
for name in ("dock_workspace", "dock_plugins", "dock_settings", "dock_log"):
102+
temp = loader.load(f)
103+
if temp is None:
104+
raise RuntimeError("Failed to load UI")
105+
finally:
106+
f.close()
107+
# temp is a QMainWindow instance created from the .ui
108+
try:
109+
# Apply geometry and top-level properties
125110
try:
126-
dw = w.findChild(QDockWidget, name)
127-
if dw:
128-
area = Qt.LeftDockWidgetArea if name in ("dock_workspace", "dock_plugins") else (Qt.RightDockWidgetArea if name == "dock_settings" else Qt.BottomDockWidgetArea)
129-
self.addDockWidget(area, dw)
111+
self.setObjectName(temp.objectName())
130112
except Exception:
131-
continue
132-
# Expose widgets by attribute for logic (from loaded root)
133-
self.ws_path = w.findChild(QLineEdit, "ws_path")
134-
self.ws_browse = w.findChild(QPushButton, "ws_browse")
135-
self.plugins_path = w.findChild(QLineEdit, "plugins_path")
136-
self.plugins_browse = w.findChild(QPushButton, "plugins_browse")
137-
self.btn_load_ws = w.findChild(QPushButton, "btn_load_ws")
138-
self.btn_save_cfg = w.findChild(QPushButton, "btn_save_cfg")
139-
self.btn_run = w.findChild(QPushButton, "btn_run")
140-
self.filter_text = w.findChild(QLineEdit, "filter_text")
141-
self.filter_phase = w.findChild(QComboBox, "filter_phase")
142-
self.list_plugins = w.findChild(QListWidget, "list_plugins")
143-
self.sp_timeout2 = w.findChild(QSpinBox, "sp_timeout2")
144-
self.chk_sandbox2 = w.findChild(QCheckBox, "chk_sandbox2")
145-
self.sp_parallel2 = w.findChild(QSpinBox, "sp_parallel2")
146-
self.sp_timeout = w.findChild(QSpinBox, "sp_timeout")
147-
self.chk_sandbox = w.findChild(QCheckBox, "chk_sandbox")
148-
self.sp_parallel = w.findChild(QSpinBox, "sp_parallel")
149-
self.txt_log = w.findChild(QPlainTextEdit, "txt_log")
113+
pass
114+
try:
115+
self.setWindowTitle(temp.windowTitle())
116+
except Exception:
117+
pass
118+
try:
119+
self.setGeometry(temp.geometry())
120+
except Exception:
121+
pass
122+
# Menubar/Statusbar
123+
try:
124+
from PySide6.QtWidgets import QMenuBar, QStatusBar
125+
mb = temp.findChild(QMenuBar)
126+
if mb:
127+
self.setMenuBar(mb)
128+
sb = temp.findChild(QStatusBar)
129+
if sb:
130+
self.setStatusBar(sb)
131+
except Exception:
132+
pass
133+
# Central widget
134+
cw = temp.centralWidget()
135+
if cw:
136+
self.setCentralWidget(cw)
137+
# Docks: transfer all docks and restore original state to preserve positions
138+
docks = temp.findChildren(QDockWidget)
139+
for dw in docks:
140+
# Add to some area first; we'll restore precise layout below
141+
try:
142+
self.addDockWidget(Qt.LeftDockWidgetArea, dw)
143+
except Exception:
144+
pass
145+
try:
146+
state = temp.saveState()
147+
self.restoreState(state)
148+
except Exception:
149+
pass
150+
finally:
151+
try:
152+
temp.deleteLater()
153+
except Exception:
154+
pass
155+
# Expose commonly used widgets by name
156+
self._ui_loaded = self
157+
self.ws_path = self.findChild(QLineEdit, "ws_path")
158+
self.ws_browse = self.findChild(QPushButton, "ws_browse")
159+
self.plugins_path = self.findChild(QLineEdit, "plugins_path")
160+
self.plugins_browse = self.findChild(QPushButton, "plugins_browse")
161+
self.btn_load_ws = self.findChild(QPushButton, "btn_load_ws")
162+
self.btn_save_cfg = self.findChild(QPushButton, "btn_save_cfg")
163+
self.btn_run = self.findChild(QPushButton, "btn_run")
164+
self.filter_text = self.findChild(QLineEdit, "filter_text")
165+
self.filter_phase = self.findChild(QComboBox, "filter_phase")
166+
self.list_plugins = self.findChild(QListWidget, "list_plugins")
167+
self.sp_timeout2 = self.findChild(QSpinBox, "sp_timeout2")
168+
self.chk_sandbox2 = self.findChild(QCheckBox, "chk_sandbox2")
169+
self.sp_parallel2 = self.findChild(QSpinBox, "sp_parallel2")
170+
self.sp_timeout = self.findChild(QSpinBox, "sp_timeout")
171+
self.chk_sandbox = self.findChild(QCheckBox, "chk_sandbox")
172+
self.sp_parallel = self.findChild(QSpinBox, "sp_parallel")
173+
self.txt_log = self.findChild(QPlainTextEdit, "txt_log")
150174
# Menus/actions
151-
self.actOpenWorkspace = w.findChild(QAction, "actOpenWorkspace")
152-
self.actSelectPluginsDir = w.findChild(QAction, "actSelectPluginsDir")
153-
self.actSaveConfig = w.findChild(QAction, "actSaveConfig")
154-
self.actRun = w.findChild(QAction, "actRun")
155-
self.menuTheme = w.findChild(QMenu, "menuTheme")
175+
self.actOpenWorkspace = self.findChild(QAction, "actOpenWorkspace")
176+
self.actSelectPluginsDir = self.findChild(QAction, "actSelectPluginsDir")
177+
self.actSaveConfig = self.findChild(QAction, "actSaveConfig")
178+
self.actRun = self.findChild(QAction, "actRun")
179+
self.menuTheme = self.findChild(QMenu, "menuTheme")
156180

157181
def _wire_menu_from_ui(self):
158182
# Connect actions
@@ -166,7 +190,15 @@ def _wire_menu_from_ui(self):
166190
self.actRun.triggered.connect(self._run)
167191
# Populate theme menu
168192
self.m_theme = self.menuTheme
169-
self._populate_theme_menu()
193+
if not self.m_theme:
194+
try:
195+
mb = self.menuBar() if hasattr(self, 'menuBar') else None
196+
if mb:
197+
self.m_theme = mb.findChild(QMenu, "menuTheme")
198+
except Exception:
199+
self.m_theme = None
200+
if self.m_theme:
201+
self._populate_theme_menu()
170202

171203
def _wire_logic(self):
172204
# Buttons (defensive: only connect when widgets are present)
@@ -228,6 +260,8 @@ def _apply_theme_file(self, path: Path):
228260

229261
def _populate_theme_menu(self):
230262
# Scan themes/ at repo root
263+
if not getattr(self, "m_theme", None):
264+
return
231265
self.m_theme.clear()
232266
try:
233267
root = Path(__file__).resolve().parents[3]
@@ -240,8 +274,11 @@ def _populate_theme_menu(self):
240274
act = self.m_theme.addAction(qss.name)
241275
act.triggered.connect(lambda _=False, p=qss: self._apply_theme_file(p))
242276
except Exception:
243-
act = self.m_theme.addAction("Themes load error")
244-
act.setEnabled(False)
277+
try:
278+
act = self.m_theme.addAction("Themes load error")
279+
act.setEnabled(False)
280+
except Exception:
281+
pass
245282

246283
# ---------- Workspace and Plugins ----------
247284
def _browse_ws(self):

0 commit comments

Comments
 (0)