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_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 const std::vector<wxString>* embeddedFonts = schematic->GetEmbeddedFiles()->UpdateFontFiles();
1385
1386 for( auto& [name, libSym] : m_libSymbols )
1387 {
1388 for( auto& [filename, embeddedFile] : libSym->EmbeddedFileMap() )
1389 {
1390 EMBEDDED_FILES::EMBEDDED_FILE* file = schematic->GetEmbeddedFile( filename );
1391
1392 if( file )
1393 {
1394 embeddedFile->compressedEncodedData = file->compressedEncodedData;
1395 embeddedFile->decompressedData = file->decompressedData;
1396 embeddedFile->data_hash = file->data_hash;
1397 embeddedFile->is_valid = file->is_valid;
1398 }
1399 }
1400
1401 libSym->RunOnChildren(
1402 [&]( SCH_ITEM* aChild )
1403 {
1404 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aChild ) )
1405 textItem->ResolveFont( embeddedFonts );
1406 } );
1407 }
1408
1409 std::vector<SCH_ITEM*> items_to_update;
1410
1411 for( SCH_ITEM* item : Items() )
1412 {
1413 bool update = false;
1414
1415 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( item ) )
1416 update |= textItem->ResolveFont( embeddedFonts );
1417
1418 item->RunOnChildren(
1419 [&]( SCH_ITEM* aChild )
1420 {
1421 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aChild ) )
1422 update |= textItem->ResolveFont( embeddedFonts );
1423 } );
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 m_aliases.insert( aAlias );
1437}
1438
1439
1441{
1442 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1443 {
1444 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1445
1446 // Add missing value and footprint instance data for legacy schematics.
1447 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1448 {
1449 symbol->AddHierarchicalReference( instance.m_Path, instance.m_Reference,
1450 instance.m_Unit );
1451 }
1452 }
1453}
1454
1455
1457{
1458 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1459 {
1460 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1461
1462 // Fix pre-8.0 legacy power symbols with invisible pins
1463 // that have mismatched pin names and value fields
1464 if( symbol->GetLibSymbolRef()
1465 && symbol->GetLibSymbolRef()->IsPower()
1466 && symbol->GetAllLibPins().size() > 0
1467 && symbol->GetAllLibPins()[0]->IsGlobalPower()
1468 && !symbol->GetAllLibPins()[0]->IsVisible() )
1469 {
1470 symbol->SetValueFieldText( symbol->GetAllLibPins()[0]->GetName() );
1471 }
1472 }
1473}
1474
1475
1477 std::vector<wxString>& aMatches )
1478{
1479 wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
1480
1481 if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
1482 aMatches.emplace_back( searchName );
1483
1484 searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
1485
1486 long tmp;
1487 wxString suffix;
1488
1489 for( auto& pair : m_libSymbols )
1490 {
1491 if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToLong( &tmp ) )
1492 aMatches.emplace_back( pair.first );
1493 }
1494
1495 return aMatches.size();
1496}
1497
1498
1499void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
1500 const SCH_SHEET_LIST& aValidSheetPaths )
1501{
1502 // The project name cannot be empty. Projects older than 7.0 did not save project names
1503 // when saving instance data. Running this algorithm with an empty project name would
1504 // clobber all instance data for projects other than the current one when a schematic
1505 // file is shared across multiple projects. Because running the schematic editor in
1506 // stand alone mode can result in an empty project name, do not assert here.
1507 if( aProjectName.IsEmpty() )
1508 return;
1509
1510 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1511 {
1512 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1513
1514 wxCHECK2( symbol, continue );
1515
1516 std::set<KIID_PATH> pathsToPrune;
1517 const std::vector<SCH_SYMBOL_INSTANCE> instances = symbol->GetInstances();
1518
1519 for( const SCH_SYMBOL_INSTANCE& instance : instances )
1520 {
1521 // Ignore instance paths from other projects.
1522 if( aProjectName != instance.m_ProjectName )
1523 continue;
1524
1525 std::optional<SCH_SHEET_PATH> pathFound =
1526 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1527
1528 // Check for paths that do not exist in the current project and paths that do
1529 // not contain the current symbol.
1530 if( !pathFound )
1531 pathsToPrune.emplace( instance.m_Path );
1532 else if( pathFound.value().LastScreen() != this )
1533 pathsToPrune.emplace( pathFound.value().Path() );
1534 }
1535
1536 for( const KIID_PATH& sheetPath : pathsToPrune )
1537 {
1538 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' symbol instance %s." ),
1539 aProjectName, sheetPath.AsString() );
1540 symbol->RemoveInstance( sheetPath );
1541 }
1542 }
1543}
1544
1545
1546void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
1547 const SCH_SHEET_LIST& aValidSheetPaths )
1548{
1549 // The project name cannot be empty. Projects older than 7.0 did not save project names
1550 // when saving instance data. Running this algorithm with an empty project name would
1551 // clobber all instance data for projects other than the current one when a schematic
1552 // file is shared across multiple projects. Because running the schematic editor in
1553 // stand alone mode can result in an empty project name, do not assert here.
1554 if( aProjectName.IsEmpty() )
1555 return;
1556
1557 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1558 {
1559 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1560
1561 wxCHECK2( sheet, continue );
1562
1563 std::set<KIID_PATH> pathsToPrune;
1564 const std::vector<SCH_SHEET_INSTANCE> instances = sheet->GetInstances();
1565
1566 for( const SCH_SHEET_INSTANCE& instance : instances )
1567 {
1568 // Ignore instance paths from other projects.
1569 if( aProjectName != instance.m_ProjectName )
1570 continue;
1571
1572 std::optional<SCH_SHEET_PATH> pathFound =
1573 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1574
1575 // Check for paths that do not exist in the current project and paths that do
1576 // not contain the current symbol.
1577 if( !pathFound )
1578 pathsToPrune.emplace( instance.m_Path );
1579 else if( pathFound.value().LastScreen() != this )
1580 pathsToPrune.emplace( pathFound.value().Path() );
1581 }
1582
1583 for( const KIID_PATH& sheetPath : pathsToPrune )
1584 {
1585 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' sheet instance %s." ),
1586 aProjectName, sheetPath.AsString() );
1587 sheet->RemoveInstance( sheetPath );
1588 }
1589 }
1590}
1591
1592
1594{
1595 wxString trimmedFieldName;
1596
1597 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1598 {
1599 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1600
1601 wxCHECK2( symbol, continue );
1602
1603 for( const SCH_FIELD& field : symbol->GetFields() )
1604 {
1605 trimmedFieldName = field.GetName();
1606 trimmedFieldName.Trim();
1607 trimmedFieldName.Trim( false );
1608
1609 if( field.GetName() != trimmedFieldName )
1610 return true;
1611 }
1612 }
1613
1614 return false;
1615}
1616
1617
1618#if defined(DEBUG)
1619void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1620{
1621 // for now, make it look like XML, expand on this later.
1622 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1623
1624 for( const SCH_ITEM* item : Items() )
1625 item->Show( nestLevel + 1, os );
1626
1627 NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1628}
1629#endif
1630
1631
1633{
1634 m_index = 0;
1635 buildScreenList( aSheet );
1636}
1637
1638
1640{
1641}
1642
1643
1645{
1646 m_index = 0;
1647
1648 if( m_screens.size() > 0 )
1649 return m_screens[0];
1650
1651 return nullptr;
1652}
1653
1654
1656{
1657 if( m_index < m_screens.size() )
1658 m_index++;
1659
1660 return GetScreen( m_index );
1661}
1662
1663
1664SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1665{
1666 if( aIndex < m_screens.size() )
1667 return m_screens[ aIndex ];
1668
1669 return nullptr;
1670}
1671
1672
1673SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1674{
1675 if( aIndex < m_sheets.size() )
1676 return m_sheets[ aIndex ];
1677
1678 return nullptr;
1679}
1680
1681
1683{
1684 if( aScreen == nullptr )
1685 return;
1686
1687 for( const SCH_SCREEN* screen : m_screens )
1688 {
1689 if( screen == aScreen )
1690 return;
1691 }
1692
1693 m_screens.push_back( aScreen );
1694 m_sheets.push_back( aSheet );
1695}
1696
1697
1699{
1700 if( aSheet && aSheet->Type() == SCH_SHEET_T )
1701 {
1702 SCH_SCREEN* screen = aSheet->GetScreen();
1703
1704 wxCHECK_RET( screen, "No screen for aSheet" );
1705
1706 addScreenToList( screen, aSheet );
1707
1708 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1709 buildScreenList( static_cast<SCH_SHEET*>( item ) );
1710 }
1711}
1712
1713
1715{
1716 SCH_SCREEN* first = GetFirst();
1717
1718 if( !first )
1719 return;
1720
1721 SCHEMATIC* sch = first->Schematic();
1722
1723 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" );
1724
1725 // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1726 SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1727 screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1728
1729 // Search for new sheet paths, not existing in aInitialSheetPathList
1730 // and existing in sheetpathList
1731 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
1732 {
1733 bool path_exists = false;
1734
1735 for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1736 {
1737 if( existing_sheetpath.Path() == sheetpath.Path() )
1738 {
1739 path_exists = true;
1740 break;
1741 }
1742 }
1743
1744 if( !path_exists )
1745 {
1746 // A new sheet path is found: clear the annotation corresponding to this new path:
1747 SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1748
1749 // Clear annotation and create the AR for this path, if not exists,
1750 // when the screen is shared by sheet paths.
1751 // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1752 // reference default value and takes the latest displayed value
1753 curr_screen->EnsureAlternateReferencesExist();
1754 curr_screen->ClearAnnotation( &sheetpath, false );
1755 }
1756 }
1757}
1758
1759
1761{
1762 std::vector<SCH_ITEM*> items;
1763 int count = 0;
1764
1765 auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1766 {
1767 return a->m_Uuid < b->m_Uuid;
1768 };
1769
1770 std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1771
1772 for( SCH_SCREEN* screen : m_screens )
1773 screen->GetHierarchicalItems( &items );
1774
1775 if( items.size() < 2 )
1776 return 0;
1777
1778 for( EDA_ITEM* item : items )
1779 {
1780 if( !unique_stamps.insert( item ).second )
1781 {
1782 // Reset to fully random UUID. This may lose reference, but better to be
1783 // deterministic about it rather than to have duplicate UUIDs with random
1784 // side-effects.
1785 const_cast<KIID&>( item->m_Uuid ) = KIID();
1786 count++;
1787
1788 // @todo If the item is a sheet, we need to decend the heirarchy from the sheet
1789 // and repace all instances of the changed UUID in sheet paths. Otherwise,
1790 // all instance paths with the sheet's UUID will get clobbered.
1791 }
1792 }
1793
1794 return count;
1795}
1796
1797
1799{
1800 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1801 {
1802 for( SCH_ITEM* item : screen->Items() )
1803 item->ClearEditFlags();
1804 }
1805}
1806
1807
1809{
1810 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1811 {
1812 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1813 {
1814 if( item == aMarker )
1815 {
1816 screen->DeleteItem( item );
1817 return;
1818 }
1819 }
1820 }
1821}
1822
1823
1824void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::MARKER_T aMarkerType, int aErrorCode,
1825 bool aIncludeExclusions )
1826{
1827 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1828 {
1829 std::vector<SCH_ITEM*> markers;
1830
1831 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1832 {
1833 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
1834 std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
1835
1836 if( marker->GetMarkerType() == aMarkerType
1837 && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
1838 && ( !marker->IsExcluded() || aIncludeExclusions ) )
1839 {
1840 markers.push_back( item );
1841 }
1842 }
1843
1844 for( SCH_ITEM* marker : markers )
1845 screen->DeleteItem( marker );
1846 }
1847}
1848
1849
1851 bool aIncludeExclusions )
1852{
1853 DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
1854}
1855
1856
1858{
1859 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1860 screen->UpdateSymbolLinks( aReporter );
1861
1862 SCH_SCREEN* first = GetFirst();
1863
1864 if( !first )
1865 return;
1866
1867 SCHEMATIC* sch = first->Schematic();
1868
1869 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
1870
1871 SCH_SHEET_LIST sheets = sch->Hierarchy();
1872
1873 // All of the library symbols have been replaced with copies so the connection graph
1874 // pointers are stale.
1875 if( sch->ConnectionGraph() )
1876 sch->ConnectionGraph()->Recalculate( sheets, true );
1877}
1878
1879
1881{
1882 bool has_symbols = false;
1883
1884 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1885 {
1886 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1887 {
1888 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1889 has_symbols = true;
1890
1891 if( !symbol->GetLibId().GetLibNickname().empty() )
1892 return false;
1893 }
1894 }
1895
1896 // return true (i.e. has no fully defined symbol) only if at least one symbol is found
1897 return has_symbols ? true : false;
1898}
1899
1900
1901size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
1902{
1903 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1904 {
1905 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1906 {
1907 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1908 const UTF8& nickname = symbol->GetLibId().GetLibNickname();
1909
1910 if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
1911 aLibNicknames.Add( nickname );
1912 }
1913 }
1914
1915 return aLibNicknames.GetCount();
1916}
1917
1918
1919int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
1920{
1921 SCH_SCREEN* screen;
1922 int cnt = 0;
1923
1924 for( screen = GetFirst(); screen; screen = GetNext() )
1925 {
1926 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1927 {
1928 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1929
1930 if( symbol->GetLibId().GetLibNickname().wx_str() != aFrom )
1931 continue;
1932
1933 LIB_ID id = symbol->GetLibId();
1934 id.SetLibNickname( aTo );
1935 symbol->SetLibId( id );
1936 cnt++;
1937 }
1938 }
1939
1940 return cnt;
1941}
1942
1943
1944bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
1945{
1946 for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1947 {
1948 if( screen->GetFileName() == aSchematicFileName )
1949 return true;
1950 }
1951
1952 return false;
1953}
1954
1955
1957{
1958 SCH_SCREEN* first = GetFirst();
1959
1960 if( !first )
1961 return;
1962
1963 SCHEMATIC* sch = first->Schematic();
1964
1965 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
1966
1967 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1968 curr_screen->GetClientSheetPaths().clear();
1969
1970 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
1971 {
1972 SCH_SCREEN* used_screen = sheetpath.LastScreen();
1973
1974 // Search for the used_screen in list and add this unique sheet path:
1975 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1976 {
1977 if( used_screen == curr_screen )
1978 {
1979 curr_screen->GetClientSheetPaths().push_back( sheetpath );
1980 break;
1981 }
1982 }
1983 }
1984}
1985
1986
1988{
1989 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1990 screen->SetLegacySymbolInstanceData();
1991}
1992
1993
1995{
1996 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1997 screen->FixLegacyPowerSymbolMismatches();
1998}
1999
2000
2002{
2003 LOCALE_IO toggle;
2004
2005 // V6 schematics may specify model names in Value fields, which we don't do in V7.
2006 // Migrate by adding an equivalent model for these symbols.
2007
2008 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
2009 {
2010 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2011 SIM_MODEL::MigrateSimModel<SCH_SYMBOL>( *symbol, &Schematic()->Prj() );
2012 }
2013}
2014
2015
2016void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
2017 const SCH_SHEET_LIST& aValidSheetPaths )
2018{
2019 if( aProjectName.IsEmpty() )
2020 return;
2021
2022 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2023 screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
2024}
2025
2026
2027void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
2028 const SCH_SHEET_LIST& aValidSheetPaths )
2029{
2030 if( aProjectName.IsEmpty() )
2031 return;
2032
2033 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2034 screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
2035}
2036
2037
2039{
2040 for( const SCH_SCREEN* screen : m_screens )
2041 {
2042 if( screen->HasSymbolFieldNamesWithWhiteSpace() )
2043 return true;
2044 }
2045
2046 return false;
2047}
const char * name
Definition: DXF_plotter.cpp:59
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:613
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:490
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
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
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.
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.
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:84
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:154
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:531
wxString GetName() const override
Definition: lib_symbol.h:148
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:333
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:155
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:317
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:82
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:171
SCH_SHEET_LIST Hierarchy() const override
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:214
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition: schematic.cpp:876
SCH_SHEET & Root() const
Definition: schematic.h:130
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:167
virtual bool IsConnectable() const
Definition: sch_item.h:450
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:282
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Definition: sch_item.cpp:209
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:465
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:1400
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:641
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:439
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:109
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition: sch_sheet.h:419
Schematic symbol object.
Definition: sch_symbol.h:77
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:235
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:136
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
Definition: sch_symbol.cpp:575
void SetValueFieldText(const wxString &aValue)
Definition: sch_symbol.cpp:883
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:241
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) override
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:953
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 * > 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:603
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:166
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition: sch_symbol.h:181
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:185
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:250
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.
Common command IDs shared by more than one of the KiCad applications.
PROJECT & Prj()
Definition: kicad.cpp:597
@ LAYER_WIRE
Definition: layer_ids.h:404
@ LAYER_NOTES
Definition: layer_ids.h:419
@ LAYER_BUS
Definition: layer_ids.h:405
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:695