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>
52#include <sch_edit_frame.h>
54#include <sch_bitmap.h>
55#include <sch_group.h>
56#include <sch_line.h>
57#include <sch_junction.h>
58#include <sch_bus_entry.h>
59#include <sch_shape.h>
60#include <sch_painter.h>
61#include <sch_sheet_pin.h>
62#include <sch_commit.h>
63#include <sim/simulator_frame.h>
64#include <symbol_lib_table.h>
65#include <symbol_library.h>
67#include <symbol_viewer_frame.h>
68#include <tool/picker_tool.h>
69#include <tool/tool_manager.h>
70#include <tools/sch_actions.h>
71#include <tools/sch_selection.h>
76#include <view/view_controls.h>
78#include <wx_filename.h>
79#include <wx/filedlg.h>
80#include <wx/log.h>
81#include <wx/treectrl.h>
82#include <wx/msgdlg.h>
85
86#ifdef KICAD_IPC_API
88#endif
89
90
96static const wxChar traceSchPaste[] = wxT( "KICAD_SCH_PASTE" );
97
98
100{
101 m_frame->NewProject();
102 return 0;
103}
104
105
107{
108 m_frame->LoadProject();
109 return 0;
110}
111
112
114{
115 m_frame->SaveProject();
116 return 0;
117}
118
119
121{
122 m_frame->SaveProject( true );
123 return 0;
124}
125
126
128{
129 SCH_SHEET* curr_sheet = m_frame->GetCurrentSheet().Last();
130 wxFileName curr_fn = curr_sheet->GetFileName();
131 wxFileDialog dlg( m_frame, _( "Schematic Files" ), curr_fn.GetPath(), curr_fn.GetFullName(),
132 FILEEXT::KiCadSchematicFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
133
134 if( dlg.ShowModal() == wxID_CANCEL )
135 return false;
136
137 wxString newFilename = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
138
139 m_frame->saveSchematicFile( curr_sheet, newFilename );
140 return 0;
141}
142
143
145{
146 SCHEMATIC& schematic = m_frame->Schematic();
147 SCH_SHEET& root = schematic.Root();
148
149 if( m_frame->GetCurrentSheet().Last() != &root )
150 {
151 SCH_SHEET_PATH rootSheetPath;
152 rootSheetPath.push_back( &root );
153
154 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet, &rootSheetPath );
155 wxSafeYield();
156 }
157
158 wxString msg;
159 msg.Printf( _( "Revert '%s' (and all sub-sheets) to last version saved?" ), schematic.GetFileName() );
160
161 if( !IsOK( m_frame, msg ) )
162 return false;
163
164 SCH_SCREENS screenList( schematic.Root() );
165
166 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
167 screen->SetContentModified( false ); // do not prompt the user for changes
168
169 m_frame->ReleaseFile();
170 m_frame->OpenProjectFiles( std::vector<wxString>( 1, schematic.GetFileName() ), KICTL_REVERT );
171
172 return 0;
173}
174
175
177{
178 m_frame->ShowSchematicSetupDialog();
179 return 0;
180}
181
182
184{
185 PICKED_ITEMS_LIST undoCmd;
187 ITEM_PICKER wrapper( m_frame->GetScreen(), undoItem, UNDO_REDO::PAGESETTINGS );
188
189 undoCmd.PushItem( wrapper );
190 undoCmd.SetDescription( _( "Page Settings" ) );
191 m_frame->SaveCopyInUndoList( undoCmd, UNDO_REDO::PAGESETTINGS, false );
192
193 DIALOG_EESCHEMA_PAGE_SETTINGS dlg( m_frame, m_frame->Schematic().GetEmbeddedFiles(),
196
197 if( dlg.ShowModal() == wxID_OK )
198 {
199 // Update text variables
200 m_frame->GetCanvas()->GetView()->MarkDirty();
201 m_frame->GetCanvas()->GetView()->UpdateAllItems( KIGFX::REPAINT );
202 m_frame->GetCanvas()->Refresh();
203
204 m_frame->OnModify();
205 }
206 else
207 {
208 m_frame->RollbackSchematicFromUndo();
209 }
210
211 return 0;
212}
213
214
216{
217 SCH_SCREENS schematic( m_frame->Schematic().Root() );
218
219 if( schematic.HasNoFullyDefinedLibIds() )
220 RescueLegacyProject( true );
221 else
223
224 return 0;
225}
226
227
228bool SCH_EDITOR_CONTROL::RescueLegacyProject( bool aRunningOnDemand )
229{
230 LEGACY_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
231 m_frame->GetCanvas()->GetBackend() );
232
233 return rescueProject( rescuer, aRunningOnDemand );
234}
235
236
238{
239 SYMBOL_LIB_TABLE_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
240 m_frame->GetCanvas()->GetBackend() );
241
242 return rescueProject( rescuer, aRunningOnDemand );
243}
244
245
246bool SCH_EDITOR_CONTROL::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
247{
248 if( !RESCUER::RescueProject( m_frame, aRescuer, aRunningOnDemand ) )
249 return false;
250
251 if( aRescuer.GetCandidateCount() )
252 {
253 KIWAY_PLAYER* viewer = m_frame->Kiway().Player( FRAME_SCH_VIEWER, false );
254
255 if( viewer )
256 static_cast<SYMBOL_VIEWER_FRAME*>( viewer )->ReCreateLibList();
257
258 if( aRunningOnDemand )
259 {
260 SCH_SCREENS schematic( m_frame->Schematic().Root() );
261
262 schematic.UpdateSymbolLinks();
263 m_frame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
264 }
265
266 m_frame->ClearUndoRedoList();
267 m_frame->SyncView();
268 m_frame->GetCanvas()->Refresh();
269 m_frame->OnModify();
270 }
271
272 return true;
273}
274
275
277{
278 DIALOG_SYMBOL_REMAP dlgRemap( m_frame );
279
280 dlgRemap.ShowQuasiModal();
281
282 m_frame->GetCanvas()->Refresh( true );
283
284 return 0;
285}
286
287
289{
290 DIALOG_PRINT dlg( m_frame );
291
292 dlg.ShowModal();
293
294 return 0;
295}
296
297
299{
301
302 dlg.ShowModal();
303
304 return 0;
305}
306
307
309{
310 m_frame->Close( false );
311 return 0;
312}
313
314
316{
317 doCrossProbeSchToPcb( aEvent, false );
318 return 0;
319}
320
321
323{
324 doCrossProbeSchToPcb( aEvent, true );
325 return 0;
326}
327
328
329void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
330{
331 // Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
332 if( m_probingPcbToSch || m_frame->IsSyncingSelection() )
333 return;
334
335 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
336 SCH_SELECTION& selection = aForce ? selTool->RequestSelection() : selTool->GetSelection();
337
338 m_frame->SendSelectItemsToPcb( selection.GetItemsSortedBySelectionOrder(), aForce );
339}
340
341
343{
344 bool savePowerSymbols = false;
345 bool map = false;
347 wxString targetLib;
348 wxString msg;
349
350 targetLib = m_frame->SelectLibrary( _( "Export Symbols" ), _( "Export symbols to library:" ),
351 { { _( "Include power symbols in export" ), &savePowerSymbols },
352 { _( "Update schematic symbols to link to exported symbols" ), &map }
353 } );
354
355 if( targetLib.empty() )
356 return 0;
357
358 SCH_SHEET_LIST sheets = m_frame->Schematic().BuildSheetListSortedByPageNumbers();
359 SCH_REFERENCE_LIST symbols;
360 sheets.GetSymbols( symbols, savePowerSymbols );
361
362 std::map<LIB_ID, LIB_SYMBOL*> libSymbols;
363 std::map<LIB_ID, std::vector<SCH_SYMBOL*>> symbolMap;
364
365 for( size_t i = 0; i < symbols.GetCount(); ++i )
366 {
367 SCH_SYMBOL* symbol = symbols[i].GetSymbol();
368 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
369 LIB_ID id = libSymbol->GetLibId();
370
371 if( libSymbols.count( id ) )
372 {
373 wxASSERT_MSG( libSymbols[id]->Compare( *libSymbol, SCH_ITEM::COMPARE_FLAGS::ERC ) == 0,
374 "Two symbols have the same LIB_ID but are different!" );
375 }
376 else
377 {
378 libSymbols[id] = libSymbol;
379 }
380
381 symbolMap[id].emplace_back( symbol );
382 }
383
384 bool append = false;
385 SCH_COMMIT commit( m_frame );
386 SYMBOL_LIB_TABLE_ROW* row = mgr.GetLibrary( targetLib );
387 SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::EnumFromStr( row->GetType() );
388 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
389
390 wxFileName dest = row->GetFullURI( true );
391 dest.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
392
393 for( const std::pair<const LIB_ID, LIB_SYMBOL*>& it : libSymbols )
394 {
395 LIB_SYMBOL* origSym = it.second;
396 LIB_SYMBOL* newSym = origSym->Flatten().release();
397
398 try
399 {
400 pi->SaveSymbol( dest.GetFullPath(), newSym );
401 }
402 catch( const IO_ERROR& ioe )
403 {
404 msg.Printf( _( "Error saving symbol %s to library '%s'." ), newSym->GetName(), row->GetNickName() );
405 msg += wxS( "\n\n" ) + ioe.What();
406 wxLogWarning( msg );
407 return 0;
408 }
409
410 if( map )
411 {
412 LIB_ID id = it.first;
413 id.SetLibNickname( targetLib );
414
415 for( SCH_SYMBOL* symbol : symbolMap[it.first] )
416 {
417 SCH_SCREEN* parentScreen = static_cast<SCH_SCREEN*>( symbol->GetParent() );
418
419 wxCHECK2( parentScreen, continue );
420
421 commit.Modify( symbol, parentScreen, RECURSE_MODE::NO_RECURSE );
422 symbol->SetLibId( id );
423 append = true;
424 }
425 }
426 }
427
428 // Save the modified symbol library table. We need to look this up by name in each table to find
429 // whether the new library is a global or project entity as the code above to choose the library
430 // returns a different type depending on whether a global or project library is chosen.
432 SYMBOL_LIB_TABLE* projectTable = nullptr;
433
434 if( !m_frame->Prj().IsNullProject() )
435 projectTable = PROJECT_SCH::SchSymbolLibTable( &m_frame->Prj() );
436
437 if( globalTable->FindRow( targetLib ) )
438 {
439 try
440 {
441 wxString globalTablePath = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
442 globalTable->Save( globalTablePath );
443 }
444 catch( const IO_ERROR& ioe )
445 {
446 msg.Printf( _( "Error saving global library table:\n\n%s" ), ioe.What() );
447 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
448 }
449 }
450 else if( projectTable && projectTable->FindRow( targetLib ) )
451 {
452 try
453 {
454 wxString projectPath = m_frame->Prj().GetProjectPath();
455 wxFileName projectTableFn( projectPath, SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
456 projectTable->Save( projectTableFn.GetFullPath() );
457 }
458 catch( const IO_ERROR& ioe )
459 {
460 msg.Printf( _( "Error saving project-specific library table:\n\n%s" ), ioe.What() );
461 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
462 }
463 }
464
465 if( append )
466 {
467 std::set<SCH_SCREEN*> processedScreens;
468
469 for( SCH_SHEET_PATH& sheet : sheets )
470 {
471 SCH_SCREEN* screen = sheet.LastScreen();
472
473 if( processedScreens.find( ( screen ) ) == processedScreens.end() )
474 {
475 processedScreens.insert( screen );
476 screen->UpdateSymbolLinks();
477 }
478 }
479
480 commit.Push( wxS( "Update Library Identifiers" ) );
481 }
482
483 return 0;
484}
485
486
487#define HITTEST_THRESHOLD_PIXELS 5
488
490{
491 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
492 KIWAY_PLAYER* sim_player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
493 SIMULATOR_FRAME* sim_Frame = static_cast<SIMULATOR_FRAME*>( sim_player );
494
495 if( !sim_Frame ) // Defensive coding; shouldn't happen.
496 return 0;
497
498 if( wxWindow* blocking_win = sim_Frame->Kiway().GetBlockingDialog() )
499 blocking_win->Close( true );
500
501 // Deactivate other tools; particularly important if another PICKER is currently running
502 Activate();
503
505 picker->SetSnapping( false );
506 picker->ClearHandlers();
507
508 picker->SetClickHandler(
509 [this]( const VECTOR2D& aPosition )
510 {
511 KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
512 SIMULATOR_FRAME* simFrame = static_cast<SIMULATOR_FRAME*>( player );
513 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
514
515 // We do not really want to keep an item selected in schematic,
516 // so clear the current selection
517 selTool->ClearSelection();
518
519 EDA_ITEM* item = selTool->GetNode( aPosition );
520 SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
521
522 if( !item )
523 return false;
524
525 if( item->Type() == SCH_PIN_T )
526 {
527 SCH_PIN* schPin = static_cast<SCH_PIN*>( item );
528 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( schPin->GetParentSymbol() );
529 SCH_PIN* libPin = schPin->GetLibPin();
530
531 if( !symbol || !libPin )
532 return false;
533
534 try
535 {
536 WX_STRING_REPORTER reporter;
537 SIM_LIB_MGR mgr( &m_frame->Prj() );
538
539 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
540 embeddedFilesStack.push_back( m_frame->Schematic().GetEmbeddedFiles() );
541
542 if( EMBEDDED_FILES* symbolEmbeddedFile = symbol->GetEmbeddedFiles() )
543 embeddedFilesStack.push_back( symbolEmbeddedFile );
544
545 mgr.SetFilesStack( std::move( embeddedFilesStack ) );
546
547 SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, true, 0, reporter ).model;
548
549 if( reporter.HasMessage() )
550 THROW_IO_ERROR( reporter.GetMessages() );
551
552 SPICE_ITEM spiceItem;
553 spiceItem.refName = symbol->GetRef( &sheet ).ToStdString();
554 std::vector<std::string> currentNames = model.SpiceGenerator().CurrentNames( spiceItem );
555
556 if( currentNames.size() == 0 )
557 {
558 return true;
559 }
560 else if( currentNames.size() == 1 )
561 {
562 if( simFrame )
563 simFrame->AddCurrentTrace( currentNames.at( 0 ) );
564
565 return true;
566 }
567
568 int modelPinIndex = model.FindModelPinIndex( libPin->GetNumber().ToStdString() );
569
570 if( modelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
571 {
572 wxString name = currentNames.at( modelPinIndex );
573
574 if( simFrame )
575 simFrame->AddCurrentTrace( name );
576 }
577 }
578 catch( const IO_ERROR& e )
579 {
581 }
582 }
583 else if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T } ) || item->IsType( { SCH_JUNCTION_T } ) )
584 {
585 if( SCH_CONNECTION* conn = static_cast<SCH_ITEM*>( item )->Connection() )
586 {
587 wxString spiceNet = UnescapeString( conn->Name() );
589
590 if( simFrame )
591 simFrame->AddVoltageTrace( wxString::Format( "V(%s)", spiceNet ) );
592 }
593 }
594
595 return true;
596 } );
597
598 picker->SetMotionHandler(
599 [this]( const VECTOR2D& aPos )
600 {
601 SCH_COLLECTOR collector;
602 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
603 collector.Collect( m_frame->GetScreen(), { SCH_ITEM_LOCATE_WIRE_T,
604 SCH_PIN_T,
605 SCH_SHEET_PIN_T }, aPos );
606
607 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
608 selectionTool->GuessSelectionCandidates( collector, aPos );
609
610 EDA_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
611 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( item );
612
613 const SCH_CONNECTION* conn = nullptr;
614
615 if( wire )
616 {
617 item = nullptr;
618 conn = wire->Connection();
619 }
620
621 if( item && item->Type() == SCH_PIN_T )
622 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::CURRENT_PROBE );
623 else
624 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::VOLTAGE_PROBE );
625
626 if( m_pickerItem != item )
627 {
628 if( m_pickerItem )
629 selectionTool->UnbrightenItem( m_pickerItem );
630
631 m_pickerItem = item;
632
633 if( m_pickerItem )
634 selectionTool->BrightenItem( m_pickerItem );
635 }
636
637 wxString connectionName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
638
639 if( m_frame->GetHighlightedConnection() != connectionName )
640 {
641 m_frame->SetHighlightedConnection( connectionName );
642
643 TOOL_EVENT dummyEvent;
644 UpdateNetHighlighting( dummyEvent );
645 }
646 } );
647
648 picker->SetFinalizeHandler(
649 [this]( const int& aFinalState )
650 {
651 if( m_pickerItem )
652 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
653
654 if( !m_frame->GetHighlightedConnection().IsEmpty() )
655 {
656 m_frame->SetHighlightedConnection( wxEmptyString );
657
658 TOOL_EVENT dummyEvent;
659 UpdateNetHighlighting( dummyEvent );
660 }
661
662 // Wake the selection tool after exiting to ensure the cursor gets updated
663 // and deselect previous selection from simulator to avoid any issue
664 // ( avoid crash in some cases when the SimProbe tool is deselected )
665 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
666 selectionTool->ClearSelection();
668 } );
669
670 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
671
672 return 0;
673}
674
675
677{
678 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
679
680 // Deactivate other tools; particularly important if another PICKER is currently running
681 Activate();
682
683 picker->SetCursor( KICURSOR::TUNE );
684 picker->SetSnapping( false );
685 picker->ClearHandlers();
686
687 picker->SetClickHandler(
688 [this]( const VECTOR2D& aPosition )
689 {
690 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
691 EDA_ITEM* item = nullptr;
692 selTool->SelectPoint( aPosition, { SCH_SYMBOL_T, SCH_FIELD_T }, &item );
693
694 if( !item )
695 return false;
696
697 if( item->Type() != SCH_SYMBOL_T )
698 {
699 item = item->GetParent();
700
701 if( item->Type() != SCH_SYMBOL_T )
702 return false;
703 }
704
705 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
706 SCH_SHEET_PATH sheetPath = symbol->Schematic()->CurrentSheet();
707 KIWAY_PLAYER* simFrame = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
708
709 if( simFrame )
710 {
711 if( wxWindow* blocking_win = simFrame->Kiway().GetBlockingDialog() )
712 blocking_win->Close( true );
713
714 static_cast<SIMULATOR_FRAME*>( simFrame )->AddTuner( sheetPath, symbol );
715 }
716
717 // We do not really want to keep a symbol selected in schematic,
718 // so clear the current selection
719 selTool->ClearSelection();
720 return true;
721 } );
722
723 picker->SetMotionHandler(
724 [this]( const VECTOR2D& aPos )
725 {
726 SCH_COLLECTOR collector;
727 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
728 collector.Collect( m_frame->GetScreen(), { SCH_SYMBOL_T, SCH_FIELD_T }, aPos );
729
730 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
731 selectionTool->GuessSelectionCandidates( collector, aPos );
732
733 EDA_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
734
735 if( item && item->Type() == SCH_FIELD_T )
736 item = static_cast<SCH_FIELD*>( item )->GetParentSymbol();
737
738 if( m_pickerItem != item )
739 {
740 if( m_pickerItem )
741 selectionTool->UnbrightenItem( m_pickerItem );
742
743 m_pickerItem = item;
744
745 if( m_pickerItem )
746 selectionTool->BrightenItem( m_pickerItem );
747 }
748 } );
749
750 picker->SetFinalizeHandler(
751 [this]( const int& aFinalState )
752 {
753 if( m_pickerItem )
754 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
755
756 // Wake the selection tool after exiting to ensure the cursor gets updated
757 // and deselect previous selection from simulator to avoid any issue
758 // ( avoid crash in some cases when the SimTune tool is deselected )
759 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
760 selectionTool->ClearSelection();
762 } );
763
764 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
765
766 return 0;
767}
768
769
770// A singleton reference for clearing the highlight
772
773
774static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
775{
776 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( aToolMgr->GetToolHolder() );
777 SCH_SELECTION_TOOL* selTool = aToolMgr->GetTool<SCH_SELECTION_TOOL>();
778 SCH_EDITOR_CONTROL* editorControl = aToolMgr->GetTool<SCH_EDITOR_CONTROL>();
779 SCH_CONNECTION* conn = nullptr;
780 SCH_ITEM* item = nullptr;
781 bool retVal = true;
782
783 if( aPosition != CLEAR )
784 {
785 ERC_TESTER erc( &editFrame->Schematic() );
786
787 if( erc.TestDuplicateSheetNames( false ) > 0 )
788 {
789 wxMessageBox( _( "Error: duplicate sub-sheet names found in current sheet." ) );
790 retVal = false;
791 }
792 else
793 {
794 item = static_cast<SCH_ITEM*>( selTool->GetNode( aPosition ) );
795 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
796
797 if( item )
798 {
799 if( item->IsConnectivityDirty() )
800 editFrame->RecalculateConnections( nullptr, NO_CLEANUP );
801
802 if( item->Type() == SCH_FIELD_T )
803 symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
804
805 if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
806 {
807 std::vector<SCH_PIN*> pins = symbol->GetPins();
808
809 if( pins.size() == 1 )
810 conn = pins[0]->Connection();
811 }
812 else
813 {
814 conn = item->Connection();
815 }
816 }
817 }
818 }
819
820 wxString connName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
821
822 if( !conn )
823 {
824 editFrame->SetStatusText( wxT( "" ) );
825 editFrame->SendCrossProbeClearHighlight();
826 editFrame->SetHighlightedConnection( wxEmptyString );
827 editorControl->SetHighlightBusMembers( false );
828 }
829 else
830 {
831 NET_NAVIGATOR_ITEM_DATA itemData( editFrame->GetCurrentSheet(), item );
832
833 if( connName != editFrame->GetHighlightedConnection() )
834 {
835 editorControl->SetHighlightBusMembers( false );
836 editFrame->SetCrossProbeConnection( conn );
837 editFrame->SetHighlightedConnection( connName, &itemData );
838 }
839 else
840 {
841 editorControl->SetHighlightBusMembers( !editorControl->GetHighlightBusMembers() );
842
843 if( item != editFrame->GetSelectedNetNavigatorItem() )
844 editFrame->SelectNetNavigatorItem( &itemData );
845 }
846 }
847
848 editFrame->UpdateNetHighlightStatus();
849
851 editorControl->UpdateNetHighlighting( dummy );
852
853 return retVal;
854}
855
856
858{
860 VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
861
862 highlightNet( m_toolMgr, cursorPos );
863
864 return 0;
865}
866
867
869{
871
872 return 0;
873}
874
875
877{
878 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
879 SCHEMATIC& schematic = m_frame->Schematic();
880 SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
881
882 std::vector<std::pair<SCH_CONNECTION*, VECTOR2D>> selectedConns;
883
884 for( EDA_ITEM* item : selectionTool->GetSelection() )
885 {
886 SCH_CONNECTION* conn = static_cast<SCH_ITEM*>( item )->Connection();
887
888 if( !conn )
889 continue;
890
891 selectedConns.emplace_back( conn, item->GetPosition() );
892 }
893
894 if( selectedConns.empty() )
895 {
896 m_frame->ShowInfoBarError( _( "No nets selected." ) );
897 return 0;
898 }
899
900 // Remove selection in favor of highlighting so the whole net is highlighted
901 selectionTool->ClearSelection();
902
903 const auto getNetNamePattern =
904 []( const SCH_CONNECTION& aConn ) -> std::optional<wxString>
905 {
906 wxString netName = aConn.Name();
907
908 if( aConn.IsBus() )
909 {
910 wxString prefix;
911
912 if( NET_SETTINGS::ParseBusVector( netName, &prefix, nullptr ) )
913 return prefix + wxT( "*" );
914 else if( NET_SETTINGS::ParseBusGroup( netName, &prefix, nullptr ) )
915 return prefix + wxT( ".*" );
916 }
917 else if( !aConn.Driver() || CONNECTION_SUBGRAPH::GetDriverPriority( aConn.Driver() )
919 {
920 return std::nullopt;
921 }
922
923 return netName;
924 };
925
926 std::set<wxString> netNames;
927
928 for( const auto& [conn, pos] : selectedConns )
929 {
930 std::optional<wxString> netNamePattern = getNetNamePattern( *conn );
931
932 if( !netNamePattern )
933 {
934 // This is a choice, we can also allow some un-labeled nets as long as some are labeled.
935 m_frame->ShowInfoBarError( _( "All selected nets must be labeled to assign a netclass." ) );
936 return 0;
937 }
938
939 netNames.insert( *netNamePattern );
940 }
941
942 wxCHECK( !netNames.empty(), 0 );
943
944 DIALOG_ASSIGN_NETCLASS dlg( m_frame, netNames, schematic.GetNetClassAssignmentCandidates(),
945 [&]( const std::vector<wxString>& aNetNames )
946 {
947 for( SCH_ITEM* item : screen->Items() )
948 {
949 bool redraw = item->IsBrightened();
950 SCH_CONNECTION* itemConn = item->Connection();
951
952 if( itemConn && alg::contains( aNetNames, itemConn->Name() ) )
953 item->SetBrightened();
954 else
955 item->ClearBrightened();
956
957 redraw |= item->IsBrightened();
958
959 if( item->Type() == SCH_SYMBOL_T )
960 {
961 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
962
963 redraw |= symbol->HasBrightenedPins();
964
965 symbol->ClearBrightenedPins();
966
967 for( SCH_PIN* pin : symbol->GetPins() )
968 {
969 SCH_CONNECTION* pin_conn = pin->Connection();
970
971 if( pin_conn && alg::contains( aNetNames, pin_conn->Name() ) )
972 {
973 pin->SetBrightened();
974 redraw = true;
975 }
976 }
977 }
978 else if( item->Type() == SCH_SHEET_T )
979 {
980 for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
981 {
982 SCH_CONNECTION* pin_conn = pin->Connection();
983
984 redraw |= pin->IsBrightened();
985
986 if( pin_conn && alg::contains( aNetNames, pin_conn->Name() ) )
987 pin->SetBrightened();
988 else
989 pin->ClearBrightened();
990
991 redraw |= pin->IsBrightened();
992 }
993 }
994
995 if( redraw )
996 getView()->Update( item, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
997 }
998
999 m_frame->GetCanvas()->ForceRefresh();
1000 } );
1001
1002 if( dlg.ShowModal() )
1003 {
1004 getView()->UpdateAllItemsConditionally(
1005 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
1006 {
1007 int flags = 0;
1008
1009 auto invalidateTextVars =
1010 [&flags]( EDA_TEXT* text )
1011 {
1012 if( text->HasTextVars() )
1013 {
1014 text->ClearRenderCache();
1015 text->ClearBoundingBoxCache();
1017 }
1018 };
1019
1020 // Netclass coloured items
1021 //
1022 if( dynamic_cast<SCH_LINE*>( aItem ) )
1023 flags |= KIGFX::REPAINT;
1024 else if( dynamic_cast<SCH_JUNCTION*>( aItem ) )
1025 flags |= KIGFX::REPAINT;
1026 else if( dynamic_cast<SCH_BUS_ENTRY_BASE*>( aItem ) )
1027 flags |= KIGFX::REPAINT;
1028
1029 // Items that might reference an item's netclass name
1030 //
1031 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
1032 {
1033 item->RunOnChildren(
1034 [&invalidateTextVars]( SCH_ITEM* aChild )
1035 {
1036 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
1037 invalidateTextVars( text );
1038 },
1040
1041 if( flags & KIGFX::GEOMETRY )
1042 m_frame->GetScreen()->Update( item, false ); // Refresh RTree
1043 }
1044
1045 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
1046 invalidateTextVars( text );
1047
1048 return flags;
1049 } );
1050 }
1051
1052 highlightNet( m_toolMgr, CLEAR );
1053 return 0;
1054}
1055
1056
1058{
1059 wxCHECK( m_frame, 0 );
1060
1061 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
1062 SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
1063 CONNECTION_GRAPH* connectionGraph = m_frame->Schematic().ConnectionGraph();
1064 wxString selectedName = m_frame->GetHighlightedConnection();
1065
1066 std::set<wxString> connNames;
1067 std::vector<EDA_ITEM*> itemsToRedraw;
1068
1069 wxCHECK( screen && connectionGraph, 0 );
1070
1071 if( !selectedName.IsEmpty() )
1072 {
1073 connNames.emplace( selectedName );
1074
1075 if( CONNECTION_SUBGRAPH* sg = connectionGraph->FindSubgraphByName( selectedName, sheetPath ) )
1076 {
1078 {
1079 for( const SCH_ITEM* item : sg->GetItems() )
1080 {
1081 wxCHECK2( item, continue );
1082
1083 if( SCH_CONNECTION* connection = item->Connection() )
1084 {
1085 for( const std::shared_ptr<SCH_CONNECTION>& member : connection->AllMembers() )
1086 {
1087 if( member )
1088 connNames.emplace( member->Name() );
1089 }
1090 }
1091 }
1092 }
1093 }
1094
1095 // Place all bus names that are connected to the selected net in the set, regardless of
1096 // their sheet. This ensures that nets that are connected to a bus on a different sheet
1097 // get their buses highlighted as well.
1098 for( CONNECTION_SUBGRAPH* sg : connectionGraph->GetAllSubgraphs( selectedName ) )
1099 {
1100 for( const auto& [_, bus_sgs] : sg->GetBusParents() )
1101 {
1102 for( CONNECTION_SUBGRAPH* bus_sg : bus_sgs )
1103 connNames.emplace( bus_sg->GetNetName() );
1104 }
1105
1106 }
1107 }
1108
1109 for( SCH_ITEM* item : screen->Items() )
1110 {
1111 if( !item || !item->IsConnectable() )
1112 continue;
1113
1114 SCH_ITEM* redrawItem = nullptr;
1115
1116 if( item->Type() == SCH_SYMBOL_T )
1117 {
1118 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1119
1120 for( SCH_PIN* pin : symbol->GetPins() )
1121 {
1122 if( SCH_CONNECTION* pin_conn = pin->Connection() )
1123 {
1124 if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
1125 {
1126 pin->SetBrightened();
1127 redrawItem = symbol;
1128 }
1129 else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
1130 {
1131 pin->ClearBrightened();
1132 redrawItem = symbol;
1133 }
1134 }
1135 }
1136
1137 if( symbol->IsPower() && symbol->GetPins().size() )
1138 {
1139 if( SCH_CONNECTION* pinConn = symbol->GetPins()[0]->Connection() )
1140 {
1142 {
1143 SCH_FIELD* field = symbol->GetField( id );
1144
1145 if( !field->IsVisible() )
1146 continue;
1147
1148 if( !field->IsBrightened() && connNames.count( pinConn->Name() ) )
1149 {
1150 field->SetBrightened();
1151 redrawItem = symbol;
1152 }
1153 else if( field->IsBrightened() && !connNames.count( pinConn->Name() ) )
1154 {
1155 field->ClearBrightened();
1156 redrawItem = symbol;
1157 }
1158 }
1159 }
1160 }
1161 }
1162 else if( item->Type() == SCH_SHEET_T )
1163 {
1164 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1165
1166 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1167 {
1168 wxCHECK2( pin, continue );
1169
1170 if( SCH_CONNECTION* pin_conn = pin->Connection() )
1171 {
1172 if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
1173 {
1174 pin->SetBrightened();
1175 redrawItem = sheet;
1176 }
1177 else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
1178 {
1179 pin->ClearBrightened();
1180 redrawItem = sheet;
1181 }
1182 }
1183 }
1184 }
1185 else
1186 {
1187 if( SCH_CONNECTION* itemConn = item->Connection() )
1188 {
1189 if( !item->IsBrightened() && connNames.count( itemConn->Name() ) )
1190 {
1191 item->SetBrightened();
1192 redrawItem = item;
1193 }
1194 else if( item->IsBrightened() && !connNames.count( itemConn->Name() ) )
1195 {
1196 item->ClearBrightened();
1197 redrawItem = item;
1198 }
1199 }
1200 }
1201
1202 if( redrawItem )
1203 itemsToRedraw.push_back( redrawItem );
1204 }
1205
1206 if( itemsToRedraw.size() )
1207 {
1208 // Be sure highlight change will be redrawn
1209 KIGFX::VIEW* view = getView();
1210
1211 for( EDA_ITEM* redrawItem : itemsToRedraw )
1213
1214 m_frame->GetCanvas()->Refresh();
1215 }
1216
1217 return 0;
1218}
1219
1220
1222{
1223 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
1224
1225 // Deactivate other tools; particularly important if another PICKER is currently running
1226 Activate();
1227
1228 picker->SetCursor( KICURSOR::BULLSEYE );
1229 picker->SetSnapping( false );
1230 picker->ClearHandlers();
1231
1232 picker->SetClickHandler(
1233 [this] ( const VECTOR2D& aPos )
1234 {
1235 return highlightNet( m_toolMgr, aPos );
1236 } );
1237
1238 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1239
1240 return 0;
1241}
1242
1243
1245{
1246 wxCHECK( m_frame, 0 );
1247
1248 if( m_frame->GetUndoCommandCount() <= 0 )
1249 return 0;
1250
1251 // Inform tools that undo command was issued
1252 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1253
1254 // Get the old list
1255 PICKED_ITEMS_LIST* undo_list = m_frame->PopCommandFromUndoList();
1256
1257 wxCHECK( undo_list, 0 );
1258
1259 m_frame->PutDataInPreviousState( undo_list );
1260
1261 // Now push the old command to the RedoList
1262 undo_list->ReversePickersListOrder();
1263 m_frame->PushCommandToRedoList( undo_list );
1264
1265 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1266
1267 m_frame->GetCanvas()->Refresh();
1268 m_frame->OnModify();
1269
1270 return 0;
1271}
1272
1273
1275{
1276 wxCHECK( m_frame, 0 );
1277
1278 if( m_frame->GetRedoCommandCount() == 0 )
1279 return 0;
1280
1281 // Inform tools that undo command was issued
1282 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1283
1284 /* Get the old list */
1285 PICKED_ITEMS_LIST* list = m_frame->PopCommandFromRedoList();
1286
1287 wxCHECK( list, 0 );
1288
1289 /* Redo the command: */
1290 m_frame->PutDataInPreviousState( list );
1291
1292 /* Put the old list in UndoList */
1293 list->ReversePickersListOrder();
1294 m_frame->PushCommandToUndoList( list );
1295
1296 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1297
1298 m_frame->GetCanvas()->Refresh();
1299 m_frame->OnModify();
1300
1301 return 0;
1302}
1303
1304
1305bool SCH_EDITOR_CONTROL::doCopy( bool aUseDuplicateClipboard )
1306{
1307 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1308 SCH_SELECTION& selection = selTool->RequestSelection();
1309 SCHEMATIC& schematic = m_frame->Schematic();
1310
1311 if( selection.Empty() )
1312 return false;
1313
1314 if( aUseDuplicateClipboard )
1315 m_duplicateIsHoverSelection = selection.IsHover();
1316
1317 selection.SetScreen( m_frame->GetScreen() );
1319
1320 for( EDA_ITEM* item : selection.GetItems() )
1321 {
1322 if( item->Type() == SCH_SHEET_T )
1323 {
1324 SCH_SHEET* sheet = (SCH_SHEET*) item;
1325 m_supplementaryClipboard[ sheet->GetFileName() ] = sheet->GetScreen();
1326 }
1327 else if( item->Type() == SCH_FIELD_T && selection.IsHover() )
1328 {
1329 // Most of the time the user is trying to duplicate the parent symbol
1330 // and the field text is in it
1331 selection.Add( item->GetParent() );
1332 }
1333 else if( item->Type() == SCH_MARKER_T )
1334 {
1335 // Don't let the markers be copied
1336 selection.Remove( item );
1337 }
1338 else if( item->Type() == SCH_GROUP_T )
1339 {
1340 // Groups need to have all their items selected
1341 static_cast<SCH_ITEM*>( item )->RunOnChildren(
1342 [&]( EDA_ITEM* aChild )
1343 {
1344 selection.Add( aChild );
1345 },
1347 }
1348 }
1349
1350 STRING_FORMATTER formatter;
1351 SCH_IO_KICAD_SEXPR plugin;
1352 SCH_SHEET_PATH selPath = m_frame->GetCurrentSheet();
1353
1354 plugin.Format( &selection, &selPath, schematic, &formatter, true );
1355
1356 std::string prettyData = formatter.GetString();
1357 KICAD_FORMAT::Prettify( prettyData, true );
1358
1359 if( selection.IsHover() )
1360 m_toolMgr->RunAction( ACTIONS::selectionClear );
1361
1362 if( aUseDuplicateClipboard )
1363 {
1364 m_duplicateClipboard = prettyData;
1365 return true;
1366 }
1367
1368 return SaveClipboard( prettyData );
1369}
1370
1371
1372bool SCH_EDITOR_CONTROL::searchSupplementaryClipboard( const wxString& aSheetFilename, SCH_SCREEN** aScreen )
1373{
1374 if( m_supplementaryClipboard.count( aSheetFilename ) > 0 )
1375 {
1376 *aScreen = m_supplementaryClipboard[ aSheetFilename ];
1377 return true;
1378 }
1379
1380 return false;
1381}
1382
1383
1385{
1386 doCopy( true ); // Use the local clipboard
1387 Paste( aEvent );
1388
1389 return 0;
1390}
1391
1392
1394{
1395 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1396
1397 if( textEntry )
1398 {
1399 textEntry->Cut();
1400 return 0;
1401 }
1402
1403 if( doCopy() )
1404 m_toolMgr->RunAction( ACTIONS::doDelete );
1405
1406 return 0;
1407}
1408
1409
1411{
1412 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1413
1414 if( textEntry )
1415 {
1416 textEntry->Copy();
1417 return 0;
1418 }
1419
1420 doCopy();
1421
1422 return 0;
1423}
1424
1425
1427{
1428 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1429 SCH_SELECTION& selection = selTool->RequestSelection();
1430
1431 if( selection.Empty() )
1432 return false;
1433
1434 wxString itemsAsText = GetSelectedItemsAsText( selection );
1435
1436 if( selection.IsHover() )
1437 m_toolMgr->RunAction( ACTIONS::selectionClear );
1438
1439 return SaveClipboard( itemsAsText.ToStdString() );
1440}
1441
1442
1444 const KIID_PATH& aClipPath, bool aForceKeepAnnotations )
1445{
1446 wxCHECK( m_frame && aSymbol, /* void */ );
1447
1448 SCH_SYMBOL_INSTANCE newInstance;
1449 bool instanceFound = false;
1450 KIID_PATH pasteLookupPath = aClipPath;
1451
1452 m_pastedSymbols.insert( aSymbol );
1453
1454 for( const SCH_SYMBOL_INSTANCE& tmp : aSymbol->GetInstances() )
1455 {
1456 if( ( tmp.m_Path.empty() && aClipPath.empty() ) || ( !aClipPath.empty() && tmp.m_Path.EndsWith( aClipPath ) ) )
1457 {
1458 newInstance = tmp;
1459 instanceFound = true;
1460
1461 wxLogTrace( traceSchPaste, wxS( "Pasting found symbol instance with reference %s, unit %d:\n"
1462 "\tClipboard path: %s\n"
1463 "\tSymbol UUID: %s." ),
1464 tmp.m_Reference,
1465 tmp.m_Unit,
1466 aClipPath.AsString(),
1467 aSymbol->m_Uuid.AsString() );
1468
1469 break;
1470 }
1471 }
1472
1473 // The pasted symbol look up paths include the symbol UUID.
1474 pasteLookupPath.push_back( aSymbol->m_Uuid );
1475
1476 if( !instanceFound )
1477 {
1478 wxLogTrace( traceSchPaste, wxS( "Clipboard symbol instance **not** found:\n\tClipboard path: %s\n"
1479 "\tSymbol UUID: %s." ),
1480 aClipPath.AsString(),
1481 aSymbol->m_Uuid.AsString() );
1482
1483 // Some legacy versions saved value fields escaped. While we still do in the symbol
1484 // editor, we don't anymore in the schematic, so be sure to unescape them.
1485 SCH_FIELD* valueField = aSymbol->GetField( FIELD_T::VALUE );
1486 valueField->SetText( UnescapeString( valueField->GetText() ) );
1487
1488 // Pasted from notepad or an older instance of eeschema. Use the values in the fields
1489 // instead.
1490 newInstance.m_Reference = aSymbol->GetField( FIELD_T::REFERENCE )->GetText();
1491 newInstance.m_Unit = aSymbol->GetUnit();
1492 }
1493
1494 newInstance.m_Path = aPastePath.Path();
1495 newInstance.m_ProjectName = m_frame->Prj().GetProjectName();
1496
1497 aSymbol->AddHierarchicalReference( newInstance );
1498
1499 if( !aForceKeepAnnotations )
1500 aSymbol->ClearAnnotation( &aPastePath, false );
1501
1502 // We might clear annotations but always leave the original unit number from the paste.
1503 aSymbol->SetUnit( newInstance.m_Unit );
1504}
1505
1506
1508 const KIID_PATH& aClipPath, bool aForceKeepAnnotations,
1509 SCH_SHEET_LIST* aPastedSheets, std::map<SCH_SHEET_PATH,
1510 SCH_REFERENCE_LIST>& aPastedSymbols )
1511{
1512 wxCHECK( aSheet && aPastedSheets, aPastePath );
1513
1514 SCH_SHEET_PATH sheetPath = aPastePath;
1515 sheetPath.push_back( aSheet );
1516
1517 aPastedSheets->push_back( sheetPath );
1518
1519 if( aSheet->GetScreen() == nullptr )
1520 return sheetPath; // We can only really set the page number but not load any items
1521
1522 for( SCH_ITEM* item : aSheet->GetScreen()->Items() )
1523 {
1524 if( item->IsConnectable() )
1525 item->SetConnectivityDirty();
1526
1527 if( item->Type() == SCH_SYMBOL_T )
1528 {
1529 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1530
1531 wxCHECK2( symbol, continue );
1532
1533 // Only do this once if the symbol is shared across multiple sheets.
1534 if( !m_pastedSymbols.count( symbol ) )
1535 {
1536 for( SCH_PIN* pin : symbol->GetPins() )
1537 {
1538 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1539 pin->SetConnectivityDirty();
1540 }
1541 }
1542
1543 updatePastedSymbol( symbol, sheetPath, aClipPath, aForceKeepAnnotations );
1544 }
1545 else if( item->Type() == SCH_SHEET_T )
1546 {
1547 SCH_SHEET* subsheet = static_cast<SCH_SHEET*>( item );
1548
1549 wxCHECK2( subsheet, continue );
1550
1551 // Make sure pins get a new UUID and set the dirty connectivity flag.
1552 if( !aPastedSheets->ContainsSheet( subsheet ) )
1553 {
1554 for( SCH_SHEET_PIN* pin : subsheet->GetPins() )
1555 {
1556 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1557 pin->SetConnectivityDirty();
1558 }
1559 }
1560
1561 KIID_PATH newClipPath = aClipPath;
1562 newClipPath.push_back( subsheet->m_Uuid );
1563
1564 updatePastedSheet( subsheet, sheetPath, newClipPath, aForceKeepAnnotations, aPastedSheets,
1565 aPastedSymbols );
1566 }
1567 }
1568
1569 sheetPath.GetSymbols( aPastedSymbols[aPastePath] );
1570
1571 return sheetPath;
1572}
1573
1574
1576{
1577 wxCHECK( aScreen, /* void */ );
1578
1579 for( const SCH_ITEM* item : aScreen->Items() )
1580 {
1581 if( item->Type() == SCH_SYMBOL_T )
1582 {
1583 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1584
1585 wxCHECK2( symbol, continue );
1586
1587 for( const SCH_SYMBOL_INSTANCE& symbolInstance : symbol->GetInstances() )
1588 {
1589 KIID_PATH pathWithSymbol = symbolInstance.m_Path;
1590
1591 pathWithSymbol.push_back( symbol->m_Uuid );
1592
1593 m_clipboardSymbolInstances[pathWithSymbol] = symbolInstance;
1594 }
1595 }
1596 }
1597}
1598
1599
1601{
1602 wxCHECK( m_frame, /* void */ );
1603
1604 for( SCH_SYMBOL* symbol : m_pastedSymbols )
1605 {
1606 wxCHECK2( symbol, continue );
1607
1608 std::vector<KIID_PATH> instancePathsToRemove;
1609
1610 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1611 {
1612 if( instance.m_ProjectName != m_frame->Prj().GetProjectName() || instance.m_Path.empty() )
1613 instancePathsToRemove.emplace_back( instance.m_Path );
1614 }
1615
1616 for( const KIID_PATH& path : instancePathsToRemove )
1617 symbol->RemoveInstance( path );
1618 }
1619}
1620
1621
1623{
1624 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1625
1626 if( textEntry )
1627 {
1628 textEntry->Paste();
1629 return 0;
1630 }
1631
1632 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1633 std::string content;
1634 VECTOR2I eventPos;
1635
1636 SCH_SHEET tempSheet;
1637
1638 std::unique_ptr<wxImage> clipImg = GetImageFromClipboard();
1639
1640 if( !aEvent.IsAction( &ACTIONS::duplicate ) && clipImg )
1641 {
1642 // Just image data
1643 auto bitmap = std::make_unique<SCH_BITMAP>();
1644
1645 bool ok = bitmap->GetReferenceImage().SetImage( *clipImg );
1646
1647 if( !ok )
1648 return 0;
1649
1650 return m_toolMgr->RunAction( SCH_ACTIONS::placeImage, bitmap.release() );
1651 }
1652
1653 if( aEvent.IsAction( &ACTIONS::duplicate ) )
1654 content = m_duplicateClipboard;
1655 else
1656 content = GetClipboardUTF8();
1657
1658 if( content.empty() )
1659 return 0;
1660
1661 if( aEvent.IsAction( &ACTIONS::duplicate ) )
1662 eventPos = getViewControls()->GetCursorPosition( false );
1663
1664 STRING_LINE_READER reader( content, "Clipboard" );
1665 SCH_IO_KICAD_SEXPR plugin;
1666
1667 // Screen object on heap is owned by the sheet.
1668 SCH_SCREEN* tempScreen = new SCH_SCREEN( &m_frame->Schematic() );
1669 tempSheet.SetScreen( tempScreen );
1670
1671 try
1672 {
1673 plugin.LoadContent( reader, &tempSheet );
1674 }
1675 catch( IO_ERROR& )
1676 {
1677 // If it wasn't content, then paste as a text object.
1678 if( content.size() > static_cast<size_t>( ADVANCED_CFG::GetCfg().m_MaxPastedTextLength ) )
1679 {
1680 int result = IsOK( m_frame, _( "Pasting a long text text string may be very slow. "
1681 "Do you want to continue?" ) );
1682 if( !result )
1683 return 0;
1684 }
1685
1686 SCH_TEXT* text_item = new SCH_TEXT( VECTOR2I( 0, 0 ), content );
1687 tempScreen->Append( text_item );
1688 }
1689
1690 m_pastedSymbols.clear();
1692
1693 // Save pasted symbol instances in case the user chooses to keep existing symbol annotation.
1694 setPastedSymbolInstances( tempScreen );
1695
1696 tempScreen->MigrateSimModels();
1697
1698 bool annotateAutomatic = m_frame->eeconfig()->m_AnnotatePanel.automatic;
1699 SCHEMATIC_SETTINGS& schematicSettings = m_frame->Schematic().Settings();
1700 int annotateStartNum = schematicSettings.m_AnnotateStartNum;
1701
1703 bool forceRemoveAnnotations = false;
1704
1705 if( aEvent.IsAction( &ACTIONS::pasteSpecial ) )
1706 {
1707 PASTE_MODE defaultPasteMode = pasteMode;
1708 DIALOG_PASTE_SPECIAL dlg( m_frame, &pasteMode );
1709
1710 if( dlg.ShowModal() == wxID_CANCEL )
1711 return 0;
1712
1713 // We have to distinguish if removing was explicit
1714 forceRemoveAnnotations = pasteMode == PASTE_MODE::REMOVE_ANNOTATIONS && pasteMode != defaultPasteMode;
1715 }
1716
1717 bool forceKeepAnnotations = pasteMode != PASTE_MODE::REMOVE_ANNOTATIONS;
1718
1719 // SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything
1720 // else. Pull them back out to start with.
1721 SCH_COMMIT commit( m_toolMgr );
1722 EDA_ITEMS loadedItems;
1723 std::vector<SCH_ITEM*> sortedLoadedItems;
1724 bool sheetsPasted = false;
1725 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
1726 SCH_SHEET_PATH& pasteRoot = m_frame->GetCurrentSheet();
1727 wxFileName destFn = pasteRoot.Last()->GetFileName();
1728
1729 if( destFn.IsRelative() )
1730 destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
1731
1732 // List of paths in the hierarchy that refer to the destination sheet of the paste
1733 SCH_SHEET_LIST sheetPathsForScreen = hierarchy.FindAllSheetsForScreen( pasteRoot.LastScreen() );
1734 sheetPathsForScreen.SortByPageNumbers();
1735
1736 // Build a list of screens from the current design (to avoid loading sheets that already exist)
1737 std::map<wxString, SCH_SCREEN*> loadedScreens;
1738
1739 for( const SCH_SHEET_PATH& item : hierarchy )
1740 {
1741 if( item.LastScreen() )
1742 loadedScreens[item.Last()->GetFileName()] = item.LastScreen();
1743 }
1744
1745 // Get set of sheet names in the current schematic to prevent duplicate sheet names on paste.
1746 std::set<wxString> existingSheetNames = pasteRoot.LastScreen()->GetSheetNames();
1747
1748 // Build symbol list for reannotation of duplicates
1749 SCH_REFERENCE_LIST existingRefs;
1750 hierarchy.GetSymbols( existingRefs );
1751 existingRefs.SortByReferenceOnly();
1752
1753 std::set<wxString> existingRefsSet;
1754
1755 for( const SCH_REFERENCE& ref : existingRefs )
1756 existingRefsSet.insert( ref.GetRef() );
1757
1758 // Build UUID map for fetching last-resolved-properties
1759 std::map<KIID, EDA_ITEM*> itemMap;
1760 hierarchy.FillItemMap( itemMap );
1761
1762 // Keep track of pasted sheets and symbols for the different paths to the hierarchy.
1763 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> pastedSymbols;
1764 std::map<SCH_SHEET_PATH, SCH_SHEET_LIST> pastedSheets;
1765
1766 for( SCH_ITEM* item : tempScreen->Items() )
1767 {
1768 if( item->Type() == SCH_SHEET_T )
1769 sortedLoadedItems.push_back( item );
1770 else
1771 loadedItems.push_back( item );
1772 }
1773
1774 sort( sortedLoadedItems.begin(), sortedLoadedItems.end(),
1775 []( SCH_ITEM* firstItem, SCH_ITEM* secondItem )
1776 {
1777 SCH_SHEET* firstSheet = static_cast<SCH_SHEET*>( firstItem );
1778 SCH_SHEET* secondSheet = static_cast<SCH_SHEET*>( secondItem );
1779 return StrNumCmp( firstSheet->GetName(), secondSheet->GetName(), false ) < 0;
1780 });
1781
1782
1783 for( SCH_ITEM* item : sortedLoadedItems )
1784 {
1785 loadedItems.push_back( item );
1786
1787 if( item->Type() == SCH_SHEET_T )
1788 {
1789 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1790 wxFileName srcFn = sheet->GetFileName();
1791
1792 if( srcFn.IsRelative() )
1793 srcFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
1794
1795 SCH_SHEET_LIST sheetHierarchy( sheet );
1796
1797 if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
1798 {
1799 auto msg = wxString::Format( _( "The pasted sheet '%s'\n"
1800 "was dropped because the destination already has "
1801 "the sheet or one of its subsheets as a parent." ),
1802 sheet->GetFileName() );
1803 DisplayError( m_frame, msg );
1804 loadedItems.pop_back();
1805 }
1806 }
1807 }
1808
1809 // Remove the references from our temporary screen to prevent freeing on the DTOR
1810 tempScreen->Clear( false );
1811
1812 for( EDA_ITEM* item : loadedItems )
1813 {
1814 KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
1815
1816 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
1817
1818 wxCHECK2( schItem, continue );
1819
1820 if( schItem->IsConnectable() )
1821 schItem->SetConnectivityDirty();
1822
1823 if( item->Type() == SCH_SYMBOL_T )
1824 {
1825 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1826
1827 // The library symbol gets set from the cached library symbols in the current
1828 // schematic not the symbol libraries. The cached library symbol may have
1829 // changed from the original library symbol which would cause the copy to
1830 // be incorrect.
1831 SCH_SCREEN* currentScreen = m_frame->GetScreen();
1832
1833 wxCHECK2( currentScreen, continue );
1834
1835 auto it = currentScreen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
1836 auto end = currentScreen->GetLibSymbols().end();
1837
1838 if( it == end )
1839 {
1840 // If can't find library definition in the design, use the pasted library
1841 it = tempScreen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
1842 end = tempScreen->GetLibSymbols().end();
1843 }
1844
1845 LIB_SYMBOL* libSymbol = nullptr;
1846
1847 if( it != end )
1848 {
1849 libSymbol = new LIB_SYMBOL( *it->second );
1850 symbol->SetLibSymbol( libSymbol );
1851 }
1852
1853 // If the symbol is already in the schematic we have to always keep the annotations. The exception
1854 // is if the user has chosen to remove them.
1855 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1856 {
1857 if( !existingRefsSet.contains( instance.m_Reference ) )
1858 {
1859 forceKeepAnnotations = !forceRemoveAnnotations;
1860 break;
1861 }
1862 }
1863
1864 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
1865 updatePastedSymbol( symbol, sheetPath, clipPath, forceKeepAnnotations );
1866
1867 // Most modes will need new KIIDs for the symbol and its pins. However, if we are pasting
1868 // unique annotations, we need to check if the symbol is not already in the hierarchy. If we
1869 // don't already have a copy of the symbol, we just keep the existing KIID data as it is likely
1870 // the same symbol being moved around the schematic.
1871 bool needsNewKiid = ( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS );
1872
1873 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1874 {
1875 if( existingRefsSet.contains( instance.m_Reference ) )
1876 {
1877 needsNewKiid = true;
1878 break;
1879 }
1880 }
1881
1882 if( needsNewKiid )
1883 {
1884 // Assign a new KIID
1885 const_cast<KIID&>( item->m_Uuid ) = KIID();
1886
1887 // Make sure pins get a new UUID
1888 for( SCH_PIN* pin : symbol->GetPins() )
1889 {
1890 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1891 pin->SetConnectivityDirty();
1892 }
1893
1894 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
1895 {
1896 // Ignore symbols from a non-existant library.
1897 if( libSymbol )
1898 {
1899 SCH_REFERENCE schReference( symbol, sheetPath );
1900 schReference.SetSheetNumber( sheetPath.GetPageNumberAsInt() );
1901 pastedSymbols[sheetPath].AddItem( schReference );
1902 }
1903 }
1904 }
1905 }
1906 else if( item->Type() == SCH_SHEET_T )
1907 {
1908 SCH_SHEET* sheet = (SCH_SHEET*) item;
1909 SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME );
1910 wxString baseName = nameField->GetText();
1911 wxString candidateName = baseName;
1912 wxString number;
1913
1914 while( !baseName.IsEmpty() && wxIsdigit( baseName.Last() ) )
1915 {
1916 number = baseName.Last() + number;
1917 baseName.RemoveLast();
1918 }
1919
1920 // Update hierarchy to include any other sheets we already added, avoiding
1921 // duplicate sheet names
1922 hierarchy = m_frame->Schematic().Hierarchy();
1923
1924 int uniquifier = std::max( 0, wxAtoi( number ) ) + 1;
1925
1926 while( existingSheetNames.count( candidateName ) )
1927 candidateName = wxString::Format( wxT( "%s%d" ), baseName, uniquifier++ );
1928
1929 nameField->SetText( candidateName );
1930 existingSheetNames.emplace( candidateName );
1931
1932 wxFileName fn = sheet->GetFileName();
1933 SCH_SCREEN* existingScreen = nullptr;
1934
1935 sheet->SetParent( pasteRoot.Last() );
1936 sheet->SetScreen( nullptr );
1937
1938 if( !fn.IsAbsolute() )
1939 {
1940 wxFileName currentSheetFileName = pasteRoot.LastScreen()->GetFileName();
1941 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, currentSheetFileName.GetPath() );
1942 }
1943
1944 // Try to find the screen for the pasted sheet by several means
1945 if( !m_frame->Schematic().Root().SearchHierarchy( fn.GetFullPath( wxPATH_UNIX ), &existingScreen ) )
1946 {
1947 if( loadedScreens.count( sheet->GetFileName() ) > 0 )
1948 existingScreen = loadedScreens.at( sheet->GetFileName() );
1949 else
1950 searchSupplementaryClipboard( sheet->GetFileName(), &existingScreen );
1951 }
1952
1953 if( existingScreen )
1954 {
1955 sheet->SetScreen( existingScreen );
1956 }
1957 else
1958 {
1959 if( !m_frame->LoadSheetFromFile( sheet, &pasteRoot, fn.GetFullPath() ) )
1960 m_frame->InitSheet( sheet, sheet->GetFileName() );
1961 }
1962
1963 // Save the symbol instances in case the user chooses to keep the existing
1964 // symbol annotation.
1966 sheetsPasted = true;
1967
1968 // Push it to the clipboard path while it still has its old KIID
1969 clipPath.push_back( sheet->m_Uuid );
1970
1971 // Assign a new KIID to the pasted sheet
1972 const_cast<KIID&>( sheet->m_Uuid ) = KIID();
1973
1974 // Make sure pins get a new UUID
1975 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1976 {
1977 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1978 pin->SetConnectivityDirty();
1979 }
1980
1981 // Once we have our new KIID we can update all pasted instances. This will either
1982 // reset the annotations or copy "kept" annotations from the supplementary clipboard.
1983 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
1984 {
1985 SCH_SHEET_PATH subPath = updatePastedSheet( sheet, sheetPath, clipPath,
1986 ( forceKeepAnnotations && annotateAutomatic ),
1987 &pastedSheets[sheetPath], pastedSymbols );
1988 }
1989 }
1990 else
1991 {
1992 SCH_ITEM* srcItem = dynamic_cast<SCH_ITEM*>( itemMap[ item->m_Uuid ] );
1993 SCH_ITEM* destItem = dynamic_cast<SCH_ITEM*>( item );
1994
1995 // Everything gets a new KIID
1996 const_cast<KIID&>( item->m_Uuid ) = KIID();
1997
1998 if( srcItem && destItem )
1999 {
2000 destItem->SetConnectivityDirty( true );
2001 destItem->SetLastResolvedState( srcItem );
2002 }
2003 }
2004
2005 // Lines need both ends selected for a move after paste so the whole line moves.
2006 if( item->Type() == SCH_LINE_T )
2007 item->SetFlags( STARTPOINT | ENDPOINT );
2008
2009 item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
2010
2011 if( !m_frame->GetScreen()->CheckIfOnDrawList( (SCH_ITEM*) item ) ) // don't want a loop!
2012 m_frame->AddToScreen( item, m_frame->GetScreen() );
2013
2014 commit.Added( (SCH_ITEM*) item, m_frame->GetScreen() );
2015
2016 // Start out hidden so the pasted items aren't "ghosted" in their original location
2017 // before being moved to the current location.
2018 getView()->Hide( item, true );
2019 }
2020
2021 if( sheetsPasted )
2022 {
2023 // The full schematic hierarchy need to be update before assigning new annotation and
2024 // page numbers.
2025 m_frame->Schematic().RefreshHierarchy();
2026
2027 // Update page numbers: Find next free numeric page number
2028 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2029 {
2030 for( SCH_SHEET_PATH& pastedSheet : pastedSheets[sheetPath] )
2031 {
2032 int page = 1;
2033 wxString pageNum = wxString::Format( "%d", page );
2034
2035 while( hierarchy.PageNumberExists( pageNum ) )
2036 pageNum = wxString::Format( "%d", ++page );
2037
2038 SCH_SHEET_INSTANCE sheetInstance;
2039
2040 sheetInstance.m_Path = pastedSheet.Path();
2041
2042 // Don't include the actual sheet in the instance path.
2043 sheetInstance.m_Path.pop_back();
2044 sheetInstance.m_PageNumber = pageNum;
2045 sheetInstance.m_ProjectName = m_frame->Prj().GetProjectName();
2046
2047 SCH_SHEET* sheet = pastedSheet.Last();
2048
2049 wxCHECK2( sheet, continue );
2050
2051 sheet->AddInstance( sheetInstance );
2052 hierarchy.push_back( pastedSheet );
2053
2054 // Remove all pasted sheet instance data that is not part of the current project.
2055 std::vector<KIID_PATH> instancesToRemove;
2056
2057 for( const SCH_SHEET_INSTANCE& instance : sheet->GetInstances() )
2058 {
2059 if( !hierarchy.HasPath( instance.m_Path ) )
2060 instancesToRemove.push_back( instance.m_Path );
2061 }
2062
2063 for( const KIID_PATH& instancePath : instancesToRemove )
2064 sheet->RemoveInstance( instancePath );
2065 }
2066 }
2067
2068 m_frame->SetSheetNumberAndCount();
2069
2070 // Get a version with correct sheet numbers since we've pasted sheets,
2071 // we'll need this when annotating next
2072 hierarchy = m_frame->Schematic().Hierarchy();
2073 }
2074
2075 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> annotatedSymbols;
2076
2077 // Update the list of symbol instances that satisfy the annotation criteria.
2078 for( const SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2079 {
2080 for( size_t i = 0; i < pastedSymbols[sheetPath].GetCount(); i++ )
2081 {
2082 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[sheetPath][i].AlwaysAnnotate() )
2083 annotatedSymbols[sheetPath].AddItem( pastedSymbols[sheetPath][i] );
2084 }
2085
2086 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[sheetPath] )
2087 {
2088 for( size_t i = 0; i < pastedSymbols[pastedSheetPath].GetCount(); i++ )
2089 {
2090 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[pastedSheetPath][i].AlwaysAnnotate() )
2091 annotatedSymbols[pastedSheetPath].AddItem( pastedSymbols[pastedSheetPath][i] );
2092 }
2093 }
2094 }
2095
2096 if( !annotatedSymbols.empty() )
2097 {
2098 ANNOTATE_ORDER_T annotateOrder = static_cast<ANNOTATE_ORDER_T>( schematicSettings.m_AnnotateSortOrder );
2099 ANNOTATE_ALGO_T annotateAlgo = static_cast<ANNOTATE_ALGO_T>( schematicSettings.m_AnnotateMethod );
2100
2101 for( SCH_SHEET_PATH& path : sheetPathsForScreen )
2102 {
2103 annotatedSymbols[path].SortByReferenceOnly();
2104 annotatedSymbols[path].SetRefDesTracker( schematicSettings.m_refDesTracker );
2105
2106 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2107 {
2108 annotatedSymbols[path].ReannotateDuplicates( existingRefs, annotateAlgo );
2109 }
2110 else
2111 {
2112 annotatedSymbols[path].ReannotateByOptions( annotateOrder, annotateAlgo, annotateStartNum,
2113 existingRefs, false, &hierarchy );
2114 }
2115
2116 annotatedSymbols[path].UpdateAnnotation();
2117
2118 // Update existing refs for next iteration
2119 for( size_t i = 0; i < annotatedSymbols[path].GetCount(); i++ )
2120 existingRefs.AddItem( annotatedSymbols[path][i] );
2121
2122 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[path] )
2123 {
2124 annotatedSymbols[pastedSheetPath].SortByReferenceOnly();
2125 annotatedSymbols[pastedSheetPath].SetRefDesTracker( schematicSettings.m_refDesTracker );
2126
2127 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2128 {
2129 annotatedSymbols[pastedSheetPath].ReannotateDuplicates( existingRefs, annotateAlgo );
2130 }
2131 else
2132 {
2133 annotatedSymbols[pastedSheetPath].ReannotateByOptions( annotateOrder, annotateAlgo,
2134 annotateStartNum, existingRefs,
2135 false, &hierarchy );
2136 }
2137
2138 annotatedSymbols[pastedSheetPath].UpdateAnnotation();
2139
2140 // Update existing refs for next iteration
2141 for( size_t i = 0; i < annotatedSymbols[pastedSheetPath].GetCount(); i++ )
2142 existingRefs.AddItem( annotatedSymbols[pastedSheetPath][i] );
2143 }
2144 }
2145 }
2146
2147 m_frame->GetCurrentSheet().UpdateAllScreenReferences();
2148
2149 // The copy operation creates instance paths that are not valid for the current project or
2150 // saved as part of another project. Prune them now so they do not accumulate in the saved
2151 // schematic file.
2153
2154 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
2155 SCH_SCREENS allScreens( m_frame->Schematic().Root() );
2156
2157 allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(), sheets );
2158 allScreens.PruneOrphanedSheetInstances( m_frame->Prj().GetProjectName(), sheets );
2159
2160 // Now clear the previous selection, select the pasted items, and fire up the "move" tool.
2161 m_toolMgr->RunAction( ACTIONS::selectionClear );
2162
2163 // If the item has a parent group, it will be part of the loadedItems, and will handle
2164 // the move action. Iterate backwards to avoid invalidating the iterator.
2165 for( int i = loadedItems.size() - 1; i >= 0; i-- )
2166 {
2167 EDA_ITEM* item = loadedItems[i];
2168
2169 if( item->GetParentGroup() )
2170 {
2171 loadedItems.erase( loadedItems.begin() + i );
2172 // These were hidden before because they would be added to the move preview,
2173 // but now they need to be shown as a preview so they appear to move when
2174 // the group moves.
2175 getView()->SetVisible( item );
2176 getView()->AddToPreview( item, false );
2177 }
2178 }
2179
2180 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &loadedItems );
2181
2182 SCH_SELECTION& selection = selTool->GetSelection();
2183
2184 if( !selection.Empty() )
2185 {
2186 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2187 {
2188 int closest_dist = INT_MAX;
2189
2190 auto processPt =
2191 [&]( const VECTOR2I& pt )
2192 {
2193 int dist = ( eventPos - pt ).EuclideanNorm();
2194
2195 if( dist < closest_dist )
2196 {
2197 selection.SetReferencePoint( pt );
2198 closest_dist = dist;
2199 }
2200 };
2201
2202 // Prefer connection points (which should remain on grid)
2203 for( EDA_ITEM* item : selection.Items() )
2204 {
2205 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
2206 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
2207
2208 if( sch_item && sch_item->IsConnectable() )
2209 {
2210 for( const VECTOR2I& pt : sch_item->GetConnectionPoints() )
2211 processPt( pt );
2212 }
2213 else if( pin )
2214 {
2215 processPt( pin->GetPosition() );
2216 }
2217
2218 // Symbols need to have their center point added since often users are trying to
2219 // move parts from their center.
2220 if( dynamic_cast<SCH_SYMBOL*>( item ) )
2221 processPt( item->GetPosition() );
2222 }
2223
2224 // Only process other points if we didn't find any connection points
2225 if( closest_dist == INT_MAX )
2226 {
2227 for( EDA_ITEM* item : selection.Items() )
2228 {
2229 switch( item->Type() )
2230 {
2231 case SCH_LINE_T:
2232 processPt( static_cast<SCH_LINE*>( item )->GetStartPoint() );
2233 processPt( static_cast<SCH_LINE*>( item )->GetEndPoint() );
2234 break;
2235
2236 case SCH_SHAPE_T:
2237 {
2238 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
2239
2240 switch( shape->GetShape() )
2241 {
2242 case SHAPE_T::RECTANGLE:
2243 for( const VECTOR2I& pt : shape->GetRectCorners() )
2244 processPt( pt );
2245
2246 break;
2247
2248 case SHAPE_T::CIRCLE:
2249 processPt( shape->GetCenter() );
2250 break;
2251
2252 case SHAPE_T::POLY:
2253 for( int ii = 0; ii < shape->GetPolyShape().TotalVertices(); ++ii )
2254 processPt( shape->GetPolyShape().CVertex( ii ) );
2255
2256 break;
2257
2258 default:
2259 processPt( shape->GetStart() );
2260 processPt( shape->GetEnd() );
2261 break;
2262 }
2263
2264 break;
2265 }
2266
2267 default:
2268 processPt( item->GetPosition() );
2269 break;
2270 }
2271 }
2272 }
2273
2274 selection.SetIsHover( m_duplicateIsHoverSelection );
2275 }
2276 // We want to the first non-group item in the selection to be the reference point.
2277 else if( selection.GetTopLeftItem()->Type() == SCH_GROUP_T )
2278 {
2279 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection.GetTopLeftItem() );
2280
2281 bool found = false;
2282 SCH_ITEM* item = nullptr;
2283
2284 group->RunOnChildren(
2285 [&]( SCH_ITEM* schItem )
2286 {
2287 if( !found && schItem->Type() != SCH_GROUP_T )
2288 {
2289 item = schItem;
2290 found = true;
2291 }
2292 },
2294
2295 if( found )
2296 selection.SetReferencePoint( item->GetPosition() );
2297 else
2298 selection.SetReferencePoint( group->GetPosition() );
2299 }
2300 else
2301 {
2302 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetTopLeftItem() );
2303
2304 selection.SetReferencePoint( item->GetPosition() );
2305 }
2306
2307 if( m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit ) )
2308 {
2309 // Pushing the commit will update the connectivity.
2310 commit.Push( _( "Paste" ) );
2311
2312 if( sheetsPasted )
2313 {
2314 m_frame->UpdateHierarchyNavigator();
2315 // UpdateHierarchyNavigator() will call RefreshNetNavigator()
2316 }
2317 else
2318 {
2319 m_frame->RefreshNetNavigator();
2320 }
2321 }
2322 else
2323 {
2324 commit.Revert();
2325 }
2326
2327 getView()->ClearPreview();
2328 }
2329
2330 return 0;
2331}
2332
2333
2335{
2336 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2337 SCH_SELECTION& selection = selTool->RequestSelection( { SCH_SYMBOL_T } );
2338 SCH_SYMBOL* symbol = nullptr;
2339 SYMBOL_EDIT_FRAME* symbolEditor;
2340
2341 if( selection.GetSize() >= 1 )
2342 symbol = (SCH_SYMBOL*) selection.Front();
2343
2344 if( selection.IsHover() )
2345 m_toolMgr->RunAction( ACTIONS::selectionClear );
2346
2347 if( !symbol )
2348 {
2349 // Giant hack: by default we assign Edit Table to the same hotkey, so give the table
2350 // tool a chance to handle it if we can't.
2351 if( SCH_EDIT_TABLE_TOOL* tableTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>() )
2352 tableTool->EditTable( aEvent );
2353
2354 return 0;
2355 }
2356
2357 if( symbol->GetEditFlags() != 0 )
2358 return 0;
2359
2360 if( symbol->IsMissingLibSymbol() )
2361 {
2362 m_frame->ShowInfoBarError( _( "Symbols with broken library symbol links cannot be edited." ) );
2363 return 0;
2364 }
2365
2367 symbolEditor = (SYMBOL_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, false );
2368
2369 if( symbolEditor )
2370 {
2371 if( wxWindow* blocking_win = symbolEditor->Kiway().GetBlockingDialog() )
2372 blocking_win->Close( true );
2373
2374 if( aEvent.IsAction( &SCH_ACTIONS::editWithLibEdit ) )
2375 {
2376 symbolEditor->LoadSymbolFromSchematic( symbol );
2377 }
2379 {
2380 symbolEditor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
2381
2382 if( !symbolEditor->IsLibraryTreeShown() )
2383 symbolEditor->ToggleLibraryTree();
2384 }
2385 }
2386
2387 return 0;
2388}
2389
2390
2392{
2393 m_frame->OnAnnotate();
2394 return 0;
2395}
2396
2397
2399{
2401 dlg.m_FirstRefDes->SetValidator( wxTextValidator( wxFILTER_EMPTY ) );
2402
2403 dlg.SetInitialFocus( dlg.m_FirstRefDes );
2404
2405 if( dlg.ShowModal() == wxID_OK )
2406 {
2407 SCH_REFERENCE startRef;
2408 startRef.SetRef( dlg.m_FirstRefDes->GetValue() );
2409
2410 if( startRef.IsSplitNeeded() )
2411 startRef.Split();
2412 else
2413 return 0;
2414
2415 int startNum = atoi( startRef.GetRefNumber().utf8_string().c_str() );
2416
2417 SCH_COMMIT commit( m_frame );
2418 SCHEMATIC* schematic = m_frame->m_schematic;
2419 SCH_REFERENCE_LIST references;
2420
2421 if( dlg.m_AllSheets->GetValue() )
2422 schematic->Hierarchy().GetSymbols( references );
2423 else
2424 schematic->CurrentSheet().GetSymbols( references );
2425
2426 references.SplitReferences();
2427
2428 for( SCH_REFERENCE& ref : references )
2429 {
2430 if( ref.GetRef() == startRef.GetRef() )
2431 {
2432 int num = atoi( ref.GetRefNumber().utf8_string().c_str() );
2433
2434 if( num >= startNum )
2435 {
2436 const SCH_SHEET_PATH& sheet = ref.GetSheetPath();
2437 wxString fullRef = ref.GetRef();
2438
2439 num += dlg.m_Increment->GetValue();
2440 fullRef << num;
2441
2442 commit.Modify( ref.GetSymbol(), sheet.LastScreen(), RECURSE_MODE::NO_RECURSE );
2443 ref.GetSymbol()->SetRef( &sheet, From_UTF8( fullRef.c_str() ) );
2444 }
2445 }
2446 }
2447
2448 if( !commit.Empty() )
2449 commit.Push( _( "Increment Annotations" ) );
2450 }
2451
2452 return 0;
2453}
2454
2455
2457{
2458 m_frame->OnOpenCvpcb();
2459 return 0;
2460}
2461
2462
2464{
2465 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
2466
2467 wxCHECK( dlg, 0 );
2468
2469 // Needed at least on Windows. Raise() is not enough
2470 dlg->Show( true );
2471
2472 // Bring it to the top if already open. Dual monitor users need this.
2473 dlg->Raise();
2474
2475 dlg->ShowEditTab();
2476
2477 return 0;
2478}
2479
2480
2482{
2484 m_frame->HardRedraw();
2485
2486 return 0;
2487}
2488
2489
2491{
2492 m_frame->OnOpenPcbnew();
2493 return 0;
2494}
2495
2496
2498{
2499 m_frame->OnUpdatePCB();
2500 return 0;
2501}
2502
2503
2505{
2507 dlg.ShowModal();
2508 return 0;
2509}
2510
2511
2513{
2515
2516 // If a plugin is removed or added, rebuild and reopen the new dialog
2517 while( result == NET_PLUGIN_CHANGE )
2519
2520 return 0;
2521}
2522
2523
2525{
2526 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
2527
2528 wxCHECK( dlg, 0 );
2529
2530 // Needed at least on Windows. Raise() is not enough
2531 dlg->Show( true );
2532
2533 // Bring it to the top if already open. Dual monitor users need this.
2534 dlg->Raise();
2535
2536 dlg->ShowExportTab();
2537
2538 return 0;
2539}
2540
2541
2543{
2545 return 0;
2546}
2547
2548
2550{
2551 m_frame->RecalculateConnections( nullptr, LOCAL_CLEANUP );
2552 m_frame->DrawCurrentSheetToClipboard();
2553 return 0;
2554}
2555
2556
2558{
2560 return 0;
2561}
2562
2563
2569
2570
2576
2577
2583
2584
2590
2591
2593{
2594 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2596
2598 m_frame->GetCanvas()->Refresh();
2599
2600 return 0;
2601}
2602
2603
2605{
2606 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2608
2610 m_frame->GetCanvas()->Refresh();
2611
2612 return 0;
2613}
2614
2615
2617{
2618 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2620
2622 m_frame->GetCanvas()->Refresh();
2623
2624 return 0;
2625}
2626
2627
2629{
2630 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2632
2634 m_frame->GetCanvas()->Refresh();
2635
2636 return 0;
2637}
2638
2639
2641{
2642 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2644
2646 m_frame->GetCanvas()->Refresh();
2647
2648 return 0;
2649}
2650
2651
2653{
2654 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2656
2657 m_frame->GetCanvas()->Refresh();
2658
2659 return 0;
2660}
2661
2662
2664{
2665 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2667
2668 m_frame->GetCanvas()->GetView()->UpdateAllItemsConditionally(
2669 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
2670 {
2671 int flags = 0;
2672
2673 auto invalidateTextVars =
2674 [&flags]( EDA_TEXT* text )
2675 {
2676 if( text->HasTextVars() )
2677 {
2678 text->ClearRenderCache();
2679 text->ClearBoundingBoxCache();
2681 }
2682 };
2683
2684 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
2685 {
2686 item->RunOnChildren(
2687 [&invalidateTextVars]( SCH_ITEM* aChild )
2688 {
2689 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
2690 invalidateTextVars( text );
2691 },
2693
2694 if( item->GetExcludedFromSim() )
2696 }
2697
2698 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
2699 invalidateTextVars( text );
2700
2701 return flags;
2702 } );
2703
2704 m_frame->GetCanvas()->Refresh();
2705
2706 return 0;
2707}
2708
2709
2711{
2712 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2714
2716 m_frame->RefreshOperatingPointDisplay();
2717 m_frame->GetCanvas()->Refresh();
2718
2719 return 0;
2720}
2721
2722
2724{
2725 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2727
2729 m_frame->RefreshOperatingPointDisplay();
2730 m_frame->GetCanvas()->Refresh();
2731
2732 return 0;
2733}
2734
2735
2737{
2738 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2740
2741 m_frame->GetRenderSettings()->m_ShowPinAltIcons = cfg->m_Appearance.show_pin_alt_icons;
2742
2744 m_frame->GetCanvas()->Refresh();
2745
2746 return 0;
2747}
2748
2749
2751{
2752 m_frame->eeconfig()->m_Drawing.line_mode = aEvent.Parameter<LINE_MODE>();
2753 m_toolMgr->PostAction( ACTIONS::refreshPreview );
2754 return 0;
2755}
2756
2757
2759{
2760 m_frame->eeconfig()->m_Drawing.line_mode++;
2761 m_frame->eeconfig()->m_Drawing.line_mode %= LINE_MODE::LINE_MODE_COUNT;
2762 m_toolMgr->PostAction( ACTIONS::refreshPreview );
2763 return 0;
2764}
2765
2766
2768{
2769 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
2771 return 0;
2772}
2773
2774
2776{
2777
2778 m_frame->ScriptingConsoleEnableDisable();
2779 return 0;
2780}
2781
2782
2784{
2785#ifdef KICAD_IPC_API
2786 if( Pgm().GetCommonSettings()->m_Api.enable_server )
2787 Pgm().GetPluginManager().ReloadPlugins();
2788#endif
2789 return 0;
2790}
2791
2792
2794{
2795 int errors = 0;
2796 wxString details;
2797 bool quiet = aEvent.Parameter<bool>();
2798
2799 // Repair duplicate IDs.
2800 std::map<KIID, EDA_ITEM*> ids;
2801 int duplicates = 0;
2802
2803 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
2804
2805 auto processItem =
2806 [&]( EDA_ITEM* aItem )
2807 {
2808 auto it = ids.find( aItem->m_Uuid );
2809
2810 if( it != ids.end() && it->second != aItem )
2811 {
2812 duplicates++;
2813 const_cast<KIID&>( aItem->m_Uuid ) = KIID();
2814 }
2815
2816 ids[ aItem->m_Uuid ] = aItem;
2817 };
2818
2819 // Symbol IDs are the most important, so give them the first crack at "claiming" a
2820 // particular KIID.
2821
2822 for( const SCH_SHEET_PATH& sheet : sheets )
2823 {
2824 SCH_SCREEN* screen = sheet.LastScreen();
2825
2826 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2827 {
2828 processItem( item );
2829
2830 for( SCH_PIN* pin : static_cast<SCH_SYMBOL*>( item )->GetPins( &sheet ) )
2831 processItem( pin );
2832 }
2833 }
2834
2835 for( const SCH_SHEET_PATH& sheet : sheets )
2836 {
2837 SCH_SCREEN* screen = sheet.LastScreen();
2838
2839 for( SCH_ITEM* item : screen->Items() )
2840 {
2841 processItem( item );
2842
2843 if( item->Type() != SCH_GROUP_T )
2844 {
2845 item->RunOnChildren(
2846 [&]( SCH_ITEM* aChild )
2847 {
2848 processItem( item );
2849 },
2851 }
2852 }
2853 }
2854
2855 /*******************************
2856 * Your test here
2857 */
2858
2859 /*******************************
2860 * Inform the user
2861 */
2862
2863 if( duplicates )
2864 {
2865 errors += duplicates;
2866 details += wxString::Format( _( "%d duplicate IDs replaced.\n" ), duplicates );
2867
2868 // Rehash sheetpaths as we may have changed their uuids.
2869 m_frame->Schematic().RefreshHierarchy();
2870 }
2871
2872 if( errors )
2873 {
2874 m_frame->OnModify();
2875
2876 wxString msg = wxString::Format( _( "%d potential problems repaired." ), errors );
2877
2878 if( !quiet )
2879 DisplayInfoMessage( m_frame, msg, details );
2880 }
2881 else if( !quiet )
2882 {
2883 DisplayInfoMessage( m_frame, _( "No errors found." ) );
2884 }
2885
2886 return 0;
2887}
2888
2889
2891{
2892 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
2893 return 0;
2894
2895 GRID_SETTINGS& gridSettings = m_toolMgr->GetSettings()->m_Window.grid;
2896 int currentIdx = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx;
2897
2898 wxArrayString gridsLabels;
2899
2900 for( const GRID& grid : gridSettings.grids )
2901 gridsLabels.Add( grid.UserUnitsMessageText( m_frame ) );
2902
2903 if( !m_frame->GetHotkeyPopup() )
2904 m_frame->CreateHotkeyPopup();
2905
2906 HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
2907
2908 if( popup )
2909 popup->Popup( _( "Grid" ), gridsLabels, currentIdx );
2910
2911 return 0;
2912}
2913
2914
2916{
2917 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
2918
2919 if( !editFrame )
2920 return 1;
2921
2922 // Need to have a group selected and it needs to have a linked design block
2923 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2924 SCH_SELECTION selection = selTool->GetSelection();
2925
2926 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
2927 return 1;
2928
2929 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
2930
2931 if( !group->HasDesignBlockLink() )
2932 return 1;
2933
2934 // Get the associated design block
2935 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
2936 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
2937 true, true ) );
2938
2939 if( !designBlock )
2940 {
2941 wxString msg;
2942 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
2943 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
2944 return 1;
2945 }
2946
2947 if( designBlock->GetSchematicFile().IsEmpty() )
2948 {
2949 wxString msg;
2950 msg.Printf( _( "Design block %s does not have a schematic file." ),
2951 group->GetDesignBlockLibId().GetUniStringLibId() );
2952 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
2953 return 1;
2954 }
2955
2956 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
2957
2958 return m_toolMgr->RunAction( SCH_ACTIONS::placeDesignBlock, designBlock.release() );
2959}
2960
2961
2963{
2964 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
2965
2966 if( !editFrame )
2967 return 1;
2968
2969 // Need to have a group selected and it needs to have a linked design block
2970 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2971 SCH_SELECTION selection = selTool->GetSelection();
2972
2973 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
2974 return 1;
2975
2976 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
2977
2978 if( !group->HasDesignBlockLink() )
2979 return 1;
2980
2981 // Get the associated design block
2982 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
2983 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
2984 true, true ) );
2985
2986 if( !designBlock )
2987 {
2988 wxString msg;
2989 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
2990 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
2991 return 1;
2992 }
2993
2994 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
2995
2996 return m_toolMgr->RunAction( SCH_ACTIONS::saveSelectionToDesignBlock ) ? 1 : 0;
2997}
2998
2999
3001{
3002 Go( &SCH_EDITOR_CONTROL::New, ACTIONS::doNew.MakeEvent() );
3003 Go( &SCH_EDITOR_CONTROL::Open, ACTIONS::open.MakeEvent() );
3004 Go( &SCH_EDITOR_CONTROL::Save, ACTIONS::save.MakeEvent() );
3011 Go( &SCH_EDITOR_CONTROL::Plot, ACTIONS::plot.MakeEvent() );
3012 Go( &SCH_EDITOR_CONTROL::Quit, ACTIONS::quit.MakeEvent() );
3013
3016
3022
3025
3031
3033
3034 Go( &SCH_EDITOR_CONTROL::Undo, ACTIONS::undo.MakeEvent() );
3035 Go( &SCH_EDITOR_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
3036 Go( &SCH_EDITOR_CONTROL::Cut, ACTIONS::cut.MakeEvent() );
3037 Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() );
3042
3044
3060
3067
3083
3085
3087
3089
3092}
const char * name
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
static TOOL_ACTION updatePcbFromSchematic
Definition actions.h:263
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:295
static TOOL_ACTION pickerTool
Definition actions.h:252
static TOOL_ACTION showSymbolEditor
Definition actions.h:259
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:115
static TOOL_ACTION undo
Definition actions.h:75
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition actions.h:213
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:264
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:223
static TOOL_ACTION print
Definition actions.h:64
static TOOL_ACTION showProperties
Definition actions.h:265
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:158
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:231
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:337
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:79
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:97
virtual bool IsVisible() const
Definition eda_text.h:186
PANEL_ANNOTATE m_AnnotatePanel
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
static const TOOL_EVENT ClearedEvent
Definition actions.h:348
static const TOOL_EVENT GridChangedByKeyEvent
Definition actions.h:366
static const TOOL_EVENT SelectedEvent
Definition actions.h:346
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:353
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:345
static const TOOL_EVENT UnselectedEvent
Definition actions.h:347
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:660
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:85
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:154
bool IsPower() const override
wxString GetName() const override
Definition lib_symbol.h:148
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
const wxString & GetNickName() const
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
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_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
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:140
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:171
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 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 toggleHiddenFields
static TOOL_ACTION saveCurrSheetCopyAs
Definition sch_actions.h:43
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 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 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 EditSymbolFields(const TOOL_EVENT &aEvent)
int GenerateBOMLegacy(const TOOL_EVENT &aEvent)
int HighlightNetCursor(const TOOL_EVENT &aEvent)
int CopyAsText(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 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 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)
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:493
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:223
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:217
virtual void SetLastResolvedState(const SCH_ITEM *aItem)
Definition sch_item.h:585
int GetBodyStyle() const
Definition sch_item.h:244
int GetUnit() const
Definition sch_item.h:238
void SetConnectivityDirty(bool aDirty=true)
Definition sch_item.h:556
bool IsConnectivityDirty() const
Definition sch_item.h:554
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:323
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:508
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:758
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 SYMB...
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:488
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:321
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:187
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:430
Schematic symbol object.
Definition sch_symbol.h:75
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:134
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:164
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:183
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
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
int FindModelPinIndex(const std::string &aSymbolPinNumber)
const SPICE_GENERATOR & SpiceGenerator() const
Definition sim_model.h:431
virtual std::vector< std::string > CurrentNames(const SPICE_ITEM &aItem) const
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:449
const std::string & GetString()
Definition richio.h:472
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:253
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
Class to handle modifications to the symbol libraries.
SYMBOL_LIB_TABLE_ROW * GetLibrary(const wxString &aLibrary) const
Find a single library within the (aggregate) library table.
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_IO object i...
const wxString GetType() const override
Return the type of symbol library table represented by this row.
static SYMBOL_LIB_TABLE & GetGlobalLibTable()
static const wxString GetSymbolLibTableFileName()
static wxString GetGlobalTableFileName()
Fetch the global symbol library table file name.
SYMBOL_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an SYMBOL_LIB_TABLE_ROW if aNickName is found in this table or in any chained fallBack table f...
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:429
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:251
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:222
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:194
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:169
This file is part of the common library.
@ VOLTAGE_PROBE
Definition cursors.h:58
@ CURRENT_PROBE
Definition cursors.h:60
@ BULLSEYE
Definition cursors.h:56
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_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:478
@ LAYER_ERC_ERR
Definition layer_ids.h:479
@ LAYER_OP_CURRENTS
Definition layer_ids.h:500
@ LAYER_OP_VOLTAGES
Definition layer_ids.h:499
void Prettify(std::string &aSource, bool aCompactSave)
@ 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:913
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
Definition for symbol library class.
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".
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:175
@ SCH_LINE_T
Definition typeinfo.h:165
@ SCH_SYMBOL_T
Definition typeinfo.h:174
@ SCH_FIELD_T
Definition typeinfo.h:152
@ SCH_SHEET_T
Definition typeinfo.h:177
@ SCH_MARKER_T
Definition typeinfo.h:160
@ SCH_SHAPE_T
Definition typeinfo.h:151
@ SCH_PIN_T
Definition typeinfo.h:155
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