Skip to content

Allow Plugins to Register Actions in Application Menu#3021

Draft
Copilot wants to merge 3 commits intodevelopfrom
copilot/add-dynamic-menu-entry
Draft

Allow Plugins to Register Actions in Application Menu#3021
Copilot wants to merge 3 commits intodevelopfrom
copilot/add-dynamic-menu-entry

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 28, 2026

Removes the menu.json file-based approach for plugin menu registration in favor of a Python API where plugins register callable actions directly. This eliminates the need for any JSON file and enables plugins to attach real Python functions (not just URLs) to menu entries.

Description

Plugins now register menu actions programmatically via a register(plugin) hook or the meshroom.core.registerMenuAction() convenience function. The registered callables are stored with a UUID and invoked through a Qt slot when the user triggers the menu item.

Features list

  • Plugin.addMenuAction(label, function, tooltip) — Meshroom-side API for registering a Python callable as a menu entry
  • NodePluginManager.executeMenuAction(actionId) — resolves and calls a registered action by UUID
  • meshroom.core.registerMenuAction() — convenience wrapper using thread-local context, usable at module level during first import
  • register(plugin) hook — called by Meshroom on every plugin load (bypasses Python module caching), recommended pattern
  • MeshroomApp.executePluginMenuAction(actionId) QML slot replaces URL-opening logic in the Plugins menu

Implementation remarks

Plugin authoring pattern — define a register(plugin) function in the package's __init__.py:

# myplugin/__init__.py
import webbrowser

def register(plugin):
    plugin.addMenuAction("Open Docs", lambda: webbrowser.open("https://..."), "Opens documentation")
    plugin.addMenuAction("Run Tool", my_tool_function)

Meshroom calls register(plugin) explicitly after each plugin load, so it works correctly even when Python has already cached the module (which would silently skip module-level registerMenuAction() calls on subsequent loads). The registerMenuAction() convenience path is still supported for first-load scenarios.

getAllMenuActions() intentionally excludes the callable from the QML model — only label, tooltip, actionId, and pluginName are exposed. QML calls back into Python via the executePluginMenuAction slot which resolves the callable by UUID.

Original prompt

Add a dynamic entry in the general menu (file, edit, etc), so plugins could add custom elements in the menu dynamically.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

- Add Plugin.loadMenuActions() to load actions from menu.json
- Add Plugin.menuActions property
- Add NodePluginManager.getAllMenuActions() to aggregate from all plugins
- Add MeshroomApp.pluginMenuActions property (QML-accessible)
- Reload menu actions and emit signal on plugin reload
- Add Plugins menu in Application.qml populated dynamically
- Add tests and sample menu.json for test plugins

Co-authored-by: fabiencastan <153585+fabiencastan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add dynamic entry to general menu for plugins Add dynamic plugin menu entries to the application menu bar Feb 28, 2026
Copilot stopped work on behalf of fabiencastan due to an error February 28, 2026 07:35
…approach

Co-authored-by: fabiencastan <153585+fabiencastan@users.noreply.github.com>
Copilot AI changed the title Add dynamic plugin menu entries to the application menu bar Replace menu.json plugin registration with a Python callable API Feb 28, 2026
@fabiencastan fabiencastan changed the title Replace menu.json plugin registration with a Python callable API Allow Plugins to Register Actions in Application Menu Mar 2, 2026
@Alxiice Alxiice closed this Mar 2, 2026
@Alxiice Alxiice deleted the copilot/add-dynamic-menu-entry branch March 2, 2026 14:50
@Alxiice Alxiice restored the copilot/add-dynamic-menu-entry branch March 2, 2026 14:56
@Alxiice Alxiice reopened this Mar 2, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 2, 2026

Codecov Report

❌ Patch coverage is 91.81818% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.80%. Comparing base (bf28c8d) to head (3f5032d).
⚠️ Report is 15 commits behind head on develop.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
meshroom/core/__init__.py 61.11% 7 Missing ⚠️
tests/plugins/meshroom/pluginA/__init__.py 75.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3021      +/-   ##
===========================================
+ Coverage    82.35%   82.80%   +0.45%     
===========================================
  Files           69       71       +2     
  Lines         9367     9522     +155     
===========================================
+ Hits          7714     7885     +171     
+ Misses        1653     1637      -16     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants