Moved core.ui to core.widgets, added wip plugin reloading, refactoring
This commit is contained in:
		| @@ -95,7 +95,7 @@ class Plugin(PluginBase): | ||||
|     def _process_changes(self, state): | ||||
|         self._fm_state = None | ||||
|  | ||||
|         if len(state.uris) == 1: | ||||
|         if state.uris and len(state.uris) == 1: | ||||
|             self._fm_state = state | ||||
|             self._set_ui_data() | ||||
|             response   = self._thumbnailer_dialog.run() | ||||
|   | ||||
| @@ -13,20 +13,20 @@ from .controller_data import Controller_Data | ||||
| from .fs_actions.file_system_actions import FileSystemActions | ||||
| from .mixins.signals_mixins import SignalsMixins | ||||
|  | ||||
| from .ui.dialogs.about_widget import AboutWidget | ||||
| from .ui.dialogs.appchooser_widget import AppchooserWidget | ||||
| from .ui.dialogs.file_exists_widget import FileExistsWidget | ||||
| from .ui.dialogs.new_file_widget import NewFileWidget | ||||
| from .ui.dialogs.message_widget import MessageWidget | ||||
| from .ui.dialogs.rename_widget import RenameWidget | ||||
| from .ui.dialogs.save_load_widget import SaveLoadWidget | ||||
| from .widgets.dialogs.about_widget import AboutWidget | ||||
| from .widgets.dialogs.appchooser_widget import AppchooserWidget | ||||
| from .widgets.dialogs.file_exists_widget import FileExistsWidget | ||||
| from .widgets.dialogs.new_file_widget import NewFileWidget | ||||
| from .widgets.dialogs.message_widget import MessageWidget | ||||
| from .widgets.dialogs.rename_widget import RenameWidget | ||||
| from .widgets.dialogs.save_load_widget import SaveLoadWidget | ||||
|  | ||||
| from .ui.popups.message_popup_widget import MessagePopupWidget | ||||
| from .ui.popups.path_menu_popup_widget import PathMenuPopupWidget | ||||
| from .ui.popups.plugins_popup_widget import PluginsPopupWidget | ||||
| from .ui.popups.io_popup_widget import IOPopupWidget | ||||
| from .widgets.popups.message_popup_widget import MessagePopupWidget | ||||
| from .widgets.popups.path_menu_popup_widget import PathMenuPopupWidget | ||||
| from .widgets.popups.plugins_popup_widget import PluginsPopupWidget | ||||
| from .widgets.popups.io_popup_widget import IOPopupWidget | ||||
|  | ||||
| from .ui.context_menu_widget import ContextMenuWidget | ||||
| from .widgets.context_menu_widget import ContextMenuWidget | ||||
|  | ||||
| from .ui_mixin import UIMixin | ||||
|  | ||||
| @@ -95,6 +95,9 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): | ||||
|         time.sleep(event_sleep_time) | ||||
|         Gtk.main_quit() | ||||
|  | ||||
|     def reload_plugins(self, widget=None, eve=None): | ||||
|         self.plugins.reload_plugins() | ||||
|  | ||||
|  | ||||
|     def do_action_from_menu_controls(self, _action=None, eve=None): | ||||
|         if not _action: | ||||
|   | ||||
| @@ -28,6 +28,7 @@ class State: | ||||
|     icon_grid: gi.overrides.Gtk.IconView = None | ||||
|     store: gi.overrides.Gtk.ListStore    = None | ||||
|     uris:           []   = None | ||||
|     uris_raw:       []   = None | ||||
|     selected_files: []   = None | ||||
|     to_copy_files:  []   = None | ||||
|     to_cut_files:   []   = None | ||||
| @@ -105,9 +106,10 @@ class Controller_Data: | ||||
|  | ||||
|         selected_files       = state.icon_grid.get_selected_items() | ||||
|         if selected_files: | ||||
|             state.uris = self.format_to_uris(state.store, state.wid, state.tid, selected_files, True) | ||||
|             state.uris     = self.format_to_uris(state.store, state.wid, state.tid, selected_files, True) | ||||
|             state.uris_raw = self.format_to_uris(state.store, state.wid, state.tid, selected_files) | ||||
|  | ||||
|         state.selected_files = self.selected_files | ||||
|         state.selected_files = event_system.emit_and_await("get_selected_files") | ||||
|  | ||||
|         # if self.to_copy_files: | ||||
|         #     state.to_copy_files  = self.format_to_uris(state.store, state.wid, state.tid, self.to_copy_files, True) | ||||
|   | ||||
| @@ -84,7 +84,7 @@ class FileSystemActions(HandlerMixin, CRUDMixin): | ||||
|  | ||||
|     def open_with_files(self, app_info): | ||||
|         state = event_system.emit_and_await("get_current_state") | ||||
|         state.tab.app_chooser_exec(app_info, state.uris) | ||||
|         state.tab.app_chooser_exec(app_info, state.uris_raw) | ||||
|  | ||||
|     def execute_files(self, in_terminal=False): | ||||
|         state       = event_system.emit_and_await("get_current_state") | ||||
|   | ||||
| @@ -9,7 +9,7 @@ from gi.repository import GObject | ||||
| from gi.repository import Gio | ||||
|  | ||||
| # Application imports | ||||
| from ..ui.io_widget import IOWidget | ||||
| from ..widgets.io_widget import IOWidget | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -48,17 +48,18 @@ class KeyboardSignalsMixin: | ||||
|  | ||||
|         mapping = self.keybindings.lookup(event) | ||||
|         if mapping: | ||||
|             # See if in filemanager scope | ||||
|             try: | ||||
|                 # See if in filemanager scope | ||||
|                 try: | ||||
|                     getattr(self, mapping)() | ||||
|                 except Exception as e: | ||||
|                     event_system.emit(mapping) | ||||
|  | ||||
|                 getattr(self, mapping)() | ||||
|                 return True | ||||
|             except Exception: | ||||
|                 # Must be plugins scope or we forgot to add method to file manager scope | ||||
|                 sender, eve_type = mapping.split("||") | ||||
|                 # Must be plugins scope, event call, OR we forgot to add method to file manager scope | ||||
|                 if "||" in mapping: | ||||
|                     sender, eve_type = mapping.split("||") | ||||
|                 else: | ||||
|                     sender = "" | ||||
|                     eve_type = mapping | ||||
|  | ||||
|                 self.handle_plugin_key_event(sender, eve_type) | ||||
|         else: | ||||
|             if settings.is_debug(): | ||||
|   | ||||
| @@ -13,9 +13,9 @@ from gi.repository import Gio | ||||
| from gi.repository import GdkPixbuf | ||||
|  | ||||
| # Application imports | ||||
| from ...ui.tab_header_widget import TabHeaderWidget | ||||
| from ...ui.icon_grid_widget import IconGridWidget | ||||
| from ...ui.icon_tree_widget import IconTreeWidget | ||||
| from ...widgets.tab_header_widget import TabHeaderWidget | ||||
| from ...widgets.icon_grid_widget import IconGridWidget | ||||
| from ...widgets.icon_tree_widget import IconTreeWidget | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,9 @@ from os.path import isdir | ||||
|  | ||||
| # Lib imports | ||||
| import gi | ||||
| gi.require_version('Gtk', '3.0') | ||||
| gi.require_version('Gdk', '3.0') | ||||
| from gi.repository import Gtk | ||||
| from gi.repository import Gdk | ||||
| from gi.repository import Gio | ||||
|  | ||||
| @@ -160,31 +162,29 @@ class WindowMixin(TabMixin): | ||||
|         path_entry.set_text(tab.get_current_directory()) | ||||
|  | ||||
|     def grid_set_selected_items(self, icons_grid): | ||||
|         items = icons_grid.get_selected_items() | ||||
|         size  = len(items) | ||||
|         new_items      = icons_grid.get_selected_items() | ||||
|         items_size     = len(new_items) | ||||
|         selected_items = event_system.emit_and_await("get_selected_files") | ||||
|  | ||||
|         if size == 1: | ||||
|         if items_size == 1: | ||||
|             # NOTE: If already in selection, likely dnd else not so wont readd | ||||
|             # if items[0] in self.selected_files: | ||||
|             if items[0] in event_system.emit_and_await("get_selected_files"): | ||||
|             if new_items[0] in selected_items: | ||||
|                 self.dnd_left_primed += 1 | ||||
|                 # NOTE: If in selection but trying to just select an already selected item. | ||||
|                 if self.dnd_left_primed > 1: | ||||
|                     self.dnd_left_primed = 0 | ||||
|                     event_system.emit_and_await("get_selected_files").clear() | ||||
|                     # self.selected_files.clear() | ||||
|                     selected_items.clear() | ||||
|  | ||||
|                 # NOTE: Likely trying dnd, just readd to selection the former set. | ||||
|                 #       Prevents losing highlighting of grid selected. | ||||
|                 for path in self.selected_files: | ||||
|                 for path in selected_items: | ||||
|                     icons_grid.select_path(path) | ||||
|  | ||||
|         if size > 0: | ||||
|             # self.selected_files = icons_grid.get_selected_items() | ||||
|             event_system.emit("set_selected_files", (icons_grid.get_selected_items(),)) | ||||
|         if items_size > 0: | ||||
|             event_system.emit("set_selected_files", (new_items,)) | ||||
|         else: | ||||
|             self.dnd_left_primed = 0 | ||||
|             event_system.emit_and_await("get_selected_files").clear() | ||||
|             selected_items.clear() | ||||
|  | ||||
|     def grid_icon_single_click(self, icons_grid, eve): | ||||
|         try: | ||||
| @@ -244,7 +244,7 @@ class WindowMixin(TabMixin): | ||||
|         store     = icons_grid.get_model() | ||||
|         treePaths = icons_grid.get_selected_items() | ||||
|         # NOTE: Need URIs as URI format for DnD to work. Will strip 'file://' | ||||
|         # further down call chain when doing internal fm stuff. | ||||
|         #       further down call chain when doing internal fm stuff. | ||||
|         uris      = self.format_to_uris(store, wid, tid, treePaths) | ||||
|         uris_text = '\n'.join(uris) | ||||
|  | ||||
| @@ -273,13 +273,9 @@ class WindowMixin(TabMixin): | ||||
|  | ||||
|     def grid_on_drag_data_received(self, widget, drag_context, x, y, data, info, time): | ||||
|         if info == 80: | ||||
|             wid, tid  = self.fm_controller.get_active_wid_and_tid() | ||||
|             notebook  = self.builder.get_object(f"window_{wid}") | ||||
|             store, tab_label = self.get_store_and_label_from_notebook(notebook, f"{wid}|{tid}") | ||||
|             tab       = self.get_fm_window(wid).get_tab_by_id(tid) | ||||
|  | ||||
|             uris = data.get_uris() | ||||
|             dest = f"{tab.get_current_directory()}" if not self.override_drop_dest else self.override_drop_dest | ||||
|             uris  = data.get_uris() | ||||
|             state = event_system.emit_and_await("get_current_state") | ||||
|             dest  = f"{state.tab.get_current_directory()}" if not self.override_drop_dest else self.override_drop_dest | ||||
|             if len(uris) == 0: | ||||
|                 uris = data.get_text().split("\n") | ||||
|  | ||||
|   | ||||
| @@ -63,3 +63,19 @@ class PluginBase: | ||||
|             Is intended to be used to setup internal signals or custom Gtk Builders/UI logic. | ||||
|         """ | ||||
|         raise PluginBaseException("Method hasn't been overriden...") | ||||
|  | ||||
|     def reload_package(self, plugin_path, module_dict_main=locals()): | ||||
|         import importlib | ||||
|         from pathlib import Path | ||||
|  | ||||
|         def reload_package_recursive(current_dir, module_dict): | ||||
|             for path in current_dir.iterdir(): | ||||
|                 if "__init__" in str(path) or path.stem not in module_dict: | ||||
|                     continue | ||||
|  | ||||
|                 if path.is_file() and path.suffix == ".py": | ||||
|                     importlib.reload(module_dict[path.stem]) | ||||
|                 elif path.is_dir(): | ||||
|                     reload_package_recursive(path, module_dict[path.stem].__dict__) | ||||
|  | ||||
|         reload_package_recursive(Path(plugin_path).parent, module_dict_main["module_dict_main"]) | ||||
|   | ||||
| @@ -117,4 +117,11 @@ class PluginsController: | ||||
|         self._plugin_collection.append(plugin) | ||||
|  | ||||
|     def reload_plugins(self, file: str = None) -> None: | ||||
|         print(f"Reloading plugins... stub.") | ||||
|         print(f"Reloading plugins...") | ||||
|         parent_path = os.getcwd() | ||||
|  | ||||
|         for plugin in self._plugin_collection: | ||||
|             os.chdir(plugin.path) | ||||
|             plugin.reference.reload_package(f"{plugin.path}/plugin.py") | ||||
|  | ||||
|         os.chdir(parent_path) | ||||
|   | ||||
| @@ -27,6 +27,11 @@ | ||||
|     <property name="can-focus">False</property> | ||||
|     <property name="stock">gtk-execute</property> | ||||
|   </object> | ||||
|   <object class="GtkImage" id="image6"> | ||||
|     <property name="visible">True</property> | ||||
|     <property name="can-focus">False</property> | ||||
|     <property name="stock">gtk-redo</property> | ||||
|   </object> | ||||
|   <object class="GtkImage" id="io_img"> | ||||
|     <property name="visible">True</property> | ||||
|     <property name="can-focus">False</property> | ||||
| @@ -122,6 +127,16 @@ | ||||
|                             <property name="can-focus">False</property> | ||||
|                           </object> | ||||
|                         </child> | ||||
|                         <child> | ||||
|                           <object class="GtkImageMenuItem"> | ||||
|                             <property name="label">Reload Plugins</property> | ||||
|                             <property name="visible">True</property> | ||||
|                             <property name="can-focus">False</property> | ||||
|                             <property name="image">image6</property> | ||||
|                             <property name="use-stock">False</property> | ||||
|                             <signal name="button-release-event" handler="reload_plugins" swapped="no"/> | ||||
|                           </object> | ||||
|                         </child> | ||||
|                         <child> | ||||
|                           <object class="GtkImageMenuItem"> | ||||
|                             <property name="label">Terminal</property> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user