From dbac82e731794050a271e9978629b82cee78c731 Mon Sep 17 00:00:00 2001 From: forbes Date: Thu, 29 Jan 2026 20:57:39 -0600 Subject: [PATCH] Fix silo loading and add integration enhancements Fix the exec() calls in Create module's Init.py and InitGui.py to pass __file__ and __name__ in the globals dict. The silo workbench code uses __file__ to resolve icon paths, but exec() without explicit globals does not provide it, causing 'name __file__ is not defined' errors. Also add three silo integration enhancements to InitGui.py: - First-startup check: launches Silo_Settings dialog if API URL is not configured on first run - File menu injection: WorkbenchManipulator inserts Silo Open, Save, and Commit commands into the File menu across all workbenches - Database activity panel: dock widget showing recent silo items, displayed on the right side of the main window --- src/Mod/Create/Init.py | 5 +- src/Mod/Create/InitGui.py | 99 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 2 deletions(-) diff --git a/src/Mod/Create/Init.py b/src/Mod/Create/Init.py index deeab6d34e..13fed152a2 100644 --- a/src/Mod/Create/Init.py +++ b/src/Mod/Create/Init.py @@ -31,7 +31,10 @@ def setup_kindred_addons(): if os.path.isfile(init_file): try: with open(init_file) as f: - exec(compile(f.read(), init_file, "exec")) + exec_globals = globals().copy() + exec_globals["__file__"] = init_file + exec_globals["__name__"] = name + exec(compile(f.read(), init_file, "exec"), exec_globals) FreeCAD.Console.PrintLog(f"Create: Loaded {name} Init.py\n") except Exception as e: FreeCAD.Console.PrintWarning( diff --git a/src/Mod/Create/InitGui.py b/src/Mod/Create/InitGui.py index d5ac7ab0d8..a07b3a8a70 100644 --- a/src/Mod/Create/InitGui.py +++ b/src/Mod/Create/InitGui.py @@ -30,7 +30,13 @@ def setup_kindred_workbenches(): if os.path.isfile(init_gui_file): try: with open(init_gui_file) as f: - exec(compile(f.read(), init_gui_file, "exec")) + exec_globals = globals().copy() + exec_globals["__file__"] = init_gui_file + exec_globals["__name__"] = name + exec( + compile(f.read(), init_gui_file, "exec"), + exec_globals, + ) FreeCAD.Console.PrintLog(f"Create: Loaded {name} workbench\n") except Exception as e: FreeCAD.Console.PrintWarning( @@ -40,3 +46,94 @@ def setup_kindred_workbenches(): setup_kindred_workbenches() FreeCAD.Console.PrintLog("Create GUI module initialized\n") + + +# --------------------------------------------------------------------------- +# Silo integration enhancements +# --------------------------------------------------------------------------- + + +def _check_silo_first_start(): + """Show Silo settings dialog on first startup if not yet configured.""" + try: + param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/KindredSilo") + if not param.GetBool("FirstStartChecked", False): + param.SetBool("FirstStartChecked", True) + if not param.GetString("ApiUrl", ""): + FreeCADGui.runCommand("Silo_Settings") + except Exception as e: + FreeCAD.Console.PrintLog(f"Create: Silo first-start check skipped: {e}\n") + + +def _setup_silo_menu(): + """Inject Silo commands into the File menu across all workbenches.""" + try: + + class SiloMenuManipulator: + def modifyMenuBar(self): + return [ + {"insert": "Silo_Open", "menuItem": "Std_Open", "after": ""}, + {"insert": "Silo_Save", "menuItem": "Std_Save", "after": ""}, + {"insert": "Silo_Commit", "menuItem": "Std_Save", "after": ""}, + ] + + FreeCADGui.addWorkbenchManipulator(SiloMenuManipulator()) + FreeCAD.Console.PrintLog("Create: Silo menu manipulator installed\n") + except Exception as e: + FreeCAD.Console.PrintLog(f"Create: Silo menu setup skipped: {e}\n") + + +def _setup_silo_activity_panel(): + """Show a dock widget with recent Silo database activity.""" + try: + from PySide import QtCore, QtWidgets + + mw = FreeCADGui.getMainWindow() + if mw is None: + return + + # Don't create duplicate panels + if mw.findChild(QtWidgets.QDockWidget, "SiloDatabaseActivity"): + return + + panel = QtWidgets.QDockWidget("Database Activity", mw) + panel.setObjectName("SiloDatabaseActivity") + + widget = QtWidgets.QWidget() + layout = QtWidgets.QVBoxLayout(widget) + + activity_list = QtWidgets.QListWidget() + layout.addWidget(activity_list) + + try: + import silo_commands + + items = silo_commands._client.list_items() + if isinstance(items, list): + for item in items[:20]: + pn = item.get("part_number", "") + desc = item.get("description", "") + updated = item.get("updated_at", "") + if updated: + updated = updated[:10] + activity_list.addItem(f"{pn} - {desc} - {updated}") + if activity_list.count() == 0: + activity_list.addItem("(No items in database)") + except Exception: + activity_list.addItem("(Unable to connect to Silo database)") + + panel.setWidget(widget) + mw.addDockWidget(QtCore.Qt.RightDockWidgetArea, panel) + except Exception as e: + FreeCAD.Console.PrintLog(f"Create: Silo activity panel skipped: {e}\n") + + +# Defer enhancements until the GUI event loop is running +try: + from PySide.QtCore import QTimer + + QTimer.singleShot(2000, _setup_silo_menu) + QTimer.singleShot(3000, _check_silo_first_start) + QTimer.singleShot(4000, _setup_silo_activity_panel) +except Exception: + pass