KiCad PCB EDA Suite
sch_sexpr_plugin.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) 2020 CERN
5 * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Wayne Stambaugh <[email protected]>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <algorithm>
24
25// For some reason wxWidgets is built with wxUSE_BASE64 unset so expose the wxWidgets
26// base64 code.
27#define wxUSE_BASE64 1
28#include <wx/base64.h>
29#include <wx/log.h>
30#include <wx/mstream.h>
31#include <advanced_config.h>
32#include <base_units.h>
33#include <trace_helpers.h>
34#include <locale_io.h>
35#include <sch_bitmap.h>
36#include <sch_bus_entry.h>
37#include <sch_symbol.h>
38#include <sch_edit_frame.h> // SYMBOL_ORIENTATION_T
39#include <sch_junction.h>
40#include <sch_line.h>
41#include <sch_shape.h>
42#include <sch_no_connect.h>
43#include <sch_text.h>
44#include <sch_textbox.h>
45#include <sch_sheet.h>
46#include <sch_sheet_pin.h>
47#include <schematic.h>
49#include <sch_screen.h>
50#include <lib_shape.h>
51#include <lib_pin.h>
52#include <lib_text.h>
53#include <lib_textbox.h>
54#include <eeschema_id.h> // for MAX_UNIT_COUNT_PER_PACKAGE definition
55#include <sch_file_versions.h>
56#include <schematic_lexer.h>
60#include <symbol_lib_table.h> // for PropPowerSymsOnly definition.
61#include <ee_selection.h>
62#include <string_utils.h>
63#include <wx_filename.h> // for ::ResolvePossibleSymlinks()
64#include <progress_reporter.h>
65#include <boost/algorithm/string/join.hpp>
66
67using namespace TSCHEMATIC_T;
68
69
70#define SCH_PARSE_ERROR( text, reader, pos ) \
71 THROW_PARSE_ERROR( text, reader.GetSource(), reader.Line(), \
72 reader.LineNumber(), pos - reader.Line() )
73
74
76 m_progressReporter( nullptr )
77{
78 init( nullptr );
79}
80
81
83{
84 delete m_cache;
85}
86
87
88void SCH_SEXPR_PLUGIN::init( SCHEMATIC* aSchematic, const PROPERTIES* aProperties )
89{
90 m_version = 0;
91 m_rootSheet = nullptr;
92 m_schematic = aSchematic;
93 m_cache = nullptr;
94 m_out = nullptr;
95 m_nextFreeFieldId = 100; // number arbitrarily > MANDATORY_FIELDS or SHEET_MANDATORY_FIELDS
96}
97
98
99SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
100 SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
101{
102 wxASSERT( !aFileName || aSchematic != nullptr );
103
104 LOCALE_IO toggle; // toggles on, then off, the C locale.
105 SCH_SHEET* sheet;
106
107 wxFileName fn = aFileName;
108
109 // Unfortunately child sheet file names the legacy schematic file format are not fully
110 // qualified and are always appended to the project path. The aFileName attribute must
111 // always be an absolute path so the project path can be used for load child sheet files.
112 wxASSERT( fn.IsAbsolute() );
113
114 if( aAppendToMe )
115 {
116 wxLogTrace( traceSchLegacyPlugin, "Append \"%s\" to sheet \"%s\".",
117 aFileName, aAppendToMe->GetFileName() );
118
119 wxFileName normedFn = aAppendToMe->GetFileName();
120
121 if( !normedFn.IsAbsolute() )
122 {
123 if( aFileName.Right( normedFn.GetFullPath().Length() ) == normedFn.GetFullPath() )
124 m_path = aFileName.Left( aFileName.Length() - normedFn.GetFullPath().Length() );
125 }
126
127 if( m_path.IsEmpty() )
128 m_path = aSchematic->Prj().GetProjectPath();
129
130 wxLogTrace( traceSchLegacyPlugin, "Normalized append path \"%s\".", m_path );
131 }
132 else
133 {
134 m_path = aSchematic->Prj().GetProjectPath();
135 }
136
137 m_currentPath.push( m_path );
138 init( aSchematic, aProperties );
139
140 if( aAppendToMe == nullptr )
141 {
142 // Clean up any allocated memory if an exception occurs loading the schematic.
143 std::unique_ptr<SCH_SHEET> newSheet = std::make_unique<SCH_SHEET>( aSchematic );
144
145 wxFileName relPath( aFileName );
146 // Do not use wxPATH_UNIX as option in MakeRelativeTo(). It can create incorrect
147 // relative paths on Windows, because paths have a disk identifier (C:, D: ...)
148 relPath.MakeRelativeTo( aSchematic->Prj().GetProjectPath() );
149
150 newSheet->SetFileName( relPath.GetFullPath() );
151 m_rootSheet = newSheet.get();
152 loadHierarchy( SCH_SHEET_PATH(), newSheet.get() );
153
154 // If we got here, the schematic loaded successfully.
155 sheet = newSheet.release();
156 m_rootSheet = nullptr; // Quiet Coverity warning.
157 }
158 else
159 {
160 wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
161 m_rootSheet = &aSchematic->Root();
162 sheet = aAppendToMe;
163 loadHierarchy( SCH_SHEET_PATH(), sheet );
164 }
165
166 wxASSERT( m_currentPath.size() == 1 ); // only the project path should remain
167
168 m_currentPath.pop(); // Clear the path stack for next call to Load
169
170 return sheet;
171}
172
173
174// Everything below this comment is recursive. Modify with care.
175
176void SCH_SEXPR_PLUGIN::loadHierarchy( const SCH_SHEET_PATH& aParentSheetPath, SCH_SHEET* aSheet )
177{
178 SCH_SCREEN* screen = nullptr;
179
180 if( !aSheet->GetScreen() )
181 {
182 // SCH_SCREEN objects store the full path and file name where the SCH_SHEET object only
183 // stores the file name and extension. Add the project path to the file name and
184 // extension to compare when calling SCH_SHEET::SearchHierarchy().
185 wxFileName fileName = aSheet->GetFileName();
186
187 if( !fileName.IsAbsolute() )
188 fileName.MakeAbsolute( m_currentPath.top() );
189
190 // Save the current path so that it gets restored when descending and ascending the
191 // sheet hierarchy which allows for sheet schematic files to be nested in folders
192 // relative to the last path a schematic was loaded from.
193 wxLogTrace( traceSchLegacyPlugin, "Saving path '%s'", m_currentPath.top() );
194 m_currentPath.push( fileName.GetPath() );
195 wxLogTrace( traceSchLegacyPlugin, "Current path '%s'", m_currentPath.top() );
196 wxLogTrace( traceSchLegacyPlugin, "Loading '%s'", fileName.GetFullPath() );
197
198 SCH_SHEET_PATH ancestorSheetPath = aParentSheetPath;
199
200 while( !ancestorSheetPath.empty() )
201 {
202 if( ancestorSheetPath.LastScreen()->GetFileName() == fileName.GetFullPath() )
203 {
204 if( !m_error.IsEmpty() )
205 m_error += "\n";
206
207 m_error += wxString::Format( _( "Could not load sheet '%s' because it already "
208 "appears as a direct ancestor in the schematic "
209 "hierarchy." ),
210 fileName.GetFullPath() );
211
212 fileName = wxEmptyString;
213
214 break;
215 }
216
217 ancestorSheetPath.pop_back();
218 }
219
220 if( ancestorSheetPath.empty() )
221 m_rootSheet->SearchHierarchy( fileName.GetFullPath(), &screen );
222
223 if( screen )
224 {
225 aSheet->SetScreen( screen );
226 aSheet->GetScreen()->SetParent( m_schematic );
227 // Do not need to load the sub-sheets - this has already been done.
228 }
229 else
230 {
231 aSheet->SetScreen( new SCH_SCREEN( m_schematic ) );
232 aSheet->GetScreen()->SetFileName( fileName.GetFullPath() );
233
234 try
235 {
236 loadFile( fileName.GetFullPath(), aSheet );
237 }
238 catch( const IO_ERROR& ioe )
239 {
240 // If there is a problem loading the root sheet, there is no recovery.
241 if( aSheet == m_rootSheet )
242 throw;
243
244 // For all subsheets, queue up the error message for the caller.
245 if( !m_error.IsEmpty() )
246 m_error += "\n";
247
248 m_error += ioe.What();
249 }
250
251 if( fileName.FileExists() )
252 {
253 aSheet->GetScreen()->SetFileReadOnly( !fileName.IsFileWritable() );
254 aSheet->GetScreen()->SetFileExists( true );
255 }
256 else
257 {
258 aSheet->GetScreen()->SetFileReadOnly( !fileName.IsDirWritable() );
259 aSheet->GetScreen()->SetFileExists( false );
260 }
261
262 SCH_SHEET_PATH currentSheetPath = aParentSheetPath;
263 currentSheetPath.push_back( aSheet );
264
265 // This was moved out of the try{} block so that any sheet definitions that
266 // the plugin fully parsed before the exception was raised will be loaded.
267 for( SCH_ITEM* aItem : aSheet->GetScreen()->Items().OfType( SCH_SHEET_T ) )
268 {
269 wxCHECK2( aItem->Type() == SCH_SHEET_T, /* do nothing */ );
270 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
271
272 // Recursion starts here.
273 loadHierarchy( currentSheetPath, sheet );
274 }
275 }
276
277 m_currentPath.pop();
278 wxLogTrace( traceSchLegacyPlugin, "Restoring path \"%s\"", m_currentPath.top() );
279 }
280}
281
282
283void SCH_SEXPR_PLUGIN::loadFile( const wxString& aFileName, SCH_SHEET* aSheet )
284{
285 FILE_LINE_READER reader( aFileName );
286
287 size_t lineCount = 0;
288
290 {
291 m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aFileName ) );
292
294 THROW_IO_ERROR( ( "Open cancelled by user." ) );
295
296 while( reader.ReadLine() )
297 lineCount++;
298
299 reader.Rewind();
300 }
301
302 SCH_SEXPR_PARSER parser( &reader, m_progressReporter, lineCount );
303
304 parser.ParseSchematic( aSheet );
305}
306
307
308void SCH_SEXPR_PLUGIN::LoadContent( LINE_READER& aReader, SCH_SHEET* aSheet, int aFileVersion )
309{
310 wxCHECK( aSheet, /* void */ );
311
312 LOCALE_IO toggle;
313 SCH_SEXPR_PARSER parser( &aReader );
314
315 parser.ParseSchematic( aSheet, true, aFileVersion );
316}
317
318
319void SCH_SEXPR_PLUGIN::Save( const wxString& aFileName, SCH_SHEET* aSheet, SCHEMATIC* aSchematic,
320 const PROPERTIES* aProperties )
321{
322 wxCHECK_RET( aSheet != nullptr, "NULL SCH_SHEET object." );
323 wxCHECK_RET( !aFileName.IsEmpty(), "No schematic file name defined." );
324
325 LOCALE_IO toggle; // toggles on, then off, the C locale, to write floating point values.
326
327 init( aSchematic, aProperties );
328
329 wxFileName fn = aFileName;
330
331 // File names should be absolute. Don't assume everything relative to the project path
332 // works properly.
333 wxASSERT( fn.IsAbsolute() );
334
335 FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
336
337 m_out = &formatter; // no ownership
338
339 Format( aSheet );
340
341 aSheet->GetScreen()->SetFileExists( true );
342}
343
344
346{
347 wxCHECK_RET( aSheet != nullptr, "NULL SCH_SHEET* object." );
348 wxCHECK_RET( m_schematic != nullptr, "NULL SCHEMATIC* object." );
349
350 SCH_SCREEN* screen = aSheet->GetScreen();
351
352 wxCHECK( screen, /* void */ );
353
354 m_out->Print( 0, "(kicad_sch (version %d) (generator eeschema)\n\n",
356
357 m_out->Print( 1, "(uuid %s)\n\n", TO_UTF8( screen->m_uuid.AsString() ) );
358
359 screen->GetPageSettings().Format( m_out, 1, 0 );
360 m_out->Print( 0, "\n" );
361 screen->GetTitleBlock().Format( m_out, 1, 0 );
362
363 // Save cache library.
364 m_out->Print( 1, "(lib_symbols\n" );
365
366 for( std::pair<const wxString, LIB_SYMBOL*>& libSymbol : screen->GetLibSymbols() )
367 SCH_SEXPR_PLUGIN_CACHE::SaveSymbol( libSymbol.second, *m_out, 2, libSymbol.first );
368
369 m_out->Print( 1, ")\n\n" );
370
371 for( const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
372 saveBusAlias( alias, 1 );
373
374 // Enforce item ordering
375 auto cmp =
376 []( const SCH_ITEM* a, const SCH_ITEM* b )
377 {
378 if( a->Type() != b->Type() )
379 return a->Type() < b->Type();
380
381 return a->m_Uuid < b->m_Uuid;
382 };
383
384 std::multiset<SCH_ITEM*, decltype( cmp )> save_map( cmp );
385
386 for( SCH_ITEM* item : screen->Items() )
387 save_map.insert( item );
388
389 KICAD_T itemType = TYPE_NOT_INIT;
391
392 for( SCH_ITEM* item : save_map )
393 {
394 if( itemType != item->Type() )
395 {
396 itemType = item->Type();
397
398 if( itemType != SCH_SYMBOL_T
399 && itemType != SCH_JUNCTION_T
400 && itemType != SCH_SHEET_T )
401 {
402 m_out->Print( 0, "\n" );
403 }
404 }
405
406 switch( item->Type() )
407 {
408 case SCH_SYMBOL_T:
409 m_out->Print( 0, "\n" );
410 saveSymbol( static_cast<SCH_SYMBOL*>( item ), nullptr, 1, false );
411 break;
412
413 case SCH_BITMAP_T:
414 saveBitmap( static_cast<SCH_BITMAP*>( item ), 1 );
415 break;
416
417 case SCH_SHEET_T:
418 m_out->Print( 0, "\n" );
419 saveSheet( static_cast<SCH_SHEET*>( item ), 1 );
420 break;
421
422 case SCH_JUNCTION_T:
423 saveJunction( static_cast<SCH_JUNCTION*>( item ), 1 );
424 break;
425
426 case SCH_NO_CONNECT_T:
427 saveNoConnect( static_cast<SCH_NO_CONNECT*>( item ), 1 );
428 break;
429
432 saveBusEntry( static_cast<SCH_BUS_ENTRY_BASE*>( item ), 1 );
433 break;
434
435 case SCH_LINE_T:
436 if( layer != item->GetLayer() )
437 {
438 if( layer == SCH_LAYER_ID_START )
439 {
440 layer = item->GetLayer();
441 }
442 else
443 {
444 layer = item->GetLayer();
445 m_out->Print( 0, "\n" );
446 }
447 }
448
449 saveLine( static_cast<SCH_LINE*>( item ), 1 );
450 break;
451
452 case SCH_SHAPE_T:
453 saveShape( static_cast<SCH_SHAPE*>( item ), 1 );
454 break;
455
456 case SCH_TEXT_T:
457 case SCH_LABEL_T:
459 case SCH_HIER_LABEL_T:
461 saveText( static_cast<SCH_TEXT*>( item ), 1 );
462 break;
463
464 case SCH_TEXTBOX_T:
465 saveTextBox( static_cast<SCH_TEXTBOX*>( item ), 1 );
466 break;
467
468 default:
469 wxASSERT( "Unexpected schematic object type in SCH_SEXPR_PLUGIN::Format()" );
470 }
471 }
472
473 // If this is the root sheet, save all of the sheet paths.
474 if( aSheet->IsRootSheet() )
475 {
476 SCH_SHEET_LIST sheetPaths( aSheet, true );
477
478 SCH_REFERENCE_LIST symbolInstances;
479
480 for( const SCH_SHEET_PATH& sheetPath : sheetPaths )
481 sheetPath.GetSymbols( symbolInstances, true, true );
482
483 symbolInstances.SortByReferenceOnly();
484
485 saveInstances( sheetPaths.GetSheetInstances(), symbolInstances.GetSymbolInstances(), 1 );
486 }
487 else
488 {
489 // Schematic files (SCH_SCREEN objects) can be shared so we have to save and restore
490 // symbol and sheet instance data even if the file being saved is not the root sheet
491 // because it is possible that the file is the root sheet of another project.
492 saveInstances( screen->m_sheetInstances, screen->m_symbolInstances, 1 );
493 }
494
495 m_out->Print( 0, ")\n" );
496}
497
498
499void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelectionPath,
500 SCH_SHEET_LIST* aFullSheetHierarchy,
501 OUTPUTFORMATTER* aFormatter, bool aForClipboard )
502{
503 wxCHECK( aSelection && aSelectionPath && aFullSheetHierarchy && aFormatter, /* void */ );
504
505 LOCALE_IO toggle;
506
507 m_out = aFormatter;
508
509 size_t i;
510 SCH_ITEM* item;
511 std::map<wxString, LIB_SYMBOL*> libSymbols;
512 SCH_SCREEN* screen = aSelection->GetScreen();
513
514 for( i = 0; i < aSelection->GetSize(); ++i )
515 {
516 item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( i ) );
517
518 wxCHECK2( item, continue );
519
520 if( item->Type() != SCH_SYMBOL_T )
521 continue;
522
523 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
524
525 wxCHECK2( symbol, continue );
526
527 wxString libSymbolLookup = symbol->GetLibId().Format().wx_str();
528
529 if( !symbol->UseLibIdLookup() )
530 libSymbolLookup = symbol->GetSchSymbolLibraryName();
531
532 auto it = screen->GetLibSymbols().find( libSymbolLookup );
533
534 if( it != screen->GetLibSymbols().end() )
535 libSymbols[ libSymbolLookup ] = it->second;
536 }
537
538 if( !libSymbols.empty() )
539 {
540 m_out->Print( 0, "(lib_symbols\n" );
541
542 for( const std::pair<const wxString, LIB_SYMBOL*>& libSymbol : libSymbols )
543 SCH_SEXPR_PLUGIN_CACHE::SaveSymbol( libSymbol.second, *m_out, 1, libSymbol.first );
544
545 m_out->Print( 0, ")\n\n" );
546 }
547
548 // Store the selected sheets instance information
549 SCH_SHEET_LIST selectedSheets;
550 selectedSheets.push_back( *aSelectionPath ); // Include the "root" of the selection
551
552 SCH_REFERENCE_LIST selectedSymbols;
553
554 for( i = 0; i < aSelection->GetSize(); ++i )
555 {
556 item = (SCH_ITEM*) aSelection->GetItem( i );
557
558 switch( item->Type() )
559 {
560 case SCH_SYMBOL_T:
561 saveSymbol( static_cast<SCH_SYMBOL*>( item ), aSelectionPath, 0, aForClipboard );
562
563 aSelectionPath->AppendSymbol( selectedSymbols, static_cast<SCH_SYMBOL*>( item ),
564 true, true );
565 break;
566
567 case SCH_BITMAP_T:
568 saveBitmap( static_cast< SCH_BITMAP* >( item ), 0 );
569 break;
570
571 case SCH_SHEET_T:
572 saveSheet( static_cast< SCH_SHEET* >( item ), 0 );
573
574 {
575 SCH_SHEET_PATH subSheetPath = *aSelectionPath;
576 subSheetPath.push_back( static_cast<SCH_SHEET*>( item ) );
577
578 aFullSheetHierarchy->GetSheetsWithinPath( selectedSheets, subSheetPath );
579 aFullSheetHierarchy->GetSymbolsWithinPath( selectedSymbols, subSheetPath, true,
580 true );
581 }
582
583 break;
584
585 case SCH_JUNCTION_T:
586 saveJunction( static_cast< SCH_JUNCTION* >( item ), 0 );
587 break;
588
589 case SCH_NO_CONNECT_T:
590 saveNoConnect( static_cast< SCH_NO_CONNECT* >( item ), 0 );
591 break;
592
595 saveBusEntry( static_cast< SCH_BUS_ENTRY_BASE* >( item ), 0 );
596 break;
597
598 case SCH_LINE_T:
599 saveLine( static_cast< SCH_LINE* >( item ), 0 );
600 break;
601
602 case SCH_SHAPE_T:
603 saveShape( static_cast<SCH_SHAPE*>( item ), 0 );
604 break;
605
606 case SCH_TEXT_T:
607 case SCH_LABEL_T:
609 case SCH_HIER_LABEL_T:
611 saveText( static_cast<SCH_TEXT*>( item ), 0 );
612 break;
613
614 case SCH_TEXTBOX_T:
615 saveTextBox( static_cast<SCH_TEXTBOX*>( item ), 0 );
616 break;
617
618 default:
619 wxASSERT( "Unexpected schematic object type in SCH_SEXPR_PLUGIN::Format()" );
620 }
621 }
622
623 // Make all instance information relative to the selection path
624 KIID_PATH selectionPath = aSelectionPath->PathWithoutRootUuid();
625
626 selectedSheets.SortByPageNumbers();
627 std::vector<SCH_SHEET_INSTANCE> sheetinstances = selectedSheets.GetSheetInstances();
628
629 for( SCH_SHEET_INSTANCE& sheetInstance : sheetinstances )
630 {
631 wxASSERT_MSG( sheetInstance.m_Path.MakeRelativeTo( selectionPath ),
632 "Sheet is not inside the selection path?" );
633 }
634
635
636 selectedSymbols.SortByReferenceOnly();
637 std::vector<SYMBOL_INSTANCE_REFERENCE> symbolInstances = selectedSymbols.GetSymbolInstances();
638
639 for( SYMBOL_INSTANCE_REFERENCE& symbolInstance : symbolInstances )
640 {
641 wxASSERT_MSG( symbolInstance.m_Path.MakeRelativeTo( selectionPath ),
642 "Symbol is not inside the selection path?" );
643 }
644
645 saveInstances( sheetinstances, symbolInstances, 0 );
646}
647
648
650 int aNestLevel, bool aForClipboard )
651{
652 wxCHECK_RET( aSymbol != nullptr && m_out != nullptr, "" );
653
654 std::string libName;
655
656 wxString symbol_name = aSymbol->GetLibId().Format();
657
658 if( symbol_name.size() )
659 {
660 libName = toUTFTildaText( symbol_name );
661 }
662 else
663 {
664 libName = "_NONAME_";
665 }
666
668 int orientation = aSymbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
669
670 if( orientation == SYM_ORIENT_90 )
671 angle = ANGLE_90;
672 else if( orientation == SYM_ORIENT_180 )
674 else if( orientation == SYM_ORIENT_270 )
676 else
677 angle = ANGLE_0;
678
679 m_out->Print( aNestLevel, "(symbol" );
680
681 if( !aSymbol->UseLibIdLookup() )
682 {
683 m_out->Print( 0, " (lib_name %s)",
684 m_out->Quotew( aSymbol->GetSchSymbolLibraryName() ).c_str() );
685 }
686
687 m_out->Print( 0, " (lib_id %s) (at %s %s %s)",
688 m_out->Quotew( aSymbol->GetLibId().Format().wx_str() ).c_str(),
692
693 bool mirrorX = aSymbol->GetOrientation() & SYM_MIRROR_X;
694 bool mirrorY = aSymbol->GetOrientation() & SYM_MIRROR_Y;
695
696 if( mirrorX || mirrorY )
697 {
698 m_out->Print( 0, " (mirror" );
699
700 if( mirrorX )
701 m_out->Print( 0, " x" );
702
703 if( mirrorY )
704 m_out->Print( 0, " y" );
705
706 m_out->Print( 0, ")" );
707 }
708
709 // The symbol unit is always set to the first instance regardless of the current sheet
710 // instance to prevent file churn.
711 int unit = ( aSymbol->GetInstanceReferences().size() == 0 ) ?
712 aSymbol->GetUnit() :
713 aSymbol->GetInstanceReferences()[0].m_Unit;
714
715 m_out->Print( 0, " (unit %d)", unit );
716
717 if( aSymbol->GetConvert() == LIB_ITEM::LIB_CONVERT::DEMORGAN )
718 m_out->Print( 0, " (convert %d)", aSymbol->GetConvert() );
719
720 m_out->Print( 0, "\n" );
721
722 m_out->Print( aNestLevel + 1, "(in_bom %s)", ( aSymbol->GetIncludeInBom() ) ? "yes" : "no" );
723 m_out->Print( 0, " (on_board %s)", ( aSymbol->GetIncludeOnBoard() ) ? "yes" : "no" );
724 m_out->Print( 0, " (dnp %s)", ( aSymbol->GetDNP() ) ? "yes" : "no" );
725
726 if( aSymbol->GetFieldsAutoplaced() != FIELDS_AUTOPLACED_NO )
727 m_out->Print( 0, " (fields_autoplaced)" );
728
729 m_out->Print( 0, "\n" );
730
731 m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aSymbol->m_Uuid.AsString() ) );
732
733 // On the first save, if the default instance is not set, use the first instance data as
734 // the default.
735 if( aSymbol->GetDefaultInstance().m_Reference == wxEmptyString &&
736 aSymbol->GetDefaultInstance().m_Unit == -1 &&
737 aSymbol->GetDefaultInstance().m_Value == wxEmptyString &&
738 aSymbol->GetDefaultInstance().m_Footprint == wxEmptyString )
739 {
740 if( !aSymbol->GetInstanceReferences().empty() )
741 aSymbol->SetDefaultInstance( aSymbol->GetInstanceReferences()[0] );
742 }
743
744 m_out->Print( aNestLevel + 1,
745 "(default_instance (reference %s) (unit %d) (value %s) (footprint %s))\n",
746 m_out->Quotew( aSymbol->GetDefaultInstance().m_Reference ).c_str(),
747 aSymbol->GetDefaultInstance().m_Unit,
748 m_out->Quotew( aSymbol->GetDefaultInstance().m_Value ).c_str(),
749 m_out->Quotew( aSymbol->GetDefaultInstance().m_Footprint ).c_str() );
750
752
753 for( SCH_FIELD& field : aSymbol->GetFields() )
754 {
755 int id = field.GetId();
756 wxString value = field.GetText();
757
758 if( !aForClipboard )
759 {
760 // The instance fields are always set to the default instance regardless of the
761 // sheet instance to prevent file churn.
762 if( id == REFERENCE_FIELD )
763 {
764 field.SetText( aSymbol->GetDefaultInstance().m_Reference );
765 }
766 else if( id == VALUE_FIELD )
767 {
768 field.SetText( aSymbol->GetDefaultInstance().m_Value );
769 }
770 else if( id == FOOTPRINT_FIELD )
771 {
772 field.SetText( aSymbol->GetDefaultInstance().m_Footprint );
773 }
774 }
775
776 try
777 {
778 saveField( &field, aNestLevel + 1 );
779 }
780 catch( ... )
781 {
782 // Restore the changed field text on write error.
783 if( id == REFERENCE_FIELD || id == VALUE_FIELD || id == FOOTPRINT_FIELD )
784 field.SetText( value );
785
786 throw;
787 }
788
789 if( id == REFERENCE_FIELD || id == VALUE_FIELD || id == FOOTPRINT_FIELD )
790 field.SetText( value );
791 }
792
793 for( const std::unique_ptr<SCH_PIN>& pin : aSymbol->GetRawPins() )
794 {
795 if( pin->GetAlt().IsEmpty() )
796 {
797 m_out->Print( aNestLevel + 1, "(pin %s (uuid %s))\n",
798 m_out->Quotew( pin->GetNumber() ).c_str(),
799 TO_UTF8( pin->m_Uuid.AsString() ) );
800 }
801 else
802 {
803 m_out->Print( aNestLevel + 1, "(pin %s (uuid %s) (alternate %s))\n",
804 m_out->Quotew( pin->GetNumber() ).c_str(),
805 TO_UTF8( pin->m_Uuid.AsString() ),
806 m_out->Quotew( pin->GetAlt() ).c_str() );
807 }
808 }
809
810 m_out->Print( aNestLevel, ")\n" );
811}
812
813
814void SCH_SEXPR_PLUGIN::saveField( SCH_FIELD* aField, int aNestLevel )
815{
816 wxCHECK_RET( aField != nullptr && m_out != nullptr, "" );
817
818 wxString fieldName = aField->GetCanonicalName();
819
820 // For some reason (bug in legacy parser?) the field ID for non-mandatory fields is -1 so
821 // check for this in order to correctly use the field name.
822
823 if( aField->GetId() == -1 /* undefined ID */ )
824 {
825 aField->SetId( m_nextFreeFieldId );
827 }
828 else if( aField->GetId() >= m_nextFreeFieldId )
829 {
830 m_nextFreeFieldId = aField->GetId() + 1;
831 }
832
833 m_out->Print( aNestLevel, "(property %s %s (id %d) (at %s %s %s)",
834 m_out->Quotew( fieldName ).c_str(),
835 m_out->Quotew( aField->GetText() ).c_str(),
836 aField->GetId(),
839 EDA_UNIT_UTILS::FormatAngle( aField->GetTextAngle() ).c_str() );
840
841 if( aField->IsNameShown() )
842 m_out->Print( aNestLevel, " (show_name)" );
843
844 if( !aField->IsDefaultFormatting()
845 || ( aField->GetTextHeight() != schIUScale.MilsToIU( DEFAULT_SIZE_TEXT ) ) )
846 {
847 m_out->Print( 0, "\n" );
848 aField->Format( m_out, aNestLevel, 0 );
849 m_out->Print( aNestLevel, ")\n" ); // Closes property token with font effects.
850 }
851 else
852 {
853 m_out->Print( 0, ")\n" ); // Closes property token without font effects.
854 }
855}
856
857
858void SCH_SEXPR_PLUGIN::saveBitmap( SCH_BITMAP* aBitmap, int aNestLevel )
859{
860 wxCHECK_RET( aBitmap != nullptr && m_out != nullptr, "" );
861
862 const wxImage* image = aBitmap->GetImage()->GetImageData();
863
864 wxCHECK_RET( image != nullptr, "wxImage* is NULL" );
865
866 m_out->Print( aNestLevel, "(image (at %s %s)",
869
870 if( aBitmap->GetImage()->GetScale() != 1.0 )
871 m_out->Print( 0, " (scale %g)", aBitmap->GetImage()->GetScale() );
872
873 m_out->Print( 0, "\n" );
874
875 m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aBitmap->m_Uuid.AsString() ) );
876
877 m_out->Print( aNestLevel + 1, "(data" );
878
879 wxMemoryOutputStream stream;
880
881 image->SaveFile( stream, wxBITMAP_TYPE_PNG );
882
883 // Write binary data in hexadecimal form (ASCII)
884 wxStreamBuffer* buffer = stream.GetOutputStreamBuffer();
885 wxString out = wxBase64Encode( buffer->GetBufferStart(), buffer->GetBufferSize() );
886
887 // Apparently the MIME standard character width for base64 encoding is 76 (unconfirmed)
888 // so use it in a vein attempt to be standard like.
889#define MIME_BASE64_LENGTH 76
890
891 size_t first = 0;
892
893 while( first < out.Length() )
894 {
895 m_out->Print( 0, "\n" );
896 m_out->Print( aNestLevel + 2, "%s", TO_UTF8( out( first, MIME_BASE64_LENGTH ) ) );
897 first += MIME_BASE64_LENGTH;
898 }
899
900 m_out->Print( 0, "\n" );
901 m_out->Print( aNestLevel + 1, ")\n" ); // Closes data token.
902 m_out->Print( aNestLevel, ")\n" ); // Closes image token.
903}
904
905
906void SCH_SEXPR_PLUGIN::saveSheet( SCH_SHEET* aSheet, int aNestLevel )
907{
908 wxCHECK_RET( aSheet != nullptr && m_out != nullptr, "" );
909
910 m_out->Print( aNestLevel, "(sheet (at %s %s) (size %s %s)",
913 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aSheet->GetSize().GetWidth() ).c_str(),
914 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aSheet->GetSize().GetHeight() ).c_str() );
915
917 m_out->Print( 0, " (fields_autoplaced)" );
918
919 m_out->Print( 0, "\n" );
920
922 aSheet->GetBorderColor() );
923
924 stroke.SetWidth( aSheet->GetBorderWidth() );
925 stroke.Format( m_out, schIUScale, aNestLevel + 1 );
926
927 m_out->Print( 0, "\n" );
928
929 m_out->Print( aNestLevel + 1, "(fill (color %d %d %d %0.4f))\n",
930 KiROUND( aSheet->GetBackgroundColor().r * 255.0 ),
931 KiROUND( aSheet->GetBackgroundColor().g * 255.0 ),
932 KiROUND( aSheet->GetBackgroundColor().b * 255.0 ),
933 aSheet->GetBackgroundColor().a );
934
935 m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aSheet->m_Uuid.AsString() ) );
936
938
939 for( SCH_FIELD& field : aSheet->GetFields() )
940 {
941 saveField( &field, aNestLevel + 1 );
942 }
943
944 for( const SCH_SHEET_PIN* pin : aSheet->GetPins() )
945 {
946 m_out->Print( aNestLevel + 1, "(pin %s %s (at %s %s %s)\n",
947 EscapedUTF8( pin->GetText() ).c_str(),
948 getSheetPinShapeToken( pin->GetShape() ),
949 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pin->GetPosition().x ).c_str(),
950 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pin->GetPosition().y ).c_str(),
951 EDA_UNIT_UTILS::FormatAngle( getSheetPinAngle( pin->GetSide() ) ).c_str() );
952
953 pin->Format( m_out, aNestLevel + 1, 0 );
954
955 m_out->Print( aNestLevel + 2, "(uuid %s)\n", TO_UTF8( pin->m_Uuid.AsString() ) );
956
957 m_out->Print( aNestLevel + 1, ")\n" ); // Closes pin token.
958 }
959
960 m_out->Print( aNestLevel, ")\n" ); // Closes sheet token.
961}
962
963
964void SCH_SEXPR_PLUGIN::saveJunction( SCH_JUNCTION* aJunction, int aNestLevel )
965{
966 wxCHECK_RET( aJunction != nullptr && m_out != nullptr, "" );
967
968 m_out->Print( aNestLevel, "(junction (at %s %s) (diameter %s) (color %d %d %d %s)\n",
972 KiROUND( aJunction->GetColor().r * 255.0 ),
973 KiROUND( aJunction->GetColor().g * 255.0 ),
974 KiROUND( aJunction->GetColor().b * 255.0 ),
975 FormatDouble2Str( aJunction->GetColor().a ).c_str() );
976
977 m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aJunction->m_Uuid.AsString() ) );
978
979 m_out->Print( aNestLevel, ")\n" );
980}
981
982
983void SCH_SEXPR_PLUGIN::saveNoConnect( SCH_NO_CONNECT* aNoConnect, int aNestLevel )
984{
985 wxCHECK_RET( aNoConnect != nullptr && m_out != nullptr, "" );
986
987 m_out->Print( aNestLevel, "(no_connect (at %s %s) (uuid %s))\n",
990 TO_UTF8( aNoConnect->m_Uuid.AsString() ) );
991}
992
993
994void SCH_SEXPR_PLUGIN::saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLevel )
995{
996 wxCHECK_RET( aBusEntry != nullptr && m_out != nullptr, "" );
997
998 // Bus to bus entries are converted to bus line segments.
999 if( aBusEntry->GetClass() == "SCH_BUS_BUS_ENTRY" )
1000 {
1001 SCH_LINE busEntryLine( aBusEntry->GetPosition(), LAYER_BUS );
1002
1003 busEntryLine.SetEndPoint( aBusEntry->GetEnd() );
1004 saveLine( &busEntryLine, aNestLevel );
1005 }
1006 else
1007 {
1008 m_out->Print( aNestLevel, "(bus_entry (at %s %s) (size %s %s)\n",
1011 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aBusEntry->GetSize().GetWidth() ).c_str(),
1012 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aBusEntry->GetSize().GetHeight() ).c_str() );
1013
1014 aBusEntry->GetStroke().Format( m_out, schIUScale, aNestLevel + 1 );
1015
1016 m_out->Print( 0, "\n" );
1017
1018 m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aBusEntry->m_Uuid.AsString() ) );
1019
1020 m_out->Print( aNestLevel, ")\n" );
1021 }
1022}
1023
1024
1025void SCH_SEXPR_PLUGIN::saveShape( SCH_SHAPE* aShape, int aNestLevel )
1026{
1027 wxCHECK_RET( aShape != nullptr && m_out != nullptr, "" );
1028
1029 switch( aShape->GetShape() )
1030 {
1031 case SHAPE_T::ARC:
1032 formatArc( m_out, aNestLevel, aShape, false, aShape->GetStroke(), aShape->GetFillMode(),
1033 aShape->GetFillColor(), aShape->m_Uuid );
1034 break;
1035
1036 case SHAPE_T::CIRCLE:
1037 formatCircle( m_out, aNestLevel, aShape, false, aShape->GetStroke(), aShape->GetFillMode(),
1038 aShape->GetFillColor(), aShape->m_Uuid );
1039 break;
1040
1041 case SHAPE_T::RECT:
1042 formatRect( m_out, aNestLevel, aShape, false, aShape->GetStroke(), aShape->GetFillMode(),
1043 aShape->GetFillColor(), aShape->m_Uuid );
1044 break;
1045
1046 case SHAPE_T::BEZIER:
1047 formatBezier( m_out, aNestLevel, aShape, false, aShape->GetStroke(), aShape->GetFillMode(),
1048 aShape->GetFillColor(), aShape->m_Uuid );
1049 break;
1050
1051 case SHAPE_T::POLY:
1052 formatPoly( m_out, aNestLevel, aShape, false, aShape->GetStroke(), aShape->GetFillMode(),
1053 aShape->GetFillColor(), aShape->m_Uuid );
1054 break;
1055
1056 default:
1058 }
1059}
1060
1061
1062void SCH_SEXPR_PLUGIN::saveLine( SCH_LINE* aLine, int aNestLevel )
1063{
1064 wxCHECK_RET( aLine != nullptr && m_out != nullptr, "" );
1065
1066 wxString lineType;
1067
1068 STROKE_PARAMS line_stroke = aLine->GetStroke();
1069
1070 switch( aLine->GetLayer() )
1071 {
1072 case LAYER_BUS: lineType = "bus"; break;
1073 case LAYER_WIRE: lineType = "wire"; break;
1074 case LAYER_NOTES: lineType = "polyline"; break;
1075 default:
1076 UNIMPLEMENTED_FOR( LayerName( aLine->GetLayer() ) );
1077 }
1078
1079 m_out->Print( aNestLevel, "(%s (pts (xy %s %s) (xy %s %s))\n",
1080 TO_UTF8( lineType ),
1085
1086 line_stroke.Format( m_out, schIUScale, aNestLevel + 1 );
1087 m_out->Print( 0, "\n" );
1088
1089 m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aLine->m_Uuid.AsString() ) );
1090
1091 m_out->Print( aNestLevel, ")\n" );
1092}
1093
1094
1095void SCH_SEXPR_PLUGIN::saveText( SCH_TEXT* aText, int aNestLevel )
1096{
1097 wxCHECK_RET( aText != nullptr && m_out != nullptr, "" );
1098
1099 // Note: label is nullptr SCH_TEXT, but not for SCH_LABEL_XXX,
1100 SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( aText );
1101
1102 m_out->Print( aNestLevel, "(%s %s",
1103 getTextTypeToken( aText->Type() ),
1104 m_out->Quotew( aText->GetText() ).c_str() );
1105
1106 if( aText->Type() == SCH_DIRECTIVE_LABEL_T )
1107 {
1108 SCH_DIRECTIVE_LABEL* flag = static_cast<SCH_DIRECTIVE_LABEL*>( aText );
1109
1110 m_out->Print( 0, " (length %s)",
1111 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, flag->GetPinLength() ).c_str() );
1112 }
1113
1114 EDA_ANGLE angle = aText->GetTextAngle();
1115
1116 if( label )
1117 {
1118 if( aText->Type() == SCH_GLOBAL_LABEL_T
1119 || aText->Type() == SCH_HIER_LABEL_T
1120 || aText->Type() == SCH_DIRECTIVE_LABEL_T )
1121 {
1122 m_out->Print( 0, " (shape %s)", getSheetPinShapeToken( label->GetShape() ) );
1123 }
1124
1125 // The angle of the text is always 0 or 90 degrees for readibility reasons,
1126 // but the item itself can have more rotation (-90 and 180 deg)
1127 switch( aText->GetTextSpinStyle() )
1128 {
1129 default:
1130 case TEXT_SPIN_STYLE::LEFT: angle += ANGLE_180; break;
1131 case TEXT_SPIN_STYLE::UP: break;
1132 case TEXT_SPIN_STYLE::RIGHT: break;
1133 case TEXT_SPIN_STYLE::BOTTOM: angle += ANGLE_180; break;
1134 }
1135 }
1136
1137 if( aText->GetText().Length() < 50 )
1138 {
1139 m_out->Print( 0, " (at %s %s %s)",
1143 }
1144 else
1145 {
1146 m_out->Print( 0, "\n" );
1147 m_out->Print( aNestLevel + 1, "(at %s %s %s)",
1151 }
1152
1154 m_out->Print( 0, " (fields_autoplaced)" );
1155
1156 m_out->Print( 0, "\n" );
1157 aText->EDA_TEXT::Format( m_out, aNestLevel, 0 );
1158
1159 m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aText->m_Uuid.AsString() ) );
1160
1161 if( label )
1162 {
1163 for( SCH_FIELD& field : label->GetFields() )
1164 saveField( &field, aNestLevel + 1 );
1165 }
1166
1167 m_out->Print( aNestLevel, ")\n" ); // Closes text token.
1168}
1169
1170
1171void SCH_SEXPR_PLUGIN::saveTextBox( SCH_TEXTBOX* aTextBox, int aNestLevel )
1172{
1173 wxCHECK_RET( aTextBox != nullptr && m_out != nullptr, "" );
1174
1175 m_out->Print( aNestLevel, "(text_box %s\n",
1176 m_out->Quotew( aTextBox->GetText() ).c_str() );
1177
1178 VECTOR2I pos = aTextBox->GetStart();
1179 VECTOR2I size = aTextBox->GetEnd() - pos;
1180
1181 m_out->Print( aNestLevel + 1, "(at %s %s %s) (size %s %s)\n",
1184 EDA_UNIT_UTILS::FormatAngle( aTextBox->GetTextAngle() ).c_str(),
1187
1188 aTextBox->GetStroke().Format( m_out, schIUScale, aNestLevel + 1 );
1189 m_out->Print( 0, "\n" );
1190 formatFill( m_out, aNestLevel + 1, aTextBox->GetFillMode(), aTextBox->GetFillColor() );
1191 m_out->Print( 0, "\n" );
1192
1193 aTextBox->EDA_TEXT::Format( m_out, aNestLevel, 0 );
1194
1195 if( aTextBox->m_Uuid != niluuid )
1196 m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aTextBox->m_Uuid.AsString() ) );
1197
1198 m_out->Print( aNestLevel, ")\n" );
1199}
1200
1201
1202void SCH_SEXPR_PLUGIN::saveBusAlias( std::shared_ptr<BUS_ALIAS> aAlias, int aNestLevel )
1203{
1204 wxCHECK_RET( aAlias != nullptr, "BUS_ALIAS* is NULL" );
1205
1206 m_out->Print( aNestLevel, "(bus_alias %s (members %s))\n",
1207 m_out->Quotew( aAlias->GetName() ).c_str(),
1208 TO_UTF8( boost::algorithm::join( aAlias->Members(), " " ) ) );
1209}
1210
1211
1212void SCH_SEXPR_PLUGIN::saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aSheets,
1213 const std::vector<SYMBOL_INSTANCE_REFERENCE>& aSymbols,
1214 int aNestLevel )
1215{
1216 if( aSheets.size() )
1217 {
1218 m_out->Print( 0, "\n" );
1219 m_out->Print( aNestLevel, "(sheet_instances\n" );
1220
1221 for( const SCH_SHEET_INSTANCE& instance : aSheets )
1222 {
1223 wxString path = instance.m_Path.AsString();
1224
1225 if( path.IsEmpty() )
1226 path = wxT( "/" ); // Root path
1227
1228 m_out->Print( aNestLevel + 1, "(path %s (page %s))\n",
1229 m_out->Quotew( path ).c_str(),
1230 m_out->Quotew( instance.m_PageNumber ).c_str() );
1231 }
1232
1233 m_out->Print( aNestLevel, ")\n" ); // Close sheet instances token.
1234 }
1235
1236 if( aSymbols.size() )
1237 {
1238 m_out->Print( 0, "\n" );
1239 m_out->Print( aNestLevel, "(symbol_instances\n" );
1240
1241 for( const SYMBOL_INSTANCE_REFERENCE& instance : aSymbols )
1242 {
1243 m_out->Print( aNestLevel + 1, "(path %s\n",
1244 m_out->Quotew( instance.m_Path.AsString() ).c_str() );
1245 m_out->Print( aNestLevel + 2, "(reference %s) (unit %d) (value %s) (footprint %s)\n",
1246 m_out->Quotew( instance.m_Reference ).c_str(),
1247 instance.m_Unit,
1248 m_out->Quotew( instance.m_Value ).c_str(),
1249 m_out->Quotew( instance.m_Footprint ).c_str() );
1250 m_out->Print( aNestLevel + 1, ")\n" );
1251 }
1252
1253 m_out->Print( aNestLevel, ")\n" ); // Close symbol instances token.
1254 }
1255}
1256
1257
1258void SCH_SEXPR_PLUGIN::cacheLib( const wxString& aLibraryFileName, const PROPERTIES* aProperties )
1259{
1260 if( !m_cache || !m_cache->IsFile( aLibraryFileName ) || m_cache->IsFileChanged() )
1261 {
1262 // a spectacular episode in memory management:
1263 delete m_cache;
1264 m_cache = new SCH_SEXPR_PLUGIN_CACHE( aLibraryFileName );
1265
1266 if( !isBuffering( aProperties ) )
1267 m_cache->Load();
1268 }
1269}
1270
1271
1273{
1274 return ( aProperties && aProperties->Exists( SCH_SEXPR_PLUGIN::PropBuffering ) );
1275}
1276
1277
1279{
1280 if( m_cache )
1281 return m_cache->GetModifyHash();
1282
1283 // If the cache hasn't been loaded, it hasn't been modified.
1284 return 0;
1285}
1286
1287
1288void SCH_SEXPR_PLUGIN::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
1289 const wxString& aLibraryPath,
1290 const PROPERTIES* aProperties )
1291{
1292 LOCALE_IO toggle; // toggles on, then off, the C locale.
1293
1294 bool powerSymbolsOnly = ( aProperties &&
1295 aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
1296
1297 cacheLib( aLibraryPath, aProperties );
1298
1299 const LIB_SYMBOL_MAP& symbols = m_cache->m_symbols;
1300
1301 for( LIB_SYMBOL_MAP::const_iterator it = symbols.begin(); it != symbols.end(); ++it )
1302 {
1303 if( !powerSymbolsOnly || it->second->IsPower() )
1304 aSymbolNameList.Add( it->first );
1305 }
1306}
1307
1308
1309void SCH_SEXPR_PLUGIN::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
1310 const wxString& aLibraryPath,
1311 const PROPERTIES* aProperties )
1312{
1313 LOCALE_IO toggle; // toggles on, then off, the C locale.
1314
1315 bool powerSymbolsOnly = ( aProperties &&
1316 aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
1317
1318 cacheLib( aLibraryPath, aProperties );
1319
1320 const LIB_SYMBOL_MAP& symbols = m_cache->m_symbols;
1321
1322 for( LIB_SYMBOL_MAP::const_iterator it = symbols.begin(); it != symbols.end(); ++it )
1323 {
1324 if( !powerSymbolsOnly || it->second->IsPower() )
1325 aSymbolList.push_back( it->second );
1326 }
1327}
1328
1329
1330LIB_SYMBOL* SCH_SEXPR_PLUGIN::LoadSymbol( const wxString& aLibraryPath, const wxString& aSymbolName,
1331 const PROPERTIES* aProperties )
1332{
1333 LOCALE_IO toggle; // toggles on, then off, the C locale.
1334
1335 cacheLib( aLibraryPath, aProperties );
1336
1337 LIB_SYMBOL_MAP::const_iterator it = m_cache->m_symbols.find( aSymbolName );
1338
1339 if( it == m_cache->m_symbols.end() )
1340 return nullptr;
1341
1342 return it->second;
1343}
1344
1345
1346void SCH_SEXPR_PLUGIN::SaveSymbol( const wxString& aLibraryPath, const LIB_SYMBOL* aSymbol,
1347 const PROPERTIES* aProperties )
1348{
1349 LOCALE_IO toggle; // toggles on, then off, the C locale.
1350
1351 cacheLib( aLibraryPath, aProperties );
1352
1353 m_cache->AddSymbol( aSymbol );
1354
1355 if( !isBuffering( aProperties ) )
1356 m_cache->Save();
1357}
1358
1359
1360void SCH_SEXPR_PLUGIN::DeleteSymbol( const wxString& aLibraryPath, const wxString& aSymbolName,
1361 const PROPERTIES* aProperties )
1362{
1363 LOCALE_IO toggle; // toggles on, then off, the C locale.
1364
1365 cacheLib( aLibraryPath, aProperties );
1366
1367 m_cache->DeleteSymbol( aSymbolName );
1368
1369 if( !isBuffering( aProperties ) )
1370 m_cache->Save();
1371}
1372
1373
1374void SCH_SEXPR_PLUGIN::CreateSymbolLib( const wxString& aLibraryPath,
1375 const PROPERTIES* aProperties )
1376{
1377 if( wxFileExists( aLibraryPath ) )
1378 {
1379 THROW_IO_ERROR( wxString::Format( _( "Symbol library '%s' already exists." ),
1380 aLibraryPath.GetData() ) );
1381 }
1382
1383 LOCALE_IO toggle;
1384
1385 delete m_cache;
1386 m_cache = new SCH_SEXPR_PLUGIN_CACHE( aLibraryPath );
1388 m_cache->Save();
1389 m_cache->Load(); // update m_writable and m_mod_time
1390}
1391
1392
1393bool SCH_SEXPR_PLUGIN::DeleteSymbolLib( const wxString& aLibraryPath,
1394 const PROPERTIES* aProperties )
1395{
1396 wxFileName fn = aLibraryPath;
1397
1398 if( !fn.FileExists() )
1399 return false;
1400
1401 // Some of the more elaborate wxRemoveFile() crap puts up its own wxLog dialog
1402 // we don't want that. we want bare metal portability with no UI here.
1403 if( wxRemove( aLibraryPath ) )
1404 {
1405 THROW_IO_ERROR( wxString::Format( _( "Symbol library '%s' cannot be deleted." ),
1406 aLibraryPath.GetData() ) );
1407 }
1408
1409 if( m_cache && m_cache->IsFile( aLibraryPath ) )
1410 {
1411 delete m_cache;
1412 m_cache = nullptr;
1413 }
1414
1415 return true;
1416}
1417
1418
1419void SCH_SEXPR_PLUGIN::SaveLibrary( const wxString& aLibraryPath, const PROPERTIES* aProperties )
1420{
1421 if( !m_cache )
1422 m_cache = new SCH_SEXPR_PLUGIN_CACHE( aLibraryPath );
1423
1424 wxString oldFileName = m_cache->GetFileName();
1425
1426 if( !m_cache->IsFile( aLibraryPath ) )
1427 {
1428 m_cache->SetFileName( aLibraryPath );
1429 }
1430
1431 // This is a forced save.
1433 m_cache->Save();
1434 m_cache->SetFileName( oldFileName );
1435}
1436
1437
1438bool SCH_SEXPR_PLUGIN::CheckHeader( const wxString& aFileName )
1439{
1440 // Open file and check first line
1441 wxTextFile tempFile;
1442
1443 tempFile.Open( aFileName );
1444 wxString firstline;
1445 // read the first line
1446 firstline = tempFile.GetFirstLine();
1447 tempFile.Close();
1448
1449 return firstline.StartsWith( "EESchema" );
1450}
1451
1452
1453bool SCH_SEXPR_PLUGIN::IsSymbolLibWritable( const wxString& aLibraryPath )
1454{
1455 wxFileName fn( aLibraryPath );
1456
1457 return ( fn.FileExists() && fn.IsFileWritable() ) || fn.IsDirWritable();
1458}
1459
1460
1461void SCH_SEXPR_PLUGIN::GetAvailableSymbolFields( std::vector<wxString>& aNames )
1462{
1463 if( !m_cache )
1464 return;
1465
1466 const LIB_SYMBOL_MAP& symbols = m_cache->m_symbols;
1467
1468 std::set<wxString> fieldNames;
1469
1470 for( LIB_SYMBOL_MAP::const_iterator it = symbols.begin(); it != symbols.end(); ++it )
1471 {
1472 std::vector<LIB_FIELD*> fields;
1473 it->second->GetFields( fields );
1474
1475 for( LIB_FIELD* field : fields )
1476 {
1477 if( field->IsMandatory() )
1478 continue;
1479
1480 // TODO(JE): enable configurability of this outside database libraries?
1481 // if( field->ShowInChooser() )
1482 fieldNames.insert( field->GetName() );
1483 }
1484 }
1485
1486 std::copy( fieldNames.begin(), fieldNames.end(), std::back_inserter( aNames ) );
1487}
1488
1489
1490void SCH_SEXPR_PLUGIN::GetDefaultSymbolFields( std::vector<wxString>& aNames )
1491{
1492 GetAvailableSymbolFields( aNames );
1493}
1494
1495
1497{
1498 LOCALE_IO toggle; // toggles on, then off, the C locale.
1499 LIB_SYMBOL_MAP map;
1500 SCH_SEXPR_PARSER parser( &aReader );
1501
1502 parser.NeedLEFT();
1503 parser.NextTok();
1504
1505 return parser.ParseSymbol( map, aFileVersion );
1506}
1507
1508
1510{
1511
1512 LOCALE_IO toggle; // toggles on, then off, the C locale.
1513 SCH_SEXPR_PLUGIN_CACHE::SaveSymbol( symbol, formatter );
1514}
1515
1516
1517const char* SCH_SEXPR_PLUGIN::PropBuffering = "buffering";
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
double GetScale() const
Definition: bitmap_base.h:78
wxImage * GetImageData()
Definition: bitmap_base.h:69
const KIID m_Uuid
Definition: eda_item.h:492
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
FILL_T GetFillMode() const
Definition: eda_shape.h:101
SHAPE_T GetShape() const
Definition: eda_shape.h:111
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:141
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:116
COLOR4D GetFillColor() const
Definition: eda_shape.h:103
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:75
int GetTextHeight() const
Definition: eda_text.h:192
bool IsDefaultFormatting() const
Definition: eda_text.cpp:760
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:117
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
virtual void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Output the object to aFormatter in s-expression form.
Definition: eda_text.cpp:775
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
SCH_SCREEN * GetScreen()
Definition: ee_selection.h:52
A LINE_READER that reads from an open file.
Definition: richio.h:173
void Rewind()
Rewind the file and resets the line number back to zero.
Definition: richio.h:222
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
Definition: richio.cpp:219
Used for text file output.
Definition: richio.h:457
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
double r
Red component.
Definition: color4d.h:384
double g
Green component.
Definition: color4d.h:385
double a
Alpha component.
Definition: color4d.h:387
double b
Blue component.
Definition: color4d.h:386
wxString AsString() const
Definition: kiid.cpp:249
Field object used in symbol libraries.
Definition: lib_field.h:60
UTF8 Format() const
Definition: lib_id.cpp:117
Define a library symbol object.
Definition: lib_symbol.h:98
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
Definition: richio.h:81
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:41
An interface used to output 8 bit text in a convenient way.
Definition: richio.h:310
std::string Quotew(const wxString &aWrapee) const
Definition: richio.cpp:499
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:431
void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Output the page class to aFormatter in s-expression form.
Definition: page_info.cpp:272
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:125
A name/value tuple with unique names and optional values.
Definition: properties.h:34
bool Exists(const std::string &aProperty) const
Definition: properties.h:41
Holds all the data relating to one schematic.
Definition: schematic.h:60
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:106
SCH_SHEET & Root() const
Definition: schematic.h:90
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:75
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:41
VECTOR2I GetPosition() const override
Definition: sch_bitmap.h:136
BITMAP_BASE * GetImage() const
Definition: sch_bitmap.h:54
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:38
VECTOR2I GetPosition() const override
virtual STROKE_PARAMS GetStroke() const override
Definition: sch_bus_entry.h:77
VECTOR2I GetEnd() const
wxSize GetSize() const
Definition: sch_bus_entry.h:71
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:50
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1052
bool IsNameShown() const
Definition: sch_field.h:149
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: sch_field.cpp:843
int GetId() const
Definition: sch_field.h:116
void SetId(int aId)
Definition: sch_field.cpp:132
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
virtual wxString GetClass() const override
Return the class name.
Definition: sch_item.h:157
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:246
FIELDS_AUTOPLACED GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition: sch_item.h:415
COLOR4D GetColor() const
Definition: sch_junction.h:114
int GetDiameter() const
Definition: sch_junction.h:109
VECTOR2I GetPosition() const override
Definition: sch_junction.h:102
LABEL_FLAG_SHAPE GetShape() const override
Definition: sch_label.h:73
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:90
bool IsFile(const wxString &aFullPathAndFileName) const
wxString GetFileName() const
void SetFileName(const wxString &aFileName)
virtual void AddSymbol(const LIB_SYMBOL *aSymbol)
void SetModified(bool aModified=true)
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
virtual STROKE_PARAMS GetStroke() const override
Definition: sch_line.h:170
VECTOR2I GetEndPoint() const
Definition: sch_line.h:137
VECTOR2I GetStartPoint() const
Definition: sch_line.h:132
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:138
VECTOR2I GetPosition() const override
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
std::vector< SYMBOL_INSTANCE_REFERENCE > GetSymbolInstances() const
void SortByReferenceOnly()
Sort the list of references by reference.
const PAGE_INFO & GetPageSettings() const
Definition: sch_screen.h:130
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
Definition: sch_screen.h:591
std::map< wxString, LIB_SYMBOL * > & GetLibSymbols()
Fetch a list of unique LIB_SYMBOL object pointers required to properly render each SCH_SYMBOL in this...
Definition: sch_screen.h:453
std::vector< SYMBOL_INSTANCE_REFERENCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
Definition: sch_screen.h:590
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
const wxString & GetFileName() const
Definition: sch_screen.h:143
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:104
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:154
KIID m_uuid
A unique identifier for each schematic file.
Definition: sch_screen.h:599
void SetFileReadOnly(bool aIsReadOnly)
Definition: sch_screen.h:145
std::set< std::shared_ptr< BUS_ALIAS > > GetBusAliases() const
Return a list of bus aliases defined in this screen.
Definition: sch_screen.h:483
void SetFileExists(bool aFileExists)
Definition: sch_screen.h:148
Object to parser s-expression symbol library and schematic file formats.
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
A cache assistant for the KiCad s-expression symbol libraries.
static void SaveSymbol(LIB_SYMBOL *aSymbol, OUTPUTFORMATTER &aFormatter, int aNestLevel=0, const wxString &aLibName=wxEmptyString)
void Save(const std::optional< bool > &aOpt=std::nullopt) override
Save the entire library to file m_libFileName;.
void DeleteSymbol(const wxString &aName) override
wxString m_error
For throwing exceptions or errors on partial loads.
void saveBusAlias(std::shared_ptr< BUS_ALIAS > aAlias, int aNestLevel)
void GetDefaultSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that should be shown by default for this library in the symb...
void Save(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const PROPERTIES *aProperties=nullptr) override
Write aSchematic to a storage file in a format that this SCH_PLUGIN implementation knows about,...
void SaveSymbol(const wxString &aLibraryPath, const LIB_SYMBOL *aSymbol, const PROPERTIES *aProperties=nullptr) override
Write aSymbol to an existing library located at aLibraryPath.
void init(SCHEMATIC *aSchematic, const PROPERTIES *aProperties=nullptr)
initialize PLUGIN like a constructor would.
wxString m_path
Root project path for loading child sheets.
void saveField(SCH_FIELD *aField, int aNestLevel)
void saveTextBox(SCH_TEXTBOX *aText, int aNestLevel)
SCHEMATIC * m_schematic
OUTPUTFORMATTER * m_out
The formatter for saving SCH_SCREEN objects.
void Format(SCH_SHEET *aSheet)
bool DeleteSymbolLib(const wxString &aLibraryPath, const PROPERTIES *aProperties=nullptr) override
Delete an existing symbol library and returns true if successful, or if library does not exist return...
static void FormatLibSymbol(LIB_SYMBOL *aPart, OUTPUTFORMATTER &aFormatter)
void saveInstances(const std::vector< SCH_SHEET_INSTANCE > &aSheets, const std::vector< SYMBOL_INSTANCE_REFERENCE > &aSymbols, int aNestLevel)
void GetAvailableSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that are present on symbols in this library.
std::stack< wxString > m_currentPath
Stack to maintain nested sheet paths.
void loadFile(const wxString &aFileName, SCH_SHEET *aSheet)
void saveLine(SCH_LINE *aLine, int aNestLevel)
virtual ~SCH_SEXPR_PLUGIN()
void SaveLibrary(const wxString &aLibraryPath, const PROPERTIES *aProperties=nullptr) override
bool isBuffering(const PROPERTIES *aProperties)
SCH_SHEET * m_rootSheet
The root sheet of the schematic being loaded.
void saveText(SCH_TEXT *aText, int aNestLevel)
static LIB_SYMBOL * ParseLibSymbol(LINE_READER &aReader, int aVersion=SEXPR_SCHEMATIC_FILE_VERSION)
void DeleteSymbol(const wxString &aLibraryPath, const wxString &aSymbolName, const PROPERTIES *aProperties=nullptr) override
Delete the entire LIB_SYMBOL associated with aAliasName from the library aLibraryPath.
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const PROPERTIES *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
void saveSheet(SCH_SHEET *aSheet, int aNestLevel)
SCH_SEXPR_PLUGIN_CACHE * m_cache
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const PROPERTIES *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
void CreateSymbolLib(const wxString &aLibraryPath, const PROPERTIES *aProperties=nullptr) override
Create a new empty symbol library at aLibraryPath.
void LoadContent(LINE_READER &aReader, SCH_SHEET *aSheet, int aVersion=SEXPR_SCHEMATIC_FILE_VERSION)
bool IsSymbolLibWritable(const wxString &aLibraryPath) override
Return true if the library at aLibraryPath is writable.
void loadHierarchy(const SCH_SHEET_PATH &aParentSheetPath, SCH_SHEET *aSheet)
PROGRESS_REPORTER * m_progressReporter
void saveSymbol(SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aSheetPath, int aNestLevel, bool aForClipboard)
static const char * PropBuffering
The property used internally by the plugin to enable cache buffering which prevents the library file ...
void saveShape(SCH_SHAPE *aShape, int aNestLevel)
void cacheLib(const wxString &aLibraryFileName, const PROPERTIES *aProperties)
void saveBitmap(SCH_BITMAP *aBitmap, int aNestLevel)
bool CheckHeader(const wxString &aFileName) override
Return true if the first line in aFileName begins with the expected header.
void saveBusEntry(SCH_BUS_ENTRY_BASE *aBusEntry, int aNestLevel)
int m_version
Version of file being loaded.
int GetModifyHash() const override
Return the modification hash from the library cache.
void saveNoConnect(SCH_NO_CONNECT *aNoConnect, int aNestLevel)
void saveJunction(SCH_JUNCTION *aJunction, int aNestLevel)
SCH_SHEET * Load(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const PROPERTIES *aProperties=nullptr) override
Load information from some input file format that this SCH_PLUGIN implementation knows about,...
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:64
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
std::vector< SCH_SHEET_INSTANCE > GetSheetInstances() const
Fetch the instance information for all of the sheets in the hiearchy.
void GetSymbolsWithinPath(SCH_REFERENCE_LIST &aReferences, const SCH_SHEET_PATH &aSheetPath, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets that are contained wi...
void GetSheetsWithinPath(SCH_SHEET_PATHS &aSheets, const SCH_SHEET_PATH &aSheetPath) const
Add a SCH_SHEET_PATH object to aSheets for each sheet in the list that are contained within aSheetPat...
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
KIID_PATH PathWithoutRootUuid() const
Get the sheet path as an KIID_PATH without the root sheet UUID prefix.
bool empty() const
Forwarded method from std::vector.
SCH_SCREEN * LastScreen()
void AppendSymbol(SCH_REFERENCE_LIST &aReferences, SCH_SYMBOL *aSymbol, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Append a SCH_REFERENCE object to aReferences based on aSymbol.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
void pop_back()
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:55
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:299
bool IsRootSheet() const
Definition: sch_sheet.cpp:193
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:91
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:706
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:365
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:161
wxSize GetSize() const
Definition: sch_sheet.h:105
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:111
int GetBorderWidth() const
Definition: sch_sheet.h:108
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:172
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:114
Schematic symbol object.
Definition: sch_symbol.h:79
const std::vector< SYMBOL_INSTANCE_REFERENCE > & GetInstanceReferences()
Definition: sch_symbol.h:138
std::vector< std::unique_ptr< SCH_PIN > > & GetRawPins()
Definition: sch_symbol.h:531
int GetUnit() const
Definition: sch_symbol.h:225
bool UseLibIdLookup() const
Definition: sch_symbol.h:187
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:296
bool GetIncludeOnBoard() const
Definition: sch_symbol.h:736
bool GetIncludeInBom() const
Definition: sch_symbol.h:733
const SYMBOL_INSTANCE_REFERENCE & GetDefaultInstance() const
Definition: sch_symbol.h:148
int GetConvert() const
Definition: sch_symbol.h:267
void SetDefaultInstance(const SYMBOL_INSTANCE_REFERENCE &aInstance)
Definition: sch_symbol.h:143
VECTOR2I GetPosition() const override
Definition: sch_symbol.h:707
int GetOrientation() const
Get the display symbol orientation.
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:172
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:812
bool GetDNP() const
Definition: sch_symbol.h:739
VECTOR2I GetPosition() const override
Definition: sch_text.h:205
TEXT_SPIN_STYLE GetTextSpinStyle() const
Definition: sch_text.h:148
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:65
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:97
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
void SetWidth(int aWidth)
Definition: stroke_params.h:99
void Format(OUTPUTFORMATTER *out, const EDA_IU_SCALE &aIuScale, int nestLevel) const
static const char * PropPowerSymsOnly
virtual void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Output the object to aFormatter in s-expression form.
Definition: title_block.cpp:30
wxString wx_str() const
Definition: utf8.cpp:46
#define _(s)
static constexpr EDA_ANGLE & ANGLE_180
Definition: eda_angle.h:416
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:414
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:412
static constexpr EDA_ANGLE & ANGLE_270
Definition: eda_angle.h:417
#define DEFAULT_SIZE_TEXT
This is the "default-of-the-default" hardcoded text size; individual application define their own def...
Definition: eda_text.h:61
const wxChar *const traceSchLegacyPlugin
Flag to enable legacy schematic plugin debug output.
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
KIID niluuid(0)
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
Definition: layer_id.cpp:30
SCH_LAYER_ID
Eeschema drawing layers.
Definition: layer_ids.h:341
@ LAYER_WIRE
Definition: layer_ids.h:344
@ LAYER_NOTES
Definition: layer_ids.h:358
@ LAYER_BUS
Definition: layer_ids.h:345
@ SCH_LAYER_ID_START
Definition: layer_ids.h:342
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:120
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
std::string FormatInternalUnits(const EDA_IU_SCALE &aIuScale, int aValue)
Converts aValue from internal units to a string appropriate for writing to file.
Definition: eda_units.cpp:143
std::string FormatAngle(const EDA_ANGLE &aAngle)
Converts aAngle from board units to a string appropriate for writing to file.
Definition: eda_units.cpp:135
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
@ SYM_ORIENT_270
@ SYM_MIRROR_Y
@ SYM_ORIENT_180
@ SYM_MIRROR_X
@ SYM_ORIENT_90
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
@ FIELDS_AUTOPLACED_NO
Definition: sch_item.h:56
Schematic and symbol library s-expression file format parser definitions.
#define MIME_BASE64_LENGTH
void formatCircle(OUTPUTFORMATTER *aFormatter, int aNestLevel, EDA_SHAPE *aCircle, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, const KIID &aUuid)
void formatArc(OUTPUTFORMATTER *aFormatter, int aNestLevel, EDA_SHAPE *aArc, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, const KIID &aUuid)
const char * getSheetPinShapeToken(LABEL_FLAG_SHAPE aShape)
void formatFill(OUTPUTFORMATTER *aFormatter, int aNestLevel, FILL_T aFillMode, const COLOR4D &aFillColor)
Fill token formatting helper.
const char * getTextTypeToken(KICAD_T aType)
void formatRect(OUTPUTFORMATTER *aFormatter, int aNestLevel, EDA_SHAPE *aRect, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, const KIID &aUuid)
void formatBezier(OUTPUTFORMATTER *aFormatter, int aNestLevel, EDA_SHAPE *aBezier, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, const KIID &aUuid)
void formatPoly(OUTPUTFORMATTER *aFormatter, int aNestLevel, EDA_SHAPE *aPolyLine, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, const KIID &aUuid)
EDA_ANGLE getSheetPinAngle(SHEET_SIDE aSide)
@ SHEET_MANDATORY_FIELDS
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
Definition: sch_sheet.h:47
std::string toUTFTildaText(const wxString &txt)
Convert a wxString to UTF8 and replace any control characters with a ~, where a control character is ...
Definition: sch_symbol.cpp:47
std::string FormatDouble2Str(double aValue)
Print a float number without using scientific notation and no trailing 0 This function is intended in...
std::string EscapedUTF8(const wxString &aString)
Return an 8 bit UTF8 string given aString in Unicode form.
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
wxLogTrace helper definitions.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_LINE_T
Definition: typeinfo.h:145
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:142
@ TYPE_NOT_INIT
Definition: typeinfo.h:81
@ SCH_SYMBOL_T
Definition: typeinfo.h:155
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:153
@ SCH_LABEL_T
Definition: typeinfo.h:150
@ SCH_SHEET_T
Definition: typeinfo.h:157
@ SCH_SHAPE_T
Definition: typeinfo.h:146
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:152
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:144
@ SCH_TEXT_T
Definition: typeinfo.h:149
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:143
@ SCH_BITMAP_T
Definition: typeinfo.h:147
@ SCH_TEXTBOX_T
Definition: typeinfo.h:148
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:151
@ SCH_JUNCTION_T
Definition: typeinfo.h:141
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:80