updated dir watch; removed keys call where senseable; added additional. debug hook; added threading and async code for testing

This commit is contained in:
itdominator 2024-06-12 00:32:14 -05:00
parent a362039e73
commit 2f954f4c79
8 changed files with 88 additions and 76 deletions

View File

@ -30,58 +30,46 @@ class FileActionSignalsMixin:
wid = tab.get_wid()
tid = tab.get_id()
dir_watcher.connect("changed", self.dir_watch_updates, (f"{wid}|{tid}",))
dir_watcher.connect("changed", self.dir_watch_updates, *(f"{wid}|{tid}",))
tab.set_dir_watcher(dir_watcher)
# NOTE: Too lazy to impliment a proper update handler and so just regen store and update tab.
# Use a lock system to prevent too many update calls for certain instances but user can manually refresh if they have urgency
def dir_watch_updates(self, file_monitor, file, other_file = None, eve_type = None, data = 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,
Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN,
Gio.FileMonitorEvent.MOVED_OUT]:
if eve_type in [Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.MOVED_OUT]:
self.update_on_soft_lock_end(data[0])
elif data[0] in self.soft_update_lock.keys():
self.soft_update_lock[data[0]]["last_update_time"] = time.time()
else:
self.soft_lock_countdown(data[0])
self.soft_lock_countdown(tab_widget_id)
@daemon_threaded
def soft_lock_countdown(self, tab_widget):
self.soft_update_lock[tab_widget] = { "last_update_time": time.time()}
def soft_lock_countdown(self, tab_widget_id):
if tab_widget_id in self.soft_update_lock:
timeout_id = self.soft_update_lock[tab_widget_id]["timeout_id"]
GLib.source_remove(timeout_id)
lock = True
while lock:
time.sleep(0.6)
last_update_time = self.soft_update_lock[tab_widget]["last_update_time"]
current_time = time.time()
if (current_time - last_update_time) > 0.6:
lock = False
timeout_id = GLib.timeout_add(0, self.update_on_soft_lock_end, 600, *(tab_widget_id,))
self.soft_update_lock[tab_widget_id] = { "timeout_id": timeout_id }
self.soft_update_lock.pop(tab_widget, None)
GLib.idle_add(self.update_on_soft_lock_end, *(tab_widget,))
def update_on_soft_lock_end(self, tab_widget):
wid, tid = tab_widget.split("|")
def update_on_soft_lock_end(self, timout_ms, tab_widget_id):
self.soft_update_lock.pop(tab_widget_id, None)
wid, tid = tab_widget_id.split("|")
notebook = self.builder.get_object(f"window_{wid}")
tab = self.get_fm_window(wid).get_tab_by_id(tid)
icon_grid = self.builder.get_object(f"{wid}|{tid}|icon_grid", use_gtk = False)
store = icon_grid.get_model()
_store, tab_widget_label = self.get_store_and_label_from_notebook(notebook, f"{wid}|{tid}")
_store, tab_widget_id_label = self.get_store_and_label_from_notebook(notebook, f"{wid}|{tid}")
tab.load_directory()
icon_grid.clear_and_set_new_store()
self.load_store(tab, icon_grid.get_store())
tab_widget_label.set_label(tab.get_end_of_path())
tab_widget_id_label.set_label(tab.get_end_of_path())
state = self.get_current_state()
if [wid, tid] in [state.wid, state.tid]:
self.set_bottom_labels(tab)
return False
def do_file_search(self, widget, eve = None):
if not self.ctrl_down and not self.shift_down and not self.alt_down:
target = widget.get_name()

View File

@ -34,7 +34,6 @@ class GridMixin:
dir = tab.get_current_directory()
files = tab.get_files()
store.clear()
for file in files:
store.append([None, file[0]])
@ -48,33 +47,51 @@ class GridMixin:
self.fm_controller.save_state()
@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.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)]
await asyncio.gather(*tasks)
GLib.idle_add(self.do_ui_update)
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)
async def get_icon(self, tab, dir, file):
@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)
def get_icon(self, tab, dir, file):
return 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)
def insert_store(self, store, itr, icon):
store.set_value(itr, 0, icon)

View File

@ -40,16 +40,15 @@ class ContextMenuWidget(Gtk.Menu):
def _emit(self, menu_item, type):
event_system.emit("do_action_from_menu_controls", type)
def make_submenu(self, name, data, keys):
def make_submenu(self, name, data):
menu = Gtk.Menu()
menu_item = Gtk.MenuItem(name)
for key in keys:
for key, value in data.items():
if isinstance(data, dict):
entry = self.make_menu_item(key, data[key])
entry = self.make_menu_item(key, value)
elif isinstance(data, list):
entry = self.make_menu_item(key, data)
entry = self.make_menu_item(key, value)
else:
continue
@ -58,11 +57,11 @@ class ContextMenuWidget(Gtk.Menu):
menu_item.set_submenu(menu)
return menu_item
def make_menu_item(self, name, data) -> Gtk.MenuItem:
def make_menu_item(self, label, data) -> Gtk.MenuItem:
if isinstance(data, dict):
return self.make_submenu(name, data, data.keys())
return self.make_submenu(label, data)
elif isinstance(data, list):
entry = Gtk.ImageMenuItem(name)
entry = Gtk.ImageMenuItem(label)
icon = getattr(Gtk, f"{data[0]}")
entry.set_image( Gtk.Image(stock=icon) )
entry.set_always_show_image(True)
@ -71,18 +70,18 @@ class ContextMenuWidget(Gtk.Menu):
def build_context_menu(self) -> None:
data = self._context_menu_data
dkeys = data.keys()
plugins_entry = None
for dkey in dkeys:
entry = self.make_menu_item(dkey, data[dkey])
for key, value in data.items():
entry = self.make_menu_item(key, value)
self.append(entry)
if dkey == "Plugins":
if key == "Plugins":
plugins_entry = entry
self.attach_to_widget(self._window, None)
self.show_all()
self.builder.expose_object("context_menu", self)
self.show_all()
if plugins_entry:
self.builder.expose_object("context_menu_plugins", plugins_entry.get_submenu())

View File

@ -55,6 +55,7 @@ class GridMixin:
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) )
@ -63,9 +64,7 @@ class GridMixin:
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)]
await asyncio.gather(*tasks)
GLib.idle_add(self.do_ui_update)
asyncio.gather(*tasks)
async def update_store(self, i, store, icon):
itr = store.get_iter(i)

View File

@ -10,6 +10,7 @@ gi.require_version('Gdk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GLib
from gi.repository import GObject
# Application imports
from core.controller import Controller
@ -24,6 +25,8 @@ class Window(Gtk.ApplicationWindow):
"""docstring for Window."""
def __init__(self, args, unknownargs):
GObject.threads_init()
super(Window, self).__init__()
settings_manager.set_main_window(self)
@ -85,7 +88,7 @@ class Window(Gtk.ApplicationWindow):
if visual != None and screen.is_composited():
self.set_visual(visual)
self.set_app_paintable(True)
self.connect("draw", self._area_draw)
# self.connect("draw", self._area_draw)
# bind css file
cssProvider = Gtk.CssProvider()

View File

@ -53,9 +53,8 @@ class ManifestProcessor:
def get_loading_data(self):
loading_data = {}
requests = self._plugin.requests
keys = requests.keys()
if "ui_target" in keys:
if "ui_target" in requests:
if requests["ui_target"] in [
"none", "other", "main_Window", "main_menu_bar",
"main_menu_bttn_box_bar", "path_menu_bar", "plugin_control_list",
@ -63,7 +62,7 @@ class ManifestProcessor:
"window_2", "window_3", "window_4"
]:
if requests["ui_target"] == "other":
if "ui_target_id" in keys:
if "ui_target_id" in requests:
loading_data["ui_target"] = self._builder.get_object(requests["ui_target_id"])
if loading_data["ui_target"] == None:
raise ManifestProcessorException('Invalid "ui_target_id" given in requests. Must have one if setting "ui_target" to "other"...')
@ -74,11 +73,11 @@ class ManifestProcessor:
else:
raise ManifestProcessorException('Unknown "ui_target" given in requests.')
if "pass_fm_events" in keys:
if "pass_fm_events" in requests:
if requests["pass_fm_events"] in ["true"]:
loading_data["pass_fm_events"] = True
if "pass_ui_objects" in keys:
if "pass_ui_objects" in requests:
if len(requests["pass_ui_objects"]) > 0:
loading_data["pass_ui_objects"] = []
for ui_id in requests["pass_ui_objects"]:
@ -87,7 +86,7 @@ class ManifestProcessor:
except ManifestProcessorException as e:
logger.error(repr(e))
if "bind_keys" in keys:
if "bind_keys" in requests:
if isinstance(requests["bind_keys"], list):
loading_data["bind_keys"] = requests["bind_keys"]

View File

@ -100,20 +100,19 @@ class PluginsController:
def execute_plugin(self, module: type, plugin: PluginInfo, loading_data: []):
plugin.reference = module.Plugin()
keys = loading_data.keys()
if "ui_target" in keys:
if "ui_target" in loading_data:
loading_data["ui_target"].add( plugin.reference.generate_reference_ui_element() )
loading_data["ui_target"].show_all()
if "pass_ui_objects" in keys:
if "pass_ui_objects" in loading_data:
plugin.reference.set_ui_object_collection( loading_data["pass_ui_objects"] )
if "pass_fm_events" in keys:
if "pass_fm_events" in loading_data:
plugin.reference.set_fm_event_system(event_system)
plugin.reference.subscribe_to_events()
if "bind_keys" in keys:
if "bind_keys" in loading_data:
keybindings.append_bindings( loading_data["bind_keys"] )
plugin.reference.run()

View File

@ -37,6 +37,14 @@ def debug_signal_handler(signal, frame):
except Exception as ex:
...
try:
import ipdb
logger.debug("\n\nStarting IPDB debugger...\n\n")
ipdb.set_trace()
return
except Exception as ex:
...
try:
import pdb
logger.debug("\n\nStarting embedded PDB debugger...\n\n")