From 5bbe01b570fbb68b6b1ff3e68ac029d7af7b8307 Mon Sep 17 00:00:00 2001 From: Alex Shvartzkop <dudesuchamazing@gmail.com> Date: Mon, 25 Dec 2023 07:00:11 +0300 Subject: [PATCH] EasyEDA Pro: support .elibz format (device libraries) --- .../io/easyedapro/easyedapro_import_utils.cpp | 11 +++-- .../io/easyedapro/easyedapro_import_utils.h | 2 +- common/io/easyedapro/easyedapro_parser.cpp | 24 +++++++--- .../sch_io/easyedapro/sch_io_easyedapro.cpp | 48 ++++++++++++------- .../sch_io/easyedapro/sch_io_easyedapro.h | 5 +- kicad/import_proj.cpp | 2 +- .../pcb_io/easyedapro/pcb_io_easyedapro.cpp | 30 +++++++++--- pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.h | 6 ++- 8 files changed, 89 insertions(+), 39 deletions(-) diff --git a/common/io/easyedapro/easyedapro_import_utils.cpp b/common/io/easyedapro/easyedapro_import_utils.cpp index 3d4b8e6b85..8bb13e6a87 100644 --- a/common/io/easyedapro/easyedapro_import_utils.cpp +++ b/common/io/easyedapro/easyedapro_import_utils.cpp @@ -140,7 +140,7 @@ EASYEDAPRO::ProjectToSelectorDialog( const nlohmann::json& aProject, bool aPcbOn } -nlohmann::json EASYEDAPRO::ReadProjectFile( const wxString& aZipFileName ) +nlohmann::json EASYEDAPRO::ReadProjectOrDeviceFile( const wxString& aZipFileName ) { std::shared_ptr<wxZipEntry> entry; wxFFileInputStream in( aZipFileName ); @@ -150,7 +150,7 @@ nlohmann::json EASYEDAPRO::ReadProjectFile( const wxString& aZipFileName ) { wxString name = entry->GetName(); - if( name == wxS( "project.json" ) ) + if( name == wxS( "project.json" ) || name == wxS( "device.json" ) ) { wxMemoryOutputStream memos; memos << zip; @@ -161,9 +161,10 @@ nlohmann::json EASYEDAPRO::ReadProjectFile( const wxString& aZipFileName ) } } - THROW_IO_ERROR( wxString::Format( _( "'%s' does not appear to be a valid EasyEDA (JLCEDA) Pro " - "project file. Cannot find project.json." ), - aZipFileName ) ); + THROW_IO_ERROR( wxString::Format( + _( "'%s' does not appear to be a valid EasyEDA (JLCEDA) Pro " + "project or library file. Cannot find project.json or device.json." ), + aZipFileName ) ); } diff --git a/common/io/easyedapro/easyedapro_import_utils.h b/common/io/easyedapro/easyedapro_import_utils.h index f61adfa5bd..d4b6477a8c 100644 --- a/common/io/easyedapro/easyedapro_import_utils.h +++ b/common/io/easyedapro/easyedapro_import_utils.h @@ -46,7 +46,7 @@ std::vector<IMPORT_PROJECT_DESC> ProjectToSelectorDialog( const nlohmann::json& bool aPcbOnly = false, bool aSchOnly = false ); -nlohmann::json ReadProjectFile( const wxString& aZipFileName ); +nlohmann::json ReadProjectOrDeviceFile( const wxString& aZipFileName ); void IterateZipFiles( const wxString& aFileName, diff --git a/common/io/easyedapro/easyedapro_parser.cpp b/common/io/easyedapro/easyedapro_parser.cpp index 126daf1bd2..b1f0f18785 100644 --- a/common/io/easyedapro/easyedapro_parser.cpp +++ b/common/io/easyedapro/easyedapro_parser.cpp @@ -195,10 +195,14 @@ void EASYEDAPRO::from_json( const nlohmann::json& j, EASYEDAPRO::PRJ_SYMBOL& d ) if( j.at( "source" ).is_string() ) d.source = j.at( "source" ).get<wxString>(); - if( j.at( "desc" ).is_string() ) + if( j.contains( "desc" ) ) d.desc = j.at( "desc" ).get<wxString>(); + else if( j.contains( "description" ) ) + d.desc = j.at( "description" ).get<wxString>(); - if( j.at( "title" ).is_string() ) + if( j.contains( "display_title" ) ) + d.title = j.at( "display_title" ).get<wxString>(); + else if( j.contains( "title" ) ) d.title = j.at( "title" ).get<wxString>(); if( j.at( "version" ).is_string() ) @@ -219,10 +223,14 @@ void EASYEDAPRO::from_json( const nlohmann::json& j, EASYEDAPRO::PRJ_FOOTPRINT& if( j.at( "source" ).is_string() ) d.source = j.at( "source" ).get<wxString>(); - if( j.at( "desc" ).is_string() ) + if( j.contains( "desc" ) ) d.desc = j.at( "desc" ).get<wxString>(); + else if( j.contains( "description" ) ) + d.desc = j.at( "description" ).get<wxString>(); - if( j.at( "title" ).is_string() ) + if( j.contains( "display_title" ) ) + d.title = j.at( "display_title" ).get<wxString>(); + else if( j.contains( "title" ) ) d.title = j.at( "title" ).get<wxString>(); if( j.at( "version" ).is_string() ) @@ -243,10 +251,14 @@ void EASYEDAPRO::from_json( const nlohmann::json& j, EASYEDAPRO::PRJ_DEVICE& d ) if( j.at( "source" ).is_string() ) d.source = j.at( "source" ).get<wxString>(); - if( j.at( "description" ).is_string() ) + if( j.contains( "desc" ) ) + d.description = j.at( "desc" ).get<wxString>(); + else if( j.contains( "description" ) ) d.description = j.at( "description" ).get<wxString>(); - if( j.at( "title" ).is_string() ) + if( j.contains( "display_title" ) ) + d.title = j.at( "display_title" ).get<wxString>(); + else if( j.contains( "title" ) ) d.title = j.at( "title" ).get<wxString>(); if( j.at( "version" ).is_string() ) diff --git a/eeschema/sch_io/easyedapro/sch_io_easyedapro.cpp b/eeschema/sch_io/easyedapro/sch_io_easyedapro.cpp index 8a96634821..3e5aa69ed4 100644 --- a/eeschema/sch_io/easyedapro/sch_io_easyedapro.cpp +++ b/eeschema/sch_io/easyedapro/sch_io_easyedapro.cpp @@ -116,7 +116,7 @@ static LIB_SYMBOL* loadSymbol( nlohmann::json project, const wxString& aLibraryP SCH_EASYEDAPRO_PARSER parser( nullptr, nullptr ); LIB_SYMBOL* symbol = nullptr; wxFileName libFname( aLibraryPath ); - wxString symLibName = EASYEDAPRO::ShortenLibName( libFname.GetName() ); + wxString symLibName = LIB_ID::FixIllegalChars( libFname.GetName(), true ); /*if( libFname.GetExt() == wxS( "esym" ) ) { @@ -146,7 +146,8 @@ static LIB_SYMBOL* loadSymbol( nlohmann::json project, const wxString& aLibraryP } } else */ - if( libFname.GetExt() == wxS( "epro" ) || libFname.GetExt() == wxS( "zip" ) ) + if( libFname.GetExt() == wxS( "elibz" ) || libFname.GetExt() == wxS( "epro" ) + || libFname.GetExt() == wxS( "zip" ) ) { std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols = project.at( "symbols" ); std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints = project.at( "footprints" ); @@ -206,7 +207,7 @@ static LIB_SYMBOL* loadSymbol( nlohmann::json project, const wxString& aLibraryP LIB_ID libID = EASYEDAPRO::ToKiCadLibID( symLibName, aAliasName ); symInfo.libSymbol->SetLibId( libID ); symInfo.libSymbol->SetName( aAliasName ); - symInfo.libSymbol->GetFootprintField().SetText( symLibName + wxS( "/" ) + fpTitle ); + symInfo.libSymbol->GetFootprintField().SetText( symLibName + wxS( ":" ) + fpTitle ); symbol = symInfo.libSymbol.release(); @@ -244,13 +245,23 @@ void SCH_IO_EASYEDAPRO::EnumerateSymbolLib( wxArrayString& aSymbolNameLi } } } - else if( fname.GetExt() == wxS( "epro" ) || fname.GetExt() == wxS( "zip" ) ) + else if( fname.GetExt() == wxS( "elibz" ) || fname.GetExt() == wxS( "epro" ) + || fname.GetExt() == wxS( "zip" ) ) { - nlohmann::json project = EASYEDAPRO::ReadProjectFile( aLibraryPath ); + nlohmann::json project = EASYEDAPRO::ReadProjectOrDeviceFile( aLibraryPath ); std::map<wxString, nlohmann::json> symbolMap = project.at( "symbols" ); for( auto& [key, value] : symbolMap ) - aSymbolNameList.Add( value.at( "title" ) ); + { + wxString title; + + if( value.contains( "display_title" ) ) + title = value.at( "display_title" ).get<wxString>(); + else + title = value.at( "title" ).get<wxString>(); + + aSymbolNameList.Add( title ); + } } } @@ -265,8 +276,11 @@ void SCH_IO_EASYEDAPRO::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolLis EnumerateSymbolLib( symbolNameList, aLibraryPath, aProperties ); - if( libFname.GetExt() == wxS( "epro" ) || libFname.GetExt() == wxS( "zip" ) ) - project = EASYEDAPRO::ReadProjectFile( aLibraryPath ); + if( libFname.GetExt() == wxS( "elibz" ) || libFname.GetExt() == wxS( "epro" ) + || libFname.GetExt() == wxS( "zip" ) ) + { + project = EASYEDAPRO::ReadProjectOrDeviceFile( aLibraryPath ); + } for( const wxString& symbolName : symbolNameList ) { @@ -292,7 +306,7 @@ void SCH_IO_EASYEDAPRO::LoadAllDataFromProject( const wxString& aProjectPath ) if( fname.GetExt() != wxS( "epro" ) && fname.GetExt() != wxS( "zip" ) ) return; - nlohmann::json project = EASYEDAPRO::ReadProjectFile( aProjectPath ); + nlohmann::json project = EASYEDAPRO::ReadProjectOrDeviceFile( aProjectPath ); std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols = project.at( "symbols" ); std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints = project.at( "footprints" ); @@ -335,7 +349,7 @@ void SCH_IO_EASYEDAPRO::LoadAllDataFromProject( const wxString& aProjectPath ) LIB_ID libID = EASYEDAPRO::ToKiCadLibID( symLibName, symData.title ); symInfo.libSymbol->SetLibId( libID ); symInfo.libSymbol->SetName( symData.title ); - symInfo.libSymbol->GetFootprintField().SetText( symLibName + wxS( "/" ) + fpTitle ); + symInfo.libSymbol->GetFootprintField().SetText( symLibName + wxS( ":" ) + fpTitle ); m_projectData->m_Symbols.emplace( baseName, std::move( symInfo ) ); } @@ -357,15 +371,17 @@ void SCH_IO_EASYEDAPRO::LoadAllDataFromProject( const wxString& aProjectPath ) } -LIB_SYMBOL* SCH_IO_EASYEDAPRO::LoadSymbol( const wxString& aLibraryPath, - const wxString& aAliasName, - const STRING_UTF8_MAP* aProperties ) +LIB_SYMBOL* SCH_IO_EASYEDAPRO::LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName, + const STRING_UTF8_MAP* aProperties ) { wxFileName libFname( aLibraryPath ); nlohmann::json project; - if( libFname.GetExt() == wxS( "epro" ) || libFname.GetExt() == wxS( "zip" ) ) - project = EASYEDAPRO::ReadProjectFile( aLibraryPath ); + if( libFname.GetExt() == wxS( "elibz" ) || libFname.GetExt() == wxS( "epro" ) + || libFname.GetExt() == wxS( "zip" ) ) + { + project = EASYEDAPRO::ReadProjectOrDeviceFile( aLibraryPath ); + } return loadSymbol( project, aLibraryPath, aAliasName, aProperties ); } @@ -413,7 +429,7 @@ SCH_SHEET* SCH_IO_EASYEDAPRO::LoadSchematicFile( const wxString& aFileName, if( fname.GetExt() != wxS( "epro" ) && fname.GetExt() != wxS( "zip" ) ) return rootSheet; - nlohmann::json project = EASYEDAPRO::ReadProjectFile( aFileName ); + nlohmann::json project = EASYEDAPRO::ReadProjectOrDeviceFile( aFileName ); std::map<wxString, EASYEDAPRO::PRJ_SCHEMATIC> prjSchematics = project.at( "schematics" ); diff --git a/eeschema/sch_io/easyedapro/sch_io_easyedapro.h b/eeschema/sch_io/easyedapro/sch_io_easyedapro.h index dd5f786392..0513ac09b0 100644 --- a/eeschema/sch_io/easyedapro/sch_io_easyedapro.h +++ b/eeschema/sch_io/easyedapro/sch_io_easyedapro.h @@ -55,7 +55,10 @@ public: return PLUGIN_FILE_DESC( _HKI( "EasyEDA (JLCEDA) Pro files" ), { "epro", "zip" } ); } - const PLUGIN_FILE_DESC GetLibraryFileDesc() const override { return GetSchematicFileDesc(); } + const PLUGIN_FILE_DESC GetLibraryFileDesc() const override + { + return PLUGIN_FILE_DESC( _HKI( "EasyEDA (JLCEDA) Pro files" ), { "elibz", "epro", "zip" } ); + } bool CanReadSchematicFile( const wxString& aFileName ) const override; diff --git a/kicad/import_proj.cpp b/kicad/import_proj.cpp index 5fe7c7b91c..b960bfa6b1 100644 --- a/kicad/import_proj.cpp +++ b/kicad/import_proj.cpp @@ -174,7 +174,7 @@ void IMPORT_PROJ_HELPER::EasyEDAProProjectHandler() if( fname.GetExt() == wxS( "epro" ) || fname.GetExt() == wxS( "zip" ) ) { - nlohmann::json project = EASYEDAPRO::ReadProjectFile( fname.GetFullPath() ); + nlohmann::json project = EASYEDAPRO::ReadProjectOrDeviceFile( fname.GetFullPath() ); std::map<wxString, EASYEDAPRO::PRJ_SCHEMATIC> prjSchematics = project.at( "schematics" ); std::map<wxString, EASYEDAPRO::PRJ_BOARD> prjBoards = project.at( "boards" ); diff --git a/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.cpp b/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.cpp index 885245a4e0..b70db93719 100644 --- a/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.cpp +++ b/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.cpp @@ -125,7 +125,7 @@ BOARD* PCB_IO_EASYEDAPRO::LoadBoard( const wxString& aFileName, BOARD* aAppendTo if( fname.GetExt() == wxS( "epro" ) || fname.GetExt() == wxS( "zip" ) ) { - nlohmann::json project = EASYEDAPRO::ReadProjectFile( aFileName ); + nlohmann::json project = EASYEDAPRO::ReadProjectOrDeviceFile( aFileName ); wxString pcbToLoad; @@ -220,13 +220,23 @@ void PCB_IO_EASYEDAPRO::FootprintEnumerate( wxArrayString& aFootprintNames, } } } - else if( fname.GetExt() == wxS( "epro" ) || fname.GetExt() == wxS( "zip" ) ) + else if( fname.GetExt() == wxS( "elibz" ) || fname.GetExt() == wxS( "epro" ) + || fname.GetExt() == wxS( "zip" ) ) { - nlohmann::json project = EASYEDAPRO::ReadProjectFile( aLibraryPath ); + nlohmann::json project = EASYEDAPRO::ReadProjectOrDeviceFile( aLibraryPath ); std::map<wxString, nlohmann::json> footprintMap = project.at( "footprints" ); for( auto& [key, value] : footprintMap ) - aFootprintNames.Add( value.at( "title" ) ); + { + wxString title; + + if( value.contains( "display_title" ) ) + title = value.at( "display_title" ).get<wxString>(); + else + title = value.at( "title" ).get<wxString>(); + + aFootprintNames.Add( title ); + } } } @@ -344,16 +354,22 @@ FOOTPRINT* PCB_IO_EASYEDAPRO::FootprintLoad( const wxString& aLibraryPath, footprint->Value().SetVisible( true ); footprint->AutoPositionFields(); } - else if( libFname.GetExt() == wxS( "epro" ) || libFname.GetExt() == wxS( "zip" ) ) + else if( libFname.GetExt() == wxS( "elibz" ) || libFname.GetExt() == wxS( "epro" ) + || libFname.GetExt() == wxS( "zip" ) ) { - nlohmann::json project = EASYEDAPRO::ReadProjectFile( aLibraryPath ); + nlohmann::json project = EASYEDAPRO::ReadProjectOrDeviceFile( aLibraryPath ); wxString fpUuid; std::map<wxString, nlohmann::json> footprintMap = project.at( "footprints" ); for( auto& [uuid, data] : footprintMap ) { - wxString title = data.at( "title" ); + wxString title; + + if( data.contains( "display_title" ) ) + title = data.at( "display_title" ).get<wxString>(); + else + title = data.at( "title" ).get<wxString>(); if( title == aFootprintName ) { diff --git a/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.h b/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.h index 9b0d10ed1b..3fb78d2bcf 100644 --- a/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.h +++ b/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro.h @@ -47,12 +47,14 @@ public: PLUGIN_FILE_DESC GetFootprintLibDesc() const override { - return PLUGIN_FILE_DESC( _HKI( "EasyEDA (JLCEDA) Pro project" ), { "epro", "zip" } ); + return PLUGIN_FILE_DESC( _HKI( "EasyEDA (JLCEDA) Pro project" ), + { "elibz", "epro", "zip" } ); } PLUGIN_FILE_DESC GetFootprintFileDesc() const override { - return PLUGIN_FILE_DESC( _HKI( "EasyEDA (JLCEDA) Pro files" ), { "efoo", "epro", "zip" } ); + return PLUGIN_FILE_DESC( _HKI( "EasyEDA (JLCEDA) Pro files" ), + { "elibz", "efoo", "epro", "zip" } ); } bool CanReadBoard( const wxString& aFileName ) const override;