chore: migrate submodules to public repos, rework docs and CI/CD
Some checks failed
Build and Test / build (push) Has been cancelled
Some checks failed
Build and Test / build (push) Has been cancelled
- Update .gitmodules: ztools, silo, and OndselSolver now reference public git.kindred-systems.com URLs instead of internal Gitea - Merge OndselSolver numerical solver with ML solver scaffolding into unified kindred/solver repository - Rewrite README.md for conciseness - Add docs/CI_CD.md with full pipeline documentation - Rework CI/CD workflows for public dockerized runners - Add multi-platform release builds (Linux, macOS, Windows) - Release workflow triggers on v* tags only - Update docs/REPOSITORY_STATE.md and docs/INTEGRATION_PLAN.md
This commit is contained in:
273
docs/CI_CD.md
Normal file
273
docs/CI_CD.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# CI/CD
|
||||
|
||||
Kindred Create uses Gitea Actions for continuous integration and release builds. Workflows are defined in `.gitea/workflows/`.
|
||||
|
||||
## Overview
|
||||
|
||||
| Workflow | Trigger | Purpose | Artifacts |
|
||||
|----------|---------|---------|-----------|
|
||||
| `build.yml` | Push to `main`, pull requests | Build + test | Linux tarball |
|
||||
| `release.yml` | Tags matching `v*` | Multi-platform release | AppImage, .deb, .dmg, .exe, .7z |
|
||||
|
||||
All builds run on public runners in dockerized mode. No host-mode or internal infrastructure is required.
|
||||
|
||||
---
|
||||
|
||||
## Build workflow (`build.yml`)
|
||||
|
||||
Runs on every push to `main` and on pull requests. Builds the project in an Ubuntu 24.04 container and runs the test suite.
|
||||
|
||||
### Steps
|
||||
|
||||
1. Install system prerequisites (GL, X11, fontconfig headers)
|
||||
2. Checkout with recursive submodules
|
||||
3. Install pixi
|
||||
4. Restore ccache from prior builds
|
||||
5. Configure via `pixi run cmake --preset conda-linux-release`
|
||||
6. Build with `pixi run cmake --build build/release -j$(nproc)`
|
||||
7. Run C++ unit tests under xvfb (Assembly_tests excluded due to discovery timeouts)
|
||||
8. Install to `build/release/install`
|
||||
9. Run Python CLI tests (`FreeCADCmd -t 0`)
|
||||
10. Run GUI tests headless (`xvfb-run FreeCAD -t 0`)
|
||||
11. Package as `.tar.xz` with SHA256 checksum
|
||||
12. Upload artifact (14-day retention)
|
||||
|
||||
### Caching
|
||||
|
||||
ccache is persisted between builds using `actions/cache`. Cache keys are scoped by branch and commit SHA, with fallback to the branch key then `main`.
|
||||
|
||||
```
|
||||
Key: ccache-build-{branch}-{sha}
|
||||
Fallback: ccache-build-{branch}-
|
||||
Fallback: ccache-build-main-
|
||||
```
|
||||
|
||||
ccache configuration: 4 GB max, zlib compression level 6, sloppy mode for include timestamps and PCH.
|
||||
|
||||
---
|
||||
|
||||
## Release workflow (`release.yml`)
|
||||
|
||||
Triggered by pushing a tag matching `v*` (e.g., `v0.1.0`, `v1.0.0-rc1`). Builds release packages for all platforms in parallel, then creates a Gitea release with all artifacts.
|
||||
|
||||
### Triggering a release
|
||||
|
||||
```bash
|
||||
git tag v0.1.0
|
||||
git push origin v0.1.0
|
||||
```
|
||||
|
||||
Or manually via `workflow_dispatch` with a tag input.
|
||||
|
||||
Tags containing `rc`, `beta`, or `alpha` are marked as pre-releases.
|
||||
|
||||
### Platform matrix
|
||||
|
||||
| Job | Runner | Container | Preset | Output |
|
||||
|-----|--------|-----------|--------|--------|
|
||||
| `build-linux` | `ubuntu-latest` | `ubuntu:24.04` | `conda-linux-release` | AppImage, .deb |
|
||||
| `build-macos` (Intel) | `macos-13` | native | `conda-macos-release` | .dmg (x86_64) |
|
||||
| `build-macos` (Apple Silicon) | `macos-14` | native | `conda-macos-release` | .dmg (arm64) |
|
||||
| `build-windows` | `windows-latest` | native | `conda-windows-release` | .exe (NSIS), .7z |
|
||||
|
||||
All four jobs run concurrently. After all succeed, `publish-release` collects artifacts and creates the Gitea release.
|
||||
|
||||
### Linux build
|
||||
|
||||
Uses the rattler-build packaging pipeline:
|
||||
|
||||
1. `pixi install` in `package/rattler-build/`
|
||||
2. `pixi run -e package create_bundle` -- invokes `linux/create_bundle.sh`
|
||||
3. The bundle script:
|
||||
- Copies the pixi conda environment to an AppDir
|
||||
- Strips unnecessary files (includes, static libs, cmake files, `__pycache__`)
|
||||
- Downloads `appimagetool` and creates a squashfs AppImage (zstd compressed)
|
||||
- Generates SHA256 checksums
|
||||
4. `package/debian/build-deb.sh` builds a .deb from the AppDir
|
||||
- Installs to `/opt/kindred-create/` with wrapper scripts in `/usr/bin/`
|
||||
- Sets up LD_LIBRARY_PATH, QT_PLUGIN_PATH, PYTHONPATH in wrappers
|
||||
- Creates desktop entry, MIME types, AppStream metainfo
|
||||
|
||||
### macOS build
|
||||
|
||||
Builds natively on macOS runners (Intel via `macos-13`, Apple Silicon via `macos-14`):
|
||||
|
||||
1. `pixi run -e package create_bundle` invokes `osx/create_bundle.sh`
|
||||
2. The bundle script:
|
||||
- Creates `FreeCAD.app` bundle with conda environment in `Contents/Resources/`
|
||||
- Runs `fix_macos_lib_paths.py` to convert absolute rpaths to `@loader_path`
|
||||
- Builds native macOS launcher from `launcher/CMakeLists.txt`
|
||||
- Patches `Info.plist` with version info
|
||||
- Creates DMG via `dmgbuild`
|
||||
- If `SIGN_RELEASE=true`: signs and notarizes via `macos_sign_and_notarize.zsh`
|
||||
|
||||
### Windows build
|
||||
|
||||
Builds natively on Windows runner:
|
||||
|
||||
1. `pixi run -e package create_bundle` invokes `windows/create_bundle.sh` (bash via Git for Windows)
|
||||
2. The bundle script:
|
||||
- Copies conda environment DLLs, Python, and FreeCAD binaries to `FreeCAD_Windows/`
|
||||
- Applies SSL certificate patch (`ssl-patch.py`)
|
||||
- Creates `qt6.conf` for Qt6 plugin paths
|
||||
- Creates `.exe` wrapper shims via Chocolatey `shimgen`
|
||||
- Compresses to `.7z` (compression level 9)
|
||||
- If `MAKE_INSTALLER=true` and NSIS available: builds NSIS installer
|
||||
3. NSIS installer (`package/WindowsInstaller/`):
|
||||
- Multi-language support (28 languages)
|
||||
- File associations for `.FCStd`
|
||||
- Start menu and desktop shortcuts
|
||||
- LZMA compression
|
||||
|
||||
### Publish step
|
||||
|
||||
`publish-release` runs after all platform builds succeed:
|
||||
|
||||
1. Downloads all artifacts from `build-linux`, `build-macos`, `build-windows`
|
||||
2. Collects release files (AppImage, .deb, .dmg, .7z, .exe, checksums)
|
||||
3. Creates a Gitea release via `gitea.com/actions/release-action`
|
||||
4. Requires `RELEASE_TOKEN` secret with repository write permissions
|
||||
|
||||
---
|
||||
|
||||
## Runner configuration
|
||||
|
||||
### Public runner setup
|
||||
|
||||
Workflows target public Gitea-compatible runners. The Linux build job runs inside a Docker container (`ubuntu:24.04`) for isolation and reproducibility. macOS and Windows jobs run directly on hosted runners.
|
||||
|
||||
**Required runner labels:**
|
||||
- `ubuntu-latest` -- Linux builds (dockerized)
|
||||
- `macos-13` -- macOS Intel builds
|
||||
- `macos-14` -- macOS Apple Silicon builds
|
||||
- `windows-latest` -- Windows builds
|
||||
|
||||
### Registering a self-hosted runner
|
||||
|
||||
If using self-hosted runners instead of hosted:
|
||||
|
||||
```bash
|
||||
# Download the Gitea runner binary
|
||||
curl -fsSL -o act_runner https://gitea.com/gitea/act_runner/releases/latest/download/act_runner-linux-amd64
|
||||
chmod +x act_runner
|
||||
|
||||
# Register with your Gitea instance
|
||||
./act_runner register \
|
||||
--instance https://git.kindred-systems.com \
|
||||
--token <RUNNER_REGISTRATION_TOKEN> \
|
||||
--labels ubuntu-latest:docker://ubuntu:24.04
|
||||
|
||||
# Start the runner
|
||||
./act_runner daemon
|
||||
```
|
||||
|
||||
For dockerized mode, the runner executes jobs inside containers. Ensure Docker is installed on the runner host.
|
||||
|
||||
The runner config file (`config.yaml`) should set:
|
||||
|
||||
```yaml
|
||||
runner:
|
||||
labels:
|
||||
- "ubuntu-latest:docker://ubuntu:24.04"
|
||||
container:
|
||||
privileged: false
|
||||
network: bridge
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Secrets
|
||||
|
||||
| Secret | Used by | Purpose |
|
||||
|--------|---------|---------|
|
||||
| `RELEASE_TOKEN` | `release.yml` (publish) | Gitea API token for creating releases |
|
||||
| `SIGNING_KEY_ID` | macOS build (optional) | Apple Developer signing identity |
|
||||
|
||||
---
|
||||
|
||||
## Build tools
|
||||
|
||||
### pixi
|
||||
|
||||
[pixi](https://pixi.sh) manages all build dependencies via conda-forge. It ensures consistent toolchains (clang, cmake, Qt6, OpenCASCADE, etc.) across all platforms without relying on system packages.
|
||||
|
||||
Key pixi tasks (defined in root `pixi.toml`):
|
||||
|
||||
| Task | Description |
|
||||
|------|-------------|
|
||||
| `pixi run configure` | CMake configure (defaults to debug) |
|
||||
| `pixi run build` | CMake build (defaults to debug) |
|
||||
| `pixi run install` | CMake install |
|
||||
| `pixi run test` | Run ctest |
|
||||
| `pixi run freecad` | Launch built FreeCAD |
|
||||
| `pixi run build-release` | CMake build (release) |
|
||||
|
||||
### CMake presets
|
||||
|
||||
Defined in `CMakePresets.json`. Release builds use:
|
||||
|
||||
| Platform | Preset | Compiler | Linker |
|
||||
|----------|--------|----------|--------|
|
||||
| Linux | `conda-linux-release` | clang/clang++ | mold |
|
||||
| macOS | `conda-macos-release` | clang/clang++ | default |
|
||||
| Windows | `conda-windows-release` | MSVC | default |
|
||||
|
||||
### ccache
|
||||
|
||||
Compiler cache is used across all builds to speed up incremental compilation. Cache is persisted between CI runs via `actions/cache`. Configuration:
|
||||
|
||||
- Max size: 4 GB
|
||||
- Compression: zlib level 6
|
||||
- Sloppy mode: include timestamps, PCH defines, time macros
|
||||
|
||||
---
|
||||
|
||||
## Adding a new platform or package format
|
||||
|
||||
1. Create a bundle script at `package/rattler-build/<platform>/create_bundle.sh`
|
||||
2. Add the platform to `package/rattler-build/pixi.toml` if needed
|
||||
3. Add a new job to `release.yml` following the existing pattern
|
||||
4. Add the new artifact pattern to the `publish-release` job's `find` command
|
||||
5. Update the release body template with the new download entry
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build fails with missing system libraries
|
||||
|
||||
The Docker container installs only minimal dependencies. If a new dependency is needed, add it to the `apt-get install` step in the workflow. Check the pixi environment first -- most dependencies should come from conda-forge, not system packages.
|
||||
|
||||
### ccache misses are high
|
||||
|
||||
ccache misses spike when:
|
||||
- The compiler version changes (pixi update)
|
||||
- CMake presets change configuration flags
|
||||
- The cache key doesn't match (new branch, force-pushed SHA)
|
||||
|
||||
Check `pixi run ccache -s` output for hit/miss ratios.
|
||||
|
||||
### Submodule checkout fails
|
||||
|
||||
Submodules pointing to internal Gitea instances require either:
|
||||
- Public mirrors of the submodule repositories
|
||||
- Runner network access to the Gitea instance
|
||||
- Submodule URLs updated to public-facing addresses in `.gitmodules`
|
||||
|
||||
### macOS signing
|
||||
|
||||
Code signing and notarization require:
|
||||
- `SIGNING_KEY_ID` secret set to the Apple Developer identity
|
||||
- `SIGN_RELEASE=true` environment variable
|
||||
- Valid Apple Developer account credentials in the runner keychain
|
||||
|
||||
Without signing, the DMG is created unsigned. Users will see Gatekeeper warnings.
|
||||
|
||||
### Windows NSIS installer not created
|
||||
|
||||
The NSIS installer requires:
|
||||
- NSIS 3.x installed in the runner environment (available via conda or Chocolatey)
|
||||
- `MAKE_INSTALLER=true` environment variable
|
||||
- Chocolatey `shimgen.exe` for wrapper executables
|
||||
|
||||
If NSIS is unavailable, only the `.7z` portable archive is produced.
|
||||
@@ -1,460 +1,159 @@
|
||||
# Kindred Create Integration Plan
|
||||
# Integration Plan
|
||||
|
||||
This document outlines the strategy for integrating ztools and Silo workbenches as built-in addons in Kindred Create while maintaining clear boundaries with FreeCAD core.
|
||||
Strategy for integrating ztools and Silo as built-in addons while maintaining clear boundaries with FreeCAD core.
|
||||
|
||||
## Goals
|
||||
|
||||
1. **Native feel** - ztools and Silo should feel like 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 that supports future Kindred-specific features
|
||||
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
|
||||
|
||||
## Current State
|
||||
|
||||
### Repository Structure
|
||||
```
|
||||
kindred-create/
|
||||
├── src/Mod/ # FreeCAD core modules (PartDesign, Sketcher, Assembly, etc.)
|
||||
├── mods/ # Kindred addons (git submodules)
|
||||
│ ├── ztools/ # Part design extensions, theme
|
||||
│ └── silo/ # Parts database integration
|
||||
└── resources/ # Branding, default preferences
|
||||
```
|
||||
|
||||
### Integration Points Today
|
||||
- **ztools**: Pure Python addon wrapping FreeCAD commands with enhanced UX
|
||||
- **Silo**: Pure Python addon with REST API integration
|
||||
- **Theme**: Preference pack + runtime stylesheet application
|
||||
|
||||
## Architecture Layers
|
||||
## Architecture layers
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Kindred Create Application │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Layer 4: Kindred Workbenches (mods/) │
|
||||
│ ┌─────────────────────┐ ┌─────────────────────┐ │
|
||||
│ │ ztools │ │ Silo │ │
|
||||
│ │ - Datum Creator │ │ - Open/Save/Commit │ │
|
||||
│ │ - Enhanced Pocket │ │ - Part numbering │ │
|
||||
│ │ - Assembly Patterns│ │ - Revision control │ │
|
||||
│ │ - Spreadsheet fmt │ │ - BOM management │ │
|
||||
│ └─────────────────────┘ └─────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Layer 3: Kindred Core Extensions (src/Mod/Kindred/) │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐│
|
||||
│ │ - KindredFeatures: Flip-side pocket, custom geometry ops ││
|
||||
│ │ - KindredGui: Shared UI components, selection helpers ││
|
||||
│ │ - Theme integration hooks ││
|
||||
│ └─────────────────────────────────────────────────────────────┘│
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Layer 2: FreeCAD Python API │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐│
|
||||
│ │ FreeCAD, FreeCADGui, Part, PartDesign, Sketcher, Assembly ││
|
||||
│ └─────────────────────────────────────────────────────────────┘│
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Layer 1: FreeCAD Core (C++) │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐│
|
||||
│ │ App::Document, Part::Feature, PartDesign::Body, etc. ││
|
||||
│ └─────────────────────────────────────────────────────────────┘│
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Kindred Create Application │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Layer 4: Kindred Workbenches (mods/) │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ ztools │ │ Silo │ │
|
||||
│ │ Datum Creator │ │ Open/Save/Commit│ │
|
||||
│ │ Enhanced Pocket │ │ Part numbering │ │
|
||||
│ │ Assembly Patterns│ │ Revision control│ │
|
||||
│ │ Spreadsheet fmt │ │ BOM management │ │
|
||||
│ └──────────────────┘ └──────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Layer 3: Kindred Bootstrap (src/Mod/Create/) │
|
||||
│ ┌─────────────────────────────────────────────────────────┐│
|
||||
│ │ Addon loading, theme application, global menu/toolbar ││
|
||||
│ │ injection via WorkbenchManipulator API ││
|
||||
│ └─────────────────────────────────────────────────────────┘│
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 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
|
||||
## Boundary definitions
|
||||
|
||||
### Layer 1: FreeCAD Core (DO NOT MODIFY)
|
||||
**Location**: `src/Mod/PartDesign/App/`, `src/Mod/Part/App/`, etc.
|
||||
### Layer 1: FreeCAD Core -- do not modify
|
||||
|
||||
These are FreeCAD's fundamental data structures and should remain untouched:
|
||||
- `PartDesign::Body` - Feature container
|
||||
- `PartDesign::Pocket`, `PartDesign::Pad` - Additive/subtractive features
|
||||
- `Part::Feature` - Base geometric feature
|
||||
- `App::Document` - Document container
|
||||
- `Sketcher::SketchObject` - 2D constraint system
|
||||
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.
|
||||
|
||||
**Rationale**: Modifying these creates merge conflicts with upstream FreeCAD and risks breaking compatibility with existing FCStd files.
|
||||
### Layer 2: FreeCAD Python API -- use as-is
|
||||
|
||||
### Layer 2: FreeCAD Python API (USE AS-IS)
|
||||
**Access via**: `import FreeCAD`, `import FreeCADGui`, `import Part`, etc.
|
||||
The Python API provides everything needed for feature creation, command registration, and geometry access. ZTools and Silo operate entirely through this layer.
|
||||
|
||||
The Python API provides everything needed for feature creation:
|
||||
- Create objects: `body.newObject("PartDesign::Pocket", "Pocket")`
|
||||
- Set properties: `pocket.Length = 10.0`
|
||||
- Register commands: `FreeCADGui.addCommand("Name", CommandClass())`
|
||||
- Access geometry: `shape.Faces`, `shape.Edges`, `shape.Vertexes`
|
||||
### Layer 3: Kindred Bootstrap -- `src/Mod/Create/`
|
||||
|
||||
### Layer 3: Kindred Core Extensions (NEW - MINIMAL)
|
||||
**Location**: `src/Mod/Kindred/` (to be created)
|
||||
The Create module is a thin Python loader that:
|
||||
- Adds `mods/` addon paths to `sys.path` and executes their `Init.py`/`InitGui.py` files
|
||||
- Installs `SiloMenuManipulator` for global File menu/toolbar injection
|
||||
- Sets up deferred Silo dock panels (auth, activity) via `QTimer`
|
||||
- Handles first-start configuration
|
||||
|
||||
A thin C++ module providing capabilities that cannot be achieved in pure Python:
|
||||
This layer does not contain C++ code. It uses FreeCAD's `WorkbenchManipulator` API for menu/toolbar injection.
|
||||
|
||||
| Component | Purpose | Justification |
|
||||
|-----------|---------|---------------|
|
||||
| `CreateFeatures` | Custom PartDesign-like features | Python feature objects have performance limitations for complex boolean operations |
|
||||
| `CreateGui` | Shared UI utilities | Common selection helpers, task panel base classes |
|
||||
| `ThemeHooks` | Theme application entry points | Ensure theme applies before any workbench loads |
|
||||
### Layer 4: Kindred Workbenches -- `mods/`
|
||||
|
||||
**Namespace**: All Kindred Create features use the `Create::` prefix (e.g., `Create::FlipPocket`).
|
||||
Pure Python workbenches following FreeCAD's addon pattern. Self-contained with `InitGui.py`, `Init.py`, and `package.xml`. Developed and versioned independently as git submodules.
|
||||
|
||||
**Design principle**: Only add C++ code when Python cannot achieve the requirement. Document why each component exists.
|
||||
---
|
||||
|
||||
### Layer 4: Kindred Workbenches (ADDON PATTERN)
|
||||
**Location**: `mods/ztools/`, `mods/silo/`
|
||||
## Phase status
|
||||
|
||||
Pure Python workbenches following FreeCAD's addon pattern:
|
||||
- Self-contained with `InitGui.py`, `Init.py`, `package.xml`
|
||||
- Register commands via `FreeCADGui.addCommand()`
|
||||
- Define toolbars/menus via `Workbench.appendToolbar()`
|
||||
- Can be developed/tested independently
|
||||
### Phase 1: Addon auto-loading -- DONE
|
||||
|
||||
## Detailed Integration Plan
|
||||
**Implementation:** `src/Mod/Create/Init.py` and `InitGui.py` load workbenches from `mods/` at startup using `exec()`. Addons degrade gracefully if submodule is absent.
|
||||
|
||||
### Phase 1: Addon Auto-Loading
|
||||
**Default workbench:** `ZToolsWorkbench` (set in `resources/preferences/KindredCreate/KindredCreate.cfg`).
|
||||
|
||||
**Goal**: ztools and Silo load automatically without user intervention.
|
||||
### Phase 2: Enhanced Pocket as C++ feature -- NOT STARTED
|
||||
|
||||
**Implementation**:
|
||||
**Goal:** Replace the Python boolean-operation workaround in `ZTools_EnhancedPocket` with a proper `Create::FlipPocket` C++ feature inheriting from `PartDesign::ProfileBased`.
|
||||
|
||||
1. **Create addon manifest** (`src/Mod/Kindred/addons.json`):
|
||||
```json
|
||||
{
|
||||
"builtin_addons": [
|
||||
{
|
||||
"name": "ztools",
|
||||
"path": "mods/ztools/ztools",
|
||||
"autoload": true,
|
||||
"workbench": "ZToolsWorkbench"
|
||||
},
|
||||
{
|
||||
"name": "silo",
|
||||
"path": "mods/silo/pkg/freecad",
|
||||
"autoload": true,
|
||||
"workbench": "SiloWorkbench"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
**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.
|
||||
|
||||
2. **Modify addon path discovery** (`src/Mod/Kindred/Init.py`):
|
||||
```python
|
||||
# Add mods/ directory to FreeCAD's module search path
|
||||
import FreeCAD
|
||||
import os
|
||||
**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
|
||||
|
||||
mods_dir = os.path.join(FreeCAD.getHomePath(), "mods")
|
||||
if os.path.isdir(mods_dir):
|
||||
for addon in os.listdir(mods_dir):
|
||||
addon_path = os.path.join(mods_dir, addon)
|
||||
if os.path.isdir(addon_path) and addon_path not in sys.path:
|
||||
sys.path.insert(0, addon_path)
|
||||
```
|
||||
**Decision:** Deferred. The Python approach is functional for current needs. Revisit when performance or feature-tree integration becomes a problem.
|
||||
|
||||
3. **Set default workbench** in preferences:
|
||||
```xml
|
||||
<!-- resources/preferences/KindredCreate/KindredCreate.cfg -->
|
||||
<FCText Name="StartUpModule">ZToolsWorkbench</FCText>
|
||||
```
|
||||
### Phase 3: Datum C++ helpers -- NOT STARTED (SUPERSEDED)
|
||||
|
||||
**Files to create/modify**:
|
||||
- Create: `src/Mod/Kindred/Init.py`
|
||||
- Create: `src/Mod/Kindred/InitGui.py`
|
||||
- Create: `src/Mod/Kindred/CMakeLists.txt`
|
||||
- Modify: `src/Mod/CMakeLists.txt` (add Kindred subdirectory)
|
||||
- Modify: `resources/preferences/KindredCreate/KindredCreate.cfg`
|
||||
**Original goal:** Create C++ geometry helper functions for datum calculations.
|
||||
|
||||
### Phase 2: Enhanced Pocket as Separate Feature
|
||||
**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.
|
||||
|
||||
**Goal**: "Flip Side to Cut" becomes a proper feature, not a command wrapper.
|
||||
**Decision:** Superseded by the AttachExtension approach. Only `tangent_to_cylinder` still uses manual placement (requires a vertex reference not currently collected by the UI).
|
||||
|
||||
**Current state** (in ztools):
|
||||
```python
|
||||
# ztools/commands/pocket_commands.py
|
||||
class ZTools_EnhancedPocket:
|
||||
def Activated(self):
|
||||
# Creates standard Pocket, then applies boolean Common
|
||||
# Workaround using existing features
|
||||
```
|
||||
### Phase 4: Theme system -- PARTIAL
|
||||
|
||||
**Proposed architecture**:
|
||||
**Goal:** Theme applies consistently at startup regardless of active workbench.
|
||||
|
||||
```
|
||||
src/Mod/Create/
|
||||
├── App/
|
||||
│ ├── CreateFeatures.cpp # Feature implementations
|
||||
│ ├── FeatureFlipPocket.cpp # Flip-side pocket feature
|
||||
│ └── FeatureFlipPocket.h
|
||||
├── Gui/
|
||||
│ ├── Command.cpp # Command registrations
|
||||
│ ├── TaskFlipPocket.cpp # Task panel
|
||||
│ └── ViewProviderFlipPocket.cpp
|
||||
└── CMakeLists.txt
|
||||
```
|
||||
**Current state:** The Catppuccin Mocha theme is set as the default via the KindredCreate preference pack. Four copies of the QSS file exist and must be kept in sync manually:
|
||||
1. `resources/preferences/KindredCreate/KindredCreate.qss` (canonical)
|
||||
2. `src/Gui/Stylesheets/KindredCreate.qss`
|
||||
3. `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss`
|
||||
4. `mods/ztools/CatppuccinMocha/CatppuccinMocha.qss`
|
||||
|
||||
**Feature design** (`Create::FlipPocket`):
|
||||
**Remaining work:** Eliminate QSS duplication via build-time copy or symlinks. Move theme responsibility out of ztools and into the Create module.
|
||||
|
||||
```cpp
|
||||
// Inherits from PartDesign::ProfileBased (same base as Pocket)
|
||||
class FeatureFlipPocket : public PartDesign::ProfileBased {
|
||||
public:
|
||||
// Properties (same as Pocket, plus flip flag)
|
||||
App::PropertyLength Length;
|
||||
App::PropertyEnumeration Type; // Dimension, ThroughAll, ToFirst, UpToFace
|
||||
App::PropertyBool Symmetric;
|
||||
App::PropertyBool FlipSide; // NEW: Cut outside instead of inside
|
||||
|
||||
// Implementation uses Boolean Common instead of Cut when FlipSide=true
|
||||
App::DocumentObjectExecReturn* execute();
|
||||
};
|
||||
```
|
||||
### Phase 5: Silo deep integration -- DONE
|
||||
|
||||
**Separation of concerns**:
|
||||
- **FreeCAD Core** (`PartDesign::Pocket`): Standard inside-cut behavior, unchanged
|
||||
- **Create Extension** (`Create::FlipPocket`): Outside-cut using boolean common
|
||||
- **ztools Workbench**: Provides UI command that creates `Create::FlipPocket`
|
||||
**Goal:** Silo commands available globally, not just in the Silo workbench.
|
||||
|
||||
**Files to create**:
|
||||
- `src/Mod/Create/App/FeatureFlipPocket.cpp`
|
||||
- `src/Mod/Create/App/FeatureFlipPocket.h`
|
||||
- `src/Mod/Create/Gui/TaskFlipPocket.cpp`
|
||||
- `src/Mod/Create/Gui/ViewProviderFlipPocket.cpp`
|
||||
**Implementation:** `SiloMenuManipulator` in `src/Mod/Create/InitGui.py` uses `FreeCADGui.addWorkbenchManipulator()` to inject Silo commands into the File menu and toolbar across all workbenches. `Silo_ToggleMode` provides a one-click swap of Ctrl+O/S/N between standard FreeCAD and Silo file commands.
|
||||
|
||||
**ztools update**:
|
||||
```python
|
||||
# mods/ztools/ztools/commands/pocket_commands.py
|
||||
class ZTools_EnhancedPocket:
|
||||
def Activated(self):
|
||||
# Now creates Create::FlipPocket instead of workaround
|
||||
body = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("pdbody")
|
||||
pocket = body.newObject("Create::FlipPocket", "FlipPocket")
|
||||
pocket.Profile = sketch
|
||||
# Show task panel...
|
||||
```
|
||||
**Dock panels:** Database Auth (1500ms) and Database Activity (4000ms) panels are created via deferred QTimers and docked in the right panel area.
|
||||
|
||||
### Phase 3: Datum System Integration
|
||||
### Phase 6: Build system integration -- PARTIAL
|
||||
|
||||
**Goal**: ztools datum creation uses stable, efficient C++ geometry calculations.
|
||||
**Goal:** CMake install rules for `mods/` submodules so packages include ztools and Silo automatically.
|
||||
|
||||
**Current state**: Pure Python geometry calculations in `ztools/datums/core.py`.
|
||||
**CI/CD status:** Release workflows (`.gitea/workflows/release.yml`) now 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.
|
||||
|
||||
**Issue**: Python geometry operations can be slow and less precise for complex cases.
|
||||
|
||||
**Proposed solution**: Create C++ helper functions, expose via Python.
|
||||
|
||||
```cpp
|
||||
// src/Mod/Create/App/DatumHelpers.cpp
|
||||
namespace Create {
|
||||
// Calculate midplane between two parallel faces
|
||||
gp_Pln computeMidplane(const TopoDS_Face& face1, const TopoDS_Face& face2);
|
||||
|
||||
// Calculate plane through three points
|
||||
gp_Pln computePlaneFrom3Points(gp_Pnt p1, gp_Pnt p2, gp_Pnt p3);
|
||||
|
||||
// Calculate axis at cylinder center
|
||||
gp_Ax1 computeCylinderAxis(const TopoDS_Face& cylinderFace);
|
||||
|
||||
// ... other datum calculations ...
|
||||
}
|
||||
```
|
||||
|
||||
**Python binding**:
|
||||
```python
|
||||
# In ztools after Create module is available
|
||||
from Create import DatumHelpers
|
||||
|
||||
plane = DatumHelpers.computeMidplane(face1, face2)
|
||||
```
|
||||
|
||||
**Separation of concerns**:
|
||||
- **FreeCAD Core** (`PartDesign::DatumPlane`): Data structure, unchanged
|
||||
- **Create Extension** (`DatumHelpers`): Geometry calculation utilities
|
||||
- **ztools Workbench**: UI, selection handling, property storage
|
||||
|
||||
### Phase 4: Theme System Refinement
|
||||
|
||||
**Goal**: Theme applies consistently at startup, no workbench dependency.
|
||||
|
||||
**Current state**: Theme applied when ztools workbench activates.
|
||||
|
||||
**Issue**: If user opens FreeCAD and doesn't activate ztools, theme isn't applied.
|
||||
|
||||
**Proposed solution**:
|
||||
|
||||
1. **Move theme to Create module** (`src/Mod/Create/InitGui.py`):
|
||||
```python
|
||||
# This runs at GUI startup, before any workbench
|
||||
def applyKindredTheme():
|
||||
from PySide import QtWidgets
|
||||
qss_path = os.path.join(FreeCAD.getResourceDir(),
|
||||
"preferences", "KindredCreate", "KindredCreate.qss")
|
||||
with open(qss_path) as f:
|
||||
QtWidgets.QApplication.instance().setStyleSheet(f.read())
|
||||
|
||||
# Apply spreadsheet colors
|
||||
applySpreadsheetColors()
|
||||
|
||||
# Run at import time
|
||||
applyKindredTheme()
|
||||
```
|
||||
|
||||
2. **Remove theme code from ztools**: ztools focuses on commands, not theming.
|
||||
|
||||
3. **Ensure load order**: Create module loads before other workbenches via `src/Mod/CMakeLists.txt` ordering.
|
||||
|
||||
### Phase 5: Silo Deep Integration
|
||||
|
||||
**Goal**: Silo commands available globally, not just in Silo workbench.
|
||||
|
||||
**Current state**: Must switch to Silo workbench to access commands.
|
||||
|
||||
**Proposed solution**:
|
||||
|
||||
1. **Global menu registration** (`src/Mod/Create/InitGui.py`):
|
||||
```python
|
||||
def setupSiloMenu():
|
||||
# Add Silo menu to menu bar regardless of active workbench
|
||||
import silo_commands
|
||||
|
||||
mw = FreeCADGui.getMainWindow()
|
||||
menuBar = mw.menuBar()
|
||||
|
||||
siloMenu = QtWidgets.QMenu("Silo", mw)
|
||||
menuBar.addMenu(siloMenu)
|
||||
|
||||
for cmd in ["Silo_Open", "Silo_Save", "Silo_Commit", "Silo_Pull", "Silo_Push"]:
|
||||
action = FreeCADGui.Command.get(cmd).getAction()
|
||||
siloMenu.addAction(action[0])
|
||||
```
|
||||
|
||||
2. **Keyboard shortcuts** (global):
|
||||
```python
|
||||
# Ctrl+Shift+O: Silo Open
|
||||
# Ctrl+Shift+S: Silo Save
|
||||
# Ctrl+Shift+C: Silo Commit
|
||||
```
|
||||
|
||||
3. **Status bar integration**: Show current Silo item info in status bar.
|
||||
|
||||
### Phase 6: Build System Integration
|
||||
|
||||
**Goal**: mods/ submodules installed correctly during build.
|
||||
|
||||
**Implementation** (`src/Mod/Create/CMakeLists.txt`):
|
||||
**Remaining work:** CMake install rules should be formalized in `src/Mod/Create/CMakeLists.txt` so that `cmake --install` includes mods/ submodules without relying on the packaging scripts to copy them:
|
||||
|
||||
```cmake
|
||||
# Install ztools workbench
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/mods/ztools/ztools
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/ztools)
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/mods/ztools/CatppuccinMocha
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/ztools)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/mods/ztools/package.xml
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/ztools)
|
||||
|
||||
# Install Silo workbench
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/mods/silo/pkg/freecad/
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/Silo)
|
||||
```
|
||||
|
||||
## File Organization Summary
|
||||
---
|
||||
|
||||
### New files to create
|
||||
## Design decisions
|
||||
|
||||
```
|
||||
src/Mod/Create/ # NEW: Kindred Create core extensions
|
||||
├── CMakeLists.txt
|
||||
├── Init.py # Addon path setup
|
||||
├── InitGui.py # Theme application, global menus
|
||||
├── App/
|
||||
│ ├── CMakeLists.txt
|
||||
│ ├── CreateModule.cpp # Module registration
|
||||
│ ├── FeatureFlipPocket.cpp/h # Flip-side pocket feature
|
||||
│ └── DatumHelpers.cpp/h # Datum geometry utilities
|
||||
└── Gui/
|
||||
├── CMakeLists.txt
|
||||
├── CreateGuiModule.cpp
|
||||
├── Command.cpp # Create-specific commands
|
||||
├── TaskFlipPocket.cpp/h
|
||||
└── ViewProviderFlipPocket.cpp/h
|
||||
```
|
||||
1. **`Create::` namespace prefix.** All Kindred Create features use this prefix to distinguish them from FreeCAD core.
|
||||
|
||||
### Files to modify
|
||||
2. **No upstream contribution.** Kindred Create is a standalone product. This allows divergent design decisions without upstream coordination.
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/Mod/CMakeLists.txt` | Add `add_subdirectory(Create)` |
|
||||
| `resources/preferences/KindredCreate/KindredCreate.cfg` | Set default workbench |
|
||||
| `mods/ztools/ztools/commands/pocket_commands.py` | Use `Create::FlipPocket` |
|
||||
| `mods/ztools/ztools/datums/core.py` | Use `Create.DatumHelpers` when available |
|
||||
3. **Silo server distributed separately.** Users deploy the Silo server independently. Setup instructions live in `mods/silo/README.md`.
|
||||
|
||||
### Files to remove/deprecate from ztools
|
||||
|
||||
| File | Reason |
|
||||
|------|--------|
|
||||
| `ztools/resources/theme.py` | Moved to Create module |
|
||||
| Theme application in `InitGui.py` | Handled globally |
|
||||
|
||||
## Implementation Priority
|
||||
|
||||
| Priority | Phase | Effort | Impact |
|
||||
|----------|-------|--------|--------|
|
||||
| 1 | Phase 1: Addon Auto-Loading | Low | High - Seamless user experience |
|
||||
| 2 | Phase 4: Theme System | Low | High - Consistent appearance |
|
||||
| 3 | Phase 5: Silo Global Menu | Medium | High - Always-available database access |
|
||||
| 4 | Phase 2: Enhanced Pocket | High | Medium - Proper feature architecture |
|
||||
| 5 | Phase 3: Datum Helpers | Medium | Medium - Performance improvement |
|
||||
| 6 | Phase 6: Build System | Low | High - Clean distribution |
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
- Create feature creation and execution
|
||||
- Datum helper calculations
|
||||
- Theme application verification
|
||||
|
||||
### Integration Tests
|
||||
- Addon auto-loading on fresh install
|
||||
- Feature creation via ztools commands
|
||||
- Silo operations with mock server
|
||||
- Theme persistence across sessions
|
||||
|
||||
### Compatibility Tests
|
||||
- Open existing FCStd files (no regressions)
|
||||
- Export to STEP/IGES (geometry unchanged)
|
||||
- Upstream FreeCAD file compatibility
|
||||
|
||||
## Migration Notes
|
||||
|
||||
### For existing ztools/silo users
|
||||
- No changes required - workbenches continue to function
|
||||
- Enhanced features available automatically when Create module present
|
||||
- Theme applies globally instead of per-workbench
|
||||
|
||||
### For developers
|
||||
- ztools can check for Create module availability:
|
||||
```python
|
||||
try:
|
||||
import Create
|
||||
HAS_CREATE = True
|
||||
except ImportError:
|
||||
HAS_CREATE = False
|
||||
|
||||
# Use C++ implementation if available, fall back to Python
|
||||
if HAS_CREATE:
|
||||
plane = Create.DatumHelpers.computeMidplane(f1, f2)
|
||||
else:
|
||||
plane = compute_midplane_python(f1, f2)
|
||||
```
|
||||
|
||||
## Design Decisions
|
||||
|
||||
1. **Naming convention**: Kindred Create features use the `Create::` prefix (e.g., `Create::FlipPocket`, `Create::DatumHelpers`) to clearly identify them as Kindred Create extensions separate from FreeCAD core.
|
||||
|
||||
2. **Upstream contribution**: Kindred Create is a standalone product and does not plan to contribute features upstream to FreeCAD. This allows for divergent design decisions optimized for Kindred Create's target use cases.
|
||||
|
||||
3. **Silo server distribution**: Silo server is distributed separately from Kindred Create. Users download and deploy the Silo server independently. Setup instructions are documented in `mods/silo/README.md`.
|
||||
|
||||
4. **Version synchronization**: ztools and Silo versions are determined by pinned git submodule commits. Updates are deliberate and tested before each Kindred Create release. To update:
|
||||
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 to <version>"
|
||||
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 Create module loads successfully even if submodules are absent. Each addon load is wrapped in try/except with console logging.
|
||||
|
||||
@@ -1,332 +1,215 @@
|
||||
# Kindred Create Repository State Report
|
||||
# Repository State
|
||||
|
||||
**Generated:** 2026-01-31
|
||||
**Branch:** main
|
||||
**Parent repo:** create-0070 @ `364a7057ef`
|
||||
**Submodules:**
|
||||
- ztools @ `8d1f195` (ztools-0065, main)
|
||||
- silo @ `c778825` (silo-0062, main)
|
||||
**Last updated:** 2026-02-03
|
||||
**Branch:** main @ `0ef9ffcf51`
|
||||
**Kindred Create:** v0.1.0
|
||||
**FreeCAD base:** v1.0.0
|
||||
|
||||
## Submodules
|
||||
|
||||
| Submodule | Path | Source | Pinned commit |
|
||||
|-----------|------|--------|---------------|
|
||||
| ztools | `mods/ztools` | `gitea.kindred.internal/kindred/ztools-0065` | `d2f94c3` |
|
||||
| silo | `mods/silo` | `gitea.kindred.internal/kindred/silo-0062` | `17a10ab` |
|
||||
| OndselSolver | `src/3rdParty/OndselSolver` | `gitea.kindred.internal/kindred/ondsel` | `e32c9cd` |
|
||||
| GSL | `src/3rdParty/GSL` | `github.com/microsoft/GSL` | `756c91a` |
|
||||
| AddonManager | `src/Mod/AddonManager` | `github.com/FreeCAD/AddonManager` | `01e242e` |
|
||||
| googletest | `tests/lib` | `github.com/google/googletest` | `56efe39` |
|
||||
|
||||
---
|
||||
|
||||
## Recent Changes (This Session)
|
||||
## Architecture
|
||||
|
||||
### Assembly Solver Fix
|
||||
- `610fd43` — PartDesign datum planes (including ZTools datums) now work
|
||||
correctly as joint references in Assembly. `findPlacement()` in
|
||||
`src/Mod/Assembly/UtilsAssembly.py` extracts geometry from
|
||||
`PartDesign::Plane` and `PartDesign::Point` objects instead of returning
|
||||
zero placements.
|
||||
|
||||
### ZTools Bug Fixes
|
||||
- `665bdb2` — Three fixes in the ztools submodule:
|
||||
- Removed `int()` wrapper from `getStandardButtons()` (Qt6/PySide6
|
||||
compatibility — `StandardButton` enum is not int-castable).
|
||||
- Guarded `_setup_ztools_viewprovider()` against C++ ViewProviders
|
||||
that lack a `Proxy` attribute (`PartDesign::Plane` uses
|
||||
`ViewProviderDatumPlane`, pure C++).
|
||||
- Changed `setEditorMode(prop, 2)` to `setPropertyStatus(prop, "Hidden")`
|
||||
for persistent attachment property hiding across save/reload.
|
||||
|
||||
### ZTools Parametric Datums via AttachExtension
|
||||
- `2c716b4` — ZTools datum planes now leverage FreeCAD's built-in
|
||||
`Part::AttachExtension` for automatic parametric updates. Instead of
|
||||
`MapMode = "Deactivated"` with manual placement, each datum type maps to a
|
||||
vanilla `MapMode` (`FlatFace`, `ThreePointsPlane`, `NormalToEdge`, etc.)
|
||||
with appropriate `AttachmentSupport` and `AttachmentOffset`. Datums update
|
||||
automatically when source geometry changes on recompute.
|
||||
|
||||
### Stylesheet Fixes (Uncommitted — Staged)
|
||||
- **Tree branch indicators**: Created `branch_closed.svg` and
|
||||
`branch_open.svg` in `images_dark-light/` with Catppuccin `#cdd6f4`
|
||||
chevrons. Added `QTreeView::branch` image rules for expand/collapse states.
|
||||
- **Spinbox/combobox arrows**: Synced all three QSS copies so the CSS
|
||||
border-triangle arrow fix (previously only in `resources/preferences/`)
|
||||
now applies at runtime via `src/Gui/Stylesheets/KindredCreate.qss`.
|
||||
- **Header clipping**: Added `min-height: 20px` to `QHeaderView::section`.
|
||||
- **QSS sync**: All four copies (`resources/preferences/`, `src/Gui/Stylesheets/`,
|
||||
`src/Gui/PreferencePacks/`, `mods/ztools/CatppuccinMocha/`) are now
|
||||
byte-identical. Merged dock widget padding and spreadsheet cell editor
|
||||
styling improvements that existed only in the Stylesheets copy.
|
||||
|
||||
### ZTools-PartDesign Merge (Uncommitted — Staged)
|
||||
- `_ZToolsPartDesignManipulator` in `mods/ztools/ztools/InitGui.py` uses
|
||||
`Gui.addWorkbenchManipulator()` to inject ZTools commands into PartDesign's
|
||||
C++ toolbars:
|
||||
- `ZTools_DatumCreator` + `ZTools_DatumManager` → "Part Design Helper Features"
|
||||
- `ZTools_EnhancedPocket` → "Part Design Modeling Features"
|
||||
- `ZTools_RotatedLinearPattern` → "Part Design Transformation Features"
|
||||
- Same commands also inserted into the Part Design menu after `PartDesign_Boolean`.
|
||||
|
||||
### Silo Enhancements (Uncommitted — Staged)
|
||||
- **File menu integration**: `SiloMenuManipulator` in `src/Mod/Create/InitGui.py`
|
||||
injects `Silo_New`, `Silo_Open`, `Silo_Save`, `Silo_Commit`, `Silo_Pull`,
|
||||
`Silo_Push`, and `Silo_BOM` into the File menu across all workbenches.
|
||||
- **Toolbar toggle**: `Silo_ToggleMode` checkable command swaps `Ctrl+O/S/N`
|
||||
between standard FreeCAD file commands and Silo equivalents. Appended to the
|
||||
global File toolbar via the manipulator.
|
||||
- **SSL certificate browsing**: Settings dialog now includes a file browser for
|
||||
custom CA certificates (`SslCertPath` preference). `_get_ssl_context()` loads
|
||||
the custom cert before system CAs.
|
||||
- **BOM integration**: Upstream BOM feature (`Silo_BOM` command with tabbed
|
||||
dialog — BOM + Where Used) merged with local changes and added to the
|
||||
Create File menu manipulator.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
create-0070/ Kindred Create (FreeCAD 1.0+ fork)
|
||||
├── src/
|
||||
│ ├── Mod/
|
||||
│ │ ├── Assembly/ Assembly solver (OndselSolver)
|
||||
│ │ ├── PartDesign/ Part modeling (C++ workbench)
|
||||
│ │ ├── Sketcher/ 2D constraint sketcher
|
||||
│ │ ├── Create/ Kindred bootstrap module (Python)
|
||||
│ │ │ └── InitGui.py Loads ztools+silo, installs manipulators
|
||||
│ │ └── ... Other FreeCAD modules
|
||||
│ └── Gui/
|
||||
│ ├── Stylesheets/ QSS themes + arrow/branch SVGs
|
||||
│ ├── PreferencePacks/ Preference pack bundles
|
||||
│ └── WorkbenchManipulatorPython.cpp Menu/toolbar injection API
|
||||
├── mods/
|
||||
│ ├── ztools/ [submodule] ztools-0065
|
||||
│ │ └── ztools/
|
||||
│ │ ├── InitGui.py ZToolsWorkbench + PartDesign manipulator
|
||||
│ │ └── ztools/
|
||||
│ │ ├── commands/ Datum, pattern, pocket, assembly, spreadsheet
|
||||
│ │ ├── datums/core.py Datum creation with AttachExtension
|
||||
│ │ └── resources/ Icons, theme utilities
|
||||
│ └── silo/ [submodule] silo-0062
|
||||
│ └── pkg/freecad/
|
||||
│ ├── InitGui.py SiloWorkbench
|
||||
│ └── silo_commands.py 12 commands + SiloClient API
|
||||
└── resources/
|
||||
└── preferences/KindredCreate/ Canonical QSS + preference pack
|
||||
```
|
||||
|
||||
### Integration Flow
|
||||
### Bootstrap flow
|
||||
|
||||
```
|
||||
FreeCAD startup
|
||||
└─ src/Mod/Create/InitGui.py exec()
|
||||
├─ exec(mods/ztools/ztools/InitGui.py)
|
||||
│ ├─ registers ZToolsWorkbench
|
||||
│ └─ installs _ZToolsPartDesignManipulator (global)
|
||||
├─ exec(mods/silo/pkg/freecad/InitGui.py)
|
||||
│ └─ registers SiloWorkbench
|
||||
└─ QTimer.singleShot(2000):
|
||||
├─ _setup_silo_menu()
|
||||
│ └─ installs SiloMenuManipulator (global)
|
||||
│ ├─ modifyMenuBar: Silo commands in File menu
|
||||
│ └─ modifyToolBars: Silo_ToggleMode in File toolbar
|
||||
├─ _check_silo_first_start()
|
||||
└─ _setup_silo_activity_panel()
|
||||
└─ src/Mod/Create/Init.py
|
||||
└─ setup_kindred_addons()
|
||||
├─ exec(mods/ztools/ztools/Init.py)
|
||||
└─ exec(mods/silo/pkg/freecad/Init.py)
|
||||
|
||||
└─ src/Mod/Create/InitGui.py
|
||||
├─ setup_kindred_workbenches()
|
||||
│ ├─ exec(mods/ztools/ztools/InitGui.py)
|
||||
│ │ ├─ registers ZToolsWorkbench
|
||||
│ │ └─ installs _ZToolsPartDesignManipulator (global)
|
||||
│ └─ exec(mods/silo/pkg/freecad/InitGui.py)
|
||||
│ └─ registers SiloWorkbench
|
||||
└─ Deferred setup (QTimer):
|
||||
├─ 1500ms: _setup_silo_auth_panel() → "Database Auth" dock
|
||||
├─ 2000ms: _setup_silo_menu() → SiloMenuManipulator
|
||||
├─ 3000ms: _check_silo_first_start() → settings prompt
|
||||
└─ 4000ms: _setup_silo_activity_panel() → "Database Activity" dock
|
||||
```
|
||||
|
||||
### Key source layout
|
||||
|
||||
```
|
||||
src/Mod/Create/ Kindred bootstrap module (Python)
|
||||
├── Init.py Adds mods/ addon paths, loads Init.py files
|
||||
└── InitGui.py Loads workbenches, installs Silo manipulators
|
||||
|
||||
mods/ztools/ [submodule] ztools workbench
|
||||
├── ztools/InitGui.py ZToolsWorkbench + PartDesign manipulator
|
||||
├── ztools/ztools/
|
||||
│ ├── commands/ Datum, pattern, pocket, assembly, spreadsheet
|
||||
│ ├── datums/core.py Datum creation via Part::AttachExtension
|
||||
│ └── resources/ Icons, theme utilities
|
||||
└── CatppuccinMocha/ Theme preference pack (QSS)
|
||||
|
||||
mods/silo/ [submodule] Silo parts database
|
||||
├── cmd/ Go server entry points
|
||||
├── internal/ Go API, database, storage packages
|
||||
├── pkg/freecad/ FreeCAD workbench (Python)
|
||||
│ ├── InitGui.py SiloWorkbench
|
||||
│ └── silo_commands.py Commands + SiloClient API
|
||||
├── deployments/ Docker compose configuration
|
||||
└── migrations/ PostgreSQL schema migrations
|
||||
|
||||
src/Gui/Stylesheets/ QSS themes and SVG assets
|
||||
resources/preferences/ Canonical preference pack (KindredCreate)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Submodule Status
|
||||
## Component status
|
||||
|
||||
### ztools (ztools-0065)
|
||||
### ztools workbench
|
||||
|
||||
| Commit | Description |
|
||||
|--------|-------------|
|
||||
| `8d1f195` | Add PartDesign WorkbenchManipulator and sync Catppuccin theme |
|
||||
| `005348b` | Leverage FreeCAD AttachExtension for parametric datum updates |
|
||||
| `0e95d1c` | Fix Qt6 StandardButton TypeError and C++ ViewProvider Proxy errors |
|
||||
| `98bd444` | Fix workbench init and spreadsheet syntax errors |
|
||||
**Registered commands (9):**
|
||||
|
||||
**Custom commands**: 9 registered
|
||||
- `ZTools_DatumCreator`, `ZTools_DatumManager`
|
||||
- `ZTools_RotatedLinearPattern`
|
||||
- `ZTools_EnhancedPocket`
|
||||
- `ZTools_AssemblyLinearPattern`, `ZTools_AssemblyPolarPattern`
|
||||
- `ZTools_SpreadsheetStyle{Bold,Italic,Underline}`, `ZTools_SpreadsheetAlign{Left,Center,Right}`, `ZTools_Spreadsheet{BgColor,TextColor,QuickAlias}`
|
||||
| Command | Function |
|
||||
|---------|----------|
|
||||
| `ZTools_DatumCreator` | Create datum planes, axes, points (16 modes) |
|
||||
| `ZTools_DatumManager` | Manage existing datum objects |
|
||||
| `ZTools_EnhancedPocket` | Flip-side pocket (cut outside sketch profile) |
|
||||
| `ZTools_RotatedLinearPattern` | Linear pattern with incremental rotation |
|
||||
| `ZTools_AssemblyLinearPattern` | Pattern assembly components linearly |
|
||||
| `ZTools_AssemblyPolarPattern` | Pattern assembly components around axis |
|
||||
| `ZTools_SpreadsheetStyle{Bold,Italic,Underline}` | Text style toggles |
|
||||
| `ZTools_SpreadsheetAlign{Left,Center,Right}` | Cell alignment |
|
||||
| `ZTools_Spreadsheet{BgColor,TextColor,QuickAlias}` | Colors and alias creation |
|
||||
|
||||
**Datum types supported**: offset_from_face, offset_from_plane, midplane,
|
||||
3_points, normal_to_edge, angled, tangent_to_cylinder
|
||||
**PartDesign integration** via `_ZToolsPartDesignManipulator`:
|
||||
- `ZTools_DatumCreator`, `ZTools_DatumManager` → "Part Design Helper Features" toolbar
|
||||
- `ZTools_EnhancedPocket` → "Part Design Modeling Features" toolbar
|
||||
- `ZTools_RotatedLinearPattern` → "Part Design Transformation Features" toolbar
|
||||
- Same commands inserted into Part Design menu after `PartDesign_Boolean`
|
||||
|
||||
### silo (silo-0062)
|
||||
**Datum types (7):** offset_from_face, offset_from_plane, midplane, 3_points, normal_to_edge, angled, tangent_to_cylinder. All except tangent_to_cylinder use `Part::AttachExtension` for automatic parametric updates.
|
||||
|
||||
| Commit | Description |
|
||||
|--------|-------------|
|
||||
| `c778825` | Add Silo mode toggle, SSL cert browsing, and BOM menu integration |
|
||||
| `8c06899` | (upstream) Various fixes |
|
||||
| `bce7d5a` | Add BOM handling and routes to API and web UI |
|
||||
| `3a79d89` | feat: add BOM system with API, database repository, and FreeCAD command |
|
||||
| `8e44ed2` | Fix SIGSEGV: defer document open after dialog close |
|
||||
### Silo workbench
|
||||
|
||||
**FreeCAD commands**: 12 registered
|
||||
- `Silo_Open`, `Silo_New`, `Silo_Save`, `Silo_Commit`
|
||||
- `Silo_Pull`, `Silo_Push`, `Silo_Info`, `Silo_BOM`
|
||||
- `Silo_TagProjects`, `Silo_Rollback`, `Silo_SetStatus`
|
||||
- `Silo_Settings`, `Silo_ToggleMode`
|
||||
**Registered commands (13):**
|
||||
|
||||
**API surface**: 38 REST routes covering items, revisions, files, BOM,
|
||||
projects, schemas, and Odoo integration stubs. See
|
||||
`mods/silo/docs/REPOSITORY_STATUS.md` for full route table.
|
||||
| Command | Function |
|
||||
|---------|----------|
|
||||
| `Silo_New` | Create new Silo-tracked document |
|
||||
| `Silo_Open` | Open file from Silo database |
|
||||
| `Silo_Save` | Save to Silo (create revision) |
|
||||
| `Silo_Commit` | Commit current revision |
|
||||
| `Silo_Pull` | Pull latest revision from server |
|
||||
| `Silo_Push` | Push local changes to server |
|
||||
| `Silo_Info` | View item metadata and history |
|
||||
| `Silo_BOM` | Bill of materials dialog (BOM + Where Used) |
|
||||
| `Silo_TagProjects` | Assign project tags |
|
||||
| `Silo_Rollback` | Rollback to previous revision |
|
||||
| `Silo_SetStatus` | Set revision status (draft/review/released/obsolete) |
|
||||
| `Silo_Settings` | Configure API URL, projects dir, SSL certificates |
|
||||
| `Silo_ToggleMode` | Swap Ctrl+O/S/N between FreeCAD and Silo commands |
|
||||
|
||||
**BOM API methods** (new):
|
||||
- `get_bom()`, `get_bom_expanded()`, `get_bom_where_used()`
|
||||
- `add_bom_entry()`, `update_bom_entry()`, `delete_bom_entry()`
|
||||
**Global integration** via `SiloMenuManipulator` in `src/Mod/Create/InitGui.py`:
|
||||
- File menu: Silo_New, Silo_Open, Silo_Save, Silo_Commit, Silo_Pull, Silo_Push, Silo_BOM
|
||||
- File toolbar: Silo_ToggleMode button
|
||||
|
||||
**Server architecture:** Go REST API (38 routes) + PostgreSQL + MinIO. See `mods/silo/docs/REPOSITORY_STATUS.md` for route details.
|
||||
|
||||
### Theme
|
||||
|
||||
**Canonical source:** `resources/preferences/KindredCreate/KindredCreate.qss`
|
||||
|
||||
Four copies must stay in sync:
|
||||
1. `resources/preferences/KindredCreate/KindredCreate.qss` (canonical)
|
||||
2. `src/Gui/Stylesheets/KindredCreate.qss`
|
||||
3. `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss`
|
||||
4. `mods/ztools/CatppuccinMocha/CatppuccinMocha.qss`
|
||||
|
||||
---
|
||||
|
||||
## Potential Issues
|
||||
## Known issues
|
||||
|
||||
### Critical
|
||||
|
||||
1. **Three QSS copies can drift again.** The canonical source is
|
||||
`resources/preferences/KindredCreate/KindredCreate.qss`. The other copies
|
||||
(`src/Gui/Stylesheets/`, `src/Gui/PreferencePacks/`, `mods/ztools/CatppuccinMocha/`)
|
||||
must be kept in sync manually. Consider a build step or symlinks to
|
||||
eliminate duplication.
|
||||
1. **QSS duplication.** Four copies of the stylesheet must be kept in sync manually. A build step or symlinks should eliminate this.
|
||||
|
||||
2. **WorkbenchManipulator command registration timing.** The
|
||||
`_ZToolsPartDesignManipulator` appends commands by name (e.g.
|
||||
`ZTools_DatumCreator`). If the ZTools workbench has not been initialized
|
||||
(first activation) when the user switches to PartDesign, the commands may
|
||||
not be registered yet. The `Create/InitGui.py` `exec()` loads the
|
||||
workbench class but `Initialize()` only runs on first activation. The
|
||||
manipulator API tolerates missing commands silently (toolbar append
|
||||
returns without error), but the buttons won't appear until ZTools
|
||||
initializes. Mitigation: force-activate ZToolsWorkbench during Create
|
||||
module load, or defer manipulator installation.
|
||||
2. **WorkbenchManipulator timing.** The `_ZToolsPartDesignManipulator` appends commands by name. If ZToolsWorkbench hasn't been activated when the user switches to PartDesign, the commands may not be registered. The manipulator API tolerates missing commands silently, but buttons won't appear.
|
||||
|
||||
3. **Silo toggle mode shortcut persistence.** `_swap_shortcuts()` stores
|
||||
original shortcuts in a module-level dict (`_original_shortcuts`). If
|
||||
FreeCAD crashes with Silo mode ON, the original shortcuts are lost and
|
||||
standard commands will have no keyboard shortcuts on next launch. Consider
|
||||
persisting original shortcuts to preferences.
|
||||
3. **Silo shortcut persistence.** `Silo_ToggleMode` stores original shortcuts in a module-level dict. If FreeCAD crashes with Silo mode on, original shortcuts are lost on next launch.
|
||||
|
||||
### High
|
||||
|
||||
4. **Silo has no authentication.** All API endpoints are publicly accessible.
|
||||
Required before multi-user deployment. See
|
||||
`mods/silo/docs/REPOSITORY_STATUS.md` for full list.
|
||||
4. **No authentication on Silo server.** All API endpoints are publicly accessible. Required before multi-user deployment.
|
||||
|
||||
5. **No unit tests for silo FreeCAD commands or ztools.** Python code has zero
|
||||
test coverage. The Go backend also lacks tests per the silo status report.
|
||||
5. **No unit tests.** Zero test coverage for ztools and Silo FreeCAD commands. Silo Go backend also lacks tests.
|
||||
|
||||
6. **Assembly solver `findPlacement()` geometry extraction is minimal.** The
|
||||
fix at `UtilsAssembly.py:1006` extracts placement from `obj.Shape.Faces[0]`
|
||||
for `PartDesign::Plane`. This works for planar datums but does not handle
|
||||
edge cases like empty shapes or non-planar datum objects.
|
||||
6. **Assembly solver datum handling is minimal.** The `findPlacement()` fix extracts placement from `obj.Shape.Faces[0]` for `PartDesign::Plane`. Does not handle empty shapes or non-planar datum objects.
|
||||
|
||||
### Medium
|
||||
|
||||
7. **`Silo_BOM` depends on `get_tracked_object()`** which looks for a
|
||||
`SiloPartNumber` property on document objects. Documents not registered
|
||||
with Silo show a warning dialog. The UX could be improved with a
|
||||
one-click registration flow from the BOM dialog.
|
||||
7. **`Silo_BOM` requires Silo-tracked document.** Depends on `SiloPartNumber` property. Unregistered documents show a warning with no registration path.
|
||||
|
||||
8. **`_ZToolsPartDesignManipulator.modifyMenuBar()` inserts after
|
||||
`PartDesign_Boolean`.** If upstream FreeCAD renames or removes this
|
||||
command, the menu insertions silently fail. The toolbar appends (by
|
||||
toolbar name) are more robust.
|
||||
8. **PartDesign menu insertion fragility.** `_ZToolsPartDesignManipulator.modifyMenuBar()` inserts after `PartDesign_Boolean`. If upstream renames this command, insertions silently fail.
|
||||
|
||||
9. **ZTools `plane_tangent_to_cylinder` falls back to manual placement**
|
||||
because the TangentPlane MapMode requires a vertex reference not currently
|
||||
collected by the UI. This is the only datum type that does not benefit
|
||||
from automatic parametric updates.
|
||||
9. **tangent_to_cylinder falls back to manual placement.** TangentPlane MapMode requires a vertex reference not collected by the current UI.
|
||||
|
||||
10. **Silo `delete_bom_entry()` uses raw `urllib.request`** instead of the
|
||||
`_request()` helper method on `SiloClient`. This bypasses error
|
||||
normalization. Should be refactored to use `self._request("DELETE", ...)`.
|
||||
10. **`delete_bom_entry()` bypasses error normalization.** Uses raw `urllib.request` instead of `SiloClient._request()`.
|
||||
|
||||
---
|
||||
|
||||
## Feature Stubs and TODOs
|
||||
## Incomplete features
|
||||
|
||||
### From silo REPOSITORY_STATUS
|
||||
### Silo
|
||||
|
||||
| Feature | Status | Location |
|
||||
|---------|--------|----------|
|
||||
| Odoo ERP integration | Stub (returns "not yet implemented") | `internal/odoo/` |
|
||||
| Part number date segments | Broken (`formatDate()` returns error) | `internal/partnum/generator.go:102` |
|
||||
| Location/Inventory APIs | Tables exist, no handlers | `migrations/001_initial.sql` |
|
||||
| File locking | Not implemented | — |
|
||||
| Authentication/Authorization | Not implemented | — |
|
||||
| Feature | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| Authentication/authorization | Not implemented | Required for multi-user |
|
||||
| File locking | Not implemented | Needed to prevent concurrent edits |
|
||||
| Odoo ERP integration | Stub only | Returns "not yet implemented" |
|
||||
| Part number date segments | Broken | `formatDate()` returns error |
|
||||
| Location/inventory APIs | Tables exist, no handlers | |
|
||||
| CSRF protection | Not implemented | Web UI only |
|
||||
| CSV import transaction rollback | Not implemented | `bom_handlers.go` |
|
||||
| CSV import rollback | Not implemented | `bom_handlers.go` |
|
||||
|
||||
### From ztools
|
||||
### ztools
|
||||
|
||||
| Feature | Status | Location |
|
||||
|---------|--------|----------|
|
||||
| Tangent-to-cylinder attachment | Manual fallback (no vertex ref) | `datums/core.py` |
|
||||
| Angled datum live editing | AttachmentOffset rotation not updated in panel | `datum_viewprovider.py` |
|
||||
| Assembly pattern undo support | Not implemented | `assembly_pattern_commands.py` |
|
||||
| Feature | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| Tangent-to-cylinder attachment | Manual fallback | No vertex ref in UI |
|
||||
| Angled datum live editing | Incomplete | AttachmentOffset not updated in panel |
|
||||
| Assembly pattern undo | Not implemented | |
|
||||
|
||||
### From Create integration plan
|
||||
### Integration plan
|
||||
|
||||
| Phase | Feature | Status |
|
||||
|-------|---------|--------|
|
||||
| 1 | Addon auto-loading | Done (`src/Mod/Create/InitGui.py`) |
|
||||
| 1 | Addon auto-loading | Done |
|
||||
| 2 | Enhanced Pocket as C++ feature | Not started |
|
||||
| 3 | Datum C++ helpers | Not started (Python AttachExtension approach used instead) |
|
||||
| 4 | Theme system refinement | Partially done (QSS synced, not moved to Create module) |
|
||||
| 5 | Silo deep integration | Done (manipulator-based menu/toolbar injection) |
|
||||
| 6 | Build system integration | Not started |
|
||||
| 3 | Datum C++ helpers | Not started (Python approach used) |
|
||||
| 4 | Theme moved to Create module | Partial (QSS synced, not relocated) |
|
||||
| 5 | Silo deep integration | Done |
|
||||
| 6 | Build system install rules for mods/ | Partial (CI/CD done, CMake install rules pending) |
|
||||
|
||||
---
|
||||
|
||||
## File Change Summary (Uncommitted)
|
||||
## Next steps
|
||||
|
||||
### Parent repo (create-0070)
|
||||
1. **Authentication** -- LDAP/FreeIPA integration for Silo multi-user deployment. Server needs auth middleware; FreeCAD client needs credential storage.
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `resources/preferences/KindredCreate/KindredCreate.qss` | Branch indicators, header min-height, dock/actiongroup improvements, spreadsheet cell editor |
|
||||
| `src/Gui/Stylesheets/KindredCreate.qss` | Synced with canonical |
|
||||
| `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss` | Synced with canonical |
|
||||
| `src/Gui/Stylesheets/images_dark-light/branch_closed.svg` | New: right-pointing chevron |
|
||||
| `src/Gui/Stylesheets/images_dark-light/branch_open.svg` | New: down-pointing chevron |
|
||||
| `src/Mod/Create/InitGui.py` | Expanded SiloMenuManipulator (BOM, full commands, toolbar toggle) |
|
||||
| `mods/silo` | Submodule pointer updated |
|
||||
| `mods/ztools` | Submodule pointer updated |
|
||||
2. **BOM-Assembly bridge** -- Auto-populate Silo BOM from Assembly component links on save.
|
||||
|
||||
### ztools submodule (committed + pushed)
|
||||
3. **File locking** -- Pessimistic locks on `Silo_Open` to prevent concurrent edits. Requires server-side lock table and client-side lock display.
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `ztools/InitGui.py` | Added `_ZToolsPartDesignManipulator` |
|
||||
| `CatppuccinMocha/CatppuccinMocha.qss` | Synced with canonical KindredCreate.qss |
|
||||
4. **Build system** -- CMake install rules for `mods/` submodules so packages include ztools and Silo without manual steps.
|
||||
|
||||
### silo submodule (committed + pushed)
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `pkg/freecad/silo_commands.py` | SSL cert browsing, `Silo_ToggleMode`, BOM merge |
|
||||
| `pkg/freecad/InitGui.py` | Added `Silo_ToggleMode` to toolbar |
|
||||
|
||||
---
|
||||
|
||||
## Silo Integration Path
|
||||
|
||||
Based on `mods/silo/docs/REPOSITORY_STATUS.md` and the existing
|
||||
`docs/INTEGRATION_PLAN.md`, the integration path forward is:
|
||||
|
||||
### Completed
|
||||
- Addon auto-loading via `src/Mod/Create/InitGui.py`
|
||||
- Global File menu injection via `WorkbenchManipulator`
|
||||
- Toolbar toggle for Silo mode (shortcut swapping)
|
||||
- SSL certificate configuration for internal CAs
|
||||
- BOM command integrated into File menu
|
||||
|
||||
### Next Steps
|
||||
1. **Authentication** — LDAP/FreeIPA integration for multi-user. Silo server
|
||||
needs auth middleware; FreeCAD client needs credential storage in preferences.
|
||||
2. **BOM-Assembly bridge** — Auto-populate Silo BOM from FreeCAD Assembly
|
||||
component links. When a user saves an assembly, extract child part numbers
|
||||
from `Assembly_InsertLink` objects and sync to Silo BOM.
|
||||
3. **File locking** — Pessimistic locks on checkout (`Silo_Open`) to prevent
|
||||
concurrent edits. Requires server-side lock table and client-side
|
||||
lock-status display.
|
||||
4. **Status bar integration** — Show current Silo item part number, revision,
|
||||
and sync status in FreeCAD's status bar. Use
|
||||
`FreeCADGui.getMainWindow().statusBar()`.
|
||||
5. **Build system** — CMake install rules for `mods/` submodules so `.deb`
|
||||
packages include ztools and silo without manual intervention.
|
||||
5. **Test coverage** -- Unit tests for ztools datum creation, Silo FreeCAD commands, and Go API endpoints.
|
||||
|
||||
Reference in New Issue
Block a user