@@ -300,6 +300,97 @@ def _run_bcasl_sync(
300300 )
301301
302302
303+ def _get_plugins_dir () -> Path :
304+ try :
305+ return Path (__file__ ).resolve ().parents [1 ] / "Plugins"
306+ except Exception :
307+ return Path ("Plugins" )
308+
309+
310+ def _resolve_ordered_plugin_ids (
311+ plugin_ids : list [str ], meta_map : dict [str , dict [str , Any ]], cfg : dict [str , Any ]
312+ ) -> list [str ]:
313+ order : list [str ] = []
314+ try :
315+ order = cfg .get ("plugin_order" , []) if isinstance (cfg , dict ) else []
316+ order = [pid for pid in order if pid in plugin_ids ]
317+ except Exception :
318+ order = []
319+ if not order :
320+ try :
321+ order = [pid for pid in compute_tag_order (meta_map ) if pid in plugin_ids ]
322+ except Exception :
323+ order = sorted (plugin_ids )
324+ remaining = [pid for pid in plugin_ids if pid not in order ]
325+ return order + remaining
326+
327+
328+ def _plugin_enabled (plugins_cfg : dict [str , Any ], pid : str ) -> bool :
329+ try :
330+ pentry = plugins_cfg .get (pid , {})
331+ if isinstance (pentry , dict ):
332+ return bool (pentry .get ("enabled" , True ))
333+ if isinstance (pentry , bool ):
334+ return bool (pentry )
335+ except Exception :
336+ pass
337+ return True
338+
339+
340+ def _build_plugin_item (
341+ pid : str ,
342+ meta : dict [str , Any ],
343+ plugins_cfg : dict [str , Any ],
344+ Qt ,
345+ QListWidgetItem ,
346+ ) -> Any :
347+ # Importer les fonctions de tagging pour afficher les phases
348+ from .tagging import get_tag_phase_name
349+
350+ label = meta .get ("name" ) or pid
351+ ver = meta .get ("version" ) or ""
352+ tags = meta .get ("tags" ) or []
353+
354+ phase_name = get_tag_phase_name (tags [0 ]) if tags else ""
355+ text = f"{ label } ({ pid } )" + (f" v{ ver } " if ver else "" )
356+ if phase_name :
357+ text += f" [Phase: { phase_name } ]"
358+
359+ item = QListWidgetItem (text )
360+
361+ # Tooltip avec description, tags et requirements
362+ try :
363+ desc = meta .get ("description" ) or ""
364+ tooltip = desc
365+ if tags :
366+ tooltip += f"\n \n Tags: { ', ' .join (tags )} "
367+ reqs = meta .get ("requirements" , [])
368+ if reqs :
369+ tooltip += f"\n \n Requirements:\n " + "\n " .join (f" • { req } " for req in reqs )
370+ if tooltip :
371+ item .setToolTip (tooltip )
372+ except Exception :
373+ pass
374+
375+ enabled = _plugin_enabled (plugins_cfg , pid )
376+ try :
377+ item .setData (0x0100 , pid )
378+ except Exception :
379+ pass
380+ if Qt is not None :
381+ item .setFlags (
382+ item .flags ()
383+ | Qt .ItemIsUserCheckable
384+ | Qt .ItemIsEnabled
385+ | Qt .ItemIsSelectable
386+ | Qt .ItemIsDragEnabled
387+ )
388+ item .setCheckState (
389+ Qt .CheckState .Checked if enabled else Qt .CheckState .Unchecked
390+ )
391+ return item
392+
393+
303394def _load_workspace_config (workspace_root : Path ) -> dict [str , Any ]:
304395 """Charge bcasl.yml si présent, sinon génère une config par défaut minimale et l'écrit.
305396
@@ -326,8 +417,7 @@ def _read_yml(p: Path) -> dict[str, Any]:
326417 # 2) Génération défaut avec fusion ARK
327418 default_cfg : dict [str , Any ] = {}
328419 try :
329- repo_root = Path (__file__ ).resolve ().parents [1 ]
330- Plugins_dir = repo_root / "Plugins"
420+ Plugins_dir = _get_plugins_dir ()
331421 detected_plugins : dict [str , Any ] = {}
332422 meta_map = _discover_bcasl_meta (Plugins_dir ) if Plugins_dir .exists () else {}
333423 if meta_map :
@@ -588,8 +678,7 @@ def open_bc_loader_dialog(self) -> None: # UI minimale
588678 )
589679 return
590680 workspace_root = Path (self .workspace_dir ).resolve ()
591- repo_root = Path (__file__ ).resolve ().parents [1 ]
592- Plugins_dir = repo_root / "Plugins"
681+ Plugins_dir = _get_plugins_dir ()
593682 if not Plugins_dir .exists ():
594683 QMessageBox .information (
595684 self ,
@@ -643,89 +732,10 @@ def open_bc_loader_dialog(self) -> None: # UI minimale
643732 lst .setSelectionMode (QAbstractItemView .SingleSelection )
644733 lst .setDragDropMode (QAbstractItemView .InternalMove )
645734
646- # Ordre initial: plugin_order si présent; sinon heuristique par tags; sinon alphabétique
647- order = []
648- try :
649- order = cfg .get ("plugin_order" , []) if isinstance (cfg , dict ) else []
650- order = [pid for pid in order if pid in plugin_ids ]
651- except Exception :
652- order = []
653- if not order :
654- try :
655- order = [
656- pid for pid in compute_tag_order (meta_map ) if pid in plugin_ids
657- ]
658- except Exception :
659- order = sorted (plugin_ids )
660-
661- remaining = [pid for pid in plugin_ids if pid not in order ]
662- ordered_ids = order + remaining
663-
664- # Importer les fonctions de tagging pour afficher les phases
665- from .tagging import get_tag_phase_name
666-
735+ ordered_ids = _resolve_ordered_plugin_ids (plugin_ids , meta_map , cfg )
667736 for pid in ordered_ids :
668737 meta = meta_map .get (pid , {})
669- label = meta .get ("name" ) or pid
670- ver = meta .get ("version" ) or ""
671- tags = meta .get ("tags" ) or []
672-
673- # Déterminer la phase d'exécution
674- phase_name = ""
675- if tags :
676- # Utiliser le premier tag pour déterminer la phase
677- phase_name = get_tag_phase_name (tags [0 ])
678-
679- # Construire le texte avec la phase
680- text = f"{ label } ({ pid } )" + (f" v{ ver } " if ver else "" )
681- if phase_name :
682- text += f" [Phase: { phase_name } ]"
683-
684- item = QListWidgetItem (text )
685- # Tooltip avec description, tags et requirements
686- try :
687- desc = meta .get ("description" ) or ""
688- tooltip = desc
689- if tags :
690- tooltip += f"\n \n Tags: { ', ' .join (tags )} "
691-
692- # Ajouter les requirements du plugin depuis meta_map
693- reqs = meta .get ("requirements" , [])
694- if reqs :
695- tooltip += f"\n \n Requirements:\n " + "\n " .join (
696- f" • { req } " for req in reqs
697- )
698-
699- if tooltip :
700- item .setToolTip (tooltip )
701- except Exception :
702- pass
703- # Etat
704- enabled = True
705- try :
706- pentry = plugins_cfg .get (pid , {})
707- if isinstance (pentry , dict ):
708- enabled = bool (pentry .get ("enabled" , True ))
709- elif isinstance (pentry , bool ):
710- enabled = pentry
711- except Exception :
712- pass
713- try :
714- item .setData (0x0100 , pid )
715- except Exception :
716- pass
717- if Qt is not None :
718- item .setFlags (
719- item .flags ()
720- | Qt .ItemIsUserCheckable
721- | Qt .ItemIsEnabled
722- | Qt .ItemIsSelectable
723- | Qt .ItemIsDragEnabled
724- )
725- if Qt is not None :
726- item .setCheckState (
727- Qt .CheckState .Checked if enabled else Qt .CheckState .Unchecked
728- )
738+ item = _build_plugin_item (pid , meta , plugins_cfg , Qt , QListWidgetItem )
729739 lst .addItem (item )
730740 layout .addWidget (lst )
731741
@@ -867,8 +877,7 @@ def run_pre_compile_async(self, on_done: Optional[callable] = None) -> None:
867877 pass
868878 return
869879 workspace_root = Path (self .workspace_dir ).resolve ()
870- repo_root = Path (__file__ ).resolve ().parents [1 ]
871- Plugins_dir = repo_root / "Plugins"
880+ Plugins_dir = _get_plugins_dir ()
872881
873882 cfg = _load_workspace_config (workspace_root )
874883 plugin_timeout = _resolve_plugin_timeout (cfg )
@@ -960,8 +969,7 @@ def run_pre_compile(self) -> Optional[object]:
960969 if not getattr (self , "workspace_dir" , None ):
961970 return None
962971 workspace_root = Path (self .workspace_dir ).resolve ()
963- repo_root = Path (__file__ ).resolve ().parents [1 ]
964- Plugins_dir = repo_root / "Plugins"
972+ Plugins_dir = _get_plugins_dir ()
965973
966974 cfg = _load_workspace_config (workspace_root )
967975 plugin_timeout = _resolve_plugin_timeout (cfg )
0 commit comments