47#include <wx/textdlg.h>
48#include <wx/filedlg.h>
61#define COLUMN_MARGIN 4
63#define COLUMN_MARGIN 15
109 int col =
m_grid->GetGridCursorCol();
114 menu.AppendSeparator();
119 menu.AppendSeparator();
127 int row =
m_grid->GetGridCursorRow();
128 int col =
m_grid->GetGridCursorCol();
133 wxString fpid =
m_grid->GetCellValue( row, col );
137 if( frame->ShowModal( &fpid,
m_dlg ) )
138 m_grid->SetCellValue( row, col, fpid );
145 wxString datasheet_uri =
m_grid->GetCellValue( row, col );
151 if( !
m_grid->CommitPendingChanges(
false ) )
159 m_dlg->ShowHideColumn( col, show );
161 wxString fieldName =
m_dataModel->GetColFieldName( col );
203 if(
resolver.ShowModal() != wxID_OK )
244 wxGridCellAttr* attr =
new wxGridCellAttr;
245 attr->SetReadOnly(
true );
248 attr =
new wxGridCellAttr;
249 attr->SetRenderer(
new wxGridCellBoolRenderer() );
251 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
254 attr =
new wxGridCellAttr;
255 attr->SetRenderer(
new wxGridCellBoolRenderer() );
257 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
263 m_filter->SetDescriptiveText(
_(
"Filter" ) );
265 attr =
new wxGridCellAttr;
269 m_grid->UseNativeColHeader(
true );
277 m_grid->SetSelectionMode( wxGrid::wxGridSelectCells );
286 wxString variantToSelect;
289 variantToSelect =
m_job->GetSelectedVariant();
291 variantToSelect =
m_parent->Schematic().GetCurrentVariant();
293 if( !variantToSelect.IsEmpty() )
297 if( toSelect == wxNOT_FOUND )
310 SetTitle(
m_job->GetSettingsDialogTitle() );
335 CallAfter( [
this, cfg]()
365 m_parent->Schematic().AddListener(
this );
370 m_grid->EnableEditing(
false );
389 for(
int i = 0; i <
m_grid->GetNumberCols(); i++ )
391 if(
m_grid->IsColShown( i ) )
393 std::string fieldName(
m_dataModel->GetColFieldName( i ).ToUTF8() );
408 m_grid->PopEventHandler(
true );
418 if( aIsLeftPanelCollapsed )
433 wxGridCellAttr* attr =
new wxGridCellAttr;
434 attr->SetReadOnly(
false );
458 attr->SetAlignment( wxALIGN_RIGHT, wxALIGN_CENTER );
459 attr->SetRenderer(
new wxGridCellNumberRenderer() );
464 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
477 attr->SetEditor(
m_grid->GetDefaultEditor() );
486 wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
489 m_grid->AutoSizeColumns(
false );
491 bool sortAscending =
true;
493 for(
int col = 0; col <
m_grid->GetNumberCols(); ++col )
519 std::string key(
m_dataModel->GetColFieldName( col ).ToUTF8() );
529 int maxWidth = defaultDlgSize.x / 3;
531 m_grid->SetColSize( col, std::clamp( textWidth, 100, maxWidth ) );
541 m_grid->SetSortingColumn( sortCol, sortAscending );
547 if( !wxDialog::TransferDataToWindow() )
570 for(
const wxString& fieldName :
m_job->m_fieldsOrdered )
573 field.
name = fieldName;
574 field.
show = !fieldName.StartsWith( wxT(
"__" ), &field.
name );
577 if( (
m_job->m_fieldsLabels.size() > i ) && !
m_job->m_fieldsLabels[i].IsEmpty() )
598 fmtPreset.
name =
m_job->m_bomFmtPresetName;
619 if( selection.GetSize() == 1 )
631 for(
int row = 0; row <
m_dataModel->GetNumberRows(); ++row )
633 std::vector<SCH_REFERENCE> references =
m_dataModel->GetRowReferences( row );
638 if( ref.GetSymbol() == symbol )
652 for(
int col = 0; col <
m_dataModel->GetNumberCols(); col++ )
658 else if( anyCol == -1 &&
m_dataModel->GetShowColumn( col ) )
662 if( valueCol != -1 &&
m_dataModel->GetShowColumn( valueCol ) )
663 m_grid->GoToCell( row, valueCol );
664 else if( refCol != -1 &&
m_dataModel->GetShowColumn( refCol ) )
665 m_grid->GoToCell( row, refCol );
666 else if( anyCol != -1 )
667 m_grid->GoToCell( row, anyCol );
685 if( !
m_grid->CommitPendingChanges() )
688 if( !wxDialog::TransferDataFromWindow() )
699 wxString currentVariant =
m_parent->Schematic().GetCurrentVariant();
703 if( !commit.
Empty() )
705 commit.
Push( wxS(
"Symbol Fields Table Edit" ) );
710 m_parent->SetCurrentSheet( currentSheet );
719 bool show,
bool groupBy,
bool addedByUser )
729 m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser,
m_parent->Schematic().GetCurrentVariant() );
731 wxGridTableMessage msg(
m_dataModel, wxGRIDTABLE_NOTIFY_COLS_APPENDED, 1 );
732 m_grid->ProcessTableMessage( msg );
735 [&]() -> std::pair<int, int>
746 auto addMandatoryField =
747 [&](
FIELD_T fieldId,
bool show,
bool groupBy )
767 auto caseInsensitiveLess = [](
const wxString& a,
const wxString& b )
769 return a.CmpNoCase( b ) < 0;
772 std::map<wxString, std::map<wxString, int>,
decltype( caseInsensitiveLess )> userFieldGroups( caseInsensitiveLess );
780 if( !field.IsMandatory() && !field.IsPrivate() )
781 userFieldGroups[field.GetName()][field.GetName()]++;
785 for(
const auto& [groupKey, exactCounts] : userFieldGroups )
787 wxString canonicalName;
791 canonicalName = tfn->m_Name;
797 for(
const auto& [
name, count] : exactCounts )
799 if( count > bestCount )
802 canonicalName =
name;
813 if( userFieldGroups.count( tfn.m_Name ) == 0 )
821 wxTextEntryDialog dlg(
this,
_(
"New field name:" ),
_(
"Add Field" ) );
823 if( dlg.ShowModal() != wxID_OK )
826 wxString fieldName = dlg.GetValue();
828 if( fieldName.IsEmpty() )
834 for(
int i = 0; i <
m_dataModel->GetNumberCols(); ++i )
836 if( fieldName.CmpNoCase(
m_dataModel->GetColFieldName( i ) ) == 0 )
838 DisplayError(
this, wxString::Format(
_(
"Field name '%s' already in use." ), fieldName ) );
861 DisplayError(
this, wxString::Format(
_(
"The first %d fields are mandatory." ),
867 return IsOK(
this, wxString::Format(
_(
"Are you sure you want to remove the field '%s'?" ),
873 int col =
m_dataModel->GetFieldNameCol( fieldName );
893 if( selectedRows.empty() )
896 int row = selectedRows[0];
902 DisplayError(
this, wxString::Format(
_(
"The first %d fields are mandatory and names cannot be changed." ),
912 int col =
m_dataModel->GetFieldNameCol( fieldName );
913 wxCHECK_RET( col != -1, wxS(
"Existing field name missing from data model" ) );
915 wxTextEntryDialog dlg(
this,
_(
"New field name:" ),
_(
"Rename Field" ), fieldName );
917 if( dlg.ShowModal() != wxID_OK )
920 wxString newFieldName = dlg.GetValue();
923 if( newFieldName == fieldName )
927 if(
m_dataModel->GetFieldNameCol( newFieldName ) != -1 )
929 wxString confirm_msg = wxString::Format(
_(
"Field name %s already exists." ), newFieldName );
938 if( labelIsAutogenerated )
962#if defined( __WXOSX__ )
963 wxPoint pos = aEvent.GetPosition();
964 wxRect ctrlRect =
m_filter->GetScreenRect();
965 int buttonWidth = ctrlRect.GetHeight();
968 if(
m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
969 SetCursor( wxCURSOR_ARROW );
970 else if(
m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
971 SetCursor( wxCURSOR_ARROW );
973 SetCursor( wxCURSOR_IBEAM );
988 switch( aEvent.GetSelection() )
990 case 0:
setScope( SCOPE::SCOPE_ALL );
break;
991 case 1:
setScope( SCOPE::SCOPE_SHEET );
break;
992 case 2:
setScope( SCOPE::SCOPE_SHEET_RECURSIVE );
break;
1014 menu.Append( 4204,
_(
"Include 'DNP' Symbols" ),
1015 _(
"Show symbols marked 'DNP' in the table. This setting also controls whether or not 'DNP' "
1016 "symbols are included on export." ),
1018 menu.Check( 4204, !
m_dataModel->GetExcludeDNP() );
1020 menu.Append( 4205,
_(
"Include 'Exclude from BOM' Symbols" ),
1021 _(
"Show symbols marked 'Exclude from BOM' in the table. Symbols marked 'Exclude from BOM' "
1022 "are never included on export." ),
1024 menu.Check( 4205,
m_dataModel->GetIncludeExcludedFromBOM() );
1026 menu.AppendSeparator();
1028 menu.Append( 4206,
_(
"Highlight on Cross-probe" ),
1029 _(
"Highlight corresponding item on canvas when it is selected in the table" ),
1033 menu.Append( 4207,
_(
"Select on Cross-probe" ),
1034 _(
"Select corresponding item on canvas when it is selected in the table" ),
1039 int menu_id =
m_bMenu->GetPopupMenuSelectionFromUser( menu );
1041 if( menu_id == 0 || menu_id == 4204 )
1049 else if( menu_id == 1 || menu_id == 4205 )
1057 else if( menu_id == 3 || menu_id == 4206 )
1064 else if( menu_id == 4 || menu_id == 4207 )
1076 int sortCol = aEvent.GetCol();
1077 std::string key(
m_dataModel->GetColFieldName( sortCol ).ToUTF8() );
1089 if(
m_grid->IsSortingBy( sortCol ) )
1092 ascending = !
m_grid->IsSortOrderAscending();
1110 int origPos = aEvent.GetCol();
1115 for(
int i = 0; i <
m_grid->GetNumberCols(); i++ )
1117 if(
m_grid->IsColShown( i ) )
1119 std::string fieldName(
m_dataModel->GetColFieldName( i ).ToUTF8() );
1127 int newPos =
m_grid->GetColPos( origPos );
1130 if( newPos < origPos )
1171 int row = aEvent.GetRow();
1173 wxCHECK( row < m_viewControlsGrid->GetNumberRows(), );
1175 switch( aEvent.GetCol() )
1181 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
1186 m_grid->SetColLabelValue( dataCol, label );
1204 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
1216 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
1218 if(
m_dataModel->ColIsQuantity( dataCol ) && value )
1220 DisplayError(
this,
_(
"The Quantity column cannot be grouped by." ) );
1227 if(
m_dataModel->ColIsItemNumber( dataCol ) && value )
1229 DisplayError(
this,
_(
"The Item Number column cannot be grouped by." ) );
1278 if(
m_dataModel->IsExpanderColumn( event.GetCol() ) )
1280 m_grid->ClearSelection();
1283 m_grid->SetGridCursor( event.GetRow(), event.GetCol() );
1296 wxPoint pos = aEvent.GetPosition();
1298 m_grid->CalcUnscrolledPosition( pos.x, pos.y, &ux, &uy );
1299 int row =
m_grid->YToRow( uy );
1300 int col =
m_grid->XToCol( ux );
1303 if( row == wxNOT_FOUND || col == wxNOT_FOUND )
1305 m_grid->GetGridWindow()->UnsetToolTip();
1309 wxString rawValue =
m_dataModel->GetValue( row, col );
1311 if( rawValue.Contains( wxT(
"${" ) ) )
1313 m_grid->GetGridWindow()->SetToolTip( rawValue );
1317 m_grid->GetGridWindow()->UnsetToolTip();
1332 std::set<SCH_REFERENCE> refs;
1333 std::set<SCH_ITEM*> symbols;
1336 if( aEvent.Selecting() )
1338 for(
int i = aEvent.GetTopRow(); i <= aEvent.GetBottomRow(); i++ )
1345 symbols.insert( ref.GetSymbol() );
1352 if( refs.size() > 0 )
1356 wxString symbol_path = refs.begin()->GetFullPath();
1369 std::vector<SCH_ITEM*> items( symbols.begin(), symbols.end() );
1371 if( refs.size() > 0 )
1372 selTool->
SyncSelection( refs.begin()->GetSheetPath(),
nullptr, items );
1385 int remainingWidth =
m_viewControlsGrid->GetSize().GetX() - showColWidth - groupByColWidth;
1434 bool saveIncludeExcudedFromBOM =
m_dataModel->GetIncludeExcludedFromBOM();
1441 if( saveIncludeExcudedFromBOM )
1485 wxFileName fn(
Prj().AbsolutePath(
m_parent->Schematic().GetFileName() ) );
1488 wxFileDialog saveDlg(
this,
_(
"Bill of Materials Output File" ),
path, fn.GetFullName(),
1493 if( saveDlg.ShowModal() == wxID_CANCEL )
1497 wxFileName file = wxFileName( saveDlg.GetPath() );
1498 wxString defaultPath = fn.GetPathWithSep();
1500 if(
IsOK(
this, wxString::Format(
_(
"Do you want to use a path relative to\n'%s'?" ), defaultPath ) ) )
1502 if( !file.MakeRelativeTo( defaultPath ) )
1504 DisplayErrorMessage(
this,
_(
"Cannot make path relative (target volume different from schematic "
1505 "file volume)!" ) );
1539 _(
"Changes have not yet been saved. Export unsaved data?" ),
"",
1540 _(
"OK" ),
_(
"Cancel" ) )
1550 std::function<bool( wxString* )> textResolver =
1551 [&]( wxString* token ) ->
bool
1556 return schematic.ResolveTextVar( &schematic.CurrentSheet(), token, 0 );
1561 if(
path.IsEmpty() )
1563 DisplayError(
this,
_(
"No output file specified in Export tab." ) );
1570 wxFileName outputFile = wxFileName::FileName(
path );
1576 msg.Printf(
_(
"Could not open/create path '%s'." ), outputFile.GetPath() );
1581 wxFFile out( outputFile.GetFullPath(),
"wb" );
1583 if( !out.IsOpened() )
1585 msg.Printf(
_(
"Could not create BOM output '%s'." ), outputFile.GetFullPath() );
1594 msg.Printf(
_(
"Could not write BOM output '%s'." ), outputFile.GetFullPath() );
1601 msg.Printf(
_(
"Wrote BOM output to '%s'" ), outputFile.GetFullPath() );
1609 EndModal( wxID_CANCEL );
1626 m_job->m_bomFmtPresetName = wxEmptyString;
1631 m_job->m_bomPresetName = wxEmptyString;
1648 m_job->m_fieldsOrdered.clear();
1649 m_job->m_fieldsLabels.clear();
1650 m_job->m_fieldsGroupBy.clear();
1654 if( modelField.show )
1655 m_job->m_fieldsOrdered.emplace_back( modelField.name );
1657 m_job->m_fieldsOrdered.emplace_back( wxT(
"__" ) + modelField.name );
1659 m_job->m_fieldsLabels.emplace_back( modelField.label );
1661 if( modelField.groupBy )
1662 m_job->m_fieldsGroupBy.emplace_back( modelField.name );
1667 EndModal( wxID_OK );
1684 m_grid->CommitPendingChanges(
true );
1700 m_parent->Schematic().RemoveListener(
this );
1703 wxCommandEvent* evt =
new wxCommandEvent( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxID_ANY );
1705 if( wxWindow* parent = GetParent() )
1706 wxQueueEvent( parent, evt );
1712 std::vector<BOM_PRESET> ret;
1714 for(
const std::pair<const wxString, BOM_PRESET>& pair :
m_bomPresets )
1716 if( !pair.second.readOnly )
1717 ret.emplace_back( pair.second );
1729 for(
const BOM_PRESET& preset : aPresetList )
1747 wxCommandEvent
dummy;
1790 int default_idx = 0;
1794 m_cbBomPresets->Append( wxGetTranslation( presetName ), (
void*) &preset );
1819 [&](
const std::pair<const wxString, BOM_PRESET>& aPair )
1821 const BOM_PRESET& preset = aPair.second;
1824 if( !( preset.sortAsc == current.sortAsc
1825 && preset.filterString == current.filterString
1826 && preset.groupSymbols == current.groupSymbols
1827 && preset.excludeDNP == current.excludeDNP
1828 && preset.includeExcludedFromBOM == current.includeExcludedFromBOM ) )
1839 if( preset.sortField != wxGetTranslation( current.
sortField ) )
1843 std::vector<BOM_FIELD>
A,
B;
1845 for(
const BOM_FIELD& field : preset.fieldsOrdered )
1847 if( field.show || field.groupBy )
1848 A.emplace_back( field );
1853 if( field.show || field.groupBy )
1854 B.emplace_back( field );
1860 if( it != m_bomPresets.end() )
1864 bool do_translate = it->second.readOnly;
1865 wxString
text = do_translate ? wxGetTranslation( it->first ) : it->first;
1866 m_cbBomPresets->SetStringSelection(
text );
1870 m_cbBomPresets->SetSelection( m_cbBomPresets->GetCount() - 3 );
1873 m_currentBomPreset =
static_cast<BOM_PRESET*
>( m_cbBomPresets->GetClientData( m_cbBomPresets->GetSelection() ) );
1882 wxString ui_label = aName;
1886 if( presetName == aName )
1888 if( preset.readOnly ==
true )
1889 ui_label = wxGetTranslation( aName );
1914 auto resetSelection =
1923 if(
index == count - 3 )
1929 else if(
index == count - 2 )
1937 wxTextEntryDialog dlg(
this,
_(
"BOM preset name:" ),
_(
"Save BOM Preset" ),
name );
1939 if( dlg.ShowModal() != wxID_OK )
1945 name = dlg.GetValue();
1963 wxMessageBox(
_(
"Default presets cannot be modified.\nPlease use a different name." ),
1964 _(
"Error" ), wxOK | wxICON_ERROR,
this );
1971 if( !
IsOK(
this,
_(
"Overwrite existing preset?" ) ) )
1992 else if(
index == count - 1 )
1995 wxArrayString headers;
1996 std::vector<wxArrayString> items;
1998 headers.Add(
_(
"Presets" ) );
2002 if( !preset.readOnly )
2006 items.emplace_back( item );
2018 if( idx != wxNOT_FOUND )
2068 for(
int i = 0; i <
m_dataModel->GetColsCount(); i++ )
2070 const wxString& fieldName(
m_dataModel->GetColFieldName( i ) );
2091 int col =
m_dataModel->GetFieldNameCol( fieldName );
2095 wxASSERT_MSG(
true,
"Fields control has a field not found in the data model." );
2100 std::string fieldNameStr( fieldName.ToUTF8() );
2103 const wxString& label =
m_dataModel->GetColLabelValue( col );
2105 m_grid->SetColLabelValue( col, label );
2120 bool groupBy =
m_dataModel->GetGroupColumn( col );
2144 std::vector<BOM_FMT_PRESET> ret;
2148 if( !preset.readOnly )
2149 ret.emplace_back( preset );
2179 wxCommandEvent
dummy;
2221 int default_idx = 0;
2250 [&](
const std::pair<const wxString, BOM_FMT_PRESET>& aPair )
2252 return ( aPair.second.fieldDelimiter == current.fieldDelimiter
2253 && aPair.second.stringDelimiter == current.stringDelimiter
2254 && aPair.second.refDelimiter == current.refDelimiter
2255 && aPair.second.refRangeDelimiter == current.refRangeDelimiter
2256 && aPair.second.keepTabs == current.keepTabs
2257 && aPair.second.keepLineBreaks == current.keepLineBreaks );
2264 bool do_translate = it->second.readOnly;
2265 wxString
text = do_translate ? wxGetTranslation( it->first ) : it->first;
2284 wxString ui_label = aName;
2288 if( presetName == aName )
2290 if( preset.readOnly )
2291 ui_label = wxGetTranslation( aName );
2316 auto resetSelection =
2325 if(
index == count - 3 )
2331 else if(
index == count - 2 )
2339 wxTextEntryDialog dlg(
this,
_(
"BOM preset name:" ),
_(
"Save BOM Preset" ),
name );
2341 if( dlg.ShowModal() != wxID_OK )
2347 name = dlg.GetValue();
2365 wxMessageBox(
_(
"Default presets cannot be modified.\nPlease use a different name." ),
2366 _(
"Error" ), wxOK | wxICON_ERROR,
this );
2373 if( !
IsOK(
this,
_(
"Overwrite existing preset?" ) ) )
2394 else if(
index == count - 1 )
2397 wxArrayString headers;
2398 std::vector<wxArrayString> items;
2400 headers.Add(
_(
"Presets" ) );
2402 for( std::pair<const wxString, BOM_FMT_PRESET>& pair :
m_bomFmtPresets )
2404 if( !pair.second.readOnly )
2407 item.Add( pair.first );
2408 items.emplace_back( item );
2420 if( idx != wxNOT_FOUND )
2475 bool modified =
false;
2478 std::vector<BOM_PRESET> presets;
2482 if( !preset.readOnly )
2483 presets.emplace_back( preset );
2499 std::vector<BOM_FMT_PRESET> fmts;
2503 if( !preset.readOnly )
2504 fmts.emplace_back( preset );
2543 AddField( field.GetCanonicalName(), field.GetName(),
true,
false,
true );
2549 std::set<SCH_SYMBOL*> symbols;
2553 symbols.insert( ref.GetSymbol() );
2558 for(
SCH_FIELD& field : symbol->GetFields() )
2559 AddField( field.GetCanonicalName(), field.GetName(),
true,
false,
true );
2611 AddField( field.GetCanonicalName(), field.GetName(),
true,
false,
true );
2614 m_parent->Schematic().GetCurrentVariant() );
2618 std::set<SCH_SYMBOL*> symbols;
2622 symbols.insert( ref.GetSymbol() );
2627 for(
SCH_FIELD& field : symbol->GetFields() )
2628 AddField( field.GetCanonicalName(), field.GetName(),
true,
false,
true );
2646 if(
m_dataModel->GetScope() != FIELDS_EDITOR_GRID_DATA_MODEL::SCOPE::SCOPE_ALL )
2660 m_grid->Connect( wxEVT_GRID_RANGE_SELECTED,
2668 m_grid->Disconnect( wxEVT_GRID_RANGE_SELECTED,
2676 std::set<wxString> selectedFullPaths;
2678 wxGridCellCoordsArray topLeft =
m_grid->GetSelectionBlockTopLeft();
2679 wxGridCellCoordsArray bottomRight =
m_grid->GetSelectionBlockBottomRight();
2681 for(
size_t i = 0; i < topLeft.size(); ++i )
2683 for(
int row = topLeft[i].GetRow(); row <= bottomRight[i].GetRow(); ++row )
2686 selectedFullPaths.insert( ref.GetFullPath() );
2690 wxArrayInt selectedRows =
m_grid->GetSelectedRows();
2692 for(
int row : selectedRows )
2695 selectedFullPaths.insert( ref.GetFullPath() );
2698 int cursorRow =
m_grid->GetGridCursorRow();
2700 if( cursorRow >= 0 && selectedFullPaths.empty() )
2703 selectedFullPaths.insert( ref.GetFullPath() );
2706 return selectedFullPaths;
2712 if( aFullPaths.empty() )
2715 m_grid->ClearSelection();
2717 bool firstSelection =
true;
2719 for(
int row = 0; row <
m_dataModel->GetNumberRows(); ++row )
2721 std::vector<SCH_REFERENCE> refs =
m_dataModel->GetRowReferences( row );
2725 if( aFullPaths.count( ref.GetFullPath() ) )
2727 m_grid->SelectRow( row,
true );
2729 if( firstSelection )
2731 m_grid->SetGridCursor( row,
m_grid->GetGridCursorCol() );
2732 firstSelection =
false;
2747 for(
size_t i = 0; i < aCachedRefs.
GetCount(); i++ )
2774 if( basePath.Path() == instance.m_Path )
2782 subSheets.push_back( sheetPath );
2800 if( !
m_parent->ShowAddVariantDialog() )
2803 wxArrayString ctrlContents;
2806 for(
const wxString& variant :
m_parent->Schematic().GetVariantNames() )
2807 ctrlContents.Add( variant );
2812 wxString currentVariant =
m_parent->Schematic().GetCurrentVariant();
2816 if( newSelection != wxNOT_FOUND )
2828 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
2830 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Cannot delete the default variant." ),
2831 10000, wxICON_ERROR );
2837 m_parent->Schematic().DeleteVariant( variantName );
2840 int newSelection = std::max( 0, selection - 1 );
2844 m_parent->SetCurrentVariant( selectedVariant );
2846 if(
m_grid->CommitPendingChanges(
true ) )
2848 m_dataModel->SetCurrentVariant( selectedVariant );
2859 m_parent->UpdateVariantSelectionCtrl(
m_parent->Schematic().GetVariantNamesForUI() );
2868 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
2870 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Cannot rename the default variant." ),
2871 10000, wxICON_ERROR );
2877 wxTextEntryDialog dlg(
this,
_(
"Enter new variant name:" ),
_(
"Rename Design Variant" ),
2878 oldVariantName, wxOK | wxCANCEL | wxCENTER );
2880 if( dlg.ShowModal() == wxID_CANCEL )
2883 wxString newVariantName = dlg.GetValue().Trim().Trim(
false );
2886 if( newVariantName.IsEmpty() )
2888 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Variant name cannot be empty." ), 10000, wxICON_ERROR );
2895 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format(
_(
"'%s' is a reserved variant name." ),
2897 10000, wxICON_ERROR );
2902 if( newVariantName == oldVariantName )
2906 for(
const wxString& existingName :
m_parent->Schematic().GetVariantNames() )
2908 if( existingName.CmpNoCase( newVariantName ) == 0
2909 && existingName.CmpNoCase( oldVariantName ) != 0 )
2911 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format(
_(
"Variant '%s' already exists." ),
2913 0000, wxICON_ERROR );
2918 m_parent->Schematic().RenameVariant( oldVariantName, newVariantName );
2922 ctrlContents.Remove( oldVariantName );
2923 ctrlContents.Add( newVariantName );
2929 if( newSelection != wxNOT_FOUND )
2933 m_parent->UpdateVariantSelectionCtrl(
m_parent->Schematic().GetVariantNamesForUI() );
2942 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
2944 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Cannot copy the default variant." ),
2945 10000, wxICON_ERROR );
2951 wxTextEntryDialog dlg(
this,
_(
"Enter name for the copied variant:" ),
_(
"Copy Design Variant" ),
2952 sourceVariantName + wxS(
"_copy" ), wxOK | wxCANCEL | wxCENTER );
2954 if( dlg.ShowModal() == wxID_CANCEL )
2957 wxString newVariantName = dlg.GetValue().Trim().Trim(
false );
2960 if( newVariantName.IsEmpty() )
2962 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Variant name cannot be empty." ), 10000, wxICON_ERROR );
2969 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format(
_(
"Variant '%s' already exists." ),
2971 10000, wxICON_ERROR );
2975 m_parent->Schematic().CopyVariant( sourceVariantName, newVariantName );
2979 ctrlContents.Add( newVariantName );
2985 if( newSelection != wxNOT_FOUND )
2989 m_parent->UpdateVariantSelectionCtrl(
m_parent->Schematic().GetVariantNamesForUI() );
2997 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
2999 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Cannot edit the default variant description." ), 10000,
3005 wxString currentDesc =
m_parent->Schematic().GetVariantDescription( variantName );
3007 wxDialog dlg(
this, wxID_ANY, wxString::Format(
_(
"Edit Description for '%s'" ), variantName ), wxDefaultPosition,
3008 wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
3010 wxBoxSizer* mainSizer =
new wxBoxSizer( wxVERTICAL );
3012 wxStaticText* label =
new wxStaticText( &dlg, wxID_ANY,
_(
"Description:" ) );
3013 mainSizer->Add( label, 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 10 );
3015 mainSizer->AddSpacer( 3 );
3017 wxTextCtrl* descCtrl =
3018 new wxTextCtrl( &dlg, wxID_ANY, currentDesc, wxDefaultPosition, wxSize( 300, 60 ), wxTE_MULTILINE );
3019 mainSizer->Add( descCtrl, 1, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 10 );
3021 wxStdDialogButtonSizer* btnSizer =
new wxStdDialogButtonSizer();
3022 btnSizer->AddButton(
new wxButton( &dlg, wxID_OK ) );
3023 btnSizer->AddButton(
new wxButton( &dlg, wxID_CANCEL ) );
3024 btnSizer->Realize();
3025 mainSizer->Add( btnSizer, 0, wxALL | wxALIGN_RIGHT, 5 );
3027 dlg.SetSizer( mainSizer );
3031 if( dlg.ShowModal() == wxID_CANCEL )
3034 wxString newDesc = descCtrl->GetValue().Trim().Trim(
false );
3036 m_parent->Schematic().SetVariantDescription( variantName, newDesc );
3043 wxString currentVariant;
3050 currentVariant =
m_parent->Schematic().GetCurrentVariant();
3052 if( currentVariant != selectedVariant )
3053 m_parent->SetCurrentVariant( selectedVariant );
3056 if( currentVariant != selectedVariant )
3058 m_grid->CommitPendingChanges(
true );
3064 if( !commit.
Empty() )
3066 commit.
Push( wxS(
"Symbol Fields Table Edit" ) );
3071 m_dataModel->SetCurrentVariant( selectedVariant );
3090 bool canModify = ( selection != wxNOT_FOUND ) && ( selection != 0 );
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
int vertPixelsFromDU(int y) const
Convert an integer number of dialog units to pixels, vertically.
void ExcludeFromControlUndoRedo(wxWindow *aWindow)
Opt a control out of the dialog's generic Ctrl+Z/Ctrl+Y undo/redo.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int horizPixelsFromDU(int x) const
Convert an integer number of dialog units to pixels, horizontally.
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
wxCheckBox * m_checkKeepLineBreaks
STD_BITMAP_BUTTON * m_deleteVariantButton
STD_BITMAP_BUTTON * m_bRefreshPreview
STD_BITMAP_BUTTON * m_editVariantDescButton
STD_BITMAP_BUTTON * m_bMenu
STD_BITMAP_BUTTON * m_addVariantButton
DIALOG_SYMBOL_FIELDS_TABLE_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Symbol Fields Table"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER)
wxCheckBox * m_checkKeepTabs
wxButton * m_buttonExport
STD_BITMAP_BUTTON * m_removeFieldButton
STD_BITMAP_BUTTON * m_browseButton
STD_BITMAP_BUTTON * m_sidebarButton
STD_BITMAP_BUTTON * m_copyVariantButton
wxTextCtrl * m_textOutput
STD_BITMAP_BUTTON * m_bRefresh
STD_BITMAP_BUTTON * m_renameFieldButton
STD_BITMAP_BUTTON * m_addFieldButton
wxTextCtrl * m_textStringDelimiter
wxChoice * m_cbBomPresets
wxListBox * m_variantListBox
wxTextCtrl * m_outputFileName
wxSplitterWindow * m_splitterMainWindow
STD_BITMAP_BUTTON * m_renameVariantButton
wxTextCtrl * m_textFieldDelimiter
wxCheckBox * m_groupSymbolsBox
wxTextCtrl * m_textRefRangeDelimiter
wxSplitterWindow * m_splitter_left
WX_GRID * m_viewControlsGrid
wxChoice * m_cbBomFmtPresets
wxTextCtrl * m_textRefDelimiter
void OnTableColSize(wxGridSizeEvent &event) override
void OnSaveAndContinue(wxCommandEvent &aEvent) override
void OnSchItemsRemoved(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem) override
BOM_FMT_PRESET * m_currentBomFmtPreset
void onAddVariant(wxCommandEvent &aEvent) override
void OnPreviewRefresh(wxCommandEvent &event) override
void OnAddField(wxCommandEvent &event) override
SCH_REFERENCE_LIST getSheetSymbolReferences(SCH_SHEET &aSheet)
void SetUserBomPresets(std::vector< BOM_PRESET > &aPresetList)
void OnSidebarToggle(wxCommandEvent &event) override
void OnOk(wxCommandEvent &aEvent) override
void OnGroupSymbolsToggled(wxCommandEvent &event) override
~DIALOG_SYMBOL_FIELDS_TABLE() override
void OnColMove(wxGridEvent &aEvent)
void OnSchItemsAdded(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem) override
void loadDefaultBomFmtPresets()
std::map< wxString, BOM_PRESET > m_bomPresets
void OnSchItemsChanged(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem) override
void ApplyBomFmtPreset(const wxString &aPresetName)
void ShowHideColumn(int aCol, bool aShow)
VIEW_CONTROLS_GRID_DATA_MODEL * m_viewControlsDataModel
SCH_EDIT_FRAME * m_parent
bool TransferDataFromWindow() override
SCH_REFERENCE_LIST m_symbolsList
void SetupColumnProperties(int aCol)
void setSideBarButtonLook(bool aIsLeftPanelCollapsed)
FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
void updateBomPresetSelection(const wxString &aName)
void updateBomFmtPresetSelection(const wxString &aName)
void OnFilterText(wxCommandEvent &aEvent) override
std::map< FIELD_T, int > m_mandatoryFieldListIndexes
void OnRemoveField(wxCommandEvent &event) override
void OnTableCellClick(wxGridEvent &event) override
wxArrayString m_bomPresetMRU
void onVariantSelectionChange(wxCommandEvent &aEvent) override
void doApplyBomFmtPreset(const BOM_FMT_PRESET &aPreset)
void loadDefaultBomPresets()
void RestoreGridSelection(const std::set< wxString > &aFullPaths)
Restores the grid selection from a previously saved set of symbol full paths.
void OnScope(wxCommandEvent &event) override
void onBomPresetChanged(wxCommandEvent &aEvent)
void OnTableValueChanged(wxGridEvent &event) override
void OnExport(wxCommandEvent &aEvent) override
void OnClose(wxCloseEvent &aEvent) override
void OnSchSheetChanged(SCHEMATIC &aSch) override
void syncBomFmtPresetSelection()
void DisableSelectionEvents()
void onCopyVariant(wxCommandEvent &aEvent) override
void onDeleteVariant(wxCommandEvent &aEvent) override
bool TransferDataToWindow() override
void OnTableRangeSelected(wxGridRangeSelectEvent &aEvent)
void OnMenu(wxCommandEvent &event) override
void updateVariantButtonStates()
void EnableSelectionEvents()
void setScope(FIELDS_EDITOR_GRID_DATA_MODEL::SCOPE aScope)
std::vector< BOM_FMT_PRESET > GetUserBomFmtPresets() const
wxArrayString m_bomFmtPresetMRU
void OnCancel(wxCommandEvent &aEvent) override
void OnFilterMouseMoved(wxMouseEvent &event) override
std::map< wxString, BOM_FMT_PRESET > m_bomFmtPresets
DIALOG_SYMBOL_FIELDS_TABLE(SCH_EDIT_FRAME *parent, JOB_EXPORT_SCH_BOM *aJob=nullptr)
BOM_FMT_PRESET GetCurrentBomFmtSettings()
Returns a formatting configuration corresponding to the values in the UI controls of the dialog.
std::set< wxString > SaveGridSelection()
Saves the current grid selection as a set of symbol full paths for later restoration.
void savePresetsToSchematic()
void SetupAllColumnProperties()
void AddField(const wxString &displayName, const wxString &aCanonicalName, bool show, bool groupBy, bool addedByUser=false)
SCH_REFERENCE_LIST getSymbolReferences(SCH_SYMBOL *aSymbol, SCH_REFERENCE_LIST &aCachedRefs)
wxString getSelectedVariant() const
void OnGridMouseMove(wxMouseEvent &aEvent)
SCHEMATIC_SETTINGS & m_schSettings
void syncBomPresetSelection()
void doApplyBomPreset(const BOM_PRESET &aPreset)
void OnPageChanged(wxNotebookEvent &event) override
void SetUserBomFmtPresets(std::vector< BOM_FMT_PRESET > &aPresetList)
void OnRegroupSymbols(wxCommandEvent &aEvent) override
void OnViewControlsCellChanged(wxGridEvent &aEvent) override
void onRenameVariant(wxCommandEvent &aEvent) override
void OnColSort(wxGridEvent &aEvent)
JOB_EXPORT_SCH_BOM * m_job
std::vector< BOM_PRESET > GetUserBomPresets() const
void OnOutputFileBrowseClicked(wxCommandEvent &event) override
void LoadFieldNames()
Construct the rows of m_fieldsCtrl and the columns of m_dataModel from a union of all field names in ...
void onBomFmtPresetChanged(wxCommandEvent &aEvent)
void ApplyBomPreset(const wxString &aPresetName)
void OnSizeViewControlsGrid(wxSizeEvent &event) override
void rebuildBomFmtPresetsWidget()
BOM_PRESET * m_lastSelectedBomPreset
void rebuildBomPresetsWidget()
BOM_PRESET * m_currentBomPreset
void onEditVariantDescription(wxCommandEvent &aEvent) override
BOM_FMT_PRESET * m_lastSelectedBomFmtPreset
void OnRenameField(wxCommandEvent &event) override
A base class for most all the KiCad significant classes used in schematics and boards.
KICAD_T Type() const
Returns the type of object.
EDA_ITEM * GetParent() const
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
PANEL_SYMBOL_FIELDS_TABLE m_FieldEditorPanel
static const wxString ITEM_NUMBER_VARIABLE
static const wxString QUANTITY_VARIABLE
VIEW_CONTROLS_GRID_DATA_MODEL * m_viewControlsDataModel
DIALOG_SYMBOL_FIELDS_TABLE * m_dlg
void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent) override
void doPopupSelection(wxCommandEvent &event) override
FIELDS_EDITOR_GRID_TRICKS(DIALOG_SYMBOL_FIELDS_TABLE *aParent, WX_GRID *aGrid, VIEW_CONTROLS_GRID_DATA_MODEL *aViewFieldsData, FIELDS_EDITOR_GRID_DATA_MODEL *aDataModel, EMBEDDED_FILES *aFiles)
FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
A general-purpose text renderer for WX_GRIDs backed by WX_GRID_TABLE_BASE tables that can handle draw...
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
GRID_TRICKS(WX_GRID *aGrid)
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.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
static REPORTER & GetInstance()
static SEARCH_STACK * SchSearchS(PROJECT *aProject)
Accessor for Eeschema search stack.
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Holds all the data relating to one schematic.
wxArrayString GetVariantNamesForUI() const
Return an array of variant names for using in wxWidgets UI controls.
SCH_SHEET_PATH & CurrentSheet() const
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
Base class for any item which can be embedded within the SCHEMATIC container class,...
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
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.
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() 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.
bool IsPower() const override
VIEW_CONTROLS_GRID_TRICKS(WX_GRID *aGrid)
void doPopupSelection(wxCommandEvent &event) override
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
wxString GetGeneratedFieldDisplayName(const wxString &aSource)
Returns any variables unexpanded, e.g.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
wxString NormalizeFilePathForTextVars(const wxString &aPath)
Normalize a file path so its text variables survive ExpandTextVars.
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.
bool IsGeneratedField(const wxString &aSource)
Returns true if the string is generated, e.g contains a single text var reference.
int OKOrCancelDialog(wxWindow *aParent, const wxString &aWarning, const wxString &aMessage, const wxString &aDetailedMessage, const wxString &aOKLabel, const wxString &aCancelLabel, bool *aApplyToAll)
Display a warning dialog with aMessage and returns the user response.
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
This file is part of the common library.
wxDEFINE_EVENT(EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxCommandEvent)
FIELDS_EDITOR_GRID_DATA_MODEL::SCOPE SCOPE
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.
This file is part of the common library.
static FILENAME_RESOLVER * resolver
std::vector< FIELD_CASE_CONFLICT > DetectFieldCaseConflicts(const SCH_REFERENCE_LIST &aSymbols)
#define DISPLAY_NAME_COLUMN
#define SHOW_FIELD_COLUMN
@ FRAME_FOOTPRINT_CHOOSER
@ GRIDTRICKS_FIRST_SHOWHIDE
@ GRIDTRICKS_FIRST_CLIENT_ID
static const std::string CsvFileExtension
static wxString CsvFileWildcard()
KICOMMON_API wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
@ SYMBOL_FILTER_NON_POWER
std::vector< FAB_LAYER_COLOR > dummy
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.
static BOM_FMT_PRESET CSV()
static std::vector< BOM_FMT_PRESET > BuiltInPresets()
wxString refRangeDelimiter
static BOM_PRESET DefaultEditing()
std::vector< BOM_FIELD > fieldsOrdered
static std::vector< BOM_PRESET > BuiltInPresets()
std::map< std::string, int > field_widths
A simple container for sheet instance information.
Hold a name of a symbol's field, field value, and default visibility.
wxString GetDefaultFieldName(FIELD_T aFieldId, bool aTranslateForHI)
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".
wxString GetCanonicalFieldName(FIELD_T aFieldType)
Definition of file extensions used in Kicad.