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 <core/base64.h>
29#include <algorithm>
30#include <chrono>
31#include <confirm.h>
32#include <connection_graph.h>
33#include <design_block.h>
43#include <project_rescue.h>
44#include <erc/erc.h>
45#include <invoke_sch_dialog.h>
46#include <locale_io.h>
47#include <string_utils.h>
48#include <kiway.h>
49#include <kiplatform/ui.h>
51#include <paths.h>
52#include <pgm_base.h>
55#include <project_sch.h>
57#include <richio.h>
59#include <sch_edit_frame.h>
61#include <sch_bitmap.h>
62#include <sch_group.h>
63#include <sch_line.h>
64#include <sch_junction.h>
65#include <sch_bus_entry.h>
66#include <sch_shape.h>
67#include <sch_painter.h>
68#include <sch_sheet_pin.h>
69#include <sch_table.h>
70#include <sch_tablecell.h>
71#include <sch_commit.h>
72#include <sim/simulator_frame.h>
74#include <symbol_viewer_frame.h>
75#include <tool/picker_tool.h>
76#include <tool/tool_manager.h>
77#include <tools/sch_actions.h>
78#include <tools/sch_selection.h>
84#include <view/view_controls.h>
86#include <wx_filename.h>
87#include <wx/filedlg.h>
88#include <wx/log.h>
89#include <wx/treectrl.h>
90#include <wx/msgdlg.h>
95#include <view/view.h>
96#include <zoom_defines.h>
98#include <gal/gal_print.h>
100#include <wx/ffile.h>
101#include <wx/filefn.h>
102#include <wx/mstream.h>
103#include <wx/clipbrd.h>
104#include <wx/imagpng.h>
105
106#ifdef KICAD_IPC_API
108#endif
109
110
116static const wxChar traceSchPaste[] = wxT( "KICAD_SCH_PASTE" );
117
118namespace
119{
120constexpr int clipboardMaxBitmapSize = 4096;
121constexpr double clipboardBboxInflation = 0.02; // Small padding around selection
122
123
124bool loadFileToBuffer( const wxString& aFileName, wxMemoryBuffer& aBuffer )
125{
126 wxFFile file( aFileName, wxS( "rb" ) );
127
128 if( !file.IsOpened() )
129 return false;
130
131 wxFileOffset size = file.Length();
132
133 if( size <= 0 )
134 return false;
135
136 void* data = aBuffer.GetWriteBuf( size );
137
138 if( file.Read( data, size ) != static_cast<size_t>( size ) )
139 {
140 aBuffer.UngetWriteBuf( 0 );
141 return false;
142 }
143
144 aBuffer.UngetWriteBuf( size );
145 return true;
146}
147
148
149std::vector<SCH_ITEM*> collectSelectionItems( const SCH_SELECTION& aSelection )
150{
151 std::vector<SCH_ITEM*> items;
152 items.reserve( aSelection.GetSize() );
153
154 for( EDA_ITEM* item : aSelection.GetItems() )
155 {
156 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item );
157
158 if( schItem )
159 items.push_back( schItem );
160 }
161
162 return items;
163}
164
165
166BOX2I expandedSelectionBox( const SCH_SELECTION& aSelection )
167{
168 BOX2I bbox = aSelection.GetBoundingBox();
169
170 if( bbox.GetWidth() > 0 && bbox.GetHeight() > 0 )
171 bbox.Inflate( bbox.GetWidth() * clipboardBboxInflation,
172 bbox.GetHeight() * clipboardBboxInflation );
173
174 return bbox;
175}
176
177
178bool generateHtmlFromPngData( const wxMemoryBuffer& aPngData, wxMemoryBuffer& aHtmlBuffer )
179{
180 if( aPngData.GetDataLen() == 0 )
181 return false;
182
183 std::vector<uint8_t> pngVec( static_cast<const uint8_t*>( aPngData.GetData() ),
184 static_cast<const uint8_t*>( aPngData.GetData() ) + aPngData.GetDataLen() );
185
186 std::vector<uint8_t> base64Data;
187 base64::encode( pngVec, base64Data );
188
189 std::string html = "<img src=\"data:image/png;base64,";
190 html.append( reinterpret_cast<const char*>( base64Data.data() ), base64Data.size() );
191 html.append( "\" />" );
192
193 aHtmlBuffer.SetDataLen( 0 );
194 aHtmlBuffer.AppendData( html.data(), html.size() );
195
196 return true;
197}
198
199
200bool plotSelectionToSvg( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection, const BOX2I& aBBox,
201 wxMemoryBuffer& aBuffer )
202{
203 SCH_RENDER_SETTINGS renderSettings( *aFrame->GetRenderSettings() );
204 renderSettings.LoadColors( aFrame->GetColorSettings() );
205 renderSettings.SetDefaultFont( aFrame->eeconfig()->m_Appearance.default_font );
206
207 std::unique_ptr<SVG_PLOTTER> plotter = std::make_unique<SVG_PLOTTER>();
208 plotter->SetRenderSettings( &renderSettings );
209
210 PAGE_INFO pageInfo = aFrame->GetScreen()->GetPageSettings();
211 pageInfo.SetWidthMils( schIUScale.IUToMils( aBBox.GetWidth() ) );
212 pageInfo.SetHeightMils( schIUScale.IUToMils( aBBox.GetHeight() ) );
213
214 plotter->SetPageSettings( pageInfo );
215 plotter->SetColorMode( true );
216
217 VECTOR2I plot_offset = aBBox.GetOrigin();
218 plotter->SetViewport( plot_offset, schIUScale.IU_PER_MILS / 10, 1.0, false );
219 plotter->SetCreator( wxT( "Eeschema-SVG" ) );
220
221 wxFileName tempFile( wxFileName::CreateTempFileName( wxS( "kicad_svg" ) ) );
222
223 if( !plotter->OpenFile( tempFile.GetFullPath() ) )
224 {
225 wxRemoveFile( tempFile.GetFullPath() );
226 return false;
227 }
228
229 LOCALE_IO toggle;
230 SCH_PLOT_OPTS plotOpts;
231 plotOpts.m_plotHopOver = aFrame->Schematic().Settings().m_HopOverScale > 0.0;
232
233 plotter->StartPlot( wxT( "1" ) );
234 aFrame->GetScreen()->Plot( plotter.get(), plotOpts, collectSelectionItems( aSelection ) );
235 plotter->EndPlot();
236 plotter.reset();
237
238 bool ok = loadFileToBuffer( tempFile.GetFullPath(), aBuffer );
239 wxRemoveFile( tempFile.GetFullPath() );
240 return ok;
241}
242
243
249wxImage renderSelectionToBitmap( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection, const BOX2I& aBBox,
250 int aWidth, int aHeight, bool aUseAlpha, bool aIncludeDrawingSheet )
251{
252 wxImage image( aWidth, aHeight, false );
253 image.SetAlpha();
254
255 double actualPPI_x = (double) aWidth / schIUScale.IUTomm( aBBox.GetWidth() ) * 25.4;
256 double actualPPI_y = (double) aHeight / schIUScale.IUTomm( aBBox.GetHeight() ) * 25.4;
257 double actualPPI = std::max( actualPPI_x, actualPPI_y );
258
259 VECTOR2D pageSizeIn( (double) aWidth / actualPPI, (double) aHeight / actualPPI );
260
261 {
264
265 std::unique_ptr<KIGFX::CAIRO_PRINT_GAL> gal = KIGFX::CAIRO_PRINT_GAL::Create( options, &image, actualPPI );
266
267 if( !gal )
268 return wxImage();
269
270 KIGFX::PRINT_CONTEXT* printCtx = gal->GetPrintCtx();
271 std::unique_ptr<KIGFX::SCH_PAINTER> painter = std::make_unique<KIGFX::SCH_PAINTER>( gal.get() );
272 std::unique_ptr<KIGFX::VIEW> view = std::make_unique<KIGFX::VIEW>();
273
274 painter->SetSchematic( &aFrame->Schematic() );
275 view->SetGAL( gal.get() );
276 view->SetPainter( painter.get() );
277 view->SetScaleLimits( ZOOM_MAX_LIMIT_EESCHEMA, ZOOM_MIN_LIMIT_EESCHEMA );
278 view->SetScale( 1.0 );
279
280 gal->SetWorldUnitLength( SCH_WORLD_UNIT );
281 gal->SetSheetSize( pageSizeIn );
282 gal->SetNativePaperSize( pageSizeIn, printCtx->HasNativeLandscapeRotation() );
283
284 // Clone items and add to view
285 std::vector<std::unique_ptr<SCH_ITEM>> clonedItems;
286 clonedItems.reserve( aSelection.GetSize() );
287
288 for( EDA_ITEM* item : aSelection.GetItems() )
289 {
290 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item );
291
292 if( !schItem )
293 continue;
294
295 SCH_ITEM* clone = static_cast<SCH_ITEM*>( schItem->Clone() );
296 clonedItems.emplace_back( clone );
297 view->Add( clone );
298 }
299
300 SCH_RENDER_SETTINGS* dstSettings = painter->GetSettings();
301 *dstSettings = *aFrame->GetRenderSettings();
302 dstSettings->m_ShowPinsElectricalType = false;
303 dstSettings->LoadColors( aFrame->GetColorSettings( false ) );
305 dstSettings->SetDefaultFont( aFrame->eeconfig()->m_Appearance.default_font );
306 dstSettings->SetIsPrinting( true );
307
308 if( aUseAlpha )
309 dstSettings->SetBackgroundColor( COLOR4D::CLEAR );
310
311 for( int i = 0; i < KIGFX::VIEW::VIEW_MAX_LAYERS; ++i )
312 {
313 view->SetLayerVisible( i, true );
314 view->SetLayerTarget( i, KIGFX::TARGET_NONCACHED );
315 }
316
317 view->SetLayerVisible( LAYER_DRAWINGSHEET, aIncludeDrawingSheet );
318
319 // Create and add drawing sheet proxy view item if requested
320 std::unique_ptr<DS_PROXY_VIEW_ITEM> drawingSheet;
321
322 if( aIncludeDrawingSheet )
323 {
324 SCH_SCREEN* screen = aFrame->GetScreen();
325
326 drawingSheet.reset( new DS_PROXY_VIEW_ITEM( schIUScale, &screen->GetPageSettings(),
327 &screen->Schematic()->Project(), &screen->GetTitleBlock(),
328 screen->Schematic()->GetProperties() ) );
329 drawingSheet->SetPageNumber( TO_UTF8( screen->GetPageNumber() ) );
330 drawingSheet->SetSheetCount( screen->GetPageCount() );
331 drawingSheet->SetFileName( TO_UTF8( screen->GetFileName() ) );
332 drawingSheet->SetColorLayer( LAYER_SCHEMATIC_DRAWINGSHEET );
333 drawingSheet->SetPageBorderColorLayer( LAYER_SCHEMATIC_PAGE_LIMITS );
334 drawingSheet->SetIsFirstPage( screen->GetVirtualPageNumber() == 1 );
335 drawingSheet->SetSheetName( TO_UTF8( aFrame->GetScreenDesc() ) );
336 drawingSheet->SetSheetPath( TO_UTF8( aFrame->GetFullScreenDesc() ) );
337
338 view->Add( drawingSheet.get() );
339 }
340
341 view->SetCenter( aBBox.Centre() );
342 view->UseDrawPriority( true );
343
344 gal->SetClearColor( dstSettings->GetBackgroundColor() );
345 gal->ClearScreen();
346
347 {
348 KIGFX::GAL_DRAWING_CONTEXT ctx( gal.get() );
349 view->Redraw();
350 }
351 }
352
353 return image;
354}
355
356
357wxImage renderSelectionToImageForClipboard( SCH_EDIT_FRAME* aFrame, const SCH_SELECTION& aSelection,
358 const BOX2I& aBBox, bool aUseAlpha, bool aIncludeDrawingSheet )
359{
360 const double c_targetPPI = 300;
361 const double c_targetPixelsPerMM = c_targetPPI / 25.4;
362
363 VECTOR2I size = aBBox.GetSize();
364
365 if( size.x <= 0 || size.y <= 0 )
366 return wxImage();
367
368 int bitmapWidth = KiROUND( schIUScale.IUTomm( size.x ) * c_targetPixelsPerMM );
369 int bitmapHeight = KiROUND( schIUScale.IUTomm( size.y ) * c_targetPixelsPerMM );
370
371 // Clamp to maximum size while preserving aspect ratio
372 if( bitmapWidth > clipboardMaxBitmapSize || bitmapHeight > clipboardMaxBitmapSize )
373 {
374 double scaleDown = (double) clipboardMaxBitmapSize / std::max( bitmapWidth, bitmapHeight );
375 bitmapWidth = KiROUND( bitmapWidth * scaleDown );
376 bitmapHeight = KiROUND( bitmapHeight * scaleDown );
377 }
378
379 if( bitmapWidth <= 0 || bitmapHeight <= 0 )
380 return wxImage();
381
382 wxImage result = renderSelectionToBitmap( aFrame, aSelection, aBBox, bitmapWidth, bitmapHeight, aUseAlpha,
383 aIncludeDrawingSheet );
384
385 return result;
386}
387} // namespace
388
389
391{
392 m_frame->NewProject();
393 return 0;
394}
395
396
398{
399 m_frame->LoadProject();
400 return 0;
401}
402
403
405{
406 m_frame->SaveProject();
407 return 0;
408}
409
410
412{
413 m_frame->SaveProject( true );
414 return 0;
415}
416
417
419{
420 SCH_SHEET* curr_sheet = m_frame->GetCurrentSheet().Last();
421 wxFileName curr_fn = curr_sheet->GetFileName();
422 wxFileDialog dlg( m_frame, _( "Schematic Files" ), curr_fn.GetPath(), curr_fn.GetFullName(),
423 FILEEXT::KiCadSchematicFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
424
426
427 if( dlg.ShowModal() == wxID_CANCEL )
428 return false;
429
430 wxString newFilename = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
431
432 m_frame->saveSchematicFile( curr_sheet, newFilename );
433 return 0;
434}
435
436
438{
439 SCHEMATIC& schematic = m_frame->Schematic();
440 SCH_SHEET& root = schematic.Root();
441
442 // Save original sheet path to restore if user cancels
443 SCH_SHEET_PATH originalSheet = m_frame->GetCurrentSheet();
444 bool wasOnSubsheet = ( m_frame->GetCurrentSheet().Last() != &root );
445
446 // Navigate to root sheet first (needed for proper reload), but don't repaint yet
447 if( wasOnSubsheet )
448 {
449 // Use the properly constructed root sheet path from the hierarchy
450 // (manually pushing root creates a path with empty KIID which causes assertions)
451 SCH_SHEET_PATH rootSheetPath = schematic.Hierarchy().at( 0 );
452
453 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet,
454 &rootSheetPath );
455 // Don't call wxSafeYield() here - avoid repainting the root sheet before the dialog
456 }
457
458 wxString msg;
459 msg.Printf( _( "Revert '%s' (and all sub-sheets) to last version saved?" ), schematic.GetFileName() );
460
461 if( !IsOK( m_frame, msg ) )
462 {
463 // User cancelled - navigate back to original sheet
464 if( wasOnSubsheet )
465 {
466 m_frame->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet,
467 &originalSheet );
468 wxSafeYield();
469 }
470
471 return false;
472 }
473
474 SCH_SCREENS screenList( schematic.Root() );
475
476 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
477 screen->SetContentModified( false ); // do not prompt the user for changes
478
479 m_frame->ReleaseFile();
480 m_frame->OpenProjectFiles( std::vector<wxString>( 1, schematic.GetFileName() ), KICTL_REVERT );
481
482 return 0;
483}
484
485
487{
488 m_frame->ShowSchematicSetupDialog();
489 return 0;
490}
491
492
494{
495 PICKED_ITEMS_LIST undoCmd;
497 ITEM_PICKER wrapper( m_frame->GetScreen(), undoItem, UNDO_REDO::PAGESETTINGS );
498
499 undoCmd.PushItem( wrapper );
500 undoCmd.SetDescription( _( "Page Settings" ) );
501 m_frame->SaveCopyInUndoList( undoCmd, UNDO_REDO::PAGESETTINGS, false );
502
503 DIALOG_EESCHEMA_PAGE_SETTINGS dlg( m_frame, m_frame->Schematic().GetEmbeddedFiles(),
506
507 if( dlg.ShowModal() == wxID_OK )
508 {
509 // Update text variables
510 m_frame->GetCanvas()->GetView()->MarkDirty();
511 m_frame->GetCanvas()->GetView()->UpdateAllItems( KIGFX::REPAINT );
512 m_frame->GetCanvas()->Refresh();
513
514 m_frame->OnModify();
515 }
516 else
517 {
518 m_frame->RollbackSchematicFromUndo();
519 }
520
521 return 0;
522}
523
524
526{
527 SCH_SCREENS schematic( m_frame->Schematic().Root() );
528
529 if( schematic.HasNoFullyDefinedLibIds() )
530 RescueLegacyProject( true );
531 else
533
534 return 0;
535}
536
537
538bool SCH_EDITOR_CONTROL::RescueLegacyProject( bool aRunningOnDemand )
539{
540 LEGACY_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
541 m_frame->GetCanvas()->GetBackend() );
542
543 return rescueProject( rescuer, aRunningOnDemand );
544}
545
546
548{
549 SYMBOL_LIB_TABLE_RESCUER rescuer( m_frame->Prj(), &m_frame->Schematic(), &m_frame->GetCurrentSheet(),
550 m_frame->GetCanvas()->GetBackend() );
551
552 return rescueProject( rescuer, aRunningOnDemand );
553}
554
555
556bool SCH_EDITOR_CONTROL::rescueProject( RESCUER& aRescuer, bool aRunningOnDemand )
557{
558 if( !RESCUER::RescueProject( m_frame, aRescuer, aRunningOnDemand ) )
559 return false;
560
561 if( aRescuer.GetCandidateCount() )
562 {
563 KIWAY_PLAYER* viewer = m_frame->Kiway().Player( FRAME_SCH_VIEWER, false );
564
565 if( viewer )
566 static_cast<SYMBOL_VIEWER_FRAME*>( viewer )->ReCreateLibList();
567
568 if( aRunningOnDemand )
569 {
570 SCH_SCREENS schematic( m_frame->Schematic().Root() );
571
572 schematic.UpdateSymbolLinks();
573 m_frame->RecalculateConnections( nullptr, GLOBAL_CLEANUP );
574 }
575
576 m_frame->ClearUndoRedoList();
577 m_frame->SyncView();
578 m_frame->GetCanvas()->Refresh();
579 m_frame->OnModify();
580 }
581
582 return true;
583}
584
585
587{
588 DIALOG_SYMBOL_REMAP dlgRemap( m_frame );
589
590 dlgRemap.ShowQuasiModal();
591
592 m_frame->GetCanvas()->Refresh( true );
593
594 return 0;
595}
596
597
599{
600 DIALOG_PRINT dlg( m_frame );
601
602 dlg.ShowModal();
603
604 return 0;
605}
606
607
609{
611
612 dlg.ShowModal();
613
614 return 0;
615}
616
617
619{
620 doCrossProbeSchToPcb( aEvent, false );
621 return 0;
622}
623
624
626{
627 doCrossProbeSchToPcb( aEvent, true );
628 return 0;
629}
630
631
632void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
633{
634 // Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
635 if( m_probingPcbToSch || m_frame->IsSyncingSelection() )
636 return;
637
638 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
639 SCH_SELECTION& selection = aForce ? selTool->RequestSelection() : selTool->GetSelection();
640
641 m_frame->SendSelectItemsToPcb( selection.GetItemsSortedBySelectionOrder(), aForce );
642}
643
644
646{
647 bool savePowerSymbols = false;
648 bool map = false;
650 wxString targetLib;
651 wxString msg;
652
653 targetLib = m_frame->SelectLibrary( _( "Export Symbols" ), _( "Export symbols to library:" ),
654 { { _( "Include power symbols in export" ), &savePowerSymbols },
655 { _( "Update schematic symbols to link to exported symbols" ), &map }
656 } );
657
658 if( targetLib.empty() )
659 return 0;
660
661 SCH_SHEET_LIST sheets = m_frame->Schematic().BuildSheetListSortedByPageNumbers();
662 SCH_REFERENCE_LIST symbols;
663 sheets.GetSymbols( symbols, savePowerSymbols );
664
665 std::map<LIB_ID, LIB_SYMBOL*> libSymbols;
666 std::map<LIB_ID, std::vector<SCH_SYMBOL*>> symbolMap;
667
668 for( size_t i = 0; i < symbols.GetCount(); ++i )
669 {
670 SCH_SYMBOL* symbol = symbols[i].GetSymbol();
671 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
672 LIB_ID id = libSymbol->GetLibId();
673
674 if( libSymbols.count( id ) )
675 {
676 wxASSERT_MSG( libSymbols[id]->Compare( *libSymbol, SCH_ITEM::COMPARE_FLAGS::ERC ) == 0,
677 "Two symbols have the same LIB_ID but are different!" );
678 }
679 else
680 {
681 libSymbols[id] = libSymbol;
682 }
683
684 symbolMap[id].emplace_back( symbol );
685 }
686
687 bool append = false;
688 SCH_COMMIT commit( m_frame );
690
691 auto optRow = adapter->GetRow( targetLib );
692 wxCHECK( optRow, 0 );
693 const LIBRARY_TABLE_ROW* row = *optRow;
694
695 SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::EnumFromStr( row->Type() );
696 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
697
698 wxFileName dest = LIBRARY_MANAGER::GetFullURI( row );
699 dest.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
700
701 for( const std::pair<const LIB_ID, LIB_SYMBOL*>& it : libSymbols )
702 {
703 LIB_SYMBOL* origSym = it.second;
704 LIB_SYMBOL* newSym = origSym->Flatten().release();
705
706 try
707 {
708 pi->SaveSymbol( dest.GetFullPath(), newSym );
709 }
710 catch( const IO_ERROR& ioe )
711 {
712 msg.Printf( _( "Error saving symbol %s to library '%s'." ), newSym->GetName(), row->Nickname() );
713 msg += wxS( "\n\n" ) + ioe.What();
714 wxLogWarning( msg );
715 return 0;
716 }
717
718 if( map )
719 {
720 LIB_ID id = it.first;
721 id.SetLibNickname( targetLib );
722
723 for( SCH_SYMBOL* symbol : symbolMap[it.first] )
724 {
725 SCH_SCREEN* parentScreen = static_cast<SCH_SCREEN*>( symbol->GetParent() );
726
727 wxCHECK2( parentScreen, continue );
728
729 commit.Modify( symbol, parentScreen, RECURSE_MODE::NO_RECURSE );
730 symbol->SetLibId( id );
731 append = true;
732 }
733 }
734 }
735
736 if( append )
737 {
738 std::set<SCH_SCREEN*> processedScreens;
739
740 for( SCH_SHEET_PATH& sheet : sheets )
741 {
742 SCH_SCREEN* screen = sheet.LastScreen();
743
744 if( processedScreens.find( ( screen ) ) == processedScreens.end() )
745 {
746 processedScreens.insert( screen );
747 screen->UpdateSymbolLinks();
748 }
749 }
750
751 commit.Push( wxS( "Update Library Identifiers" ) );
752 }
753
754 return 0;
755}
756
757
758#define HITTEST_THRESHOLD_PIXELS 5
759
761{
762 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
763 KIWAY_PLAYER* sim_player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
764 SIMULATOR_FRAME* sim_Frame = static_cast<SIMULATOR_FRAME*>( sim_player );
765
766 if( !sim_Frame ) // Defensive coding; shouldn't happen.
767 return 0;
768
769 if( wxWindow* blocking_win = sim_Frame->Kiway().GetBlockingDialog() )
770 blocking_win->Close( true );
771
772 // Deactivate other tools; particularly important if another PICKER is currently running
773 Activate();
774
776 picker->SetSnapping( false );
777 picker->ClearHandlers();
778
779 picker->SetClickHandler(
780 [this]( const VECTOR2D& aPosition )
781 {
782 KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
783 SIMULATOR_FRAME* simFrame = static_cast<SIMULATOR_FRAME*>( player );
784 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
785
786 // We do not really want to keep an item selected in schematic,
787 // so clear the current selection
788 selTool->ClearSelection();
789
790 EDA_ITEM* item = selTool->GetNode( aPosition );
791 SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
792 wxString variant = m_frame->Schematic().GetCurrentVariant();
793
794 if( !item )
795 return false;
796
797 if( item->Type() == SCH_PIN_T )
798 {
799 SCH_PIN* schPin = static_cast<SCH_PIN*>( item );
800 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( schPin->GetParentSymbol() );
801 SCH_PIN* libPin = schPin->GetLibPin();
802
803 if( !symbol || !libPin )
804 return false;
805
806 try
807 {
808 WX_STRING_REPORTER reporter;
809 SIM_LIB_MGR mgr( &m_frame->Prj() );
810
811 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
812 embeddedFilesStack.push_back( m_frame->Schematic().GetEmbeddedFiles() );
813
814 if( EMBEDDED_FILES* symbolEmbeddedFile = symbol->GetEmbeddedFiles() )
815 embeddedFilesStack.push_back( symbolEmbeddedFile );
816
817 mgr.SetFilesStack( std::move( embeddedFilesStack ) );
818
819 SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, true, 0, variant, reporter ).model;
820
821 if( reporter.HasMessage() )
822 THROW_IO_ERROR( reporter.GetMessages() );
823
824 SPICE_ITEM spiceItem;
825 spiceItem.refName = symbol->GetRef( &sheet ).ToStdString();
826 std::vector<std::string> currentNames = model.SpiceGenerator().CurrentNames( spiceItem );
827
828 if( currentNames.size() == 0 )
829 {
830 return true;
831 }
832 else if( currentNames.size() == 1 )
833 {
834 if( simFrame )
835 simFrame->AddCurrentTrace( currentNames.at( 0 ) );
836
837 return true;
838 }
839
840 int modelPinIndex = model.FindModelPinIndex( libPin->GetNumber().ToStdString() );
841
842 if( modelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
843 {
844 wxString name = currentNames.at( modelPinIndex );
845
846 if( simFrame )
847 simFrame->AddCurrentTrace( name );
848 }
849 }
850 catch( const IO_ERROR& e )
851 {
853 }
854 }
855 else if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T } ) || item->IsType( { SCH_JUNCTION_T } ) )
856 {
857 if( SCH_CONNECTION* conn = static_cast<SCH_ITEM*>( item )->Connection() )
858 {
859 wxString spiceNet = UnescapeString( conn->Name() );
861
862 if( simFrame )
863 simFrame->AddVoltageTrace( wxString::Format( "V(%s)", spiceNet ) );
864 }
865 }
866
867 return true;
868 } );
869
870 picker->SetMotionHandler(
871 [this]( const VECTOR2D& aPos )
872 {
873 SCH_COLLECTOR collector;
874 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
875 collector.Collect( m_frame->GetScreen(), { SCH_ITEM_LOCATE_WIRE_T,
876 SCH_PIN_T,
877 SCH_SHEET_PIN_T }, aPos );
878
879 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
880 selectionTool->GuessSelectionCandidates( collector, aPos );
881
882 EDA_ITEM* item = collector.GetCount() == 1 ? collector[0] : nullptr;
883 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( item );
884
885 const SCH_CONNECTION* conn = nullptr;
886
887 if( wire )
888 {
889 item = nullptr;
890 conn = wire->Connection();
891 }
892
893 if( item && item->Type() == SCH_PIN_T )
894 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::CURRENT_PROBE );
895 else
896 m_toolMgr->GetTool<PICKER_TOOL>()->SetCursor( KICURSOR::VOLTAGE_PROBE );
897
898 if( m_pickerItem != item )
899 {
900 if( m_pickerItem )
901 selectionTool->UnbrightenItem( m_pickerItem );
902
903 m_pickerItem = item;
904
905 if( m_pickerItem )
906 selectionTool->BrightenItem( m_pickerItem );
907 }
908
909 wxString connectionName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
910
911 if( m_frame->GetHighlightedConnection() != connectionName )
912 {
913 m_frame->SetHighlightedConnection( connectionName );
914
915 TOOL_EVENT dummyEvent;
916 UpdateNetHighlighting( dummyEvent );
917 }
918 } );
919
920 picker->SetFinalizeHandler(
921 [this]( const int& aFinalState )
922 {
923 if( m_pickerItem )
924 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
925
926 if( !m_frame->GetHighlightedConnection().IsEmpty() )
927 {
928 m_frame->SetHighlightedConnection( wxEmptyString );
929
930 TOOL_EVENT dummyEvent;
931 UpdateNetHighlighting( dummyEvent );
932 }
933
934 // Wake the selection tool after exiting to ensure the cursor gets updated
935 // and deselect previous selection from simulator to avoid any issue
936 // ( avoid crash in some cases when the SimProbe tool is deselected )
937 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
938 selectionTool->ClearSelection();
940 } );
941
942 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
943
944 return 0;
945}
946
947
949{
950 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
951
952 // Deactivate other tools; particularly important if another PICKER is currently running
953 Activate();
954
955 picker->SetCursor( KICURSOR::TUNE );
956 picker->SetSnapping( false );
957 picker->ClearHandlers();
958
959 picker->SetClickHandler(
960 [this]( const VECTOR2D& aPosition )
961 {
962 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
963 EDA_ITEM* item = nullptr;
964 selTool->SelectPoint( aPosition, { SCH_SYMBOL_T, SCH_FIELD_T }, &item );
965
966 if( !item )
967 return false;
968
969 if( item->Type() != SCH_SYMBOL_T )
970 {
971 item = item->GetParent();
972
973 if( item->Type() != SCH_SYMBOL_T )
974 return false;
975 }
976
977 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
978 SCH_SHEET_PATH sheetPath = symbol->Schematic()->CurrentSheet();
979 KIWAY_PLAYER* simFrame = m_frame->Kiway().Player( FRAME_SIMULATOR, false );
980
981 if( simFrame )
982 {
983 if( wxWindow* blocking_win = simFrame->Kiway().GetBlockingDialog() )
984 blocking_win->Close( true );
985
986 static_cast<SIMULATOR_FRAME*>( simFrame )->AddTuner( sheetPath, symbol );
987 }
988
989 // We do not really want to keep a symbol selected in schematic,
990 // so clear the current selection
991 selTool->ClearSelection();
992 return true;
993 } );
994
995 picker->SetMotionHandler(
996 [this]( const VECTOR2D& aPos )
997 {
998 SCH_COLLECTOR collector;
999 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
1000 collector.Collect( m_frame->GetScreen(), { SCH_SYMBOL_T, SCH_FIELD_T }, aPos );
1001
1002 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1003 selectionTool->GuessSelectionCandidates( collector, aPos );
1004
1005 EDA_ITEM* item = collector.GetCount() == 1 ? collector[0] : nullptr;
1006
1007 if( item && item->Type() == SCH_FIELD_T )
1008 item = static_cast<SCH_FIELD*>( item )->GetParentSymbol();
1009
1010 if( m_pickerItem != item )
1011 {
1012 if( m_pickerItem )
1013 selectionTool->UnbrightenItem( m_pickerItem );
1014
1015 m_pickerItem = item;
1016
1017 if( m_pickerItem )
1018 selectionTool->BrightenItem( m_pickerItem );
1019 }
1020 } );
1021
1022 picker->SetFinalizeHandler(
1023 [this]( const int& aFinalState )
1024 {
1025 if( m_pickerItem )
1026 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
1027
1028 // Wake the selection tool after exiting to ensure the cursor gets updated
1029 // and deselect previous selection from simulator to avoid any issue
1030 // ( avoid crash in some cases when the SimTune tool is deselected )
1031 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1032 selectionTool->ClearSelection();
1034 } );
1035
1036 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1037
1038 return 0;
1039}
1040
1041
1042// A singleton reference for clearing the highlight
1044
1045
1046static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
1047{
1048 SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( aToolMgr->GetToolHolder() );
1049 SCH_SELECTION_TOOL* selTool = aToolMgr->GetTool<SCH_SELECTION_TOOL>();
1050 SCH_EDITOR_CONTROL* editorControl = aToolMgr->GetTool<SCH_EDITOR_CONTROL>();
1051 SCH_CONNECTION* conn = nullptr;
1052 SCH_ITEM* item = nullptr;
1053 bool retVal = true;
1054
1055 if( aPosition != CLEAR )
1056 {
1057 ERC_TESTER erc( &editFrame->Schematic() );
1058
1059 if( erc.TestDuplicateSheetNames( false ) > 0 )
1060 {
1061 wxMessageBox( _( "Error: duplicate sub-sheet names found in current sheet." ) );
1062 retVal = false;
1063 }
1064 else
1065 {
1066 item = static_cast<SCH_ITEM*>( selTool->GetNode( aPosition ) );
1067 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1068
1069 if( item )
1070 {
1071 if( item->IsConnectivityDirty() )
1072 editFrame->RecalculateConnections( nullptr, NO_CLEANUP );
1073
1074 if( item->Type() == SCH_FIELD_T )
1075 symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
1076
1077 if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
1078 {
1079 std::vector<SCH_PIN*> pins = symbol->GetPins();
1080
1081 if( pins.size() == 1 )
1082 conn = pins[0]->Connection();
1083 }
1084 else
1085 {
1086 conn = item->Connection();
1087 }
1088 }
1089 }
1090 }
1091
1092 wxString connName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
1093
1094 if( !conn )
1095 {
1096 editFrame->SetStatusText( wxT( "" ) );
1097 editFrame->SendCrossProbeClearHighlight();
1098 editFrame->SetHighlightedConnection( wxEmptyString );
1099 editorControl->SetHighlightBusMembers( false );
1100 }
1101 else
1102 {
1103 NET_NAVIGATOR_ITEM_DATA itemData( editFrame->GetCurrentSheet(), item );
1104
1105 if( connName != editFrame->GetHighlightedConnection() )
1106 {
1107 editorControl->SetHighlightBusMembers( false );
1108 editFrame->SetCrossProbeConnection( conn );
1109 editFrame->SetHighlightedConnection( connName, &itemData );
1110 }
1111 else
1112 {
1113 editorControl->SetHighlightBusMembers( !editorControl->GetHighlightBusMembers() );
1114
1115 if( item != editFrame->GetSelectedNetNavigatorItem() )
1116 editFrame->SelectNetNavigatorItem( &itemData );
1117 }
1118 }
1119
1120 editFrame->UpdateNetHighlightStatus();
1121
1123 editorControl->UpdateNetHighlighting( dummy );
1124
1125 return retVal;
1126}
1127
1128
1130{
1132 VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1133
1134 highlightNet( m_toolMgr, cursorPos );
1135
1136 return 0;
1137}
1138
1139
1141{
1143
1144 return 0;
1145}
1146
1147
1149{
1150 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1151 SCHEMATIC& schematic = m_frame->Schematic();
1152 SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
1153
1154 std::vector<std::pair<SCH_CONNECTION*, VECTOR2D>> selectedConns;
1155
1156 for( EDA_ITEM* item : selectionTool->GetSelection() )
1157 {
1158 SCH_CONNECTION* conn = static_cast<SCH_ITEM*>( item )->Connection();
1159
1160 if( !conn )
1161 continue;
1162
1163 selectedConns.emplace_back( conn, item->GetPosition() );
1164 }
1165
1166 if( selectedConns.empty() )
1167 {
1168 m_frame->ShowInfoBarError( _( "No nets selected." ) );
1169 return 0;
1170 }
1171
1172 // Remove selection in favor of highlighting so the whole net is highlighted
1173 selectionTool->ClearSelection();
1174
1175 const auto getNetNamePattern =
1176 []( const SCH_CONNECTION& aConn ) -> std::optional<wxString>
1177 {
1178 wxString netName = aConn.Name();
1179
1180 if( aConn.IsBus() )
1181 {
1182 wxString prefix;
1183
1184 if( NET_SETTINGS::ParseBusVector( netName, &prefix, nullptr ) )
1185 return prefix + wxT( "*" );
1186 else if( NET_SETTINGS::ParseBusGroup( netName, &prefix, nullptr ) )
1187 return prefix + wxT( ".*" );
1188 }
1189 else if( !aConn.Driver() || CONNECTION_SUBGRAPH::GetDriverPriority( aConn.Driver() )
1191 {
1192 return std::nullopt;
1193 }
1194
1195 return netName;
1196 };
1197
1198 std::set<wxString> netNames;
1199
1200 for( const auto& [conn, pos] : selectedConns )
1201 {
1202 std::optional<wxString> netNamePattern = getNetNamePattern( *conn );
1203
1204 if( !netNamePattern )
1205 {
1206 // This is a choice, we can also allow some un-labeled nets as long as some are labeled.
1207 m_frame->ShowInfoBarError( _( "All selected nets must be labeled to assign a netclass." ) );
1208 return 0;
1209 }
1210
1211 netNames.insert( *netNamePattern );
1212 }
1213
1214 wxCHECK( !netNames.empty(), 0 );
1215
1216 DIALOG_ASSIGN_NETCLASS dlg( m_frame, netNames, schematic.GetNetClassAssignmentCandidates(),
1217 [&]( const std::vector<wxString>& aNetNames )
1218 {
1219 for( SCH_ITEM* item : screen->Items() )
1220 {
1221 bool redraw = item->IsBrightened();
1222 SCH_CONNECTION* itemConn = item->Connection();
1223
1224 if( itemConn && alg::contains( aNetNames, itemConn->Name() ) )
1225 item->SetBrightened();
1226 else
1227 item->ClearBrightened();
1228
1229 redraw |= item->IsBrightened();
1230
1231 if( item->Type() == SCH_SYMBOL_T )
1232 {
1233 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1234
1235 redraw |= symbol->HasBrightenedPins();
1236
1237 symbol->ClearBrightenedPins();
1238
1239 for( SCH_PIN* pin : symbol->GetPins() )
1240 {
1241 SCH_CONNECTION* pin_conn = pin->Connection();
1242
1243 if( pin_conn && alg::contains( aNetNames, pin_conn->Name() ) )
1244 {
1245 pin->SetBrightened();
1246 redraw = true;
1247 }
1248 }
1249 }
1250 else if( item->Type() == SCH_SHEET_T )
1251 {
1252 for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
1253 {
1254 SCH_CONNECTION* pin_conn = pin->Connection();
1255
1256 redraw |= pin->IsBrightened();
1257
1258 if( pin_conn && alg::contains( aNetNames, pin_conn->Name() ) )
1259 pin->SetBrightened();
1260 else
1261 pin->ClearBrightened();
1262
1263 redraw |= pin->IsBrightened();
1264 }
1265 }
1266
1267 if( redraw )
1268 getView()->Update( item, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
1269 }
1270
1271 m_frame->GetCanvas()->ForceRefresh();
1272 } );
1273
1274 if( dlg.ShowModal() )
1275 {
1276 getView()->UpdateAllItemsConditionally(
1277 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
1278 {
1279 int flags = 0;
1280
1281 auto invalidateTextVars =
1282 [&flags]( EDA_TEXT* text )
1283 {
1284 if( text->HasTextVars() )
1285 {
1286 text->ClearRenderCache();
1287 text->ClearBoundingBoxCache();
1289 }
1290 };
1291
1292 // Netclass coloured items
1293 //
1294 if( dynamic_cast<SCH_LINE*>( aItem ) )
1295 flags |= KIGFX::REPAINT;
1296 else if( dynamic_cast<SCH_JUNCTION*>( aItem ) )
1297 flags |= KIGFX::REPAINT;
1298 else if( dynamic_cast<SCH_BUS_ENTRY_BASE*>( aItem ) )
1299 flags |= KIGFX::REPAINT;
1300
1301 // Items that might reference an item's netclass name
1302 //
1303 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
1304 {
1305 item->RunOnChildren(
1306 [&invalidateTextVars]( SCH_ITEM* aChild )
1307 {
1308 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
1309 invalidateTextVars( text );
1310 },
1312
1313 if( flags & KIGFX::GEOMETRY )
1314 m_frame->GetScreen()->Update( item, false ); // Refresh RTree
1315 }
1316
1317 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
1318 invalidateTextVars( text );
1319
1320 return flags;
1321 } );
1322 }
1323
1324 highlightNet( m_toolMgr, CLEAR );
1325 return 0;
1326}
1327
1328
1330{
1331 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1332
1333 if( !selectionTool )
1334 return 0;
1335
1336 wxString netName;
1337
1338 for( EDA_ITEM* item : selectionTool->GetSelection() )
1339 {
1340 if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
1341 {
1342 if( SCH_CONNECTION* conn = schItem->Connection() )
1343 {
1344 if( !conn->GetNetName().IsEmpty() )
1345 {
1346 netName = conn->GetNetName();
1347 break;
1348 }
1349 }
1350 }
1351 }
1352
1353 if( netName.IsEmpty() )
1354 netName = m_frame->GetHighlightedConnection();
1355
1356 if( netName.IsEmpty() )
1357 {
1358 m_frame->ShowInfoBarError( _( "No connected net selected." ) );
1359 return 0;
1360 }
1361
1362 m_frame->FindNetInInspector( netName );
1363
1364 return 0;
1365}
1366
1367
1369{
1370 wxCHECK( m_frame, 0 );
1371
1372 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
1373 SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
1374 CONNECTION_GRAPH* connectionGraph = m_frame->Schematic().ConnectionGraph();
1375 wxString selectedName = m_frame->GetHighlightedConnection();
1376
1377 std::set<wxString> connNames;
1378 std::vector<EDA_ITEM*> itemsToRedraw;
1379
1380 wxCHECK( screen && connectionGraph, 0 );
1381
1382 if( !selectedName.IsEmpty() )
1383 {
1384 connNames.emplace( selectedName );
1385
1386 if( CONNECTION_SUBGRAPH* sg = connectionGraph->FindSubgraphByName( selectedName, sheetPath ) )
1387 {
1389 {
1390 for( const SCH_ITEM* item : sg->GetItems() )
1391 {
1392 wxCHECK2( item, continue );
1393
1394 if( SCH_CONNECTION* connection = item->Connection() )
1395 {
1396 for( const std::shared_ptr<SCH_CONNECTION>& member : connection->AllMembers() )
1397 {
1398 if( member )
1399 connNames.emplace( member->Name() );
1400 }
1401 }
1402 }
1403 }
1404 }
1405
1406 // Place all bus names that are connected to the selected net in the set, regardless of
1407 // their sheet. This ensures that nets that are connected to a bus on a different sheet
1408 // get their buses highlighted as well.
1409 for( CONNECTION_SUBGRAPH* sg : connectionGraph->GetAllSubgraphs( selectedName ) )
1410 {
1411 for( const auto& [_, bus_sgs] : sg->GetBusParents() )
1412 {
1413 for( CONNECTION_SUBGRAPH* bus_sg : bus_sgs )
1414 connNames.emplace( bus_sg->GetNetName() );
1415 }
1416 }
1417 }
1418
1419 for( SCH_ITEM* item : screen->Items() )
1420 {
1421 if( !item || !item->IsConnectable() )
1422 continue;
1423
1424 SCH_ITEM* redrawItem = nullptr;
1425
1426 if( item->Type() == SCH_SYMBOL_T )
1427 {
1428 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1429
1430 for( SCH_PIN* pin : symbol->GetPins() )
1431 {
1432 SCH_CONNECTION* pin_conn = pin->Connection();
1433
1434 if( pin_conn )
1435 {
1436 if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
1437 {
1438 pin->SetBrightened();
1439 redrawItem = symbol;
1440 }
1441 else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
1442 {
1443 pin->ClearBrightened();
1444 redrawItem = symbol;
1445 }
1446 }
1447 else if( pin->IsBrightened() )
1448 {
1449 pin->ClearBrightened();
1450 redrawItem = symbol;
1451 }
1452 }
1453
1454 if( symbol->IsPower() && symbol->GetPins().size() )
1455 {
1456 SCH_CONNECTION* pinConn = symbol->GetPins()[0]->Connection();
1457
1459 {
1460 SCH_FIELD* field = symbol->GetField( id );
1461
1462 if( !field->IsVisible() )
1463 continue;
1464
1465 if( pinConn )
1466 {
1467 if( !field->IsBrightened() && connNames.count( pinConn->Name() ) )
1468 {
1469 field->SetBrightened();
1470 redrawItem = symbol;
1471 }
1472 else if( field->IsBrightened() && !connNames.count( pinConn->Name() ) )
1473 {
1474 field->ClearBrightened();
1475 redrawItem = symbol;
1476 }
1477 }
1478 else if( field->IsBrightened() )
1479 {
1480 field->ClearBrightened();
1481 redrawItem = symbol;
1482 }
1483 }
1484 }
1485 }
1486 else if( item->Type() == SCH_SHEET_T )
1487 {
1488 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1489
1490 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1491 {
1492 wxCHECK2( pin, continue );
1493
1494 SCH_CONNECTION* pin_conn = pin->Connection();
1495
1496 if( pin_conn )
1497 {
1498 if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
1499 {
1500 pin->SetBrightened();
1501 redrawItem = sheet;
1502 }
1503 else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
1504 {
1505 pin->ClearBrightened();
1506 redrawItem = sheet;
1507 }
1508 }
1509 else if( pin->IsBrightened() )
1510 {
1511 pin->ClearBrightened();
1512 redrawItem = sheet;
1513 }
1514 }
1515 }
1516 else
1517 {
1518 SCH_CONNECTION* itemConn = item->Connection();
1519
1520 if( itemConn )
1521 {
1522 if( !item->IsBrightened() && connNames.count( itemConn->Name() ) )
1523 {
1524 item->SetBrightened();
1525 redrawItem = item;
1526 }
1527 else if( item->IsBrightened() && !connNames.count( itemConn->Name() ) )
1528 {
1529 item->ClearBrightened();
1530 redrawItem = item;
1531 }
1532 }
1533 else if( item->IsBrightened() )
1534 {
1535 item->ClearBrightened();
1536 redrawItem = item;
1537 }
1538 }
1539
1540 if( redrawItem )
1541 itemsToRedraw.push_back( redrawItem );
1542 }
1543
1544 if( itemsToRedraw.size() )
1545 {
1546 // Be sure highlight change will be redrawn
1547 KIGFX::VIEW* view = getView();
1548
1549 for( EDA_ITEM* redrawItem : itemsToRedraw )
1551
1552 m_frame->GetCanvas()->Refresh();
1553 }
1554
1555 return 0;
1556}
1557
1558
1560{
1561 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
1562
1563 // Deactivate other tools; particularly important if another PICKER is currently running
1564 Activate();
1565
1566 picker->SetCursor( KICURSOR::BULLSEYE );
1567 picker->SetSnapping( false );
1568 picker->ClearHandlers();
1569
1570 picker->SetClickHandler(
1571 [this]( const VECTOR2D& aPos )
1572 {
1573 return highlightNet( m_toolMgr, aPos );
1574 } );
1575
1576 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
1577
1578 return 0;
1579}
1580
1581
1583{
1584 wxCHECK( m_frame, 0 );
1585
1586 if( m_frame->GetUndoCommandCount() <= 0 )
1587 return 0;
1588
1589 // Inform tools that undo command was issued
1590 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1591
1592 // Get the old list
1593 PICKED_ITEMS_LIST* undo_list = m_frame->PopCommandFromUndoList();
1594
1595 wxCHECK( undo_list, 0 );
1596
1597 m_frame->PutDataInPreviousState( undo_list );
1598
1599 // Now push the old command to the RedoList
1600 undo_list->ReversePickersListOrder();
1601 m_frame->PushCommandToRedoList( undo_list );
1602
1603 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1604
1605 m_frame->GetCanvas()->Refresh();
1606 m_frame->OnModify();
1607
1608 return 0;
1609}
1610
1611
1613{
1614 wxCHECK( m_frame, 0 );
1615
1616 if( m_frame->GetRedoCommandCount() == 0 )
1617 return 0;
1618
1619 // Inform tools that undo command was issued
1620 m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
1621
1622 /* Get the old list */
1623 PICKED_ITEMS_LIST* list = m_frame->PopCommandFromRedoList();
1624
1625 wxCHECK( list, 0 );
1626
1627 /* Redo the command: */
1628 m_frame->PutDataInPreviousState( list );
1629
1630 /* Put the old list in UndoList */
1631 list->ReversePickersListOrder();
1632 m_frame->PushCommandToUndoList( list );
1633
1634 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->RebuildSelection();
1635
1636 m_frame->GetCanvas()->Refresh();
1637 m_frame->OnModify();
1638
1639 return 0;
1640}
1641
1642
1643bool SCH_EDITOR_CONTROL::doCopy( bool aUseDuplicateClipboard )
1644{
1645 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1646 SCH_SELECTION& selection = selTool->RequestSelection();
1647 SCHEMATIC& schematic = m_frame->Schematic();
1648
1649 if( selection.Empty() )
1650 return false;
1651
1652 if( aUseDuplicateClipboard )
1653 m_duplicateIsHoverSelection = selection.IsHover();
1654
1655 selection.SetScreen( m_frame->GetScreen() );
1657
1658 for( EDA_ITEM* item : selection.GetItems() )
1659 {
1660 if( item->Type() == SCH_SHEET_T )
1661 {
1662 SCH_SHEET* sheet = (SCH_SHEET*) item;
1663 m_supplementaryClipboard[sheet->GetFileName()] = sheet->GetScreen();
1664 }
1665 else if( item->Type() == SCH_FIELD_T && selection.IsHover() )
1666 {
1667 // Most of the time the user is trying to duplicate the parent symbol
1668 // and the field text is in it
1669 selection.Add( item->GetParent() );
1670 }
1671 else if( item->Type() == SCH_MARKER_T )
1672 {
1673 // Don't let the markers be copied
1674 selection.Remove( item );
1675 }
1676 else if( item->Type() == SCH_GROUP_T )
1677 {
1678 // Groups need to have all their items selected
1679 static_cast<SCH_ITEM*>( item )->RunOnChildren(
1680 [&]( EDA_ITEM* aChild )
1681 {
1682 selection.Add( aChild );
1683 },
1685 }
1686 }
1687
1688 bool result = true;
1689 STRING_FORMATTER formatter;
1690 SCH_IO_KICAD_SEXPR plugin;
1691 SCH_SHEET_PATH selPath = m_frame->GetCurrentSheet();
1692
1693 plugin.Format( &selection, &selPath, schematic, &formatter, true );
1694
1695 std::string prettyData = formatter.GetString();
1696 KICAD_FORMAT::Prettify( prettyData, KICAD_FORMAT::FORMAT_MODE::COMPACT_TEXT_PROPERTIES );
1697
1698 if( !aUseDuplicateClipboard )
1699 {
1700 wxLogNull doNotLog; // disable logging of failed clipboard actions
1701
1702 result &= wxTheClipboard->Open();
1703
1704 if( result )
1705 {
1706 wxDataObjectComposite* data = new wxDataObjectComposite();
1707
1708 // Add KiCad data
1709 wxCustomDataObject* kicadObj = new wxCustomDataObject( wxDataFormat( "application/kicad" ) );
1710 kicadObj->SetData( prettyData.size(), prettyData.data() );
1711 data->Add( kicadObj );
1712
1713 BOX2I selectionBox = expandedSelectionBox( selection );
1714
1715 if( selectionBox.GetWidth() > 0 && selectionBox.GetHeight() > 0 )
1716 {
1717 // Add bitmap data (encoded once, used for both PNG clipboard and HTML)
1718 wxImage image = renderSelectionToImageForClipboard( m_frame, selection, selectionBox, true, false );
1719 wxMemoryBuffer pngBuffer;
1720
1721 if( image.IsOk() && EncodeImageToPng( image, pngBuffer ) )
1722 {
1723 AddPngToClipboardData( data, pngBuffer, &image );
1724
1725 // Add HTML with embedded base64 PNG for pasting into documents
1726 wxMemoryBuffer htmlBuffer;
1727
1728 if( generateHtmlFromPngData( pngBuffer, htmlBuffer ) )
1729 {
1730 wxCustomDataObject* htmlObj = new wxCustomDataObject( wxDF_HTML );
1731 htmlObj->SetData( htmlBuffer.GetDataLen(), htmlBuffer.GetData() );
1732 data->Add( htmlObj );
1733 }
1734 }
1735 else
1736 {
1737 wxLogDebug( wxS( "Failed to generate bitmap for clipboard" ) );
1738 }
1739
1740 // Add SVG data
1741 wxMemoryBuffer svgBuffer;
1742
1743 if( plotSelectionToSvg( m_frame, selection, selectionBox, svgBuffer ) )
1744 {
1745 wxCustomDataObject* svgObj = new wxCustomDataObject( wxDataFormat( "image/svg+xml" ) );
1746 svgObj->SetData( svgBuffer.GetDataLen(), svgBuffer.GetData() );
1747 data->Add( svgObj );
1748 }
1749 else
1750 {
1751 wxLogDebug( wxS( "Failed to generate SVG for clipboard" ) );
1752 }
1753 }
1754
1755 // Finally add text data
1756 data->Add( new wxTextDataObject( wxString::FromUTF8( prettyData ) ) );
1757
1758 result &= wxTheClipboard->SetData( data );
1759 result &= wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
1760 wxTheClipboard->Close();
1761 }
1762 }
1763
1764 if( selection.IsHover() )
1765 m_toolMgr->RunAction( ACTIONS::selectionClear );
1766
1767 if( aUseDuplicateClipboard )
1768 {
1769 m_duplicateClipboard = prettyData;
1770 return true;
1771 }
1772
1773 return result;
1774}
1775
1776
1777bool SCH_EDITOR_CONTROL::searchSupplementaryClipboard( const wxString& aSheetFilename, SCH_SCREEN** aScreen )
1778{
1779 if( m_supplementaryClipboard.count( aSheetFilename ) > 0 )
1780 {
1781 *aScreen = m_supplementaryClipboard[aSheetFilename];
1782 return true;
1783 }
1784
1785 return false;
1786}
1787
1788
1790{
1791 doCopy( true ); // Use the local clipboard
1792 Paste( aEvent );
1793
1794 return 0;
1795}
1796
1797
1799{
1800 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1801
1802 if( textEntry )
1803 {
1804 textEntry->Cut();
1805 return 0;
1806 }
1807
1808 if( doCopy() )
1809 m_toolMgr->RunAction( ACTIONS::doDelete );
1810
1811 return 0;
1812}
1813
1814
1816{
1817 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
1818
1819 if( textEntry )
1820 {
1821 textEntry->Copy();
1822 return 0;
1823 }
1824
1825 doCopy();
1826
1827 return 0;
1828}
1829
1830
1832{
1833 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1834 SCH_SELECTION& selection = selTool->RequestSelection();
1835
1836 if( selection.Empty() )
1837 return false;
1838
1839 wxString itemsAsText = GetSelectedItemsAsText( selection );
1840
1841 if( selection.IsHover() )
1842 m_toolMgr->RunAction( ACTIONS::selectionClear );
1843
1844 return SaveClipboard( itemsAsText.ToStdString() );
1845}
1846
1847
1849 const KIID_PATH& aClipPath, bool aForceKeepAnnotations )
1850{
1851 wxCHECK( m_frame && aSymbol, /* void */ );
1852
1853 SCH_SYMBOL_INSTANCE newInstance;
1854 bool instanceFound = false;
1855 KIID_PATH pasteLookupPath = aClipPath;
1856
1857 m_pastedSymbols.insert( aSymbol );
1858
1859 for( const SCH_SYMBOL_INSTANCE& tmp : aSymbol->GetInstances() )
1860 {
1861 if( ( tmp.m_Path.empty() && aClipPath.empty() ) || ( !aClipPath.empty() && tmp.m_Path.EndsWith( aClipPath ) ) )
1862 {
1863 newInstance = tmp;
1864 instanceFound = true;
1865
1866 wxLogTrace( traceSchPaste, wxS( "Pasting found symbol instance with reference %s, unit %d:\n"
1867 "\tClipboard path: %s\n"
1868 "\tSymbol UUID: %s." ),
1869 tmp.m_Reference,
1870 tmp.m_Unit,
1871 aClipPath.AsString(),
1872 aSymbol->m_Uuid.AsString() );
1873
1874 break;
1875 }
1876 }
1877
1878 // The pasted symbol look up paths include the symbol UUID.
1879 pasteLookupPath.push_back( aSymbol->m_Uuid );
1880
1881 if( !instanceFound )
1882 {
1883 wxLogTrace( traceSchPaste, wxS( "Clipboard symbol instance **not** found:\n\tClipboard path: %s\n"
1884 "\tSymbol UUID: %s." ),
1885 aClipPath.AsString(),
1886 aSymbol->m_Uuid.AsString() );
1887
1888 // Some legacy versions saved value fields escaped. While we still do in the symbol
1889 // editor, we don't anymore in the schematic, so be sure to unescape them.
1890 SCH_FIELD* valueField = aSymbol->GetField( FIELD_T::VALUE );
1891 valueField->SetText( UnescapeString( valueField->GetText() ) );
1892
1893 // Pasted from notepad or an older instance of eeschema. Use the values in the fields
1894 // instead.
1895 newInstance.m_Reference = aSymbol->GetField( FIELD_T::REFERENCE )->GetText();
1896 newInstance.m_Unit = aSymbol->GetUnit();
1897 }
1898
1899 newInstance.m_Path = aPastePath.Path();
1900 newInstance.m_ProjectName = m_frame->Prj().GetProjectName();
1901
1902 aSymbol->AddHierarchicalReference( newInstance );
1903
1904 if( !aForceKeepAnnotations )
1905 aSymbol->ClearAnnotation( &aPastePath, false );
1906
1907 // We might clear annotations but always leave the original unit number from the paste.
1908 aSymbol->SetUnit( newInstance.m_Unit );
1909}
1910
1911
1913 const KIID_PATH& aClipPath, bool aForceKeepAnnotations,
1914 SCH_SHEET_LIST* aPastedSheets, std::map<SCH_SHEET_PATH,
1915 SCH_REFERENCE_LIST>& aPastedSymbols )
1916{
1917 wxCHECK( aSheet && aPastedSheets, aPastePath );
1918
1919 SCH_SHEET_PATH sheetPath = aPastePath;
1920 sheetPath.push_back( aSheet );
1921
1922 aPastedSheets->push_back( sheetPath );
1923
1924 if( aSheet->GetScreen() == nullptr )
1925 return sheetPath; // We can only really set the page number but not load any items
1926
1927 for( SCH_ITEM* item : aSheet->GetScreen()->Items() )
1928 {
1929 if( item->IsConnectable() )
1930 item->SetConnectivityDirty();
1931
1932 if( item->Type() == SCH_SYMBOL_T )
1933 {
1934 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1935
1936 wxCHECK2( symbol, continue );
1937
1938 // Only do this once if the symbol is shared across multiple sheets.
1939 if( !m_pastedSymbols.count( symbol ) )
1940 {
1941 for( SCH_PIN* pin : symbol->GetPins() )
1942 {
1943 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1944 pin->SetConnectivityDirty();
1945 }
1946 }
1947
1948 updatePastedSymbol( symbol, sheetPath, aClipPath, aForceKeepAnnotations );
1949 }
1950 else if( item->Type() == SCH_SHEET_T )
1951 {
1952 SCH_SHEET* subsheet = static_cast<SCH_SHEET*>( item );
1953
1954 wxCHECK2( subsheet, continue );
1955
1956 // Make sure pins get a new UUID and set the dirty connectivity flag.
1957 if( !aPastedSheets->ContainsSheet( subsheet ) )
1958 {
1959 for( SCH_SHEET_PIN* pin : subsheet->GetPins() )
1960 {
1961 const_cast<KIID&>( pin->m_Uuid ) = KIID();
1962 pin->SetConnectivityDirty();
1963 }
1964 }
1965
1966 KIID_PATH newClipPath = aClipPath;
1967 newClipPath.push_back( subsheet->m_Uuid );
1968
1969 updatePastedSheet( subsheet, sheetPath, newClipPath, aForceKeepAnnotations, aPastedSheets, aPastedSymbols );
1970 }
1971 }
1972
1973 sheetPath.GetSymbols( aPastedSymbols[aPastePath] );
1974
1975 return sheetPath;
1976}
1977
1978
1980{
1981 wxCHECK( aScreen, /* void */ );
1982
1983 for( const SCH_ITEM* item : aScreen->Items() )
1984 {
1985 if( item->Type() == SCH_SYMBOL_T )
1986 {
1987 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1988
1989 wxCHECK2( symbol, continue );
1990
1991 for( const SCH_SYMBOL_INSTANCE& symbolInstance : symbol->GetInstances() )
1992 {
1993 KIID_PATH pathWithSymbol = symbolInstance.m_Path;
1994
1995 pathWithSymbol.push_back( symbol->m_Uuid );
1996
1997 m_clipboardSymbolInstances[pathWithSymbol] = symbolInstance;
1998 }
1999 }
2000 }
2001}
2002
2003
2005{
2006 wxCHECK( m_frame, /* void */ );
2007
2008 for( SCH_SYMBOL* symbol : m_pastedSymbols )
2009 {
2010 wxCHECK2( symbol, continue );
2011
2012 std::vector<KIID_PATH> instancePathsToRemove;
2013
2014 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2015 {
2016 if( instance.m_ProjectName != m_frame->Prj().GetProjectName() || instance.m_Path.empty() )
2017 instancePathsToRemove.emplace_back( instance.m_Path );
2018 }
2019
2020 for( const KIID_PATH& path : instancePathsToRemove )
2021 symbol->RemoveInstance( path );
2022 }
2023}
2024
2025
2027{
2028 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
2029
2030 if( textEntry )
2031 {
2032 textEntry->Paste();
2033 return 0;
2034 }
2035
2036 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2037 std::string content;
2038 VECTOR2I eventPos;
2039
2040 SCH_SHEET tempSheet;
2041
2042 // Priority for paste:
2043 // 1. application/kicad format (handled by GetClipboardUTF8 which checks this first)
2044 // 2. Text data that can be parsed as KiCad S-expressions
2045 // 3. Bitmap/image data (fallback only if no valid text content)
2046 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2047 content = m_duplicateClipboard;
2048 else
2049 content = GetClipboardUTF8();
2050
2051 // Only fall back to image data if there's no text content
2052 if( content.empty() )
2053 {
2054 std::unique_ptr<wxBitmap> clipImg = GetImageFromClipboard();
2055
2056 if( clipImg )
2057 {
2058 auto bitmap = std::make_unique<SCH_BITMAP>();
2059
2060 if( bitmap->GetReferenceImage().SetImage( clipImg->ConvertToImage() ) )
2061 return m_toolMgr->RunAction( SCH_ACTIONS::placeImage, bitmap.release() );
2062 }
2063
2064 return 0;
2065 }
2066
2067 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2068 eventPos = getViewControls()->GetCursorPosition( false );
2069
2070 STRING_LINE_READER reader( content, "Clipboard" );
2071 SCH_IO_KICAD_SEXPR plugin;
2072
2073 // Screen object on heap is owned by the sheet.
2074 SCH_SCREEN* tempScreen = new SCH_SCREEN( &m_frame->Schematic() );
2075 tempSheet.SetScreen( tempScreen );
2076
2077 try
2078 {
2079 plugin.LoadContent( reader, &tempSheet );
2080 }
2081 catch( IO_ERROR& )
2082 {
2083 // If it wasn't schematic content, paste as a text object
2084 {
2085 if( content.size() > static_cast<size_t>( ADVANCED_CFG::GetCfg().m_MaxPastedTextLength ) )
2086 {
2087 int result = IsOK( m_frame, _( "Pasting a long text text string may be very slow. "
2088 "Do you want to continue?" ) );
2089 if( !result )
2090 return 0;
2091 }
2092
2093 SCH_TEXT* text_item = new SCH_TEXT( VECTOR2I( 0, 0 ), content );
2094 tempScreen->Append( text_item );
2095 }
2096 }
2097
2098 SELECTION& currentSelection = selTool->GetSelection();
2099
2100 bool hasTableCells = false;
2101
2102 for( EDA_ITEM* item : currentSelection )
2103 {
2104 if( item->Type() == SCH_TABLECELL_T )
2105 {
2106 hasTableCells = true;
2107 break;
2108 }
2109 }
2110
2111 if( hasTableCells )
2112 {
2113 SCH_TABLE* clipboardTable = nullptr;
2114
2115 for( SCH_ITEM* item : tempScreen->Items() )
2116 {
2117 if( item->Type() == SCH_TABLE_T )
2118 {
2119 clipboardTable = static_cast<SCH_TABLE*>( item );
2120 break;
2121 }
2122 }
2123
2124 if( clipboardTable )
2125 {
2126 SCH_EDIT_TABLE_TOOL* tableEditTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>();
2127
2128 if( tableEditTool )
2129 {
2130 wxString errorMsg;
2131
2132 if( !tableEditTool->validatePasteIntoSelection( currentSelection, errorMsg ) )
2133 {
2134 DisplayError( m_frame, errorMsg );
2135 return 0;
2136 }
2137
2138 SCH_COMMIT commit( m_toolMgr );
2139
2140 if( tableEditTool->pasteCellsIntoSelection( currentSelection, clipboardTable, commit ) )
2141 {
2142 commit.Push( _( "Paste Cells" ) );
2143 return 0;
2144 }
2145 else
2146 {
2147 DisplayError( m_frame, _( "Failed to paste cells" ) );
2148 return 0;
2149 }
2150 }
2151 }
2152 }
2153
2154 m_pastedSymbols.clear();
2156
2157 // Save pasted symbol instances in case the user chooses to keep existing symbol annotation.
2158 setPastedSymbolInstances( tempScreen );
2159
2160 tempScreen->MigrateSimModels();
2161
2162 bool annotateAutomatic = m_frame->eeconfig()->m_AnnotatePanel.automatic;
2163 SCHEMATIC_SETTINGS& schematicSettings = m_frame->Schematic().Settings();
2164 int annotateStartNum = schematicSettings.m_AnnotateStartNum;
2165
2167 bool forceRemoveAnnotations = false;
2168
2169 if( aEvent.IsAction( &ACTIONS::pasteSpecial ) )
2170 {
2171 PASTE_MODE defaultPasteMode = pasteMode;
2172 DIALOG_PASTE_SPECIAL dlg( m_frame, &pasteMode );
2173
2174 if( dlg.ShowModal() == wxID_CANCEL )
2175 return 0;
2176
2177 // We have to distinguish if removing was explicit
2178 forceRemoveAnnotations = pasteMode == PASTE_MODE::REMOVE_ANNOTATIONS && pasteMode != defaultPasteMode;
2179 }
2180
2181 bool forceKeepAnnotations = pasteMode != PASTE_MODE::REMOVE_ANNOTATIONS;
2182
2183 // SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything
2184 // else. Pull them back out to start with.
2185 SCH_COMMIT commit( m_toolMgr );
2186 EDA_ITEMS loadedItems;
2187 std::vector<SCH_ITEM*> sortedLoadedItems;
2188 bool sheetsPasted = false;
2189 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
2190 SCH_SHEET_PATH& pasteRoot = m_frame->GetCurrentSheet();
2191 wxFileName destFn = pasteRoot.Last()->GetFileName();
2192
2193 if( destFn.IsRelative() )
2194 destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
2195
2196 // List of paths in the hierarchy that refer to the destination sheet of the paste
2197 SCH_SHEET_LIST sheetPathsForScreen = hierarchy.FindAllSheetsForScreen( pasteRoot.LastScreen() );
2198 sheetPathsForScreen.SortByPageNumbers();
2199
2200 // Build a list of screens from the current design (to avoid loading sheets that already exist)
2201 std::map<wxString, SCH_SCREEN*> loadedScreens;
2202
2203 for( const SCH_SHEET_PATH& item : hierarchy )
2204 {
2205 if( item.LastScreen() )
2206 loadedScreens[item.Last()->GetFileName()] = item.LastScreen();
2207 }
2208
2209 // Get set of sheet names in the current schematic to prevent duplicate sheet names on paste.
2210 std::set<wxString> existingSheetNames = pasteRoot.LastScreen()->GetSheetNames();
2211
2212 // Build symbol list for reannotation of duplicates
2213 SCH_REFERENCE_LIST existingRefs;
2214 hierarchy.GetSymbols( existingRefs );
2215 existingRefs.SortByReferenceOnly();
2216
2217 std::set<wxString> existingRefsSet;
2218
2219 for( const SCH_REFERENCE& ref : existingRefs )
2220 existingRefsSet.insert( ref.GetRef() );
2221
2222 // Build UUID map for fetching last-resolved-properties
2223 std::map<KIID, EDA_ITEM*> itemMap;
2224 hierarchy.FillItemMap( itemMap );
2225
2226 // Keep track of pasted sheets and symbols for the different paths to the hierarchy.
2227 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> pastedSymbols;
2228 std::map<SCH_SHEET_PATH, SCH_SHEET_LIST> pastedSheets;
2229
2230 for( SCH_ITEM* item : tempScreen->Items() )
2231 {
2232 if( item->Type() == SCH_SHEET_T )
2233 sortedLoadedItems.push_back( item );
2234 else
2235 loadedItems.push_back( item );
2236 }
2237
2238 sort( sortedLoadedItems.begin(), sortedLoadedItems.end(),
2239 []( SCH_ITEM* firstItem, SCH_ITEM* secondItem )
2240 {
2241 SCH_SHEET* firstSheet = static_cast<SCH_SHEET*>( firstItem );
2242 SCH_SHEET* secondSheet = static_cast<SCH_SHEET*>( secondItem );
2243 return StrNumCmp( firstSheet->GetName(), secondSheet->GetName(), false ) < 0;
2244 } );
2245
2246
2247 for( SCH_ITEM* item : sortedLoadedItems )
2248 {
2249 loadedItems.push_back( item );
2250
2251 if( item->Type() == SCH_SHEET_T )
2252 {
2253 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
2254 wxFileName srcFn = sheet->GetFileName();
2255
2256 if( srcFn.IsRelative() )
2257 srcFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
2258
2259 SCH_SHEET_LIST sheetHierarchy( sheet );
2260
2261 if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
2262 {
2263 auto msg = wxString::Format( _( "The pasted sheet '%s'\n"
2264 "was dropped because the destination already has "
2265 "the sheet or one of its subsheets as a parent." ),
2266 sheet->GetFileName() );
2267 DisplayError( m_frame, msg );
2268 loadedItems.pop_back();
2269 }
2270 }
2271 }
2272
2273 // Remove the references from our temporary screen to prevent freeing on the DTOR
2274 tempScreen->Clear( false );
2275
2276 for( EDA_ITEM* item : loadedItems )
2277 {
2278 KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
2279
2280 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
2281
2282 wxCHECK2( schItem, continue );
2283
2284 if( schItem->IsConnectable() )
2285 schItem->SetConnectivityDirty();
2286
2287 if( item->Type() == SCH_SYMBOL_T )
2288 {
2289 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2290
2291 // The library symbol gets set from the cached library symbols in the current
2292 // schematic not the symbol libraries. The cached library symbol may have
2293 // changed from the original library symbol which would cause the copy to
2294 // be incorrect.
2295 SCH_SCREEN* currentScreen = m_frame->GetScreen();
2296
2297 wxCHECK2( currentScreen, continue );
2298
2299 // First get the library symbol from the clipboard (if available)
2300 auto clipIt = tempScreen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
2301 LIB_SYMBOL* clipLibSymbol = ( clipIt != tempScreen->GetLibSymbols().end() )
2302 ? clipIt->second
2303 : nullptr;
2304
2305 // Then check the current screen
2306 auto it = currentScreen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
2307 auto end = currentScreen->GetLibSymbols().end();
2308
2309 LIB_SYMBOL* libSymbol = nullptr;
2310
2311 if( it != end && clipLibSymbol )
2312 {
2313 // Both exist - check if power types match. If they differ (e.g., one is
2314 // local power and the other is global power), use the clipboard version
2315 // to preserve the copied symbol's power type.
2316 if( clipLibSymbol->IsLocalPower() != it->second->IsLocalPower()
2317 || clipLibSymbol->IsGlobalPower() != it->second->IsGlobalPower() )
2318 {
2319 libSymbol = new LIB_SYMBOL( *clipLibSymbol );
2320 }
2321 else
2322 {
2323 libSymbol = new LIB_SYMBOL( *it->second );
2324 }
2325 }
2326 else if( it != end )
2327 {
2328 libSymbol = new LIB_SYMBOL( *it->second );
2329 }
2330 else if( clipLibSymbol )
2331 {
2332 libSymbol = new LIB_SYMBOL( *clipLibSymbol );
2333 }
2334
2335 if( libSymbol )
2336 symbol->SetLibSymbol( libSymbol );
2337
2338 // If the symbol is already in the schematic we have to always keep the annotations. The exception
2339 // is if the user has chosen to remove them.
2340 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2341 {
2342 if( !existingRefsSet.contains( instance.m_Reference ) )
2343 {
2344 forceKeepAnnotations = !forceRemoveAnnotations;
2345 break;
2346 }
2347 }
2348
2349 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2350 updatePastedSymbol( symbol, sheetPath, clipPath, forceKeepAnnotations );
2351
2352 // Most modes will need new KIIDs for the symbol and its pins. However, if we are pasting
2353 // unique annotations, we need to check if the symbol is not already in the hierarchy. If we
2354 // don't already have a copy of the symbol, we just keep the existing KIID data as it is likely
2355 // the same symbol being moved around the schematic.
2356 bool needsNewKiid = ( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS );
2357
2358 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
2359 {
2360 if( existingRefsSet.contains( instance.m_Reference ) )
2361 {
2362 needsNewKiid = true;
2363 break;
2364 }
2365 }
2366
2367 if( needsNewKiid )
2368 {
2369 // Assign a new KIID
2370 const_cast<KIID&>( item->m_Uuid ) = KIID();
2371
2372 // Make sure pins get a new UUID
2373 for( SCH_PIN* pin : symbol->GetPins() )
2374 {
2375 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2376 pin->SetConnectivityDirty();
2377 }
2378
2379 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2380 {
2381 // Ignore symbols from a non-existant library.
2382 if( libSymbol )
2383 {
2384 SCH_REFERENCE schReference( symbol, sheetPath );
2385 schReference.SetSheetNumber( sheetPath.GetPageNumberAsInt() );
2386 pastedSymbols[sheetPath].AddItem( schReference );
2387 }
2388 }
2389 }
2390 }
2391 else if( item->Type() == SCH_SHEET_T )
2392 {
2393 SCH_SHEET* sheet = (SCH_SHEET*) item;
2394 SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME );
2395 wxString baseName = nameField->GetText();
2396 wxString candidateName = baseName;
2397 wxString number;
2398
2399 while( !baseName.IsEmpty() && wxIsdigit( baseName.Last() ) )
2400 {
2401 number = baseName.Last() + number;
2402 baseName.RemoveLast();
2403 }
2404
2405 // Update hierarchy to include any other sheets we already added, avoiding
2406 // duplicate sheet names
2407 hierarchy = m_frame->Schematic().Hierarchy();
2408
2409 int uniquifier = std::max( 0, wxAtoi( number ) ) + 1;
2410
2411 while( existingSheetNames.count( candidateName ) )
2412 candidateName = wxString::Format( wxT( "%s%d" ), baseName, uniquifier++ );
2413
2414 nameField->SetText( candidateName );
2415 existingSheetNames.emplace( candidateName );
2416
2417 wxFileName fn = sheet->GetFileName();
2418 SCH_SCREEN* existingScreen = nullptr;
2419
2420 sheet->SetParent( pasteRoot.Last() );
2421 sheet->SetScreen( nullptr );
2422
2423 if( !fn.IsAbsolute() )
2424 {
2425 wxFileName currentSheetFileName = pasteRoot.LastScreen()->GetFileName();
2426 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, currentSheetFileName.GetPath() );
2427 }
2428
2429 // Try to find the screen for the pasted sheet by several means
2430 if( !m_frame->Schematic().Root().SearchHierarchy( fn.GetFullPath( wxPATH_UNIX ), &existingScreen ) )
2431 {
2432 if( loadedScreens.count( sheet->GetFileName() ) > 0 )
2433 existingScreen = loadedScreens.at( sheet->GetFileName() );
2434 else
2435 searchSupplementaryClipboard( sheet->GetFileName(), &existingScreen );
2436 }
2437
2438 if( existingScreen )
2439 {
2440 sheet->SetScreen( existingScreen );
2441 }
2442 else
2443 {
2444 if( !m_frame->LoadSheetFromFile( sheet, &pasteRoot, fn.GetFullPath() ) )
2445 m_frame->InitSheet( sheet, sheet->GetFileName() );
2446 }
2447
2448 // Save the symbol instances in case the user chooses to keep the existing
2449 // symbol annotation.
2451 sheetsPasted = true;
2452
2453 // Push it to the clipboard path while it still has its old KIID
2454 clipPath.push_back( sheet->m_Uuid );
2455
2456 // Assign a new KIID to the pasted sheet
2457 const_cast<KIID&>( sheet->m_Uuid ) = KIID();
2458
2459 // Make sure pins get a new UUID
2460 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
2461 {
2462 const_cast<KIID&>( pin->m_Uuid ) = KIID();
2463 pin->SetConnectivityDirty();
2464 }
2465
2466 // Once we have our new KIID we can update all pasted instances. This will either
2467 // reset the annotations or copy "kept" annotations from the supplementary clipboard.
2468 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2469 {
2470 SCH_SHEET_PATH subPath = updatePastedSheet( sheet, sheetPath, clipPath,
2471 ( forceKeepAnnotations && annotateAutomatic ),
2472 &pastedSheets[sheetPath], pastedSymbols );
2473 }
2474 }
2475 else
2476 {
2477 SCH_ITEM* srcItem = dynamic_cast<SCH_ITEM*>( itemMap[item->m_Uuid] );
2478 SCH_ITEM* destItem = dynamic_cast<SCH_ITEM*>( item );
2479
2480 // Everything gets a new KIID
2481 const_cast<KIID&>( item->m_Uuid ) = KIID();
2482
2483 if( srcItem && destItem )
2484 {
2485 destItem->SetConnectivityDirty( true );
2486 destItem->SetLastResolvedState( srcItem );
2487 }
2488 }
2489
2490 // Lines need both ends selected for a move after paste so the whole line moves.
2491 if( item->Type() == SCH_LINE_T )
2492 item->SetFlags( STARTPOINT | ENDPOINT );
2493
2494 item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
2495
2496 if( !m_frame->GetScreen()->CheckIfOnDrawList( (SCH_ITEM*) item ) ) // don't want a loop!
2497 m_frame->AddToScreen( item, m_frame->GetScreen() );
2498
2499 commit.Added( (SCH_ITEM*) item, m_frame->GetScreen() );
2500
2501 // Start out hidden so the pasted items aren't "ghosted" in their original location
2502 // before being moved to the current location.
2503 getView()->Hide( item, true );
2504 }
2505
2506 if( sheetsPasted )
2507 {
2508 // The full schematic hierarchy need to be update before assigning new annotation and
2509 // page numbers.
2510 m_frame->Schematic().RefreshHierarchy();
2511
2512 // Update page numbers: Find next free numeric page number
2513 for( SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2514 {
2515 for( SCH_SHEET_PATH& pastedSheet : pastedSheets[sheetPath] )
2516 {
2517 int page = 1;
2518 wxString pageNum = wxString::Format( "%d", page );
2519
2520 while( hierarchy.PageNumberExists( pageNum ) )
2521 pageNum = wxString::Format( "%d", ++page );
2522
2523 SCH_SHEET_INSTANCE sheetInstance;
2524
2525 sheetInstance.m_Path = pastedSheet.Path();
2526
2527 // Don't include the actual sheet in the instance path.
2528 sheetInstance.m_Path.pop_back();
2529 sheetInstance.m_PageNumber = pageNum;
2530 sheetInstance.m_ProjectName = m_frame->Prj().GetProjectName();
2531
2532 SCH_SHEET* sheet = pastedSheet.Last();
2533
2534 wxCHECK2( sheet, continue );
2535
2536 sheet->AddInstance( sheetInstance );
2537 hierarchy.push_back( pastedSheet );
2538
2539 // Remove all pasted sheet instance data that is not part of the current project.
2540 std::vector<KIID_PATH> instancesToRemove;
2541
2542 for( const SCH_SHEET_INSTANCE& instance : sheet->GetInstances() )
2543 {
2544 if( !hierarchy.HasPath( instance.m_Path ) )
2545 instancesToRemove.push_back( instance.m_Path );
2546 }
2547
2548 for( const KIID_PATH& instancePath : instancesToRemove )
2549 sheet->RemoveInstance( instancePath );
2550 }
2551 }
2552
2553 m_frame->SetSheetNumberAndCount();
2554
2555 // Get a version with correct sheet numbers since we've pasted sheets,
2556 // we'll need this when annotating next
2557 hierarchy = m_frame->Schematic().Hierarchy();
2558 }
2559
2560 std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> annotatedSymbols;
2561
2562 // Update the list of symbol instances that satisfy the annotation criteria.
2563 for( const SCH_SHEET_PATH& sheetPath : sheetPathsForScreen )
2564 {
2565 for( size_t i = 0; i < pastedSymbols[sheetPath].GetCount(); i++ )
2566 {
2567 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[sheetPath][i].AlwaysAnnotate() )
2568 annotatedSymbols[sheetPath].AddItem( pastedSymbols[sheetPath][i] );
2569 }
2570
2571 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[sheetPath] )
2572 {
2573 for( size_t i = 0; i < pastedSymbols[pastedSheetPath].GetCount(); i++ )
2574 {
2575 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS || pastedSymbols[pastedSheetPath][i].AlwaysAnnotate() )
2576 annotatedSymbols[pastedSheetPath].AddItem( pastedSymbols[pastedSheetPath][i] );
2577 }
2578 }
2579 }
2580
2581 if( !annotatedSymbols.empty() )
2582 {
2583 ANNOTATE_ORDER_T annotateOrder = static_cast<ANNOTATE_ORDER_T>( schematicSettings.m_AnnotateSortOrder );
2584 ANNOTATE_ALGO_T annotateAlgo = static_cast<ANNOTATE_ALGO_T>( schematicSettings.m_AnnotateMethod );
2585
2586 for( SCH_SHEET_PATH& path : sheetPathsForScreen )
2587 {
2588 annotatedSymbols[path].SortByReferenceOnly();
2589 annotatedSymbols[path].SetRefDesTracker( schematicSettings.m_refDesTracker );
2590
2591 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2592 {
2593 annotatedSymbols[path].ReannotateDuplicates( existingRefs, annotateAlgo );
2594 }
2595 else
2596 {
2597 annotatedSymbols[path].ReannotateByOptions( annotateOrder, annotateAlgo, annotateStartNum,
2598 existingRefs, false, &hierarchy );
2599 }
2600
2601 annotatedSymbols[path].UpdateAnnotation();
2602
2603 // Update existing refs for next iteration
2604 for( size_t i = 0; i < annotatedSymbols[path].GetCount(); i++ )
2605 existingRefs.AddItem( annotatedSymbols[path][i] );
2606
2607 for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[path] )
2608 {
2609 annotatedSymbols[pastedSheetPath].SortByReferenceOnly();
2610 annotatedSymbols[pastedSheetPath].SetRefDesTracker( schematicSettings.m_refDesTracker );
2611
2612 if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
2613 {
2614 annotatedSymbols[pastedSheetPath].ReannotateDuplicates( existingRefs, annotateAlgo );
2615 }
2616 else
2617 {
2618 annotatedSymbols[pastedSheetPath].ReannotateByOptions( annotateOrder, annotateAlgo,
2619 annotateStartNum, existingRefs,
2620 false, &hierarchy );
2621 }
2622
2623 annotatedSymbols[pastedSheetPath].UpdateAnnotation();
2624
2625 // Update existing refs for next iteration
2626 for( size_t i = 0; i < annotatedSymbols[pastedSheetPath].GetCount(); i++ )
2627 existingRefs.AddItem( annotatedSymbols[pastedSheetPath][i] );
2628 }
2629 }
2630 }
2631
2632 m_frame->GetCurrentSheet().UpdateAllScreenReferences();
2633
2634 // The copy operation creates instance paths that are not valid for the current project or
2635 // saved as part of another project. Prune them now so they do not accumulate in the saved
2636 // schematic file.
2638
2639 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
2640 SCH_SCREENS allScreens( m_frame->Schematic().Root() );
2641
2642 allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(), sheets );
2643 allScreens.PruneOrphanedSheetInstances( m_frame->Prj().GetProjectName(), sheets );
2644
2645 // Now clear the previous selection, select the pasted items, and fire up the "move" tool.
2646 m_toolMgr->RunAction( ACTIONS::selectionClear );
2647
2648 // If the item has a parent group, it will be part of the loadedItems, and will handle
2649 // the move action. Iterate backwards to avoid invalidating the iterator.
2650 for( int i = loadedItems.size() - 1; i >= 0; i-- )
2651 {
2652 EDA_ITEM* item = loadedItems[i];
2653
2654 if( item->GetParentGroup() )
2655 {
2656 loadedItems.erase( loadedItems.begin() + i );
2657 // These were hidden before because they would be added to the move preview,
2658 // but now they need to be shown as a preview so they appear to move when
2659 // the group moves.
2660 getView()->SetVisible( item );
2661 getView()->AddToPreview( item, false );
2662 }
2663 }
2664
2665 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &loadedItems );
2666
2667 SCH_SELECTION& selection = selTool->GetSelection();
2668
2669 if( !selection.Empty() )
2670 {
2671 if( aEvent.IsAction( &ACTIONS::duplicate ) )
2672 {
2673 int closest_dist = INT_MAX;
2674
2675 auto processPt =
2676 [&]( const VECTOR2I& pt )
2677 {
2678 int dist = ( eventPos - pt ).EuclideanNorm();
2679
2680 if( dist < closest_dist )
2681 {
2682 selection.SetReferencePoint( pt );
2683 closest_dist = dist;
2684 }
2685 };
2686
2687 // Prefer connection points (which should remain on grid)
2688 for( EDA_ITEM* item : selection.Items() )
2689 {
2690 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
2691 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
2692
2693 if( sch_item && sch_item->IsConnectable() )
2694 {
2695 for( const VECTOR2I& pt : sch_item->GetConnectionPoints() )
2696 processPt( pt );
2697 }
2698 else if( pin )
2699 {
2700 processPt( pin->GetPosition() );
2701 }
2702
2703 // Symbols need to have their center point added since often users are trying to
2704 // move parts from their center.
2705 if( dynamic_cast<SCH_SYMBOL*>( item ) )
2706 processPt( item->GetPosition() );
2707 }
2708
2709 // Only process other points if we didn't find any connection points
2710 if( closest_dist == INT_MAX )
2711 {
2712 for( EDA_ITEM* item : selection.Items() )
2713 {
2714 switch( item->Type() )
2715 {
2716 case SCH_LINE_T:
2717 processPt( static_cast<SCH_LINE*>( item )->GetStartPoint() );
2718 processPt( static_cast<SCH_LINE*>( item )->GetEndPoint() );
2719 break;
2720
2721 case SCH_SHAPE_T:
2722 {
2723 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
2724
2725 switch( shape->GetShape() )
2726 {
2727 case SHAPE_T::RECTANGLE:
2728 for( const VECTOR2I& pt : shape->GetRectCorners() )
2729 processPt( pt );
2730
2731 break;
2732
2733 case SHAPE_T::CIRCLE:
2734 processPt( shape->GetCenter() );
2735 break;
2736
2737 case SHAPE_T::POLY:
2738 for( int ii = 0; ii < shape->GetPolyShape().TotalVertices(); ++ii )
2739 processPt( shape->GetPolyShape().CVertex( ii ) );
2740
2741 break;
2742
2743 default:
2744 processPt( shape->GetStart() );
2745 processPt( shape->GetEnd() );
2746 break;
2747 }
2748
2749 break;
2750 }
2751
2752 default:
2753 processPt( item->GetPosition() );
2754 break;
2755 }
2756 }
2757 }
2758
2759 selection.SetIsHover( m_duplicateIsHoverSelection );
2760 }
2761 // We want to the first non-group item in the selection to be the reference point.
2762 else if( selection.GetTopLeftItem()->Type() == SCH_GROUP_T )
2763 {
2764 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection.GetTopLeftItem() );
2765
2766 bool found = false;
2767 SCH_ITEM* item = nullptr;
2768
2769 group->RunOnChildren(
2770 [&]( SCH_ITEM* schItem )
2771 {
2772 if( !found && schItem->Type() != SCH_GROUP_T )
2773 {
2774 item = schItem;
2775 found = true;
2776 }
2777 },
2779
2780 if( found )
2781 selection.SetReferencePoint( item->GetPosition() );
2782 else
2783 selection.SetReferencePoint( group->GetPosition() );
2784 }
2785 else
2786 {
2787 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetTopLeftItem() );
2788
2789 selection.SetReferencePoint( item->GetPosition() );
2790 }
2791
2792 if( m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit ) )
2793 {
2794 // Pushing the commit will update the connectivity.
2795 commit.Push( _( "Paste" ) );
2796
2797 if( sheetsPasted )
2798 {
2799 m_frame->UpdateHierarchyNavigator();
2800 // UpdateHierarchyNavigator() will call RefreshNetNavigator()
2801 }
2802 else
2803 {
2804 m_frame->RefreshNetNavigator();
2805 }
2806 }
2807 else
2808 {
2809 commit.Revert();
2810 }
2811
2812 getView()->ClearPreview();
2813 }
2814
2815 return 0;
2816}
2817
2818
2820{
2821 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
2822 SCH_SELECTION& selection = selTool->RequestSelection( { SCH_SYMBOL_T } );
2823 SCH_SYMBOL* symbol = nullptr;
2824 SYMBOL_EDIT_FRAME* symbolEditor;
2825
2826 if( selection.GetSize() >= 1 )
2827 symbol = (SCH_SYMBOL*) selection.Front();
2828
2829 if( selection.IsHover() )
2830 m_toolMgr->RunAction( ACTIONS::selectionClear );
2831
2832 if( !symbol )
2833 {
2834 // Giant hack: by default we assign Edit Table to the same hotkey, so give the table
2835 // tool a chance to handle it if we can't.
2836 if( SCH_EDIT_TABLE_TOOL* tableTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>() )
2837 tableTool->EditTable( aEvent );
2838
2839 return 0;
2840 }
2841
2842 if( symbol->GetEditFlags() != 0 )
2843 return 0;
2844
2845 if( symbol->IsMissingLibSymbol() )
2846 {
2847 m_frame->ShowInfoBarError( _( "Symbols with broken library symbol links cannot be edited." ) );
2848 return 0;
2849 }
2850
2852 symbolEditor = (SYMBOL_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, false );
2853
2854 if( symbolEditor )
2855 {
2856 if( wxWindow* blocking_win = symbolEditor->Kiway().GetBlockingDialog() )
2857 blocking_win->Close( true );
2858
2859 if( aEvent.IsAction( &SCH_ACTIONS::editWithLibEdit ) )
2860 {
2861 symbolEditor->LoadSymbolFromSchematic( symbol );
2862 }
2864 {
2865 symbolEditor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
2866
2867 if( !symbolEditor->IsLibraryTreeShown() )
2868 symbolEditor->ToggleLibraryTree();
2869 }
2870 }
2871
2872 return 0;
2873}
2874
2875
2877{
2878 m_frame->OnAnnotate();
2879 return 0;
2880}
2881
2882
2884{
2886 dlg.m_FirstRefDes->SetValidator( wxTextValidator( wxFILTER_EMPTY ) );
2887
2888 dlg.SetInitialFocus( dlg.m_FirstRefDes );
2889
2890 if( dlg.ShowModal() == wxID_OK )
2891 {
2892 SCH_REFERENCE startRef;
2893 startRef.SetRef( dlg.m_FirstRefDes->GetValue() );
2894
2895 if( startRef.IsSplitNeeded() )
2896 startRef.Split();
2897 else
2898 return 0;
2899
2900 int startNum = atoi( startRef.GetRefNumber().utf8_string().c_str() );
2901
2902 SCH_COMMIT commit( m_frame );
2903 SCHEMATIC* schematic = m_frame->m_schematic;
2904 SCH_REFERENCE_LIST references;
2905
2906 if( dlg.m_AllSheets->GetValue() )
2907 schematic->Hierarchy().GetSymbols( references );
2908 else
2909 schematic->CurrentSheet().GetSymbols( references );
2910
2911 references.SplitReferences();
2912
2913 for( SCH_REFERENCE& ref : references )
2914 {
2915 if( ref.GetRef() == startRef.GetRef() )
2916 {
2917 int num = atoi( ref.GetRefNumber().utf8_string().c_str() );
2918
2919 if( num >= startNum )
2920 {
2921 const SCH_SHEET_PATH& sheet = ref.GetSheetPath();
2922 wxString fullRef = ref.GetRef();
2923
2924 num += dlg.m_Increment->GetValue();
2925 fullRef << num;
2926
2927 commit.Modify( ref.GetSymbol(), sheet.LastScreen(), RECURSE_MODE::NO_RECURSE );
2928 ref.GetSymbol()->SetRef( &sheet, From_UTF8( fullRef.c_str() ) );
2929 }
2930 }
2931 }
2932
2933 if( !commit.Empty() )
2934 commit.Push( _( "Increment Annotations" ) );
2935 }
2936
2937 return 0;
2938}
2939
2940
2942{
2943 m_frame->OnOpenCvpcb();
2944 return 0;
2945}
2946
2947
2949{
2950 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
2951
2952 wxCHECK( dlg, 0 );
2953
2954 // Needed at least on Windows. Raise() is not enough
2955 dlg->Show( true );
2956
2957 // Bring it to the top if already open. Dual monitor users need this.
2958 dlg->Raise();
2959
2960 return 0;
2961}
2962
2963
2965{
2967 m_frame->HardRedraw();
2968
2969 return 0;
2970}
2971
2972
2974{
2975 m_frame->OnOpenPcbnew();
2976 return 0;
2977}
2978
2979
2981{
2982 m_frame->OnUpdatePCB();
2983 return 0;
2984}
2985
2986
2988{
2990 dlg.ShowModal();
2991 return 0;
2992}
2993
2994
2996{
2998
2999 // If a plugin is removed or added, rebuild and reopen the new dialog
3000 while( result == NET_PLUGIN_CHANGE )
3002
3003 return 0;
3004}
3005
3006
3008{
3009 DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
3010
3011 wxCHECK( dlg, 0 );
3012
3013 // Needed at least on Windows. Raise() is not enough
3014 dlg->Show( true );
3015
3016 // Bring it to the top if already open. Dual monitor users need this.
3017 dlg->Raise();
3018
3019 dlg->ShowExportTab();
3020
3021 return 0;
3022}
3023
3024
3026{
3028 return 0;
3029}
3030
3031
3033{
3034 m_frame->RecalculateConnections( nullptr, LOCAL_CLEANUP );
3035
3036 // Create a selection with all items from the current sheet
3037 SCH_SELECTION sheetSelection;
3038 SCH_SCREEN* screen = m_frame->GetScreen();
3039
3040 for( SCH_ITEM* item : screen->Items() )
3041 {
3042 sheetSelection.Add( item );
3043 }
3044
3045 // Get the full page bounding box for rendering the complete sheet
3046 BOX2I pageBBox( VECTOR2I( 0, 0 ), m_frame->GetPageSizeIU() );
3047
3048 // Render the full sheet selection including the worksheet
3049 wxImage image = renderSelectionToImageForClipboard( m_frame, sheetSelection, pageBBox, true, true );
3050
3051 if( image.IsOk() )
3052 {
3053 wxLogNull doNotLog; // disable logging of failed clipboard actions
3054
3055 if( wxTheClipboard->Open() )
3056 {
3057 wxDataObjectComposite* data = new wxDataObjectComposite();
3058
3060
3061 wxTheClipboard->SetData( data );
3062 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
3063 wxTheClipboard->Close();
3064 }
3065 }
3066 else
3067 {
3068 wxLogMessage( _( "Cannot create the schematic image" ) );
3069 }
3070
3071 return 0;
3072}
3073
3074
3076{
3078 return 0;
3079}
3080
3081
3087
3088
3094
3095
3101
3102
3108
3109
3115
3116
3118{
3119 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3121
3123 m_frame->GetCanvas()->Refresh();
3124
3125 return 0;
3126}
3127
3128
3130{
3131 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3133
3135 m_frame->GetCanvas()->Refresh();
3136
3137 return 0;
3138}
3139
3140
3142{
3143 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3145
3147 m_frame->GetCanvas()->Refresh();
3148
3149 return 0;
3150}
3151
3152
3154{
3155 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3157
3159 m_frame->GetCanvas()->Refresh();
3160
3161 return 0;
3162}
3163
3164
3166{
3167 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3169
3171 m_frame->GetCanvas()->Refresh();
3172
3173 return 0;
3174}
3175
3176
3178{
3179 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3181
3182 m_frame->GetCanvas()->Refresh();
3183
3184 return 0;
3185}
3186
3187
3189{
3190 SCH_SHEET_PATH* sheetPath = &m_frame->GetCurrentSheet();
3191 wxString variant = m_frame->Schematic().GetCurrentVariant();
3192 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3194
3195 m_frame->GetCanvas()->GetView()->UpdateAllItemsConditionally(
3196 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
3197 {
3198 int flags = 0;
3199
3200 auto invalidateTextVars =
3201 [&flags]( EDA_TEXT* text )
3202 {
3203 if( text->HasTextVars() )
3204 {
3205 text->ClearRenderCache();
3206 text->ClearBoundingBoxCache();
3208 }
3209 };
3210
3211 if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
3212 {
3213 item->RunOnChildren(
3214 [&invalidateTextVars]( SCH_ITEM* aChild )
3215 {
3216 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild ) )
3217 invalidateTextVars( text );
3218 },
3220
3221 if( item->GetExcludedFromSim( sheetPath, variant ) )
3223 }
3224
3225 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
3226 invalidateTextVars( text );
3227
3228 return flags;
3229 } );
3230
3231 m_frame->GetCanvas()->Refresh();
3232
3233 return 0;
3234}
3235
3236
3238{
3239 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3241
3243 m_frame->RefreshOperatingPointDisplay();
3244 m_frame->GetCanvas()->Refresh();
3245
3246 return 0;
3247}
3248
3249
3251{
3252 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3254
3256 m_frame->RefreshOperatingPointDisplay();
3257 m_frame->GetCanvas()->Refresh();
3258
3259 return 0;
3260}
3261
3262
3264{
3265 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3267
3268 m_frame->GetRenderSettings()->m_ShowPinAltIcons = cfg->m_Appearance.show_pin_alt_icons;
3269
3271 m_frame->GetCanvas()->Refresh();
3272
3273 return 0;
3274}
3275
3276
3278{
3279 m_frame->eeconfig()->m_Drawing.line_mode = aEvent.Parameter<LINE_MODE>();
3280 m_toolMgr->PostAction( ACTIONS::refreshPreview );
3281 // Notify toolbar to update selection
3283 return 0;
3284}
3285
3286
3288{
3289 m_frame->eeconfig()->m_Drawing.line_mode++;
3290 m_frame->eeconfig()->m_Drawing.line_mode %= LINE_MODE::LINE_MODE_COUNT;
3291 m_toolMgr->PostAction( ACTIONS::refreshPreview );
3292 // Notify toolbar to update selection
3294 return 0;
3295}
3296
3297
3299{
3300 EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
3302 return 0;
3303}
3304
3305
3307{
3308 m_frame->ScriptingConsoleEnableDisable();
3309 return 0;
3310}
3311
3312
3314{
3315#ifdef KICAD_IPC_API
3316 if( Pgm().GetCommonSettings()->m_Api.enable_server )
3317 Pgm().GetPluginManager().ReloadPlugins();
3318#endif
3319 return 0;
3320}
3321
3323{
3324 // Update the left toolbar Line modes group icon to match current mode
3325 switch( static_cast<LINE_MODE>( m_frame->eeconfig()->m_Drawing.line_mode ) )
3326 {
3327 case LINE_MODE::LINE_MODE_FREE: m_frame->SelectToolbarAction( SCH_ACTIONS::lineModeFree ); break;
3328 case LINE_MODE::LINE_MODE_90: m_frame->SelectToolbarAction( SCH_ACTIONS::lineMode90 ); break;
3329 default:
3330 case LINE_MODE::LINE_MODE_45: m_frame->SelectToolbarAction( SCH_ACTIONS::lineMode45 ); break;
3331 }
3332
3333 return 0;
3334}
3335
3336
3338{
3339 int errors = 0;
3340 wxString details;
3341 bool quiet = aEvent.Parameter<bool>();
3342
3343 // Repair duplicate IDs.
3344 std::map<KIID, EDA_ITEM*> ids;
3345 int duplicates = 0;
3346
3347 SCH_SHEET_LIST sheets = m_frame->Schematic().Hierarchy();
3348
3349 auto processItem =
3350 [&]( EDA_ITEM* aItem )
3351 {
3352 auto it = ids.find( aItem->m_Uuid );
3353
3354 if( it != ids.end() && it->second != aItem )
3355 {
3356 duplicates++;
3357 const_cast<KIID&>( aItem->m_Uuid ) = KIID();
3358 }
3359
3360 ids[ aItem->m_Uuid ] = aItem;
3361 };
3362
3363 // Symbol IDs are the most important, so give them the first crack at "claiming" a
3364 // particular KIID.
3365
3366 for( const SCH_SHEET_PATH& sheet : sheets )
3367 {
3368 SCH_SCREEN* screen = sheet.LastScreen();
3369
3370 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
3371 {
3372 processItem( item );
3373
3374 for( SCH_PIN* pin : static_cast<SCH_SYMBOL*>( item )->GetPins( &sheet ) )
3375 processItem( pin );
3376 }
3377 }
3378
3379 for( const SCH_SHEET_PATH& sheet : sheets )
3380 {
3381 SCH_SCREEN* screen = sheet.LastScreen();
3382
3383 for( SCH_ITEM* item : screen->Items() )
3384 {
3385 processItem( item );
3386
3387 if( item->Type() != SCH_GROUP_T )
3388 {
3389 item->RunOnChildren(
3390 [&]( SCH_ITEM* aChild )
3391 {
3392 processItem( item );
3393 },
3395 }
3396 }
3397 }
3398
3399 /*******************************
3400 * Your test here
3401 */
3402
3403 /*******************************
3404 * Inform the user
3405 */
3406
3407 if( duplicates )
3408 {
3409 errors += duplicates;
3410 details += wxString::Format( _( "%d duplicate IDs replaced.\n" ), duplicates );
3411
3412 // Rehash sheetpaths as we may have changed their uuids.
3413 m_frame->Schematic().RefreshHierarchy();
3414 }
3415
3416 if( errors )
3417 {
3418 m_frame->OnModify();
3419
3420 wxString msg = wxString::Format( _( "%d potential problems repaired." ), errors );
3421
3422 if( !quiet )
3423 DisplayInfoMessage( m_frame, msg, details );
3424 }
3425 else if( !quiet )
3426 {
3427 DisplayInfoMessage( m_frame, _( "No errors found." ) );
3428 }
3429
3430 return 0;
3431}
3432
3433
3435{
3436 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
3437 return 0;
3438
3439 GRID_SETTINGS& gridSettings = m_toolMgr->GetSettings()->m_Window.grid;
3440 int currentIdx = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx;
3441
3442 wxArrayString gridsLabels;
3443
3444 for( const GRID& grid : gridSettings.grids )
3445 gridsLabels.Add( grid.UserUnitsMessageText( m_frame ) );
3446
3447 if( !m_frame->GetHotkeyPopup() )
3448 m_frame->CreateHotkeyPopup();
3449
3450 HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
3451
3452 if( popup )
3453 popup->Popup( _( "Grid" ), gridsLabels, currentIdx );
3454
3455 return 0;
3456}
3457
3458
3460{
3461 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3462
3463 if( !editFrame )
3464 return 1;
3465
3466 // Need to have a group selected and it needs to have a linked design block
3467 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3468 SCH_SELECTION selection = selTool->GetSelection();
3469
3470 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3471 return 1;
3472
3473 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3474
3475 if( !group->HasDesignBlockLink() )
3476 return 1;
3477
3478 // Get the associated design block
3479 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3480 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3481 true, true ) );
3482
3483 if( !designBlock )
3484 {
3485 wxString msg;
3486 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
3487 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3488 return 1;
3489 }
3490
3491 if( designBlock->GetSchematicFile().IsEmpty() )
3492 {
3493 wxString msg;
3494 msg.Printf( _( "Design block %s does not have a schematic file." ),
3495 group->GetDesignBlockLibId().GetUniStringLibId() );
3496 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3497 return 1;
3498 }
3499
3500 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3501
3502 return m_toolMgr->RunAction( SCH_ACTIONS::placeDesignBlock, designBlock.release() );
3503}
3504
3505
3507{
3508 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3509
3510 if( !editFrame )
3511 return 1;
3512
3513 // Need to have a group selected and it needs to have a linked design block
3514 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
3515 SCH_SELECTION selection = selTool->GetSelection();
3516
3517 if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T )
3518 return 1;
3519
3520 SCH_GROUP* group = static_cast<SCH_GROUP*>( selection[0] );
3521
3522 if( !group->HasDesignBlockLink() )
3523 return 1;
3524
3525 // Get the associated design block
3526 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
3527 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
3528 true, true ) );
3529
3530 if( !designBlock )
3531 {
3532 wxString msg;
3533 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
3534 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
3535 return 1;
3536 }
3537
3538 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
3539
3540 return m_toolMgr->RunAction( SCH_ACTIONS::updateDesignBlockFromSelection ) ? 1 : 0;
3541}
3542
3543
3545{
3546 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3547
3548 if( !editFrame )
3549 return 1;
3550
3551 editFrame->AddVariant();
3552
3553 return 0;
3554}
3555
3556
3558{
3559 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
3560
3561 if( !editFrame )
3562 return 1;
3563
3564 editFrame->RemoveVariant();
3565 return 0;
3566}
3567
3568
3570{
3571 Go( &SCH_EDITOR_CONTROL::New, ACTIONS::doNew.MakeEvent() );
3572 Go( &SCH_EDITOR_CONTROL::Open, ACTIONS::open.MakeEvent() );
3573 Go( &SCH_EDITOR_CONTROL::Save, ACTIONS::save.MakeEvent() );
3580 Go( &SCH_EDITOR_CONTROL::Plot, ACTIONS::plot.MakeEvent() );
3581
3584
3590
3593
3599
3602
3603 Go( &SCH_EDITOR_CONTROL::Undo, ACTIONS::undo.MakeEvent() );
3604 Go( &SCH_EDITOR_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
3605 Go( &SCH_EDITOR_CONTROL::Cut, ACTIONS::cut.MakeEvent() );
3606 Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() );
3611
3613
3629
3637
3654
3656
3658
3660
3663
3666}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
static TOOL_ACTION updatePcbFromSchematic
Definition actions.h:264
static TOOL_ACTION paste
Definition actions.h:80
static TOOL_ACTION revert
Definition actions.h:62
static TOOL_ACTION saveAs
Definition actions.h:59
static TOOL_ACTION copy
Definition actions.h:78
static TOOL_ACTION pluginsReload
Definition actions.h:294
static TOOL_ACTION pickerTool
Definition actions.h:253
static TOOL_ACTION showSymbolEditor
Definition actions.h:260
static TOOL_ACTION pasteSpecial
Definition actions.h:81
static TOOL_ACTION plot
Definition actions.h:65
static TOOL_ACTION open
Definition actions.h:57
static TOOL_ACTION pageSettings
Definition actions.h:63
static TOOL_ACTION showSearch
Definition actions.h:116
static TOOL_ACTION undo
Definition actions.h:75
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition actions.h:214
static TOOL_ACTION duplicate
Definition actions.h:84
static TOOL_ACTION doDelete
Definition actions.h:85
static TOOL_ACTION save
Definition actions.h:58
static TOOL_ACTION redo
Definition actions.h:76
static TOOL_ACTION updateSchematicFromPcb
Definition actions.h:265
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
static TOOL_ACTION print
Definition actions.h:64
static TOOL_ACTION showProperties
Definition actions.h:266
static TOOL_ACTION doNew
Definition actions.h:54
static TOOL_ACTION cut
Definition actions.h:77
static TOOL_ACTION copyAsText
Definition actions.h:79
static TOOL_ACTION refreshPreview
Definition actions.h:159
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:232
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
int GetPageCount() const
Definition base_screen.h:72
int GetVirtualPageNumber() const
Definition base_screen.h:75
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition base_screen.h:85
const wxString & GetPageNumber() const
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr Vec Centre() const
Definition box2.h:97
constexpr size_type GetHeight() const
Definition box2.h:215
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr const SizeVec & GetSize() const
Definition box2.h:206
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
int m_Threshold
Definition collector.h:236
static const COLOR4D CLEAR
Definition color4d.h:407
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:277
EDA_ITEM_FLAGS GetEditFlags() const
Definition eda_item.h:153
const KIID m_Uuid
Definition eda_item.h:521
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:197
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
void ClearBrightened()
Definition eda_item.h:143
void SetBrightened()
Definition eda_item.h:140
EDA_ITEM * GetParent() const
Definition eda_item.h:112
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:118
bool IsBrightened() const
Definition eda_item.h:129
SHAPE_POLY_SET & GetPolyShape()
Definition eda_shape.h:337
SHAPE_T GetShape() const
Definition eda_shape.h:169
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:216
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:174
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 bool IsVisible() const
Definition eda_text.h:187
bool validatePasteIntoSelection(const SELECTION &aSel, wxString &aErrorMsg)
Validate if paste-into-cells is possible for the given selection.
bool pasteCellsIntoSelection(const SELECTION &aSel, T_TABLE *aSourceTable, T_COMMIT &aCommit)
Paste text content from source table into selected cells.
PANEL_ANNOTATE m_AnnotatePanel
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
static const TOOL_EVENT ClearedEvent
Definition actions.h:347
static const TOOL_EVENT GridChangedByKeyEvent
Definition actions.h:365
static const TOOL_EVENT SelectedEvent
Definition actions.h:345
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:352
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:344
static const TOOL_EVENT UnselectedEvent
Definition actions.h:346
Similar to EDA_VIEW_SWITCHER, this dialog is a popup that shows feedback when using a hotkey to cycle...
void Popup(const wxString &aTitle, const wxArrayString &aItems, int aSelection)
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
static std::unique_ptr< CAIRO_PRINT_GAL > Create(GAL_DISPLAY_OPTIONS &aOptions, wxImage *aImage, double aDPI)
GAL_ANTIALIASING_MODE antialiasing_mode
The grid style to draw the grid in.
virtual bool HasNativeLandscapeRotation() const =0
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color used to draw a layer.
void SetDefaultFont(const wxString &aFont)
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
void SetIsPrinting(bool isPrinting)
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:1696
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition view.h:400
void ClearPreview()
Definition view.cpp:1718
static constexpr int VIEW_MAX_LAYERS
Maximum number of layers that may be shown.
Definition view.h:745
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1572
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition view.cpp:1644
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition view.cpp:1740
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition view.cpp:1623
bool EndsWith(const KIID_PATH &aPath) const
Test if aPath from the last path towards the first path.
Definition kiid.cpp:347
wxString AsString() const
Definition kiid.cpp:368
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:247
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:685
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
const wxString & Type() const
const wxString & Nickname() const
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
Define a library symbol object.
Definition lib_symbol.h:83
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:152
bool IsPower() const override
wxString GetName() const override
Definition lib_symbol.h:145
bool IsLocalPower() const override
bool IsGlobalPower() const override
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:41
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.
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:79
void SetHeightMils(double aHeightInMils)
void SetWidthMils(double aWidthInMils)
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.
SCHEMATIC_SETTINGS & Settings() const
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:103
const std::map< wxString, wxString > * GetProperties()
Definition schematic.h:106
SCH_SHEET & Root() const
Definition schematic.h:132
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:187
static TOOL_ACTION showPcbNew
static TOOL_ACTION assignFootprints
static TOOL_ACTION lineModeNext
static TOOL_ACTION toggleOPCurrents
static TOOL_ACTION saveToLinkedDesignBlock
Definition sch_actions.h:71
static TOOL_ACTION clearHighlight
static TOOL_ACTION removeVariant
static TOOL_ACTION editSymbolFields
static TOOL_ACTION importFPAssignments
static TOOL_ACTION toggleAnnotateAuto
static TOOL_ACTION editLibSymbolWithLibEdit
static TOOL_ACTION toggleERCWarnings
static TOOL_ACTION schematicSetup
static TOOL_ACTION toggleDirectiveLabels
static TOOL_ACTION highlightNetTool
static TOOL_ACTION findNetInInspector
static TOOL_ACTION toggleHiddenFields
static TOOL_ACTION saveCurrSheetCopyAs
Definition sch_actions.h:43
static TOOL_ACTION showRemoteSymbolPanel
static TOOL_ACTION repairSchematic
static TOOL_ACTION remapSymbols
static TOOL_ACTION lineMode45
static TOOL_ACTION editSymbolLibraryLinks
static TOOL_ACTION simTune
static TOOL_ACTION generateBOM
static TOOL_ACTION showHierarchy
static TOOL_ACTION showNetNavigator
static TOOL_ACTION markSimExclusions
static TOOL_ACTION placeImage
static TOOL_ACTION editWithLibEdit
static TOOL_ACTION toggleERCErrors
static TOOL_ACTION incrementAnnotations
static TOOL_ACTION 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 updateDesignBlockFromSelection
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
SCH_RENDER_SETTINGS * GetRenderSettings()
EESCHEMA_SETTINGS * eeconfig() const
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
Base class for a bus or wire entry.
void Collect(SCH_SCREEN *aScreen, const std::vector< KICAD_T > &aScanTypes, const VECTOR2I &aPos, int aUnit=0, int aBodyStyle=0)
Scan a EDA_ITEM using this class's Inspector method which does the collection.
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
virtual void Revert() override
Revert the commit by restoring the modified items state.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString Name(bool aIgnoreSheet=false) const
Handle actions specific to the schematic editor.
int PageSetup(const TOOL_EVENT &aEvent)
bool RescueLegacyProject(bool aRunningOnDemand)
int ToggleDirectiveLabels(const TOOL_EVENT &aEvent)
int SaveAs(const TOOL_EVENT &aEvent)
int MarkSimExclusions(const TOOL_EVENT &aEvent)
int Annotate(const TOOL_EVENT &aEvent)
int ShowSchematicSetup(const TOOL_EVENT &aEvent)
int HighlightNet(const TOOL_EVENT &aEvent)
Remove any net highlighting.
int ClearHighlight(const TOOL_EVENT &aEvent)
Update net highlighting after an edit.
int FindNetInInspector(const TOOL_EVENT &aEvent)
int EditSymbolFields(const TOOL_EVENT &aEvent)
int GenerateBOMLegacy(const TOOL_EVENT &aEvent)
int HighlightNetCursor(const TOOL_EVENT &aEvent)
int CopyAsText(const TOOL_EVENT &aEvent)
int AddVariant(const TOOL_EVENT &aEvent)
int ImportFPAssignments(const TOOL_EVENT &aEvent)
int ChangeLineMode(const TOOL_EVENT &aEvent)
void doCrossProbeSchToPcb(const TOOL_EVENT &aEvent, bool aForce)
int ExportSymbolsToLibrary(const TOOL_EVENT &aEvent)
int SaveCurrSheetCopyAs(const TOOL_EVENT &aEvent)
Saves the currently-open schematic sheet to an other name.
bool rescueProject(RESCUER &aRescuer, bool aRunningOnDemand)
int CrossProbeToPcb(const TOOL_EVENT &aEvent)
Equivalent to the above, but initiated by the user.
int PlaceLinkedDesignBlock(const TOOL_EVENT &aEvent)
int ToggleRemoteSymbolPanel(const TOOL_EVENT &aEvent)
int 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)
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
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.
wxString GetFullScreenDesc() const override
void ToggleSchematicHierarchy()
Toggle the show/hide state of the left side schematic navigation panel.
const wxString & GetHighlightedConnection() const
void UpdateNetHighlightStatus()
wxString GetScreenDesc() const override
Return a human-readable description of the current screen.
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.
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:116
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:526
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:258
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:252
virtual void SetLastResolvedState(const SCH_ITEM *aItem)
Definition sch_item.h:618
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:589
bool IsConnectivityDirty() const
Definition sch_item.h:587
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:471
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:541
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
void SetBackgroundColor(const COLOR4D &aColor) override
Set the background color.
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
void LoadColors(const COLOR_SETTINGS *aSettings) override
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:747
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.
const PAGE_INFO & GetPageSettings() const
Definition sch_screen.h:140
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:496
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
const wxString & GetFileName() const
Definition sch_screen.h:153
SCHEMATIC * Schematic() const
const TITLE_BLOCK & GetTitleBlock() const
Definition sch_screen.h:164
void Plot(PLOTTER *aPlotter, const SCH_PLOT_OPTS &aPlotOpts) const
Plot all the schematic objects to aPlotter.
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...
BOX2I GetBoundingBox() const override
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:48
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:376
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:145
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:233
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:511
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
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
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.
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)
virtual void Add(EDA_ITEM *aItem)
Definition selection.cpp:42
const std::deque< EDA_ITEM * > GetItems() const
Definition selection.h:126
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition selection.h:105
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the index-th vertex in a given hole outline within a given outline.
The SIMULATOR_FRAME holds the main user-interface for running simulations.
void AddCurrentTrace(const wxString &aDeviceName)
Add a current trace for a given device to the current plot.
void AddVoltageTrace(const wxString &aNetName)
Add a voltage trace for a given net to the current plot.
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
Definition sim_lib_mgr.h:48
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:422
const std::string & GetString()
Definition richio.h:445
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:226
The symbol library editor main window.
bool IsLibraryTreeShown() const override
void LoadSymbol(const wxString &aLibrary, const wxString &aSymbol, int Unit)
void LoadSymbolFromSchematic(SCH_SYMBOL *aSymbol)
Load a symbol from the schematic to edit in place.
void ToggleLibraryTree() override
An interface to the global shared library manager that is schematic-specific and linked to one projec...
Class to handle modifications to the symbol libraries.
Symbol library viewer main window.
SCH_EDIT_FRAME * getEditFrame() const
Definition tool_base.h:186
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:44
KIGFX::VIEW * getView() const
Definition tool_base.cpp:38
Generic, UI-independent tool event.
Definition tool_event.h:171
bool DisableGridSnapping() const
Definition tool_event.h:371
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
void Go(int(SCH_EDIT_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Master controller class:
TOOLS_HOLDER * GetToolHolder() const
A wrapper for reporting to a wxString object.
Definition reporter.h:191
const wxString & GetMessages() const
Definition reporter.cpp:78
std::unique_ptr< wxBitmap > GetImageFromClipboard()
Get image data from the clipboard, if there is any.
bool EncodeImageToPng(const wxImage &aImage, wxMemoryBuffer &aOutput)
Encode an image to PNG format with fast compression settings optimized for clipboard use.
bool AddTransparentImageToClipboardData(wxDataObjectComposite *aData, wxImage aImage)
Adds an image to clipboard data in a platform-specific way such that transparency is supported.
bool SaveClipboard(const std::string &aTextUTF8)
Store information to the system clipboard.
Definition clipboard.cpp:36
std::string GetClipboardUTF8()
Return the information currently stored in the system clipboard.
bool AddPngToClipboardData(wxDataObjectComposite *aData, const wxMemoryBuffer &aPngData, const wxImage *aFallbackImage)
Adds pre-encoded PNG data to clipboard in a platform-specific way.
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:629
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
#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_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:278
@ LAYER_ERC_WARN
Definition layer_ids.h:479
@ LAYER_ERC_ERR
Definition layer_ids.h:480
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:496
@ LAYER_OP_CURRENTS
Definition layer_ids.h:502
@ LAYER_SCHEMATIC_PAGE_LIMITS
Definition layer_ids.h:497
@ 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
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition definitions.h:38
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:717
void encode(const std::vector< uint8_t > &aInput, std::vector< uint8_t > &aOutput)
Definition base64.cpp:76
#define MAX_PAGE_SIZE_EESCHEMA_MILS
Definition page_info.h:36
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
Plotting engines similar to ps (PostScript, Gerber, svg)
static bool highlightNet(TOOL_MANAGER *aToolMgr, const VECTOR2D &aPosition)
#define HITTEST_THRESHOLD_PIXELS
static VECTOR2D CLEAR
Class to handle a set of SCH_ITEMs.
std::vector< EDA_ITEM * > EDA_ITEMS
ANNOTATE_ORDER_T
Schematic annotation order options.
ANNOTATE_ALGO_T
Schematic annotation type options.
wxString GetSelectedItemsAsText(const SELECTION &aSel)
constexpr double SCH_WORLD_UNIT(1e-7/0.0254)
@ 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)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::vector< GRID > grids
Common grid settings, available to every frame.
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
static constexpr auto NOT_CONNECTED
Definition sim_model.h:73
std::string refName
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
std::string path
KIBIS_MODEL * model
KIBIS_PIN * pin
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition tool_action.h:49
@ TA_UNDO_REDO_PRE
This event is sent before undo/redo command is performed.
Definition tool_event.h:106
@ TC_MESSAGE
Definition tool_event.h:58
@ SCH_GROUP_T
Definition typeinfo.h:177
@ SCH_TABLE_T
Definition typeinfo.h:169
@ SCH_LINE_T
Definition typeinfo.h:167
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_TABLECELL_T
Definition typeinfo.h:170
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_SHEET_T
Definition typeinfo.h:179
@ SCH_MARKER_T
Definition typeinfo.h:162
@ SCH_SHAPE_T
Definition typeinfo.h:153
@ SCH_PIN_T
Definition typeinfo.h:157
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:39
#define ZOOM_MIN_LIMIT_EESCHEMA
#define ZOOM_MAX_LIMIT_EESCHEMA