32#include <wx/txtstrm.h>
33#include <wx/wfstream.h>
34#include <wx/mstream.h>
35#include <wx/zipstrm.h>
49 std::map<wxString, EASYEDAPRO::BLOB>
m_Blobs;
67 if( aFileName.Lower().EndsWith( wxS(
".epro" ) ) )
71 else if( aFileName.Lower().EndsWith( wxS(
".zip" ) ) )
73 std::shared_ptr<wxZipEntry> entry;
74 wxFFileInputStream in( aFileName );
75 wxZipInputStream
zip( in );
80 while( entry.reset(
zip.GetNextEntry() ), entry.get() != NULL )
82 wxString
name = entry->GetName();
84 if(
name == wxS(
"project.json" ) )
102 const wxString& aAliasName,
const std::map<std::string, UTF8>* aProperties )
106 wxFileName libFname( aLibraryPath );
137 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
138 || libFname.GetExt() == wxS(
"zip" ) )
140 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
141 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints;
142 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices;
144 if(
project.contains(
"footprints" ) )
145 prjFootprints =
project.at(
"footprints" );
147 if(
project.contains(
"devices" ) )
148 prjDevices =
project.at(
"devices" );
150 auto prjSymIt = std::find_if( prjSymbols.begin(), prjSymbols.end(),
151 [&](
const auto& pair )
153 return pair.second.title == aAliasName;
156 if( prjSymIt == prjSymbols.end() )
159 wxString prjSymUuid = prjSymIt->first;
161 wxString description;
163 std::map<wxString, wxString> deviceAttributes;
166 for(
auto& [key, device] : prjDevices )
168 auto val =
get_opt( device.attributes,
"Symbol" );
170 if( val && *val == prjSymUuid )
172 description = device.description;
173 deviceAttributes = device.attributes;
175 if( device.custom_tags.is_string() )
176 customTags = device.custom_tags.get<wxString>();
178 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
180 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
182 fpTitle = prjFp->title;
189 auto cb = [&](
const wxString&
name,
const wxString& symUuid, wxInputStream&
zip ) ->
bool
191 if( !
name.EndsWith( wxS(
".esym" ) ) )
194 if( symUuid != prjSymUuid )
197 wxTextInputStream txt(
zip, wxS(
" " ), wxConvUTF8 );
199 std::vector<nlohmann::json> lines;
200 while(
zip.CanRead() )
202 nlohmann::json js = nlohmann::json::parse( txt.ReadLine() );
203 lines.emplace_back( js );
216 wxString keywords = customTags;
217 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
236 std::vector<LIB_SYMBOL*>
result;
248 const wxString& aLibraryPath,
249 const std::map<std::string, UTF8>* aProperties )
251 wxFileName fname( aLibraryPath );
253 if( fname.GetExt() == wxS(
"esym" ) )
255 wxFFileInputStream ffis( aLibraryPath );
256 wxTextInputStream txt( ffis, wxS(
" " ), wxConvUTF8 );
258 while( ffis.CanRead() )
260 wxString line = txt.ReadLine();
262 if( !line.Contains( wxS(
"ATTR" ) ) )
265 nlohmann::json js = nlohmann::json::parse( line );
266 if( js.at( 0 ) ==
"ATTR" && js.at( 3 ) ==
"Symbol" )
268 aSymbolNameList.Add( js.at( 4 ).get<wxString>() );
272 else if( fname.GetExt() == wxS(
"elibz" ) || fname.GetExt() == wxS(
"epro" )
273 || fname.GetExt() == wxS(
"zip" ) )
276 std::map<wxString, nlohmann::json> symbolMap =
project.at(
"symbols" );
278 for(
auto& [key, value] : symbolMap )
282 if( value.contains(
"display_title" ) )
283 title = value.at(
"display_title" ).get<wxString>();
285 title = value.at(
"title" ).get<wxString>();
287 aSymbolNameList.Add( title );
294 const wxString& aLibraryPath,
295 const std::map<std::string, UTF8>* aProperties )
297 wxFileName libFname( aLibraryPath );
298 wxArrayString symbolNameList;
303 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
304 || libFname.GetExt() == wxS(
"zip" ) )
309 for(
const wxString& symbolName : symbolNameList )
314 aSymbolList.push_back( sym );
327 wxFileName fname( aProjectPath );
330 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
335 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
336 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints =
project.at(
"footprints" );
337 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices =
project.at(
"devices" );
339 auto cb = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
341 if( !
name.EndsWith( wxS(
".esym" ) ) && !
name.EndsWith( wxS(
".eblob" ) ) )
346 if(
name.EndsWith( wxS(
".esym" ) ) )
348 wxString description;
350 std::map<wxString, wxString> deviceAttributes;
353 for(
auto& [key, device] : prjDevices )
355 auto val =
get_opt( device.attributes,
"Symbol" );
357 if( val && *val == baseName )
359 description = device.description;
360 deviceAttributes = device.attributes;
362 if( device.custom_tags.is_string() )
363 customTags = device.custom_tags.get<wxString>();
365 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
367 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
369 fpTitle = prjFp->title;
387 wxString keywords = customTags;
388 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
394 m_projectData->m_Symbols.emplace( baseName, std::move( symInfo ) );
396 else if(
name.EndsWith( wxS(
".eblob" ) ) )
398 for(
const nlohmann::json& line : lines )
400 if( line.at( 0 ) ==
"BLOB" )
415 const std::map<std::string, UTF8>* aProperties )
417 wxFileName libFname( aLibraryPath );
420 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
421 || libFname.GetExt() == wxS(
"zip" ) )
432 const std::map<std::string, UTF8>* aProperties )
434 wxCHECK( !aFileName.IsEmpty() && aSchematic,
nullptr );
443 wxCHECK_MSG( aSchematic->
IsValid(),
nullptr,
444 wxS(
"Can't append to a schematic with no root!" ) );
446 rootSheet = aAppendToMe;
467 wxFileName fname( aFileName );
470 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
475 std::map<wxString, EASYEDAPRO::PRJ_SCHEMATIC> prjSchematics =
project.at(
"schematics" );
477 wxString schematicToLoad;
479 if( aProperties && aProperties->contains(
"sch_id" ) )
481 schematicToLoad = wxString::FromUTF8( aProperties->at(
"sch_id" ) );
485 if( prjSchematics.size() == 1 )
487 schematicToLoad = prjSchematics.begin()->first;
494 if( chosen.size() > 0 )
495 schematicToLoad = chosen[0].SchematicId;
497 else if( !prjSchematics.empty() )
500 schematicToLoad = prjSchematics.begin()->first;
504 if( schematicToLoad.empty() )
509 wxFileName rootFname( aFileName );
510 rootFname.SetFullName( rootBaseName + wxS(
"." )
513 rootSheet->
SetName( prjSchematics[schematicToLoad].
name );
517 const std::vector<EASYEDAPRO::PRJ_SHEET>& prjSchematicSheets =
518 prjSchematics[schematicToLoad].sheets;
525 const int schSheetsCount = prjSchematicSheets.size();
527 auto cbs = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
529 if( !
name.EndsWith( wxS(
".esch" ) ) )
532 wxArrayString nameParts = wxSplit(
name,
'\\',
'\0' );
534 if( nameParts.size() == 1 )
535 nameParts = wxSplit(
name,
'/',
'\0' );
537 if( nameParts.size() < 3 )
540 wxString schematicUuid = nameParts[1];
541 wxString sheetFileName = nameParts[2];
542 wxString sheetId = sheetFileName.BeforeLast(
'.' );
544 sheetId.ToInt( &sheetId_i );
546 if( schematicUuid != schematicToLoad )
549 auto prjSheetIt = std::find_if( prjSchematicSheets.begin(), prjSchematicSheets.end(),
552 return s.id == sheetId_i;
555 if( prjSheetIt == prjSchematicSheets.end() )
560 if( schSheetsCount > 1 )
562 wxString sheetBaseName =
565 wxFileName sheetFname( aFileName );
566 sheetFname.SetFullName( sheetBaseName + wxS(
"." )
569 wxFileName relSheetPath( sheetFname );
570 relSheetPath.MakeRelativeTo( rootFname.GetPath() );
572 std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
573 subSheet->SetFileName( relSheetPath.GetFullPath() );
574 subSheet->SetName( prjSheetIt->name );
579 subSheet->SetScreen( screen );
584 + ( subSheet->GetSize().y +
schIUScale.MilsToIU( 200 ) ) * ( sheetId_i - 1 );
586 subSheet->SetPosition( pos );
612 for(
auto& [symbolUuid, symInfo] :
m_projectData->m_Symbols )
614 if( symInfo.libSymbol )
constexpr EDA_IU_SCALE schIUScale
void SetPageNumber(const wxString &aPageNumber)
RAII class to set and restore the fontconfig reporter.
A logical library item identifier and consists of various portions much like a URI.
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Define a library symbol object.
SCH_FIELD & GetFootprintField()
Return reference to the footprint field.
void SetDescription(const wxString &aDescription)
Gets the Description field text value */.
void SetKeyWords(const wxString &aKeyWords)
void SetLibId(const LIB_ID &aLibId)
virtual void SetName(const wxString &aName)
static LOAD_INFO_REPORTER & GetInstance()
CHOOSE_PROJECT_HANDLER m_choose_project_handler
Callback to choose projects to import.
Holds all the data relating to one schematic.
void SetCurrentSheet(const SCH_SHEET_PATH &aPath)
int FixupJunctionsAfterImport()
Add junctions to this schematic where required.
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
SCH_SHEET_PATH & CurrentSheet() const
EASYEDAPRO::SYM_INFO ParseSymbol(const std::vector< nlohmann::json > &aLines, const std::map< wxString, wxString > &aDeviceAttributes)
void ParseSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const nlohmann::json &aProject, std::map< wxString, EASYEDAPRO::SYM_INFO > &aSymbolMap, const std::map< wxString, EASYEDAPRO::BLOB > &aBlobMap, const std::vector< nlohmann::json > &aLines, const wxString &aLibName)
void SetText(const wxString &aText) override
std::vector< LIB_SYMBOL * > GetImportedCachedLibrarySymbols() override
Return the canonical symbol definitions produced by the last LoadSchematicFile().
void LoadAllDataFromProject(const wxString &aLibraryPath)
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
int GetModifyHash() const override
Return the modification hash from the library cache.
std::vector< std::unique_ptr< LIB_SYMBOL > > m_importedLibSymbols
Definitions from the last LoadSchematicFile, cloned out to the import reconciler on request.
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
bool CanReadSchematicFile(const wxString &aFileName) const override
Checks if this SCH_IO can read the specified schematic file.
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
SCH_IO(const wxString &aName)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
const KIID & GetUuid() const
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
void SetFileName(const wxString &aFilename)
void SetName(const wxString &aName)
SCH_SCREEN * GetScreen() const
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
static const std::string KiCadSchematicFileExtension
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
LIB_ID ToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
void IterateZipFiles(const wxString &aFileName, std::function< bool(const wxString &, const wxString &, wxInputStream &)> aCallback)
std::vector< nlohmann::json > ParseJsonLines(wxInputStream &aInput, const wxString &aSource)
wxString NormalizeEasyEDAText(wxString aText)
Replace EasyEDA temperature glyph (℃) with °C.
std::vector< IMPORT_PROJECT_DESC > ProjectToSelectorDialog(const nlohmann::json &aProject, bool aPcbOnly=false, bool aSchOnly=false)
nlohmann::json ReadProjectOrDeviceFile(const wxString &aZipFileName)
wxString ShortenLibName(wxString aProjectName)
LIB_SYMBOL * loadSymbol(const wxString &aLibraryPath, nlohmann::json aFileData, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties)
static LIB_SYMBOL * loadSymbol(nlohmann::json project, const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
std::unique_ptr< LIB_SYMBOL > libSymbol
std::map< wxString, EASYEDAPRO::BLOB > m_Blobs
std::map< wxString, EASYEDAPRO::SYM_INFO > m_Symbols
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< int32_t > VECTOR2I
Definition of file extensions used in Kicad.