app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Drive your own KiCad from an AI, in the background: open every editor, read the whole board as data (the EDA Bridge Standard board model), stack-up, part heights, netlists, place, route, pour, DRC and exports.
← Commit history
1.0.34: 1.0.34 (wiki #107): the window placement memory reads the flat file the Python build (0.9.x) wrote, so an upgrading user's remembered windows survive the first native save. Found on arav-rog during the two-monitor tests, which passed: a PCB editor parked on a second display at negative x and a different DPI scale came back there after a force-kill (moved:true), a remembered rect on a display that is not connected was refused, and an idle window was left alone.
1 file changed
+25−2
rust/crates/kicad-core/src/window_memory.rs+25−2@@ -44,11 +44,23 @@ fn i32_of(v: &Value, k: &str) -> Option<i32> { v.get(k).and_then(Value::as_i64).map(|n| n as i32) } +fn legacy_kind(k: &str) -> String {+ match k {+ "kicad" => "project_manager".to_string(),+ other => other.replace(' ', "_"),+ }+}+ pub fn from_json(doc: &Value) -> Memory { let mut out = Memory::new();- let Some(windows) = doc.get("windows").and_then(Value::as_object) else { return out };+ // The Python build (0.9.x) wrote a flat file: {"pcb editor": {x, y, w, h, maximized}}. Read it+ // too, or the first native save replaces it and the user's other window kinds are lost+ // (seen on arav-rog, wiki #107).+ let legacy = doc.get("windows").is_none();+ let Some(windows) = doc.get("windows").and_then(Value::as_object).or_else(|| if legacy { doc.as_object() } else { None }) else { return out }; for (kind, v) in windows {- let (Some(x), Some(y), Some(width), Some(height)) = (i32_of(v, "x"), i32_of(v, "y"), i32_of(v, "width"), i32_of(v, "height")) else { continue };+ let kind = &if legacy { legacy_kind(kind) } else { kind.clone() };+ let (Some(x), Some(y), Some(width), Some(height)) = (i32_of(v, "x"), i32_of(v, "y"), i32_of(v, "width").or_else(|| i32_of(v, "w")), i32_of(v, "height").or_else(|| i32_of(v, "h"))) else { continue }; if width <= 0 || height <= 0 { continue; // a zero rect is not a placement, it is a window that was not up }@@ -136,6 +148,17 @@ mod tests { Placement { x, y, width: w, height: h, maximized: max } } + #[test]+ fn the_python_builds_flat_file_is_read_not_discarded() {+ let doc = json!({"pcb editor": {"x": -2300, "y": 300, "w": 1600, "h": 1000, "maximized": false},+ "kicad": {"x": -11, "y": -11, "w": 2582, "h": 1390, "maximized": true},+ "3d viewer": {"x": 0, "y": 0, "w": 0, "h": 0, "maximized": false}});+ let mem = from_json(&doc);+ assert_eq!(mem.get("pcb_editor").unwrap().place, p(-2300, 300, 1600, 1000, false));+ assert!(mem.get("project_manager").unwrap().place.maximized);+ assert!(mem.get("3d_viewer").is_none());+ }+ #[test] fn a_window_on_a_second_monitor_is_remembered_and_put_back() { let mut mem = Memory::new();