First Commit
Sedona sax editor AI yardimi ile yaziliyor
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
"""Kit manifest loading, slot inheritance, and which slots are worth showing."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from tkinter import messagebox
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import app_state
|
||||
|
||||
|
||||
def read_summary_facet(slot_element):
|
||||
"""Reads a slot's '@summary' facet. Absent means summary, matching manifest convention."""
|
||||
facets = slot_element.find("facets")
|
||||
if facets is None:
|
||||
return True
|
||||
for bool_facet in facets.findall("bool"):
|
||||
if bool_facet.get("name") == "summary":
|
||||
return (bool_facet.get("val", "true").strip().lower() != "false")
|
||||
return True
|
||||
|
||||
|
||||
def get_slots_with_inheritance(type_name, kit_schemas):
|
||||
"""Recursively resolves the slots for a given type by traversing its base chain."""
|
||||
if type_name not in kit_schemas:
|
||||
kit_prefix = type_name.split("::")[0] if "::" in type_name else type_name
|
||||
messagebox.showerror("Schema Warning", f"Kit {kit_prefix} is not in Schema selection!")
|
||||
sys.exit(1)
|
||||
|
||||
type_element = kit_schemas[type_name]
|
||||
base_type = type_element.get("base")
|
||||
|
||||
resolved_slots = []
|
||||
if base_type:
|
||||
resolved_slots = get_slots_with_inheritance(base_type, kit_schemas)
|
||||
|
||||
current_slots = []
|
||||
for slot in type_element.findall("slot"):
|
||||
current_slots.append({
|
||||
"name": slot.get("name"),
|
||||
"type": slot.get("type"),
|
||||
"default": slot.get("default", "false"),
|
||||
"flags": slot.get("flags", ""), # Capture visibility flags ('o' maps to operator/hidden)
|
||||
"summary": read_summary_facet(slot),
|
||||
"declared_id": int(slot.get("id"))
|
||||
})
|
||||
|
||||
current_slots.sort(key=lambda s: s["declared_id"])
|
||||
resolved_slots.extend(current_slots)
|
||||
return resolved_slots
|
||||
|
||||
|
||||
def compile_schema_registry(manifest_paths):
|
||||
"""Loads and maps types across multiple kit files, ensuring all dependencies exist."""
|
||||
kit_schemas = {}
|
||||
|
||||
for path in manifest_paths:
|
||||
try:
|
||||
tree = ET.parse(path)
|
||||
root = tree.getroot()
|
||||
kit_name = root.get("name")
|
||||
|
||||
for type_tag in root.findall("type"):
|
||||
type_name = f"{kit_name}::{type_tag.get('name')}"
|
||||
kit_schemas[type_name] = type_tag
|
||||
except Exception as e:
|
||||
print(f"Error parsing manifest {path}: {e}")
|
||||
|
||||
app_state.final_components_registry.clear()
|
||||
for type_name in kit_schemas.keys():
|
||||
flat_slots = get_slots_with_inheritance(type_name, kit_schemas)
|
||||
|
||||
resolved_type_structure = []
|
||||
for sequence_id, slot_data in enumerate(flat_slots):
|
||||
resolved_type_structure.append({
|
||||
"slot_id": sequence_id,
|
||||
"name": slot_data["name"],
|
||||
"type": slot_data["type"],
|
||||
"default": slot_data["default"],
|
||||
"flags": slot_data["flags"],
|
||||
"summary": slot_data["summary"]
|
||||
})
|
||||
app_state.final_components_registry[type_name] = resolved_type_structure
|
||||
|
||||
|
||||
def load_schema_kits_and_manifests():
|
||||
"""Scans the schema block of the SAX file and maps/loads corresponding manifest definitions."""
|
||||
app_state.active_schema_kits.clear()
|
||||
if app_state.xml_root_element is None:
|
||||
return
|
||||
|
||||
schema_elem = app_state.xml_root_element.find("schema")
|
||||
if schema_elem is None:
|
||||
return
|
||||
|
||||
manifest_paths = []
|
||||
for kit in schema_elem.findall("kit"):
|
||||
name = kit.get("name")
|
||||
checksum = kit.get("checksum")
|
||||
if not name:
|
||||
continue
|
||||
app_state.active_schema_kits[name] = checksum
|
||||
|
||||
manifest_dir = os.path.join(app_state.SEDONA_HOME, "manifests", name)
|
||||
manifest_path = None
|
||||
|
||||
if checksum:
|
||||
target_file = os.path.join(manifest_dir, f"{name}-{checksum}.xml")
|
||||
if os.path.exists(target_file):
|
||||
manifest_path = target_file
|
||||
|
||||
if not manifest_path and os.path.exists(manifest_dir):
|
||||
files = [f for f in os.listdir(manifest_dir) if f.startswith(f"{name}-") and f.endswith(".xml")]
|
||||
if files:
|
||||
files.sort()
|
||||
manifest_path = os.path.join(manifest_dir, files[-1])
|
||||
|
||||
if manifest_path:
|
||||
manifest_paths.append(manifest_path)
|
||||
else:
|
||||
messagebox.showerror("Schema Warning", f"Kit {name} is not in Schema selection!")
|
||||
sys.exit(1)
|
||||
|
||||
compile_schema_registry(manifest_paths)
|
||||
|
||||
|
||||
def get_slots_for_type(type_str, linked_slots=()):
|
||||
"""
|
||||
Returns the slots worth painting for a given type, prefixed with double-digit
|
||||
index tags taken from the manifest so hidden rows leave gaps rather than renumber.
|
||||
|
||||
Visibility, in order of precedence:
|
||||
- a linked slot is always shown, so its wire has a row to anchor to
|
||||
- '@summary false' hides the slot, even when it is runtime
|
||||
- runtime slots (no 'c' flag) are shown; they hold the live signal path
|
||||
- config slots that nothing links to are hidden as clutter
|
||||
- the 'o' (operator) flag hides a slot outright
|
||||
"""
|
||||
if type_str not in app_state.final_components_registry:
|
||||
return []
|
||||
|
||||
slots_list = []
|
||||
for slot_data in app_state.final_components_registry[type_str]:
|
||||
slot_name = slot_data["name"]
|
||||
if not slot_name:
|
||||
continue
|
||||
if "o" in slot_data["flags"]:
|
||||
continue
|
||||
|
||||
is_linked = slot_name in linked_slots
|
||||
if not is_linked:
|
||||
if not slot_data.get("summary", True):
|
||||
continue
|
||||
if "c" in slot_data["flags"]:
|
||||
continue
|
||||
|
||||
# Format to double digits (e.g., 00, 01, 02)
|
||||
padded_id = f"{slot_data['slot_id']:02d}"
|
||||
display_label = f"{padded_id}. {slot_name}"
|
||||
|
||||
# Keep structural name unchanged for XML lookup inside comp, but pass display label
|
||||
slots_list.append((slot_name, display_label))
|
||||
|
||||
return slots_list
|
||||
Reference in New Issue
Block a user