From af9837abf18355e6095270e69e4e2182f8e5ebe1 Mon Sep 17 00:00:00 2001 From: forbes Date: Fri, 13 Feb 2026 14:06:36 -0600 Subject: [PATCH] cherry-pick #5: theme QSS refinements (eb80c07f57a) Resolved conflicts: kept HEAD versions of QSS (has later refinements), InitGui.py (has newer origin architecture), and silo submodule. --- docs/REPOSITORY_STATE.md | 332 ++++++++++++++++++ .../KindredCreate/KindredCreate.qss | 27 +- .../KindredCreate/KindredCreate.qss | 82 ++++- 3 files changed, 427 insertions(+), 14 deletions(-) create mode 100644 docs/REPOSITORY_STATE.md diff --git a/docs/REPOSITORY_STATE.md b/docs/REPOSITORY_STATE.md new file mode 100644 index 0000000000..79690d9e68 --- /dev/null +++ b/docs/REPOSITORY_STATE.md @@ -0,0 +1,332 @@ +# Kindred Create Repository State Report + +**Generated:** 2026-01-31 +**Branch:** main +**Parent repo:** create-0070 @ `364a7057ef` +**Submodules:** +- ztools @ `8d1f195` (ztools-0065, main) +- silo @ `c778825` (silo-0062, main) + +--- + +## Recent Changes (This Session) + +### 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 + +``` +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() +``` + +--- + +## Submodule Status + +### ztools (ztools-0065) + +| 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 | + +**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}` + +**Datum types supported**: offset_from_face, offset_from_plane, midplane, +3_points, normal_to_edge, angled, tangent_to_cylinder + +### silo (silo-0062) + +| 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 | + +**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` + +**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. + +**BOM API methods** (new): +- `get_bom()`, `get_bom_expanded()`, `get_bom_where_used()` +- `add_bom_entry()`, `update_bom_entry()`, `delete_bom_entry()` + +--- + +## Potential 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. + +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. + +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. + +### 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. + +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. + +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. + +### 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. + +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. + +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. + +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", ...)`. + +--- + +## Feature Stubs and TODOs + +### From silo REPOSITORY_STATUS + +| 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 | — | +| CSRF protection | Not implemented | Web UI only | +| CSV import transaction rollback | Not implemented | `bom_handlers.go` | + +### From 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` | + +### From Create integration plan + +| Phase | Feature | Status | +|-------|---------|--------| +| 1 | Addon auto-loading | Done (`src/Mod/Create/InitGui.py`) | +| 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 | + +--- + +## File Change Summary (Uncommitted) + +### Parent repo (create-0070) + +| 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 | + +### ztools submodule (committed + pushed) + +| File | Change | +|------|--------| +| `ztools/InitGui.py` | Added `_ZToolsPartDesignManipulator` | +| `CatppuccinMocha/CatppuccinMocha.qss` | Synced with canonical KindredCreate.qss | + +### 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. diff --git a/resources/preferences/KindredCreate/KindredCreate.qss b/resources/preferences/KindredCreate/KindredCreate.qss index 6ce5343d31..e96a6fc061 100644 --- a/resources/preferences/KindredCreate/KindredCreate.qss +++ b/resources/preferences/KindredCreate/KindredCreate.qss @@ -247,8 +247,9 @@ QDockWidget { QDockWidget::title { background-color: #181825; color: #cdd6f4; - padding: 6px; + padding: 8px 6px; border-bottom: 1px solid #313244; + min-height: 18px; } QDockWidget::close-button, @@ -757,6 +758,16 @@ QTreeView::branch:selected { background-color: #45475a; } +QTreeView::branch:has-children:!has-siblings:closed, +QTreeView::branch:closed:has-children:has-siblings { + image: url(qss:images_dark-light/branch_closed.svg); +} + +QTreeView::branch:open:has-children:!has-siblings, +QTreeView::branch:open:has-children:has-siblings { + image: url(qss:images_dark-light/branch_open.svg); +} + /* ============================================================================= List View ============================================================================= */ @@ -830,6 +841,7 @@ QHeaderView::section { border-right: 1px solid #45475a; border-bottom: 1px solid #45475a; padding: 6px 8px; + min-height: 20px; } QHeaderView::section:hover { @@ -1103,7 +1115,8 @@ QSint--ActionGroup QToolButton { color: #cdd6f4; border: none; border-radius: 4px; - padding: 6px; + padding: 8px 6px; + min-height: 18px; } QSint--ActionGroup QToolButton:hover { @@ -1151,6 +1164,16 @@ SpreadsheetGui--SheetTableView QHeaderView::section { padding: 4px; } +/* Spreadsheet cell editor - reduce padding for better text visibility */ +SpreadsheetGui--SheetTableView QLineEdit { + background-color: #313244; + color: #cdd6f4; + border: 1px solid #cba6f7; + border-radius: 0px; + padding: 1px 2px; + margin: 0px; +} + /* Python Console */ Gui--PythonConsole { background-color: #11111b; diff --git a/src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss b/src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss index 6ce5343d31..7d7d8ae502 100644 --- a/src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss +++ b/src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss @@ -247,8 +247,9 @@ QDockWidget { QDockWidget::title { background-color: #181825; color: #cdd6f4; - padding: 6px; + padding: 8px 6px; border-bottom: 1px solid #313244; + min-height: 18px; } QDockWidget::close-button, @@ -465,13 +466,35 @@ QSpinBox::down-button:pressed, QDoubleSpinBox::down-button:pressed { } QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { - width: 8px; - height: 8px; + width: 0px; + height: 0px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-bottom: 6px solid #cdd6f4; +} + +QSpinBox::up-arrow:hover, QDoubleSpinBox::up-arrow:hover { + border-bottom-color: #f5e0dc; +} + +QSpinBox::up-arrow:disabled, QDoubleSpinBox::up-arrow:disabled { + border-bottom-color: #6c7086; } QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { - width: 8px; - height: 8px; + width: 0px; + height: 0px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 6px solid #cdd6f4; +} + +QSpinBox::down-arrow:hover, QDoubleSpinBox::down-arrow:hover { + border-top-color: #f5e0dc; +} + +QSpinBox::down-arrow:disabled, QDoubleSpinBox::down-arrow:disabled { + border-top-color: #6c7086; } /* ============================================================================= @@ -516,8 +539,15 @@ QComboBox::drop-down:hover { } QComboBox::down-arrow { - width: 10px; - height: 10px; + width: 0px; + height: 0px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 6px solid #cdd6f4; +} + +QComboBox::down-arrow:disabled { + border-top-color: #6c7086; } QComboBox QAbstractItemView { @@ -757,6 +787,16 @@ QTreeView::branch:selected { background-color: #45475a; } +QTreeView::branch:has-children:!has-siblings:closed, +QTreeView::branch:closed:has-children:has-siblings { + image: url(qss:images_dark-light/branch_closed.svg); +} + +QTreeView::branch:open:has-children:!has-siblings, +QTreeView::branch:open:has-children:has-siblings { + image: url(qss:images_dark-light/branch_open.svg); +} + /* ============================================================================= List View ============================================================================= */ @@ -830,6 +870,7 @@ QHeaderView::section { border-right: 1px solid #45475a; border-bottom: 1px solid #45475a; padding: 6px 8px; + min-height: 20px; } QHeaderView::section:hover { @@ -842,13 +883,19 @@ QHeaderView::section:checked { } QHeaderView::down-arrow { - width: 10px; - height: 10px; + width: 0px; + height: 0px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 6px solid #cdd6f4; } QHeaderView::up-arrow { - width: 10px; - height: 10px; + width: 0px; + height: 0px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 6px solid #cdd6f4; } /* ============================================================================= @@ -1103,7 +1150,8 @@ QSint--ActionGroup QToolButton { color: #cdd6f4; border: none; border-radius: 4px; - padding: 6px; + padding: 8px 6px; + min-height: 18px; } QSint--ActionGroup QToolButton:hover { @@ -1151,6 +1199,16 @@ SpreadsheetGui--SheetTableView QHeaderView::section { padding: 4px; } +/* Spreadsheet cell editor - reduce padding for better text visibility */ +SpreadsheetGui--SheetTableView QLineEdit { + background-color: #313244; + color: #cdd6f4; + border: 1px solid #cba6f7; + border-radius: 0px; + padding: 1px 2px; + margin: 0px; +} + /* Python Console */ Gui--PythonConsole { background-color: #11111b;