KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_io_easyeda.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 Alex Shvartzkop <[email protected]>
5 * Copyright (C) 2023-2024 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include "sch_easyeda_parser.h"
26#include "sch_io_easyeda.h"
27
28#include <schematic.h>
29#include <sch_sheet.h>
30#include <sch_screen.h>
32#include <project_sch.h>
34#include <string_utils.h>
35
36#include <wx/log.h>
37#include <wx/stdstream.h>
38#include <wx/zipstrm.h>
39
40#include <nlohmann/json.hpp>
41#include <core/map_helpers.h>
42#include <wx/wfstream.h>
43
44
45static bool FindSchFileInStream( const wxString& aName, wxInputStream& aStream,
46 nlohmann::json& aOut, EASYEDA::DOCUMENT& aDoc,
47 EASYEDA::DOC_TYPE& aDocType )
48{
49 if( aName.Lower().EndsWith( wxS( ".json" ) ) )
50 {
51 wxStdInputStream sin( aStream );
52 nlohmann::json js = nlohmann::json::parse( sin, nullptr, false );
53
54 if( js.is_discarded() )
55 return false;
56
59
60 if( doc.docType )
61 type = *doc.docType;
62 else
63 type = doc.head.docType;
64
66 || type == EASYEDA::DOC_TYPE::SYMBOL )
67 {
68 aOut = js;
69 aDoc = doc;
70 aDocType = type;
71 return true;
72 }
73 }
74 else if( aName.Lower().EndsWith( wxS( ".zip" ) ) )
75 {
76 std::shared_ptr<wxZipEntry> entry;
77 wxZipInputStream zip( aStream );
78
79 if( !zip.IsOk() )
80 return false;
81
82 while( entry.reset( zip.GetNextEntry() ), entry.get() != NULL )
83 {
84 wxString name = entry->GetName();
85
86 if( FindSchFileInStream( name, zip, aOut, aDoc, aDocType ) )
87 return true;
88 }
89 }
90
91 return false;
92}
93
94
95bool SCH_IO_EASYEDA::CanReadSchematicFile( const wxString& aFileName ) const
96{
97 if( !SCH_IO::CanReadSchematicFile( aFileName ) )
98 return false;
99
100 try
101 {
102 wxFFileInputStream in( aFileName );
103 nlohmann::json js;
105 EASYEDA::DOC_TYPE docType;
106
107 return FindSchFileInStream( aFileName, in, js, doc, docType );
108 }
109 catch( nlohmann::json::exception& )
110 {
111 }
112 catch( std::exception& )
113 {
114 }
115
116 return false;
117}
118
119
120bool SCH_IO_EASYEDA::CanReadLibrary( const wxString& aFileName ) const
121{
122 return CanReadSchematicFile( aFileName );
123}
124
125
127{
128 return 0;
129}
130
131
132LIB_SYMBOL* loadSymbol( const wxString& aLibraryPath, nlohmann::json aFileData,
133 const wxString& aAliasName, const STRING_UTF8_MAP* aProperties )
134{
135 SCH_EASYEDA_PARSER parser( nullptr, nullptr );
136 std::map<wxString, int> namesCounter;
137
138 try
139 {
140 wxFFileInputStream in( aLibraryPath );
141 nlohmann::json js;
142 EASYEDA::DOCUMENT topDoc;
143 EASYEDA::DOC_TYPE topDocType;
144
145 if( !FindSchFileInStream( aLibraryPath, in, js, topDoc, topDocType ) )
146 {
147 THROW_IO_ERROR( wxString::Format( _( "Unable to find a valid schematic file in '%s'" ),
148 aLibraryPath ) );
149 }
150
151 if( topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_SHEET
152 || topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_LIST )
153 {
155
156 for( const EASYEDA::DOCUMENT& subDoc : *schDoc.schematics )
157 {
158 if( subDoc.docType )
159 {
161 continue;
162 }
163 else
164 {
166 continue;
167 }
168
169 EASYEDA::DOCUMENT dataStrDoc = subDoc.dataStr->get<EASYEDA::DOCUMENT>();
170
171 for( wxString shap : dataStrDoc.shape )
172 {
173 if( !shap.Contains( wxS( "LIB" ) ) )
174 continue;
175
176 shap.Replace( wxS( "#@$" ), wxS( "\n" ) );
177 wxArrayString parts = wxSplit( shap, '\n', '\0' );
178
179 if( parts.size() < 1 )
180 continue;
181
182 wxArrayString paramsRoot = wxSplit( parts[0], '~', '\0' );
183
184 if( paramsRoot.size() < 1 )
185 continue;
186
187 wxString rootType = paramsRoot[0];
188
189 if( rootType == wxS( "LIB" ) )
190 {
191 if( paramsRoot.size() < 4 )
192 continue;
193
194 VECTOR2D origin( parser.Convert( paramsRoot[1] ),
195 parser.Convert( paramsRoot[2] ) );
196
197 wxString symbolName = wxString::Format( wxS( "Unknown_%s_%s" ),
198 paramsRoot[1], paramsRoot[2] );
199
200 wxArrayString paramParts = wxSplit( paramsRoot[3], '`', '\0' );
201
202 std::map<wxString, wxString> paramMap;
203
204 for( size_t i = 1; i < paramParts.size(); i += 2 )
205 {
206 wxString key = paramParts[i - 1];
207 wxString value = paramParts[i];
208
209 if( key == wxS( "spiceSymbolName" ) && !value.IsEmpty() )
210 symbolName = value;
211
212 paramMap[key] = value;
213 }
214
215 int& serial = namesCounter[symbolName];
216
217 if( serial > 0 )
218 symbolName << wxS( "_" ) << serial;
219
220 serial++;
221
222 paramMap[wxS( "spiceSymbolName" )] = symbolName;
223
224 if( symbolName == aAliasName )
225 {
226 parts.RemoveAt( 0 );
227
228 return parser.ParseSymbol( origin, paramMap, parts );
229 }
230 }
231 }
232 }
233 }
234 else if( topDocType == EASYEDA::DOC_TYPE::SYMBOL )
235 {
237
238 wxString symbolName = wxS( "Unknown" );
239
240 std::optional<std::map<wxString, wxString>> c_para;
241
242 if( symDoc.c_para )
243 c_para = symDoc.c_para;
244 else if( topDoc.head.c_para )
245 c_para = topDoc.head.c_para;
246
247 if( !c_para )
248 return nullptr;
249
250 symbolName = get_def( *c_para, wxS( "name" ), symbolName );
251
252 int& serial = namesCounter[symbolName];
253
254 if( serial > 0 )
255 symbolName << wxS( "_" ) << serial;
256
257 serial++;
258
259 if( symbolName != aAliasName )
260 return nullptr;
261
262 VECTOR2D origin( topDoc.head.x, topDoc.head.y );
263
264 return parser.ParseSymbol( origin, *c_para, topDoc.shape );
265 }
266 }
267 catch( nlohmann::json::exception& e )
268 {
269 THROW_IO_ERROR( wxString::Format( _( "Error loading symbol '%s' from library '%s': %s" ),
270 aAliasName, aLibraryPath, e.what() ) );
271 }
272 catch( std::exception& e )
273 {
274 THROW_IO_ERROR( wxString::Format( _( "Error loading symbol '%s' from library '%s': %s" ),
275 aAliasName, aLibraryPath, e.what() ) );
276 }
277
278 return nullptr;
279}
280
281
282void SCH_IO_EASYEDA::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
283 const wxString& aLibraryPath,
284 const STRING_UTF8_MAP* aProperties )
285{
286 std::map<wxString, int> namesCounter;
287
288 try
289 {
290 wxFFileInputStream in( aLibraryPath );
291 nlohmann::json js;
292 EASYEDA::DOCUMENT topDoc;
293 EASYEDA::DOC_TYPE topDocType;
294
295 if( !FindSchFileInStream( aLibraryPath, in, js, topDoc, topDocType ) )
296 {
297 THROW_IO_ERROR( wxString::Format( _( "Unable to find a valid schematic file in '%s'" ),
298 aLibraryPath ) );
299 }
300
301 if( topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_SHEET
302 || topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_LIST )
303 {
305
306 for( const EASYEDA::DOCUMENT& subDoc : *schDoc.schematics )
307 {
308 if( subDoc.docType )
309 {
311 continue;
312 }
313 else
314 {
316 continue;
317 }
318
319 EASYEDA::DOCUMENT dataStrDoc = subDoc.dataStr->get<EASYEDA::DOCUMENT>();
320
321 for( wxString shap : dataStrDoc.shape )
322 {
323 if( !shap.Contains( wxS( "LIB" ) ) )
324 continue;
325
326 shap.Replace( wxS( "#@$" ), wxS( "\n" ) );
327 wxArrayString parts = wxSplit( shap, '\n', '\0' );
328
329 if( parts.size() < 1 )
330 continue;
331
332 wxArrayString paramsRoot = wxSplit( parts[0], '~', '\0' );
333
334 if( paramsRoot.size() < 1 )
335 continue;
336
337 wxString rootType = paramsRoot[0];
338
339 if( rootType == wxS( "LIB" ) )
340 {
341 if( paramsRoot.size() < 4 )
342 continue;
343
344 wxString symbolName = wxString::Format( wxS( "Unknown_%s_%s" ),
345 paramsRoot[1], paramsRoot[2] );
346
347 wxArrayString paramParts = wxSplit( paramsRoot[3], '`', '\0' );
348
349 std::map<wxString, wxString> paramMap;
350
351 for( size_t i = 1; i < paramParts.size(); i += 2 )
352 {
353 wxString key = paramParts[i - 1];
354 wxString value = paramParts[i];
355
356 if( key == wxS( "spiceSymbolName" ) && !value.IsEmpty() )
357 symbolName = value;
358
359 paramMap[key] = value;
360 }
361
362 int& serial = namesCounter[symbolName];
363
364 if( serial > 0 )
365 symbolName << wxS( "_" ) << serial;
366
367 serial++;
368
369 aSymbolNameList.Add( symbolName );
370 }
371 }
372 }
373 }
374 else if( topDocType == EASYEDA::DOC_TYPE::SYMBOL )
375 {
377
378 wxString packageName = wxS( "Unknown" );
379
380 if( symDoc.c_para )
381 {
382 packageName = get_def( *symDoc.c_para, wxS( "name" ), packageName );
383 }
384 else if( topDoc.head.c_para )
385 {
386 packageName = get_def( *topDoc.head.c_para, wxS( "name" ), packageName );
387 }
388
389 aSymbolNameList.Add( packageName );
390 }
391 }
392 catch( nlohmann::json::exception& e )
393 {
394 THROW_IO_ERROR( wxString::Format( _( "Error enumerating symbol library '%s': %s" ),
395 aLibraryPath, e.what() ) );
396 }
397 catch( std::exception& e )
398 {
399 THROW_IO_ERROR( wxString::Format( _( "Error enumerating symbol library '%s': %s" ),
400 aLibraryPath, e.what() ) );
401 }
402}
403
404
405void SCH_IO_EASYEDA::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
406 const wxString& aLibraryPath,
407 const STRING_UTF8_MAP* aProperties )
408{
409 wxFFileInputStream in( aLibraryPath );
410 nlohmann::json js;
411 EASYEDA::DOCUMENT topDoc;
412 EASYEDA::DOC_TYPE topDocType;
413
414 if( !FindSchFileInStream( aLibraryPath, in, js, topDoc, topDocType ) )
415 {
416 THROW_IO_ERROR( wxString::Format( _( "Unable to find a valid schematic file in '%s'" ),
417 aLibraryPath ) );
418 }
419
420 try
421 {
422 wxArrayString symbolNameList;
423
424 EnumerateSymbolLib( symbolNameList, aLibraryPath, aProperties );
425
426 for( const wxString& symbolName : symbolNameList )
427 {
428 LIB_SYMBOL* sym = loadSymbol( aLibraryPath, js, symbolName, aProperties );
429
430 if( sym )
431 aSymbolList.push_back( sym );
432 }
433 }
434 catch( nlohmann::json::exception& e )
435 {
436 THROW_IO_ERROR( wxString::Format( _( "Error enumerating symbol library '%s': %s" ),
437 aLibraryPath, e.what() ) );
438 }
439 catch( std::exception& e )
440 {
441 THROW_IO_ERROR( wxString::Format( _( "Error enumerating symbol library '%s': %s" ),
442 aLibraryPath, e.what() ) );
443 }
444}
445
446
447LIB_SYMBOL* SCH_IO_EASYEDA::LoadSymbol( const wxString& aLibraryPath,
448 const wxString& aAliasName,
449 const STRING_UTF8_MAP* aProperties )
450{
451 try
452 {
453 wxFFileInputStream in( aLibraryPath );
454 nlohmann::json js;
455 EASYEDA::DOCUMENT topDoc;
456 EASYEDA::DOC_TYPE topDocType;
457
458 if( !FindSchFileInStream( aLibraryPath, in, js, topDoc, topDocType ) )
459 {
460 THROW_IO_ERROR( wxString::Format( _( "Unable to find a valid schematic file in '%s'" ),
461 aLibraryPath ) );
462 }
463
464 return loadSymbol( aLibraryPath, js, aAliasName, aProperties );
465 }
466 catch( nlohmann::json::exception& e )
467 {
468 THROW_IO_ERROR( wxString::Format( _( "Error loading symbol '%s' from library '%s': %s" ),
469 aAliasName, aLibraryPath, e.what() ) );
470 }
471 catch( std::exception& e )
472 {
473 THROW_IO_ERROR( wxString::Format( _( "Error loading symbol '%s' from library '%s': %s" ),
474 aAliasName, aLibraryPath, e.what() ) );
475 }
476
477 return nullptr;
478}
479
480
481static void LoadSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet, const wxString& aFileName )
482{
483 SCH_EASYEDA_PARSER parser( nullptr, nullptr );
484
485 try
486 {
487 wxFFileInputStream in( aFileName );
488 nlohmann::json js;
489 EASYEDA::DOCUMENT topDoc;
490 EASYEDA::DOC_TYPE topDocType;
491
492 if( !FindSchFileInStream( aFileName, in, js, topDoc, topDocType ) )
493 {
494 THROW_IO_ERROR( wxString::Format( _( "Unable to find a valid schematic file in '%s'" ),
495 aFileName ) );
496 }
497
498 if( topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_SHEET
499 || topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_LIST )
500 {
501 int pageNum = 1;
503
504 for( const EASYEDA::DOCUMENT& subDoc : *schDoc.schematics )
505 {
506 if( subDoc.docType )
507 {
509 continue;
510 }
511 else
512 {
514 continue;
515 }
516
517 EASYEDA::DOCUMENT dataStrDoc = subDoc.dataStr->get<EASYEDA::DOCUMENT>();
518
519 if( schDoc.schematics->size() > 1 )
520 {
521 wxString sheetTitle =
522 !subDoc.title.empty() ? subDoc.title : ( wxString() << pageNum );
523
524 wxString sheetBaseName = EscapeString( sheetTitle, CTX_FILENAME );
525
526 wxFileName sheetFname( aFileName );
527 sheetFname.SetFullName(
528 sheetBaseName + wxS( "." )
529 + wxString::FromUTF8( FILEEXT::KiCadSchematicFileExtension ) );
530
531 wxFileName relSheetPath( sheetFname );
532 relSheetPath.MakeRelativeTo(
533 wxFileName( aRootSheet->GetFileName() ).GetPath() );
534
535 std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
536 subSheet->SetFileName( relSheetPath.GetFullPath() );
537 subSheet->SetName( sheetTitle );
538
539 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
540 screen->SetFileName( sheetFname.GetFullPath() );
541 screen->SetPageNumber( wxString() << pageNum );
542 subSheet->SetScreen( screen );
543
544 VECTOR2I pos;
545 pos.x = schIUScale.MilsToIU( 200 );
546 pos.y = schIUScale.MilsToIU( 200 )
547 + ( subSheet->GetSize().y + schIUScale.MilsToIU( 200 ) )
548 * ( pageNum - 1 );
549
550 subSheet->SetPosition( pos );
551
552 SCH_SHEET_PATH sheetPath;
553 sheetPath.push_back( aRootSheet );
554 sheetPath.push_back( subSheet.get() );
555 sheetPath.SetPageNumber( wxString() << pageNum );
556 aSchematic->SetCurrentSheet( sheetPath );
557
558 parser.ParseSchematic( aSchematic, subSheet.get(), aFileName,
559 dataStrDoc.shape );
560
561 aRootSheet->GetScreen()->Append( subSheet.release() );
562 }
563 else
564 {
565 parser.ParseSchematic( aSchematic, aRootSheet, aFileName, dataStrDoc.shape );
566 }
567
568 pageNum++;
569 }
570 }
571 }
572 catch( nlohmann::json::exception& e )
573 {
575 wxString::Format( _( "Error loading schematic '%s': %s" ), aFileName, e.what() ) );
576 }
577 catch( std::exception& e )
578 {
580 wxString::Format( _( "Error loading schematic '%s': %s" ), aFileName, e.what() ) );
581 }
582}
583
584
585SCH_SHEET* SCH_IO_EASYEDA::LoadSchematicFile( const wxString& aFileName, SCHEMATIC* aSchematic,
586 SCH_SHEET* aAppendToMe,
587 const STRING_UTF8_MAP* aProperties )
588{
589 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
590
591 SCH_SHEET* rootSheet = nullptr;
592
593 if( aAppendToMe )
594 {
595 wxCHECK_MSG( aSchematic->IsValid(), nullptr,
596 wxS( "Can't append to a schematic with no root!" ) );
597
598 rootSheet = &aSchematic->Root();
599 }
600 else
601 {
602 rootSheet = new SCH_SHEET( aSchematic );
603 rootSheet->SetFileName( aFileName );
604 aSchematic->SetRoot( rootSheet );
605 }
606
607 if( !rootSheet->GetScreen() )
608 {
609 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
610
611 screen->SetFileName( aFileName );
612 rootSheet->SetScreen( screen );
613 }
614
615 SYMBOL_LIB_TABLE* libTable = PROJECT_SCH::SchSymbolLibTable( &aSchematic->Prj() );
616
617 wxCHECK_MSG( libTable, nullptr, wxS( "Could not load symbol lib table." ) );
618 LoadSchematic( aSchematic, rootSheet, aFileName );
620
621 return rootSheet;
622}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
void SetPageNumber(const wxString &aPageNumber)
Definition: base_screen.h:79
static double Convert(const wxString &aValue)
Define a library symbol object.
Definition: lib_symbol.h:78
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
Holds all the data relating to one schematic.
Definition: schematic.h:75
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:136
void SetCurrentSheet(const SCH_SHEET_PATH &aPath) override
Definition: schematic.h:141
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:184
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:121
SCH_SHEET & Root() const
Definition: schematic.h:105
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:90
void ParseSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName, wxArrayString aShapes)
LIB_SYMBOL * ParseSymbol(const VECTOR2D &aOrigin, std::map< wxString, wxString > aParams, wxArrayString aShapes)
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...
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
int GetModifyHash() const override
Return the modification hash from the library cache.
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.
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,...
bool CanReadSchematicFile(const wxString &aFileName) const override
Checks if this SCH_IO can read the specified schematic file.
virtual bool CanReadSchematicFile(const wxString &aFileName) const
Checks if this SCH_IO can read the specified schematic file.
Definition: sch_io.cpp:46
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:150
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:115
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.
Definition: sch_sheet.h:57
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:312
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:306
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:162
A name/value tuple with unique names and optional values.
#define _(s)
static const std::string KiCadSchematicFileExtension
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
wxString get_def(const std::map< wxString, wxString > &aMap, const char *aKey, const char *aDefval="")
Definition: map_helpers.h:64
static void LoadSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName)
static bool FindSchFileInStream(const wxString &aName, wxInputStream &aStream, nlohmann::json &aOut, EASYEDA::DOCUMENT &aDoc, EASYEDA::DOC_TYPE &aDocType)
LIB_SYMBOL * loadSymbol(const wxString &aLibraryPath, nlohmann::json aFileData, 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:...
@ CTX_FILENAME
Definition: string_utils.h:61
std::optional< std::vector< DOCUMENT > > schematics
std::optional< std::map< wxString, wxString > > c_para
std::optional< nlohmann::json > dataStr
std::optional< DOC_TYPE > docType
std::optional< std::map< wxString, wxString > > c_para
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
Definition of file extensions used in Kicad.