diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index b7f378778e..a65e44ad90 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -51,3 +51,4 @@ - [FileOrigin Interface](./reference/cpp-file-origin.md) - [OriginManager](./reference/cpp-origin-manager.md) +- [CommandOrigin](./reference/cpp-command-origin.md) diff --git a/docs/src/reference/cpp-command-origin.md b/docs/src/reference/cpp-command-origin.md new file mode 100644 index 0000000000..f895328554 --- /dev/null +++ b/docs/src/reference/cpp-command-origin.md @@ -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