Files
create/mods/sdk/kindred_sdk/context.py
forbes 99a08e4e99
All checks were successful
Build and Test / build (pull_request) Successful in 30m5s
feat(sdk): remove fallbacks, add deprecation warnings, bump v1.0.0 (#357)
- Bump SDK_VERSION to 1.0.0 in version.py and package.xml
- Remove <pure_python> tag from package.xml (kcsdk is C++)
- Remove all FreeCADGui.* fallback paths in context.py, dock.py,
  toolbar.py, menu.py; require kcsdk module
- Remove query fallbacks in origin.py (keep register/unregister
  which still need FreeCADGui.addOrigin/removeOrigin)
- Add deprecation warnings to 11 superseded FreeCADGui methods
  in ApplicationPy.cpp (not addOrigin/removeOrigin)
- All 39 Tier 1 tests pass
2026-03-01 14:32:08 -06:00

167 lines
5.1 KiB
Python

"""Editing context and overlay registration wrappers.
Routes through the ``kcsdk`` C++ module. The legacy ``FreeCADGui``
Python bindings are deprecated — kcsdk is required.
"""
import FreeCAD
try:
import kcsdk as _kcsdk
except ImportError:
_kcsdk = None
def _require_kcsdk():
if _kcsdk is None:
raise RuntimeError(
"kcsdk module not available. "
"The kindred_sdk requires the kcsdk C++ module (libKCSDK)."
)
def register_context(context_id, label, color, toolbars, match, priority=50):
"""Register an editing context.
Parameters
----------
context_id : str
Unique identifier (e.g. ``"myaddon.edit"``).
label : str
Display label template. Supports ``{name}`` placeholder.
color : str
Hex color for the breadcrumb (e.g. ``"#f38ba8"``).
toolbars : list[str]
Toolbar names to show when this context is active.
match : callable
Zero-argument callable returning *True* when this context is active.
priority : int, optional
Higher values are checked first. Default 50.
"""
if not isinstance(context_id, str):
raise TypeError(f"context_id must be str, got {type(context_id).__name__}")
if not isinstance(toolbars, list):
raise TypeError(f"toolbars must be list, got {type(toolbars).__name__}")
if not callable(match):
raise TypeError("match must be callable")
_require_kcsdk()
try:
_kcsdk.register_context(context_id, label, color, toolbars, match, priority)
except Exception as e:
FreeCAD.Console.PrintWarning(
f"kindred_sdk: Failed to register context '{context_id}': {e}\n"
)
def unregister_context(context_id):
"""Remove a previously registered editing context."""
if not isinstance(context_id, str):
raise TypeError(f"context_id must be str, got {type(context_id).__name__}")
_require_kcsdk()
try:
_kcsdk.unregister_context(context_id)
except Exception as e:
FreeCAD.Console.PrintWarning(
f"kindred_sdk: Failed to unregister context '{context_id}': {e}\n"
)
def register_overlay(overlay_id, toolbars, match):
"""Register an editing overlay.
Overlays add toolbars to whatever context is currently active when
*match* returns True.
Parameters
----------
overlay_id : str
Unique overlay identifier.
toolbars : list[str]
Toolbar names to append.
match : callable
Zero-argument callable returning *True* when the overlay applies.
"""
if not isinstance(overlay_id, str):
raise TypeError(f"overlay_id must be str, got {type(overlay_id).__name__}")
if not isinstance(toolbars, list):
raise TypeError(f"toolbars must be list, got {type(toolbars).__name__}")
if not callable(match):
raise TypeError("match must be callable")
_require_kcsdk()
try:
_kcsdk.register_overlay(overlay_id, toolbars, match)
except Exception as e:
FreeCAD.Console.PrintWarning(
f"kindred_sdk: Failed to register overlay '{overlay_id}': {e}\n"
)
def unregister_overlay(overlay_id):
"""Remove a previously registered editing overlay."""
if not isinstance(overlay_id, str):
raise TypeError(f"overlay_id must be str, got {type(overlay_id).__name__}")
_require_kcsdk()
try:
_kcsdk.unregister_overlay(overlay_id)
except Exception as e:
FreeCAD.Console.PrintWarning(
f"kindred_sdk: Failed to unregister overlay '{overlay_id}': {e}\n"
)
def inject_commands(context_id, toolbar_name, commands):
"""Inject commands into a context's toolbar.
Parameters
----------
context_id : str
Target context identifier.
toolbar_name : str
Toolbar within that context.
commands : list[str]
Command names to add.
"""
if not isinstance(context_id, str):
raise TypeError(f"context_id must be str, got {type(context_id).__name__}")
if not isinstance(toolbar_name, str):
raise TypeError(f"toolbar_name must be str, got {type(toolbar_name).__name__}")
if not isinstance(commands, list):
raise TypeError(f"commands must be list, got {type(commands).__name__}")
_require_kcsdk()
try:
_kcsdk.inject_commands(context_id, toolbar_name, commands)
except Exception as e:
FreeCAD.Console.PrintWarning(
f"kindred_sdk: Failed to inject commands into '{context_id}': {e}\n"
)
def current_context():
"""Return the current editing context as a dict.
Keys: ``id``, ``label``, ``color``, ``toolbars``, ``breadcrumb``,
``breadcrumbColors``. Returns ``None`` if no context is active.
"""
_require_kcsdk()
try:
return _kcsdk.current_context()
except Exception as e:
FreeCAD.Console.PrintWarning(
f"kindred_sdk: Failed to get current context: {e}\n"
)
return None
def refresh_context():
"""Force re-resolution and update of the editing context."""
_require_kcsdk()
try:
_kcsdk.refresh()
except Exception as e:
FreeCAD.Console.PrintWarning(f"kindred_sdk: Failed to refresh context: {e}\n")