36#include <wx/txtstrm.h>
37#include <wx/wfstream.h>
38#include <wx/mstream.h>
39#include <wx/zipstrm.h>
43#include <nlohmann/json.hpp>
55 std::map<wxString, EASYEDAPRO::BLOB>
m_Blobs;
74 if( aFileName.Lower().EndsWith( wxS(
".epro" ) ) )
78 else if( aFileName.Lower().EndsWith( wxS(
".zip" ) ) )
80 std::shared_ptr<wxZipEntry> entry;
81 wxFFileInputStream in( aFileName );
82 wxZipInputStream
zip( in );
87 while( entry.reset(
zip.GetNextEntry() ), entry.get() != NULL )
89 wxString
name = entry->GetName();
91 if(
name == wxS(
"project.json" ) )
109 const wxString& aAliasName,
const std::map<std::string, UTF8>* aProperties )
113 wxFileName libFname( aLibraryPath );
144 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
145 || libFname.GetExt() == wxS(
"zip" ) )
147 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
148 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints;
149 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices;
151 if(
project.contains(
"footprints" ) )
152 prjFootprints =
project.at(
"footprints" );
154 if(
project.contains(
"devices" ) )
155 prjDevices =
project.at(
"devices" );
157 auto prjSymIt = std::find_if( prjSymbols.begin(), prjSymbols.end(),
158 [&](
const auto& pair )
160 return pair.second.title == aAliasName;
163 if( prjSymIt == prjSymbols.end() )
166 wxString prjSymUuid = prjSymIt->first;
168 wxString description;
170 std::map<wxString, wxString> deviceAttributes;
173 for(
auto& [key, device] : prjDevices )
175 auto val =
get_opt( device.attributes,
"Symbol" );
177 if( val && *val == prjSymUuid )
179 description = device.description;
180 deviceAttributes = device.attributes;
182 if( device.custom_tags.is_string() )
183 customTags = device.custom_tags.get<wxString>();
185 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
187 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
189 fpTitle = prjFp->title;
196 auto cb = [&](
const wxString&
name,
const wxString& symUuid, wxInputStream&
zip ) ->
bool
198 if( !
name.EndsWith( wxS(
".esym" ) ) )
201 if( symUuid != prjSymUuid )
204 wxTextInputStream txt(
zip, wxS(
" " ), wxConvUTF8 );
206 std::vector<nlohmann::json> lines;
207 while(
zip.CanRead() )
209 nlohmann::json js = nlohmann::json::parse( txt.ReadLine() );
210 lines.emplace_back( js );
220 symInfo.
libSymbol->SetName( aAliasName );
221 symInfo.
libSymbol->GetFootprintField().SetText( symLibName + wxS(
":" ) + fpTitle );
223 wxString keywords = customTags;
224 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
226 symInfo.
libSymbol->SetKeyWords( keywords );
228 description.Replace( wxS(
"\u2103" ), wxS(
"\u00B0C" ),
true );
230 symInfo.
libSymbol->SetDescription( description );
244 const wxString& aLibraryPath,
245 const std::map<std::string, UTF8>* aProperties )
247 wxFileName fname( aLibraryPath );
249 if( fname.GetExt() == wxS(
"esym" ) )
251 wxFFileInputStream ffis( aLibraryPath );
252 wxTextInputStream txt( ffis, wxS(
" " ), wxConvUTF8 );
254 while( ffis.CanRead() )
256 wxString line = txt.ReadLine();
258 if( !line.Contains( wxS(
"ATTR" ) ) )
261 nlohmann::json js = nlohmann::json::parse( line );
262 if( js.at( 0 ) ==
"ATTR" && js.at( 3 ) ==
"Symbol" )
264 aSymbolNameList.Add( js.at( 4 ).get<wxString>() );
268 else if( fname.GetExt() == wxS(
"elibz" ) || fname.GetExt() == wxS(
"epro" )
269 || fname.GetExt() == wxS(
"zip" ) )
272 std::map<wxString, nlohmann::json> symbolMap =
project.at(
"symbols" );
274 for(
auto& [key, value] : symbolMap )
278 if( value.contains(
"display_title" ) )
279 title = value.at(
"display_title" ).get<wxString>();
281 title = value.at(
"title" ).get<wxString>();
283 aSymbolNameList.Add( title );
290 const wxString& aLibraryPath,
291 const std::map<std::string, UTF8>* aProperties )
293 wxFileName libFname( aLibraryPath );
294 wxArrayString symbolNameList;
299 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
300 || libFname.GetExt() == wxS(
"zip" ) )
305 for(
const wxString& symbolName : symbolNameList )
310 aSymbolList.push_back( sym );
323 wxFileName fname( aProjectPath );
326 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
331 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
332 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints =
project.at(
"footprints" );
333 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices =
project.at(
"devices" );
335 auto cb = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
337 if( !
name.EndsWith( wxS(
".esym" ) ) && !
name.EndsWith( wxS(
".eblob" ) ) )
342 if(
name.EndsWith( wxS(
".esym" ) ) )
344 wxString description;
346 std::map<wxString, wxString> deviceAttributes;
349 for(
auto& [key, device] : prjDevices )
351 auto val =
get_opt( device.attributes,
"Symbol" );
353 if( val && *val == baseName )
355 description = device.description;
356 deviceAttributes = device.attributes;
358 if( device.custom_tags.is_string() )
359 customTags = device.custom_tags.get<wxString>();
361 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
363 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
365 fpTitle = prjFp->title;
381 symInfo.
libSymbol->GetFootprintField().SetText( symLibName + wxS(
":" ) + fpTitle );
383 wxString keywords = customTags;
384 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
386 symInfo.
libSymbol->SetKeyWords( keywords );
388 description.Replace( wxS(
"\u2103" ), wxS(
"\u00B0C" ),
true );
390 symInfo.
libSymbol->SetDescription( description );
394 else if(
name.EndsWith( wxS(
".eblob" ) ) )
396 for(
const nlohmann::json& line : lines )
398 if( line.at( 0 ) ==
"BLOB" )
413 const std::map<std::string, UTF8>* aProperties )
415 wxFileName libFname( aLibraryPath );
418 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
419 || libFname.GetExt() == wxS(
"zip" ) )
430 const std::map<std::string, UTF8>* aProperties )
432 wxCHECK( !aFileName.IsEmpty() && aSchematic,
nullptr );
441 wxCHECK_MSG( aSchematic->
IsValid(),
nullptr,
442 wxS(
"Can't append to a schematic with no root!" ) );
444 rootSheet = &aSchematic->
Root();
450 aSchematic->
SetRoot( rootSheet );
462 wxCHECK_MSG( libTable,
nullptr, wxS(
"Could not load symbol lib table." ) );
465 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;
499 if( schematicToLoad.empty() )
504 wxFileName rootFname( aFileName );
505 rootFname.SetFullName( rootBaseName + wxS(
"." )
508 rootSheet->
SetName( prjSchematics[schematicToLoad].
name );
512 const std::vector<EASYEDAPRO::PRJ_SHEET>& prjSchematicSheets =
513 prjSchematics[schematicToLoad].sheets;
520 const int schSheetsCount = prjSchematicSheets.size();
522 auto cbs = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
524 if( !
name.EndsWith( wxS(
".esch" ) ) )
527 wxArrayString nameParts = wxSplit(
name,
'\\',
'\0' );
529 if( nameParts.size() == 1 )
530 nameParts = wxSplit(
name,
'/',
'\0' );
532 if( nameParts.size() < 3 )
535 wxString schematicUuid = nameParts[1];
536 wxString sheetFileName = nameParts[2];
537 wxString sheetId = sheetFileName.BeforeLast(
'.' );
539 sheetId.ToInt( &sheetId_i );
541 if( schematicUuid != schematicToLoad )
544 auto prjSheetIt = std::find_if( prjSchematicSheets.begin(), prjSchematicSheets.end(),
547 return s.id == sheetId_i;
550 if( prjSheetIt == prjSchematicSheets.end() )
555 if( schSheetsCount > 1 )
557 wxString sheetBaseName =
560 wxFileName sheetFname( aFileName );
561 sheetFname.SetFullName( sheetBaseName + wxS(
"." )
564 wxFileName relSheetPath( sheetFname );
565 relSheetPath.MakeRelativeTo( rootFname.GetPath() );
567 std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
568 subSheet->SetFileName( relSheetPath.GetFullPath() );
569 subSheet->SetName( prjSheetIt->name );
574 subSheet->SetScreen( screen );
581 subSheet->SetPosition( pos );
609 sch_plugin->CreateLibrary( libFileName.GetFullPath() );
610 wxString libTableUri = wxS(
"${KIPRJMOD}/" ) + libFileName.GetFullName();
622 libTable->
Format( &formatter, 0 );
631 std::map<std::string, UTF8> properties;
635 sch_plugin->SaveSymbol( libFileName.GetFullPath(), symInfo.libSymbol.release(),
638 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 void SetElem(PROJECT::ELEM aIndex, _ELEM *aElem)
virtual const wxString GetProjectPath() const
Return the full path of the project.
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)
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.
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,...
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.
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 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
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.