From 34ec57958d3fff5e20974d894f80334ce227f299 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Thu, 14 Mar 2024 09:43:30 -0400 Subject: [PATCH] Fix Eagle board import when footprint library versions exist. This was a crude hack that appends the library URN ordinal to the name of the footprint so that it can be correctly looked up by the "element" node. The Eagle XML DTD does not make it clear how the URN "ASSET_ID" and "VERSION" are used to look up the appropriate "ASSET_TYPE" so this is a best guess and seems to work correctly. The inferred edge clearance dialog had to be disabled when importing third party boards because on GTK (and possibly other platforms) the dialog would completely hang KiCad preventing the imported board and possible schematic from being saved. Fixes https://gitlab.com/kicad/code/kicad/-/issues/12897 --- common/io/eagle/eagle_parser.cpp | 8 ++++++++ common/io/eagle/eagle_parser.h | 1 + pcbnew/files.cpp | 20 ++++++++++++-------- pcbnew/pcb_edit_frame.h | 2 +- pcbnew/pcb_io/eagle/pcb_io_eagle.cpp | 28 +++++++++++++++++++++++++--- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/common/io/eagle/eagle_parser.cpp b/common/io/eagle/eagle_parser.cpp index 94274277be..4f78f723ea 100644 --- a/common/io/eagle/eagle_parser.cpp +++ b/common/io/eagle/eagle_parser.cpp @@ -979,13 +979,20 @@ EELEMENT::EELEMENT( wxXmlNode* aElement ) */ @@ -1001,6 +1008,7 @@ EELEMENT::EELEMENT( wxXmlNode* aElement ) y = parseRequiredAttribute( aElement, "y" ); // optional + library_urn = parseOptionalAttribute( aElement, "library_urn" ); locked = parseOptionalAttribute( aElement, "locked" ); smashed = parseOptionalAttribute( aElement, "smashed" ); rot = parseOptionalAttribute( aElement, "rot" ); diff --git a/common/io/eagle/eagle_parser.h b/common/io/eagle/eagle_parser.h index a5ba22cd6f..4958428f73 100644 --- a/common/io/eagle/eagle_parser.h +++ b/common/io/eagle/eagle_parser.h @@ -817,6 +817,7 @@ struct EELEMENT { wxString name; wxString library; + opt_wxString library_urn; wxString package; wxString value; ECOORD x; diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 66617d7a42..b26ae0d97f 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -444,7 +444,7 @@ bool PCB_EDIT_FRAME::Files_io_from_id( int id ) } -int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard ) +int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg ) { PCB_LAYER_COLLECTOR collector; @@ -472,14 +472,15 @@ int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard ) } } - if( mixed ) + if( mixed && aShowUserMsg ) { // If they had different widths then we can't ensure that fills will be the same. - DisplayInfoMessage( this, _( "If the zones on this board are refilled the Copper Edge Clearance " - "setting will be used (see Board Setup > Design Rules > Constraints).\n" - "This may result in different fills from previous KiCad versions which " - "used the line thicknesses of the board boundary on the Edge Cuts " - "layer." ) ); + DisplayInfoMessage( this, + _( "If the zones on this board are refilled the Copper Edge " + "Clearance setting will be used (see Board Setup > Design " + "Rules > Constraints).\n This may result in different fills " + "from previous KiCad versions which used the line thicknesses " + "of the board boundary on the Edge Cuts layer." ) ); } return std::max( 0, edgeWidth / 2 ); @@ -745,7 +746,10 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in // edge widths. if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded ) { - int edgeClearance = inferLegacyEdgeClearance( loadedBoard ); + // Do not show the inferred edge clearance warning dialog when loading third + // party boards. For some reason the dialog completely hangs all of KiCad and + // the imported board cannot be saved. + int edgeClearance = inferLegacyEdgeClearance( loadedBoard, !converted ); loadedBoard->GetDesignSettings().m_CopperEdgeClearance = edgeClearance; } diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h index cf0545e742..2a25e0c061 100644 --- a/pcbnew/pcb_edit_frame.h +++ b/pcbnew/pcb_edit_frame.h @@ -805,7 +805,7 @@ protected: void onSize( wxSizeEvent& aEvent ); - int inferLegacyEdgeClearance( BOARD* aBoard ); + int inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg = true ); void redrawNetnames( wxTimerEvent& aEvent ); diff --git a/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp b/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp index 30af1d4d0c..b4c62523fa 100644 --- a/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp +++ b/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp @@ -1138,6 +1138,15 @@ void PCB_IO_EAGLE::loadLibrary( wxXmlNode* aLib, const wxString* aLibName ) if( !aLib ) return; + wxString urn = aLib->GetAttribute( "urn" ); + + wxString urnOrdinal; + + if( !urn.IsEmpty() ) + { + urnOrdinal = urn.AfterLast( ':' ); + } + // library will have node, skip that and get the single packages node wxXmlNode* packages = MapChildren( aLib )["packages"]; @@ -1160,7 +1169,11 @@ void PCB_IO_EAGLE::loadLibrary( wxXmlNode* aLib, const wxString* aLibName ) m_xpath->push( "package", "name" ); wxString pack_ref = package->GetAttribute( "name" ); - ReplaceIllegalFileNameChars( pack_ref, '_' ); + + if( !urnOrdinal.IsEmpty() ) + pack_ref += wxS( "_" ) + urnOrdinal; + + pack_ref = EscapeString( pack_ref, CTX_LIBID ); m_xpath->Value( pack_ref.ToUTF8() ); @@ -1248,13 +1261,21 @@ void PCB_IO_EAGLE::loadElements( wxXmlNode* aElements ) m_xpath->Value( e.name.c_str() ); - wxString pkg_key = makeKey( e.library, e.package ); + wxString packageName = e.package; + + if( e.library_urn ) + { + wxString libOrdinal = *e.library_urn; + packageName = e.package + wxS( "_" ) + libOrdinal.AfterLast( ':' ); + } + + wxString pkg_key = makeKey( e.library, packageName ); auto it = m_templates.find( pkg_key ); if( it == m_templates.end() ) { wxString emsg = wxString::Format( _( "No '%s' package in library '%s'." ), - e.package, e.library ); + packageName, e.library ); THROW_IO_ERROR( emsg ); } @@ -3203,6 +3224,7 @@ void PCB_IO_EAGLE::cacheLib( const wxString& aLibPath ) m_xpath->push( "eagle.drawing.library" ); wxXmlNode* library = drawingChildren["library"]; + loadLibrary( library, nullptr ); m_xpath->pop();