All checks were successful
Build and Test / build (pull_request) Successful in 29m17s
- docs/src/reference/kcsdk-python.md: full kcsdk Python API reference - docs/src/development/writing-an-addon.md: step-by-step addon guide - docs/INTEGRATION_PLAN.md: add Phase 7 KCSDK section - docs/ARCHITECTURE.md: add src/Gui/SDK/ to source layout - docs/src/SUMMARY.md: add new pages to mdBook navigation
237 lines
17 KiB
Markdown
237 lines
17 KiB
Markdown
# Integration Plan
|
|
|
|
Strategy for integrating ztools and Silo as built-in addons while maintaining clear boundaries with FreeCAD core.
|
|
|
|
## Goals
|
|
|
|
1. **Native feel** -- ztools and Silo behave as first-class citizens, not bolted-on addons
|
|
2. **Clean boundaries** -- Clear separation between FreeCAD core, Kindred extensions, and addon code
|
|
3. **Minimal core modifications** -- Preserve FreeCAD's container models (Part, Body, Assembly)
|
|
4. **Maintainability** -- Easy to pull upstream FreeCAD changes without merge conflicts
|
|
5. **Extensibility** -- Architecture supports future Kindred-specific features
|
|
|
|
## Architecture layers
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Kindred Create Application │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Layer 5: Kindred Addons (mods/) │
|
|
│ ┌──────────────────┐ ┌──────────────────┐ │
|
|
│ │ ztools │ │ Silo │ │
|
|
│ │ Datum Creator │ │ Open/Save/Commit│ │
|
|
│ │ Enhanced Pocket │ │ Part numbering │ │
|
|
│ │ Assembly Patterns│ │ Revision control│ │
|
|
│ │ Spreadsheet fmt │ │ BOM management │ │
|
|
│ └──────────────────┘ └──────────────────┘ │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Layer 4: Kindred Addon SDK (mods/sdk/) │
|
|
│ ┌─────────────────────────────────────────────────────────┐│
|
|
│ │ Stable API contract: context, theme, origin, dock ││
|
|
│ │ Isolates addons from FreeCADGui.* platform internals ││
|
|
│ └─────────────────────────────────────────────────────────┘│
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Layer 3: Kindred Create Module (src/Mod/Create/) │
|
|
│ ┌─────────────────────────────────────────────────────────┐│
|
|
│ │ Python: manifest-driven addon loader, Silo integration ││
|
|
│ │ C++: CreateApp / CreateGui libraries (feature scaffold)││
|
|
│ └─────────────────────────────────────────────────────────┘│
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Layer 2: FreeCAD Python API │
|
|
│ ┌─────────────────────────────────────────────────────────┐│
|
|
│ │ FreeCAD, FreeCADGui, Part, PartDesign, Sketcher, ││
|
|
│ │ Assembly, WorkbenchManipulator ││
|
|
│ └─────────────────────────────────────────────────────────┘│
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Layer 1: FreeCAD Core (C++) │
|
|
│ ┌─────────────────────────────────────────────────────────┐│
|
|
│ │ App::Document, Part::Feature, PartDesign::Body, etc. ││
|
|
│ └─────────────────────────────────────────────────────────┘│
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Boundary definitions
|
|
|
|
### Layer 1: FreeCAD Core -- do not modify
|
|
|
|
FreeCAD's fundamental data structures: `PartDesign::Body`, `PartDesign::Pocket`, `Part::Feature`, `App::Document`, `Sketcher::SketchObject`. Modifying these creates merge conflicts with upstream and risks breaking FCStd file compatibility.
|
|
|
|
### Layer 2: FreeCAD Python API -- use as-is
|
|
|
|
The Python API provides everything needed for feature creation, command registration, and geometry access. ZTools and Silo operate entirely through this layer. Stable FreeCAD APIs (`Gui.addCommand()`, `Gui.addWorkbench()`, `Gui.addWorkbenchManipulator()`) are called directly — they do not need SDK wrappers.
|
|
|
|
### Layer 3: Kindred Create Module -- `src/Mod/Create/`
|
|
|
|
The Create module serves two roles:
|
|
|
|
**Python bootstrap** (`Init.py`, `InitGui.py`, `addon_loader.py`):
|
|
- Scans `mods/` for `package.xml` manifests with `<kindred>` extensions
|
|
- Validates version compatibility, resolves dependencies via topological sort
|
|
- Loads addons in priority order (sdk → ztools → silo)
|
|
- Populates `FreeCAD.KindredAddons` registry for runtime introspection
|
|
- Sets up deferred Silo dock panels, origin registration, and update checker
|
|
|
|
**C++ module scaffold** (`App/`, `Gui/`, `CreateGlobal.h`):
|
|
- `CreateApp.so` and `CreateGui.so` shared libraries
|
|
- Currently scaffold-only (no features). Will host `Create::FlipPocket` and other C++ features that need to compile with the application rather than live in `mods/`.
|
|
- Follows the Assembly module pattern (`PyMOD_INIT_FUNC`, `Py::ExtensionModule`)
|
|
|
|
### Layer 4: Kindred Addon SDK -- `mods/sdk/`
|
|
|
|
The SDK is a pure-Python package that provides stable wrappers around Kindred-specific platform APIs. Addons import from `kindred_sdk` instead of calling `FreeCADGui.*` platform internals directly. This creates a single adaptation point during upstream rebases.
|
|
|
|
SDK modules:
|
|
- `context` — editing context registration (`register_context`, `register_overlay`, `inject_commands`, etc.)
|
|
- `theme` — YAML-driven palette system (`get_theme_tokens`, `load_palette`, `Palette`)
|
|
- `origin` — FileOrigin registration (`register_origin`, `unregister_origin`)
|
|
- `dock` — deferred dock panel helper (`register_dock_panel`)
|
|
- `compat` — version detection (`create_version`, `freecad_version`)
|
|
|
|
The SDK is loaded first (priority 0) and has no dependencies.
|
|
|
|
### Layer 5: Kindred Addons -- `mods/`
|
|
|
|
Pure Python addons with `package.xml` manifests. Self-contained with `Init.py`, `InitGui.py`, and `<kindred>` metadata. Developed and versioned independently as git submodules. Must declare `<dependency>sdk</dependency>` to use SDK APIs.
|
|
|
|
---
|
|
|
|
## Phase status
|
|
|
|
### Phase 1: Addon auto-loading -- DONE
|
|
|
|
**Implementation:** `src/Mod/Create/addon_loader.py` implements manifest-driven loading with dependency resolution. Replaces the original `exec()`-based approach. Each addon provides a `package.xml` with `<kindred>` extensions specifying version bounds, load priority, and dependencies.
|
|
|
|
**Default workbench:** `PartDesignWorkbench` (set in `PreferencePacks/KindredCreate/KindredCreate.cfg`). ZTools is no longer a workbench — its commands are injected into native workbench toolbars via the `EditingContextResolver` and `WorkbenchManipulator` systems.
|
|
|
|
**Registry:** `FreeCAD.KindredAddons` provides runtime introspection — `.loaded()` returns addon names and states, `.get(name)` returns manifest data, `.contexts()` lists registered editing contexts.
|
|
|
|
### Phase 1.5: Addon SDK -- DONE
|
|
|
|
**Goal:** Provide a stable API contract between the Create platform and addons, isolating addons from `FreeCADGui.*` platform internals that may change during upstream rebases.
|
|
|
|
**Implementation:** `mods/sdk/kindred_sdk/` package with wrappers for editing contexts, theme tokens, FileOrigin registration, and dock panel creation. YAML-driven palette system (`palettes/catppuccin-mocha.yaml`) replaces hardcoded color dicts that were duplicated across 5+ locations.
|
|
|
|
**Migration:** Silo has been migrated to use the SDK (#250) — it declares `<dependency>sdk</dependency>` and uses `kindred_sdk` for overlay registration and theme tokens. ztools has **not yet been migrated**: its `package.xml` lacks `<kindred>` metadata and its `InitGui.py` does not import from `kindred_sdk`. See KNOWN_ISSUES.md next step #9.
|
|
|
|
### Phase 1.75: C++ module scaffold -- DONE
|
|
|
|
**Goal:** Establish `src/Mod/Create/App/` and `src/Mod/Create/Gui/` so Kindred-specific C++ features have a proper build target.
|
|
|
|
**Implementation:** `CreateApp.so` and `CreateGui.so` shared libraries following the Assembly module pattern. Currently scaffold-only — no features registered. The existing Python bootstrap continues working alongside the C++ module.
|
|
|
|
### Phase 2: Enhanced Pocket as C++ feature -- NOT STARTED
|
|
|
|
**Goal:** Replace the Python boolean-operation workaround in `ZTools_EnhancedPocket` with a proper `Create::FlipPocket` C++ feature inheriting from `PartDesign::ProfileBased`.
|
|
|
|
**Rationale:** The current Python implementation creates a standard Pocket then applies a boolean Common. A native feature would integrate properly with the feature tree, support undo/redo correctly, and perform better on complex geometry.
|
|
|
|
**Scope:**
|
|
- `src/Mod/Create/App/FeatureFlipPocket.cpp` -- Feature implementation
|
|
- `src/Mod/Create/Gui/TaskFlipPocket.cpp` -- Task panel
|
|
- `src/Mod/Create/Gui/ViewProviderFlipPocket.cpp` -- View provider
|
|
- Update `ZTools_EnhancedPocket` to create `Create::FlipPocket` instead of the workaround
|
|
|
|
**Decision:** Deferred. The Python approach is functional for current needs. Revisit when performance or feature-tree integration becomes a problem.
|
|
|
|
### Phase 3: Datum C++ helpers -- NOT STARTED (SUPERSEDED)
|
|
|
|
**Original goal:** Create C++ geometry helper functions for datum calculations.
|
|
|
|
**Current state:** The Python implementation now uses FreeCAD's built-in `Part::AttachExtension` for automatic parametric updates. Each datum type maps to a native MapMode (`FlatFace`, `ThreePointsPlane`, `NormalToEdge`, etc.) with appropriate `AttachmentSupport` and `AttachmentOffset`. This eliminates the need for custom geometry calculations.
|
|
|
|
**Decision:** Superseded by the AttachExtension approach. Only `tangent_to_cylinder` still uses manual placement (requires a vertex reference not currently collected by the UI).
|
|
|
|
### Phase 4: Theme system -- DONE
|
|
|
|
**Goal:** Theme applies consistently at startup regardless of active workbench.
|
|
|
|
**Current state:** The Catppuccin Mocha theme is set as the default via the KindredCreate preference pack. The canonical QSS lives in `src/Gui/Stylesheets/KindredCreate.qss`. The PreferencePacks copy is generated at build time via `configure_file()` in `src/Gui/PreferencePacks/CMakeLists.txt`.
|
|
|
|
Theme colors are now centralized in the SDK's YAML palette (`mods/sdk/kindred_sdk/palettes/catppuccin-mocha.yaml`). Addons use `kindred_sdk.theme.get_theme_tokens()` instead of hardcoding color dicts. The SDK provides a `Palette` class for programmatic access to colors and semantic roles.
|
|
|
|
### Phase 5: Silo deep integration -- DONE
|
|
|
|
**Goal:** Silo commands available globally, not just in the Silo workbench.
|
|
|
|
**Implementation:** The unified origin system (`FileOrigin`, `OriginManager`, `OriginSelectorWidget`) in `src/Gui/` delegates all file operations (New/Open/Save) to the selected origin. Standard commands (`Std_New`, `Std_Open`, `Std_Save`) and origin commands (`Origin_Commit`, `Origin_Pull`, `Origin_Push`, `Origin_Info`, `Origin_BOM`) are built into the File toolbar and menu. The Silo workbench no longer has its own toolbar — it only provides a menu with admin/management commands.
|
|
|
|
**Dock panels:** Database Auth (2000ms), Database Activity (4000ms), and Start Panel panels are created via deferred QTimers using `kindred_sdk.register_dock_panel()`. The Activity panel displays real-time server events via SSE with automatic reconnection. The Start Panel provides an in-viewport landing page with recent files and Silo integration.
|
|
|
|
### Phase 6: Build system integration -- DONE
|
|
|
|
**Goal:** CMake install rules for `mods/` submodules so packages include ztools, Silo, and SDK automatically.
|
|
|
|
**Implementation:** `src/Mod/Create/CMakeLists.txt` includes install rules for all addons (`mods/ztools`, `mods/silo`, `mods/sdk`) and the C++ module scaffold (`App/`, `Gui/`). Build-time code generation: `version.py.in` → `version.py` via `configure_file()`.
|
|
|
|
**CI/CD status:** Release workflows (`.gitea/workflows/release.yml`) build for Linux (AppImage + .deb), macOS (DMG for Intel + Apple Silicon), and Windows (.exe NSIS installer + .7z archive). Builds run on public runners in dockerized mode. Releases are triggered by `v*` tags. See `docs/CI_CD.md` for details.
|
|
|
|
---
|
|
|
|
### Phase 7: KCSDK — C++-backed SDK module -- IN PROGRESS
|
|
|
|
**Goal:** Replace the pure-Python SDK wrappers with a C++ shared library (`libKCSDK.so`) and pybind11 bindings (`kcsdk.so`). This gives addons a stable, typed API with proper GIL safety and enables future C++ addon development without Python.
|
|
|
|
**Architecture:**
|
|
|
|
```
|
|
Python Addons (silo, future addons, ...)
|
|
|
|
|
kindred_sdk (mods/sdk/) <- convenience layer (try kcsdk, fallback FreeCADGui)
|
|
|
|
|
kcsdk.so (pybind11 module) <- C++ API bindings
|
|
|
|
|
KCSDK (C++ shared library) <- SDKRegistry + provider interfaces
|
|
|
|
|
FreeCADGui (EditingContextResolver, DockWindowManager, OriginManager, ...)
|
|
```
|
|
|
|
**Sub-phases:**
|
|
|
|
| # | Issue | Status | Description |
|
|
|---|-------|--------|-------------|
|
|
| 1 | #350 | DONE | Scaffold KCSDK library + kcsdk pybind11 module |
|
|
| 2 | #351 | DONE | Migrate editing context API to kcsdk |
|
|
| 3 | #352 | DONE | Panel provider system (IPanelProvider) |
|
|
| 4 | #353 | — | C++ theme engine |
|
|
| 5 | #354 | — | Toolbar provider system (IToolbarProvider) |
|
|
| 6 | #355 | — | Menu and action system |
|
|
| 7 | #356 | — | Status bar provider + origin migration |
|
|
| 8 | #357 | — | Deprecation cleanup + SDK v1.0.0 |
|
|
|
|
**Key files:**
|
|
|
|
- `src/Gui/SDK/` — C++ library (KCSDKGlobal.h, Types.h, SDKRegistry, IPanelProvider, WidgetBridge)
|
|
- `src/Gui/SDK/bindings/` — pybind11 module (kcsdk_py.cpp, PyIPanelProvider, PyProviderHolder)
|
|
- `mods/sdk/kindred_sdk/` — Python wrappers with kcsdk/legacy fallback
|
|
|
|
**Design decisions:**
|
|
|
|
- **No Qt in public C++ API** — `Types.h` uses `std::string`, `std::vector`, `std::function`. Qt conversion happens internally in `SDKRegistry.cpp`.
|
|
- **GIL-safe Python callables** — Python callbacks stored via `std::make_shared<py::object>` with `py::gil_scoped_acquire` before every invocation.
|
|
- **PySide widget bridging** — `WidgetBridge::toQWidget()` converts PySide QWidget objects to C++ `QWidget*` via `Gui::PythonWrapper` (Shiboken).
|
|
- **Provider pattern** — Interfaces like `IPanelProvider` enable addons to register factories. The registry calls `create_widget()` once and manages the lifecycle through `DockWindowManager`.
|
|
|
|
---
|
|
|
|
## Design decisions
|
|
|
|
1. **`Create::` namespace prefix.** All Kindred Create C++ features use this prefix to distinguish them from FreeCAD core.
|
|
|
|
2. **No upstream contribution.** Kindred Create is a standalone product. This allows divergent design decisions without upstream coordination. Category 3 bug fixes (see `UPSTREAM.md`) may be upstreamed to reduce patch burden.
|
|
|
|
3. **Silo server distributed separately.** Users deploy the Silo server independently. Setup instructions live in `mods/silo/README.md`.
|
|
|
|
4. **Version synchronization via submodule pins.** ztools and Silo versions are pinned git submodule commits. Updates are deliberate:
|
|
```bash
|
|
cd mods/ztools && git pull origin main && cd ../..
|
|
git add mods/ztools && git commit -m "Update ztools submodule"
|
|
```
|
|
|
|
5. **Python-first approach.** C++ extensions are deferred until Python cannot achieve the requirement. The AttachExtension approach for datums validated this strategy.
|
|
|
|
6. **Graceful degradation.** The addon loader skips addons that fail validation or loading. Each addon load is wrapped in try/except with console logging. The SDK, ztools, and Silo can all be absent without breaking the bootstrap.
|
|
|
|
7. **SDK as adaptation layer.** Addons call `kindred_sdk.*` instead of `FreeCADGui.*` platform internals. This creates a single point of adaptation during upstream rebases — update the SDK wrappers, not every addon.
|
|
|
|
8. **Manifest-driven loading.** Addons declare version bounds, dependencies, and load priority in `package.xml` `<kindred>` extensions. This replaces hardcoded load lists and enables third-party addons in the future.
|