@@ -164,6 +164,7 @@ def _load_ui_from_designer(self):
164164 self .filter_text = self .findChild (QLineEdit , "filter_text" )
165165 self .filter_phase = self .findChild (QComboBox , "filter_phase" )
166166 self .list_plugins = self .findChild (QListWidget , "list_plugins" )
167+ self .cb_theme = self .findChild (QComboBox , "cb_theme" )
167168 self .sp_timeout2 = self .findChild (QSpinBox , "sp_timeout2" )
168169 self .chk_sandbox2 = self .findChild (QCheckBox , "chk_sandbox2" )
169170 self .sp_parallel2 = self .findChild (QSpinBox , "sp_parallel2" )
@@ -215,6 +216,13 @@ def _wire_logic(self):
215216 self .btn_run .clicked .connect (self ._run )
216217 except Exception :
217218 pass
219+ # Theme combobox populate and wiring
220+ try :
221+ if self .cb_theme :
222+ self ._populate_theme_combobox ()
223+ self .cb_theme .currentIndexChanged .connect (self ._apply_theme_from_combobox )
224+ except Exception :
225+ pass
218226 # Filters
219227 try :
220228 if self .filter_text :
@@ -257,12 +265,79 @@ def _apply_theme_file(self, path: Path):
257265 QApplication .instance ().setStyleSheet (qss )
258266 except Exception :
259267 pass
268+ # Persist selected theme
269+ try :
270+ from PySide6 .QtCore import QSettings
271+ s = QSettings ("BCASL" , "BCASL Studio" )
272+ s .setValue ("theme" , str (path ))
273+ except Exception :
274+ pass
275+
276+ def _clear_theme (self ):
277+ try :
278+ from PySide6 .QtWidgets import QApplication
279+ QApplication .instance ().setStyleSheet ("" )
280+ except Exception :
281+ pass
282+ try :
283+ from PySide6 .QtCore import QSettings
284+ QSettings ("BCASL" , "BCASL Studio" ).remove ("theme" )
285+ except Exception :
286+ pass
287+
288+ def _populate_theme_combobox (self ):
289+ root = Path (__file__ ).resolve ().parents [3 ]
290+ themes_dir = root / "themes"
291+ items = [("System (No theme)" , "" )] # (label, path)
292+ try :
293+ if themes_dir .is_dir ():
294+ for qss in sorted (themes_dir .glob ("*.qss" )):
295+ items .append ((qss .name , str (qss )))
296+ except Exception :
297+ pass
298+ try :
299+ self .cb_theme .blockSignals (True )
300+ self .cb_theme .clear ()
301+ for label , path in items :
302+ self .cb_theme .addItem (label , path )
303+ # Set from saved settings
304+ from PySide6 .QtCore import QSettings
305+ s = QSettings ("BCASL" , "BCASL Studio" )
306+ saved = s .value ("theme" , "" , type = str ) or ""
307+ idx = 0
308+ for i in range (self .cb_theme .count ()):
309+ if self .cb_theme .itemData (i ) == saved :
310+ idx = i
311+ break
312+ self .cb_theme .setCurrentIndex (idx )
313+ finally :
314+ try :
315+ self .cb_theme .blockSignals (False )
316+ except Exception :
317+ pass
318+
319+ def _apply_theme_from_combobox (self ):
320+ try :
321+ data = self .cb_theme .currentData ()
322+ if not data :
323+ self ._clear_theme ()
324+ return
325+ self ._apply_theme_file (Path (data ))
326+ except Exception :
327+ pass
260328
261329 def _populate_theme_menu (self ):
262330 # Scan themes/ at repo root
263331 if not getattr (self , "m_theme" , None ):
264332 return
265333 self .m_theme .clear ()
334+ # Add system default/no theme option
335+ try :
336+ act_sys = self .m_theme .addAction ("System (No theme)" )
337+ act_sys .triggered .connect (lambda _ = False : self ._clear_theme ())
338+ self .m_theme .addSeparator ()
339+ except Exception :
340+ pass
266341 try :
267342 root = Path (__file__ ).resolve ().parents [3 ]
268343 themes_dir = root / "themes"
@@ -319,15 +394,10 @@ def _settings_to_ui(self):
319394 except Exception :
320395 self .sp_timeout .setValue (0 )
321396 self .chk_sandbox .setChecked (bool (opts .get ("sandbox" , True )))
322- try :
323- self .sp_parallel .setValue (int (opts .get ("plugin_parallelism" , 0 )))
324- except Exception :
325- self .sp_parallel .setValue (0 )
326- # Mirror into compact controls
397+ # Mirror into compact controls
327398 try :
328399 self .sp_timeout2 .setValue (int (float (opts .get ("plugin_timeout_s" , 0.0 ))))
329400 self .chk_sandbox2 .setChecked (bool (opts .get ("sandbox" , True )))
330- self .sp_parallel2 .setValue (int (opts .get ("plugin_parallelism" , 0 )))
331401 except Exception :
332402 pass
333403
@@ -338,11 +408,9 @@ def _ui_to_settings(self):
338408 if hasattr (self , "sp_timeout2" ):
339409 self .cfg .options ["plugin_timeout_s" ] = float (self .sp_timeout2 .value ())
340410 self .cfg .options ["sandbox" ] = bool (self .chk_sandbox2 .isChecked ())
341- self .cfg .options ["plugin_parallelism" ] = int (self .sp_parallel2 .value ())
342411 else :
343412 self .cfg .options ["plugin_timeout_s" ] = float (self .sp_timeout .value ())
344413 self .cfg .options ["sandbox" ] = bool (self .chk_sandbox .isChecked ())
345- self .cfg .options ["plugin_parallelism" ] = int (self .sp_parallel .value ())
346414
347415 def _populate_plugins (self ):
348416 if not self .plugins_dir or not self .cfg :
@@ -431,7 +499,6 @@ def _sync_settings_from_compact(self):
431499 try :
432500 self .sp_timeout .setValue (int (self .sp_timeout2 .value ()))
433501 self .chk_sandbox .setChecked (bool (self .chk_sandbox2 .isChecked ()))
434- self .sp_parallel .setValue (int (self .sp_parallel2 .value ()))
435502 except Exception :
436503 pass
437504
0 commit comments