feat(kc): foundation — Silo tree infrastructure, document observer, and base objects #37
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Build the core infrastructure that creates Silo metadata tree nodes in the FreeCAD document tree when a
.kcfile is opened. This is Phase 1 of the Silo Metadata Viewport specification — no viewer widgets yet, just the tree structure and lifecycle management.Background
When a
.kcfile is opened, thesilo/directory in the ZIP contains metadata files (manifest, metadata, history, etc.). These should appear as nodes in the document tree under a "Silo" group, below the standard geometry objects. Currently,kc_format.pypreservessilo/entries across saves but does not parse or expose them as document objects.Scope
New files
src/Mod/Create/silo_objects.pySiloViewerObject—App::FeaturePythonproxy with transient properties (SiloPath,ContentType,RawContent). All properties useProp_Transient(flag2) so nothing is written toDocument.xml.__getstate__returnsNone.src/Mod/Create/silo_viewproviders.pySiloViewerViewProvider— controls tree icon viagetIcon(), context menu viasetupContextMenu(), anddoubleClicked()(stub returningFalsefor now).src/Mod/Create/silo_tree.pySiloTreeBuilder— readssilo/entries from a ZIP file, createsApp::DocumentObjectGroup"Silo" with conditional child objects based on whichsilo/entries exist. Handles stale stub cleanup on load.src/Mod/Create/silo_document.pySiloDocumentObserver— hooksslotCreatedDocument+QTimer.singleShot(0)to create tree after restore. Also hooksslotActivateDocumentas fallback guard.Modified files
src/Mod/Create/kc_format.pypre_reinjectcallback hook so the viewport module can updatesilo/cache entries before they are written back to the ZIP on save.src/Mod/Create/InitGui.pySiloDocumentObservervia deferredQTimerafterkc_formatregistration (observer ordering matters for save-back).src/Mod/Create/CMakeLists.txt.pyfiles to the install list.Tree structure
Key technical decisions
Transient properties: All
SiloViewerObjectproperties are created withProp_Transient(value2) viaobj.addProperty("App::PropertyString", "SiloPath", "Silo", "doc", 2). This prevents property content from being written toDocument.xml. Minimal stubs (name + type) still appear — these are harmless and cleaned on next load.Restore hook: Python observer API lacks
slotFinishRestoreDocument. UseslotCreatedDocument(doc)— checkdoc.FileNameends with.kc, thenQTimer.singleShot(0, lambda: _build_tree(doc))to defer to next event loop tick (document fully loaded by then).slotActivateDocumentserves as fallback for documents opened before observer registration.Save-back coordination:
kc_format.pycachessilo/entries inslotStartSaveDocumentand reinjects inslotFinishSaveDocument. The newpre_reinjecthook is called between cache and reinject, allowing modified object content to overwrite cache entries before ZIP write.Stale stub cleanup: On restore,
SiloTreeBuilderremoves any existing "Silo" group and children before creating fresh objects fromsilo/data. This handles the edge case of.kcfiles with leftover XML stubs.Acceptance criteria
.kcwithsilo/manifest.jsoncreates a "Silo" group with a "Manifest" child in the tree.kcwith multiplesilo/entries creates the correct conditional tree nodes.kcwith onlysilo/manifest.jsoncreates only Silo > Manifest (no empty groups).kcrecreates the tree identicallyDocument.xmlin the saved ZIP contains only minimal stubs for Silo objects (no property content).fcstdproduces no Silo tree objectsFalse).kcin vanilla FreeCAD produces no errors (stubs log harmless warnings)Dependencies
kc_format.pyinfrastructureReferences
docs/KC_SPECIFICATION.md§3 (Document Tree Structure), §4 (Base Classes), §6.1 (Creation)docs/SILO_VIEWPORT_PLAN.mdPhase 1