diff --git a/eeschema/qa/data/eagle_schematics/empty.sch b/eeschema/qa/data/eagle_schematics/empty.sch
index f452a832b6..a33e0c1b84 100644
--- a/eeschema/qa/data/eagle_schematics/empty.sch
+++ b/eeschema/qa/data/eagle_schematics/empty.sch
@@ -1,48 +1,48 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eeschema/sch_eagle_plugin.cpp b/eeschema/sch_eagle_plugin.cpp
index 4b13fb5f6f..2ef5d5a810 100644
--- a/eeschema/sch_eagle_plugin.cpp
+++ b/eeschema/sch_eagle_plugin.cpp
@@ -23,18 +23,82 @@
#include
#include
+#include
+#include
#include
#include
+#include
+
using namespace std;
+typedef unordered_map< string, wxXmlNode* > NodeMap;
+
+NodeMap mapChildren( wxXmlNode* currentNode )
+{
+ // Map node_name -> node_pointer
+ NodeMap nodesMap;
+
+ // Loop through all children mapping them in nodesMap
+ currentNode = currentNode->GetChildren();
+ while( currentNode )
+ {
+ // Create a new pair in the map
+ // key: current node name
+ // value: current node pointer
+ nodesMap[currentNode->GetName().ToStdString()] = currentNode;
+
+ // Get next child
+ currentNode = currentNode->GetNext();
+ }
+
+ return nodesMap;
+}
+
+
+void kicadLayer( int aEagleLayer )
+{
+ /**
+ * Layers in Kicad schematics are not actually layers, but abstract groups mainly used to
+ * decide item colours.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+ switch( aEagleLayer )
+ {
+ case 90: break;
+ case 91: break;
+ case 92: break;
+ case 93: break;
+ case 94: break;
+ case 95: break;
+ case 96: break;
+ case 97: break;
+ case 98: break;
+ }
+}
+
SCH_EAGLE_PLUGIN::SCH_EAGLE_PLUGIN()
{
m_rootSheet = nullptr;
}
+
SCH_EAGLE_PLUGIN::~SCH_EAGLE_PLUGIN()
{
}
@@ -61,13 +125,14 @@ int SCH_EAGLE_PLUGIN::GetModifyHash() const
void SCH_EAGLE_PLUGIN::SaveLibrary( const wxString& aFileName, const PROPERTIES* aProperties )
{
+
}
SCH_SHEET* SCH_EAGLE_PLUGIN::Load( const wxString& aFileName, KIWAY* aKiway,
SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
{
- // TODO: Handle Kiway adn uncomment next line.
+ // TODO: Handle Kiway and uncomment next line.
// wxASSERT( !aFileName || aKiway != NULL );
// Load the document
@@ -83,13 +148,11 @@ SCH_SHEET* SCH_EAGLE_PLUGIN::Load( const wxString& aFileName, KIWAY* aKiway,
if( aAppendToMe )
{
m_rootSheet = aAppendToMe->GetRootSheet();
- // deleter = make_unique( nullptr );
}
else
{
m_rootSheet = new SCH_SHEET();
m_rootSheet->SetFileName( aFileName );
- // deleter = make_unique( m_rootSheet );
}
// Retrieve the root as current node
@@ -97,144 +160,385 @@ SCH_SHEET* SCH_EAGLE_PLUGIN::Load( const wxString& aFileName, KIWAY* aKiway,
// If the attribute is found, store the Eagle version;
// otherwise, store the dummy "0.0" version.
- m_version = currentNode->GetAttribute("version", "0.0");
+ m_version = currentNode->GetAttribute( "version", "0.0" );
- // Loop through all children
- currentNode = currentNode->GetChildren();
- while( currentNode )
- {
- wxString nodeName = currentNode->GetName();
+ // Map all children into a readable dictionary
+ NodeMap children = mapChildren( currentNode );
- if( nodeName == "compatibility" )
- {
- // TODO: handle compatibility nodes
- }
- else if( nodeName == "drawing")
- {
- loadDrawing( currentNode );
- }
- else // DEFAULT
- {
- THROW_IO_ERROR( wxString::Format( _( "XML node '%s' unknown" ), nodeName ) );
- }
+ // TODO: handle compatibility nodes
+ // wxXmlNode* compatibility = children["compatibility"];
- currentNode = currentNode->GetNext();
- }
+ // Load drawing
+ loadDrawing( children["drawing"] );
deleter.release();
return m_rootSheet;
}
-void SCH_EAGLE_PLUGIN::loadDrawing( wxXmlNode* currentNode )
+
+void SCH_EAGLE_PLUGIN::loadDrawing( wxXmlNode* aDrawingNode )
{
- currentNode = currentNode->GetChildren();
+ // Map all children into a readable dictionary
+ NodeMap drawingChildren = mapChildren( aDrawingNode );
+
+ // Board nodes should not appear in .sch files
+ // wxXmlNode* board = drawingChildren["board"]
+
+ // TODO: handle grid nodes
+ // wxXmlNode* grid = drawingChildren["grid"]
+
+ // TODO: handle layers nodes
+ // wxXmlNode* layers = drawingChildren["layers"]
+
+ // TODO: handle library nodes
+ // wxXmlNode* library = drawingChildren["library"]
+
+ // TODO: handle settings nodes
+ // wxXmlNode* settings = drawingChildren["settings"]
+
+ // Load schematic
+ loadSchematic( drawingChildren["schematic"] );
+}
+
+
+void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* aSchematicNode )
+{
+ // Map all children into a readable dictionary
+ NodeMap schematicChildren = mapChildren( aSchematicNode );
+
+ // TODO : handle classes nodes
+ // wxXmlNode* classes = schematicChildren["classes"];
+
+ // TODO : handle description nodes
+ // wxXmlNode* description = schematicChildren["description"];
+
+ // TODO : handle errors nodes
+ // wxXmlNode* errors = schematicChildren["errors"];
+
+ // TODO : handle modules nodes
+ // wxXmlNode* modules = schematicChildren["modules"];
+
+ // TODO : handle parts nodes
+ // wxXmlNode* parts = schematicChildren["parts"];
+
+ // TODO : handle variantdefs nodes
+ // wxXmlNode* variantdefs = schematicChildren["variantdefs"];
+
+ // TODO: handle attributes node
+ // wxXmlNode* attributes = schematicChildren["attributes"];
+ // Possible children: constant, display, font, layer, name, ratio, rot, size, value, x, y
+
+ // Loop through all the libraries
+ wxXmlNode* libraryNode = schematicChildren["libraries"]->GetChildren();
+ while( libraryNode )
+ {
+ loadLibrary( libraryNode );
+ libraryNode = libraryNode->GetNext();
+ }
+
+ // Loop through all the sheets
+ wxXmlNode* sheetNode = schematicChildren["sheets"]->GetChildren();
+ while( sheetNode )
+ {
+ loadSheet( sheetNode );
+ sheetNode = sheetNode->GetNext();
+ }
+}
+
+
+void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode )
+{
+ // Map all children into a readable dictionary
+ NodeMap sheetChildren = mapChildren( aSheetNode );
+
+ // Loop through all busses
+ // From the DTD: "Buses receive names which determine which signals they include.
+ // A bus is a drawing object. It does not create any electrical connections.
+ // These are always created by means of the nets and their names."
+ wxXmlNode* busNode = sheetChildren["busses"]->GetChildren();
+ while( busNode )
+ {
+ // Get the bus name
+ wxString busName = busNode->GetAttribute( "name" );
+
+ // Load segments of this bus
+ loadSegments( busNode );
+
+ // Get next bus
+ busNode = busNode->GetNext();
+ }
+
+ // Loop through all nets
+ // From the DTD: "Net is an electrical connection in a schematic."
+ wxXmlNode* netNode = sheetChildren["nets"]->GetChildren();
+ while( netNode )
+ {
+ // Get the net name and class
+ wxString netName = netNode->GetAttribute( "name" );
+ wxString netClass = netNode->GetAttribute( "class" );
+
+ // Load segments of this net
+ loadSegments( netNode );
+
+ // Get next net
+ netNode = netNode->GetNext();
+ }
+
+ // Loop through all instances
+ wxXmlNode* instanceNode = sheetChildren["instances"]->GetChildren();
+ while( instanceNode )
+ {
+ loadInstance( instanceNode );
+ instanceNode = instanceNode->GetNext();
+ }
+
+ // Loop through all moduleinsts
+ wxXmlNode* moduleinstNode = sheetChildren["moduleinsts"]->GetChildren();
+ while( moduleinstNode )
+ {
+ loadModuleinst( moduleinstNode );
+ moduleinstNode = moduleinstNode->GetNext();
+ }
+
+ // TODO: do something with the description
+ // wxXmlNode* description = sheetChildren["description"];
+ // wxString language = description->GetAttribute( "language", "en" ); // Defaults to "en"
+ // wxString description = description->GetNodeContent();
+
+ // TODO: do something with the plain
+ // wxXmlNode* plain = sheetChildren["plain"];
+}
+
+
+void SCH_EAGLE_PLUGIN::loadSegments( wxXmlNode* aSegmentsNode )
+{
+ // Loop through all segments
+ wxXmlNode* currentSegment = aSegmentsNode->GetChildren();
+
+ while( currentSegment )
+ {
+ // Loop through all segment children
+ wxXmlNode* segmentAttribute = currentSegment->GetChildren();
+
+ while( segmentAttribute )
+ {
+ wxString nodeName = segmentAttribute->GetName();
+
+ if( nodeName == "junction" )
+ {
+ // TODO: handle junctions attributes
+ segmentAttribute->GetAttribute( "x" );
+ segmentAttribute->GetAttribute( "y" );
+ }
+ else if( nodeName == "label" )
+ {
+ // TODO: handle labels attributes
+ segmentAttribute->GetAttribute( "x" ); // REQUIRED
+ segmentAttribute->GetAttribute( "y" ); // REQUIRED
+ segmentAttribute->GetAttribute( "size" ); // REQUIRED
+ segmentAttribute->GetAttribute( "layer" ); // REQUIRED
+ segmentAttribute->GetAttribute( "font" ); // Defaults to "proportional"
+ segmentAttribute->GetAttribute( "ratio" ); // Defaults to "8"
+ segmentAttribute->GetAttribute( "rot" ); // Defaults to "R0"
+ segmentAttribute->GetAttribute( "xref" ); // Defaults to "no"
+ }
+ else if( nodeName == "pinref" )
+ {
+ // TODO: handle pinref attributes
+ segmentAttribute->GetAttribute( "gate" ); // REQUIRED
+ segmentAttribute->GetAttribute( "part" ); // REQUIRED
+ segmentAttribute->GetAttribute( "pin" ); // REQUIRED
+ }
+ else if( nodeName == "portref" )
+ {
+ // TODO: handle portref attributes
+ segmentAttribute->GetAttribute( "moduleinst" ); // REQUIRED
+ segmentAttribute->GetAttribute( "port" ); // REQUIRED
+ }
+ else if( nodeName == "wire" )
+ {
+ loadWire( segmentAttribute );
+ }
+ else // DEFAULT
+ {
+ THROW_IO_ERROR( wxString::Format( _( "XML node '%s' unknown" ), nodeName ) );
+ }
+
+ // Get next segment attribute
+ segmentAttribute = segmentAttribute->GetNext();
+ }
+
+ currentSegment = currentSegment->GetNext();
+ }
+}
+
+
+SCH_LINE* SCH_EAGLE_PLUGIN::loadWire( wxXmlNode* aWireNode )
+{
+ std::unique_ptr< SCH_LINE > wire( new SCH_LINE );
+
+ wxString layer = aWireNode->GetAttribute( "layer" ); // REQUIRED
+ wxString width = aWireNode->GetAttribute( "width" ); // REQUIRED
+ wxString x1 = aWireNode->GetAttribute( "x1" ); // REQUIRED
+ wxString x2 = aWireNode->GetAttribute( "x2" ); // REQUIRED
+ wxString y1 = aWireNode->GetAttribute( "y1" ); // REQUIRED
+ wxString y2 = aWireNode->GetAttribute( "y2" ); // REQUIRED
+ wxString cap = aWireNode->GetAttribute( "cap", "round" ); // Defaults to "round"
+ wxString curve = aWireNode->GetAttribute( "curve", "0" ); // Defaults to "0"
+ wxString style = aWireNode->GetAttribute( "style", "continuous" ); // Defaults to "continuous"
+ // wxString extent = aWireNode->GetAttribute( "extent" ); // Non-required, defaults to NOTHING
+
+ // TODO: layer map?
+ // wire->SetLayer( layerMap( layer ) );
+
+ // if( strCompare( "Wire", line, &line ) )
+ // wire->SetLayer( LAYER_WIRE );
+ // else if( strCompare( "Bus", line, &line ) )
+ // wire->SetLayer( LAYER_BUS );
+ // else if( strCompare( "Notes", line, &line ) )
+ // wire->SetLayer( LAYER_NOTES );
+ // else
+ // SCH_PARSE_ERROR( "invalid line type", aReader, line );
+
+ wxPoint begin, end;
+
+ begin.x = wxAtoi( x1 );
+ begin.y = wxAtoi( y1 );
+ end.x = wxAtoi( x2 );
+ end.y = wxAtoi( y2 );
+
+ wire->SetStartPoint( begin );
+ wire->SetEndPoint( end );
+
+ return wire.release();
+
+}
+
+
+void SCH_EAGLE_PLUGIN::loadInstance( wxXmlNode* aInstanceNode )
+{
+}
+
+
+void SCH_EAGLE_PLUGIN::loadModuleinst( wxXmlNode* aModuleinstNode )
+{
+}
+
+
+void SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode )
+{
+ // Read the library name
+ wxString libName = aLibraryNode->GetAttribute( "name" );
+
+ // Query all children and map them into a readable dictionary
+ NodeMap libraryChildren = mapChildren( aLibraryNode );
+
+ // TODO: Do something with the description
+ // wxXmlNode* libraryChildren["description"];
+
+ // Loop through the devicesets and load each of them
+ // wxXmlNode* devicesetNode = libraryChildren["devicesets"].GetChildren();
+ // while( devicesetNode )
+ // {
+ // loadDeviceset( devicesetNode );
+ // devicesetNode = devicesetNode->GetNext();
+ // }
+
+ // Loop through the packages and load each of them
+ // wxXmlNode* packageNode = libraryChildren["packages"].GetChildren();
+ // while( packageNode )
+ // {
+ // loadPackage( packageNode );
+ // packageNode = packageNode->GetNext();
+ // }
+
+ // Loop through the symbols and load each of them
+ wxXmlNode* symbolNode = libraryChildren["symbols"]->GetChildren();
+ while( symbolNode )
+ {
+ loadSymbol( symbolNode );
+ symbolNode = symbolNode->GetNext();
+ }
+}
+
+
+LIB_PART* SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode )
+{
+ // Create a new part with the symbol name
+ wxString symbolName = aSymbolNode->GetAttribute( "name" );
+ std::unique_ptr< LIB_PART > part( new LIB_PART( symbolName ) );
+
+ wxXmlNode* currentNode = aSymbolNode->GetChildren();
while( currentNode )
{
wxString nodeName = currentNode->GetName();
- if( nodeName == "board" )
+ if( nodeName == "description" )
{
- // TODO: handle board nodes
+ // TODO: Do something with the description
}
- else if( nodeName == "grid" )
+ else if( nodeName == "dimension" )
{
- // TODO: handle grid nodes
+ // TODO: Handle dimension
}
- else if( nodeName == "layers" )
+ else if( nodeName == "frame" )
{
- // TODO: handle layers nodes
}
- else if( nodeName == "library" )
+ else if( nodeName == "circle" )
{
- // TODO: handle library nodes
+ part->AddDrawItem( loadCircle( part, currentNode ) );
}
- else if( nodeName == "schematic" )
+ else if( nodeName == "pin" )
{
- loadSchematic( currentNode );
+ part->AddDrawItem( loadPin( part, currentNode ) );
}
- else if( nodeName == "settings" )
+ else if( nodeName == "polygon" )
{
- // TODO: handle settings nodes
+ part->AddDrawItem( loadPolyline( part, currentNode ) );
}
- else // DEFAULT
+ else if( nodeName == "rectangle" )
{
- THROW_IO_ERROR( wxString::Format( _( "XML node '%s' unknown" ), nodeName ) );
+ part->AddDrawItem( loadRectangle( part, currentNode ) );
+ }
+ else if( nodeName == "text" )
+ {
+ part->AddDrawItem( loadText( part, currentNode ) );
+ }
+ else if( nodeName == "wire" )
+ {
+ part->AddDrawItem( loadPolyline( part, currentNode ) );
}
currentNode = currentNode->GetNext();
}
+
+ return part.release();
}
-void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* currentNode )
+LIB_CIRCLE* SCH_EAGLE_PLUGIN::loadCircle( LIB_PART* aPart, wxXmlNode* aCircleNode )
{
- currentNode = currentNode->GetChildren();
+ unique_ptr< LIB_CIRCLE > circle( new LIB_CIRCLE( aPart.get() ) );
- while( currentNode )
- {
- wxString nodeName = currentNode->GetName();
+ int layer = wxAtoi( aCircleNode->GetAttribute( "layer" ) );
- if( nodeName == "attributes" )
- {
- wxXmlNode* attributeNode = currentNode->GetChildren();
- while( attributeNode )
- {
- // TODO: handle attributes
- // Possible attributes: constant, display, font, layer, name,
- // ratio, rot, size, value, x, y.
- attributeNode = attributeNode->GetNext();
- }
- }
- else if( nodeName == "classes" )
- {
- // TODO : handle classes nodes
- }
- else if( nodeName == "description" )
- {
- // TODO : handle description nodes
- }
- else if( nodeName == "errors" )
- {
- // TODO : handle errors nodes
- }
- else if( nodeName == "libraries" )
- {
- // TODO : handle libraries nodes
- }
- else if( nodeName == "modules" )
- {
- // TODO : handle modules nodes
- }
- else if( nodeName == "parts" )
- {
- // TODO : handle parts nodes
- }
- else if( nodeName == "sheets" )
- {
- wxXmlNode* sheetNode = currentNode->GetChildren();
- while( sheetNode )
- {
- loadSheet( sheetNode );
- sheetNode = sheetNode->GetNext();
- }
- }
- else if( nodeName == "variantdefs" )
- {
- // TODO : handle variantdefs nodes
- }
- else // DEFAULT
- {
- THROW_IO_ERROR( wxString::Format( _( "XML node '%s' unknown" ), nodeName ) );
- }
+ int x;
+ int y;
+ int radius;
+ int width;
- currentNode = currentNode->GetNext();
- }
+ aCircleNode->GetAttribute( "x" ).ToDouble( &x );
+ aCircleNode->GetAttribute( "y" ).ToDouble( &y );
+ aCircleNode->GetAttribute( "radius" ).ToDouble( &radius );
+ aCircleNode->GetAttribute( "width" ).ToDouble( &width );
+
+ circle->SetPosition( wxPoint( x, y ) );
+ circle->SetRadius( radius );
+ circle->SetWidth( width ;
+
+ return circle.release();
}
-void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* currentNode )
-{
-
-}
void SCH_EAGLE_PLUGIN::Save( const wxString& aFileName, SCH_SCREEN* aSchematic, KIWAY* aKiway,
const PROPERTIES* aProperties )
@@ -299,6 +603,38 @@ bool SCH_EAGLE_PLUGIN::IsSymbolLibWritable( const wxString& aLibraryPath )
return false;
}
+
void SCH_EAGLE_PLUGIN::SymbolLibOptions( PROPERTIES* aListToAppendTo ) const
{
}
+
+// approved
+// attribute
+// circle
+// clearance
+// connect
+// contactref
+// description
+// dimension
+// frame
+// gate
+// grid
+// hole
+// junction
+// label
+// layer
+// note
+// pad
+// param
+// pin
+// pinref
+// port
+// portref
+// rectangle
+// setting
+// smd
+// textvariant
+// variantdef
+// vertex
+// via
+// wire
diff --git a/eeschema/sch_eagle_plugin.h b/eeschema/sch_eagle_plugin.h
index 7459e59eb0..d76247fc78 100644
--- a/eeschema/sch_eagle_plugin.h
+++ b/eeschema/sch_eagle_plugin.h
@@ -24,6 +24,7 @@
#include
+#include
#include
// class KIWAY;
@@ -47,7 +48,7 @@
/**
* Class SCH_EAGLE_PLUGIN
- * is a #SCH_PLUGIN derivation for loading Autodesk Eagle schematic files.
+ * is a #SCH_PLUGIN derivation for loading 6.x+ Eagle schematic files.
*
*
* As with all SCH_PLUGINs there is no UI dependencies i.e. windowing
@@ -104,9 +105,16 @@ public:
private:
- void loadDrawing( wxXmlNode* node );
- void loadSchematic( wxXmlNode* node );
- void loadSheet( wxXmlNode* node );
+ void loadDrawing( wxXmlNode* aDrawingNode );
+ void loadSchematic( wxXmlNode* aSchematicNode );
+ void loadSheet( wxXmlNode* aSheetNode );
+ void loadSegments( wxXmlNode* aSegmentsNode );
+ SCH_LINE* loadWire( wxXmlNode* aWireNode );
+ void loadInstance( wxXmlNode* aInstanceNode );
+ void loadModuleinst( wxXmlNode* aModuleinstNode );
+ void loadLibrary( wxXmlNode* aLibraryNode );
+ LIB_PART* loadSymbol( wxXmlNode* aSymbolNode );
+
SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded..
wxString m_version; ///< Eagle file version.