opendataeditor icon indicating copy to clipboard operation
opendataeditor copied to clipboard

ODE plug-ins - Research

Open romicolman opened this issue 8 months ago • 0 comments

This ticket is to investigate what would we need to do, from a technical point of view, to allow the implementation of plug-ins into de ODE.


Plugin Systems

There is a simple way of doing it in which we could load a Plugin class from a path (similar to AI Models) and execute the logic. Something like this could do the trick:

Loading the plugins

We could load all the plugins after the initialization of the application with a simple function to iterate a Plugin path and import it.

import importlib.util
import pathlib

# Plugin loader
def load_plugins(plugins_dir: pathlib.Path):
    """Read PLUGINS_PATH and load all the Plugin objects from the .py files."""
    plugins = []
    for file in plugins_dir.glob("*.py"):
        module_name = file.stem
        spec = importlib.util.spec_from_file_location(module_name, file)
        module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(module)
        # Open Plugin
        if hasattr(module, "Plugin"):
            plugin = module.Plugin()
        # Validate Plugin
        if not hasattr(plugin, "name"):
            print(f"{plugin} does not have a name, it will not be loaded.")
            continue
        if not hasattr(plugin, "action"):
            print(f"{plugin} does not have an action attribute, it will not be loaded.")
            continue
        plugins.append(module.Plugin())
    return plugins


class MainWindow(QMainWindow):

    def __init__(self):
        # Other init steps

        self._menu_bar()

        # Load Plugins
        self.plugins = load_plugins(paths.PLUGINS_PATH)
        for plugin in self.plugins:
            self.menu_plugins.addAction(plugin.action)

   def _menu_bar(self):
        # Tools
        self.menu_plugins = QMenu()
        self.menuBar().addMenu(self.menu_plugins)

Plugin classes

In order to develop a plugin there will be need to define a simple Plugin class inside the Python module with an interface we propose and validate. Something like this:

from PySide6.QtWidgets import QMessageBox
from PySide6.QtGui import QAction


class Plugin:
    def __init__(self):
        super().__init__()
        self.name = "Example Plugin"
        self.action = QAction("Example Plugin Action")
        self.action.triggered.connect(self.handle_action)

    def handle_action(self):
        QMessageBox.information(None, "Example Plugin", "It works!")

Small Demo

https://github.com/user-attachments/assets/e9991ff5-ecff-4ec9-b663-1b95dc65c952

Considerations

  1. We could have a PluginBase class that users can extend, but that requires an ODE package for people to work with. I think it is a little bit overkill as a first step. A clear documentation on how to develop it should be enough.
  2. Hooking functions defined in Python modules is quite straightforward. I guess the challenge will be in how to distribute the plugins and how organizations can distribute to its own users as well.

romicolman avatar May 12 '25 07:05 romicolman