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__)) | ||||||
| @@ -23,8 +23,11 @@ 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: | ||||||
|             getattr(self, mapping)() |             try: | ||||||
|             return True |                 # See if in filemanager scope | ||||||
|  |                 getattr(self, mapping)() | ||||||
|  |                 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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user