
App 模块是 FreeCAD 的 核心业务逻辑层 ,构建在 Base 层之上,定义了文档、属性、特征、表达式、事务等核心概念,是整个 FreeCAD 的"心脏"。App 模块约有 120+ 个源文件,是整个 FreeCAD 的灵魂所在,涵盖了 文档生命周期、属性系统、表达式引擎、事务/撤销、扩展机制、链接系统 等所有核心业务抽象。Base 层 : 提供"语言"——类型系统、Python绑定、序列化原语、设计模式基础;App 层 : 使用"语言"构建"产物"——文档、属性、特征、表达式、事务等业务概念

架构总览



类继承层次图



核心子系统详解

1. Application — 应用单例
- 全局访问 : App::GetApplication()
- 文档管理 : newDocument() / getDocument() / closeDocument()
- 参数管理 : GetUserParameter() / GetSystemParameter() → 管理 user.cfg / system.cfg
- 路径管理 : 通过 ApplicationDirectories 管理资源、宏、插件等路径
- 链接解析 : getLinksTo() / getLinkedObject() 管理对象间的引用关系
- 信号系统 : 文档打开/关闭、对象变更等全局信号
- 动态加载 : 按需加载 .pyd 模块文件

2. Document — 文档容器
- 继承: PropertyContainer — 文档自身也有属性(如 Comment、Company、Author、License)
- 对象管理: addObject() / removeObject() / getObject()
- 事务栈: 维护 Undo/Redo 事务历史
- 依赖图: 维护对象间的依赖关系,驱动重计算排序
- 重计算引擎: recompute() 按拓扑序重新执行所有标记为 Touched 的对象
- 状态管理: 30+ 种状态标志位(Closable, Restoring, Recomputing, ...)
- XML序列化: 通过 Save / Restore 将整个文档写入 .FCStd 文件

3. Property 属性系统
FreeCAD 最核心的抽象之一,所有可持久化数据都通过属性系统管理:

每个属性有 32 位的 StatusBits 控制行为:
- Touched — 是否需要重计算
- Immutable — 是否不可变
- ReadOnly / Hidden — 编辑器中只读/隐藏
- Transient — 不保存到文件
- Output — 输出属性(不触发父对象重计算)
- NoRecompute — 变更不触发重计算
- CopyOnChange — 变更时复制链接对象
4. DocumentObject — 文档对象 (★最核心的类)
class DocumentObject: public TransactionalObject
{
PropertyString Label; // 用户可见标签
PropertyString Label2; // 描述
PropertyExpressionEngine ExpressionEngine; // 表达式引擎
PropertyBool Visibility; // 可见性
// 信号
signal<void(...)> signalBeforeChange; // 属性即将变更
signal<void(...)> signalChanged; // 属性已变更
signal<void(...)> signalEarlyChanged; // 早期变更通知
// 核心方法
virtual DocumentObjectExecReturn* recompute(); // 重计算
virtual DocumentObjectExecReturn* execute(); // 执行
virtual PyObject* getPyObject(); // Python绑定
virtual const char* getViewProviderName(); // 关联ViewProvider跨层桥接
};
关键状态位 ( ObjectStatus ):


5. 事务系统 (Transaction)
- Transaction : 原子事务记录,包含对象的增/删/属性变更
- Undo/Redo : 通过 apply(doc, forward=true/false) 实现撤销/重做
- 跨文档事务 : 支持同一事务ID关联多个文档的操作,实现联合撤销
- AutoTransaction : RAII风格的自动事务,函数返回时自动提交
- 事务类型: addObjectNew , addObjectDel , addObjectChange , addOrRemoveProperty , renameProperty

6. 表达式系统 (Expression)
基于 LALR 解析器的表达式引擎,支持:
- 算术运算 : + , - , * , / , ^ , %
- 比较运算 : == , != , < , > , <= , >=
- 逻辑运算 : && , || , !
- 条件表达式 : test ? true_value : false_value
- 函数调用 : sin() , cos() , sqrt() , min() , max() , round() , abs() 等
- 属性引用 : Box.Length , Spreadsheet.A1 等跨对象引用
- 范围 : start:end:step 语法
- 单位支持 : 表达式结果自动处理单位转换

7. 扩展系统 (Extension)
FreeCAD 用 Extension 模式 代替多重继承:

一个对象可以注册多个扩展,例如 DocumentObjectGroup = DocumentObject + GroupExtension 。

8. 链接系统 (Link)
- 26+ 种 PropertyLink 变体 :
PropertyLink — 单个对象引用
PropertyLinkSub — 引用子元素(如面、边)
PropertyXLink — 跨文档链接
PropertyLinkList — 对象列表引用
PropertyLinkSubList — 子元素列表引用
- Link 对象 : App::Link — 创建对象的实例/引用副本
- LinkGroup : App::LinkGroup — 管理一组链接实例
- LinkElement : App::LinkElement — 引用单个子元素的链接
- 链接解析 : 通过 getLinkedObject(true) 递归解析到最终目标

依赖关系



数据流 / 重计算流程



核心设计原则

1. 属性即一切 : 所有持久化数据必须通过 Property 系统,确保类型安全、序列化、信号通知
2. Extension 替代多重继承 : 通过 ExtensionContainer + Extension 实现灵活的行为组合
3. 不可变 API : 属性变更通过 GIL + 事务 + 重计算引擎保证一致性
4. 依赖驱动 : 对象间通过链接属性建立依赖,自动推导重计算顺序
5. App/Gui 分离 : App 层完全无 GUI 依赖,通过 getViewProviderName() 实现弱引用
6. FeaturePython : 通过 FeaturePythonImp 将 Python 方法注入 C++ 对象,支持宏录制
夜雨聆风