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