34#include <wx/txtstrm.h>
35#include <wx/wfstream.h>
36#include <wx/mstream.h>
37#include <wx/zipstrm.h>
41#include <nlohmann/json.hpp>
53 std::map<wxString, EASYEDAPRO::BLOB>
m_Blobs;
72 if( aFileName.Lower().EndsWith( wxS(
".epro" ) ) )
76 else if( aFileName.Lower().EndsWith( wxS(
".zip" ) ) )
78 std::shared_ptr<wxZipEntry> entry;
79 wxFFileInputStream in( aFileName );
80 wxZipInputStream
zip( in );
85 while( entry.reset(
zip.GetNextEntry() ), entry.get() != NULL )
87 wxString
name = entry->GetName();
89 if(
name == wxS(
"project.json" ) )
111 wxFileName libFname( aLibraryPath );
142 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
143 || libFname.GetExt() == wxS(
"zip" ) )
145 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
146 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints =
project.at(
"footprints" );
147 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices =
project.at(
"devices" );
149 auto prjSymIt = std::find_if( prjSymbols.begin(), prjSymbols.end(),
150 [&](
const auto& pair )
152 return pair.second.title == aAliasName;
155 if( prjSymIt == prjSymbols.end() )
158 wxString prjSymUuid = prjSymIt->first;
161 for(
auto& [key, device] : prjDevices )
163 auto val =
get_opt( device.attributes,
"Symbol" );
165 if( val && *val == prjSymUuid )
167 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
169 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
171 fpTitle = prjFp->title;
178 auto cb = [&](
const wxString&
name,
const wxString& symUuid, wxInputStream&
zip ) ->
bool
180 if( !
name.EndsWith( wxS(
".esym" ) ) )
183 if( symUuid != prjSymUuid )
186 wxTextInputStream txt(
zip, wxS(
" " ), wxConvUTF8 );
188 std::vector<nlohmann::json> lines;
189 while(
zip.CanRead() )
191 nlohmann::json js = nlohmann::json::parse( txt.ReadLine() );
192 lines.emplace_back( js );
202 symInfo.
libSymbol->SetName( aAliasName );
203 symInfo.
libSymbol->GetFootprintField().SetText( symLibName + wxS(
":" ) + fpTitle );
217 const wxString& aLibraryPath,
220 wxFileName fname( aLibraryPath );
222 if( fname.GetExt() == wxS(
"esym" ) )
224 wxFFileInputStream ffis( aLibraryPath );
225 wxTextInputStream txt( ffis, wxS(
" " ), wxConvUTF8 );
227 while( ffis.CanRead() )
229 wxString line = txt.ReadLine();
231 if( !line.Contains( wxS(
"ATTR" ) ) )
234 nlohmann::json js = nlohmann::json::parse( line );
235 if( js.at( 0 ) ==
"ATTR" && js.at( 3 ) ==
"Symbol" )
237 aSymbolNameList.Add( js.at( 4 ).get<wxString>() );
241 else if( fname.GetExt() == wxS(
"elibz" ) || fname.GetExt() == wxS(
"epro" )
242 || fname.GetExt() == wxS(
"zip" ) )
245 std::map<wxString, nlohmann::json> symbolMap =
project.at(
"symbols" );
247 for(
auto& [key, value] : symbolMap )
251 if( value.contains(
"display_title" ) )
252 title = value.at(
"display_title" ).get<wxString>();
254 title = value.at(
"title" ).get<wxString>();
256 aSymbolNameList.Add( title );
263 const wxString& aLibraryPath,
266 wxFileName libFname( aLibraryPath );
267 wxArrayString symbolNameList;
272 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
273 || libFname.GetExt() == wxS(
"zip" ) )
278 for(
const wxString& symbolName : symbolNameList )
283 aSymbolList.push_back( sym );
296 wxFileName fname( aProjectPath );
299 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
304 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
305 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints =
project.at(
"footprints" );
306 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices =
project.at(
"devices" );
308 auto cb = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
310 if( !
name.EndsWith( wxS(
".esym" ) ) && !
name.EndsWith( wxS(
".eblob" ) ) )
315 if(
name.EndsWith( wxS(
".esym" ) ) )
325 for(
auto& [key, device] : prjDevices )
327 auto val =
get_opt( device.attributes,
"Symbol" );
329 if( val && *val == baseName )
331 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
333 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
335 fpTitle = prjFp->title;
345 symInfo.
libSymbol->GetFootprintField().SetText( symLibName + wxS(
":" ) + fpTitle );
349 else if(
name.EndsWith( wxS(
".eblob" ) ) )
351 for(
const nlohmann::json& line : lines )
353 if( line.at( 0 ) ==
"BLOB" )
370 wxFileName libFname( aLibraryPath );
373 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
374 || libFname.GetExt() == wxS(
"zip" ) )
387 wxCHECK( !aFileName.IsEmpty() && aSchematic,
nullptr );
393 wxCHECK_MSG( aSchematic->
IsValid(),
nullptr,
394 wxS(
"Can't append to a schematic with no root!" ) );
396 rootSheet = &aSchematic->
Root();
402 aSchematic->
SetRoot( rootSheet );
414 wxCHECK_MSG( libTable,
nullptr, wxS(
"Could not load symbol lib table." ) );
417 wxFileName fname( aFileName );
422 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
427 std::map<wxString, EASYEDAPRO::PRJ_SCHEMATIC> prjSchematics =
project.at(
"schematics" );
429 wxString schematicToLoad;
431 if( aProperties && aProperties->
Exists(
"sch_id" ) )
433 schematicToLoad = wxString::FromUTF8( aProperties->at(
"sch_id" ) );
437 if( prjSchematics.size() == 1 )
439 schematicToLoad = prjSchematics.begin()->first;
446 if( chosen.size() > 0 )
447 schematicToLoad = chosen[0].SchematicId;
451 if( schematicToLoad.empty() )
456 wxFileName rootFname( aFileName );
457 rootFname.SetFullName( rootBaseName + wxS(
"." )
460 rootSheet->
SetName( prjSchematics[schematicToLoad].
name );
464 const std::vector<EASYEDAPRO::PRJ_SHEET>& prjSchematicSheets =
465 prjSchematics[schematicToLoad].sheets;
472 const int schSheetsCount = prjSchematicSheets.size();
474 auto cbs = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
476 if( !
name.EndsWith( wxS(
".esch" ) ) )
479 wxArrayString nameParts = wxSplit(
name,
'\\',
'\0' );
481 if( nameParts.size() == 1 )
482 nameParts = wxSplit(
name,
'/',
'\0' );
484 if( nameParts.size() < 3 )
487 wxString schematicUuid = nameParts[1];
488 wxString sheetFileName = nameParts[2];
489 wxString sheetId = sheetFileName.BeforeLast(
'.' );
491 sheetId.ToInt( &sheetId_i );
493 if( schematicUuid != schematicToLoad )
496 auto prjSheetIt = std::find_if( prjSchematicSheets.begin(), prjSchematicSheets.end(),
499 return s.id == sheetId_i;
502 if( prjSheetIt == prjSchematicSheets.end() )
507 if( schSheetsCount > 1 )
509 wxString sheetBaseName =
512 wxFileName sheetFname( aFileName );
513 sheetFname.SetFullName( sheetBaseName + wxS(
"." )
516 wxFileName relSheetPath( sheetFname );
517 relSheetPath.MakeRelativeTo( rootFname.GetPath() );
519 std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
520 subSheet->SetFileName( relSheetPath.GetFullPath() );
521 subSheet->SetName( prjSheetIt->name );
526 subSheet->SetScreen( screen );
533 subSheet->SetPosition( pos );
561 sch_plugin->CreateLibrary( libFileName.GetFullPath() );
562 wxString libTableUri = wxS(
"${KIPRJMOD}/" ) + libFileName.GetFullName();
574 libTable->
Format( &formatter, 0 );
587 sch_plugin->SaveSymbol( libFileName.GetFullPath(), symInfo.libSymbol.release(),
590 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)
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 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.