diff --git a/plugins/template/__main__.py b/plugins/template/__main__.py index ac0f74f..8264621 100644 --- a/plugins/template/__main__.py +++ b/plugins/template/__main__.py @@ -1,5 +1,5 @@ # Python imports -import sys, threading, subprocess, time +import os, threading, subprocess, time # Gtk imports import gi @@ -9,45 +9,74 @@ from gi.repository import Gtk # Application imports +# NOTE: Threads will not die with parent's destruction def threaded(fn): def wrapper(*args, **kwargs): threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start() return wrapper +# NOTE: Insure threads die with parent's destruction +def daemon_threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start() + return wrapper + + + class Plugin: def __init__(self, builder, event_system): - self._plugin_name = "Example Plugin" - self._builder = builder - self._event_system = event_system - self._message = None - self._time_out = 5 + self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + self._plugin_name = "Example Plugin" + self._plugin_author = "John Doe" + self._plugin_version = "0.0.1" - button = Gtk.Button(label=self._plugin_name) - button.connect("button-release-event", self._do_action) + self._builder = builder + self._event_system = event_system + self._event_sleep_time = .5 + self._event_message = None - plugin_list = self._builder.get_object("plugin_socket") + button = Gtk.Button(label=self._plugin_name) + button.connect("button-release-event", self.send_message) + + # self._module_event_observer() # NOTE: Enable if you want the plugin to watch for events sent to it + + plugin_list = self._builder.get_object("plugin_socket") plugin_list.add(button) plugin_list.show_all() - @threaded - def _do_action(self, widget=None, eve=None): + def send_message(self, widget=None, eve=None): message = "Hello, World!" - self._event_system.push_gui_event(["some_type", "display_message", ("warning", message, None)]) + self._event_system.push_gui_event([self._plugin_name, "display_message", ("warning", message, None)]) - def set_message(self, data): - self._message = data - def get_plugin_name(self): return self._plugin_name + def get_plugin_author(self): + return self._plugin_author + + def get_plugin_version(self): + return self._plugin_version + def get_socket_id(self): return self._socket_id - def _run_timeout(self): - timeout = 0 - while not self._message and timeout < self._time_out: - time.sleep(1) - timeout += 1 + @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] is self._plugin_name: + target_id, method_target, data = self._event_system.consume_module_event() + + if not method_target: + self._event_message = data + else: + method = getattr(self.__class__, f"{method_target}") + data = method(*(self, *parameters)) + except Exception as e: + print(repr(e)) diff --git a/plugins/youtube_download/__main__.py b/plugins/youtube_download/__main__.py index f264fcf..bc81cbb 100644 --- a/plugins/youtube_download/__main__.py +++ b/plugins/youtube_download/__main__.py @@ -1,5 +1,5 @@ # Python imports -import os, sys, threading, subprocess, time +import os, threading, subprocess, time # Gtk imports import gi @@ -9,49 +9,78 @@ from gi.repository import Gtk # Application imports +# NOTE: Threads will not die with parent's destruction def threaded(fn): def wrapper(*args, **kwargs): threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start() return wrapper +# NOTE: Insure threads die with parent's destruction +def daemon_threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start() + return wrapper + + + class Plugin: - def __init__(self, builder, event_system): - self._plugin_name = "Youtube Download" - self._builder = builder - self._event_system = event_system - self._message = None - self._time_out = 5 + def __init__(self, fm_builder, fm_event_system): + self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + self._plugin_name = "Youtube Download" + self._plugin_author = "ITDominator" + self._plugin_version = "0.0.1" - self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + self._fm_builder = fm_builder + self._fm_event_system = fm_event_system + self._event_sleep_time = .5 + self._fm_event_message = None - button = Gtk.Button(label=self._plugin_name) + + button = Gtk.Button(label=self._plugin_name) button.connect("button-release-event", self._do_download) - plugin_list = self._builder.get_object("plugin_socket") + self._module_event_observer() + + plugin_list = self._fm_builder.get_object("plugin_socket") plugin_list.add(button) plugin_list.show_all() + @daemon_threaded + def _module_event_observer(self): + while True: + time.sleep(self._event_sleep_time) + event = self._fm_event_system.read_module_event() + if event: + try: + if event[0] is self._plugin_name: + target_id, method_target, data = self._fm_event_system.consume_module_event() + + if not method_target: + self._fm_event_message = data + else: + method = getattr(self.__class__, f"{method_target}") + data = method(*(self, *parameters)) + except Exception as e: + print(repr(e)) + @threaded def _do_download(self, widget=None, eve=None): - self._event_system.push_gui_event([self._plugin_name, "get_current_state", ()]) - self._run_timeout() + self._fm_event_system.push_gui_event([self._plugin_name, "get_current_state", ()]) + while not self._fm_event_message: + pass - if self._message: - state = self._message - subprocess.Popen([f'{self.SCRIPT_PTH}/download.sh' , state.tab.get_current_directory()]) - self._message = None + state = self._fm_event_message + subprocess.Popen([f'{self.SCRIPT_PTH}/download.sh' , state.tab.get_current_directory()]) + self._fm_event_message = None - def set_message(self, data): - self._message = data - def get_plugin_name(self): return self._plugin_name - def _run_timeout(self): - timeout = 0 - while not self._message and timeout < self._time_out: - time.sleep(1) - timeout += 1 + def get_plugin_author(self): + return self._plugin_author + + def get_plugin_version(self): + return self._plugin_version 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 e690fe3..ae1c305 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py @@ -15,17 +15,17 @@ class EventSystem(IPCServer): def __init__(self): super(EventSystem, self).__init__() - # NOTE: The format used is list of [type, target, (data,)] Where: - # type is useful context for control flow, - # target is the method to call, - # data is the method parameters to give + # 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 = [] - # Makeshift fake "events" type system FIFO + # Makeshift "events" system FIFO def _pop_gui_event(self) -> None: if len(self._gui_events) > 0: return self._gui_events.pop(0) @@ -42,20 +42,20 @@ class EventSystem(IPCServer): self._gui_events.append(event) return None - raise Exception("Invald event format! Please do: [type, target, (data,)]") + raise Exception("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 Exception("Invald event format! Please do: [type, target, (data,)]") + raise Exception("Invald event format! Please do: ['target_id': str, method_target: method, (data,): any]") def read_gui_event(self) -> list: - return self._gui_events[0] + return self._gui_events[0] if self._gui_events else None def read_module_event(self) -> list: - return self._module_events[0] + return self._module_events[0] if self._module_events else None def consume_gui_event(self) -> list: return self._pop_gui_event() @@ -69,6 +69,6 @@ class EventSystem(IPCServer): # __builtins__.update({"event_system": Builtins()}) builtins.app_name = "SolarFM" builtins.event_system = EventSystem() -builtins.event_sleep_time = 0.2 +builtins.event_sleep_time = 0.05 builtins.trace_debug = False builtins.debug = False diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py index aefcd5e..bedf202 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py @@ -17,7 +17,7 @@ class Application(EventSystem): def __init__(self, args, unknownargs): if not trace_debug: event_system.create_ipc_listener() - time.sleep(0.1) + time.sleep(0.05) if not event_system.is_ipc_alive: if unknownargs: 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 5b40296..4e0491a 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 @@ -1,5 +1,5 @@ # Python imports -import os, gc, threading, time, shlex +import os, gc, threading, time # Lib imports import gi @@ -14,7 +14,14 @@ from .signals.keyboard_signals_mixin import KeyboardSignalsMixin from .controller_data import Controller_Data +# NOTE: Threads will not die with parent's destruction def threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start() + return wrapper + +# NOTE: Insure threads die with parent's destruction +def daemon_threaded(fn): def wrapper(*args, **kwargs): threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start() return wrapper @@ -62,20 +69,20 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi event = event_system.consume_gui_event() if event: try: - type, target, data = event - if type: - method = getattr(self.__class__, "handle_gui_event_and_set_message") - GLib.idle_add(method, *(self, type, target, data)) + 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__, target) - GLib.idle_add(method, *(self, *data,)) + method = getattr(self.__class__, method_target) + GLib.idle_add(method, *(self, *parameters,)) except Exception as e: print(repr(e)) - def handle_gui_event_and_set_message(self, type, target, parameters): - method = getattr(self.__class__, f"{target}") + def handle_gui_event_and_return_message(self, sender, method_target, parameters): + method = getattr(self.__class__, f"{method_target}") data = method(*(self, *parameters)) - self.plugins.send_message_to_plugin(type, data) + event_system.push_module_event([sender, None, data]) def save_load_session(self, action="save_session"): wid, tid = self.fm_controller.get_active_wid_and_tid() @@ -110,7 +117,7 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi def load_session(self, session_json): if debug: - print(f"Session Data: {session_json}") + self.logger.debug(f"Session Data: {session_json}") self.ctrl_down = False self.shift_down = False @@ -186,5 +193,4 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi def open_terminal(self, widget=None, eve=None): wid, tid = self.fm_controller.get_active_wid_and_tid() tab = self.get_fm_window(wid).get_tab_by_id(tid) - dir = tab.get_current_directory() - tab.execute([f"{tab.terminal_app}"], start_dir=shlex.quote(dir)) + tab.execute([f"{tab.terminal_app}"], start_dir=tab.get_current_directory()) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/widget_file_action_mixin.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/widget_file_action_mixin.py index 7421555..84005de 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/widget_file_action_mixin.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/widget_file_action_mixin.py @@ -45,7 +45,7 @@ class WidgetFileActionMixin: watcher = tab.get_dir_watcher() watcher.cancel() if debug: - print(f"Watcher Is Cancelled: {watcher.is_cancelled()}") + self.logger.debug(f"Watcher Is Cancelled: {watcher.is_cancelled()}") cur_dir = tab.get_current_directory() @@ -64,7 +64,7 @@ class WidgetFileActionMixin: Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.MOVED_OUT]: if debug: - print(eve_type) + self.logger.debug(eve_type) if eve_type in [Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.MOVED_OUT]: self.update_on_soft_lock_end(data[0]) @@ -85,7 +85,6 @@ class WidgetFileActionMixin: if (current_time - last_update_time) > 0.6: lock = False - self.soft_update_lock.pop(tab_widget, None) GLib.idle_add(self.update_on_soft_lock_end, *(tab_widget,)) @@ -427,10 +426,10 @@ class WidgetFileActionMixin: start = "-copy" if debug: - print(f"Path: {full_path}") - print(f"Base Path: {base_path}") - print(f'Name: {file_name}') - print(f"Extension: {extension}") + self.logger.debug(f"Path: {full_path}") + self.logger.debug(f"Base Path: {base_path}") + self.logger.debug(f'Name: {file_name}') + self.logger.debug(f"Extension: {extension}") i = 2 while target.query_exists(): diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins.py index c28817b..92cf234 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins.py @@ -12,6 +12,8 @@ from gi.repository import Gtk, Gio class Plugin: name: str = None + author: str = None + version: str = None module: str = None reference: type = None @@ -61,6 +63,9 @@ class Plugins: plugin_reference = app.Plugin(self._builder, event_system) plugin = Plugin() plugin.name = plugin_reference.get_plugin_name() + plugin.author = plugin_reference.get_plugin_author() + plugin.version = plugin_reference.get_plugin_version() + plugin.module = path plugin.reference = plugin_reference @@ -74,10 +79,3 @@ class Plugins: def reload_plugins(self, file: str = None) -> None: print(f"Reloading plugins... stub.") - - def send_message_to_plugin(self, target: str , data: type) -> None: - print("Trying to send message to plugin...") - for plugin in self._plugin_collection: - if target in plugin.name: - print('Found plugin; posting message...') - plugin.reference.set_message(data) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/utils/launcher.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/utils/launcher.py index 7ad1d23..eab19cd 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/utils/launcher.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/utils/launcher.py @@ -59,7 +59,7 @@ class Launcher: app_info.launch_uris_async(uris) def remux_video(self, hash, file): - remux_vid_pth = self.REMUX_FOLDER + "/" + hash + ".mp4" + remux_vid_pth = "{self.REMUX_FOLDER}/{hash}.mp4" self.logger.debug(remux_vid_pth) if not os.path.isfile(remux_vid_pth): diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/logger.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/logger.py index 63db6e2..c33444f 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/logger.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/logger.py @@ -5,39 +5,39 @@ import os, logging class Logger: - def __init__(self, config_path: str): - self._CONFIG_PATH = config_path - - def get_logger(self, loggerName: str = "NO_LOGGER_NAME_PASSED", createFile: bool = True) -> logging.Logger: - """ - Create a new logging object and return it. - :note: - NOSET # Don't know the actual log level of this... (defaulting or literally none?) - Log Levels (From least to most) + """ + Create a new logging object and return it. + :note: + NOSET # Don't know the actual log level of this... (defaulting or literally none?) + Log Levels (From least to most) Type Value CRITICAL 50 ERROR 40 WARNING 30 INFO 20 DEBUG 10 - :param loggerName: Sets the name of the logger object. (Used in log lines) - :param createFile: Whether we create a log file or just pump to terminal + :param loggerName: Sets the name of the logger object. (Used in log lines) + :param createFile: Whether we create a log file or just pump to terminal - :return: the logging object we created - """ + :return: the logging object we created + """ - globalLogLvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels - chLogLevel = logging.CRITICAL # Prety musch the only one we change ever - fhLogLevel = logging.DEBUG + def __init__(self, config_path: str, _ch_log_lvl = logging.CRITICAL, _fh_log_lvl = logging.INFO): + self._CONFIG_PATH = config_path + self.global_lvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels + self.ch_log_lvl = _ch_log_lvl # Prety much the only one we ever change + self.fh_log_lvl = _fh_log_lvl + + def get_logger(self, loggerName: str = "NO_LOGGER_NAME_PASSED", createFile: bool = True) -> logging.Logger: log = logging.getLogger(loggerName) - log.setLevel(globalLogLvl) + log.setLevel(self.global_lvl) # Set our log output styles fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S') cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s') ch = logging.StreamHandler() - ch.setLevel(level=chLogLevel) + ch.setLevel(level=self.ch_log_lvl) ch.setFormatter(cFormatter) log.addHandler(ch) @@ -49,7 +49,7 @@ class Logger: os.mkdir(folder) fh = logging.FileHandler(file) - fh.setLevel(level=fhLogLevel) + fh.setLevel(level=self.fh_log_lvl) fh.setFormatter(fFormatter) log.addHandler(fh) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/settings.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/settings.py index 6d93e77..80bbc01 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/settings.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/settings.py @@ -59,7 +59,7 @@ class Settings: self._keybindings.configure(keybindings) self._main_window = None - self._logger = Logger(self._CONFIG_PATH).get_logger() + self._logger = Logger(self._CONFIG_PATH, _fh_log_lvl=20).get_logger() self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE)