35#include <wx/txtstrm.h>
36#include <wx/wfstream.h>
37#include <wx/mstream.h>
38#include <wx/zipstrm.h>
42#include <nlohmann/json.hpp>
54 std::map<wxString, EASYEDAPRO::BLOB>
m_Blobs;
73 if( aFileName.Lower().EndsWith( wxS(
".epro" ) ) )
77 else if( aFileName.Lower().EndsWith( wxS(
".zip" ) ) )
79 std::shared_ptr<wxZipEntry> entry;
80 wxFFileInputStream in( aFileName );
81 wxZipInputStream
zip( in );
86 while( entry.reset(
zip.GetNextEntry() ), entry.get() != NULL )
88 wxString
name = entry->GetName();
90 if(
name == wxS(
"project.json" ) )
112 wxFileName libFname( aLibraryPath );
143 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
144 || libFname.GetExt() == wxS(
"zip" ) )
146 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
147 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints;
148 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices;
150 if(
project.contains(
"footprints" ) )
151 prjFootprints =
project.at(
"footprints" );
153 if(
project.contains(
"devices" ) )
154 prjDevices =
project.at(
"devices" );
156 auto prjSymIt = std::find_if( prjSymbols.begin(), prjSymbols.end(),
157 [&](
const auto& pair )
159 return pair.second.title == aAliasName;
162 if( prjSymIt == prjSymbols.end() )
165 wxString prjSymUuid = prjSymIt->first;
167 wxString description;
169 std::map<wxString, wxString> deviceAttributes;
172 for(
auto& [key, device] : prjDevices )
174 auto val =
get_opt( device.attributes,
"Symbol" );
176 if( val && *val == prjSymUuid )
178 description = device.description;
179 deviceAttributes = device.attributes;
181 if( device.custom_tags.is_string() )
182 customTags = device.custom_tags.get<wxString>();
184 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
186 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
188 fpTitle = prjFp->title;
195 auto cb = [&](
const wxString&
name,
const wxString& symUuid, wxInputStream&
zip ) ->
bool
197 if( !
name.EndsWith( wxS(
".esym" ) ) )
200 if( symUuid != prjSymUuid )
203 wxTextInputStream txt(
zip, wxS(
" " ), wxConvUTF8 );
205 std::vector<nlohmann::json> lines;
206 while(
zip.CanRead() )
208 nlohmann::json js = nlohmann::json::parse( txt.ReadLine() );
209 lines.emplace_back( js );
219 symInfo.
libSymbol->SetName( aAliasName );
220 symInfo.
libSymbol->GetFootprintField().SetText( symLibName + wxS(
":" ) + fpTitle );
222 wxString keywords = customTags;
223 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
225 symInfo.
libSymbol->SetKeyWords( keywords );
227 description.Replace( wxS(
"\u2103" ), wxS(
"\u00B0C" ),
true );
229 symInfo.
libSymbol->SetDescription( description );
243 const wxString& aLibraryPath,
246 wxFileName fname( aLibraryPath );
248 if( fname.GetExt() == wxS(
"esym" ) )
250 wxFFileInputStream ffis( aLibraryPath );
251 wxTextInputStream txt( ffis, wxS(
" " ), wxConvUTF8 );
253 while( ffis.CanRead() )
255 wxString line = txt.ReadLine();
257 if( !line.Contains( wxS(
"ATTR" ) ) )
260 nlohmann::json js = nlohmann::json::parse( line );
261 if( js.at( 0 ) ==
"ATTR" && js.at( 3 ) ==
"Symbol" )
263 aSymbolNameList.Add( js.at( 4 ).get<wxString>() );
267 else if( fname.GetExt() == wxS(
"elibz" ) || fname.GetExt() == wxS(
"epro" )
268 || fname.GetExt() == wxS(
"zip" ) )
271 std::map<wxString, nlohmann::json> symbolMap =
project.at(
"symbols" );
273 for(
auto& [key, value] : symbolMap )
277 if( value.contains(
"display_title" ) )
278 title = value.at(
"display_title" ).get<wxString>();
280 title = value.at(
"title" ).get<wxString>();
282 aSymbolNameList.Add( title );
289 const wxString& aLibraryPath,
292 wxFileName libFname( aLibraryPath );
293 wxArrayString symbolNameList;
298 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
299 || libFname.GetExt() == wxS(
"zip" ) )
304 for(
const wxString& symbolName : symbolNameList )
309 aSymbolList.push_back( sym );
322 wxFileName fname( aProjectPath );
325 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
330 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
331 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints =
project.at(
"footprints" );
332 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices =
project.at(
"devices" );
334 auto cb = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
336 if( !
name.EndsWith( wxS(
".esym" ) ) && !
name.EndsWith( wxS(
".eblob" ) ) )
341 if(
name.EndsWith( wxS(
".esym" ) ) )
343 wxString description;
345 std::map<wxString, wxString> deviceAttributes;
348 for(
auto& [key, device] : prjDevices )
350 auto val =
get_opt( device.attributes,
"Symbol" );
352 if( val && *val == baseName )
354 description = device.description;
355 deviceAttributes = device.attributes;
357 if( device.custom_tags.is_string() )
358 customTags = device.custom_tags.get<wxString>();
360 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
362 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
364 fpTitle = prjFp->title;
380 symInfo.
libSymbol->GetFootprintField().SetText( symLibName + wxS(
":" ) + fpTitle );
382 wxString keywords = customTags;
383 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
385 symInfo.
libSymbol->SetKeyWords( keywords );
387 description.Replace( wxS(
"\u2103" ), wxS(
"\u00B0C" ),
true );
389 symInfo.
libSymbol->SetDescription( description );
393 else if(
name.EndsWith( wxS(
".eblob" ) ) )
395 for(
const nlohmann::json& line : lines )
397 if( line.at( 0 ) ==
"BLOB" )
414 wxFileName libFname( aLibraryPath );
417 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
418 || libFname.GetExt() == wxS(
"zip" ) )
431 wxCHECK( !aFileName.IsEmpty() && aSchematic,
nullptr );
440 wxCHECK_MSG( aSchematic->
IsValid(),
nullptr,
441 wxS(
"Can't append to a schematic with no root!" ) );
443 rootSheet = &aSchematic->
Root();
449 aSchematic->
SetRoot( rootSheet );
461 wxCHECK_MSG( libTable,
nullptr, wxS(
"Could not load symbol lib table." ) );
464 wxFileName fname( aFileName );
469 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
474 std::map<wxString, EASYEDAPRO::PRJ_SCHEMATIC> prjSchematics =
project.at(
"schematics" );
476 wxString schematicToLoad;
478 if( aProperties && aProperties->
Exists(
"sch_id" ) )
480 schematicToLoad = wxString::FromUTF8( aProperties->at(
"sch_id" ) );
484 if( prjSchematics.size() == 1 )
486 schematicToLoad = prjSchematics.begin()->first;
493 if( chosen.size() > 0 )
494 schematicToLoad = chosen[0].SchematicId;
498 if( schematicToLoad.empty() )
503 wxFileName rootFname( aFileName );
504 rootFname.SetFullName( rootBaseName + wxS(
"." )
507 rootSheet->
SetName( prjSchematics[schematicToLoad].
name );
511 const std::vector<EASYEDAPRO::PRJ_SHEET>& prjSchematicSheets =
512 prjSchematics[schematicToLoad].sheets;
519 const int schSheetsCount = prjSchematicSheets.size();
521 auto cbs = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
523 if( !
name.EndsWith( wxS(
".esch" ) ) )
526 wxArrayString nameParts = wxSplit(
name,
'\\',
'\0' );
528 if( nameParts.size() == 1 )
529 nameParts = wxSplit(
name,
'/',
'\0' );
531 if( nameParts.size() < 3 )
534 wxString schematicUuid = nameParts[1];
535 wxString sheetFileName = nameParts[2];
536 wxString sheetId = sheetFileName.BeforeLast(
'.' );
538 sheetId.ToInt( &sheetId_i );
540 if( schematicUuid != schematicToLoad )
543 auto prjSheetIt = std::find_if( prjSchematicSheets.begin(), prjSchematicSheets.end(),
546 return s.id == sheetId_i;
549 if( prjSheetIt == prjSchematicSheets.end() )
554 if( schSheetsCount > 1 )
556 wxString sheetBaseName =
559 wxFileName sheetFname( aFileName );
560 sheetFname.SetFullName( sheetBaseName + wxS(
"." )
563 wxFileName relSheetPath( sheetFname );
564 relSheetPath.MakeRelativeTo( rootFname.GetPath() );
566 std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
567 subSheet->SetFileName( relSheetPath.GetFullPath() );
568 subSheet->SetName( prjSheetIt->name );
573 subSheet->SetScreen( screen );
580 subSheet->SetPosition( pos );
608 sch_plugin->CreateLibrary( libFileName.GetFullPath() );
609 wxString libTableUri = wxS(
"${KIPRJMOD}/" ) + libFileName.GetFullName();
621 libTable->
Format( &formatter, 0 );
634 sch_plugin->SaveSymbol( libFileName.GetFullPath(), symInfo.libSymbol.release(),
637 sch_plugin->SaveLibrary( libFileName.GetFullPath() );
constexpr EDA_IU_SCALE schIUScale
void SetPageNumber(const wxString &aPageNumber)
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
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.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
CHOOSE_PROJECT_HANDLER m_choose_project_handler
Callback to choose projects to import.
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
virtual const wxString GetProjectPath() const
Return the full path of the project.
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Holds all the data relating to one schematic.
SCH_SHEET_PATH & CurrentSheet() const override
void SetCurrentSheet(const SCH_SHEET_PATH &aPath) override
void FixupJunctions()
Add junctions to this schematic where required.
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
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)
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const STRING_UTF8_MAP *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const STRING_UTF8_MAP *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
void LoadAllDataFromProject(const wxString &aLibraryPath)
int GetModifyHash() const override
Return the modification hash from the library cache.
bool CanReadSchematicFile(const wxString &aFileName) const override
Checks if this SCH_IO can read the specified schematic file.
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const STRING_UTF8_MAP *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
static const char * PropBuffering
The property used internally by the plugin to enable cache buffering which prevents the library file ...
Base class that schematic file and library loading and saving plugins should derive from.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
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.
A name/value tuple with unique names and optional values.
bool Exists(const std::string &aProperty) const
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_IO object i...
static const wxString & GetSymbolLibTableFileName()
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indentation level of aIndentLevel.
static REPORTER & GetInstance()
static void SetReporter(REPORTER *aReporter)
Set the reporter to use for reporting font substitution warnings.
static const std::string KiCadSchematicFileExtension
static const std::string KiCadSymbolLibFileExtension
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
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)
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 STRING_UTF8_MAP *aProperties)
static LIB_SYMBOL * loadSymbol(nlohmann::json project, const wxString &aLibraryPath, const wxString &aAliasName, const STRING_UTF8_MAP *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
constexpr int MilsToIU(int mils) const
std::map< wxString, EASYEDAPRO::BLOB > m_Blobs
std::map< wxString, EASYEDAPRO::SYM_INFO > m_Symbols
Definition of file extensions used in Kicad.