feat(sdk): add context lifecycle callbacks (#381) #399

Merged
forbes merged 1 commits from feat/sdk-lifecycle-callbacks into main 2026-03-04 19:34:53 +00:00
Owner

Summary

Expose EditingContextResolver::contextChanged to Python addons via a two-layer design, enabling addons to declaratively react to context transitions without connecting to raw FreeCAD signals.

Changes

C++ layer (src/Gui/SDK/)

  • SDKRegistry.h/cpp — New onContextChanged(callback) method that stores std::function callbacks and lazily connects to the Qt contextChanged signal on first registration. Thread-safe callback iteration with mutex-guarded snapshot.
  • kcsdk_py.cpp — New kcsdk.on_context_changed(callback) pybind11 binding that wraps Python callables with GIL-safe invocation and error_already_set handling.

Python layer (mods/sdk/kindred_sdk/)

  • lifecycle.py (new) — Context enter/exit callback dispatch:
    • on_context_enter(context_id, callback) — subscribe to context activation ("*" wildcard supported)
    • on_context_exit(context_id, callback) — subscribe to context deactivation
    • Tracks previous context internally to derive enter/exit transitions
    • Emits context.enter / context.exit on the SDK event bus (#382)
    • Graceful degradation if kcsdk C++ module unavailable
  • init.py — Exports on_context_enter, on_context_exit
  • InitGui.py — Calls _init_lifecycle() during SDK GUI init

Usage

import kindred_sdk as sdk

sdk.on_context_enter("sketcher.edit", lambda ctx: print(f"Entered: {ctx['id']}"))
sdk.on_context_exit("sketcher.edit", lambda ctx: print(f"Exited: {ctx['id']}"))

# Wildcard — fires on any context change
sdk.on_context_enter("*", lambda ctx: print(f"Now in: {ctx['id']}"))

# Event bus integration
sdk.on("context.enter", lambda data: print(f"Bus: {data['id']}"))

Verification

  • ninja -C build/debug KCSDK — compiles clean (776/776 targets)
  • Python syntax check passed on all new/modified Python files

Closes #381

## Summary Expose `EditingContextResolver::contextChanged` to Python addons via a two-layer design, enabling addons to declaratively react to context transitions without connecting to raw FreeCAD signals. ## Changes ### C++ layer (`src/Gui/SDK/`) - **SDKRegistry.h/cpp** — New `onContextChanged(callback)` method that stores `std::function` callbacks and lazily connects to the Qt `contextChanged` signal on first registration. Thread-safe callback iteration with mutex-guarded snapshot. - **kcsdk_py.cpp** — New `kcsdk.on_context_changed(callback)` pybind11 binding that wraps Python callables with GIL-safe invocation and `error_already_set` handling. ### Python layer (`mods/sdk/kindred_sdk/`) - **lifecycle.py** (new) — Context enter/exit callback dispatch: - `on_context_enter(context_id, callback)` — subscribe to context activation (`"*"` wildcard supported) - `on_context_exit(context_id, callback)` — subscribe to context deactivation - Tracks previous context internally to derive enter/exit transitions - Emits `context.enter` / `context.exit` on the SDK event bus (#382) - Graceful degradation if `kcsdk` C++ module unavailable - **__init__.py** — Exports `on_context_enter`, `on_context_exit` - **InitGui.py** — Calls `_init_lifecycle()` during SDK GUI init ## Usage ```python import kindred_sdk as sdk sdk.on_context_enter("sketcher.edit", lambda ctx: print(f"Entered: {ctx['id']}")) sdk.on_context_exit("sketcher.edit", lambda ctx: print(f"Exited: {ctx['id']}")) # Wildcard — fires on any context change sdk.on_context_enter("*", lambda ctx: print(f"Now in: {ctx['id']}")) # Event bus integration sdk.on("context.enter", lambda data: print(f"Bus: {data['id']}")) ``` ## Verification - `ninja -C build/debug KCSDK` — compiles clean (776/776 targets) - Python syntax check passed on all new/modified Python files Closes #381
forbes added 1 commit 2026-03-04 16:01:21 +00:00
feat(sdk): add context lifecycle callbacks (#381)
All checks were successful
Build and Test / build (pull_request) Successful in 29m7s
d2ec22f5ff
Expose EditingContextResolver::contextChanged to Python addons via
two-layer design:

C++ layer:
- SDKRegistry::onContextChanged() stores callbacks and lazily connects
  to the Qt signal on first registration
- pybind11 binding kcsdk.on_context_changed() wraps Python callables
  with GIL-safe invocation

Python layer:
- kindred_sdk.on_context_enter(context_id, callback) subscribes to
  context activation ("*" wildcard supported)
- kindred_sdk.on_context_exit(context_id, callback) subscribes to
  context deactivation
- Internal tracking of previous context derives enter/exit transitions
- Emits context.enter / context.exit on the SDK event bus

Closes #381
forbes merged commit 73d14b82ba into main 2026-03-04 19:34:53 +00:00
forbes deleted branch feat/sdk-lifecycle-callbacks 2026-03-04 19:34:54 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/create#399