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