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.
IMenuProvider: declarative menu placement with optional context awareness.
C++ interface with pybind11 bindings + GIL-safe holder. SDKMenuManipulator
(shared WorkbenchManipulator) injects menu items on workbench switch,
filtered by editing context when context_ids() is non-empty.
register_command(): thin Python wrapper around FreeCADGui.addCommand()
that standardizes the calling convention within the SDK contract.
Python wrappers (kindred_sdk.register_menu, kindred_sdk.register_command)
use kcsdk-first routing with FreeCADGui fallback.
EditingContextResolver constructor did not call refresh(), leaving
d->current as a default empty EditingContext. When BreadcrumbToolBar
queried currentContext() on creation, it received an empty context
with no breadcrumb segments, causing the navbar to appear blank.
Add refresh() at end of constructor so the initial state is resolved
before any View3DInventor queries it.
Add context/overlay registration, injection, query, and refresh to the
KCSDK C++ library and kcsdk pybind11 module.
New files:
- src/Gui/SDK/Types.h — ContextDef, OverlayDef, ContextSnapshot structs
(plain C++, no Qt in public API)
Modified:
- src/Gui/SDK/SDKRegistry.h/.cpp — register_context/overlay, unregister,
inject_commands, current_context, refresh (delegates to
EditingContextResolver with std↔Qt conversion)
- src/Gui/SDK/CMakeLists.txt — add Types.h, link FreeCADGui
- src/Gui/SDK/bindings/kcsdk_py.cpp — bind all context functions with
GIL-safe match callable wrapping and dict-based snapshot return
- mods/sdk/kindred_sdk/context.py — try kcsdk first, fall back to
FreeCADGui for backwards compatibility
Copy QuickNav and ZTools source trees into reference/ for developer
reference during the UI/UX rework. These are plain directories (not
submodules) and are not included in the build.
- reference/quicknav/ — QuickNav addon source
- reference/ztools/ — ZTools addon source
Part of the UI/UX rework preparation. See #346.
- Remove ZTools install block from src/Mod/Create/CMakeLists.txt
- Remove mods/ztools submodule entry from .gitmodules
- Remove 'ztools' from legacy fallback order in addon_loader.py
- Remove ztools imports and test classes from test_kindred_pure.py
(TestTypeMatches, TestMatchScore, TestSelectionItemProperties,
TestColumnToIndex, TestDatumModes)
- Remove 'ztools Workbench' from issue template component lists
- Remove mods/ztools submodule from git tracking
ZTools will be archived to a reference folder in a separate step (#345).
This is part of the UI/UX rework epic (#346).
- Remove QuickNav install block from src/Mod/Create/CMakeLists.txt
- Remove mods/quicknav submodule entry from .gitmodules
- Remove quicknav imports and TestWorkbenchMap tests from test_kindred_pure.py
- Remove mods/quicknav submodule from git tracking
QuickNav will be archived to a reference folder in a separate step (#345).
This is part of the UI/UX rework epic (#346).
Rotation::evaluateVector() computes angle = 2*acos(w) which gives
values in [0, 2*pi]. When the relative quaternion has w < 0 (opposite
hemisphere), the angle exceeds pi even though q and -q represent the
same rotation. This caused the validator to report ~350 degree 'flips'
and reject valid solver output.
Fix: map the angle to [0, pi] before comparing against the 91-degree
threshold. This is the short-arc equivalent — the minimum rotation
angle between two orientations regardless of quaternion sign convention.
Points solver to fix/drag-quat-continuity (solver#40) which fixes
the planar constraint drift during interactive drag by enforcing
quaternion continuity on dragged parts and detecting branch jumps
beyond simple hemisphere negation.
Updates solver to include the fix for PlanarConstraint axial drift
when combined with CylindricalConstraint. The distance residual now
uses a world-frame reference normal (Const nodes) instead of the
body-attached normal that rotates with the body.
Updates mods/solver to include fix for the planar half-space correction
that caused 'flipped orientation' rejections when dragging a body
connected by a Cylindrical joint + distance=0 Planar constraint.
The solver's PlanarConstraint half-space tracker was reflecting the body
through the plane when the face normal dot product crossed zero during
legitimate rotation about the cylindrical axis. Now returns a tracking-
only HalfSpace (no correction) for on-plane constraints, matching the
pattern used by Cylindrical/Revolute/Concentric trackers.
See: kindred/solver#38
When parts with structured part numbers (e.g., P03-0001) are inserted
into an assembly multiple times, UniqueNameManager::decomposeName()
treats the trailing digits as an auto-generated suffix and increments
them (P03-0002, P03-0003), corrupting the part number.
Add a makeInstanceLabel() helper in AssemblyLink.cpp that appends -N
instance suffixes instead (P03-0001-1, P03-0001-2). All instances get
a suffix starting at -1 so the original part number is never modified.
Applied at all three Label.setValue() sites in
synchronizeComponents() (AssemblyLink, link group, and regular link
creation paths).
Also add a UniqueNameManager test documenting the trailing-digit
decomposition behavior for structured part numbers.
Closes#327
Three QSS issues caused headings to render with only the top ~60%
visible:
- QGroupBox: margin-top 12px was insufficient for the title rendered
in subcontrol-origin: margin. Increased to 16px and added 2px
vertical padding to the title.
- QDockWidget::title: min-height 18px conflicted with padding 8px 6px,
constraining the content area. Removed min-height to let Qt auto-size
from padding + font metrics.
- QSint--ActionGroup QToolButton: min-height 18px forced a height that
was then clipped by the C++ setFixedHeight(headerSize) calculation.
Set min-height to 0px so the C++ layout controls sizing.
Closes#325
The publish-release job was missing the target_commitish field in the
Gitea release creation API payload. Without it, Gitea cannot resolve
the tag to a git object and returns HTTP 500 with 'object does not
exist'.
Add COMMIT_SHA (from github.sha) to the job env and pass it as
target_commitish in the JSON payload.
Closes#326
The interactive drag section described the original naive implementation
(re-solve from scratch each step) and called the caching layer a
'planned future optimization'. In reality _DragCache is fully
implemented: pre_drag() builds the system, Jacobian, and compiled
evaluator once, and drag_step() reuses them.
Update code snippets, add _DragCache field table, and document the
single_equation_pass exclusion from the drag path.
Picks up fix/drag-orientation-stability (kindred/solver#36):
- Half-space tracking for all compound constraints with branch ambiguity
- Quaternion continuity enforcement during interactive drag