36#include <wx/txtstrm.h>
37#include <wx/wfstream.h>
38#include <wx/mstream.h>
39#include <wx/zipstrm.h>
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 );
223 wxString keywords = customTags;
224 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
228 description.Replace( wxS(
"\u2103" ), wxS(
"\u00B0C" ),
true );
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;
383 wxString keywords = customTags;
384 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
388 description.Replace( wxS(
"\u2103" ), wxS(
"\u00B0C" ),
true );
392 m_projectData->m_Symbols.emplace( baseName, std::move( symInfo ) );
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 );
465 wxCHECK_MSG( libTable,
nullptr, wxS(
"Could not load symbol lib table." ) );
468 wxFileName fname( aFileName );
473 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
478 std::map<wxString, EASYEDAPRO::PRJ_SCHEMATIC> prjSchematics =
project.at(
"schematics" );
480 wxString schematicToLoad;
482 if( aProperties && aProperties->contains(
"sch_id" ) )
484 schematicToLoad = wxString::FromUTF8( aProperties->at(
"sch_id" ) );
488 if( prjSchematics.size() == 1 )
490 schematicToLoad = prjSchematics.begin()->first;
497 if( chosen.size() > 0 )
498 schematicToLoad = chosen[0].SchematicId;
502 if( schematicToLoad.empty() )
507 wxFileName rootFname( aFileName );
508 rootFname.SetFullName( rootBaseName + wxS(
"." )
511 rootSheet->
SetName( prjSchematics[schematicToLoad].
name );
515 const std::vector<EASYEDAPRO::PRJ_SHEET>& prjSchematicSheets =
516 prjSchematics[schematicToLoad].sheets;
523 const int schSheetsCount = prjSchematicSheets.size();
525 auto cbs = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
527 if( !
name.EndsWith( wxS(
".esch" ) ) )
530 wxArrayString nameParts = wxSplit(
name,
'\\',
'\0' );
532 if( nameParts.size() == 1 )
533 nameParts = wxSplit(
name,
'/',
'\0' );
535 if( nameParts.size() < 3 )
538 wxString schematicUuid = nameParts[1];
539 wxString sheetFileName = nameParts[2];
540 wxString sheetId = sheetFileName.BeforeLast(
'.' );
542 sheetId.ToInt( &sheetId_i );
544 if( schematicUuid != schematicToLoad )
547 auto prjSheetIt = std::find_if( prjSchematicSheets.begin(), prjSchematicSheets.end(),
550 return s.id == sheetId_i;
553 if( prjSheetIt == prjSchematicSheets.end() )
558 if( schSheetsCount > 1 )
560 wxString sheetBaseName =
563 wxFileName sheetFname( aFileName );
564 sheetFname.SetFullName( sheetBaseName + wxS(
"." )
567 wxFileName relSheetPath( sheetFname );
568 relSheetPath.MakeRelativeTo( rootFname.GetPath() );
570 std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
571 subSheet->SetFileName( relSheetPath.GetFullPath() );
572 subSheet->SetName( prjSheetIt->name );
577 subSheet->SetScreen( screen );
582 + ( subSheet->GetSize().y +
schIUScale.MilsToIU( 200 ) ) * ( sheetId_i - 1 );
584 subSheet->SetPosition( pos );
612 sch_plugin->CreateLibrary( libFileName.GetFullPath() );
613 wxString libTableUri = wxS(
"${KIPRJMOD}/" ) + libFileName.GetFullName();
625 libTable->
Format( &formatter, 0 );
634 std::map<std::string, UTF8> properties;
637 for(
auto& [symbolUuid, symInfo] :
m_projectData->m_Symbols )
638 sch_plugin->SaveSymbol( libFileName.GetFullPath(), symInfo.libSymbol.release(),
641 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.
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)
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.
void SetCurrentSheet(const SCH_SHEET_PATH &aPath)
PROJECT & Project() const
Return a reference to the project this schematic is part of.
void FixupJunctionsAfterImport()
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.
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
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 ...
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.
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
std::map< wxString, EASYEDAPRO::BLOB > m_Blobs
std::map< wxString, EASYEDAPRO::SYM_INFO > m_Symbols
VECTOR2< int32_t > VECTOR2I
Definition of file extensions used in Kicad.