From ded86b81ec4845d769de29d718d5d998bab9f989 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Thu, 29 Sep 2022 17:22:33 -0500 Subject: [PATCH] Event system logic rework --- plugins/favorites/plugin.py | 22 ++----- plugins/file_properties/plugin.py | 7 +-- plugins/movie_tv_info/plugin.py | 16 ++--- plugins/searcher/plugin.py | 7 +-- plugins/template/plugin.py | 4 +- plugins/vod_thumbnailer/plugin.py | 32 +++++----- plugins/youtube_download/plugin.py | 17 ++--- .../SolarFM/solarfm/__builtins__.py | 18 +----- .../SolarFM/solarfm/core/controller.py | 38 +++-------- .../SolarFM/solarfm/core/controller_data.py | 2 + .../SolarFM/solarfm/plugins/plugin_base.py | 31 ++------- .../solarfm/plugins/plugins_controller.py | 1 + .../solarfm/utils/endpoint_registry.py | 22 +++++++ .../SolarFM/solarfm/utils/event_system.py | 63 +++++-------------- .../SolarFM/solarfm/utils/ipc_server.py | 7 ++- 15 files changed, 102 insertions(+), 185 deletions(-) create mode 100644 src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/endpoint_registry.py diff --git a/plugins/favorites/plugin.py b/plugins/favorites/plugin.py index e586de7..aca3f63 100644 --- a/plugins/favorites/plugin.py +++ b/plugins/favorites/plugin.py @@ -38,7 +38,6 @@ class Plugin(PluginBase): self._favorites_dialog = None self._favorites_store = None self._favorites = None - self._state = None self._selected = None @@ -48,8 +47,6 @@ class Plugin(PluginBase): return button def run(self): - self._module_event_observer() - self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -81,19 +78,15 @@ class Plugin(PluginBase): @threaded def _get_state(self, widget=None, eve=None): - self._event_system.push_gui_event([self.name, "get_current_state", ()]) - self.wait_for_fm_message() + self._event_system.post_event("get_current_state", None) - self._state = self._event_message - self._event_message = None @threaded def _set_current_dir_lbl(self, widget=None, eve=None): - self.wait_for_state() - self._current_dir_lbl.set_label(f"Current Directory:\n{self._state.tab.get_current_directory()}") + self._current_dir_lbl.set_label(f"Current Directory:\n{self._fm_state.tab.get_current_directory()}") def _add_to_favorite(self, state): - current_directory = self._state.tab.get_current_directory() + current_directory = self._fm_state.tab.get_current_directory() self._favorites_store.append([current_directory]) self._favorites.append(current_directory) self._save_favorites() @@ -111,11 +104,10 @@ class Plugin(PluginBase): def _set_selected_path(self, widget=None, eve=None): path = self._favorites_store.get_value(self._selected, 0) self._ui_objects[0].set_text(path) - - + self._set_current_dir_lbl() def _show_favorites_menu(self, widget=None, eve=None): - self._state = None + self._fm_state = None self._get_state() self._set_current_dir_lbl() self._favorites_dialog.run() @@ -127,7 +119,3 @@ class Plugin(PluginBase): selected = user_data.get_selected()[1] if selected: self._selected = selected - - def wait_for_state(self): - while not self._state: - pass diff --git a/plugins/file_properties/plugin.py b/plugins/file_properties/plugin.py index 29472ed..5177943 100644 --- a/plugins/file_properties/plugin.py +++ b/plugins/file_properties/plugin.py @@ -89,8 +89,6 @@ class Plugin(PluginBase): return button def run(self): - self._module_event_observer() - self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -109,10 +107,9 @@ class Plugin(PluginBase): @threaded def _show_properties_page(self, widget=None, eve=None): - self._event_system.push_gui_event([self.name, "get_current_state", ()]) - self.wait_for_fm_message() + event_system.post_event("get_current_state", None) - state = self._event_message + state = self._fm_state self._event_message = None GLib.idle_add(self._process_changes, (state)) diff --git a/plugins/movie_tv_info/plugin.py b/plugins/movie_tv_info/plugin.py index 3a4a1c5..64df1c6 100644 --- a/plugins/movie_tv_info/plugin.py +++ b/plugins/movie_tv_info/plugin.py @@ -39,7 +39,6 @@ class Plugin(PluginBase): self._dialog = None self._thumbnail_preview_img = None self._tmdb = scraper.get_tmdb_scraper() - self._state = None self._overview = None self._file_name = None self._file_location = None @@ -53,8 +52,6 @@ class Plugin(PluginBase): return button def run(self): - self._module_event_observer() - self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -80,19 +77,18 @@ class Plugin(PluginBase): @threaded def _show_info_page(self, widget=None, eve=None): - self._event_system.push_gui_event([self.name, "get_current_state", ()]) - self.wait_for_fm_message() + self._event_system.post_event("get_current_state", None) - state = self._event_message + state = self._fm_state self._event_message = None GLib.idle_add(self._process_changes, (state)) def _process_changes(self, state): - self._state = None + self._fm_state = None if len(state.selected_files) == 1: - self._state = state + self._fm_state = state self._set_ui_data() response = self._thumbnailer_dialog.run() if response in [Gtk.ResponseType.CLOSE, Gtk.ResponseType.DELETE_EVENT]: @@ -111,8 +107,8 @@ class Plugin(PluginBase): print(video_data["videos"]) if not keys in ("", None) and "videos" in keys else ... def get_video_data(self): - uri = self._state.selected_files[0] - path = self._state.tab.get_current_directory() + uri = self._fm_state.selected_files[0] + path = self._fm_state.tab.get_current_directory() parts = uri.split("/") _title = parts[ len(parts) - 1 ] diff --git a/plugins/searcher/plugin.py b/plugins/searcher/plugin.py index 3ace6ba..9328a90 100644 --- a/plugins/searcher/plugin.py +++ b/plugins/searcher/plugin.py @@ -98,8 +98,6 @@ class Plugin(PluginBase): return button def run(self): - self._module_event_observer() - self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -127,10 +125,9 @@ class Plugin(PluginBase): @daemon_threaded def _show_grep_list_page(self, widget=None, eve=None): - self._event_system.push_gui_event([self.name, "get_current_state", ()]) - self.wait_for_fm_message() + self._event_system.post_event("get_current_state", None) - state = self._event_message + state = self._fm_state self._event_message = None GLib.idle_add(self._process_queries, (state)) diff --git a/plugins/template/plugin.py b/plugins/template/plugin.py index 08c2b72..b99308a 100644 --- a/plugins/template/plugin.py +++ b/plugins/template/plugin.py @@ -39,8 +39,8 @@ class Plugin(PluginBase): return button def run(self): - self._module_event_observer() + ... def send_message(self, widget=None, eve=None): message = "Hello, World!" - self._event_system.push_gui_event([self.name, "display_message", ("warning", message, None)]) + event_system.post_event("display_message", ("warning", message, None)) diff --git a/plugins/vod_thumbnailer/plugin.py b/plugins/vod_thumbnailer/plugin.py index 4a8abad..3d6f164 100644 --- a/plugins/vod_thumbnailer/plugin.py +++ b/plugins/vod_thumbnailer/plugin.py @@ -42,7 +42,6 @@ class Plugin(PluginBase): self._file_name = None self._file_location = None self._file_hash = None - self._state = None def get_ui_element(self): @@ -51,8 +50,6 @@ class Plugin(PluginBase): return button def run(self): - self._module_event_observer() - self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -78,20 +75,19 @@ class Plugin(PluginBase): @threaded def _show_thumbnailer_page(self, widget=None, eve=None): - self._event_system.push_gui_event([self.name, "get_current_state", ()]) - self.wait_for_fm_message() + self._event_system.post_event("get_current_state", None) - state = self._event_message + state = self._fm_state self._event_message = None GLib.idle_add(self._process_changes, (state)) def _process_changes(self, state): - self._state = None + self._fm_state = None if len(state.selected_files) == 1: if state.selected_files[0].lower().endswith(state.tab.fvideos): - self._state = state + self._fm_state = state self._set_ui_data() response = self._thumbnailer_dialog.run() if response in [Gtk.ResponseType.CLOSE, Gtk.ResponseType.DELETE_EVENT]: @@ -103,32 +99,32 @@ class Plugin(PluginBase): file = self._file_name.get_text() dir = self._file_location.get_text() file_hash = self._file_hash.get_text() - hash_img_pth = f"{self._state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg" + hash_img_pth = f"{self._fm_state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg" try: os.remove(hash_img_pth) if os.path.isfile(hash_img_pth) else ... - self._state.tab.create_thumbnail(dir, file, f"{scrub_percent}%") + self._fm_state.tab.create_thumbnail(dir, file, f"{scrub_percent}%") preview_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth) self._thumbnail_preview_img.set_from_pixbuf(preview_pixbuf) - img_pixbuf = self._state.tab.create_scaled_image(hash_img_pth) - tree_pth = self._state.icon_grid.get_selected_items()[0] - itr = self._state.store.get_iter(tree_pth) - pixbuff = self._state.store.get(itr, 0)[0] - self._state.store.set(itr, 0, img_pixbuf) + img_pixbuf = self._fm_state.tab.create_scaled_image(hash_img_pth) + tree_pth = self._fm_state.icon_grid.get_selected_items()[0] + itr = self._fm_state.store.get_iter(tree_pth) + pixbuff = self._fm_state.store.get(itr, 0)[0] + self._fm_state.store.set(itr, 0, img_pixbuf) except Exception as e: print(repr(e)) print("Couldn't regenerate thumbnail!") def _set_ui_data(self): - uri = self._state.selected_files[0] - path = self._state.tab.get_current_directory() + uri = self._fm_state.selected_files[0] + path = self._fm_state.tab.get_current_directory() parts = uri.split("/") file_hash = hashlib.sha256(str.encode(uri)).hexdigest() - hash_img_pth = f"{self._state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg" + hash_img_pth = f"{self._fm_state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg" preview_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth) self._thumbnail_preview_img.set_from_pixbuf(preview_pixbuf) diff --git a/plugins/youtube_download/plugin.py b/plugins/youtube_download/plugin.py index d2d4919..5ebf3b1 100644 --- a/plugins/youtube_download/plugin.py +++ b/plugins/youtube_download/plugin.py @@ -40,14 +40,15 @@ class Plugin(PluginBase): return button def run(self): - self._module_event_observer() + ... + def _do_download(self, widget=None, eve=None): + self._event_system.post_event("get_current_state", None) + + dir = self._fm_state.tab.get_current_directory() + self._download(dir) + @threaded - def _do_download(self, widget=None, eve=None): - self._event_system.push_gui_event([self.name, "get_current_state", ()]) - self.wait_for_fm_message() - - state = self._event_message - subprocess.Popen([f'{self.path}/download.sh' , state.tab.get_current_directory()]) - self._event_message = None + def _download(self, dir): + subprocess.Popen([f'{self.path}/download.sh', dir]) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py index d9a77d8..428f16f 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py @@ -5,6 +5,7 @@ import builtins, threading # Application imports from utils.event_system import EventSystem +from utils.endpoint_registry import EndpointRegistry @@ -24,23 +25,6 @@ def daemon_threaded_wrapper(fn): -class EndpointRegistry(): - def __init__(self): - self._endpoints = {} - - def register(self, rule, **options): - def decorator(f): - self._endpoints[rule] = f - return f - - return decorator - - def get_endpoints(self): - return self._endpoints - - - - # NOTE: Just reminding myself we can add to builtins two different ways... # __builtins__.update({"event_system": Builtins()}) builtins.app_name = "SolarFM" diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller.py index e844325..8d99d05 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller.py @@ -28,52 +28,32 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi if debug: self.window.set_interactive_debugging(True) + if not trace_debug: - self.gui_event_observer() + self._subscribe_to_events() if unknownargs: for arg in unknownargs: if os.path.isdir(arg): message = f"FILE|{arg}" - event_system.send_ipc_message(message) + event_system.post_event("post_file_to_ipc", message) if args.new_tab and os.path.isdir(args.new_tab): message = f"FILE|{args.new_tab}" - event_system.send_ipc_message(message) + event_system.post_event("post_file_to_ipc", message) + def _subscribe_to_events(self): + event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc) + event_system.subscribe("get_current_state", self.get_current_state) + event_system.subscribe("display_message", self.display_message) + def tear_down(self, widget=None, eve=None): self.fm_controller.save_state() time.sleep(event_sleep_time) Gtk.main_quit() - @daemon_threaded - def gui_event_observer(self): - while True: - time.sleep(event_sleep_time) - event = event_system.consume_gui_event() - if event: - try: - sender_id, method_target, parameters = event - if sender_id: - method = getattr(self.__class__, "handle_gui_event_and_return_message") - GLib.idle_add(method, *(self, sender_id, method_target, parameters)) - else: - method = getattr(self.__class__, method_target) - GLib.idle_add(method, *(self, *parameters,)) - except Exception as e: - print(repr(e)) - - def handle_gui_event_and_return_message(self, sender, method_target, parameters): - method = getattr(self.__class__, f"{method_target}") - data = method(*(self, *parameters)) - 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"): wid, tid = self.fm_controller.get_active_wid_and_tid() tab = self.get_fm_window(wid).get_tab_by_id(tid) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller_data.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller_data.py index fbd5e89..04a6656 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller_data.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller_data.py @@ -154,6 +154,8 @@ class Controller_Data: # if self.to_cut_files: # state.to_cut_files = self.format_to_uris(state.store, state.wid, state.tid, self.to_cut_files, True) + event_system.post_event("update_state_info_plugins", state) + return state diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugin_base.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugin_base.py index 8e33157..effd377 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugin_base.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugin_base.py @@ -13,10 +13,9 @@ class PluginBase: self._builder = None self._ui_objects = None - + self._fm_state = None self._event_system = None - self._event_sleep_time = .5 - self._event_message = None + def set_fm_event_system(self, fm_event_system): self._event_system = fm_event_system @@ -24,32 +23,14 @@ class PluginBase: def set_ui_object_collection(self, ui_objects): self._ui_objects = ui_objects - def wait_for_fm_message(self): - while not self._event_message: - pass def clear_children(self, widget: type) -> None: ''' Clear children of a gtk widget. ''' for child in widget.get_children(): widget.remove(child) - @daemon_threaded - def _module_event_observer(self): - while True: - time.sleep(self._event_sleep_time) - event = self._event_system.read_module_event() - if event: - try: - if event[0] == self.name: - target_id, method_target, data = self._event_system.consume_module_event() + def subscribe_to_events(self): + self._event_system.subscribe("update_state_info_plugins", self._update_fm_state_info) - if not method_target: - self._event_message = data - else: - method = getattr(self.__class__, f"{method_target}") - if data: - data = method(*(self, *data)) - else: - method(*(self,)) - except Exception as e: - print(repr(e)) + def _update_fm_state_info(self, state): + self._fm_state = state diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins_controller.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins_controller.py index 1ef2001..11f9dda 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins_controller.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins_controller.py @@ -93,6 +93,7 @@ class PluginsController: if "pass_fm_events" in keys: plugin.reference.set_fm_event_system(event_system) + plugin.reference.subscribe_to_events() if "bind_keys" in keys: self._keybindings.append_bindings( loading_data["bind_keys"] ) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/endpoint_registry.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/endpoint_registry.py new file mode 100644 index 0000000..15ffa9e --- /dev/null +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/endpoint_registry.py @@ -0,0 +1,22 @@ +# Python imports + +# Lib imports + +# Application imports + + + + +class EndpointRegistry(): + def __init__(self): + self._endpoints = {} + + def register(self, rule, **options): + def decorator(f): + self._endpoints[rule] = f + return f + + return decorator + + def get_endpoints(self): + return self._endpoints diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/event_system.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/event_system.py index f3ea280..53aa64e 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/event_system.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/event_system.py @@ -1,4 +1,5 @@ # Python imports +from collections import defaultdict # Lib imports @@ -7,57 +8,23 @@ -class EventSystemPushException(Exception): - ... - - class EventSystem: - """ Inheret IPCServerMixin. Create an pub/sub systems. """ + """ Create event system. """ def __init__(self): - # NOTE: The format used is list of ['who', target, (data,)] Where: - # who is the sender or target ID and is used for context and control flow, - # method_target is the method to call, - # data is the method parameters OR message data to give - # Where data may be any kind of data - self._gui_events = [] - self._module_events = [] + self.subscribers = defaultdict(list) - # Makeshift "events" system FIFO - def _pop_gui_event(self) -> None: - if len(self._gui_events) > 0: - return self._gui_events.pop(0) - return None + def subscribe(self, event_type, fn): + self.subscribers[event_type].append(fn) - def _pop_module_event(self) -> None: - if len(self._module_events) > 0: - return self._module_events.pop(0) - return None - - - def push_gui_event(self, event: list) -> None: - if len(event) == 3: - self._gui_events.append(event) - return None - - raise EventSystemPushException("Invald event format! Please do: ['sender_id': str, method_target: method, (data,): any]") - - def push_module_event(self, event: list) -> None: - if len(event) == 3: - self._module_events.append(event) - return None - - raise EventSystemPushException("Invald event format! Please do: ['target_id': str, method_target: method, (data,): any]") - - def read_gui_event(self) -> list: - return self._gui_events[0] if self._gui_events else None - - def read_module_event(self) -> list: - return self._module_events[0] if self._module_events else None - - def consume_gui_event(self) -> list: - return self._pop_gui_event() - - def consume_module_event(self) -> list: - return self._pop_module_event() + def post_event(self, event_type, data): + if event_type in self.subscribers: + for fn in self.subscribers[event_type]: + if data: + if hasattr(data, '__iter__'): + fn(*data) + else: + fn(data) + else: + fn() diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py index 1ddf584..c73dc0a 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py @@ -29,6 +29,11 @@ class IPCServer: elif conn_type == "local_network_unsecured": self._ipc_authkey = None + self._subscribe_to_events() + + def _subscribe_to_events(self): + event_system.subscribe("post_file_to_ipc", self.send_ipc_message) + @daemon_threaded def create_ipc_listener(self) -> None: @@ -60,7 +65,7 @@ class IPCServer: if "FILE|" in msg: file = msg.split("FILE|")[1].strip() if file: - event_system.push_gui_event([None, "handle_file_from_ipc", (file,)]) + event_system.post_event("handle_file_from_ipc", file) conn.close() break