"""Kindred Silo addon — GUI initialization. Registers the SiloWorkbench, Silo file origin, overlay context, dock panels (auth + activity), document observer, and start page override. """ import os import FreeCAD import FreeCADGui FreeCAD.Console.PrintMessage("Kindred Silo InitGui.py loading...\n") # --------------------------------------------------------------------------- # Workbench # --------------------------------------------------------------------------- class SiloWorkbench(FreeCADGui.Workbench): """Kindred Silo workbench for item database integration.""" MenuText = "Kindred Silo" ToolTip = "Item database and part management for Kindred Create" Icon = "" def __init__(self): icon_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "freecad", "resources", "icons", "silo.svg", ) if os.path.exists(icon_path): self.__class__.Icon = icon_path def Initialize(self): """Called when workbench is first activated.""" import silo_commands # Register Silo as a file origin in the unified origin system try: import silo_origin silo_origin.register_silo_origin() except Exception as e: FreeCAD.Console.PrintWarning(f"Could not register Silo origin: {e}\n") # Silo origin toolbar — shown as an overlay on any context when the # active document is Silo-tracked. Registered as Unavailable so # EditingContextResolver controls visibility via the overlay system. self.silo_toolbar_commands = [ "Silo_Commit", "Silo_Pull", "Silo_Push", "Separator", "Silo_Info", "Silo_BOM", "Silo_Jobs", ] self.appendToolbar("Silo Origin", self.silo_toolbar_commands, "Unavailable") # Silo menu provides admin/management commands. self.menu_commands = [ "Silo_Info", "Silo_BOM", "Silo_Jobs", "Silo_TagProjects", "Silo_SetStatus", "Silo_Rollback", "Silo_SaveAsTemplate", "Separator", "Silo_Settings", "Silo_Auth", "Silo_Runners", "Silo_StartPanel", "Silo_Diag", ] self.appendMenu("Silo", self.menu_commands) def Activated(self): """Called when workbench is activated.""" FreeCAD.Console.PrintMessage("Kindred Silo workbench activated\n") FreeCADGui.runCommand("Silo_StartPanel", 0) def Deactivated(self): pass def GetClassName(self): return "Gui::PythonWorkbench" FreeCADGui.addWorkbench(SiloWorkbench()) FreeCAD.Console.PrintMessage("Silo workbench registered\n") # --------------------------------------------------------------------------- # Silo overlay context — adds "Silo Origin" toolbar to any active context # when the current document is Silo-tracked. # --------------------------------------------------------------------------- def _register_silo_overlay(): """Register the Silo overlay after the Silo workbench has initialised.""" def _silo_overlay_match(): """Return True if the active document is Silo-tracked.""" try: doc = FreeCAD.ActiveDocument if not doc: return False from silo_origin import get_silo_origin origin = get_silo_origin() return origin.ownsDocument(doc) except Exception: return False try: from kindred_sdk import register_overlay register_overlay( "silo", # overlay id ["Silo Origin"], # toolbar names to append _silo_overlay_match, # match function ) except Exception as e: FreeCAD.Console.PrintWarning(f"Silo overlay registration failed: {e}\n") # --------------------------------------------------------------------------- # Document observer — builds the Silo metadata tree when .kc files open. # --------------------------------------------------------------------------- def _register_silo_document_observer(): """Register the Silo document observer for .kc tree building.""" try: import silo_document silo_document.register() except Exception as e: FreeCAD.Console.PrintLog(f"Silo: document observer registration skipped: {e}\n") # --------------------------------------------------------------------------- # Dock panels — auth and activity widgets via SDK # --------------------------------------------------------------------------- def _setup_silo_auth_panel(): """Dock the Silo authentication panel in the right-hand side panel.""" try: from kindred_sdk import register_dock_panel def _factory(): import silo_commands auth = silo_commands.SiloAuthDockWidget() # Prevent GC of the auth timer by stashing on the widget auth.widget._auth = auth return auth.widget register_dock_panel("SiloDatabaseAuth", "Database Auth", _factory) except Exception as e: FreeCAD.Console.PrintLog(f"Silo: auth panel skipped: {e}\n") def _setup_silo_activity_panel(): """Show a dock widget with recent Silo database activity.""" try: from kindred_sdk import register_dock_panel def _factory(): from PySide import QtWidgets 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)") return widget register_dock_panel("SiloDatabaseActivity", "Database Activity", _factory) except Exception as e: FreeCAD.Console.PrintLog(f"Silo: activity panel skipped: {e}\n") # --------------------------------------------------------------------------- # First-start check # --------------------------------------------------------------------------- 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"Silo: first-start check skipped: {e}\n") # --------------------------------------------------------------------------- # Start page override — must happen before the C++ StartLauncher fires # at ~100ms after GUI init. # --------------------------------------------------------------------------- try: import silo_start silo_start.register() except Exception as e: FreeCAD.Console.PrintWarning(f"Silo Start page override failed: {e}\n") # --------------------------------------------------------------------------- # Handle kindred:// URLs passed as command-line arguments on cold start. # --------------------------------------------------------------------------- def _handle_startup_urls(): """Process any kindred:// URLs passed as command-line arguments.""" import sys from silo_commands import handle_kindred_url for arg in sys.argv[1:]: if arg.startswith("kindred://"): handle_kindred_url(arg) # --------------------------------------------------------------------------- # Deferred setup — staggered timers for non-blocking startup # --------------------------------------------------------------------------- from PySide import QtCore as _QtCore _QtCore.QTimer.singleShot(500, _handle_startup_urls) _QtCore.QTimer.singleShot(600, _register_silo_document_observer) _QtCore.QTimer.singleShot(2000, _setup_silo_auth_panel) _QtCore.QTimer.singleShot(2500, _register_silo_overlay) _QtCore.QTimer.singleShot(3000, _check_silo_first_start) _QtCore.QTimer.singleShot(4000, _setup_silo_activity_panel)