more attempts at leak fixes; thumbnailer plugin updates and corrections

This commit is contained in:
2025-10-12 20:24:04 -05:00
parent cddecb7ce7
commit d237afea94
7 changed files with 64 additions and 36 deletions

View File

@@ -54,6 +54,7 @@ class Controller_Data:
self.ctrl_down = False self.ctrl_down = False
self.shift_down = False self.shift_down = False
self.alt_down = False self.alt_down = False
self.was_midified_key = None
self._state = State() self._state = State()
self.message_dialog = MessageWidget() self.message_dialog = MessageWidget()

View File

@@ -20,6 +20,8 @@ class FileActionSignalsMixin:
if tab.get_dir_watcher(): if tab.get_dir_watcher():
watcher = tab.get_dir_watcher() watcher = tab.get_dir_watcher()
watcher.cancel() watcher.cancel()
watcher.disconnect(watcher.watch_id)
watcher.run_dispose()
if settings_manager.is_debug(): if settings_manager.is_debug():
logger.debug(f"Watcher Is Cancelled: {watcher.is_cancelled()}") logger.debug(f"Watcher Is Cancelled: {watcher.is_cancelled()}")
@@ -30,8 +32,9 @@ class FileActionSignalsMixin:
wid = tab.get_wid() wid = tab.get_wid()
tid = tab.get_id() tid = tab.get_id()
dir_watcher.connect("changed", self.dir_watch_updates, *(f"{wid}|{tid}",)) watch_id = dir_watcher.connect("changed", self.dir_watch_updates, *(f"{wid}|{tid}",))
tab.set_dir_watcher(dir_watcher) tab.set_dir_watcher(dir_watcher)
dir_watcher.watch_id = watch_id
def dir_watch_updates(self, file_monitor, file, other_file = None, eve_type = None, tab_widget_id = None): def dir_watch_updates(self, file_monitor, file, other_file = None, eve_type = None, tab_widget_id = None):
if eve_type in [Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED, if eve_type in [Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED,
@@ -68,14 +71,6 @@ class FileActionSignalsMixin:
if [wid, tid] in [state.wid, state.tid]: if [wid, tid] in [state.wid, state.tid]:
self.set_bottom_labels(tab) 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 return False
def do_file_search(self, widget, eve = None): def do_file_search(self, widget, eve = None):

View File

@@ -34,7 +34,7 @@ class KeyboardSignalsMixin:
self.alt_down = False self.alt_down = False
def on_global_key_press_controller(self, eve, user_data): def on_global_key_press_controller(self, eve, user_data):
keyname = Gdk.keyval_name(user_data.keyval).lower() keyname = Gdk.keyval_name(user_data.keyval).lower()
modifiers = Gdk.ModifierType(user_data.get_state() & ~Gdk.ModifierType.LOCK_MASK) modifiers = Gdk.ModifierType(user_data.get_state() & ~Gdk.ModifierType.LOCK_MASK)
self.was_midified_key = True if modifiers != 0 else False self.was_midified_key = True if modifiers != 0 else False

View File

@@ -26,30 +26,32 @@ class GridMixin:
for file in files: for file in files:
store.append([None, file[0]]) store.append([None, file[0]])
Gtk.main_iteration()
self.generate_icons(tab, store, dir, files) self.generate_icons(tab, store, dir, files)
# NOTE: Not likely called often from here but it could be useful # NOTE: Not likely called often from here but it could be useful
if save_state and not trace_debug: if save_state and not trace_debug:
self.fm_controller.save_state() self.fm_controller.save_state()
dir = None @daemon_threaded
files = None
def generate_icons(self, tab, store, dir, files): def generate_icons(self, tab, store, dir, files):
for i, file in enumerate(files): for i, file in enumerate(files):
self.make_and_load_icon( i, store, tab, dir, file[0]) self.make_and_load_icon(i, store, tab, dir, file[0])
def update_store(self, i, store, icon):
itr = store.get_iter(i)
GLib.idle_add(self.insert_store, store, itr, icon.copy())
itr = None
del icon
@daemon_threaded
def make_and_load_icon(self, i, store, tab, dir, file): def make_and_load_icon(self, i, store, tab, dir, file):
icon = tab.create_icon(dir, file) icon = tab.create_icon(dir, file)
GLib.idle_add(self.update_store, i, store, icon) # self.update_store(i, store, icon)
GLib.idle_add(self.update_store, i, store, icon.copy())
icon.run_dispose()
def update_store(self, i, store, icon):
try:
itr = store.get_iter(i)
except Exception:
return
self.insert_store(store, itr, icon)
# GLib.idle_add(self.insert_store, store, itr, icon.copy())
# icon.run_dispose()
icon = None icon = None
def get_icon(self, tab, dir, file): def get_icon(self, tab, dir, file):

View File

@@ -74,17 +74,25 @@ class TabMixin(GridMixin):
watcher = tab.get_dir_watcher() watcher = tab.get_dir_watcher()
watcher.cancel() watcher.cancel()
watcher.disconnect(watcher.watch_id)
watcher.run_dispose()
self.get_fm_window(wid).delete_tab_by_id(tid) self.get_fm_window(wid).delete_tab_by_id(tid)
tab_box.unload_signals() tab_box.clear_signals_and_data()
icon_grid.unload_signals() icon_grid.clear_signals_and_data()
icon_grid.set_model(None)
self.builder.dereference_object(f"{wid}|{tid}|icon_grid") self.builder.dereference_object(f"{wid}|{tid}|icon_grid")
self.builder.dereference_object(f"{wid}|{tid}") self.builder.dereference_object(f"{wid}|{tid}")
notebook.remove_page( notebook.page_num(scroll) ) notebook.remove_page( notebook.page_num(scroll) )
tab_box.run_dispose()
icon_grid.run_dispose()
scroll.run_dispose()
tab_box.unparent()
icon_grid.unparent()
scroll.unparent()
if not settings_manager.is_trace_debug(): if not settings_manager.is_trace_debug():
self.fm_controller.save_state() self.fm_controller.save_state()
@@ -103,6 +111,8 @@ class TabMixin(GridMixin):
_tab = window.get_tab_by_id(tid) _tab = window.get_tab_by_id(tid)
watcher = _tab.get_dir_watcher() watcher = _tab.get_dir_watcher()
watcher.cancel() watcher.cancel()
watcher.disconnect(watcher.watch_id)
watcher.run_dispose()
window.get_all_tabs().insert(new_index, window.get_all_tabs().pop(i)) window.get_all_tabs().insert(new_index, window.get_all_tabs().pop(i))
tab = window.get_tab_by_id(tid) tab = window.get_tab_by_id(tid)
@@ -110,11 +120,6 @@ class TabMixin(GridMixin):
if not settings_manager.is_trace_debug(): if not settings_manager.is_trace_debug():
self.fm_controller.save_state() self.fm_controller.save_state()
wid, tid = None, None
window = None
tab = None
def on_tab_switch_update(self, notebook, content = None, index = None): def on_tab_switch_update(self, notebook, content = None, index = None):
self.selected_files.clear() self.selected_files.clear()
wid, tid = content.get_children()[0].get_name().split("|") wid, tid = content.get_children()[0].get_name().split("|")
@@ -123,8 +128,6 @@ class TabMixin(GridMixin):
self.set_path_text(wid, tid) self.set_path_text(wid, tid)
self.set_window_title() self.set_window_title()
wid, tid = None, None
def get_id_from_tab_box(self, tab_box): def get_id_from_tab_box(self, tab_box):
return tab_box.tab.get_id() return tab_box.tab.get_id()

View File

@@ -1,4 +1,5 @@
# Python imports # Python imports
import gc
# Lib imports # Lib imports
import gi import gi
@@ -77,14 +78,14 @@ class IconGridWidget(Gtk.IconView):
return self.get_model() return self.get_model()
def clear_and_set_new_store(self): def clear_and_set_new_store(self):
self.set_model(None) self._clear_store()
self.set_model( self.set_model(
Gtk.ListStore( Gtk.ListStore(
GdkPixbuf.Pixbuf or GdkPixbuf.PixbufAnimation or None, str or None GdkPixbuf.Pixbuf or GdkPixbuf.PixbufAnimation or None, str or None
) )
) )
def unload_signals(self): def clear_signals_and_data(self):
self.unset_model_drag_dest() self.unset_model_drag_dest()
self.unset_model_drag_source() self.unset_model_drag_source()
@@ -92,3 +93,29 @@ class IconGridWidget(Gtk.IconView):
self.disconnect(handle_id) self.disconnect(handle_id)
self._handler_ids.clear() self._handler_ids.clear()
self._clear_store()
def _clear_store(self):
store = self.get_model()
if store:
iter = store.get_iter_first()
while iter:
next_iter = store.iter_next(iter)
item = store.get_value(iter, 0)
if item:
item.run_dispose()
item = None
store.set_value(iter, 0, None)
store.set_value(iter, 1, None)
store.unref_node(iter)
iter = next_iter
store.clear()
store.run_dispose()
del store
gc.collect()
self.set_model(None)

View File

@@ -47,7 +47,7 @@ class TabHeaderWidget(Gtk.Box):
self.show_all() self.show_all()
def unload_signals(self): def clear_signals_and_data(self):
self.close_btn.disconnect(self._handler_id) self.close_btn.disconnect(self._handler_id)
self._close_tab = None self._close_tab = None
self._handler_id = None self._handler_id = None