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