opendataeditor
opendataeditor copied to clipboard
ODE plug-ins - Research
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
- We could have a
PluginBaseclass 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. - 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.