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
Delete rust/crates/kicad-core/src/ipc/silk_fields.rs.orig
1 file changed
−255
rust/crates/kicad-core/src/ipc/silk_fields.rs.origdeleted−255@@ -1,255 +0,0 @@-use super::*;-use crate::silk_fields as fields;-use kicad_ipc_rs::FieldItem;--fn id(item: &EditablePcbItem) -> Option<&str> {- match item {- EditablePcbItem::Field(f) => f- .proto()- .text- .as_ref()?- .id- .as_ref()- .map(|x| x.value.as_str()),- _ => None,- }-}-fn apply_geometry(mut field: FieldItem, e: &fields::Edit) -> RResult<EditablePcbItem> {- let f = field.proto_mut();- if f.name != e.name {- return Err(RoutingError::new(- "field_identity_mismatch",- "Native field name does not match saved reference/value property",- ));- }- f.visible = e.visible;- let b = f- .text- .as_mut()- .ok_or_else(|| RoutingError::new("field_unavailable", "Native field has no board text"))?;- if b.locked == 2 || b.knockout {- return Err(RoutingError::new(- "field_locked_or_knockout",- "Locked/knockout fields are not supported",- ));- }- b.layer = BoardLayerInfo::id_from_name(&e.text.layer).unwrap();- let t = b- .text- .as_mut()- .ok_or_else(|| RoutingError::new("field_unavailable", "Native field has no text"))?;- if t.text != e.text.text {- return Err(RoutingError::new(- "field_identity_mismatch",- "Native field text differs from the candidate",- ));- }- let p = t.position.get_or_insert_with(Default::default);- p.x_nm = nm(e.text.x);- p.y_nm = nm(e.text.y);- let a = t.attributes.get_or_insert_with(Default::default);- if a.bold- || a.italic- || a.underlined- || (!a.font_name.is_empty() && a.font_name != "KiCad Font")- {- return Err(RoutingError::new(- "field_style_unsupported",- "Only plain native stroke-font fields are supported",- ));- }- a.horizontal_alignment = match e.text.align.as_str() {- "left" => 1,- "right" => 3,- _ => 2,- };- a.vertical_alignment = 2;- a.angle.get_or_insert_with(Default::default).value_degrees = e.text.rotation;- a.line_spacing = 1.;- a.stroke_width.get_or_insert_with(Default::default).value_nm = nm(e.text.stroke);- let size = a.size.get_or_insert_with(Default::default);- size.x_nm = nm(e.text.width);- size.y_nm = nm(e.text.height);- a.mirrored = e.text.mirrored;- a.multiline = t.text.contains('\n');- Ok(EditablePcbItem::Field(field))-}--pub fn silk_fields_batch(ctx: &Ctx, args: &Value) -> RResult<Value> {- if args["expectedRevision"]- .as_str()- .filter(|s| !s.is_empty())- .is_none()- {- return Err(RoutingError::new(- "revision_required",- "Read the board revision before editing fields",- ));- }- let s = connect(ctx, args)?;- let (text, _, revision) = s.snapshot()?;- check_revision(args, &revision)?;- let plan = fields::prepare(&text, args)?;- let ids: Vec<_> = plan.edits.iter().map(|e| e.text.id.clone()).collect();- let native = s- .client- .get_editable_items_by_id(ids.clone())- .map_err(map_err)?;- let mut updates = Vec::new();- for e in &plan.edits {- let f = native- .iter()- .find(|f| id(f) == Some(e.text.id.as_str()))- .ok_or_else(|| {- RoutingError::new(- "native_field_unavailable",- "KiCad did not return the exact nested field UUID; no whole-footprint fallback",- )- })?;- let EditablePcbItem::Field(f) = f else {- unreachable!()- };- updates.push(apply_geometry(f.clone(), e)?);- }- let before = drc_snapshot(ctx.kicad_cli.as_deref(), &s.source_path(), &text)?;- let after = drc_snapshot(ctx.kicad_cli.as_deref(), &s.source_path(), &plan.candidate)?;- let all = |mut v: Value| {- if let Some(a) = v["violations"].as_array_mut() {- for x in a {- x["severity"] = json!("error");- }- }- v- };- let added = new_errors(&all(before), &all(after.clone()))?;- if !added.is_empty() {- return Err(- RoutingError::new("drc_rejected", "Field geometry adds native DRC findings")- .with("violations", json!(added))- .with("mutated", json!(false)),- );- }- if args["dryRun"] == true {- return Ok(- json!({"success":true,"mutated":false,"revision":revision,"drc":after,"updatedIds":ids}),- );- }- check_revision(args, &s.revision()?)?;- transaction(&s, "Adom reference/value fields", || {- let reply = s.client.update_editable_items(updates.clone())?;- let actual: HashSet<_> = reply.iter().filter_map(id).collect();- if actual != ids.iter().map(String::as_str).collect() {- return Err(IpcFailure::from(- "Native field update did not preserve all field UUIDs".to_string(),- ));- }- Ok(())- })?;- let mut out = json!({"success":true,"committed":true,"mutated":true,"undoSteps":1,"updatedIds":ids,"footprintIds":plan.edits.iter().map(|e|&e.footprint_id).collect::<Vec<_>>(),"saved":false,"drc":after,"_hint":"Only nested reference/value fields were updated; no whole footprint replacement. Inspect postCommit errors before any retry, then refresh the exact linked views and inspect the board."});- match s.client.get_editable_items_by_id(ids.clone()) {- Ok(actual) => {- let matches = updates.iter().all(|want| {- actual.iter().any(|got| {- id(got) == id(want) && got.clone().into_any() == want.clone().into_any()- })- });- out["fieldsVerified"] = json!(matches);- if !matches {- out["success"] = json!(false);- out["postCommitFieldError"]=json!("Native field readback differs from requested geometry or preserved content; inspect before retrying");- }- }- Err(e) => {- out["success"] = json!(false);- out["postCommitFieldError"] = json!(e.to_string());- }- }- match s.snapshot() {- Ok((current, _, rev)) => {- out["revision"] = json!(rev);- let set = ids.iter().cloned().collect();- let preserved = match (- fields::preserved_geometry(&text, &set),- fields::preserved_geometry(¤t, &set),- ) {- (Ok(before), Ok(after)) => before == after,- _ => false,- };- out["otherBoardDataVerified"] = json!(preserved);- if !preserved {- out["success"] = json!(false);- out["postCommitPreservationError"]=json!("Board data outside the requested fields changed; this may also indicate concurrent editing");- }- }- Err(e) => {- out["success"] = json!(false);- out["postCommitReadbackError"] = json!(e.message);- }- }- match s.client.get_item_bounding_boxes(ids,false){- Ok(rows)=>out["bounds"]=json!(rows.iter().map(|b|json!({"id":b.item_id,"boxMm":[b.x_nm as f64/1e6,b.y_nm as f64/1e6,(b.x_nm+b.width_nm) as f64/1e6,(b.y_nm+b.height_nm) as f64/1e6]})).collect::<Vec<_>>()),- Err(e)=>{out["success"]=json!(false);out["postCommitBoundsError"]=json!(e.to_string());}- }- if args["save"] == true && out["success"] == true {- match s.client.save_document() {- Ok(()) => out["saved"] = json!(true),- Err(e) => {- out["success"] = json!(false);- out["postCommitSaveError"] = json!(e.to_string());- }- }- }- Ok(out)-}--#[cfg(test)]-mod tests {- use super::*;- #[test]- fn nested_field_uuid_and_content_survive_geometry_update() {- let mut f = FieldItem::from_proto(Default::default());- let p = f.proto_mut();- p.name = "Reference".into();- p.id = Some(Default::default());- p.visible = true;- let b = p.text.get_or_insert_with(Default::default);- b.id.get_or_insert_with(Default::default).value = "field-id".into();- b.locked = 1;- let text = b.text.get_or_insert_with(Default::default);- text.text = "R1".into();- text.hyperlink = "preserve-me".into();- let e=fields::Edit{text:crate::silk_text::Text::parse(&json!({"text":"R1","layer":"B.SilkS","x":12.,"y":19.,"rotation":90.,"height":0.7,"width":0.6,"stroke":0.1,"align":"right"}),"field-id".into()).unwrap(),visible:false,footprint_id:"parent".into(),name:"Reference".into()};- let result = apply_geometry(f, &e).unwrap();- assert_eq!(id(&result), Some("field-id"));- let EditablePcbItem::Field(field) = result else {- panic!("not a field")- };- let p = field.proto();- assert_eq!(p.name, "Reference");- assert!(!p.visible);- assert_eq!(p.id.as_ref().unwrap().id, 0);- let b = p.text.as_ref().unwrap();- let t = b.text.as_ref().unwrap();- assert_eq!(t.text, "R1");- assert_eq!(t.hyperlink, "preserve-me");- assert_eq!(t.position.as_ref().unwrap().x_nm, 12_000_000);- assert_eq!(b.layer, BoardLayerInfo::id_from_name("B.SilkS").unwrap());- let a = t.attributes.as_ref().unwrap();- assert_eq!(a.horizontal_alignment, 3);- assert!(a.mirrored);- assert_eq!(a.size.as_ref().unwrap().y_nm, 700_000);- let mut bold = field.clone();- bold.proto_mut()- .text- .as_mut()- .unwrap()- .text- .as_mut()- .unwrap()- .attributes- .as_mut()- .unwrap()- .bold = true;- assert!(apply_geometry(bold, &e).is_err());- }-}