ADDED: Support EAGLE libraries directly in Symbol Library Table.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/2214
This commit is contained in:
parent
9ed19192de
commit
a16bdb7288
|
@ -30,6 +30,7 @@
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <richio.h>
|
#include <richio.h>
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
#include <wx/regex.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
@ -145,6 +146,36 @@ bool substituteVariable( wxString* aText )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString convertDescription( wxString aDescr )
|
||||||
|
{
|
||||||
|
aDescr.Replace( wxS( "\n" ), wxS( " " ) );
|
||||||
|
aDescr.Replace( wxS( "\r" ), wxEmptyString );
|
||||||
|
|
||||||
|
wxRegEx( wxS( "<a\\s+(?:[^>]*?\\s+)?href=\"([^\"]*)\"[^>]*>" ) )
|
||||||
|
.ReplaceAll( &aDescr, wxS( "\\1 " ) );
|
||||||
|
|
||||||
|
aDescr.Replace( wxS( "<p>" ), wxS( "\n\n" ) );
|
||||||
|
aDescr.Replace( wxS( "</p>" ), wxS( "\n\n" ) );
|
||||||
|
|
||||||
|
aDescr.Replace( wxS( "<br>" ), wxS( "\n" ) );
|
||||||
|
aDescr.Replace( wxS( "<ul>" ), wxS( "\n" ) );
|
||||||
|
aDescr.Replace( wxS( "</ul>" ), wxS( "\n\n" ) );
|
||||||
|
aDescr.Replace( wxS( "<li></li>" ), wxS( "\n" ) );
|
||||||
|
aDescr.Replace( wxS( "<li>" ), wxS( "\n \u2022 " ) ); // Bullet point
|
||||||
|
|
||||||
|
aDescr = RemoveHTMLTags( aDescr );
|
||||||
|
|
||||||
|
wxRegEx( wxS( "\n +" ) ).ReplaceAll( &aDescr, wxS( "\n" ) );
|
||||||
|
wxRegEx( wxS( " +\n" ) ).ReplaceAll( &aDescr, wxS( "\n" ) );
|
||||||
|
|
||||||
|
wxRegEx( wxS( "\n{3,}" ) ).ReplaceAll( &aDescr, wxS( "\n\n" ) );
|
||||||
|
wxRegEx( wxS( "^\n+" ) ).ReplaceAll( &aDescr, wxEmptyString );
|
||||||
|
wxRegEx( wxS( "\n+$" ) ).ReplaceAll( &aDescr, wxEmptyString );
|
||||||
|
|
||||||
|
return aDescr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<> template<>
|
template<> template<>
|
||||||
OPTIONAL_XML_ATTRIBUTE<wxString>::OPTIONAL_XML_ATTRIBUTE( wxString aData )
|
OPTIONAL_XML_ATTRIBUTE<wxString>::OPTIONAL_XML_ATTRIBUTE( wxString aData )
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,6 +59,9 @@ wxString interpretText( const wxString& aText );
|
||||||
///< Translates Eagle special text reference to a KiCad variable reference
|
///< Translates Eagle special text reference to a KiCad variable reference
|
||||||
bool substituteVariable( wxString* aText );
|
bool substituteVariable( wxString* aText );
|
||||||
|
|
||||||
|
///< Converts Eagle's HTML description into KiCad description format
|
||||||
|
wxString convertDescription( wxString aDescr );
|
||||||
|
|
||||||
static inline wxXmlNode* getChildrenNodes( NODE_MAP& aMap, const wxString& aName )
|
static inline wxXmlNode* getChildrenNodes( NODE_MAP& aMap, const wxString& aName )
|
||||||
{
|
{
|
||||||
auto it = aMap.find( aName );
|
auto it = aMap.find( aName );
|
||||||
|
|
|
@ -421,24 +421,7 @@ SCH_SHEET* SCH_EAGLE_PLUGIN::LoadSchematicFile( const wxString& aFileName, SCHEM
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the document
|
// Load the document
|
||||||
wxXmlDocument xmlDocument;
|
wxXmlDocument xmlDocument = loadXmlDocument( m_filename.GetFullPath() );
|
||||||
wxFFileInputStream stream( m_filename.GetFullPath() );
|
|
||||||
|
|
||||||
// read first line to check for Eagle XML format file
|
|
||||||
wxTextInputStream text( stream );
|
|
||||||
wxString line = text.ReadLine();
|
|
||||||
if( !line.StartsWith( wxT( "<?xml" ) ) )
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR( wxString::Format( _( "'%s' is an Eagle binary-format schematic file; "
|
|
||||||
"only Eagle XML-format schematics can be imported." ),
|
|
||||||
m_filename.GetFullPath() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !stream.IsOk() || !xmlDocument.Load( stream ) )
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR( wxString::Format( _( "Unable to read file '%s'." ),
|
|
||||||
m_filename.GetFullPath() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete on exception, if I own m_rootSheet, according to aAppendToMe
|
// Delete on exception, if I own m_rootSheet, according to aAppendToMe
|
||||||
unique_ptr<SCH_SHEET> deleter( aAppendToMe ? nullptr : m_rootSheet );
|
unique_ptr<SCH_SHEET> deleter( aAppendToMe ? nullptr : m_rootSheet );
|
||||||
|
@ -527,6 +510,144 @@ SCH_SHEET* SCH_EAGLE_PLUGIN::LoadSchematicFile( const wxString& aFileName, SCHEM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_EAGLE_PLUGIN::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
|
||||||
|
const wxString& aLibraryPath,
|
||||||
|
const STRING_UTF8_MAP* aProperties )
|
||||||
|
{
|
||||||
|
m_filename = aLibraryPath;
|
||||||
|
m_libName = m_filename.GetName();
|
||||||
|
|
||||||
|
ensureLoadedLibrary( aLibraryPath );
|
||||||
|
|
||||||
|
auto it = m_eagleLibs.find( m_libName );
|
||||||
|
|
||||||
|
if( it != m_eagleLibs.end() )
|
||||||
|
{
|
||||||
|
for( const auto& [symName, libSymbol] : it->second.KiCadSymbols )
|
||||||
|
aSymbolNameList.push_back( symName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_EAGLE_PLUGIN::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
|
||||||
|
const wxString& aLibraryPath,
|
||||||
|
const STRING_UTF8_MAP* aProperties )
|
||||||
|
{
|
||||||
|
m_filename = aLibraryPath;
|
||||||
|
m_libName = m_filename.GetName();
|
||||||
|
|
||||||
|
ensureLoadedLibrary( aLibraryPath );
|
||||||
|
|
||||||
|
auto it = m_eagleLibs.find( m_libName );
|
||||||
|
|
||||||
|
if( it != m_eagleLibs.end() )
|
||||||
|
{
|
||||||
|
for( const auto& [symName, libSymbol] : it->second.KiCadSymbols )
|
||||||
|
aSymbolList.push_back( libSymbol );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LIB_SYMBOL* SCH_EAGLE_PLUGIN::LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName,
|
||||||
|
const STRING_UTF8_MAP* aProperties )
|
||||||
|
{
|
||||||
|
m_filename = aLibraryPath;
|
||||||
|
m_libName = m_filename.GetName();
|
||||||
|
|
||||||
|
ensureLoadedLibrary( aLibraryPath );
|
||||||
|
|
||||||
|
auto it = m_eagleLibs.find( m_libName );
|
||||||
|
|
||||||
|
if( it != m_eagleLibs.end() )
|
||||||
|
{
|
||||||
|
auto it2 = it->second.KiCadSymbols.find( aAliasName );
|
||||||
|
|
||||||
|
if( it2 != it->second.KiCadSymbols.end() )
|
||||||
|
return it2->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long long SCH_EAGLE_PLUGIN::getLibraryTimestamp( const wxString& aLibraryPath ) const
|
||||||
|
{
|
||||||
|
wxFileName fn( aLibraryPath );
|
||||||
|
|
||||||
|
if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
|
||||||
|
return fn.GetModificationTime().GetValue().GetValue();
|
||||||
|
else
|
||||||
|
return wxDateTime( 0.0 ).GetValue().GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_EAGLE_PLUGIN::ensureLoadedLibrary( const wxString& aLibraryPath )
|
||||||
|
{
|
||||||
|
if( m_eagleLibs.find( m_libName ) != m_eagleLibs.end() )
|
||||||
|
{
|
||||||
|
wxCHECK( m_timestamps.count( m_libName ), /*void*/ );
|
||||||
|
|
||||||
|
if( m_timestamps.at( m_libName ) == getLibraryTimestamp( aLibraryPath ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCALE_IO toggle; // toggles on, then off, the C locale.
|
||||||
|
|
||||||
|
if( m_progressReporter )
|
||||||
|
{
|
||||||
|
m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aLibraryPath ) );
|
||||||
|
|
||||||
|
if( !m_progressReporter->KeepRefreshing() )
|
||||||
|
THROW_IO_ERROR( ( "Open canceled by user." ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the document
|
||||||
|
wxXmlDocument xmlDocument = loadXmlDocument( m_filename.GetFullPath() );
|
||||||
|
|
||||||
|
// Retrieve the root as current node
|
||||||
|
wxXmlNode* currentNode = xmlDocument.GetRoot();
|
||||||
|
|
||||||
|
// If the attribute is found, store the Eagle version;
|
||||||
|
// otherwise, store the dummy "0.0" version.
|
||||||
|
m_version = currentNode->GetAttribute( wxT( "version" ), wxT( "0.0" ) );
|
||||||
|
|
||||||
|
// Map all children into a readable dictionary
|
||||||
|
NODE_MAP children = MapChildren( currentNode );
|
||||||
|
|
||||||
|
// Load drawing
|
||||||
|
loadDrawing( children["drawing"] );
|
||||||
|
|
||||||
|
// Remember timestamp
|
||||||
|
m_timestamps[m_libName] = getLibraryTimestamp( aLibraryPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxXmlDocument SCH_EAGLE_PLUGIN::loadXmlDocument( const wxString& aFileName )
|
||||||
|
{
|
||||||
|
wxXmlDocument xmlDocument;
|
||||||
|
wxFFileInputStream stream( m_filename.GetFullPath() );
|
||||||
|
|
||||||
|
// read first line to check for Eagle XML format file
|
||||||
|
wxTextInputStream text( stream );
|
||||||
|
wxString line = text.ReadLine();
|
||||||
|
|
||||||
|
if( !line.StartsWith( wxT( "<?xml" ) ) && !line.StartsWith( wxT( "<!--" ) ) )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( wxString::Format( _( "'%s' is an Eagle binary-format file; "
|
||||||
|
"only Eagle XML-format files can be imported." ),
|
||||||
|
m_filename.GetFullPath() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !stream.IsOk() || !xmlDocument.Load( stream ) )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR(
|
||||||
|
wxString::Format( _( "Unable to read file '%s'." ), m_filename.GetFullPath() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return xmlDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SCH_EAGLE_PLUGIN::loadDrawing( wxXmlNode* aDrawingNode )
|
void SCH_EAGLE_PLUGIN::loadDrawing( wxXmlNode* aDrawingNode )
|
||||||
{
|
{
|
||||||
// Map all children into a readable dictionary
|
// Map all children into a readable dictionary
|
||||||
|
@ -542,7 +663,15 @@ void SCH_EAGLE_PLUGIN::loadDrawing( wxXmlNode* aDrawingNode )
|
||||||
if( layers )
|
if( layers )
|
||||||
loadLayerDefs( layers );
|
loadLayerDefs( layers );
|
||||||
|
|
||||||
// wxXmlNode* library = drawingChildren["library"]
|
wxXmlNode* libraryNode = drawingChildren["library"];
|
||||||
|
|
||||||
|
if( libraryNode )
|
||||||
|
{
|
||||||
|
EAGLE_LIBRARY& elib = m_eagleLibs[m_libName];
|
||||||
|
elib.name = m_libName;
|
||||||
|
|
||||||
|
loadLibrary( libraryNode, &elib );
|
||||||
|
}
|
||||||
|
|
||||||
// wxXmlNode* settings = drawingChildren["settings"]
|
// wxXmlNode* settings = drawingChildren["settings"]
|
||||||
|
|
||||||
|
@ -1873,9 +2002,14 @@ EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode,
|
||||||
EDEVICE_SET edeviceset = EDEVICE_SET( devicesetNode );
|
EDEVICE_SET edeviceset = EDEVICE_SET( devicesetNode );
|
||||||
|
|
||||||
wxString prefix = edeviceset.prefix ? edeviceset.prefix.Get() : wxString( wxT( "" ) );
|
wxString prefix = edeviceset.prefix ? edeviceset.prefix.Get() : wxString( wxT( "" ) );
|
||||||
|
wxString deviceSetDescr;
|
||||||
|
|
||||||
NODE_MAP deviceSetChildren = MapChildren( devicesetNode );
|
NODE_MAP deviceSetChildren = MapChildren( devicesetNode );
|
||||||
wxXmlNode* deviceNode = getChildrenNodes( deviceSetChildren, wxT( "devices" ) );
|
wxXmlNode* deviceNode = getChildrenNodes( deviceSetChildren, wxT( "devices" ) );
|
||||||
|
wxXmlNode* deviceSetDescrNode = getChildrenNodes( deviceSetChildren, wxT( "description" ) );
|
||||||
|
|
||||||
|
if( deviceSetDescrNode )
|
||||||
|
deviceSetDescr = convertDescription( UnescapeHTML( deviceSetDescrNode->GetContent() ) );
|
||||||
|
|
||||||
// For each device in the device set:
|
// For each device in the device set:
|
||||||
while( deviceNode )
|
while( deviceNode )
|
||||||
|
@ -1939,26 +2073,42 @@ EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode,
|
||||||
// Don't set the footprint field if no package is defined in the Eagle schematic.
|
// Don't set the footprint field if no package is defined in the Eagle schematic.
|
||||||
if( edevice.package )
|
if( edevice.package )
|
||||||
{
|
{
|
||||||
// assume that footprint library is identical to project name
|
wxString libName;
|
||||||
wxString packageString = m_schematic->Prj().GetProjectName() + wxT( ":" ) +
|
|
||||||
aEagleLibrary->package[symbolName];
|
if( m_schematic )
|
||||||
|
{
|
||||||
|
// assume that footprint library is identical to project name
|
||||||
|
libName = m_schematic->Prj().GetProjectName();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
libName = m_libName;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString packageString = libName + wxT( ":" ) + aEagleLibrary->package[symbolName];
|
||||||
|
|
||||||
libSymbol->GetFootprintField().SetText( packageString );
|
libSymbol->GetFootprintField().SetText( packageString );
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString libName = libSymbol->GetName();
|
wxString libName = libSymbol->GetName();
|
||||||
libSymbol->SetName( libName );
|
libSymbol->SetName( libName );
|
||||||
|
libSymbol->SetDescription( deviceSetDescr );
|
||||||
|
|
||||||
// If duplicate symbol names exist in multiple Eagle symbol libraries, prefix the
|
if( m_pi )
|
||||||
// Eagle symbol library name to the symbol which should ensure that it is unique.
|
|
||||||
if( m_pi->LoadSymbol( getLibFileName().GetFullPath(), libName ) )
|
|
||||||
{
|
{
|
||||||
libName = aEagleLibrary->name + wxT( "_" ) + libName;
|
// If duplicate symbol names exist in multiple Eagle symbol libraries, prefix the
|
||||||
libName = EscapeString( libName, CTX_LIBID );
|
// Eagle symbol library name to the symbol which should ensure that it is unique.
|
||||||
libSymbol->SetName( libName );
|
if( m_pi->LoadSymbol( getLibFileName().GetFullPath(), libName ) )
|
||||||
|
{
|
||||||
|
libName = aEagleLibrary->name + wxT( "_" ) + libName;
|
||||||
|
libName = EscapeString( libName, CTX_LIBID );
|
||||||
|
libSymbol->SetName( libName );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pi->SaveSymbol( getLibFileName().GetFullPath(),
|
||||||
|
new LIB_SYMBOL( *libSymbol.get() ), m_properties.get() );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pi->SaveSymbol( getLibFileName().GetFullPath(), new LIB_SYMBOL( *libSymbol.get() ),
|
|
||||||
m_properties.get() );
|
|
||||||
aEagleLibrary->KiCadSymbols.insert( libName, libSymbol.release() );
|
aEagleLibrary->KiCadSymbols.insert( libName, libSymbol.release() );
|
||||||
|
|
||||||
// Store information on whether the value of VALUE_FIELD for a part should be
|
// Store information on whether the value of VALUE_FIELD for a part should be
|
||||||
|
|
|
@ -100,10 +100,10 @@ public:
|
||||||
return PLUGIN_FILE_DESC( _HKI( "Eagle XML schematic files" ), { "sch" } );
|
return PLUGIN_FILE_DESC( _HKI( "Eagle XML schematic files" ), { "sch" } );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*const PLUGIN_FILE_DESC GetLibraryFileDesc() const override
|
const PLUGIN_FILE_DESC GetLibraryFileDesc() const override
|
||||||
{
|
{
|
||||||
return PLUGIN_FILE_DESC( _HKI( "Eagle XML library files" ), { "lbr" } );
|
return PLUGIN_FILE_DESC( _HKI( "Eagle XML library files" ), { "lbr" } );
|
||||||
}*/
|
}
|
||||||
|
|
||||||
bool CanReadSchematicFile( const wxString& aFileName ) const override;
|
bool CanReadSchematicFile( const wxString& aFileName ) const override;
|
||||||
bool CanReadLibrary( const wxString& aFileName ) const override;
|
bool CanReadLibrary( const wxString& aFileName ) const override;
|
||||||
|
@ -114,10 +114,24 @@ public:
|
||||||
SCH_SHEET* aAppendToMe = nullptr,
|
SCH_SHEET* aAppendToMe = nullptr,
|
||||||
const STRING_UTF8_MAP* aProperties = nullptr ) override;
|
const STRING_UTF8_MAP* aProperties = nullptr ) override;
|
||||||
|
|
||||||
|
void EnumerateSymbolLib( wxArrayString& aSymbolNameList, const wxString& aLibraryPath,
|
||||||
|
const STRING_UTF8_MAP* aProperties ) override;
|
||||||
|
|
||||||
|
void EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList, const wxString& aLibraryPath,
|
||||||
|
const STRING_UTF8_MAP* aProperties ) override;
|
||||||
|
|
||||||
|
LIB_SYMBOL* LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName,
|
||||||
|
const STRING_UTF8_MAP* aProperties ) override;
|
||||||
|
|
||||||
|
bool IsSymbolLibWritable( const wxString& aLibraryPath ) override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkpoint();
|
void checkpoint();
|
||||||
|
|
||||||
bool checkHeader( const wxString& aFileName ) const;
|
bool checkHeader( const wxString& aFileName ) const;
|
||||||
|
wxXmlDocument loadXmlDocument( const wxString& aFileName );
|
||||||
|
long long getLibraryTimestamp( const wxString& aLibraryPath ) const;
|
||||||
|
void ensureLoadedLibrary( const wxString& aLibraryPath );
|
||||||
|
|
||||||
void loadDrawing( wxXmlNode* aDrawingNode );
|
void loadDrawing( wxXmlNode* aDrawingNode );
|
||||||
void loadLayerDefs( wxXmlNode* aLayers );
|
void loadLayerDefs( wxXmlNode* aLayers );
|
||||||
|
@ -239,9 +253,10 @@ private:
|
||||||
wxString m_libName; ///< Library name to save symbols
|
wxString m_libName; ///< Library name to save symbols
|
||||||
SCHEMATIC* m_schematic; ///< Passed to Load(), the schematic object being loaded
|
SCHEMATIC* m_schematic; ///< Passed to Load(), the schematic object being loaded
|
||||||
|
|
||||||
EPART_MAP m_partlist;
|
EPART_MAP m_partlist;
|
||||||
std::map<wxString, EAGLE_LIBRARY> m_eagleLibs;
|
std::map<wxString, long long> m_timestamps;
|
||||||
std::unordered_map<wxString, bool> m_userValue; ///< deviceset/@uservalue for device.
|
std::map<wxString, EAGLE_LIBRARY> m_eagleLibs;
|
||||||
|
std::unordered_map<wxString, bool> m_userValue; ///< deviceset/@uservalue for device.
|
||||||
|
|
||||||
SCH_PLUGIN::SCH_PLUGIN_RELEASER m_pi; ///< PI to create KiCad symbol library.
|
SCH_PLUGIN::SCH_PLUGIN_RELEASER m_pi; ///< PI to create KiCad symbol library.
|
||||||
std::unique_ptr<STRING_UTF8_MAP> m_properties; ///< Library plugin properties.
|
std::unique_ptr<STRING_UTF8_MAP> m_properties; ///< Library plugin properties.
|
||||||
|
|
|
@ -1786,7 +1786,10 @@ FOOTPRINT* EAGLE_PLUGIN::makeFootprint( wxXmlNode* aPackage, const wxString& aPk
|
||||||
const wxString& itemName = packageItem->GetName();
|
const wxString& itemName = packageItem->GetName();
|
||||||
|
|
||||||
if( itemName == wxT( "description" ) )
|
if( itemName == wxT( "description" ) )
|
||||||
m->SetLibDescription( packageItem->GetNodeContent() );
|
{
|
||||||
|
wxString descr = convertDescription( UnescapeHTML( packageItem->GetNodeContent() ) );
|
||||||
|
m->SetLibDescription( descr );
|
||||||
|
}
|
||||||
else if( itemName == wxT( "wire" ) )
|
else if( itemName == wxT( "wire" ) )
|
||||||
packageWire( m.get(), packageItem );
|
packageWire( m.get(), packageItem );
|
||||||
else if( itemName == wxT( "pad" ) )
|
else if( itemName == wxT( "pad" ) )
|
||||||
|
|
Loading…
Reference in New Issue