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 );
285 if( !
m_parent->Schematic().GetCurrentVariant().IsEmpty() )
289 if( toSelect == wxNOT_FOUND )
302 SetTitle(
m_job->GetSettingsDialogTitle() );
324 CallAfter( [
this, cfg]()
354 m_parent->Schematic().AddListener(
this );
359 m_grid->EnableEditing(
false );
378 for(
int i = 0; i <
m_grid->GetNumberCols(); i++ )
380 if(
m_grid->IsColShown( i ) )
382 std::string fieldName(
m_dataModel->GetColFieldName( i ).ToUTF8() );
397 m_grid->PopEventHandler(
true );
407 if( aIsLeftPanelCollapsed )
422 wxGridCellAttr* attr =
new wxGridCellAttr;
423 attr->SetReadOnly(
false );
447 attr->SetAlignment( wxALIGN_RIGHT, wxALIGN_CENTER );
448 attr->SetRenderer(
new wxGridCellNumberRenderer() );
453 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
466 attr->SetEditor(
m_grid->GetDefaultEditor() );
475 wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
478 m_grid->AutoSizeColumns(
false );
480 bool sortAscending =
true;
482 for(
int col = 0; col <
m_grid->GetNumberCols(); ++col )
508 std::string key(
m_dataModel->GetColFieldName( col ).ToUTF8() );
518 int maxWidth = defaultDlgSize.x / 3;
520 m_grid->SetColSize( col, std::clamp( textWidth, 100, maxWidth ) );
530 m_grid->SetSortingColumn( sortCol, sortAscending );
536 if( !wxDialog::TransferDataToWindow() )
559 for(
const wxString& fieldName :
m_job->m_fieldsOrdered )
562 field.
name = fieldName;
563 field.
show = !fieldName.StartsWith( wxT(
"__" ), &field.
name );
566 if( (
m_job->m_fieldsLabels.size() > i ) && !
m_job->m_fieldsLabels[i].IsEmpty() )
587 fmtPreset.
name =
m_job->m_bomFmtPresetName;
608 if( selection.GetSize() == 1 )
620 for(
int row = 0; row <
m_dataModel->GetNumberRows(); ++row )
622 std::vector<SCH_REFERENCE> references =
m_dataModel->GetRowReferences( row );
627 if( ref.GetSymbol() == symbol )
641 for(
int col = 0; col <
m_dataModel->GetNumberCols(); col++ )
647 else if( anyCol == -1 &&
m_dataModel->GetShowColumn( col ) )
651 if( valueCol != -1 &&
m_dataModel->GetShowColumn( valueCol ) )
652 m_grid->GoToCell( row, valueCol );
653 else if( refCol != -1 &&
m_dataModel->GetShowColumn( refCol ) )
654 m_grid->GoToCell( row, refCol );
655 else if( anyCol != -1 )
656 m_grid->GoToCell( row, anyCol );
674 if( !
m_grid->CommitPendingChanges() )
677 if( !wxDialog::TransferDataFromWindow() )
688 wxString currentVariant =
m_parent->Schematic().GetCurrentVariant();
692 if( !commit.
Empty() )
694 commit.
Push( wxS(
"Symbol Fields Table Edit" ) );
699 m_parent->SetCurrentSheet( currentSheet );
708 bool show,
bool groupBy,
bool addedByUser )
718 m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser,
m_parent->Schematic().GetCurrentVariant() );
720 wxGridTableMessage msg(
m_dataModel, wxGRIDTABLE_NOTIFY_COLS_APPENDED, 1 );
721 m_grid->ProcessTableMessage( msg );
724 [&]() -> std::pair<int, int>
735 auto addMandatoryField =
736 [&](
FIELD_T fieldId,
bool show,
bool groupBy )
756 auto caseInsensitiveLess = [](
const wxString& a,
const wxString& b )
758 return a.CmpNoCase( b ) < 0;
761 std::map<wxString, std::map<wxString, int>,
decltype( caseInsensitiveLess )> userFieldGroups( caseInsensitiveLess );
769 if( !field.IsMandatory() && !field.IsPrivate() )
770 userFieldGroups[field.GetName()][field.GetName()]++;
774 for(
const auto& [groupKey, exactCounts] : userFieldGroups )
776 wxString canonicalName;
780 canonicalName = tfn->m_Name;
786 for(
const auto& [
name, count] : exactCounts )
788 if( count > bestCount )
791 canonicalName =
name;
802 if( userFieldGroups.count( tfn.m_Name ) == 0 )
810 wxTextEntryDialog dlg(
this,
_(
"New field name:" ),
_(
"Add Field" ) );
812 if( dlg.ShowModal() != wxID_OK )
815 wxString fieldName = dlg.GetValue();
817 if( fieldName.IsEmpty() )
823 for(
int i = 0; i <
m_dataModel->GetNumberCols(); ++i )
825 if( fieldName.CmpNoCase(
m_dataModel->GetColFieldName( i ) ) == 0 )
827 DisplayError(
this, wxString::Format(
_(
"Field name '%s' already in use." ), fieldName ) );
850 DisplayError(
this, wxString::Format(
_(
"The first %d fields are mandatory." ),
856 return IsOK(
this, wxString::Format(
_(
"Are you sure you want to remove the field '%s'?" ),
862 int col =
m_dataModel->GetFieldNameCol( fieldName );
882 if( selectedRows.empty() )
885 int row = selectedRows[0];
891 DisplayError(
this, wxString::Format(
_(
"The first %d fields are mandatory and names cannot be changed." ),
901 int col =
m_dataModel->GetFieldNameCol( fieldName );
902 wxCHECK_RET( col != -1, wxS(
"Existing field name missing from data model" ) );
904 wxTextEntryDialog dlg(
this,
_(
"New field name:" ),
_(
"Rename Field" ), fieldName );
906 if( dlg.ShowModal() != wxID_OK )
909 wxString newFieldName = dlg.GetValue();
912 if( newFieldName == fieldName )
916 if(
m_dataModel->GetFieldNameCol( newFieldName ) != -1 )
918 wxString confirm_msg = wxString::Format(
_(
"Field name %s already exists." ), newFieldName );
927 if( labelIsAutogenerated )
951#if defined( __WXOSX__ )
952 wxPoint pos = aEvent.GetPosition();
953 wxRect ctrlRect =
m_filter->GetScreenRect();
954 int buttonWidth = ctrlRect.GetHeight();
957 if(
m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
958 SetCursor( wxCURSOR_ARROW );
959 else if(
m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
960 SetCursor( wxCURSOR_ARROW );
962 SetCursor( wxCURSOR_IBEAM );
977 switch( aEvent.GetSelection() )
979 case 0:
setScope( SCOPE::SCOPE_ALL );
break;
980 case 1:
setScope( SCOPE::SCOPE_SHEET );
break;
981 case 2:
setScope( SCOPE::SCOPE_SHEET_RECURSIVE );
break;
1003 menu.Append( 4204,
_(
"Include 'DNP' Symbols" ),
1004 _(
"Show symbols marked 'DNP' in the table. This setting also controls whether or not 'DNP' "
1005 "symbols are included on export." ),
1007 menu.Check( 4204, !
m_dataModel->GetExcludeDNP() );
1009 menu.Append( 4205,
_(
"Include 'Exclude from BOM' Symbols" ),
1010 _(
"Show symbols marked 'Exclude from BOM' in the table. Symbols marked 'Exclude from BOM' "
1011 "are never included on export." ),
1013 menu.Check( 4205,
m_dataModel->GetIncludeExcludedFromBOM() );
1015 menu.AppendSeparator();
1017 menu.Append( 4206,
_(
"Highlight on Cross-probe" ),
1018 _(
"Highlight corresponding item on canvas when it is selected in the table" ),
1022 menu.Append( 4207,
_(
"Select on Cross-probe" ),
1023 _(
"Select corresponding item on canvas when it is selected in the table" ),
1028 int menu_id =
m_bMenu->GetPopupMenuSelectionFromUser( menu );
1030 if( menu_id == 0 || menu_id == 4204 )
1038 else if( menu_id == 1 || menu_id == 4205 )
1046 else if( menu_id == 3 || menu_id == 4206 )
1053 else if( menu_id == 4 || menu_id == 4207 )
1065 int sortCol = aEvent.GetCol();
1066 std::string key(
m_dataModel->GetColFieldName( sortCol ).ToUTF8() );
1078 if(
m_grid->IsSortingBy( sortCol ) )
1081 ascending = !
m_grid->IsSortOrderAscending();
1099 int origPos = aEvent.GetCol();
1104 for(
int i = 0; i <
m_grid->GetNumberCols(); i++ )
1106 if(
m_grid->IsColShown( i ) )
1108 std::string fieldName(
m_dataModel->GetColFieldName( i ).ToUTF8() );
1116 int newPos =
m_grid->GetColPos( origPos );
1119 if( newPos < origPos )
1160 int row = aEvent.GetRow();
1162 wxCHECK( row < m_viewControlsGrid->GetNumberRows(), );
1164 switch( aEvent.GetCol() )
1170 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
1175 m_grid->SetColLabelValue( dataCol, label );
1193 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
1205 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
1207 if(
m_dataModel->ColIsQuantity( dataCol ) && value )
1209 DisplayError(
this,
_(
"The Quantity column cannot be grouped by." ) );
1216 if(
m_dataModel->ColIsItemNumber( dataCol ) && value )
1218 DisplayError(
this,
_(
"The Item Number column cannot be grouped by." ) );
1267 if(
m_dataModel->IsExpanderColumn( event.GetCol() ) )
1269 m_grid->ClearSelection();
1272 m_grid->SetGridCursor( event.GetRow(), event.GetCol() );
1285 wxPoint pos = aEvent.GetPosition();
1287 m_grid->CalcUnscrolledPosition( pos.x, pos.y, &ux, &uy );
1288 int row =
m_grid->YToRow( uy );
1289 int col =
m_grid->XToCol( ux );
1292 if( row == wxNOT_FOUND || col == wxNOT_FOUND )
1294 m_grid->GetGridWindow()->UnsetToolTip();
1298 wxString rawValue =
m_dataModel->GetValue( row, col );
1300 if( rawValue.Contains( wxT(
"${" ) ) )
1302 m_grid->GetGridWindow()->SetToolTip( rawValue );
1306 m_grid->GetGridWindow()->UnsetToolTip();
1321 std::set<SCH_REFERENCE> refs;
1322 std::set<SCH_ITEM*> symbols;
1325 if( aEvent.Selecting() )
1327 for(
int i = aEvent.GetTopRow(); i <= aEvent.GetBottomRow(); i++ )
1334 symbols.insert( ref.GetSymbol() );
1341 if( refs.size() > 0 )
1345 wxString symbol_path = refs.begin()->GetFullPath();
1358 std::vector<SCH_ITEM*> items( symbols.begin(), symbols.end() );
1360 if( refs.size() > 0 )
1361 selTool->
SyncSelection( refs.begin()->GetSheetPath(),
nullptr, items );
1374 int remainingWidth =
m_viewControlsGrid->GetSize().GetX() - showColWidth - groupByColWidth;
1423 bool saveIncludeExcudedFromBOM =
m_dataModel->GetIncludeExcludedFromBOM();
1430 if( saveIncludeExcudedFromBOM )
1474 wxFileName fn(
Prj().AbsolutePath(
m_parent->Schematic().GetFileName() ) );
1477 wxFileDialog saveDlg(
this,
_(
"Bill of Materials Output File" ),
path, fn.GetFullName(),
1482 if( saveDlg.ShowModal() == wxID_CANCEL )
1486 wxFileName file = wxFileName( saveDlg.GetPath() );
1487 wxString defaultPath = fn.GetPathWithSep();
1489 if(
IsOK(
this, wxString::Format(
_(
"Do you want to use a path relative to\n'%s'?" ), defaultPath ) ) )
1491 if( !file.MakeRelativeTo( defaultPath ) )
1493 DisplayErrorMessage(
this,
_(
"Cannot make path relative (target volume different from schematic "
1494 "file volume)!" ) );
1528 _(
"Changes have not yet been saved. Export unsaved data?" ),
"",
1529 _(
"OK" ),
_(
"Cancel" ) )
1539 std::function<bool( wxString* )> textResolver =
1540 [&]( wxString* token ) ->
bool
1545 return schematic.ResolveTextVar( &schematic.CurrentSheet(), token, 0 );
1550 if(
path.IsEmpty() )
1552 DisplayError(
this,
_(
"No output file specified in Export tab." ) );
1559 wxFileName outputFile = wxFileName::FileName(
path );
1565 msg.Printf(
_(
"Could not open/create path '%s'." ), outputFile.GetPath() );
1570 wxFFile out( outputFile.GetFullPath(),
"wb" );
1572 if( !out.IsOpened() )
1574 msg.Printf(
_(
"Could not create BOM output '%s'." ), outputFile.GetFullPath() );
1583 msg.Printf(
_(
"Could not write BOM output '%s'." ), outputFile.GetFullPath() );
1590 msg.Printf(
_(
"Wrote BOM output to '%s'" ), outputFile.GetFullPath() );
1598 EndModal( wxID_CANCEL );
1615 m_job->m_bomFmtPresetName = wxEmptyString;
1620 m_job->m_bomPresetName = wxEmptyString;
1637 m_job->m_fieldsOrdered.clear();
1638 m_job->m_fieldsLabels.clear();
1639 m_job->m_fieldsGroupBy.clear();
1643 if( modelField.show )
1644 m_job->m_fieldsOrdered.emplace_back( modelField.name );
1646 m_job->m_fieldsOrdered.emplace_back( wxT(
"__" ) + modelField.name );
1648 m_job->m_fieldsLabels.emplace_back( modelField.label );
1650 if( modelField.groupBy )
1651 m_job->m_fieldsGroupBy.emplace_back( modelField.name );
1656 if( !selectedVariant.IsEmpty() )
1657 m_job->m_variantNames.push_back( selectedVariant );
1659 EndModal( wxID_OK );
1676 m_grid->CommitPendingChanges(
true );
1692 m_parent->Schematic().RemoveListener(
this );
1695 wxCommandEvent* evt =
new wxCommandEvent( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxID_ANY );
1697 if( wxWindow* parent = GetParent() )
1698 wxQueueEvent( parent, evt );
1704 std::vector<BOM_PRESET> ret;
1706 for(
const std::pair<const wxString, BOM_PRESET>& pair :
m_bomPresets )
1708 if( !pair.second.readOnly )
1709 ret.emplace_back( pair.second );
1721 for(
const BOM_PRESET& preset : aPresetList )
1739 wxCommandEvent
dummy;
1782 int default_idx = 0;
1786 m_cbBomPresets->Append( wxGetTranslation( presetName ), (
void*) &preset );
1811 [&](
const std::pair<const wxString, BOM_PRESET>& aPair )
1813 const BOM_PRESET& preset = aPair.second;
1816 if( !( preset.sortAsc == current.sortAsc
1817 && preset.filterString == current.filterString
1818 && preset.groupSymbols == current.groupSymbols
1819 && preset.excludeDNP == current.excludeDNP
1820 && preset.includeExcludedFromBOM == current.includeExcludedFromBOM ) )
1831 if( preset.sortField != wxGetTranslation( current.
sortField ) )
1835 std::vector<BOM_FIELD>
A,
B;
1837 for(
const BOM_FIELD& field : preset.fieldsOrdered )
1839 if( field.show || field.groupBy )
1840 A.emplace_back( field );
1845 if( field.show || field.groupBy )
1846 B.emplace_back( field );
1852 if( it != m_bomPresets.end() )
1856 bool do_translate = it->second.readOnly;
1857 wxString
text = do_translate ? wxGetTranslation( it->first ) : it->first;
1858 m_cbBomPresets->SetStringSelection(
text );
1862 m_cbBomPresets->SetSelection( m_cbBomPresets->GetCount() - 3 );
1865 m_currentBomPreset =
static_cast<BOM_PRESET*
>( m_cbBomPresets->GetClientData( m_cbBomPresets->GetSelection() ) );
1874 wxString ui_label = aName;
1878 if( presetName == aName )
1880 if( preset.readOnly ==
true )
1881 ui_label = wxGetTranslation( aName );
1906 auto resetSelection =
1915 if(
index == count - 3 )
1921 else if(
index == count - 2 )
1929 wxTextEntryDialog dlg(
this,
_(
"BOM preset name:" ),
_(
"Save BOM Preset" ),
name );
1931 if( dlg.ShowModal() != wxID_OK )
1937 name = dlg.GetValue();
1955 wxMessageBox(
_(
"Default presets cannot be modified.\nPlease use a different name." ),
1956 _(
"Error" ), wxOK | wxICON_ERROR,
this );
1963 if( !
IsOK(
this,
_(
"Overwrite existing preset?" ) ) )
1984 else if(
index == count - 1 )
1987 wxArrayString headers;
1988 std::vector<wxArrayString> items;
1990 headers.Add(
_(
"Presets" ) );
1994 if( !preset.readOnly )
1998 items.emplace_back( item );
2010 if( idx != wxNOT_FOUND )
2060 for(
int i = 0; i <
m_dataModel->GetColsCount(); i++ )
2062 const wxString& fieldName(
m_dataModel->GetColFieldName( i ) );
2083 int col =
m_dataModel->GetFieldNameCol( fieldName );
2087 wxASSERT_MSG(
true,
"Fields control has a field not found in the data model." );
2092 std::string fieldNameStr( fieldName.ToUTF8() );
2095 const wxString& label =
m_dataModel->GetColLabelValue( col );
2097 m_grid->SetColLabelValue( col, label );
2112 bool groupBy =
m_dataModel->GetGroupColumn( col );
2136 std::vector<BOM_FMT_PRESET> ret;
2140 if( !preset.readOnly )
2141 ret.emplace_back( preset );
2171 wxCommandEvent
dummy;
2213 int default_idx = 0;
2242 [&](
const std::pair<const wxString, BOM_FMT_PRESET>& aPair )
2244 return ( aPair.second.fieldDelimiter == current.fieldDelimiter
2245 && aPair.second.stringDelimiter == current.stringDelimiter
2246 && aPair.second.refDelimiter == current.refDelimiter
2247 && aPair.second.refRangeDelimiter == current.refRangeDelimiter
2248 && aPair.second.keepTabs == current.keepTabs
2249 && aPair.second.keepLineBreaks == current.keepLineBreaks );
2256 bool do_translate = it->second.readOnly;
2257 wxString
text = do_translate ? wxGetTranslation( it->first ) : it->first;
2276 wxString ui_label = aName;
2280 if( presetName == aName )
2282 if( preset.readOnly )
2283 ui_label = wxGetTranslation( aName );
2308 auto resetSelection =
2317 if(
index == count - 3 )
2323 else if(
index == count - 2 )
2331 wxTextEntryDialog dlg(
this,
_(
"BOM preset name:" ),
_(
"Save BOM Preset" ),
name );
2333 if( dlg.ShowModal() != wxID_OK )
2339 name = dlg.GetValue();
2357 wxMessageBox(
_(
"Default presets cannot be modified.\nPlease use a different name." ),
2358 _(
"Error" ), wxOK | wxICON_ERROR,
this );
2365 if( !
IsOK(
this,
_(
"Overwrite existing preset?" ) ) )
2386 else if(
index == count - 1 )
2389 wxArrayString headers;
2390 std::vector<wxArrayString> items;
2392 headers.Add(
_(
"Presets" ) );
2394 for( std::pair<const wxString, BOM_FMT_PRESET>& pair :
m_bomFmtPresets )
2396 if( !pair.second.readOnly )
2399 item.Add( pair.first );
2400 items.emplace_back( item );
2412 if( idx != wxNOT_FOUND )
2467 bool modified =
false;
2470 std::vector<BOM_PRESET> presets;
2474 if( !preset.readOnly )
2475 presets.emplace_back( preset );
2491 std::vector<BOM_FMT_PRESET> fmts;
2495 if( !preset.readOnly )
2496 fmts.emplace_back( preset );
2535 AddField( field.GetCanonicalName(), field.GetName(),
true,
false,
true );
2541 std::set<SCH_SYMBOL*> symbols;
2545 symbols.insert( ref.GetSymbol() );
2550 for(
SCH_FIELD& field : symbol->GetFields() )
2551 AddField( field.GetCanonicalName(), field.GetName(),
true,
false,
true );
2603 AddField( field.GetCanonicalName(), field.GetName(),
true,
false,
true );
2606 m_parent->Schematic().GetCurrentVariant() );
2610 std::set<SCH_SYMBOL*> symbols;
2614 symbols.insert( ref.GetSymbol() );
2619 for(
SCH_FIELD& field : symbol->GetFields() )
2620 AddField( field.GetCanonicalName(), field.GetName(),
true,
false,
true );
2638 if(
m_dataModel->GetScope() != FIELDS_EDITOR_GRID_DATA_MODEL::SCOPE::SCOPE_ALL )
2652 m_grid->Connect( wxEVT_GRID_RANGE_SELECTED,
2660 m_grid->Disconnect( wxEVT_GRID_RANGE_SELECTED,
2668 std::set<wxString> selectedFullPaths;
2670 wxGridCellCoordsArray topLeft =
m_grid->GetSelectionBlockTopLeft();
2671 wxGridCellCoordsArray bottomRight =
m_grid->GetSelectionBlockBottomRight();
2673 for(
size_t i = 0; i < topLeft.size(); ++i )
2675 for(
int row = topLeft[i].GetRow(); row <= bottomRight[i].GetRow(); ++row )
2678 selectedFullPaths.insert( ref.GetFullPath() );
2682 wxArrayInt selectedRows =
m_grid->GetSelectedRows();
2684 for(
int row : selectedRows )
2687 selectedFullPaths.insert( ref.GetFullPath() );
2690 int cursorRow =
m_grid->GetGridCursorRow();
2692 if( cursorRow >= 0 && selectedFullPaths.empty() )
2695 selectedFullPaths.insert( ref.GetFullPath() );
2698 return selectedFullPaths;
2704 if( aFullPaths.empty() )
2707 m_grid->ClearSelection();
2709 bool firstSelection =
true;
2711 for(
int row = 0; row <
m_dataModel->GetNumberRows(); ++row )
2713 std::vector<SCH_REFERENCE> refs =
m_dataModel->GetRowReferences( row );
2717 if( aFullPaths.count( ref.GetFullPath() ) )
2719 m_grid->SelectRow( row,
true );
2721 if( firstSelection )
2723 m_grid->SetGridCursor( row,
m_grid->GetGridCursorCol() );
2724 firstSelection =
false;
2739 for(
size_t i = 0; i < aCachedRefs.
GetCount(); i++ )
2766 if( basePath.Path() == instance.m_Path )
2774 subSheets.push_back( sheetPath );
2792 if( !
m_parent->ShowAddVariantDialog() )
2795 wxArrayString ctrlContents;
2798 for(
const wxString& variant :
m_parent->Schematic().GetVariantNames() )
2799 ctrlContents.Add( variant );
2804 wxString currentVariant =
m_parent->Schematic().GetCurrentVariant();
2808 if( newSelection != wxNOT_FOUND )
2820 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
2822 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Cannot delete the default variant." ),
2823 10000, wxICON_ERROR );
2829 m_parent->Schematic().DeleteVariant( variantName );
2832 int newSelection = std::max( 0, selection - 1 );
2836 m_parent->SetCurrentVariant( selectedVariant );
2838 if(
m_grid->CommitPendingChanges(
true ) )
2840 m_dataModel->SetCurrentVariant( selectedVariant );
2851 m_parent->UpdateVariantSelectionCtrl(
m_parent->Schematic().GetVariantNamesForUI() );
2860 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
2862 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Cannot rename the default variant." ),
2863 10000, wxICON_ERROR );
2869 wxTextEntryDialog dlg(
this,
_(
"Enter new variant name:" ),
_(
"Rename Design Variant" ),
2870 oldVariantName, wxOK | wxCANCEL | wxCENTER );
2872 if( dlg.ShowModal() == wxID_CANCEL )
2875 wxString newVariantName = dlg.GetValue().Trim().Trim(
false );
2878 if( newVariantName.IsEmpty() )
2880 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Variant name cannot be empty." ), 10000, wxICON_ERROR );
2887 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format(
_(
"'%s' is a reserved variant name." ),
2889 10000, wxICON_ERROR );
2894 if( newVariantName == oldVariantName )
2898 for(
const wxString& existingName :
m_parent->Schematic().GetVariantNames() )
2900 if( existingName.CmpNoCase( newVariantName ) == 0
2901 && existingName.CmpNoCase( oldVariantName ) != 0 )
2903 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format(
_(
"Variant '%s' already exists." ),
2905 0000, wxICON_ERROR );
2910 m_parent->Schematic().RenameVariant( oldVariantName, newVariantName );
2914 ctrlContents.Remove( oldVariantName );
2915 ctrlContents.Add( newVariantName );
2921 if( newSelection != wxNOT_FOUND )
2925 m_parent->UpdateVariantSelectionCtrl(
m_parent->Schematic().GetVariantNamesForUI() );
2934 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
2936 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Cannot copy the default variant." ),
2937 10000, wxICON_ERROR );
2943 wxTextEntryDialog dlg(
this,
_(
"Enter name for the copied variant:" ),
_(
"Copy Design Variant" ),
2944 sourceVariantName + wxS(
"_copy" ), wxOK | wxCANCEL | wxCENTER );
2946 if( dlg.ShowModal() == wxID_CANCEL )
2949 wxString newVariantName = dlg.GetValue().Trim().Trim(
false );
2952 if( newVariantName.IsEmpty() )
2954 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Variant name cannot be empty." ), 10000, wxICON_ERROR );
2961 m_parent->GetInfoBar()->ShowMessageFor( wxString::Format(
_(
"Variant '%s' already exists." ),
2963 10000, wxICON_ERROR );
2967 m_parent->Schematic().CopyVariant( sourceVariantName, newVariantName );
2971 ctrlContents.Add( newVariantName );
2977 if( newSelection != wxNOT_FOUND )
2981 m_parent->UpdateVariantSelectionCtrl(
m_parent->Schematic().GetVariantNamesForUI() );
2989 if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
2991 m_parent->GetInfoBar()->ShowMessageFor(
_(
"Cannot edit the default variant description." ), 10000,
2997 wxString currentDesc =
m_parent->Schematic().GetVariantDescription( variantName );
2999 wxDialog dlg(
this, wxID_ANY, wxString::Format(
_(
"Edit Description for '%s'" ), variantName ), wxDefaultPosition,
3000 wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
3002 wxBoxSizer* mainSizer =
new wxBoxSizer( wxVERTICAL );
3004 wxStaticText* label =
new wxStaticText( &dlg, wxID_ANY,
_(
"Description:" ) );
3005 mainSizer->Add( label, 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 10 );
3007 mainSizer->AddSpacer( 3 );
3009 wxTextCtrl* descCtrl =
3010 new wxTextCtrl( &dlg, wxID_ANY, currentDesc, wxDefaultPosition, wxSize( 300, 60 ), wxTE_MULTILINE );
3011 mainSizer->Add( descCtrl, 1, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 10 );
3013 wxStdDialogButtonSizer* btnSizer =
new wxStdDialogButtonSizer();
3014 btnSizer->AddButton(
new wxButton( &dlg, wxID_OK ) );
3015 btnSizer->AddButton(
new wxButton( &dlg, wxID_CANCEL ) );
3016 btnSizer->Realize();
3017 mainSizer->Add( btnSizer, 0, wxALL | wxALIGN_RIGHT, 5 );
3019 dlg.SetSizer( mainSizer );
3023 if( dlg.ShowModal() == wxID_CANCEL )
3026 wxString newDesc = descCtrl->GetValue().Trim().Trim(
false );
3028 m_parent->Schematic().SetVariantDescription( variantName, newDesc );
3035 wxString currentVariant;
3042 currentVariant =
m_parent->Schematic().GetCurrentVariant();
3044 if( currentVariant != selectedVariant )
3045 m_parent->SetCurrentVariant( selectedVariant );
3048 if( currentVariant != selectedVariant )
3050 m_grid->CommitPendingChanges(
true );
3056 if( !commit.
Empty() )
3058 commit.
Push( wxS(
"Symbol Fields Table Edit" ) );
3063 m_dataModel->SetCurrentVariant( selectedVariant );
3082 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)
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.