Commit Graph

17 Commits

Author SHA1 Message Date
forbes
2bf969c62a fix: use TangentPlane MapMode for tangent-to-cylinder datums (#58)
plane_tangent_to_cylinder() now derives a vertex from the cylinder
face's edges and uses TangentPlane MapMode with AttachmentOffset to
encode the angular position. This makes tangent datums parametric —
they auto-update when cylinder geometry changes.

Add _find_cylinder_vertex() and _vertex_angle_on_cylinder() helpers.
Store vertex_angle in ZTools_Params for the edit panel to compute
AttachmentOffset updates. Falls back to manual placement when no
vertex can be resolved (non-Body datums).
2026-02-08 18:53:13 -06:00
forbes
04f9df75cb fix: update AttachmentOffset during angled datum editing (#66)
on_param_changed() now recomputes AttachmentOffset.Rotation for angled
datums and recalculates Placement for tangent_cylinder datums when the
angle spinner changes. Previously only ZTools_Params was updated,
leaving the visual representation unchanged until a manual recompute.

Add _resolve_source_refs() helper to parse ZTools_SourceRefs and
resolve stored object/subname pairs to actual shapes for the rotation
and placement math.
2026-02-08 18:42:28 -06:00
forbes
2132c4e64c fix: use append instead of fragile insert chain in PartDesign menu (#57)
Replace the chained insert operations in modifyMenuBar() with independent
append operations. The old approach anchored on PartDesign_Boolean and
chained each subsequent command off the previous insertion — a single
missing anchor caused a cascade failure.

The new approach uses append with PartDesign_Body as the parent locator.
Each operation is independent, so a failure in one does not affect the
others.
2026-02-08 18:07:18 -06:00
forbes
12e332240a fix: register commands and manipulator at module scope (#52)
Move command imports and PartDesign manipulator installation from
ZToolsWorkbench.Initialize() to module scope. This ensures commands
are registered and the manipulator is available before any workbench
activates, fixing the case where PartDesign activates before ZTools
and ztools buttons never appear.
2026-02-08 17:57:54 -06:00
forbes
d2f94c3d78 fix: defer PartDesign manipulator registration until commands are imported
The _ZToolsPartDesignManipulator was registered at module load time via
Gui.addWorkbenchManipulator(), but the commands it references
(ZTools_DatumCreator, ZTools_DatumManager, ZTools_EnhancedPocket,
ZTools_RotatedLinearPattern) are not registered until Initialize()
imports the command modules.

Move the addWorkbenchManipulator() call into Initialize() with a guard
to prevent duplicate registration. This eliminates the 'Unknown command'
warnings on startup.
2026-02-01 19:51:56 -06:00
Zoe Forbes
9dde3ad67b feat(theme): add spanning tree branch lines to CatppuccinMocha
Replace simple open/closed arrow indicators with full spanning tree
branch lines (vline, T-junction, L-junction) using the _dark SVG
variants. This renders the model tree with ASCII pipe-style connectors
instead of bare disclosure arrows.
2026-01-31 20:49:39 -06:00
Zoe Forbes
6507dff1a1 fix(datum): fix selection table column alignment
Use fixed-width columns (28px) for the type icon and remove button
instead of ResizeToContents, which was sizing them to the header text
width rather than the content. The 'Type' header label is removed
since the narrow icon column is self-explanatory. The remove button
uses setFixedSize(24,24) to sit cleanly within its fixed column.
2026-01-31 20:41:27 -06:00
Zoe Forbes
6f4ac5ffb1 fix(datum): prevent RuntimeError from deleted Qt widgets in params UI
QFormLayout.removeRow() destroys the widgets it owns, transferring
ownership to Qt which immediately deletes the underlying C++ objects.
The update_params_ui() method was calling removeRow(0) in a loop to
clear the parameter fields before re-populating them for the new mode.
This destroyed the long-lived QDoubleSpinBox instances (offset_spin,
angle_spin, param_spin, x/y/z_spin) stored as instance attributes.

On the next call to update_params_ui() — triggered by selection
changes, row removal, or mode override — the method attempted to
addRow() with these same Python references, but the C++ objects behind
them had already been freed by Qt. This produced:

  RuntimeError: Internal C++ object (PySide6.QtWidgets.QDoubleSpinBox)
  already deleted.

The fix replaces the removeRow() loop with a new _clear_params_layout()
method that uses QLayout.takeAt() to detach items from the layout
without destroying them. Each widget is hidden and reparented to None
(releasing Qt's ownership) so it survives the layout clearing and can
be safely re-added with addRow() and show() on the next mode switch.
2026-01-31 20:39:20 -06:00
Zoe Forbes
8d1f195e56 Add PartDesign WorkbenchManipulator and sync Catppuccin theme
- _ZToolsPartDesignManipulator: injects ZTools commands into PartDesign
  workbench toolbars (Helper, Modeling, Transformation) and menus via
  Gui.addWorkbenchManipulator() - no workbench switch needed
- Sync CatppuccinMocha.qss with canonical KindredCreate.qss: tree branch
  indicators, header min-height, dock/actiongroup padding, spreadsheet
  cell editor styling, CSS border-triangle arrows
2026-01-31 09:21:38 -06:00
Zoe Forbes
005348b8a9 Leverage FreeCAD AttachExtension for parametric datum updates
ZTools datum planes now use FreeCAD's built-in attachment engine instead
of setting MapMode='Deactivated' with manual placement. This means
datums automatically update when source geometry changes on recompute.

Each datum type maps to a vanilla MapMode:
  offset_from_face  -> FlatFace + AttachmentOffset.Base.z = distance
  offset_from_plane -> FlatFace + AttachmentOffset.Base.z = distance
  midplane          -> FlatFace on face1 + offset = half gap distance
  3_points          -> ThreePointsPlane (3 vertex refs)
  normal_to_edge    -> NormalToEdge + MapPathParameter for position
  angled            -> FlatFace + AttachmentOffset.Rotation for angle
  tangent_cylinder  -> manual fallback (TangentPlane needs vertex ref)

The C++ AttachExtension handles: automatic recompute via
extensionExecute(), dependency tracking via PropertyLinkSubList,
topology change handling, and live preview via extensionOnChanged().

Non-Body datums (Part::Plane) lack AttachExtension and continue to
use manual placement as before.

Other changes:
- New _configure_attachment() helper sets MapMode, AttachmentSupport,
  AttachmentOffset, and MapPathParameter on datum objects
- _setup_ztools_datum() accepts optional attachment parameters and
  falls back to manual placement when not provided
- DatumEditTaskPanel.on_param_changed() writes to AttachmentOffset
  and MapPathParameter for live editing instead of TODO stubs
- AttachmentSupport added to hidden properties list
- Spreadsheet links target AttachmentOffset.Base.z instead of
  Placement.Base.z for attached datums
- ZTools metadata (ZTools_Type, ZTools_Params, ZTools_SourceRefs)
  preserved for edit UI and styling
2026-01-31 08:09:53 -06:00
Zoe Forbes
0e95d1cc76 Fix Qt6 StandardButton TypeError and C++ ViewProvider Proxy errors
Three fixes:

1. Remove int() wrapper from getStandardButtons() return values.
   In Qt6/PySide6, the | operator on QDialogButtonBox.StandardButton
   returns a StandardButton enum that is not convertible to int via
   int(). FreeCAD's task panel system accepts the enum directly.
   Affected files: datum_commands.py, datum_viewprovider.py,
   assembly_pattern_commands.py

2. Guard _setup_ztools_viewprovider() against C++ ViewProviders.
   PartDesign datum objects (Plane, Line, Point) use pure C++
   ViewProviders (e.g. ViewProviderDatumPlane) that don't expose a
   Proxy attribute. The previous code crashed with:
   'Gui.ViewProviderGeometryObject' object has no attribute 'Proxy'
   Now checks hasattr(vo, 'Proxy') before attempting assignment and
   wraps the assignment in try/except as a secondary guard.

3. Use persistent setPropertyStatus('Hidden') instead of transient
   setEditorMode(2) for hiding attachment properties (MapMode,
   Support, etc.). setEditorMode is session-only and resets on
   document reload, leaving 'MapMode: Deactivated' visible in the
   property panel. setPropertyStatus persists in the document file.
2026-01-31 04:26:06 -06:00
Zoe Forbes
98bd444221 Fix workbench init and spreadsheet syntax errors
- Use Gui.activateWorkbench() instead of calling Initialize() directly
  on dependent workbenches. Direct calls skip the C++ __Workbench__
  injection step, causing 'AssemblyWorkbench has no attribute
  __Workbench__' errors.
- Fix duplicated generator expression in spreadsheet_commands.py
- Fix missing else clause in spreadsheet_commands.py
2026-01-29 22:42:29 -06:00
Zoe Forbes
4627fea225 Fix workbench not loading 2026-01-28 17:07:31 -06:00
Zoe Forbes
e6f1de4ef8 add kindred integration docs 2026-01-26 23:06:14 -06:00
Zoe Forbes
2f03558a33 add spreadsheet commands 2026-01-26 06:34:59 -06:00
Zoe Forbes
a66dac7afc Improve datum behaviour 2026-01-24 23:24:39 -06:00
Zoe Forbes
981b15804e first commit 2026-01-24 15:16:09 -06:00