35#include <wx/txtstrm.h>
36#include <wx/wfstream.h>
37#include <wx/mstream.h>
38#include <wx/zipstrm.h>
56 std::map<wxString, EASYEDAPRO::BLOB>
m_Blobs;
75 if( aFileName.Lower().EndsWith( wxS(
".epro" ) ) )
79 else if( aFileName.Lower().EndsWith( wxS(
".zip" ) ) )
81 std::shared_ptr<wxZipEntry> entry;
82 wxFFileInputStream in( aFileName );
83 wxZipInputStream
zip( in );
88 while( entry.reset(
zip.GetNextEntry() ), entry.get() != NULL )
90 wxString
name = entry->GetName();
92 if(
name == wxS(
"project.json" ) )
110 const wxString& aAliasName,
const std::map<std::string, UTF8>* aProperties )
114 wxFileName libFname( aLibraryPath );
145 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
146 || libFname.GetExt() == wxS(
"zip" ) )
148 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
149 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints;
150 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices;
152 if(
project.contains(
"footprints" ) )
153 prjFootprints =
project.at(
"footprints" );
155 if(
project.contains(
"devices" ) )
156 prjDevices =
project.at(
"devices" );
158 auto prjSymIt = std::find_if( prjSymbols.begin(), prjSymbols.end(),
159 [&](
const auto& pair )
161 return pair.second.title == aAliasName;
164 if( prjSymIt == prjSymbols.end() )
167 wxString prjSymUuid = prjSymIt->first;
169 wxString description;
171 std::map<wxString, wxString> deviceAttributes;
174 for(
auto& [key, device] : prjDevices )
176 auto val =
get_opt( device.attributes,
"Symbol" );
178 if( val && *val == prjSymUuid )
180 description = device.description;
181 deviceAttributes = device.attributes;
183 if( device.custom_tags.is_string() )
184 customTags = device.custom_tags.get<wxString>();
186 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
188 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
190 fpTitle = prjFp->title;
197 auto cb = [&](
const wxString&
name,
const wxString& symUuid, wxInputStream&
zip ) ->
bool
199 if( !
name.EndsWith( wxS(
".esym" ) ) )
202 if( symUuid != prjSymUuid )
205 wxTextInputStream txt(
zip, wxS(
" " ), wxConvUTF8 );
207 std::vector<nlohmann::json> lines;
208 while(
zip.CanRead() )
210 nlohmann::json js = nlohmann::json::parse( txt.ReadLine() );
211 lines.emplace_back( js );
224 wxString keywords = customTags;
225 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
229 description.Replace( wxS(
"\u2103" ), wxS(
"\u00B0C" ),
true );
245 const wxString& aLibraryPath,
246 const std::map<std::string, UTF8>* aProperties )
248 wxFileName fname( aLibraryPath );
250 if( fname.GetExt() == wxS(
"esym" ) )
252 wxFFileInputStream ffis( aLibraryPath );
253 wxTextInputStream txt( ffis, wxS(
" " ), wxConvUTF8 );
255 while( ffis.CanRead() )
257 wxString line = txt.ReadLine();
259 if( !line.Contains( wxS(
"ATTR" ) ) )
262 nlohmann::json js = nlohmann::json::parse( line );
263 if( js.at( 0 ) ==
"ATTR" && js.at( 3 ) ==
"Symbol" )
265 aSymbolNameList.Add( js.at( 4 ).get<wxString>() );
269 else if( fname.GetExt() == wxS(
"elibz" ) || fname.GetExt() == wxS(
"epro" )
270 || fname.GetExt() == wxS(
"zip" ) )
273 std::map<wxString, nlohmann::json> symbolMap =
project.at(
"symbols" );
275 for(
auto& [key, value] : symbolMap )
279 if( value.contains(
"display_title" ) )
280 title = value.at(
"display_title" ).get<wxString>();
282 title = value.at(
"title" ).get<wxString>();
284 aSymbolNameList.Add( title );
291 const wxString& aLibraryPath,
292 const std::map<std::string, UTF8>* aProperties )
294 wxFileName libFname( aLibraryPath );
295 wxArrayString symbolNameList;
300 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
301 || libFname.GetExt() == wxS(
"zip" ) )
306 for(
const wxString& symbolName : symbolNameList )
311 aSymbolList.push_back( sym );
324 wxFileName fname( aProjectPath );
327 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
332 std::map<wxString, EASYEDAPRO::PRJ_SYMBOL> prjSymbols =
project.at(
"symbols" );
333 std::map<wxString, EASYEDAPRO::PRJ_FOOTPRINT> prjFootprints =
project.at(
"footprints" );
334 std::map<wxString, EASYEDAPRO::PRJ_DEVICE> prjDevices =
project.at(
"devices" );
336 auto cb = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
338 if( !
name.EndsWith( wxS(
".esym" ) ) && !
name.EndsWith( wxS(
".eblob" ) ) )
343 if(
name.EndsWith( wxS(
".esym" ) ) )
345 wxString description;
347 std::map<wxString, wxString> deviceAttributes;
350 for(
auto& [key, device] : prjDevices )
352 auto val =
get_opt( device.attributes,
"Symbol" );
354 if( val && *val == baseName )
356 description = device.description;
357 deviceAttributes = device.attributes;
359 if( device.custom_tags.is_string() )
360 customTags = device.custom_tags.get<wxString>();
362 if(
auto fpUuid =
get_opt( device.attributes,
"Footprint" ) )
364 if(
auto prjFp =
get_opt( prjFootprints, *fpUuid ) )
366 fpTitle = prjFp->title;
384 wxString keywords = customTags;
385 keywords.Replace( wxS(
":" ), wxS(
" " ),
true );
389 description.Replace( wxS(
"\u2103" ), wxS(
"\u00B0C" ),
true );
393 m_projectData->m_Symbols.emplace( baseName, std::move( symInfo ) );
395 else if(
name.EndsWith( wxS(
".eblob" ) ) )
397 for(
const nlohmann::json& line : lines )
399 if( line.at( 0 ) ==
"BLOB" )
414 const std::map<std::string, UTF8>* aProperties )
416 wxFileName libFname( aLibraryPath );
419 if( libFname.GetExt() == wxS(
"elibz" ) || libFname.GetExt() == wxS(
"epro" )
420 || libFname.GetExt() == wxS(
"zip" ) )
431 const std::map<std::string, UTF8>* aProperties )
433 wxCHECK( !aFileName.IsEmpty() && aSchematic,
nullptr );
442 wxCHECK_MSG( aSchematic->
IsValid(),
nullptr,
443 wxS(
"Can't append to a schematic with no root!" ) );
445 rootSheet = &aSchematic->
Root();
451 aSchematic->
SetRoot( rootSheet );
466 wxFileName fname( aFileName );
471 if( fname.GetExt() != wxS(
"epro" ) && fname.GetExt() != wxS(
"zip" ) )
476 std::map<wxString, EASYEDAPRO::PRJ_SCHEMATIC> prjSchematics =
project.at(
"schematics" );
478 wxString schematicToLoad;
480 if( aProperties && aProperties->contains(
"sch_id" ) )
482 schematicToLoad = wxString::FromUTF8( aProperties->at(
"sch_id" ) );
486 if( prjSchematics.size() == 1 )
488 schematicToLoad = prjSchematics.begin()->first;
495 if( chosen.size() > 0 )
496 schematicToLoad = chosen[0].SchematicId;
500 if( schematicToLoad.empty() )
505 wxFileName rootFname( aFileName );
506 rootFname.SetFullName( rootBaseName + wxS(
"." )
509 rootSheet->
SetName( prjSchematics[schematicToLoad].
name );
513 const std::vector<EASYEDAPRO::PRJ_SHEET>& prjSchematicSheets =
514 prjSchematics[schematicToLoad].sheets;
521 const int schSheetsCount = prjSchematicSheets.size();
523 auto cbs = [&](
const wxString&
name,
const wxString& baseName, wxInputStream&
zip ) ->
bool
525 if( !
name.EndsWith( wxS(
".esch" ) ) )
528 wxArrayString nameParts = wxSplit(
name,
'\\',
'\0' );
530 if( nameParts.size() == 1 )
531 nameParts = wxSplit(
name,
'/',
'\0' );
533 if( nameParts.size() < 3 )
536 wxString schematicUuid = nameParts[1];
537 wxString sheetFileName = nameParts[2];
538 wxString sheetId = sheetFileName.BeforeLast(
'.' );
540 sheetId.ToInt( &sheetId_i );
542 if( schematicUuid != schematicToLoad )
545 auto prjSheetIt = std::find_if( prjSchematicSheets.begin(), prjSchematicSheets.end(),
548 return s.id == sheetId_i;
551 if( prjSheetIt == prjSchematicSheets.end() )
556 if( schSheetsCount > 1 )
558 wxString sheetBaseName =
561 wxFileName sheetFname( aFileName );
562 sheetFname.SetFullName( sheetBaseName + wxS(
"." )
565 wxFileName relSheetPath( sheetFname );
566 relSheetPath.MakeRelativeTo( rootFname.GetPath() );
568 std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
569 subSheet->SetFileName( relSheetPath.GetFullPath() );
570 subSheet->SetName( prjSheetIt->name );
575 subSheet->SetScreen( screen );
580 + ( subSheet->GetSize().y +
schIUScale.MilsToIU( 200 ) ) * ( sheetId_i - 1 );
582 subSheet->SetPosition( pos );
609 wxCHECK_MSG(
table,
nullptr,
"Could not load symbol lib table." );
611 if( !
table->HasRow( libName ) )
614 sch_plugin->CreateLibrary( libFileName.GetFullPath() );
615 wxString libTableUri = wxS(
"${KIPRJMOD}/" ) + libFileName.GetFullName();
620 row.
SetURI( libTableUri );
629 std::map<std::string, UTF8> properties;
632 for(
auto& [symbolUuid, symInfo] :
m_projectData->m_Symbols )
633 sch_plugin->SaveSymbol( libFileName.GetFullPath(), symInfo.libSymbol.release(),
636 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.
std::optional< LIBRARY_TABLE * > ProjectTable() const
Retrieves the project library table for this adapter type, or nullopt if one doesn't exist.
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
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)
CHOOSE_PROJECT_HANDLER m_choose_project_handler
Callback to choose projects to import.
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
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.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
std::optional< LIB_STATUS > LoadOne(const wxString &aNickname)
Loads or reloads the given library, if it exists.
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.