Files
create/mods/sdk/kindred_sdk/command.py
forbes 2bf083609d
All checks were successful
Build and Test / build (pull_request) Successful in 28m41s
feat(sdk): add IMenuProvider interface and register_command wrapper (#355)
IMenuProvider: declarative menu placement with optional context awareness.
C++ interface with pybind11 bindings + GIL-safe holder. SDKMenuManipulator
(shared WorkbenchManipulator) injects menu items on workbench switch,
filtered by editing context when context_ids() is non-empty.

register_command(): thin Python wrapper around FreeCADGui.addCommand()
that standardizes the calling convention within the SDK contract.

Python wrappers (kindred_sdk.register_menu, kindred_sdk.register_command)
use kcsdk-first routing with FreeCADGui fallback.
2026-03-01 13:13:44 -06:00

59 lines
1.8 KiB
Python

"""Command registration wrapper.
Provides a standardized SDK entry point for registering FreeCAD commands.
This is a thin wrapper around ``FreeCADGui.addCommand()`` — no C++ interface
is needed since FreeCAD's command system is already stable and well-known.
"""
import FreeCAD
def register_command(name, activated, resources, is_active=None):
"""Register a FreeCAD command through the SDK.
Parameters
----------
name : str
Command name (e.g. ``"MyAddon_DoThing"``).
activated : callable
Called when command is triggered. Receives an optional ``int``
index argument (for group commands).
resources : dict
Command resources passed to ``GetResources()``. Common keys:
``MenuText``, ``ToolTip``, ``Pixmap``, ``Accel``.
is_active : callable, optional
Zero-arg callable returning ``True`` when the command should be
enabled. Default: always active.
"""
if not callable(activated):
raise TypeError("activated must be callable")
if not isinstance(resources, dict):
raise TypeError("resources must be a dict")
if is_active is not None and not callable(is_active):
raise TypeError("is_active must be callable or None")
_resources = dict(resources)
_activated = activated
_is_active = is_active
class _SDKCommand:
def GetResources(self):
return _resources
def Activated(self, index=0):
_activated()
def IsActive(self):
if _is_active is not None:
return bool(_is_active())
return True
try:
import FreeCADGui
FreeCADGui.addCommand(name, _SDKCommand())
except Exception as e:
FreeCAD.Console.PrintWarning(
f"kindred_sdk: Failed to register command '{name}': {e}\n"
)