Implement live device add/delete component and app actions
Fix add component from palette in live mode: resolve <app> element as comp_id 0, fix type_id lookup to use type_name_map, set type_name on newly added SoxComponent, sync device values into DOM after add, write meta position back to device, and subscribe new component to COV. Fix delete component in live mode: clean up subscriptions for deleted component and all its descendants. Add tree root context menu with device app actions (save, hibernate, quit, restart, reboot) in live mode. Device save clears dirty state. Clean up connection lost handling to do a full disconnect. Fix slot registry to copy base slots and renumber IDs correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+14
-9
@@ -66,6 +66,7 @@ def live_add_component(parent_element, kit_name, type_name, comp_name, config_va
|
||||
|
||||
try:
|
||||
new_comp = ds.sox_client.add(parent_id, kit_id, type_id_val, comp_name, sox_config)
|
||||
ds.after_add(new_comp.id)
|
||||
return new_comp.id
|
||||
except Exception as e:
|
||||
app_state.set_status(f"Add failed: {e}", warn=True)
|
||||
@@ -84,8 +85,16 @@ def live_delete_component(element):
|
||||
if comp_id is None:
|
||||
return False
|
||||
|
||||
descendant_ids = []
|
||||
for desc in element.iter():
|
||||
if desc.tag == "comp" and desc is not element:
|
||||
did = _comp_id(desc)
|
||||
if did is not None:
|
||||
descendant_ids.append(did)
|
||||
|
||||
try:
|
||||
ds.sox_client.delete(comp_id)
|
||||
ds.after_delete(comp_id, descendant_ids)
|
||||
return True
|
||||
except Exception as e:
|
||||
app_state.set_status(f"Delete failed: {e}", warn=True)
|
||||
@@ -189,6 +198,8 @@ def live_invoke(element, slot_name, arg=None):
|
||||
# ── Helpers ─────────────────────────────────────────────────────
|
||||
|
||||
def _comp_id(element):
|
||||
if element.tag == "app":
|
||||
return 0
|
||||
cid = element.get("id")
|
||||
if cid is None:
|
||||
return None
|
||||
@@ -222,15 +233,9 @@ def _kit_id(ds, kit_name):
|
||||
def _type_id(ds, kit_id, type_name):
|
||||
if kit_id is None:
|
||||
return None
|
||||
for (kid, tid), slots in ds.sox_client.slot_registry.items():
|
||||
if kid == kit_id:
|
||||
comp = ds.sox_client.cache_get(0)
|
||||
if comp and comp.type_name.endswith(f"::{type_name}"):
|
||||
return tid
|
||||
# fallback: search all cached components for a matching type_name
|
||||
for c in ds.sox_client.cache:
|
||||
if c is not None and c.kit_id == kit_id and c.type_name.endswith(f"::{type_name}"):
|
||||
return c.type_id
|
||||
for (kid, tid), full_name in ds.sox_client.type_name_map.items():
|
||||
if kid == kit_id and full_name.endswith(f"::{type_name}"):
|
||||
return tid
|
||||
return None
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user