App tree: keep expanded folders open; only the - sign closes one

Rebuilding the tree (live child loads, edits) now restores every row that
was expanded, matched by component id or name path. Double-click no longer
toggles a row through ttk's default binding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 19:25:44 +03:00
co-authored by Claude Opus 5.5
parent 05ca7e9035
commit 96a703c5d5
3 changed files with 56 additions and 5 deletions
+47 -1
View File
@@ -59,9 +59,53 @@ def parse_xml_to_tree(treeview, parent_node, xml_element):
parse_xml_to_tree(treeview, node_id, child)
def _expansion_key(treeview, item, parent_key):
"""Names a tree row in a way that survives a rebuild of the tree.
A component's id is stable across edits and across a fresh DOM read from the
device; a row without one (the root, or an id-less file component) falls back to
its name under its parent's key.
"""
elem = app_state.tree_element_map.get(item)
comp_id = elem.get("id") if elem is not None else None
if comp_id is not None and treeview.parent(item) != "":
return ("id", comp_id)
name = elem.get("name", "") if elem is not None else treeview.item(item, "text")
return ("path", parent_key, name)
def _collect_open_keys(treeview, parent="", parent_key=None, found=None):
"""Returns the keys of every row that is expanded right now."""
if found is None:
found = set()
for item in treeview.get_children(parent):
key = _expansion_key(treeview, item, parent_key)
if treeview.item(item, "open"):
found.add(key)
_collect_open_keys(treeview, item, key, found)
return found
def _reopen_keys(treeview, open_keys, parent="", parent_key=None):
"""Expands again the rows that were expanded before the rebuild.
Setting the open flag in code does not raise <<TreeviewOpen>>, so this never
starts a live child load of its own.
"""
for item in treeview.get_children(parent):
key = _expansion_key(treeview, item, parent_key)
if key in open_keys:
treeview.item(item, open=True)
_reopen_keys(treeview, open_keys, item, key)
def refresh_treeview_from_dom(xml_root):
"""Rebuilds navigation tree structures using current XML DOM trees."""
"""Rebuilds navigation tree structures using current XML DOM trees.
Rows the user had expanded stay expanded; only the user's own "-" closes one.
"""
tree = app_state.tree
open_keys = _collect_open_keys(tree)
app_state.tree_element_map.clear()
for item in tree.get_children():
@@ -88,6 +132,8 @@ def refresh_treeview_from_dom(xml_root):
else:
parse_xml_to_tree(tree, root_node, xml_root)
_reopen_keys(tree, open_keys)
if _tree_filled is not None:
_tree_filled()