Bringing to latest changes #3
|
@ -3,7 +3,7 @@ Copy the example and rename it to your desired name. Plugins define a ui target
|
||||||
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.
|
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
|
### Manifest Example (All are required.)
|
||||||
```
|
```
|
||||||
class Manifest:
|
class Manifest:
|
||||||
path: str = os.path.dirname(os.path.realpath(__file__))
|
path: str = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
@ -24,7 +24,10 @@ class Manifest:
|
||||||
permissions: {} = {
|
permissions: {} = {
|
||||||
'ui_target': "plugin_control_list",
|
'ui_target': "plugin_control_list",
|
||||||
'ui_target_id': "<some other Gtk Glade ID>" # Only needed if using "other" in "ui_target". See below for predefined "ui_target" options...
|
'ui_target_id': "<some other Gtk Glade ID>" # Only needed if using "other" in "ui_target". See below for predefined "ui_target" options...
|
||||||
'pass_fm_events': "true" # If empty or undefined will be ignored.
|
'pass_fm_events': "true" # If empty or not present will be ignored.
|
||||||
|
'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.
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ class Manifest:
|
||||||
support: str = ""
|
support: str = ""
|
||||||
permissions: {} = {
|
permissions: {} = {
|
||||||
'ui_target': "plugin_control_list",
|
'ui_target': "plugin_control_list",
|
||||||
'pass_fm_events': "true"
|
'pass_fm_events': "true",
|
||||||
|
'bind_keys': [f"{name}||send_message:<Control>f"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ class Plugin(Manifest):
|
||||||
|
|
||||||
def send_message(self, widget=None, eve=None):
|
def send_message(self, widget=None, eve=None):
|
||||||
message = "Hello, World!"
|
message = "Hello, World!"
|
||||||
|
print("here")
|
||||||
self._event_system.push_gui_event([self.name, "display_message", ("warning", message, None)])
|
self._event_system.push_gui_event([self.name, "display_message", ("warning", message, None)])
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,13 +69,17 @@ class Plugin(Manifest):
|
||||||
event = self._event_system.read_module_event()
|
event = self._event_system.read_module_event()
|
||||||
if event:
|
if event:
|
||||||
try:
|
try:
|
||||||
if event[0] is self.name:
|
if event[0] == self.name:
|
||||||
target_id, method_target, data = self._event_system.consume_module_event()
|
target_id, method_target, data = self._event_system.consume_module_event()
|
||||||
|
|
||||||
if not method_target:
|
if not method_target:
|
||||||
self._event_message = data
|
self._event_message = data
|
||||||
else:
|
else:
|
||||||
method = getattr(self.__class__, f"{method_target}")
|
method = getattr(self.__class__, f"{method_target}")
|
||||||
data = method(*(self, *parameters))
|
if data:
|
||||||
|
data = method(*(self, *data))
|
||||||
|
else:
|
||||||
|
method(*(self,))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
print("ewww here")
|
||||||
print(repr(e))
|
print(repr(e))
|
||||||
|
|
|
@ -63,14 +63,17 @@ class Plugin(Manifest):
|
||||||
event = self._fm_event_system.read_module_event()
|
event = self._fm_event_system.read_module_event()
|
||||||
if event:
|
if event:
|
||||||
try:
|
try:
|
||||||
if event[0] is self.name:
|
if event[0] == self.name:
|
||||||
target_id, method_target, data = self._fm_event_system.consume_module_event()
|
target_id, method_target, data = self._fm_event_system.consume_module_event()
|
||||||
|
|
||||||
if not method_target:
|
if not method_target:
|
||||||
self._fm_event_message = data
|
self._fm_event_message = data
|
||||||
else:
|
else:
|
||||||
method = getattr(self.__class__, f"{method_target}")
|
method = getattr(self.__class__, f"{method_target}")
|
||||||
data = method(*(self, *parameters))
|
if data:
|
||||||
|
data = method(*(self, *data))
|
||||||
|
else:
|
||||||
|
method(*(self,))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(repr(e))
|
print(repr(e))
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,10 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi
|
||||||
data = method(*(self, *parameters))
|
data = method(*(self, *parameters))
|
||||||
event_system.push_module_event([sender, None, data])
|
event_system.push_module_event([sender, None, data])
|
||||||
|
|
||||||
|
def handle_plugin_key_event(self, sender, method_target, parameters=()):
|
||||||
|
event_system.push_module_event([sender, method_target, parameters])
|
||||||
|
|
||||||
|
|
||||||
def save_load_session(self, action="save_session"):
|
def save_load_session(self, action="save_session"):
|
||||||
wid, tid = self.fm_controller.get_active_wid_and_tid()
|
wid, tid = self.fm_controller.get_active_wid_and_tid()
|
||||||
tab = self.get_fm_window(wid).get_tab_by_id(tid)
|
tab = self.get_fm_window(wid).get_tab_by_id(tid)
|
||||||
|
|
|
@ -19,6 +19,39 @@ def threaded(fn):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: Consider trying to use Gtk.TreeView with css that turns it into a grid...
|
||||||
|
# Can possibly use this to dynamicly load icons instead...
|
||||||
|
class Icon(Gtk.HBox):
|
||||||
|
def __init__(self, tab, dir, file):
|
||||||
|
super(Icon, self).__init__()
|
||||||
|
|
||||||
|
self.load_icon(tab, dir, file)
|
||||||
|
|
||||||
|
@threaded
|
||||||
|
def load_icon(self, tab, dir, file):
|
||||||
|
icon = tab.create_icon(dir, file)
|
||||||
|
|
||||||
|
if not icon:
|
||||||
|
path = f"{dir}/{file}"
|
||||||
|
icon = self.get_system_thumbnail(path, tab.sys_icon_wh[0])
|
||||||
|
|
||||||
|
if not icon:
|
||||||
|
icon = GdkPixbuf.Pixbuf.new_from_file(tab.DEFAULT_ICON)
|
||||||
|
|
||||||
|
self.add(Gtk.Image.new_from_pixbuf(icon))
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
def get_system_thumbnail(self, file, size):
|
||||||
|
try:
|
||||||
|
gio_file = Gio.File.new_for_path(file)
|
||||||
|
info = gio_file.query_info('standard::icon' , 0, None)
|
||||||
|
icon = info.get_icon().get_names()[0]
|
||||||
|
icon_path = self.icon_theme.lookup_icon(icon , size , 0).get_filename()
|
||||||
|
return GdkPixbuf.Pixbuf.new_from_file(icon_path)
|
||||||
|
except Exception as e:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class GridMixin:
|
class GridMixin:
|
||||||
"""docstring for WidgetMixin"""
|
"""docstring for WidgetMixin"""
|
||||||
|
|
||||||
|
@ -86,6 +119,15 @@ class GridMixin:
|
||||||
tid.hide()
|
tid.hide()
|
||||||
return tab_widget
|
return tab_widget
|
||||||
|
|
||||||
|
def create_scroll_and_store(self, tab, wid, use_tree_view=False):
|
||||||
|
if not use_tree_view:
|
||||||
|
scroll, store = self.create_icon_grid_widget(tab, wid)
|
||||||
|
else:
|
||||||
|
# TODO: Fix global logic to make the below work too
|
||||||
|
scroll, store = self.create_icon_tree_widget(tab, wid)
|
||||||
|
|
||||||
|
return scroll, store
|
||||||
|
|
||||||
def create_icon_grid_widget(self, tab, wid):
|
def create_icon_grid_widget(self, tab, wid):
|
||||||
scroll = Gtk.ScrolledWindow()
|
scroll = Gtk.ScrolledWindow()
|
||||||
grid = Gtk.IconView()
|
grid = Gtk.IconView()
|
||||||
|
@ -112,7 +154,6 @@ class GridMixin:
|
||||||
grid.connect("drag-data-received", self.grid_on_drag_data_received)
|
grid.connect("drag-data-received", self.grid_on_drag_data_received)
|
||||||
grid.connect("drag-motion", self.grid_on_drag_motion)
|
grid.connect("drag-motion", self.grid_on_drag_motion)
|
||||||
|
|
||||||
|
|
||||||
URI_TARGET_TYPE = 80
|
URI_TARGET_TYPE = 80
|
||||||
uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE)
|
uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE)
|
||||||
targets = [ uri_target ]
|
targets = [ uri_target ]
|
||||||
|
@ -167,12 +208,14 @@ class GridMixin:
|
||||||
grid.enable_model_drag_dest(targets, action)
|
grid.enable_model_drag_dest(targets, action)
|
||||||
grid.enable_model_drag_source(0, targets, action)
|
grid.enable_model_drag_source(0, targets, action)
|
||||||
|
|
||||||
|
|
||||||
grid.show_all()
|
grid.show_all()
|
||||||
scroll.add(grid)
|
scroll.add(grid)
|
||||||
grid.set_name(f"{wid}|{tab.get_id()}")
|
grid.set_name(f"{wid}|{tab.get_id()}")
|
||||||
scroll.set_name(f"{wid}|{tab.get_id()}")
|
scroll.set_name(f"{wid}|{tab.get_id()}")
|
||||||
|
self.builder.expose_object(f"{wid}|{tab.get_id()}|icon_grid", grid)
|
||||||
|
self.builder.expose_object(f"{wid}|{tab.get_id()}", scroll)
|
||||||
grid.columns_autosize()
|
grid.columns_autosize()
|
||||||
|
|
||||||
self.builder.expose_object(f"{wid}|{tab.get_id()}", scroll)
|
self.builder.expose_object(f"{wid}|{tab.get_id()}", scroll)
|
||||||
return scroll, store
|
return scroll, store
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,7 @@ class TabMixin(GridMixin):
|
||||||
tab.set_path(path)
|
tab.set_path(path)
|
||||||
|
|
||||||
tab_widget = self.create_tab_widget(tab)
|
tab_widget = self.create_tab_widget(tab)
|
||||||
scroll, store = self.create_icon_grid_widget(tab, wid)
|
scroll, store = self.create_scroll_and_store(tab, wid)
|
||||||
# TODO: Fix global logic to make the below work too
|
|
||||||
# scroll, store = self.create_icon_tree_widget(tab, wid)
|
|
||||||
index = notebook.append_page(scroll, tab_widget)
|
index = notebook.append_page(scroll, tab_widget)
|
||||||
|
|
||||||
self.fm_controller.set_wid_and_tid(wid, tab.get_id())
|
self.fm_controller.set_wid_and_tid(wid, tab.get_id())
|
||||||
|
|
|
@ -46,8 +46,14 @@ class KeyboardSignalsMixin:
|
||||||
|
|
||||||
mapping = self.keybindings.lookup(event)
|
mapping = self.keybindings.lookup(event)
|
||||||
if mapping:
|
if mapping:
|
||||||
|
try:
|
||||||
|
# See if in filemanager scope
|
||||||
getattr(self, mapping)()
|
getattr(self, mapping)()
|
||||||
return True
|
return True
|
||||||
|
except Exception:
|
||||||
|
# Must be plugins scope or we forgot to add method to file manager scope
|
||||||
|
sender, method_target = mapping.split("||")
|
||||||
|
self.handle_plugin_key_event(sender, method_target)
|
||||||
else:
|
else:
|
||||||
if debug:
|
if debug:
|
||||||
print(f"on_global_key_release_controller > key > {keyname}")
|
print(f"on_global_key_release_controller > key > {keyname}")
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Plugin:
|
||||||
name: str = None
|
name: str = None
|
||||||
author: str = None
|
author: str = None
|
||||||
version: str = None
|
version: str = None
|
||||||
suppoert: str = None
|
support: str = None
|
||||||
permissions:{} = None
|
permissions:{} = None
|
||||||
reference: type = None
|
reference: type = None
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ class Plugins:
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
self._builder = self._settings.get_builder()
|
self._builder = self._settings.get_builder()
|
||||||
self._plugins_path = self._settings.get_plugins_path()
|
self._plugins_path = self._settings.get_plugins_path()
|
||||||
|
self._keybindings = self._settings.get_keybindings()
|
||||||
|
|
||||||
self._plugins_dir_watcher = None
|
self._plugins_dir_watcher = None
|
||||||
self._plugin_collection = []
|
self._plugin_collection = []
|
||||||
|
|
||||||
|
@ -114,6 +116,10 @@ class Plugins:
|
||||||
if permissions["pass_fm_events"] in ["true"]:
|
if permissions["pass_fm_events"] in ["true"]:
|
||||||
loading_data["pass_fm_events"] = True
|
loading_data["pass_fm_events"] = True
|
||||||
|
|
||||||
|
if "bind_keys" in keys:
|
||||||
|
if isinstance(permissions["bind_keys"], list):
|
||||||
|
loading_data["bind_keys"] = permissions["bind_keys"]
|
||||||
|
|
||||||
return loading_data
|
return loading_data
|
||||||
|
|
||||||
def execute_plugin(self, module: type, plugin: Plugin, loading_data: []):
|
def execute_plugin(self, module: type, plugin: Plugin, loading_data: []):
|
||||||
|
@ -127,6 +133,9 @@ class Plugins:
|
||||||
if "pass_fm_events" in keys:
|
if "pass_fm_events" in keys:
|
||||||
plugin.reference.set_fm_event_system(event_system)
|
plugin.reference.set_fm_event_system(event_system)
|
||||||
|
|
||||||
|
if "bind_keys" in keys:
|
||||||
|
self._keybindings.append_bindings(loading_data["bind_keys"])
|
||||||
|
|
||||||
plugin.reference.run()
|
plugin.reference.run()
|
||||||
self._plugin_collection.append(plugin)
|
self._plugin_collection.append(plugin)
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,17 @@ class Keybindings:
|
||||||
self.keymap = Gdk.Keymap.get_default()
|
self.keymap = Gdk.Keymap.get_default()
|
||||||
self.configure({})
|
self.configure({})
|
||||||
|
|
||||||
|
def print_keys(self):
|
||||||
|
print(self.keys)
|
||||||
|
|
||||||
|
def append_bindings(self, combos):
|
||||||
|
"""Accept new binding(s) and reload"""
|
||||||
|
for item in combos:
|
||||||
|
method, keys = item.split(":")
|
||||||
|
self.keys[method] = keys
|
||||||
|
|
||||||
|
self.reload()
|
||||||
|
|
||||||
def configure(self, bindings):
|
def configure(self, bindings):
|
||||||
"""Accept new bindings and reconfigure with them"""
|
"""Accept new bindings and reconfigure with them"""
|
||||||
self.keys = bindings
|
self.keys = bindings
|
||||||
|
|
Loading…
Reference in New Issue