logical_layers/debug2.py

236 lines
7.0 KiB
Python

# debug2.py
import pcbnew
import sys
import wx
import os
from .backend import manager
from .backend.resolvers import find_item_by_uuid, get_item_uuid
def log(msg):
print(f"[DEBUG2] {msg}")
def debug_dump_layer(layer_idx=0):
"""Prints the internal state of a specific layer."""
if layer_idx >= len(manager.layers):
log("Invalid layer index")
return
l = manager.layers[layer_idx]
log(f"Layer '{l.name}' (Visible: {l.visible})")
log(f" On Board Items: {len(l.on_board_items)}")
for item in l.on_board_items:
log(f" - {item['uuid']} ({item['class']})")
log(f" Stored Items: {len(l.stored_items)}")
for item in l.stored_items:
log(f" - {item}")
def debug_check_item_state(item):
"""Checks flags and state of an item."""
if not item:
return "None"
state = []
try:
if item.IsSelected(): state.append("Selected")
if item.IsLocked(): state.append("Locked")
if item.GetParent(): state.append(f"HasParent({item.GetParent().GetClass()})")
except Exception as e:
state.append(f"ErrorChecking({e})")
return ", ".join(state)
def clear_selection_safe():
"""Safely clears selection by iterating selected items."""
try:
sel = pcbnew.GetCurrentSelection()
items = [i for i in sel]
if not items:
return
log(f" [ACTION] Clearing selection of {len(items)} items...")
for item in items:
if hasattr(item, 'ClearSelected'):
item.ClearSelected()
if hasattr(item, 'ClearBrightened'):
item.ClearBrightened()
except Exception as e:
log(f" [FAIL] Failed to clear selection: {e}")
def serialize_item_safe(item):
"""
Attempts to serialize an item using PCB_IO_KICAD_SEXPR (Format).
"""
if not item: return None
try:
sf = pcbnew.STRING_FORMATTER()
plugin = pcbnew.PCB_IO_KICAD_SEXPR()
plugin.SetOutputFormatter(sf)
plugin.Format(item)
return sf.GetString()
except Exception as e:
log(f" [WARN] Plugin serialization failed: {e}")
try:
sf = pcbnew.STRING_FORMATTER()
if hasattr(item, 'Serialize'):
item.Serialize(sf)
return sf.GetString()
except Exception as e2:
log(f" [FAIL] Direct serialization failed: {e2}")
return None
def debug_test_hide(layer_idx=0):
"""
Performs a FULL hide operation with logging:
1. Clear Selection
2. Serialize & Save to Disk
3. Remove from Board
4. Update Layer State
"""
log("--- TEST HIDE START ---")
if layer_idx >= len(manager.layers):
log("Invalid layer index")
return
layer = manager.layers[layer_idx]
board = pcbnew.GetBoard()
# Ensure storage is ready
if not manager.storage.setup_paths():
log("[FAIL] Could not setup storage paths")
return
if not layer.visible:
log("Layer is already hidden. forcing visible=True for test logic (assuming items are on board).")
log(f"Iterating {len(layer.on_board_items)} items to hide...")
clear_selection_safe()
new_stored_items = []
items_to_remove = []
for i, entry in enumerate(layer.on_board_items):
uuid = entry['uuid']
log(f"Item {i}: UUID {uuid}")
item = find_item_by_uuid(board, uuid)
if item is None:
log(" [FAIL] Item not found on board")
continue
# Serialize
sexpr = serialize_item_safe(item)
if not sexpr:
log(" [FAIL] Serialization failed")
continue
# Save to disk
item_data = {
'class': item.GetClass(),
'sexpr': sexpr,
'uuid': uuid
}
if hasattr(item, 'GetReference'): item_data['ref'] = item.GetReference()
if hasattr(item, 'GetNetname'): item_data['net'] = item.GetNetname()
filename = manager.storage.save_item(item_data, uuid)
if filename:
log(f" [OK] Saved to {filename}")
new_stored_items.append(filename)
items_to_remove.append(item)
else:
log(" [FAIL] Failed to save file")
# Remove items
log(f"Removing {len(items_to_remove)} items...")
for item in items_to_remove:
try:
if item.IsLocked(): item.SetLocked(False)
board.Remove(item)
except Exception as e:
log(f" [FAIL] Remove failed: {e}")
# Update Layer State
layer.stored_items = new_stored_items
layer.on_board_items = []
layer.visible = False
manager.save()
pcbnew.Refresh()
log("--- TEST HIDE END ---")
def debug_test_unhide(layer_idx=0):
"""
Performs a FULL unhide operation with logging:
1. Load from Disk
2. Deserialize
3. Add to Board
4. Update Layer State
"""
log("--- TEST UNHIDE START ---")
if layer_idx >= len(manager.layers):
log("Invalid layer index")
return
layer = manager.layers[layer_idx]
board = pcbnew.GetBoard()
if layer.visible:
log("Layer is visible. Forcing visible=False for test logic.")
log(f"Iterating {len(layer.stored_items)} stored items to restore...")
new_on_board = []
for filename in layer.stored_items:
log(f"Loading {filename}...")
item_data = manager.storage.load_item(filename)
if not item_data:
log(" [FAIL] Load failed")
continue
cls_name = item_data.get('class')
sexpr = item_data.get('sexpr')
uuid = item_data.get('uuid')
if not hasattr(pcbnew, cls_name):
log(f" [FAIL] Unknown class {cls_name}")
continue
try:
cls = getattr(pcbnew, cls_name)
try: item = cls(board)
except: item = cls()
# Fix: STRING_LINE_READER requires 2 arguments in KiCad 9 (data, source_name)
lr = pcbnew.STRING_LINE_READER(sexpr, "restore")
item.Deserialize(lr)
board.Add(item)
# Re-verify UUID
new_uuid = get_item_uuid(item)
log(f" [OK] Restored item {new_uuid}")
new_on_board.append({'uuid': new_uuid, 'class': cls_name})
except Exception as e:
log(f" [FAIL] Restore failed: {e}")
# Update Layer State
layer.on_board_items = new_on_board
layer.stored_items = []
layer.visible = True
manager.save()
pcbnew.Refresh()
log("--- TEST UNHIDE END ---")
def debug_reset_state(layer_idx=0):
"""Resets a layer to 'Visible' and empty, useful if state gets desynced."""
if layer_idx >= len(manager.layers): return
l = manager.layers[layer_idx]
l.visible = True
l.on_board_items = []
l.stored_items = []
manager.save()
log(f"Layer {l.name} state reset to Visible/Empty.")