extending plugins to load pre or post app start
This commit is contained in:
parent
cc5966dab2
commit
62debf9ece
|
@ -1,2 +1,31 @@
|
||||||
### Note
|
### Note
|
||||||
Copy the example and rename it to your desired name. The Main class and passed in arguments are required. You don't necessarily need to use the passed in socket_id or event_system.
|
Copy the example and rename it to your desired name. Plugins define a ui target slot with the 'ui_target' requests data but don't have to if not directly interacted with.
|
||||||
|
Plugins must have a run method defined; though, you do not need to necessarily do anything within it. The run method implies that the passed in event system or other data is ready for the plugin to use.
|
||||||
|
|
||||||
|
|
||||||
|
### Manifest Example (All are required even if empty.)
|
||||||
|
```
|
||||||
|
class Manifest:
|
||||||
|
name: str = "Example Plugin"
|
||||||
|
author: str = "John Doe"
|
||||||
|
version: str = "0.0.1"
|
||||||
|
support: str = ""
|
||||||
|
requests: {} = {
|
||||||
|
'pass_ui_objects': ["plugin_control_list"],
|
||||||
|
'pass_events': "true",
|
||||||
|
'bind_keys': []
|
||||||
|
}
|
||||||
|
pre_launch: bool = False
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Requests
|
||||||
|
```
|
||||||
|
requests: {} = {
|
||||||
|
'pass_events': "true", # If empty or not present will be ignored.
|
||||||
|
"pass_ui_objects": [""], # Request reference to a UI component. Will be passed back as array to plugin.
|
||||||
|
'bind_keys': [f"{name}||send_message:<Control>f"],
|
||||||
|
f"{name}||do_save:<Control>s"] # Bind keys with method and key pare using list. Must pass "name" like shown with delimiter to its right.
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
PyGObject
|
PyGObject==3.40.1
|
||||||
pygobject-stubs --no-cache-dir --config-settings=config=Gtk3,Gdk3,Soup2
|
pygobject-stubs --no-cache-dir --config-settings=config=Gtk3,Gdk3,Soup2
|
||||||
pyxdg
|
setproctitle==1.2.2
|
||||||
setproctitle
|
pyxdg==0.27
|
||||||
sqlmodel
|
psutil==5.8.0
|
||||||
|
pycryptodome==3.20.0
|
||||||
|
sqlmodel==0.0.19
|
|
@ -28,7 +28,10 @@ class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
|
||||||
self._load_controllers()
|
self._load_controllers()
|
||||||
|
|
||||||
if args.no_plugins == "false":
|
if args.no_plugins == "false":
|
||||||
self.plugins.launch_plugins()
|
self.plugins_controller.pre_launch_plugins()
|
||||||
|
|
||||||
|
if args.no_plugins == "false":
|
||||||
|
self.plugins_controller.post_launch_plugins()
|
||||||
|
|
||||||
for file in settings_manager.get_starting_files():
|
for file in settings_manager.get_starting_files():
|
||||||
event_system.emit("post-file-to-ipc", file)
|
event_system.emit("post-file-to-ipc", file)
|
||||||
|
|
|
@ -17,6 +17,7 @@ class BaseControllerData:
|
||||||
def setup_controller_data(self) -> None:
|
def setup_controller_data(self) -> None:
|
||||||
self.window = settings_manager.get_main_window()
|
self.window = settings_manager.get_main_window()
|
||||||
self.builder = BuilderWrapper()
|
self.builder = BuilderWrapper()
|
||||||
|
self.plugins_controller = PluginsController()
|
||||||
|
|
||||||
self.base_container = None
|
self.base_container = None
|
||||||
self.was_midified_key = False
|
self.was_midified_key = False
|
||||||
|
@ -25,7 +26,7 @@ class BaseControllerData:
|
||||||
self.alt_down = False
|
self.alt_down = False
|
||||||
|
|
||||||
self._load_glade_file()
|
self._load_glade_file()
|
||||||
self.plugins = PluginsController()
|
|
||||||
|
|
||||||
def collect_files_dirs(self, args, unknownargs):
|
def collect_files_dirs(self, args, unknownargs):
|
||||||
files = []
|
files = []
|
||||||
|
|
|
@ -22,6 +22,7 @@ class Plugin:
|
||||||
support: str = None
|
support: str = None
|
||||||
requests:{} = None
|
requests:{} = None
|
||||||
reference: type = None
|
reference: type = None
|
||||||
|
pre_launch: bool = False
|
||||||
|
|
||||||
|
|
||||||
class ManifestProcessor:
|
class ManifestProcessor:
|
||||||
|
@ -46,23 +47,25 @@ class ManifestProcessor:
|
||||||
plugin.support = self._manifest["support"]
|
plugin.support = self._manifest["support"]
|
||||||
plugin.requests = self._manifest["requests"]
|
plugin.requests = self._manifest["requests"]
|
||||||
|
|
||||||
|
if "pre_launch" in self._manifest.keys():
|
||||||
|
plugin.pre_launch = True if self._manifest["pre_launch"] == "true" else False
|
||||||
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
||||||
def get_loading_data(self):
|
def get_loading_data(self):
|
||||||
loading_data = {}
|
loading_data = {}
|
||||||
requests = self._plugin.requests
|
requests = self._plugin.requests
|
||||||
keys = requests.keys()
|
|
||||||
|
|
||||||
if "pass_events" in keys:
|
if "pass_events" in requests:
|
||||||
if requests["pass_events"] in ["true"]:
|
if requests["pass_events"] in ["true"]:
|
||||||
loading_data["pass_events"] = True
|
loading_data["pass_events"] = True
|
||||||
|
|
||||||
if "bind_keys" in keys:
|
if "pass_ui_objects" in requests:
|
||||||
if isinstance(requests["bind_keys"], list):
|
|
||||||
loading_data["bind_keys"] = requests["bind_keys"]
|
|
||||||
|
|
||||||
if "pass_ui_objects" in keys:
|
|
||||||
if isinstance(requests["pass_ui_objects"], list):
|
if isinstance(requests["pass_ui_objects"], list):
|
||||||
loading_data["pass_ui_objects"] = [ self._builder.get_object(obj) for obj in requests["pass_ui_objects"] ]
|
loading_data["pass_ui_objects"] = [ self._builder.get_object(obj) for obj in requests["pass_ui_objects"] ]
|
||||||
|
|
||||||
|
if "bind_keys" in requests:
|
||||||
|
if isinstance(requests["bind_keys"], list):
|
||||||
|
loading_data["bind_keys"] = requests["bind_keys"]
|
||||||
|
|
||||||
return self._plugin, loading_data
|
return self._plugin, loading_data
|
||||||
|
|
|
@ -10,6 +10,7 @@ from os.path import isdir
|
||||||
import gi
|
import gi
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GLib
|
||||||
from gi.repository import Gio
|
from gi.repository import Gio
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
@ -35,11 +36,23 @@ class PluginsController:
|
||||||
|
|
||||||
self._plugins_dir_watcher = None
|
self._plugins_dir_watcher = None
|
||||||
self._plugin_collection = []
|
self._plugin_collection = []
|
||||||
|
self._plugin_manifests = {}
|
||||||
|
|
||||||
|
self._load_manifests()
|
||||||
|
|
||||||
|
|
||||||
def launch_plugins(self) -> None:
|
def _load_manifests(self):
|
||||||
|
logger.info(f"Loading manifests...")
|
||||||
|
|
||||||
|
for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]:
|
||||||
|
manifest = ManifestProcessor(path, self._builder)
|
||||||
|
self._plugin_manifests[path] = {
|
||||||
|
"path": path,
|
||||||
|
"folder": folder,
|
||||||
|
"manifest": manifest
|
||||||
|
}
|
||||||
|
|
||||||
self._set_plugins_watcher()
|
self._set_plugins_watcher()
|
||||||
self.load_plugins()
|
|
||||||
|
|
||||||
def _set_plugins_watcher(self) -> None:
|
def _set_plugins_watcher(self) -> None:
|
||||||
self._plugins_dir_watcher = Gio.File.new_for_path(self._plugins_path) \
|
self._plugins_dir_watcher = Gio.File.new_for_path(self._plugins_path) \
|
||||||
|
@ -52,21 +65,47 @@ class PluginsController:
|
||||||
Gio.FileMonitorEvent.MOVED_OUT]:
|
Gio.FileMonitorEvent.MOVED_OUT]:
|
||||||
self.reload_plugins(file)
|
self.reload_plugins(file)
|
||||||
|
|
||||||
def load_plugins(self, file: str = None) -> None:
|
def pre_launch_plugins(self) -> None:
|
||||||
logger.info(f"Loading plugins...")
|
logger.info(f"Loading pre-launch plugins...")
|
||||||
|
plugin_manifests: {} = {}
|
||||||
|
|
||||||
|
for key in self._plugin_manifests:
|
||||||
|
target_manifest = self._plugin_manifests[key]["manifest"]
|
||||||
|
if target_manifest.is_pre_launch():
|
||||||
|
plugin_manifests[key] = self._plugin_manifests[key]
|
||||||
|
|
||||||
|
self._load_plugins(plugin_manifests, is_pre_launch = True)
|
||||||
|
|
||||||
|
def post_launch_plugins(self) -> None:
|
||||||
|
logger.info(f"Loading post-launch plugins...")
|
||||||
|
plugin_manifests: {} = {}
|
||||||
|
|
||||||
|
for key in self._plugin_manifests:
|
||||||
|
target_manifest = self._plugin_manifests[key]["manifest"]
|
||||||
|
if not target_manifest.is_pre_launch():
|
||||||
|
plugin_manifests[key] = self._plugin_manifests[key]
|
||||||
|
|
||||||
|
self._load_plugins(plugin_manifests)
|
||||||
|
|
||||||
|
def _load_plugins(self, plugin_manifests: {} = {}, is_pre_launch: bool = False) -> None:
|
||||||
parent_path = os.getcwd()
|
parent_path = os.getcwd()
|
||||||
|
|
||||||
for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]:
|
for key in plugin_manifests:
|
||||||
|
target_manifest = plugin_manifests[key]
|
||||||
|
path, folder, manifest = target_manifest["path"], target_manifest["folder"], target_manifest["manifest"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
target = join(path, "plugin.py")
|
target = join(path, "plugin.py")
|
||||||
manifest = ManifestProcessor(path, self._builder)
|
|
||||||
|
|
||||||
if not os.path.exists(target):
|
if not os.path.exists(target):
|
||||||
raise InvalidPluginException("Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load...")
|
raise InvalidPluginException("Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load...")
|
||||||
|
|
||||||
plugin, loading_data = manifest.get_loading_data()
|
plugin, loading_data = manifest.get_loading_data()
|
||||||
module = self.load_plugin_module(path, folder, target)
|
module = self.load_plugin_module(path, folder, target)
|
||||||
|
|
||||||
|
if is_pre_launch:
|
||||||
self.execute_plugin(module, plugin, loading_data)
|
self.execute_plugin(module, plugin, loading_data)
|
||||||
|
else:
|
||||||
|
GLib.idle_add(self.execute_plugin, *(module, plugin, loading_data))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info(f"Malformed Plugin: Not loading -->: '{folder}' !")
|
logger.info(f"Malformed Plugin: Not loading -->: '{folder}' !")
|
||||||
logger.debug("Trace: ", traceback.print_exc())
|
logger.debug("Trace: ", traceback.print_exc())
|
||||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Loading…
Reference in New Issue