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

(cherry picked from commit 34ec57958d)
This commit is contained in:
Wayne Stambaugh 2024-03-14 09:43:30 -04:00
parent ab6c64b49a
commit 9e4efe5d72
5 changed files with 47 additions and 12 deletions

View File

@ -979,13 +979,20 @@ EELEMENT::EELEMENT( wxXmlNode* aElement )
<!ATTLIST element
name %String; #REQUIRED
library %String; #REQUIRED
library_urn %Urn; ""
package %String; #REQUIRED
package3d_urn %Urn; ""
override_package3d_urn %Urn; ""
override_package_urn %Urn; ""
override_locally_modified %Bool; "no"
value %String; #REQUIRED
x %Coord; #REQUIRED
y %Coord; #REQUIRED
locked %Bool; "no"
populate %Bool; "yes"
smashed %Bool; "no"
rot %Rotation; "R0"
grouprefs IDREFS #IMPLIED
>
*/
@ -1001,6 +1008,7 @@ EELEMENT::EELEMENT( wxXmlNode* aElement )
y = parseRequiredAttribute<ECOORD>( aElement, "y" );
// optional
library_urn = parseOptionalAttribute<wxString>( aElement, "library_urn" );
locked = parseOptionalAttribute<bool>( aElement, "locked" );
smashed = parseOptionalAttribute<bool>( aElement, "smashed" );
rot = parseOptionalAttribute<EROT>( aElement, "rot" );

View File

@ -817,6 +817,7 @@ struct EELEMENT
{
wxString name;
wxString library;
opt_wxString library_urn;
wxString package;
wxString value;
ECOORD x;

View File

@ -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<wxString>& 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;
}

View File

@ -804,7 +804,7 @@ protected:
void onSize( wxSizeEvent& aEvent );
int inferLegacyEdgeClearance( BOARD* aBoard );
int inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg = true );
void redrawNetnames( wxTimerEvent& aEvent );

View File

@ -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 <xmlattr> 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();