From d32285abe8ca00d4f974be1cbd5864091f05d1f0 Mon Sep 17 00:00:00 2001 From: Arda Aydin Date: Sat, 12 Sep 2026 09:11:14 +0300 Subject: [PATCH] Fix tree expand in live mode: use focused item and run IO in background _on_tree_open used tree.selection() which may differ from the opened node; switched to tree.focus(). Network calls in _live_tree_expand now run in a daemon thread so the UI stays responsive during lazy loading. Co-Authored-By: Claude Opus 4.6 --- app_state.py | 2 +- main.py | 46 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/app_state.py b/app_state.py index c054ae1..2df469d 100644 --- a/app_state.py +++ b/app_state.py @@ -8,7 +8,7 @@ so later rebinding would only ever be seen by the module that did it. import configparser import os -VERSION = "0.0.0.078" +VERSION = "0.0.0.079" PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties") DEFAULT_GRID_SIZE = 10 DEFAULT_ADD_TIMESTAMP = True diff --git a/main.py b/main.py index ea2ae94..f3c1f9d 100644 --- a/main.py +++ b/main.py @@ -1352,13 +1352,13 @@ def attach_tree_scrollbars(container, tree): def _on_tree_open(event): tree.after_idle(fit_tree_column, tree) if app_state.live_mode: - sel = tree.selection() - if sel: - elem = app_state.tree_element_map.get(sel[0]) + opened = tree.focus() + if opened: + elem = app_state.tree_element_map.get(opened) if elem is not None: cid = elem.get("id") if cid is not None: - _live_tree_expand(int(cid)) + _live_tree_expand(int(cid), opened) tree.bind("<>", _on_tree_open, add="+") tree.bind("<>", lambda event: tree.after_idle(fit_tree_column, tree), add="+") @@ -2041,20 +2041,42 @@ def _start_cov_polling(): _cov_poll_id = app_state.window.after(100, poll) -def _live_tree_expand(comp_id): +def _live_tree_expand(comp_id, tree_item_id): """Called when user expands a tree node in live mode to lazy-load children.""" ds = app_state.device_session if ds is None or not ds.is_connected: return - children = ds.load_children(comp_id) - if not children: - return + app_state.set_status("Loading children...") - sax_root = ds.build_dom_tree(ds.sox_client.cache_get(0)) - ds.build_links_elements(sax_root) - app_state.xml_root_element = sax_root - sax_file.refresh_treeview_from_dom(sax_root) + def _bg(): + try: + children = ds.load_children(comp_id) + if not children: + app_state.window.after(0, lambda: app_state.set_status("No children")) + return + sax_root = ds.build_dom_tree(ds.sox_client.cache_get(0)) + ds.build_links_elements(sax_root) + + def _ui(): + app_state.xml_root_element = sax_root + sax_file.refresh_treeview_from_dom(sax_root) + # Re-open and select the node the user clicked + for iid, elem in app_state.tree_element_map.items(): + if elem.get("id") == str(comp_id): + tree.item(iid, open=True) + tree.selection_set(iid) + tree.see(iid) + break + app_state.set_status(f"Loaded {len(children)} children") + + app_state.window.after(0, _ui) + except Exception as exc: + app_state.window.after( + 0, lambda: app_state.set_status(f"Load error: {exc}", warn=True) + ) + + threading.Thread(target=_bg, daemon=True).start() # --- UI Setup ---