112 lines
3.6 KiB
Python
112 lines
3.6 KiB
Python
# backend/resolvers.py
|
|
import pcbnew
|
|
|
|
def get_item_uuid(item):
|
|
"""
|
|
Robustly retrieve the UUID string from a KiCad item.
|
|
Prioritizes m_Uuid property (KiCad 9 SWIG) over GetKIID().
|
|
"""
|
|
if not item: return None
|
|
try:
|
|
# KiCad 9 / SWIG property access
|
|
if hasattr(item, 'm_Uuid'):
|
|
return item.m_Uuid.AsString()
|
|
# Legacy / Alternative accessor
|
|
if hasattr(item, 'GetKIID'):
|
|
return item.GetKIID().AsString()
|
|
except:
|
|
pass
|
|
return None
|
|
|
|
def resolve_to_trackable_item(item):
|
|
"""
|
|
Resolves an item to the actual object we want to track.
|
|
- If item is a Pad/Text/Shape inside a Footprint -> Returns the Footprint.
|
|
- If item is a Group -> Returns None (we track contents, not groups).
|
|
- Otherwise -> Returns the item itself.
|
|
"""
|
|
if not item: return None
|
|
|
|
cls = item.GetClass()
|
|
if cls == "PCB_GROUP":
|
|
return None
|
|
|
|
# Check for Parent (e.g. Pad -> Footprint)
|
|
parent = item.GetParent()
|
|
if parent and parent.GetClass() == "FOOTPRINT":
|
|
return parent
|
|
|
|
return item
|
|
|
|
def cast_item(item):
|
|
"""
|
|
Casts a generic BOARD_ITEM to its specific class type.
|
|
Required for methods like Serialize or Format to work correctly.
|
|
"""
|
|
if not item: return None
|
|
|
|
# Try generic Cast() first (Available on some BOARD_ITEM wrappers)
|
|
if hasattr(item, 'Cast'):
|
|
try:
|
|
return item.Cast()
|
|
except:
|
|
pass
|
|
|
|
# Fallback to manual casting based on class name
|
|
cls = item.GetClass()
|
|
try:
|
|
if cls == "FOOTPRINT": return pcbnew.Cast_to_FOOTPRINT(item)
|
|
if cls == "PCB_TRACK": return pcbnew.Cast_to_PCB_TRACK(item)
|
|
if cls == "PCB_VIA": return pcbnew.Cast_to_PCB_VIA(item)
|
|
if cls == "PCB_ARC": return pcbnew.Cast_to_PCB_ARC(item)
|
|
if cls == "PCB_SHAPE": return pcbnew.Cast_to_PCB_SHAPE(item)
|
|
if cls == "PCB_TEXT": return pcbnew.Cast_to_PCB_TEXT(item)
|
|
if cls == "PCB_TEXTBOX": return pcbnew.Cast_to_PCB_TEXTBOX(item)
|
|
if cls == "ZONE": return pcbnew.Cast_to_ZONE(item)
|
|
if cls == "PCB_GROUP": return pcbnew.Cast_to_PCB_GROUP(item)
|
|
if cls == "PCB_TARGET": return pcbnew.Cast_to_PCB_TARGET(item)
|
|
if cls == "PCB_DIM_ALIGNED": return pcbnew.Cast_to_PCB_DIM_ALIGNED(item)
|
|
if cls == "PCB_DIM_ORTHOGONAL": return pcbnew.Cast_to_PCB_DIM_ORTHOGONAL(item)
|
|
if cls == "PCB_DIM_CENTER": return pcbnew.Cast_to_PCB_DIM_CENTER(item)
|
|
if cls == "PCB_DIM_LEADER": return pcbnew.Cast_to_PCB_DIM_LEADER(item)
|
|
if cls == "PCB_DIM_RADIAL": return pcbnew.Cast_to_PCB_DIM_RADIAL(item)
|
|
except:
|
|
pass
|
|
|
|
return item
|
|
|
|
def find_item_by_uuid(board, uuid):
|
|
"""
|
|
Locates an item on the board by its UUID string.
|
|
Checks standard lists (Tracks, Footprints, Drawings, Zones).
|
|
Returns a CAST item (specific type) if found.
|
|
"""
|
|
item = None
|
|
if hasattr(board, 'GetItem'):
|
|
try:
|
|
item = board.GetItem(pcbnew.KIID(uuid))
|
|
except: pass
|
|
|
|
if not item:
|
|
# Fallback lists for older API or if GetItem fails
|
|
lists = []
|
|
try: lists.append(board.GetTracks())
|
|
except: pass
|
|
try: lists.append(board.GetFootprints())
|
|
except: pass
|
|
try: lists.append(board.GetDrawings())
|
|
except: pass
|
|
try: lists.append(board.Zones())
|
|
except: pass
|
|
|
|
for lst in lists:
|
|
for candidate in lst:
|
|
if get_item_uuid(candidate) == uuid:
|
|
item = candidate
|
|
break
|
|
if item: break
|
|
|
|
if item:
|
|
return cast_item(item)
|
|
|
|
return None |