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:
+47
-1
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user