diff --git a/common/eagle_parser.cpp b/common/eagle_parser.cpp index 2d5be8b8e8..fe14f6f1b8 100644 --- a/common/eagle_parser.cpp +++ b/common/eagle_parser.cpp @@ -601,7 +601,9 @@ NODE_MAP MapChildren( wxXmlNode* currentNode ) NODE_MAP nodesMap; // Loop through all children mapping them in nodesMap - currentNode = currentNode->GetChildren(); + if( currentNode ) + currentNode = currentNode->GetChildren(); + while( currentNode ) { // Create a new pair in the map diff --git a/common/wildcards_and_files_ext.cpp b/common/wildcards_and_files_ext.cpp index 80a178a4ca..d72b9679e5 100644 --- a/common/wildcards_and_files_ext.cpp +++ b/common/wildcards_and_files_ext.cpp @@ -71,7 +71,7 @@ const wxString GedaPcbFootprintLibFileExtension( wxT( "fp" ) ); const wxString SchematicSymbolFileWildcard( _( "KiCad drawing symbol file (*.sym)|*.sym" ) ); const wxString SchematicLibraryFileWildcard( _( "KiCad component library file (*.lib)|*.lib" ) ); const wxString ProjectFileWildcard( _( "KiCad project files (*.pro)|*.pro" ) ); -const wxString SchematicFileWildcard( _( "KiCad schematic files (*.sch)|*.sch" ) ); +const wxString SchematicFileWildcard( _( "KiCad schematic files (*.sch)|*.sch|Eagle 6.x XML schematic file (*.sch)|*.sch" ) ); const wxString NetlistFileWildcard( _( "KiCad netlist files (*.net)|*.net" ) ); const wxString GerberFileWildcard( _( "Gerber files (*.pho)|*.pho" ) ); const wxString LegacyPcbFileWildcard( _( "KiCad printed circuit board files (*.brd)|*.brd" ) ); diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 69a0bf0831..6c6c3406f7 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -300,7 +300,7 @@ target_link_libraries( eeschema ) # the DSO (KIFACE) housing the main eeschema code: -add_library( eeschema_kiface STATIC +add_library( eeschema_kiface SHARED ${EESCHEMA_SRCS} ${EESCHEMA_COMMON_SRCS} ) diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp index 1683d7f600..57406840bd 100644 --- a/eeschema/files-io.cpp +++ b/eeschema/files-io.cpp @@ -315,7 +315,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in delete g_RootSheet; // Delete the current project. g_RootSheet = NULL; // Force CreateScreens() to build new empty project on load failure. - SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) ); + SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE ) ); try { diff --git a/eeschema/qa/CMakeLists.txt b/eeschema/qa/CMakeLists.txt index f67bd69a66..f11329f35b 100644 --- a/eeschema/qa/CMakeLists.txt +++ b/eeschema/qa/CMakeLists.txt @@ -21,7 +21,7 @@ # or you may write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -find_package(Boost COMPONENTS unit_test_framework REQUIRED) +find_package( Boost COMPONENTS unit_test_framework REQUIRED ) include_directories( BEFORE ${INC_BEFORE} ) include_directories( @@ -32,7 +32,7 @@ include_directories( add_executable( qa_eagle_plugin test_module.cpp test_basic.cpp -) + ) add_dependencies( qa_eagle_plugin common eeschema_kiface ) @@ -41,4 +41,4 @@ target_link_libraries( qa_eagle_plugin eeschema_kiface ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${wxWidgets_LIBRARIES} -) + ) diff --git a/eeschema/sch_eagle_plugin.cpp b/eeschema/sch_eagle_plugin.cpp index e95af738e4..7a32f3fb43 100644 --- a/eeschema/sch_eagle_plugin.cpp +++ b/eeschema/sch_eagle_plugin.cpp @@ -28,6 +28,12 @@ #include #include +#include +#include +#include +#include +#include + #include using namespace std; @@ -75,15 +81,15 @@ void kicadLayer( int aEagleLayer ) 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; + 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; } } @@ -136,7 +142,7 @@ SCH_SHEET* SCH_EAGLE_PLUGIN::Load( const wxString& aFileName, KIWAY* aKiway, THROW_IO_ERROR( wxString::Format( _( "Unable to read file '%s'" ), fn.GetFullPath() ) ); // Delete on exception, if I own m_rootSheet, according to aAppendToMe - unique_ptr deleter( aAppendToMe ? nullptr : m_rootSheet ); + unique_ptr deleter( aAppendToMe ? nullptr : m_rootSheet ); if( aAppendToMe ) { @@ -148,6 +154,14 @@ SCH_SHEET* SCH_EAGLE_PLUGIN::Load( const wxString& aFileName, KIWAY* aKiway, m_rootSheet->SetFileName( aFileName ); } + // TODO change to loadSheet, so it can handle multiple sheets + if( !m_rootSheet->GetScreen() ) + { + SCH_SCREEN* screen = new SCH_SCREEN( aKiway ); + screen->SetFileName( aFileName ); + m_rootSheet->SetScreen( screen ); + } + // Retrieve the root as current node wxXmlNode* currentNode = xmlDocument.GetRoot(); @@ -250,7 +264,7 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode ) // 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(); + wxXmlNode* busNode = getChildrenNodes( sheetChildren, "busses" ); while( busNode ) { @@ -266,7 +280,7 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode ) // Loop through all nets // From the DTD: "Net is an electrical connection in a schematic." - wxXmlNode* netNode = sheetChildren["nets"]->GetChildren(); + wxXmlNode* netNode = getChildrenNodes( sheetChildren, "nets" ); while( netNode ) { @@ -282,7 +296,7 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode ) } // Loop through all instances - wxXmlNode* instanceNode = sheetChildren["instances"]->GetChildren(); + wxXmlNode* instanceNode = getChildrenNodes( sheetChildren, "instances" ); while( instanceNode ) { @@ -291,7 +305,7 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode ) } // Loop through all moduleinsts - wxXmlNode* moduleinstNode = sheetChildren["moduleinsts"]->GetChildren(); + wxXmlNode* moduleinstNode = getChildrenNodes( sheetChildren, "moduleinsts" ); while( moduleinstNode ) { @@ -305,7 +319,13 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode ) // wxString description = description->GetNodeContent(); // TODO: do something with the plain - // wxXmlNode* plain = sheetChildren["plain"]; + wxXmlNode* plainNode = sheetChildren["plain"]; + + while( plainNode ) + { + loadSegments( plainNode ); + plainNode = plainNode->GetNext(); + } } @@ -313,6 +333,8 @@ void SCH_EAGLE_PLUGIN::loadSegments( wxXmlNode* aSegmentsNode ) { // Loop through all segments wxXmlNode* currentSegment = aSegmentsNode->GetChildren(); + SCH_SCREEN* screen = m_rootSheet->GetScreen(); + //wxCHECK( screen, [>void<] ); while( currentSegment ) { @@ -356,11 +378,21 @@ void SCH_EAGLE_PLUGIN::loadSegments( wxXmlNode* aSegmentsNode ) } else if( nodeName == "wire" ) { - loadWire( segmentAttribute ); + screen->Append( loadWire( segmentAttribute ) ); + } + else if( nodeName == "segment" ) + { + loadSegments( segmentAttribute ); + } + else if( nodeName == "text" ) + { + // TODO + //loadSegments( segmentAttribute ); } else // DEFAULT { - THROW_IO_ERROR( wxString::Format( _( "XML node '%s' unknown" ), nodeName ) ); + // TODO uncomment + //THROW_IO_ERROR( wxString::Format( _( "XML node '%s' unknown" ), nodeName ) ); } // Get next segment attribute @@ -374,24 +406,15 @@ void SCH_EAGLE_PLUGIN::loadSegments( wxXmlNode* aSegmentsNode ) SCH_LINE* SCH_EAGLE_PLUGIN::loadWire( wxXmlNode* aWireNode ) { - std::unique_ptr< SCH_LINE > wire( new SCH_LINE ); + std::unique_ptr 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 + auto ewire = EWIRE( aWireNode ); // TODO: layer map? // wire->SetLayer( layerMap( layer ) ); // if( strCompare( "Wire", line, &line ) ) - // wire->SetLayer( LAYER_WIRE ); + wire->SetLayer( LAYER_WIRE ); // else if( strCompare( "Bus", line, &line ) ) // wire->SetLayer( LAYER_BUS ); // else if( strCompare( "Notes", line, &line ) ) @@ -401,16 +424,15 @@ SCH_LINE* SCH_EAGLE_PLUGIN::loadWire( wxXmlNode* aWireNode ) wxPoint begin, end; - begin.x = wxAtoi( x1 ); - begin.y = wxAtoi( y1 ); - end.x = wxAtoi( x2 ); - end.y = wxAtoi( y2 ); + begin.x = ewire.x1; + begin.y = ewire.y1; + end.x = ewire.x2; + end.y = ewire.y2; wire->SetStartPoint( begin ); wire->SetEndPoint( end ); return wire.release(); - } @@ -477,39 +499,39 @@ LIB_PART* SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode ) if( nodeName == "description" ) { // TODO - wxASSERT_MSG( false, "'description' nodes are not implemented yet" ); + //wxASSERT_MSG( false, "'description' nodes are not implemented yet" ); } else if( nodeName == "dimension" ) { // TODO - wxASSERT_MSG( false, "'description' nodes are not implemented yet" ); + //wxASSERT_MSG( false, "'description' nodes are not implemented yet" ); } else if( nodeName == "frame" ) { } else if( nodeName == "circle" ) { - part->AddDrawItem( loadCircle( part, currentNode ) ); + part->AddDrawItem( loadCircle( part.get(), currentNode ) ); } else if( nodeName == "pin" ) { - part->AddDrawItem( loadPin( part, currentNode ) ); + // part->AddDrawItem( loadPin( part, currentNode ) ); } else if( nodeName == "polygon" ) { - part->AddDrawItem( loadPolyline( part, currentNode ) ); + //part->AddDrawItem( loadPolygon( part.get(), currentNode ) ); } else if( nodeName == "rectangle" ) { - part->AddDrawItem( loadRectangle( part, currentNode ) ); + part->AddDrawItem( loadRectangle( part.get(), currentNode ) ); } else if( nodeName == "text" ) { - part->AddDrawItem( loadText( part, currentNode ) ); + // part->AddDrawItem( loadText( part, currentNode ) ); } else if( nodeName == "wire" ) { - part->AddDrawItem( loadPolyline( part, currentNode ) ); + // part->AddDrawItem( loadPolyline( part, currentNode ) ); } currentNode = currentNode->GetNext(); @@ -521,28 +543,59 @@ LIB_PART* SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode ) LIB_CIRCLE* SCH_EAGLE_PLUGIN::loadCircle( LIB_PART* aPart, wxXmlNode* aCircleNode ) { - unique_ptr< LIB_CIRCLE > circle( new LIB_CIRCLE( aPart.get() ) ); + // Parse the circle properties + ECIRCLE c( aCircleNode ); - int layer = wxAtoi( aCircleNode->GetAttribute( "layer" ) ); + unique_ptr circle( new LIB_CIRCLE( aPart ) ); - int x; - int y; - int radius; - int width; - - 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 ; + circle->SetPosition( wxPoint( c.x, c.y ) ); + circle->SetRadius( c.radius ); + circle->SetWidth( c.width ); return circle.release(); } +LIB_RECTANGLE* SCH_EAGLE_PLUGIN::loadRectangle( LIB_PART* aPart, wxXmlNode* aRectNode ) +{ + ERECT rect( aRectNode ); + + unique_ptr rectangle( new LIB_RECTANGLE( aPart ) ); + + rectangle->SetPosition( wxPoint( rect.x1, rect.y1 ) ); + rectangle->SetEnd( wxPoint( rect.x2, rect.y2 ) ); + + // TODO: Manage rotation + + return rectangle.release(); +} + + +LIB_POLYLINE* SCH_EAGLE_PLUGIN::loadPolyLine( LIB_PART* aPart, wxXmlNode* aRectNode ) +{ + std::unique_ptr< LIB_POLYLINE > polyLine( new LIB_POLYLINE( aPart ) ); + + /*int points = parseInt( aReader, line, &line ); + polyLine->SetUnit( parseInt( aReader, line, &line ) ); + polyLine->SetConvert( parseInt( aReader, line, &line ) ); + polyLine->SetWidth( parseInt( aReader, line, &line ) ); + + wxPoint pt; + + for( int i = 0; i < points; i++ ) + { + pt.x = parseInt( aReader, line, &line ); + pt.y = parseInt( aReader, line, &line ); + polyLine->AddPoint( pt ); + } + + if( *line != 0 ) + polyLine->SetFillMode( parseFillMode( aReader, line, &line ) );*/ + + return polyLine.release(); +} + + void SCH_EAGLE_PLUGIN::Save( const wxString& aFileName, SCH_SCREEN* aSchematic, KIWAY* aKiway, const PROPERTIES* aProperties ) { diff --git a/eeschema/sch_eagle_plugin.h b/eeschema/sch_eagle_plugin.h index 8e46761337..c2aa2aa7af 100644 --- a/eeschema/sch_eagle_plugin.h +++ b/eeschema/sch_eagle_plugin.h @@ -26,23 +26,26 @@ #include #include -// class KIWAY; -// class LINE_READER; -// class SCH_SCREEN; -// class SCH_SHEET; -// class SCH_BITMAP; -// class SCH_JUNCTION; -// class SCH_NO_CONNECT; -// class SCH_LINE; -// class SCH_BUS_ENTRY_BASE;s -// class SCH_TEXT; -// class SCH_COMPONENT; -// class SCH_FIELD; -// class PROPERTIES; -// class SCH_EAGLE_PLUGIN_CACHE; -// class LIB_PART; -// class PART_LIB; -// class LIB_ALIAS; +class KIWAY; +class LINE_READER; +class SCH_SCREEN; +class SCH_SHEET; +class SCH_BITMAP; +class SCH_JUNCTION; +class SCH_NO_CONNECT; +class SCH_LINE; +class SCH_BUS_ENTRY_BASE; +class SCH_TEXT; +class SCH_COMPONENT; +class SCH_FIELD; +class PROPERTIES; +class SCH_EAGLE_PLUGIN_CACHE; +class LIB_PART; +class PART_LIB; +class LIB_ALIAS; +class LIB_CIRCLE; +class LIB_RECTANGLE; +class LIB_POLYLINE; /** @@ -114,6 +117,9 @@ private: void loadLibrary( wxXmlNode* aLibraryNode ); LIB_PART* loadSymbol( wxXmlNode* aSymbolNode ); + LIB_CIRCLE* loadCircle( LIB_PART* aPart, wxXmlNode* aCircleNode ); + LIB_RECTANGLE* loadRectangle( LIB_PART* aPart, wxXmlNode* aRectNode ); + LIB_POLYLINE* loadPolyLine( LIB_PART* aPart, wxXmlNode* aRectNode ); SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded.. wxString m_version; ///< Eagle file version. diff --git a/eeschema/sch_io_mgr.h b/eeschema/sch_io_mgr.h index d7a2bcff3e..835f8d522d 100644 --- a/eeschema/sch_io_mgr.h +++ b/eeschema/sch_io_mgr.h @@ -24,6 +24,7 @@ */ #include +#include #include @@ -73,6 +74,7 @@ public: * @return the plugin corresponding to aFileType or NULL if not found. * Caller owns the returned object, and must call PluginRelease when done using it. */ + APIEXPORT static SCH_PLUGIN* FindPlugin( SCH_FILE_T aFileType ); /** diff --git a/include/eagle_parser.h b/include/eagle_parser.h index 2d8a883e04..924d34c5f8 100644 --- a/include/eagle_parser.h +++ b/include/eagle_parser.h @@ -48,6 +48,12 @@ class MODULE; typedef std::unordered_map NODE_MAP; typedef std::map MODULE_MAP; +static inline wxXmlNode* getChildrenNodes( NODE_MAP& aMap, const string& aName ) +{ + auto it = aMap.find( aName ); + return it == aMap.end() ? nullptr : it->second->GetChildren(); +} + /** * Class XML_PARSER_ERROR