From e96d9e682db34ff0c8b1f416cf9cc4355c93e89d Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sun, 9 Oct 2022 20:59:44 -0500 Subject: [PATCH] Rewired settings, improved plugin structural coupling, cleanedup session file generation n load --- plugins/README.md | 24 +------ plugins/favorites/plugin.py | 12 ++-- plugins/file_properties/plugin.py | 11 ++- plugins/movie_tv_info/plugin.py | 11 ++- plugins/movie_tv_info/tmdbscraper/__init__.py | 3 + plugins/searcher/mixins/file_search_mixin.py | 8 ++- plugins/searcher/mixins/grep_search_mixin.py | 10 ++- plugins/searcher/plugin.py | 14 ++-- plugins/searcher/utils/ipc_server.py | 10 ++- plugins/searcher/utils/search.py | 68 +++++++++++-------- plugins/template/plugin.py | 2 +- plugins/trasher/plugin.py | 18 +++-- plugins/vod_thumbnailer/plugin.py | 12 ++-- plugins/youtube_download/plugin.py | 5 +- .../SolarFM/solarfm/__builtins__.py | 8 +-- .../solarfm-0.0.1/SolarFM/solarfm/__main__.py | 4 ++ .../solarfm-0.0.1/SolarFM/solarfm/app.py | 13 ++-- .../SolarFM/solarfm/core/controller.py | 22 +++--- .../SolarFM/solarfm/core/controller_data.py | 20 +++--- .../solarfm/core/mixins/ui/grid_mixin.py | 2 +- .../solarfm/core/mixins/ui/pane_mixin.py | 3 +- .../solarfm/core/mixins/ui/tab_mixin.py | 15 ++-- .../mixins/ui/widget_file_action_mixin.py | 18 ++--- .../solarfm/core/mixins/ui/window_mixin.py | 6 +- .../core/signals/keyboard_signals_mixin.py | 5 +- .../SolarFM/solarfm/plugins/plugin_base.py | 30 +++++++- .../solarfm/plugins/plugins_controller.py | 11 ++- .../solarfm/shellfm/windows/controller.py | 18 +++-- .../tabs/icons/mixins/xdg/IconTheme.py | 6 +- .../SolarFM/solarfm/utils/ipc_server.py | 2 +- .../SolarFM/solarfm/utils/settings.py | 13 ++++ 31 files changed, 232 insertions(+), 172 deletions(-) create mode 100644 plugins/movie_tv_info/tmdbscraper/__init__.py diff --git a/plugins/README.md b/plugins/README.md index 45cabc0..1f18e50 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -25,7 +25,7 @@ requests: {} = { 'pass_fm_events': "true", # If empty or not present will be ignored. "pass_ui_objects": [""], # Request reference to a UI component. Will be passed back as array to plugin. 'bind_keys': [f"{name}||send_message:f"], - f"{name}||do_save:s"] # Bind keys with method and key pare using list. Must pass "name" like shown with delimiter to its right. + f"{name}||do_save:s"] # Bind keys with method and key pare using list. Must pass "name" like shown with delimiter to its right. } ``` @@ -40,25 +40,3 @@ UI Targets:
  • context_menu
  • other
  • - -### Methods -``` -# Must define and return a widget if "ui_target" is defined. -def get_ui_element(self): - button = Gtk.Button(label=self.name) - button.connect("button-release-event", self._do_download) - return button - -# Must define in plugin if "pass_fm_events" is set to "true" string. -def set_fm_event_system(self, fm_event_system): - self._fm_event_system = fm_event_system - -# Must define regardless if needed. Can just pass if plugin does stuff in its __init__ -def run(self): - self._module_event_observer() - -# Must define in plugin if "pass_ui_objects" is set and an array of valid glade UI IDs. -def set_ui_object_collection(self, ui_objects): - self._ui_objects = ui_objects - -``` diff --git a/plugins/favorites/plugin.py b/plugins/favorites/plugin.py index 3a68f05..e55fe8a 100644 --- a/plugins/favorites/plugin.py +++ b/plugins/favorites/plugin.py @@ -41,11 +41,6 @@ class Plugin(PluginBase): self._selected = None - def get_ui_element(self): - button = Gtk.Button(label=self.name) - button.connect("button-release-event", self._show_favorites_menu) - return button - def run(self): self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -76,9 +71,14 @@ class Plugin(PluginBase): f.write('[]') + def generate_reference_ui_element(self): + button = Gtk.Button(label=self.name) + button.connect("button-release-event", self._show_favorites_menu) + return button + @threaded def _get_state(self, widget=None, eve=None): - self._event_system.emit("get_current_state + self._event_system.emit("get_current_state") @threaded diff --git a/plugins/file_properties/plugin.py b/plugins/file_properties/plugin.py index 2cb6262..ec41032 100644 --- a/plugins/file_properties/plugin.py +++ b/plugins/file_properties/plugin.py @@ -83,11 +83,6 @@ class Plugin(PluginBase): } - def get_ui_element(self): - button = Gtk.Button(label=self.name) - button.connect("button-release-event", self._show_properties_page) - return button - def run(self): self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -103,11 +98,15 @@ class Plugin(PluginBase): self._file_owner = self._builder.get_object("file_owner") self._file_group = self._builder.get_object("file_group") + def generate_reference_ui_element(self): + button = Gtk.Button(label=self.name) + button.connect("button-release-event", self._show_properties_page) + return button @threaded def _show_properties_page(self, widget=None, eve=None): - event_system.emit("get_current_state + event_system.emit("get_current_state") state = self._fm_state self._event_message = None diff --git a/plugins/movie_tv_info/plugin.py b/plugins/movie_tv_info/plugin.py index f7f9c3c..3f8459e 100644 --- a/plugins/movie_tv_info/plugin.py +++ b/plugins/movie_tv_info/plugin.py @@ -45,12 +45,6 @@ class Plugin(PluginBase): self._trailer_link = None - - def get_ui_element(self): - button = Gtk.Button(label=self.name) - button.connect("button-release-event", self._show_info_page) - return button - def run(self): self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -75,6 +69,11 @@ class Plugin(PluginBase): self._file_hash = self._builder.get_object("file_hash") self._trailer_link = self._builder.get_object("trailer_link") + def generate_reference_ui_element(self): + button = Gtk.Button(label=self.name) + button.connect("button-release-event", self._show_info_page) + return button + @threaded def _show_info_page(self, widget=None, eve=None): self._event_system.emit("get_current_state") diff --git a/plugins/movie_tv_info/tmdbscraper/__init__.py b/plugins/movie_tv_info/tmdbscraper/__init__.py new file mode 100644 index 0000000..d36fa8c --- /dev/null +++ b/plugins/movie_tv_info/tmdbscraper/__init__.py @@ -0,0 +1,3 @@ +""" + Pligin Module +""" diff --git a/plugins/searcher/mixins/file_search_mixin.py b/plugins/searcher/mixins/file_search_mixin.py index ffcc32a..749cf9d 100644 --- a/plugins/searcher/mixins/file_search_mixin.py +++ b/plugins/searcher/mixins/file_search_mixin.py @@ -1,8 +1,10 @@ # Python imports -import threading, subprocess, signal, time, json, shlex +import threading, subprocess, signal, json, shlex # Lib imports -from gi.repository import GLib +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk, GLib # Application imports from ..widgets.file_preview_widget import FilePreviewWidget @@ -61,6 +63,8 @@ class FileSearchMixin: self._list_proc = subprocess.Popen(command, cwd=self.path, stdin=None, stdout=None, stderr=None) def _load_file_ui(self, data): + Gtk.main_iteration() + if not data in ("", None): jdata = json.loads( data ) target = jdata[0] diff --git a/plugins/searcher/mixins/grep_search_mixin.py b/plugins/searcher/mixins/grep_search_mixin.py index dc8372d..ad5c9da 100644 --- a/plugins/searcher/mixins/grep_search_mixin.py +++ b/plugins/searcher/mixins/grep_search_mixin.py @@ -1,8 +1,10 @@ # Python imports -import threading, subprocess, signal, time, json, shlex +import threading, subprocess, signal, json, shlex # Lib imports -from gi.repository import GLib +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk, GLib # Application imports from ..widgets.grep_preview_widget import GrepPreviewWidget @@ -53,7 +55,7 @@ class GrepSearchMixin: def _exec_grep_query(self, widget=None, eve=None): query = widget.get_text() - if not query in ("", None): + if not query.strip() in ("", None): self.grep_query = query target_dir = shlex.quote( self._fm_state.tab.get_current_directory() ) @@ -61,6 +63,8 @@ class GrepSearchMixin: self._grep_proc = subprocess.Popen(command, cwd=self.path, stdin=None, stdout=None, stderr=None) def _load_grep_ui(self, data): + Gtk.main_iteration() + if not data in ("", None): jdata = json.loads( data ) jkeys = jdata.keys() diff --git a/plugins/searcher/plugin.py b/plugins/searcher/plugin.py index 4b66a63..f941dc9 100644 --- a/plugins/searcher/plugin.py +++ b/plugins/searcher/plugin.py @@ -52,11 +52,6 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase): self.search_query = "" - def get_ui_element(self): - button = Gtk.Button(label=self.name) - button.connect("button-release-event", self._show_page) - return button - def run(self): self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -84,6 +79,11 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase): self.create_ipc_listener() + def generate_reference_ui_element(self): + button = Gtk.Button(label=self.name) + button.connect("button-release-event", self._show_page) + return button + def _show_page(self, widget=None, eve=None): self._event_system.emit("get_current_state") @@ -109,6 +109,8 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase): self.grep_list_parent.add(self._grep_list) self.grep_list_parent.show_all() + Gtk.main_iteration() + def reset_file_list_box(self) -> None: try: child = self.file_list_parent.get_children()[0] @@ -121,3 +123,5 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase): self._file_list.set_orientation(Gtk.Orientation.VERTICAL) self.file_list_parent.add(self._file_list) self.file_list_parent.show_all() + + Gtk.main_iteration() diff --git a/plugins/searcher/utils/ipc_server.py b/plugins/searcher/utils/ipc_server.py index 96969cf..e4ca2aa 100644 --- a/plugins/searcher/utils/ipc_server.py +++ b/plugins/searcher/utils/ipc_server.py @@ -1,11 +1,9 @@ # Python imports -import os, threading, time, pickle +import os, threading, pickle from multiprocessing.connection import Listener, Client # Lib imports -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk, GLib +from gi.repository import GLib # Application imports @@ -64,12 +62,12 @@ class IPCServer: if "SEARCH|" in msg: file = msg.split("SEARCH|")[1].strip() if file: - GLib.idle_add(self._load_file_ui, file) + GLib.idle_add(self._load_file_ui, file, priority=GLib.PRIORITY_LOW) if "GREP|" in msg: data = msg.split("GREP|")[1].strip() if data: - GLib.idle_add(self._load_grep_ui, data) + GLib.idle_add(self._load_grep_ui, data, priority=GLib.PRIORITY_LOW) conn.close() diff --git a/plugins/searcher/utils/search.py b/plugins/searcher/utils/search.py index 5c1efca..692fbc2 100755 --- a/plugins/searcher/utils/search.py +++ b/plugins/searcher/utils/search.py @@ -16,8 +16,9 @@ from multiprocessing.connection import Client _ipc_address = f'/tmp/solarfm-search_grep-ipc.sock' _ipc_authkey = b'' + bytes(f'solarfm-search_grep-ipc', 'utf-8') -filter = (".cpp", ".css", ".c", ".go", ".html", ".htm", ".java", ".js", ".json", ".lua", ".md", ".py", ".rs", ".toml", ".xml", ".pom") + \ - (".txt", ".text", ".sh", ".cfg", ".conf", ".log") +filter = (".mkv", ".mp4", ".webm", ".avi", ".mov", ".m4v", ".mpg", ".mpeg", ".wmv", ".flv") + \ + (".png", ".jpg", ".jpeg", ".gif", ".ico", ".tga", ".webp") + \ + (".psf", ".mp3", ".ogg", ".flac", ".m4a") # NOTE: Threads WILL NOT die with parent's destruction. def threaded(fn): @@ -33,12 +34,12 @@ def daemon_threaded(fn): def send_ipc_message(message) -> None: - with Client(address=_ipc_address, family="AF_UNIX", authkey=_ipc_authkey) as conn: - conn.send(message) - conn.close() + conn = Client(address=_ipc_address, family="AF_UNIX", authkey=_ipc_authkey) + conn.send(message) + conn.close() # NOTE: Kinda important as this prevents overloading the UI thread - time.sleep(0.04) + time.sleep(0.05) def file_search(path, query): @@ -57,35 +58,44 @@ def _search_for_string(file, query): b64_file = base64.urlsafe_b64encode(file.encode('utf-8')).decode('utf-8') grep_result_set = {} padding = 15 + with open(file, 'r') as fp: # NOTE: I know there's an issue if there's a very large file with content # all on one line will lower and dupe it. And, yes, it will only # return one instance from the file. - for i, raw in enumerate(fp): - line = None - llower = raw.lower() - if not query in llower: - continue + try: + for i, raw in enumerate(fp): + line = None + llower = raw.lower() + if not query in llower: + continue - if len(raw) > 72: - start = 0 - end = len(raw) - 1 - index = llower.index(query) - sindex = llower.index(query) - 15 if index >= 15 else abs(start - index) - index - eindex = sindex + 15 if end > (index + 15) else abs(index - end) + index - line = raw[sindex:eindex] - else: - line = raw + if len(raw) > 72: + start = 0 + end = len(raw) - 1 + index = llower.index(query) + sindex = llower.index(query) - 15 if index >= 15 else abs(start - index) - index + eindex = sindex + 15 if end > (index + 15) else abs(index - end) + index + line = raw[sindex:eindex] + else: + line = raw - b64_line = base64.urlsafe_b64encode(line.encode('utf-8')).decode('utf-8') - if f"{b64_file}" in grep_result_set.keys(): - grep_result_set[f"{b64_file}"][f"{i+1}"] = b64_line - else: - grep_result_set[f"{b64_file}"] = {} - grep_result_set[f"{b64_file}"] = {f"{i+1}": b64_line} + b64_line = base64.urlsafe_b64encode(line.encode('utf-8')).decode('utf-8') + if f"{b64_file}" in grep_result_set.keys(): + grep_result_set[f"{b64_file}"][f"{i+1}"] = b64_line + else: + grep_result_set[f"{b64_file}"] = {} + grep_result_set[f"{b64_file}"] = {f"{i+1}": b64_line} + + except Exception as e: + ... + + try: + data = f"GREP|{json.dumps(grep_result_set)}" + send_ipc_message(data) + except Exception as e: + ... - data = f"GREP|{json.dumps(grep_result_set)}" - send_ipc_message(data) @daemon_threaded @@ -99,7 +109,7 @@ def grep_search(path, query): if os.path.isdir(target): grep_search(target, query) else: - if target.lower().endswith(filter): + if not target.lower().endswith(filter): size = os.path.getsize(target) if not size > 5000: _search_for_string(target, query) diff --git a/plugins/template/plugin.py b/plugins/template/plugin.py index dff5d40..5535f4d 100644 --- a/plugins/template/plugin.py +++ b/plugins/template/plugin.py @@ -33,7 +33,7 @@ class Plugin(PluginBase): # where self.name should not be needed for message comms - def get_ui_element(self): + def generate_reference_ui_element(self): button = Gtk.Button(label=self.name) button.connect("button-release-event", self.send_message) return button diff --git a/plugins/trasher/plugin.py b/plugins/trasher/plugin.py index cbfe70d..78cc759 100644 --- a/plugins/trasher/plugin.py +++ b/plugins/trasher/plugin.py @@ -39,7 +39,14 @@ class Plugin(PluginBase): self.trashman.regenerate() - def get_ui_element(self): + + def run(self): + self._event_system.subscribe("show_trash_buttons", self._show_trash_buttons) + self._event_system.subscribe("hide_trash_buttons", self._hide_trash_buttons) + self._event_system.subscribe("delete_files", self.delete_files) + self._event_system.subscribe("trash_files", self.trash_files) + + def generate_reference_ui_element(self): self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -61,10 +68,6 @@ class Plugin(PluginBase): return trasher - def run(self): - self._event_system.subscribe("show_trash_buttons", self._show_trash_buttons) - self._event_system.subscribe("hide_trash_buttons", self._hide_trash_buttons) - def _show_trash_buttons(self): self._builder.get_object("restore_from_trash").show() self._builder.get_object("empty_trash").show() @@ -74,6 +77,7 @@ class Plugin(PluginBase): self._builder.get_object("empty_trash").hide() def delete_files(self, widget = None, eve = None): + self._event_system.emit("do_hide_context_menu") self._event_system.emit("get_current_state") state = self._fm_state uris = state.selected_files @@ -97,19 +101,23 @@ class Plugin(PluginBase): break def trash_files(self, widget = None, eve = None, verbocity = False): + self._event_system.emit("do_hide_context_menu") self._event_system.emit("get_current_state") state = self._fm_state for uri in state.selected_files: self.trashman.trash(uri, verbocity) def restore_trash_files(self, widget = None, eve = None, verbocity = False): + self._event_system.emit("do_hide_context_menu") self._event_system.emit("get_current_state") state = self._fm_state for uri in state.selected_files: self.trashman.restore(filename=uri.split("/")[-1], verbose = verbocity) def empty_trash(self, widget = None, eve = None, verbocity = False): + self._event_system.emit("do_hide_context_menu") self.trashman.empty(verbose = verbocity) def go_to_trash(self, widget = None, eve = None, verbocity = False): + self._event_system.emit("do_hide_context_menu") self._event_system.emit("go_to_path", self.trash_files_path) diff --git a/plugins/vod_thumbnailer/plugin.py b/plugins/vod_thumbnailer/plugin.py index c74f551..e730797 100644 --- a/plugins/vod_thumbnailer/plugin.py +++ b/plugins/vod_thumbnailer/plugin.py @@ -44,11 +44,6 @@ class Plugin(PluginBase): self._file_hash = None - def get_ui_element(self): - button = Gtk.Button(label=self.name) - button.connect("button-release-event", self._show_thumbnailer_page) - return button - def run(self): self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) @@ -72,10 +67,15 @@ class Plugin(PluginBase): self._thumbnail_preview_img = self._builder.get_object("thumbnail_preview_img") self._file_hash = self._builder.get_object("file_hash") + def generate_reference_ui_element(self): + button = Gtk.Button(label=self.name) + button.connect("button-release-event", self._show_thumbnailer_page) + return button + @threaded def _show_thumbnailer_page(self, widget=None, eve=None): - self._event_system.emit("get_current_state + self._event_system.emit("get_current_state") state = self._fm_state self._event_message = None diff --git a/plugins/youtube_download/plugin.py b/plugins/youtube_download/plugin.py index da13c75..1b4ce50 100644 --- a/plugins/youtube_download/plugin.py +++ b/plugins/youtube_download/plugin.py @@ -33,8 +33,7 @@ class Plugin(PluginBase): self.name = "Youtube Download" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus # where self.name should not be needed for message comms - - def get_ui_element(self): + def generate_reference_ui_element(self): button = Gtk.Button(label=self.name) button.connect("button-release-event", self._do_download) return button @@ -44,7 +43,7 @@ class Plugin(PluginBase): def _do_download(self, widget=None, eve=None): - self._event_system.emit("get_current_state + self._event_system.emit("get_current_state") dir = self._fm_state.tab.get_current_directory() self._download(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 428f16f..9ed03c8 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py @@ -6,7 +6,7 @@ import builtins, threading # Application imports from utils.event_system import EventSystem from utils.endpoint_registry import EndpointRegistry - +from utils.settings import Settings @@ -28,11 +28,11 @@ def daemon_threaded_wrapper(fn): # NOTE: Just reminding myself we can add to builtins two different ways... # __builtins__.update({"event_system": Builtins()}) builtins.app_name = "SolarFM" +builtins.settings = Settings() +builtins.logger = settings.get_logger() builtins.event_system = EventSystem() builtins.endpoint_registry = EndpointRegistry() + builtins.threaded = threaded_wrapper builtins.daemon_threaded = daemon_threaded_wrapper builtins.event_sleep_time = 0.05 -builtins.trace_debug = False -builtins.debug = False -builtins.app_settings = None diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/__main__.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/__main__.py index 2dfcfe2..9bfffcb 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/__main__.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/__main__.py @@ -15,6 +15,7 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports +from __builtins__ import * from app import Application @@ -27,6 +28,9 @@ if __name__ == "__main__": parser = argparse.ArgumentParser() # Add long and short arguments + parser.add_argument("--debug", "-d", default="false", help="Do extra console messaging.") + parser.add_argument("--trace-debug", "-td", default="false", help="Disable saves, ignore IPC lock, do extra console messaging.") + parser.add_argument("--new-tab", "-t", default="", help="Open a file into new tab.") parser.add_argument("--new-window", "-w", default="", help="Open a file into a new window.") # Read arguments (If any...) 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 a16c779..7df637a 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py @@ -4,7 +4,7 @@ import os, inspect, time # Lib imports # Application imports -from __builtins__ import * + from utils.ipc_server import IPCServer from utils.settings import Settings from core.controller import Controller @@ -22,8 +22,14 @@ class Application(IPCServer): def __init__(self, args, unknownargs): super(Application, self).__init__() + if args.debug == "true": + settings.set_debug(True) - if not trace_debug: + if args.trace_debug == "true": + settings.set_trace_debug(True) + + # NOTE: Instance found, sending files to it... + if not settings.is_trace_debug(): self.create_ipc_listener() time.sleep(0.05) @@ -41,10 +47,9 @@ class Application(IPCServer): raise AppLaunchException(f"IPC Server Exists: Will send path(s) to it and close...\nNote: If no fm exists, remove /tmp/{app_name}-ipc.sock") - settings = Settings() settings.create_window() - controller = Controller(args, unknownargs, settings) + controller = Controller(args, unknownargs) if not controller: raise ControllerStartExceptio("Controller exited and doesn't exist...") 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 c034bd3..428edb4 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 @@ -18,18 +18,18 @@ from .controller_data import Controller_Data class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMixin, Controller_Data): """ Controller coordinates the mixins and is somewhat the root hub of it all. """ - def __init__(self, args, unknownargs, _settings): - self.setup_controller_data(_settings) + def __init__(self, args, unknownargs): + self.setup_controller_data() self.window.show() self.generate_windows(self.fm_controller_data) self.plugins.launch_plugins() - if debug: + if settings.is_debug(): self.window.set_interactive_debugging(True) - - if not trace_debug: + # NOTE: Open files if passed in from cli and not trace debugging... + if not settings.is_trace_debug(): self._subscribe_to_events() if unknownargs: @@ -51,7 +51,9 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi event_system.subscribe("do_hide_context_menu", self.do_hide_context_menu) def tear_down(self, widget=None, eve=None): - self.fm_controller.save_state() + if not settings.is_trace_debug(): + self.fm_controller.save_state() + time.sleep(event_sleep_time) Gtk.main_quit() @@ -62,7 +64,9 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi save_load_dialog = self.builder.get_object("save_load_dialog") if action == "save_session": - self.fm_controller.save_state() + if not settings.is_trace_debug(): + self.fm_controller.save_state() + return elif action == "save_session_as": save_load_dialog.set_action(Gtk.FileChooserAction.SAVE) @@ -88,8 +92,8 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi save_load_dialog.hide() def load_session(self, session_json): - if debug: - self.logger.debug(f"Session Data: {session_json}") + if settings.is_debug(): + logger.debug(f"Session Data: {session_json}") self.ctrl_down = False self.shift_down = False 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 3e69f9f..14524e0 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 @@ -28,17 +28,15 @@ class Controller_Data: """ Controller_Data contains most of the state of the app at ay given time. It also has some support methods. """ __slots__ = "settings", "builder", "logger", "keybindings", "trashman", "fm_controller", "window", "window1", "window2", "window3", "window4" - def setup_controller_data(self, _settings: type) -> None: - self.settings = _settings - self.builder = self.settings.get_builder() - self.logger = self.settings.get_logger() - self.keybindings = self.settings.get_keybindings() + def setup_controller_data(self) -> None: + self.builder = settings.get_builder() + self.keybindings = settings.get_keybindings() self.fm_controller = WindowController() - self.plugins = PluginsController(_settings) + self.plugins = PluginsController() self.fm_controller_data = self.fm_controller.get_state_from_file() - self.window = self.settings.get_main_window() + self.window = settings.get_main_window() self.window1 = self.builder.get_object("window_1") self.window2 = self.builder.get_object("window_2") self.window3 = self.builder.get_object("window_3") @@ -64,7 +62,7 @@ class Controller_Data: self.trash_files_path = f"{GLib.get_user_data_dir()}/Trash/files" self.trash_info_path = f"{GLib.get_user_data_dir()}/Trash/info" - self.icon_theme = self.settings.get_icon_theme() + self.icon_theme = settings.get_icon_theme() # In compress commands: # %n: First selected filename/dir to archive @@ -116,9 +114,9 @@ class Controller_Data: self.shift_down = False self.alt_down = False - self.success_color = self.settings.get_success_color() - self.warning_color = self.settings.get_warning_color() - self.error_color = self.settings.get_error_color() + self.success_color = settings.get_success_color() + self.warning_color = settings.get_warning_color() + self.error_color = settings.get_error_color() # sys.excepthook = self.custom_except_hook self.window.connect("delete-event", self.tear_down) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/grid_mixin.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/grid_mixin.py index 2d3afeb..c93a3ca 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/grid_mixin.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/grid_mixin.py @@ -61,7 +61,7 @@ class GridMixin: self.create_icon(i, tab, store, dir, file[0]) # NOTE: Not likely called often from here but it could be useful - if save_state: + if save_state and not trace_debug: self.fm_controller.save_state() @threaded diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/pane_mixin.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/pane_mixin.py index 3d2c888..380efa7 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/pane_mixin.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/pane_mixin.py @@ -56,4 +56,5 @@ class PaneMixin: def _save_state(self, state, pane_index): window = self.fm_controller.get_window_by_index(pane_index - 1) window.set_is_hidden(state) - self.fm_controller.save_state() + if not settings.is_trace_debug(): + self.fm_controller.save_state() diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/tab_mixin.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/tab_mixin.py index 539f840..683e6b4 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/tab_mixin.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/tab_mixin.py @@ -22,7 +22,7 @@ class TabMixin(GridMixin): notebook = self.builder.get_object(f"window_{wid}") path_entry = self.builder.get_object(f"path_entry") tab = self.fm_controller.add_tab_for_window_by_nickname(f"window_{wid}") - tab.logger = self.logger + tab.logger = logger tab.set_wid(wid) if not path: @@ -63,7 +63,8 @@ class TabMixin(GridMixin): watcher.cancel() self.get_fm_window(wid).delete_tab_by_id(tid) notebook.remove_page(page) - self.fm_controller.save_state() + if not settings.is_trace_debug(): + self.fm_controller.save_state() self.set_window_title() def on_tab_reorder(self, child, page_num, new_index): @@ -80,7 +81,8 @@ class TabMixin(GridMixin): tab = window.get_tab_by_id(tid) self.set_file_watcher(tab) - self.fm_controller.save_state() + if not settings.is_trace_debug(): + self.fm_controller.save_state() def on_tab_switch_update(self, notebook, content=None, index=None): self.selected_files.clear() @@ -115,7 +117,8 @@ class TabMixin(GridMixin): tab_label.set_label(tab.get_end_of_path()) self.set_window_title() self.set_file_watcher(tab) - self.fm_controller.save_state() + if not settings.is_trace_debug(): + self.fm_controller.save_state() def do_action_from_bar_controls(self, widget, eve=None): action = widget.get_name() @@ -127,7 +130,9 @@ class TabMixin(GridMixin): if action == "create_tab": dir = tab.get_current_directory() self.create_tab(wid, None, dir) - self.fm_controller.save_state() + if not settings.is_trace_debug(): + self.fm_controller.save_state() + return if action == "go_up": tab.pop_from_path() 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 0058147..e680801 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 @@ -40,8 +40,8 @@ class WidgetFileActionMixin: if tab.get_dir_watcher(): watcher = tab.get_dir_watcher() watcher.cancel() - if debug: - self.logger.debug(f"Watcher Is Cancelled: {watcher.is_cancelled()}") + if settings.is_debug(): + logger.debug(f"Watcher Is Cancelled: {watcher.is_cancelled()}") cur_dir = tab.get_current_directory() @@ -59,8 +59,8 @@ class WidgetFileActionMixin: if eve_type in [Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED, Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.MOVED_OUT]: - if debug: - self.logger.debug(eve_type) + if settings.is_debug(): + logger.debug(eve_type) if eve_type in [Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.MOVED_OUT]: self.update_on_soft_lock_end(data[0]) @@ -389,11 +389,11 @@ class WidgetFileActionMixin: target = Gio.File.new_for_path(full_path) start = "-copy" - if debug: - 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}") + if settings.is_debug(): + logger.debug(f"Path: {full_path}") + logger.debug(f"Base Path: {base_path}") + logger.debug(f'Name: {file_name}') + logger.debug(f"Extension: {extension}") i = 2 while target.query_exists(): diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/window_mixin.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/window_mixin.py index 2ab6be1..fddb9d3 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/window_mixin.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/window_mixin.py @@ -24,8 +24,8 @@ class WindowMixin(TabMixin): for j, value in enumerate(session_json): i = j + 1 notebook_tggl_button = self.builder.get_object(f"tggl_notebook_{i}") - is_hidden = True if value[0]["window"]["isHidden"] == "True" else False - tabs = value[0]["window"]["tabs"] + is_hidden = True if value["window"]["isHidden"] == "True" else False + tabs = value["window"]["tabs"] self.fm_controller.create_window() notebook_tggl_button.set_active(True) @@ -112,7 +112,7 @@ class WindowMixin(TabMixin): file_size = file_info.get_size() combined_size += file_size except WindowException as e: - if debug: + if settings.is_debug(): print(repr(e)) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/signals/keyboard_signals_mixin.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/signals/keyboard_signals_mixin.py index e4151f8..bde0689 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/signals/keyboard_signals_mixin.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/signals/keyboard_signals_mixin.py @@ -55,7 +55,7 @@ class KeyboardSignalsMixin: sender, eve_type = mapping.split("||") self.handle_plugin_key_event(sender, eve_type) else: - if debug: + if settings.is_debug(): print(f"on_global_key_release_controller > key > {keyname}") if self.ctrl_down: @@ -91,5 +91,6 @@ class KeyboardSignalsMixin: self.get_fm_window(wid).delete_tab_by_id(tid) notebook.remove_page(page) - self.fm_controller.save_state() + if not trace_debug: + self.fm_controller.save_state() self.set_window_title() 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 effd377..44aec62 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 @@ -6,6 +6,10 @@ import os, time # Application imports +class PluginBaseException(Exception): + ... + + class PluginBase: def __init__(self): self.name = "Example Plugin" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus @@ -18,14 +22,23 @@ class PluginBase: def set_fm_event_system(self, fm_event_system): + """ + Requests Key: 'pass_fm_events': "true" + Must define in plugin if "pass_fm_events" is set to "true" string. + """ self._event_system = fm_event_system def set_ui_object_collection(self, ui_objects): + """ + Requests Key: "pass_ui_objects": [""] + Request reference to a UI component. Will be passed back as array to plugin. + Must define in plugin if set and an array of valid glade UI IDs is given. + """ self._ui_objects = ui_objects def clear_children(self, widget: type) -> None: - ''' Clear children of a gtk widget. ''' + """ Clear children of a gtk widget. """ for child in widget.get_children(): widget.remove(child) @@ -34,3 +47,18 @@ class PluginBase: def _update_fm_state_info(self, state): self._fm_state = state + + def generate_reference_ui_element(self): + """ + Requests Key: 'ui_target': "plugin_control_list", + Must define regardless if needed and can 'pass' if plugin doesn't use it. + Must return a widget if "ui_target" is set. + """ + raise PluginBaseException("Method hasn't been overriden...") + + def run(self): + """ + Must define regardless if needed and can 'pass' if plugin doesn't need it. + Is intended to be used to setup internal signals or custom Gtk Builders/UI logic. + """ + raise PluginBaseException("Method hasn't been overriden...") 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 63cccfe..41adcef 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 @@ -20,14 +20,13 @@ class InvalidPluginException(Exception): class PluginsController: """PluginsController controller""" - def __init__(self, settings: type): + def __init__(self): path = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, path) # NOTE: I think I'm not using this correctly... - self._settings = settings - self._builder = self._settings.get_builder() - self._plugins_path = self._settings.get_plugins_path() - self._keybindings = self._settings.get_keybindings() + self._builder = settings.get_builder() + self._plugins_path = settings.get_plugins_path() + self._keybindings = settings.get_keybindings() self._plugins_dir_watcher = None self._plugin_collection = [] @@ -95,7 +94,7 @@ class PluginsController: keys = loading_data.keys() if "ui_target" in keys: - loading_data["ui_target"].add( plugin.reference.get_ui_element() ) + loading_data["ui_target"].add( plugin.reference.generate_reference_ui_element() ) loading_data["ui_target"].show_all() if "pass_ui_objects" in keys: diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/controller.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/controller.py index abec786..f2b0e16 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/controller.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/controller.py @@ -158,17 +158,15 @@ class WindowController: tabs.append(tab.get_current_directory()) windows.append( - [ - { - 'window':{ - "ID": window.get_id(), - "Name": window.get_name(), - "Nickname": window.get_nickname(), - "isHidden": f"{window.is_hidden()}", - 'tabs': tabs - } + { + 'window':{ + "ID": window.get_id(), + "Name": window.get_name(), + "Nickname": window.get_nickname(), + "isHidden": f"{window.is_hidden()}", + 'tabs': tabs } - ] + } ) with open(session_file, 'w') as outfile: diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/mixins/xdg/IconTheme.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/mixins/xdg/IconTheme.py index 2ff3c05..61ee2c3 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/mixins/xdg/IconTheme.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/mixins/xdg/IconTheme.py @@ -322,10 +322,8 @@ def getIconPath(iconname, size = None, theme = None, extensions = ["png", "svg", icon_cache[tmp] = [time.time(), icon] return icon except UnicodeDecodeError as e: - if debug: - raise e - else: - pass + ... + # we haven't found anything? "hicolor" is our fallback if theme != "hicolor": 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 f71691b..5aa0ebd 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 @@ -59,7 +59,7 @@ class IPCServer: def handle_message(self, conn, start_time) -> None: while True: msg = conn.recv() - if debug: + if settings.is_debug(): print(msg) if "FILE|" in msg: 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 3826e3d..0967a25 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 @@ -63,6 +63,9 @@ class Settings: self._builder = Gtk.Builder() self._builder.add_from_file(self._GLADE_FILE) + self._trace_debug = False + self._debug = False + def create_window(self) -> None: # Get window and connect signals @@ -111,3 +114,13 @@ class Settings: def get_success_color(self) -> str: return self._success_color def get_warning_color(self) -> str: return self._warning_color def get_error_color(self) -> str: return self._error_color + + def is_trace_debug(self) -> str: return self._trace_debug + def is_debug(self) -> str: return self._debug + + + def set_trace_debug(self, trace_debug): + self._trace_debug = trace_debug + + def set_debug(self, debug): + self._debug = debug