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