41#include <wx/filename.h>
46 PCB_IO( wxS(
"EasyEDA (JLCEDA) Pro v3" ) )
87 wxFileName fileName( aLibraryPath );
89 if( !fileName.FileExists() )
92 wxDateTime modified = fileName.GetModificationTime();
94 if( !modified.IsValid() )
97 return modified.GetTicks();
102 bool aBestEfforts,
const std::map<std::string, UTF8>* aProperties )
106 std::map<wxString, wxString> footprintMap =
109 for(
const auto& [
name, uuid] : footprintMap )
110 aFootprintNames.Add(
name );
116 std::vector<FOOTPRINT*>
result;
128 const wxString& aFootprintName,
bool aKeepUUID,
129 const std::map<std::string, UTF8>* aProperties )
135 std::map<wxString, wxString> footprintMap =
138 auto fpIt = footprintMap.find( aFootprintName );
140 if( fpIt == footprintMap.end() )
148 const nlohmann::json&
index =
v3.GetLibraryIndex();
151 std::unique_ptr<FOOTPRINT> footprint;
157 catch( nlohmann::json::exception& e )
159 THROW_IO_ERRORF(
_(
"Cannot load footprint '%s' from '%s': %s" ), aFootprintName, aLibraryPath, e.what() );
163 THROW_IO_ERRORF(
_(
"Cannot load footprint '%s' from '%s'" ), aFootprintName, aLibraryPath );
166 if(
index.contains(
"devices" ) &&
index.at(
"devices" ).is_object() )
168 for(
const auto& [devUuid, deviceJson] :
index.at(
"devices" ).items() )
170 if( !deviceJson.is_object() || !deviceJson.contains(
"attributes" )
171 || !deviceJson.at(
"attributes" ).is_object() )
176 const nlohmann::json& attrs = deviceJson.at(
"attributes" );
178 if( !attrs.contains(
"Footprint" )
186 wxString modelTransform;
188 if( attrs.contains(
"3D Model" ) )
191 if( attrs.contains(
"3D Model Title" ) )
194 modelTitle = modelUuid;
196 if( attrs.contains(
"3D Model Transform" ) )
207 footprint->Reference().SetVisible(
true );
208 footprint->Value().SetText( aFootprintName );
209 footprint->Value().SetVisible(
true );
210 footprint->AutoPositionFields();
217 const std::map<std::string, UTF8>* aProperties,
PROJECT* aProject )
241 pcbToLoad = wxString::FromUTF8(
m_props->at(
"pcb_id" ) );
245 std::map<wxString, nlohmann::json> prjPcbs =
project.at(
"pcbs" );
247 if( prjPcbs.size() == 1 )
249 pcbToLoad = prjPcbs.begin()->first;
253 std::vector<IMPORT_PROJECT_DESC> chosen =
256 if( !chosen.empty() )
257 pcbToLoad = chosen[0].PCBId;
259 else if( !prjPcbs.empty() )
261 pcbToLoad = prjPcbs.begin()->first;
265 if( pcbToLoad.empty() )
272 wxFileName sourceName( aFileName );
277 std::map<wxString, std::unique_ptr<FOOTPRINT>> footprints;
278 std::set<wxString> usedLibNames;
280 for(
const auto& [uuid, rawDoc] : adapter.
GetRawDocs( wxS(
"FOOTPRINT" ) ) )
282 std::unique_ptr<FOOTPRINT> footprint( parser.
ParseFootprint( blobs, rawDoc ) );
287 std::string uuidKey = std::string( uuid.ToUTF8() );
288 const nlohmann::json& fpMetas =
project.at(
"footprints" );
289 wxString fpTitle = uuid;
291 if( fpMetas.contains( uuidKey ) )
296 footprints.emplace( uuid, std::move( footprint ) );
302 THROW_IO_ERRORF(
_(
"PCB document '%s' not found in '%s'" ), pcbToLoad, aFileName );
304 std::multimap<wxString, EASYEDAPRO::POURED> poured;
311 for(
auto& [uuid, footprint] : footprints )
319 Report( wxString::Format(
_(
"EasyEDA (JLCEDA) Pro v3 import skipped %d unsupported object(s)." ),
Information pertinent to a Pcbnew printed circuit board.
Parses EasyEDA Pro v3 .epro2 archives.
void Load()
Load all v3 docs from the archive.
const V3_DOC_RAW * FindRawDoc(const wxString &aDocType, const wxString &aUuid) const
const std::map< wxString, V3_DOC_RAW > & GetRawDocs(const wxString &aDocType) const
static bool IsV3Library(const wxString &aFileName, const wxString &aRequiredDocType=wxEmptyString)
Return true if aFileName looks like an EasyEDA Pro v3 library archive.
int GetSkippedCount() const
static bool IsV3Archive(const wxString &aFileName)
Return true if aFileName looks like an EasyEDA Pro v3 archive.
RAII class to set and restore the fontconfig reporter.
virtual void Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) const
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
virtual bool CanReadLibrary(const wxString &aFileName) const
Checks if this IO object can read the specified library file/directory.
static LOAD_INFO_REPORTER & GetInstance()
void FillFootprintModelInfo(FOOTPRINT *footprint, const wxString &modelUuid, const wxString &modelTitle, const wxString &modelTransform) const
void ParseBoard(BOARD *aBoard, const nlohmann::json &aProject, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, const std::map< wxString, EASYEDAPRO::BLOB > &aBlobMap, const std::multimap< wxString, EASYEDAPRO::POURED > &aPouredMap, const EASYEDAPRO::V3_DOC_RAW &aDoc, const wxString &aFpLibName)
std::unique_ptr< FOOTPRINT > ParseFootprint(const std::map< wxString, EASYEDAPRO::BLOB > &aBlobMap, const EASYEDAPRO::V3_DOC_RAW &aDoc)
long long GetLibraryTimestamp(const wxString &aLibraryPath) const override
Generate a timestamp representing all the files in the library (including the library directory).
std::unique_ptr< EASYEDAPRO::V3_DOC_PARSER > m_cachedLibraryParser
bool CanReadBoard(const wxString &aFileName) const override
Checks if this PCB_IO can read the specified board file.
~PCB_IO_EASYEDAPRO_V3() override
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
void loadBoard(const wxString &aFileName, BOARD &aBoard, bool aIsNewLoad, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Parse aFileName into aBoard.
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
wxString m_cachedLibraryPath
std::vector< std::unique_ptr< FOOTPRINT > > m_importedLibFootprints
Definitions from the last LoadBoard, cloned out to the import reconciler on request.
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Return a list of footprint names contained within the library at aLibraryPath.
std::unique_ptr< FOOTPRINT > FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PC...
const EASYEDAPRO::V3_DOC_PARSER & getCachedLibraryParser(const wxString &aLibraryPath) const
long long m_cachedLibraryTimestamp
BOARD * m_board
The board BOARD being worked on, no ownership here.
PCB_IO(const wxString &aName)
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
CHOOSE_PROJECT_HANDLER m_choose_project_handler
Callback to choose projects to import.
Container for project specific data.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_ERRORF(msg,...)
#define THROW_IO_CANCELLED()
nlohmann::json BuildV3ProjectIndexFromRawDocs(const V3_DOC_PARSER &aParser, bool aIncludeLibraryMetadata=true)
Build a minimal legacy-style project index from parsed v3 raw documents.
LIB_ID ToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
wxString MakeUniqueLibName(std::set< wxString > &aUsedNames, const wxString &aName, const wxString &aFallback)
Allocate a unique library item name, recording it in aUsedNames.
wxString GetV3LibraryItemTitle(const nlohmann::json &aMetadata, const wxString &aUuid)
std::vector< IMPORT_PROJECT_DESC > ProjectToSelectorDialog(const nlohmann::json &aProject, bool aPcbOnly=false, bool aSchOnly=false)
wxString ShortenLibName(wxString aProjectName)
wxString V3JsonToString(const nlohmann::json &aValue, const wxString &aDefault)
std::map< wxString, wxString > BuildV3LibraryItemMap(const V3_DOC_PARSER &aParser, const char *aIndexKey, const wxString &aDocType)
std::map< wxString, BLOB > BuildV3BlobMap(const V3_DOC_PARSER &aParser)
Raw parsed document from an EasyEDA Pro v3 .epru stream.
wxString result
Test unit parsing edge cases and error handling.