KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_screen.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) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
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
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <stack>
28#include <wx/filefn.h>
29#include <wx/log.h>
30
31#include <eda_item.h>
32#include <id.h>
33#include <string_utils.h>
34#include <kiway.h>
35#include <plotters/plotter.h>
36#include <sch_plotter.h>
37#include <project.h>
38#include <project_sch.h>
39#include <reporter.h>
40#include <trace_helpers.h>
41#include <sch_edit_frame.h>
42#include <sch_item.h>
43
44#include <symbol_library.h>
45#include <connection_graph.h>
46#include <junction_helpers.h>
47#include <sch_pin.h>
48#include <sch_symbol.h>
49#include <sch_group.h>
50#include <sch_junction.h>
51#include <sch_line.h>
52#include <sch_marker.h>
53#include <sch_sheet.h>
54#include <sch_sheet_pin.h>
55#include <sch_text.h>
56#include <schematic.h>
58#include <symbol_lib_table.h>
59#include <tool/common_tools.h>
60#include <sim/sim_model.h> // For V6 to V7 simulation model migration.
61#include <locale_io.h>
62
63#include <algorithm>
64#include <math/vector3.h>
65#include <memory>
66
67// TODO(JE) Debugging only
68#include <core/profile.h>
69#include "sch_bus_entry.h"
70#include "sch_shape.h"
71
77static const wxChar DanglingProfileMask[] = wxT( "DANGLING_PROFILE" );
78
79
81 BASE_SCREEN( aParent, SCH_SCREEN_T ),
84 m_isReadOnly( false ),
85 m_fileExists( false )
86{
88 m_refCount = 0;
89 m_zoomInitialized = false;
90 m_LastZoomLevel = 1.0;
91
92 // Suitable for schematic only. For symbol_editor and viewlib, must be set to true
93 m_Center = false;
94
95 InitDataPoints( m_paper.GetSizeIU( schIUScale.IU_PER_MILS ) );
96}
97
98
104
105
107{
108 wxCHECK_MSG( GetParent() && GetParent()->Type() == SCHEMATIC_T, nullptr,
109 wxT( "SCH_SCREEN must have a SCHEMATIC parent!" ) );
110
111 return static_cast<SCHEMATIC*>( GetParent() );
112}
113
114
116{
117 for( const std::pair<const wxString, LIB_SYMBOL*>& libSymbol : m_libSymbols )
118 delete libSymbol.second;
119
120 m_libSymbols.clear();
121}
122
123
124void SCH_SCREEN::SetFileName( const wxString& aFileName )
125{
126 // Don't assert here. We still call this after failing to load a file in order to show the
127 // user what we *tried* to load.
128 // wxASSERT( aFileName.IsEmpty() || wxIsAbsolutePath( aFileName ) );
129
130 m_fileName = aFileName;
131}
132
133
135{
136 m_refCount++;
137}
138
139
141{
142 wxCHECK_RET( m_refCount != 0, wxT( "Screen reference count already zero. Bad programmer!" ) );
143 m_refCount--;
144}
145
146
147bool SCH_SCREEN::HasItems( KICAD_T aItemType ) const
148{
149 EE_RTREE::EE_TYPE sheets = m_rtree.OfType( aItemType );
150
151 return sheets.begin() != sheets.end();
152}
153
154
155bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
156{
157 return aItem && SCH_SCREEN_T == aItem->Type();
158}
159
160
161void SCH_SCREEN::Append( SCH_ITEM* aItem, bool aUpdateLibSymbol )
162{
163 if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
164 {
165 // Ensure the item can reach the SCHEMATIC through this screen
166 aItem->SetParent( this );
167
168 if( aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
169 {
170 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
171
172 if( symbol->GetLibSymbolRef() )
173 {
174 symbol->GetLibSymbolRef()->GetDrawItems().sort();
175
176 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
177
178 if( it == m_libSymbols.end() || !it->second )
179 {
181 new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
182 }
183 else
184 {
185 // The original library symbol may have changed since the last time
186 // it was added to the schematic. If it has changed, then a new name
187 // must be created for the library symbol list to prevent all of the
188 // other schematic symbols referencing that library symbol from changing.
189 LIB_SYMBOL* foundSymbol = it->second;
190
191 foundSymbol->GetDrawItems().sort();
192
193 if( *foundSymbol != *symbol->GetLibSymbolRef() )
194 {
195 wxString newName;
196 std::vector<wxString> matches;
197
198 getLibSymbolNameMatches( *symbol, matches );
199 foundSymbol = nullptr;
200
201 for( const wxString& libSymbolName : matches )
202 {
203 it = m_libSymbols.find( libSymbolName );
204
205 if( it == m_libSymbols.end() )
206 continue;
207
208 foundSymbol = it->second;
209
210 wxCHECK2( foundSymbol, continue );
211
212 wxString tmp = symbol->GetLibSymbolRef()->GetName();
213
214 // Temporarily update the new symbol library symbol name so it
215 // doesn't fail on the name comparison below.
216 symbol->GetLibSymbolRef()->SetName( foundSymbol->GetName() );
217
218 if( *foundSymbol == *symbol->GetLibSymbolRef() )
219 {
220 newName = libSymbolName;
221 symbol->GetLibSymbolRef()->SetName( tmp );
222 break;
223 }
224
225 symbol->GetLibSymbolRef()->SetName( tmp );
226 foundSymbol = nullptr;
227 }
228
229 if( !foundSymbol )
230 {
231 int cnt = 1;
232
233 newName.Printf( wxT( "%s_%d" ),
235 cnt );
236
237 while( m_libSymbols.find( newName ) != m_libSymbols.end() )
238 {
239 cnt += 1;
240 newName.Printf( wxT( "%s_%d" ),
242 cnt );
243 }
244 }
245
246 // Update the schematic symbol library link as this symbol only exists
247 // in the schematic.
248 symbol->SetSchSymbolLibraryName( newName );
249
250 if( !foundSymbol )
251 {
252 // Update the schematic symbol library link as this symbol does not
253 // exist in any symbol library.
254 LIB_ID newLibId( wxEmptyString, newName );
255 LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
256
257 newLibSymbol->SetLibId( newLibId );
258 newLibSymbol->SetName( newName );
259 symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
260 m_libSymbols[newName] = newLibSymbol;
261 }
262 }
263 }
264 }
265 }
266
267 m_rtree.insert( aItem );
269 }
270}
271
272
274{
275 wxCHECK_RET( aScreen, "Invalid screen object." );
276
277 // No need to descend the hierarchy. Once the top level screen is copied, all of its
278 // children are copied as well.
279 for( SCH_ITEM* aItem : aScreen->m_rtree )
280 Append( aItem );
281
282 aScreen->Clear( false );
283}
284
285
286void SCH_SCREEN::Clear( bool aFree )
287{
288 if( aFree )
289 {
290 FreeDrawList();
292 }
293 else
294 {
295 m_rtree.clear();
296 }
297
298 // Clear the project settings
300
301 m_titles.Clear();
302}
303
304
306{
307 // We don't know which order we will encounter dependent items (e.g. pins or fields), so
308 // we store the items to be deleted until we've fully cleared the tree before deleting
309 std::vector<SCH_ITEM*> delete_list;
310
311 std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
312 []( SCH_ITEM* aItem )
313 {
314 return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
315 } );
316
317 m_rtree.clear();
318
319 for( SCH_ITEM* item : delete_list )
320 delete item;
321}
322
323
324void SCH_SCREEN::Update( SCH_ITEM* aItem, bool aUpdateLibSymbol )
325{
326 if( Remove( aItem, aUpdateLibSymbol ) )
327 Append( aItem, aUpdateLibSymbol );
328}
329
330
331bool SCH_SCREEN::Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol )
332{
333 bool retv = m_rtree.remove( aItem );
334
335 // Check if the library symbol for the removed schematic symbol is still required.
336 if( retv && aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
337 {
338 SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
339
340 bool removeUnusedLibSymbol = true;
341
342 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
343 {
344 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
345
346 if( removedSymbol->GetSchSymbolLibraryName() == symbol->GetSchSymbolLibraryName() )
347 {
348 removeUnusedLibSymbol = false;
349 break;
350 }
351 }
352
353 if( removeUnusedLibSymbol )
354 {
355 auto it = m_libSymbols.find( removedSymbol->GetSchSymbolLibraryName() );
356
357 if( it != m_libSymbols.end() )
358 {
359 delete it->second;
360 m_libSymbols.erase( it );
361 }
362 }
363 }
364
365 return retv;
366}
367
368
370{
371 wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
372
373 // Markers are not saved in the file, no need to flag as modified.
374 // TODO: Maybe we should have a listing somewhere of items that aren't saved?
375 if( aItem->Type() != SCH_MARKER_T )
377
378 Remove( aItem );
379
380 if( aItem->Type() == SCH_SHEET_PIN_T )
381 {
382 // This structure is attached to a sheet, get the parent sheet object.
383 SCH_SHEET_PIN* sheetPin = (SCH_SHEET_PIN*) aItem;
384 SCH_SHEET* sheet = sheetPin->GetParent();
385 wxCHECK_RET( sheet, wxT( "Sheet pin parent not properly set, bad programmer!" ) );
386 sheet->RemovePin( sheetPin );
387 return;
388 }
389
390 delete aItem;
391}
392
393
394bool SCH_SCREEN::CheckIfOnDrawList( const SCH_ITEM* aItem ) const
395{
396 return m_rtree.contains( aItem, true );
397}
398
399
400SCH_ITEM* SCH_SCREEN::GetItem( const VECTOR2I& aPosition, int aAccuracy, KICAD_T aType ) const
401{
402 BOX2I bbox;
403 bbox.SetOrigin( aPosition );
404 bbox.Inflate( aAccuracy );
405
406 for( SCH_ITEM* item : Items().Overlapping( aType, bbox ) )
407 {
408 if( item->HitTest( aPosition, aAccuracy ) )
409 return item;
410 }
411
412 return nullptr;
413}
414
415
416std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aSecondPass )
417{
418#define PROCESSED CANDIDATE // Don't use SKIP_STRUCT; IsConnected() returns false if it's set.
419
420 std::set<SCH_ITEM*> retval;
421 std::stack<SCH_LINE*> to_search;
422
423 wxCHECK_MSG( aSegment && aSegment->Type() == SCH_LINE_T, retval, wxT( "Invalid pointer." ) );
424
425 to_search.push( aSegment );
426
427 while( !to_search.empty() )
428 {
429 SCH_ITEM* item = to_search.top();
430 to_search.pop();
431
432 if( item->HasFlag( PROCESSED ) )
433 continue;
434
435 item->SetFlags( PROCESSED );
436
437 for( SCH_ITEM* candidate : Items().Overlapping( SCH_LINE_T, item->GetBoundingBox() ) )
438 {
439 SCH_LINE* line = static_cast<SCH_LINE*>( candidate );
440
441 if( line->HasFlag( PROCESSED ) )
442 continue;
443
444 // Skip connecting lines on different layers (e.g. buses)
445 if( item->GetLayer() != line->GetLayer() )
446 continue;
447
448 // SCH_RTREE::Overlapping() included crossing lines.
449 if( !item->IsEndPoint( line->GetStartPoint() ) && !item->IsEndPoint( line->GetEndPoint() ) )
450 continue;
451
452 to_search.push( line );
453 retval.insert( line );
454
455 for( VECTOR2I pt : { line->GetStartPoint(), line->GetEndPoint() } )
456 {
457 if( item->IsConnected( pt ) )
458 {
459 SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T );
460
461 if( aSecondPass && junction )
462 retval.insert( junction );
463 }
464 }
465 }
466 }
467
468 for( SCH_ITEM* item : Items() )
469 item->ClearTempFlags();
470
471 return retval;
472}
473
474
475bool SCH_SCREEN::IsJunction( const VECTOR2I& aPosition ) const
476{
478 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
479 return info.isJunction;
480}
481
482
483bool SCH_SCREEN::IsExplicitJunction( const VECTOR2I& aPosition ) const
484{
486 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
487
488 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires );
489}
490
491
492bool SCH_SCREEN::IsExplicitJunctionNeeded( const VECTOR2I& aPosition ) const
493{
495 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
496
497 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires )
498 && !info.hasExplicitJunctionDot;
499}
500
501
503{
505 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, true );
506
507 return info.isJunction && (!info.hasBusEntry || info.hasBusEntryToMultipleWires );
508}
509
510
512 SPIN_STYLE aDefaultOrientation,
513 const SCH_SHEET_PATH* aSheet ) const
514{
515 auto ret = aDefaultOrientation;
516
517 for( SCH_ITEM* item : Items().Overlapping( aPosition ) )
518 {
519 if( item->GetEditFlags() & STRUCT_DELETED )
520 continue;
521
522 switch( item->Type() )
523 {
525 {
526 auto busEntry = static_cast<const SCH_BUS_WIRE_ENTRY*>( item );
527 if( busEntry->m_connected_bus_item )
528 {
529 // bus connected, take the bus direction into consideration only if it is
530 // vertical or horizontal
531 auto bus = static_cast<const SCH_LINE*>( busEntry->m_connected_bus_item );
532 if( bus->Angle().AsDegrees() == 90.0 )
533 {
534 // bus is vertical -> label shall be horizontal and
535 // shall be placed to the side where the bus entry is
536 if( aPosition.x < bus->GetPosition().x )
537 ret = SPIN_STYLE::LEFT;
538 else if( aPosition.x > bus->GetPosition().x )
539 ret = SPIN_STYLE::RIGHT;
540 }
541 else if( bus->Angle().AsDegrees() == 0.0 )
542 {
543 // bus is horizontal -> label shall be vertical and
544 // shall be placed to the side where the bus entry is
545 if( aPosition.y < bus->GetPosition().y )
546 ret = SPIN_STYLE::UP;
547 else if( aPosition.y > bus->GetPosition().y )
548 ret = SPIN_STYLE::BOTTOM;
549 }
550 }
551 }
552 break;
553
554 case SCH_LINE_T:
555 {
556 auto line = static_cast<const SCH_LINE*>( item );
557 // line angles goes between -90 and 90 degrees, but normalize
558 auto angle = line->Angle().Normalize90().AsDegrees();
559
560 if( -45 < angle && angle <= 45 )
561 {
562 if( line->GetStartPoint().x <= line->GetEndPoint().x )
563 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::RIGHT : SPIN_STYLE::LEFT;
564 else
565 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::LEFT : SPIN_STYLE::RIGHT;
566 }
567 else
568 {
569 if( line->GetStartPoint().y <= line->GetEndPoint().y )
570 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::BOTTOM : SPIN_STYLE::UP;
571 else
572 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::UP : SPIN_STYLE::BOTTOM;
573 }
574 }
575 break;
576
577 case SCH_SYMBOL_T:
578 {
579 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
580
581 for( SCH_PIN* pin : symbol->GetPins( aSheet ) )
582 {
583 if( pin->GetPosition() == aPosition )
584 {
585 ret = GetPinSpinStyle( *pin, *symbol );
586 break;
587 }
588 }
589 }
590 break;
591
592 default: break;
593 }
594 }
595
596 return ret;
597}
598
599
600bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
601{
602 wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
603 wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
604
605 SCH_SHEET_PIN* sheetPin;
606 SCH_LABEL_BASE* label;
607
608 switch( aLayer )
609 {
610 case LAYER_BUS:
611 if( GetBus( aPosition ) )
612 return true;
613
614 sheetPin = GetSheetPin( aPosition );
615
616 if( sheetPin && sheetPin->IsConnected( aPosition ) )
617 return true;
618
619 label = GetLabel( aPosition );
620
621 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
622 return true;
623
624 break;
625
626 case LAYER_NOTES:
627 if( GetLine( aPosition ) )
628 return true;
629
630 break;
631
632 case LAYER_WIRE:
633 if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T ) )
634 return true;
635
636 if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
637 return true;
638
639 if( GetPin( aPosition, nullptr, true ) )
640 return true;
641
642 if( GetWire( aPosition ) )
643 return true;
644
645 label = GetLabel( aPosition, 1 );
646
647 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
648 return true;
649
650 sheetPin = GetSheetPin( aPosition );
651
652 if( sheetPin && sheetPin->IsConnected( aPosition ) )
653 return true;
654
655 break;
656
657 default:
658 break;
659 }
660
661 return false;
662}
663
664
666{
667 wxCHECK_RET( Schematic(), "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" );
668
669 wxString msg;
670 std::vector<SCH_SYMBOL*> symbols;
672
673 // This will be a nullptr if an s-expression schematic is loaded.
674 SYMBOL_LIBS* legacyLibs = PROJECT_SCH::SchLibs( &Schematic()->Project() );
675
676 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
677 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
678
679 // Remove them from the R tree. Their bounding box size may change.
680 for( SCH_SYMBOL* symbol : symbols )
681 Remove( symbol );
682
683 // Clear all existing symbol links.
685
686 for( SCH_SYMBOL* symbol : symbols )
687 {
688 LIB_SYMBOL* tmp = nullptr;
689
690 // If the symbol is already in the internal library, map the symbol to it.
691 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
692
693 if( ( it != m_libSymbols.end() ) )
694 {
695 if( aReporter )
696 {
697 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
698 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
699 symbol->GetField( FIELD_T::VALUE )->GetText(),
700 UnescapeString( symbol->GetLibId().Format() ) );
701 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
702 }
703
704 // Internal library symbols are already flattened so just make a copy.
705 symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
706 continue;
707 }
708
709 if( !symbol->GetLibId().IsValid() )
710 {
711 if( aReporter )
712 {
713 msg.Printf( _( "Schematic symbol reference '%s' library identifier is not valid. "
714 "Unable to link library symbol." ),
715 UnescapeString( symbol->GetLibId().Format() ) );
716 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
717 }
718
719 continue;
720 }
721
722 // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the library nickname
723 // is not found in the table so check if the library still exists in the table
724 // before attempting to load the symbol.
725 if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
726 {
727 if( aReporter )
728 {
729 msg.Printf( _( "Symbol library '%s' not found and no fallback cache library "
730 "available. Unable to link library symbol." ),
731 symbol->GetLibId().GetLibNickname().wx_str() );
732 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
733 }
734
735 continue;
736 }
737
738 if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
739 {
740 try
741 {
742 tmp = libs->LoadSymbol( symbol->GetLibId() );
743 }
744 catch( const IO_ERROR& ioe )
745 {
746 if( aReporter )
747 {
748 msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
749 UnescapeString( symbol->GetLibId().Format() ) );
750 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
751 }
752 }
753 }
754
755 if( !tmp && legacyLibs && legacyLibs->GetLibraryCount() )
756 {
757 SYMBOL_LIB& legacyCacheLib = legacyLibs->back();
758
759 // It better be the cache library.
760 wxCHECK2( legacyCacheLib.IsCache(), continue );
761
762 wxString id = symbol->GetLibId().Format();
763
764 id.Replace( ':', '_' );
765
766 if( aReporter )
767 {
768 msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
769 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
770 symbol->GetField( FIELD_T::VALUE )->GetText(),
771 UnescapeString( id ) );
772 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
773 }
774
775 tmp = legacyCacheLib.FindSymbol( id );
776 }
777
778 if( tmp )
779 {
780 // We want a full symbol not just the top level child symbol.
781 std::unique_ptr<LIB_SYMBOL> libSymbol = tmp->Flatten();
782 libSymbol->SetParent();
783
784 m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
785 new LIB_SYMBOL( *libSymbol ) } );
786
787 if( aReporter )
788 {
789 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
790 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
791 symbol->GetField( FIELD_T::VALUE )->GetText(),
792 UnescapeString( symbol->GetLibId().Format() ) );
793 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
794 }
795
796 symbol->SetLibSymbol( libSymbol.release() );
797 }
798 else
799 {
800 if( aReporter )
801 {
802 msg.Printf( _( "No library symbol found for schematic symbol '%s %s'." ),
803 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
804 symbol->GetField( FIELD_T::VALUE )->GetText() );
805 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
806 }
807 }
808 }
809
810 // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
811 // item with the new bbox
812 for( SCH_SYMBOL* symbol : symbols )
813 Append( symbol );
814}
815
816
818{
819 std::vector<SCH_SYMBOL*> symbols;
820
821 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
822 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
823
824 for( SCH_SYMBOL* symbol : symbols )
825 {
826 // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
827 m_rtree.remove( symbol );
828
829 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
830
831 if( it != m_libSymbols.end() )
832 symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
833 else
834 symbol->SetLibSymbol( nullptr );
835
836 m_rtree.insert( symbol );
837 }
838}
839
840
842{
843 for( SCH_ITEM* item : Items() )
844 item->SetConnectivityDirty( true );
845}
846
847
848void SCH_SCREEN::Plot( PLOTTER* aPlotter, const SCH_PLOT_OPTS& aPlotOpts ) const
849{
850 // Ensure links are up to date, even if a library was reloaded for some reason:
851 std::vector<SCH_ITEM*> junctions;
852 std::vector<SCH_ITEM*> bitmaps;
853 std::vector<SCH_SYMBOL*> symbols;
854 std::vector<SCH_ITEM*> other;
855
856 for( SCH_ITEM* item : Items() )
857 {
858 if( item->IsMoving() )
859 continue;
860
861 if( item->Type() == SCH_JUNCTION_T )
862 junctions.push_back( item );
863 else if( item->Type() == SCH_BITMAP_T )
864 bitmaps.push_back( item );
865 else
866 other.push_back( item );
867
868 // Where the symbols overlap each other, we need to plot the text items a second
869 // time to get them on top of the overlapping element. This collection is in addition
870 // to the symbols already collected in `other`
871 if( item->Type() == SCH_SYMBOL_T )
872 {
873 for( SCH_ITEM* sym : m_rtree.Overlapping( SCH_SYMBOL_T, item->GetBoundingBox() ) )
874 {
875 if( sym != item )
876 {
877 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
878 break;
879 }
880 }
881 }
882 }
883
885 std::sort( other.begin(), other.end(),
886 []( const SCH_ITEM* a, const SCH_ITEM* b )
887 {
888 if( a->Type() == b->Type() )
889 return a->GetLayer() > b->GetLayer();
890
891 return a->Type() > b->Type();
892 } );
893
894 auto* renderSettings = static_cast<SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() );
895 constexpr bool background = true;
896
897 // Bitmaps are drawn first to ensure they are in the background
898 // This is particularly important for the wxPostscriptDC (used in *nix printers) as
899 // the bitmap PS command clears the screen
900 for( SCH_ITEM* item : bitmaps )
901 {
902 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
903 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
904 }
905
906 // Plot the background items
907 for( SCH_ITEM* item : other )
908 {
909 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
910 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
911 }
912
913 // Plot the foreground items
914 for( SCH_ITEM* item : other )
915 {
916 double lineWidth = item->GetEffectivePenWidth( renderSettings );
917 aPlotter->SetCurrentLineWidth( lineWidth );
918
919 if( item->Type() != SCH_LINE_T )
920 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
921 else
922 {
923 SCH_LINE* aLine = static_cast<SCH_LINE*>( item );
924
925 if( !aLine->IsWire() || !aPlotOpts.m_plotHopOver )
926 {
927 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
928 }
929 else
930 {
931 double arcRadius = lineWidth * aLine->Schematic()->Settings().m_HopOverScale;
932 std::vector<VECTOR3I> curr_wire_shape = aLine->BuildWireWithHopShape( this, arcRadius );
933
934 for( size_t ii = 1; ii < curr_wire_shape.size(); ii++ )
935 {
936 VECTOR2I start( curr_wire_shape[ii-1].x, curr_wire_shape[ii-1].y );
937
938 if( curr_wire_shape[ii-1].z == 0 ) // This is the start point of a segment
939 // there are always 2 points in list for a segment
940 {
941 VECTOR2I end( curr_wire_shape[ii].x, curr_wire_shape[ii].y );
942
943 SCH_LINE curr_line( *aLine );
944 curr_line.SetStartPoint( start );
945 curr_line.SetEndPoint( end );
946 curr_line.Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
947 }
948 else // This is the start point of a arc. there are always 3 points in list for an arc
949 {
950 VECTOR2I arc_middle( curr_wire_shape[ii].x, curr_wire_shape[ii].y );
951 ii++;
952 VECTOR2I arc_end( curr_wire_shape[ii].x, curr_wire_shape[ii].y );
953 ii++;
954
955 SCH_SHAPE arc( SHAPE_T::ARC, aLine->GetLayer(), lineWidth );
956
957 arc.SetArcGeometry( start, arc_middle, arc_end );
958 // Hop are a small arc, so use a solid line style gives best results
960 arc.Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
961 }
962 }
963 }
964 }
965 }
966
967 // After plotting the symbols as a group above (in `other`), we need to overplot the pins
968 // and symbols to ensure that they are always visible
969 TRANSFORM savedTransform = renderSettings->m_Transform;
970
971 for( const SCH_SYMBOL* sym :symbols )
972 {
973 renderSettings->m_Transform = sym->GetTransform();
974 aPlotter->SetCurrentLineWidth( sym->GetEffectivePenWidth( renderSettings ) );
975
976 for( SCH_FIELD field : sym->GetFields() )
977 {
978 field.ClearRenderCache();
979 field.Plot( aPlotter, false, aPlotOpts, sym->GetUnit(), sym->GetBodyStyle(), { 0, 0 },
980 static_cast<const SYMBOL*>( sym )->GetDNP() );
981 }
982
983 sym->PlotPins( aPlotter );
984
985 if( static_cast<const SYMBOL*>( sym )->GetDNP() )
986 sym->PlotDNP( aPlotter );
987 }
988
989 renderSettings->m_Transform = savedTransform;
990
991 for( SCH_ITEM* item : junctions )
992 {
993 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
994 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
995 }
996}
997
998
1000{
1001 for( SCH_ITEM* item : Items() )
1002 item->ClearTempFlags();
1003}
1004
1005
1006SCH_PIN* SCH_SCREEN::GetPin( const VECTOR2I& aPosition, SCH_SYMBOL** aSymbol,
1007 bool aEndPointOnly ) const
1008{
1009 SCH_SYMBOL* candidate = nullptr;
1010 SCH_PIN* pin = nullptr;
1011
1012 for( SCH_ITEM* item : Items().Overlapping( SCH_SYMBOL_T, aPosition ) )
1013 {
1014 candidate = static_cast<SCH_SYMBOL*>( item );
1015
1016 if( aEndPointOnly )
1017 {
1018 pin = nullptr;
1019
1020 if( !candidate->GetLibSymbolRef() )
1021 continue;
1022
1023 for( SCH_PIN* test_pin : candidate->GetLibPins() )
1024 {
1025 if( candidate->GetPinPhysicalPosition( test_pin ) == aPosition )
1026 {
1027 pin = test_pin;
1028 break;
1029 }
1030 }
1031
1032 if( pin )
1033 break;
1034 }
1035 else
1036 {
1037 pin = static_cast<SCH_PIN*>( candidate->GetDrawItem( aPosition, SCH_PIN_T ) );
1038
1039 if( pin )
1040 break;
1041 }
1042 }
1043
1044 if( pin && aSymbol )
1045 *aSymbol = candidate;
1046
1047 return pin;
1048}
1049
1050
1052{
1053 SCH_SHEET_PIN* sheetPin = nullptr;
1054
1055 for( SCH_ITEM* item : Items().Overlapping( SCH_SHEET_T, aPosition ) )
1056 {
1057 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1058
1059 sheetPin = sheet->GetPin( aPosition );
1060
1061 if( sheetPin )
1062 break;
1063 }
1064
1065 return sheetPin;
1066}
1067
1068
1069size_t SCH_SCREEN::CountConnectedItems( const VECTOR2I& aPos, bool aTestJunctions ) const
1070{
1071 size_t count = 0;
1072
1073 for( const SCH_ITEM* item : Items().Overlapping( aPos ) )
1074 {
1075 if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
1076 count++;
1077 }
1078
1079 return count;
1080}
1081
1082
1083void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1084{
1085
1086 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1087 {
1088 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1089
1090 symbol->ClearAnnotation( aSheetPath, aResetPrefix );
1091 }
1092}
1093
1094
1096{
1097 if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
1098 return;
1099
1100 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1101 {
1102 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1103
1104 // Add (when not existing) all sheet path entries
1105 for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
1106 symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
1107 }
1108}
1109
1110
1111void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems ) const
1112{
1113 static const std::vector<KICAD_T> hierarchicalTypes = { SCH_SYMBOL_T,
1116
1117 for( SCH_ITEM* item : Items() )
1118 {
1119 if( item->IsType( hierarchicalTypes ) )
1120 aItems->push_back( item );
1121 }
1122}
1123
1124
1125void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
1126{
1127 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1128 aItems->push_back( item );
1129
1130 std::sort( aItems->begin(), aItems->end(),
1131 []( EDA_ITEM* a, EDA_ITEM* b ) -> bool
1132 {
1133 if( a->GetPosition().x == b->GetPosition().x )
1134 {
1135 // Ensure deterministic sort
1136 if( a->GetPosition().y == b->GetPosition().y )
1137 return a->m_Uuid < b->m_Uuid;
1138
1139 return a->GetPosition().y < b->GetPosition().y;
1140 }
1141 else
1142 {
1143 return a->GetPosition().x < b->GetPosition().x;
1144 }
1145 } );
1146}
1147
1148
1150 std::function<void( SCH_ITEM* )>* aChangedHandler ) const
1151{
1152 PROF_TIMER timer( __FUNCTION__ );
1153
1154 std::vector<DANGLING_END_ITEM> endPointsByPos;
1155 std::vector<DANGLING_END_ITEM> endPointsByType;
1156
1157 auto get_ends =
1158 [&]( SCH_ITEM* item )
1159 {
1160 if( item->IsConnectable() )
1161 item->GetEndPoints( endPointsByType );
1162 };
1163
1164 auto update_state =
1165 [&]( SCH_ITEM* item )
1166 {
1167 if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
1168 {
1169 if( aChangedHandler )
1170 ( *aChangedHandler )( item );
1171 }
1172 };
1173
1174 for( SCH_ITEM* item : Items() )
1175 {
1176 get_ends( item );
1177 item->RunOnChildren( get_ends, RECURSE_MODE::NO_RECURSE );
1178 }
1179
1180 PROF_TIMER sortTimer( "SCH_SCREEN::TestDanglingEnds pre-sort" );
1181 endPointsByPos = endPointsByType;
1182 DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
1183 sortTimer.Stop();
1184
1185 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1186 sortTimer.Show();
1187
1188 for( SCH_ITEM* item : Items() )
1189 {
1190 update_state( item );
1191 item->RunOnChildren( update_state, RECURSE_MODE::NO_RECURSE );
1192 }
1193
1194 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1195 timer.Show();
1196}
1197
1198
1199SCH_LINE* SCH_SCREEN::GetLine( const VECTOR2I& aPosition, int aAccuracy, int aLayer,
1200 SCH_LINE_TEST_T aSearchType ) const
1201{
1202 // an accuracy of 0 had problems with rounding errors; use at least 1
1203 aAccuracy = std::max( aAccuracy, 1 );
1204
1205 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1206 {
1207 if( item->Type() != SCH_LINE_T )
1208 continue;
1209
1210 if( item->GetLayer() != aLayer )
1211 continue;
1212
1213 if( !item->HitTest( aPosition, aAccuracy ) )
1214 continue;
1215
1216 switch( aSearchType )
1217 {
1218 case ENTIRE_LENGTH_T:
1219 return (SCH_LINE*) item;
1220
1222 if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1223 return (SCH_LINE*) item;
1224 break;
1225
1226 case END_POINTS_ONLY_T:
1227 if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1228 return (SCH_LINE*) item;
1229 }
1230 }
1231
1232 return nullptr;
1233}
1234
1235
1236std::vector<SCH_LINE*> SCH_SCREEN::GetBusesAndWires( const VECTOR2I& aPosition,
1237 bool aIgnoreEndpoints ) const
1238{
1239 std::vector<SCH_LINE*> retVal;
1240
1241 for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, aPosition ) )
1242 {
1243 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } ) )
1244 {
1245 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
1246
1247 if( aIgnoreEndpoints && wire->IsEndPoint( aPosition ) )
1248 continue;
1249
1250 if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), aPosition ) )
1251 retVal.push_back( wire );
1252 }
1253 }
1254
1255 return retVal;
1256}
1257
1258
1259std::vector<VECTOR2I> SCH_SCREEN::GetConnections() const
1260{
1261 std::vector<VECTOR2I> retval;
1262
1263 for( SCH_ITEM* item : Items() )
1264 {
1265 // Avoid items that are changing
1266 if( !( item->GetEditFlags() & ( IS_MOVING | IS_DELETED ) ) )
1267 {
1268 std::vector<VECTOR2I> pts = item->GetConnectionPoints();
1269 retval.insert( retval.end(), pts.begin(), pts.end() );
1270 }
1271 }
1272
1273 // We always have some overlapping connection points. Drop duplicates here
1274 std::sort( retval.begin(), retval.end(),
1275 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1276 {
1277 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1278 } );
1279
1280 retval.erase( std::unique( retval.begin(), retval.end() ), retval.end() );
1281
1282 return retval;
1283}
1284
1285
1286std::vector<VECTOR2I> SCH_SCREEN::GetNeededJunctions( const std::deque<EDA_ITEM*>& aItems ) const
1287{
1288 std::vector<VECTOR2I> pts;
1289 std::vector<VECTOR2I> connections = GetConnections();
1290
1291 for( const EDA_ITEM* edaItem : aItems )
1292 {
1293 const SCH_ITEM* item = dynamic_cast<const SCH_ITEM*>( edaItem );
1294
1295 if( !item || !item->IsConnectable() )
1296 continue;
1297
1298 std::vector<VECTOR2I> new_pts = item->GetConnectionPoints();
1299 pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
1300
1301 // If the item is a line, we also add any connection points from the rest of the schematic
1302 // that terminate on the line after it is moved.
1303 if( item->Type() == SCH_LINE_T )
1304 {
1305 SCH_LINE* line = (SCH_LINE*) item;
1306
1307 for( const VECTOR2I& pt : connections )
1308 {
1309 if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
1310 pts.push_back( pt );
1311 }
1312 }
1313 }
1314
1315 // We always have some overlapping connection points. Drop duplicates here
1316 std::sort( pts.begin(), pts.end(),
1317 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1318 {
1319 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1320 } );
1321
1322 pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
1323
1324 // We only want the needed junction points, remove all the others
1325 pts.erase( std::remove_if( pts.begin(), pts.end(),
1326 [this]( const VECTOR2I& a ) -> bool
1327 {
1328 return !IsExplicitJunctionNeeded( a );
1329 } ),
1330 pts.end() );
1331
1332 return pts;
1333}
1334
1335
1336SCH_LABEL_BASE* SCH_SCREEN::GetLabel( const VECTOR2I& aPosition, int aAccuracy ) const
1337{
1338 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1339 {
1340 switch( item->Type() )
1341 {
1342 case SCH_LABEL_T:
1343 case SCH_GLOBAL_LABEL_T:
1344 case SCH_HIER_LABEL_T:
1346 if( item->HitTest( aPosition, aAccuracy ) )
1347 return static_cast<SCH_LABEL_BASE*>( item );
1348
1349 break;
1350
1351 default:
1352 ;
1353 }
1354 }
1355
1356 return nullptr;
1357}
1358
1359
1361{
1362 wxCHECK( aLibSymbol, /* void */ );
1363
1364 wxString libSymbolName = aLibSymbol->GetLibId().Format().wx_str();
1365
1366 auto it = m_libSymbols.find( libSymbolName );
1367
1368 if( it != m_libSymbols.end() )
1369 {
1370 delete it->second;
1371 m_libSymbols.erase( it );
1372 }
1373
1374 m_libSymbols[libSymbolName] = aLibSymbol;
1375}
1376
1377
1379{
1380 SCHEMATIC* schematic = Schematic();
1381
1382 const std::vector<wxString>* embeddedFonts = schematic->GetEmbeddedFiles()->UpdateFontFiles();
1383
1384 for( auto& [name, libSym] : m_libSymbols )
1385 {
1386 for( auto& [filename, embeddedFile] : libSym->EmbeddedFileMap() )
1387 {
1388 EMBEDDED_FILES::EMBEDDED_FILE* file = schematic->GetEmbeddedFile( filename );
1389
1390 if( file )
1391 {
1392 embeddedFile->compressedEncodedData = file->compressedEncodedData;
1393 embeddedFile->decompressedData = file->decompressedData;
1394 embeddedFile->data_hash = file->data_hash;
1395 embeddedFile->is_valid = file->is_valid;
1396 }
1397 }
1398
1399 libSym->RunOnChildren(
1400 [&]( SCH_ITEM* aChild )
1401 {
1402 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aChild ) )
1403 textItem->ResolveFont( embeddedFonts );
1404 },
1406 }
1407
1408 std::vector<SCH_ITEM*> items_to_update;
1409
1410 for( SCH_ITEM* item : Items() )
1411 {
1412 bool update = false;
1413
1414 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( item ) )
1415 update |= textItem->ResolveFont( embeddedFonts );
1416
1417 item->RunOnChildren(
1418 [&]( SCH_ITEM* aChild )
1419 {
1420 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aChild ) )
1421 update |= textItem->ResolveFont( embeddedFonts );
1422 },
1424
1425 if( update )
1426 items_to_update.push_back( item );
1427 }
1428
1429 for( SCH_ITEM* item : items_to_update )
1430 Update( item );
1431}
1432
1433
1434void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
1435{
1436 if( SCHEMATIC* schematic = Schematic() )
1437 schematic->AddBusAlias( aAlias );
1438}
1439
1440
1442{
1443 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1444 {
1445 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1446
1447 // Add missing value and footprint instance data for legacy schematics.
1448 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1449 {
1450 symbol->AddHierarchicalReference( instance.m_Path, instance.m_Reference,
1451 instance.m_Unit );
1452 }
1453 }
1454}
1455
1456
1458{
1459 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1460 {
1461 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1462
1463 // Fix pre-8.0 legacy power symbols with invisible pins
1464 // that have mismatched pin names and value fields
1465 if( symbol->GetLibSymbolRef()
1466 && symbol->GetLibSymbolRef()->IsGlobalPower()
1467 && symbol->GetAllLibPins().size() > 0
1468 && symbol->GetAllLibPins()[0]->IsGlobalPower()
1469 && !symbol->GetAllLibPins()[0]->IsVisible() )
1470 {
1471 symbol->SetValueFieldText( symbol->GetAllLibPins()[0]->GetName() );
1472 }
1473 }
1474}
1475
1476
1478 std::vector<wxString>& aMatches )
1479{
1480 wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
1481
1482 if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
1483 aMatches.emplace_back( searchName );
1484
1485 searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
1486
1487 long tmp;
1488 wxString suffix;
1489
1490 for( auto& pair : m_libSymbols )
1491 {
1492 if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToLong( &tmp ) )
1493 aMatches.emplace_back( pair.first );
1494 }
1495
1496 return aMatches.size();
1497}
1498
1499
1500void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
1501 const SCH_SHEET_LIST& aValidSheetPaths )
1502{
1503 // The project name cannot be empty. Projects older than 7.0 did not save project names
1504 // when saving instance data. Running this algorithm with an empty project name would
1505 // clobber all instance data for projects other than the current one when a schematic
1506 // file is shared across multiple projects. Because running the schematic editor in
1507 // stand alone mode can result in an empty project name, do not assert here.
1508 if( aProjectName.IsEmpty() )
1509 return;
1510
1511 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1512 {
1513 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1514
1515 wxCHECK2( symbol, continue );
1516
1517 std::set<KIID_PATH> pathsToPrune;
1518 const std::vector<SCH_SYMBOL_INSTANCE> instances = symbol->GetInstances();
1519
1520 for( const SCH_SYMBOL_INSTANCE& instance : instances )
1521 {
1522 // Ignore instance paths from other projects.
1523 if( aProjectName != instance.m_ProjectName )
1524 continue;
1525
1526 std::optional<SCH_SHEET_PATH> pathFound =
1527 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1528
1529 // Check for paths that do not exist in the current project and paths that do
1530 // not contain the current symbol.
1531 if( !pathFound )
1532 pathsToPrune.emplace( instance.m_Path );
1533 else if( pathFound.value().LastScreen() != this )
1534 pathsToPrune.emplace( pathFound.value().Path() );
1535 }
1536
1537 for( const KIID_PATH& sheetPath : pathsToPrune )
1538 {
1539 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' symbol instance %s." ),
1540 aProjectName, sheetPath.AsString() );
1541 symbol->RemoveInstance( sheetPath );
1542 }
1543 }
1544}
1545
1546
1547void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
1548 const SCH_SHEET_LIST& aValidSheetPaths )
1549{
1550 // The project name cannot be empty. Projects older than 7.0 did not save project names
1551 // when saving instance data. Running this algorithm with an empty project name would
1552 // clobber all instance data for projects other than the current one when a schematic
1553 // file is shared across multiple projects. Because running the schematic editor in
1554 // stand alone mode can result in an empty project name, do not assert here.
1555 if( aProjectName.IsEmpty() )
1556 return;
1557
1558 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1559 {
1560 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1561
1562 wxCHECK2( sheet, continue );
1563
1564 std::set<KIID_PATH> pathsToPrune;
1565 const std::vector<SCH_SHEET_INSTANCE> instances = sheet->GetInstances();
1566
1567 for( const SCH_SHEET_INSTANCE& instance : instances )
1568 {
1569 // Ignore instance paths from other projects.
1570 if( aProjectName != instance.m_ProjectName )
1571 continue;
1572
1573 std::optional<SCH_SHEET_PATH> pathFound =
1574 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1575
1576 // Check for paths that do not exist in the current project and paths that do
1577 // not contain the current symbol.
1578 if( !pathFound )
1579 pathsToPrune.emplace( instance.m_Path );
1580 else if( pathFound.value().LastScreen() != this )
1581 pathsToPrune.emplace( pathFound.value().Path() );
1582 }
1583
1584 for( const KIID_PATH& sheetPath : pathsToPrune )
1585 {
1586 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' sheet instance %s." ),
1587 aProjectName, sheetPath.AsString() );
1588 sheet->RemoveInstance( sheetPath );
1589 }
1590 }
1591}
1592
1593
1595{
1596 wxString trimmedFieldName;
1597
1598 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1599 {
1600 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1601
1602 wxCHECK2( symbol, continue );
1603
1604 for( const SCH_FIELD& field : symbol->GetFields() )
1605 {
1606 trimmedFieldName = field.GetName();
1607 trimmedFieldName.Trim();
1608 trimmedFieldName.Trim( false );
1609
1610 if( field.GetName() != trimmedFieldName )
1611 return true;
1612 }
1613 }
1614
1615 return false;
1616}
1617
1618
1619std::set<wxString> SCH_SCREEN::GetSheetNames() const
1620{
1621 std::set<wxString> retv;
1622
1623 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1624 {
1625 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1626
1627 wxCHECK2( sheet, continue );
1628
1629 retv.emplace( sheet->GetName() );
1630 }
1631
1632 return retv;
1633}
1634
1635
1637{
1638 wxCHECK( Schematic(), false );
1639
1640 SCH_SHEET_LIST hierarchy = Schematic()->Hierarchy();
1641
1642 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1643 {
1644 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1645
1646 const std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
1647
1648 for( const SCH_SYMBOL_INSTANCE& instance : symbolInstances )
1649 {
1650 if( !hierarchy.HasPath( instance.m_Path ) )
1651 return true;
1652 }
1653 }
1654
1655 return false;
1656}
1657
1658
1659wxString SCH_SCREEN::GroupsSanityCheck( bool repair )
1660{
1661 if( repair )
1662 {
1663 while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
1664 {
1665 };
1666
1667 return wxEmptyString;
1668 }
1669 return GroupsSanityCheckInternal( repair );
1670}
1671
1672
1674{
1675 // Cycle detection
1676 //
1677 // Each group has at most one parent group.
1678 // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
1679 // If we ever see a group that we've already marked, that's a cycle.
1680 // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
1681 //
1682 // Algorithm below is linear in the # of groups because each group is visited only once.
1683 // There may be extra time taken due to the container access calls and iterators.
1684 //
1685 // Groups we know are cycle free
1686 std::unordered_set<EDA_GROUP*> knownCycleFreeGroups;
1687 // Groups in the current chain we're exploring.
1688 std::unordered_set<EDA_GROUP*> currentChainGroups;
1689 // Groups we haven't checked yet.
1690 std::unordered_set<EDA_GROUP*> toCheckGroups;
1691
1692 // Initialize set of groups and generators to check that could participate in a cycle.
1693 for( SCH_ITEM* item : Items().OfType( SCH_GROUP_T ) )
1694 toCheckGroups.insert( static_cast<SCH_GROUP*>( item ) );
1695
1696 while( !toCheckGroups.empty() )
1697 {
1698 currentChainGroups.clear();
1699 EDA_GROUP* group = *toCheckGroups.begin();
1700
1701 while( true )
1702 {
1703 if( currentChainGroups.find( group ) != currentChainGroups.end() )
1704 {
1705 if( repair )
1706 Remove( static_cast<SCH_ITEM*>( group->AsEdaItem() ) );
1707
1708 return "Cycle detected in group membership";
1709 }
1710 else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
1711 {
1712 // Parent is a group we know does not lead to a cycle
1713 break;
1714 }
1715
1716 currentChainGroups.insert( group );
1717 // We haven't visited currIdx yet, so it must be in toCheckGroups
1718 toCheckGroups.erase( group );
1719
1720 group = group->AsEdaItem()->GetParentGroup();
1721
1722 if( !group )
1723 {
1724 // end of chain and no cycles found in this chain
1725 break;
1726 }
1727 }
1728
1729 // No cycles found in chain, so add it to set of groups we know don't participate
1730 // in a cycle.
1731 knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
1732 }
1733
1734 // Success
1735 return "";
1736}
1737
1738
1740{
1741 wxCHECK( Schematic() && !m_fileName.IsEmpty(), false );
1742
1743 wxFileName thisScreenFn( m_fileName );
1744 wxFileName thisProjectFn( Schematic()->Project().GetProjectFullName() );
1745
1746 wxCHECK( thisProjectFn.IsAbsolute(), false );
1747
1748 if( thisScreenFn.GetDirCount() < thisProjectFn.GetDirCount() )
1749 return false;
1750
1751 while( thisProjectFn.GetDirCount() != thisScreenFn.GetDirCount() )
1752 thisScreenFn.RemoveLastDir();
1753
1754 return thisScreenFn.GetPath() == thisProjectFn.GetPath();
1755}
1756
1757
1758std::set<wxString> SCH_SCREEN::GetVariantNames() const
1759{
1760 std::set<wxString> variantNames;
1761
1762 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1763 {
1764 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1765
1766 wxCHECK2( symbol, continue );
1767
1768 const std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
1769
1770 for( const SCH_SYMBOL_INSTANCE& instance : symbolInstances )
1771 {
1772 for( const auto& [name, variant] : instance.m_Variants )
1773 variantNames.emplace( name );
1774 }
1775 }
1776
1777 for( const SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1778 {
1779 const SCH_SHEET* sheet = static_cast<const SCH_SHEET*>( item );
1780
1781 wxCHECK2( sheet, continue );
1782
1783 const std::vector<SCH_SHEET_INSTANCE> sheetInstances = sheet->GetInstances();
1784
1785 for( const SCH_SHEET_INSTANCE& instance : sheetInstances )
1786 {
1787 for( const auto& [name, variant] : instance.m_Variants )
1788 variantNames.emplace( name );
1789 }
1790 }
1791
1792 return variantNames;
1793}
1794
1795
1796void SCH_SCREEN::DeleteVariant( const wxString& aVariantName )
1797{
1798 wxCHECK( !aVariantName.IsEmpty(), /* void */ );
1799
1800 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1801 {
1802 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1803
1804 wxCHECK2( symbol, continue );
1805
1806 std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
1807
1808 for( SCH_SYMBOL_INSTANCE& instance : symbolInstances )
1809 {
1810 if( instance.m_Variants.contains( aVariantName ) )
1811 instance.m_Variants.erase( aVariantName );
1812 }
1813 }
1814
1815 for( const SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1816 {
1817 const SCH_SHEET* sheet = static_cast<const SCH_SHEET*>( item );
1818
1819 wxCHECK2( sheet, continue );
1820
1821 std::vector<SCH_SHEET_INSTANCE> sheetInstances = sheet->GetInstances();
1822
1823 for( SCH_SHEET_INSTANCE& instance : sheetInstances )
1824 {
1825 if( instance.m_Variants.contains( aVariantName ) )
1826 instance.m_Variants.erase( aVariantName );
1827 }
1828 }
1829}
1830
1831
1832#if defined(DEBUG)
1833void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1834{
1835 // for now, make it look like XML, expand on this later.
1836 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1837
1838 for( const SCH_ITEM* item : Items() )
1839 item->Show( nestLevel + 1, os );
1840
1841 NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1842}
1843#endif
1844
1845
1847{
1848 m_index = 0;
1849 buildScreenList( aSheet );
1850}
1851
1852
1856
1857
1859{
1860 m_index = 0;
1861
1862 if( m_screens.size() > 0 )
1863 return m_screens[0];
1864
1865 return nullptr;
1866}
1867
1868
1870{
1871 if( m_index < m_screens.size() )
1872 m_index++;
1873
1874 return GetScreen( m_index );
1875}
1876
1877
1878SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1879{
1880 if( aIndex < m_screens.size() )
1881 return m_screens[ aIndex ];
1882
1883 return nullptr;
1884}
1885
1886
1887SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1888{
1889 if( aIndex < m_sheets.size() )
1890 return m_sheets[ aIndex ];
1891
1892 return nullptr;
1893}
1894
1895
1897{
1898 if( aScreen == nullptr )
1899 return;
1900
1901 for( const SCH_SCREEN* screen : m_screens )
1902 {
1903 if( screen == aScreen )
1904 return;
1905 }
1906
1907 m_screens.push_back( aScreen );
1908 m_sheets.push_back( aSheet );
1909}
1910
1911
1913{
1914 if( aSheet && aSheet->Type() == SCH_SHEET_T )
1915 {
1916 SCH_SCREEN* screen = aSheet->GetScreen();
1917
1918 if( !screen )
1919 return;
1920
1921 addScreenToList( screen, aSheet );
1922
1923 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1924 buildScreenList( static_cast<SCH_SHEET*>( item ) );
1925 }
1926}
1927
1928
1930{
1931 SCH_SCREEN* first = GetFirst();
1932
1933 if( !first )
1934 return;
1935
1936 SCHEMATIC* sch = first->Schematic();
1937
1938 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" );
1939
1940 // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1941 SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1942 screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1943
1944 // Search for new sheet paths, not existing in aInitialSheetPathList
1945 // and existing in sheetpathList
1946 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
1947 {
1948 bool path_exists = false;
1949
1950 for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1951 {
1952 if( existing_sheetpath.Path() == sheetpath.Path() )
1953 {
1954 path_exists = true;
1955 break;
1956 }
1957 }
1958
1959 if( !path_exists )
1960 {
1961 // A new sheet path is found: clear the annotation corresponding to this new path:
1962 SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1963
1964 // Clear annotation and create the AR for this path, if not exists,
1965 // when the screen is shared by sheet paths.
1966 // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1967 // reference default value and takes the latest displayed value
1968 curr_screen->EnsureAlternateReferencesExist();
1969 curr_screen->ClearAnnotation( &sheetpath, false );
1970 }
1971 }
1972}
1973
1974
1976{
1977 std::vector<SCH_ITEM*> items;
1978 int count = 0;
1979
1980 auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1981 {
1982 return a->m_Uuid < b->m_Uuid;
1983 };
1984
1985 std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1986
1987 for( SCH_SCREEN* screen : m_screens )
1988 screen->GetHierarchicalItems( &items );
1989
1990 if( items.size() < 2 )
1991 return 0;
1992
1993 for( EDA_ITEM* item : items )
1994 {
1995 if( !unique_stamps.insert( item ).second )
1996 {
1997 // Reset to fully random UUID. This may lose reference, but better to be
1998 // deterministic about it rather than to have duplicate UUIDs with random
1999 // side-effects.
2000 const_cast<KIID&>( item->m_Uuid ) = KIID();
2001 count++;
2002
2003 // @todo If the item is a sheet, we need to descend the hierarchy from the sheet
2004 // and replace all instances of the changed UUID in sheet paths. Otherwise,
2005 // all instance paths with the sheet's UUID will get clobbered.
2006 }
2007 }
2008
2009 return count;
2010}
2011
2012
2014{
2015 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2016 {
2017 for( SCH_ITEM* item : screen->Items() )
2018 item->ClearEditFlags();
2019 }
2020}
2021
2022
2024{
2025 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2026 {
2027 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
2028 {
2029 if( item == aMarker )
2030 {
2031 screen->DeleteItem( item );
2032 return;
2033 }
2034 }
2035 }
2036}
2037
2038
2039void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::MARKER_T aMarkerType, int aErrorCode,
2040 bool aIncludeExclusions )
2041{
2042 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2043 {
2044 std::vector<SCH_ITEM*> markers;
2045
2046 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
2047 {
2048 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
2049 std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
2050
2051 if( marker->GetMarkerType() == aMarkerType
2052 && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
2053 && ( !marker->IsExcluded() || aIncludeExclusions ) )
2054 {
2055 markers.push_back( item );
2056 }
2057 }
2058
2059 for( SCH_ITEM* marker : markers )
2060 screen->DeleteItem( marker );
2061 }
2062}
2063
2064
2066 bool aIncludeExclusions )
2067{
2068 DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
2069}
2070
2071
2073{
2074 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2075 screen->UpdateSymbolLinks( aReporter );
2076
2077 SCH_SCREEN* first = GetFirst();
2078
2079 if( !first )
2080 return;
2081
2082 SCHEMATIC* sch = first->Schematic();
2083
2084 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
2085
2086 SCH_SHEET_LIST sheets = sch->Hierarchy();
2087
2088 // All of the library symbols have been replaced with copies so the connection graph
2089 // pointers are stale.
2090 if( sch->ConnectionGraph() )
2091 sch->ConnectionGraph()->Recalculate( sheets, true );
2092}
2093
2094
2096{
2097 bool has_symbols = false;
2098
2099 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2100 {
2101 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2102 {
2103 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2104 has_symbols = true;
2105
2106 if( !symbol->GetLibId().GetLibNickname().empty() )
2107 return false;
2108 }
2109 }
2110
2111 // return true (i.e. has no fully defined symbol) only if at least one symbol is found
2112 return has_symbols ? true : false;
2113}
2114
2115
2116size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
2117{
2118 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2119 {
2120 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2121 {
2122 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2123 const UTF8& nickname = symbol->GetLibId().GetLibNickname();
2124
2125 if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
2126 aLibNicknames.Add( nickname );
2127 }
2128 }
2129
2130 return aLibNicknames.GetCount();
2131}
2132
2133
2134int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
2135{
2136 SCH_SCREEN* screen;
2137 int cnt = 0;
2138
2139 for( screen = GetFirst(); screen; screen = GetNext() )
2140 {
2141 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2142 {
2143 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2144
2145 if( symbol->GetLibId().GetLibNickname().wx_str() != aFrom )
2146 continue;
2147
2148 LIB_ID id = symbol->GetLibId();
2149 id.SetLibNickname( aTo );
2150 symbol->SetLibId( id );
2151 cnt++;
2152 }
2153 }
2154
2155 return cnt;
2156}
2157
2158
2159bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
2160{
2161 for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2162 {
2163 if( screen->GetFileName() == aSchematicFileName )
2164 return true;
2165 }
2166
2167 return false;
2168}
2169
2170
2172{
2173 SCH_SCREEN* first = GetFirst();
2174
2175 if( !first )
2176 return;
2177
2178 SCHEMATIC* sch = first->Schematic();
2179
2180 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
2181
2182 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
2183 curr_screen->GetClientSheetPaths().clear();
2184
2185 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
2186 {
2187 SCH_SCREEN* used_screen = sheetpath.LastScreen();
2188
2189 // Search for the used_screen in list and add this unique sheet path:
2190 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
2191 {
2192 if( used_screen == curr_screen )
2193 {
2194 curr_screen->GetClientSheetPaths().push_back( sheetpath );
2195 break;
2196 }
2197 }
2198 }
2199}
2200
2201
2203{
2204 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2205 screen->SetLegacySymbolInstanceData();
2206}
2207
2208
2210{
2211 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2212 screen->FixLegacyPowerSymbolMismatches();
2213}
2214
2215
2217{
2218 LOCALE_IO toggle;
2219
2220 // V6 schematics may specify model names in Value fields, which we don't do in V7.
2221 // Migrate by adding an equivalent model for these symbols.
2222
2223 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
2224 {
2225 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2226 SIM_MODEL::MigrateSimModel<SCH_SYMBOL>( *symbol, &Schematic()->Project() );
2227 }
2228}
2229
2230
2231void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
2232 const SCH_SHEET_LIST& aValidSheetPaths )
2233{
2234 if( aProjectName.IsEmpty() )
2235 return;
2236
2237 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2238 screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
2239}
2240
2241
2242void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
2243 const SCH_SHEET_LIST& aValidSheetPaths )
2244{
2245 if( aProjectName.IsEmpty() )
2246 return;
2247
2248 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2249 screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
2250}
2251
2252
2254{
2255 for( const SCH_SCREEN* screen : m_screens )
2256 {
2257 if( screen->HasSymbolFieldNamesWithWhiteSpace() )
2258 return true;
2259 }
2260
2261 return false;
2262}
2263
2264
2265std::set<wxString> SCH_SCREENS::GetVariantNames() const
2266{
2267 std::set<wxString> variantNames;
2268
2269 for( const SCH_SCREEN* screen : m_screens )
2270 {
2271 for( const wxString& variantName : screen->GetVariantNames() )
2272 variantNames.emplace( variantName );
2273 }
2274
2275 return variantNames;
2276}
2277
2278
2279void SCH_SCREENS::DeleteVariant( const wxString& aVariantName )
2280{
2281 wxCHECK( !aVariantName.IsEmpty(), /* void */ );
2282
2283 for( SCH_SCREEN* screen : m_screens )
2284 screen->DeleteVariant( aVariantName );
2285}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
int m_virtualPageNumber
An integer based page number used for printing a range of pages.
bool m_Center
Center on screen.
Definition base_screen.h:96
int m_pageCount
The number of BASE_SCREEN objects in this design.
BASE_SCREEN(EDA_ITEM *aParent, KICAD_T aType=SCREEN_T)
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
void InitDataPoints(const VECTOR2I &aPageSizeInternalUnits)
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr void SetOrigin(const Vec &pos)
Definition box2.h:237
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
static void sort_dangling_end_items(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos)
Both contain the same information.
Definition sch_item.cpp:825
EDA_ANGLE Normalize90()
Definition eda_angle.h:257
double AsDegrees() const
Definition eda_angle.h:116
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:110
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:142
const KIID m_Uuid
Definition eda_item.h:516
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
EDA_ITEM * GetParent() const
Definition eda_item.h:112
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:146
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:39
bool IsNew() const
Definition eda_item.h:124
void SetLineStyle(const LINE_STYLE aStyle)
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
EMBEDDED_FILE * GetEmbeddedFile(const wxString &aName) const
Returns the embedded file with the given name or nullptr if it does not exist.
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Definition kiid.h:49
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
wxString GetUniStringLibId() const
Definition lib_id.h:148
UTF8 Format() const
Definition lib_id.cpp:119
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition lib_id.h:112
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:87
Define a library symbol object.
Definition lib_symbol.h:87
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:156
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition lib_symbol.h:690
wxString GetName() const override
Definition lib_symbol.h:150
bool IsGlobalPower() const override
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
void SetLibId(const LIB_ID &aLibId)
Definition lib_symbol.h:157
virtual void SetName(const wxString &aName)
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:41
bool IsExcluded() const
Definition marker_base.h:93
std::shared_ptr< RC_ITEM > GetRCItem() const
enum MARKER_T GetMarkerType() const
Definition marker_base.h:91
Base plotter engine class.
Definition plotter.h:121
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:152
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
A small class to help profiling.
Definition profile.h:49
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
Definition profile.h:105
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition profile.h:88
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
static SYMBOL_LIBS * SchLibs(PROJECT *aProject)
These are all prefaced with "Sch".
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition reporter.h:112
Holds all the data relating to one schematic.
Definition schematic.h:88
SCHEMATIC_SETTINGS & Settings() const
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
EMBEDDED_FILES * GetEmbeddedFiles() override
CONNECTION_GRAPH * ConnectionGraph() const
Definition schematic.h:183
SCH_SHEET & Root() const
Definition schematic.h:140
Class for a wire to bus entry.
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:52
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
virtual bool IsEndPoint(const VECTOR2I &aPt) const
Test if aPt is an end point of this schematic object.
Definition sch_item.h:496
virtual bool IsConnectable() const
Definition sch_item.h:505
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:244
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:321
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Definition sch_item.cpp:343
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:520
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:42
void SetStartPoint(const VECTOR2I &aPosition)
Definition sch_line.h:140
std::vector< VECTOR3I > BuildWireWithHopShape(const SCH_SCREEN *aScreen, double aArcRadius) const
For wires only: build the list of points to draw the shape using segments and 180 deg arcs Points are...
bool IsWire() const
Return true if the line is a wire.
Definition sch_line.cpp:989
EDA_ANGLE Angle() const
Get the angle between the start and end lines.
Definition sch_line.h:104
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
Definition sch_line.cpp:880
VECTOR2I GetEndPoint() const
Definition sch_line.h:148
VECTOR2I GetStartPoint() const
Definition sch_line.h:139
bool IsEndPoint(const VECTOR2I &aPoint) const override
Test if aPt is an end point of this schematic object.
Definition sch_line.h:91
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:149
SCH_SCREEN * GetNext()
unsigned int m_index
Definition sch_screen.h:871
std::vector< SCH_SHEET * > m_sheets
Definition sch_screen.h:870
SCH_SCREEN * GetScreen(unsigned int aIndex) const
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
void DeleteMarker(SCH_MARKER *aMarker)
Delete a specific marker.
void DeleteMarkers(enum MARKER_BASE::MARKER_T aMarkerTyp, int aErrorCode, bool aIncludeExclusions=true)
Delete all markers of a particular type and error code.
void buildScreenList(SCH_SHEET *aSheet)
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
SCH_SCREEN * GetFirst()
void DeleteAllMarkers(enum MARKER_BASE::MARKER_T aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
int ChangeSymbolLibNickname(const wxString &aFrom, const wxString &aTo)
Change all of the symbol library nicknames.
SCH_SCREENS(SCH_SHEET *aSheet)
void BuildClientSheetPathList()
Build the list of sheet paths sharing a screen for each screen in use.
bool HasSymbolFieldNamesWithWhiteSpace() const
void ClearAnnotationOfNewSheetPaths(SCH_SHEET_LIST &aInitialSheetPathList)
Clear the annotation for the symbols inside new sheetpaths when a complex hierarchy is modified and n...
void DeleteVariant(const wxString &aVariantName)
void PruneOrphanedSymbolInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
bool HasNoFullyDefinedLibIds()
Test all of the schematic symbols to see if all LIB_ID objects library nickname is not set.
void ClearEditFlags()
SCH_SHEET * GetSheet(unsigned int aIndex) const
int ReplaceDuplicateTimeStamps()
Test all sheet and symbol objects in the schematic for duplicate time stamps and replaces them as nec...
std::set< wxString > GetVariantNames() const
std::vector< SCH_SCREEN * > m_screens
Definition sch_screen.h:869
bool HasSchematic(const wxString &aSchematicFileName)
Check if one of the schematics in the list of screens is aSchematicFileName.
size_t GetLibNicknames(wxArrayString &aLibNicknames)
Fetch all of the symbol library nicknames into aLibNicknames.
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
void addScreenToList(SCH_SCREEN *aScreen, SCH_SHEET *aSheet)
std::set< wxString > GetVariantNames() const
std::map< wxString, LIB_SYMBOL * > m_libSymbols
Library symbols required for this schematic.
Definition sch_screen.h:692
SCH_PIN * GetPin(const VECTOR2I &aPosition, SCH_SYMBOL **aSymbol=nullptr, bool aEndPointOnly=false) const
Test the screen for a symbol pin item at aPosition.
bool m_fileExists
Flag to indicate the file associated with this screen has been created.
Definition sch_screen.h:689
void ClearDrawingState()
Clear the state flags of all the items in the screen.
SCH_LINE * GetLine(const VECTOR2I &aPosition, int aAccuracy=0, int aLayer=LAYER_NOTES, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Return a line item located at aPosition.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
bool HasSymbolFieldNamesWithWhiteSpace() const
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition.
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
bool HasItems(KICAD_T aItemType) const
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
bool HasInstanceDataFromOtherProjects() const
Check symbols for instance data from other projects.
void PruneOrphanedSymbolInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
Remove all invalid symbol instance data in this screen object for the project defined by aProjectName...
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition sch_screen.h:186
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project SYMB...
SCH_LINE * GetWire(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition sch_screen.h:436
std::set< wxString > GetSheetNames() const
TITLE_BLOCK m_titles
Definition sch_screen.h:676
void TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr, std::function< void(SCH_ITEM *)> *aChangedHandler=nullptr) const
Test all of the connectable objects in the schematic for unused connection points.
void EnsureAlternateReferencesExist()
For screens shared by many sheetpaths (complex hierarchies): to be able to clear or modify any refere...
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
Remove all invalid sheet instance data in this screen object for the project defined by aProjectName ...
std::vector< SCH_LINE * > GetBusesAndWires(const VECTOR2I &aPosition, bool aIgnoreEndpoints=false) const
Return buses and wires passing through aPosition.
wxString GroupsSanityCheckInternal(bool repair)
int m_modification_sync
Definition sch_screen.h:680
double m_LastZoomLevel
last value for the zoom level, useful in Eeschema when changing the current displayed sheet to reuse ...
Definition sch_screen.h:658
bool IsExplicitJunction(const VECTOR2I &aPosition) const
Indicate that a junction dot is necessary at the given location.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:117
int m_fileFormatVersionAtLoad
Definition sch_screen.h:662
void DecRefCount()
std::set< SCH_ITEM * > MarkConnections(SCH_LINE *aSegment, bool aSecondPass)
Return all wires and junctions connected to aSegment which are not connected any symbol pin or all gr...
SCH_ITEM * GetItem(const VECTOR2I &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicate that a junction dot may be placed at the given location.
void clearLibSymbols()
wxString m_fileName
Definition sch_screen.h:661
bool IsTerminalPoint(const VECTOR2I &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void IncRefCount()
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
static bool ClassOf(const EDA_ITEM *aItem)
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
void DeleteVariant(const wxString &aVariantName)
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition sch_screen.h:442
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
SCH_SCREEN(EDA_ITEM *aParent=nullptr)
SCHEMATIC * Schematic() const
EE_RTREE m_rtree
Definition sch_screen.h:678
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
void GetHierarchicalItems(std::vector< SCH_ITEM * > *aItems) const
Add all schematic sheet and symbol objects in the screen to aItems.
bool IsExplicitJunctionNeeded(const VECTOR2I &aPosition) const
Indicate that a junction dot is necessary at the given location, and does not yet exist.
SCH_SHEET_PIN * GetSheetPin(const VECTOR2I &aPosition) const
Test the screen if aPosition is a sheet label object.
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
bool InProjectPath() const
Check if the schematic file is in the current project path.
void FreeDrawList()
Free all the items from the schematic associated with the screen.
void Plot(PLOTTER *aPlotter, const SCH_PLOT_OPTS &aPlotOpts) const
Plot all the schematic objects to aPlotter.
virtual wxString GetClass() const override
Return the class name.
Definition sch_screen.h:131
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
void SetConnectivityDirty()
bool m_zoomInitialized
Definition sch_screen.h:683
std::vector< VECTOR2I > GetNeededJunctions(const std::deque< EDA_ITEM * > &aItems) const
Return the unique set of points belonging to aItems where a junction is needed.
PAGE_INFO m_paper
Definition sch_screen.h:675
bool IsJunction(const VECTOR2I &aPosition) const
Test if a junction is required for the items at aPosition on the screen.
bool m_isReadOnly
Read only status of the screen file.
Definition sch_screen.h:686
void GetSheets(std::vector< SCH_ITEM * > *aItems) const
Similar to Items().OfType( SCH_SHEET_T ), but return the sheets in a deterministic order (L-R,...
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
std::vector< VECTOR2I > GetConnections() const
Collect a unique list of all possible connection points in the schematic.
SPIN_STYLE GetLabelOrientationForPoint(const VECTOR2I &aPosition, SPIN_STYLE aDefaultOrientation, const SCH_SHEET_PATH *aSheet) const
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear the annotation for the symbols in aSheetPath on the screen.
size_t CountConnectedItems(const VECTOR2I &aPos, bool aTestJunctions) const
void MigrateSimModels()
Migrate any symbols having V6 simulation models to their V7 equivalents.
void DeleteItem(SCH_ITEM *aItem)
Remove aItem from the linked list and deletes the object.
size_t getLibSymbolNameMatches(const SCH_SYMBOL &aSymbol, std::vector< wxString > &aMatches)
Return a list of potential library symbol matches for aSymbol.
SCH_LABEL_BASE * GetLabel(const VECTOR2I &aPosition, int aAccuracy=0) const
Return a label item located at aPosition.
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
bool HasPath(const KIID_PATH &aPath) const
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Define a sheet pin (label) used in sheets to create hierarchical schematics.
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:47
void RemoveInstance(const KIID_PATH &aInstancePath)
wxString GetName() const
Definition sch_sheet.h:113
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:116
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:458
Schematic symbol object.
Definition sch_symbol.h:75
void SetLibId(const LIB_ID &aName)
SCH_ITEM * GetDrawItem(const VECTOR2I &aPosition, KICAD_T aType=TYPE_NOT_INIT)
Return the symbol library item at aPosition that is part of this symbol.
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:134
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
void SetValueFieldText(const wxString &aValue)
wxString GetSchSymbolLibraryName() const
bool AddSheetPathReferenceEntryIfMissing(const KIID_PATH &aSheetPath)
Add an instance to the alternate references list (m_instanceReferences), if this entry does not alrea...
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
std::vector< SCH_PIN * > GetAllLibPins() const
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:164
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition sch_symbol.h:179
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:183
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
VECTOR2I GetPinPhysicalPosition(const SCH_PIN *Pin) const
static void MigrateSimModel(T &aSymbol, const PROJECT *aProject)
A collection of SYMBOL_LIB objects.
int GetLibraryCount()
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
Object used to load, save, search, and otherwise manipulate symbol library files.
bool IsCache() const
LIB_SYMBOL * FindSymbol(const wxString &aName) const
Find LIB_SYMBOL by aName.
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:63
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
Definition symbol.h:211
for transforming drawing coordinates for a wxDC device context.
Definition transform.h:46
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition utf8.h:72
bool empty() const
Definition utf8.h:110
wxString wx_str() const
Definition utf8.cpp:45
#define _(s)
@ NO_RECURSE
Definition eda_item.h:52
#define IS_DELETED
#define STRUCT_DELETED
flag indication structures to be erased
#define IS_MOVING
Item being moved.
@ ERCE_UNSPECIFIED
static const wxChar DanglingProfileMask[]
Flag to enable connectivity profiling.
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
@ LAYER_WIRE
Definition layer_ids.h:452
@ LAYER_NOTES
Definition layer_ids.h:467
@ LAYER_BUS
Definition layer_ids.h:453
POINT_INFO AnalyzePoint(const EE_RTREE &aItem, const VECTOR2I &aPosition, bool aBreakCrossings)
Check a tree of items for a confluence at a given point and work out what kind of junction it is,...
PAGE_SIZE_TYPE
Definition page_info.h:50
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
Class to handle a set of SCH_ITEMs.
#define PROCESSED
SCH_LINE_TEST_T
Definition sch_screen.h:71
@ ENTIRE_LENGTH_T
Definition sch_screen.h:72
@ EXCLUDE_END_POINTS_T
Definition sch_screen.h:74
@ END_POINTS_ONLY_T
Definition sch_screen.h:73
wxString UnescapeString(const wxString &aSource)
The EE_TYPE struct provides a type-specific auto-range iterator to the RTree.
Definition sch_rtree.h:195
iterator begin()
Definition sch_rtree.h:225
iterator end()
Definition sch_rtree.h:230
std::vector< char > decompressedData
A selection of information about a point in the schematic that might be eligible for turning into a j...
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
SPIN_STYLE GetPinSpinStyle(const SCH_PIN &aPin, const SCH_SYMBOL &aSymbol)
Get the spin style for a pin's label, taking into account the pin's orientation, as well as the given...
Definition for symbol library class.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
VECTOR2I end
wxLogTrace helper definitions.
bool IsPointOnSegment(const VECTOR2I &aSegStart, const VECTOR2I &aSegEnd, const VECTOR2I &aTestPoint)
Test if aTestPoint is on line defined by aSegStart and aSegEnd.
Definition trigo.cpp:89
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:78
@ SCH_GROUP_T
Definition typeinfo.h:177
@ SCH_LINE_T
Definition typeinfo.h:167
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:175
@ SCH_LABEL_T
Definition typeinfo.h:171
@ SCH_SHEET_T
Definition typeinfo.h:179
@ SCH_MARKER_T
Definition typeinfo.h:162
@ SCH_HIER_LABEL_T
Definition typeinfo.h:173
@ SCH_SCREEN_T
Definition typeinfo.h:206
@ SCH_LABEL_LOCATE_ANY_T
Definition typeinfo.h:195
@ SCHEMATIC_T
Definition typeinfo.h:208
@ SCH_SHEET_PIN_T
Definition typeinfo.h:178
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:165
@ SCH_BITMAP_T
Definition typeinfo.h:168
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:172
@ SCH_JUNCTION_T
Definition typeinfo.h:163
@ SCH_PIN_T
Definition typeinfo.h:157
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695