diff --git a/plugins/file_properties/plugin.py b/plugins/file_properties/plugin.py index 1036fcf..a402831 100644 --- a/plugins/file_properties/plugin.py +++ b/plugins/file_properties/plugin.py @@ -122,7 +122,6 @@ class Plugin(PluginBase): uri = state.uris[0] path = state.tab.get_current_directory() - properties = self._set_ui_data(uri, path) response = self._properties_dialog.run() if response in [Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT]: @@ -168,13 +167,13 @@ class Plugin(PluginBase): def _set_ui_data(self, uri, path): properties = Properties() - file_info = Gio.File.new_for_path(uri).query_info(attributes="standard::*,owner::*,time::access,time::changed", - flags=Gio.FileQueryInfoFlags.NONE, - cancellable=None) + file_info = Gio.File.new_for_path(uri).query_info(attributes = "standard::*,owner::*,time::access,time::changed", + flags = Gio.FileQueryInfoFlags.NONE, + cancellable = None) is_symlink = file_info.get_attribute_as_string("standard::is-symlink") properties.file_uri = uri - properties.file_target = file_info.get_attribute_as_string("standard::symlink-target") if is_symlink else "" + properties.file_target = file_info.get_attribute_as_string("standard::symlink-target") if is_symlink in [True, "TRUE"] else "" properties.file_name = file_info.get_display_name() properties.file_location = path properties.mime_type = file_info.get_content_type() @@ -186,7 +185,7 @@ class Plugin(PluginBase): # NOTE: Read = 4, Write = 2, Exec = 1 command = ["stat", "-c", "%a", uri] - with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: + with subprocess.Popen(command, stdout = subprocess.PIPE) as proc: properties.chmod_stat = list(proc.stdout.read().decode("UTF-8").strip()) owner = self._chmod_map[f"{properties.chmod_stat[0]}"] group = self._chmod_map[f"{properties.chmod_stat[1]}"] diff --git a/src/solarfm/__main__.py b/src/solarfm/__main__.py index f5121f8..bd6cfe0 100644 --- a/src/solarfm/__main__.py +++ b/src/solarfm/__main__.py @@ -51,4 +51,4 @@ if __name__ == "__main__": main(args, unknownargs) except Exception as e: traceback.print_exc() - quit() \ No newline at end of file + quit() diff --git a/src/solarfm/core/controller.py b/src/solarfm/core/controller.py index 79b0796..049bd71 100644 --- a/src/solarfm/core/controller.py +++ b/src/solarfm/core/controller.py @@ -135,46 +135,48 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): event_system.emit("hide_rename_file_menu") if action == "open": - event_system.emit("open_files") + event_system.emit_and_await("open_files") if action == "open_with": - event_system.emit("show_appchooser_menu") + event_system.emit_and_await("show_appchooser_menu") if action == "open_2_new_tab": - event_system.emit("open_2_new_tab") + event_system.emit_and_await("open_2_new_tab") if action == "execute": - event_system.emit("execute_files") + event_system.emit_and_await("execute_files") if action == "execute_in_terminal": - event_system.emit("execute_files", (True,)) + event_system.emit_and_await("execute_files", (True,)) if action == "rename": - event_system.emit("rename_files") + event_system.emit_and_await("rename_files") if action == "cut": - event_system.emit("cut_files") + event_system.emit_and_await("cut_files") if action == "copy": - event_system.emit("copy_files") + event_system.emit_and_await("copy_files") if action == "copy_path": - event_system.emit("copy_path") + event_system.emit_and_await("copy_path") if action == "copy_name": - event_system.emit("copy_name") + event_system.emit_and_await("copy_name") if action == "copy_path_name": - event_system.emit("copy_path_name") + event_system.emit_and_await("copy_path_name") if action == "paste": - event_system.emit("paste_files") + event_system.emit_and_await("paste_files") if action == "create": - event_system.emit("create_files") + event_system.emit_and_await("create_files") if action in ["save_session", "save_session_as", "load_session"]: - event_system.emit("save_load_session", (action)) + event_system.emit_and_await("save_load_session", (action)) if action == "about_page": - event_system.emit("show_about_page") + event_system.emit_and_await("show_about_page") if action == "io_popup": - event_system.emit("show_io_popup") + event_system.emit_and_await("show_io_popup") if action == "plugins_popup": - event_system.emit("show_plugins_popup") + event_system.emit_and_await("show_plugins_popup") if action == "messages_popup": - event_system.emit("show_messages_popup") + event_system.emit_and_await("show_messages_popup") if action == "ui_debug": - event_system.emit("load_interactive_debug") + event_system.emit_and_await("load_interactive_debug") if action == "tear_down": - event_system.emit("tear_down") + event_system.emit_and_await("tear_down") + + action = None def go_home(self, widget=None, eve=None): @@ -192,11 +194,14 @@ class Controller(UIMixin, SignalsMixins, Controller_Data): 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() + top_main_menubar = None 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) tab.execute([f"{tab.terminal_app}"], start_dir=tab.get_current_directory()) + wid, tid, tab = None, None, None + def go_to_path(self, path: str): self.builder.get_object("path_entry").set_text(path) diff --git a/src/solarfm/core/controller_data.py b/src/solarfm/core/controller_data.py index da7b7b0..35e2618 100644 --- a/src/solarfm/core/controller_data.py +++ b/src/solarfm/core/controller_data.py @@ -114,6 +114,9 @@ class Controller_Data: uris.append(fpath) + tab = None + dir = None + return uris diff --git a/src/solarfm/core/mixins/signals/file_action_signals_mixin.py b/src/solarfm/core/mixins/signals/file_action_signals_mixin.py index a30c862..9acce62 100644 --- a/src/solarfm/core/mixins/signals/file_action_signals_mixin.py +++ b/src/solarfm/core/mixins/signals/file_action_signals_mixin.py @@ -68,6 +68,14 @@ class FileActionSignalsMixin: if [wid, tid] in [state.wid, state.tid]: self.set_bottom_labels(tab) + wid, tid = None, None + notebook = None + tab = None + icon_grid = None + store = None + _store, tab_widget_id_label = None, None + state = None + return False def do_file_search(self, widget, eve = None): @@ -90,4 +98,4 @@ class FileActionSignalsMixin: items = icon_grid.get_selected_items() if len(items) > 0: - icon_grid.scroll_to_path(items[0], False, 0.5, 0.5) \ No newline at end of file + icon_grid.scroll_to_path(items[0], False, 0.5, 0.5) diff --git a/src/solarfm/core/mixins/ui/grid_mixin.py b/src/solarfm/core/mixins/ui/grid_mixin.py index c0c9948..1cdcb4f 100644 --- a/src/solarfm/core/mixins/ui/grid_mixin.py +++ b/src/solarfm/core/mixins/ui/grid_mixin.py @@ -45,7 +45,10 @@ class GridMixin: if save_state and not trace_debug: self.fm_controller.save_state() + dir = None + files = None + @daemon_threaded def generate_icons(self, tab, store, dir, files): for i, file in enumerate(files): # GLib.Thread(f"{i}", self.make_and_load_icon, i, store, tab, dir, file[0]) @@ -54,14 +57,16 @@ class GridMixin: def update_store(self, i, store, icon): itr = store.get_iter(i) GLib.idle_add(self.insert_store, store, itr, icon) + itr = None @daemon_threaded def make_and_load_icon(self, i, store, tab, dir, file): icon = tab.create_icon(dir, file) self.update_store(i, store, icon) + icon = None def get_icon(self, tab, dir, file): - return tab.create_icon(dir, file) + tab.create_icon(dir, file) # @daemon_threaded @@ -159,6 +164,7 @@ class GridMixin: store = icon_grid.get_model() tab_label = notebook.get_tab_label(obj).get_children()[0] + icon_grid = None return store, tab_label def get_icon_grid_from_notebook(self, notebook, _name): diff --git a/src/solarfm/core/mixins/ui/tab_mixin.py b/src/solarfm/core/mixins/ui/tab_mixin.py index 656aafe..79a2617 100644 --- a/src/solarfm/core/mixins/ui/tab_mixin.py +++ b/src/solarfm/core/mixins/ui/tab_mixin.py @@ -41,16 +41,26 @@ class TabMixin(GridMixin): notebook.set_tab_reorderable(scroll, True) self.fm_controller.set_wid_and_tid(wid, tab.get_id()) - path_entry.set_text(tab.get_current_directory()) + # path_entry.set_text(tab.get_current_directory()) + event_system.emit("go_to_path", (tab.get_current_directory(),)) # NOTE: Not efficent if I understand how notebook.show_all() notebook.set_current_page(index) ctx = notebook.get_style_context() ctx.add_class("notebook-unselected-focus") self.load_store(tab, store) - self.set_window_title() + event_system.emit("set_window_title", (tab.get_current_directory(),)) self.set_file_watcher(tab) + tab_widget = None + scroll, store = None, None + index = None + notebook = None + path_entry = None + tab = None + ctx = None + + def get_tab_widget(self, tab): tab_widget = self.create_tab_widget() tab_widget.tab = tab @@ -63,6 +73,7 @@ class TabMixin(GridMixin): def close_tab(self, button, eve = None): notebook = button.get_parent().get_parent() if notebook.get_n_pages() == 1: + notebook = None return tab_box = button.get_parent() @@ -79,25 +90,35 @@ class TabMixin(GridMixin): self.builder.dereference_object(f"{wid}|{tid}|icon_grid") self.builder.dereference_object(f"{wid}|{tid}") - icon_grid.set_model(None) + iter = store.get_iter_first() + while iter: + next_iter = store.iter_next(iter) + store.unref_node(iter) + iter = next_iter + + store.clear() store.run_dispose() + + icon_grid.set_model(None) icon_grid.run_dispose() scroll.run_dispose() tab_box.run_dispose() - del store - del icon_grid - del scroll - del tab_box - del watcher - del tab + iter = None + wid, tid = None, None + store = None + icon_grid = None + scroll = None + tab_box = None + watcher = None + tab = None + notebook = None if not settings_manager.is_trace_debug(): self.fm_controller.save_state() self.set_window_title() - gc.collect() # NOTE: Not actually getting called even tho set in the glade file... @@ -121,6 +142,11 @@ class TabMixin(GridMixin): if not settings_manager.is_trace_debug(): self.fm_controller.save_state() + wid, tid = None, None + window = None + tab = None + + def on_tab_switch_update(self, notebook, content = None, index = None): self.selected_files.clear() wid, tid = content.get_children()[0].get_name().split("|") @@ -129,6 +155,8 @@ class TabMixin(GridMixin): self.set_path_text(wid, tid) self.set_window_title() + wid, tid = None, None + def get_id_from_tab_box(self, tab_box): return tab_box.tab.get_id() @@ -146,6 +174,8 @@ class TabMixin(GridMixin): state.tab.load_directory() self.load_store(state.tab, state.store) + state = None + def update_tab(self, tab_label, tab, store, wid, tid): self.load_store(tab, store) self.set_path_text(wid, tid) @@ -186,16 +216,38 @@ class TabMixin(GridMixin): if isinstance(focused_obj, Gtk.Entry): self.process_path_menu(widget, tab, dir) + action = None + store = None + if path.endswith(".") or path == dir: + tab_label = None + notebook = None + wid, tid = None, None + path = None + tab = None return if not tab.set_path(path): + tab_label = None + notebook = None + wid, tid = None, None + path = None + tab = None return icon_grid = self.get_icon_grid_from_notebook(notebook, f"{wid}|{tid}") icon_grid.clear_and_set_new_store() self.update_tab(tab_label, tab, icon_grid.get_store(), wid, tid) + action = None + wid, tid = None, None + notebook = None + store, tab_label = None, None + path = None + tab = None + icon_grid = None + + def process_path_menu(self, gtk_entry, tab, dir): path_menu_buttons = self.builder.get_object("path_menu_buttons") query = gtk_entry.get_text().replace(dir, "") @@ -212,6 +264,10 @@ class TabMixin(GridMixin): path_menu_buttons.add(button) show_path_menu = True + path_menu_buttons = None + query = None + files = None + if not show_path_menu: event_system.emit("hide_path_menu") else: @@ -242,10 +298,17 @@ class TabMixin(GridMixin): path_entry.set_position(-1) event_system.emit("hide_path_menu") + state = None + path = None + path_entry = None + def show_hide_hidden_files(self): wid, tid = self.fm_controller.get_active_wid_and_tid() tab = self.get_fm_window(wid).get_tab_by_id(tid) tab.set_hiding_hidden(not tab.is_hiding_hidden()) tab.load_directory() - self.builder.get_object("refresh_tab").released() \ No newline at end of file + self.builder.get_object("refresh_tab").released() + + wid, tid = None, None + tab = None diff --git a/src/solarfm/core/mixins/ui/window_mixin.py b/src/solarfm/core/mixins/ui/window_mixin.py index 2fc76db..5d6aea7 100644 --- a/src/solarfm/core/mixins/ui/window_mixin.py +++ b/src/solarfm/core/mixins/ui/window_mixin.py @@ -46,11 +46,19 @@ class WindowMixin(TabMixin): self.window.set_title(f"{app_name} ~ {dir}") self.set_bottom_labels(tab) + wid, tid = None, None + notebook = None + tab = None + dir = None + def set_path_text(self, wid, tid): path_entry = self.builder.get_object("path_entry") tab = self.get_fm_window(wid).get_tab_by_id(tid) path_entry.set_text(tab.get_current_directory()) + path_entry = None + tab = None + def grid_set_selected_items(self, icons_grid): new_items = icons_grid.get_selected_items() items_size = len(new_items) @@ -164,6 +172,12 @@ class WindowMixin(TabMixin): if target not in current: self.fm_controller.set_wid_and_tid(wid, tid) + current = None + target = None + wid, tid = None, None + store = None + path_at_loc = None + def grid_on_drag_data_received(self, widget, drag_context, x, y, data, info, time): if info == 80: @@ -183,4 +197,4 @@ class WindowMixin(TabMixin): Gtk.drag_finish(drag_context, False, False, time) def create_new_tab_notebook(self, widget=None, wid=None, path=None): - self.create_tab(wid, None, path) \ No newline at end of file + self.create_tab(wid, None, path) diff --git a/src/solarfm/core/ui_mixin.py b/src/solarfm/core/ui_mixin.py index 0c04c7b..22842c9 100644 --- a/src/solarfm/core/ui_mixin.py +++ b/src/solarfm/core/ui_mixin.py @@ -35,7 +35,7 @@ class UIMixin(PaneMixin, WindowMixin): nickname = session["window"]["Nickname"] tabs = session["window"]["tabs"] isHidden = True if session["window"]["isHidden"] == "True" else False - event_system.emit("load_files_view_state", (nickname, tabs, isHidden)) + event_system.emit_and_await("load_files_view_state", (nickname, tabs, isHidden)) def _focus_last_visible_notebook(self, icon_grid): @@ -47,6 +47,8 @@ class UIMixin(PaneMixin, WindowMixin): icon_grid.event(Gdk.Event().new(type = Gdk.EventType.BUTTON_RELEASE)) + window = None + def _current_loading_process(self, session_json = None): if session_json: for j, value in enumerate(session_json): diff --git a/src/solarfm/core/widgets/context_menu_widget.py b/src/solarfm/core/widgets/context_menu_widget.py index bbab184..70745e7 100644 --- a/src/solarfm/core/widgets/context_menu_widget.py +++ b/src/solarfm/core/widgets/context_menu_widget.py @@ -16,10 +16,7 @@ class ContextMenuWidget(Gtk.Menu): def __init__(self): super(ContextMenuWidget, self).__init__() - self.builder = settings_manager.get_builder() - self._builder = Gtk.Builder() - self._context_menu_data = settings_manager.get_context_menu_data() - self._window = settings_manager.get_main_window() + self._builder = Gtk.Builder() self._setup_styling() self._setup_signals() @@ -32,14 +29,48 @@ class ContextMenuWidget(Gtk.Menu): def _setup_signals(self): event_system.subscribe("show_context_menu", self.show_context_menu) event_system.subscribe("hide_context_menu", self.hide_context_menu) - settings_manager.register_signals_to_builder([self,], self._builder) + settings_manager.register_signals_to_builder(self, self._builder) def _load_widgets(self): + self.builder = settings_manager.get_builder() + self._window = settings_manager.get_main_window() + self._context_menu_data = settings_manager.get_context_menu_data() + + self.builder.expose_object("context_menu", self) + self.build_context_menu() def _emit(self, menu_item, type): event_system.emit("do_action_from_menu_controls", type) + + def build_context_menu(self) -> None: + data = self._context_menu_data + plugins_entry = None + + for key, value in data.items(): + entry = self.make_menu_item(key, value) + self.append(entry) + if key == "Plugins": + plugins_entry = entry + + self.attach_to_widget(self._window, None) + self.show_all() + + if plugins_entry: + self.builder.expose_object("context_menu_plugins", plugins_entry.get_submenu()) + + def make_menu_item(self, label, data) -> Gtk.MenuItem: + if isinstance(data, dict): + return self.make_submenu(label, data) + elif isinstance(data, list): + entry = Gtk.ImageMenuItem(label) + icon = getattr(Gtk, f"{data[0]}") + entry.set_image( Gtk.Image(stock=icon) ) + entry.set_always_show_image(True) + entry.connect("activate", self._emit, (data[1])) + return entry + def make_submenu(self, name, data): menu = Gtk.Menu() menu_item = Gtk.MenuItem(name) @@ -57,36 +88,9 @@ class ContextMenuWidget(Gtk.Menu): menu_item.set_submenu(menu) return menu_item - def make_menu_item(self, label, data) -> Gtk.MenuItem: - if isinstance(data, dict): - return self.make_submenu(label, data) - elif isinstance(data, list): - entry = Gtk.ImageMenuItem(label) - icon = getattr(Gtk, f"{data[0]}") - entry.set_image( Gtk.Image(stock=icon) ) - entry.set_always_show_image(True) - entry.connect("activate", self._emit, (data[1])) - return entry - def build_context_menu(self) -> None: - data = self._context_menu_data - plugins_entry = None - - for key, value in data.items(): - entry = self.make_menu_item(key, value) - self.append(entry) - if key == "Plugins": - plugins_entry = entry - - self.attach_to_widget(self._window, None) - self.builder.expose_object("context_menu", self) - self.show_all() - - if plugins_entry: - self.builder.expose_object("context_menu_plugins", plugins_entry.get_submenu()) - - def show_context_menu(self, widget=None, eve=None): + def show_context_menu(self, widget = None, eve = None): self.builder.get_object("context_menu").popup_at_pointer(None) - def hide_context_menu(self, widget=None, eve=None): + def hide_context_menu(self, widget = None, eve = None): self.builder.get_object("context_menu").popdown() diff --git a/src/solarfm/core/widgets/dialogs/about_widget.py b/src/solarfm/core/widgets/dialogs/about_widget.py index b5535d9..6f661fd 100644 --- a/src/solarfm/core/widgets/dialogs/about_widget.py +++ b/src/solarfm/core/widgets/dialogs/about_widget.py @@ -39,11 +39,10 @@ class AboutWidget: self.about_page = self._builder.get_object("about_page") builder.expose_object(f"about_page", self.about_page) - - def show_about_page(self, widget=None, eve=None): + def show_about_page(self, widget = None, eve = None): response = self.about_page.run() if response in [Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT]: self.hide_about_page() - def hide_about_page(self, widget=None, eve=None): + def hide_about_page(self, widget = None, eve = None): self.about_page.hide() diff --git a/src/solarfm/core/widgets/files_view/grid_mixin.py b/src/solarfm/core/widgets/files_view/grid_mixin.py index a6b9ee6..083fb81 100644 --- a/src/solarfm/core/widgets/files_view/grid_mixin.py +++ b/src/solarfm/core/widgets/files_view/grid_mixin.py @@ -31,7 +31,6 @@ class GridMixin: # return - dir = tab.get_current_directory() files = tab.get_files() @@ -46,32 +45,56 @@ class GridMixin: if save_state and not trace_debug: self.fm_controller.save_state() + dir = None + files = None @daemon_threaded def generate_icons(self, tab, store, dir, files): - try: - loop = asyncio.get_running_loop() - except RuntimeError: - loop = None + for i, file in enumerate(files): + # GLib.Thread(f"{i}", self.make_and_load_icon, i, store, tab, dir, file[0]) + self.make_and_load_icon( i, store, tab, dir, file[0]) - if loop and loop.is_running(): - loop = asyncio.get_event_loop() - loop.create_task( self.create_icons(tab, store, dir, files) ) - else: - asyncio.run( self.create_icons(tab, store, dir, files) ) - - async def create_icons(self, tab, store, dir, files): - icons = [self.get_icon(tab, dir, file[0]) for file in files] - data = await asyncio.gather(*icons) - tasks = [self.update_store(i, store, icon) for i, icon in enumerate(data)] - asyncio.gather(*tasks) - - async def update_store(self, i, store, icon): + def update_store(self, i, store, icon): itr = store.get_iter(i) GLib.idle_add(self.insert_store, store, itr, icon) + itr = None + + @daemon_threaded + def make_and_load_icon(self, i, store, tab, dir, file): + icon = tab.create_icon(dir, file) + self.update_store(i, store, icon) + icon = None + + def get_icon(self, tab, dir, file): + tab.create_icon(dir, file) + + + # @daemon_threaded + # def generate_icons(self, tab, store, dir, files): + # try: + # loop = asyncio.get_running_loop() + # except RuntimeError: + # loop = None + + # if loop and loop.is_running(): + # loop = asyncio.get_event_loop() + # loop.create_task( self.create_icons(tab, store, dir, files) ) + # else: + # asyncio.run( self.create_icons(tab, store, dir, files) ) + + # async def create_icons(self, tab, store, dir, files): + # icons = [self.get_icon(tab, dir, file[0]) for file in files] + # data = await asyncio.gather(*icons) + # tasks = [self.update_store(i, store, icon) for i, icon in enumerate(data)] + # asyncio.gather(*tasks) + + # async def update_store(self, i, store, icon): + # itr = store.get_iter(i) + # GLib.idle_add(self.insert_store, store, itr, icon) + + # async def get_icon(self, tab, dir, file): + # return tab.create_icon(dir, file) - async def get_icon(self, tab, dir, file): - return tab.create_icon(dir, file) def insert_store(self, store, itr, icon): store.set_value(itr, 0, icon) @@ -141,4 +164,11 @@ class GridMixin: store = icon_grid.get_model() tab_label = notebook.get_tab_label(obj).get_children()[0] - return store, tab_label \ No newline at end of file + return store, tab_label + + def get_icon_grid_from_notebook(self, notebook, _name): + for obj in notebook.get_children(): + icon_grid = obj.get_children()[0] + name = icon_grid.get_name() + if name == _name: + return icon_grid diff --git a/src/solarfm/core/widgets/files_view/tab_mixin.py b/src/solarfm/core/widgets/files_view/tab_mixin.py index 4bb474c..8a49f94 100644 --- a/src/solarfm/core/widgets/files_view/tab_mixin.py +++ b/src/solarfm/core/widgets/files_view/tab_mixin.py @@ -41,18 +41,26 @@ class TabMixin(GridMixin): notebook.set_tab_reorderable(scroll, True) self.fm_controller.set_wid_and_tid(wid, tab.get_id()) - event_system.emit("go_to_path", (tab.get_current_directory(),)) # NOTE: Not efficent if I understand how # path_entry.set_text(tab.get_current_directory()) + event_system.emit("go_to_path", (tab.get_current_directory(),)) # NOTE: Not efficent if I understand how notebook.show_all() notebook.set_current_page(index) ctx = notebook.get_style_context() ctx.add_class("notebook-unselected-focus") self.load_store(tab, store) - # self.set_window_title() event_system.emit("set_window_title", (tab.get_current_directory(),)) self.set_file_watcher(tab) + tab_widget = None + scroll, store = None, None + index = None + notebook = None + # path_entry = None + tab = None + ctx = None + + def get_tab_widget(self, tab): tab_widget = self.create_tab_widget() tab_widget.tab_id = tab.get_id() @@ -65,6 +73,7 @@ class TabMixin(GridMixin): def close_tab(self, button, eve = None): notebook = button.get_parent().get_parent() if notebook.get_n_pages() == 1: + notebook = None return tab_box = button.get_parent() @@ -81,19 +90,30 @@ class TabMixin(GridMixin): self.builder.dereference_object(f"{wid}|{tid}|icon_grid") self.builder.dereference_object(f"{wid}|{tid}") - icon_grid.set_model(None) + iter = store.get_iter_first() + while iter: + next_iter = store.iter_next(iter) + store.unref_node(iter) + iter = next_iter + + store.clear() store.run_dispose() + + icon_grid.set_model(None) icon_grid.run_dispose() scroll.run_dispose() tab_box.run_dispose() - del store - del icon_grid - del scroll - del tab_box - del watcher - del tab + iter = None + wid, tid = None, None + store = None + icon_grid = None + scroll = None + tab_box = None + watcher = None + tab = None + notebook = None if not settings_manager.is_trace_debug(): self.fm_controller.save_state() @@ -123,6 +143,11 @@ class TabMixin(GridMixin): if not settings_manager.is_trace_debug(): self.fm_controller.save_state() + wid, tid = None, None + window = None + tab = None + + def on_tab_switch_update(self, notebook, content = None, index = None): self.selected_files.clear() wid, tid = content.get_children()[0].tab.get_name().split("|") @@ -130,6 +155,8 @@ class TabMixin(GridMixin): self.set_path_text(wid, tid) self.set_window_title() + wid, tid = None, None + def get_id_from_tab_box(self, tab_box): return tab_box.tab.get_id() @@ -147,6 +174,8 @@ class TabMixin(GridMixin): state.tab.load_directory() self.load_store(state.tab, state.store) + state = None + def update_tab(self, tab_label, tab, store, wid, tid): self.load_store(tab, store) self.set_path_text(wid, tid) @@ -187,16 +216,38 @@ class TabMixin(GridMixin): if isinstance(focused_obj, Gtk.Entry): self.process_path_menu(widget, tab, dir) + action = None + store = None + if path.endswith(".") or path == dir: + tab_label = None + notebook = None + wid, tid = None, None + path = None + tab = None return if not tab.set_path(path): + tab_label = None + notebook = None + wid, tid = None, None + path = None + tab = None return icon_grid = self.get_icon_grid_from_notebook(notebook, f"{wid}|{tid}") icon_grid.clear_and_set_new_store() self.update_tab(tab_label, tab, store, wid, tid) + action = None + wid, tid = None, None + notebook = None + store, tab_label = None, None + path = None + tab = None + icon_grid = None + + def process_path_menu(self, gtk_entry, tab, dir): path_menu_buttons = self.builder.get_object("path_menu_buttons") query = gtk_entry.get_text().replace(dir, "") @@ -213,6 +264,10 @@ class TabMixin(GridMixin): path_menu_buttons.add(button) show_path_menu = True + path_menu_buttons = None + query = None + files = None + if not show_path_menu: event_system.emit("hide_path_menu") else: @@ -244,9 +299,16 @@ class TabMixin(GridMixin): path_entry.set_position(-1) event_system.emit("hide_path_menu") + state = None + path = None + path_entry = None + def show_hide_hidden_files(self): wid, tid = self.fm_controller.get_active_wid_and_tid() tab = self.get_fm_window(wid).get_tab_by_id(tid) tab.set_hiding_hidden(not tab.is_hiding_hidden()) tab.load_directory() - self.builder.get_object("refresh_tab").released() \ No newline at end of file + self.builder.get_object("refresh_tab").released() + + wid, tid = None, None + tab = None diff --git a/src/solarfm/core/widgets/files_view/window_mixin.py b/src/solarfm/core/widgets/files_view/window_mixin.py index a8eb8f5..23a12ab 100644 --- a/src/solarfm/core/widgets/files_view/window_mixin.py +++ b/src/solarfm/core/widgets/files_view/window_mixin.py @@ -42,10 +42,17 @@ class WindowMixin(TabMixin): event_system.emit("set_window_title", (dir,)) self.set_bottom_labels(tab) + wid, tid = None, None + notebook = None + tab = None + dir = None + def set_path_text(self, wid, tid): tab = self.get_fm_window(wid).get_tab_by_id(tid) event_system.emit("go_to_path", (tab.get_current_directory(),)) + tab = None + def grid_set_selected_items(self, icons_grid): new_items = icons_grid.get_selected_items() items_size = len(new_items) @@ -160,6 +167,12 @@ class WindowMixin(TabMixin): if target not in current: self.fm_controller.set_wid_and_tid(wid, tid) + current = None + target = None + wid, tid = None, None + store = None + path_at_loc = None + def grid_on_drag_data_received(self, widget, drag_context, x, y, data, info, time): if info == 80: @@ -179,4 +192,4 @@ class WindowMixin(TabMixin): Gtk.drag_finish(drag_context, False, False, time) def create_new_tab_notebook(self, widget=None, wid=None, path=None): - self.create_tab(wid, None, path) \ No newline at end of file + self.create_tab(wid, None, path) diff --git a/src/solarfm/core/widgets/icon_grid_widget.py b/src/solarfm/core/widgets/icon_grid_widget.py index 2326912..e758ee2 100644 --- a/src/solarfm/core/widgets/icon_grid_widget.py +++ b/src/solarfm/core/widgets/icon_grid_widget.py @@ -77,9 +77,18 @@ class IconGridWidget(Gtk.IconView): def clear_and_set_new_store(self): store = self.get_model() if store: + iter = store.get_iter_first() + while iter: + next_iter = store.iter_next(iter) + store.unref_node(iter) + iter = next_iter + + store.clear() store.run_dispose() + store = None self.set_model(None) store = Gtk.ListStore(GdkPixbuf.Pixbuf or GdkPixbuf.PixbufAnimation or None, str or None) # store = Gtk.ListStore(Gtk.DirectoryList) self.set_model(store) + store = None diff --git a/src/solarfm/core/widgets/popups/message_popup_widget.py b/src/solarfm/core/widgets/popups/message_popup_widget.py index f3517a4..d8bf706 100644 --- a/src/solarfm/core/widgets/popups/message_popup_widget.py +++ b/src/solarfm/core/widgets/popups/message_popup_widget.py @@ -61,7 +61,6 @@ class MessagePopupWidget(Gtk.Popover): scroll_window.set_hexpand(True) vbox.set_orientation(Gtk.Orientation.VERTICAL) - self.builder.expose_object(f"message_popup_widget", self) self.builder.expose_object(f"message_text_view", message_text_view) scroll_window.add(message_text_view) @@ -126,4 +125,4 @@ class MessagePopupWidget(Gtk.Popover): with open(target, "w") as f: f.write(text) - save_location_prompt.destroy() \ No newline at end of file + save_location_prompt.destroy() diff --git a/src/solarfm/utils/ipc_server.py b/src/solarfm/utils/ipc_server.py index eda6dab..8fecbf2 100644 --- a/src/solarfm/utils/ipc_server.py +++ b/src/solarfm/utils/ipc_server.py @@ -60,7 +60,11 @@ class IPCServer(Singleton): try: conn = listener.accept() start_time = time.perf_counter() + GLib.idle_add(self._handle_ipc_message, *(conn, start_time,)) + + conn = None + start_time = None except Exception as e: logger.debug( repr(e) ) @@ -74,19 +78,24 @@ class IPCServer(Singleton): if "FILE|" in msg: file = msg.split("FILE|")[1].strip() if file: - event_system.emit("handle_file_from_ipc", file) + event_system.emit_and_await("handle_file_from_ipc", file) + msg = None + file = None conn.close() break if msg in ['close connection', 'close server']: + msg = None conn.close() break # NOTE: Not perfect but insures we don't lock up the connection for too long. end_time = time.perf_counter() if (end_time - start_time) > self._ipc_timeout: + msg = None + end_time = None conn.close() break @@ -126,4 +135,4 @@ class IPCServer(Singleton): logger.error("IPC Socket no longer valid.... Removing.") os.unlink(self._ipc_address) except Exception as e: - logger.error( repr(e) ) \ No newline at end of file + logger.error( repr(e) ) diff --git a/src/solarfm/utils/settings_manager/manager.py b/src/solarfm/utils/settings_manager/manager.py index 0c431bb..2be6222 100644 --- a/src/solarfm/utils/settings_manager/manager.py +++ b/src/solarfm/utils/settings_manager/manager.py @@ -171,4 +171,4 @@ class SettingsManager(StartCheckMixin, Singleton): def save_settings(self): with open(self._CONFIG_FILE, 'w') as outfile: - json.dump(self.settings.as_dict(), outfile, separators=(',', ':'), indent=4) \ No newline at end of file + json.dump(self.settings.as_dict(), outfile, separators=(',', ':'), indent=4) diff --git a/user_config/bin/solarfm b/user_config/bin/solarfm index e833ed3..cb94caf 100755 --- a/user_config/bin/solarfm +++ b/user_config/bin/solarfm @@ -20,6 +20,9 @@ function main() { files[$size]="${target}" done + G_SLICE=always-malloc + G_DEBUG=gc-friendly + GOBJECT_DEBUG=instance-count python /opt/solarfm.zip "${files[@]}" } main "$@"; diff --git a/user_config/usr/share/solarfm/ui_widgets/about_ui.glade b/user_config/usr/share/solarfm/ui_widgets/about_ui.glade index f559f6c..db5df48 100644 --- a/user_config/usr/share/solarfm/ui_widgets/about_ui.glade +++ b/user_config/usr/share/solarfm/ui_widgets/about_ui.glade @@ -8,7 +8,7 @@ False 5 center-on-parent - ../icons/solarfm.png + ../icons/solarfm-64x64.png dialog True True @@ -19,6 +19,7 @@ Copyright (C) 2021 GPL2 by ITDominator https://code.itdominator.com/itdominator/SolarFM + ITDominator SolarFM - Copyright (C) 2021 ITDominator GPL2 @@ -367,7 +368,9 @@ Public License instead of this License. SolarFM is developed on Atom, git, and using Python 3+ with Gtk GObject introspection. - translator-credits + ... + ... + ... ../icons/solarfm-64x64.png True custom