KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eeschema/cross-probing.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) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <wx/tokenzr.h>
27#include <fmt.h>
28#include <kiface_base.h>
29#include <kiway.h>
30#include <kiway_mail.h>
31#include <eda_dde.h>
32#include <connection_graph.h>
33#include <sch_sheet.h>
34#include <sch_symbol.h>
35#include <sch_reference_list.h>
36#include <string_utils.h>
40#include <project_sch.h>
41#include <richio.h>
42#include <tools/sch_actions.h>
44#include <advanced_config.h>
45
46#include <pgm_base.h>
49#include <widgets/kistatusbar.h>
50#include <wx/filefn.h>
51#include <wx/log.h>
52#include <trace_helpers.h>
53
54SCH_ITEM* SCH_EDITOR_CONTROL::FindSymbolAndItem( const wxString* aPath, const wxString* aReference,
55 bool aSearchHierarchy, SCH_SEARCH_T aSearchType,
56 const wxString& aSearchText )
57{
58 SCH_SHEET_PATH* sheetWithSymbolFound = nullptr;
59 SCH_SYMBOL* symbol = nullptr;
60 SCH_PIN* pin = nullptr;
61 SCH_SHEET_LIST sheetList;
62 SCH_ITEM* foundItem = nullptr;
63
64 if( !aSearchHierarchy )
65 sheetList.push_back( m_frame->GetCurrentSheet() );
66 else
67 sheetList = m_frame->Schematic().Hierarchy();
68
69 for( SCH_SHEET_PATH& sheet : sheetList )
70 {
71 SCH_SCREEN* screen = sheet.LastScreen();
72
73 for( EDA_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
74 {
75 SCH_SYMBOL* candidate = static_cast<SCH_SYMBOL*>( item );
76
77 // Search by path if specified, otherwise search by reference
78 bool found = false;
79
80 if( aPath )
81 {
82 wxString path = sheet.PathAsString() + candidate->m_Uuid.AsString();
83 found = ( *aPath == path );
84 }
85 else
86 {
87 found = ( aReference && aReference->CmpNoCase( candidate->GetRef( &sheet ) ) == 0 );
88 }
89
90 if( found )
91 {
92 symbol = candidate;
93 sheetWithSymbolFound = &sheet;
94
95 if( aSearchType == HIGHLIGHT_PIN )
96 {
97 pin = symbol->GetPin( aSearchText );
98
99 // Ensure we have found the right unit in case of multi-units symbol
100 if( pin )
101 {
102 int unit = pin->GetLibPin()->GetUnit();
103
104 if( unit != 0 && unit != symbol->GetUnit() )
105 {
106 pin = nullptr;
107 continue;
108 }
109
110 // Get pin position in true schematic coordinate
111 foundItem = pin;
112 break;
113 }
114 }
115 else
116 {
117 foundItem = symbol;
118 break;
119 }
120 }
121 }
122
123 if( foundItem )
124 break;
125 }
126
127 CROSS_PROBING_SETTINGS& crossProbingSettings = m_frame->eeconfig()->m_CrossProbing;
128
129 if( symbol )
130 {
131 if( *sheetWithSymbolFound != m_frame->GetCurrentSheet() )
132 {
133 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet,
134 sheetWithSymbolFound );
135 }
136
137 if( crossProbingSettings.center_on_items )
138 {
139 if( crossProbingSettings.zoom_to_fit )
140 {
141 BOX2I bbox = symbol->GetBoundingBox();
142
143 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->ZoomFitCrossProbeBBox( bbox );
144 }
145
146 if( pin )
147 m_frame->FocusOnItem( pin );
148 else
149 m_frame->FocusOnItem( symbol );
150 }
151 }
152
153 /* Print diag */
154 wxString msg;
155 wxString displayRef;
156
157 if( aReference )
158 displayRef = *aReference;
159 else if( aPath )
160 displayRef = *aPath;
161
162 if( symbol )
163 {
164 if( aSearchType == HIGHLIGHT_PIN )
165 {
166 if( foundItem )
167 msg.Printf( _( "%s pin %s found" ), displayRef, aSearchText );
168 else
169 msg.Printf( _( "%s found but pin %s not found" ), displayRef, aSearchText );
170 }
171 else
172 {
173 msg.Printf( _( "%s found" ), displayRef );
174 }
175 }
176 else
177 {
178 msg.Printf( _( "%s not found" ), displayRef );
179 }
180
181 m_frame->SetStatusText( msg );
182 m_frame->GetCanvas()->Refresh();
183
184 return foundItem;
185}
186
187
188/* Execute a remote command sent via a socket on port KICAD_PCB_PORT_SERVICE_NUMBER
189 *
190 * Commands are:
191 *
192 * $PART: "reference" Put cursor on symbol.
193 * $PART: "reference" $REF: "ref" Put cursor on symbol reference.
194 * $PART: "reference" $VAL: "value" Put cursor on symbol value.
195 * $PART: "reference" $PAD: "pin name" Put cursor on the symbol pin.
196 * $NET: "netname" Highlight a specified net
197 * $CLEAR: "HIGHLIGHTED" Clear symbols highlight
198 *
199 * $CONFIG Show the Manage Symbol Libraries dialog
200 * $ERC Show the ERC dialog
201 */
202void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
203{
205 char line[1024];
206
207 strncpy( line, cmdline, sizeof( line ) - 1 );
208 line[ sizeof( line ) - 1 ] = '\0';
209
210 char* idcmd = strtok( line, " \n\r" );
211 char* text = strtok( nullptr, "\"\n\r" );
212
213 if( idcmd == nullptr )
214 return;
215
216 CROSS_PROBING_SETTINGS& crossProbingSettings = eeconfig()->m_CrossProbing;
217
218 if( strcmp( idcmd, "$CONFIG" ) == 0 )
219 {
221 return;
222 }
223 else if( strcmp( idcmd, "$ERC" ) == 0 )
224 {
226 return;
227 }
228 else if( strcmp( idcmd, "$NET:" ) == 0 )
229 {
230 if( !crossProbingSettings.auto_highlight )
231 return;
232
233 wxString netName = From_UTF8( text );
234
235 if( auto sg = Schematic().ConnectionGraph()->FindFirstSubgraphByName( netName ) )
236 m_highlightedConn = sg->GetDriverConnection()->Name();
237 else
238 m_highlightedConn = wxEmptyString;
239
242
243 SetStatusText( _( "Highlighted net:" ) + wxS( " " ) + UnescapeString( netName ) );
244 return;
245 }
246 else if( strcmp( idcmd, "$CLEAR:" ) == 0 )
247 {
248 // Cross-probing is now done through selection so we no longer need a clear command
249 return;
250 }
251
252 if( !crossProbingSettings.on_selection )
253 return;
254
255 if( text == nullptr )
256 return;
257
258 if( strcmp( idcmd, "$PART:" ) != 0 )
259 return;
260
261 wxString part_ref = From_UTF8( text );
262
263 /* look for a complement */
264 idcmd = strtok( nullptr, " \n\r" );
265
266 if( idcmd == nullptr ) // Highlight symbol only (from CvPcb or Pcbnew)
267 {
268 // Highlight symbol part_ref, or clear Highlight, if part_ref is not existing
269 editor->FindSymbolAndItem( nullptr, &part_ref, true, HIGHLIGHT_SYMBOL, wxEmptyString );
270 return;
271 }
272
273 text = strtok( nullptr, "\"\n\r" );
274
275 if( text == nullptr )
276 return;
277
278 wxString msg = From_UTF8( text );
279
280 if( strcmp( idcmd, "$REF:" ) == 0 )
281 {
282 // Highlighting the reference itself isn't actually that useful, and it's harder to
283 // see. Highlight the parent and display the message.
284 editor->FindSymbolAndItem( nullptr, &part_ref, true, HIGHLIGHT_SYMBOL, msg );
285 }
286 else if( strcmp( idcmd, "$VAL:" ) == 0 )
287 {
288 // Highlighting the value itself isn't actually that useful, and it's harder to see.
289 // Highlight the parent and display the message.
290 editor->FindSymbolAndItem( nullptr, &part_ref, true, HIGHLIGHT_SYMBOL, msg );
291 }
292 else if( strcmp( idcmd, "$PAD:" ) == 0 )
293 {
294 editor->FindSymbolAndItem( nullptr, &part_ref, true, HIGHLIGHT_PIN, msg );
295 }
296 else
297 {
298 editor->FindSymbolAndItem( nullptr, &part_ref, true, HIGHLIGHT_SYMBOL, wxEmptyString );
299 }
300}
301
302
303void SCH_EDIT_FRAME::SendSelectItemsToPcb( const std::vector<EDA_ITEM*>& aItems, bool aForce )
304{
305 std::vector<wxString> parts;
306
307 for( EDA_ITEM* item : aItems )
308 {
309 switch( item->Type() )
310 {
311 case SCH_SYMBOL_T:
312 {
313 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
314 wxString ref = symbol->GetField( FIELD_T::REFERENCE )->GetText();
315
316 parts.push_back( wxT( "F" ) + EscapeString( ref, CTX_IPC ) );
317 break;
318 }
319
320 case SCH_SHEET_T:
321 {
322 // For cross probing, we need the full path of the sheet, because
323 // we search by the footprint path prefix in the PCB editor
324 wxString full_path = GetCurrentSheet().PathAsString() + item->m_Uuid.AsString();
325
326 parts.push_back( wxT( "S" ) + full_path );
327 break;
328 }
329
330 case SCH_PIN_T:
331 {
332 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
333 SYMBOL* symbol = pin->GetParentSymbol();
334 wxString ref = symbol->GetRef( &GetCurrentSheet(), false );
335
336 parts.push_back( wxT( "P" ) + EscapeString( ref, CTX_IPC ) + wxT( "/" )
337 + EscapeString( pin->GetShownNumber(), CTX_IPC ) );
338 break;
339 }
340
341 default:
342 break;
343 }
344 }
345
346 if( parts.empty() )
347 return;
348
349 std::string command = "$SELECT: 0,";
350
351 for( wxString part : parts )
352 {
353 command += part;
354 command += ",";
355 }
356
357 command.pop_back();
358
359 if( Kiface().IsSingle() )
360 {
361 SendCommand( MSG_TO_PCB, command );
362 }
363 else
364 {
365 // Typically ExpressMail is going to be s-expression packets, but since
366 // we have existing interpreter of the selection packet on the other
367 // side in place, we use that here.
369 command, this );
370 }
371}
372
373
374void SCH_EDIT_FRAME::SendCrossProbeNetName( const wxString& aNetName )
375{
376 // The command is a keyword followed by a quoted string.
377
378 std::string packet = fmt::format( "$NET: \"{}\"", TO_UTF8( aNetName ) );
379
380 if( !packet.empty() )
381 {
382 if( Kiface().IsSingle() )
383 {
384 SendCommand( MSG_TO_PCB, packet );
385 }
386 else
387 {
388 // Typically ExpressMail is going to be s-expression packets, but since
389 // we have existing interpreter of the cross probe packet on the other
390 // side in place, we use that here.
392 }
393 }
394}
395
396
398{
399 if( !aConnection )
400 {
402 return;
403 }
404
405 if( aConnection->IsNet() )
406 {
407 SendCrossProbeNetName( aConnection->Name() );
408 return;
409 }
410
411 if( aConnection->Members().empty() )
412 return;
413
414 auto all_members = aConnection->AllMembers();
415
416 wxString nets = all_members[0]->Name();
417
418 if( all_members.size() == 1 )
419 {
420 SendCrossProbeNetName( nets );
421 return;
422 }
423
424 // TODO: This could be replaced by just sending the bus name once we have bus contents
425 // included as part of the netlist sent from Eeschema to Pcbnew (and thus Pcbnew can
426 // natively keep track of bus membership)
427
428 for( size_t i = 1; i < all_members.size(); i++ )
429 nets << "," << all_members[i]->Name();
430
431 std::string packet = fmt::format( "$NETS: \"{}\"", TO_UTF8( nets ) );
432
433 if( !packet.empty() )
434 {
435 if( Kiface().IsSingle() )
436 SendCommand( MSG_TO_PCB, packet );
437 else
438 {
439 // Typically ExpressMail is going to be s-expression packets, but since
440 // we have existing interpreter of the cross probe packet on the other
441 // side in place, we use that here.
443 }
444 }
445}
446
447
449{
450 std::string packet = "$CLEAR\n";
451
452 if( Kiface().IsSingle() )
453 {
454 SendCommand( MSG_TO_PCB, packet );
455 }
456 else
457 {
458 // Typically ExpressMail is going to be s-expression packets, but since
459 // we have existing interpreter of the cross probe packet on the other
460 // side in place, we use that here.
462 }
463}
464
465
467 const SCH_SHEET_LIST& aSchematicSheetList, const SCH_SHEET_PATH& aSheetPath,
468 std::unordered_map<wxString, std::vector<SCH_REFERENCE>>& aSyncSymMap,
469 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>>& aSyncPinMap,
470 bool aRecursive = false )
471{
472 if( aRecursive )
473 {
474 // Iterate over children
475 for( const SCH_SHEET_PATH& candidate : aSchematicSheetList )
476 {
477 if( candidate == aSheetPath || !candidate.IsContainedWithin( aSheetPath ) )
478 continue;
479
480 findSymbolsAndPins( aSchematicSheetList, candidate, aSyncSymMap, aSyncPinMap,
481 aRecursive );
482 }
483 }
484
485 SCH_REFERENCE_LIST references;
486
487 aSheetPath.GetSymbols( references, false, true );
488
489 for( unsigned ii = 0; ii < references.GetCount(); ii++ )
490 {
491 SCH_REFERENCE& schRef = references[ii];
492
493 if( schRef.IsSplitNeeded() )
494 schRef.Split();
495
496 SCH_SYMBOL* symbol = schRef.GetSymbol();
497 wxString refNum = schRef.GetRefNumber();
498 wxString fullRef = schRef.GetRef() + refNum;
499
500 // Skip power symbols
501 if( fullRef.StartsWith( wxS( "#" ) ) )
502 continue;
503
504 // Unannotated symbols are not supported
505 if( refNum.compare( wxS( "?" ) ) == 0 )
506 continue;
507
508 // Look for whole footprint
509 auto symMatchIt = aSyncSymMap.find( fullRef );
510
511 if( symMatchIt != aSyncSymMap.end() )
512 {
513 symMatchIt->second.emplace_back( schRef );
514
515 // Whole footprint was selected, no need to select pins
516 continue;
517 }
518
519 // Look for pins
520 auto symPinMatchIt = aSyncPinMap.find( fullRef );
521
522 if( symPinMatchIt != aSyncPinMap.end() )
523 {
524 std::unordered_map<wxString, SCH_PIN*>& pinMap = symPinMatchIt->second;
525 std::vector<SCH_PIN*> pinsOnSheet = symbol->GetPins( &aSheetPath );
526
527 for( SCH_PIN* pin : pinsOnSheet )
528 {
529 int pinUnit = pin->GetLibPin()->GetUnit();
530
531 if( pinUnit > 0 && pinUnit != schRef.GetUnit() )
532 continue;
533
534 auto pinIt = pinMap.find( pin->GetNumber() );
535
536 if( pinIt != pinMap.end() )
537 pinIt->second = pin;
538 }
539 }
540 }
541
542 return false;
543}
544
545
547 const SCH_SHEET_LIST& aSchematicSheetList, const SCH_SHEET_PATH& aSheetPath,
548 std::unordered_map<wxString, std::vector<SCH_REFERENCE>>& aSyncSymMap,
549 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>>& aSyncPinMap,
550 std::unordered_map<SCH_SHEET_PATH, bool>& aCache )
551{
552 auto cacheIt = aCache.find( aSheetPath );
553
554 if( cacheIt != aCache.end() )
555 return cacheIt->second;
556
557 // Iterate over children
558 for( const SCH_SHEET_PATH& candidate : aSchematicSheetList )
559 {
560 if( candidate == aSheetPath || !candidate.IsContainedWithin( aSheetPath ) )
561 continue;
562
563 bool childRet = sheetContainsOnlyWantedItems( aSchematicSheetList, candidate, aSyncSymMap,
564 aSyncPinMap, aCache );
565
566 if( !childRet )
567 {
568 aCache.emplace( aSheetPath, false );
569 return false;
570 }
571 }
572
573 SCH_REFERENCE_LIST references;
574 aSheetPath.GetSymbols( references, false, true );
575
576 if( references.GetCount() == 0 ) // Empty sheet, obviously do not contain wanted items
577 {
578 aCache.emplace( aSheetPath, false );
579 return false;
580 }
581
582 for( unsigned ii = 0; ii < references.GetCount(); ii++ )
583 {
584 SCH_REFERENCE& schRef = references[ii];
585
586 if( schRef.IsSplitNeeded() )
587 schRef.Split();
588
589 wxString refNum = schRef.GetRefNumber();
590 wxString fullRef = schRef.GetRef() + refNum;
591
592 // Skip power symbols
593 if( fullRef.StartsWith( wxS( "#" ) ) )
594 continue;
595
596 // Unannotated symbols are not supported
597 if( refNum.compare( wxS( "?" ) ) == 0 )
598 continue;
599
600 if( aSyncSymMap.find( fullRef ) == aSyncSymMap.end() )
601 {
602 aCache.emplace( aSheetPath, false );
603 return false; // Some symbol is not wanted.
604 }
605
606 if( aSyncPinMap.find( fullRef ) != aSyncPinMap.end() )
607 {
608 aCache.emplace( aSheetPath, false );
609 return false; // Looking for specific pins, so can't be mapped
610 }
611 }
612
613 aCache.emplace( aSheetPath, true );
614 return true;
615}
616
617
618std::optional<std::tuple<SCH_SHEET_PATH, SCH_ITEM*, std::vector<SCH_ITEM*>>>
619findItemsFromSyncSelection( const SCHEMATIC& aSchematic, const std::string aSyncStr,
620 bool aFocusOnFirst )
621{
622 wxArrayString syncArray = wxStringTokenize( aSyncStr, wxS( "," ) );
623
624 std::unordered_map<wxString, std::vector<SCH_REFERENCE>> syncSymMap;
625 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>> syncPinMap;
626 std::unordered_map<SCH_SHEET_PATH, double> symScores;
627 std::unordered_map<SCH_SHEET_PATH, bool> fullyWantedCache;
628
629 std::optional<wxString> focusSymbol;
630 std::optional<std::pair<wxString, wxString>> focusPin;
631 std::unordered_map<SCH_SHEET_PATH, std::vector<SCH_ITEM*>> focusItemResults;
632
633 const SCH_SHEET_LIST allSheetsList = aSchematic.Hierarchy();
634
635 // In orderedSheets, the current sheet comes first.
636 std::vector<SCH_SHEET_PATH> orderedSheets;
637 orderedSheets.reserve( allSheetsList.size() );
638 orderedSheets.push_back( aSchematic.CurrentSheet() );
639
640 for( const SCH_SHEET_PATH& sheetPath : allSheetsList )
641 {
642 if( sheetPath != aSchematic.CurrentSheet() )
643 orderedSheets.push_back( sheetPath );
644 }
645
646 // Init sync maps from the sync string
647 for( size_t i = 0; i < syncArray.size(); i++ )
648 {
649 wxString syncEntry = syncArray[i];
650
651 if( syncEntry.empty() )
652 continue;
653
654 wxString syncData = syncEntry.substr( 1 );
655
656 switch( syncEntry.GetChar( 0 ).GetValue() )
657 {
658 case 'F': // Select by footprint: F<Reference>
659 {
660 wxString symRef = UnescapeString( syncData );
661
662 if( aFocusOnFirst && ( i == 0 ) )
663 focusSymbol = symRef;
664
665 syncSymMap[symRef] = std::vector<SCH_REFERENCE>();
666 break;
667 }
668
669 case 'P': // Select by pad: P<Footprint reference>/<Pad number>
670 {
671 wxString symRef = UnescapeString( syncData.BeforeFirst( '/' ) );
672 wxString padNum = UnescapeString( syncData.AfterFirst( '/' ) );
673
674 if( aFocusOnFirst && ( i == 0 ) )
675 focusPin = std::make_pair( symRef, padNum );
676
677 syncPinMap[symRef][padNum] = nullptr;
678 break;
679 }
680
681 default:
682 break;
683 }
684 }
685
686 // Lambda definitions
687 auto flattenSyncMaps =
688 [&syncSymMap, &syncPinMap]() -> std::vector<SCH_ITEM*>
689 {
690 std::vector<SCH_ITEM*> allVec;
691
692 for( const auto& [symRef, symbols] : syncSymMap )
693 {
694 for( const SCH_REFERENCE& ref : symbols )
695 allVec.push_back( ref.GetSymbol() );
696 }
697
698 for( const auto& [symRef, pinMap] : syncPinMap )
699 {
700 for( const auto& [padNum, pin] : pinMap )
701 {
702 if( pin )
703 allVec.push_back( pin );
704 }
705 }
706
707 return allVec;
708 };
709
710 auto clearSyncMaps =
711 [&syncSymMap, &syncPinMap]()
712 {
713 for( auto& [symRef, symbols] : syncSymMap )
714 symbols.clear();
715
716 for( auto& [reference, pins] : syncPinMap )
717 {
718 for( auto& [number, pin] : pins )
719 pin = nullptr;
720 }
721 };
722
723 auto syncMapsValuesEmpty =
724 [&syncSymMap, &syncPinMap]() -> bool
725 {
726 for( const auto& [symRef, symbols] : syncSymMap )
727 {
728 if( symbols.size() > 0 )
729 return false;
730 }
731
732 for( const auto& [symRef, pins] : syncPinMap )
733 {
734 for( const auto& [padNum, pin] : pins )
735 {
736 if( pin )
737 return false;
738 }
739 }
740
741 return true;
742 };
743
744 auto checkFocusItems =
745 [&]( const SCH_SHEET_PATH& aSheet )
746 {
747 if( focusSymbol )
748 {
749 auto findIt = syncSymMap.find( *focusSymbol );
750
751 if( findIt != syncSymMap.end() )
752 {
753 if( findIt->second.size() > 0 )
754 focusItemResults[aSheet].push_back( findIt->second.front().GetSymbol() );
755 }
756 }
757 else if( focusPin )
758 {
759 auto findIt = syncPinMap.find( focusPin->first );
760
761 if( findIt != syncPinMap.end() )
762 {
763 if( findIt->second[focusPin->second] )
764 focusItemResults[aSheet].push_back( findIt->second[focusPin->second] );
765 }
766 }
767 };
768
769 auto makeRetForSheet =
770 [&]( const SCH_SHEET_PATH& aSheet, SCH_ITEM* aFocusItem )
771 {
772 clearSyncMaps();
773
774 // Fill sync maps
775 findSymbolsAndPins( allSheetsList, aSheet, syncSymMap, syncPinMap );
776 std::vector<SCH_ITEM*> itemsVector = flattenSyncMaps();
777
778 // Add fully wanted sheets to vector
779 for( SCH_ITEM* item : aSheet.LastScreen()->Items().OfType( SCH_SHEET_T ) )
780 {
781 KIID_PATH kiidPath = aSheet.Path();
782 kiidPath.push_back( item->m_Uuid );
783
784 std::optional<SCH_SHEET_PATH> subsheetPath =
785 allSheetsList.GetSheetPathByKIIDPath( kiidPath );
786
787 if( !subsheetPath )
788 continue;
789
790 if( sheetContainsOnlyWantedItems( allSheetsList, *subsheetPath, syncSymMap,
791 syncPinMap, fullyWantedCache ) )
792 {
793 itemsVector.push_back( item );
794 }
795 }
796
797 return std::make_tuple( aSheet, aFocusItem, itemsVector );
798 };
799
800 if( aFocusOnFirst )
801 {
802 for( const SCH_SHEET_PATH& sheetPath : orderedSheets )
803 {
804 clearSyncMaps();
805
806 findSymbolsAndPins( allSheetsList, sheetPath, syncSymMap, syncPinMap );
807
808 checkFocusItems( sheetPath );
809 }
810
811 if( focusItemResults.size() > 0 )
812 {
813 for( const SCH_SHEET_PATH& sheetPath : orderedSheets )
814 {
815 const std::vector<SCH_ITEM*>& items = focusItemResults[sheetPath];
816
817 if( !items.empty() )
818 return makeRetForSheet( sheetPath, items.front() );
819 }
820 }
821 }
822 else
823 {
824 for( const SCH_SHEET_PATH& sheetPath : orderedSheets )
825 {
826 clearSyncMaps();
827
828 findSymbolsAndPins( allSheetsList, sheetPath, syncSymMap, syncPinMap );
829
830 if( !syncMapsValuesEmpty() )
831 {
832 // Something found on sheet
833 return makeRetForSheet( sheetPath, nullptr );
834 }
835 }
836 }
837
838 return std::nullopt;
839}
840
841
843{
844 std::string& payload = mail.GetPayload();
845
846 switch( mail.Command() )
847 {
849 {
850 std::stringstream ss( payload );
851 std::string file;
852
855 std::optional<LIBRARY_TABLE*> optTable = manager.Table( LIBRARY_TABLE_TYPE::SYMBOL,
857
858 wxCHECK_RET( optTable.has_value(), "Could not load symbol lib table." );
859 LIBRARY_TABLE* table = optTable.value();
860
861 wxString projectPath = Prj().GetProjectPath();
862
863 // First line of payload is the source project directory.
864 std::string srcProjDir;
865 std::getline( ss, srcProjDir, '\n' );
866
867 std::vector<wxString> toLoad;
868
869 while( std::getline( ss, file, '\n' ) )
870 {
871 if( file.empty() )
872 continue;
873
874 wxFileName fn( file );
876 SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
877
878 if( type == SCH_IO_MGR::SCH_FILE_UNKNOWN )
879 {
880 wxLogTrace( "KIWAY", "Unknown file type: %s", fn.GetFullPath() );
881 continue;
882 }
883
884 pi.reset( SCH_IO_MGR::FindPlugin( type ) );
885
886 wxString libTableUri;
887 bool isProjectLocal = fn.GetFullPath().StartsWith( wxString( srcProjDir ) );
888
889 if( isProjectLocal )
890 {
891 // Project-local library: copy into the KiCad project directory and use a
892 // project-relative path so the sym-lib-table stays portable.
893 if( !fn.FileExists() )
894 continue;
895
896 wxFileName projectFn( projectPath, fn.GetFullName() );
897
898 if( fn.GetFullPath() != projectFn.GetFullPath() && !projectFn.FileExists() )
899 wxCopyFile( fn.GetFullPath(), projectFn.GetFullPath() );
900
901 libTableUri = wxS( "${KIPRJMOD}/" ) + fn.GetFullName();
902 }
903 else
904 {
905 // External library referenced by absolute path. Preserve the original path.
906 libTableUri = fn.GetFullPath();
907 }
908
909 if( !table->HasRow( fn.GetName() ) )
910 {
911 LIBRARY_TABLE_ROW& row = table->InsertRow();
912 row.SetNickname( fn.GetName() );
913 row.SetURI( libTableUri );
914 row.SetType( SCH_IO_MGR::ShowType( type ) );
915 toLoad.emplace_back( fn.GetName() );
916 }
917 }
918
919 if( !toLoad.empty() )
920 {
921 bool success = true;
922
923 table->Save().map_error(
924 [&]( const LIBRARY_ERROR& aError )
925 {
926 wxLogError( wxT( "Error saving project library table:\n\n" ) + aError.message );
927 success = false;
928 } );
929
930 if( success )
931 {
933
934 std::ranges::for_each( toLoad,
935 [adapter]( const wxString& aNick )
936 {
937 adapter->LoadOne( aNick );
938 } );
939 }
940 }
941
945
946 break;
947 }
948
949 case MAIL_CROSS_PROBE:
950 ExecuteRemoteCommand( payload.c_str() );
951 break;
952
953 case MAIL_SELECTION:
954 if( !eeconfig()->m_CrossProbing.on_selection )
955 break;
956
958
960 {
961 // $SELECT: 0,<spec1>,<spec2>,<spec3>
962 // Try to select specified items.
963
964 // $SELECT: 1,<spec1>,<spec2>,<spec3>
965 // Select and focus on <spec1> item, select other specified items that are on the
966 // same sheet.
967
968 std::string prefix = "$SELECT: ";
969
970 std::string paramStr = payload.substr( prefix.size() );
971
972 // Empty/broken command: we need at least 2 chars for sync string.
973 if( paramStr.size() < 2 )
974 break;
975
976 std::string syncStr = paramStr.substr( 2 );
977
978 bool focusOnFirst = ( paramStr[0] == '1' );
979
980 std::optional<std::tuple<SCH_SHEET_PATH, SCH_ITEM*, std::vector<SCH_ITEM*>>> findRet =
981 findItemsFromSyncSelection( Schematic(), syncStr, focusOnFirst );
982
983 if( findRet )
984 {
985 auto& [sheetPath, focusItem, items] = *findRet;
986
987 m_syncingPcbToSchSelection = true; // recursion guard
988
989 GetToolManager()->GetTool<SCH_SELECTION_TOOL>()->SyncSelection( sheetPath, focusItem,
990 items );
991
993
994 if( eeconfig()->m_CrossProbing.flash_selection )
995 {
996 wxLogTrace( traceCrossProbeFlash, "MAIL_SELECTION(_FORCE): flash enabled, items=%zu", items.size() );
997 if( items.empty() )
998 {
999 wxLogTrace( traceCrossProbeFlash, "MAIL_SELECTION(_FORCE): nothing to flash" );
1000 }
1001 else
1002 {
1003 std::vector<SCH_ITEM*> itemPtrs;
1004 std::copy( items.begin(), items.end(), std::back_inserter( itemPtrs ) );
1005
1006 StartCrossProbeFlash( itemPtrs );
1007 }
1008 }
1009 else
1010 {
1011 wxLogTrace( traceCrossProbeFlash, "MAIL_SELECTION(_FORCE): flash disabled" );
1012 }
1013 }
1014
1015 break;
1016 }
1017
1019 {
1020 if( !payload.empty() )
1021 {
1022 wxString annotationMessage( payload );
1023
1024 // Ensure schematic is OK for netlist creation (especially that it is fully annotated):
1025 if( !ReadyToNetlist( annotationMessage ) )
1026 return;
1027 }
1028
1029 if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity )
1031
1032 NETLIST_EXPORTER_KICAD exporter( &Schematic() );
1033 STRING_FORMATTER formatter;
1034
1035 exporter.Format( &formatter, GNL_ALL | GNL_OPT_KICAD );
1036
1037 payload = formatter.GetString();
1038 break;
1039 }
1040
1041 case MAIL_SCH_GET_ITEM:
1042 {
1043 KIID uuid( payload );
1045
1046 if( SCH_ITEM* item = m_schematic->ResolveItem( uuid, &path, true ) )
1047 {
1048 if( item->Type() == SCH_SHEET_T )
1049 payload = static_cast<SCH_SHEET*>( item )->GetShownName( false );
1050 else if( item->Type() == SCH_SYMBOL_T )
1051 payload = static_cast<SCH_SYMBOL*>( item )->GetRef( &path, true );
1052 else
1053 payload = item->GetFriendlyName();
1054 }
1055
1056 break;
1057 }
1058
1060 try
1061 {
1062 SCH_EDITOR_CONTROL* controlTool = m_toolManager->GetTool<SCH_EDITOR_CONTROL>();
1063 controlTool->AssignFootprints( payload );
1064 }
1065 catch( const IO_ERROR& )
1066 {
1067 }
1068 break;
1069
1070 case MAIL_SCH_REFRESH:
1071 {
1073
1075 GetCanvas()->Refresh();
1076 break;
1077 }
1078
1079 case MAIL_IMPORT_FILE:
1080 {
1081 // Extract file format type and path (plugin type, path and properties keys, values
1082 // separated with \n)
1083 std::stringstream ss( payload );
1084 char delim = '\n';
1085
1086 std::string formatStr;
1087 wxCHECK( std::getline( ss, formatStr, delim ), /* void */ );
1088
1089 std::string fnameStr;
1090 wxCHECK( std::getline( ss, fnameStr, delim ), /* void */ );
1091
1092 int importFormat;
1093
1094 try
1095 {
1096 importFormat = std::stoi( formatStr );
1097 }
1098 catch( std::invalid_argument& )
1099 {
1100 wxFAIL;
1101 importFormat = -1;
1102 }
1103
1104 std::map<std::string, UTF8> props;
1105
1106 do
1107 {
1108 std::string key, value;
1109
1110 if( !std::getline( ss, key, delim ) )
1111 break;
1112
1113 std::getline( ss, value, delim ); // We may want an empty string as value
1114
1115 props.emplace( key, value );
1116
1117 } while( true );
1118
1119 if( importFormat >= 0 )
1120 importFile( fnameStr, importFormat, props.empty() ? nullptr : &props );
1121
1122 break;
1123 }
1124
1125 case MAIL_SCH_SAVE:
1126 if( SaveProject() )
1127 payload = "success";
1128
1129 break;
1130
1131 case MAIL_SCH_UPDATE:
1133 break;
1134
1135 case MAIL_RELOAD_LIB:
1136 {
1137 if( m_designBlocksPane && m_designBlocksPane->IsShown() )
1138 {
1139 m_designBlocksPane->RefreshLibs();
1140 SyncView();
1141 }
1142
1143 // Show any symbol library load errors in the status bar
1144 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
1145 {
1147 wxString errors = adapter->GetLibraryLoadErrors();
1148
1149 if( !errors.IsEmpty() )
1150 statusBar->SetLoadWarningMessages( errors );
1151 }
1152
1153 break;
1154 }
1155
1157 {
1158 wxString targetFile( payload );
1159
1160 for( SCH_SHEET_PATH& sheetPath : m_schematic->Hierarchy() )
1161 {
1162 SCH_SCREEN* screen = sheetPath.LastScreen();
1163
1164 if( screen && screen->GetFileName() == targetFile )
1165 {
1166 m_toolManager->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet, &sheetPath );
1167 payload = "success";
1168 Raise();
1169 return;
1170 }
1171 }
1172
1173 payload.clear();
1174 break;
1175 }
1176
1177 default:;
1178
1179 }
1180}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
static TOOL_ACTION showSymbolLibTable
Definition actions.h:282
static TOOL_ACTION updateSchematicFromPcb
Definition actions.h:265
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
CROSS_PROBING_SETTINGS m_CrossProbing
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:99
const KIID m_Uuid
Definition eda_item.h:522
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1576
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:244
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition kiway_mail.h:38
std::string & GetPayload()
Return the payload, which can be any text but it typically self identifying s-expression.
Definition kiway_mail.h:56
MAIL_T Command()
Returns the MAIL_T associated with this mail.
Definition kiway_mail.h:48
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
Definition kiway.cpp:505
wxString GetLibraryLoadErrors() const
Returns all library load errors as newline-separated strings for display.
std::optional< LIBRARY_TABLE * > Table(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope)
Retrieves a given table; creating a new empty project table if a valid project is loaded and the give...
void LoadProjectTables(std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
(Re)loads the project library tables in the given list, or all tables if no list is given
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
Generate the KiCad netlist format supported by Pcbnew.
void Format(OUTPUTFORMATTER *aOutputFormatter, int aCtl)
Output this s-expression netlist into aOutputFormatter.
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:133
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:177
Holds all the data relating to one schematic.
Definition schematic.h:88
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:187
static TOOL_ACTION runERC
Inspection and Editing.
static TOOL_ACTION changeSheet
static TOOL_ACTION updateNetHighlighting
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SyncView()
Mark all items for refresh.
EESCHEMA_SETTINGS * eeconfig() const
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
bool IsNet() const
const std::vector< std::shared_ptr< SCH_CONNECTION > > AllMembers() const
wxString Name(bool aIgnoreSheet=false) const
const std::vector< std::shared_ptr< SCH_CONNECTION > > & Members() const
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void AssignFootprints(const std::string &aChangedSetOfReferences)
SCH_ITEM * FindSymbolAndItem(const wxString *aPath, const wxString *aReference, bool aSearchHierarchy, SCH_SEARCH_T aSearchType, const wxString &aSearchText)
Find a symbol in the schematic and an item in this symbol and select it.
bool ReadyToNetlist(const wxString &aAnnotateMessage)
Check if we are ready to write a netlist file for the current schematic.
bool m_syncingPcbToSchSelection
friend class SCH_EDITOR_CONTROL
void SendSelectItemsToPcb(const std::vector< EDA_ITEM * > &aItems, bool aForce)
Send items to board editor for selection.
void SendCrossProbeClearHighlight()
Tell Pcbnew to clear the existing highlighted net, if one exists.
SCHEMATIC * m_schematic
The currently loaded schematic.
SCH_SHEET_PATH & GetCurrentSheet() const
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr)
Generate the connection data for the entire schematic hierarchy.
SCHEMATIC & Schematic() const
void ExecuteRemoteCommand(const char *cmdline) override
Execute a remote command sent via a socket on port KICAD_SCH_PORT_SERVICE_NUMBER (which defaults to 4...
void RefreshNetNavigator(const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr)
SCH_DESIGN_BLOCK_PANE * m_designBlocksPane
bool importFile(const wxString &aFileName, int aFileType, const std::map< std::string, UTF8 > *aProperties=nullptr)
Load the given filename but sets the path to the current project path.
void SendCrossProbeNetName(const wxString &aNetName)
Send a net name to Pcbnew for highlighting.
void KiwayMailIn(KIWAY_MAIL_EVENT &aEvent) override
Receive #KIWAY_ROUTED_EVENT messages from other players.
void StartCrossProbeFlash(const std::vector< SCH_ITEM * > &aItems)
wxString m_highlightedConn
The highlighted net or bus or empty string.
void SetCrossProbeConnection(const SCH_CONNECTION *aConnection)
Send a connection (net or bus) to Pcbnew for highlighting.
void TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
bool SaveProject(bool aSaveAs=false)
Save the currently-open schematic (including its hierarchy) and associated project.
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:116
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
static SCH_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a symbol library using the file extension of aLibPath.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:168
int GetUnit() const
Definition sch_item.h:239
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
A helper to define a symbol's reference designator in a schematic.
void Split()
Attempt to split the reference designator into a name (U) and number (1).
bool IsSplitNeeded()
Determine if this reference needs to be split or if it likely already has been.
SCH_SYMBOL * GetSymbol() const
wxString GetRef() const
wxString GetRefNumber() const
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:119
const wxString & GetFileName() const
Definition sch_screen.h:154
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...
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Adds SCH_REFERENCE object to aReferences for each symbol in the sheet.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCH_SCREEN * LastScreen()
bool IsContainedWithin(const SCH_SHEET_PATH &aSheetPathToTest) const
Check if this path is contained inside aSheetPathToTest.
wxString PathAsString() const
Return the path of time stamps which do not changes even when editing sheet parameters.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
Schematic symbol object.
Definition sch_symbol.h:76
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:422
const std::string & GetString()
Definition richio.h:445
An interface to the global shared library manager that is schematic-specific and linked to one projec...
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:63
virtual const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const =0
TOOL_MANAGER * m_toolManager
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
#define _(s)
bool SendCommand(int aService, const std::string &aMessage)
Used by a client to sent (by a socket connection) a data to a server.
Definition eda_dde.cpp:230
DDE server & client.
#define MSG_TO_PCB
Definition eda_dde.h:49
std::optional< std::tuple< SCH_SHEET_PATH, SCH_ITEM *, std::vector< SCH_ITEM * > > > findItemsFromSyncSelection(const SCHEMATIC &aSchematic, const std::string aSyncStr, bool aFocusOnFirst)
bool findSymbolsAndPins(const SCH_SHEET_LIST &aSchematicSheetList, const SCH_SHEET_PATH &aSheetPath, std::unordered_map< wxString, std::vector< SCH_REFERENCE > > &aSyncSymMap, std::unordered_map< wxString, std::unordered_map< wxString, SCH_PIN * > > &aSyncPinMap, bool aRecursive=false)
bool sheetContainsOnlyWantedItems(const SCH_SHEET_LIST &aSchematicSheetList, const SCH_SHEET_PATH &aSheetPath, std::unordered_map< wxString, std::vector< SCH_REFERENCE > > &aSyncSymMap, std::unordered_map< wxString, std::unordered_map< wxString, SCH_PIN * > > &aSyncPinMap, std::unordered_map< SCH_SHEET_PATH, bool > &aCache)
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ FRAME_SCH_VIEWER
Definition frame_type.h:36
@ FRAME_CVPCB
Definition frame_type.h:52
const wxChar *const traceCrossProbeFlash
Flag to enable debug output for cross-probe flash operations.
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
PROJECT & Prj()
Definition kicad.cpp:642
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:83
@ MAIL_IMPORT_FILE
Definition mail_type.h:48
@ MAIL_SCH_REFRESH
Definition mail_type.h:53
@ MAIL_CROSS_PROBE
Definition mail_type.h:39
@ MAIL_SELECTION_FORCE
Definition mail_type.h:41
@ MAIL_SCH_SAVE
Definition mail_type.h:43
@ MAIL_ASSIGN_FOOTPRINTS
Definition mail_type.h:42
@ MAIL_SCH_GET_ITEM
Definition mail_type.h:50
@ MAIL_SCH_UPDATE
Definition mail_type.h:47
@ MAIL_ADD_LOCAL_LIB
Definition mail_type.h:54
@ MAIL_SCH_NAVIGATE_TO_SHEET
Definition mail_type.h:60
@ MAIL_SCH_GET_NETLIST
Definition mail_type.h:49
@ MAIL_SELECTION
Definition mail_type.h:40
@ MAIL_RELOAD_LIB
Definition mail_type.h:57
@ ALL
All except INITIAL_ADD.
Definition view_item.h:59
#define GNL_ALL
@ GNL_OPT_KICAD
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
SCH_SEARCH_T
Schematic search type used by the socket link with Pcbnew.
@ HIGHLIGHT_SYMBOL
@ HIGHLIGHT_PIN
@ GLOBAL_CLEANUP
Definition schematic.h:77
KIWAY Kiway(KFCTL_STANDALONE)
wxString UnescapeString(const wxString &aSource)
wxString From_UTF8(const char *cstring)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
@ CTX_IPC
Cross-probing behavior.
bool on_selection
Synchronize the selection for multiple items too.
bool zoom_to_fit
Zoom to fit items (ignored if center_on_items is off).
bool center_on_items
Automatically pan to cross-probed items.
bool auto_highlight
Automatically turn on highlight mode in the target frame.
wxString message
@ REFERENCE
Field Reference of part, i.e. "IC21".
std::string path
KIBIS_PIN * pin
wxLogTrace helper definitions.
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_SHEET_T
Definition typeinfo.h:179
@ SCH_PIN_T
Definition typeinfo.h:157