KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_symbol_fields_table.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) 2017 Oliver Walters
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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <advanced_config.h>
22#include <common.h>
23#include <base_units.h>
24#include <confirm.h>
25#include <eda_doc.h>
26#include <fields_grid_table.h>
27#include <schematic_settings.h>
28#include <general.h>
29#include <grid_tricks.h>
30#include <string_utils.h>
31#include <template_fieldnames.h>
32#include <kiface_base.h>
33#include <sch_edit_frame.h>
34#include <sch_group.h>
35#include <widgets/wx_infobar.h>
36#include <sch_reference_list.h>
40#include <widgets/wx_grid.h>
41#include <wx/debug.h>
42#include <wx/grid.h>
43#include <wx/textdlg.h>
44#include <wx/msgdlg.h>
49#include <project_sch.h>
51#include <jobs/job_export_bom.h>
52#include <tools/sch_actions.h>
54#include <sch_sheet_path.h>
55
56wxDEFINE_EVENT( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxCommandEvent );
57
59
60
61// Used for the footprint chooser grid helper
62static wxString getFootprintChooserSymbolNetlist( const std::vector<SCH_REFERENCE>& aReferences,
63 const wxString& aVariantName )
64{
65 std::vector<LIB_SYMBOL*> symbols;
66
67 for( const SCH_REFERENCE& reference : aReferences )
68 {
69 SCH_SYMBOL* symbol = reference.GetSymbol();
70
71 if( !symbol )
72 return wxEmptyString;
73
74 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
75
76 if( LIB_SYMBOL* variantSymbol =
77 symbol->GetVariantLibSymbol( aVariantName, reference.GetSheetPath() ) )
78 {
79 libSymbol = variantSymbol;
80 }
81
82 symbols.push_back( libSymbol );
83 }
84
85 return BuildFootprintChooserSymbolNetlist( symbols );
86}
87
88
89enum
90{
99};
100
102{
103public:
105 VIEW_CONTROLS_GRID_DATA_MODEL* aViewFieldsData,
107 FIELDS_TABLE_GRID_TRICKS( aParent, aGrid, aDataModel ),
108 m_dlg( aParent ),
109 m_viewControlsDataModel( aViewFieldsData ),
110 m_dataModel( aDataModel ),
111 m_files( aFiles )
112 {}
113
114protected:
115 bool toggleCell( int aRow, int aCol, bool aPreserveSelection = false ) override
116 {
117 if( !m_grid->IsEditable() || m_dataModel->IsCellReadOnly( aRow, aCol ) )
118 return false;
119
120 return GRID_TRICKS::toggleCell( aRow, aCol, aPreserveSelection );
121 }
122
123 void showFieldsTablePopupMenu( wxMenu& aMenu, wxGridEvent& aEvent ) override
124 {
125 int row = m_grid->GetGridCursorRow();
126 int col = m_grid->GetGridCursorCol();
127
128 if( row >= 0 && col >= 0 )
129 {
130 if( m_dataModel->GetColFieldName( col ) == GetDefaultFieldName( FIELD_T::FOOTPRINT, UNTRANSLATED ) )
131 {
132 aMenu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ), _( "Browse for footprint" ) );
133 aMenu.AppendSeparator();
134 }
135 else if( m_dataModel->GetColFieldName( col ) == GetDefaultFieldName( FIELD_T::DATASHEET, UNTRANSLATED ) )
136 {
137 aMenu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ), _( "Show datasheet in browser" ) );
138 aMenu.AppendSeparator();
139 }
140
141 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( m_dlg->GetParent() );
142
143 if( frame && !frame->Schematic().GetCurrentVariant().IsEmpty() )
144 {
145 std::vector<SCH_REFERENCE> refs = m_dataModel->GetRowReferences( row );
146
147 if( refs.size() == 1 && refs[0].GetSymbol() )
148 {
149 aMenu.AppendSeparator();
150 aMenu.Append( MYID_SET_VARIANT_SYMBOL, _( "Set Variant Symbol..." ) );
151
152 const SCH_SYMBOL* symbol = refs[0].GetSymbol();
153 wxString variantName = frame->Schematic().GetCurrentVariant();
154 auto variant = symbol->GetVariant( refs[0].GetSheetPath(), variantName );
155
156 if( variant && variant->m_SymbolOverride )
157 aMenu.Append( MYID_CLEAR_VARIANT_SYMBOL, _( "Clear Variant Symbol" ) );
158 }
159 }
160 }
161
162 GRID_TRICKS::showPopupMenu( aMenu, aEvent );
163 }
164
165 void doFieldsTablePopupSelection( wxCommandEvent& aEvent ) override
166 {
167 int row = m_grid->GetGridCursorRow();
168 int col = m_grid->GetGridCursorCol();
169
170 if( aEvent.GetId() == MYID_SELECT_FOOTPRINT )
171 {
172 // pick a footprint using the footprint picker.
173 wxString fpid = m_grid->GetCellValue( row, col );
174
175 wxString symbolNetlist = getFootprintChooserSymbolNetlist(
176 m_dataModel->GetRowReferences( row ), m_dataModel->GetCurrentVariant() );
177
178 if( SelectFootprintFromChooser( m_dlg, fpid, symbolNetlist ) )
179 m_grid->SetCellValue( row, col, fpid );
180 }
181 else if( aEvent.GetId() == MYID_SHOW_DATASHEET )
182 {
183 wxString datasheetUri = m_grid->GetCellValue( row, col );
184 GetAssociatedDocument( m_dlg, datasheetUri, &m_dlg->Prj(), PROJECT_SCH::SchSearchS( &m_dlg->Prj() ),
185 { m_files } );
186 }
187 else if( aEvent.GetId() == MYID_SET_VARIANT_SYMBOL
188 || aEvent.GetId() == MYID_CLEAR_VARIANT_SYMBOL )
189 {
190 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( m_dlg->GetParent() );
191
192 if( !frame )
193 return;
194
195 std::vector<SCH_REFERENCE> refs = m_dataModel->GetRowReferences( row );
196
197 if( refs.size() != 1 || !refs[0].GetSymbol() )
198 return;
199
200 SCH_SELECTION_TOOL* selectionTool = frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
201 std::vector<SCH_ITEM*> items = { refs[0].GetSymbol() };
202 selectionTool->SyncSelection( refs[0].GetSheetPath(), nullptr, items );
203
204 if( aEvent.GetId() == MYID_SET_VARIANT_SYMBOL )
206 else
208 }
209 else if( aEvent.GetId() >= GRIDTRICKS_FIRST_SHOWHIDE )
210 {
211 if( !m_grid->CommitPendingChanges( false ) )
212 return;
213
214 // Pop-up column order is the order of the shown fields, not the viewControls order
215 col = aEvent.GetId() - GRIDTRICKS_FIRST_SHOWHIDE;
216
217 bool show = !m_dataModel->GetShowColumn( col );
218
219 m_dlg->ShowHideColumn( col, show );
220
221 wxString fieldName = m_dataModel->GetColFieldName( col );
222
223 for( row = 0; row < m_viewControlsDataModel->GetNumberRows(); row++ )
224 {
225 if( m_viewControlsDataModel->GetUntranslatedFieldName( row ) == fieldName )
226 m_viewControlsDataModel->SetValueAsBool( row, SHOW_FIELD_COLUMN, show );
227 }
228
229 if( m_viewControlsDataModel->GetView() )
230 m_viewControlsDataModel->GetView()->ForceRefresh();
231 }
232 else
233 {
235 }
236 }
237
238private:
243};
244
245
247 DIALOG_FIELDS_TABLE( aParent, aParent->eeconfig()->m_FieldEditorPanel,
248 aParent->Schematic().Settings(), aJob ),
249 m_parent( aParent ),
250 m_templateFieldNames( aParent->Prj().GetProjectFile().m_TemplateFieldNames )
251{
252 // Get all symbols from the list of schematic sheets
253 m_parent->Schematic().Hierarchy().GetSymbols( m_symbolsList, SYMBOL_FILTER_NON_POWER );
254
255 if( auto conflicts = DetectFieldCaseConflicts( m_symbolsList ); !conflicts.empty() )
256 {
257 DIALOG_RESOLVE_FIELD_CASE_CONFLICTS resolver( this, m_parent, std::move( conflicts ) );
258
259 if( resolver.ShowModal() != wxID_OK )
260 {
261 m_aborted = true;
262 return;
263 }
264
265 m_symbolsList.Clear();
266 m_parent->Schematic().Hierarchy().GetSymbols( m_symbolsList, SYMBOL_FILTER_NON_POWER );
267 }
268
270
271 m_grid->UseNativeColHeader( true );
272 m_grid->SetTable( m_dataModel, true );
273
274 // The field-list grid regroups its rows, so the dialog's position-based Ctrl+Z would shift
275 // values onto the wrong field.
277
278 // must be done after SetTable(), which appears to re-set it
279 m_grid->SetSelectionMode( wxGrid::wxGridSelectCells );
280
281 // add Cut, Copy, and Paste to wxGrid
283 &m_parent->Schematic() ) );
284
285 m_variantListBox->Set( m_parent->Schematic().GetVariantNamesForUI() );
286
287 // A job keeps its own variant, otherwise follow the schematic.
288 wxString variantToSelect;
289
290 if( m_job )
291 variantToSelect = m_job->GetSelectedVariant();
292 else
293 variantToSelect = m_parent->Schematic().GetCurrentVariant();
294
295 if( !variantToSelect.IsEmpty() )
296 {
297 int toSelect = m_variantListBox->FindString( variantToSelect );
298
299 if( toSelect == wxNOT_FOUND )
300 m_variantListBox->SetSelection( 0 );
301 else
302 m_variantListBox->SetSelection( toSelect );
303 }
304 else
305 {
306 m_variantListBox->SetSelection( 0 );
307 }
308
310
311 if( m_job )
312 SetTitle( m_job->GetSettingsDialogTitle() );
313 else
314 SetTitle( _( "Symbol Fields Table" ) );
315
316 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
317 // non-job versions (which have different sizes).
318 m_hash_key = TO_UTF8( GetTitle() );
319
320 // Set the current variant for highlighting variant-specific field values
321 m_dataModel->SetCurrentVariant( resolveVariant() );
322
324 m_grid->ClearSelection();
325
327
329
330 SetSize( GetDefaultDialogSize() );
331
333
335
336 if( m_job )
337 m_outputFileName->SetValue( m_job->GetConfiguredOutputPath() );
338 else
339 m_outputFileName->SetValue( m_cfgBomSettings.m_BomExportFileName );
340
341 Center();
342
343 // Connect Events
344 m_grid->Bind( wxEVT_GRID_COL_SORT, &DIALOG_SYMBOL_FIELDS_TABLE::OnColSort, this );
345 m_grid->Bind( wxEVT_GRID_COL_MOVE, &DIALOG_SYMBOL_FIELDS_TABLE::OnColMove, this );
346 m_grid->GetGridWindow()->Bind( wxEVT_MOTION, &DIALOG_SYMBOL_FIELDS_TABLE::OnGridMouseMove, this );
349
350 if( !m_job )
351 {
352 // Start listening for schematic changes
353 m_parent->Schematic().AddListener( this );
354 }
355 else
356 {
357 // Don't allow editing
358 m_grid->EnableEditing( false );
359 m_buttonApply->Hide();
360 m_buttonExport->Hide();
361 }
362}
363
364
366{
367 if( m_aborted )
368 return;
369
372
373 // Disconnect Events
374 m_grid->GetGridWindow()->Unbind( wxEVT_MOTION, &DIALOG_SYMBOL_FIELDS_TABLE::OnGridMouseMove, this );
375 m_grid->Unbind( wxEVT_GRID_COL_SORT, &DIALOG_SYMBOL_FIELDS_TABLE::OnColSort, this );
376 m_grid->Unbind( wxEVT_GRID_COL_MOVE, &DIALOG_SYMBOL_FIELDS_TABLE::OnColMove, this );
379
380 // Delete the GRID_TRICKS.
381 m_grid->PopEventHandler( true );
382
383 // we gave ownership of m_viewControlsDataModel & m_dataModel to the wxGrids...
384}
385
386
388{
389 return new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ), { &m_parent->Schematic() } );
390}
391
392
394{
395 return new GRID_CELL_FPID_EDITOR(
396 this,
397 [this]( int aRow )
398 {
399 return getFootprintChooserSymbolNetlist( m_dataModel->GetRowReferences( aRow ),
400 m_dataModel->GetCurrentVariant() );
401 } );
402}
403
404
406{
407 if( !wxDialog::TransferDataToWindow() )
408 return false;
409
410 LoadFieldNames(); // loads rows into m_viewControlsDataModel and columns into m_dataModel
411
412 // Load our BOM view presets
413 SetUserBomPresets( m_cfgBomSettings.m_BomPresets );
414
415 BOM_PRESET preset = m_cfgBomSettings.m_BomSettings;
416
417 if( m_job )
418 loadJobBomPreset( *m_job, preset );
419
420 ApplyBomPreset( preset );
422
423 // Load BOM export format presets
424 SetUserBomFmtPresets( m_cfgBomSettings.m_BomFmtPresets );
425 BOM_FMT_PRESET fmtPreset = m_cfgBomSettings.m_BomFmtSettings;
426
427 if( m_job )
428 loadJobBomFmtPreset( *m_job, fmtPreset );
429
430 ApplyBomFmtPreset( fmtPreset );
432
433 if( !m_job )
434 m_outputFileName->SetValue( m_cfgBomSettings.m_BomExportFileName );
435
436 TOOL_MANAGER* toolManager = m_parent->GetToolManager();
437 SCH_SELECTION_TOOL* selectionTool = toolManager->GetTool<SCH_SELECTION_TOOL>();
438 SCH_SELECTION& selection = selectionTool->GetSelection();
439 SCH_SYMBOL* symbol = nullptr;
440
441 m_dataModel->SetGroupingEnabled( m_groupSymbolsBox->GetValue() );
442
443 setScope( static_cast<SCOPE>( m_scope->GetSelection() ) );
444
445 if( selection.GetSize() == 1 )
446 {
447 EDA_ITEM* item = selection.Front();
448
449 if( item->Type() == SCH_SYMBOL_T )
450 symbol = static_cast<SCH_SYMBOL*>( item );
451 else if( item->GetParent() && item->GetParent()->Type() == SCH_SYMBOL_T )
452 symbol = static_cast<SCH_SYMBOL*>( item->GetParent() );
453 }
454
455 if( symbol )
456 {
457 for( int row = 0; row < m_dataModel->GetNumberRows(); ++row )
458 {
459 std::vector<SCH_REFERENCE> references = m_dataModel->GetRowReferences( row );
460 bool found = false;
461
462 for( const SCH_REFERENCE& ref : references )
463 {
464 if( ref.GetSymbol() == symbol )
465 {
466 found = true;
467 break;
468 }
469 }
470
471 if( found )
472 {
473 // Find the value column and the reference column if they're shown
474 int valueCol = -1;
475 int refCol = -1;
476 int anyCol = -1;
477
478 for( int col = 0; col < m_dataModel->GetNumberCols(); col++ )
479 {
480 if( m_dataModel->ColIsValue( col ) )
481 valueCol = col;
482 else if( m_dataModel->ColIsReference( col ) )
483 refCol = col;
484 else if( anyCol == -1 && m_dataModel->GetShowColumn( col ) )
485 anyCol = col;
486 }
487
488 if( valueCol != -1 && m_dataModel->GetShowColumn( valueCol ) )
489 m_grid->GoToCell( row, valueCol );
490 else if( refCol != -1 && m_dataModel->GetShowColumn( refCol ) )
491 m_grid->GoToCell( row, refCol );
492 else if( anyCol != -1 )
493 m_grid->GoToCell( row, anyCol );
494
495 break;
496 }
497 }
498 }
499
500 // We don't want table range selection events to happen until we've loaded the data or we
501 // we'll clear our selection as the grid is built before the code above can get the
502 // user's current selection.
504
505 return true;
506}
507
508
510{
511 if( !m_grid->CommitPendingChanges() )
512 return false;
513
514 if( !wxDialog::TransferDataFromWindow() )
515 return false;
516
517 if( m_job )
518 {
519 // and exit, don't even dream of saving changes from the data model
520 return true;
521 }
522
523 SCH_COMMIT commit( m_parent );
524 SCH_SHEET_PATH currentSheet = m_parent->GetCurrentSheet();
525 wxString currentVariant = m_parent->Schematic().GetCurrentVariant();
526
527 m_dataModel->ApplyData( commit, m_templateFieldNames, currentVariant );
528
529 if( !commit.Empty() )
530 {
531 commit.Push( wxS( "Symbol Fields Table Edit" ) ); // Push clears the commit buffer.
532 m_parent->OnModify();
533 }
534
535 // Reset the view to where we left the user
536 m_parent->SetCurrentSheet( currentSheet );
537 m_parent->SyncView();
538 m_parent->Refresh();
539
540 return true;
541}
542
543
545{
546 auto addMandatoryField =
547 [&]( FIELD_T aFieldId, bool aShow, bool aGroupBy )
548 {
549 m_mandatoryFieldListIndexes[aFieldId] = m_viewControlsDataModel->GetNumberRows();
550
552 aShow, aGroupBy );
553 };
554
555 // Add mandatory fields first show groupBy
556 addMandatoryField( FIELD_T::REFERENCE, true, true );
557 addMandatoryField( FIELD_T::VALUE, true, true );
558 addMandatoryField( FIELD_T::FOOTPRINT, true, true );
559 addMandatoryField( FIELD_T::DATASHEET, true, false );
560 addMandatoryField( FIELD_T::DESCRIPTION, false, false );
561
562 // Generated fields present only in the fields table
565
566 // User field names are stored and matched case-sensitively (see issue #24021), so each
567 // distinct name gets its own column rather than collapsing case variants together.
568 std::set<wxString> userFieldNames;
569
570 for( const SCH_REFERENCE& ref : m_symbolsList )
571 {
572 SCH_SYMBOL* symbol = ref.GetSymbol();
573
574 for( const SCH_FIELD& field : symbol->GetFields() )
575 {
576 if( !field.IsMandatory() && !field.IsPrivate() )
577 userFieldNames.insert( field.GetName() );
578 }
579 }
580
581 for( const wxString& fieldName : userFieldNames )
582 AddField( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, false );
583
584 // Add any templateFieldNames which aren't already present.
585 for( const TEMPLATE_FIELDNAME& templateField : m_templateFieldNames.GetResolvedTemplateFieldNames() )
586 {
587 if( userFieldNames.count( templateField.m_Name ) == 0 )
588 AddField( templateField.m_Name, GetGeneratedFieldDisplayName( templateField.m_Name ), false, false );
589 }
590}
591
592
594{
595 m_dataModel->SetPath( m_parent->GetCurrentSheet() );
596 m_dataModel->SetScope( aScope );
597
598 if( aScope == SCOPE::SCOPE_SELECTION )
600
601 m_dataModel->RebuildRows();
602}
603
604
606{
607 std::unordered_set<KIID_PATH> selectionItems;
608 SCH_SELECTION_TOOL* selectionTool = m_parent->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
609 const SCH_SELECTION& selection = selectionTool->GetSelection();
610 const KIID_PATH currentSheetPath = m_parent->GetCurrentSheet().Path();
611
612 auto addSelectionItem = [&]( EDA_ITEM* aItem )
613 {
614 SCH_SYMBOL* symbol = nullptr;
615
616 if( aItem->Type() == SCH_SYMBOL_T )
617 symbol = static_cast<SCH_SYMBOL*>( aItem );
618 else if( aItem->GetParent() && aItem->GetParent()->Type() == SCH_SYMBOL_T )
619 symbol = static_cast<SCH_SYMBOL*>( aItem->GetParent() );
620
621 if( symbol )
622 {
623 KIID_PATH path = currentSheetPath;
624 path.push_back( symbol->m_Uuid );
625 selectionItems.insert( path );
626
627 return;
628 }
629
630 if( aItem->Type() == SCH_SHEET_T )
631 {
632 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
633
634 SCH_SHEET_PATH selectedPath = m_parent->GetCurrentSheet();
635 selectedPath.push_back( sheet );
636
637 SCH_REFERENCE_LIST references;
638 m_parent->Schematic().Hierarchy().GetSymbolsWithinPath( references, selectedPath, SYMBOL_FILTER_NON_POWER );
639
640 for( const SCH_REFERENCE& ref : references )
641 {
642 if( ref.GetSymbol() )
643 {
644 KIID_PATH path = ref.GetSheetPath().Path();
645 path.push_back( ref.GetSymbol()->m_Uuid );
646 selectionItems.insert( path );
647 }
648 }
649 }
650 };
651
652 for( EDA_ITEM* item : selection )
653 {
654 if( item->Type() == SCH_GROUP_T )
655 static_cast<SCH_GROUP*>( item )->RunOnChildren( addSelectionItem, RECURSE_MODE::RECURSE );
656 else
657 addSelectionItem( item );
658 }
659
660 m_dataModel->SetSelectionItems( selectionItems );
661}
662
663
664void DIALOG_SYMBOL_FIELDS_TABLE::OnScope( wxCommandEvent& aEvent )
665{
666 switch( aEvent.GetSelection() )
667 {
668 case 0: setScope( SCOPE::SCOPE_ALL ); break;
669 case 1: setScope( SCOPE::SCOPE_SHEET ); break;
670 case 2: setScope( SCOPE::SCOPE_SHEET_RECURSIVE ); break;
671 case 3: setScope( SCOPE::SCOPE_SELECTION ); break;
672 }
673}
674
675
676void DIALOG_SYMBOL_FIELDS_TABLE::OnMenu( wxCommandEvent& aEvent )
677{
678 // Build a pop menu:
679 wxMenu menu;
680
681 menu.Append( MYID_INCLUDE_DNP, _( "Include 'DNP' Symbols" ),
682 _( "Show symbols marked 'DNP' in the table. This setting also controls whether or not 'DNP' "
683 "symbols are included on export." ),
684 wxITEM_CHECK );
685 menu.Check( MYID_INCLUDE_DNP, !m_dataModel->GetExcludeDNP() );
686
687 menu.Append( MYID_INCLUDE_EXCLUDED_FROM_BOM, _( "Include 'Exclude from BOM' Symbols" ),
688 _( "Show symbols marked 'Exclude from BOM' in the table. Symbols marked 'Exclude from BOM' "
689 "are never included on export." ),
690 wxITEM_CHECK );
691 menu.Check( MYID_INCLUDE_EXCLUDED_FROM_BOM, m_dataModel->GetIncludeExcludedFromBOM() );
692
693 menu.AppendSeparator();
694
695 menu.Append( MYID_HIGHLIGHT_ON_CROSS_PROBE, _( "Highlight on Cross-probe" ),
696 _( "Highlight corresponding item on canvas when it is selected in the table" ),
697 wxITEM_CHECK );
698 menu.Check( MYID_HIGHLIGHT_ON_CROSS_PROBE, m_cfgDialogSettings.selection_mode == 0 );
699
700 menu.Append( MYID_SELECT_ON_CROSS_PROBE, _( "Select on Cross-probe" ),
701 _( "Select corresponding item on canvas when it is selected in the table" ),
702 wxITEM_CHECK );
703 menu.Check( MYID_SELECT_ON_CROSS_PROBE, m_cfgDialogSettings.selection_mode == 1 );
704
705 // menuId is the selected submenu id from the popup menu or wxID_NONE
706 int menuId = m_bMenu->GetPopupMenuSelectionFromUser( menu );
707
708 if( menuId == 0 || menuId == MYID_INCLUDE_DNP )
709 {
710 m_dataModel->SetExcludeDNP( !m_dataModel->GetExcludeDNP() );
711 m_dataModel->RebuildRows();
712 m_grid->ForceRefresh();
713
715 }
716 else if( menuId == 1 || menuId == MYID_INCLUDE_EXCLUDED_FROM_BOM )
717 {
718 m_dataModel->SetIncludeExcludedFromBOM( !m_dataModel->GetIncludeExcludedFromBOM() );
719 m_dataModel->RebuildRows();
720 m_grid->ForceRefresh();
721
723 }
724 else if( menuId == 3 || menuId == MYID_HIGHLIGHT_ON_CROSS_PROBE )
725 {
726 if( m_cfgDialogSettings.selection_mode != 0 )
727 m_cfgDialogSettings.selection_mode = 0;
728 else
729 m_cfgDialogSettings.selection_mode = 2;
730 }
731 else if( menuId == 4 || menuId == MYID_SELECT_ON_CROSS_PROBE )
732 {
733 if( m_cfgDialogSettings.selection_mode != 1 )
734 m_cfgDialogSettings.selection_mode = 1;
735 else
736 m_cfgDialogSettings.selection_mode = 2;
737 }
738}
739
740
742{
743 // Cross-probing should only work in Edit page
744 if( m_nbPages->GetSelection() != 0 )
745 return;
746
747 // Cross-probing is disabled when we're in selection scope mode, otherwise
748 // we're just in a loop
749 if( m_dataModel->GetScope() == SCOPE::SCOPE_SELECTION )
750 return;
751
752 // Multi-select can grab the rows that are expanded child refs, and also the row
753 // containing the list of all child refs. Make sure we add refs/symbols uniquely
754 std::set<SCH_REFERENCE> refs;
755 std::set<SCH_ITEM*> symbols;
756
757 for( int row : aRows )
758 {
759 for( const SCH_REFERENCE& ref : m_dataModel->GetRowReferences( row ) )
760 refs.insert( ref );
761 }
762
763 for( const SCH_REFERENCE& ref : refs )
764 symbols.insert( ref.GetSymbol() );
765
766 if( m_cfgDialogSettings.selection_mode == 0 )
767 {
768 SCH_EDITOR_CONTROL* editor = m_parent->GetToolManager()->GetTool<SCH_EDITOR_CONTROL>();
769
770 if( refs.size() > 0 )
771 {
772 // Use of full path based on UUID allows select of not yet annotated or duplicated
773 // symbols
774 wxString symbolPath = refs.begin()->GetFullPath();
775
776 // Focus only handles one item at this time
777 editor->FindSymbolAndItem( &symbolPath, nullptr, true, HIGHLIGHT_SYMBOL, wxEmptyString );
778 }
779 else
780 {
781 m_parent->ClearFocus();
782 }
783 }
784 else if( m_cfgDialogSettings.selection_mode == 1 )
785 {
786 SCH_SELECTION_TOOL* selectionTool = m_parent->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
787 std::vector<SCH_ITEM*> items( symbols.begin(), symbols.end() );
788
789 if( refs.size() > 0 )
790 selectionTool->SyncSelection( refs.begin()->GetSheetPath(), nullptr, items );
791 else
792 selectionTool->ClearSelection();
793 }
794}
795
796
798{
800 {
801 m_cfgBomSettings.m_BomExportFileName = m_outputFileName->GetValue();
802 m_parent->SaveProject();
803 ClearModify();
804 }
805}
806
807
808void DIALOG_SYMBOL_FIELDS_TABLE::OnCancel( wxCommandEvent& aEvent )
809{
810 if( m_job )
811 {
812 EndModal( wxID_CANCEL );
813 }
814 else
815 {
816 // Discard any unsaved edit in the output filename field
817 m_outputFileName->SetValue( m_cfgBomSettings.m_BomExportFileName );
818 Close();
819 }
820}
821
822
823void DIALOG_SYMBOL_FIELDS_TABLE::OnOk( wxCommandEvent& aEvent )
824{
826 return;
827
828 if( m_job )
829 {
831 EndModal( wxID_OK );
832 }
833 else
834 {
835 if( m_cfgBomSettings.m_BomExportFileName != m_outputFileName->GetValue() )
836 {
837 m_cfgBomSettings.m_BomExportFileName = m_outputFileName->GetValue();
838 m_parent->OnModify();
839 }
840
841 Close();
842 }
843}
844
845
846void DIALOG_SYMBOL_FIELDS_TABLE::OnClose( wxCloseEvent& aEvent )
847{
848 if( m_job )
849 {
850 aEvent.Skip();
851 return;
852 }
853
854 m_grid->CommitPendingChanges( true );
855
856 if( m_dataModel->IsEdited() && aEvent.CanVeto() )
857 {
858 if( !HandleUnsavedChanges( this, _( "Save changes?" ),
859 [&]() -> bool
860 {
861 return TransferDataFromWindow();
862 } ) )
863 {
864 aEvent.Veto();
865 return;
866 }
867 }
868
869 if( savePresets( true ) )
870 m_parent->OnModify();
871
872 // Stop listening to schematic events
873 m_parent->Schematic().RemoveListener( this );
874 m_parent->ClearFocus();
875
876 wxCommandEvent* event = new wxCommandEvent( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxID_ANY );
877
878 if( wxWindow* parentWindow = GetParent() )
879 wxQueueEvent( parentWindow, event );
880}
881
882
883void DIALOG_SYMBOL_FIELDS_TABLE::OnSchItemsAdded( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem )
884{
885 std::set<KIID_PATH> savedSelection = SaveGridSelection();
886
887 SCH_REFERENCE_LIST allRefs;
888 m_parent->Schematic().Hierarchy().GetSymbols( allRefs, SYMBOL_FILTER_ALL );
889
890 for( SCH_ITEM* item : aSchItem )
891 {
892 if( item->Type() == SCH_SYMBOL_T )
893 {
894 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
895
896 // Don't add power symbols
897 if( !symbol->IsMissingLibSymbol() && symbol->IsPower() )
898 continue;
899
900 // Add all fields again in case this symbol has a new one
901 for( SCH_FIELD& field : symbol->GetFields() )
902 {
903 if( !field.IsMandatory() && !field.IsPrivate() )
904 AddField( field.GetUntranslatedName(), field.GetName(), true, false, false );
905 }
906
907 m_dataModel->AddReferences( getSymbolReferences( symbol, allRefs ) );
908 }
909 else if( item->Type() == SCH_SHEET_T )
910 {
911 std::set<SCH_SYMBOL*> symbols;
912 SCH_REFERENCE_LIST refs = getSheetSymbolReferences( *static_cast<SCH_SHEET*>( item ) );
913
914 for( SCH_REFERENCE& ref : refs )
915 symbols.insert( ref.GetSymbol() );
916
917 for( SCH_SYMBOL* symbol : symbols )
918 {
919 // Add all fields again in case this symbol has a new one
920 for( SCH_FIELD& field : symbol->GetFields() )
921 {
922 if( !field.IsMandatory() && !field.IsPrivate() )
923 AddField( field.GetUntranslatedName(), field.GetName(), true, false, false );
924 }
925 }
926
927 m_dataModel->AddReferences( refs );
928 }
929 }
930
931 rebuildRowsPreservingSelection( savedSelection );
932}
933
934
935void DIALOG_SYMBOL_FIELDS_TABLE::OnSchItemsRemoved( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem )
936{
937 std::set<KIID_PATH> savedSelection = SaveGridSelection();
938
939 for( SCH_ITEM* item : aSchItem )
940 {
941 if( item->Type() == SCH_SYMBOL_T )
942 m_dataModel->RemoveSymbol( *static_cast<SCH_SYMBOL*>( item ) );
943 else if( item->Type() == SCH_SHEET_T )
944 m_dataModel->RemoveReferences( getSheetSymbolReferences( *static_cast<SCH_SHEET*>( item ) ) );
945 }
946
947 rebuildRowsPreservingSelection( savedSelection );
948}
949
950
951void DIALOG_SYMBOL_FIELDS_TABLE::OnSchItemsChanged( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem )
952{
953 std::set<KIID_PATH> savedSelection = SaveGridSelection();
954
955 SCH_REFERENCE_LIST allRefs;
956 m_parent->Schematic().Hierarchy().GetSymbols( allRefs, SYMBOL_FILTER_ALL );
957
958 for( SCH_ITEM* item : aSchItem )
959 {
960 if( item->Type() == SCH_SYMBOL_T )
961 {
962 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
963
964 // Don't add power symbols
965 if( !symbol->IsMissingLibSymbol() && symbol->IsPower() )
966 continue;
967
968 // Add all fields again in case this symbol has a new one
969 for( SCH_FIELD& field : symbol->GetFields() )
970 {
971 if( !field.IsMandatory() && !field.IsPrivate() )
972 AddField( field.GetUntranslatedName(), field.GetName(), true, false, false );
973 }
974
975 m_dataModel->UpdateReferences( getSymbolReferences( symbol, allRefs ) );
976 }
977 else if( item->Type() == SCH_SHEET_T )
978 {
979 std::set<SCH_SYMBOL*> symbols;
980 SCH_REFERENCE_LIST refs = getSheetSymbolReferences( *static_cast<SCH_SHEET*>( item ) );
981
982 for( SCH_REFERENCE& ref : refs )
983 symbols.insert( ref.GetSymbol() );
984
985 for( SCH_SYMBOL* symbol : symbols )
986 {
987 // Add all fields again in case this symbol has a new one
988 for( SCH_FIELD& field : symbol->GetFields() )
989 {
990 if( !field.IsMandatory() && !field.IsPrivate() )
991 AddField( field.GetUntranslatedName(), field.GetName(), true, false, false );
992 }
993 }
994
995 m_dataModel->UpdateReferences( refs );
996 }
997 }
998
999 rebuildRowsPreservingSelection( savedSelection );
1000}
1001
1002
1004{
1005 m_dataModel->SetPath( aSch.CurrentSheet() );
1006
1007 if( m_dataModel->GetScope() != SCOPE::SCOPE_ALL )
1009}
1010
1011
1013{
1014 if( m_dataModel->GetScope() == SCOPE::SCOPE_SELECTION )
1016}
1017
1018
1023
1024
1025void DIALOG_SYMBOL_FIELDS_TABLE::rebuildRowsPreservingSelection( const std::set<KIID_PATH>& aSavedSelection )
1026{
1028
1029 if( m_dataModel->GetScope() == SCOPE::SCOPE_SELECTION )
1031
1032 m_dataModel->RebuildRows();
1033 RestoreGridSelection( aSavedSelection );
1034
1036}
1037
1038
1040 SCH_REFERENCE_LIST& aCachedRefs )
1041{
1042 SCH_REFERENCE_LIST symbolRefs;
1043
1044 for( size_t i = 0; i < aCachedRefs.GetCount(); i++ )
1045 {
1046 SCH_REFERENCE& ref = aCachedRefs[i];
1047
1048 if( ref.GetSymbol() == aSymbol )
1049 {
1050 ref.Split(); // Figures out if we are annotated or not
1051 symbolRefs.AddItem( ref );
1052 }
1053 }
1054
1055 return symbolRefs;
1056}
1057
1058
1060{
1061 SCH_SHEET_LIST allSheets = m_parent->Schematic().Hierarchy();
1062 SCH_REFERENCE_LIST sheetRefs;
1063
1064 // We need to operate on all instances of the sheet
1065 for( const SCH_SHEET_INSTANCE& instance : aSheet.GetInstances() )
1066 {
1067 // For every sheet instance we need to get the current schematic sheet
1068 // instance that matches that particular sheet path from the root
1069 for( SCH_SHEET_PATH& basePath : allSheets )
1070 {
1071 if( basePath.Path() == instance.m_Path )
1072 {
1073 SCH_SHEET_PATH sheetPath = basePath;
1074 sheetPath.push_back( &aSheet );
1075
1076 // Create a list of all sheets in this path, starting with the path
1077 // of the sheet that we just deleted, then all of its subsheets
1078 SCH_SHEET_LIST subSheets;
1079 subSheets.push_back( sheetPath );
1080 allSheets.GetSheetsWithinPath( subSheets, sheetPath );
1081
1082 subSheets.GetSymbolsWithinPath( sheetRefs, sheetPath, SYMBOL_FILTER_NON_POWER, false );
1083 break;
1084 }
1085 }
1086 }
1087
1088 for( SCH_REFERENCE& ref : sheetRefs )
1089 ref.Split();
1090
1091 return sheetRefs;
1092}
1093
1094
1095void DIALOG_SYMBOL_FIELDS_TABLE::onAddVariant( wxCommandEvent& aEvent )
1096{
1097 if( !m_parent->ShowAddVariantDialog( this ) )
1098 return;
1099
1100 wxArrayString ctrlContents;
1101 ctrlContents.Add( GetDefaultVariantName() );
1102
1103 for( const wxString& variant : m_parent->Schematic().GetVariantNames() )
1104 ctrlContents.Add( variant );
1105
1106 ctrlContents.Sort( SortVariantNames );
1107 m_variantListBox->Set( ctrlContents );
1108
1109 wxString currentVariant = m_parent->Schematic().GetCurrentVariant();
1110 int newSelection = m_variantListBox->FindString(
1111 currentVariant.IsEmpty() ? GetDefaultVariantName() : currentVariant );
1112
1113 if( newSelection != wxNOT_FOUND )
1114 m_variantListBox->SetSelection( newSelection );
1115
1117}
1118
1119
1121{
1122 int selection = m_variantListBox->GetSelection();
1123
1124 // An empty or default selection cannot be deleted.
1125 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
1126 {
1127 m_parent->GetInfoBar()->ShowMessageFor( _( "Cannot delete the default variant." ),
1128 10000, wxICON_ERROR );
1129 return;
1130 }
1131
1132 wxString variantName = m_variantListBox->GetString( selection );
1133 m_variantListBox->Delete( selection );
1134
1135 SCH_COMMIT commit( m_parent );
1136
1137 m_parent->Schematic().DeleteVariant( variantName, &commit );
1138
1139 if( !commit.Empty() )
1140 commit.Push( wxString::Format( wxS( "Delete Variant '%s'" ), variantName ) );
1141
1142 m_parent->OnModify();
1143
1144 int newSelection = std::max( 0, selection - 1 );
1145 m_variantListBox->SetSelection( newSelection );
1146
1147 wxString selectedVariant = getSelectedVariant();
1148 m_parent->SetCurrentVariant( selectedVariant );
1149
1150 if( m_grid->CommitPendingChanges( true ) )
1151 {
1152 m_dataModel->SetCurrentVariant( selectedVariant );
1153 m_dataModel->UpdateReferences( m_dataModel->GetReferenceList() );
1154 m_dataModel->RebuildRows();
1155
1156 if( m_nbPages->GetSelection() == 1 )
1158 else
1159 m_grid->ForceRefresh();
1160 }
1161
1163 m_parent->UpdateVariantSelectionCtrl( m_parent->Schematic().GetVariantNamesForUI() );
1164}
1165
1166
1168{
1169 int selection = m_variantListBox->GetSelection();
1170
1171 // An empty or default selection cannot be renamed.
1172 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
1173 {
1174 m_parent->GetInfoBar()->ShowMessageFor( _( "Cannot rename the default variant." ),
1175 10000, wxICON_ERROR );
1176 return;
1177 }
1178
1179 wxString oldVariantName = m_variantListBox->GetString( selection );
1180
1181 wxTextEntryDialog dlg( this, _( "Enter new variant name:" ), _( "Rename Design Variant" ),
1182 oldVariantName, wxOK | wxCANCEL | wxCENTER );
1183
1184 if( dlg.ShowModal() == wxID_CANCEL )
1185 return;
1186
1187 wxString newVariantName = dlg.GetValue().Trim().Trim( false );
1188
1189 // Empty name is not allowed.
1190 if( newVariantName.IsEmpty() )
1191 {
1192 m_parent->GetInfoBar()->ShowMessageFor( _( "Variant name cannot be empty." ), 10000, wxICON_ERROR );
1193 return;
1194 }
1195
1196 // Reserved name is not allowed (case-insensitive).
1197 if( newVariantName.CmpNoCase( GetDefaultVariantName() ) == 0 )
1198 {
1199 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format( _( "'%s' is a reserved variant name." ),
1201 10000, wxICON_ERROR );
1202 return;
1203 }
1204
1205 // Same name (exact match) - nothing to do
1206 if( newVariantName == oldVariantName )
1207 return;
1208
1209 // Duplicate name is not allowed (case-insensitive).
1210 for( const wxString& existingName : m_parent->Schematic().GetVariantNames() )
1211 {
1212 if( existingName.CmpNoCase( newVariantName ) == 0
1213 && existingName.CmpNoCase( oldVariantName ) != 0 )
1214 {
1215 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format( _( "Variant '%s' already exists." ),
1216 existingName ),
1217 0000, wxICON_ERROR );
1218 return;
1219 }
1220 }
1221
1222 m_parent->Schematic().RenameVariant( oldVariantName, newVariantName );
1223 m_parent->OnModify();
1224
1225 wxArrayString ctrlContents = m_variantListBox->GetStrings();
1226 ctrlContents.Remove( oldVariantName );
1227 ctrlContents.Add( newVariantName );
1228 ctrlContents.Sort( SortVariantNames );
1229 m_variantListBox->Set( ctrlContents );
1230
1231 int newSelection = m_variantListBox->FindString( newVariantName );
1232
1233 if( newSelection != wxNOT_FOUND )
1234 m_variantListBox->SetSelection( newSelection );
1235
1237 m_parent->UpdateVariantSelectionCtrl( m_parent->Schematic().GetVariantNamesForUI() );
1238}
1239
1240
1241void DIALOG_SYMBOL_FIELDS_TABLE::onCopyVariant( wxCommandEvent& aEvent )
1242{
1243 int selection = m_variantListBox->GetSelection();
1244
1245 // An empty or default selection cannot be copied.
1246 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
1247 {
1248 m_parent->GetInfoBar()->ShowMessageFor( _( "Cannot copy the default variant." ),
1249 10000, wxICON_ERROR );
1250 return;
1251 }
1252
1253 wxString sourceVariantName = m_variantListBox->GetString( selection );
1254
1255 wxTextEntryDialog dlg( this, _( "Enter name for the copied variant:" ), _( "Copy Design Variant" ),
1256 sourceVariantName + wxS( "_copy" ), wxOK | wxCANCEL | wxCENTER );
1257
1258 if( dlg.ShowModal() == wxID_CANCEL )
1259 return;
1260
1261 wxString newVariantName = dlg.GetValue().Trim().Trim( false );
1262
1263 // Empty name is not allowed.
1264 if( newVariantName.IsEmpty() )
1265 {
1266 m_parent->GetInfoBar()->ShowMessageFor( _( "Variant name cannot be empty." ), 10000, wxICON_ERROR );
1267 return;
1268 }
1269
1270 // Duplicate name is not allowed.
1271 if( m_variantListBox->FindString( newVariantName ) != wxNOT_FOUND )
1272 {
1273 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format( _( "Variant '%s' already exists." ),
1274 newVariantName ),
1275 10000, wxICON_ERROR );
1276 return;
1277 }
1278
1279 m_parent->Schematic().CopyVariant( sourceVariantName, newVariantName );
1280 m_parent->OnModify();
1281
1282 wxArrayString ctrlContents = m_variantListBox->GetStrings();
1283 ctrlContents.Add( newVariantName );
1284 ctrlContents.Sort( SortVariantNames );
1285 m_variantListBox->Set( ctrlContents );
1286
1287 int newSelection = m_variantListBox->FindString( newVariantName );
1288
1289 if( newSelection != wxNOT_FOUND )
1290 m_variantListBox->SetSelection( newSelection );
1291
1293 m_parent->UpdateVariantSelectionCtrl( m_parent->Schematic().GetVariantNamesForUI() );
1294}
1295
1296
1298{
1299 int selection = m_variantListBox->GetSelection();
1300
1301 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
1302 {
1303 m_parent->GetInfoBar()->ShowMessageFor( _( "Cannot edit the default variant description." ), 10000,
1304 wxICON_ERROR );
1305 return;
1306 }
1307
1308 wxString variantName = m_variantListBox->GetString( selection );
1309 wxString currentDesc = m_parent->Schematic().GetVariantDescription( variantName );
1310
1311 wxDialog dlg( this, wxID_ANY, wxString::Format( _( "Edit Description for '%s'" ), variantName ), wxDefaultPosition,
1312 wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
1313
1314 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
1315
1316 wxStaticText* label = new wxStaticText( &dlg, wxID_ANY, _( "Description:" ) );
1317 mainSizer->Add( label, 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 10 );
1318
1319 mainSizer->AddSpacer( 3 );
1320
1321 wxTextCtrl* descCtrl =
1322 new wxTextCtrl( &dlg, wxID_ANY, currentDesc, wxDefaultPosition, wxSize( 300, 60 ), wxTE_MULTILINE );
1323 mainSizer->Add( descCtrl, 1, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 10 );
1324
1325 wxStdDialogButtonSizer* btnSizer = new wxStdDialogButtonSizer();
1326 btnSizer->AddButton( new wxButton( &dlg, wxID_OK ) );
1327 btnSizer->AddButton( new wxButton( &dlg, wxID_CANCEL ) );
1328 btnSizer->Realize();
1329 mainSizer->Add( btnSizer, 0, wxALL | wxALIGN_RIGHT, 5 );
1330
1331 dlg.SetSizer( mainSizer );
1332 dlg.Fit();
1333 dlg.Centre();
1334
1335 if( dlg.ShowModal() == wxID_CANCEL )
1336 return;
1337
1338 wxString newDesc = descCtrl->GetValue().Trim().Trim( false );
1339
1340 m_parent->Schematic().SetVariantDescription( variantName, newDesc );
1341 m_parent->OnModify();
1342}
1343
1344
1346{
1347 wxString currentVariant;
1348 wxString selectedVariant = getSelectedVariant();
1349
1351
1352 if( m_job )
1353 {
1354 m_grid->CommitPendingChanges( true );
1355
1356 if( m_parent )
1357 m_parent->SetCurrentVariant( selectedVariant );
1358
1359 m_dataModel->SetCurrentVariant( selectedVariant );
1360 m_dataModel->UpdateReferences( m_dataModel->GetReferenceList() );
1361 m_dataModel->RebuildRows();
1362
1363 if( m_nbPages->GetSelection() == 1 )
1365 else
1366 m_grid->ForceRefresh();
1367
1369 return;
1370 }
1371
1372 if( m_parent )
1373 {
1374 currentVariant = m_parent->Schematic().GetCurrentVariant();
1375
1376 if( currentVariant != selectedVariant )
1377 m_parent->SetCurrentVariant( selectedVariant );
1378 }
1379
1380 if( currentVariant != selectedVariant )
1381 {
1382 m_grid->CommitPendingChanges( true );
1383
1384 SCH_COMMIT commit( m_parent );
1385
1386 m_dataModel->ApplyData( commit, m_templateFieldNames, currentVariant );
1387
1388 if( !commit.Empty() )
1389 {
1390 commit.Push( wxS( "Symbol Fields Table Edit" ) ); // Push clears the commit buffer.
1391 m_parent->OnModify();
1392 }
1393
1394 // Update the data model's current variant for field highlighting
1395 m_dataModel->SetCurrentVariant( selectedVariant );
1396 m_dataModel->UpdateReferences( m_dataModel->GetReferenceList() );
1397 m_dataModel->RebuildRows();
1398
1399 if( m_nbPages->GetSelection() == 1 )
1401 else
1402 m_grid->ForceRefresh();
1403
1405 }
1406}
1407
1408
1410{
1411 int selection = m_variantListBox->GetSelection();
1412
1413 // Copy, rename, and delete are only enabled for non-default variant selections
1414 bool canModify = ( selection != wxNOT_FOUND ) && ( selection != 0 );
1415
1416 m_copyVariantButton->Enable( canModify );
1417 m_renameVariantButton->Enable( canModify );
1418 m_editVariantDescButton->Enable( canModify );
1419 m_deleteVariantButton->Enable( canModify );
1420}
1421
1422
1424{
1425 // A job keeps its own variant, otherwise follow the schematic.
1426 if( m_job )
1427 return getSelectedVariant();
1428
1429 return m_parent->Schematic().GetCurrentVariant();
1430}
1431
1432
1434{
1435 SCHEMATIC& schematic = m_parent->Schematic();
1436
1437 return schematic.ResolveTextVar( &schematic.CurrentSheet(), aToken, 0 );
1438}
bool Empty() const
Definition commit.h:142
STD_BITMAP_BUTTON * m_renameVariantButton
STD_BITMAP_BUTTON * m_copyVariantButton
STD_BITMAP_BUTTON * m_deleteVariantButton
STD_BITMAP_BUTTON * m_editVariantDescButton
void saveJobSettings(JOB_EXPORT_BOM &aJob)
void SetUserBomFmtPresets(std::vector< BOM_FMT_PRESET > &aPresetList)
wxSize GetDefaultDialogSize() const
void OnColMove(wxGridEvent &aEvent)
void OnColSort(wxGridEvent &aEvent)
void OnGridMouseMove(wxMouseEvent &aEvent)
bool savePresets(bool aSaveCurrentSettings)
wxString getSelectedVariant() const
void RestoreGridSelection(const std::set< KIID_PATH > &aItemKeys)
Restore a selection previously returned by SaveGridSelection().
std::map< FIELD_T, int > m_mandatoryFieldListIndexes
void onBomFmtPresetChanged(wxCommandEvent &aEvent)
void SetUserBomPresets(std::vector< BOM_PRESET > &aPresetList)
void ApplyBomFmtPreset(const wxString &aPresetName)
DIALOG_FIELDS_TABLE(wxWindow *aParent, FIELDS_TABLE_SETTINGS &aPanelSettings, FIELDS_TABLE_BOM_SETTINGS &aBomSettings, JOB_EXPORT_BOM *aJob)
FIELDS_TABLE_BOM_SETTINGS & m_cfgBomSettings
static void loadJobBomFmtPreset(const JOB_EXPORT_BOM &aJob, BOM_FMT_PRESET &aPreset)
FIELDS_TABLE_SETTINGS & m_cfgDialogSettings
static void loadJobBomPreset(const JOB_EXPORT_BOM &aJob, BOM_PRESET &aPreset)
void onBomPresetChanged(wxCommandEvent &aEvent)
std::set< KIID_PATH > SaveGridSelection()
Save the grid selection by stable item identity so it can survive a row rebuild.
void ApplyBomPreset(const wxString &aPresetName)
VIEW_CONTROLS_GRID_DATA_MODEL * m_viewControlsDataModel
void AddField(const wxString &aFieldName, const wxString &aLabelValue, bool aShow, bool aGroupBy, bool aAddedByUser=false)
void ExcludeFromControlUndoRedo(wxWindow *aWindow)
Opt a control out of the dialog's generic Ctrl+Z/Ctrl+Y undo/redo.
void OptOut(wxWindow *aWindow)
Opt out of control state saving.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:94
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void OnSaveAndContinue(wxCommandEvent &aEvent) override
void OnSchItemsRemoved(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem) override
void onAddVariant(wxCommandEvent &aEvent) override
SCH_REFERENCE_LIST getSheetSymbolReferences(SCH_SHEET &aSheet)
wxGridCellEditor * createDatasheetEditor() override
void OnOk(wxCommandEvent &aEvent) override
void OnSchSelectionChanged(SCHEMATIC &aSch) override
void OnSchItemsAdded(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem) override
void OnSchItemsChanged(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem) override
void OnTableSelectionChanged(const std::set< int > &aRows) override
SYMBOL_FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
void onVariantSelectionChange(wxCommandEvent &aEvent) override
void OnClose(wxCloseEvent &aEvent) override
void OnSchSheetChanged(SCHEMATIC &aSch) override
void onCopyVariant(wxCommandEvent &aEvent) override
void setScope(SYMBOL_FIELDS_EDITOR_GRID_DATA_MODEL::SCOPE aScope)
void onDeleteVariant(wxCommandEvent &aEvent) override
DIALOG_SYMBOL_FIELDS_TABLE(SCH_EDIT_FRAME *aParent, JOB_EXPORT_BOM *aJob=nullptr)
void OnCancel(wxCommandEvent &aEvent) override
void OnMenu(wxCommandEvent &aEvent) override
SCH_REFERENCE_LIST getSymbolReferences(SCH_SYMBOL *aSymbol, SCH_REFERENCE_LIST &aCachedRefs)
bool resolveTextVar(wxString *aToken) const override
void onRenameVariant(wxCommandEvent &aEvent) override
void LoadFieldNames()
Construct the rows of m_fieldsCtrl and the columns of m_dataModel from a union of all field names in ...
void OnScope(wxCommandEvent &aEvent) override
wxGridCellEditor * createFootprintEditor() override
void onEditVariantDescription(wxCommandEvent &aEvent) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
const KIID m_Uuid
Definition eda_item.h:597
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM * GetParent() const
Definition eda_item.h:112
static const wxString ITEM_NUMBER_VARIABLE
FIELDS_TABLE_GRID_TRICKS(DIALOG_FIELDS_TABLE *aDialog, WX_GRID *aGrid, FIELDS_TABLE_DATA_MODEL_BASE *aDataModel)
static constexpr int FIRST_CLIENT_ID
virtual void doPopupSelection(wxCommandEvent &event)
virtual void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent)
WX_GRID * m_grid
I don't own the grid, but he owns me.
virtual bool toggleCell(int aRow, int aCol, bool aPreserveSelection=false)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
Define a library symbol object.
Definition lib_symbol.h:119
static SEARCH_STACK * SchSearchS(PROJECT *aProject)
Accessor for Eeschema search stack.
Holds all the data relating to one schematic.
Definition schematic.h:148
wxString GetCurrentVariant() const
Return the current variant being edited.
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:303
static TOOL_ACTION clearVariantSymbol
static TOOL_ACTION setVariantSymbol
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Handle actions specific to the schematic editor.
Schematic editor (Eeschema) main window.
SCHEMATIC & Schematic() const
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:48
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void AddItem(const SCH_REFERENCE &aItem)
A helper to define a symbol's reference designator in a schematic.
void Split()
Attempt to split the reference designator into a name (U) and number (1).
SCH_SYMBOL * GetSymbol() const
void SyncSelection(const std::optional< SCH_SHEET_PATH > &targetSheetPath, SCH_ITEM *focusItem, const std::vector< SCH_ITEM * > &items)
int ClearSelection(const TOOL_EVENT &aEvent)
Select all visible items in sheet.
SCH_SELECTION & GetSelection()
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void GetSymbolsWithinPath(SCH_REFERENCE_LIST &aReferences, const SCH_SHEET_PATH &aSheetPath, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets that are contained wi...
void GetSheetsWithinPath(std::vector< SCH_SHEET_PATH > &aSheets, const SCH_SHEET_PATH &aSheetPath) const
Add a SCH_SHEET_PATH object to aSheets for each sheet in the list that are contained within aSheetPat...
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:519
Schematic symbol object.
Definition sch_symbol.h:75
std::optional< SCH_SYMBOL_VARIANT > GetVariant(const SCH_SHEET_PATH &aInstance, const wxString &aVariantName) const
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
bool IsMissingLibSymbol() const
Check to see if the library symbol is set to the dummy library symbol.
LIB_SYMBOL * GetVariantLibSymbol(const wxString &aVariantName, const SCH_SHEET_PATH &aPath) const
Resolve the alternate library symbol for a given variant.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:183
bool IsPower() const override
void showFieldsTablePopupMenu(wxMenu &aMenu, wxGridEvent &aEvent) override
SYMBOL_FIELDS_EDITOR_GRID_TRICKS(DIALOG_SYMBOL_FIELDS_TABLE *aParent, WX_GRID *aGrid, VIEW_CONTROLS_GRID_DATA_MODEL *aViewFieldsData, SYMBOL_FIELDS_EDITOR_GRID_DATA_MODEL *aDataModel, EMBEDDED_FILES *aFiles)
SYMBOL_FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
void doFieldsTablePopupSelection(wxCommandEvent &aEvent) override
bool toggleCell(int aRow, int aCol, bool aPreserveSelection=false) override
VIEW_CONTROLS_GRID_DATA_MODEL * m_viewControlsDataModel
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Master controller class:
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
wxString GetGeneratedFieldDisplayName(const wxString &aSource)
Returns any variables unexpanded, e.g.
Definition common.cpp:481
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:146
This file is part of the common library.
LIB_FIELDS_EDITOR_GRID_DATA_MODEL::SCOPE SCOPE
@ MYID_INCLUDE_EXCLUDED_FROM_BOM
wxDEFINE_EVENT(EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxCommandEvent)
static wxString getFootprintChooserSymbolNetlist(const std::vector< SCH_REFERENCE > &aReferences, const wxString &aVariantName)
@ MYID_HIGHLIGHT_ON_CROSS_PROBE
#define _(s)
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, PROJECT *aProject, SEARCH_STACK *aPaths, std::vector< EMBEDDED_FILES * > aFilesStack)
Open a document (file) with the suitable browser.
Definition eda_doc.cpp:59
This file is part of the common library.
@ RECURSE
Definition eda_item.h:51
static FILENAME_RESOLVER * resolver
wxString BuildFootprintChooserSymbolNetlist(const LIB_SYMBOL *aSymbol)
bool SelectFootprintFromChooser(DIALOG_SHIM *aDialog, wxString &aFootprint, const wxString &aSymbolNetlist)
@ GRIDTRICKS_FIRST_SHOWHIDE
Definition grid_tricks.h:47
@ HIGHLIGHT_SYMBOL
Class to handle a set of SCH_ITEMs.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
@ SYMBOL_FILTER_NON_POWER
@ SYMBOL_FILTER_ALL
wxString GetDefaultVariantName()
int SortVariantNames(const wxString &aLhs, const wxString &aRhs)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
A simple container for sheet instance information.
Hold a name of a symbol's field, field value, and default visibility.
std::vector< FIELD_CASE_CONFLICT > DetectFieldCaseConflicts(const SCH_REFERENCE_LIST &aSymbols)
wxString GetDefaultFieldName(FIELD_T aFieldId, TRANSLATION aTranslation)
Return a default symbol field name for a mandatory field type.
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
@ UNTRANSLATED
@ TRANSLATED
std::string path
@ SCH_GROUP_T
Definition typeinfo.h:169
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_SHEET_T
Definition typeinfo.h:171