feat(sdk): add status bar widget wrapper and origin query bindings (#356)
register_status_widget(): pure Python wrapper that adds a live widget to the main window status bar with context menu discoverability. Origin query bindings (kcsdk.list_origins, active_origin, get_origin, set_active_origin): thin C++ forwarding to OriginManager with Python wrappers using kcsdk-first routing. IOriginProvider and IStatusBarProvider C++ interfaces dropped — existing FileOrigin stack is already complete, and status bar widgets don't need C++ lifecycle management.
This commit is contained in:
@@ -13,28 +13,41 @@ from kindred_sdk.context import (
|
||||
)
|
||||
from kindred_sdk.dock import register_dock_panel
|
||||
from kindred_sdk.menu import register_menu
|
||||
from kindred_sdk.origin import register_origin, unregister_origin
|
||||
from kindred_sdk.origin import (
|
||||
active_origin,
|
||||
get_origin,
|
||||
list_origins,
|
||||
register_origin,
|
||||
set_active_origin,
|
||||
unregister_origin,
|
||||
)
|
||||
from kindred_sdk.statusbar import register_status_widget
|
||||
from kindred_sdk.theme import get_theme_tokens, load_palette
|
||||
from kindred_sdk.toolbar import register_toolbar
|
||||
from kindred_sdk.version import SDK_VERSION
|
||||
|
||||
__all__ = [
|
||||
"SDK_VERSION",
|
||||
"active_origin",
|
||||
"create_version",
|
||||
"current_context",
|
||||
"freecad_version",
|
||||
"get_origin",
|
||||
"get_theme_tokens",
|
||||
"inject_commands",
|
||||
"list_origins",
|
||||
"load_palette",
|
||||
"refresh_context",
|
||||
"register_command",
|
||||
"register_context",
|
||||
"unregister_context",
|
||||
"register_overlay",
|
||||
"unregister_overlay",
|
||||
"inject_commands",
|
||||
"current_context",
|
||||
"refresh_context",
|
||||
"get_theme_tokens",
|
||||
"load_palette",
|
||||
"register_menu",
|
||||
"register_toolbar",
|
||||
"register_origin",
|
||||
"unregister_origin",
|
||||
"register_dock_panel",
|
||||
"create_version",
|
||||
"freecad_version",
|
||||
"register_menu",
|
||||
"register_origin",
|
||||
"register_status_widget",
|
||||
"register_toolbar",
|
||||
"set_active_origin",
|
||||
"unregister_context",
|
||||
"unregister_origin",
|
||||
"unregister_overlay",
|
||||
"register_overlay",
|
||||
]
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
"""FileOrigin registration wrappers.
|
||||
"""FileOrigin registration and query wrappers.
|
||||
|
||||
Wraps ``FreeCADGui.addOrigin()`` / ``removeOrigin()`` with validation
|
||||
and error handling. Addons implement the FileOrigin duck-typed
|
||||
interface directly (see Silo's ``SiloOrigin`` for the full contract).
|
||||
|
||||
Query functions (``list_origins``, ``active_origin``, etc.) route
|
||||
through the ``kcsdk`` C++ module when available, falling back to
|
||||
``FreeCADGui.*`` for backwards compatibility.
|
||||
"""
|
||||
|
||||
import FreeCAD
|
||||
|
||||
# Try to import the C++ SDK module; None if not yet built/installed.
|
||||
try:
|
||||
import kcsdk as _kcsdk
|
||||
except ImportError:
|
||||
_kcsdk = None
|
||||
|
||||
_REQUIRED_METHODS = ("id", "name", "type", "ownsDocument")
|
||||
|
||||
|
||||
@@ -40,3 +50,96 @@ def unregister_origin(origin):
|
||||
FreeCAD.Console.PrintLog(f"kindred_sdk: Unregistered origin '{origin.id()}'\n")
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning(f"kindred_sdk: Failed to unregister origin: {e}\n")
|
||||
|
||||
|
||||
def list_origins():
|
||||
"""Return IDs of all registered origins.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list[str]
|
||||
Origin IDs (always includes ``"local"``).
|
||||
"""
|
||||
if _kcsdk is not None:
|
||||
try:
|
||||
return _kcsdk.list_origins()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return _gui().listOrigins()
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning(f"kindred_sdk: list_origins failed: {e}\n")
|
||||
return []
|
||||
|
||||
|
||||
def active_origin():
|
||||
"""Return info about the currently active origin.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict or None
|
||||
Origin info dict with keys: ``id``, ``name``, ``nickname``,
|
||||
``type``, ``tracksExternally``, ``requiresAuthentication``,
|
||||
``supportsRevisions``, ``supportsBOM``, ``supportsPartNumbers``,
|
||||
``connectionState``.
|
||||
"""
|
||||
if _kcsdk is not None:
|
||||
try:
|
||||
return _kcsdk.active_origin()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return _gui().activeOrigin()
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning(f"kindred_sdk: active_origin failed: {e}\n")
|
||||
return None
|
||||
|
||||
|
||||
def set_active_origin(origin_id):
|
||||
"""Set the active origin by ID.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
origin_id : str
|
||||
The origin ID to activate.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if the origin was found and activated.
|
||||
"""
|
||||
if _kcsdk is not None:
|
||||
try:
|
||||
return _kcsdk.set_active_origin(origin_id)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return _gui().setActiveOrigin(origin_id)
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning(f"kindred_sdk: set_active_origin failed: {e}\n")
|
||||
return False
|
||||
|
||||
|
||||
def get_origin(origin_id):
|
||||
"""Get info about a specific origin by ID.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
origin_id : str
|
||||
The origin ID to look up.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict or None
|
||||
Origin info dict, or None if not found.
|
||||
"""
|
||||
if _kcsdk is not None:
|
||||
try:
|
||||
return _kcsdk.get_origin(origin_id)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return _gui().getOrigin(origin_id)
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning(f"kindred_sdk: get_origin failed: {e}\n")
|
||||
return None
|
||||
|
||||
74
mods/sdk/kindred_sdk/statusbar.py
Normal file
74
mods/sdk/kindred_sdk/statusbar.py
Normal file
@@ -0,0 +1,74 @@
|
||||
"""Status bar widget registration wrapper.
|
||||
|
||||
Provides a standardized SDK entry point for adding widgets to the main
|
||||
window's status bar. This is a pure Python wrapper — no C++ interface
|
||||
is needed since the widget is created once and Qt manages its lifecycle.
|
||||
"""
|
||||
|
||||
import FreeCAD
|
||||
|
||||
|
||||
def register_status_widget(object_name, label, widget, position="right"):
|
||||
"""Add a widget to the main window status bar.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
object_name : str
|
||||
Qt object name for duplicate prevention.
|
||||
label : str
|
||||
Display name shown in the status bar's right-click context menu
|
||||
(becomes the widget's ``windowTitle``).
|
||||
widget : QWidget
|
||||
The widget instance to add. The caller keeps its own reference
|
||||
for live updates (e.g. connecting signals, updating text).
|
||||
position : str, optional
|
||||
``"left"`` (stretches) or ``"right"`` (permanent, fixed width).
|
||||
Default ``"right"``.
|
||||
"""
|
||||
if not isinstance(object_name, str) or not object_name:
|
||||
raise TypeError("object_name must be a non-empty string")
|
||||
if not isinstance(label, str) or not label:
|
||||
raise TypeError("label must be a non-empty string")
|
||||
if position not in ("left", "right"):
|
||||
raise ValueError(f"position must be 'left' or 'right', got {position!r}")
|
||||
|
||||
try:
|
||||
import FreeCADGui
|
||||
from PySide import QtWidgets
|
||||
|
||||
mw = FreeCADGui.getMainWindow()
|
||||
if mw is None:
|
||||
FreeCAD.Console.PrintWarning(
|
||||
"kindred_sdk: Main window not available, "
|
||||
f"cannot register status widget '{object_name}'\n"
|
||||
)
|
||||
return
|
||||
|
||||
sb = mw.statusBar()
|
||||
|
||||
# Duplicate check
|
||||
for child in sb.children():
|
||||
if (
|
||||
isinstance(child, QtWidgets.QWidget)
|
||||
and child.objectName() == object_name
|
||||
):
|
||||
FreeCAD.Console.PrintLog(
|
||||
f"kindred_sdk: Status widget '{object_name}' already exists, skipping\n"
|
||||
)
|
||||
return
|
||||
|
||||
widget.setObjectName(object_name)
|
||||
widget.setWindowTitle(label)
|
||||
|
||||
if position == "left":
|
||||
sb.addWidget(widget)
|
||||
else:
|
||||
sb.addPermanentWidget(widget)
|
||||
|
||||
FreeCAD.Console.PrintLog(
|
||||
f"kindred_sdk: Registered status widget '{object_name}'\n"
|
||||
)
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning(
|
||||
f"kindred_sdk: Failed to register status widget '{object_name}': {e}\n"
|
||||
)
|
||||
Reference in New Issue
Block a user