# 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.")