KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_editor_control.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-2023 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26
27#include <clipboard.h>
28#include <confirm.h>
29#include <connection_graph.h>
30#include <design_block.h>
40#include <project_rescue.h>
41#include <erc/erc.h>
42#include <invoke_sch_dialog.h>
43#include <string_utils.h>
44#include <kiway.h>
46#include <paths.h>
47#include <pgm_base.h>
50#include <project_sch.h>
51#include <richio.h>
53#include <sch_edit_frame.h>
55#include <sch_bitmap.h>
56#include <sch_group.h>
57#include <sch_line.h>
58#include <sch_junction.h>
59#include <sch_bus_entry.h>
60#include <sch_shape.h>
61#include <sch_painter.h>
62#include <sch_sheet_pin.h>
63#include <sch_table.h>
64#include <sch_tablecell.h>
65#include <sch_commit.h>
66#include <sim/simulator_frame.h>
68#include <symbol_viewer_frame.h>
69#include <tool/picker_tool.h>
70#include <tool/tool_manager.h>
71#include <tools/sch_actions.h>
72#include <tools/sch_selection.h>
77#include <view/view_controls.h>
79#include <wx_filename.h>
80#include <wx/filedlg.h>
81#include <wx/log.h>
82#include <wx/treectrl.h>
83#include <wx/msgdlg.h>
87
88#ifdef KICAD_IPC_API
90#endif
91
92
98static const wxChar traceSchPaste[] = wxT( "KICAD_SCH_PASTE" );
99
100
102{
103 m_frame->NewProject();
104 return 0;
105}
106
107
109{
110 m_frame->LoadProject();
111 return 0;
112}
113
114
116{
117 m_frame->SaveProject();
118 return 0;
119}
120
121
123{
124 m_frame->SaveProject( true );
125 return 0;
126}
127
128
130{
131 SCH_SHEET* curr_sheet = m_frame->GetCurrentSheet().Last();
132 wxFileName curr_fn = curr_sheet->GetFileName();
133 wxFileDialog dlg( m_frame, _( "Schematic Files" ), curr_fn.GetPath(), curr_fn.GetFullName(),
134 FILEEXT::KiCadSchematicFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
135
136 if( dlg.ShowModal() == wxID_CANCEL )
137 return false;
138
139 wxString newFilename = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
140
141 m_frame->saveSchematicFile( curr_sheet, newFilename );
142 return 0;
143}
144
145
147{
148 SCHEMATIC& schematic = m_frame->Schematic();
149 SCH_SHEET& root = schematic.Root();
150
151 if( m_frame->GetCurrentSheet().Last() != &root )
152 {
153 SCH_SHEET_PATH rootSheetPath;
154 rootSheetPath.push_back( &root );
155
156 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet, &rootSheetPath );
157 wxSafeYield();
158 }
159
160 wxString msg;
161 msg.Printf( _( "Revert '%s' (and all sub-sheets) to last version saved?" ), schematic.GetFileName() );
162
163 if( !IsOK( m_frame, msg ) )
164 return false;
165
166 SCH_SCREENS screenList( schematic.Root() );
167
168 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
169 screen->SetContentModified( false ); // do not prompt the user for changes
170
171 m_frame->ReleaseFile();
172 m_frame->OpenProjectFiles( std::vector<wxString>( 1, schematic.GetFileName() ), KICTL_REVERT );
173
174 return 0;
175}
176
177
179{
180 m_frame->ShowSchematicSetupDialog();
181 return 0;
182}
183
184
186{
187 PICKED_ITEMS_LIST undoCmd;
189 ITEM_PICKER wrapper( m_frame->GetScreen(), undoItem, UNDO_REDO::PAGESETTINGS );
190
191 undoCmd.PushItem( wrapper );
192 undoCmd.SetDescription( _( "Page Settings" ) );
193 m_frame->SaveCopyInUndoList( undoCmd, UNDO_REDO::PAGESETTINGS, false );
194
195 DIALOG_EESCHEMA_PAGE_SETTINGS dlg( m_frame, m_frame->Schematic().GetEmbeddedFiles(),
198
199 if( dlg.ShowModal() == wxID_OK )
200 {
201 // Update text variables
202 m_frame->GetCanvas()->GetView()->MarkDirty();
203 m_frame->GetCanvas()->GetView()->UpdateAllItems( KIGFX::REPAINT );
204 m_frame->GetCanvas()->Refresh();
205
206 m_frame->OnModify();
207 }
208 else
209 {
210 m_frame->RollbackSchematicFromUndo();
211 }
212
213 return 0;
214}
215
216
218{
219 SCH_SCREENS schematic( m_frame->Schematic().Root() );
220
221 if( schematic.HasNoFullyDefinedLibIds() )
222 RescueLegacyProject( true );
223 else
225
226 return 0;
227}
228
229
230bool SCH_EDITOR_CONTROL::RescueLegacyProject( bool aRunningOnDemand )
231{
232 LEGACY_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
233 m_frame->GetCanvas()->GetBackend() );
234
235 return rescueProject( rescuer, aRunningOnDemand );
236}
237
238
240{
241 SYMBOL_LIB_TABLE_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
242 m_frame->GetCanvas()->GetBackend() );
243
244 return rescueProject( rescuer, aRunningOnDemand );
245}
246
247
248bool SCH_EDITOR_CONTROL::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
249{
250 if( !RESCUER::RescueProject( m_frame, aRescuer, aRunningOnDemand ) )
251 return false;
252
253 if( aRescuer.GetCandidateCount() )
254 {
255 KIWAY_PLAYER* viewer = m_frame->Kiway().Player( FRAME_SCH_VIEWER, false );
256
257 if( viewer )
258 static_cast<SYMBOL_VIEWER_FRAME*>( viewer )->ReCreateLibList();
259
260 if( aRunningOnDemand )
261 {
262 SCH_SCREENS schematic( m_frame->Schematic().Root() );
263
264 schematic.UpdateSymbolLinks();
265 m_frame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
266 }
267
268 m_frame->ClearUndoRedoList();
269 m_frame->SyncView();
270 m_frame->GetCanvas()->Refresh();
271 m_frame->OnModify();
272 }
273
274 return true;
275}
276
277
279{
280 DIALOG_SYMBOL_REMAP dlgRemap( m_frame );
281
282 dlgRemap.ShowQuasiModal();
283
284 m_frame->GetCanvas()->Refresh( true );
285
286 return 0;
287}
288
289
291{
292 DIALOG_PRINT dlg( m_frame );
293
294 dlg.ShowModal();
295
296 return 0;
297}
298
299
301{
303
304 dlg.ShowModal();
305
306 return 0;
307}
308
309
311{
312 m_frame->Close( false );
313 return 0;
314}
315
316
318{
319 doCrossProbeSchToPcb( aEvent, false );
320 return 0;
321}
322
323
325{
326 doCrossProbeSchToPcb( aEvent, true );
327 return 0;
328}
329
330
331void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
332{
333 // Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
334 if( m_probingPcbToSch || m_frame->IsSyncingSelection() )
335 return;
336
337 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
338 SCH_SELECTION& selection = aForce ? selTool->RequestSelection() : selTool->GetSelection();
339
340 m_frame->SendSelectItemsToPcb( selection.GetItemsSortedBySelectionOrder(), aForce );
341}
342
343
345{
346 bool savePowerSymbols = false;
347 bool map = false;
349 wxString targetLib;
350 wxString msg;
351
352 targetLib = m_frame->SelectLibrary( _( "Export Symbols" ), _( "Export symbols to library:" ),
353 { { _( "Include power symbols in export" ), &savePowerSymbols },
354 { _( "Update schematic symbols to link to exported symbols" ), &map }
355 } );
356
357 if( targetLib.empty() )
358 return 0;
359
360 SCH_SHEET_LIST sheets = m_frame->Schematic().BuildSheetListSortedByPageNumbers();
361 SCH_REFERENCE_LIST symbols;
362 sheets.GetSymbols( symbols, savePowerSymbols );
363
364 std::map<LIB_ID, LIB_SYMBOL*> libSymbols;
365 std::map<LIB_ID, std::vector<SCH_SYMBOL*>> symbolMap;
366
367 for( size_t i = 0; i < symbols.GetCount(); ++i )
368 {
369 SCH_SYMBOL* symbol = symbols[i].GetSymbol();
370 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
371 LIB_ID id = libSymbol->GetLibId();
372
373 if( libSymbols.count( id ) )
374 {
375 wxASSERT_MSG( libSymbols[id]->Compare( *libSymbol, SCH_ITEM::COMPARE_FLAGS::ERC ) == 0,
376 "Two symbols have the same LIB_ID but are different!" );
377 }
378 else
379 {
380 libSymbols[id] = libSymbol;
381 }
382
383 symbolMap[id].emplace_back( symbol );
384 }
385
386 bool append = false;
387 SCH_COMMIT commit( m_frame );
389
390 auto optRow = adapter->GetRow( targetLib );
391 wxCHECK( optRow, 0 );
392 const LIBRARY_TABLE_ROW* row = *optRow;
393
394 SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::EnumFromStr( row->Type() );
395 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
396
397 wxFileName dest = LIBRARY_MANAGER::GetFullURI( row );
398 dest.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
399
400 for( const std::pair<const LIB_ID, LIB_SYMBOL*>& it : libSymbols )
401 {
402 LIB_SYMBOL* origSym = it.second;
403 LIB_SYMBOL* newSym = origSym->Flatten().release();
404
405 try
406 {
407 pi->SaveSymbol( dest.GetFullPath(), newSym );
408 }
409 catch( const IO_ERROR& ioe )
410 {
411 msg.Printf( _( "Error saving symbol %s to library '%s'." ), newSym->GetName(), row->Nickname() );
412 msg += wxS( "\n\n" ) + ioe.What();
413 wxLogWarning( msg );
414 return 0;
415 }
416
417 if( map )
418 {
419 LIB_ID id = it.first;
420 id.SetLibNickname( targetLib );
421
422 for( SCH_SYMBOL* symbol : symbolMap[it.first] )
423 {
424 SCH_SCREEN* parentScreen = static_cast<SCH_SCREEN*>( symbol->GetParent() );
425
426 wxCHECK2( parentScreen, continue );
427
428 commit.Modify( symbol, parentScreen, RECURSE_MODE::NO_RECURSE );
429 symbol->SetLibId( id );
430 append = true;
431 }
432 }
433 }
434
435 if( append )
436 {
437 std::set<SCH_SCREEN*> processedScreens;
438
439 for( SCH_SHEET_PATH& sheet : sheets )
440 {
441 SCH_SCREEN* screen = sheet.LastScreen();
442
443 if( processedScreens.find( ( screen ) ) == processedScreens.end() )
444 {
445 processedScreens.insert( screen );
446 screen->UpdateSymbolLinks();
447 }
448 }
449
450 commit.Push( wxS( "Update Library Identifiers" ) );
451 }
452
453 return 0;
454}
455
456
457#define HITTEST_THRESHOLD_PIXELS 5
458
460{
461 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
462 KIWAY_PLAYER* sim_player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
463 SIMULATOR_FRAME* sim_Frame = static_cast<SIMULATOR_FRAME*>( sim_player );
464
465 if( !sim_Frame ) // Defensive coding; shouldn't happen.
466 return 0;
467
468 if( wxWindow* blocking_win = sim_Frame->Kiway().GetBlockingDialog() )
469 blocking_win->Close( true );
470
471 // Deactivate other tools; particularly important if another PICKER is currently running
472 Activate();
473
475 picker->SetSnapping( false );
476 picker->ClearHandlers();
477
478 picker->SetClickHandler(
479 [this]( const VECTOR2D& aPosition )
480 {
481 KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
482 SIMULATOR_FRAME* simFrame = static_cast<SIMULATOR_FRAME*>( player );
483 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
484
485 // We do not really want to keep an item selected in schematic,
486 // so clear the current selection
487 selTool->ClearSelection();
488
489 EDA_ITEM* item = selTool->GetNode( aPosition );
490 SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
491
492 if( !item )
493 return false;
494
495 if( item->Type() == SCH_PIN_T )
496 {
497 SCH_PIN* schPin = static_cast<SCH_PIN*>( item );
498 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( schPin->GetParentSymbol() );
499 SCH_PIN* libPin = schPin->GetLibPin();
500
501 if( !symbol || !libPin )
502 return false;
503
504 try
505 {
506 WX_STRING_REPORTER reporter;
507 SIM_LIB_MGR mgr( &m_frame->Prj() );
508
509 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
510 embeddedFilesStack.push_back( m_frame->Schematic().GetEmbeddedFiles() );
511
512 if( EMBEDDED_FILES* symbolEmbeddedFile = symbol->GetEmbeddedFiles() )
513 embeddedFilesStack.push_back( symbolEmbeddedFile );
514
515 mgr.SetFilesStack( std::move( embeddedFilesStack ) );
516
517 SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, true, 0, reporter ).model;
518
519 if( reporter.HasMessage() )
520 THROW_IO_ERROR( reporter.GetMessages() );
521
522 SPICE_ITEM spiceItem;
523 spiceItem.refName = symbol->GetRef( &sheet ).ToStdString();
524 std::vector<std::string> currentNames = model.SpiceGenerator().CurrentNames( spiceItem );
525
526 if( currentNames.size() == 0 )
527 {
528 return true;
529 }
530 else if( currentNames.size() == 1 )
531 {
532 if( simFrame )
533 simFrame->AddCurrentTrace( currentNames.at( 0 ) );
534
535 return true;
536 }
537
538 int modelPinIndex = model.FindModelPinIndex( libPin->GetNumber().ToStdString() );
539
540 if( modelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
541 {
542 wxString name = currentNames.at( modelPinIndex );
543
544 if( simFrame )
545 simFrame->AddCurrentTrace( name );
546 }
547 }
548 catch( const IO_ERROR& e )
549 {
551 }
552 }
553 else if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T } ) || item->IsType( { SCH_JUNCTION_T } ) )
554 {
555 if( SCH_CONNECTION* conn = static_cast<SCH_ITEM*>( item )->Connection() )
556 {
557 wxString spiceNet = UnescapeString( conn->Name() );
559
560 if( simFrame )
561 simFrame->AddVoltageTrace( wxString::Format( "V(%s)", spiceNet ) );
562 }
563 }
564
565 return true;
566 } );
567
568 picker->SetMotionHandler(
569 [this]( const VECTOR2D& aPos )
570 {
571 SCH_COLLECTOR collector;
572 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
573 collector.Collect( m_frame->GetScreen(), { SCH_ITEM_LOCATE_WIRE_T,
574 SCH_PIN_T,
575 SCH_SHEET_PIN_T }, aPos );
576
577 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
578 selectionTool->GuessSelectionCandidates( collector, aPos );
579
580 EDA_ITEM* item = collector.GetCount() == 1 ? collector[0] : nullptr;
581 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( item );
582
583 const SCH_CONNECTION* conn = nullptr;
584
585 if( wire )
586 {
587 item = nullptr;
588 conn = wire->Connection();
589 }
590
591 if( item && item->Type() == SCH_PIN_T )
592 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::CURRENT_PROBE );
593 else
594 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::VOLTAGE_PROBE );
595
596 if( m_pickerItem != item )
597 {
598 if( m_pickerItem )
599 selectionTool->UnbrightenItem( m_pickerItem );
600
601 m_pickerItem = item;
602
603 if( m_pickerItem )
604 selectionTool->BrightenItem( m_pickerItem );
605 }
606
607 wxString connectionName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
608
609 if( m_frame->GetHighlightedConnection() != connectionName )
610 {
611 m_frame->SetHighlightedConnection( connectionName );
612
613 TOOL_EVENT dummyEvent;
614 UpdateNetHighlighting( dummyEvent );
615 }
616 } );
617
618 picker->SetFinalizeHandler(
619 [this]( const int& aFinalState )
620 {
621 if( m_pickerItem )
622 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
623
624 if( !m_frame->GetHighlightedConnection().IsEmpty() )
625 {
626 m_frame->SetHighlightedConnection( wxEmptyString );
627
628 TOOL_EVENT dummyEvent;
629 UpdateNetHighlighting( dummyEvent );
630 }
631
632 // Wake the selection tool after exiting to ensure the cursor gets updated
633 // and deselect previous selection from simulator to avoid any issue
634 // ( avoid crash in some cases when the SimProbe tool is deselected )
635 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
636 selectionTool->ClearSelection();
638 } );
639
640 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
641
642 return 0;
643}
644
645
647{
648 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
649
650 // Deactivate other tools; particularly important if another PICKER is currently running
651 Activate();
652
653 picker->SetCursor( KICURSOR::TUNE );
654 picker->SetSnapping( false );
655 picker->ClearHandlers();
656
657 picker->SetClickHandler(
658 [this]( const VECTOR2D& aPosition )
659 {
660 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
661 EDA_ITEM* item = nullptr;
662 selTool->SelectPoint( aPosition, { SCH_SYMBOL_T, SCH_FIELD_T }, &item );
663
664 if( !item )
665 return false;
666
667 if( item->Type() != SCH_SYMBOL_T )
668 {
669 item = item->GetParent();
670
671 if( item->Type() != SCH_SYMBOL_T )
672 return false;
673 }
674
675 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
676 SCH_SHEET_PATH sheetPath = symbol->Schematic()->CurrentSheet();
677 KIWAY_PLAYER* simFrame = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
678
679 if( simFrame )
680 {
681 if( wxWindow* blocking_win = simFrame->Kiway().GetBlockingDialog() )
682 blocking_win->Close( true );
683
684 static_cast<SIMULATOR_FRAME*>( simFrame )->AddTuner( sheetPath, symbol );
685 }
686
687 // We do not really want to keep a symbol selected in schematic,
688 // so clear the current selection
689 selTool->ClearSelection();
690 return true;
691 } );
692
693 picker->SetMotionHandler(
694 [this]( const VECTOR2D& aPos )
695 {
696 SCH_COLLECTOR collector;
697 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
698 collector.Collect( m_frame->GetScreen(), { SCH_SYMBOL_T, SCH_FIELD_T }, aPos );
699
700 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
701 selectionTool->GuessSelectionCandidates( collector, aPos );
702
703 EDA_ITEM* item = collector.GetCount() == 1 ? collector[0] : nullptr;
704
705 if( item && item->Type() == SCH_FIELD_T )
706 item = static_cast<SCH_FIELD*>( item )->GetParentSymbol();
707
708 if( m_pickerItem != item )
709 {
710 if( m_pickerItem )
711 selectionTool->UnbrightenItem( m_pickerItem );
712
713 m_pickerItem = item;
714
715 if( m_pickerItem )
716 selectionTool->BrightenItem( m_pickerItem );
717 }
718 } );
719
720 picker->SetFinalizeHandler(
721 [this]( const int& aFinalState )
722 {
723 if( m_pickerItem )
724 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
725
726 // Wake the selection tool after exiting to ensure the cursor gets updated
727 // and deselect previous selection from simulator to avoid any issue
728 // ( avoid crash in some cases when the SimTune tool is deselected )
729 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
730 selectionTool->ClearSelection();
732 } );
733
734 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
735
736 return 0;
737}
738
739
740// A singleton reference for clearing the highlight
742
743
744static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
745{
746 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( aToolMgr->GetToolHolder() );
747 SCH_SELECTION_TOOL* selTool = aToolMgr->GetTool<SCH_SELECTION_TOOL>();
748 SCH_EDITOR_CONTROL* editorControl = aToolMgr->GetTool<SCH_EDITOR_CONTROL>();
749 SCH_CONNECTION* conn = nullptr;
750 SCH_ITEM* item = nullptr;
751 bool retVal = true;
752
753 if( aPosition != CLEAR )
754 {
755 ERC_TESTER erc( &editFrame->Schematic() );
756
757 if( erc.TestDuplicateSheetNames( false ) > 0 )
758 {
759 wxMessageBox( _( "Error: duplicate sub-sheet names found in current sheet." ) );
760 retVal = false;
761 }
762 else
763 {
764 item = static_cast<SCH_ITEM*>( selTool->GetNode( aPosition ) );
765 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
766
767 if( item )
768 {
769 if( item->IsConnectivityDirty() )
770 editFrame->RecalculateConnections( nullptr, NO_CLEANUP );
771
772 if( item->Type() == SCH_FIELD_T )
773 symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
774
775 if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
776 {
777 std::vector<SCH_PIN*> pins = symbol->GetPins();
778
779 if( pins.size() == 1 )
780 conn = pins[0]->Connection();
781 }
782 else
783 {
784 conn = item->Connection();
785 }
786 }
787 }
788 }
789
790 wxString connName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
791
792 if( !conn )
793 {
794 editFrame->SetStatusText( wxT( "" ) );
795 editFrame->SendCrossProbeClearHighlight();
796 editFrame->SetHighlightedConnection( wxEmptyString );
797 editorControl->SetHighlightBusMembers( false );
798 }
799 else
800 {
801 NET_NAVIGATOR_ITEM_DATA itemData( editFrame->GetCurrentSheet(), item );
802
803 if( connName != editFrame->GetHighlightedConnection() )
804 {
805 editorControl->SetHighlightBusMembers( false );
806 editFrame->SetCrossProbeConnection( conn );
807 editFrame->SetHighlightedConnection( connName, &itemData );
808 }
809 else
810 {
811 editorControl->SetHighlightBusMembers( !editorControl->GetHighlightBusMembers() );
812
813 if( item != editFrame->GetSelectedNetNavigatorItem() )
814 editFrame->SelectNetNavigatorItem( &itemData );
815 }
816 }
817
818 editFrame->UpdateNetHighlightStatus();
819
821 editorControl->UpdateNetHighlighting( dummy );
822
823 return retVal;
824}
825
826
828{
830 VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
831
832 highlightNet( m_toolMgr, cursorPos );
833
834 return 0;
835}
836
837
839{
841
842 return 0;
843}
844
845
847{
848 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
849 SCHEMATIC& schematic = m_frame->Schematic();
850 SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
851
852 std::vector<std::pair<SCH_CONNECTION*, VECTOR2D>> selectedConns;
853
854 for( EDA_ITEM* item : selectionTool->GetSelection() )
855 {
856 SCH_CONNECTION* conn = static_cast<SCH_ITEM*>( item )->Connection();
857
858 if( !conn )
859 continue;
860
861 selectedConns.emplace_back( conn, item->GetPosition() );
862 }
863
864 if( selectedConns.empty() )
865 {
866 m_frame->ShowInfoBarError( _( "No nets selected." ) );
867 return 0;
868 }
869
870 // Remove selection in favor of highlighting so the whole net is highlighted
871 selectionTool->ClearSelection();
872
873 const auto getNetNamePattern =
874 []( const SCH_CONNECTION& aConn ) -> std::optional<wxString>
875 {
876 wxString netName = aConn.Name();
877
878 if( aConn.IsBus() )
879 {
880 wxString prefix;
881
882 if( NET_SETTINGS::ParseBusVector( netName, &prefix, nullptr ) )
883 return prefix + wxT( "*" );
884 else if( NET_SETTINGS::ParseBusGroup( netName, &prefix, nullptr ) )
885 return prefix + wxT( ".*" );
886 }
887 else if( !aConn.Driver() || CONNECTION_SUBGRAPH::GetDriverPriority( aConn.Driver() )
889 {
890 return std::nullopt;
891 }
892
893 return netName;
894 };
895
896 std::set<wxString> netNames;
897
898 for( const auto& [conn, pos] : selectedConns )
899 {
900 std::optional<wxString> netNamePattern = getNetNamePattern( *conn );
901
902 if( !netNamePattern )
903 {
904 // This is a choice, we can also allow some un-labeled nets as long as some are labeled.
905 m_frame->ShowInfoBarError( _( "All selected nets must be labeled to assign a netclass." ) );
906 return 0;
907 }
908
909 netNames.insert( *netNamePattern );
910 }
911
912 wxCHECK( !netNames.empty(), 0 );
913
914 DIALOG_ASSIGN_NETCLASS dlg( m_frame, netNames, schematic.GetNetClassAssignmentCandidates(),
915 [&]( const std::vector<wxString>& aNetNames )
916 {
917 for( SCH_ITEM* item : screen->Items() )
918 {
919 bool redraw = item->IsBrightened();
920 SCH_CONNECTION* itemConn = item->Connection();
921
922 if( itemConn && alg::contains( aNetNames, itemConn->Name() ) )
923 item->SetBrightened();
924 else
925 item->ClearBrightened();
926
927 redraw |= item->IsBrightened();
928
929 if( item->Type() == SCH_SYMBOL_T )
930 {
931 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
932
933 redraw |= symbol->HasBrightenedPins();
934
935 symbol->ClearBrightenedPins();
936
937 for( SCH_PIN* pin : symbol->GetPins() )
938 {
939 SCH_CONNECTION* pin_conn = pin->Connection();
940
941 if( pin_conn && alg::contains( aNetNames, pin_conn->Name() ) )
942 {
943 pin->SetBrightened();
944 redraw = true;
945 }
946 }
947 }
948 else if( item->Type() == SCH_SHEET_T )
949 {
950 for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
951 {
952 SCH_CONNECTION* pin_conn = pin->Connection();
953
954 redraw |= pin->IsBrightened();
955
956 if( pin_conn && alg::contains( aNetNames, pin_conn->Name() ) )
957 pin->SetBrightened();
958 else
959 pin->ClearBrightened();
960
961 redraw |= pin->IsBrightened();
962 }
963 }
964
965 if( redraw )
966 getView()->Update( item, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
967 }
968
969 m_frame->GetCanvas()->ForceRefresh();
970 } );
971
972 if( dlg.ShowModal() )
973 {
974 getView()->UpdateAllItemsConditionally(
975 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
976 {
977 int flags = 0;
978
979 auto invalidateTextVars =
980 [&flags]( EDA_TEXT* text )
981 {
982 if( text->HasTextVars() )
983 {
984 text->ClearRenderCache();
985 text->ClearBoundingBoxCache();
987 }
988 };
989
990 // Netclass coloured items
991 //
992 if( dynamic_cast<SCH_LINE*>( aItem ) )
993 flags |= KIGFX::REPAINT;
994 else if( dynamic_cast<SCH_JUNCTION*>( aItem ) )
995 flags |= KIGFX::REPAINT;
996 else if( dynamic_cast<SCH_BUS_ENTRY_BASE*>( aItem ) )
997 flags |= KIGFX::REPAINT;
998
999 // Items that might reference an item's netclass name
1000 //
1001 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
1002 {
1003 item->RunOnChildren(
1004 [&invalidateTextVars]( SCH_ITEM* aChild )
1005 {
1006 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
1007 invalidateTextVars( text );
1008 },
1010
1011 if( flags & KIGFX::GEOMETRY )
1012 m_frame->GetScreen()->Update( item, false ); // Refresh RTree
1013 }
1014
1015 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
1016 invalidateTextVars( text );
1017
1018 return flags;
1019 } );
1020 }
1021
1022 highlightNet( m_toolMgr, CLEAR );
1023 return 0;
1024}
1025
1026
1028{
1029 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1030
1031 if( !selectionTool )
1032 return 0;
1033
1034 wxString netName;
1035
1036 for( EDA_ITEM* item : selectionTool->GetSelection() )
1037 {
1038 if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
1039 {
1040 if( SCH_CONNECTION* conn = schItem->Connection() )
1041 {
1042 if( !conn->GetNetName().IsEmpty() )
1043 {
1044 netName = conn->GetNetName();
1045 break;
1046 }
1047 }
1048 }
1049 }
1050
1051 if( netName.IsEmpty() )
1052 netName = m_frame->GetHighlightedConnection();
1053
1054 if( netName.IsEmpty() )
1055 {
1056 m_frame->ShowInfoBarError( _( "No connected net selected." ) );
1057 return 0;
1058 }
1059
1060 m_frame->FindNetInInspector( netName );
1061
1062 return 0;
1063}
1064
1065
1067{
1068 wxCHECK( m_frame, 0 );
1069
1070 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
1071 SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
1072 CONNECTION_GRAPH* connectionGraph = m_frame->Schematic().ConnectionGraph();
1073 wxString selectedName = m_frame->GetHighlightedConnection();
1074
1075 std::set<wxString> connNames;
1076 std::vector<EDA_ITEM*> itemsToRedraw;
1077
1078 wxCHECK( screen && connectionGraph, 0 );
1079
1080 if( !selectedName.IsEmpty() )
1081 {
1082 connNames.emplace( selectedName );
1083
1084 if( CONNECTION_SUBGRAPH* sg = connectionGraph->FindSubgraphByName( selectedName, sheetPath ) )
1085 {
1087 {
1088 for( const SCH_ITEM* item : sg->GetItems() )
1089 {
1090 wxCHECK2( item, continue );
1091
1092 if( SCH_CONNECTION* connection = item->Connection() )
1093 {
1094 for( const std::shared_ptr<SCH_CONNECTION>& member : connection->AllMembers() )
1095 {
1096 if( member )
1097 connNames.emplace( member->Name() );
1098 }
1099 }
1100 }
1101 }
1102 }
1103
1104 // Place all bus names that are connected to the selected net in the set, regardless of
1105 // their sheet. This ensures that nets that are connected to a bus on a different sheet
1106 // get their buses highlighted as well.
1107 for( CONNECTION_SUBGRAPH* sg : connectionGraph->GetAllSubgraphs( selectedName ) )
1108 {
1109 for( const auto& [_, bus_sgs] : sg->GetBusParents() )
1110 {
1111 for( CONNECTION_SUBGRAPH* bus_sg : bus_sgs )
1112 connNames.emplace( bus_sg->GetNetName() );
1113 }
1114 }
1115 }
1116
1117 for( SCH_ITEM* item : screen->Items() )
1118 {
1119 if( !item || !item->IsConnectable() )
1120 continue;
1121
1122 SCH_ITEM* redrawItem = nullptr;
1123
1124 if( item->Type() == SCH_SYMBOL_T )
1125 {
1126 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1127
1128 for( SCH_PIN* pin : symbol->GetPins() )
1129 {
1130 if( SCH_CONNECTION* pin_conn = pin->Connection() )
1131 {
1132 if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
1133 {
1134 pin->SetBrightened();
1135 redrawItem = symbol;
1136 }
1137 else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
1138 {
1139 pin->ClearBrightened();
1140 redrawItem = symbol;
1141 }
1142 }
1143 }
1144
1145 if( symbol->IsPower() && symbol->GetPins().size() )
1146 {
1147 if( SCH_CONNECTION* pinConn = symbol->GetPins()[0]->Connection() )
1148 {
1150 {
1151 SCH_FIELD* field = symbol->GetField( id );
1152
1153 if( !field->IsVisible() )
1154 continue;
1155
1156 if( !field->IsBrightened() && connNames.count( pinConn->Name() ) )
1157 {
1158 field->SetBrightened();
1159 redrawItem = symbol;
1160 }
1161 else if( field->IsBrightened() && !connNames.count( pinConn->Name() ) )
1162 {
1163 field->ClearBrightened();
1164 redrawItem = symbol;
1165 }
1166 }
1167 }
1168 }
1169 }
1170 else if( item->Type() == SCH_SHEET_T )
1171 {
1172 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1173
1174 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1175 {
1176 wxCHECK2( pin, continue );
1177
1178 if( SCH_CONNECTION* pin_conn = pin->Connection() )
1179 {
1180 if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
1181 {
1182 pin->SetBrightened();
1183 redrawItem = sheet;
1184 }
1185 else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
1186 {
1187 pin->ClearBrightened();
1188 redrawItem = sheet;
1189 }
1190 }
1191 }
1192 }
1193 else
1194 {
1195 if( SCH_CONNECTION* itemConn = item->Connection() )
1196 {
1197 if( !item->IsBrightened() && connNames.count( itemConn->Name() ) )
1198 {
1199 item->SetBrightened();
1200 redrawItem = item;
1201 }
1202 else if( item->IsBrightened() && !connNames.count( itemConn->Name() ) )
1203 {
1204 item->ClearBrightened();
1205 redrawItem = item;
1206 }
1207 }
1208 }
1209
1210 if( redrawItem )
1211 itemsToRedraw.push_back( redrawItem );
1212 }
1213
1214 if( itemsToRedraw.size() )
1215 {
1216 // Be sure highlight change will be redrawn
1217 KIGFX::VIEW* view = getView();
1218
1219 for( EDA_ITEM* redrawItem : itemsToRedraw )
1221
1222 m_frame->GetCanvas()->Refresh();
1223 }
1224
1225 return 0;
1226}
1227
1228
1230{
1231 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
1232
1233 // Deactivate other tools; particularly important if another PICKER is currently running
1234 Activate();
1235
1236 picker->SetCursor( KICURSOR::BULLSEYE );
1237 picker->SetSnapping( false );
1238 picker->ClearHandlers();
1239
1240 picker->SetClickHandler(
1241 [this]( const VECTOR2D& aPos )
1242 {
1243 return highlightNet( m_toolMgr, aPos );
1244 } );
1245
1246 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1247
1248 return 0;
1249}
1250
1251
1253{
1254 wxCHECK( m_frame, 0 );
1255
1256 if( m_frame->GetUndoCommandCount() <= 0 )
1257 return 0;
1258
1259 // Inform tools that undo command was issued
1260 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1261
1262 // Get the old list
1263 PICKED_ITEMS_LIST* undo_list = m_frame->PopCommandFromUndoList();
1264
1265 wxCHECK( undo_list, 0 );
1266
1267 m_frame->PutDataInPreviousState( undo_list );
1268
1269 // Now push the old command to the RedoList
1270 undo_list->ReversePickersListOrder();
1271 m_frame->PushCommandToRedoList( undo_list );
1272
1273 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1274
1275 m_frame->GetCanvas()->Refresh();
1276 m_frame->OnModify();
1277
1278 return 0;
1279}
1280
1281
1283{
1284 wxCHECK( m_frame, 0 );
1285
1286 if( m_frame->GetRedoCommandCount() == 0 )
1287 return 0;
1288
1289 // Inform tools that undo command was issued
1290 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1291
1292 /* Get the old list */
1293 PICKED_ITEMS_LIST* list = m_frame->PopCommandFromRedoList();
1294
1295 wxCHECK( list, 0 );
1296
1297 /* Redo the command: */
1298 m_frame->PutDataInPreviousState( list );
1299
1300 /* Put the old list in UndoList */
1301 list->ReversePickersListOrder();
1302 m_frame->PushCommandToUndoList( list );
1303
1304 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1305
1306 m_frame->GetCanvas()->Refresh();
1307 m_frame->OnModify();
1308
1309 return 0;
1310}
1311
1312
1313bool SCH_EDITOR_CONTROL::doCopy( bool aUseDuplicateClipboard )
1314{
1315 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1316 SCH_SELECTION& selection = selTool->RequestSelection();
1317 SCHEMATIC& schematic = m_frame->Schematic();
1318
1319 if( selection.Empty() )
1320 return false;
1321
1322 if( aUseDuplicateClipboard )
1323 m_duplicateIsHoverSelection = selection.IsHover();
1324
1325 selection.SetScreen( m_frame->GetScreen() );
1327
1328 for( EDA_ITEM* item : selection.GetItems() )
1329 {
1330 if( item->Type() == SCH_SHEET_T )
1331 {
1332 SCH_SHEET* sheet = (SCH_SHEET*) item;
1333 m_supplementaryClipboard[sheet->GetFileName()] = sheet->GetScreen();
1334 }
1335 else if( item->Type() == SCH_FIELD_T && selection.IsHover() )
1336 {
1337 // Most of the time the user is trying to duplicate the parent symbol
1338 // and the field text is in it
1339 selection.Add( item->GetParent() );
1340 }
1341 else if( item->Type() == SCH_MARKER_T )
1342 {
1343 // Don't let the markers be copied
1344 selection.Remove( item );
1345 }
1346 else if( item->Type() == SCH_GROUP_T )
1347 {
1348 // Groups need to have all their items selected
1349 static_cast<SCH_ITEM*>( item )->RunOnChildren(
1350 [&]( EDA_ITEM* aChild )
1351 {
1352 selection.Add( aChild );
1353 },
1355 }
1356 }
1357
1358 STRING_FORMATTER formatter;
1359 SCH_IO_KICAD_SEXPR plugin;
1360 SCH_SHEET_PATH selPath = m_frame->GetCurrentSheet();
1361
1362 plugin.Format( &selection, &selPath, schematic, &formatter, true );
1363
1364 std::string prettyData = formatter.GetString();
1365 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::COMPACT_TEXT_PROPERTIES );
1366
1367 if( selection.IsHover() )
1368 m_toolMgr->RunAction( ACTIONS::selectionClear );
1369
1370 if( aUseDuplicateClipboard )
1371 {
1372 m_duplicateClipboard = prettyData;
1373 return true;
1374 }
1375
1376 return SaveClipboard( prettyData );
1377}
1378
1379
1380bool SCH_EDITOR_CONTROL::searchSupplementaryClipboard( const wxString& aSheetFilename, SCH_SCREEN** aScreen )
1381{
1382 if( m_supplementaryClipboard.count( aSheetFilename ) > 0 )
1383 {
1384 *aScreen = m_supplementaryClipboard[aSheetFilename];
1385 return true;
1386 }
1387
1388 return false;
1389}
1390
1391
1393{
1394 doCopy( true ); // Use the local clipboard
1395 Paste( aEvent );
1396
1397 return 0;
1398}
1399
1400
1402{
1403 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1404
1405 if( textEntry )
1406 {
1407 textEntry->Cut();
1408 return 0;
1409 }
1410
1411 if( doCopy() )
1412 m_toolMgr->RunAction( ACTIONS::doDelete );
1413
1414 return 0;
1415}
1416
1417
1419{
1420 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1421
1422 if( textEntry )
1423 {
1424 textEntry->Copy();
1425 return 0;
1426 }
1427
1428 doCopy();
1429
1430 return 0;
1431}
1432
1433
1435{
1436 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1437 SCH_SELECTION& selection = selTool->RequestSelection();
1438
1439 if( selection.Empty() )
1440 return false;
1441
1442 wxString itemsAsText = GetSelectedItemsAsText( selection );
1443
1444 if( selection.IsHover() )
1445 m_toolMgr->RunAction( ACTIONS::selectionClear );
1446
1447 return SaveClipboard( itemsAsText.ToStdString() );
1448}
1449
1450
1452 const KIID_PATH& aClipPath, bool aForceKeepAnnotations )
1453{
1454 wxCHECK( m_frame && aSymbol, /* void */ );
1455
1456 SCH_SYMBOL_INSTANCE newInstance;
1457 bool instanceFound = false;
1458 KIID_PATH pasteLookupPath = aClipPath;
1459
1460 m_pastedSymbols.insert( aSymbol );
1461
1462 for( const SCH_SYMBOL_INSTANCE& tmp : aSymbol->GetInstances() )
1463 {
1464 if( ( tmp.m_Path.empty() && aClipPath.empty() ) || ( !aClipPath.empty() && tmp.m_Path.EndsWith( aClipPath ) ) )
1465 {
1466 newInstance = tmp;
1467 instanceFound = true;
1468
1469 wxLogTrace( traceSchPaste, wxS( "Pasting found symbol instance with reference %s, unit %d:\n"
1470 "\tClipboard path: %s\n"
1471 "\tSymbol UUID: %s." ),
1472 tmp.m_Reference,
1473 tmp.m_Unit,
1474 aClipPath.AsString(),
1475 aSymbol->m_Uuid.AsString() );
1476
1477 break;
1478 }
1479 }
1480
1481 // The pasted symbol look up paths include the symbol UUID.
1482 pasteLookupPath.push_back( aSymbol->m_Uuid );
1483
1484 if( !instanceFound )
1485 {
1486 wxLogTrace( traceSchPaste, wxS( "Clipboard symbol instance **not** found:\n\tClipboard path: %s\n"
1487 "\tSymbol UUID: %s." ),
1488 aClipPath.AsString(),
1489 aSymbol->m_Uuid.AsString() );
1490
1491 // Some legacy versions saved value fields escaped. While we still do in the symbol
1492 // editor, we don't anymore in the schematic, so be sure to unescape them.
1493 SCH_FIELD* valueField = aSymbol->GetField( FIELD_T::VALUE );
1494 valueField->SetText( UnescapeString( valueField->GetText() ) );
1495
1496 // Pasted from notepad or an older instance of eeschema. Use the values in the fields
1497 // instead.
1498 newInstance.m_Reference = aSymbol->GetField( FIELD_T::REFERENCE )->GetText();
1499 newInstance.m_Unit = aSymbol->GetUnit();
1500 }
1501
1502 newInstance.m_Path = aPastePath.Path();
1503 newInstance.m_ProjectName = m_frame->Prj().GetProjectName();
1504
1505 aSymbol->AddHierarchicalReference( newInstance );
1506
1507 if( !aForceKeepAnnotations )
1508 aSymbol->ClearAnnotation( &aPastePath, false );
1509
1510 // We might clear annotations but always leave the original unit number from the paste.
1511 aSymbol->SetUnit( newInstance.m_Unit );
1512}
1513
1514
1516 const KIID_PATH& aClipPath, bool aForceKeepAnnotations,
1517 SCH_SHEET_LIST* aPastedSheets, std::map<SCH_SHEET_PATH,
1518 SCH_REFERENCE_LIST>& aPastedSymbols )
1519{
1520 wxCHECK( aSheet && aPastedSheets, aPastePath );
1521
1522 SCH_SHEET_PATH sheetPath = aPastePath;
1523 sheetPath.push_back( aSheet );
1524
1525 aPastedSheets->push_back( sheetPath );
1526
1527 if( aSheet->GetScreen() == nullptr )
1528 return sheetPath; // We can only really set the page number but not load any items
1529
1530 for( SCH_ITEM* item : aSheet->GetScreen()->Items() )
1531 {
1532 if( item->IsConnectable() )
1533 item->SetConnectivityDirty();
1534
1535 if( item->Type() == SCH_SYMBOL_T )
1536 {
1537 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1538
1539 wxCHECK2( symbol, continue );
1540
1541 // Only do this once if the symbol is shared across multiple sheets.
1542 if( !m_pastedSymbols.count( symbol ) )
1543 {
1544 for( SCH_PIN* pin : symbol->GetPins() )
1545 {
1546 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1547 pin->SetConnectivityDirty();
1548 }
1549 }
1550
1551 updatePastedSymbol( symbol, sheetPath, aClipPath, aForceKeepAnnotations );
1552 }
1553 else if( item->Type() == SCH_SHEET_T )
1554 {
1555 SCH_SHEET* subsheet = static_cast<SCH_SHEET*>( item );
1556
1557 wxCHECK2( subsheet, continue );
1558
1559 // Make sure pins get a new UUID and set the dirty connectivity flag.
1560 if( !aPastedSheets->ContainsSheet( subsheet ) )
1561 {
1562 for( SCH_SHEET_PIN* pin : subsheet->GetPins() )
1563 {
1564 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1565 pin->SetConnectivityDirty();
1566 }
1567 }
1568
1569 KIID_PATH newClipPath = aClipPath;
1570 newClipPath.push_back( subsheet->m_Uuid );
1571
1572 updatePastedSheet( subsheet, sheetPath, newClipPath, aForceKeepAnnotations, aPastedSheets, aPastedSymbols );
1573 }
1574 }
1575
1576 sheetPath.GetSymbols( aPastedSymbols[aPastePath] );
1577
1578 return sheetPath;
1579}
1580
1581
1583{
1584 wxCHECK( aScreen, /* void */ );
1585
1586 for( const SCH_ITEM* item : aScreen->Items() )
1587 {
1588 if( item->Type() == SCH_SYMBOL_T )
1589 {
1590 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1591
1592 wxCHECK2( symbol, continue );
1593
1594 for( const SCH_SYMBOL_INSTANCE& symbolInstance : symbol->GetInstances() )
1595 {
1596 KIID_PATH pathWithSymbol = symbolInstance.m_Path;
1597
1598 pathWithSymbol.push_back( symbol->m_Uuid );
1599
1600 m_clipboardSymbolInstances[pathWithSymbol] = symbolInstance;
1601 }
1602 }
1603 }
1604}
1605
1606
1608{
1609 wxCHECK( m_frame, /* void */ );
1610
1611 for( SCH_SYMBOL* symbol : m_pastedSymbols )
1612 {
1613 wxCHECK2( symbol, continue );
1614
1615 std::vector<KIID_PATH> instancePathsToRemove;
1616
1617 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1618 {
1619 if( instance.m_ProjectName != m_frame->Prj().GetProjectName() || instance.m_Path.empty() )
1620 instancePathsToRemove.emplace_back( instance.m_Path );
1621 }
1622
1623 for( const KIID_PATH& path : instancePathsToRemove )
1624 symbol->RemoveInstance( path );
1625 }
1626}
1627
1628
1630{
1631 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1632
1633 if( textEntry )
1634 {
1635 textEntry->Paste();
1636 return 0;
1637 }
1638
1639 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1640 std::string content;
1641 VECTOR2I eventPos;
1642
1643 SCH_SHEET tempSheet;
1644
1645 std::unique_ptr<wxImage> clipImg = GetImageFromClipboard();
1646
1647 if( !aEvent.IsAction( &ACTIONS::duplicate ) && clipImg )
1648 {
1649 // Just image data
1650 auto bitmap = std::make_unique<SCH_BITMAP>();
1651
1652 bool ok = bitmap->GetReferenceImage().SetImage( *clipImg );
1653
1654 if( !ok )
1655 return 0;
1656
1657 return m_toolMgr->RunAction( SCH_ACTIONS::placeImage, bitmap.release() );
1658 }
1659
1660 if( aEvent.IsAction( &ACTIONS::duplicate ) )
1661 content = m_duplicateClipboard;
1662 else
1663 content = GetClipboardUTF8();
1664
1665 if( content.empty() )
1666 return 0;
1667
1668 if( aEvent.IsAction( &ACTIONS::duplicate ) )
1669 eventPos = getViewControls()->GetCursorPosition( false );
1670
1671 STRING_LINE_READER reader( content, "Clipboard" );
1672 SCH_IO_KICAD_SEXPR plugin;
1673
1674 // Screen object on heap is owned by the sheet.
1675 SCH_SCREEN* tempScreen = new SCH_SCREEN( &m_frame->Schematic() );
1676 tempSheet.SetScreen( tempScreen );
1677
1678 try
1679 {
1680 plugin.LoadContent( reader, &tempSheet );
1681 }
1682 catch( IO_ERROR& )
1683 {
1684 // If it wasn't schematic content, paste as a text object
1685 {
1686 if( content.size() > static_cast<size_t>( ADVANCED_CFG::GetCfg().m_MaxPastedTextLength ) )
1687 {
1688 int result = IsOK( m_frame, _( "Pasting a long text text string may be very slow. "
1689 "Do you want to continue?" ) );
1690 if( !result )
1691 return 0;
1692 }
1693
1694 SCH_TEXT* text_item = new SCH_TEXT( VECTOR2I( 0, 0 ), content );
1695 tempScreen->Append( text_item );
1696 }
1697 }
1698
1699 SELECTION& currentSelection = selTool->GetSelection();
1700
1701 bool hasTableCells = false;
1702
1703 for( EDA_ITEM* item : currentSelection )
1704 {
1705 if( item->Type() == SCH_TABLECELL_T )
1706 {
1707 hasTableCells = true;
1708 break;
1709 }
1710 }
1711
1712 if( hasTableCells )
1713 {
1714 SCH_TABLE* clipboardTable = nullptr;
1715
1716 for( SCH_ITEM* item : tempScreen->Items() )
1717 {
1718 if( item->Type() == SCH_TABLE_T )
1719 {
1720 clipboardTable = static_cast<SCH_TABLE*>( item );
1721 break;
1722 }
1723 }
1724
1725 if( clipboardTable )
1726 {
1727 SCH_EDIT_TABLE_TOOL* tableEditTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>();
1728
1729 if( tableEditTool )
1730 {
1731 wxString errorMsg;
1732
1733 if( !tableEditTool->validatePasteIntoSelection( currentSelection, errorMsg ) )
1734 {
1735 DisplayError( m_frame, errorMsg );
1736 return 0;
1737 }
1738
1739 SCH_COMMIT commit( m_toolMgr );
1740
1741 if( tableEditTool->pasteCellsIntoSelection( currentSelection, clipboardTable, commit ) )
1742 {
1743 commit.Push( _( "Paste Cells" ) );
1744 return 0;
1745 }
1746 else
1747 {
1748 DisplayError( m_frame, _( "Failed to paste cells" ) );
1749 return 0;
1750 }
1751 }
1752 }
1753 }
1754
1755 m_pastedSymbols.clear();
1757
1758 // Save pasted symbol instances in case the user chooses to keep existing symbol annotation.
1759 setPastedSymbolInstances( tempScreen );
1760
1761 tempScreen->MigrateSimModels();
1762
1763 bool annotateAutomatic = m_frame->eeconfig()->m_AnnotatePanel.automatic;
1764 SCHEMATIC_SETTINGS& schematicSettings = m_frame->Schematic().Settings();
1765 int annotateStartNum = schematicSettings.m_AnnotateStartNum;
1766
1768 bool forceRemoveAnnotations = false;
1769
1770 if( aEvent.IsAction( &ACTIONS::pasteSpecial ) )
1771 {
1772 PASTE_MODE defaultPasteMode = pasteMode;
1773 DIALOG_PASTE_SPECIAL dlg( m_frame, &pasteMode );
1774
1775 if( dlg.ShowModal() == wxID_CANCEL )
1776 return 0;
1777
1778 // We have to distinguish if removing was explicit
1779 forceRemoveAnnotations = pasteMode == PASTE_MODE::REMOVE_ANNOTATIONS && pasteMode != defaultPasteMode;
1780 }
1781
1782 bool forceKeepAnnotations = pasteMode != PASTE_MODE::REMOVE_ANNOTATIONS;
1783
1784 // SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything
1785 // else. Pull them back out to start with.
1786 SCH_COMMIT commit( m_toolMgr );
1787 EDA_ITEMS loadedItems;
1788 std::vector<SCH_ITEM*> sortedLoadedItems;
1789 bool sheetsPasted = false;
1790 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
1791 SCH_SHEET_PATH& pasteRoot = m_frame->GetCurrentSheet();
1792 wxFileName destFn = pasteRoot.Last()->GetFileName();
1793
1794 if( destFn.IsRelative() )
1795 destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
1796
1797 // List of paths in the hierarchy that refer to the destination sheet of the paste
1798 SCH_SHEET_LIST sheetPathsForScreen = hierarchy.FindAllSheetsForScreen( pasteRoot.LastScreen() );
1799 sheetPathsForScreen.SortByPageNumbers();
1800
1801 // Build a list of screens from the current design (to avoid loading sheets that already exist)
1802 std::map<wxString, SCH_SCREEN*> loadedScreens;
1803
1804 for( const SCH_SHEET_PATH& item : hierarchy )
1805 {
1806 if( item.LastScreen() )
1807 loadedScreens[item.Last()->GetFileName()] = item.LastScreen();
1808 }
1809
1810 // Get set of sheet names in the current schematic to prevent duplicate sheet names on paste.
1811 std::set<wxString> existingSheetNames = pasteRoot.LastScreen()->GetSheetNames();
1812
1813 // Build symbol list for reannotation of duplicates
1814 SCH_REFERENCE_LIST existingRefs;
1815 hierarchy.GetSymbols( existingRefs );
1816 existingRefs.SortByReferenceOnly();
1817
1818 std::set<wxString> existingRefsSet;
1819
1820 for( const SCH_REFERENCE& ref : existingRefs )
1821 existingRefsSet.insert( ref.GetRef() );
1822
1823 // Build UUID map for fetching last-resolved-properties
1824 std::map<KIID, EDA_ITEM*> itemMap;
1825 hierarchy.FillItemMap( itemMap );
1826
1827 // Keep track of pasted sheets and symbols for the different paths to the hierarchy.
1828 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> pastedSymbols;
1829 std::map<SCH_SHEET_PATH, SCH_SHEET_LIST> pastedSheets;
1830
1831 for( SCH_ITEM* item : tempScreen->Items() )
1832 {
1833 if( item->Type() == SCH_SHEET_T )
1834 sortedLoadedItems.push_back( item );
1835 else
1836 loadedItems.push_back( item );
1837 }
1838
1839 sort( sortedLoadedItems.begin(), sortedLoadedItems.end(),
1840 []( SCH_ITEM* firstItem, SCH_ITEM* secondItem )
1841 {
1842 SCH_SHEET* firstSheet = static_cast<SCH_SHEET*>( firstItem );
1843 SCH_SHEET* secondSheet = static_cast<SCH_SHEET*>( secondItem );
1844 return StrNumCmp( firstSheet->GetName(), secondSheet->GetName(), false ) < 0;
1845 } );
1846
1847
1848 for( SCH_ITEM* item : sortedLoadedItems )
1849 {
1850 loadedItems.push_back( item );
1851
1852 if( item->Type() == SCH_SHEET_T )
1853 {
1854 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1855 wxFileName srcFn = sheet->GetFileName();
1856
1857 if( srcFn.IsRelative() )
1858 srcFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
1859
1860 SCH_SHEET_LIST sheetHierarchy( sheet );
1861
1862 if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
1863 {
1864 auto msg = wxString::Format( _( "The pasted sheet '%s'\n"
1865 "was dropped because the destination already has "
1866 "the sheet or one of its subsheets as a parent." ),
1867 sheet->GetFileName() );
1868 DisplayError( m_frame, msg );
1869 loadedItems.pop_back();
1870 }
1871 }
1872 }
1873
1874 // Remove the references from our temporary screen to prevent freeing on the DTOR
1875 tempScreen->Clear( false );
1876
1877 for( EDA_ITEM* item : loadedItems )
1878 {
1879 KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
1880
1881 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
1882
1883 wxCHECK2( schItem, continue );
1884
1885 if( schItem->IsConnectable() )
1886 schItem->SetConnectivityDirty();
1887
1888 if( item->Type() == SCH_SYMBOL_T )
1889 {
1890 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1891
1892 // The library symbol gets set from the cached library symbols in the current
1893 // schematic not the symbol libraries. The cached library symbol may have
1894 // changed from the original library symbol which would cause the copy to
1895 // be incorrect.
1896 SCH_SCREEN* currentScreen = m_frame->GetScreen();
1897
1898 wxCHECK2( currentScreen, continue );
1899
1900 auto it = currentScreen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
1901 auto end = currentScreen->GetLibSymbols().end();
1902
1903 if( it == end )
1904 {
1905 // If can't find library definition in the design, use the pasted library
1906 it = tempScreen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
1907 end = tempScreen->GetLibSymbols().end();
1908 }
1909
1910 LIB_SYMBOL* libSymbol = nullptr;
1911
1912 if( it != end )
1913 {
1914 libSymbol = new LIB_SYMBOL( *it->second );
1915 symbol->SetLibSymbol( libSymbol );
1916 }
1917
1918 // If the symbol is already in the schematic we have to always keep the annotations. The exception
1919 // is if the user has chosen to remove them.
1920 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1921 {
1922 if( !existingRefsSet.contains( instance.m_Reference ) )
1923 {
1924 forceKeepAnnotations = !forceRemoveAnnotations;
1925 break;
1926 }
1927 }
1928
1929 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
1930 updatePastedSymbol( symbol, sheetPath, clipPath, forceKeepAnnotations );
1931
1932 // Most modes will need new KIIDs for the symbol and its pins. However, if we are pasting
1933 // unique annotations, we need to check if the symbol is not already in the hierarchy. If we
1934 // don't already have a copy of the symbol, we just keep the existing KIID data as it is likely
1935 // the same symbol being moved around the schematic.
1936 bool needsNewKiid = ( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS );
1937
1938 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1939 {
1940 if( existingRefsSet.contains( instance.m_Reference ) )
1941 {
1942 needsNewKiid = true;
1943 break;
1944 }
1945 }
1946
1947 if( needsNewKiid )
1948 {
1949 // Assign a new KIID
1950 const_cast<KIID&>( item->m_Uuid ) = KIID();
1951
1952 // Make sure pins get a new UUID
1953 for( SCH_PIN* pin : symbol->GetPins() )
1954 {
1955 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1956 pin->SetConnectivityDirty();
1957 }
1958
1959 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
1960 {
1961 // Ignore symbols from a non-existant library.
1962 if( libSymbol )
1963 {
1964 SCH_REFERENCE schReference( symbol, sheetPath );
1965 schReference.SetSheetNumber( sheetPath.GetPageNumberAsInt() );
1966 pastedSymbols[sheetPath].AddItem( schReference );
1967 }
1968 }
1969 }
1970 }
1971 else if( item->Type() == SCH_SHEET_T )
1972 {
1973 SCH_SHEET* sheet = (SCH_SHEET*) item;
1974 SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME );
1975 wxString baseName = nameField->GetText();
1976 wxString candidateName = baseName;
1977 wxString number;
1978
1979 while( !baseName.IsEmpty() && wxIsdigit( baseName.Last() ) )
1980 {
1981 number = baseName.Last() + number;
1982 baseName.RemoveLast();
1983 }
1984
1985 // Update hierarchy to include any other sheets we already added, avoiding
1986 // duplicate sheet names
1987 hierarchy = m_frame->Schematic().Hierarchy();
1988
1989 int uniquifier = std::max( 0, wxAtoi( number ) ) + 1;
1990
1991 while( existingSheetNames.count( candidateName ) )
1992 candidateName = wxString::Format( wxT( "%s%d" ), baseName, uniquifier++ );
1993
1994 nameField->SetText( candidateName );
1995 existingSheetNames.emplace( candidateName );
1996
1997 wxFileName fn = sheet->GetFileName();
1998 SCH_SCREEN* existingScreen = nullptr;
1999
2000 sheet->SetParent( pasteRoot.Last() );
2001 sheet->SetScreen( nullptr );
2002
2003 if( !fn.IsAbsolute() )
2004 {
2005 wxFileName currentSheetFileName = pasteRoot.LastScreen()->GetFileName();
2006 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, currentSheetFileName.GetPath() );
2007 }
2008
2009 // Try to find the screen for the pasted sheet by several means
2010 if( !m_frame->Schematic().Root().SearchHierarchy( fn.GetFullPath( wxPATH_UNIX ), &existingScreen ) )
2011 {
2012 if( loadedScreens.count( sheet->GetFileName() ) > 0 )
2013 existingScreen = loadedScreens.at( sheet->GetFileName() );
2014 else
2015 searchSupplementaryClipboard( sheet->GetFileName(), &existingScreen );
2016 }
2017
2018 if( existingScreen )
2019 {
2020 sheet->SetScreen( existingScreen );
2021 }
2022 else
2023 {
2024 if( !m_frame->LoadSheetFromFile( sheet, &pasteRoot, fn.GetFullPath() ) )
2025 m_frame->InitSheet( sheet, sheet->GetFileName() );
2026 }
2027
2028 // Save the symbol instances in case the user chooses to keep the existing
2029 // symbol annotation.
2031 sheetsPasted = true;
2032
2033 // Push it to the clipboard path while it still has its old KIID
2034 clipPath.push_back( sheet->m_Uuid );
2035
2036 // Assign a new KIID to the pasted sheet
2037 const_cast<KIID&>( sheet->m_Uuid ) = KIID();
2038
2039 // Make sure pins get a new UUID
2040 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
2041 {
2042 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2043 pin->SetConnectivityDirty();
2044 }
2045
2046 // Once we have our new KIID we can update all pasted instances. This will either
2047 // reset the annotations or copy "kept" annotations from the supplementary clipboard.
2048 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2049 {
2050 SCH_SHEET_PATH subPath = updatePastedSheet( sheet, sheetPath, clipPath,
2051 ( forceKeepAnnotations && annotateAutomatic ),
2052 &pastedSheets[sheetPath], pastedSymbols );
2053 }
2054 }
2055 else
2056 {
2057 SCH_ITEM* srcItem = dynamic_cast<SCH_ITEM*>( itemMap[item->m_Uuid] );
2058 SCH_ITEM* destItem = dynamic_cast<SCH_ITEM*>( item );
2059
2060 // Everything gets a new KIID
2061 const_cast<KIID&>( item->m_Uuid ) = KIID();
2062
2063 if( srcItem && destItem )
2064 {
2065 destItem->SetConnectivityDirty( true );
2066 destItem->SetLastResolvedState( srcItem );
2067 }
2068 }
2069
2070 // Lines need both ends selected for a move after paste so the whole line moves.
2071 if( item->Type() == SCH_LINE_T )
2072 item->SetFlags( STARTPOINT | ENDPOINT );
2073
2074 item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
2075
2076 if( !m_frame->GetScreen()->CheckIfOnDrawList( (SCH_ITEM*) item ) ) // don't want a loop!
2077 m_frame->AddToScreen( item, m_frame->GetScreen() );
2078
2079 commit.Added( (SCH_ITEM*) item, m_frame->GetScreen() );
2080
2081 // Start out hidden so the pasted items aren't "ghosted" in their original location
2082 // before being moved to the current location.
2083 getView()->Hide( item, true );
2084 }
2085
2086 if( sheetsPasted )
2087 {
2088 // The full schematic hierarchy need to be update before assigning new annotation and
2089 // page numbers.
2090 m_frame->Schematic().RefreshHierarchy();
2091
2092 // Update page numbers: Find next free numeric page number
2093 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2094 {
2095 for( SCH_SHEET_PATH& pastedSheet : pastedSheets[sheetPath] )
2096 {
2097 int page = 1;
2098 wxString pageNum = wxString::Format( "%d", page );
2099
2100 while( hierarchy.PageNumberExists( pageNum ) )
2101 pageNum = wxString::Format( "%d", ++page );
2102
2103 SCH_SHEET_INSTANCE sheetInstance;
2104
2105 sheetInstance.m_Path = pastedSheet.Path();
2106
2107 // Don't include the actual sheet in the instance path.
2108 sheetInstance.m_Path.pop_back();
2109 sheetInstance.m_PageNumber = pageNum;
2110 sheetInstance.m_ProjectName = m_frame->Prj().GetProjectName();
2111
2112 SCH_SHEET* sheet = pastedSheet.Last();
2113
2114 wxCHECK2( sheet, continue );
2115
2116 sheet->AddInstance( sheetInstance );
2117 hierarchy.push_back( pastedSheet );
2118
2119 // Remove all pasted sheet instance data that is not part of the current project.
2120 std::vector<KIID_PATH> instancesToRemove;
2121
2122 for( const SCH_SHEET_INSTANCE& instance : sheet->GetInstances() )
2123 {
2124 if( !hierarchy.HasPath( instance.m_Path ) )
2125 instancesToRemove.push_back( instance.m_Path );
2126 }
2127
2128 for( const KIID_PATH& instancePath : instancesToRemove )
2129 sheet->RemoveInstance( instancePath );
2130 }
2131 }
2132
2133 m_frame->SetSheetNumberAndCount();
2134
2135 // Get a version with correct sheet numbers since we've pasted sheets,
2136 // we'll need this when annotating next
2137 hierarchy = m_frame->Schematic().Hierarchy();
2138 }
2139
2140 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> annotatedSymbols;
2141
2142 // Update the list of symbol instances that satisfy the annotation criteria.
2143 for( const SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2144 {
2145 for( size_t i = 0; i < pastedSymbols[sheetPath].GetCount(); i++ )
2146 {
2147 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[sheetPath][i].AlwaysAnnotate() )
2148 annotatedSymbols[sheetPath].AddItem( pastedSymbols[sheetPath][i] );
2149 }
2150
2151 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[sheetPath] )
2152 {
2153 for( size_t i = 0; i < pastedSymbols[pastedSheetPath].GetCount(); i++ )
2154 {
2155 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[pastedSheetPath][i].AlwaysAnnotate() )
2156 annotatedSymbols[pastedSheetPath].AddItem( pastedSymbols[pastedSheetPath][i] );
2157 }
2158 }
2159 }
2160
2161 if( !annotatedSymbols.empty() )
2162 {
2163 ANNOTATE_ORDER_T annotateOrder = static_cast<ANNOTATE_ORDER_T>( schematicSettings.m_AnnotateSortOrder );
2164 ANNOTATE_ALGO_T annotateAlgo = static_cast<ANNOTATE_ALGO_T>( schematicSettings.m_AnnotateMethod );
2165
2166 for( SCH_SHEET_PATH& path : sheetPathsForScreen )
2167 {
2168 annotatedSymbols[path].SortByReferenceOnly();
2169 annotatedSymbols[path].SetRefDesTracker( schematicSettings.m_refDesTracker );
2170
2171 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2172 {
2173 annotatedSymbols[path].ReannotateDuplicates( existingRefs, annotateAlgo );
2174 }
2175 else
2176 {
2177 annotatedSymbols[path].ReannotateByOptions( annotateOrder, annotateAlgo, annotateStartNum,
2178 existingRefs, false, &hierarchy );
2179 }
2180
2181 annotatedSymbols[path].UpdateAnnotation();
2182
2183 // Update existing refs for next iteration
2184 for( size_t i = 0; i < annotatedSymbols[path].GetCount(); i++ )
2185 existingRefs.AddItem( annotatedSymbols[path][i] );
2186
2187 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[path] )
2188 {
2189 annotatedSymbols[pastedSheetPath].SortByReferenceOnly();
2190 annotatedSymbols[pastedSheetPath].SetRefDesTracker( schematicSettings.m_refDesTracker );
2191
2192 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2193 {
2194 annotatedSymbols[pastedSheetPath].ReannotateDuplicates( existingRefs, annotateAlgo );
2195 }
2196 else
2197 {
2198 annotatedSymbols[pastedSheetPath].ReannotateByOptions( annotateOrder, annotateAlgo,
2199 annotateStartNum, existingRefs,
2200 false, &hierarchy );
2201 }
2202
2203 annotatedSymbols[pastedSheetPath].UpdateAnnotation();
2204
2205 // Update existing refs for next iteration
2206 for( size_t i = 0; i < annotatedSymbols[pastedSheetPath].GetCount(); i++ )
2207 existingRefs.AddItem( annotatedSymbols[pastedSheetPath][i] );
2208 }
2209 }
2210 }
2211
2212 m_frame->GetCurrentSheet().UpdateAllScreenReferences();
2213
2214 // The copy operation creates instance paths that are not valid for the current project or
2215 // saved as part of another project. Prune them now so they do not accumulate in the saved
2216 // schematic file.
2218
2219 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
2220 SCH_SCREENS allScreens( m_frame->Schematic().Root() );
2221
2222 allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(), sheets );
2223 allScreens.PruneOrphanedSheetInstances( m_frame->Prj().GetProjectName(), sheets );
2224
2225 // Now clear the previous selection, select the pasted items, and fire up the "move" tool.
2226 m_toolMgr->RunAction( ACTIONS::selectionClear );
2227
2228 // If the item has a parent group, it will be part of the loadedItems, and will handle
2229 // the move action. Iterate backwards to avoid invalidating the iterator.
2230 for( int i = loadedItems.size() - 1; i >= 0; i-- )
2231 {
2232 EDA_ITEM* item = loadedItems[i];
2233
2234 if( item->GetParentGroup() )
2235 {
2236 loadedItems.erase( loadedItems.begin() + i );
2237 // These were hidden before because they would be added to the move preview,
2238 // but now they need to be shown as a preview so they appear to move when
2239 // the group moves.
2240 getView()->SetVisible( item );
2241 getView()->AddToPreview( item, false );
2242 }
2243 }
2244
2245 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &loadedItems );
2246
2247 SCH_SELECTION& selection = selTool->GetSelection();
2248
2249 if( !selection.Empty() )
2250 {
2251 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2252 {
2253 int closest_dist = INT_MAX;
2254
2255 auto processPt =
2256 [&]( const VECTOR2I& pt )
2257 {
2258 int dist = ( eventPos - pt ).EuclideanNorm();
2259
2260 if( dist < closest_dist )
2261 {
2262 selection.SetReferencePoint( pt );
2263 closest_dist = dist;
2264 }
2265 };
2266
2267 // Prefer connection points (which should remain on grid)
2268 for( EDA_ITEM* item : selection.Items() )
2269 {
2270 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
2271 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
2272
2273 if( sch_item && sch_item->IsConnectable() )
2274 {
2275 for( const VECTOR2I& pt : sch_item->GetConnectionPoints() )
2276 processPt( pt );
2277 }
2278 else if( pin )
2279 {
2280 processPt( pin->GetPosition() );
2281 }
2282
2283 // Symbols need to have their center point added since often users are trying to
2284 // move parts from their center.
2285 if( dynamic_cast<SCH_SYMBOL*>( item ) )
2286 processPt( item->GetPosition() );
2287 }
2288
2289 // Only process other points if we didn't find any connection points
2290 if( closest_dist == INT_MAX )
2291 {
2292 for( EDA_ITEM* item : selection.Items() )
2293 {
2294 switch( item->Type() )
2295 {
2296 case SCH_LINE_T:
2297 processPt( static_cast<SCH_LINE*>( item )->GetStartPoint() );
2298 processPt( static_cast<SCH_LINE*>( item )->GetEndPoint() );
2299 break;
2300
2301 case SCH_SHAPE_T:
2302 {
2303 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
2304
2305 switch( shape->GetShape() )
2306 {
2307 case SHAPE_T::RECTANGLE:
2308 for( const VECTOR2I& pt : shape->GetRectCorners() )
2309 processPt( pt );
2310
2311 break;
2312
2313 case SHAPE_T::CIRCLE:
2314 processPt( shape->GetCenter() );
2315 break;
2316
2317 case SHAPE_T::POLY:
2318 for( int ii = 0; ii < shape->GetPolyShape().TotalVertices(); ++ii )
2319 processPt( shape->GetPolyShape().CVertex( ii ) );
2320
2321 break;
2322
2323 default:
2324 processPt( shape->GetStart() );
2325 processPt( shape->GetEnd() );
2326 break;
2327 }
2328
2329 break;
2330 }
2331
2332 default:
2333 processPt( item->GetPosition() );
2334 break;
2335 }
2336 }
2337 }
2338
2339 selection.SetIsHover( m_duplicateIsHoverSelection );
2340 }
2341 // We want to the first non-group item in the selection to be the reference point.
2342 else if( selection.GetTopLeftItem()->Type() == SCH_GROUP_T )
2343 {
2344 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection.GetTopLeftItem() );
2345
2346 bool found = false;
2347 SCH_ITEM* item = nullptr;
2348
2349 group->RunOnChildren(
2350 [&]( SCH_ITEM* schItem )
2351 {
2352 if( !found && schItem->Type() != SCH_GROUP_T )
2353 {
2354 item = schItem;
2355 found = true;
2356 }
2357 },
2359
2360 if( found )
2361 selection.SetReferencePoint( item->GetPosition() );
2362 else
2363 selection.SetReferencePoint( group->GetPosition() );
2364 }
2365 else
2366 {
2367 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetTopLeftItem() );
2368
2369 selection.SetReferencePoint( item->GetPosition() );
2370 }
2371
2372 if( m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit ) )
2373 {
2374 // Pushing the commit will update the connectivity.
2375 commit.Push( _( "Paste" ) );
2376
2377 if( sheetsPasted )
2378 {
2379 m_frame->UpdateHierarchyNavigator();
2380 // UpdateHierarchyNavigator() will call RefreshNetNavigator()
2381 }
2382 else
2383 {
2384 m_frame->RefreshNetNavigator();
2385 }
2386 }
2387 else
2388 {
2389 commit.Revert();
2390 }
2391
2392 getView()->ClearPreview();
2393 }
2394
2395 return 0;
2396}
2397
2398
2400{
2401 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2402 SCH_SELECTION& selection = selTool->RequestSelection( { SCH_SYMBOL_T } );
2403 SCH_SYMBOL* symbol = nullptr;
2404 SYMBOL_EDIT_FRAME* symbolEditor;
2405
2406 if( selection.GetSize() >= 1 )
2407 symbol = (SCH_SYMBOL*) selection.Front();
2408
2409 if( selection.IsHover() )
2410 m_toolMgr->RunAction( ACTIONS::selectionClear );
2411
2412 if( !symbol )
2413 {
2414 // Giant hack: by default we assign Edit Table to the same hotkey, so give the table
2415 // tool a chance to handle it if we can't.
2416 if( SCH_EDIT_TABLE_TOOL* tableTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>() )
2417 tableTool->EditTable( aEvent );
2418
2419 return 0;
2420 }
2421
2422 if( symbol->GetEditFlags() != 0 )
2423 return 0;
2424
2425 if( symbol->IsMissingLibSymbol() )
2426 {
2427 m_frame->ShowInfoBarError( _( "Symbols with broken library symbol links cannot be edited." ) );
2428 return 0;
2429 }
2430
2432 symbolEditor = (SYMBOL_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, false );
2433
2434 if( symbolEditor )
2435 {
2436 if( wxWindow* blocking_win = symbolEditor->Kiway().GetBlockingDialog() )
2437 blocking_win->Close( true );
2438
2439 if( aEvent.IsAction( &SCH_ACTIONS::editWithLibEdit ) )
2440 {
2441 symbolEditor->LoadSymbolFromSchematic( symbol );
2442 }
2444 {
2445 symbolEditor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
2446
2447 if( !symbolEditor->IsLibraryTreeShown() )
2448 symbolEditor->ToggleLibraryTree();
2449 }
2450 }
2451
2452 return 0;
2453}
2454
2455
2457{
2458 m_frame->OnAnnotate();
2459 return 0;
2460}
2461
2462
2464{
2466 dlg.m_FirstRefDes->SetValidator( wxTextValidator( wxFILTER_EMPTY ) );
2467
2468 dlg.SetInitialFocus( dlg.m_FirstRefDes );
2469
2470 if( dlg.ShowModal() == wxID_OK )
2471 {
2472 SCH_REFERENCE startRef;
2473 startRef.SetRef( dlg.m_FirstRefDes->GetValue() );
2474
2475 if( startRef.IsSplitNeeded() )
2476 startRef.Split();
2477 else
2478 return 0;
2479
2480 int startNum = atoi( startRef.GetRefNumber().utf8_string().c_str() );
2481
2482 SCH_COMMIT commit( m_frame );
2483 SCHEMATIC* schematic = m_frame->m_schematic;
2484 SCH_REFERENCE_LIST references;
2485
2486 if( dlg.m_AllSheets->GetValue() )
2487 schematic->Hierarchy().GetSymbols( references );
2488 else
2489 schematic->CurrentSheet().GetSymbols( references );
2490
2491 references.SplitReferences();
2492
2493 for( SCH_REFERENCE& ref : references )
2494 {
2495 if( ref.GetRef() == startRef.GetRef() )
2496 {
2497 int num = atoi( ref.GetRefNumber().utf8_string().c_str() );
2498
2499 if( num >= startNum )
2500 {
2501 const SCH_SHEET_PATH& sheet = ref.GetSheetPath();
2502 wxString fullRef = ref.GetRef();
2503
2504 num += dlg.m_Increment->GetValue();
2505 fullRef << num;
2506
2507 commit.Modify( ref.GetSymbol(), sheet.LastScreen(), RECURSE_MODE::NO_RECURSE );
2508 ref.GetSymbol()->SetRef( &sheet, From_UTF8( fullRef.c_str() ) );
2509 }
2510 }
2511 }
2512
2513 if( !commit.Empty() )
2514 commit.Push( _( "Increment Annotations" ) );
2515 }
2516
2517 return 0;
2518}
2519
2520
2522{
2523 m_frame->OnOpenCvpcb();
2524 return 0;
2525}
2526
2527
2529{
2530 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
2531
2532 wxCHECK( dlg, 0 );
2533
2534 // Needed at least on Windows. Raise() is not enough
2535 dlg->Show( true );
2536
2537 // Bring it to the top if already open. Dual monitor users need this.
2538 dlg->Raise();
2539
2540 dlg->ShowEditTab();
2541
2542 return 0;
2543}
2544
2545
2547{
2549 m_frame->HardRedraw();
2550
2551 return 0;
2552}
2553
2554
2556{
2557 m_frame->OnOpenPcbnew();
2558 return 0;
2559}
2560
2561
2563{
2564 m_frame->OnUpdatePCB();
2565 return 0;
2566}
2567
2568
2570{
2572 dlg.ShowModal();
2573 return 0;
2574}
2575
2576
2578{
2580
2581 // If a plugin is removed or added, rebuild and reopen the new dialog
2582 while( result == NET_PLUGIN_CHANGE )
2584
2585 return 0;
2586}
2587
2588
2590{
2591 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
2592
2593 wxCHECK( dlg, 0 );
2594
2595 // Needed at least on Windows. Raise() is not enough
2596 dlg->Show( true );
2597
2598 // Bring it to the top if already open. Dual monitor users need this.
2599 dlg->Raise();
2600
2601 dlg->ShowExportTab();
2602
2603 return 0;
2604}
2605
2606
2608{
2610 return 0;
2611}
2612
2613
2615{
2616 m_frame->RecalculateConnections( nullptr, LOCAL_CLEANUP );
2617 m_frame->DrawCurrentSheetToClipboard();
2618 return 0;
2619}
2620
2621
2623{
2625 return 0;
2626}
2627
2628
2634
2635
2641
2642
2648
2649
2655
2656
2662
2663
2665{
2666 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2668
2670 m_frame->GetCanvas()->Refresh();
2671
2672 return 0;
2673}
2674
2675
2677{
2678 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2680
2682 m_frame->GetCanvas()->Refresh();
2683
2684 return 0;
2685}
2686
2687
2689{
2690 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2692
2694 m_frame->GetCanvas()->Refresh();
2695
2696 return 0;
2697}
2698
2699
2701{
2702 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2704
2706 m_frame->GetCanvas()->Refresh();
2707
2708 return 0;
2709}
2710
2711
2713{
2714 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2716
2718 m_frame->GetCanvas()->Refresh();
2719
2720 return 0;
2721}
2722
2723
2725{
2726 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2728
2729 m_frame->GetCanvas()->Refresh();
2730
2731 return 0;
2732}
2733
2734
2736{
2737 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2739
2740 m_frame->GetCanvas()->GetView()->UpdateAllItemsConditionally(
2741 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
2742 {
2743 int flags = 0;
2744
2745 auto invalidateTextVars =
2746 [&flags]( EDA_TEXT* text )
2747 {
2748 if( text->HasTextVars() )
2749 {
2750 text->ClearRenderCache();
2751 text->ClearBoundingBoxCache();
2753 }
2754 };
2755
2756 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
2757 {
2758 item->RunOnChildren(
2759 [&invalidateTextVars]( SCH_ITEM* aChild )
2760 {
2761 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
2762 invalidateTextVars( text );
2763 },
2765
2766 if( item->GetExcludedFromSim() )
2768 }
2769
2770 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
2771 invalidateTextVars( text );
2772
2773 return flags;
2774 } );
2775
2776 m_frame->GetCanvas()->Refresh();
2777
2778 return 0;
2779}
2780
2781
2783{
2784 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2786
2788 m_frame->RefreshOperatingPointDisplay();
2789 m_frame->GetCanvas()->Refresh();
2790
2791 return 0;
2792}
2793
2794
2796{
2797 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2799
2801 m_frame->RefreshOperatingPointDisplay();
2802 m_frame->GetCanvas()->Refresh();
2803
2804 return 0;
2805}
2806
2807
2809{
2810 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2812
2813 m_frame->GetRenderSettings()->m_ShowPinAltIcons = cfg->m_Appearance.show_pin_alt_icons;
2814
2816 m_frame->GetCanvas()->Refresh();
2817
2818 return 0;
2819}
2820
2821
2823{
2824 m_frame->eeconfig()->m_Drawing.line_mode = aEvent.Parameter<LINE_MODE>();
2825 m_toolMgr->PostAction( ACTIONS::refreshPreview );
2826 // Notify toolbar to update selection
2828 return 0;
2829}
2830
2831
2833{
2834 m_frame->eeconfig()->m_Drawing.line_mode++;
2835 m_frame->eeconfig()->m_Drawing.line_mode %= LINE_MODE::LINE_MODE_COUNT;
2836 m_toolMgr->PostAction( ACTIONS::refreshPreview );
2837 // Notify toolbar to update selection
2839 return 0;
2840}
2841
2842
2844{
2845 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2847 return 0;
2848}
2849
2850
2852{
2853 m_frame->ScriptingConsoleEnableDisable();
2854 return 0;
2855}
2856
2857
2859{
2860#ifdef KICAD_IPC_API
2861 if( Pgm().GetCommonSettings()->m_Api.enable_server )
2862 Pgm().GetPluginManager().ReloadPlugins();
2863#endif
2864 return 0;
2865}
2866
2868{
2869 // Update the left toolbar Line modes group icon to match current mode
2870 switch( static_cast<LINE_MODE>( m_frame->eeconfig()->m_Drawing.line_mode ) )
2871 {
2872 case LINE_MODE::LINE_MODE_FREE: m_frame->SelectLeftToolbarAction( SCH_ACTIONS::lineModeFree ); break;
2873 case LINE_MODE::LINE_MODE_90: m_frame->SelectLeftToolbarAction( SCH_ACTIONS::lineMode90 ); break;
2874 default:
2875 case LINE_MODE::LINE_MODE_45: m_frame->SelectLeftToolbarAction( SCH_ACTIONS::lineMode45 ); break;
2876 }
2877
2878 return 0;
2879}
2880
2881
2883{
2884 int errors = 0;
2885 wxString details;
2886 bool quiet = aEvent.Parameter<bool>();
2887
2888 // Repair duplicate IDs.
2889 std::map<KIID, EDA_ITEM*> ids;
2890 int duplicates = 0;
2891
2892 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
2893
2894 auto processItem =
2895 [&]( EDA_ITEM* aItem )
2896 {
2897 auto it = ids.find( aItem->m_Uuid );
2898
2899 if( it != ids.end() && it->second != aItem )
2900 {
2901 duplicates++;
2902 const_cast<KIID&>( aItem->m_Uuid ) = KIID();
2903 }
2904
2905 ids[ aItem->m_Uuid ] = aItem;
2906 };
2907
2908 // Symbol IDs are the most important, so give them the first crack at "claiming" a
2909 // particular KIID.
2910
2911 for( const SCH_SHEET_PATH& sheet : sheets )
2912 {
2913 SCH_SCREEN* screen = sheet.LastScreen();
2914
2915 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2916 {
2917 processItem( item );
2918
2919 for( SCH_PIN* pin : static_cast<SCH_SYMBOL*>( item )->GetPins( &sheet ) )
2920 processItem( pin );
2921 }
2922 }
2923
2924 for( const SCH_SHEET_PATH& sheet : sheets )
2925 {
2926 SCH_SCREEN* screen = sheet.LastScreen();
2927
2928 for( SCH_ITEM* item : screen->Items() )
2929 {
2930 processItem( item );
2931
2932 if( item->Type() != SCH_GROUP_T )
2933 {
2934 item->RunOnChildren(
2935 [&]( SCH_ITEM* aChild )
2936 {
2937 processItem( item );
2938 },
2940 }
2941 }
2942 }
2943
2944 /*******************************
2945 * Your test here
2946 */
2947
2948 /*******************************
2949 * Inform the user
2950 */
2951
2952 if( duplicates )
2953 {
2954 errors += duplicates;
2955 details += wxString::Format( _( "%d duplicate IDs replaced.\n" ), duplicates );
2956
2957 // Rehash sheetpaths as we may have changed their uuids.
2958 m_frame->Schematic().RefreshHierarchy();
2959 }
2960
2961 if( errors )
2962 {
2963 m_frame->OnModify();
2964
2965 wxString msg = wxString::Format( _( "%d potential problems repaired." ), errors );
2966
2967 if( !quiet )
2968 DisplayInfoMessage( m_frame, msg, details );
2969 }
2970 else if( !quiet )
2971 {
2972 DisplayInfoMessage( m_frame, _( "No errors found." ) );
2973 }
2974
2975 return 0;
2976}
2977
2978
2980{
2981 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
2982 return 0;
2983
2984 GRID_SETTINGS& gridSettings = m_toolMgr->GetSettings()->m_Window.grid;
2985 int currentIdx = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx;
2986
2987 wxArrayString gridsLabels;
2988
2989 for( const GRID& grid : gridSettings.grids )
2990 gridsLabels.Add( grid.UserUnitsMessageText( m_frame ) );
2991
2992 if( !m_frame->GetHotkeyPopup() )
2993 m_frame->CreateHotkeyPopup();
2994
2995 HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
2996
2997 if( popup )
2998 popup->Popup( _( "Grid" ), gridsLabels, currentIdx );
2999
3000 return 0;
3001}
3002
3003
3005{
3006 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3007
3008 if( !editFrame )
3009 return 1;
3010
3011 // Need to have a group selected and it needs to have a linked design block
3012 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3013 SCH_SELECTION selection = selTool->GetSelection();
3014
3015 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3016 return 1;
3017
3018 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3019
3020 if( !group->HasDesignBlockLink() )
3021 return 1;
3022
3023 // Get the associated design block
3024 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3025 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3026 true, true ) );
3027
3028 if( !designBlock )
3029 {
3030 wxString msg;
3031 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
3032 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3033 return 1;
3034 }
3035
3036 if( designBlock->GetSchematicFile().IsEmpty() )
3037 {
3038 wxString msg;
3039 msg.Printf( _( "Design block %s does not have a schematic file." ),
3040 group->GetDesignBlockLibId().GetUniStringLibId() );
3041 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3042 return 1;
3043 }
3044
3045 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3046
3047 return m_toolMgr->RunAction( SCH_ACTIONS::placeDesignBlock, designBlock.release() );
3048}
3049
3050
3052{
3053 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3054
3055 if( !editFrame )
3056 return 1;
3057
3058 // Need to have a group selected and it needs to have a linked design block
3059 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3060 SCH_SELECTION selection = selTool->GetSelection();
3061
3062 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3063 return 1;
3064
3065 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3066
3067 if( !group->HasDesignBlockLink() )
3068 return 1;
3069
3070 // Get the associated design block
3071 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3072 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3073 true, true ) );
3074
3075 if( !designBlock )
3076 {
3077 wxString msg;
3078 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
3079 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3080 return 1;
3081 }
3082
3083 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3084
3085 return m_toolMgr->RunAction( SCH_ACTIONS::saveSelectionToDesignBlock ) ? 1 : 0;
3086}
3087
3088
3090{
3091 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3092
3093 if( !editFrame )
3094 return 1;
3095
3096 editFrame->AddVariant();
3097
3098 return 0;
3099}
3100
3101
3103{
3104 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3105
3106 if( !editFrame )
3107 return 1;
3108
3109 editFrame->RemoveVariant();
3110 return 0;
3111}
3112
3113
3115{
3116 Go( &SCH_EDITOR_CONTROL::New, ACTIONS::doNew.MakeEvent() );
3117 Go( &SCH_EDITOR_CONTROL::Open, ACTIONS::open.MakeEvent() );
3118 Go( &SCH_EDITOR_CONTROL::Save, ACTIONS::save.MakeEvent() );
3125 Go( &SCH_EDITOR_CONTROL::Plot, ACTIONS::plot.MakeEvent() );
3126 Go( &SCH_EDITOR_CONTROL::Quit, ACTIONS::quit.MakeEvent() );
3127
3130
3136
3139
3145
3148
3149 Go( &SCH_EDITOR_CONTROL::Undo, ACTIONS::undo.MakeEvent() );
3150 Go( &SCH_EDITOR_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
3151 Go( &SCH_EDITOR_CONTROL::Cut, ACTIONS::cut.MakeEvent() );
3152 Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() );
3157
3159
3175
3183
3200
3202
3204
3206
3209
3212}
const char * name
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
static TOOL_ACTION updatePcbFromSchematic
Definition actions.h:264
static TOOL_ACTION paste
Definition actions.h:80
static TOOL_ACTION revert
Definition actions.h:62
static TOOL_ACTION saveAs
Definition actions.h:59
static TOOL_ACTION copy
Definition actions.h:78
static TOOL_ACTION pluginsReload
Definition actions.h:294
static TOOL_ACTION pickerTool
Definition actions.h:253
static TOOL_ACTION showSymbolEditor
Definition actions.h:260
static TOOL_ACTION pasteSpecial
Definition actions.h:81
static TOOL_ACTION plot
Definition actions.h:65
static TOOL_ACTION open
Definition actions.h:57
static TOOL_ACTION pageSettings
Definition actions.h:63
static TOOL_ACTION showSearch
Definition actions.h:116
static TOOL_ACTION undo
Definition actions.h:75
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition actions.h:214
static TOOL_ACTION duplicate
Definition actions.h:84
static TOOL_ACTION doDelete
Definition actions.h:85
static TOOL_ACTION quit
Definition actions.h:66
static TOOL_ACTION save
Definition actions.h:58
static TOOL_ACTION redo
Definition actions.h:76
static TOOL_ACTION updateSchematicFromPcb
Definition actions.h:265
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
static TOOL_ACTION print
Definition actions.h:64
static TOOL_ACTION showProperties
Definition actions.h:266
static TOOL_ACTION doNew
Definition actions.h:54
static TOOL_ACTION cut
Definition actions.h:77
static TOOL_ACTION copyAsText
Definition actions.h:79
static TOOL_ACTION refreshPreview
Definition actions.h:159
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:232
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition base_screen.h:85
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
int m_Threshold
Definition collector.h:236
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition commit.h:84
bool Empty() const
Definition commit.h:137
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
Calculate the connectivity of a schematic and generates netlists.
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Return the subgraph for a given net name on a given sheet.
const std::vector< CONNECTION_SUBGRAPH * > & GetAllSubgraphs(const wxString &aNetName) const
A subgraph is a set of items that are electrically connected on a single sheet.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
void SelectLibId(const LIB_ID &aLibId)
DESIGN_BLOCK * GetDesignBlock(const LIB_ID &aLibId, bool aUseCacheLib, bool aShowErrorMsg)
Load design block from design block library table.
Class DIALOG_INCREMENT_ANNOTATIONS_BASE.
void SetWksFileName(const wxString &aFilename)
bool Show(bool show) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
int ShowModal() override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual VECTOR2I GetPosition() const
Definition eda_item.h:272
EDA_ITEM_FLAGS GetEditFlags() const
Definition eda_item.h:148
const KIID m_Uuid
Definition eda_item.h:516
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:192
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
void ClearBrightened()
Definition eda_item.h:138
void SetBrightened()
Definition eda_item.h:135
EDA_ITEM * GetParent() const
Definition eda_item.h:112
bool IsBrightened() const
Definition eda_item.h:129
SHAPE_POLY_SET & GetPolyShape()
Definition eda_shape.h:336
SHAPE_T GetShape() const
Definition eda_shape.h:168
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:215
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:173
std::vector< VECTOR2I > GetRectCorners() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:98
virtual bool IsVisible() const
Definition eda_text.h:187
bool validatePasteIntoSelection(const SELECTION &aSel, wxString &aErrorMsg)
Validate if paste-into-cells is possible for the given selection.
bool pasteCellsIntoSelection(const SELECTION &aSel, T_TABLE *aSourceTable, T_COMMIT &aCommit)
Paste text content from source table into selected cells.
PANEL_ANNOTATE m_AnnotatePanel
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
static const TOOL_EVENT ClearedEvent
Definition actions.h:347
static const TOOL_EVENT GridChangedByKeyEvent
Definition actions.h:365
static const TOOL_EVENT SelectedEvent
Definition actions.h:345
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:352
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:344
static const TOOL_EVENT UnselectedEvent
Definition actions.h:346
Similar to EDA_VIEW_SWITCHER, this dialog is a popup that shows feedback when using a hotkey to cycle...
void Popup(const wxString &aTitle, const wxArrayString &aItems, int aSelection)
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
An interface for classes handling user events controlling the view behavior such as zooming,...
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:86
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition view.cpp:1685
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition view.h:400
void ClearPreview()
Definition view.cpp:1707
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1561
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition view.cpp:1633
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition view.cpp:1729
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition view.cpp:1612
bool EndsWith(const KIID_PATH &aPath) const
Test if aPath from the last path towards the first path.
Definition kiid.cpp:335
wxString AsString() const
Definition kiid.cpp:356
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:246
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
wxWindow * GetBlockingDialog()
Gets the window pointer to the blocking dialog (to send it signals)
Definition kiway.cpp:680
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
const wxString & Type() const
const wxString & Nickname() const
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
Define a library symbol object.
Definition lib_symbol.h:83
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:153
bool IsPower() const override
wxString GetName() const override
Definition lib_symbol.h:146
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
static void ConvertToSpiceMarkup(wxString *aNetName)
Remove formatting wrappers and replace illegal spice net name characters with underscores.
Tree view item data for the net navigator.
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList)
Parse a bus group label into the name and a list of components.
static bool ParseBusVector(const wxString &aBus, wxString *aName, std::vector< wxString > *aMemberList)
Parse a bus vector (e.g.
A holder to handle information on schematic or board items.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
void SetDescription(const wxString &aDescription)
void ReversePickersListOrder()
Reverse the order of pickers stored in this list.
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition picker_tool.h:92
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition picker_tool.h:81
void SetSnapping(bool aSnap)
Definition picker_tool.h:66
void SetCursor(KICURSOR aCursor)
Definition picker_tool.h:64
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
virtual bool HasMessage() const
Returns true if any messages were reported.
Definition reporter.h:134
static bool RescueProject(wxWindow *aParent, RESCUER &aRescuer, bool aRunningOnDemand)
size_t GetCandidateCount()
Return the number of rescue candidates found.
These are loaded from Eeschema settings but then overwritten by the project settings.
std::shared_ptr< REFDES_TRACKER > m_refDesTracker
A list of previously used schematic reference designators.
Holds all the data relating to one schematic.
Definition schematic.h:88
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
SCH_SHEET & Root() const
Definition schematic.h:125
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:186
static TOOL_ACTION showPcbNew
static TOOL_ACTION assignFootprints
static TOOL_ACTION lineModeNext
static TOOL_ACTION toggleOPCurrents
static TOOL_ACTION saveToLinkedDesignBlock
Definition sch_actions.h:71
static TOOL_ACTION clearHighlight
static TOOL_ACTION removeVariant
static TOOL_ACTION editSymbolFields
static TOOL_ACTION importFPAssignments
static TOOL_ACTION toggleAnnotateAuto
static TOOL_ACTION editLibSymbolWithLibEdit
static TOOL_ACTION toggleERCWarnings
static TOOL_ACTION schematicSetup
static TOOL_ACTION toggleDirectiveLabels
static TOOL_ACTION highlightNetTool
static TOOL_ACTION findNetInInspector
static TOOL_ACTION toggleHiddenFields
static TOOL_ACTION saveCurrSheetCopyAs
Definition sch_actions.h:43
static TOOL_ACTION showRemoteSymbolPanel
static TOOL_ACTION repairSchematic
static TOOL_ACTION remapSymbols
static TOOL_ACTION lineMode45
static TOOL_ACTION editSymbolLibraryLinks
static TOOL_ACTION simTune
static TOOL_ACTION generateBOM
static TOOL_ACTION showHierarchy
static TOOL_ACTION showNetNavigator
static TOOL_ACTION markSimExclusions
static TOOL_ACTION placeImage
static TOOL_ACTION editWithLibEdit
static TOOL_ACTION toggleERCErrors
static TOOL_ACTION incrementAnnotations
static TOOL_ACTION saveSelectionToDesignBlock
static TOOL_ACTION rescueSymbols
static TOOL_ACTION angleSnapModeChanged
static TOOL_ACTION placeLinkedDesignBlock
Definition sch_actions.h:70
static TOOL_ACTION generateBOMLegacy
static TOOL_ACTION placeDesignBlock
Definition sch_actions.h:69
static TOOL_ACTION toggleOPVoltages
static TOOL_ACTION simProbe
static TOOL_ACTION lineMode90
static TOOL_ACTION lineModeFree
static TOOL_ACTION changeSheet
static TOOL_ACTION highlightNet
static TOOL_ACTION assignNetclass
static TOOL_ACTION annotate
static TOOL_ACTION showDesignBlockPanel
static TOOL_ACTION togglePinAltIcons
static TOOL_ACTION toggleERCExclusions
static TOOL_ACTION updateNetHighlighting
static TOOL_ACTION exportNetlist
static TOOL_ACTION drawSheetOnClipboard
static TOOL_ACTION exportSymbolsToLibrary
static TOOL_ACTION toggleHiddenPins
static TOOL_ACTION selectOnPCB
static TOOL_ACTION addVariant
static TOOL_ACTION move
Base class for a bus or wire entry.
void Collect(SCH_SCREEN *aScreen, const std::vector< KICAD_T > &aScanTypes, const VECTOR2I &aPos, int aUnit=0, int aBodyStyle=0)
Scan a EDA_ITEM using this class's Inspector method which does the collection.
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
virtual void Revert() override
Revert the commit by restoring the modified items state.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString Name(bool aIgnoreSheet=false) const
Handle actions specific to the schematic editor.
int PageSetup(const TOOL_EVENT &aEvent)
bool RescueLegacyProject(bool aRunningOnDemand)
int ToggleDirectiveLabels(const TOOL_EVENT &aEvent)
int SaveAs(const TOOL_EVENT &aEvent)
int MarkSimExclusions(const TOOL_EVENT &aEvent)
int Annotate(const TOOL_EVENT &aEvent)
int ShowSchematicSetup(const TOOL_EVENT &aEvent)
int HighlightNet(const TOOL_EVENT &aEvent)
Remove any net highlighting.
int ClearHighlight(const TOOL_EVENT &aEvent)
Update net highlighting after an edit.
int FindNetInInspector(const TOOL_EVENT &aEvent)
int EditSymbolFields(const TOOL_EVENT &aEvent)
int GenerateBOMLegacy(const TOOL_EVENT &aEvent)
int HighlightNetCursor(const TOOL_EVENT &aEvent)
int CopyAsText(const TOOL_EVENT &aEvent)
int AddVariant(const TOOL_EVENT &aEvent)
int ImportFPAssignments(const TOOL_EVENT &aEvent)
int ChangeLineMode(const TOOL_EVENT &aEvent)
void doCrossProbeSchToPcb(const TOOL_EVENT &aEvent, bool aForce)
int ExportSymbolsToLibrary(const TOOL_EVENT &aEvent)
int SaveCurrSheetCopyAs(const TOOL_EVENT &aEvent)
Saves the currently-open schematic sheet to an other name.
bool rescueProject(RESCUER &aRescuer, bool aRunningOnDemand)
int CrossProbeToPcb(const TOOL_EVENT &aEvent)
Equivalent to the above, but initiated by the user.
int PlaceLinkedDesignBlock(const TOOL_EVENT &aEvent)
int ToggleRemoteSymbolPanel(const TOOL_EVENT &aEvent)
int Quit(const TOOL_EVENT &aEvent)
int RemapSymbols(const TOOL_EVENT &aEvent)
int DrawSheetOnClipboard(const TOOL_EVENT &aEvent)
SCH_SHEET_PATH updatePastedSheet(SCH_SHEET *aSheet, const SCH_SHEET_PATH &aPastePath, const KIID_PATH &aClipPath, bool aForceKeepAnnotations, SCH_SHEET_LIST *aPastedSheets, std::map< SCH_SHEET_PATH, SCH_REFERENCE_LIST > &aPastedSymbols)
int TogglePinAltIcons(const TOOL_EVENT &aEvent)
int RescueSymbols(const TOOL_EVENT &aEvent)
Perform rescue operations to recover old projects from before certain changes were made.
int AssignNetclass(const TOOL_EVENT &aEvent)
std::string m_duplicateClipboard
int ExportNetlist(const TOOL_EVENT &aEvent)
int Open(const TOOL_EVENT &aEvent)
int Paste(const TOOL_EVENT &aEvent)
int ToggleOPVoltages(const TOOL_EVENT &aEvent)
int Copy(const TOOL_EVENT &aEvent)
int SaveToLinkedDesignBlock(const TOOL_EVENT &aEvent)
int ToggleERCWarnings(const TOOL_EVENT &aEvent)
int NextLineMode(const TOOL_EVENT &aEvent)
int Redo(const TOOL_EVENT &aEvent)
Clipboard support.
int UpdatePCB(const TOOL_EVENT &aEvent)
int RemoveVariant(const TOOL_EVENT &aEvent)
int UpdateFromPCB(const TOOL_EVENT &aEvent)
int ToggleAnnotateAuto(const TOOL_EVENT &aEvent)
int ToggleHiddenPins(const TOOL_EVENT &aEvent)
int Duplicate(const TOOL_EVENT &aEvent)
int IncrementAnnotations(const TOOL_EVENT &aEvent)
bool searchSupplementaryClipboard(const wxString &aSheetFilename, SCH_SCREEN **aScreen)
int GridFeedback(const TOOL_EVENT &aEvent)
int ShowSearch(const TOOL_EVENT &aEvent)
int EditWithSymbolEditor(const TOOL_EVENT &aEvent)
int SimTune(const TOOL_EVENT &aEvent)
Highlight net under the cursor.
int EditSymbolLibraryLinks(const TOOL_EVENT &aEvent)
int New(const TOOL_EVENT &aEvent)
std::map< wxString, SCH_SCREEN * > m_supplementaryClipboard
int ExplicitCrossProbeToPcb(const TOOL_EVENT &aEvent)
int ToggleOPCurrents(const TOOL_EVENT &aEvent)
int ShowPcbNew(const TOOL_EVENT &aEvent)
int UpdateNetHighlighting(const TOOL_EVENT &aEvent)
Launch a tool to highlight nets.
int ToggleERCErrors(const TOOL_EVENT &aEvent)
int TogglePythonConsole(const TOOL_EVENT &aEvent)
int ShowHierarchy(const TOOL_EVENT &aEvent)
int OnAngleSnapModeChanged(const TOOL_EVENT &aEvent)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int ShowNetNavigator(const TOOL_EVENT &aEvent)
int SimProbe(const TOOL_EVENT &aEvent)
void updatePastedSymbol(SCH_SYMBOL *aSymbol, const SCH_SHEET_PATH &aPastePath, const KIID_PATH &aClipPath, bool aForceKeepAnnotations)
int ShowCvpcb(const TOOL_EVENT &aEvent)
int ToggleLibraryTree(const TOOL_EVENT &aEvent)
int RepairSchematic(const TOOL_EVENT &aEvent)
std::set< SCH_SYMBOL * > m_pastedSymbols
void prunePastedSymbolInstances()
Remove all pasted symbol instances that do not belong to the current project.
int Cut(const TOOL_EVENT &aEvent)
int ToggleProperties(const TOOL_EVENT &aEvent)
std::map< KIID_PATH, SCH_SYMBOL_INSTANCE > m_clipboardSymbolInstances
int Save(const TOOL_EVENT &aEvent)
bool RescueSymbolLibTableProject(bool aRunningOnDemand)
Notifies pcbnew about the selected item.
bool doCopy(bool aUseDuplicateClipboard=false)
< copy selection to clipboard or to m_duplicateClipboard
int Undo(const TOOL_EVENT &aEvent)
int ToggleERCExclusions(const TOOL_EVENT &aEvent)
int Plot(const TOOL_EVENT &aEvent)
int Print(const TOOL_EVENT &aEvent)
int Revert(const TOOL_EVENT &aEvent)
int GenerateBOM(const TOOL_EVENT &aEvent)
int ReloadPlugins(const TOOL_EVENT &aEvent)
void setPastedSymbolInstances(const SCH_SCREEN *aScreen)
int ToggleHiddenFields(const TOOL_EVENT &aEvent)
Schematic editor (Eeschema) main window.
void ToggleProperties() override
SCH_DESIGN_BLOCK_PANE * GetDesignBlockPane() const
void ToggleLibraryTree() override
void SetHighlightedConnection(const wxString &aConnection, const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr)
void SendCrossProbeClearHighlight()
Tell Pcbnew to clear the existing highlighted net, if one exists.
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.
const SCH_ITEM * GetSelectedNetNavigatorItem() const
SCHEMATIC & Schematic() const
void ToggleSearch()
Toggle the show/hide state of Search pane.
void ToggleSchematicHierarchy()
Toggle the show/hide state of the left side schematic navigation panel.
const wxString & GetHighlightedConnection() const
void UpdateNetHighlightStatus()
void SelectNetNavigatorItem(const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr)
void SetCrossProbeConnection(const SCH_CONNECTION *aConnection)
Send a connection (net or bus) to Pcbnew for highlighting.
void SetText(const wxString &aText) override
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:52
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void LoadContent(LINE_READER &aReader, SCH_SHEET *aSheet, int aVersion=SEXPR_SCHEMATIC_FILE_VERSION)
void Format(SCH_SHEET *aSheet)
static SCH_FILE_T EnumFromStr(const wxString &aFileType)
Return the #SCH_FILE_T from the corresponding plugin type name: "kicad", "legacy",...
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
virtual bool IsConnectable() const
Definition sch_item.h:507
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:250
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:244
virtual void SetLastResolvedState(const SCH_ITEM *aItem)
Definition sch_item.h:599
int GetBodyStyle() const
Definition sch_item.h:247
int GetUnit() const
Definition sch_item.h:238
void SetConnectivityDirty(bool aDirty=true)
Definition sch_item.h:570
bool IsConnectivityDirty() const
Definition sch_item.h:568
virtual void SetUnit(int aUnit)
Definition sch_item.h:237
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition sch_item.cpp:352
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:522
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:42
SCH_PIN * GetLibPin() const
Definition sch_pin.h:89
const wxString & GetNumber() const
Definition sch_pin.h:124
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SortByReferenceOnly()
Sort the list of references by reference.
void SplitReferences()
Attempt to split all reference designators into a name (U) and number (1).
void AddItem(const SCH_REFERENCE &aItem)
A helper to define a symbol's reference designator in a schematic.
void SetRef(const wxString &aReference)
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.
wxString GetRef() const
void SetSheetNumber(int aSheetNumber)
wxString GetRefNumber() const
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:728
SCH_SCREEN * GetNext()
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
SCH_SCREEN * GetFirst()
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
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 Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project #SYM...
std::set< wxString > GetSheetNames() const
const std::map< wxString, LIB_SYMBOL * > & GetLibSymbols() const
Fetch a list of unique LIB_SYMBOL object pointers required to properly render each SCH_SYMBOL in this...
Definition sch_screen.h:485
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:117
const wxString & GetFileName() const
Definition sch_screen.h:152
void MigrateSimModels()
Migrate any symbols having V6 simulation models to their V7 equivalents.
EDA_ITEM * GetNode(const VECTOR2I &aPosition)
Finds a connected item at a point (usually the cursor position).
bool SelectPoint(const VECTOR2I &aWhere, const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, EDA_ITEM **aItem=nullptr, bool *aSelectionCancelledFlag=nullptr, bool aCheckLocked=false, bool aAdd=false, bool aSubtract=false, bool aExclusiveOr=false)
Perform a click-type selection at a point (usually the cursor position).
int ClearSelection(const TOOL_EVENT &aEvent)
Select all visible items in sheet.
void GuessSelectionCandidates(SCH_COLLECTOR &collector, const VECTOR2I &aPos)
Apply heuristics to try and determine a single object when multiple are found under the cursor.
SCH_SELECTION & GetSelection()
SCH_SELECTION & RequestSelection(const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, bool aPromoteCellSelections=false, bool aPromoteGroups=false)
Return either an existing selection (filtered), or the selection at the current cursor position if th...
VECTOR2I GetCenter() const
Definition sch_shape.h:88
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Fill an item cache for temporary use when many items need to be fetched.
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
SCH_SHEET_LIST FindAllSheetsForScreen(const SCH_SCREEN *aScreen) const
Return a SCH_SHEET_LIST with a copy of all the SCH_SHEET_PATH using a particular screen.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
bool PageNumberExists(const wxString &aPageNumber) const
bool ContainsSheet(const SCH_SHEET *aSheet) const
bool HasPath(const KIID_PATH &aPath) const
bool TestForRecursion(const SCH_SHEET_LIST &aSrcSheetHierarchy, const wxString &aDestFileName)
Test every SCH_SHEET_PATH in this SCH_SHEET_LIST to verify if adding the sheets stored in aSrcSheetHi...
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()
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:47
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:341
void RemoveInstance(const KIID_PATH &aInstancePath)
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
void AddInstance(const SCH_SHEET_INSTANCE &aInstance)
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:116
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition sch_sheet.h:198
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:478
Schematic symbol object.
Definition sch_symbol.h:76
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SYMBOLs don't currently support embedded files, but their LIB_SYMBOL counterparts do.
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:135
wxString GetSchSymbolLibraryName() const
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
bool IsMissingLibSymbol() const
Check to see if the library symbol is set to the dummy library symbol.
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:165
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:184
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
bool IsPower() const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
void BrightenItem(EDA_ITEM *aItem)
void UnbrightenItem(EDA_ITEM *aItem)
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the index-th vertex in a given hole outline within a given outline.
The SIMULATOR_FRAME holds the main user-interface for running simulations.
void AddCurrentTrace(const wxString &aDeviceName)
Add a current trace for a given device to the current plot.
void AddVoltageTrace(const wxString &aNetName)
Add a voltage trace for a given net to the current plot.
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
Definition sim_lib_mgr.h:48
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:422
const std::string & GetString()
Definition richio.h:445
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:226
The symbol library editor main window.
bool IsLibraryTreeShown() const override
void LoadSymbol(const wxString &aLibrary, const wxString &aSymbol, int Unit)
void LoadSymbolFromSchematic(SCH_SYMBOL *aSymbol)
Load a symbol from the schematic to edit in place.
void ToggleLibraryTree() override
An interface to the global shared library manager that is schematic-specific and linked to one projec...
Class to handle modifications to the symbol libraries.
Symbol library viewer main window.
SCH_EDIT_FRAME * getEditFrame() const
Definition tool_base.h:186
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:44
KIGFX::VIEW * getView() const
Definition tool_base.cpp:38
Generic, UI-independent tool event.
Definition tool_event.h:171
bool DisableGridSnapping() const
Definition tool_event.h:371
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
void Go(int(SCH_EDIT_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Master controller class:
TOOLS_HOLDER * GetToolHolder() const
A wrapper for reporting to a wxString object.
Definition reporter.h:191
const wxString & GetMessages() const
Definition reporter.cpp:77
bool SaveClipboard(const std::string &aTextUTF8)
Store information to the system clipboard.
Definition clipboard.cpp:38
std::string GetClipboardUTF8()
Return the information currently stored in the system clipboard.
Definition clipboard.cpp:58
std::unique_ptr< wxImage > GetImageFromClipboard()
Get image data from the clipboard, if there is any.
Definition clipboard.cpp:84
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition common.cpp:580
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:177
This file is part of the common library.
@ VOLTAGE_PROBE
Definition cursors.h:60
@ CURRENT_PROBE
Definition cursors.h:62
@ BULLSEYE
Definition cursors.h:58
int InvokeDialogCreateBOM(SCH_EDIT_FRAME *aCaller)
Create and show DIALOG_BOM and return whatever DIALOG_BOM::ShowModal() returns.
bool InvokeDialogEditSymbolsLibId(SCH_EDIT_FRAME *aCaller)
Run a dialog to modify the LIB_ID of symbols for instance when a symbol has moved from a symbol libra...
int InvokeDialogNetList(SCH_EDIT_FRAME *aCaller)
#define _(s)
@ RECURSE
Definition eda_item.h:51
@ NO_RECURSE
Definition eda_item.h:52
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition eda_item.h:566
#define IS_PASTED
Modifier on IS_NEW which indicates it came from clipboard.
#define IS_NEW
New item, just created.
#define ENDPOINT
ends. (Used to support dragging.)
#define IS_MOVING
Item being moved.
#define STARTPOINT
When a line is selected, these flags indicate which.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:46
@ LINE_MODE_90
@ LINE_MODE_45
@ LINE_MODE_FREE
@ LINE_MODE_COUNT
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ FRAME_SCH_VIEWER
Definition frame_type.h:36
@ FRAME_SIMULATOR
Definition frame_type.h:38
static const std::string KiCadSchematicFileExtension
static wxString KiCadSchematicFileWildcard()
static const wxChar traceSchPaste[]
Flag to enable schematic paste debugging output.
#define NET_PLUGIN_CHANGE
Create and shows DIALOG_EXPORT_NETLIST and returns whatever DIALOG_EXPORT_NETLIST::ShowModal() return...
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
@ LAYER_ERC_WARN
Definition layer_ids.h:479
@ LAYER_ERC_ERR
Definition layer_ids.h:480
@ LAYER_OP_CURRENTS
Definition layer_ids.h:502
@ LAYER_OP_VOLTAGES
Definition layer_ids.h:501
void Prettify(std::string &aSource, FORMAT_MODE aMode)
Pretty-prints s-expression text according to KiCad format rules.
@ REPAINT
Item needs to be redrawn.
Definition view_item.h:58
@ GEOMETRY
Position or shape has changed.
Definition view_item.h:55
#define MAX_PAGE_SIZE_EESCHEMA_MILS
Definition page_info.h:36
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:946
see class PGM_BASE
static bool highlightNet(TOOL_MANAGER *aToolMgr, const VECTOR2D &aPosition)
#define HITTEST_THRESHOLD_PIXELS
static VECTOR2D CLEAR
Class to handle a set of SCH_ITEMs.
ANNOTATE_ORDER_T
Schematic annotation order options.
ANNOTATE_ALGO_T
Schematic annotation type options.
wxString GetSelectedItemsAsText(const SELECTION &aSel)
@ LOCAL_CLEANUP
Definition schematic.h:76
@ NO_CLEANUP
Definition schematic.h:75
@ GLOBAL_CLEANUP
Definition schematic.h:77
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
wxString From_UTF8(const char *cstring)
std::vector< GRID > grids
Common grid settings, available to every frame.
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
static constexpr auto NOT_CONNECTED
Definition sim_model.h:73
std::string refName
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
std::string path
KIBIS_MODEL * model
KIBIS_PIN * pin
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition tool_action.h:49
@ TA_UNDO_REDO_PRE
This event is sent before undo/redo command is performed.
Definition tool_event.h:106
@ TC_MESSAGE
Definition tool_event.h:58
@ SCH_GROUP_T
Definition typeinfo.h:177
@ SCH_TABLE_T
Definition typeinfo.h:169
@ SCH_LINE_T
Definition typeinfo.h:167
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_TABLECELL_T
Definition typeinfo.h:170
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_SHEET_T
Definition typeinfo.h:179
@ SCH_MARKER_T
Definition typeinfo.h:162
@ SCH_SHAPE_T
Definition typeinfo.h:153
@ SCH_PIN_T
Definition typeinfo.h:157
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:39