Update schematic variants
This commit is contained in:
@@ -138,6 +138,9 @@ i18n_status.csv
|
||||
qa/data/**/*.csv
|
||||
qa/data/**/*.spice
|
||||
|
||||
# Unignore variant test comparison files
|
||||
!qa/data/cli/variants/*.bom.csv
|
||||
|
||||
# Don't actually ignore any of these files, since we need them in the tree
|
||||
!resources/linux/icons/hicolor/**/**/*
|
||||
!resources/linux/icons-nightly/hicolor/**/**/*
|
||||
|
||||
@@ -40,7 +40,8 @@ JOB_EXPORT_SCH_BOM::JOB_EXPORT_SCH_BOM() :
|
||||
m_sortField(),
|
||||
m_sortAsc( true ),
|
||||
m_filterString(),
|
||||
m_excludeDNP( false )
|
||||
m_excludeDNP( false ),
|
||||
m_variantNames()
|
||||
{
|
||||
m_params.emplace_back( new JOB_PARAM<wxString>( "field_delimiter",
|
||||
&m_fieldDelimiter,
|
||||
@@ -79,7 +80,9 @@ JOB_EXPORT_SCH_BOM::JOB_EXPORT_SCH_BOM() :
|
||||
&m_bomFmtPresetName,
|
||||
m_bomFmtPresetName ) );
|
||||
|
||||
m_params.emplace_back( new JOB_PARAM<wxString>( "variant", &m_variant, m_variant ) );
|
||||
m_params.emplace_back( new JOB_PARAM_LIST<wxString>( "variant_names",
|
||||
&m_variantNames,
|
||||
m_variantNames ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +55,9 @@ public:
|
||||
bool m_sortAsc;
|
||||
wxString m_filterString;
|
||||
bool m_excludeDNP;
|
||||
wxString m_variant;
|
||||
|
||||
// Variant names to export. Empty vector means default variant only.
|
||||
std::vector<wxString> m_variantNames;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,7 +55,8 @@ JOB_EXPORT_SCH_NETLIST::JOB_EXPORT_SCH_NETLIST() :
|
||||
m_spiceSaveAllVoltages( false ),
|
||||
m_spiceSaveAllCurrents( false ),
|
||||
m_spiceSaveAllDissipations( false ),
|
||||
m_spiceSaveAllEvents( false )
|
||||
m_spiceSaveAllEvents( false ),
|
||||
m_variantNames()
|
||||
{
|
||||
m_params.emplace_back( new JOB_PARAM<FORMAT>( "format", &format, format ) );
|
||||
m_params.emplace_back( new JOB_PARAM<bool>( "spice.save_all_voltages", &m_spiceSaveAllVoltages,
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define JOB_EXPORT_SCH_NETLIST_H
|
||||
|
||||
#include <kicommon.h>
|
||||
#include <vector>
|
||||
#include "job.h"
|
||||
|
||||
class KICOMMON_API JOB_EXPORT_SCH_NETLIST : public JOB
|
||||
@@ -54,6 +55,9 @@ public:
|
||||
bool m_spiceSaveAllCurrents;
|
||||
bool m_spiceSaveAllDissipations;
|
||||
bool m_spiceSaveAllEvents;
|
||||
|
||||
// Variant names to export. Empty vector means default variant only.
|
||||
std::vector<wxString> m_variantNames;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -53,7 +53,8 @@ JOB_EXPORT_SCH_PLOT::JOB_EXPORT_SCH_PLOT( bool aOutputIsDirectory ) :
|
||||
m_PDFPropertyPopups( true ),
|
||||
m_PDFHierarchicalLinks( true ),
|
||||
m_PDFMetadata( true ),
|
||||
m_theme()
|
||||
m_theme(),
|
||||
m_variantNames()
|
||||
{
|
||||
m_params.emplace_back( new JOB_PARAM<SCH_PLOT_FORMAT>( "format",
|
||||
&m_plotFormat, m_plotFormat ) );
|
||||
|
||||
@@ -68,6 +68,9 @@ public:
|
||||
bool m_PDFHierarchicalLinks;
|
||||
bool m_PDFMetadata;
|
||||
wxString m_theme;
|
||||
|
||||
// Variant names to export. Empty vector means default variant only.
|
||||
std::vector<wxString> m_variantNames;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -339,6 +339,7 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataToWindow()
|
||||
m_excludeFromSimCheckBox->SetValue( m_libEntry->GetExcludedFromSim() );
|
||||
m_excludeFromBomCheckBox->SetValue( m_libEntry->GetExcludedFromBOM() );
|
||||
m_excludeFromBoardCheckBox->SetValue( m_libEntry->GetExcludedFromBoard() );
|
||||
m_excludeFromPosFilesCheckBox->SetValue( m_libEntry->GetExcludedFromPosFiles() );
|
||||
|
||||
m_ShowPinNumButt->SetValue( m_libEntry->GetShowPinNumbers() );
|
||||
m_ShowPinNameButt->SetValue( m_libEntry->GetShowPinNames() );
|
||||
@@ -685,6 +686,7 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
m_libEntry->SetExcludedFromSim( m_excludeFromSimCheckBox->GetValue() );
|
||||
m_libEntry->SetExcludedFromBOM( m_excludeFromBomCheckBox->GetValue() );
|
||||
m_libEntry->SetExcludedFromBoard( m_excludeFromBoardCheckBox->GetValue() );
|
||||
m_libEntry->SetExcludedFromPosFiles( m_excludeFromPosFilesCheckBox->GetValue() );
|
||||
|
||||
m_libEntry->SetShowPinNumbers( m_ShowPinNumButt->GetValue() );
|
||||
m_libEntry->SetShowPinNames( m_ShowPinNameButt->GetValue() );
|
||||
@@ -1185,9 +1187,11 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::onPowerCheckBox( wxCommandEvent& aEvent )
|
||||
m_excludeFromSimCheckBox->SetValue( true );
|
||||
m_excludeFromBomCheckBox->SetValue( true );
|
||||
m_excludeFromBoardCheckBox->SetValue( true );
|
||||
m_excludeFromPosFilesCheckBox->SetValue( true );
|
||||
m_excludeFromBomCheckBox->Enable( false );
|
||||
m_excludeFromBoardCheckBox->Enable( false );
|
||||
m_excludeFromSimCheckBox->Enable( false );
|
||||
m_excludeFromPosFilesCheckBox->Enable( false );
|
||||
m_spiceFieldsButton->Show( false );
|
||||
m_OptionLocalPower->Enable( true );
|
||||
}
|
||||
@@ -1196,6 +1200,7 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::onPowerCheckBox( wxCommandEvent& aEvent )
|
||||
m_excludeFromBomCheckBox->Enable( true );
|
||||
m_excludeFromBoardCheckBox->Enable( true );
|
||||
m_excludeFromSimCheckBox->Enable( true );
|
||||
m_excludeFromPosFilesCheckBox->Enable( true );
|
||||
m_spiceFieldsButton->Show( true );
|
||||
m_OptionLocalPower->Enable( false );
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -262,6 +262,9 @@ DIALOG_LIB_SYMBOL_PROPERTIES_BASE::DIALOG_LIB_SYMBOL_PROPERTIES_BASE( wxWindow*
|
||||
m_excludeFromBoardCheckBox = new wxCheckBox( sbSizerAttributes->GetStaticBox(), wxID_ANY, _("Exclude from board"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sbSizerAttributes->Add( m_excludeFromBoardCheckBox, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_excludeFromPosFilesCheckBox = new wxCheckBox( sbSizerAttributes->GetStaticBox(), wxID_ANY, _("Exclude from position files"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sbSizerAttributes->Add( m_excludeFromPosFilesCheckBox, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bSizerRightCol->Add( sbSizerAttributes, 1, wxEXPAND|wxALL, 5 );
|
||||
|
||||
@@ -606,6 +609,7 @@ DIALOG_LIB_SYMBOL_PROPERTIES_BASE::DIALOG_LIB_SYMBOL_PROPERTIES_BASE( wxWindow*
|
||||
m_excludeFromSimCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_excludeFromBomCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_excludeFromBoardCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_excludeFromPosFilesCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_unitSpinCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnUnitSpinCtrlKillFocus ), NULL, this );
|
||||
m_unitSpinCtrl->Connect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnUnitSpinCtrl ), NULL, this );
|
||||
m_unitSpinCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnUnitSpinCtrlText ), NULL, this );
|
||||
@@ -651,6 +655,7 @@ DIALOG_LIB_SYMBOL_PROPERTIES_BASE::~DIALOG_LIB_SYMBOL_PROPERTIES_BASE()
|
||||
m_excludeFromSimCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_excludeFromBomCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_excludeFromBoardCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_excludeFromPosFilesCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_unitSpinCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnUnitSpinCtrlKillFocus ), NULL, this );
|
||||
m_unitSpinCtrl->Disconnect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnUnitSpinCtrl ), NULL, this );
|
||||
m_unitSpinCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES_BASE::OnUnitSpinCtrlText ), NULL, this );
|
||||
|
||||
@@ -1894,6 +1894,72 @@
|
||||
<event name="OnCheckBox">OnCheckBox</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Exclude from position files</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_excludeFromPosFilesCheckBox</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnCheckBox">OnCheckBox</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -75,6 +75,7 @@ class DIALOG_LIB_SYMBOL_PROPERTIES_BASE : public DIALOG_SHIM
|
||||
wxCheckBox* m_excludeFromSimCheckBox;
|
||||
wxCheckBox* m_excludeFromBomCheckBox;
|
||||
wxCheckBox* m_excludeFromBoardCheckBox;
|
||||
wxCheckBox* m_excludeFromPosFilesCheckBox;
|
||||
wxPanel* m_PanelUnitsAndBodyStyles;
|
||||
wxStaticText* m_staticTextNbUnits;
|
||||
wxSpinCtrl* m_unitSpinCtrl;
|
||||
|
||||
@@ -210,6 +210,7 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent,
|
||||
m_addVariantButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
|
||||
m_deleteVariantButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
m_renameVariantButton->SetBitmap( KiBitmapBundle( BITMAPS::small_edit ) );
|
||||
m_copyVariantButton->SetBitmap( KiBitmapBundle( BITMAPS::copy ) );
|
||||
|
||||
m_sidebarButton->SetBitmap( KiBitmapBundle( BITMAPS::left ) );
|
||||
|
||||
@@ -275,6 +276,8 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent,
|
||||
m_variantListBox->SetSelection( 0 );
|
||||
}
|
||||
|
||||
updateVariantButtonStates();
|
||||
|
||||
if( !ADVANCED_CFG::GetCfg().m_EnableVariantsUI )
|
||||
m_splitter_left->Unsplit( m_variantsPanel );
|
||||
|
||||
@@ -285,6 +288,9 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent,
|
||||
// non-job versions (which have different sizes).
|
||||
m_hash_key = TO_UTF8( GetTitle() );
|
||||
|
||||
// Set the current variant for highlighting variant-specific field values
|
||||
m_dataModel->SetCurrentVariant( m_parent->Schematic().GetCurrentVariant() );
|
||||
|
||||
SetInitialFocus( m_grid );
|
||||
m_grid->ClearSelection();
|
||||
|
||||
@@ -1559,7 +1565,10 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnOk( wxCommandEvent& aEvent )
|
||||
m_job->m_fieldsGroupBy.emplace_back( modelField.name );
|
||||
}
|
||||
|
||||
m_job->m_variant = getSelectedVariant();
|
||||
wxString selectedVariant = getSelectedVariant();
|
||||
|
||||
if( !selectedVariant.IsEmpty() )
|
||||
m_job->m_variantNames.push_back( selectedVariant );
|
||||
|
||||
EndModal( wxID_OK );
|
||||
}
|
||||
@@ -2614,24 +2623,26 @@ SCH_REFERENCE_LIST DIALOG_SYMBOL_FIELDS_TABLE::getSheetSymbolReferences( SCH_SHE
|
||||
|
||||
void DIALOG_SYMBOL_FIELDS_TABLE::onAddVariant( wxCommandEvent& aEvent )
|
||||
{
|
||||
wxTextEntryDialog dlg( this, _( "Add new variant name:" ), _( "New Variant" ), wxEmptyString,
|
||||
wxOK | wxCANCEL | wxCENTER );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
if( !m_parent->ShowAddVariantDialog() )
|
||||
return;
|
||||
|
||||
// Empty strings and duplicate variant names are not allowed.
|
||||
if( dlg.GetValue().IsEmpty() || ( m_variantListBox->FindString( dlg.GetValue() ) != wxNOT_FOUND ) )
|
||||
{
|
||||
wxBell();
|
||||
return;
|
||||
}
|
||||
wxArrayString ctrlContents;
|
||||
ctrlContents.Add( GetDefaultVariantName() );
|
||||
|
||||
wxArrayString ctrlContents = m_variantListBox->GetStrings();
|
||||
for( const wxString& variant : m_parent->Schematic().GetVariantNames() )
|
||||
ctrlContents.Add( variant );
|
||||
|
||||
ctrlContents.Add( dlg.GetValue() );
|
||||
ctrlContents.Sort( SortVariantNames );
|
||||
m_variantListBox->Set( ctrlContents );
|
||||
|
||||
wxString currentVariant = m_parent->Schematic().GetCurrentVariant();
|
||||
int newSelection = m_variantListBox->FindString(
|
||||
currentVariant.IsEmpty() ? GetDefaultVariantName() : currentVariant );
|
||||
|
||||
if( newSelection != wxNOT_FOUND )
|
||||
m_variantListBox->SetSelection( newSelection );
|
||||
|
||||
updateVariantButtonStates();
|
||||
}
|
||||
|
||||
|
||||
@@ -2642,49 +2653,152 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onDeleteVariant( wxCommandEvent& aEvent )
|
||||
// An empty or default selection cannot be deleted.
|
||||
if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
|
||||
{
|
||||
wxBell();
|
||||
m_parent->GetInfoBar()->ShowMessageFor( _( "Cannot delete the default variant." ),
|
||||
10000, wxICON_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
wxString variantName = m_variantListBox->GetString( selection );
|
||||
m_variantListBox->SetSelection( selection - 1 );
|
||||
m_variantListBox->Delete( selection );
|
||||
m_parent->Schematic().DeleteVariant( variantName );
|
||||
|
||||
int newSelection = std::max( 0, selection - 1 );
|
||||
m_variantListBox->SetSelection( newSelection );
|
||||
|
||||
wxString selectedVariant = getSelectedVariant();
|
||||
m_parent->SetCurrentVariant( selectedVariant );
|
||||
|
||||
if( m_grid->CommitPendingChanges( true ) )
|
||||
{
|
||||
m_dataModel->SetCurrentVariant( selectedVariant );
|
||||
m_dataModel->UpdateReferences( m_dataModel->GetReferenceList(), selectedVariant );
|
||||
m_dataModel->RebuildRows();
|
||||
|
||||
if( m_nbPages->GetSelection() == 1 )
|
||||
PreviewRefresh();
|
||||
else
|
||||
m_grid->ForceRefresh();
|
||||
}
|
||||
|
||||
updateVariantButtonStates();
|
||||
m_parent->UpdateVariantSelectionCtrl( m_parent->Schematic().GetVariantNamesForUI() );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_SYMBOL_FIELDS_TABLE::onRenameVariant( wxCommandEvent& aEvent )
|
||||
{
|
||||
// wxArrayInt selections;
|
||||
int selection = m_variantListBox->GetSelection();
|
||||
|
||||
// // Only allow renaming a single selection that is not the default.
|
||||
// if( ( m_variantListBox->GetSelections( selections ) != 1 ) || ( selections[0] == 0 ) )
|
||||
// {
|
||||
// wxBell();
|
||||
// return;
|
||||
// }
|
||||
// An empty or default selection cannot be renamed.
|
||||
if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
|
||||
{
|
||||
m_parent->GetInfoBar()->ShowMessageFor( _( "Cannot rename the default variant." ),
|
||||
10000, wxICON_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
// wxArrayString ctrlContents = m_variantListBox->GetStrings();
|
||||
// wxString oldVariantName = ctrlContents[selections[0]];
|
||||
wxString oldVariantName = m_variantListBox->GetString( selection );
|
||||
|
||||
// wxTextEntryDialog dlg( this, _( "Add new variant name:" ), _( "New Variant" ), oldVariantName,
|
||||
// wxOK | wxCANCEL | wxCENTER );
|
||||
wxTextEntryDialog dlg( this, _( "Enter new variant name:" ), _( "Rename Variant" ),
|
||||
oldVariantName, wxOK | wxCANCEL | wxCENTER );
|
||||
|
||||
// if( dlg.ShowModal() == wxID_CANCEL )
|
||||
// return;
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
// wxString newVariantName = dlg.GetValue();
|
||||
wxString newVariantName = dlg.GetValue().Trim().Trim( false );
|
||||
|
||||
// if( newVariantName.IsEmpty() || ( newVariantName == oldVariantName ) || ( newVariantName == ctrlContents[0] ) )
|
||||
// {
|
||||
// wxBell();
|
||||
// return;
|
||||
// }
|
||||
// Empty name is not allowed.
|
||||
if( newVariantName.IsEmpty() )
|
||||
{
|
||||
m_parent->GetInfoBar()->ShowMessageFor( _( "Variant name cannot be empty." ),
|
||||
10000, wxICON_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
// ctrlContents.Remove( m_variantListBox->GetString( selections[0] ) );
|
||||
// ctrlContents.Add( newVariantName );
|
||||
// ctrlContents.Sort( SortVariantNames );
|
||||
// m_variantListBox->Set( ctrlContents );
|
||||
// Same name - nothing to do
|
||||
if( newVariantName == oldVariantName )
|
||||
return;
|
||||
|
||||
// Duplicate name is not allowed.
|
||||
if( m_variantListBox->FindString( newVariantName ) != wxNOT_FOUND )
|
||||
{
|
||||
m_parent->GetInfoBar()->ShowMessageFor( wxString::Format( _( "Variant '%s' already exists." ),
|
||||
newVariantName ),
|
||||
10000, wxICON_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
m_parent->Schematic().RenameVariant( oldVariantName, newVariantName );
|
||||
|
||||
wxArrayString ctrlContents = m_variantListBox->GetStrings();
|
||||
ctrlContents.Remove( oldVariantName );
|
||||
ctrlContents.Add( newVariantName );
|
||||
ctrlContents.Sort( SortVariantNames );
|
||||
m_variantListBox->Set( ctrlContents );
|
||||
|
||||
int newSelection = m_variantListBox->FindString( newVariantName );
|
||||
|
||||
if( newSelection != wxNOT_FOUND )
|
||||
m_variantListBox->SetSelection( newSelection );
|
||||
|
||||
updateVariantButtonStates();
|
||||
m_parent->UpdateVariantSelectionCtrl( m_parent->Schematic().GetVariantNamesForUI() );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_SYMBOL_FIELDS_TABLE::onCopyVariant( wxCommandEvent& aEvent )
|
||||
{
|
||||
int selection = m_variantListBox->GetSelection();
|
||||
|
||||
// An empty or default selection cannot be copied.
|
||||
if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
|
||||
{
|
||||
m_parent->GetInfoBar()->ShowMessageFor( _( "Cannot copy the default variant." ),
|
||||
10000, wxICON_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
wxString sourceVariantName = m_variantListBox->GetString( selection );
|
||||
|
||||
wxTextEntryDialog dlg( this, _( "Enter name for the copied variant:" ), _( "Copy Variant" ),
|
||||
sourceVariantName + wxS( "_copy" ), wxOK | wxCANCEL | wxCENTER );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
wxString newVariantName = dlg.GetValue().Trim().Trim( false );
|
||||
|
||||
// Empty name is not allowed.
|
||||
if( newVariantName.IsEmpty() )
|
||||
{
|
||||
m_parent->GetInfoBar()->ShowMessageFor( _( "Variant name cannot be empty." ),
|
||||
10000, wxICON_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
// Duplicate name is not allowed.
|
||||
if( m_variantListBox->FindString( newVariantName ) != wxNOT_FOUND )
|
||||
{
|
||||
m_parent->GetInfoBar()->ShowMessageFor( wxString::Format( _( "Variant '%s' already exists." ),
|
||||
newVariantName ),
|
||||
10000, wxICON_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
m_parent->Schematic().CopyVariant( sourceVariantName, newVariantName );
|
||||
|
||||
wxArrayString ctrlContents = m_variantListBox->GetStrings();
|
||||
ctrlContents.Add( newVariantName );
|
||||
ctrlContents.Sort( SortVariantNames );
|
||||
m_variantListBox->Set( ctrlContents );
|
||||
|
||||
int newSelection = m_variantListBox->FindString( newVariantName );
|
||||
|
||||
if( newSelection != wxNOT_FOUND )
|
||||
m_variantListBox->SetSelection( newSelection );
|
||||
|
||||
updateVariantButtonStates();
|
||||
m_parent->UpdateVariantSelectionCtrl( m_parent->Schematic().GetVariantNamesForUI() );
|
||||
}
|
||||
|
||||
|
||||
@@ -2693,6 +2807,8 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onVariantSelectionChange( wxCommandEvent& aEven
|
||||
wxString currentVariant;
|
||||
wxString selectedVariant = getSelectedVariant();
|
||||
|
||||
updateVariantButtonStates();
|
||||
|
||||
if( m_parent )
|
||||
{
|
||||
currentVariant = m_parent->Schematic().GetCurrentVariant();
|
||||
@@ -2705,6 +2821,9 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onVariantSelectionChange( wxCommandEvent& aEven
|
||||
{
|
||||
if( m_grid->CommitPendingChanges( true ) )
|
||||
{
|
||||
// Update the data model's current variant for field highlighting
|
||||
m_dataModel->SetCurrentVariant( selectedVariant );
|
||||
|
||||
m_dataModel->UpdateReferences( m_dataModel->GetReferenceList(), selectedVariant );
|
||||
m_dataModel->RebuildRows();
|
||||
|
||||
@@ -2722,6 +2841,19 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onVariantSelectionChange( wxCommandEvent& aEven
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_SYMBOL_FIELDS_TABLE::updateVariantButtonStates()
|
||||
{
|
||||
int selection = m_variantListBox->GetSelection();
|
||||
|
||||
// Copy, rename, and delete are only enabled for non-default variant selections
|
||||
bool canModify = ( selection != wxNOT_FOUND ) && ( selection != 0 );
|
||||
|
||||
m_copyVariantButton->Enable( canModify );
|
||||
m_renameVariantButton->Enable( canModify );
|
||||
m_deleteVariantButton->Enable( canModify );
|
||||
}
|
||||
|
||||
|
||||
wxString DIALOG_SYMBOL_FIELDS_TABLE::getSelectedVariant() const
|
||||
{
|
||||
wxString retv;
|
||||
|
||||
@@ -142,8 +142,11 @@ private:
|
||||
void onAddVariant( wxCommandEvent& aEvent ) override;
|
||||
void onDeleteVariant( wxCommandEvent& aEvent ) override;
|
||||
void onRenameVariant( wxCommandEvent& aEvent ) override;
|
||||
void onCopyVariant( wxCommandEvent& aEvent ) override;
|
||||
void onVariantSelectionChange( wxCommandEvent& aEvent ) override;
|
||||
|
||||
void updateVariantButtonStates();
|
||||
|
||||
wxString getSelectedVariant() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -150,6 +150,9 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
m_renameVariantButton = new STD_BITMAP_BUTTON( m_variantsPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bSizer14->Add( m_renameVariantButton, 0, 0, 5 );
|
||||
|
||||
m_copyVariantButton = new STD_BITMAP_BUTTON( m_variantsPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bSizer14->Add( m_copyVariantButton, 0, 0, 5 );
|
||||
|
||||
|
||||
bSizer14->Add( 15, 0, 0, 0, 5 );
|
||||
|
||||
@@ -441,6 +444,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
m_variantListBox->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onVariantSelectionChange ), NULL, this );
|
||||
m_addVariantButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onAddVariant ), NULL, this );
|
||||
m_renameVariantButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onRenameVariant ), NULL, this );
|
||||
m_copyVariantButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onCopyVariant ), NULL, this );
|
||||
m_deleteVariantButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onDeleteVariant ), NULL, this );
|
||||
m_nbPages->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPageChanged ), NULL, this );
|
||||
m_filter->Connect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
@@ -480,6 +484,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::~DIALOG_SYMBOL_FIELDS_TABLE_BASE()
|
||||
m_variantListBox->Disconnect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onVariantSelectionChange ), NULL, this );
|
||||
m_addVariantButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onAddVariant ), NULL, this );
|
||||
m_renameVariantButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onRenameVariant ), NULL, this );
|
||||
m_copyVariantButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onCopyVariant ), NULL, this );
|
||||
m_deleteVariantButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::onDeleteVariant ), NULL, this );
|
||||
m_nbPages->Disconnect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPageChanged ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
|
||||
@@ -1226,6 +1226,81 @@
|
||||
<event name="OnButtonClick">onRenameVariant</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag"></property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">MyButton</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_copyVariantButton</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">onCopyVariant</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag"></property>
|
||||
|
||||
@@ -67,6 +67,7 @@ class DIALOG_SYMBOL_FIELDS_TABLE_BASE : public DIALOG_SHIM
|
||||
wxListBox* m_variantListBox;
|
||||
STD_BITMAP_BUTTON* m_addVariantButton;
|
||||
STD_BITMAP_BUTTON* m_renameVariantButton;
|
||||
STD_BITMAP_BUTTON* m_copyVariantButton;
|
||||
STD_BITMAP_BUTTON* m_deleteVariantButton;
|
||||
wxPanel* m_rightPanel;
|
||||
wxNotebook* m_nbPages;
|
||||
@@ -117,6 +118,7 @@ class DIALOG_SYMBOL_FIELDS_TABLE_BASE : public DIALOG_SHIM
|
||||
virtual void onVariantSelectionChange( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onAddVariant( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onRenameVariant( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onCopyVariant( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onDeleteVariant( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnPageChanged( wxNotebookEvent& event ) { event.Skip(); }
|
||||
virtual void OnFilterMouseMoved( wxMouseEvent& event ) { event.Skip(); }
|
||||
|
||||
@@ -550,6 +550,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
|
||||
m_cbExcludeFromSim->SetValue( m_symbol->GetExcludedFromSim( &sheetPath, variantName ) );
|
||||
m_cbExcludeFromBom->SetValue( m_symbol->GetExcludedFromBOM( &sheetPath, variantName ) );
|
||||
m_cbExcludeFromBoard->SetValue( m_symbol->GetExcludedFromBoard() );
|
||||
m_cbExcludeFromPosFiles->SetValue( m_symbol->GetExcludedFromPosFiles() );
|
||||
m_cbDNP->SetValue( m_symbol->GetDNP( &sheetPath, variantName ) );
|
||||
|
||||
if( m_part )
|
||||
@@ -784,8 +785,8 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
// Restore the default field text for existing fields.
|
||||
tmp->SetText( defaultText, ¤tSheet );
|
||||
|
||||
tmp->SetText( m_symbol->Schematic()->ConvertRefsToKIIDs( field.GetText() ),
|
||||
¤tSheet, currentVariant );
|
||||
wxString variantText = m_symbol->Schematic()->ConvertRefsToKIIDs( field.GetText() );
|
||||
tmp->SetText( variantText, ¤tSheet, currentVariant );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,6 +797,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
m_symbol->SetExcludedFromSim( m_cbExcludeFromSim->IsChecked(), ¤tSheet, currentVariant );
|
||||
m_symbol->SetExcludedFromBOM( m_cbExcludeFromBom->IsChecked(), ¤tSheet, currentVariant );
|
||||
m_symbol->SetExcludedFromBoard( m_cbExcludeFromBoard->IsChecked() );
|
||||
m_symbol->SetExcludedFromPosFiles( m_cbExcludeFromPosFiles->IsChecked() );
|
||||
m_symbol->SetDNP( m_cbDNP->IsChecked(), ¤tSheet, currentVariant );
|
||||
|
||||
// Update any assignments
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -218,6 +218,11 @@ DIALOG_SYMBOL_PROPERTIES_BASE::DIALOG_SYMBOL_PROPERTIES_BASE( wxWindow* parent,
|
||||
|
||||
sbAttributes->Add( m_cbExcludeFromBoard, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_cbExcludeFromPosFiles = new wxCheckBox( sbAttributes->GetStaticBox(), wxID_ANY, _("Exclude from position files"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cbExcludeFromPosFiles->SetToolTip( _("This is useful for adding symbols that should not be included in the \nexported position files used for pick and place machines") );
|
||||
|
||||
sbAttributes->Add( m_cbExcludeFromPosFiles, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_cbDNP = new wxCheckBox( sbAttributes->GetStaticBox(), wxID_ANY, _("Do not populate"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sbAttributes->Add( m_cbDNP, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
@@ -361,6 +366,7 @@ DIALOG_SYMBOL_PROPERTIES_BASE::DIALOG_SYMBOL_PROPERTIES_BASE( wxWindow* parent,
|
||||
m_cbExcludeFromSim->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_cbExcludeFromBom->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_cbExcludeFromBoard->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_cbExcludeFromPosFiles->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_updateSymbolBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnUpdateSymbol ), NULL, this );
|
||||
m_changeSymbolBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnExchangeSymbol ), NULL, this );
|
||||
m_editSchematicSymbolBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnEditSymbol ), NULL, this );
|
||||
@@ -393,6 +399,7 @@ DIALOG_SYMBOL_PROPERTIES_BASE::~DIALOG_SYMBOL_PROPERTIES_BASE()
|
||||
m_cbExcludeFromSim->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_cbExcludeFromBom->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_cbExcludeFromBoard->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_cbExcludeFromPosFiles->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnCheckBox ), NULL, this );
|
||||
m_updateSymbolBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnUpdateSymbol ), NULL, this );
|
||||
m_changeSymbolBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnExchangeSymbol ), NULL, this );
|
||||
m_editSchematicSymbolBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_PROPERTIES_BASE::OnEditSymbol ), NULL, this );
|
||||
|
||||
@@ -1569,6 +1569,72 @@
|
||||
<event name="OnCheckBox">OnCheckBox</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Exclude from position files</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_cbExcludeFromPosFiles</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip">This is useful for adding symbols that should not be included in the 
exported position files used for pick and place machines</property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnCheckBox">OnCheckBox</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -66,6 +66,7 @@ class DIALOG_SYMBOL_PROPERTIES_BASE : public DIALOG_SHIM
|
||||
wxCheckBox* m_cbExcludeFromSim;
|
||||
wxCheckBox* m_cbExcludeFromBom;
|
||||
wxCheckBox* m_cbExcludeFromBoard;
|
||||
wxCheckBox* m_cbExcludeFromPosFiles;
|
||||
wxCheckBox* m_cbDNP;
|
||||
wxButton* m_updateSymbolBtn;
|
||||
wxButton* m_changeSymbolBtn;
|
||||
|
||||
@@ -284,6 +284,16 @@ int EESCHEMA_JOBS_HANDLER::JobExportPlot( JOB* aJob )
|
||||
aJob->SetTitleBlock( sch->RootScreen()->GetTitleBlock() );
|
||||
sch->Project().ApplyTextVars( aJob->GetVarOverrides() );
|
||||
|
||||
// Apply variant if specified
|
||||
if( !aPlotJob->m_variantNames.empty() )
|
||||
{
|
||||
// For plot export, we use the first variant name from the set
|
||||
wxString variantName = *aPlotJob->m_variantNames.begin();
|
||||
|
||||
if( variantName != wxS( "all" ) )
|
||||
sch->SetCurrentVariant( variantName );
|
||||
}
|
||||
|
||||
std::unique_ptr<SCH_RENDER_SETTINGS> renderSettings = std::make_unique<SCH_RENDER_SETTINGS>();
|
||||
InitRenderSettings( renderSettings.get(), aPlotJob->m_theme, sch, aPlotJob->m_drawingSheet );
|
||||
|
||||
@@ -352,12 +362,14 @@ int EESCHEMA_JOBS_HANDLER::JobExportPlot( JOB* aJob )
|
||||
plotOpts.m_theme = aPlotJob->m_theme;
|
||||
plotOpts.m_useBackgroundColor = aPlotJob->m_useBackgroundColor;
|
||||
plotOpts.m_plotHopOver = aPlotJob->m_show_hop_over;
|
||||
plotOpts.m_variant = aPlotJob->m_variant;
|
||||
|
||||
// Use variant from m_variantNames if specified, otherwise use the schematic's current variant
|
||||
if( !aPlotJob->m_variantNames.empty() )
|
||||
plotOpts.m_variant = aPlotJob->m_variantNames.front();
|
||||
|
||||
// Always export dxf in mm by kicad-cli (similar to Pcbnew)
|
||||
plotOpts.m_DXF_File_Unit = DXF_UNITS::MM;
|
||||
|
||||
sch->SetCurrentVariant( plotOpts.m_variant );
|
||||
schPlotter->Plot( format, plotOpts, renderSettings.get(), m_reporter );
|
||||
|
||||
if( m_reporter->HasMessageOfSeverity( RPT_SEVERITY_ERROR ) )
|
||||
@@ -381,6 +393,16 @@ int EESCHEMA_JOBS_HANDLER::JobExportNetlist( JOB* aJob )
|
||||
aJob->SetTitleBlock( sch->RootScreen()->GetTitleBlock() );
|
||||
sch->Project().ApplyTextVars( aJob->GetVarOverrides() );
|
||||
|
||||
// Apply variant if specified
|
||||
if( !aNetJob->m_variantNames.empty() )
|
||||
{
|
||||
// For netlist export, we use the first variant name from the set
|
||||
wxString variantName = *aNetJob->m_variantNames.begin();
|
||||
|
||||
if( variantName != wxS( "all" ) )
|
||||
sch->SetCurrentVariant( variantName );
|
||||
}
|
||||
|
||||
// Annotation warning check
|
||||
SCH_REFERENCE_LIST referenceList;
|
||||
sch->Hierarchy().GetSymbols( referenceList );
|
||||
@@ -498,7 +520,16 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
|
||||
|
||||
aJob->SetTitleBlock( sch->RootScreen()->GetTitleBlock() );
|
||||
sch->Project().ApplyTextVars( aJob->GetVarOverrides() );
|
||||
sch->SetCurrentVariant( aBomJob->m_variant );
|
||||
|
||||
wxString currentVariant;
|
||||
|
||||
if( !aBomJob->m_variantNames.empty() )
|
||||
{
|
||||
currentVariant = aBomJob->m_variantNames.front();
|
||||
|
||||
if( currentVariant != wxS( "all" ) )
|
||||
sch->SetCurrentVariant( currentVariant );
|
||||
}
|
||||
|
||||
// Annotation warning check
|
||||
SCH_REFERENCE_LIST referenceList;
|
||||
@@ -536,16 +567,16 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
|
||||
for( FIELD_T fieldId : MANDATORY_FIELDS )
|
||||
{
|
||||
dataModel.AddColumn( GetCanonicalFieldName( fieldId ),
|
||||
GetDefaultFieldName( fieldId, DO_TRANSLATE ), false, aBomJob->m_variant );
|
||||
GetDefaultFieldName( fieldId, DO_TRANSLATE ), false, currentVariant );
|
||||
}
|
||||
|
||||
// Generated/virtual fields (e.g. ${QUANTITY}, ${ITEM_NUMBER}) present only in the fields table
|
||||
dataModel.AddColumn( FIELDS_EDITOR_GRID_DATA_MODEL::QUANTITY_VARIABLE,
|
||||
GetGeneratedFieldDisplayName( FIELDS_EDITOR_GRID_DATA_MODEL::QUANTITY_VARIABLE ),
|
||||
false, aBomJob->m_variant );
|
||||
false, currentVariant );
|
||||
dataModel.AddColumn( FIELDS_EDITOR_GRID_DATA_MODEL::ITEM_NUMBER_VARIABLE,
|
||||
GetGeneratedFieldDisplayName( FIELDS_EDITOR_GRID_DATA_MODEL::ITEM_NUMBER_VARIABLE ),
|
||||
false, aBomJob->m_variant );
|
||||
false, currentVariant );
|
||||
|
||||
// Attribute fields (boolean flags on symbols)
|
||||
dataModel.AddColumn( wxS( "${DNP}" ), GetGeneratedFieldDisplayName( wxS( "${DNP}" ) ),
|
||||
@@ -572,7 +603,7 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
|
||||
}
|
||||
|
||||
for( const wxString& fieldName : userFieldNames )
|
||||
dataModel.AddColumn( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, aBomJob->m_variant );
|
||||
dataModel.AddColumn( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, currentVariant );
|
||||
|
||||
// Add any templateFieldNames which aren't already present in the userFieldNames
|
||||
for( const TEMPLATE_FIELDNAME& templateFieldname :
|
||||
@@ -581,7 +612,7 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
|
||||
if( userFieldNames.count( templateFieldname.m_Name ) == 0 )
|
||||
{
|
||||
dataModel.AddColumn( templateFieldname.m_Name, GetGeneratedFieldDisplayName( templateFieldname.m_Name ),
|
||||
false, aBomJob->m_variant );
|
||||
false, currentVariant );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,41 +725,11 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
|
||||
preset.excludeDNP = aBomJob->m_excludeDNP;
|
||||
}
|
||||
|
||||
dataModel.ApplyBomPreset( preset, aBomJob->m_variant );
|
||||
|
||||
if( aBomJob->GetConfiguredOutputPath().IsEmpty() )
|
||||
{
|
||||
wxFileName fn = sch->GetFileName();
|
||||
fn.SetName( fn.GetName() );
|
||||
fn.SetExt( FILEEXT::CsvFileExtension );
|
||||
|
||||
aBomJob->SetConfiguredOutputPath( fn.GetFullName() );
|
||||
}
|
||||
|
||||
wxString outPath = aBomJob->GetFullOutputPath( &sch->Project() );
|
||||
|
||||
if( !PATHS::EnsurePathExists( outPath, true ) )
|
||||
{
|
||||
m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
|
||||
return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
|
||||
}
|
||||
|
||||
wxFile f;
|
||||
|
||||
if( !f.Open( outPath, wxFile::write ) )
|
||||
{
|
||||
m_reporter->Report( wxString::Format( _( "Unable to open destination '%s'" ), outPath ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
|
||||
return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
|
||||
}
|
||||
|
||||
BOM_FMT_PRESET fmt;
|
||||
|
||||
// Load a format preset if one is specified
|
||||
if( !aBomJob->m_bomFmtPresetName.IsEmpty() )
|
||||
{
|
||||
// Find the preset
|
||||
std::optional<BOM_FMT_PRESET> schFmtPreset;
|
||||
|
||||
for( const BOM_FMT_PRESET& p : BOM_FMT_PRESET::BuiltInPresets() )
|
||||
@@ -770,13 +771,76 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
|
||||
fmt.keepLineBreaks = aBomJob->m_keepLineBreaks;
|
||||
}
|
||||
|
||||
bool res = f.Write( dataModel.Export( fmt ) );
|
||||
if( aBomJob->GetConfiguredOutputPath().IsEmpty() )
|
||||
{
|
||||
wxFileName fn = sch->GetFileName();
|
||||
fn.SetName( fn.GetName() );
|
||||
fn.SetExt( FILEEXT::CsvFileExtension );
|
||||
|
||||
if( !res )
|
||||
return CLI::EXIT_CODES::ERR_UNKNOWN;
|
||||
aBomJob->SetConfiguredOutputPath( fn.GetFullName() );
|
||||
}
|
||||
|
||||
m_reporter->Report( wxString::Format( _( "Wrote bill of materials to '%s'." ), outPath ),
|
||||
RPT_SEVERITY_ACTION );
|
||||
wxString configuredPath = aBomJob->GetConfiguredOutputPath();
|
||||
bool hasVariantPlaceholder = configuredPath.Contains( wxS( "${VARIANT}" ) );
|
||||
|
||||
// Determine which variants to process
|
||||
std::vector<wxString> variantsToProcess;
|
||||
|
||||
if( aBomJob->m_variantNames.size() > 1 && hasVariantPlaceholder )
|
||||
{
|
||||
variantsToProcess = aBomJob->m_variantNames;
|
||||
}
|
||||
else
|
||||
{
|
||||
variantsToProcess.push_back( currentVariant );
|
||||
}
|
||||
|
||||
for( const wxString& variantName : variantsToProcess )
|
||||
{
|
||||
std::vector<wxString> singleVariant = { variantName };
|
||||
dataModel.SetVariantNames( singleVariant );
|
||||
dataModel.SetCurrentVariant( variantName );
|
||||
dataModel.ApplyBomPreset( preset, variantName );
|
||||
|
||||
wxString outPath;
|
||||
|
||||
if( hasVariantPlaceholder )
|
||||
{
|
||||
wxString variantPath = configuredPath;
|
||||
variantPath.Replace( wxS( "${VARIANT}" ), variantName );
|
||||
aBomJob->SetConfiguredOutputPath( variantPath );
|
||||
outPath = aBomJob->GetFullOutputPath( &sch->Project() );
|
||||
aBomJob->SetConfiguredOutputPath( configuredPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
outPath = aBomJob->GetFullOutputPath( &sch->Project() );
|
||||
}
|
||||
|
||||
if( !PATHS::EnsurePathExists( outPath, true ) )
|
||||
{
|
||||
m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
|
||||
return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
|
||||
}
|
||||
|
||||
wxFile f;
|
||||
|
||||
if( !f.Open( outPath, wxFile::write ) )
|
||||
{
|
||||
m_reporter->Report( wxString::Format( _( "Unable to open destination '%s'" ), outPath ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
|
||||
return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
|
||||
}
|
||||
|
||||
bool res = f.Write( dataModel.Export( fmt ) );
|
||||
|
||||
if( !res )
|
||||
return CLI::EXIT_CODES::ERR_UNKNOWN;
|
||||
|
||||
m_reporter->Report( wxString::Format( _( "Wrote bill of materials to '%s'." ), outPath ),
|
||||
RPT_SEVERITY_ACTION );
|
||||
}
|
||||
|
||||
return CLI::EXIT_CODES::OK;
|
||||
}
|
||||
|
||||
@@ -354,16 +354,87 @@ wxString FIELDS_EDITOR_GRID_DATA_MODEL::GetValue( int aRow, int aCol )
|
||||
|
||||
wxGridCellAttr* FIELDS_EDITOR_GRID_DATA_MODEL::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind )
|
||||
{
|
||||
wxGridCellAttr* attr = nullptr;
|
||||
|
||||
if( GetColFieldName( aCol ) == GetCanonicalFieldName( FIELD_T::DATASHEET )
|
||||
|| IsURL( GetValue( m_rows[aRow], aCol ) ) )
|
||||
{
|
||||
if( m_urlEditor )
|
||||
{
|
||||
m_urlEditor->IncRef();
|
||||
return enhanceAttr( m_urlEditor, aRow, aCol, aKind );
|
||||
attr = m_urlEditor;
|
||||
}
|
||||
}
|
||||
|
||||
// Highlight cells that differ from default when viewing a variant
|
||||
if( !m_currentVariant.IsEmpty() && aRow >= 0 && aRow < (int) m_rows.size()
|
||||
&& aCol >= 0 && aCol < (int) m_cols.size() )
|
||||
{
|
||||
const wxString& fieldName = m_cols[aCol].m_fieldName;
|
||||
|
||||
// Skip Reference and generated fields (like ${QUANTITY}) for highlighting
|
||||
if( !ColIsReference( aCol ) && !ColIsQuantity( aCol ) && !ColIsItemNumber( aCol ) )
|
||||
{
|
||||
const DATA_MODEL_ROW& row = m_rows[aRow];
|
||||
|
||||
// Check if any symbol in this row has a variant-specific value
|
||||
bool hasVariantDifference = false;
|
||||
|
||||
for( const SCH_REFERENCE& ref : row.m_Refs )
|
||||
{
|
||||
wxString defaultValue = getDefaultFieldValue( ref, fieldName );
|
||||
|
||||
KIID_PATH symbolKey = KIID_PATH();
|
||||
|
||||
if( const SCH_SYMBOL* symbol = ref.GetSymbol() )
|
||||
{
|
||||
symbolKey = ref.GetSheetPath().Path();
|
||||
symbolKey.push_back( symbol->m_Uuid );
|
||||
}
|
||||
|
||||
// Get the current value from the data store
|
||||
wxString currentValue;
|
||||
|
||||
if( m_dataStore.contains( symbolKey ) && m_dataStore[symbolKey].contains( fieldName ) )
|
||||
currentValue = m_dataStore[symbolKey][fieldName];
|
||||
|
||||
if( currentValue != defaultValue )
|
||||
{
|
||||
hasVariantDifference = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( hasVariantDifference )
|
||||
{
|
||||
if( !attr )
|
||||
{
|
||||
attr = new wxGridCellAttr();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clone so we don't modify the shared URL editor attr
|
||||
wxGridCellAttr* newAttr = attr->Clone();
|
||||
attr->DecRef();
|
||||
attr = newAttr;
|
||||
}
|
||||
|
||||
// Use a subtle highlight color that works in both light and dark themes
|
||||
// Light yellow in light mode, darker yellow-ish in dark mode
|
||||
wxColour bg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
|
||||
bool isDark = ( bg.Red() + bg.Green() + bg.Blue() ) < 384;
|
||||
|
||||
if( isDark )
|
||||
attr->SetBackgroundColour( wxColour( 80, 80, 40 ) ); // Dark gold/brown
|
||||
else
|
||||
attr->SetBackgroundColour( wxColour( 255, 255, 200 ) ); // Light yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( attr )
|
||||
return enhanceAttr( attr, aRow, aCol, aKind );
|
||||
|
||||
return WX_GRID_TABLE_BASE::GetAttr( aRow, aCol, aKind );
|
||||
}
|
||||
|
||||
@@ -784,6 +855,38 @@ wxString FIELDS_EDITOR_GRID_DATA_MODEL::getAttributeValue( const SCH_REFERENCE&
|
||||
}
|
||||
|
||||
|
||||
wxString FIELDS_EDITOR_GRID_DATA_MODEL::getDefaultFieldValue( const SCH_REFERENCE& aRef,
|
||||
const wxString& aFieldName )
|
||||
{
|
||||
const SCH_SYMBOL* symbol = aRef.GetSymbol();
|
||||
|
||||
if( !symbol )
|
||||
return wxEmptyString;
|
||||
|
||||
// For attributes, get the default (non-variant) value
|
||||
if( isAttribute( aFieldName ) )
|
||||
return getAttributeValue( aRef, aFieldName, wxEmptyString );
|
||||
|
||||
// For regular fields, get the text without variant override
|
||||
if( const SCH_FIELD* field = symbol->GetField( aFieldName ) )
|
||||
{
|
||||
if( field->IsPrivate() )
|
||||
return wxEmptyString;
|
||||
|
||||
// Get the field text with empty variant name (default value)
|
||||
wxString value = symbol->Schematic()->ConvertKIIDsToRefs(
|
||||
field->GetText( &aRef.GetSheetPath(), wxEmptyString ) );
|
||||
return value;
|
||||
}
|
||||
|
||||
// For generated fields, return the field name itself
|
||||
if( IsGeneratedField( aFieldName ) )
|
||||
return aFieldName;
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
bool FIELDS_EDITOR_GRID_DATA_MODEL::setAttributeValue( SCH_REFERENCE& aRef,
|
||||
const wxString& aAttributeName,
|
||||
const wxString& aValue,
|
||||
@@ -855,16 +958,56 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::RebuildRows()
|
||||
if( !m_filter.IsEmpty() && !matcher.Find( ref.GetFullRef().Lower() ) )
|
||||
continue;
|
||||
|
||||
if( m_excludeDNP && ( ref.GetSymbol()->GetDNP( &ref.GetSheetPath() )
|
||||
|| ref.GetSheetPath().GetDNP() ) )
|
||||
if( m_excludeDNP )
|
||||
{
|
||||
continue;
|
||||
bool isDNP = false;
|
||||
|
||||
if( !m_variantNames.empty() )
|
||||
{
|
||||
for( const wxString& variantName : m_variantNames )
|
||||
{
|
||||
if( ref.GetSymbol()->GetDNP( &ref.GetSheetPath(), variantName )
|
||||
|| ref.GetSheetPath().GetDNP( variantName ) )
|
||||
{
|
||||
isDNP = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isDNP = ref.GetSymbol()->GetDNP( &ref.GetSheetPath(), m_currentVariant )
|
||||
|| ref.GetSheetPath().GetDNP( m_currentVariant );
|
||||
}
|
||||
|
||||
if( isDNP )
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !m_includeExcluded && ( ref.GetSymbol()->GetExcludedFromBOM()
|
||||
|| ref.GetSheetPath().GetExcludedFromBOM() ) )
|
||||
if( !m_includeExcluded )
|
||||
{
|
||||
continue;
|
||||
bool isExcluded = false;
|
||||
|
||||
if( !m_variantNames.empty() )
|
||||
{
|
||||
for( const wxString& variantName : m_variantNames )
|
||||
{
|
||||
if( ref.GetSymbol()->GetExcludedFromBOM( &ref.GetSheetPath(), variantName )
|
||||
|| ref.GetSheetPath().GetExcludedFromBOM( variantName ) )
|
||||
{
|
||||
isExcluded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isExcluded = ref.GetSymbol()->GetExcludedFromBOM( &ref.GetSheetPath(), m_currentVariant )
|
||||
|| ref.GetSheetPath().GetExcludedFromBOM( m_currentVariant );
|
||||
}
|
||||
|
||||
if( isExcluded )
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the symbol if on the current sheet or, in the sheet path somewhere
|
||||
@@ -1210,6 +1353,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyBomPreset( const BOM_PRESET& aPreset, c
|
||||
SetFilter( aPreset.filterString );
|
||||
SetExcludeDNP( aPreset.excludeDNP );
|
||||
SetIncludeExcludedFromBOM( aPreset.includeExcludedFromBOM );
|
||||
SetCurrentVariant( aVariantName );
|
||||
|
||||
RebuildRows();
|
||||
}
|
||||
|
||||
@@ -332,6 +332,20 @@ public:
|
||||
|
||||
const SCH_REFERENCE_LIST& GetReferenceList() const { return m_symbolsList; }
|
||||
|
||||
/**
|
||||
* Set the current variant name for highlighting purposes.
|
||||
*
|
||||
* When a variant is set, cells that differ from the default (non-variant) value
|
||||
* will be highlighted.
|
||||
*
|
||||
* @param aVariantName The name of the current variant, or empty string for default.
|
||||
*/
|
||||
void SetCurrentVariant( const wxString& aVariantName ) { m_currentVariant = aVariantName; }
|
||||
const wxString& GetCurrentVariant() const { return m_currentVariant; }
|
||||
|
||||
void SetVariantNames( const std::vector<wxString>& aVariantNames ) { m_variantNames = aVariantNames; }
|
||||
const std::vector<wxString>& GetVariantNames() const { return m_variantNames; }
|
||||
|
||||
private:
|
||||
static bool cmp( const DATA_MODEL_ROW& lhGroup, const DATA_MODEL_ROW& rhGroup,
|
||||
FIELDS_EDITOR_GRID_DATA_MODEL* dataModel, int sortCol, bool ascending );
|
||||
@@ -345,6 +359,17 @@ private:
|
||||
wxString getAttributeValue( const SCH_REFERENCE& aRef, const wxString& aAttributeName,
|
||||
const wxString& aVariantNames );
|
||||
|
||||
/**
|
||||
* Get the default (non-variant) value for a field.
|
||||
*
|
||||
* This retrieves the field value as it would appear without any variant override.
|
||||
*
|
||||
* @param aRef The symbol reference.
|
||||
* @param aFieldName The name of the field.
|
||||
* @return The default field value.
|
||||
*/
|
||||
wxString getDefaultFieldValue( const SCH_REFERENCE& aRef, const wxString& aFieldName );
|
||||
|
||||
/**
|
||||
* Set the attribute value.
|
||||
*
|
||||
@@ -388,6 +413,8 @@ protected:
|
||||
bool m_includeExcluded;
|
||||
bool m_rebuildsEnabled;
|
||||
wxGridCellAttr* m_urlEditor;
|
||||
wxString m_currentVariant; ///< Current variant name for highlighting
|
||||
std::vector<wxString> m_variantNames; ///< Variant names for multi-variant DNP filtering
|
||||
|
||||
std::vector<DATA_MODEL_COL> m_cols;
|
||||
std::vector<DATA_MODEL_ROW> m_rows;
|
||||
|
||||
+19
-2
@@ -2129,6 +2129,15 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
|
||||
if( m_excludedFromPosFiles != aRhs.m_excludedFromPosFiles )
|
||||
{
|
||||
retv = ( m_excludedFromPosFiles ) ? -1 : 1;
|
||||
REPORT( _( "Exclude from position files settings differ." ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
}
|
||||
|
||||
if( !aReporter )
|
||||
@@ -2223,6 +2232,9 @@ double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
|
||||
if( m_excludedFromSim != other.m_excludedFromSim )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_excludedFromPosFiles != other.m_excludedFromPosFiles )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_flags != other.m_flags )
|
||||
similarity *= 0.9;
|
||||
|
||||
@@ -2396,13 +2408,18 @@ static struct LIB_SYMBOL_DESC
|
||||
&LIB_SYMBOL::SetExcludedFromSimProp,
|
||||
&LIB_SYMBOL::GetExcludedFromSimProp ),
|
||||
groupAttributes );
|
||||
propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Exclude from Board" ), &SYMBOL::SetExcludedFromBoard,
|
||||
&SYMBOL::GetExcludedFromBoard ),
|
||||
propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Board" ),
|
||||
&LIB_SYMBOL::SetExcludedFromBoardProp,
|
||||
&LIB_SYMBOL::GetExcludedFromBoardProp ),
|
||||
groupAttributes );
|
||||
propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Bill of Materials" ),
|
||||
&LIB_SYMBOL::SetExcludedFromBOMProp,
|
||||
&LIB_SYMBOL::GetExcludedFromBOMProp ),
|
||||
groupAttributes );
|
||||
propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Position Files" ),
|
||||
&LIB_SYMBOL::SetExcludedFromPosFilesProp,
|
||||
&LIB_SYMBOL::GetExcludedFromPosFilesProp ),
|
||||
groupAttributes );
|
||||
|
||||
const wxString groupUnits = _HKI( "Units and Body Styles" );
|
||||
|
||||
|
||||
@@ -507,6 +507,19 @@ public:
|
||||
SetExcludedFromBOM( aExclude );
|
||||
}
|
||||
|
||||
bool GetExcludedFromBoardProp() const
|
||||
{
|
||||
return GetExcludedFromBoard();
|
||||
}
|
||||
|
||||
void SetExcludedFromBoardProp( bool aExclude )
|
||||
{
|
||||
SetExcludedFromBoard( aExclude );
|
||||
}
|
||||
|
||||
bool GetExcludedFromPosFilesProp() const { return GetExcludedFromPosFiles(); }
|
||||
void SetExcludedFromPosFilesProp( bool aExclude ) { SetExcludedFromPosFiles( aExclude ); }
|
||||
|
||||
std::set<KIFONT::OUTLINE_FONT*> GetFonts() const override;
|
||||
|
||||
EMBEDDED_FILES* GetEmbeddedFiles() override;
|
||||
|
||||
@@ -396,6 +396,12 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl )
|
||||
xproperty->AddAttribute( wxT( "name" ), wxT( "exclude_from_board" ) );
|
||||
}
|
||||
|
||||
if( symbol->ResolveExcludedFromPosFiles() )
|
||||
{
|
||||
xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
|
||||
xproperty->AddAttribute( wxT( "name" ), wxT( "exclude_from_pos_files" ) );
|
||||
}
|
||||
|
||||
if( symbol->ResolveDNP() || sheet.GetDNP() )
|
||||
{
|
||||
xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
|
||||
|
||||
@@ -267,6 +267,13 @@ public:
|
||||
|
||||
void SetCurrentVariant( const wxString& aVariantName );
|
||||
|
||||
/**
|
||||
* Show a dialog to create a new variant with name and description.
|
||||
*
|
||||
* @return true if a variant was created, false if cancelled or invalid input
|
||||
*/
|
||||
bool ShowAddVariantDialog();
|
||||
|
||||
void onVariantSelected( wxCommandEvent& aEvent );
|
||||
|
||||
/**
|
||||
|
||||
@@ -1089,7 +1089,6 @@ void SCH_FIELD::SetText( const wxString& aText, const SCH_SHEET_PATH* aPath, con
|
||||
{
|
||||
wxCHECK( aPath && m_parent, /* void */ );
|
||||
|
||||
// Don't allow modification of text value of generated fields.
|
||||
if( m_isGeneratedField )
|
||||
return;
|
||||
|
||||
|
||||
@@ -133,4 +133,5 @@
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20250901 // Stacked Pin notation
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20250922 // Schematic variants.
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20251012 // Flat schematic hierarchy support
|
||||
#define SEXPR_SCHEMATIC_FILE_VERSION 20251028 // Updated properties formatting (do_not_autoplace, show_name)
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20251028 // Updated properties formatting (do_not_autoplace, show_name)
|
||||
#define SEXPR_SCHEMATIC_FILE_VERSION 20260101 // PCB variants
|
||||
|
||||
@@ -736,6 +736,7 @@ void SCH_IO_KICAD_SEXPR::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSche
|
||||
KICAD_FORMAT::FormatBool( m_out, "exclude_from_sim", aSymbol->GetExcludedFromSim() );
|
||||
KICAD_FORMAT::FormatBool( m_out, "in_bom", !aSymbol->GetExcludedFromBOM() );
|
||||
KICAD_FORMAT::FormatBool( m_out, "on_board", !aSymbol->GetExcludedFromBoard() );
|
||||
KICAD_FORMAT::FormatBool( m_out, "in_pos_files", !aSymbol->GetExcludedFromPosFiles() );
|
||||
KICAD_FORMAT::FormatBool( m_out, "dnp", aSymbol->GetDNP() );
|
||||
|
||||
AUTOPLACE_ALGO fieldsAutoplaced = aSymbol->GetFieldsAutoplaced();
|
||||
@@ -909,6 +910,12 @@ void SCH_IO_KICAD_SEXPR::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSche
|
||||
if( variant.m_ExcludedFromBOM != aSymbol->GetExcludedFromBOM() )
|
||||
KICAD_FORMAT::FormatBool( m_out, "in_bom", variant.m_ExcludedFromBOM );
|
||||
|
||||
if( variant.m_ExcludedFromBoard != aSymbol->GetExcludedFromBoard() )
|
||||
KICAD_FORMAT::FormatBool( m_out, "on_board", !variant.m_ExcludedFromBoard );
|
||||
|
||||
if( variant.m_ExcludedFromPosFiles != aSymbol->GetExcludedFromPosFiles() )
|
||||
KICAD_FORMAT::FormatBool( m_out, "in_pos_files", !variant.m_ExcludedFromPosFiles );
|
||||
|
||||
for( const auto&[fname, fvalue] : variant.m_Fields )
|
||||
{
|
||||
m_out->Print( "(field (name %s) (value %s))",
|
||||
|
||||
@@ -330,6 +330,7 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMAT
|
||||
KICAD_FORMAT::FormatBool( &aFormatter, "exclude_from_sim", aSymbol->GetExcludedFromSim() );
|
||||
KICAD_FORMAT::FormatBool( &aFormatter, "in_bom", !aSymbol->GetExcludedFromBOM() );
|
||||
KICAD_FORMAT::FormatBool( &aFormatter, "on_board", !aSymbol->GetExcludedFromBoard() );
|
||||
KICAD_FORMAT::FormatBool( &aFormatter, "in_pos_files", !aSymbol->GetExcludedFromPosFiles() );
|
||||
|
||||
KICAD_FORMAT::FormatBool( &aFormatter, "duplicate_pin_numbers_are_jumpers",
|
||||
aSymbol->GetDuplicatePinNumbersAreJumpers() );
|
||||
|
||||
@@ -417,6 +417,11 @@ LIB_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseLibSymbol( LIB_SYMBOL_MAP& aSymbolLi
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_in_pos_files:
|
||||
symbol->SetExcludedFromPosFiles( !parseBool() );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_duplicate_pin_numbers_are_jumpers:
|
||||
symbol->SetDuplicatePinNumbersAreJumpers( parseBool() );
|
||||
NeedRIGHT();
|
||||
@@ -3211,6 +3216,11 @@ SCH_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseSchematicSymbol()
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_in_pos_files:
|
||||
symbol->SetExcludedFromPosFiles( !parseBool() );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_dnp:
|
||||
symbol->SetDNP( parseBool() );
|
||||
NeedRIGHT();
|
||||
@@ -3392,6 +3402,16 @@ SCH_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseSchematicSymbol()
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_on_board:
|
||||
variant.m_ExcludedFromBoard = !parseBool();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_in_pos_files:
|
||||
variant.m_ExcludedFromPosFiles = !parseBool();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_field:
|
||||
{
|
||||
wxString fieldName;
|
||||
@@ -3428,7 +3448,7 @@ SCH_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseSchematicSymbol()
|
||||
}
|
||||
|
||||
default:
|
||||
Expecting( "dnp, exclude_from_sim, field, in_bom, or name" );
|
||||
Expecting( "dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
|
||||
}
|
||||
|
||||
instance.m_Variants[variant.m_Name] = variant;
|
||||
@@ -3843,6 +3863,16 @@ SCH_SHEET* SCH_IO_KICAD_SEXPR_PARSER::parseSheet()
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_on_board:
|
||||
variant.m_ExcludedFromBoard = !parseBool();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_in_pos_files:
|
||||
variant.m_ExcludedFromPosFiles = !parseBool();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_field:
|
||||
{
|
||||
wxString fieldName;
|
||||
@@ -3879,7 +3909,7 @@ SCH_SHEET* SCH_IO_KICAD_SEXPR_PARSER::parseSheet()
|
||||
}
|
||||
|
||||
default:
|
||||
Expecting( "dnp, exclude_from_sim, field, in_bom, or name" );
|
||||
Expecting( "dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
|
||||
}
|
||||
|
||||
instance.m_Variants[variant.m_Name] = variant;
|
||||
|
||||
+20
-3
@@ -306,14 +306,31 @@ bool SCH_ITEM::ResolveExcludedFromBOM( const SCH_SHEET_PATH* aInstance,
|
||||
}
|
||||
|
||||
|
||||
bool SCH_ITEM::ResolveExcludedFromBoard() const
|
||||
bool SCH_ITEM::ResolveExcludedFromBoard( const SCH_SHEET_PATH* aInstance,
|
||||
const wxString& aVariantName ) const
|
||||
{
|
||||
if( GetExcludedFromBoard() )
|
||||
if( GetExcludedFromBoard( aInstance, aVariantName ) )
|
||||
return true;
|
||||
|
||||
for( SCH_RULE_AREA* area : m_rule_areas_cache )
|
||||
{
|
||||
if( area->GetExcludedFromBoard() )
|
||||
if( area->GetExcludedFromBoard( aInstance, aVariantName ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_ITEM::ResolveExcludedFromPosFiles( const SCH_SHEET_PATH* aInstance,
|
||||
const wxString& aVariantName ) const
|
||||
{
|
||||
if( GetExcludedFromPosFiles( aInstance, aVariantName ) )
|
||||
return true;
|
||||
|
||||
for( SCH_RULE_AREA* area : m_rule_areas_cache )
|
||||
{
|
||||
if( area->GetExcludedFromPosFiles( aInstance, aVariantName ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+13
-3
@@ -266,9 +266,19 @@ public:
|
||||
bool ResolveExcludedFromBOM( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const;
|
||||
|
||||
virtual void SetExcludedFromBoard( bool aExcludeFromBoard ) { }
|
||||
virtual bool GetExcludedFromBoard() const { return false; }
|
||||
bool ResolveExcludedFromBoard() const;
|
||||
virtual void SetExcludedFromBoard( bool aExclude, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) { }
|
||||
virtual bool GetExcludedFromBoard( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const { return false; }
|
||||
bool ResolveExcludedFromBoard( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const;
|
||||
|
||||
virtual void SetExcludedFromPosFiles( bool aExclude, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) { }
|
||||
virtual bool GetExcludedFromPosFiles( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const { return false; }
|
||||
bool ResolveExcludedFromPosFiles( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const;
|
||||
|
||||
virtual void SetDNP( bool aDNP, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) { }
|
||||
|
||||
@@ -91,8 +91,17 @@ public:
|
||||
/**
|
||||
* Set or clear exclude from board netlist flag.
|
||||
*/
|
||||
void SetExcludedFromBoard( bool aExcludeFromBoard ) override { m_excludedFromBoard = aExcludeFromBoard; }
|
||||
bool GetExcludedFromBoard() const override { return m_excludedFromBoard; }
|
||||
void SetExcludedFromBoard( bool aExclude, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) override
|
||||
{
|
||||
m_excludedFromBoard = aExclude;
|
||||
}
|
||||
|
||||
bool GetExcludedFromBoard( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const override
|
||||
{
|
||||
return m_excludedFromBoard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or clear the 'Do Not Populate' flag.
|
||||
|
||||
@@ -1904,6 +1904,100 @@ void SCH_SCREEN::DeleteVariant( const wxString& aVariantName, SCH_COMMIT* aCommi
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::RenameVariant( const wxString& aOldName, const wxString& aNewName,
|
||||
SCH_COMMIT* aCommit )
|
||||
{
|
||||
wxCHECK( !aOldName.IsEmpty() && !aNewName.IsEmpty(), /* void */ );
|
||||
|
||||
for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
|
||||
|
||||
for( SCH_SYMBOL_INSTANCE& instance : symbolInstances )
|
||||
{
|
||||
if( instance.m_Variants.contains( aOldName ) )
|
||||
{
|
||||
if( aCommit )
|
||||
aCommit->Modify( item, this );
|
||||
|
||||
symbol->RenameVariant( instance.m_Path, aOldName, aNewName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
|
||||
{
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
wxCHECK2( sheet, continue );
|
||||
|
||||
std::vector<SCH_SHEET_INSTANCE> sheetInstances = sheet->GetInstances();
|
||||
|
||||
for( SCH_SHEET_INSTANCE& instance : sheetInstances )
|
||||
{
|
||||
if( instance.m_Variants.contains( aOldName ) )
|
||||
{
|
||||
if( aCommit )
|
||||
aCommit->Modify( item, this );
|
||||
|
||||
sheet->RenameVariant( instance.m_Path, aOldName, aNewName );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::CopyVariant( const wxString& aSourceVariant, const wxString& aNewVariant,
|
||||
SCH_COMMIT* aCommit )
|
||||
{
|
||||
wxCHECK( !aSourceVariant.IsEmpty() && !aNewVariant.IsEmpty(), /* void */ );
|
||||
|
||||
for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
|
||||
|
||||
for( SCH_SYMBOL_INSTANCE& instance : symbolInstances )
|
||||
{
|
||||
if( instance.m_Variants.contains( aSourceVariant ) )
|
||||
{
|
||||
if( aCommit )
|
||||
aCommit->Modify( item, this );
|
||||
|
||||
symbol->CopyVariant( instance.m_Path, aSourceVariant, aNewVariant );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
|
||||
{
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
wxCHECK2( sheet, continue );
|
||||
|
||||
std::vector<SCH_SHEET_INSTANCE> sheetInstances = sheet->GetInstances();
|
||||
|
||||
for( SCH_SHEET_INSTANCE& instance : sheetInstances )
|
||||
{
|
||||
if( instance.m_Variants.contains( aSourceVariant ) )
|
||||
{
|
||||
if( aCommit )
|
||||
aCommit->Modify( item, this );
|
||||
|
||||
sheet->CopyVariant( instance.m_Path, aSourceVariant, aNewVariant );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
||||
{
|
||||
@@ -2365,3 +2459,23 @@ void SCH_SCREENS::DeleteVariant( const wxString& aVariantName, SCH_COMMIT* aComm
|
||||
for( SCH_SCREEN* screen : m_screens )
|
||||
screen->DeleteVariant( aVariantName, aCommit );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREENS::RenameVariant( const wxString& aOldName, const wxString& aNewName,
|
||||
SCH_COMMIT* aCommit )
|
||||
{
|
||||
wxCHECK( !aOldName.IsEmpty() && !aNewName.IsEmpty(), /* void */ );
|
||||
|
||||
for( SCH_SCREEN* screen : m_screens )
|
||||
screen->RenameVariant( aOldName, aNewName, aCommit );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREENS::CopyVariant( const wxString& aSourceVariant, const wxString& aNewVariant,
|
||||
SCH_COMMIT* aCommit )
|
||||
{
|
||||
wxCHECK( !aSourceVariant.IsEmpty() && !aNewVariant.IsEmpty(), /* void */ );
|
||||
|
||||
for( SCH_SCREEN* screen : m_screens )
|
||||
screen->CopyVariant( aSourceVariant, aNewVariant, aCommit );
|
||||
}
|
||||
|
||||
@@ -631,6 +631,12 @@ public:
|
||||
|
||||
void DeleteVariant( const wxString& aVariantName, SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
void RenameVariant( const wxString& aOldName, const wxString& aNewName,
|
||||
SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
void CopyVariant( const wxString& aSourceVariant, const wxString& aNewVariant,
|
||||
SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
private:
|
||||
friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances.
|
||||
friend SCH_IO_KICAD_SEXPR_PARSER; // Only to load instance information from schematic file.
|
||||
@@ -872,6 +878,12 @@ public:
|
||||
|
||||
void DeleteVariant( const wxString& aVariantName, SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
void RenameVariant( const wxString& aOldName, const wxString& aNewName,
|
||||
SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
void CopyVariant( const wxString& aSourceVariant, const wxString& aNewVariant,
|
||||
SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
private:
|
||||
void addScreenToList( SCH_SCREEN* aScreen, SCH_SHEET* aSheet );
|
||||
void buildScreenList( SCH_SHEET* aSheet);
|
||||
|
||||
+34
-1
@@ -1851,6 +1851,39 @@ void SCH_SHEET::DeleteVariant( const KIID_PATH& aPath, const wxString& aVariantN
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET::RenameVariant( const KIID_PATH& aPath, const wxString& aOldName,
|
||||
const wxString& aNewName )
|
||||
{
|
||||
SCH_SHEET_INSTANCE* instance = getInstance( aPath );
|
||||
|
||||
// The instance path must already exist and contain the old variant.
|
||||
if( !instance || !instance->m_Variants.contains( aOldName ) )
|
||||
return;
|
||||
|
||||
// Get the variant data, update the name, and re-insert with new key
|
||||
SCH_SHEET_VARIANT variant = instance->m_Variants[aOldName];
|
||||
variant.m_Name = aNewName;
|
||||
instance->m_Variants.erase( aOldName );
|
||||
instance->m_Variants.insert( std::make_pair( aNewName, variant ) );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET::CopyVariant( const KIID_PATH& aPath, const wxString& aSourceVariant,
|
||||
const wxString& aNewVariant )
|
||||
{
|
||||
SCH_SHEET_INSTANCE* instance = getInstance( aPath );
|
||||
|
||||
// The instance path must already exist and contain the source variant.
|
||||
if( !instance || !instance->m_Variants.contains( aSourceVariant ) )
|
||||
return;
|
||||
|
||||
// Copy the variant data with a new name
|
||||
SCH_SHEET_VARIANT variant = instance->m_Variants[aSourceVariant];
|
||||
variant.m_Name = aNewVariant;
|
||||
instance->m_Variants.insert( std::make_pair( aNewVariant, variant ) );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET::SetDNP( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
|
||||
{
|
||||
if( !aInstance || aVariantName.IsEmpty() )
|
||||
@@ -2114,7 +2147,7 @@ static struct SCH_SHEET_DESC
|
||||
const wxString groupAttributes = _HKI( "Attributes" );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Board" ),
|
||||
&SCH_SHEET::SetExcludedFromBoard, &SCH_SHEET::GetExcludedFromBoard ),
|
||||
&SCH_SHEET::SetExcludedFromBoardProp, &SCH_SHEET::GetExcludedFromBoardProp ),
|
||||
groupAttributes );
|
||||
propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Simulation" ),
|
||||
&SCH_SHEET::SetExcludedFromSimProp, &SCH_SHEET::GetExcludedFromSimProp ),
|
||||
|
||||
+31
-2
@@ -458,8 +458,20 @@ public:
|
||||
/**
|
||||
* Set or clear exclude from board netlist flag.
|
||||
*/
|
||||
void SetExcludedFromBoard( bool aExcludeFromBoard ) override { m_excludedFromBoard = aExcludeFromBoard; }
|
||||
bool GetExcludedFromBoard() const override { return m_excludedFromBoard; }
|
||||
void SetExcludedFromBoard( bool aExclude, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) override
|
||||
{
|
||||
m_excludedFromBoard = aExclude;
|
||||
}
|
||||
|
||||
bool GetExcludedFromBoard( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const override
|
||||
{
|
||||
return m_excludedFromBoard;
|
||||
}
|
||||
|
||||
bool GetExcludedFromBoardProp() const { return GetExcludedFromBoard(); }
|
||||
void SetExcludedFromBoardProp( bool aExclude ) { SetExcludedFromBoard( aExclude ); }
|
||||
|
||||
/**
|
||||
* Set or clear the 'Do Not Populate' flags
|
||||
@@ -525,12 +537,29 @@ public:
|
||||
|
||||
void DeleteVariant( const KIID_PATH& aPath, const wxString& aVariantName );
|
||||
|
||||
void RenameVariant( const KIID_PATH& aPath, const wxString& aOldName, const wxString& aNewName );
|
||||
|
||||
void CopyVariant( const KIID_PATH& aPath, const wxString& aSourceVariant,
|
||||
const wxString& aNewVariant );
|
||||
|
||||
void AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SHEET_VARIANT& aVariant );
|
||||
void DeleteVariant( const SCH_SHEET_PATH& aInstance, const wxString& aVariantName )
|
||||
{
|
||||
DeleteVariant( aInstance.Path(), aVariantName );
|
||||
}
|
||||
|
||||
void RenameVariant( const SCH_SHEET_PATH& aInstance, const wxString& aOldName,
|
||||
const wxString& aNewName )
|
||||
{
|
||||
RenameVariant( aInstance.Path(), aOldName, aNewName );
|
||||
}
|
||||
|
||||
void CopyVariant( const SCH_SHEET_PATH& aInstance, const wxString& aSourceVariant,
|
||||
const wxString& aNewVariant )
|
||||
{
|
||||
CopyVariant( aInstance.Path(), aSourceVariant, aNewVariant );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the instance data of this sheet has any changes compared to \a aOther.
|
||||
*
|
||||
|
||||
@@ -100,6 +100,8 @@ void SCH_SYMBOL_VARIANT::InitializeAttributes( const SCH_SYMBOL& aSymbol )
|
||||
m_DNP = aSymbol.GetDNP();
|
||||
m_ExcludedFromBOM = aSymbol.GetExcludedFromBOM();
|
||||
m_ExcludedFromSim = aSymbol.GetExcludedFromSim();
|
||||
m_ExcludedFromBoard = aSymbol.GetExcludedFromBoard();
|
||||
m_ExcludedFromPosFiles = aSymbol.GetExcludedFromPosFiles();
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +110,8 @@ void SCH_SHEET_VARIANT::InitializeAttributes( const SCH_SHEET& aSheet )
|
||||
m_DNP = aSheet.GetDNP();
|
||||
m_ExcludedFromBOM = aSheet.GetExcludedFromBOM();
|
||||
m_ExcludedFromSim = aSheet.GetExcludedFromSim();
|
||||
m_ExcludedFromBoard = aSheet.GetExcludedFromBoard();
|
||||
m_ExcludedFromPosFiles = false; // Sheets don't have position files exclusion
|
||||
}
|
||||
|
||||
|
||||
@@ -299,6 +303,21 @@ bool SCH_SHEET_PATH::GetExcludedFromSim() const
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_PATH::GetExcludedFromSim( const wxString& aVariantName ) const
|
||||
{
|
||||
if( aVariantName.IsEmpty() )
|
||||
return GetExcludedFromSim();
|
||||
|
||||
for( SCH_SHEET* sheet : m_sheets )
|
||||
{
|
||||
if( sheet->GetExcludedFromSim( this, aVariantName ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_PATH::GetExcludedFromBOM() const
|
||||
{
|
||||
for( SCH_SHEET* sheet : m_sheets )
|
||||
@@ -311,6 +330,21 @@ bool SCH_SHEET_PATH::GetExcludedFromBOM() const
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_PATH::GetExcludedFromBOM( const wxString& aVariantName ) const
|
||||
{
|
||||
if( aVariantName.IsEmpty() )
|
||||
return GetExcludedFromBOM();
|
||||
|
||||
for( SCH_SHEET* sheet : m_sheets )
|
||||
{
|
||||
if( sheet->GetExcludedFromBOM( this, aVariantName ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_PATH::GetExcludedFromBoard() const
|
||||
{
|
||||
for( SCH_SHEET* sheet : m_sheets )
|
||||
@@ -335,6 +369,21 @@ bool SCH_SHEET_PATH::GetDNP() const
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_PATH::GetDNP( const wxString& aVariantName ) const
|
||||
{
|
||||
if( aVariantName.IsEmpty() )
|
||||
return GetDNP();
|
||||
|
||||
for( SCH_SHEET* sheet : m_sheets )
|
||||
{
|
||||
if( sheet->GetDNP( this, aVariantName ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
wxString SCH_SHEET_PATH::PathAsString() const
|
||||
{
|
||||
wxString s;
|
||||
|
||||
@@ -51,6 +51,8 @@ public:
|
||||
m_Name( aName ),
|
||||
m_ExcludedFromSim( false ),
|
||||
m_ExcludedFromBOM( false ),
|
||||
m_ExcludedFromBoard( false ),
|
||||
m_ExcludedFromPosFiles( false ),
|
||||
m_DNP( false )
|
||||
{
|
||||
}
|
||||
@@ -58,8 +60,11 @@ public:
|
||||
virtual ~VARIANT() = default;
|
||||
|
||||
wxString m_Name;
|
||||
wxString m_Description;
|
||||
bool m_ExcludedFromSim;
|
||||
bool m_ExcludedFromBOM;
|
||||
bool m_ExcludedFromBoard;
|
||||
bool m_ExcludedFromPosFiles;
|
||||
bool m_DNP;
|
||||
std::map<wxString, wxString> m_Fields;
|
||||
};
|
||||
@@ -71,9 +76,7 @@ public:
|
||||
* Schematic symbol variants are a set of field and/or properties differentials against the default symbol
|
||||
* values. Each symbol instance may contain 0 or more variants.
|
||||
*
|
||||
* @note The two exceptions to this are the #REFERENCE field and the #SYMBOL::m_excludeFromBoard property.
|
||||
* Changing either of these would effectively be a new board. They are immutable and will always
|
||||
* be the symbol default value.
|
||||
* @note The #REFERENCE field is immutable across variants. Changing it would effectively be a new board.
|
||||
*/
|
||||
class SCH_SYMBOL_VARIANT : public VARIANT
|
||||
{
|
||||
@@ -110,6 +113,8 @@ struct SCH_SYMBOL_INSTANCE
|
||||
bool m_DNP = false;
|
||||
bool m_ExcludedFromBOM = false;
|
||||
bool m_ExcludedFromSim = false;
|
||||
bool m_ExcludedFromBoard = false;
|
||||
bool m_ExcludedFromPosFiles = false;
|
||||
|
||||
/// A list of symbol variants.
|
||||
std::map<wxString, SCH_SYMBOL_VARIANT> m_Variants;
|
||||
@@ -154,6 +159,8 @@ struct SCH_SHEET_INSTANCE
|
||||
bool m_DNP = false;
|
||||
bool m_ExcludedFromBOM = false;
|
||||
bool m_ExcludedFromSim = false;
|
||||
bool m_ExcludedFromBoard = false;
|
||||
bool m_ExcludedFromPosFiles = false;
|
||||
|
||||
/// A list of sheet variants.
|
||||
std::map<wxString, SCH_SHEET_VARIANT> m_Variants;
|
||||
@@ -354,9 +361,12 @@ public:
|
||||
SCH_SCREEN* LastScreen() const;
|
||||
|
||||
bool GetExcludedFromSim() const;
|
||||
bool GetExcludedFromSim( const wxString& aVariantName ) const;
|
||||
bool GetExcludedFromBOM() const;
|
||||
bool GetExcludedFromBOM( const wxString& aVariantName ) const;
|
||||
bool GetExcludedFromBoard() const;
|
||||
bool GetDNP() const;
|
||||
bool GetDNP( const wxString& aVariantName ) const;
|
||||
|
||||
/**
|
||||
* Fetch a SCH_ITEM by ID.
|
||||
|
||||
+209
-15
@@ -677,6 +677,13 @@ void SCH_SYMBOL::SetRefProp( const wxString& aRef )
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::SetValueProp( const wxString& aValue )
|
||||
{
|
||||
wxString currentVariant = Schematic()->GetCurrentVariant();
|
||||
SetValueFieldText( aValue, &Schematic()->CurrentSheet(), currentVariant );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
|
||||
{
|
||||
KIID_PATH path = sheet->Path();
|
||||
@@ -734,7 +741,10 @@ void SCH_SYMBOL::SetFieldText( const wxString& aFieldName, const wxString& aFiel
|
||||
break;
|
||||
|
||||
default:
|
||||
if( aFieldText != field->GetText( aPath ) ) // Do not set the variant unless it's different than the default.
|
||||
{
|
||||
wxString defaultText = field->GetText( aPath );
|
||||
|
||||
if( aFieldText != defaultText )
|
||||
{
|
||||
if( aVariantName.IsEmpty() )
|
||||
{
|
||||
@@ -763,6 +773,7 @@ void SCH_SYMBOL::SetFieldText( const wxString& aFieldName, const wxString& aFiel
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1061,6 +1072,124 @@ bool SCH_SYMBOL::GetExcludedFromSim( const SCH_SHEET_PATH* aInstance, const wxSt
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::SetExcludedFromBoard( bool aEnable, const SCH_SHEET_PATH* aInstance,
|
||||
const wxString& aVariantName )
|
||||
{
|
||||
if( !aInstance || aVariantName.IsEmpty() )
|
||||
{
|
||||
m_excludedFromBoard = aEnable;
|
||||
return;
|
||||
}
|
||||
|
||||
SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
|
||||
|
||||
wxCHECK_MSG( instance, /* void */,
|
||||
wxString::Format( wxS( "Cannot set exclude from board for invalid sheet path '%s'." ),
|
||||
aInstance->PathHumanReadable() ) );
|
||||
|
||||
if( aVariantName.IsEmpty() )
|
||||
{
|
||||
m_excludedFromBoard = aEnable;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( instance->m_Variants.contains( aVariantName )
|
||||
&& ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromBoard ) )
|
||||
{
|
||||
instance->m_Variants[aVariantName].m_ExcludedFromBoard = aEnable;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCH_SYMBOL_VARIANT variant( aVariantName );
|
||||
|
||||
variant.InitializeAttributes( *this );
|
||||
variant.m_ExcludedFromBoard = aEnable;
|
||||
AddVariant( *aInstance, variant );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::GetExcludedFromBoard( const SCH_SHEET_PATH* aInstance,
|
||||
const wxString& aVariantName ) const
|
||||
{
|
||||
if( !aInstance || aVariantName.IsEmpty() )
|
||||
return m_excludedFromBoard;
|
||||
|
||||
SCH_SYMBOL_INSTANCE instance;
|
||||
|
||||
if( !GetInstance( instance, aInstance->Path() ) )
|
||||
return m_excludedFromBoard;
|
||||
|
||||
if( aVariantName.IsEmpty() )
|
||||
return m_excludedFromBoard;
|
||||
else if( instance.m_Variants.contains( aVariantName ) )
|
||||
return instance.m_Variants[aVariantName].m_ExcludedFromBoard;
|
||||
|
||||
// If variant is not defined yet, return default exclude from board setting.
|
||||
return m_excludedFromBoard;
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::SetExcludedFromPosFiles( bool aEnable, const SCH_SHEET_PATH* aInstance,
|
||||
const wxString& aVariantName )
|
||||
{
|
||||
if( !aInstance || aVariantName.IsEmpty() )
|
||||
{
|
||||
m_excludedFromPosFiles = aEnable;
|
||||
return;
|
||||
}
|
||||
|
||||
SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
|
||||
|
||||
wxCHECK_MSG( instance, /* void */,
|
||||
wxString::Format( wxS( "Cannot set exclude from pos files for invalid sheet path '%s'." ),
|
||||
aInstance->PathHumanReadable() ) );
|
||||
|
||||
if( aVariantName.IsEmpty() )
|
||||
{
|
||||
m_excludedFromPosFiles = aEnable;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( instance->m_Variants.contains( aVariantName )
|
||||
&& ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromPosFiles ) )
|
||||
{
|
||||
instance->m_Variants[aVariantName].m_ExcludedFromPosFiles = aEnable;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCH_SYMBOL_VARIANT variant( aVariantName );
|
||||
|
||||
variant.InitializeAttributes( *this );
|
||||
variant.m_ExcludedFromPosFiles = aEnable;
|
||||
AddVariant( *aInstance, variant );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::GetExcludedFromPosFiles( const SCH_SHEET_PATH* aInstance,
|
||||
const wxString& aVariantName ) const
|
||||
{
|
||||
if( !aInstance || aVariantName.IsEmpty() )
|
||||
return m_excludedFromPosFiles;
|
||||
|
||||
SCH_SYMBOL_INSTANCE instance;
|
||||
|
||||
if( !GetInstance( instance, aInstance->Path() ) )
|
||||
return m_excludedFromPosFiles;
|
||||
|
||||
if( aVariantName.IsEmpty() )
|
||||
return m_excludedFromPosFiles;
|
||||
else if( instance.m_Variants.contains( aVariantName ) )
|
||||
return instance.m_Variants[aVariantName].m_ExcludedFromPosFiles;
|
||||
|
||||
// If variant is not defined yet, return default exclude from position files setting.
|
||||
return m_excludedFromPosFiles;
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::SetUnitSelection( int aUnitSelection )
|
||||
{
|
||||
for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
|
||||
@@ -1084,7 +1213,11 @@ const wxString SCH_SYMBOL::GetValue( bool aResolve, const SCH_SHEET_PATH* aInsta
|
||||
if( variant && variant->m_Fields.contains( GetField( FIELD_T::VALUE )->GetName() ) )
|
||||
return variant->m_Fields[GetField( FIELD_T::VALUE )->GetName()];
|
||||
|
||||
return wxEmptyString;
|
||||
// Fall back to default value when variant doesn't have an override
|
||||
if( aResolve )
|
||||
return GetField( FIELD_T::VALUE )->GetShownText( aInstance, aAllowExtraText );
|
||||
|
||||
return GetField( FIELD_T::VALUE )->GetText();
|
||||
}
|
||||
|
||||
|
||||
@@ -1097,18 +1230,23 @@ void SCH_SYMBOL::SetValueFieldText( const wxString& aValue, const SCH_SHEET_PATH
|
||||
return;
|
||||
}
|
||||
|
||||
std::optional variant = GetVariant( *aInstance, aVariantName );
|
||||
SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
|
||||
|
||||
if( variant )
|
||||
wxCHECK( instance, /* void */ );
|
||||
|
||||
wxString fieldName = GetField( FIELD_T::VALUE )->GetName();
|
||||
|
||||
if( instance->m_Variants.contains( aVariantName ) )
|
||||
{
|
||||
variant->m_Fields[GetField( FIELD_T::VALUE )->GetName()] = aValue;
|
||||
instance->m_Variants[aVariantName].m_Fields[fieldName] = aValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCH_SYMBOL_VARIANT newVariant( aVariantName );
|
||||
|
||||
newVariant.m_Fields[GetField( FIELD_T::VALUE )->GetName()] = aValue;
|
||||
AddVariant( *aInstance, newVariant );
|
||||
newVariant.InitializeAttributes( *this );
|
||||
newVariant.m_Fields[fieldName] = aValue;
|
||||
instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1591,6 +1729,13 @@ void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
|
||||
|
||||
|
||||
bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
|
||||
{
|
||||
return ResolveTextVar( aPath, token, wxEmptyString, aDepth );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token,
|
||||
const wxString& aVariantName, int aDepth ) const
|
||||
{
|
||||
static wxRegEx operatingPoint( wxT( "^"
|
||||
"OP"
|
||||
@@ -1697,9 +1842,23 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i
|
||||
if( token->IsSameAs( fieldName, false ) )
|
||||
{
|
||||
if( field.GetId() == FIELD_T::REFERENCE )
|
||||
{
|
||||
*token = GetRef( aPath, true );
|
||||
}
|
||||
else if( !aVariantName.IsEmpty() )
|
||||
{
|
||||
// Check for variant-specific field value
|
||||
std::optional<SCH_SYMBOL_VARIANT> variant = GetVariant( *aPath, aVariantName );
|
||||
|
||||
if( variant && variant->m_Fields.contains( fieldName ) )
|
||||
*token = variant->m_Fields.at( fieldName );
|
||||
else
|
||||
*token = field.GetShownText( aPath, false, aDepth + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
*token = field.GetShownText( aPath, false, aDepth + 1 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3422,6 +3581,39 @@ void SCH_SYMBOL::DeleteVariant( const KIID_PATH& aPath, const wxString& aVariant
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::RenameVariant( const KIID_PATH& aPath, const wxString& aOldName,
|
||||
const wxString& aNewName )
|
||||
{
|
||||
SCH_SYMBOL_INSTANCE* instance = getInstance( aPath );
|
||||
|
||||
// The instance path must already exist and contain the old variant.
|
||||
if( !instance || !instance->m_Variants.contains( aOldName ) )
|
||||
return;
|
||||
|
||||
// Get the variant data, update the name, and re-insert with new key
|
||||
SCH_SYMBOL_VARIANT variant = instance->m_Variants[aOldName];
|
||||
variant.m_Name = aNewName;
|
||||
instance->m_Variants.erase( aOldName );
|
||||
instance->m_Variants.insert( std::make_pair( aNewName, variant ) );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::CopyVariant( const KIID_PATH& aPath, const wxString& aSourceVariant,
|
||||
const wxString& aNewVariant )
|
||||
{
|
||||
SCH_SYMBOL_INSTANCE* instance = getInstance( aPath );
|
||||
|
||||
// The instance path must already exist and contain the source variant.
|
||||
if( !instance || !instance->m_Variants.contains( aSourceVariant ) )
|
||||
return;
|
||||
|
||||
// Copy the variant data with a new name
|
||||
SCH_SYMBOL_VARIANT variant = instance->m_Variants[aSourceVariant];
|
||||
variant.m_Name = aNewVariant;
|
||||
instance->m_Variants.insert( std::make_pair( aNewVariant, variant ) );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::operator==( const SCH_ITEM& aOther ) const
|
||||
{
|
||||
if( Type() != aOther.Type() )
|
||||
@@ -3668,13 +3860,6 @@ static struct SCH_SYMBOL_DESC
|
||||
|
||||
const wxString groupAttributes = _HKI( "Attributes" );
|
||||
|
||||
// This property is created in lib_symbol.cpp as SYMBOL property, so do not recreate it
|
||||
#if 0
|
||||
propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Exclude From Board" ),
|
||||
&SYMBOL::SetExcludedFromBoard,
|
||||
&SYMBOL::GetExcludedFromBoard ),
|
||||
groupAttributes );
|
||||
#endif
|
||||
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Simulation" ),
|
||||
&SCH_SYMBOL::SetExcludedFromSimProp,
|
||||
&SCH_SYMBOL::GetExcludedFromSimProp ),
|
||||
@@ -3683,7 +3868,16 @@ static struct SCH_SYMBOL_DESC
|
||||
&SCH_SYMBOL::SetExcludedFromBOMProp,
|
||||
&SCH_SYMBOL::GetExcludedFromBOMProp ),
|
||||
groupAttributes );
|
||||
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Do not Populate" ), &SCH_SYMBOL::SetDNPProp,
|
||||
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Board" ),
|
||||
&SCH_SYMBOL::SetExcludedFromBoardProp,
|
||||
&SCH_SYMBOL::GetExcludedFromBoardProp ),
|
||||
groupAttributes );
|
||||
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Position Files" ),
|
||||
&SCH_SYMBOL::SetExcludedFromPosFilesProp,
|
||||
&SCH_SYMBOL::GetExcludedFromPosFilesProp ),
|
||||
groupAttributes );
|
||||
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Do not Populate" ),
|
||||
&SCH_SYMBOL::SetDNPProp,
|
||||
&SCH_SYMBOL::GetDNPProp ),
|
||||
groupAttributes );
|
||||
}
|
||||
|
||||
+61
-4
@@ -361,10 +361,23 @@ public:
|
||||
/**
|
||||
* Resolve any references to system tokens supported by the symbol.
|
||||
*
|
||||
* @param aPath the sheet path for context.
|
||||
* @param token the token to resolve (modified in place with the result).
|
||||
* @param aDepth a counter to limit recursion and circular references.
|
||||
*/
|
||||
bool ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth = 0 ) const;
|
||||
|
||||
/**
|
||||
* Resolve any references to system tokens supported by the symbol with variant support.
|
||||
*
|
||||
* @param aPath the sheet path for context.
|
||||
* @param token the token to resolve (modified in place with the result).
|
||||
* @param aVariantName optional variant name to resolve field values for a specific variant.
|
||||
* @param aDepth a counter to limit recursion and circular references.
|
||||
*/
|
||||
bool ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token,
|
||||
const wxString& aVariantName, int aDepth = 0 ) const;
|
||||
|
||||
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
|
||||
|
||||
/**
|
||||
@@ -500,10 +513,7 @@ public:
|
||||
return GetValue( false, &Schematic()->CurrentSheet(), false, Schematic()->GetCurrentVariant() );
|
||||
}
|
||||
|
||||
void SetValueProp( const wxString& aValue )
|
||||
{
|
||||
SetValueFieldText( aValue, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
|
||||
}
|
||||
void SetValueProp( const wxString& aValue ); // Implemented in sch_symbol.cpp for tracing
|
||||
|
||||
int GetUnitProp() const
|
||||
{
|
||||
@@ -721,6 +731,36 @@ public:
|
||||
SetExcludedFromSim( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
|
||||
}
|
||||
|
||||
void SetExcludedFromBoard( bool aEnable, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) override;
|
||||
bool GetExcludedFromBoard( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const override;
|
||||
|
||||
bool GetExcludedFromBoardProp() const
|
||||
{
|
||||
return GetExcludedFromBoard( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
|
||||
}
|
||||
|
||||
void SetExcludedFromBoardProp( bool aEnable )
|
||||
{
|
||||
SetExcludedFromBoard( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
|
||||
}
|
||||
|
||||
void SetExcludedFromPosFiles( bool aEnable, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) override;
|
||||
bool GetExcludedFromPosFiles( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const override;
|
||||
|
||||
bool GetExcludedFromPosFilesProp() const
|
||||
{
|
||||
return GetExcludedFromPosFiles( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
|
||||
}
|
||||
|
||||
void SetExcludedFromPosFilesProp( bool aEnable )
|
||||
{
|
||||
SetExcludedFromPosFiles( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
|
||||
}
|
||||
|
||||
/**
|
||||
* SCH_SYMBOLs don't currently support embedded files, but their LIB_SYMBOL counterparts
|
||||
* do.
|
||||
@@ -901,6 +941,11 @@ public:
|
||||
|
||||
void DeleteVariant( const KIID_PATH& aPath, const wxString& aVariantName );
|
||||
|
||||
void RenameVariant( const KIID_PATH& aPath, const wxString& aOldName, const wxString& aNewName );
|
||||
|
||||
void CopyVariant( const KIID_PATH& aPath, const wxString& aSourceVariant,
|
||||
const wxString& aNewVariant );
|
||||
|
||||
std::optional<SCH_SYMBOL_VARIANT> GetVariant( const SCH_SHEET_PATH& aInstance, const wxString& aVariantName ) const;
|
||||
void AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SYMBOL_VARIANT& aVariant );
|
||||
|
||||
@@ -909,6 +954,18 @@ public:
|
||||
DeleteVariant( aInstance.Path(), aVariantName );
|
||||
}
|
||||
|
||||
void RenameVariant( const SCH_SHEET_PATH& aInstance, const wxString& aOldName,
|
||||
const wxString& aNewName )
|
||||
{
|
||||
RenameVariant( aInstance.Path(), aOldName, aNewName );
|
||||
}
|
||||
|
||||
void CopyVariant( const SCH_SHEET_PATH& aInstance, const wxString& aSourceVariant,
|
||||
const wxString& aNewVariant )
|
||||
{
|
||||
CopyVariant( aInstance.Path(), aSourceVariant, aNewVariant );
|
||||
}
|
||||
|
||||
bool operator==( const SCH_ITEM& aOther ) const override;
|
||||
|
||||
protected:
|
||||
|
||||
+117
-8
@@ -418,6 +418,8 @@ void SCHEMATIC::GetContextualTextVars( wxArrayString* aVars ) const
|
||||
add( wxT( "FILENAME" ) );
|
||||
add( wxT( "FILEPATH" ) );
|
||||
add( wxT( "PROJECTNAME" ) );
|
||||
add( wxT( "VARIANT" ) );
|
||||
add( wxT( "VARIANT_DESC" ) );
|
||||
|
||||
if( !CurrentSheet().empty() )
|
||||
CurrentSheet().LastScreen()->GetTitleBlock().GetContextualTextVars( aVars );
|
||||
@@ -468,11 +470,16 @@ bool SCHEMATIC::ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* toke
|
||||
*token = m_project->GetProjectName();
|
||||
return true;
|
||||
}
|
||||
else if( token->IsSameAs( wxT( "VARIANTNAME" ) ) )
|
||||
else if( token->IsSameAs( wxT( "VARIANTNAME" ) ) || token->IsSameAs( wxT( "VARIANT" ) ) )
|
||||
{
|
||||
*token = m_currentVariant;
|
||||
return true;
|
||||
}
|
||||
else if( token->IsSameAs( wxT( "VARIANT_DESC" ) ) )
|
||||
{
|
||||
*token = GetVariantDescription( m_currentVariant );
|
||||
return true;
|
||||
}
|
||||
|
||||
// aSheetPath->LastScreen() can be null during schematic loading
|
||||
if( aSheetPath->LastScreen() && aSheetPath->LastScreen()->GetTitleBlock().TextVarResolver( token, m_project ) )
|
||||
@@ -737,6 +744,18 @@ bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
|
||||
sheetPath = Hierarchy().GetSheetPathByKIIDPath( path ).value_or( sheetPath );
|
||||
}
|
||||
|
||||
// Parse optional variant name from syntax ${REF:FIELD:VARIANT}
|
||||
// remainder is "FIELD" or "FIELD:VARIANT"
|
||||
wxString variantName;
|
||||
wxString fieldName = remainder;
|
||||
int colonPos = remainder.Find( ':' );
|
||||
|
||||
if( colonPos != wxNOT_FOUND )
|
||||
{
|
||||
fieldName = remainder.Left( colonPos );
|
||||
variantName = remainder.Mid( colonPos + 1 );
|
||||
}
|
||||
|
||||
// Note: We don't expand nested variables or evaluate math expressions here.
|
||||
// The multi-pass loop in GetShownText handles all variable and expression resolution
|
||||
// before cross-references are resolved. This ensures table cell variables like ${ROW}
|
||||
@@ -746,17 +765,16 @@ bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
|
||||
{
|
||||
SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
|
||||
|
||||
bool resolved = refSymbol->ResolveTextVar( &sheetPath, &remainder, aDepth + 1 );
|
||||
bool resolved = refSymbol->ResolveTextVar( &sheetPath, &fieldName, variantName, aDepth + 1 );
|
||||
|
||||
if( resolved )
|
||||
{
|
||||
*token = std::move( remainder );
|
||||
*token = std::move( fieldName );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Field/function not found on symbol
|
||||
*token =
|
||||
wxString::Format( wxT( "<Unresolved: %s:%s>" ), refSymbol->GetRef( &sheetPath, false ), remainder );
|
||||
*token = wxString::Format( wxT( "<Unresolved: %s:%s>" ), refSymbol->GetRef( &sheetPath, false ), fieldName );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -818,17 +836,17 @@ bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
|
||||
|
||||
if( foundSymbol )
|
||||
{
|
||||
bool resolved = foundSymbol->ResolveTextVar( &foundPath, &remainder, aDepth + 1 );
|
||||
bool resolved = foundSymbol->ResolveTextVar( &foundPath, &fieldName, variantName, aDepth + 1 );
|
||||
|
||||
if( resolved )
|
||||
{
|
||||
*token = std::move( remainder );
|
||||
*token = std::move( fieldName );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Field/function not found on symbol
|
||||
*token = wxString::Format( wxT( "<Unresolved: %s:%s>" ), foundSymbol->GetRef( &foundPath, false ),
|
||||
remainder );
|
||||
fieldName );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2128,6 +2146,18 @@ void SCHEMATIC::SetCurrentVariant( const wxString& aVariantName )
|
||||
}
|
||||
|
||||
|
||||
void SCHEMATIC::AddVariant( const wxString& aVariantName )
|
||||
{
|
||||
m_variantNames.emplace( aVariantName );
|
||||
|
||||
// Ensure the variant is registered in the project file
|
||||
auto& descriptions = Settings().m_VariantDescriptions;
|
||||
|
||||
if( descriptions.find( aVariantName ) == descriptions.end() )
|
||||
descriptions[aVariantName] = wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
void SCHEMATIC::DeleteVariant( const wxString& aVariantName, SCH_COMMIT* aCommit )
|
||||
{
|
||||
wxCHECK( m_rootSheet, /* void */ );
|
||||
@@ -2137,6 +2167,76 @@ void SCHEMATIC::DeleteVariant( const wxString& aVariantName, SCH_COMMIT* aCommit
|
||||
allScreens.DeleteVariant( aVariantName, aCommit );
|
||||
|
||||
m_variantNames.erase( aVariantName );
|
||||
Settings().m_VariantDescriptions.erase( aVariantName );
|
||||
}
|
||||
|
||||
|
||||
void SCHEMATIC::RenameVariant( const wxString& aOldName, const wxString& aNewName,
|
||||
SCH_COMMIT* aCommit )
|
||||
{
|
||||
wxCHECK( m_rootSheet, /* void */ );
|
||||
wxCHECK( !aOldName.IsEmpty() && !aNewName.IsEmpty(), /* void */ );
|
||||
wxCHECK( m_variantNames.contains( aOldName ), /* void */ );
|
||||
|
||||
m_variantNames.erase( aOldName );
|
||||
m_variantNames.insert( aNewName );
|
||||
|
||||
auto& descriptions = Settings().m_VariantDescriptions;
|
||||
|
||||
if( descriptions.count( aOldName ) )
|
||||
{
|
||||
descriptions[aNewName] = descriptions[aOldName];
|
||||
descriptions.erase( aOldName );
|
||||
}
|
||||
|
||||
if( m_currentVariant == aOldName )
|
||||
m_currentVariant = aNewName;
|
||||
|
||||
SCH_SCREENS allScreens( m_rootSheet );
|
||||
allScreens.RenameVariant( aOldName, aNewName, aCommit );
|
||||
}
|
||||
|
||||
|
||||
void SCHEMATIC::CopyVariant( const wxString& aSourceVariant, const wxString& aNewVariant,
|
||||
SCH_COMMIT* aCommit )
|
||||
{
|
||||
wxCHECK( m_rootSheet, /* void */ );
|
||||
wxCHECK( !aSourceVariant.IsEmpty() && !aNewVariant.IsEmpty(), /* void */ );
|
||||
wxCHECK( m_variantNames.contains( aSourceVariant ), /* void */ );
|
||||
wxCHECK( !m_variantNames.contains( aNewVariant ), /* void */ );
|
||||
|
||||
AddVariant( aNewVariant );
|
||||
|
||||
auto& descriptions = Settings().m_VariantDescriptions;
|
||||
|
||||
if( descriptions.count( aSourceVariant ) )
|
||||
descriptions[aNewVariant] = descriptions[aSourceVariant];
|
||||
|
||||
SCH_SCREENS allScreens( m_rootSheet );
|
||||
allScreens.CopyVariant( aSourceVariant, aNewVariant, aCommit );
|
||||
}
|
||||
|
||||
|
||||
wxString SCHEMATIC::GetVariantDescription( const wxString& aVariantName ) const
|
||||
{
|
||||
const auto& descriptions = Settings().m_VariantDescriptions;
|
||||
auto it = descriptions.find( aVariantName );
|
||||
|
||||
if( it != descriptions.end() )
|
||||
return it->second;
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
void SCHEMATIC::SetVariantDescription( const wxString& aVariantName, const wxString& aDescription )
|
||||
{
|
||||
auto& descriptions = Settings().m_VariantDescriptions;
|
||||
|
||||
if( aDescription.IsEmpty() )
|
||||
descriptions.erase( aVariantName );
|
||||
else
|
||||
descriptions[aVariantName] = aDescription;
|
||||
}
|
||||
|
||||
|
||||
@@ -2147,6 +2247,15 @@ void SCHEMATIC::LoadVariants()
|
||||
SCH_SCREENS screens( m_rootSheet );
|
||||
std::set<wxString> variantNames = screens.GetVariantNames();
|
||||
m_variantNames.insert( variantNames.begin(), variantNames.end() );
|
||||
|
||||
// Register any unknown variants to the project file with empty descriptions
|
||||
auto& descriptions = Settings().m_VariantDescriptions;
|
||||
|
||||
for( const wxString& name : variantNames )
|
||||
{
|
||||
if( descriptions.find( name ) == descriptions.end() )
|
||||
descriptions[name] = wxEmptyString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+47
-1
@@ -465,7 +465,53 @@ public:
|
||||
*/
|
||||
void DeleteVariant( const wxString& aVariantName, SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
void AddVariant( const wxString& aVariantName ) { m_variantNames.emplace( aVariantName ); }
|
||||
void AddVariant( const wxString& aVariantName );
|
||||
|
||||
/**
|
||||
* Rename a variant from @a aOldName to @a aNewName.
|
||||
*
|
||||
* This updates the variant name in all symbols and sheets throughout the schematic.
|
||||
*
|
||||
* @param aOldName is the current name of the variant to rename.
|
||||
* @param aNewName is the new name for the variant.
|
||||
* @param aCommit is an optional SCH_COMMIT for undo/redo support.
|
||||
*/
|
||||
void RenameVariant( const wxString& aOldName, const wxString& aNewName,
|
||||
SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
/**
|
||||
* Copy a variant from @a aSourceVariant to @a aNewVariant.
|
||||
*
|
||||
* This creates a new variant with data copied from the source variant for all
|
||||
* symbols and sheets throughout the schematic.
|
||||
*
|
||||
* @param aSourceVariant is the name of the variant to copy from.
|
||||
* @param aNewVariant is the name of the new variant to create.
|
||||
* @param aCommit is an optional SCH_COMMIT for undo/redo support.
|
||||
*/
|
||||
void CopyVariant( const wxString& aSourceVariant, const wxString& aNewVariant,
|
||||
SCH_COMMIT* aCommit = nullptr );
|
||||
|
||||
/**
|
||||
* Return the set of variant names (without the default placeholder).
|
||||
*/
|
||||
const std::set<wxString>& GetVariantNames() const { return m_variantNames; }
|
||||
|
||||
/**
|
||||
* Return the description for a variant.
|
||||
*
|
||||
* @param aVariantName is the name of the variant.
|
||||
* @return the description or an empty string if the variant has no description.
|
||||
*/
|
||||
wxString GetVariantDescription( const wxString& aVariantName ) const;
|
||||
|
||||
/**
|
||||
* Set the description for a variant.
|
||||
*
|
||||
* @param aVariantName is the name of the variant.
|
||||
* @param aDescription is the description to set.
|
||||
*/
|
||||
void SetVariantDescription( const wxString& aVariantName, const wxString& aDescription );
|
||||
|
||||
/**
|
||||
* This is a throw away method for variant testing.
|
||||
|
||||
@@ -79,6 +79,7 @@ instances
|
||||
inverted
|
||||
inverted_clock
|
||||
in_bom
|
||||
in_pos_files
|
||||
iref
|
||||
italic
|
||||
jumper_pin_groups
|
||||
|
||||
@@ -262,6 +262,46 @@ SCHEMATIC_SETTINGS::SCHEMATIC_SETTINGS( JSON_SETTINGS* aParent, const std::strin
|
||||
m_refDesTracker->Deserialize( aData );
|
||||
}, {} ) );
|
||||
|
||||
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "variants",
|
||||
[&]() -> nlohmann::json
|
||||
{
|
||||
nlohmann::json ret = nlohmann::json::array();
|
||||
|
||||
for( const auto& [name, description] : m_VariantDescriptions )
|
||||
{
|
||||
nlohmann::json entry;
|
||||
entry["name"] = name;
|
||||
|
||||
if( !description.IsEmpty() )
|
||||
entry["description"] = description;
|
||||
|
||||
ret.push_back( entry );
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
[&]( const nlohmann::json& aJson )
|
||||
{
|
||||
m_VariantDescriptions.clear();
|
||||
|
||||
if( aJson.is_array() )
|
||||
{
|
||||
for( const auto& entry : aJson )
|
||||
{
|
||||
if( entry.contains( "name" ) )
|
||||
{
|
||||
wxString name = entry["name"].get<wxString>();
|
||||
wxString desc;
|
||||
|
||||
if( entry.contains( "description" ) )
|
||||
desc = entry["description"].get<wxString>();
|
||||
|
||||
m_VariantDescriptions[name] = desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, nlohmann::json::array() ) );
|
||||
|
||||
registerMigration( 0, 1,
|
||||
[&]() -> bool
|
||||
{
|
||||
|
||||
@@ -122,6 +122,12 @@ public:
|
||||
* This is used to avoid reusing designators in the same project.
|
||||
*/
|
||||
std::shared_ptr<REFDES_TRACKER> m_refDesTracker;
|
||||
|
||||
/**
|
||||
* A map of variant names to their descriptions.
|
||||
* This is stored in the project file and is the authoritative source for variant metadata.
|
||||
*/
|
||||
std::map<wxString, wxString> m_VariantDescriptions;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+37
-9
@@ -74,6 +74,7 @@ public:
|
||||
m_excludedFromSim( false ),
|
||||
m_excludedFromBOM( false ),
|
||||
m_excludedFromBoard( false ),
|
||||
m_excludedFromPosFiles( false ),
|
||||
m_DNP( false )
|
||||
{ }
|
||||
|
||||
@@ -85,6 +86,7 @@ public:
|
||||
m_excludedFromSim( base.m_excludedFromSim ),
|
||||
m_excludedFromBOM( base.m_excludedFromBOM ),
|
||||
m_excludedFromBoard( base.m_excludedFromBoard ),
|
||||
m_excludedFromPosFiles( base.m_excludedFromPosFiles ),
|
||||
m_DNP( base.m_DNP )
|
||||
{ }
|
||||
|
||||
@@ -92,14 +94,15 @@ public:
|
||||
{
|
||||
SCH_ITEM::operator=( aItem );
|
||||
|
||||
m_pinNameOffset = aItem.m_pinNameOffset;
|
||||
m_showPinNames = aItem.m_showPinNames;
|
||||
m_showPinNumbers = aItem.m_showPinNumbers;
|
||||
m_pinNameOffset = aItem.m_pinNameOffset;
|
||||
m_showPinNames = aItem.m_showPinNames;
|
||||
m_showPinNumbers = aItem.m_showPinNumbers;
|
||||
|
||||
m_excludedFromSim = aItem.m_excludedFromSim;
|
||||
m_excludedFromBOM = aItem.m_excludedFromBOM;
|
||||
m_excludedFromBoard = aItem.m_excludedFromBoard;
|
||||
m_DNP = aItem.m_DNP;
|
||||
m_excludedFromSim = aItem.m_excludedFromSim;
|
||||
m_excludedFromBOM = aItem.m_excludedFromBOM;
|
||||
m_excludedFromBoard = aItem.m_excludedFromBoard;
|
||||
m_excludedFromPosFiles = aItem.m_excludedFromPosFiles;
|
||||
m_DNP = aItem.m_DNP;
|
||||
|
||||
return *this;
|
||||
};
|
||||
@@ -204,8 +207,32 @@ public:
|
||||
/**
|
||||
* Set or clear exclude from board netlist flag.
|
||||
*/
|
||||
void SetExcludedFromBoard( bool aExcludeFromBoard ) override { m_excludedFromBoard = aExcludeFromBoard; }
|
||||
bool GetExcludedFromBoard() const override { return m_excludedFromBoard; }
|
||||
void SetExcludedFromBoard( bool aExclude, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) override
|
||||
{
|
||||
m_excludedFromBoard = aExclude;
|
||||
}
|
||||
|
||||
bool GetExcludedFromBoard( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const override
|
||||
{
|
||||
return m_excludedFromBoard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or clear exclude from position files flag.
|
||||
*/
|
||||
void SetExcludedFromPosFiles( bool aExclude, const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) override
|
||||
{
|
||||
m_excludedFromPosFiles = aExclude;
|
||||
}
|
||||
|
||||
bool GetExcludedFromPosFiles( const SCH_SHEET_PATH* aInstance = nullptr,
|
||||
const wxString& aVariantName = wxEmptyString ) const override
|
||||
{
|
||||
return m_excludedFromPosFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or clear the 'Do Not Populate' flag.
|
||||
@@ -247,6 +274,7 @@ protected:
|
||||
bool m_excludedFromSim;
|
||||
bool m_excludedFromBOM;
|
||||
bool m_excludedFromBoard;
|
||||
bool m_excludedFromPosFiles;
|
||||
bool m_DNP; ///< True if symbol is set to 'Do Not Populate'.
|
||||
|
||||
int m_previewUnit = 1;
|
||||
|
||||
@@ -300,7 +300,12 @@ void SCH_EDIT_FRAME::UpdateVariantSelectionCtrl( const wxArrayString& aVariantNa
|
||||
if( selectionIndex != wxNOT_FOUND )
|
||||
currentSelection = m_currentVariantCtrl->GetString( selectionIndex );
|
||||
|
||||
m_currentVariantCtrl->Set( aVariantNames );
|
||||
// Add all variant names, a separator, and "Add New Variant..." at the end
|
||||
wxArrayString contents = aVariantNames;
|
||||
contents.Add( wxS( "---" ) );
|
||||
contents.Add( _( "Add New Variant..." ) );
|
||||
|
||||
m_currentVariantCtrl->Set( contents );
|
||||
|
||||
selectionIndex = m_currentVariantCtrl->FindString( currentSelection );
|
||||
|
||||
@@ -317,11 +322,44 @@ void SCH_EDIT_FRAME::onVariantSelected( wxCommandEvent& aEvent )
|
||||
return;
|
||||
|
||||
int selection = m_currentVariantCtrl->GetSelection();
|
||||
int count = m_currentVariantCtrl->GetCount();
|
||||
|
||||
if( selection == wxNOT_FOUND || count == 0 )
|
||||
return;
|
||||
|
||||
// "Add New Variant..." is always the last item, separator is second-to-last
|
||||
if( selection == count - 1 )
|
||||
{
|
||||
// Restore previous selection before showing dialog
|
||||
int previousSelection = m_currentVariantCtrl->FindString(
|
||||
Schematic().GetCurrentVariant().IsEmpty() ? GetDefaultVariantName()
|
||||
: Schematic().GetCurrentVariant() );
|
||||
|
||||
if( previousSelection != wxNOT_FOUND )
|
||||
m_currentVariantCtrl->SetSelection( previousSelection );
|
||||
|
||||
ShowAddVariantDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
// Separator line - ignore selection
|
||||
if( selection == count - 2 )
|
||||
{
|
||||
int previousSelection = m_currentVariantCtrl->FindString(
|
||||
Schematic().GetCurrentVariant().IsEmpty() ? GetDefaultVariantName()
|
||||
: Schematic().GetCurrentVariant() );
|
||||
|
||||
if( previousSelection != wxNOT_FOUND )
|
||||
m_currentVariantCtrl->SetSelection( previousSelection );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
wxString selectedString = m_currentVariantCtrl->GetString( selection );
|
||||
wxString selectedVariant;
|
||||
|
||||
if( ( selection != wxNOT_FOUND ) && ( m_currentVariantCtrl->GetString( selection ) != GetDefaultVariantName() ) )
|
||||
selectedVariant = m_currentVariantCtrl->GetString( selection );
|
||||
if( selectedString != GetDefaultVariantName() )
|
||||
selectedVariant = selectedString;
|
||||
|
||||
Schematic().SetCurrentVariant( selectedVariant );
|
||||
UpdateProperties();
|
||||
@@ -329,6 +367,77 @@ void SCH_EDIT_FRAME::onVariantSelected( wxCommandEvent& aEvent )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::ShowAddVariantDialog()
|
||||
{
|
||||
// Create a dialog with both name and description fields
|
||||
wxDialog dlg( this, wxID_ANY, _( "New Variant" ), wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
|
||||
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
// Name field
|
||||
wxStaticText* nameLabel = new wxStaticText( &dlg, wxID_ANY, _( "Variant name:" ) );
|
||||
mainSizer->Add( nameLabel, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
wxTextCtrl* nameCtrl = new wxTextCtrl( &dlg, wxID_ANY );
|
||||
mainSizer->Add( nameCtrl, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
// Description field
|
||||
wxStaticText* descLabel = new wxStaticText( &dlg, wxID_ANY, _( "Description (optional):" ) );
|
||||
mainSizer->Add( descLabel, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
wxTextCtrl* descCtrl = new wxTextCtrl( &dlg, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxSize( 300, 60 ), wxTE_MULTILINE );
|
||||
mainSizer->Add( descCtrl, 1, wxALL | wxEXPAND, 5 );
|
||||
|
||||
// Buttons
|
||||
wxStdDialogButtonSizer* btnSizer = new wxStdDialogButtonSizer();
|
||||
btnSizer->AddButton( new wxButton( &dlg, wxID_OK ) );
|
||||
btnSizer->AddButton( new wxButton( &dlg, wxID_CANCEL ) );
|
||||
btnSizer->Realize();
|
||||
mainSizer->Add( btnSizer, 0, wxALL | wxALIGN_RIGHT, 5 );
|
||||
|
||||
dlg.SetSizer( mainSizer );
|
||||
dlg.Fit();
|
||||
dlg.Centre();
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return false;
|
||||
|
||||
wxString variantName = nameCtrl->GetValue().Trim().Trim( false );
|
||||
wxString variantDesc = descCtrl->GetValue().Trim().Trim( false );
|
||||
|
||||
// Empty strings and duplicate variant names are not allowed.
|
||||
if( variantName.IsEmpty() )
|
||||
{
|
||||
GetInfoBar()->ShowMessageFor( _( "Variant name cannot be empty." ),
|
||||
10000, wxICON_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( Schematic().GetVariantNames().contains( variantName ) )
|
||||
{
|
||||
GetInfoBar()->ShowMessageFor( wxString::Format( _( "Variant '%s' already exists." ),
|
||||
variantName ),
|
||||
10000, wxICON_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add variant to the schematic
|
||||
Schematic().AddVariant( variantName );
|
||||
|
||||
if( !variantDesc.IsEmpty() )
|
||||
Schematic().SetVariantDescription( variantName, variantDesc );
|
||||
|
||||
// Update the variant selector and select the new variant
|
||||
UpdateVariantSelectionCtrl( Schematic().GetVariantNamesForUI() );
|
||||
SetCurrentVariant( variantName );
|
||||
UpdateProperties();
|
||||
HardRedraw();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::SetCurrentVariant( const wxString& aVariantName )
|
||||
{
|
||||
if( !m_currentVariantCtrl )
|
||||
|
||||
+22
-5
@@ -98,10 +98,23 @@ int CLI::COMMAND::Perform( KIWAY& aKiway )
|
||||
}
|
||||
}
|
||||
|
||||
if( m_hasVariantArg )
|
||||
if( m_hasVariantArg && m_argParser.is_used( ARG_VARIANT ) )
|
||||
{
|
||||
auto variantName = m_argParser.get<std::string>( ARG_VARIANT );
|
||||
m_argVariantName = From_UTF8( variantName );
|
||||
auto variantNames = m_argParser.get<std::vector<std::string>>( ARG_VARIANT );
|
||||
|
||||
for( const auto& name : variantNames )
|
||||
m_argVariantNames.push_back( From_UTF8( name ) );
|
||||
|
||||
if( m_argVariantNames.size() > 1 && m_hasOutputArg && !m_argOutput.IsEmpty() )
|
||||
{
|
||||
if( !m_argOutput.Contains( wxS( "${VARIANT}" ) ) )
|
||||
{
|
||||
wxFprintf( stderr,
|
||||
_( "When specifying multiple variants, the output path must contain "
|
||||
"${VARIANT} to generate separate output files for each variant.\n" ) );
|
||||
return EXIT_CODES::ERR_ARGS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return doPerform( aKiway );
|
||||
@@ -190,8 +203,12 @@ void CLI::COMMAND::addVariantsArg()
|
||||
m_hasVariantArg = true;
|
||||
|
||||
m_argParser.add_argument( ARG_VARIANT )
|
||||
.default_value( std::string() )
|
||||
.default_value( std::vector<std::string>() )
|
||||
.append()
|
||||
.help( UTF8STDSTR(
|
||||
_( "The variant name to output.\n"
|
||||
_( "The variant name(s) to output, can be used multiple times to specify "
|
||||
"multiple variants.\n"
|
||||
"When specifying multiple variants, use ${VARIANT} in the output path to "
|
||||
"generate separate files for each variant.\n"
|
||||
"When no --variant argument is provided the default variant is output." ) ) );
|
||||
}
|
||||
|
||||
+3
-3
@@ -156,11 +156,11 @@ protected:
|
||||
bool m_hasVariantArg;
|
||||
|
||||
/**
|
||||
* The name of the variant to output.
|
||||
* The list of variant names to output.
|
||||
*
|
||||
* An empty string indicates the default variant.
|
||||
* An empty vector indicates the default variant.
|
||||
*/
|
||||
wxString m_argVariantName;
|
||||
std::vector<wxString> m_argVariantNames;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -139,6 +139,7 @@ int CLI::SCH_EXPORT_BOM_COMMAND::doPerform( KIWAY& aKiway )
|
||||
// Basic options
|
||||
bomJob->m_filename = m_argInput;
|
||||
bomJob->SetConfiguredOutputPath( m_argOutput );
|
||||
bomJob->m_variantNames = m_argVariantNames;
|
||||
|
||||
bomJob->m_bomPresetName = From_UTF8( m_argParser.get<std::string>( ARG_PRESET ).c_str() );
|
||||
bomJob->m_bomFmtPresetName = From_UTF8( m_argParser.get<std::string>( ARG_FMT_PRESET ).c_str() );
|
||||
@@ -166,7 +167,6 @@ int CLI::SCH_EXPORT_BOM_COMMAND::doPerform( KIWAY& aKiway )
|
||||
bomJob->m_sortAsc = m_argParser.get<bool>( ARG_SORT_ASC );
|
||||
bomJob->m_filterString = From_UTF8( m_argParser.get<std::string>( ARG_FILTER ).c_str() );
|
||||
bomJob->m_excludeDNP = m_argParser.get<bool>( ARG_EXCLUDE_DNP );
|
||||
bomJob->m_variant = From_UTF8( m_argParser.get<std::string>( ARG_VARIANT ).c_str() );
|
||||
|
||||
if( m_argParser.get<bool>( DEPRECATED_ARG_INCLUDE_EXCLUDED_FROM_BOM ) )
|
||||
wxFprintf( stdout, DEPRECATED_ARG_INCLUDE_EXCLUDED_FROM_BOM_WARNING );
|
||||
|
||||
@@ -34,6 +34,7 @@ CLI::SCH_EXPORT_NETLIST_COMMAND::SCH_EXPORT_NETLIST_COMMAND() : COMMAND( "netlis
|
||||
{
|
||||
m_argParser.add_description( UTF8STDSTR( _( "Export a netlist" ) ) );
|
||||
addCommonArgs( true, true, false, false );
|
||||
addVariantsArg();
|
||||
|
||||
m_argParser.add_argument( ARG_FORMAT )
|
||||
.default_value( std::string( "kicadsexpr" ) )
|
||||
@@ -50,6 +51,7 @@ int CLI::SCH_EXPORT_NETLIST_COMMAND::doPerform( KIWAY& aKiway )
|
||||
|
||||
netJob->m_filename = m_argInput;
|
||||
netJob->SetConfiguredOutputPath( m_argOutput );
|
||||
netJob->m_variantNames = m_argVariantNames;
|
||||
|
||||
if( !wxFile::Exists( netJob->m_filename ) )
|
||||
{
|
||||
|
||||
@@ -182,6 +182,7 @@ int CLI::SCH_EXPORT_PLOT_COMMAND::doPerform( KIWAY& aKiway )
|
||||
|
||||
plotJob->m_drawingSheet = m_argDrawingSheet;
|
||||
plotJob->SetVarOverrides( m_argDefineVars );
|
||||
plotJob->m_variantNames = m_argVariantNames;
|
||||
|
||||
// PDF local options
|
||||
if( m_plotFormat == SCH_PLOT_FORMAT::PDF )
|
||||
@@ -191,7 +192,6 @@ int CLI::SCH_EXPORT_PLOT_COMMAND::doPerform( KIWAY& aKiway )
|
||||
plotJob->m_PDFMetadata = !m_argParser.get<bool>( ARG_EXCLUDE_PDF_METADATA );
|
||||
}
|
||||
|
||||
plotJob->m_variant = From_UTF8( m_argParser.get<std::string>( ARG_VARIANT ).c_str() );
|
||||
int exitCode = aKiway.ProcessJob( KIWAY::FACE_SCH, plotJob.get() );
|
||||
|
||||
return exitCode;
|
||||
|
||||
@@ -763,6 +763,46 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
|
||||
if( ( aNetlistComponent->GetProperties().count( wxT( "exclude_from_pos_files" ) ) > 0 )
|
||||
!= ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_POS_FILES ) > 0 ) )
|
||||
{
|
||||
if( m_isDryRun )
|
||||
{
|
||||
if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_pos_files" ) ) )
|
||||
{
|
||||
msg.Printf( _( "Add %s 'exclude from position files' fabrication attribute." ),
|
||||
aPcbFootprint->GetReference() );
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Printf( _( "Remove %s 'exclude from position files' fabrication attribute." ),
|
||||
aPcbFootprint->GetReference() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int attributes = aPcbFootprint->GetAttributes();
|
||||
|
||||
if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_pos_files" ) ) )
|
||||
{
|
||||
attributes |= FP_EXCLUDE_FROM_POS_FILES;
|
||||
msg.Printf( _( "Added %s 'exclude from position files' fabrication attribute." ),
|
||||
aPcbFootprint->GetReference() );
|
||||
}
|
||||
else
|
||||
{
|
||||
attributes &= ~FP_EXCLUDE_FROM_POS_FILES;
|
||||
msg.Printf( _( "Removed %s 'exclude from position files' fabrication attribute." ),
|
||||
aPcbFootprint->GetReference() );
|
||||
}
|
||||
|
||||
changed = true;
|
||||
aPcbFootprint->SetAttributes( attributes );
|
||||
}
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
|
||||
if( aNetlistComponent->GetDuplicatePadNumbersAreJumpers()
|
||||
!= aPcbFootprint->GetDuplicatePadNumbersAreJumpers() )
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
(sym_lib_table
|
||||
(version 7)
|
||||
(lib (name "pic_programmer") (type "KiCad") (uri "${KIPRJMOD}/pic_programmer.kicad_sym") (options "") (descr ""))
|
||||
)
|
||||
@@ -0,0 +1,744 @@
|
||||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"apply_defaults_to_fp_fields": false,
|
||||
"apply_defaults_to_fp_shapes": false,
|
||||
"apply_defaults_to_fp_text": false,
|
||||
"board_outline_line_width": 0.381,
|
||||
"copper_line_width": 0.381,
|
||||
"copper_text_italic": false,
|
||||
"copper_text_size_h": 1.524,
|
||||
"copper_text_size_v": 2.032,
|
||||
"copper_text_thickness": 0.3048,
|
||||
"copper_text_upright": true,
|
||||
"courtyard_line_width": 0.05,
|
||||
"dimension_precision": 1,
|
||||
"dimension_units": 0,
|
||||
"dimensions": {
|
||||
"arrow_length": 1270000,
|
||||
"extension_offset": 500000,
|
||||
"keep_text_aligned": true,
|
||||
"suppress_zeroes": false,
|
||||
"text_position": 0,
|
||||
"units_format": 1
|
||||
},
|
||||
"fab_line_width": 0.1,
|
||||
"fab_text_italic": false,
|
||||
"fab_text_size_h": 1.0,
|
||||
"fab_text_size_v": 1.0,
|
||||
"fab_text_thickness": 0.15,
|
||||
"fab_text_upright": false,
|
||||
"other_line_width": 0.1,
|
||||
"other_text_italic": false,
|
||||
"other_text_size_h": 1.0,
|
||||
"other_text_size_v": 1.0,
|
||||
"other_text_thickness": 0.15,
|
||||
"other_text_upright": true,
|
||||
"pads": {
|
||||
"drill": 0.75,
|
||||
"height": 1.3,
|
||||
"width": 1.3
|
||||
},
|
||||
"silk_line_width": 0.381,
|
||||
"silk_text_italic": false,
|
||||
"silk_text_size_h": 1.524,
|
||||
"silk_text_size_v": 1.524,
|
||||
"silk_text_thickness": 0.3048,
|
||||
"silk_text_upright": true,
|
||||
"zones": {
|
||||
"45_degree_only": false,
|
||||
"min_clearance": 0.508
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [
|
||||
{
|
||||
"gap": 0.0,
|
||||
"via_gap": 0.0,
|
||||
"width": 0.0
|
||||
}
|
||||
],
|
||||
"drc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"connection_width": "warning",
|
||||
"copper_edge_clearance": "error",
|
||||
"copper_sliver": "warning",
|
||||
"courtyards_overlap": "error",
|
||||
"creepage": "error",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"footprint": "error",
|
||||
"footprint_filters_mismatch": "ignore",
|
||||
"footprint_symbol_mismatch": "warning",
|
||||
"footprint_type_mismatch": "warning",
|
||||
"hole_clearance": "error",
|
||||
"hole_near_hole": "error",
|
||||
"hole_to_hole": "error",
|
||||
"holes_co_located": "warning",
|
||||
"invalid_outline": "error",
|
||||
"isolated_copper": "warning",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"length_out_of_range": "error",
|
||||
"lib_footprint_issues": "warning",
|
||||
"lib_footprint_mismatch": "warning",
|
||||
"malformed_courtyard": "error",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"mirrored_text_on_front_layer": "warning",
|
||||
"missing_courtyard": "warning",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
"nonmirrored_text_on_back_layer": "warning",
|
||||
"npth_inside_courtyard": "warning",
|
||||
"overlapping_pads": "warning",
|
||||
"padstack": "error",
|
||||
"pth_inside_courtyard": "warning",
|
||||
"shorting_items": "error",
|
||||
"silk_edge_clearance": "ignore",
|
||||
"silk_over_copper": "error",
|
||||
"silk_overlap": "error",
|
||||
"skew_out_of_range": "error",
|
||||
"solder_mask_bridge": "error",
|
||||
"starved_thermal": "error",
|
||||
"text_height": "warning",
|
||||
"text_thickness": "warning",
|
||||
"through_hole_pad_without_hole": "error",
|
||||
"too_many_vias": "error",
|
||||
"track_angle": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_segment_length": "error",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
"rule_severitieslegacy_courtyards_overlap": true,
|
||||
"rule_severitieslegacy_no_courtyard_defined": false,
|
||||
"rules": {
|
||||
"allow_blind_buried_vias": false,
|
||||
"allow_microvias": false,
|
||||
"max_error": 0.01,
|
||||
"min_clearance": 0.0,
|
||||
"min_connection": 0.0,
|
||||
"min_copper_edge_clearance": 0.01,
|
||||
"min_groove_width": 0.0,
|
||||
"min_hole_clearance": 0.0,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.508,
|
||||
"min_microvia_drill": 0.127,
|
||||
"min_resolved_spokes": 1,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.8,
|
||||
"min_text_thickness": 0.12,
|
||||
"min_through_hole_diameter": 0.5,
|
||||
"min_track_width": 0.25,
|
||||
"min_via_annular_width": 0.05,
|
||||
"min_via_diameter": 0.9,
|
||||
"solder_mask_to_copper_clearance": 0.0,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"teardrop_options": [
|
||||
{
|
||||
"td_onpthpad": true,
|
||||
"td_onroundshapesonly": false,
|
||||
"td_onsmdpad": true,
|
||||
"td_ontrackend": false,
|
||||
"td_onvia": true
|
||||
}
|
||||
],
|
||||
"teardrop_parameters": [
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_round_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_rect_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_track_end",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
}
|
||||
],
|
||||
"track_widths": [
|
||||
0.5,
|
||||
0.4,
|
||||
0.5
|
||||
],
|
||||
"tuning_pattern_settings": {
|
||||
"diff_pair_defaults": {
|
||||
"corner_radius_percentage": 100,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.1,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
},
|
||||
"diff_pair_skew_defaults": {
|
||||
"corner_radius_percentage": 100,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.1,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
},
|
||||
"single_track_defaults": {
|
||||
"corner_radius_percentage": 100,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.1,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
}
|
||||
},
|
||||
"via_dimensions": [
|
||||
{
|
||||
"diameter": 1.6,
|
||||
"drill": 0.6
|
||||
}
|
||||
],
|
||||
"zones_allow_external_fillets": false,
|
||||
"zones_use_no_outline": true
|
||||
},
|
||||
"ipc2581": {
|
||||
"dist": "",
|
||||
"distpn": "",
|
||||
"internal_id": "",
|
||||
"mfg": "",
|
||||
"mpn": ""
|
||||
},
|
||||
"layer_pairs": [],
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"component_class_settings": {
|
||||
"assignments": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"sheet_component_classes": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_label_syntax": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"conflicting_netclasses": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"footprint_filter": "ignore",
|
||||
"footprint_link_issues": "warning",
|
||||
"four_way_junction": "ignore",
|
||||
"global_label_dangling": "warning",
|
||||
"ground_pin_not_ground": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"isolated_pin_label": "warning",
|
||||
"label_dangling": "error",
|
||||
"label_multiple_wires": "warning",
|
||||
"lib_symbol_issues": "warning",
|
||||
"lib_symbol_mismatch": "warning",
|
||||
"missing_bidi_pin": "warning",
|
||||
"missing_input_pin": "warning",
|
||||
"missing_power_pin": "error",
|
||||
"missing_unit": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "error",
|
||||
"no_connect_dangling": "error",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "error",
|
||||
"power_pin_not_driven": "error",
|
||||
"same_local_global_label": "warning",
|
||||
"similar_label_and_power": "warning",
|
||||
"similar_labels": "warning",
|
||||
"similar_power": "warning",
|
||||
"simulation_model_issue": "ignore",
|
||||
"single_global_label": "warning",
|
||||
"stacked_pin_name": "warning",
|
||||
"unannotated": "error",
|
||||
"unconnected_wire_endpoint": "warning",
|
||||
"undefined_netclass": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"legacy": {
|
||||
"common": {
|
||||
"NetDir": ""
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "variants.kicad_pro",
|
||||
"version": 3
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.25,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.25,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.508,
|
||||
"microvia_drill": 0.127,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"priority": 2147483647,
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.5,
|
||||
"tuning_profile": "",
|
||||
"via_diameter": 1.6,
|
||||
"via_drill": 0.6,
|
||||
"wire_width": 6
|
||||
},
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.28,
|
||||
"diff_pair_gap": 0.28,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.28,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.508,
|
||||
"microvia_drill": 0.127,
|
||||
"name": "POWER",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"priority": 0,
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.8,
|
||||
"tuning_profile": "",
|
||||
"via_diameter": 1.6,
|
||||
"via_drill": 0.6,
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 5
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": [
|
||||
{
|
||||
"netclass": "POWER",
|
||||
"pattern": "GND"
|
||||
},
|
||||
{
|
||||
"netclass": "POWER",
|
||||
"pattern": "VCC"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "variants.net",
|
||||
"plot": "",
|
||||
"pos_files": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "pic_programmer.step",
|
||||
"svg": "",
|
||||
"vmrl": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"annotation": {
|
||||
"method": 0,
|
||||
"sort_order": 0
|
||||
},
|
||||
"bom_export_filename": "${PROJECTNAME}.csv",
|
||||
"bom_fmt_presets": [],
|
||||
"bom_fmt_settings": {
|
||||
"field_delimiter": ",",
|
||||
"keep_line_breaks": false,
|
||||
"keep_tabs": false,
|
||||
"name": "CSV",
|
||||
"ref_delimiter": ",",
|
||||
"ref_range_delimiter": "",
|
||||
"string_delimiter": "\""
|
||||
},
|
||||
"bom_presets": [],
|
||||
"bom_settings": {
|
||||
"exclude_dnp": false,
|
||||
"fields_ordered": [
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Reference",
|
||||
"name": "Reference",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Value",
|
||||
"name": "Value",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Datasheet",
|
||||
"name": "Datasheet",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Footprint",
|
||||
"name": "Footprint",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "Quantity",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "${QUANTITY}",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "#",
|
||||
"name": "${ITEM_NUMBER}",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Champ4",
|
||||
"name": "Champ4",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Description",
|
||||
"name": "Description",
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"filter_string": "",
|
||||
"group_symbols": true,
|
||||
"include_excluded_from_bom": false,
|
||||
"name": "",
|
||||
"sort_asc": true,
|
||||
"sort_field": "Reference"
|
||||
},
|
||||
"bus_aliases": {},
|
||||
"connection_grid_size": 50.0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_bus_thickness": 12.0,
|
||||
"default_junction_size": 36.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"default_wire_thickness": 6.0,
|
||||
"field_names": [],
|
||||
"hop_over_size_choice": 0,
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.2,
|
||||
"operating_point_overlay_i_precision": 3,
|
||||
"operating_point_overlay_i_range": "~A",
|
||||
"operating_point_overlay_v_precision": 3,
|
||||
"operating_point_overlay_v_range": "~V",
|
||||
"overbar_offset_ratio": 1.23,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.2
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"fix_passive_vals": false,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 0,
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"reuse_designators": true,
|
||||
"space_save_all_events": true,
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_model_current_sheet_as_root": true,
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_dissipations": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0,
|
||||
"top_level_sheets": [
|
||||
{
|
||||
"filename": "variants.kicad_sch",
|
||||
"name": "pic_programmer",
|
||||
"uuid": "2e45d1d2-c73f-46e5-98d6-3a9dc360bff5"
|
||||
}
|
||||
],
|
||||
"used_designators": "",
|
||||
"variants": [
|
||||
{
|
||||
"description": "testing variant 1 description",
|
||||
"name": "Variant 1"
|
||||
},
|
||||
{
|
||||
"description": "Test of variant 2 desc",
|
||||
"name": "Variant2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"2e45d1d2-c73f-46e5-98d6-3a9dc360bff5",
|
||||
"pic_programmer"
|
||||
],
|
||||
[
|
||||
"00000000-0000-0000-0000-00004804a5e2",
|
||||
"pic_sockets"
|
||||
]
|
||||
],
|
||||
"text_variables": {},
|
||||
"tuning_profiles": {
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"tuning_profiles_impedance_geometric": []
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
"Refs","Value"
|
||||
"C1","100µF"
|
||||
"C2","220uF"
|
||||
"C3","22uF/25V"
|
||||
"C4","0"
|
||||
"C5","10nF"
|
||||
"C6","100nF"
|
||||
"C7","100nF"
|
||||
"C9","220nF"
|
||||
"D1","1N4004"
|
||||
"D2","BAT43"
|
||||
"D3","BAT43"
|
||||
"D4","BAT43"
|
||||
"D5","BAT43"
|
||||
"D6","BAT43"
|
||||
"D7","BAT43"
|
||||
"D8","RED-LED"
|
||||
"D9","GREEN-LED"
|
||||
"D10","SCHOTTKY"
|
||||
"D11","BAT43"
|
||||
"D12","YELLOW-LED"
|
||||
"J1","DB9-FEMAL"
|
||||
"L1","22uH"
|
||||
"P1","CONN_2"
|
||||
"P2","SUPP28"
|
||||
"P3","SUPP40"
|
||||
"Q1","BC237"
|
||||
"Q2","BC307"
|
||||
"Q3","BC307"
|
||||
"R1","10K"
|
||||
"R2","10K"
|
||||
"R3","10K"
|
||||
"R4","10K"
|
||||
"R5","10K"
|
||||
"R6","10K"
|
||||
"R7","10K"
|
||||
"R8","1K"
|
||||
"R9","2.2K"
|
||||
"R10","5,1K"
|
||||
"R11","22K"
|
||||
"R12","2k"
|
||||
"R13","4k"
|
||||
"R14","470"
|
||||
"R15","6.2K"
|
||||
"R16","62K"
|
||||
"R17","22K"
|
||||
"R18","220"
|
||||
"R19","2.2K"
|
||||
"R20","2.2K"
|
||||
"R21","470"
|
||||
"RV1","1K"
|
||||
"U1","24Cxx"
|
||||
"U2","74HC125"
|
||||
"U3","7805"
|
||||
"U4","LT1373"
|
||||
"U5","PIC_18_PINS"
|
||||
"U6","PIC_8_PINS"
|
||||
|
@@ -0,0 +1,56 @@
|
||||
"Refs","Value"
|
||||
"C1","100µF"
|
||||
"C2","220uF"
|
||||
"C3","22uF/25V"
|
||||
"C4","0"
|
||||
"C5","10nF"
|
||||
"C6","100nF"
|
||||
"C7","100nF"
|
||||
"C9","220nF"
|
||||
"D1","1N4004"
|
||||
"D2","BAT43"
|
||||
"D3","BAT43"
|
||||
"D4","BAT43"
|
||||
"D5","BAT43"
|
||||
"D6","BAT43"
|
||||
"D7","BAT43"
|
||||
"D8","RED-LED"
|
||||
"D9","GREEN-LED"
|
||||
"D10","SCHOTTKY"
|
||||
"D11","BAT43"
|
||||
"D12","YELLOW-LED"
|
||||
"L1","22uH"
|
||||
"P1","CONN_2"
|
||||
"P2","SUPP28"
|
||||
"P3","SUPP40"
|
||||
"Q1","BC237"
|
||||
"Q2","BC307"
|
||||
"Q3","BC307"
|
||||
"R1","10K"
|
||||
"R2","10K"
|
||||
"R3","10K"
|
||||
"R4","10K"
|
||||
"R5","10K"
|
||||
"R6","10K"
|
||||
"R7","10K"
|
||||
"R8","1K"
|
||||
"R9","2.2K"
|
||||
"R10","5,1K"
|
||||
"R11","22K"
|
||||
"R12","2k"
|
||||
"R13","4k"
|
||||
"R14","470"
|
||||
"R15","6.2K"
|
||||
"R16","62K"
|
||||
"R17","22K"
|
||||
"R18","220"
|
||||
"R19","2.2K"
|
||||
"R20","2.2K"
|
||||
"R21","470"
|
||||
"RV1","1K"
|
||||
"U1","24Cxx"
|
||||
"U2","74HC125"
|
||||
"U3","7805"
|
||||
"U4","LT1373"
|
||||
"U5","PIC_18_PINS"
|
||||
"U6","PIC_8_PINS"
|
||||
|
@@ -0,0 +1,56 @@
|
||||
"Refs","Value"
|
||||
"C1","100µF"
|
||||
"C2","220uF"
|
||||
"C3","22uF/25V"
|
||||
"C4","0"
|
||||
"C5","10nF"
|
||||
"C6","100nF"
|
||||
"C7","100nF"
|
||||
"C9","220nF"
|
||||
"D1","1N4004"
|
||||
"D2","BAT43"
|
||||
"D3","BAT43"
|
||||
"D4","BAT43"
|
||||
"D5","BAT43"
|
||||
"D6","BAT43"
|
||||
"D7","BAT43"
|
||||
"D8","RED-LED"
|
||||
"D9","GREEN-LED"
|
||||
"D10","SCHOTTKY"
|
||||
"D11","BAT43"
|
||||
"D12","YELLOW-LED"
|
||||
"J1","DB9-FEMAL"
|
||||
"L1","22uH"
|
||||
"P1","CONN_2"
|
||||
"P2","SUPP28"
|
||||
"P3","SUPP40"
|
||||
"Q1","BC237"
|
||||
"Q2","BC307"
|
||||
"Q3","BC307"
|
||||
"R1","10K"
|
||||
"R2","10K"
|
||||
"R3","10K"
|
||||
"R4","10K"
|
||||
"R5","10K"
|
||||
"R6","10K"
|
||||
"R7","10K"
|
||||
"R8","1K"
|
||||
"R9","2.2K"
|
||||
"R10","5,1K"
|
||||
"R11","22K"
|
||||
"R12","2k"
|
||||
"R13","4k"
|
||||
"R15","6.2K"
|
||||
"R16","62K"
|
||||
"R17","22K"
|
||||
"R18","220"
|
||||
"R19","2.2K"
|
||||
"R20","2.2K"
|
||||
"R21","470"
|
||||
"RV1","1K"
|
||||
"U1","24Cxx"
|
||||
"U2","74HC125"
|
||||
"U3","7805"
|
||||
"U4","LT1373"
|
||||
"U5","PIC_18_PINS"
|
||||
"U6","PIC_8_PINS"
|
||||
|
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"ERC": {
|
||||
"crossprobe": true,
|
||||
"scroll_on_crossprobe": true
|
||||
"scroll_on_crossprobe": true,
|
||||
"show_all_errors": false
|
||||
},
|
||||
"annotation": {
|
||||
"automatic": true,
|
||||
@@ -174,6 +175,7 @@
|
||||
"scope": 0,
|
||||
"selection_mode": 0,
|
||||
"sidebar_collapsed": false,
|
||||
"variant_sash_pos": 500,
|
||||
"width": 0
|
||||
},
|
||||
"find_replace": {
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
"units": 1
|
||||
},
|
||||
"template": {
|
||||
"last_used": "",
|
||||
"window": {
|
||||
"pos": {
|
||||
"x": -1,
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
(fp_lib_table
|
||||
(version 7)
|
||||
(lib (name "footprints") (type "KiCad") (uri "${KIPRJMOD}/libs/pic_programmer_fp.pretty") (options "") (descr "project specific"))
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
(sym_lib_table
|
||||
(version 7)
|
||||
(lib (name "pic_programmer") (type "KiCad") (uri "${KIPRJMOD}/pic_programmer.kicad_sym") (options "") (descr ""))
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,744 @@
|
||||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"apply_defaults_to_fp_fields": false,
|
||||
"apply_defaults_to_fp_shapes": false,
|
||||
"apply_defaults_to_fp_text": false,
|
||||
"board_outline_line_width": 0.381,
|
||||
"copper_line_width": 0.381,
|
||||
"copper_text_italic": false,
|
||||
"copper_text_size_h": 1.524,
|
||||
"copper_text_size_v": 2.032,
|
||||
"copper_text_thickness": 0.3048,
|
||||
"copper_text_upright": true,
|
||||
"courtyard_line_width": 0.05,
|
||||
"dimension_precision": 1,
|
||||
"dimension_units": 0,
|
||||
"dimensions": {
|
||||
"arrow_length": 1270000,
|
||||
"extension_offset": 500000,
|
||||
"keep_text_aligned": true,
|
||||
"suppress_zeroes": false,
|
||||
"text_position": 0,
|
||||
"units_format": 1
|
||||
},
|
||||
"fab_line_width": 0.1,
|
||||
"fab_text_italic": false,
|
||||
"fab_text_size_h": 1.0,
|
||||
"fab_text_size_v": 1.0,
|
||||
"fab_text_thickness": 0.15,
|
||||
"fab_text_upright": false,
|
||||
"other_line_width": 0.1,
|
||||
"other_text_italic": false,
|
||||
"other_text_size_h": 1.0,
|
||||
"other_text_size_v": 1.0,
|
||||
"other_text_thickness": 0.15,
|
||||
"other_text_upright": true,
|
||||
"pads": {
|
||||
"drill": 0.75,
|
||||
"height": 1.3,
|
||||
"width": 1.3
|
||||
},
|
||||
"silk_line_width": 0.381,
|
||||
"silk_text_italic": false,
|
||||
"silk_text_size_h": 1.524,
|
||||
"silk_text_size_v": 1.524,
|
||||
"silk_text_thickness": 0.3048,
|
||||
"silk_text_upright": true,
|
||||
"zones": {
|
||||
"45_degree_only": false,
|
||||
"min_clearance": 0.508
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [
|
||||
{
|
||||
"gap": 0.0,
|
||||
"via_gap": 0.0,
|
||||
"width": 0.0
|
||||
}
|
||||
],
|
||||
"drc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"connection_width": "warning",
|
||||
"copper_edge_clearance": "error",
|
||||
"copper_sliver": "warning",
|
||||
"courtyards_overlap": "error",
|
||||
"creepage": "error",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"footprint": "error",
|
||||
"footprint_filters_mismatch": "ignore",
|
||||
"footprint_symbol_mismatch": "warning",
|
||||
"footprint_type_mismatch": "warning",
|
||||
"hole_clearance": "error",
|
||||
"hole_near_hole": "error",
|
||||
"hole_to_hole": "error",
|
||||
"holes_co_located": "warning",
|
||||
"invalid_outline": "error",
|
||||
"isolated_copper": "warning",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"length_out_of_range": "error",
|
||||
"lib_footprint_issues": "warning",
|
||||
"lib_footprint_mismatch": "warning",
|
||||
"malformed_courtyard": "error",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"mirrored_text_on_front_layer": "warning",
|
||||
"missing_courtyard": "warning",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
"nonmirrored_text_on_back_layer": "warning",
|
||||
"npth_inside_courtyard": "warning",
|
||||
"overlapping_pads": "warning",
|
||||
"padstack": "error",
|
||||
"pth_inside_courtyard": "warning",
|
||||
"shorting_items": "error",
|
||||
"silk_edge_clearance": "ignore",
|
||||
"silk_over_copper": "error",
|
||||
"silk_overlap": "error",
|
||||
"skew_out_of_range": "error",
|
||||
"solder_mask_bridge": "error",
|
||||
"starved_thermal": "error",
|
||||
"text_height": "warning",
|
||||
"text_thickness": "warning",
|
||||
"through_hole_pad_without_hole": "error",
|
||||
"too_many_vias": "error",
|
||||
"track_angle": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_segment_length": "error",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
"rule_severitieslegacy_courtyards_overlap": true,
|
||||
"rule_severitieslegacy_no_courtyard_defined": false,
|
||||
"rules": {
|
||||
"allow_blind_buried_vias": false,
|
||||
"allow_microvias": false,
|
||||
"max_error": 0.01,
|
||||
"min_clearance": 0.0,
|
||||
"min_connection": 0.0,
|
||||
"min_copper_edge_clearance": 0.01,
|
||||
"min_groove_width": 0.0,
|
||||
"min_hole_clearance": 0.0,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.508,
|
||||
"min_microvia_drill": 0.127,
|
||||
"min_resolved_spokes": 1,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.8,
|
||||
"min_text_thickness": 0.12,
|
||||
"min_through_hole_diameter": 0.5,
|
||||
"min_track_width": 0.25,
|
||||
"min_via_annular_width": 0.05,
|
||||
"min_via_diameter": 0.9,
|
||||
"solder_mask_to_copper_clearance": 0.0,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"teardrop_options": [
|
||||
{
|
||||
"td_onpthpad": true,
|
||||
"td_onroundshapesonly": false,
|
||||
"td_onsmdpad": true,
|
||||
"td_ontrackend": false,
|
||||
"td_onvia": true
|
||||
}
|
||||
],
|
||||
"teardrop_parameters": [
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_round_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_rect_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_track_end",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
}
|
||||
],
|
||||
"track_widths": [
|
||||
0.5,
|
||||
0.4,
|
||||
0.5
|
||||
],
|
||||
"tuning_pattern_settings": {
|
||||
"diff_pair_defaults": {
|
||||
"corner_radius_percentage": 100,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.1,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
},
|
||||
"diff_pair_skew_defaults": {
|
||||
"corner_radius_percentage": 100,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.1,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
},
|
||||
"single_track_defaults": {
|
||||
"corner_radius_percentage": 100,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.1,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
}
|
||||
},
|
||||
"via_dimensions": [
|
||||
{
|
||||
"diameter": 1.6,
|
||||
"drill": 0.6
|
||||
}
|
||||
],
|
||||
"zones_allow_external_fillets": false,
|
||||
"zones_use_no_outline": true
|
||||
},
|
||||
"ipc2581": {
|
||||
"dist": "",
|
||||
"distpn": "",
|
||||
"internal_id": "",
|
||||
"mfg": "",
|
||||
"mpn": ""
|
||||
},
|
||||
"layer_pairs": [],
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"component_class_settings": {
|
||||
"assignments": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"sheet_component_classes": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_label_syntax": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"conflicting_netclasses": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"footprint_filter": "ignore",
|
||||
"footprint_link_issues": "warning",
|
||||
"four_way_junction": "ignore",
|
||||
"global_label_dangling": "warning",
|
||||
"ground_pin_not_ground": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"isolated_pin_label": "warning",
|
||||
"label_dangling": "error",
|
||||
"label_multiple_wires": "warning",
|
||||
"lib_symbol_issues": "warning",
|
||||
"lib_symbol_mismatch": "warning",
|
||||
"missing_bidi_pin": "warning",
|
||||
"missing_input_pin": "warning",
|
||||
"missing_power_pin": "error",
|
||||
"missing_unit": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "error",
|
||||
"no_connect_dangling": "error",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "error",
|
||||
"power_pin_not_driven": "error",
|
||||
"same_local_global_label": "warning",
|
||||
"similar_label_and_power": "warning",
|
||||
"similar_labels": "warning",
|
||||
"similar_power": "warning",
|
||||
"simulation_model_issue": "ignore",
|
||||
"single_global_label": "warning",
|
||||
"stacked_pin_name": "warning",
|
||||
"unannotated": "error",
|
||||
"unconnected_wire_endpoint": "warning",
|
||||
"undefined_netclass": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"legacy": {
|
||||
"common": {
|
||||
"NetDir": ""
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "variants.kicad_pro",
|
||||
"version": 3
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.25,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.25,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.508,
|
||||
"microvia_drill": 0.127,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"priority": 2147483647,
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.5,
|
||||
"tuning_profile": "",
|
||||
"via_diameter": 1.6,
|
||||
"via_drill": 0.6,
|
||||
"wire_width": 6
|
||||
},
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.28,
|
||||
"diff_pair_gap": 0.28,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.28,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.508,
|
||||
"microvia_drill": 0.127,
|
||||
"name": "POWER",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"priority": 0,
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.8,
|
||||
"tuning_profile": "",
|
||||
"via_diameter": 1.6,
|
||||
"via_drill": 0.6,
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 5
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": [
|
||||
{
|
||||
"netclass": "POWER",
|
||||
"pattern": "GND"
|
||||
},
|
||||
{
|
||||
"netclass": "POWER",
|
||||
"pattern": "VCC"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "variants.net",
|
||||
"plot": "",
|
||||
"pos_files": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "pic_programmer.step",
|
||||
"svg": "",
|
||||
"vmrl": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"annotation": {
|
||||
"method": 0,
|
||||
"sort_order": 0
|
||||
},
|
||||
"bom_export_filename": "${PROJECTNAME}.csv",
|
||||
"bom_fmt_presets": [],
|
||||
"bom_fmt_settings": {
|
||||
"field_delimiter": ",",
|
||||
"keep_line_breaks": false,
|
||||
"keep_tabs": false,
|
||||
"name": "CSV",
|
||||
"ref_delimiter": ",",
|
||||
"ref_range_delimiter": "",
|
||||
"string_delimiter": "\""
|
||||
},
|
||||
"bom_presets": [],
|
||||
"bom_settings": {
|
||||
"exclude_dnp": false,
|
||||
"fields_ordered": [
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Reference",
|
||||
"name": "Reference",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Value",
|
||||
"name": "Value",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Datasheet",
|
||||
"name": "Datasheet",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Footprint",
|
||||
"name": "Footprint",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "Quantity",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "${QUANTITY}",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "#",
|
||||
"name": "${ITEM_NUMBER}",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Champ4",
|
||||
"name": "Champ4",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Description",
|
||||
"name": "Description",
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"filter_string": "",
|
||||
"group_symbols": true,
|
||||
"include_excluded_from_bom": false,
|
||||
"name": "",
|
||||
"sort_asc": true,
|
||||
"sort_field": "Reference"
|
||||
},
|
||||
"bus_aliases": {},
|
||||
"connection_grid_size": 50.0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_bus_thickness": 12.0,
|
||||
"default_junction_size": 36.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"default_wire_thickness": 6.0,
|
||||
"field_names": [],
|
||||
"hop_over_size_choice": 0,
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.2,
|
||||
"operating_point_overlay_i_precision": 3,
|
||||
"operating_point_overlay_i_range": "~A",
|
||||
"operating_point_overlay_v_precision": 3,
|
||||
"operating_point_overlay_v_range": "~V",
|
||||
"overbar_offset_ratio": 1.23,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.2
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"fix_passive_vals": false,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 0,
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"reuse_designators": true,
|
||||
"space_save_all_events": true,
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_model_current_sheet_as_root": true,
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_dissipations": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0,
|
||||
"top_level_sheets": [
|
||||
{
|
||||
"filename": "variants.kicad_sch",
|
||||
"name": "pic_programmer",
|
||||
"uuid": "2e45d1d2-c73f-46e5-98d6-3a9dc360bff5"
|
||||
}
|
||||
],
|
||||
"used_designators": "",
|
||||
"variants": [
|
||||
{
|
||||
"description": "testing variant 1 description",
|
||||
"name": "Variant 1"
|
||||
},
|
||||
{
|
||||
"description": "Test of variant 2 desc",
|
||||
"name": "Variant2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"2e45d1d2-c73f-46e5-98d6-3a9dc360bff5",
|
||||
"pic_programmer"
|
||||
],
|
||||
[
|
||||
"00000000-0000-0000-0000-00004804a5e2",
|
||||
"pic_sockets"
|
||||
]
|
||||
],
|
||||
"text_variables": {},
|
||||
"tuning_profiles": {
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"tuning_profiles_impedance_geometric": []
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -140,6 +140,96 @@ def test_sch_export_pdf( kitest,
|
||||
kitest.add_attachment( str( output_filepath ) )
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_file,output_fn,compare_fn,line_skip_count,cli_args",
|
||||
[("cli/variants/variants.kicad_sch", "variants_default.bom.csv", "cli/variants/variants_default.bom.csv", 0,
|
||||
["--exclude-dnp", "--fields", "Reference,Value", "--labels", "Refs,Value"]),
|
||||
("cli/variants/variants.kicad_sch", "variants_v1.bom.csv", "cli/variants/variants_v1.bom.csv", 0,
|
||||
["--variant", "Variant 1", "--exclude-dnp", "--fields", "Reference,Value", "--labels", "Refs,Value"]),
|
||||
("cli/variants/variants.kicad_sch", "variants_v2.bom.csv", "cli/variants/variants_v2.bom.csv", 0,
|
||||
["--variant", "Variant2", "--exclude-dnp", "--fields", "Reference,Value", "--labels", "Refs,Value"]),
|
||||
])
|
||||
def test_sch_export_bom_variants( kitest,
|
||||
test_file: str,
|
||||
output_fn: str,
|
||||
compare_fn: str,
|
||||
line_skip_count: int,
|
||||
cli_args: List[str] ):
|
||||
"""Test BOM export with variant support and DNP exclusion"""
|
||||
input_file = kitest.get_data_file_path( test_file )
|
||||
compare_filepath = kitest.get_data_file_path( compare_fn )
|
||||
|
||||
output_filepath = kitest.get_output_path( "cli/" ).joinpath( output_fn )
|
||||
|
||||
command = [utils.kicad_cli(), "sch", "export", "bom"]
|
||||
command.extend( cli_args )
|
||||
command.append( "-o" )
|
||||
command.append( str( output_filepath ) )
|
||||
command.append( input_file )
|
||||
|
||||
stdout, stderr, exitcode = utils.run_and_capture( command )
|
||||
|
||||
assert exitcode == 0
|
||||
assert stderr == ''
|
||||
|
||||
assert utils.textdiff_files( compare_filepath, str( output_filepath ), line_skip_count )
|
||||
|
||||
kitest.add_attachment( str( output_filepath ) )
|
||||
|
||||
|
||||
def test_sch_export_bom_multi_variant_requires_placeholder( kitest ):
|
||||
"""Test that multiple variants require ${VARIANT} in output path"""
|
||||
input_file = kitest.get_data_file_path( "cli/variants/variants.kicad_sch" )
|
||||
|
||||
output_filepath = kitest.get_output_path( "cli/" ).joinpath( "multi_variant_fail.csv" )
|
||||
|
||||
command = [utils.kicad_cli(), "sch", "export", "bom"]
|
||||
command.extend( ["--variant", "Variant 1", "--variant", "Variant2"] )
|
||||
command.extend( ["--exclude-dnp", "--fields", "Reference,Value", "--labels", "Refs,Value"] )
|
||||
command.append( "-o" )
|
||||
command.append( str( output_filepath ) )
|
||||
command.append( input_file )
|
||||
|
||||
stdout, stderr, exitcode = utils.run_and_capture( command )
|
||||
|
||||
assert exitcode == 1
|
||||
assert "VARIANT" in stderr
|
||||
|
||||
|
||||
def test_sch_export_bom_multi_variant_with_placeholder( kitest ):
|
||||
"""Test BOM export with multiple variants using ${VARIANT} placeholder"""
|
||||
input_file = kitest.get_data_file_path( "cli/variants/variants.kicad_sch" )
|
||||
|
||||
output_dir = kitest.get_output_path( "cli/" )
|
||||
output_pattern = str( output_dir.joinpath( "bom_${VARIANT}.csv" ) )
|
||||
|
||||
command = [utils.kicad_cli(), "sch", "export", "bom"]
|
||||
command.extend( ["--variant", "Variant 1", "--variant", "Variant2"] )
|
||||
command.extend( ["--exclude-dnp", "--fields", "Reference,Value", "--labels", "Refs,Value"] )
|
||||
command.append( "-o" )
|
||||
command.append( output_pattern )
|
||||
command.append( input_file )
|
||||
|
||||
stdout, stderr, exitcode = utils.run_and_capture( command )
|
||||
|
||||
assert exitcode == 0
|
||||
assert stderr == ''
|
||||
|
||||
v1_path = output_dir.joinpath( "bom_Variant 1.csv" )
|
||||
v2_path = output_dir.joinpath( "bom_Variant2.csv" )
|
||||
|
||||
assert v1_path.exists(), f"Expected output file {v1_path} not found"
|
||||
assert v2_path.exists(), f"Expected output file {v2_path} not found"
|
||||
|
||||
v1_compare = kitest.get_data_file_path( "cli/variants/variants_v1.bom.csv" )
|
||||
v2_compare = kitest.get_data_file_path( "cli/variants/variants_v2.bom.csv" )
|
||||
|
||||
assert utils.textdiff_files( v1_compare, str( v1_path ), 0 )
|
||||
assert utils.textdiff_files( v2_compare, str( v2_path ), 0 )
|
||||
|
||||
kitest.add_attachment( str( v1_path ) )
|
||||
kitest.add_attachment( str( v2_path ) )
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_file,output_fn,line_skip_count,cli_args",
|
||||
[("cli/basic_test/basic_test.kicad_sch", "basic_test.pythonbom", 6, [])
|
||||
])
|
||||
|
||||
@@ -486,6 +486,14 @@ BOOST_AUTO_TEST_CASE( Compare )
|
||||
BOOST_CHECK( m_part_no_data.Compare( testPart, SCH_ITEM::COMPARE_FLAGS::EQUALITY ) < 0 );
|
||||
m_part_no_data.SetExcludedFromBoard( false );
|
||||
|
||||
// Include in position files support tests.
|
||||
testPart.SetExcludedFromPosFiles( true );
|
||||
BOOST_CHECK( m_part_no_data.Compare( testPart, SCH_ITEM::COMPARE_FLAGS::EQUALITY ) > 0 );
|
||||
testPart.SetExcludedFromPosFiles( false );
|
||||
m_part_no_data.SetExcludedFromPosFiles( true );
|
||||
BOOST_CHECK( m_part_no_data.Compare( testPart, SCH_ITEM::COMPARE_FLAGS::EQUALITY ) < 0 );
|
||||
m_part_no_data.SetExcludedFromPosFiles( false );
|
||||
|
||||
// Show pin names flag comparison tests.
|
||||
m_part_no_data.SetShowPinNames( false );
|
||||
BOOST_CHECK( m_part_no_data.Compare( testPart, SCH_ITEM::COMPARE_FLAGS::EQUALITY ) < 0 );
|
||||
|
||||
@@ -132,6 +132,16 @@ BOOST_AUTO_TEST_CASE( SchSymbolVariantTest )
|
||||
symbol->SetExcludedFromSim( true, &m_schematic->Hierarchy()[0], variantName );
|
||||
BOOST_CHECK( symbol->GetExcludedFromSim( &m_schematic->Hierarchy()[0], variantName ) );
|
||||
|
||||
// Test exclude from board property variant.
|
||||
BOOST_CHECK( !symbol->GetExcludedFromBoard() );
|
||||
symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], variantName );
|
||||
BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], variantName ) );
|
||||
|
||||
// Test exclude from position files property variant.
|
||||
BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
|
||||
symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], variantName );
|
||||
BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], variantName ) );
|
||||
|
||||
// Test a value field variant change.
|
||||
BOOST_CHECK( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0 ) == wxS( "1K" ) );
|
||||
@@ -185,4 +195,557 @@ BOOST_AUTO_TEST_CASE( FieldAdditionByName )
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test variant description methods.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( VariantDescription )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
wxString variantName = wxS( "TestVariant" );
|
||||
wxString description = wxS( "This is a test variant description" );
|
||||
|
||||
// Add a variant
|
||||
m_schematic->AddVariant( variantName );
|
||||
BOOST_CHECK( m_schematic->GetVariantNames().contains( variantName ) );
|
||||
|
||||
// Set description
|
||||
m_schematic->SetVariantDescription( variantName, description );
|
||||
BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( variantName ), description );
|
||||
|
||||
// Empty description for non-existent variant
|
||||
BOOST_CHECK( m_schematic->GetVariantDescription( wxS( "NonExistent" ) ).IsEmpty() );
|
||||
|
||||
// Clear description
|
||||
m_schematic->SetVariantDescription( variantName, wxEmptyString );
|
||||
BOOST_CHECK( m_schematic->GetVariantDescription( variantName ).IsEmpty() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test ${VARIANT} text variable resolution.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( TextVariableVARIANT )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
wxString variantName = wxS( "MilitaryGrade" );
|
||||
|
||||
// Add a variant and set it as current
|
||||
m_schematic->AddVariant( variantName );
|
||||
m_schematic->SetCurrentVariant( variantName );
|
||||
|
||||
// Test that ${VARIANT} resolves to the current variant name
|
||||
wxString token = wxS( "VARIANT" );
|
||||
bool resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK_EQUAL( token, variantName );
|
||||
|
||||
// Also test VARIANTNAME (legacy/alias)
|
||||
token = wxS( "VARIANTNAME" );
|
||||
resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK_EQUAL( token, variantName );
|
||||
|
||||
// Empty variant
|
||||
m_schematic->SetCurrentVariant( wxEmptyString );
|
||||
token = wxS( "VARIANT" );
|
||||
resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK( token.IsEmpty() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test ${VARIANT_DESC} text variable resolution.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( TextVariableVARIANT_DESC )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
wxString variantName = wxS( "IndustrialVariant" );
|
||||
wxString description = wxS( "Industrial temperature range components" );
|
||||
|
||||
// Add a variant with description and set it as current
|
||||
m_schematic->AddVariant( variantName );
|
||||
m_schematic->SetVariantDescription( variantName, description );
|
||||
m_schematic->SetCurrentVariant( variantName );
|
||||
|
||||
// Test that ${VARIANT_DESC} resolves to the variant description
|
||||
wxString token = wxS( "VARIANT_DESC" );
|
||||
bool resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK_EQUAL( token, description );
|
||||
|
||||
// Test with no description set
|
||||
m_schematic->SetVariantDescription( variantName, wxEmptyString );
|
||||
token = wxS( "VARIANT_DESC" );
|
||||
resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK( token.IsEmpty() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test RenameVariant preserves data.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( RenameVariantPreservesData )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
SCH_SYMBOL* symbol = GetFirstSymbol();
|
||||
BOOST_REQUIRE( symbol );
|
||||
|
||||
wxString oldName = wxS( "OriginalVariant" );
|
||||
wxString newName = wxS( "RenamedVariant" );
|
||||
wxString description = wxS( "Original description" );
|
||||
|
||||
// Set up the variant with data
|
||||
m_schematic->AddVariant( oldName );
|
||||
m_schematic->SetVariantDescription( oldName, description );
|
||||
m_schematic->SetCurrentVariant( oldName );
|
||||
|
||||
// Set symbol variant properties
|
||||
symbol->SetDNP( true, &m_schematic->Hierarchy()[0], oldName );
|
||||
symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "100K" ), &m_schematic->Hierarchy()[0], oldName );
|
||||
|
||||
// Verify the data is set
|
||||
BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], oldName ) );
|
||||
BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0, oldName ), wxS( "100K" ) );
|
||||
|
||||
// Rename the variant
|
||||
m_schematic->RenameVariant( oldName, newName );
|
||||
|
||||
// Verify old name is gone
|
||||
BOOST_CHECK( !m_schematic->GetVariantNames().contains( oldName ) );
|
||||
|
||||
// Verify new name exists
|
||||
BOOST_CHECK( m_schematic->GetVariantNames().contains( newName ) );
|
||||
|
||||
// Verify description was preserved
|
||||
BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( newName ), description );
|
||||
|
||||
// Verify current variant was updated
|
||||
BOOST_CHECK_EQUAL( m_schematic->GetCurrentVariant(), newName );
|
||||
|
||||
// Verify symbol variant data was preserved
|
||||
BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], newName ) );
|
||||
BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0, newName ), wxS( "100K" ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test CopyVariant creates an independent copy.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( CopyVariantCreatesIndependentCopy )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
SCH_SYMBOL* symbol = GetFirstSymbol();
|
||||
BOOST_REQUIRE( symbol );
|
||||
|
||||
wxString sourceVariant = wxS( "SourceVariant" );
|
||||
wxString copyVariant = wxS( "CopiedVariant" );
|
||||
wxString description = wxS( "Source description" );
|
||||
|
||||
// Set up the source variant
|
||||
m_schematic->AddVariant( sourceVariant );
|
||||
m_schematic->SetVariantDescription( sourceVariant, description );
|
||||
|
||||
// Set symbol variant properties for source
|
||||
symbol->SetDNP( true, &m_schematic->Hierarchy()[0], sourceVariant );
|
||||
symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], sourceVariant );
|
||||
symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], sourceVariant );
|
||||
symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], sourceVariant );
|
||||
symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "47K" ), &m_schematic->Hierarchy()[0], sourceVariant );
|
||||
|
||||
// Copy the variant
|
||||
m_schematic->CopyVariant( sourceVariant, copyVariant );
|
||||
|
||||
// Verify both variants exist
|
||||
BOOST_CHECK( m_schematic->GetVariantNames().contains( sourceVariant ) );
|
||||
BOOST_CHECK( m_schematic->GetVariantNames().contains( copyVariant ) );
|
||||
|
||||
// Verify description was copied
|
||||
BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( copyVariant ), description );
|
||||
|
||||
// Verify symbol properties were copied
|
||||
BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], copyVariant ) );
|
||||
BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], copyVariant ) );
|
||||
BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], copyVariant ) );
|
||||
BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], copyVariant ) );
|
||||
BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0, copyVariant ), wxS( "47K" ) );
|
||||
|
||||
// Modify the copy and verify source is unchanged
|
||||
symbol->SetDNP( false, &m_schematic->Hierarchy()[0], copyVariant );
|
||||
symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "100K" ), &m_schematic->Hierarchy()[0], copyVariant );
|
||||
|
||||
// Source should still have original values
|
||||
BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], sourceVariant ) );
|
||||
BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0, sourceVariant ), wxS( "47K" ) );
|
||||
|
||||
// Copy should have modified values
|
||||
BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], copyVariant ) );
|
||||
BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0, copyVariant ), wxS( "100K" ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test variant field value difference detection.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( VariantFieldDifferenceDetection )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
SCH_SYMBOL* symbol = GetFirstSymbol();
|
||||
BOOST_REQUIRE( symbol );
|
||||
|
||||
wxString variantName1 = wxS( "DiffTestVariant1" );
|
||||
wxString variantName2 = wxS( "DiffTestVariant2" );
|
||||
|
||||
// Get the default value
|
||||
wxString defaultValue = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0 );
|
||||
BOOST_CHECK_EQUAL( defaultValue, wxS( "1K" ) );
|
||||
|
||||
// Add a variant and set a different value
|
||||
m_schematic->AddVariant( variantName1 );
|
||||
symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "2.2K" ), &m_schematic->Hierarchy()[0], variantName1 );
|
||||
|
||||
// Get variant value
|
||||
wxString variantValue = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0, variantName1 );
|
||||
BOOST_CHECK_EQUAL( variantValue, wxS( "2.2K" ) );
|
||||
|
||||
// Verify values differ
|
||||
BOOST_CHECK( defaultValue != variantValue );
|
||||
|
||||
// Add another variant with same value as default to verify equality detection
|
||||
m_schematic->AddVariant( variantName2 );
|
||||
symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "1K" ), &m_schematic->Hierarchy()[0], variantName2 );
|
||||
wxString variantValue2 = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
|
||||
false, 0, variantName2 );
|
||||
|
||||
// Second variant should have the same value as default
|
||||
BOOST_CHECK_EQUAL( defaultValue, variantValue2 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test variant DNP filtering for BOM.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( VariantDNPFiltering )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
SCH_SYMBOL* symbol = GetFirstSymbol();
|
||||
BOOST_REQUIRE( symbol );
|
||||
|
||||
wxString variantName = wxS( "DNPVariant" );
|
||||
|
||||
// By default, symbol should not be DNP
|
||||
BOOST_CHECK( !symbol->GetDNP() );
|
||||
BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxEmptyString ) );
|
||||
|
||||
// Add a variant where symbol is DNP
|
||||
m_schematic->AddVariant( variantName );
|
||||
symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
|
||||
|
||||
// Default should still not be DNP
|
||||
BOOST_CHECK( !symbol->GetDNP() );
|
||||
BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxEmptyString ) );
|
||||
|
||||
// Variant should be DNP
|
||||
BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
|
||||
|
||||
// Test exclude from BOM as well
|
||||
BOOST_CHECK( !symbol->GetExcludedFromBOM() );
|
||||
symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], variantName );
|
||||
BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], variantName ) );
|
||||
BOOST_CHECK( !symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], wxEmptyString ) );
|
||||
|
||||
// Test exclude from board as well
|
||||
BOOST_CHECK( !symbol->GetExcludedFromBoard() );
|
||||
symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], variantName );
|
||||
BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], variantName ) );
|
||||
BOOST_CHECK( !symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], wxEmptyString ) );
|
||||
|
||||
// Test exclude from position files as well
|
||||
BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
|
||||
symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], variantName );
|
||||
BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], variantName ) );
|
||||
BOOST_CHECK( !symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], wxEmptyString ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test GetVariantNamesForUI returns properly formatted array.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( GetVariantNamesForUI )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
// Add some variants
|
||||
m_schematic->AddVariant( wxS( "Zebra" ) );
|
||||
m_schematic->AddVariant( wxS( "Alpha" ) );
|
||||
m_schematic->AddVariant( wxS( "Beta" ) );
|
||||
|
||||
wxArrayString variantNames = m_schematic->GetVariantNamesForUI();
|
||||
|
||||
// Should have at least 4 items (default + 3 variants)
|
||||
BOOST_CHECK( variantNames.GetCount() >= 4 );
|
||||
|
||||
// First item should be the default placeholder
|
||||
// The actual string may vary but should represent "default"
|
||||
BOOST_CHECK( !variantNames[0].IsEmpty() );
|
||||
|
||||
// Remaining items should be sorted
|
||||
// Alpha, Beta, Zebra
|
||||
bool foundAlpha = false;
|
||||
bool foundBeta = false;
|
||||
bool foundZebra = false;
|
||||
|
||||
for( size_t i = 1; i < variantNames.GetCount(); i++ )
|
||||
{
|
||||
if( variantNames[i] == wxS( "Alpha" ) )
|
||||
foundAlpha = true;
|
||||
else if( variantNames[i] == wxS( "Beta" ) )
|
||||
foundBeta = true;
|
||||
else if( variantNames[i] == wxS( "Zebra" ) )
|
||||
foundZebra = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( foundAlpha );
|
||||
BOOST_CHECK( foundBeta );
|
||||
BOOST_CHECK( foundZebra );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that SetValueFieldText correctly persists variant field values.
|
||||
* This tests the fix for a bug where variant values were not saved because
|
||||
* GetVariant returned a copy instead of modifying the instance directly.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( SetValueFieldTextPersistsVariantValue )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
SCH_SYMBOL* symbol = GetFirstSymbol();
|
||||
BOOST_REQUIRE( symbol );
|
||||
|
||||
wxString variantName = wxS( "PersistenceTest" );
|
||||
wxString newValue = wxS( "4.7K" );
|
||||
wxString defaultValue = symbol->GetField( FIELD_T::VALUE )->GetText();
|
||||
|
||||
// Add the variant
|
||||
m_schematic->AddVariant( variantName );
|
||||
|
||||
// Set value using SetValueFieldText (the function that had the bug)
|
||||
symbol->SetValueFieldText( newValue, &m_schematic->Hierarchy()[0], variantName );
|
||||
|
||||
// Verify that the variant value was actually saved by reading it back
|
||||
std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
|
||||
BOOST_REQUIRE( variant.has_value() );
|
||||
|
||||
wxString fieldName = symbol->GetField( FIELD_T::VALUE )->GetName();
|
||||
BOOST_CHECK( variant->m_Fields.contains( fieldName ) );
|
||||
BOOST_CHECK_EQUAL( variant->m_Fields.at( fieldName ), newValue );
|
||||
|
||||
// Verify through GetValue method as well
|
||||
wxString retrievedValue = symbol->GetValue( false, &m_schematic->Hierarchy()[0], false, variantName );
|
||||
BOOST_CHECK_EQUAL( retrievedValue, newValue );
|
||||
|
||||
// Verify default value is unchanged
|
||||
wxString retrievedDefault = symbol->GetValue( false, &m_schematic->Hierarchy()[0], false, wxEmptyString );
|
||||
BOOST_CHECK_EQUAL( retrievedDefault, defaultValue );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that SetFieldText works consistently with SetValueFieldText for the VALUE field.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( SetFieldTextAndSetValueFieldTextConsistency )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
SCH_SYMBOL* symbol = GetFirstSymbol();
|
||||
BOOST_REQUIRE( symbol );
|
||||
|
||||
wxString variantName1 = wxS( "MethodTest1" );
|
||||
wxString variantName2 = wxS( "MethodTest2" );
|
||||
wxString value1 = wxS( "10K" );
|
||||
wxString value2 = wxS( "22K" );
|
||||
wxString fieldName = symbol->GetField( FIELD_T::VALUE )->GetName();
|
||||
|
||||
m_schematic->AddVariant( variantName1 );
|
||||
m_schematic->AddVariant( variantName2 );
|
||||
|
||||
// Set variant 1 using SetValueFieldText
|
||||
symbol->SetValueFieldText( value1, &m_schematic->Hierarchy()[0], variantName1 );
|
||||
|
||||
// Set variant 2 using SetFieldText
|
||||
symbol->SetFieldText( fieldName, value2, &m_schematic->Hierarchy()[0], variantName2 );
|
||||
|
||||
// Both methods should produce the same result structure
|
||||
std::optional<SCH_SYMBOL_VARIANT> variant1 = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName1 );
|
||||
std::optional<SCH_SYMBOL_VARIANT> variant2 = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName2 );
|
||||
|
||||
BOOST_REQUIRE( variant1.has_value() );
|
||||
BOOST_REQUIRE( variant2.has_value() );
|
||||
|
||||
BOOST_CHECK( variant1->m_Fields.contains( fieldName ) );
|
||||
BOOST_CHECK( variant2->m_Fields.contains( fieldName ) );
|
||||
|
||||
BOOST_CHECK_EQUAL( variant1->m_Fields.at( fieldName ), value1 );
|
||||
BOOST_CHECK_EQUAL( variant2->m_Fields.at( fieldName ), value2 );
|
||||
|
||||
// Verify through GetValue
|
||||
BOOST_CHECK_EQUAL( symbol->GetValue( false, &m_schematic->Hierarchy()[0], false, variantName1 ), value1 );
|
||||
BOOST_CHECK_EQUAL( symbol->GetValue( false, &m_schematic->Hierarchy()[0], false, variantName2 ), value2 );
|
||||
|
||||
// Verify through GetFieldText
|
||||
BOOST_CHECK_EQUAL( symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName1 ), value1 );
|
||||
BOOST_CHECK_EQUAL( symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName2 ), value2 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test variant-specific field dereferencing via ${REF:FIELD:VARIANT} syntax.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( VariantSpecificFieldDereferencing )
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
|
||||
fn.AppendDir( wxS( "variant_test" ) );
|
||||
fn.SetName( wxS( "variant_test" ) );
|
||||
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
LoadSchematic( fn.GetFullPath() );
|
||||
BOOST_REQUIRE( m_schematic );
|
||||
|
||||
SCH_SYMBOL* symbol = GetFirstSymbol();
|
||||
BOOST_REQUIRE( symbol );
|
||||
|
||||
wxString variantName = wxS( "MilitaryGrade" );
|
||||
wxString variantValue = wxS( "1K-MIL" );
|
||||
wxString defaultValue = wxS( "1K" );
|
||||
|
||||
// Create a variant with a different value field
|
||||
m_schematic->AddVariant( variantName );
|
||||
symbol->GetField( FIELD_T::VALUE )->SetText( variantValue, &m_schematic->Hierarchy()[0], variantName );
|
||||
|
||||
// Verify default value
|
||||
BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], false, 0 ),
|
||||
defaultValue );
|
||||
|
||||
// Get the symbol's reference (R1) for cross-reference testing
|
||||
wxString symbolRef = symbol->GetRef( &m_schematic->Hierarchy()[0], false );
|
||||
|
||||
// Test 1: ResolveCrossReference with variant syntax - should return variant-specific value
|
||||
wxString token = symbolRef + wxS( ":VALUE:" ) + variantName;
|
||||
bool resolved = m_schematic->ResolveCrossReference( &token, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK_EQUAL( token, variantValue );
|
||||
|
||||
// Test 2: ResolveCrossReference without variant - should return default value
|
||||
token = symbolRef + wxS( ":VALUE" );
|
||||
resolved = m_schematic->ResolveCrossReference( &token, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK_EQUAL( token, defaultValue );
|
||||
|
||||
// Test 3: ResolveCrossReference with non-existent variant - should return default value
|
||||
token = symbolRef + wxS( ":VALUE:NonExistentVariant" );
|
||||
resolved = m_schematic->ResolveCrossReference( &token, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK_EQUAL( token, defaultValue );
|
||||
|
||||
// Test 4: ResolveTextVar with variant parameter directly
|
||||
token = wxS( "VALUE" );
|
||||
resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, variantName, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK_EQUAL( token, variantValue );
|
||||
|
||||
// Test 5: ResolveTextVar with empty variant - should return default
|
||||
token = wxS( "VALUE" );
|
||||
resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, wxEmptyString, 0 );
|
||||
BOOST_CHECK( resolved );
|
||||
BOOST_CHECK_EQUAL( token, defaultValue );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Reference in New Issue
Block a user