docs(c++): CommandOrigin commands (Commit/Pull/Push/Info/BOM)

Document the five origin commands: activation pattern (ownership lookup
via findOwningOrigin, capability gate check), command table with IDs,
shortcuts, icons and capability gates, eType flags for undo integration,
registration in CreateOriginCommands(), and the full dispatch call chain
from C++ through FileOriginPython bridge to Python SiloOrigin.

Closes #134
This commit is contained in:
2026-02-10 07:59:45 -06:00
parent 98218661d0
commit 633bef6b18
2 changed files with 143 additions and 0 deletions

View File

@@ -51,3 +51,4 @@
- [FileOrigin Interface](./reference/cpp-file-origin.md)
- [OriginManager](./reference/cpp-origin-manager.md)
- [CommandOrigin](./reference/cpp-command-origin.md)

View File

@@ -0,0 +1,142 @@
# CommandOrigin — File Menu Origin Commands
> **Source:** `src/Gui/CommandOrigin.cpp`
> **Namespace:** `Gui`
> **Registration:** `Gui::CreateOriginCommands()`
Five FreeCAD commands expose the extended operations defined by
[FileOrigin](./cpp-file-origin.md). Each command follows the same
pattern: look up the owning origin for the active document via
[OriginManager](./cpp-origin-manager.md), check whether that origin
advertises the required capability, and dispatch to the corresponding
`FileOrigin` virtual method.
## Command Table
| Command ID | Menu Text | Shortcut | Capability Gate | Dispatches To | Icon |
|-----------|-----------|----------|-----------------|---------------|------|
| `Origin_Commit` | &Commit | `Ctrl+Shift+C` | `supportsRevisions()` | `commitDocument(doc)` | `silo-commit` |
| `Origin_Pull` | &Pull | `Ctrl+Shift+P` | `supportsRevisions()` | `pullDocument(doc)` | `silo-pull` |
| `Origin_Push` | Pu&sh | `Ctrl+Shift+U` | `supportsRevisions()` | `pushDocument(doc)` | `silo-push` |
| `Origin_Info` | &Info | — | `supportsPartNumbers()` | `showInfo(doc)` | `silo-info` |
| `Origin_BOM` | &Bill of Materials | — | `supportsBOM()` | `showBOM(doc)` | `silo-bom` |
All commands belong to the `"File"` group.
## Activation Pattern
Every command shares the same `isActive()` / `activated()` structure:
```
isActive():
doc = App::GetApplication().getActiveDocument()
if doc is null → return false
origin = OriginManager::instance()->findOwningOrigin(doc)
return origin != null AND origin->supportsXxx()
activated():
doc = App::GetApplication().getActiveDocument()
if doc is null → return
origin = OriginManager::instance()->findOwningOrigin(doc)
if origin AND origin->supportsXxx():
origin->xxxDocument(doc)
```
This means the commands **automatically grey out** in the menu when:
- No document is open.
- The active document is owned by an origin that doesn't support the
capability (e.g., a local document has no Commit/Pull/Push).
For a local-only document, all five commands are inactive. When a Silo
document is active, all five become available because
[SiloOrigin](../reference/cpp-file-origin.md) returns `true` for
`supportsRevisions()`, `supportsBOM()`, and `supportsPartNumbers()`.
## Ownership Resolution
The commands use `findOwningOrigin(doc)` rather than `currentOrigin()`
because the active document may belong to a **different** origin than the
one currently selected in the toolbar. For example, a user might have
Silo selected as the current origin but be viewing a local document in
another tab — the commands correctly detect that the local document has
no revision support.
See [OriginManager § Document-Origin Resolution](./cpp-origin-manager.md#document-origin-resolution)
for the full lookup algorithm.
## Command Type Flags
| Command | `eType` | Meaning |
|---------|---------|---------|
| Commit | `AlterDoc` | Marks document as modified (undo integration) |
| Pull | `AlterDoc` | Marks document as modified |
| Push | `AlterDoc` | Marks document as modified |
| Info | `0` | Read-only, no undo integration |
| BOM | `0` | Read-only, no undo integration |
`AlterDoc` commands participate in FreeCAD's transaction/undo system.
Info and BOM are view-only dialogs that don't modify the document.
## Registration
All five commands are registered in a single function called during
application startup:
```cpp
void Gui::CreateOriginCommands()
{
CommandManager& rcCmdMgr = Application::Instance->commandManager();
rcCmdMgr.addCommand(new OriginCmdCommit());
rcCmdMgr.addCommand(new OriginCmdPull());
rcCmdMgr.addCommand(new OriginCmdPush());
rcCmdMgr.addCommand(new OriginCmdInfo());
rcCmdMgr.addCommand(new OriginCmdBOM());
}
```
This is called from the Gui module initialization alongside other
command registration functions (`CreateDocCommands`,
`CreateMacroCommands`, etc.).
## What the Commands Actually Do
The C++ commands are **thin dispatchers** — they contain no business
logic. The actual work happens in the origin implementation:
- **Local origin** — all five extended methods are no-ops (defaults from
`FileOrigin` base class return `false` or do nothing).
- **Silo origin** (Python) — each method delegates to the corresponding
`Silo_*` FreeCAD command:
| C++ dispatch | Python SiloOrigin method | Delegates to |
|-------------|-------------------------|--------------|
| `commitDocument()` | `SiloOrigin.commitDocument()` | `Silo_Commit` command |
| `pullDocument()` | `SiloOrigin.pullDocument()` | `Silo_Pull` command |
| `pushDocument()` | `SiloOrigin.pushDocument()` | `Silo_Push` command |
| `showInfo()` | `SiloOrigin.showInfo()` | `Silo_Info` command |
| `showBOM()` | `SiloOrigin.showBOM()` | `Silo_BOM` command |
The call chain for a Commit, for example:
```
User clicks File > Commit (or Ctrl+Shift+C)
→ OriginCmdCommit::activated()
→ OriginManager::findOwningOrigin(doc) [C++]
→ SiloOrigin.ownsDocument(doc) [Python via bridge]
→ origin->commitDocument(doc) [C++ virtual]
→ FileOriginPython::commitDocument(doc) [bridge]
→ SiloOrigin.commitDocument(doc) [Python]
→ FreeCADGui.runCommand("Silo_Commit") [Python command]
```
## See Also
- [FileOrigin Interface](./cpp-file-origin.md) — defines the virtual
methods these commands dispatch to
- [OriginManager](./cpp-origin-manager.md) — provides
`findOwningOrigin()` used by every command
- [FileOriginPython](./cpp-file-origin-python.md) — bridges the dispatch
from C++ to Python origins
- [SiloOrigin adapter](./cpp-file-origin.md) — Python implementation
that handles the actual Silo operations