Eagle schematic importer improvements.

Change Eagle file importer to use a two pass import.  The first pass
parses the entire Eagle file into an associated E* object.  The second
pass converts the parsed E* objects into the appropriate KiCad objects.

Improve handling of Eagle versioned libraries.

Add helpers to IO_BASE to ease handling of PROGRESS_REPORTER and REPORTER
objects.

ADDED: Support for importing Eagle schematic modules.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/1813
This commit is contained in:
Wayne Stambaugh 2024-04-09 16:13:58 -04:00
parent e0e837189d
commit 889931505b
8 changed files with 3949 additions and 1463 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,9 @@
#include <unordered_set>
#include <io/io_base.h>
#include <progress_reporter.h>
#include <ki_exception.h>
#include <reporter.h>
#include <wildcards_and_files_ext.h>
#include <wx/filename.h>
@ -115,3 +117,24 @@ bool IO_BASE::CanReadLibrary( const wxString& aFileName ) const
return false;
}
void IO_BASE::Report( const wxString& aText, SEVERITY aSeverity )
{
if( !m_reporter )
return;
m_reporter->Report( aText, aSeverity );
}
void IO_BASE::AdvanceProgressPhase()
{
if( !m_progressReporter )
return;
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( _( "Loading file canceled by user." ) );
m_progressReporter->AdvancePhase();
}

View File

@ -57,6 +57,7 @@ const wxChar* const traceGalProfile = wxT( "KICAD_GAL_PROFILE" );
const wxChar* const traceKiCad2Step = wxT( "KICAD2STEP" );
const wxChar* const traceUiProfile = wxT( "KICAD_UI_PROFILE" );
const wxChar* const traceGit = wxT( "KICAD_GIT" );
const wxChar* const traceEagleIo = wxT( "KICAD_EAGLE_IO" );
wxString dump( const wxArrayString& aArray )

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 CERN
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
* @author Maciej Suminski <maciej.suminski@cern.ch>
@ -31,7 +31,6 @@
#include <io/eagle/eagle_parser.h>
#include <geometry/seg.h>
#include <boost/ptr_container/ptr_map.hpp>
class EDA_TEXT;
class KIWAY;
@ -58,19 +57,24 @@ class wxXmlNode;
struct EAGLE_LIBRARY
{
wxString name;
boost::ptr_map<wxString, LIB_SYMBOL> KiCadSymbols;
std::unordered_map<wxString, wxXmlNode*> SymbolNodes;
std::unordered_map<wxString, int> GateUnit;
std::map<wxString, std::unique_ptr<LIB_SYMBOL>> KiCadSymbols;
/**
* Map Eagle gate unit number (which are strings) to KiCad library symbol unit number.
*
* The look up name is #EDEVICE name + #EDEVICE name + #EGATE name separated by underscores.
* Hashing would be faster but it would be nearly impossible to debug so use string look up
* for now.
*/
std::unordered_map<wxString, int> GateToUnitMap;
std::unordered_map<wxString, wxString> package;
};
typedef boost::ptr_map<wxString, EPART> EPART_LIST;
/**
* A #SCH_IO derivation for loading 6.x+ Eagle schematic files.
*
* As with all SCH_IO there is no UI dependencies i.e. windowing calls allowed.
* As with all #SCH_IO objects there are no UI dependencies i.e. windowing calls allowed.
*/
class SCH_IO_EAGLE : public SCH_IO
{
@ -111,20 +115,22 @@ public:
bool IsLibraryWritable( const wxString& aLibraryPath ) override { return false; }
private:
void checkpoint();
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 loadLayerDefs( wxXmlNode* aLayers );
void loadSchematic( wxXmlNode* aSchematicNode );
void loadSheet( wxXmlNode* aSheetNode, int sheetcount );
void loadInstance( wxXmlNode* aInstanceNode );
EAGLE_LIBRARY* loadLibrary( wxXmlNode* aLibraryNode, EAGLE_LIBRARY* aEagleLib );
void countNets( wxXmlNode* aSchematicNode );
void loadDrawing( const std::unique_ptr<EDRAWING>& aDrawing );
void loadLayerDefs( const std::vector<std::unique_ptr<ELAYER>>& aLayers );
void loadSchematic( const ESCHEMATIC& aSchematic );
void loadSheet( const std::unique_ptr<ESHEET>& aSheet );
void loadInstance( const std::unique_ptr<EINSTANCE>& aInstance,
const std::map<wxString, std::unique_ptr<EPART>>& aParts );
SCH_SHEET* loadModuleInstance( const std::unique_ptr<EMODULEINST>& aModuleInstance );
EAGLE_LIBRARY* loadLibrary( const ELIBRARY* aLibrary, EAGLE_LIBRARY* aEagleLib );
void countNets( const ESCHEMATIC& aSchematic );
/// Move any labels on the wire to the new end point of the wire.
void moveLabels( SCH_LINE* aWire, const VECTOR2I& aNewEndPoint );
@ -139,29 +145,41 @@ private:
std::pair<VECTOR2I, const SEG*> findNearestLinePoint( const VECTOR2I& aPoint,
const std::vector<SEG>& aLines ) const;
void loadSegments( wxXmlNode* aSegmentsNode, const wxString& aNetName,
void loadSegments( const std::vector<std::unique_ptr<ESEGMENT>>& aSegments,
const wxString& aNetName,
const wxString& aNetClass );
SCH_SHAPE* loadPolyLine( wxXmlNode* aPolygonNode );
SCH_ITEM* loadWire( wxXmlNode* aWireNode, SEG& endpoints );
SCH_SHAPE* loadCircle( wxXmlNode* aCircleNode );
SCH_SHAPE* loadRectangle( wxXmlNode* aRectNode );
SCH_TEXT* loadLabel( wxXmlNode* aLabelNode, const wxString& aNetName );
SCH_JUNCTION* loadJunction( wxXmlNode* aJunction );
SCH_TEXT* loadPlainText( wxXmlNode* aSchText );
void loadFrame( wxXmlNode* aFrameNode, std::vector<SCH_ITEM*>& aItems );
SCH_SHAPE* loadPolyLine( const std::unique_ptr<EPOLYGON>& aPolygon );
SCH_ITEM* loadWire( const std::unique_ptr<EWIRE>& aWire, SEG& endpoints );
SCH_SHAPE* loadCircle( const std::unique_ptr<ECIRCLE>& aCircle );
SCH_SHAPE* loadRectangle( const std::unique_ptr<ERECT>& aRect );
SCH_TEXT* loadLabel( const std::unique_ptr<ELABEL>& aLabel, const wxString& aNetName );
SCH_JUNCTION* loadJunction( const std::unique_ptr<EJUNCTION>& aJunction );
SCH_TEXT* loadPlainText( const std::unique_ptr<ETEXT>& aSchText );
void loadFrame( const std::unique_ptr<EFRAME>& aFrame,
std::vector<SCH_ITEM*>& aItems );
bool loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptr<LIB_SYMBOL>& aSymbol,
EDEVICE* aDevice, int aGateNumber, const wxString& aGateName );
SCH_SHAPE* loadSymbolCircle( wxXmlNode* aCircleNode, int aGateNumber );
SCH_SHAPE* loadSymbolRectangle( wxXmlNode* aRectNode, int aGateNumber );
SCH_SHAPE* loadSymbolPolyLine( wxXmlNode* aPolygonNode, int aGateNumber );
SCH_ITEM* loadSymbolWire( wxXmlNode* aWireNode, int aGateNumber );
SCH_PIN* loadPin( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlNode*, EPIN* epin,
bool loadSymbol( const std::unique_ptr<ESYMBOL>& aEsymbol,
std::unique_ptr<LIB_SYMBOL>& aSymbol,
const std::unique_ptr<EDEVICE>& aDevice, int aGateNumber,
const wxString& aGateName );
SCH_SHAPE* loadSymbolCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol,
const std::unique_ptr<ECIRCLE>& aCircle,
int aGateNumber );
SCH_SHAPE* loadSymbolRectangle( std::unique_ptr<LIB_SYMBOL>& aSymbol,
const std::unique_ptr<ERECT>& aRectangle,
int aGateNumber );
SCH_SHAPE* loadSymbolPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol,
const std::unique_ptr<EPOLYGON>& aPolygon, int aGateNumber );
SCH_ITEM* loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol,
const std::unique_ptr<EWIRE>& aWire,
int aGateNumber );
SCH_PIN* loadPin( std::unique_ptr<LIB_SYMBOL>& aSymbol, const std::unique_ptr<EPIN>& aPin,
int aGateNumber );
SCH_TEXT* loadSymbolText( wxXmlNode* aLibText, int aGateNumber );
void loadSymbolFrame( wxXmlNode* aFrameNode, std::vector<SCH_ITEM*>& aLines );
void loadTextAttributes( EDA_TEXT* aText, const ETEXT& aAttribs ) const;
SCH_TEXT* loadSymbolText( std::unique_ptr<LIB_SYMBOL>& aSymbol,
const std::unique_ptr<ETEXT>& aText,
int aGateNumber );
void loadTextAttributes( EDA_TEXT* aText,
const std::unique_ptr<ETEXT>& aAttributes ) const;
void loadFieldAttributes( SCH_FIELD* aField, const SCH_TEXT* aText ) const;
///< Move net labels that are detached from any wire to the nearest wire
@ -230,18 +248,19 @@ private:
wxFileName m_filename;
wxString m_libName; ///< Library name to save symbols
SCHEMATIC* m_schematic; ///< Passed to Load(), the schematic object being loaded
EMODULE* m_module; ///< The current module being loaded or nullptr
EPART_MAP m_partlist;
std::map<wxString, const EPART*> m_partlist;
std::map<wxString, long long> m_timestamps;
std::map<wxString, EAGLE_LIBRARY> m_eagleLibs;
std::map<wxString, std::unique_ptr<EMODULE>> m_eagleModules;
std::unordered_map<wxString, bool> m_userValue; ///< deviceset/@uservalue for device.
IO_RELEASER<SCH_IO> m_pi; ///< PI to create KiCad symbol library.
std::unique_ptr<STRING_UTF8_MAP> m_properties; ///< Library plugin properties.
unsigned m_doneCount;
unsigned m_lastProgressCount;
unsigned m_totalCount; ///< for progress reporting
int m_sheetIndex;
std::map<wxString, int> m_netCounts;
std::map<int, SCH_LAYER_ID> m_layerMap;
@ -270,6 +289,9 @@ private:
///< Positions of pins and wire endings mapped to its parent
std::map<VECTOR2I, std::set<const EDA_ITEM*>> m_connPoints;
///< The fully parsed Eagle schematic file.
std::unique_ptr<EAGLE_DOC> m_eagleDoc;
};
#endif // SCH_IO_EAGLE_H_

View File

@ -24,6 +24,7 @@
#include <vector>
#include <string>
#include <wx/string.h>
#include <widgets/report_severity.h>
class REPORTER;
class PROGRESS_REPORTER;
@ -187,6 +188,10 @@ public:
*/
virtual void GetLibraryOptions( STRING_UTF8_MAP* aListToAppendTo ) const;
virtual void Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED );
virtual void AdvanceProgressPhase();
protected:
// Delete the zero-argument base constructor to force proper construction
IO_BASE() = delete;
@ -213,4 +218,4 @@ protected:
PROGRESS_REPORTER* m_progressReporter;
};
#endif // IO_BASE_H_
#endif // IO_BASE_H_

View File

@ -234,6 +234,13 @@ extern KICOMMON_API const wxChar* const traceUiProfile;
*/
extern KICOMMON_API const wxChar* const traceGit;
/*
* Flag to enable Eagle I/O debug tracing.
*
* Use "KICAD_EAGLE_IO" to enable.
*/
extern KICOMMON_API const wxChar* const traceEagleIo;
///@}
/**