diff --git a/src/versions/solarfm-0.0.1/solarfm/__builtins__.py b/src/versions/solarfm-0.0.1/solarfm/__builtins__.py index b1d9d84..6ead649 100644 --- a/src/versions/solarfm-0.0.1/solarfm/__builtins__.py +++ b/src/versions/solarfm-0.0.1/solarfm/__builtins__.py @@ -7,12 +7,12 @@ import sys # Application imports from utils.event_system import EventSystem -from utils.endpoint_registry import EndpointRegistry from utils.keybindings import Keybindings from utils.logger import Logger from utils.settings_manager.manager import SettingsManager + # NOTE: Threads WILL NOT die with parent's destruction. def threaded_wrapper(fn): def wrapper(*args, **kwargs): @@ -39,7 +39,6 @@ def sizeof_fmt_def(num, suffix="B"): builtins.app_name = "SolarFM" builtins.keybindings = Keybindings() builtins.event_system = EventSystem() -builtins.endpoint_registry = EndpointRegistry() builtins.settings_manager = SettingsManager() settings_manager.load_settings() @@ -52,7 +51,7 @@ builtins.logger = Logger(settings_manager.get_home_config_path(), \ builtins.threaded = threaded_wrapper builtins.daemon_threaded = daemon_threaded_wrapper builtins.sizeof_fmt = sizeof_fmt_def -builtins.event_sleep_time = 0.05 + def custom_except_hook(exc_type, exc_value, exc_traceback): @@ -62,5 +61,4 @@ def custom_except_hook(exc_type, exc_value, exc_traceback): logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) - sys.excepthook = custom_except_hook diff --git a/src/versions/solarfm-0.0.1/solarfm/app.py b/src/versions/solarfm-0.0.1/solarfm/app.py index e80ab92..2661090 100644 --- a/src/versions/solarfm-0.0.1/solarfm/app.py +++ b/src/versions/solarfm-0.0.1/solarfm/app.py @@ -25,7 +25,7 @@ class Application(IPCServer): try: self.create_ipc_listener() except Exception: - ... + self.socket_realization_check() if not self.is_ipc_alive: for arg in unknownargs + [args.new_tab,]: @@ -35,6 +35,16 @@ class Application(IPCServer): raise AppLaunchException(f"{app_name} IPC Server Exists: Will send path(s) to it and close...") + self.setup_debug_hook() + + Window(args, unknownargs) + + + def socket_realization_check(self): + self.send_test_ipc_message() + self.create_ipc_listener() + + def setup_debug_hook(self): try: # kill -SIGUSR2 from Linux/Unix or SIGBREAK signal from Windows signal.signal( @@ -44,5 +54,3 @@ class Application(IPCServer): except ValueError: # Typically: ValueError: signal only works in main thread ... - - Window(args, unknownargs) diff --git a/src/versions/solarfm-0.0.1/solarfm/core/controller.py b/src/versions/solarfm-0.0.1/solarfm/core/controller.py index b07fb5f..a3fbe2a 100644 --- a/src/versions/solarfm-0.0.1/solarfm/core/controller.py +++ b/src/versions/solarfm-0.0.1/solarfm/core/controller.py @@ -65,9 +65,11 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): FileSystemActions() def _subscribe_to_events(self): + event_system.subscribe("shutting_down", self._shutting_down) event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc) event_system.subscribe("generate_file_views", self._generate_file_views) event_system.subscribe("clear_notebooks", self.clear_notebooks) + event_system.subscribe("set_window_title", self._set_window_title) event_system.subscribe("unset_selected_files_views", self._unset_selected_files_views) event_system.subscribe("get_current_state", self.get_current_state) @@ -107,6 +109,10 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): FileExistsWidget() SaveLoadWidget() + def _shutting_down(self): + if not settings_manager.is_trace_debug(): + self.fm_controller.save_state() + def reload_plugins(self, widget=None, eve=None): self.plugins.reload_plugins() @@ -162,28 +168,22 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): event_system.emit("tear_down") - @endpoint_registry.register(rule="go_home") def go_home(self, widget=None, eve=None): self.builder.get_object("go_home").released() - @endpoint_registry.register(rule="refresh_tab") def refresh_tab(self, widget=None, eve=None): self.builder.get_object("refresh_tab").released() - @endpoint_registry.register(rule="go_up") def go_up(self, widget=None, eve=None): self.builder.get_object("go_up").released() - @endpoint_registry.register(rule="grab_focus_path_entry") def grab_focus_path_entry(self, widget=None, eve=None): self.builder.get_object("path_entry").grab_focus() - @endpoint_registry.register(rule="tggl_top_main_menubar") def tggl_top_main_menubar(self, widget=None, eve=None): top_main_menubar = self.builder.get_object("top_main_menubar") top_main_menubar.hide() if top_main_menubar.is_visible() else top_main_menubar.show() - @endpoint_registry.register(rule="open_terminal") 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) diff --git a/src/versions/solarfm-0.0.1/solarfm/core/controller_data.py b/src/versions/solarfm-0.0.1/solarfm/core/controller_data.py index 2605c64..061943a 100644 --- a/src/versions/solarfm-0.0.1/solarfm/core/controller_data.py +++ b/src/versions/solarfm-0.0.1/solarfm/core/controller_data.py @@ -1,7 +1,6 @@ # Python imports import os import subprocess -from dataclasses import dataclass # Lib imports import gi @@ -9,55 +8,13 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports +from .sfm_builder import SFMBuilder from .widgets.dialogs.message_widget import MessageWidget from .widgets.dialogs.user_pass_widget import UserPassWidget -from shellfm.windows.controller import WindowController +from utils.types.state import State from plugins.plugins_controller import PluginsController - - - -@dataclass(slots=True) -class State: - fm_controller: any = None - notebooks: any = None - wid: int = None - tid: int = None - tab: type = None - 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 - message_dialog: type = None - user_pass_dialog: type = None - - - -class SFMBuilder(Gtk.Builder): - """docstring for SFMBuilder.""" - - def __init__(self): - super(SFMBuilder, self).__init__() - - self.objects = {} - - def get_object(self, id: str, use_gtk: bool = True) -> any: - if not use_gtk: - return self.objects[id] - - return super(SFMBuilder, self).get_object(id) - - def expose_object(self, id: str, object: any, use_gtk: bool = True) -> None: - if not use_gtk: - self.objects[id] = object - else: - super(SFMBuilder, self).expose_object(id, object) - - def dereference_object(self, id: str) -> None: - del self.objects[id] +from shellfm.windows.controller import WindowController diff --git a/src/versions/solarfm-0.0.1/solarfm/core/mixins/ui/window_mixin.py b/src/versions/solarfm-0.0.1/solarfm/core/mixins/ui/window_mixin.py index 34ffb8b..3d1d577 100644 --- a/src/versions/solarfm-0.0.1/solarfm/core/mixins/ui/window_mixin.py +++ b/src/versions/solarfm-0.0.1/solarfm/core/mixins/ui/window_mixin.py @@ -85,7 +85,7 @@ class WindowMixin(TabMixin): self.set_window_title() if eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == 1: # l-click - if self.ctrl_down: + if eve.state & Gdk.ModifierType.CONTROL_MASK: self.dnd_left_primed = 0 if self.single_click_open: # FIXME: need to find a way to pass the model index diff --git a/src/versions/solarfm-0.0.1/solarfm/core/sfm_builder.py b/src/versions/solarfm-0.0.1/solarfm/core/sfm_builder.py new file mode 100644 index 0000000..6077bdf --- /dev/null +++ b/src/versions/solarfm-0.0.1/solarfm/core/sfm_builder.py @@ -0,0 +1,33 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports + + + +class SFMBuilder(Gtk.Builder): + """docstring for SFMBuilder.""" + + def __init__(self): + super(SFMBuilder, self).__init__() + + self.objects = {} + + def get_object(self, id: str, use_gtk: bool = True) -> any: + if not use_gtk: + return self.objects[id] + + return super(SFMBuilder, self).get_object(id) + + def expose_object(self, id: str, object: any, use_gtk: bool = True) -> None: + if not use_gtk: + self.objects[id] = object + else: + super(SFMBuilder, self).expose_object(id, object) + + def dereference_object(self, id: str) -> None: + del self.objects[id] diff --git a/src/versions/solarfm-0.0.1/solarfm/core/ui_mixin.py b/src/versions/solarfm-0.0.1/solarfm/core/ui_mixin.py index 4c44c33..f8bb4af 100644 --- a/src/versions/solarfm-0.0.1/solarfm/core/ui_mixin.py +++ b/src/versions/solarfm-0.0.1/solarfm/core/ui_mixin.py @@ -77,7 +77,7 @@ class UIMixin(PaneMixin, WindowMixin): scroll_win = notebook.get_children()[-1] icon_grid = scroll_win.get_children()[0] - self._focus_last_visible_notebook(icon_grid) + # self._focus_last_visible_notebook(icon_grid) except UIMixinException as e: logger.info("\n: The saved session might be missing window data! :\nLocation: ~/.config/solarfm/session.json\nFix: Back it up and delete it to reset.\n") logger.debug(repr(e)) diff --git a/src/versions/solarfm-0.0.1/solarfm/core/widgets/files_view/window_mixin.py b/src/versions/solarfm-0.0.1/solarfm/core/widgets/files_view/window_mixin.py index e8ad629..59a33dc 100644 --- a/src/versions/solarfm-0.0.1/solarfm/core/widgets/files_view/window_mixin.py +++ b/src/versions/solarfm-0.0.1/solarfm/core/widgets/files_view/window_mixin.py @@ -80,7 +80,7 @@ class WindowMixin(TabMixin): self.set_window_title() if eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == 1: # l-click - if self.ctrl_down: + if eve.state & Gdk.ModifierType.CONTROL_MASK: self.dnd_left_primed = 0 if self.single_click_open: # FIXME: need to find a way to pass the model index diff --git a/src/versions/solarfm-0.0.1/solarfm/core/widgets/icon_grid_widget.py b/src/versions/solarfm-0.0.1/solarfm/core/widgets/icon_grid_widget.py index 368319d..51088b3 100644 --- a/src/versions/solarfm-0.0.1/solarfm/core/widgets/icon_grid_widget.py +++ b/src/versions/solarfm-0.0.1/solarfm/core/widgets/icon_grid_widget.py @@ -20,8 +20,6 @@ class IconGridWidget(Gtk.IconView): def __init__(self): super(IconGridWidget, self).__init__() - # self._store = None - self._setup_styling() self._setup_signals() self._set_up_dnd() diff --git a/src/versions/solarfm-0.0.1/solarfm/core/window.py b/src/versions/solarfm-0.0.1/solarfm/core/window.py index 8829ef8..7352f70 100644 --- a/src/versions/solarfm-0.0.1/solarfm/core/window.py +++ b/src/versions/solarfm-0.0.1/solarfm/core/window.py @@ -88,11 +88,7 @@ class Window(Gtk.ApplicationWindow): cr.set_operator(cairo.OPERATOR_OVER) - def _tear_down(self, widget=None, eve=None): - if not settings_manager.is_trace_debug(): - self._controller.fm_controller.save_state() - + def _tear_down(self, widget = None, eve = None): + event_system.emit("shutting_down") settings_manager.clear_pid() - time.sleep(event_sleep_time) - Gtk.main_quit() diff --git a/src/versions/solarfm-0.0.1/solarfm/plugins/plugin_base.py b/src/versions/solarfm-0.0.1/solarfm/plugins/plugin_base.py index 1c1613f..4eef833 100644 --- a/src/versions/solarfm-0.0.1/solarfm/plugins/plugin_base.py +++ b/src/versions/solarfm-0.0.1/solarfm/plugins/plugin_base.py @@ -24,32 +24,12 @@ class PluginBase: self._event_system = None - def set_fm_event_system(self, fm_event_system): + def run(self): """ - Requests Key: 'pass_fm_events': "true" - Must define in plugin if "pass_fm_events" is set to "true" string. + 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. """ - 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. """ - for child in widget.get_children(): - widget.remove(child) - - def subscribe_to_events(self): - self._event_system.subscribe("update_state_info_plugins", self._update_fm_state_info) - - def _update_fm_state_info(self, state): - self._fm_state = state + raise PluginBaseException("Method hasn't been overriden...") def generate_reference_ui_element(self): """ @@ -59,12 +39,26 @@ class PluginBase: """ raise PluginBaseException("Method hasn't been overriden...") - def run(self): + def set_ui_object_collection(self, ui_objects): """ - 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. + 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. """ - raise PluginBaseException("Method hasn't been overriden...") + self._ui_objects = ui_objects + + 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 subscribe_to_events(self): + self._event_system.subscribe("update_state_info_plugins", self._update_fm_state_info) + + def _update_fm_state_info(self, state): + self._fm_state = state def _connect_builder_signals(self, caller_class, builder): classes = [caller_class] @@ -94,3 +88,9 @@ class PluginBase: reload_package_recursive(path, module_dict[path.stem].__dict__) reload_package_recursive(Path(plugin_path).parent, module_dict_main["module_dict_main"]) + + + def clear_children(self, widget: type) -> None: + """ Clear children of a gtk widget. """ + for child in widget.get_children(): + widget.remove(child) diff --git a/src/versions/solarfm-0.0.1/solarfm/utils/endpoint_registry.py b/src/versions/solarfm-0.0.1/solarfm/utils/endpoint_registry.py deleted file mode 100644 index 86e4295..0000000 --- a/src/versions/solarfm-0.0.1/solarfm/utils/endpoint_registry.py +++ /dev/null @@ -1,22 +0,0 @@ -# Python imports - -# Lib imports - -# Application imports -from .singleton import Singleton - - - -class EndpointRegistry(Singleton): - 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/utils/ipc_server.py b/src/versions/solarfm-0.0.1/solarfm/utils/ipc_server.py index 563b086..1b8af6b 100644 --- a/src/versions/solarfm-0.0.1/solarfm/utils/ipc_server.py +++ b/src/versions/solarfm-0.0.1/solarfm/utils/ipc_server.py @@ -43,13 +43,13 @@ class IPCServer(Singleton): if os.path.exists(self._ipc_address) and settings.is_dirty_start(): os.unlink(self._ipc_address) - listener = Listener(address=self._ipc_address, family="AF_UNIX", authkey=self._ipc_authkey) + listener = Listener(address = self._ipc_address, family = "AF_UNIX", authkey = self._ipc_authkey) + elif "unsecured" not in self._conn_type: - listener = Listener((self._ipc_address, self._ipc_port), authkey=self._ipc_authkey) + listener = Listener((self._ipc_address, self._ipc_port), authkey = self._ipc_authkey) else: listener = Listener((self._ipc_address, self._ipc_port)) - self.is_ipc_alive = True self._run_ipc_loop(listener) @@ -61,15 +61,14 @@ class IPCServer(Singleton): start_time = time.perf_counter() GLib.idle_add(self._handle_ipc_message, *(conn, start_time,)) except Exception as e: - ... + logger.debug( repr(e) ) listener.close() def _handle_ipc_message(self, conn, start_time) -> None: while True: msg = conn.recv() - if settings_manager.is_debug(): - print(msg) + logger.debug(msg) if "FILE|" in msg: file = msg.split("FILE|")[1].strip() @@ -103,6 +102,25 @@ class IPCServer(Singleton): conn.send(message) conn.close() except ConnectionRefusedError as e: - print("Connection refused...") + logger.error("Connection refused...") except Exception as e: - print(repr(e)) \ No newline at end of file + logger.error( repr(e) ) + + + def send_test_ipc_message(self, message: str = "Empty Data...") -> None: + try: + if self._conn_type == "socket": + conn = Client(address=self._ipc_address, family="AF_UNIX", authkey=self._ipc_authkey) + elif "unsecured" not in self._conn_type: + conn = Client((self._ipc_address, self._ipc_port), authkey=self._ipc_authkey) + else: + conn = Client((self._ipc_address, self._ipc_port)) + + conn.send(message) + conn.close() + except ConnectionRefusedError as e: + if self._conn_type == "socket": + logger.error("IPC Socket no longer valid.... Removing.") + os.unlink(self._ipc_address) + except Exception as e: + logger.error( repr(e) ) diff --git a/src/versions/solarfm-0.0.1/solarfm/utils/types/__init__.py b/src/versions/solarfm-0.0.1/solarfm/utils/types/__init__.py new file mode 100644 index 0000000..a8e5edd --- /dev/null +++ b/src/versions/solarfm-0.0.1/solarfm/utils/types/__init__.py @@ -0,0 +1,3 @@ +""" + Utils module +""" diff --git a/src/versions/solarfm-0.0.1/solarfm/utils/types/state.py b/src/versions/solarfm-0.0.1/solarfm/utils/types/state.py new file mode 100644 index 0000000..ebd6d81 --- /dev/null +++ b/src/versions/solarfm-0.0.1/solarfm/utils/types/state.py @@ -0,0 +1,27 @@ +# Python imports +from dataclasses import dataclass + +# Lib imports +from gi.overrides.Gtk import IconView +from gi.overrides.Gtk import ListStore + +# Application imports + + + +@dataclass(slots=True) +class State: + fm_controller: any = None + notebooks: any = None + wid: int = None + tid: int = None + tab: type = None + icon_grid: IconView = None + store: ListStore = None + uris: list = None + uris_raw: list = None + selected_files: list = None + to_copy_files: list = None + to_cut_files: list = None + message_dialog: type = None + user_pass_dialog: type = None