From da63e6e44e75d29abcdcbc8b402272b74a010c7f Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sat, 1 Oct 2022 16:04:46 -0500 Subject: [PATCH] Moved trash logic to plugin structure --- plugins/trasher/__init__.py | 3 + plugins/trasher/__main__.py | 3 + plugins/trasher/manifest.json | 12 + plugins/trasher/plugin.py | 115 +++ .../solarfm => plugins}/trasher/trash.py | 0 plugins/trasher/trasher.glade | 126 ++++ .../solarfm => plugins}/trasher/xdgtrash.py | 0 .../SolarFM/solarfm/core/controller.py | 20 +- .../SolarFM/solarfm/core/controller_data.py | 6 +- .../mixins/ui/widget_file_action_mixin.py | 39 - .../solarfm/core/mixins/ui/window_mixin.py | 7 +- .../SolarFM/solarfm/trasher/__init__.py | 3 - .../usr/share/solarfm/Main_Window.glade | 694 +++++++----------- 13 files changed, 556 insertions(+), 472 deletions(-) create mode 100644 plugins/trasher/__init__.py create mode 100644 plugins/trasher/__main__.py create mode 100644 plugins/trasher/manifest.json create mode 100644 plugins/trasher/plugin.py rename {src/versions/solarfm-0.0.1/SolarFM/solarfm => plugins}/trasher/trash.py (100%) create mode 100644 plugins/trasher/trasher.glade rename {src/versions/solarfm-0.0.1/SolarFM/solarfm => plugins}/trasher/xdgtrash.py (100%) delete mode 100755 src/versions/solarfm-0.0.1/SolarFM/solarfm/trasher/__init__.py diff --git a/plugins/trasher/__init__.py b/plugins/trasher/__init__.py new file mode 100644 index 0000000..d36fa8c --- /dev/null +++ b/plugins/trasher/__init__.py @@ -0,0 +1,3 @@ +""" + Pligin Module +""" diff --git a/plugins/trasher/__main__.py b/plugins/trasher/__main__.py new file mode 100644 index 0000000..a576329 --- /dev/null +++ b/plugins/trasher/__main__.py @@ -0,0 +1,3 @@ +""" + Pligin Package +""" diff --git a/plugins/trasher/manifest.json b/plugins/trasher/manifest.json new file mode 100644 index 0000000..e6f0c35 --- /dev/null +++ b/plugins/trasher/manifest.json @@ -0,0 +1,12 @@ +{ + "manifest": { + "name": "Trasher", + "author": "ITDominator", + "version": "0.0.1", + "support": "", + "requests": { + "ui_target": "context_menu", + "pass_fm_events": "true" + } + } +} diff --git a/plugins/trasher/plugin.py b/plugins/trasher/plugin.py new file mode 100644 index 0000000..cbfe70d --- /dev/null +++ b/plugins/trasher/plugin.py @@ -0,0 +1,115 @@ +# Python imports +import os, threading, subprocess, inspect + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk, GLib, Gio + +# Application imports +from plugins.plugin_base import PluginBase +from .xdgtrash import XDGTrash + + +# 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: Threads WILL 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(PluginBase): + def __init__(self): + super().__init__() + self.path = os.path.dirname(os.path.realpath(__file__)) + self._GLADE_FILE = f"{self.path}/trasher.glade" + self.name = "Trasher" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus + # where self.name should not be needed for message comms + self.trashman = XDGTrash() + 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.trashman.regenerate() + + def get_ui_element(self): + self._builder = Gtk.Builder() + self._builder.add_from_file(self._GLADE_FILE) + + classes = [self] + handlers = {} + for c in classes: + methods = None + try: + methods = inspect.getmembers(c, predicate=inspect.ismethod) + handlers.update(methods) + except Exception as e: + print(repr(e)) + + self._builder.connect_signals(handlers) + + trasher = self._builder.get_object("trasher") + trasher.show_all() + + 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() + + def _hide_trash_buttons(self): + self._builder.get_object("restore_from_trash").hide() + self._builder.get_object("empty_trash").hide() + + def delete_files(self, widget = None, eve = None): + self._event_system.emit("get_current_state") + state = self._fm_state + uris = state.selected_files + response = None + + state.warning_alert.format_secondary_text(f"Do you really want to delete the {len(uris)} file(s)?") + for uri in uris: + file = Gio.File.new_for_path(uri) + + if not response: + response = state.warning_alert.run() + state.warning_alert.hide() + if response == Gtk.ResponseType.YES: + type = file.query_file_type(flags=Gio.FileQueryInfoFlags.NONE) + + if type == Gio.FileType.DIRECTORY: + state.tab.delete_file( file.get_path() ) + else: + file.delete(cancellable=None) + else: + break + + def trash_files(self, widget = None, eve = None, verbocity = False): + 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("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.trashman.empty(verbose = verbocity) + + def go_to_trash(self, widget = None, eve = None, verbocity = False): + self._event_system.emit("go_to_path", self.trash_files_path) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/trasher/trash.py b/plugins/trasher/trash.py similarity index 100% rename from src/versions/solarfm-0.0.1/SolarFM/solarfm/trasher/trash.py rename to plugins/trasher/trash.py diff --git a/plugins/trasher/trasher.glade b/plugins/trasher/trasher.glade new file mode 100644 index 0000000..54837b9 --- /dev/null +++ b/plugins/trasher/trasher.glade @@ -0,0 +1,126 @@ + + + + + + True + False + user-trash + + + True + False + user-trash + + + True + True + 5 + 10 + True + + + True + False + vertical + + + Restore From Trash + restore_from_trash + True + True + True + Restore From Trash... + + + + False + True + 0 + + + + + Empty Trash + empty_trash + True + True + True + Empty Trash... + + + + False + True + 1 + + + + + Trash + trash + True + True + True + Move to Trash... + 20 + trash_img + True + + + + False + True + 2 + + + + + Go To Trash + go_to_trash + True + True + True + Go To Trash... + trash_img2 + True + + + + False + True + 3 + + + + + gtk-delete + delete + True + True + True + Delete... + 20 + True + True + + + + False + True + 4 + + + + + + + True + False + False + Trash + center + + + + diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/trasher/xdgtrash.py b/plugins/trasher/xdgtrash.py similarity index 100% rename from src/versions/solarfm-0.0.1/SolarFM/solarfm/trasher/xdgtrash.py rename to plugins/trasher/xdgtrash.py 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 7a9c930..c034bd3 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 @@ -47,6 +47,8 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi 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) + event_system.subscribe("go_to_path", self.go_to_path) + 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() @@ -100,7 +102,7 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi gc.collect() - def do_action_from_menu_controls(self, widget, event_button): + def do_action_from_menu_controls(self, widget, eve = None): action = widget.get_name() self.hide_context_menu() self.hide_new_file_menu() @@ -124,16 +126,6 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi self.paste_files() if action == "archive": self.show_archiver_dialogue() - if action == "delete": - self.delete_files() - if action == "trash": - self.trash_files() - if action == "go_to_trash": - self.path_entry.set_text(self.trash_files_path) - if action == "restore_from_trash": - self.restore_trash_files() - if action == "empty_trash": - self.empty_trash() if action == "create": self.create_files() if action in ["save_session", "save_session_as", "load_session"]: @@ -169,3 +161,9 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi wid, tid = self.fm_controller.get_active_wid_and_tid() tab = self.get_fm_window(wid).get_tab_by_id(tid) tab.execute([f"{tab.terminal_app}"], start_dir=tab.get_current_directory()) + + def go_to_path(self, path): + self.path_entry.set_text(path) + + def do_hide_context_menu(self): + self.hide_context_menu() 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 ea44a63..3e69f9f 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 @@ -7,7 +7,6 @@ import gi from gi.repository import GLib # Application imports -from trasher.xdgtrash import XDGTrash from shellfm.windows.controller import WindowController from plugins.plugins_controller import PluginsController @@ -22,6 +21,7 @@ class State: selected_files: [] = None to_copy_files: [] = None to_cut_files: [] = None + warning_alert: type = None class Controller_Data: @@ -34,11 +34,9 @@ class Controller_Data: self.logger = self.settings.get_logger() self.keybindings = self.settings.get_keybindings() - self.trashman = XDGTrash() self.fm_controller = WindowController() self.plugins = PluginsController(_settings) self.fm_controller_data = self.fm_controller.get_state_from_file() - self.trashman.regenerate() self.window = self.settings.get_main_window() self.window1 = self.builder.get_object("window_1") @@ -142,6 +140,7 @@ class Controller_Data: state.tab = self.get_fm_window(state.wid).get_tab_by_id(state.tid) state.icon_grid = self.builder.get_object(f"{state.wid}|{state.tid}|icon_grid") state.store = state.icon_grid.get_model() + state.warning_alert = self.warning_alert selected_files = state.icon_grid.get_selected_items() @@ -155,7 +154,6 @@ class Controller_Data: # state.to_cut_files = self.format_to_uris(state.store, state.wid, state.tid, self.to_cut_files, True) event_system.emit("update_state_info_plugins", state) - return state 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 9072990..0058147 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 @@ -208,45 +208,6 @@ class WidgetFileActionMixin: elif self.to_cut_files: self.handle_files(self.to_cut_files, "move", target) - def delete_files(self): - state = self.get_current_state() - uris = self.format_to_uris(state.store, state.wid, state.tid, self.selected_files, True) - response = None - - self.warning_alert.format_secondary_text(f"Do you really want to delete the {len(uris)} file(s)?") - for uri in uris: - file = Gio.File.new_for_path(uri) - - if not response: - response = self.warning_alert.run() - self.warning_alert.hide() - if response == Gtk.ResponseType.YES: - type = file.query_file_type(flags=Gio.FileQueryInfoFlags.NONE) - - if type == Gio.FileType.DIRECTORY: - state.tab.delete_file( file.get_path() ) - else: - file.delete(cancellable=None) - else: - break - - - def trash_files(self): - state = self.get_current_state() - uris = self.format_to_uris(state.store, state.wid, state.tid, self.selected_files, True) - for uri in uris: - self.trashman.trash(uri, False) - - def restore_trash_files(self): - state = self.get_current_state() - uris = self.format_to_uris(state.store, state.wid, state.tid, self.selected_files, True) - for uri in uris: - self.trashman.restore(filename=uri.split("/")[-1], verbose=False) - - def empty_trash(self): - self.trashman.empty(verbose=False) - - def create_files(self): fname_field = self.builder.get_object("new_fname_field") self.show_new_file_menu(fname_field) 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 1d22380..513182e 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 @@ -88,12 +88,11 @@ class WindowMixin(TabMixin): formatted_mount_free = self.sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::free")) ) formatted_mount_size = self.sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::size")) ) + # NOTE: Hides empty trash and other desired buttons based on context. if self.trash_files_path == current_directory: - self.builder.get_object("restore_from_trash").show() - self.builder.get_object("empty_trash").show() + event_system.emit("show_trash_buttons") else: - self.builder.get_object("restore_from_trash").hide() - self.builder.get_object("empty_trash").hide() + event_system.emit("hide_trash_buttons") # If something selected self.bottom_size_label.set_label(f"{formatted_mount_free} free / {formatted_mount_size}") diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/trasher/__init__.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/trasher/__init__.py deleted file mode 100755 index 5c16e50..0000000 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/trasher/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Trasher module -""" diff --git a/user_config/usr/share/solarfm/Main_Window.glade b/user_config/usr/share/solarfm/Main_Window.glade index 2bf3bd8..2343d0c 100644 --- a/user_config/usr/share/solarfm/Main_Window.glade +++ b/user_config/usr/share/solarfm/Main_Window.glade @@ -668,6 +668,289 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe False gtk-edit + + False + False + mouse + splashscreen + True + False + False + static + + + + False + vertical + 2 + + + False + end + + + + + + + + + False + False + 0 + + + + + True + False + vertical + + + True + True + 5 + 5 + True + True + + + True + False + vertical + + + gtk-open + open + True + True + True + Open... + True + + + + False + True + 0 + + + + + Open With + open_with + True + True + True + open_with_img + True + + + + False + True + 1 + + + + + gtk-execute + execute + True + True + True + True + + + + False + True + 2 + + + + + Execute in Terminal + execute_in_terminal + True + True + True + exec_in_term_img + + + + False + True + 3 + + + + + + + True + False + False + Open + center + + + + + False + True + 4 + + + + + True + True + 5 + 5 + True + True + + + True + False + vertical + + + gtk-new + create + True + True + True + New File/Folder... + True + + + + False + True + 0 + + + + + Rename + rename + True + True + True + Rename... + rename_img2 + True + + + + False + True + 1 + + + + + gtk-cut + cut + True + True + True + Cut... + True + True + + + + False + True + 2 + + + + + gtk-copy + copy + True + True + True + Copy... + True + True + + + + False + True + 3 + + + + + gtk-paste + paste + True + True + True + Paste... + True + True + + + + False + True + 4 + + + + + Archive + archive + True + True + True + Archive... + archive_img + True + + + + False + True + 5 + + + + + + + True + False + False + File Actions + center + end + + + + + False + True + 5 + + + + + False + True + 1 + + + + + False dialog @@ -2321,417 +2604,6 @@ SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspe - - True - False - user-trash - - - True - False - user-trash - - - False - False - mouse - splashscreen - True - False - False - static - - - - False - vertical - 2 - - - False - end - - - - - - - - - False - False - 0 - - - - - True - False - vertical - - - True - True - 5 - 5 - True - True - - - True - False - vertical - - - gtk-open - open - True - True - True - Open... - True - - - - False - True - 0 - - - - - Open With - open_with - True - True - True - open_with_img - True - - - - False - True - 1 - - - - - gtk-execute - execute - True - True - True - True - - - - False - True - 2 - - - - - Execute in Terminal - execute_in_terminal - True - True - True - exec_in_term_img - - - - False - True - 3 - - - - - - - True - False - False - Open - center - - - - - False - True - 4 - - - - - True - True - 5 - 5 - True - True - - - True - False - vertical - - - gtk-new - create - True - True - True - New File/Folder... - True - - - - False - True - 0 - - - - - Rename - rename - True - True - True - Rename... - rename_img2 - True - - - - False - True - 1 - - - - - gtk-cut - cut - True - True - True - Cut... - True - True - - - - False - True - 2 - - - - - gtk-copy - copy - True - True - True - Copy... - True - True - - - - False - True - 3 - - - - - gtk-paste - paste - True - True - True - Paste... - True - True - - - - False - True - 4 - - - - - Archive - archive - True - True - True - Archive... - archive_img - True - - - - False - True - 5 - - - - - - - True - False - False - File Actions - center - end - - - - - False - True - 5 - - - - - True - True - 5 - 10 - True - - - True - False - vertical - - - Restore From Trash - restore_from_trash - True - True - True - Restore From Trash... - - - - False - True - 0 - - - - - Empty Trash - empty_trash - True - True - True - Empty Trash... - - - - False - True - 1 - - - - - Trash - trash - True - True - True - Move to Trash... - 20 - trash_img - True - - - - False - True - 2 - - - - - Go To Trash - go_to_trash - True - True - True - Go To Trash... - trash_img2 - True - - - - False - True - 3 - - - - - gtk-delete - delete - True - True - True - Delete... - 20 - True - True - - - - False - True - 4 - - - - - - - True - False - False - Trash - center - - - - - False - True - 6 - - - - - False - True - 1 - - - - - False False