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 (C) 1992-2024 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_junction.h>
50#include <sch_line.h>
51#include <sch_marker.h>
52#include <sch_sheet.h>
53#include <sch_sheet_pin.h>
54#include <sch_text.h>
55#include <schematic.h>
57#include <symbol_lib_table.h>
58#include <tool/common_tools.h>
59#include <sim/sim_model.h> // For V6 to V7 simulation model migration.
60#include <locale_io.h>
61
62#include <algorithm>
63
64// TODO(JE) Debugging only
65#include <core/profile.h>
66#include "sch_bus_entry.h"
67
68/*
69 * Flag to enable profiling of the TestDanglingEnds() function.
70 * @ingroup trace_env_vars
71 */
72static const wxChar DanglingProfileMask[] = wxT( "DANGLING_PROFILE" );
73
75 BASE_SCREEN( aParent, SCH_SCREEN_T ),
76 m_fileFormatVersionAtLoad( 0 ),
77 m_paper( wxT( "A4" ) ),
78 m_isReadOnly( false ),
79 m_fileExists( false )
80{
82 m_refCount = 0;
83 m_zoomInitialized = false;
84 m_LastZoomLevel = 1.0;
85
86 // Suitable for schematic only. For symbol_editor and viewlib, must be set to true
87 m_Center = false;
88
90}
91
92
94{
97}
98
99
101{
102 wxCHECK_MSG( GetParent() && GetParent()->Type() == SCHEMATIC_T, nullptr,
103 wxT( "SCH_SCREEN must have a SCHEMATIC parent!" ) );
104
105 return static_cast<SCHEMATIC*>( GetParent() );
106}
107
108
110{
111 for( const std::pair<const wxString, LIB_SYMBOL*>& libSymbol : m_libSymbols )
112 delete libSymbol.second;
113
114 m_libSymbols.clear();
115}
116
117
118void SCH_SCREEN::SetFileName( const wxString& aFileName )
119{
120 wxASSERT( aFileName.IsEmpty() || wxIsAbsolutePath( aFileName ) );
121
122 m_fileName = aFileName;
123}
124
125
127{
128 m_refCount++;
129}
130
131
133{
134 wxCHECK_RET( m_refCount != 0, wxT( "Screen reference count already zero. Bad programmer!" ) );
135 m_refCount--;
136}
137
138
139bool SCH_SCREEN::HasItems( KICAD_T aItemType ) const
140{
141 EE_RTREE::EE_TYPE sheets = m_rtree.OfType( aItemType );
142
143 return sheets.begin() != sheets.end();
144}
145
146
147bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
148{
149 return aItem && SCH_SCREEN_T == aItem->Type();
150}
151
152
153void SCH_SCREEN::Append( SCH_ITEM* aItem, bool aUpdateLibSymbol )
154{
155 if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
156 {
157 // Ensure the item can reach the SCHEMATIC through this screen
158 aItem->SetParent( this );
159
160 if( aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
161 {
162 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
163
164 if( symbol->GetLibSymbolRef() )
165 {
166 symbol->GetLibSymbolRef()->GetDrawItems().sort();
167
168 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
169
170 if( it == m_libSymbols.end() || !it->second )
171 {
173 new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
174 }
175 else
176 {
177 // The original library symbol may have changed since the last time
178 // it was added to the schematic. If it has changed, then a new name
179 // must be created for the library symbol list to prevent all of the
180 // other schematic symbols referencing that library symbol from changing.
181 LIB_SYMBOL* foundSymbol = it->second;
182
183 foundSymbol->GetDrawItems().sort();
184
185 if( *foundSymbol != *symbol->GetLibSymbolRef() )
186 {
187 wxString newName;
188 std::vector<wxString> matches;
189
190 getLibSymbolNameMatches( *symbol, matches );
191 foundSymbol = nullptr;
192
193 for( const wxString& libSymbolName : matches )
194 {
195 it = m_libSymbols.find( libSymbolName );
196
197 if( it == m_libSymbols.end() )
198 continue;
199
200 foundSymbol = it->second;
201
202 wxCHECK2( foundSymbol, continue );
203
204 wxString tmp = symbol->GetLibSymbolRef()->GetName();
205
206 // Temporarily update the new symbol library symbol name so it
207 // doesn't fail on the name comparison below.
208 symbol->GetLibSymbolRef()->SetName( foundSymbol->GetName() );
209
210 if( *foundSymbol == *symbol->GetLibSymbolRef() )
211 {
212 newName = libSymbolName;
213 symbol->GetLibSymbolRef()->SetName( tmp );
214 break;
215 }
216
217 symbol->GetLibSymbolRef()->SetName( tmp );
218 foundSymbol = nullptr;
219 }
220
221 if( !foundSymbol )
222 {
223 int cnt = 1;
224
225 newName.Printf( wxT( "%s_%d" ),
227 cnt );
228
229 while( m_libSymbols.find( newName ) != m_libSymbols.end() )
230 {
231 cnt += 1;
232 newName.Printf( wxT( "%s_%d" ),
234 cnt );
235 }
236 }
237
238 // Update the schematic symbol library link as this symbol only exists
239 // in the schematic.
240 symbol->SetSchSymbolLibraryName( newName );
241
242 if( !foundSymbol )
243 {
244 // Update the schematic symbol library link as this symbol does not
245 // exist in any symbol library.
246 LIB_ID newLibId( wxEmptyString, newName );
247 LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
248
249 newLibSymbol->SetLibId( newLibId );
250 newLibSymbol->SetName( newName );
251 symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
252 m_libSymbols[newName] = newLibSymbol;
253 }
254 }
255 }
256 }
257 }
258
259 m_rtree.insert( aItem );
261 }
262}
263
264
266{
267 wxCHECK_RET( aScreen, "Invalid screen object." );
268
269 // No need to descend the hierarchy. Once the top level screen is copied, all of its
270 // children are copied as well.
271 for( SCH_ITEM* aItem : aScreen->m_rtree )
272 Append( aItem );
273
274 aScreen->Clear( false );
275}
276
277
278void SCH_SCREEN::Clear( bool aFree )
279{
280 if( aFree )
281 {
282 FreeDrawList();
284 }
285 else
286 {
287 m_rtree.clear();
288 }
289
290 // Clear the project settings
292
293 m_titles.Clear();
294}
295
296
298{
299 // We don't know which order we will encounter dependent items (e.g. pins or fields), so
300 // we store the items to be deleted until we've fully cleared the tree before deleting
301 std::vector<SCH_ITEM*> delete_list;
302
303 std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
304 []( SCH_ITEM* aItem )
305 {
306 return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
307 } );
308
309 m_rtree.clear();
310
311 for( SCH_ITEM* item : delete_list )
312 delete item;
313}
314
315
316void SCH_SCREEN::Update( SCH_ITEM* aItem, bool aUpdateLibSymbol )
317{
318 if( Remove( aItem, aUpdateLibSymbol ) )
319 Append( aItem, aUpdateLibSymbol );
320}
321
322
323bool SCH_SCREEN::Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol )
324{
325 bool retv = m_rtree.remove( aItem );
326
327 // Check if the library symbol for the removed schematic symbol is still required.
328 if( retv && aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
329 {
330 SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
331
332 bool removeUnusedLibSymbol = true;
333
334 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
335 {
336 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
337
338 if( removedSymbol->GetSchSymbolLibraryName() == symbol->GetSchSymbolLibraryName() )
339 {
340 removeUnusedLibSymbol = false;
341 break;
342 }
343 }
344
345 if( removeUnusedLibSymbol )
346 {
347 auto it = m_libSymbols.find( removedSymbol->GetSchSymbolLibraryName() );
348
349 if( it != m_libSymbols.end() )
350 {
351 delete it->second;
352 m_libSymbols.erase( it );
353 }
354 }
355 }
356
357 return retv;
358}
359
360
362{
363 wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
364
365 // Markers are not saved in the file, no need to flag as modified.
366 // TODO: Maybe we should have a listing somewhere of items that aren't saved?
367 if( aItem->Type() != SCH_MARKER_T )
369
370 Remove( aItem );
371
372 if( aItem->Type() == SCH_SHEET_PIN_T )
373 {
374 // This structure is attached to a sheet, get the parent sheet object.
375 SCH_SHEET_PIN* sheetPin = (SCH_SHEET_PIN*) aItem;
376 SCH_SHEET* sheet = sheetPin->GetParent();
377 wxCHECK_RET( sheet, wxT( "Sheet pin parent not properly set, bad programmer!" ) );
378 sheet->RemovePin( sheetPin );
379 return;
380 }
381
382 delete aItem;
383}
384
385
386bool SCH_SCREEN::CheckIfOnDrawList( const SCH_ITEM* aItem ) const
387{
388 return m_rtree.contains( aItem, true );
389}
390
391
392SCH_ITEM* SCH_SCREEN::GetItem( const VECTOR2I& aPosition, int aAccuracy, KICAD_T aType ) const
393{
394 BOX2I bbox;
395 bbox.SetOrigin( aPosition );
396 bbox.Inflate( aAccuracy );
397
398 for( SCH_ITEM* item : Items().Overlapping( aType, bbox ) )
399 {
400 if( item->HitTest( aPosition, aAccuracy ) )
401 return item;
402 }
403
404 return nullptr;
405}
406
407
408std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aSecondPass )
409{
410#define PROCESSED CANDIDATE // Don't use SKIP_STRUCT; IsConnected() returns false if it's set.
411
412 std::set<SCH_ITEM*> retval;
413 std::stack<SCH_LINE*> to_search;
414
415 wxCHECK_MSG( aSegment && aSegment->Type() == SCH_LINE_T, retval, wxT( "Invalid pointer." ) );
416
417 to_search.push( aSegment );
418
419 while( !to_search.empty() )
420 {
421 SCH_ITEM* item = to_search.top();
422 to_search.pop();
423
424 if( item->HasFlag( PROCESSED ) )
425 continue;
426
427 item->SetFlags( PROCESSED );
428
429 for( SCH_ITEM* candidate : Items().Overlapping( SCH_LINE_T, item->GetBoundingBox() ) )
430 {
431 SCH_LINE* line = static_cast<SCH_LINE*>( candidate );
432
433 if( line->HasFlag( PROCESSED ) )
434 continue;
435
436 // Skip connecting lines on different layers (e.g. buses)
437 if( item->GetLayer() != line->GetLayer() )
438 continue;
439
440 for( VECTOR2I pt : { line->GetStartPoint(), line->GetEndPoint() } )
441 {
442 if( item->IsConnected( pt ) )
443 {
444 SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T );
445 SCH_ITEM* pin = GetItem( pt, 0, SCH_PIN_T );
446
447 if( item->IsSelected() && aSecondPass )
448 {
449 if( junction )
450 retval.insert( junction );
451
452 retval.insert( line );
453 to_search.push( line );
454 }
455 else if( !junction && !pin )
456 {
457 retval.insert( line );
458 to_search.push( line );
459 }
460
461 break;
462 }
463 else if( line->GetLayer() == LAYER_NOTES && item->GetLayer() == LAYER_NOTES )
464 {
465 retval.insert( line );
466 to_search.push( line );
467 }
468 }
469 }
470 }
471
472 for( SCH_ITEM* item : Items() )
473 item->ClearTempFlags();
474
475 return retval;
476}
477
478
479bool SCH_SCREEN::IsJunction( const VECTOR2I& aPosition ) const
480{
482 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
483 return info.isJunction;
484}
485
486
487bool SCH_SCREEN::IsExplicitJunction( const VECTOR2I& aPosition ) const
488{
490 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
491
492 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires );
493}
494
495
496bool SCH_SCREEN::IsExplicitJunctionNeeded( const VECTOR2I& aPosition ) const
497{
499 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
500
501 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires )
502 && !info.hasExplicitJunctionDot;
503}
504
505
507{
509 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, true );
510
511 return info.isJunction && (!info.hasBusEntry || info.hasBusEntryToMultipleWires );
512}
513
514
516 SPIN_STYLE aDefaultOrientation,
517 const SCH_SHEET_PATH* aSheet ) const
518{
519 auto ret = aDefaultOrientation;
520 for( SCH_ITEM* item : Items().Overlapping( aPosition ) )
521 {
522 if( item->GetEditFlags() & STRUCT_DELETED )
523 continue;
524
525 switch( item->Type() )
526 {
528 {
529 auto busEntry = static_cast<const SCH_BUS_WIRE_ENTRY*>( item );
530 if( busEntry->m_connected_bus_item )
531 {
532 // bus connected, take the bus direction into consideration ony if it is
533 // vertical or horizontal
534 auto bus = static_cast<const SCH_LINE*>( busEntry->m_connected_bus_item );
535 if( bus->Angle().AsDegrees() == 90.0 )
536 {
537 // bus is vertical -> label shall be horizontal and
538 // shall be placed to the side where the bus entry is
539 if( aPosition.x < bus->GetPosition().x )
540 ret = SPIN_STYLE::LEFT;
541 else if( aPosition.x > bus->GetPosition().x )
542 ret = SPIN_STYLE::RIGHT;
543 }
544 else if( bus->Angle().AsDegrees() == 0.0 )
545 {
546 // bus is horizontal -> label shall be vertical and
547 // shall be placed to the side where the bus entry is
548 if( aPosition.y < bus->GetPosition().y )
549 ret = SPIN_STYLE::UP;
550 else if( aPosition.y > bus->GetPosition().y )
551 ret = SPIN_STYLE::BOTTOM;
552 }
553 }
554 }
555 break;
556
557 case SCH_LINE_T:
558 {
559 auto line = static_cast<const SCH_LINE*>( item );
560 // line angles goes between -90 and 90 degrees, but normalize
561 auto angle = line->Angle().Normalize90().AsDegrees();
562
563 if( -45 < angle && angle <= 45 )
564 {
565 if( line->GetStartPoint().x <= line->GetEndPoint().x )
566 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::RIGHT : SPIN_STYLE::LEFT;
567 else
568 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::LEFT : SPIN_STYLE::RIGHT;
569 }
570 else
571 {
572 if( line->GetStartPoint().y <= line->GetEndPoint().y )
573 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::BOTTOM : SPIN_STYLE::UP;
574 else
575 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::UP : SPIN_STYLE::BOTTOM;
576 }
577 }
578 break;
579
580 case SCH_SYMBOL_T:
581 {
582 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
583
584 for( SCH_PIN* pin : symbol->GetPins( aSheet ) )
585 {
586 if( pin->GetPosition() == aPosition )
587 {
588 ret = GetPinSpinStyle( *pin, *symbol );
589 break;
590 }
591 }
592 }
593 break;
594 default: break;
595 }
596 }
597 return ret;
598}
599
600
601bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
602{
603 wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
604 wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
605
606 SCH_SHEET_PIN* sheetPin;
607 SCH_LABEL_BASE* label;
608
609 switch( aLayer )
610 {
611 case LAYER_BUS:
612 if( GetBus( aPosition ) )
613 return true;
614
615 sheetPin = GetSheetPin( aPosition );
616
617 if( sheetPin && sheetPin->IsConnected( aPosition ) )
618 return true;
619
620 label = GetLabel( aPosition );
621
622 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
623 return true;
624
625 break;
626
627 case LAYER_NOTES:
628 if( GetLine( aPosition ) )
629 return true;
630
631 break;
632
633 case LAYER_WIRE:
634 if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T ) )
635 return true;
636
637 if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
638 return true;
639
640 if( GetPin( aPosition, nullptr, true ) )
641 return true;
642
643 if( GetWire( aPosition ) )
644 return true;
645
646 label = GetLabel( aPosition, 1 );
647
648 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
649 return true;
650
651 sheetPin = GetSheetPin( aPosition );
652
653 if( sheetPin && sheetPin->IsConnected( aPosition ) )
654 return true;
655
656 break;
657
658 default:
659 break;
660 }
661
662 return false;
663}
664
665
667{
668 wxCHECK_RET( Schematic(), "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" );
669
670 wxString msg;
671 std::unique_ptr< LIB_SYMBOL > libSymbol;
672 std::vector<SCH_SYMBOL*> symbols;
674
675 // This will be a nullptr if an s-expression schematic is loaded.
676 SYMBOL_LIBS* legacyLibs = PROJECT_SCH::SchLibs( &Schematic()->Prj() );
677
678 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
679 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
680
681 // Remove them from the R tree. There bounding box size may change.
682 for( SCH_SYMBOL* symbol : symbols )
683 Remove( symbol );
684
685 // Clear all existing symbol links.
687
688 for( SCH_SYMBOL* symbol : symbols )
689 {
690 LIB_SYMBOL* tmp = nullptr;
691 libSymbol.reset();
692
693 // If the symbol is already in the internal library, map the symbol to it.
694 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
695
696 if( ( it != m_libSymbols.end() ) )
697 {
698 if( aReporter )
699 {
700 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
701 symbol->GetField( REFERENCE_FIELD )->GetText(),
702 symbol->GetField( VALUE_FIELD )->GetText(),
703 UnescapeString( symbol->GetLibId().Format() ) );
704 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
705 }
706
707 // Internal library symbols are already flattened so just make a copy.
708 symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
709 continue;
710 }
711
712 if( !symbol->GetLibId().IsValid() )
713 {
714 if( aReporter )
715 {
716 msg.Printf( _( "Schematic symbol reference '%s' library identifier is not valid. "
717 "Unable to link library symbol." ),
718 UnescapeString( symbol->GetLibId().Format() ) );
719 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
720 }
721
722 continue;
723 }
724
725 // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the library nickname
726 // is not found in the table so check if the library still exists in the table
727 // before attempting to load the symbol.
728 if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
729 {
730 if( aReporter )
731 {
732 msg.Printf( _( "Symbol library '%s' not found and no fallback cache library "
733 "available. Unable to link library symbol." ),
734 symbol->GetLibId().GetLibNickname().wx_str() );
735 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
736 }
737
738 continue;
739 }
740
741 if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
742 {
743 try
744 {
745 tmp = libs->LoadSymbol( symbol->GetLibId() );
746 }
747 catch( const IO_ERROR& ioe )
748 {
749 if( aReporter )
750 {
751 msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
752 UnescapeString( symbol->GetLibId().Format() ) );
753 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
754 }
755 }
756 }
757
758 if( !tmp && legacyLibs && legacyLibs->GetLibraryCount() )
759 {
760 SYMBOL_LIB& legacyCacheLib = legacyLibs->back();
761
762 // It better be the cache library.
763 wxCHECK2( legacyCacheLib.IsCache(), continue );
764
765 wxString id = symbol->GetLibId().Format();
766
767 id.Replace( ':', '_' );
768
769 if( aReporter )
770 {
771 msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
772 symbol->GetField( REFERENCE_FIELD )->GetText(),
773 symbol->GetField( VALUE_FIELD )->GetText(),
774 UnescapeString( id ) );
775 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
776 }
777
778 tmp = legacyCacheLib.FindSymbol( id );
779 }
780
781 if( tmp )
782 {
783 // We want a full symbol not just the top level child symbol.
784 libSymbol = tmp->Flatten();
785 libSymbol->SetParent();
786
787 m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
788 new LIB_SYMBOL( *libSymbol.get() ) } );
789
790 if( aReporter )
791 {
792 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
793 symbol->GetField( REFERENCE_FIELD )->GetText(),
794 symbol->GetField( VALUE_FIELD )->GetText(),
795 UnescapeString( symbol->GetLibId().Format() ) );
796 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
797 }
798 }
799 else
800 {
801 if( aReporter )
802 {
803 msg.Printf( _( "No library symbol found for schematic symbol '%s %s'." ),
804 symbol->GetField( REFERENCE_FIELD )->GetText(),
805 symbol->GetField( VALUE_FIELD )->GetText() );
806 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
807 }
808 }
809
810 if( libSymbol.get() ) // Only change the old link if the new link exists
811 symbol->SetLibSymbol( libSymbol.release() );
812 }
813
814 // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
815 // item with the new bbox
816 for( SCH_SYMBOL* symbol : symbols )
817 Append( symbol );
818}
819
820
822{
823 std::vector<SCH_SYMBOL*> symbols;
824
825 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
826 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
827
828 for( SCH_SYMBOL* symbol : symbols )
829 {
830 // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
831 m_rtree.remove( symbol );
832
833 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
834
835 LIB_SYMBOL* libSymbol = nullptr;
836
837 if( it != m_libSymbols.end() )
838 libSymbol = new LIB_SYMBOL( *it->second );
839
840 symbol->SetLibSymbol( libSymbol );
841
842 m_rtree.insert( symbol );
843 }
844}
845
846
848{
849 for( SCH_ITEM* item : Items() )
850 item->SetConnectivityDirty( true );
851}
852
853
855{
856 // Ensure links are up to date, even if a library was reloaded for some reason:
857 std::vector<SCH_ITEM*> junctions;
858 std::vector<SCH_ITEM*> bitmaps;
859 std::vector<SCH_ITEM*> other;
860
861 for( SCH_ITEM* item : Items() )
862 {
863 if( item->IsMoving() )
864 continue;
865
866 if( item->Type() == SCH_JUNCTION_T )
867 junctions.push_back( item );
868 else if( item->Type() == SCH_BITMAP_T )
869 bitmaps.push_back( item );
870 else
871 other.push_back( item );
872 }
873
875 std::stable_sort( other.begin(), other.end(),
876 []( const SCH_ITEM* a, const SCH_ITEM* b )
877 {
878 if( a->Type() == b->Type() )
879 return a->GetLayer() > b->GetLayer();
880
881 return a->Type() < b->Type();
882 } );
883
884 for( SCH_ITEM* item : bitmaps )
885 item->Print( aSettings, 0, 0, VECTOR2I( 0, 0 ), false, false );
886
887 for( SCH_ITEM* item : other )
888 item->PrintBackground( aSettings, 0, 0, VECTOR2I( 0, 0 ), false );
889
890 for( SCH_ITEM* item : other )
891 item->Print( aSettings, 0, 0, VECTOR2I( 0, 0 ), false, false );
892
893 for( SCH_ITEM* item : junctions )
894 item->Print( aSettings, 0, 0, VECTOR2I( 0, 0 ), false, false );
895}
896
897
898void SCH_SCREEN::Plot( PLOTTER* aPlotter, const SCH_PLOT_OPTS& aPlotOpts ) const
899{
900 // Ensure links are up to date, even if a library was reloaded for some reason:
901 std::vector<SCH_ITEM*> junctions;
902 std::vector<SCH_ITEM*> bitmaps;
903 std::vector<SCH_SYMBOL*> symbols;
904 std::vector<SCH_ITEM*> other;
905
906 for( SCH_ITEM* item : Items() )
907 {
908 if( item->IsMoving() )
909 continue;
910
911 if( item->Type() == SCH_JUNCTION_T )
912 junctions.push_back( item );
913 else if( item->Type() == SCH_BITMAP_T )
914 bitmaps.push_back( item );
915 else
916 other.push_back( item );
917
918 // Where the symbols overlap each other, we need to plot the text items a second
919 // time to get them on top of the overlapping element. This collection is in addition
920 // to the symbols already collected in `other`
921 if( item->Type() == SCH_SYMBOL_T )
922 {
923 for( SCH_ITEM* sym : m_rtree.Overlapping( SCH_SYMBOL_T, item->GetBoundingBox() ) )
924 {
925 if( sym != item )
926 {
927 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
928 break;
929 }
930 }
931 }
932 }
933
935 std::sort( other.begin(), other.end(),
936 []( const SCH_ITEM* a, const SCH_ITEM* b )
937 {
938 if( a->Type() == b->Type() )
939 return a->GetLayer() > b->GetLayer();
940
941 return a->Type() > b->Type();
942 } );
943
944 auto* renderSettings = static_cast<SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() );
945 constexpr bool background = true;
946
947 // Bitmaps are drawn first to ensure they are in the background
948 // This is particularly important for the wxPostscriptDC (used in *nix printers) as
949 // the bitmap PS command clears the screen
950 for( SCH_ITEM* item : bitmaps )
951 {
952 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
953 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
954 }
955
956 // Plot the background items
957 for( SCH_ITEM* item : other )
958 {
959 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
960 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
961 }
962
963 // Plot the foreground items
964 for( SCH_ITEM* item : other )
965 {
966 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
967 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
968 }
969
970 // After plotting the symbols as a group above (in `other`), we need to overplot the pins
971 // and symbols to ensure that they are always visible
972 TRANSFORM savedTransform = renderSettings->m_Transform;
973
974 for( const SCH_SYMBOL* sym :symbols )
975 {
976 renderSettings->m_Transform = sym->GetTransform();
977 aPlotter->SetCurrentLineWidth( sym->GetEffectivePenWidth( renderSettings ) );
978
979 for( SCH_FIELD field : sym->GetFields() )
980 {
981 field.ClearRenderCache();
982 field.Plot( aPlotter, false, aPlotOpts, sym->GetUnit(), sym->GetBodyStyle(), { 0, 0 },
983 sym->GetDNP() );
984 }
985
986 sym->PlotPins( aPlotter );
987
988 if( sym->GetDNP() )
989 sym->PlotDNP( aPlotter );
990 }
991
992 renderSettings->m_Transform = savedTransform;
993
994 for( SCH_ITEM* item : junctions )
995 {
996 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
997 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
998 }
999}
1000
1001
1003{
1004 for( SCH_ITEM* item : Items() )
1005 item->ClearTempFlags();
1006}
1007
1008
1009SCH_PIN* SCH_SCREEN::GetPin( const VECTOR2I& aPosition, SCH_SYMBOL** aSymbol,
1010 bool aEndPointOnly ) const
1011{
1012 SCH_SYMBOL* candidate = nullptr;
1013 SCH_PIN* pin = nullptr;
1014
1015 for( SCH_ITEM* item : Items().Overlapping( SCH_SYMBOL_T, aPosition ) )
1016 {
1017 candidate = static_cast<SCH_SYMBOL*>( item );
1018
1019 if( aEndPointOnly )
1020 {
1021 pin = nullptr;
1022
1023 if( !candidate->GetLibSymbolRef() )
1024 continue;
1025
1026 for( SCH_PIN* test_pin : candidate->GetLibPins() )
1027 {
1028 if( candidate->GetPinPhysicalPosition( test_pin ) == aPosition )
1029 {
1030 pin = test_pin;
1031 break;
1032 }
1033 }
1034
1035 if( pin )
1036 break;
1037 }
1038 else
1039 {
1040 pin = static_cast<SCH_PIN*>( candidate->GetDrawItem( aPosition, SCH_PIN_T ) );
1041
1042 if( pin )
1043 break;
1044 }
1045 }
1046
1047 if( pin && aSymbol )
1048 *aSymbol = candidate;
1049
1050 return pin;
1051}
1052
1053
1055{
1056 SCH_SHEET_PIN* sheetPin = nullptr;
1057
1058 for( SCH_ITEM* item : Items().Overlapping( SCH_SHEET_T, aPosition ) )
1059 {
1060 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1061
1062 sheetPin = sheet->GetPin( aPosition );
1063
1064 if( sheetPin )
1065 break;
1066 }
1067
1068 return sheetPin;
1069}
1070
1071
1072size_t SCH_SCREEN::CountConnectedItems( const VECTOR2I& aPos, bool aTestJunctions ) const
1073{
1074 size_t count = 0;
1075
1076 for( const SCH_ITEM* item : Items().Overlapping( aPos ) )
1077 {
1078 if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
1079 count++;
1080 }
1081
1082 return count;
1083}
1084
1085
1086void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1087{
1088
1089 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1090 {
1091 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1092
1093 symbol->ClearAnnotation( aSheetPath, aResetPrefix );
1094 }
1095}
1096
1097
1099{
1100 if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
1101 return;
1102
1103 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1104 {
1105 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1106
1107 // Add (when not existing) all sheet path entries
1108 for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
1109 symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
1110 }
1111}
1112
1113
1114void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems ) const
1115{
1116 static const std::vector<KICAD_T> hierarchicalTypes = { SCH_SYMBOL_T,
1119
1120 for( SCH_ITEM* item : Items() )
1121 {
1122 if( item->IsType( hierarchicalTypes ) )
1123 aItems->push_back( item );
1124 }
1125}
1126
1127
1128void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
1129{
1130 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1131 aItems->push_back( item );
1132
1133 std::sort( aItems->begin(), aItems->end(),
1134 []( EDA_ITEM* a, EDA_ITEM* b ) -> bool
1135 {
1136 if( a->GetPosition().x == b->GetPosition().x )
1137 {
1138 // Ensure deterministic sort
1139 if( a->GetPosition().y == b->GetPosition().y )
1140 return a->m_Uuid < b->m_Uuid;
1141
1142 return a->GetPosition().y < b->GetPosition().y;
1143 }
1144 else
1145 {
1146 return a->GetPosition().x < b->GetPosition().x;
1147 }
1148 } );
1149}
1150
1151
1153 std::function<void( SCH_ITEM* )>* aChangedHandler ) const
1154{
1155 PROF_TIMER timer( __FUNCTION__ );
1156
1157 std::vector<DANGLING_END_ITEM> endPointsByPos;
1158 std::vector<DANGLING_END_ITEM> endPointsByType;
1159
1160 auto get_ends =
1161 [&]( SCH_ITEM* item )
1162 {
1163 if( item->IsConnectable() )
1164 item->GetEndPoints( endPointsByType );
1165 };
1166
1167 auto update_state =
1168 [&]( SCH_ITEM* item )
1169 {
1170 if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
1171 {
1172 if( aChangedHandler )
1173 ( *aChangedHandler )( item );
1174 }
1175 };
1176
1177 for( SCH_ITEM* item : Items() )
1178 {
1179 get_ends( item );
1180 item->RunOnChildren( get_ends );
1181 }
1182
1183 PROF_TIMER sortTimer( "SCH_SCREEN::TestDanglingEnds pre-sort" );
1184 endPointsByPos = endPointsByType;
1185 DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
1186 sortTimer.Stop();
1187
1188 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1189 sortTimer.Show();
1190
1191 for( SCH_ITEM* item : Items() )
1192 {
1193 update_state( item );
1194 item->RunOnChildren( update_state );
1195 }
1196
1197 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1198 timer.Show();
1199}
1200
1201
1202SCH_LINE* SCH_SCREEN::GetLine( const VECTOR2I& aPosition, int aAccuracy, int aLayer,
1203 SCH_LINE_TEST_T aSearchType ) const
1204{
1205 // an accuracy of 0 had problems with rounding errors; use at least 1
1206 aAccuracy = std::max( aAccuracy, 1 );
1207
1208 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1209 {
1210 if( item->Type() != SCH_LINE_T )
1211 continue;
1212
1213 if( item->GetLayer() != aLayer )
1214 continue;
1215
1216 if( !item->HitTest( aPosition, aAccuracy ) )
1217 continue;
1218
1219 switch( aSearchType )
1220 {
1221 case ENTIRE_LENGTH_T:
1222 return (SCH_LINE*) item;
1223
1225 if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1226 return (SCH_LINE*) item;
1227 break;
1228
1229 case END_POINTS_ONLY_T:
1230 if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1231 return (SCH_LINE*) item;
1232 }
1233 }
1234
1235 return nullptr;
1236}
1237
1238
1239std::vector<SCH_LINE*> SCH_SCREEN::GetBusesAndWires( const VECTOR2I& aPosition,
1240 bool aIgnoreEndpoints ) const
1241{
1242 std::vector<SCH_LINE*> retVal;
1243
1244 for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, aPosition ) )
1245 {
1246 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } ) )
1247 {
1248 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
1249
1250 if( aIgnoreEndpoints && wire->IsEndPoint( aPosition ) )
1251 continue;
1252
1253 if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), aPosition ) )
1254 retVal.push_back( wire );
1255 }
1256 }
1257
1258 return retVal;
1259}
1260
1261
1262std::vector<VECTOR2I> SCH_SCREEN::GetConnections() const
1263{
1264 std::vector<VECTOR2I> retval;
1265
1266 for( SCH_ITEM* item : Items() )
1267 {
1268 // Avoid items that are changing
1269 if( !( item->GetEditFlags() & ( IS_MOVING | IS_DELETED ) ) )
1270 {
1271 std::vector<VECTOR2I> pts = item->GetConnectionPoints();
1272 retval.insert( retval.end(), pts.begin(), pts.end() );
1273 }
1274 }
1275
1276 // We always have some overlapping connection points. Drop duplicates here
1277 std::sort( retval.begin(), retval.end(),
1278 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1279 {
1280 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1281 } );
1282 retval.erase( std::unique( retval.begin(), retval.end() ), retval.end() );
1283
1284 return retval;
1285}
1286
1287
1288std::vector<VECTOR2I> SCH_SCREEN::GetNeededJunctions( const std::deque<EDA_ITEM*>& aItems ) const
1289{
1290 std::vector<VECTOR2I> pts;
1291 std::vector<VECTOR2I> connections = GetConnections();
1292
1293 for( const EDA_ITEM* edaItem : aItems )
1294 {
1295 const SCH_ITEM* item = dynamic_cast<const SCH_ITEM*>( edaItem );
1296
1297 if( !item || !item->IsConnectable() )
1298 continue;
1299
1300 std::vector<VECTOR2I> new_pts = item->GetConnectionPoints();
1301 pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
1302
1303 // If the item is a line, we also add any connection points from the rest of the schematic
1304 // that terminate on the line after it is moved.
1305 if( item->Type() == SCH_LINE_T )
1306 {
1307 SCH_LINE* line = (SCH_LINE*) item;
1308
1309 for( const VECTOR2I& pt : connections )
1310 {
1311 if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
1312 pts.push_back( pt );
1313 }
1314 }
1315 }
1316
1317 // We always have some overlapping connection points. Drop duplicates here
1318 std::sort( pts.begin(), pts.end(),
1319 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1320 {
1321 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1322 } );
1323
1324 pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
1325
1326 // We only want the needed junction points, remove all the others
1327 pts.erase( std::remove_if( pts.begin(), pts.end(),
1328 [this]( const VECTOR2I& a ) -> bool
1329 {
1330 return !IsExplicitJunctionNeeded( a );
1331 } ),
1332 pts.end() );
1333
1334 return pts;
1335}
1336
1337
1338SCH_LABEL_BASE* SCH_SCREEN::GetLabel( const VECTOR2I& aPosition, int aAccuracy ) const
1339{
1340 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1341 {
1342 switch( item->Type() )
1343 {
1344 case SCH_LABEL_T:
1345 case SCH_GLOBAL_LABEL_T:
1346 case SCH_HIER_LABEL_T:
1348 if( item->HitTest( aPosition, aAccuracy ) )
1349 return static_cast<SCH_LABEL_BASE*>( item );
1350
1351 break;
1352
1353 default:
1354 ;
1355 }
1356 }
1357
1358 return nullptr;
1359}
1360
1361
1363{
1364 wxCHECK( aLibSymbol, /* void */ );
1365
1366 wxString libSymbolName = aLibSymbol->GetLibId().Format().wx_str();
1367
1368 auto it = m_libSymbols.find( libSymbolName );
1369
1370 if( it != m_libSymbols.end() )
1371 {
1372 delete it->second;
1373 m_libSymbols.erase( it );
1374 }
1375
1376 m_libSymbols[libSymbolName] = aLibSymbol;
1377}
1378
1379
1381{
1382 SCHEMATIC* schematic = Schematic();
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}
1400
1401
1402void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
1403{
1404 m_aliases.insert( aAlias );
1405}
1406
1407
1409{
1410 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1411 {
1412 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1413
1414 // Add missing value and footprint instance data for legacy schematics.
1415 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1416 {
1417 symbol->AddHierarchicalReference( instance.m_Path, instance.m_Reference,
1418 instance.m_Unit );
1419 }
1420 }
1421}
1422
1423
1425{
1426 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1427 {
1428 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1429
1430 // Fix pre-8.0 legacy power symbols with invisible pins
1431 // that have mismatched pin names and value fields
1432 if( symbol->GetLibSymbolRef()
1433 && symbol->GetLibSymbolRef()->IsPower()
1434 && symbol->GetAllLibPins().size() > 0
1435 && symbol->GetAllLibPins()[0]->IsGlobalPower()
1436 && !symbol->GetAllLibPins()[0]->IsVisible() )
1437 {
1438 symbol->SetValueFieldText( symbol->GetAllLibPins()[0]->GetName() );
1439 }
1440 }
1441}
1442
1443
1445 std::vector<wxString>& aMatches )
1446{
1447 wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
1448
1449 if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
1450 aMatches.emplace_back( searchName );
1451
1452 searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
1453
1454 long tmp;
1455 wxString suffix;
1456
1457 for( auto& pair : m_libSymbols )
1458 {
1459 if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToLong( &tmp ) )
1460 aMatches.emplace_back( pair.first );
1461 }
1462
1463 return aMatches.size();
1464}
1465
1466
1467void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
1468 const SCH_SHEET_LIST& aValidSheetPaths )
1469{
1470 // The project name cannot be empty. Projects older than 7.0 did not save project names
1471 // when saving instance data. Running this algorithm with an empty project name would
1472 // clobber all instance data for projects other than the current one when a schematic
1473 // file is shared across multiple projects. Because running the schematic editor in
1474 // stand alone mode can result in an empty project name, do not assert here.
1475 if( aProjectName.IsEmpty() )
1476 return;
1477
1478 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1479 {
1480 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1481
1482 wxCHECK2( symbol, continue );
1483
1484 std::set<KIID_PATH> pathsToPrune;
1485 const std::vector<SCH_SYMBOL_INSTANCE> instances = symbol->GetInstances();
1486
1487 for( const SCH_SYMBOL_INSTANCE& instance : instances )
1488 {
1489 // Ignore instance paths from other projects.
1490 if( aProjectName != instance.m_ProjectName )
1491 continue;
1492
1493 std::optional<SCH_SHEET_PATH> pathFound =
1494 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1495
1496 // Check for paths that do not exist in the current project and paths that do
1497 // not contain the current symbol.
1498 if( !pathFound )
1499 pathsToPrune.emplace( instance.m_Path );
1500 else if( pathFound.value().LastScreen() != this )
1501 pathsToPrune.emplace( pathFound.value().Path() );
1502 }
1503
1504 for( const KIID_PATH& sheetPath : pathsToPrune )
1505 {
1506 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' symbol instance %s." ),
1507 aProjectName, sheetPath.AsString() );
1508 symbol->RemoveInstance( sheetPath );
1509 }
1510 }
1511}
1512
1513
1514void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
1515 const SCH_SHEET_LIST& aValidSheetPaths )
1516{
1517 // The project name cannot be empty. Projects older than 7.0 did not save project names
1518 // when saving instance data. Running this algorithm with an empty project name would
1519 // clobber all instance data for projects other than the current one when a schematic
1520 // file is shared across multiple projects. Because running the schematic editor in
1521 // stand alone mode can result in an empty project name, do not assert here.
1522 if( aProjectName.IsEmpty() )
1523 return;
1524
1525 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1526 {
1527 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1528
1529 wxCHECK2( sheet, continue );
1530
1531 std::set<KIID_PATH> pathsToPrune;
1532 const std::vector<SCH_SHEET_INSTANCE> instances = sheet->GetInstances();
1533
1534 for( const SCH_SHEET_INSTANCE& instance : instances )
1535 {
1536 // Ignore instance paths from other projects.
1537 if( aProjectName != instance.m_ProjectName )
1538 continue;
1539
1540 std::optional<SCH_SHEET_PATH> pathFound =
1541 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1542
1543 // Check for paths that do not exist in the current project and paths that do
1544 // not contain the current symbol.
1545 if( !pathFound )
1546 pathsToPrune.emplace( instance.m_Path );
1547 else if( pathFound.value().LastScreen() != this )
1548 pathsToPrune.emplace( pathFound.value().Path() );
1549 }
1550
1551 for( const KIID_PATH& sheetPath : pathsToPrune )
1552 {
1553 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' sheet instance %s." ),
1554 aProjectName, sheetPath.AsString() );
1555 sheet->RemoveInstance( sheetPath );
1556 }
1557 }
1558}
1559
1560
1562{
1563 wxString trimmedFieldName;
1564
1565 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1566 {
1567 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1568
1569 wxCHECK2( symbol, continue );
1570
1571 for( const SCH_FIELD& field : symbol->GetFields() )
1572 {
1573 trimmedFieldName = field.GetName();
1574 trimmedFieldName.Trim();
1575 trimmedFieldName.Trim( false );
1576
1577 if( field.GetName() != trimmedFieldName )
1578 return true;
1579 }
1580 }
1581
1582 return false;
1583}
1584
1585
1586#if defined(DEBUG)
1587void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1588{
1589 // for now, make it look like XML, expand on this later.
1590 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1591
1592 for( const SCH_ITEM* item : Items() )
1593 item->Show( nestLevel + 1, os );
1594
1595 NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1596}
1597#endif
1598
1599
1601{
1602 m_index = 0;
1603 buildScreenList( aSheet );
1604}
1605
1606
1608{
1609}
1610
1611
1613{
1614 m_index = 0;
1615
1616 if( m_screens.size() > 0 )
1617 return m_screens[0];
1618
1619 return nullptr;
1620}
1621
1622
1624{
1625 if( m_index < m_screens.size() )
1626 m_index++;
1627
1628 return GetScreen( m_index );
1629}
1630
1631
1632SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1633{
1634 if( aIndex < m_screens.size() )
1635 return m_screens[ aIndex ];
1636
1637 return nullptr;
1638}
1639
1640
1641SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1642{
1643 if( aIndex < m_sheets.size() )
1644 return m_sheets[ aIndex ];
1645
1646 return nullptr;
1647}
1648
1649
1651{
1652 if( aScreen == nullptr )
1653 return;
1654
1655 for( const SCH_SCREEN* screen : m_screens )
1656 {
1657 if( screen == aScreen )
1658 return;
1659 }
1660
1661 m_screens.push_back( aScreen );
1662 m_sheets.push_back( aSheet );
1663}
1664
1665
1667{
1668 if( aSheet && aSheet->Type() == SCH_SHEET_T )
1669 {
1670 SCH_SCREEN* screen = aSheet->GetScreen();
1671
1672 wxCHECK_RET( screen, "No screen for aSheet" );
1673
1674 addScreenToList( screen, aSheet );
1675
1676 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1677 buildScreenList( static_cast<SCH_SHEET*>( item ) );
1678 }
1679}
1680
1681
1683{
1684 SCH_SCREEN* first = GetFirst();
1685
1686 if( !first )
1687 return;
1688
1689 SCHEMATIC* sch = first->Schematic();
1690
1691 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" );
1692
1693 // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1694 SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1695 screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1696
1697 // Search for new sheet paths, not existing in aInitialSheetPathList
1698 // and existing in sheetpathList
1699 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
1700 {
1701 bool path_exists = false;
1702
1703 for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1704 {
1705 if( existing_sheetpath.Path() == sheetpath.Path() )
1706 {
1707 path_exists = true;
1708 break;
1709 }
1710 }
1711
1712 if( !path_exists )
1713 {
1714 // A new sheet path is found: clear the annotation corresponding to this new path:
1715 SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1716
1717 // Clear annotation and create the AR for this path, if not exists,
1718 // when the screen is shared by sheet paths.
1719 // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1720 // reference default value and takes the latest displayed value
1721 curr_screen->EnsureAlternateReferencesExist();
1722 curr_screen->ClearAnnotation( &sheetpath, false );
1723 }
1724 }
1725}
1726
1727
1729{
1730 std::vector<SCH_ITEM*> items;
1731 int count = 0;
1732
1733 auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1734 {
1735 return a->m_Uuid < b->m_Uuid;
1736 };
1737
1738 std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1739
1740 for( SCH_SCREEN* screen : m_screens )
1741 screen->GetHierarchicalItems( &items );
1742
1743 if( items.size() < 2 )
1744 return 0;
1745
1746 for( EDA_ITEM* item : items )
1747 {
1748 if( !unique_stamps.insert( item ).second )
1749 {
1750 // Reset to fully random UUID. This may lose reference, but better to be
1751 // deterministic about it rather than to have duplicate UUIDs with random
1752 // side-effects.
1753 const_cast<KIID&>( item->m_Uuid ) = KIID();
1754 count++;
1755
1756 // @todo If the item is a sheet, we need to decend the heirarchy from the sheet
1757 // and repace all instances of the changed UUID in sheet paths. Otherwise,
1758 // all instance paths with the sheet's UUID will get clobbered.
1759 }
1760 }
1761
1762 return count;
1763}
1764
1765
1767{
1768 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1769 {
1770 for( SCH_ITEM* item : screen->Items() )
1771 item->ClearEditFlags();
1772 }
1773}
1774
1775
1777{
1778 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1779 {
1780 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1781 {
1782 if( item == aMarker )
1783 {
1784 screen->DeleteItem( item );
1785 return;
1786 }
1787 }
1788 }
1789}
1790
1791
1792void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::MARKER_T aMarkerType, int aErrorCode,
1793 bool aIncludeExclusions )
1794{
1795 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1796 {
1797 std::vector<SCH_ITEM*> markers;
1798
1799 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1800 {
1801 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
1802 std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
1803
1804 if( marker->GetMarkerType() == aMarkerType
1805 && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
1806 && ( !marker->IsExcluded() || aIncludeExclusions ) )
1807 {
1808 markers.push_back( item );
1809 }
1810 }
1811
1812 for( SCH_ITEM* marker : markers )
1813 screen->DeleteItem( marker );
1814 }
1815}
1816
1817
1819 bool aIncludeExclusions )
1820{
1821 DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
1822}
1823
1824
1826{
1827 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1828 screen->UpdateSymbolLinks( aReporter );
1829
1830 SCH_SCREEN* first = GetFirst();
1831
1832 if( !first )
1833 return;
1834
1835 SCHEMATIC* sch = first->Schematic();
1836
1837 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
1838
1839 SCH_SHEET_LIST sheets = sch->Hierarchy();
1840
1841 // All of the library symbols have been replaced with copies so the connection graph
1842 // pointers are stale.
1843 if( sch->ConnectionGraph() )
1844 sch->ConnectionGraph()->Recalculate( sheets, true );
1845}
1846
1847
1849{
1850 bool has_symbols = false;
1851
1852 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1853 {
1854 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1855 {
1856 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1857 has_symbols = true;
1858
1859 if( !symbol->GetLibId().GetLibNickname().empty() )
1860 return false;
1861 }
1862 }
1863
1864 // return true (i.e. has no fully defined symbol) only if at least one symbol is found
1865 return has_symbols ? true : false;
1866}
1867
1868
1869size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
1870{
1871 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1872 {
1873 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1874 {
1875 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1876 const UTF8& nickname = symbol->GetLibId().GetLibNickname();
1877
1878 if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
1879 aLibNicknames.Add( nickname );
1880 }
1881 }
1882
1883 return aLibNicknames.GetCount();
1884}
1885
1886
1887int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
1888{
1889 SCH_SCREEN* screen;
1890 int cnt = 0;
1891
1892 for( screen = GetFirst(); screen; screen = GetNext() )
1893 {
1894 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1895 {
1896 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1897
1898 if( symbol->GetLibId().GetLibNickname().wx_str() != aFrom )
1899 continue;
1900
1901 LIB_ID id = symbol->GetLibId();
1902 id.SetLibNickname( aTo );
1903 symbol->SetLibId( id );
1904 cnt++;
1905 }
1906 }
1907
1908 return cnt;
1909}
1910
1911
1912bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
1913{
1914 for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1915 {
1916 if( screen->GetFileName() == aSchematicFileName )
1917 return true;
1918 }
1919
1920 return false;
1921}
1922
1923
1925{
1926 SCH_SCREEN* first = GetFirst();
1927
1928 if( !first )
1929 return;
1930
1931 SCHEMATIC* sch = first->Schematic();
1932
1933 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
1934
1935 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1936 curr_screen->GetClientSheetPaths().clear();
1937
1938 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
1939 {
1940 SCH_SCREEN* used_screen = sheetpath.LastScreen();
1941
1942 // Search for the used_screen in list and add this unique sheet path:
1943 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1944 {
1945 if( used_screen == curr_screen )
1946 {
1947 curr_screen->GetClientSheetPaths().push_back( sheetpath );
1948 break;
1949 }
1950 }
1951 }
1952}
1953
1954
1956{
1957 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1958 screen->SetLegacySymbolInstanceData();
1959}
1960
1961
1963{
1964 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1965 screen->FixLegacyPowerSymbolMismatches();
1966}
1967
1968
1970{
1971 LOCALE_IO toggle;
1972
1973 // V6 schematics may specify model names in Value fields, which we don't do in V7.
1974 // Migrate by adding an equivalent model for these symbols.
1975
1976 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1977 {
1978 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1979 SIM_MODEL::MigrateSimModel<SCH_SYMBOL>( *symbol, &Schematic()->Prj() );
1980 }
1981}
1982
1983
1984void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
1985 const SCH_SHEET_LIST& aValidSheetPaths )
1986{
1987 if( aProjectName.IsEmpty() )
1988 return;
1989
1990 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1991 screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
1992}
1993
1994
1995void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
1996 const SCH_SHEET_LIST& aValidSheetPaths )
1997{
1998 if( aProjectName.IsEmpty() )
1999 return;
2000
2001 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2002 screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
2003}
2004
2005
2007{
2008 for( const SCH_SCREEN* screen : m_screens )
2009 {
2010 if( screen->HasSymbolFieldNamesWithWhiteSpace() )
2011 return true;
2012 }
2013
2014 return false;
2015}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
Handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:41
int m_virtualPageNumber
An integer based page number used for printing a range of pages.
Definition: base_screen.h:119
bool m_Center
Center on screen.
Definition: base_screen.h:96
int m_pageCount
The number of BASE_SCREEN objects in this design.
Definition: base_screen.h:111
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
void InitDataPoints(const VECTOR2I &aPageSizeInternalUnits)
Definition: base_screen.cpp:46
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)
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:615
EDA_ANGLE Normalize90()
Definition: eda_angle.h:249
double AsDegrees() const
Definition: eda_angle.h:113
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:77
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
const KIID m_Uuid
Definition: eda_item.h:489
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
bool IsSelected() const
Definition: eda_item.h:110
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
EDA_ITEM * GetParent() const
Definition: eda_item.h:103
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:131
bool IsNew() const
Definition: eda_item.h:107
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:243
bool remove(SCH_ITEM *aItem)
Remove an item from the tree.
Definition: sch_rtree.h:78
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
Definition: sch_rtree.h:59
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition: sch_rtree.h:125
iterator end()
Returns a read/write iterator that points to one past the last element in the EE_RTREE.
Definition: sch_rtree.h:285
iterator begin()
Returns a read/write iterator that points to the first element in the EE_RTREE N.B.
Definition: sch_rtree.h:276
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
void clear()
Remove all items from the RTree.
Definition: sch_rtree.h:111
EMBEDDED_FILE * GetEmbeddedFile(const wxString &aName) const
Returns the embedded file with the given name or nullptr if it does not exist.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
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:99
wxString GetUniStringLibId() const
Definition: lib_id.h:148
UTF8 Format() const
Definition: lib_id.cpp:118
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:78
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:143
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:499
wxString GetName() const override
Definition: lib_symbol.h:137
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:304
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:144
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:288
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:49
bool IsExcluded() const
Definition: marker_base.h:98
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:112
enum MARKER_T GetMarkerType() const
Definition: marker_base.h:96
void sort()
Definition: multivector.h:248
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
Base plotter engine class.
Definition: plotter.h:105
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:136
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)
Definition: project_sch.cpp:90
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:72
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:100
Holds all the data relating to one schematic.
Definition: schematic.h:77
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:162
SCH_SHEET_LIST Hierarchy() const override
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:214
SCH_SHEET & Root() const
Definition: schematic.h:121
Class for a wire to bus entry.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
virtual bool IsConnectable() const
Definition: sch_item.h:449
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:281
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Definition: sch_item.cpp:212
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:464
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
EDA_ANGLE Angle() const
Gets the angle between the start and end lines.
Definition: sch_line.h:103
VECTOR2I GetEndPoint() const
Definition: sch_line.h:141
VECTOR2I GetStartPoint() const
Definition: sch_line.h:136
bool IsEndPoint(const VECTOR2I &aPoint) const
Definition: sch_line.h:90
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:712
SCH_SCREEN * GetNext()
unsigned int m_index
Definition: sch_screen.h:848
std::vector< SCH_SHEET * > m_sheets
Definition: sch_screen.h:847
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()
built 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 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::vector< SCH_SCREEN * > m_screens
Definition: sch_screen.h:846
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::map< wxString, LIB_SYMBOL * > m_libSymbols
Library symbols required for this schematic.
Definition: sch_screen.h:673
SCH_PIN * GetPin(const VECTOR2I &aPosition, SCH_SYMBOL **aSymbol=nullptr, bool aEndPointOnly=false) const
Test the screen for a symbol pin item at aPosition.
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)
Definition: sch_screen.cpp:153
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 (and transfers ownership of the pointer).
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
bool HasItems(KICAD_T aItemType) const
Definition: sch_screen.cpp:139
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
Definition: sch_screen.cpp:278
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:177
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project SYMB...
Definition: sch_screen.cpp:666
SCH_LINE * GetWire(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:428
int m_refCount
Definition: sch_screen.h:641
TITLE_BLOCK m_titles
Definition: sch_screen.h:654
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.
int m_modification_sync
Definition: sch_screen.h:658
double m_LastZoomLevel
last value for the zoom level, useful in Eeschema when changing the current displayed sheet to reuse ...
Definition: sch_screen.h:636
bool IsExplicitJunction(const VECTOR2I &aPosition) const
Indicates that a junction dot is necessary at the given location.
Definition: sch_screen.cpp:487
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
void DecRefCount()
Definition: sch_screen.cpp:132
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.
Definition: sch_screen.cpp:408
void Print(const SCH_RENDER_SETTINGS *aSettings)
Print all the items in the screen to aDC.
Definition: sch_screen.cpp:854
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.
Definition: sch_screen.cpp:392
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicates that a juction dot may be placed at the given location.
Definition: sch_screen.cpp:506
void clearLibSymbols()
Definition: sch_screen.cpp:109
wxString m_fileName
Definition: sch_screen.h:639
bool IsTerminalPoint(const VECTOR2I &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:601
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
Definition: sch_screen.cpp:821
void IncRefCount()
Definition: sch_screen.cpp:126
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:118
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_screen.cpp:147
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:434
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:323
SCH_SCREEN(EDA_ITEM *aParent=nullptr)
Definition: sch_screen.cpp:74
SCHEMATIC * Schematic() const
Definition: sch_screen.cpp:100
EE_RTREE m_rtree
Definition: sch_screen.h:656
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
Indicates that a junction dot is necessary at the given location, and does not yet exist.
Definition: sch_screen.cpp:496
SCH_SHEET_PIN * GetSheetPin(const VECTOR2I &aPosition) const
Test the screen if aPosition is a sheet label object.
void FreeDrawList()
Free all the items from the schematic associated with the screen.
Definition: sch_screen.cpp:297
void Plot(PLOTTER *aPlotter, const SCH_PLOT_OPTS &aPlotOpts) const
Plot all the schematic objects to aPlotter.
Definition: sch_screen.cpp:898
virtual wxString GetClass() const override
Return the class name.
Definition: sch_screen.h:122
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:316
void SetConnectivityDirty()
Definition: sch_screen.cpp:847
bool m_zoomInitialized
Definition: sch_screen.h:661
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:653
bool IsJunction(const VECTOR2I &aPosition) const
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:479
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
Definition: sch_screen.cpp:386
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
Definition: sch_screen.cpp:515
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)
Removes aItem from the linked list and deletes the object.
Definition: sch_screen.cpp:361
std::set< std::shared_ptr< BUS_ALIAS >, BusAliasCmp > m_aliases
List of bus aliases stored in this screen.
Definition: sch_screen.h:670
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.
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.
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.
Definition: sch_sheet_pin.h:66
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:57
void RemoveInstance(const KIID_PATH &aInstancePath)
Definition: sch_sheet.cpp:1405
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:640
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:438
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition: sch_sheet.h:417
Schematic symbol object.
Definition: sch_symbol.h:104
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:264
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:163
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
Definition: sch_symbol.cpp:609
void SetValueFieldText(const wxString &aValue)
Definition: sch_symbol.cpp:917
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:270
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.
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve a list of the SCH_PINs for the given sheet path.
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.
Definition: sch_symbol.cpp:637
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:193
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition: sch_symbol.h:208
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:987
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:212
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:279
VECTOR2I GetPinPhysicalPosition(const SCH_PIN *Pin) const
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.
void Clear()
Definition: title_block.h:113
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:104
wxString wx_str() const
Definition: utf8.cpp:45
#define _(s)
#define IS_DELETED
#define STRUCT_DELETED
flag indication structures to be erased
#define IS_MOVING
Item being moved.
@ ERCE_UNSPECIFIED
Definition: erc_settings.h:38
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.
PROJECT & Prj()
Definition: kicad.cpp:595
@ LAYER_WIRE
Definition: layer_ids.h:357
@ LAYER_NOTES
Definition: layer_ids.h:372
@ LAYER_BUS
Definition: layer_ids.h:358
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,...
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
static const wxChar DanglingProfileMask[]
Definition: sch_screen.cpp:72
#define PROCESSED
SCH_LINE_TEST_T
Definition: sch_screen.h:70
@ ENTIRE_LENGTH_T
Definition: sch_screen.h:71
@ EXCLUDE_END_POINTS_T
Definition: sch_screen.h:73
@ END_POINTS_ONLY_T
Definition: sch_screen.h:72
wxString UnescapeString(const wxString &aSource)
const double IU_PER_MILS
Definition: base_units.h:77
The EE_TYPE struct provides a type-specific auto-range iterator to the RTree.
Definition: sch_rtree.h:192
iterator begin()
Definition: sch_rtree.h:222
iterator end()
Definition: sch_rtree.h:227
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.
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
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_LINE_T
Definition: typeinfo.h:163
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_LABEL_T
Definition: typeinfo.h:167
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_MARKER_T
Definition: typeinfo.h:158
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_SCREEN_T
Definition: typeinfo.h:201
@ SCH_LABEL_LOCATE_ANY_T
Definition: typeinfo.h:190
@ SCHEMATIC_T
Definition: typeinfo.h:203
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168
@ SCH_JUNCTION_T
Definition: typeinfo.h:159
@ SCH_PIN_T
Definition: typeinfo.h:153
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691