236 lines
7.0 KiB
Python
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.") |