Document & Object Model
Relevant source files
The following files were used as context for generating this wiki page:
The Document and Object Model forms the core architectural backbone of Parashell, managing the lifecycle, relationships, and data integrity of all entities within the application. The system is designed around a hierarchical structure where a Document serves as a container for multiple DocumentObject instances. This model facilitates complex CAD workflows by providing a centralized mechanism for dependency tracking, recomputation, and undo/redo operations.
At its heart, the model separates data representation from logic, utilizing a property-based system to handle object attributes. This allows for a flexible and extensible framework where new features can be added by deriving from base classes or using extensions. The synchronization of state across different components is maintained through an observer pattern, ensuring that changes in the document are propagated to interested listeners such as the GUI or external modules.
Document Architecture
The Document class is the primary management entity. It maintains a collection of objects and coordinates high-level operations such as saving, loading, and recomputing the document state. Documents are identified by unique internal names and labels, providing both programmatic and user-friendly references.
Key Components of Document
- Object Management: Tracks all
DocumentObjectinstances using a unique naming scheme. - Dependency Tracking: Managed through a Directed Acyclic Graph (DAG) logic to ensure objects are recomputed in the correct order.
- Transaction Management: Supports undo and redo functionality by capturing state changes within defined transaction blocks.
- Observation: Uses
DocumentObserverto notify external systems of document-level events like object addition, removal, or modification.
Sources: src/App/Document.cpp, src/App/DocumentObserver.cpp
Document Lifecycle Flow
The following diagram illustrates the typical lifecycle of a document from creation to object management.
The document ensures that any modification to an object triggers a dependency check. If an object "A" depends on object "B", changing "B" will mark "A" as touched and require its recomputation.
Sources: src/App/Document.cpp:50-150
DocumentObject Model
The DocumentObject is the base class for all entities that can exist within a document. It acts as a container for Property objects, which store the actual data (e.g., geometry, placement, parameters).
Features and Logic
- Extensions: Objects can be augmented with
Extensionclasses to provide additional functionality without deep inheritance hierarchies. - Status Flags: Internal flags track the state of the object, such as whether it is "touched" (needs recompute), "error" (failed last execution), or "hidden".
- Recomputation: The
execute()method is implemented by derived classes to perform the actual calculations based on current property values.
Sources: src/App/DocumentObject.cpp, src/App/CMakeLists.txt
DocumentObject Property Structure
| Component | Description |
|---|---|
| Properties | Key-value pairs defining the data of the object. |
| Extensions | Optional modules added at runtime to enhance behavior. |
| Labels | User-editable strings for identifying objects in the tree. |
| Status Flags | Bitmask indicating the current state (Touched, Error, etc.). |
Sources: src/App/DocumentObject.cpp:200-300
Observation and Synchronization
The model uses an observer pattern implemented via the DocumentObserver class. This mechanism decouples the core document logic from the user interface and other high-level modules.
Observer Notifications
Listeners derived from DocumentObserver receive callbacks for various events:
- onAdded: Triggered when a new object is inserted.
- onRemoved: Triggered before an object is deleted.
- onChange: Triggered when an object's property is modified.
- onDocumentRestored: Triggered after an undo/redo operation.
Sources: src/App/DocumentObserver.cpp:1-50
Document-Observer Sequence
This diagram shows how a property change propagates through the system.
Metadata and Package Management
The Metadata class handles the parsing and management of package-related information, often defined in package.xml files. This is used to define dependencies, versions, and licensing for document-related modules or workbenches.
Metadata Features
- XML Parsing: Uses Xerces-C to parse package definitions.
- Dependency Resolution: Validates if the current environment meets the requirements defined in the metadata (e.g., FreeCAD version, Python version).
- Version Comparison: Implements logic to compare semantic versions (Major.Minor.Patch).
| Field | Type | Description |
|---|---|---|
| Name | String | The unique identifier for the package. |
| Version | Meta::Version | Semantic versioning (e.g., 1.0.0). |
| Dependencies | Vector | List of required packages and version constraints. |
| Licenses | Vector | Licensing information (e.g., LGPL). |
Sources: src/App/Metadata.cpp:100-250, src/Mod/Test/TestData/content_items.xml
Version Comparison Logic
The system evaluates dependencies based on conditional operators:
version_lt: Less thanversion_lte: Less than or equalversion_eq: Exactly equalversion_gte: Greater than or equalversion_gt: Greater than
Sources: src/App/Metadata.cpp:450-500
Build System Integration
The underlying model is integrated into the application via a complex CMake configuration that generates Python bindings for C++ classes. This allows the Document and Object model to be fully accessible via the Python scripting console.
Key Build Targets
- FreeCADApp: The main shared library containing the document model.
- Pyi Generation: Metadata, Document, and DocumentObject headers are used to generate
.pyifiles for Python type hinting and interface definition. - Extensions: Extension modules like
OriginGroupExtensionandGeoFeatureare linked to provide specialized object types.
Sources: src/App/CMakeLists.txt:1-150
The Document & Object Model provides a robust framework for managing complex data hierarchies in Parashell. By combining property-based data storage, a DAG-driven recompute engine, and a flexible observer system, it ensures that data remains consistent and synchronized across all parts of the application. The inclusion of metadata management and deep integration with the Python API further extends the system's capabilities, making it a highly customizable core for CAD development.