More schematic variant work.

Everything in the variant handling should be working with the exception of
the job handling and command line interface.
This commit is contained in:
Wayne Stambaugh
2025-12-30 11:11:33 -05:00
parent 6056c50227
commit ca0bfe0bba
31 changed files with 1960 additions and 445 deletions
+48 -6
View File
@@ -144,9 +144,16 @@ DIALOG_FIELD_PROPERTIES::DIALOG_FIELD_PROPERTIES( SCH_BASE_FRAME* aParent, const
// show text variable cross-references in a human-readable format
if( aField->Schematic() )
m_text = aField->Schematic()->ConvertKIIDsToRefs( aField->GetText() );
{
const SCH_SHEET_PATH& sheetPath = aField->Schematic()->CurrentSheet();
wxString variant = aField->Schematic()->GetCurrentVariant();
m_text = aField->Schematic()->ConvertKIIDsToRefs( aField->GetText( &sheetPath, variant ) );
}
else
{
m_text = aField->GetText();
}
m_font = m_field->GetFont();
m_isItalic = aField->IsItalic();
@@ -581,7 +588,17 @@ void DIALOG_FIELD_PROPERTIES::updateText( SCH_FIELD* aField )
void DIALOG_FIELD_PROPERTIES::UpdateField( SCH_FIELD* aField )
{
aField->SetText( m_text );
if( aField->Schematic() )
{
const SCH_SHEET_PATH& sheetPath = aField->Schematic()->CurrentSheet();
wxString variant = aField->Schematic()->GetCurrentVariant();
aField->SetText( m_text, &sheetPath, variant );
}
else
{
aField->SetText( m_text );
}
updateText( aField );
@@ -605,6 +622,18 @@ void DIALOG_FIELD_PROPERTIES::UpdateField( SCH_COMMIT* aCommit, SCH_FIELD* aFiel
{
SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
SCH_ITEM* parent = dynamic_cast<SCH_ITEM*>( aField->GetParent() );
bool fieldTextSet = false;
SCH_SHEET_PATH sheetPath;
wxString variantName;
// convert any text variable cross-references to their UUIDs
m_text = aField->Schematic()->ConvertRefsToKIIDs( m_text );
if( aField->Schematic() )
{
sheetPath = aField->Schematic()->CurrentSheet();
variantName = aField->Schematic()->GetCurrentVariant();
}
if( parent && parent->Type() == SCH_SYMBOL_T )
{
@@ -612,6 +641,10 @@ void DIALOG_FIELD_PROPERTIES::UpdateField( SCH_COMMIT* aCommit, SCH_FIELD* aFiel
if( m_fieldId == FIELD_T::REFERENCE )
symbol->SetRef( aSheetPath, m_text );
else
symbol->SetFieldText( aField->GetName(), m_text, &sheetPath, variantName );
fieldTextSet = true;
// Set the unit selection in multiple units per package
if( m_unitChoice->IsShown() )
@@ -621,6 +654,16 @@ void DIALOG_FIELD_PROPERTIES::UpdateField( SCH_COMMIT* aCommit, SCH_FIELD* aFiel
symbol->SetUnit( unit_selection );
}
}
else if( parent && parent->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( parent );
if( !aField->IsMandatory() )
{
sheet->SetFieldText( aField->GetName(), m_text, &sheetPath, variantName );
fieldTextSet = true;
}
}
else if( parent && parent->Type() == SCH_GLOBAL_LABEL_T )
{
if( m_fieldId == FIELD_T::INTERSHEET_REFS )
@@ -648,16 +691,15 @@ void DIALOG_FIELD_PROPERTIES::UpdateField( SCH_COMMIT* aCommit, SCH_FIELD* aFiel
if( aField->GetEffectiveVertJustify() != m_verticalJustification )
positioningModified = true;
// convert any text variable cross-references to their UUIDs
m_text = aField->Schematic()->ConvertRefsToKIIDs( m_text );
// Changing a sheetname need to update the hierarchy navigator
bool needUpdateHierNav = false;
if( m_fieldId == FIELD_T::SHEET_NAME )
needUpdateHierNav = m_text != aField->GetText();
aField->SetText( m_text );
if( !fieldTextSet )
aField->SetText( m_text );
updateText( aField );
aField->SetPosition( m_position );
+42 -15
View File
@@ -125,6 +125,9 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataToWindow()
if( !wxDialog::TransferDataToWindow() )
return false;
SCH_SHEET_PATH instance = m_frame->GetCurrentSheet();
wxString variantName = m_frame->Schematic().GetCurrentVariant();
// Push a copy of each field into m_updateFields
for( SCH_FIELD& field : m_sheet->GetFields() )
{
@@ -140,6 +143,9 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataToWindow()
}
#endif
if( !field_copy.IsMandatory() )
field_copy.SetText( m_sheet->GetFieldText( field.GetName(), &instance, variantName ) );
// change offset to be symbol-relative
field_copy.Offset( -m_sheet->GetPosition() );
@@ -167,15 +173,13 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataToWindow()
m_borderSwatch->SetSwatchBackground( canvas );
m_backgroundSwatch->SetSwatchBackground( canvas );
SCH_SHEET_PATH instance = m_frame->GetCurrentSheet();
instance.push_back( m_sheet );
m_pageNumberTextCtrl->ChangeValue( instance.GetPageNumber() );
m_cbExcludeFromSim->SetValue( m_sheet->GetExcludedFromSim() );
m_cbExcludeFromBom->SetValue( m_sheet->GetExcludedFromBOM() );
m_cbExcludeFromSim->SetValue( m_sheet->GetExcludedFromSim( &instance, variantName ) );
m_cbExcludeFromBom->SetValue( m_sheet->GetExcludedFromBOM( &instance, variantName ) );
m_cbExcludeFromBoard->SetValue( m_sheet->GetExcludedFromBoard() );
m_cbDNP->SetValue( m_sheet->GetDNP() );
m_cbDNP->SetValue( m_sheet->GetDNP( &instance, variantName ) );
instance.push_back( m_sheet );
m_pageNumberTextCtrl->ChangeValue( instance.GetPageNumber() );
return true;
}
@@ -362,6 +366,9 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
if( positioningChanged( m_fields, m_sheet ) )
m_sheet->SetFieldsAutoplaced( AUTOPLACE_NONE );
SCH_SHEET_PATH instance = m_frame->GetCurrentSheet();
wxString variantName = m_frame->Schematic().GetCurrentVariant();
for( int ii = m_fields->GetNumberRows() - 1; ii >= 0; ii-- )
{
SCH_FIELD& field = m_fields->at( ii );
@@ -375,9 +382,31 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
m_fields->erase( m_fields->begin() + ii );
else if( fieldName.IsEmpty() )
field.SetName( _( "untitled" ) );
}
m_sheet->SetFields( *m_fields );
SCH_FIELD* existingField = m_sheet->GetField( fieldName );
SCH_FIELD* tmp;
if( !existingField )
{
m_sheet->AddOptionalField( field );
}
else
{
wxString defaultText = m_sheet->Schematic()->ConvertRefsToKIIDs( existingField->GetText() );
tmp = const_cast<SCH_FIELD*>( existingField );
*tmp = field;
if( !variantName.IsEmpty() )
{
// Restore the default field text for existing fields.
tmp->SetText( defaultText, &instance );
tmp->SetText( m_sheet->Schematic()->ConvertRefsToKIIDs( field.GetText() ),
&instance, variantName );
}
}
}
m_sheet->SetBorderWidth( m_borderWidth.GetIntValue() );
@@ -404,12 +433,10 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
m_sheet->SetBorderColor( m_borderSwatch->GetSwatchColor() );
m_sheet->SetBackgroundColor( m_backgroundSwatch->GetSwatchColor() );
m_sheet->SetExcludedFromSim( m_cbExcludeFromSim->GetValue() );
m_sheet->SetExcludedFromBOM( m_cbExcludeFromBom->GetValue() );
m_sheet->SetExcludedFromSim( m_cbExcludeFromSim->GetValue(), &instance, variantName );
m_sheet->SetExcludedFromBOM( m_cbExcludeFromBom->GetValue(), &instance, variantName );
m_sheet->SetExcludedFromBoard( m_cbExcludeFromBoard->GetValue() );
m_sheet->SetDNP( m_cbDNP->GetValue() );
SCH_SHEET_PATH instance = m_frame->GetCurrentSheet();
m_sheet->SetDNP( m_cbDNP->GetValue(), &instance, variantName );
instance.push_back( m_sheet );
+81 -66
View File
@@ -263,6 +263,20 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent,
m_variantListBox->Set( parent->Schematic().GetVariantNamesForUI() );
if( !m_parent->Schematic().GetCurrentVariant().IsEmpty() )
{
int toSelect = m_variantListBox->FindString( m_parent->Schematic().GetCurrentVariant() );
if( toSelect == wxNOT_FOUND )
m_variantListBox->SetSelection( 0 );
else
m_variantListBox->SetSelection( toSelect );
}
else
{
m_variantListBox->SetSelection( 0 );
}
if( !ADVANCED_CFG::GetCfg().m_EnableVariantsUI )
m_splitter_left->Unsplit( m_variantsPanel );
@@ -553,7 +567,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::SetupAllColumnProperties()
bool DIALOG_SYMBOL_FIELDS_TABLE::TransferDataToWindow()
{
if( !wxDialog::TransferDataFromWindow() )
if( !wxDialog::TransferDataToWindow() )
return false;
TOOL_MANAGER* toolMgr = m_parent->GetToolManager();
@@ -644,11 +658,11 @@ bool DIALOG_SYMBOL_FIELDS_TABLE::TransferDataFromWindow()
return true;
}
std::set<wxString> selectedVariantNames;
SCH_COMMIT commit( m_parent );
SCH_SHEET_PATH currentSheet = m_parent->GetCurrentSheet();
wxString currentVariant = m_parent->Schematic().GetCurrentVariant();
m_dataModel->ApplyData( commit, m_schSettings.m_TemplateFieldNames, selectedVariantNames );
m_dataModel->ApplyData( commit, m_schSettings.m_TemplateFieldNames, currentVariant );
if( !commit.Empty() )
{
@@ -676,7 +690,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::AddField( const wxString& aFieldName, const wxS
return;
}
m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser, getSelectedVariants() );
m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser, m_parent->Schematic().GetCurrentVariant() );
wxGridTableMessage msg( m_dataModel, wxGRIDTABLE_NOTIFY_COLS_APPENDED, 1 );
m_grid->ProcessTableMessage( msg );
@@ -1940,7 +1954,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::doApplyBomPreset( const BOM_PRESET& aPreset )
// Basically, we apply the BOM preset to the data model and then
// update our UI to reflect resulting the data model state, not the preset.
m_dataModel->ApplyBomPreset( aPreset, getSelectedVariants() );
m_dataModel->ApplyBomPreset( aPreset, m_parent->Schematic().GetCurrentVariant() );
// BOM Presets can add, but not remove, columns, so make sure the view controls
// grid has all of them before starting
@@ -2481,7 +2495,8 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnSchItemsChanged( SCHEMATIC& aSch, std::vector
for( SCH_FIELD& field : symbol->GetFields() )
AddField( field.GetCanonicalName(), field.GetName(), true, false, true );
m_dataModel->UpdateReferences( getSymbolReferences( symbol, allRefs ), getSelectedVariants() );
m_dataModel->UpdateReferences( getSymbolReferences( symbol, allRefs ),
m_parent->Schematic().GetCurrentVariant() );
}
else if( item->Type() == SCH_SHEET_T )
{
@@ -2498,7 +2513,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnSchItemsChanged( SCHEMATIC& aSch, std::vector
AddField( field.GetCanonicalName(), field.GetName(), true, false, true );
}
m_dataModel->UpdateReferences( refs, getSelectedVariants() );
m_dataModel->UpdateReferences( refs, m_parent->Schematic().GetCurrentVariant() );
}
}
@@ -2618,99 +2633,99 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onAddVariant( wxCommandEvent& aEvent )
void DIALOG_SYMBOL_FIELDS_TABLE::onDeleteVariant( wxCommandEvent& aEvent )
{
wxArrayInt selections;
int selection = m_variantListBox->GetSelection();
// An empty or default selection cannot be deleted.
if( ( m_variantListBox->GetSelections( selections ) == 0 ) || ( selections[0] == 0 ) )
if( ( selection == wxNOT_FOUND ) || ( selection == 0 ) )
{
wxBell();
return;
}
wxArrayString ctrlContents = m_variantListBox->GetStrings();
for( int selection : selections )
{
wxString variantName = m_variantListBox->GetString( selection );
ctrlContents.Remove( variantName );
m_parent->Schematic().DeleteVariant( variantName );
}
m_variantListBox->Set( ctrlContents );
wxString variantName = m_variantListBox->GetString( selection );
m_variantListBox->SetSelection( selection - 1 );
m_variantListBox->Delete( selection );
m_parent->Schematic().DeleteVariant( variantName );
}
void DIALOG_SYMBOL_FIELDS_TABLE::onRenameVariant( wxCommandEvent& aEvent )
{
wxArrayInt selections;
// wxArrayInt selections;
// Only allow renaming a single selection that is not the default.
if( ( m_variantListBox->GetSelections( selections ) != 1 ) || ( selections[0] == 0 ) )
{
wxBell();
return;
}
// // Only allow renaming a single selection that is not the default.
// if( ( m_variantListBox->GetSelections( selections ) != 1 ) || ( selections[0] == 0 ) )
// {
// wxBell();
// return;
// }
wxArrayString ctrlContents = m_variantListBox->GetStrings();
wxString oldVariantName = ctrlContents[selections[0]];
// wxArrayString ctrlContents = m_variantListBox->GetStrings();
// wxString oldVariantName = ctrlContents[selections[0]];
wxTextEntryDialog dlg( this, _( "Add new variant name:" ), _( "New Variant" ), oldVariantName,
wxOK | wxCANCEL | wxCENTER );
// wxTextEntryDialog dlg( this, _( "Add new variant name:" ), _( "New 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();
if( newVariantName.IsEmpty() || ( newVariantName == oldVariantName ) || ( newVariantName == ctrlContents[0] ) )
{
wxBell();
return;
}
// if( newVariantName.IsEmpty() || ( newVariantName == oldVariantName ) || ( newVariantName == ctrlContents[0] ) )
// {
// wxBell();
// return;
// }
ctrlContents.Remove( m_variantListBox->GetString( selections[0] ) );
ctrlContents.Add( newVariantName );
ctrlContents.Sort( SortVariantNames );
m_variantListBox->Set( ctrlContents );
// ctrlContents.Remove( m_variantListBox->GetString( selections[0] ) );
// ctrlContents.Add( newVariantName );
// ctrlContents.Sort( SortVariantNames );
// m_variantListBox->Set( ctrlContents );
}
void DIALOG_SYMBOL_FIELDS_TABLE::onVariantSelectionChange( wxCommandEvent& aEvent )
{
std::set<wxString> selectedVariants = getSelectedVariants();
m_dataModel->UpdateReferences( m_symbolsList, selectedVariants );
wxString currentVariant;
wxString selectedVariant = getSelectedVariant();
if( m_parent )
{
wxString selectedVariant = GetDefaultVariantName();
currentVariant = m_parent->Schematic().GetCurrentVariant();
// Selecting more than one variant in the schematic editor doesn't make any sense. Select the first
// variant in the table editor dialog as the variant to show in the schematic editor.
if( selectedVariants.size() >= 1 )
selectedVariant = *selectedVariants.cbegin();
m_parent->SetCurrentVariant( selectedVariant );
if( currentVariant != selectedVariant )
m_parent->SetCurrentVariant( selectedVariant );
}
}
std::set<wxString> DIALOG_SYMBOL_FIELDS_TABLE::getSelectedVariants() const
{
std::set<wxString> retv;
wxArrayInt selections;
if( m_variantListBox->GetSelections( selections ) )
if( currentVariant != selectedVariant )
{
for( int selection : selections )
if( m_grid->CommitPendingChanges( true ) )
{
if( selection == 0 )
continue;
m_dataModel->UpdateReferences( m_dataModel->GetReferenceList(), selectedVariant );
m_dataModel->RebuildRows();
retv.emplace( m_variantListBox->GetString( selection ) );
if( m_nbPages->GetSelection() == 1 )
PreviewRefresh();
else
m_grid->ForceRefresh();
syncBomFmtPresetSelection();
}
else
{
}
}
}
return retv;
wxString DIALOG_SYMBOL_FIELDS_TABLE::getSelectedVariant() const
{
wxString retv;
int selection = m_variantListBox->GetSelection();
if( ( selection == wxNOT_FOUND ) || ( m_variantListBox->GetString( selection ) == GetDefaultVariantName() ) )
return retv;
return m_variantListBox->GetString( selection );
}
@@ -144,7 +144,7 @@ private:
void onRenameVariant( wxCommandEvent& aEvent ) override;
void onVariantSelectionChange( wxCommandEvent& aEvent ) override;
std::set<wxString> getSelectedVariants() const;
wxString getSelectedVariant() const;
private:
std::map<wxString, BOM_PRESET> m_bomPresets;
@@ -138,7 +138,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
m_staticText9->Wrap( -1 );
bMargins2->Add( m_staticText9, 0, wxTOP|wxBOTTOM|wxLEFT, 2 );
m_variantListBox = new wxListBox( m_variantsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
m_variantListBox = new wxListBox( m_variantsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB|wxLB_SINGLE );
bMargins2->Add( m_variantListBox, 1, wxEXPAND|wxBOTTOM, 2 );
wxBoxSizer* bSizer14;
@@ -1053,7 +1053,7 @@
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="style">wxLB_NEEDED_SB|wxLB_SINGLE</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
+47 -31
View File
@@ -400,6 +400,10 @@ DIALOG_SYMBOL_PROPERTIES::DIALOG_SYMBOL_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH
evt->SetClientData( new VECTOR2I( 0, FDC_VALUE ) );
QueueEvent( evt );
// Remind user that they are editing the current variant.
if( !aParent->Schematic().GetCurrentVariant().IsEmpty() )
SetTitle( GetTitle() + wxS( " - " ) + aParent->Schematic().GetCurrentVariant() + _( " Variant" ) );
finishDialogSettings();
}
@@ -434,6 +438,10 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
if( !wxDialog::TransferDataToWindow() )
return false;
const SCHEMATIC& schematic = GetParent()->Schematic();
SCH_SHEET_PATH& sheetPath = schematic.CurrentSheet();
wxString variantName = schematic.GetCurrentVariant();
std::optional<SCH_SYMBOL_VARIANT> variant = m_symbol->GetVariant( sheetPath, variantName );
std::set<wxString> defined;
// Push a copy of each field into m_updateFields
@@ -443,8 +451,8 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
// change offset to be symbol-relative
field.Offset( -m_symbol->GetPosition() );
field.SetText( m_symbol->Schematic()->ConvertKIIDsToRefs( field.GetText() ) );
field.SetText( schematic.ConvertKIIDsToRefs( m_symbol->GetFieldText( field.GetName(), &sheetPath,
variantName ) ) );
defined.insert( field.GetName() );
m_fields->push_back( field );
@@ -452,7 +460,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
// Add in any template fieldnames not yet defined:
for( const TEMPLATE_FIELDNAME& templateFieldname :
GetParent()->Schematic().Settings().m_TemplateFieldNames.GetTemplateFieldNames() )
schematic.Settings().m_TemplateFieldNames.GetTemplateFieldNames() )
{
if( defined.count( templateFieldname.m_Name ) <= 0 )
{
@@ -471,7 +479,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
{
// Ensure symbol unit is the currently selected unit (mandatory in complex hierarchies)
// from the current sheet path, because it can be modified by previous calculations
m_symbol->SetUnit( m_symbol->GetUnitSelection( &GetParent()->GetCurrentSheet() ) );
m_symbol->SetUnit( m_symbol->GetUnitSelection( &sheetPath ) );
for( int ii = 1; ii <= m_symbol->GetUnitCount(); ii++ )
m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii, false ) );
@@ -539,10 +547,10 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
case SYM_MIRROR_Y: m_mirrorCtrl->SetSelection( 2 ); break;
}
m_cbExcludeFromSim->SetValue( m_symbol->GetExcludedFromSim() );
m_cbExcludeFromBom->SetValue( m_symbol->GetExcludedFromBOM() );
m_cbExcludeFromSim->SetValue( m_symbol->GetExcludedFromSim( &sheetPath, variantName ) );
m_cbExcludeFromBom->SetValue( m_symbol->GetExcludedFromBOM( &sheetPath, variantName ) );
m_cbExcludeFromBoard->SetValue( m_symbol->GetExcludedFromBoard() );
m_cbDNP->SetValue( m_symbol->GetDNP( &GetParent()->GetCurrentSheet() ) );
m_cbDNP->SetValue( m_symbol->GetDNP( &sheetPath, variantName ) );
if( m_part )
{
@@ -694,7 +702,10 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
SCH_COMMIT commit( GetParent() );
SCH_SCREEN* currentScreen = GetParent()->GetScreen();
SCH_SHEET_PATH currentSheet = GetParent()->Schematic().CurrentSheet();
wxString currentVariant = GetParent()->Schematic().GetCurrentVariant();
bool replaceOnCurrentScreen;
wxCHECK( currentScreen, false );
// This needs to be done before the LIB_ID is changed to prevent stale library symbols in
@@ -740,13 +751,9 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
// change all field positions from relative to absolute
for( SCH_FIELD& field : *m_fields )
{
field.Offset( m_symbol->GetPosition() );
field.SetText( m_symbol->Schematic()->ConvertRefsToKIIDs( field.GetText() ) );
}
SCH_FIELDS& fields = m_symbol->GetFields();
fields.clear();
int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
for( SCH_FIELD& field : *m_fields )
{
@@ -757,31 +764,40 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
else if( fieldName.IsEmpty() )
field.SetName( _( "untitled" ) );
fields.push_back( field );
}
// The const version of GetField() is used to prevent a new field from automatically being created.
const SCH_FIELD* existingField = m_symbol->GetField( fieldName );
SCH_FIELD* tmp;
int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
if( !existingField )
{
tmp = m_symbol->GetField( fieldName );
*tmp = field;
}
else
{
wxString defaultText = m_symbol->Schematic()->ConvertRefsToKIIDs( existingField->GetText() );
tmp = const_cast<SCH_FIELD*>( existingField );
*tmp = field;
if( !currentVariant.IsEmpty() )
{
// Restore the default field text for existing fields.
tmp->SetText( defaultText, &currentSheet );
tmp->SetText( m_symbol->Schematic()->ConvertRefsToKIIDs( field.GetText() ),
&currentSheet, currentVariant );
}
}
for( SCH_FIELD& field : fields )
{
if( !field.IsMandatory() )
field.SetOrdinal( ordinal++ );
}
// Reference has a specific initialization, depending on the current active sheet
// because for a given symbol, in a complex hierarchy, there are more than one
// reference.
m_symbol->SetRef( &GetParent()->GetCurrentSheet(), m_fields->GetField( FIELD_T::REFERENCE )->GetText() );
// Similar for Value and Footprint, except that the GUI behavior is that they are kept
// in sync between multiple instances.
m_symbol->SetValueFieldText( m_fields->GetField( FIELD_T::VALUE )->GetText() );
m_symbol->SetFootprintFieldText( m_fields->GetField( FIELD_T::FOOTPRINT )->GetText() );
m_symbol->SetExcludedFromSim( m_cbExcludeFromSim->IsChecked() );
m_symbol->SetExcludedFromBOM( m_cbExcludeFromBom->IsChecked() );
m_symbol->SetExcludedFromSim( m_cbExcludeFromSim->IsChecked(), &currentSheet, currentVariant );
m_symbol->SetExcludedFromBOM( m_cbExcludeFromBom->IsChecked(), &currentSheet, currentVariant );
m_symbol->SetExcludedFromBoard( m_cbExcludeFromBoard->IsChecked() );
m_symbol->SetDNP( m_cbDNP->IsChecked(), &GetParent()->GetCurrentSheet() );
m_symbol->SetDNP( m_cbDNP->IsChecked(), &currentSheet, currentVariant );
// Update any assignments
if( m_dataModel )
@@ -798,7 +814,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
// Keep fields other than the reference, include/exclude flags, and alternate pin assignements
// in sync in multi-unit parts.
m_symbol->SyncOtherUnits( GetParent()->GetCurrentSheet(), commit, nullptr );
m_symbol->SyncOtherUnits( currentSheet, commit, nullptr );
if( replaceOnCurrentScreen )
currentScreen->Append( m_symbol );
+80 -124
View File
@@ -30,9 +30,6 @@
#include "fields_data_model.h"
static wxString multipleValues = wxS( "<...>" );
/**
* Create a unique key for the data store by combining the #KIID_PATH from the
* #SCH_SHEET_PATH with the symbol's UUID.
@@ -201,7 +198,7 @@ const wxString FIELDS_EDITOR_GRID_DATA_MODEL::ITEM_NUMBER_VARIABLE = wxS( "${ITE
void FIELDS_EDITOR_GRID_DATA_MODEL::AddColumn( const wxString& aFieldName, const wxString& aLabel,
bool aAddedByUser, const std::set<wxString>& aVariantNames )
bool aAddedByUser, const wxString& aVariantName )
{
// Don't add a field twice
if( GetFieldNameCol( aFieldName ) != -1 )
@@ -210,13 +207,13 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::AddColumn( const wxString& aFieldName, const
m_cols.push_back( { aFieldName, aLabel, aAddedByUser, false, false } );
for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
updateDataStoreSymbolField( m_symbolsList[i], aFieldName, aVariantNames );
updateDataStoreSymbolField( m_symbolsList[i], aFieldName, aVariantName );
}
void FIELDS_EDITOR_GRID_DATA_MODEL::updateDataStoreSymbolField( const SCH_REFERENCE& aSymbolRef,
const wxString& aFieldName,
const std::set<wxString>& aVariantNames )
const wxString& aFieldName,
const wxString& aVariantName )
{
const SCH_SYMBOL* symbol = aSymbolRef.GetSymbol();
@@ -227,7 +224,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::updateDataStoreSymbolField( const SCH_REFERE
if( isAttribute( aFieldName ) )
{
m_dataStore[key][aFieldName] = getAttributeValue( *symbol, aFieldName, aVariantNames );
m_dataStore[key][aFieldName] = getAttributeValue( aSymbolRef, aFieldName, aVariantName );
}
else if( const SCH_FIELD* field = symbol->GetField( aFieldName ) )
{
@@ -237,24 +234,8 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::updateDataStoreSymbolField( const SCH_REFERE
return;
}
wxString value = symbol->Schematic()->ConvertKIIDsToRefs( field->GetText() );
for( const wxString& variantName : aVariantNames )
{
std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( aSymbolRef.GetSheetPath(), variantName );
if( !variant || !variant->m_Fields.contains( aFieldName ) )
continue;
if( value.IsEmpty() )
{
value = variant->m_Fields[aFieldName];
continue;
}
if( value != variant->m_Fields[aFieldName] )
value = multipleValues;
}
wxString value = symbol->Schematic()->ConvertKIIDsToRefs( field->GetText( &aSymbolRef.GetSheetPath(),
aVariantName ) );
m_dataStore[key][aFieldName] = value;
}
@@ -784,81 +765,52 @@ bool FIELDS_EDITOR_GRID_DATA_MODEL::isAttribute( const wxString& aFieldName )
}
wxString FIELDS_EDITOR_GRID_DATA_MODEL::getAttributeValue( const SCH_SYMBOL& aSymbol, const wxString& aAttributeName,
const std::set<wxString>& aVariantNames )
wxString FIELDS_EDITOR_GRID_DATA_MODEL::getAttributeValue( const SCH_REFERENCE& aRef, const wxString& aAttributeName,
const wxString& aVariantName )
{
wxString retv;
if( aAttributeName == wxS( "${DNP}" ) )
return aRef.GetSymbolDNP( aVariantName ) ? wxS( "1" ) : wxS( "0" );
auto getAttrString = [&]( const wxString aVariantName = wxEmptyString )->wxString
{
if( aAttributeName == wxS( "${DNP}" ) )
return aSymbol.GetDNP( nullptr, aVariantName ) ? wxS( "1" ) : wxS( "0" );
if( aAttributeName == wxS( "${EXCLUDE_FROM_BOARD}" ) )
return aRef.GetSymbolExcludedFromBoard() ? wxS( "1" ) : wxS( "0" );
if( aAttributeName == wxS( "${EXCLUDE_FROM_BOARD}" ) )
return aSymbol.GetExcludedFromBoard() ? wxS( "1" ) : wxS( "0" );
if( aAttributeName == wxS( "${EXCLUDE_FROM_BOM}" ) )
return aRef.GetSymbolExcludedFromBOM( aVariantName ) ? wxS( "1" ) : wxS( "0" );
if( aAttributeName == wxS( "${EXCLUDE_FROM_BOM}" ) )
return aSymbol.GetExcludedFromBOM( nullptr, aVariantName ) ? wxS( "1" ) : wxS( "0" );
if( aAttributeName == wxS( "${EXCLUDE_FROM_SIM}" ) )
return aRef.GetSymbolExcludedFromSim( aVariantName ) ? wxS( "1" ) : wxS( "0" );
if( aAttributeName == wxS( "${EXCLUDE_FROM_SIM}" ) )
return aSymbol.GetExcludedFromSim( nullptr, aVariantName ) ? wxS( "1" ) : wxS( "0" );
return wxS( "0" );
};
if( aVariantNames.empty() )
{
retv = getAttrString();
}
else
{
for( const wxString& variantName : aVariantNames )
{
if( retv.IsEmpty() )
{
retv = getAttrString( variantName );
continue;
}
if( retv != getAttrString( variantName ) )
retv = multipleValues;
}
}
return retv;
return wxS( "0" );
}
bool FIELDS_EDITOR_GRID_DATA_MODEL::setAttributeValue( SCH_SYMBOL& aSymbol,
bool FIELDS_EDITOR_GRID_DATA_MODEL::setAttributeValue( SCH_REFERENCE& aRef,
const wxString& aAttributeName,
const wxString& aValue,
const wxString& aVariantName )
{
if( aValue == multipleValues )
return false;
bool attrChanged = false;
bool newValue = aValue == wxS( "1" );
if( aAttributeName == wxS( "${DNP}" ) )
{
attrChanged = aSymbol.GetDNP( nullptr, aVariantName ) != newValue;
aSymbol.SetDNP( newValue, nullptr, aVariantName );
attrChanged = aRef.GetSymbolDNP( aVariantName ) != newValue;
aRef.SetSymbolDNP( newValue, aVariantName );
}
else if( aAttributeName == wxS( "${EXCLUDE_FROM_BOARD}" ) )
{
attrChanged = aSymbol.GetExcludedFromBoard() != newValue;
aSymbol.SetExcludedFromBoard( newValue );
attrChanged = aRef.GetSymbolExcludedFromBoard() != newValue;
aRef.SetSymbolExcludedFromBoard( newValue );
}
else if( aAttributeName == wxS( "${EXCLUDE_FROM_BOM}" ) )
{
attrChanged = aSymbol.GetExcludedFromBOM( nullptr, aVariantName ) != newValue;
aSymbol.SetExcludedFromBOM( newValue, nullptr, aVariantName );
attrChanged = aRef.GetSymbolExcludedFromBOM( aVariantName ) != newValue;
aRef.SetSymbolExcludedFromBOM( newValue, aVariantName );
}
else if( aAttributeName == wxS( "${EXCLUDE_FROM_SIM}" ) )
{
attrChanged = aSymbol.GetExcludedFromSim( nullptr, aVariantName ) != newValue;
aSymbol.SetExcludedFromSim( newValue, nullptr, aVariantName );
attrChanged = aRef.GetSymbolExcludedFromSim( aVariantName ) != newValue;
aRef.SetSymbolExcludedFromSim( newValue, aVariantName );
}
return attrChanged;
@@ -1065,7 +1017,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ExpandAfterSort()
void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyData( SCH_COMMIT& aCommit, TEMPLATES& aTemplateFieldnames,
std::set<wxString>& aVariantNames )
const wxString& aVariantName )
{
bool symbolModified = false;
std::unique_ptr<SCH_SYMBOL> symbolCopy;
@@ -1089,16 +1041,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyData( SCH_COMMIT& aCommit, TEMPLATES& a
// Attributes bypass the field logic, so handle them first
if( isAttribute( srcName ) )
{
if( aVariantNames.empty() )
{
symbolModified |= setAttributeValue( *symbol, srcName, srcValue );
}
else
{
for( const wxString& name : aVariantNames )
symbolModified |= setAttributeValue( *symbol, srcName, srcValue, name );
}
symbolModified |= setAttributeValue( m_symbolsList[i], srcName, srcValue, aVariantName );
continue;
}
@@ -1107,10 +1050,6 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyData( SCH_COMMIT& aCommit, TEMPLATES& a
if( IsGeneratedField( srcName ) )
continue;
// Don't change values in the case of multiple variants selected.
if( srcValue == multipleValues )
continue;
SCH_FIELD* destField = symbol->GetField( srcName );
if( destField && destField->IsPrivate() )
@@ -1148,36 +1087,10 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyData( SCH_COMMIT& aCommit, TEMPLATES& a
if( destField->GetId() == FIELD_T::REFERENCE )
continue;
wxString previousValue = destField->GetText();
wxString previousValue = destField->GetText( &m_symbolsList[i].GetSheetPath(), aVariantName );
if( aVariantNames.empty() )
{
destField->SetText( symbol->Schematic()->ConvertRefsToKIIDs( srcValue ) );
}
else
{
for( const wxString& variantName : aVariantNames )
{
std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_symbolsList[i].GetSheetPath(),
variantName );
if( !variant )
{
SCH_SYMBOL_VARIANT newVariant( variantName );
newVariant.m_Fields[srcName] = srcValue;
symbol->AddVariant( m_symbolsList[i].GetSheetPath(), newVariant );
symbolModified |= true;
}
else if( !variant->m_Fields.contains( srcName )
|| ( variant->m_Fields[srcName] != srcValue ) )
{
variant->m_Fields[srcName] = srcValue;
symbol->AddVariant( m_symbolsList[i].GetSheetPath(), *variant );
symbolModified |= true;
}
}
}
destField->SetText( symbol->Schematic()->ConvertRefsToKIIDs( srcValue ), &m_symbolsList[i].GetSheetPath(),
aVariantName );
if( !createField && ( previousValue != srcValue ) )
symbolModified = true;
@@ -1241,8 +1154,7 @@ int FIELDS_EDITOR_GRID_DATA_MODEL::GetDataWidth( int aCol )
}
void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyBomPreset( const BOM_PRESET& aPreset,
const std::set<wxString>& aVariantNames )
void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyBomPreset( const BOM_PRESET& aPreset, const wxString& aVariantName )
{
// Hide and un-group everything by default
for( size_t i = 0; i < m_cols.size(); i++ )
@@ -1270,7 +1182,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyBomPreset( const BOM_PRESET& aPreset,
// they won't be saved to the symbols anyway
if( col == -1 )
{
AddColumn( field.name, field.label, true, aVariantNames );
AddColumn( field.name, field.label, true, aVariantName );
col = GetFieldNameCol( field.name );
}
else
@@ -1480,7 +1392,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::RemoveReferences( const SCH_REFERENCE_LIST&
void FIELDS_EDITOR_GRID_DATA_MODEL::UpdateReferences( const SCH_REFERENCE_LIST& aRefs,
const std::set<wxString>& aVariantNames )
const wxString& aVariantName )
{
bool refListChanged = false;
@@ -1490,7 +1402,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::UpdateReferences( const SCH_REFERENCE_LIST&
// columns; we must have all fields in the symbol added to the data model at this point,
// and some of the data model columns may be variables that are not present in the symbol
for( const DATA_MODEL_COL& col : m_cols )
updateDataStoreSymbolField( ref, col.m_fieldName, aVariantNames );
updateDataStoreSymbolField( ref, col.m_fieldName, aVariantName );
if( !m_symbolsList.Contains( ref ) )
{
@@ -1502,3 +1414,47 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::UpdateReferences( const SCH_REFERENCE_LIST&
if( refListChanged )
m_symbolsList.SortBySymbolPtr();
}
bool FIELDS_EDITOR_GRID_DATA_MODEL::DeleteRows( size_t aPosition, size_t aNumRows )
{
size_t curNumRows = m_rows.size();
if( aPosition >= curNumRows )
{
wxFAIL_MSG( wxString::Format( wxT( "Called FIELDS_EDITOR_GRID_DATA_MODEL::DeleteRows(aPosition=%lu, "
"aNumRows=%lu)\nPosition value is invalid for present table with %lu rows" ),
(unsigned long) aPosition, (unsigned long) aNumRows,
(unsigned long) curNumRows ) );
return false;
}
if( aNumRows > curNumRows - aPosition )
{
aNumRows = curNumRows - aPosition;
}
if( aNumRows >= curNumRows )
{
m_rows.clear();
m_dataStore.clear();
}
else
{
const auto first = m_rows.begin() + aPosition;
std::vector<SCH_REFERENCE> dataMapRefs = first->m_Refs;
m_rows.erase( first, first + aNumRows );
for( const SCH_REFERENCE& ref : dataMapRefs )
m_dataStore.erase( ref.GetSheetPath().Path() );
}
if( GetView() )
{
wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aPosition, aNumRows );
GetView()->ProcessTableMessage( msg );
}
return true;
}
+13 -9
View File
@@ -153,7 +153,7 @@ public:
static const wxString ITEM_NUMBER_VARIABLE;
void AddColumn( const wxString& aFieldName, const wxString& aLabel, bool aAddedByUser,
const std::set<wxString>& aVariantNames );
const wxString& aVariantName );
void RemoveColumn( int aCol );
void RenameColumn( int aCol, const wxString& newName );
@@ -267,7 +267,7 @@ public:
void CollapseForSort();
void ExpandAfterSort();
void ApplyData( SCH_COMMIT& aCommit, TEMPLATES& aTemplateFieldnames, std::set<wxString>& aVariantNames );
void ApplyData( SCH_COMMIT& aCommit, TEMPLATES& aTemplateFieldnames, const wxString& aVariantName );
bool IsEdited() { return m_edited; }
@@ -319,14 +319,18 @@ public:
return m_cols[aCol].m_show;
}
void ApplyBomPreset( const BOM_PRESET& preset, const std::set<wxString>& aVariantNames );
void ApplyBomPreset( const BOM_PRESET& preset, const wxString& aVariantName );
BOM_PRESET GetBomSettings();
wxString Export( const BOM_FMT_PRESET& settings );
void AddReferences( const SCH_REFERENCE_LIST& aRefs );
void RemoveReferences( const SCH_REFERENCE_LIST& aRefs );
void RemoveSymbol( const SCH_SYMBOL& aSymbol );
void UpdateReferences( const SCH_REFERENCE_LIST& aRefs, const std::set<wxString>& aVariantNames );
void UpdateReferences( const SCH_REFERENCE_LIST& aRefs, const wxString& aVariantName );
bool DeleteRows( size_t aPosition = 0, size_t aNumRows = 1 ) override;
const SCH_REFERENCE_LIST& GetReferenceList() const { return m_symbolsList; }
private:
static bool cmp( const DATA_MODEL_ROW& lhGroup, const DATA_MODEL_ROW& rhGroup,
@@ -338,20 +342,20 @@ private:
// Helper functions to deal with translating wxGrid values to and from
// named field values like ${DNP}
bool isAttribute( const wxString& aFieldName );
wxString getAttributeValue( const SCH_SYMBOL&, const wxString& aAttributeName,
const std::set<wxString>& aVariantNames );
wxString getAttributeValue( const SCH_REFERENCE& aRef, const wxString& aAttributeName,
const wxString& aVariantNames );
/**
* Set the attribute value.
*
* @param aSymbol is the symbol to set the attribute.
* @param aReference is a reference to the symbol to set the attribute.
* @param aAttributeName is the name of the symbol attribute.
* @param aValue is the value to set the attribute.
* @param aVariantName is an optional variant name to set the variant attribute.
* @retval true if the symbol attribute value has changed.
* @retval false if the symbol attribute has **not** changed.
*/
bool setAttributeValue( SCH_SYMBOL& aSymbol, const wxString& aAttributeName, const wxString& aValue,
bool setAttributeValue( SCH_REFERENCE& aRef, const wxString& aAttributeName, const wxString& aValue,
const wxString& aVariantName = wxEmptyString );
/* Helper function to get the resolved field value.
@@ -363,7 +367,7 @@ private:
void Sort();
void updateDataStoreSymbolField( const SCH_REFERENCE& aSymbolRef, const wxString& aFieldName,
const std::set<wxString>& aVariantNames );
const wxString& aVariantName );
protected:
/**
+3
View File
@@ -693,6 +693,9 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
screen->MigrateSimModels();
Schematic().LoadVariants();
UpdateVariantSelectionCtrl( Schematic().GetVariantNamesForUI() );
}
// After the schematic is successfully loaded, we load the drawing sheet.
+2 -1
View File
@@ -356,7 +356,8 @@ public:
return GetReferenceField().GetText();
}
const wxString GetValue( bool aResolve, const SCH_SHEET_PATH* aPath, bool aAllowExtraText ) const override
const wxString GetValue( bool aResolve, const SCH_SHEET_PATH* aPath, bool aAllowExtraText,
const wxString& aVariantName = wxEmptyString ) const override
{
return GetValueField().GetText();
}
+6 -1
View File
@@ -472,6 +472,9 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
wxPoint canvas_pos = GetCanvas()->GetScreenPosition();
hierarchy_pane.FloatingPosition( canvas_pos.x + 10, canvas_pos.y + 10 );
if( ADVANCED_CFG::GetCfg().m_EnableVariantsUI )
Bind( wxEVT_CHOICE, &SCH_EDIT_FRAME::onVariantSelected, this );
Bind( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, &SCH_EDIT_FRAME::onCloseSymbolDiffDialog, this );
Bind( EDA_EVT_CLOSE_ERC_DIALOG, &SCH_EDIT_FRAME::onCloseErcDialog, this );
Bind( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, &SCH_EDIT_FRAME::onCloseSymbolFieldsTableDialog, this );
@@ -3041,7 +3044,7 @@ void SCH_EDIT_FRAME::RemoveVariant()
wxString variantName = dlg.GetStringSelection();
if( variantName.IsEmpty() || ( m_currentVariantCtrl->FindString( variantName ) != wxNOT_FOUND ) )
if( variantName.IsEmpty() )
return;
Schematic().DeleteVariant( variantName );
@@ -3067,6 +3070,8 @@ void SCH_EDIT_FRAME::RemoveVariant()
SetCurrentVariant( wxEmptyString );
}
}
GetCanvas()->Refresh();
}
+130 -9
View File
@@ -188,17 +188,64 @@ wxString SCH_FIELD::GetShownName() const
}
wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth ) const
wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth,
const wxString& aVariantName ) const
{
// Use local depth counter so each text element starts fresh
int depth = 0;
wxString variantName;
std::function<bool( wxString* )> libSymbolResolver = [&]( wxString* token ) -> bool
{
LIB_SYMBOL* symbol = static_cast<LIB_SYMBOL*>( m_parent );
return symbol->ResolveTextVar( token, depth + 1 );
};
if( SCHEMATIC* schematic = Schematic() )
variantName = schematic->GetCurrentVariant();
std::function<bool( wxString* )> symbolResolver = [&]( wxString* token ) -> bool
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( m_parent );
return symbol->ResolveTextVar( aPath, token, depth + 1 );
};
wxString text = getUnescapedText( aPath, variantName );
std::function<bool( wxString* )> schematicResolver = [&]( wxString* token ) -> bool
{
if( !aPath )
return false;
if( SCHEMATIC* schematic = Schematic() )
return schematic->ResolveTextVar( aPath, token, depth + 1 );
return false;
};
std::function<bool( wxString* )> sheetResolver = [&]( wxString* token ) -> bool
{
if( !aPath )
return false;
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_parent );
SCHEMATIC* schematic = Schematic();
SCH_SHEET_PATH path = *aPath;
path.push_back( sheet );
bool retval = sheet->ResolveTextVar( &path, token, depth + 1 );
if( schematic )
retval |= schematic->ResolveTextVar( &path, token, depth + 1 );
return retval;
};
std::function<bool( wxString* )> labelResolver = [&]( wxString* token ) -> bool
{
if( !aPath )
return false;
SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( m_parent );
return label->ResolveTextVar( aPath, token, depth + 1 );
};
wxString text = getUnescapedText( aPath, aVariantName );
if( IsNameShown() && aAllowExtraText )
text = GetShownName() << wxS( ": " ) << text;
@@ -222,10 +269,13 @@ wxString SCH_FIELD::GetShownText( bool aAllowExtraText, int aDepth ) const
if( SCHEMATIC* schematic = Schematic() )
{
const SCH_SHEET_PATH& currentSheet = schematic->CurrentSheet();
wxString variantName = schematic->GetCurrentVariant();
wxLogTrace( traceSchFieldRendering,
"GetShownText (no path arg): field=%s, current sheet path='%s', size=%zu, empty=%d", GetName(),
currentSheet.Path().AsString(), currentSheet.size(), currentSheet.empty() ? 1 : 0 );
return GetShownText( &currentSheet, aAllowExtraText, aDepth );
"GetShownText (no path arg): field=%s, current sheet path='%s', variant='%s', size=%zu, empty=%d",
GetName(), currentSheet.Path().AsString(), variantName, currentSheet.size(),
currentSheet.empty() ? 1 : 0 );
return GetShownText( &currentSheet, aAllowExtraText, aDepth, variantName );
}
else
return GetShownText( nullptr, aAllowExtraText, aDepth );
@@ -1035,6 +1085,77 @@ void SCH_FIELD::SetText( const wxString& aText )
}
void SCH_FIELD::SetText( const wxString& aText, const SCH_SHEET_PATH* aPath, const wxString& aVariantName )
{
wxCHECK( aPath && m_parent, /* void */ );
// Don't allow modification of text value of generated fields.
if( m_isGeneratedField )
return;
wxString tmp = aText;
if( IsMandatory() )
tmp = aText.Strip( wxString::both ) ;
switch( m_parent->Type() )
{
case SCH_SYMBOL_T:
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( m_parent );
wxCHECK( symbol, /* void */ );
symbol->SetFieldText( GetName(), aText, aPath, aVariantName );
break;
}
case SCH_SHEET_T:
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_parent );
wxCHECK( sheet, /* void */ );
sheet->SetFieldText( GetName(), aText, aPath, aVariantName );
break;
}
default:
SCH_FIELD::SetText( aText );
break;
}
}
wxString SCH_FIELD::GetText( const SCH_SHEET_PATH* aPath, const wxString& aVariantName ) const
{
wxString retv;
wxCHECK( aPath && m_parent, retv );
switch( m_parent->Type() )
{
case SCH_SYMBOL_T:
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( m_parent );
wxCHECK( symbol, retv );
retv = symbol->GetFieldText( GetName(), aPath, aVariantName );
break;
}
case SCH_SHEET_T:
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_parent );
wxCHECK( sheet, retv );
retv = sheet->GetFieldText( GetName(), aPath, aVariantName );
break;
}
default:
retv = GetText();
break;
}
return retv;
}
wxString SCH_FIELD::GetName( bool aUseDefaultName ) const
{
if( m_parent && m_parent->IsType( labelTypes ) )
@@ -1160,7 +1281,7 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS&
wxString text;
if( Schematic() )
text = GetShownText( &Schematic()->CurrentSheet(), true );
text = GetShownText( &Schematic()->CurrentSheet(), true, 0, Schematic()->GetCurrentVariant() );
else
text = GetShownText( true );
+8 -1
View File
@@ -113,6 +113,12 @@ public:
void SetText( const wxString& aText ) override;
void SetText( const wxString& aText, const SCH_SHEET_PATH* aPath, const wxString& aVariantName = wxEmptyString );
virtual const wxString& GetText() const override { return EDA_TEXT::GetText(); }
wxString GetText( const SCH_SHEET_PATH* aPath, const wxString& aVariantName = wxEmptyString ) const;
FIELD_T GetId() const { return m_id; }
int GetOrdinal() const
@@ -131,7 +137,8 @@ public:
* with the ${} stripped.
*/
wxString GetShownName() const;
wxString GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth = 0 ) const;
wxString GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth = 0,
const wxString& aVariantName = wxEmptyString ) const;
wxString GetShownText( bool aAllowExtraText, int aDepth = 0 ) const override;
@@ -3377,12 +3377,35 @@ SCH_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseSchematicSymbol()
case T_field:
{
NeedSYMBOL();
wxString fieldName = FromUTF8();
NeedRIGHT();
NeedSYMBOL();
wxString fieldValue = FromUTF8();
NeedRIGHT();
wxString fieldName;
wxString fieldValue;
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
if( token != T_LEFT )
Expecting( T_LEFT );
token = NextTok();
switch( token )
{
case T_name:
NeedSYMBOL();
fieldName = FromUTF8();
NeedRIGHT();
break;
case T_value:
NeedSYMBOL();
fieldValue = FromUTF8();
NeedRIGHT();
break;
default:
Expecting( "name or value" );
}
}
variant.m_Fields[fieldName] = fieldValue;
break;
}
@@ -3394,7 +3417,6 @@ SCH_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseSchematicSymbol()
instance.m_Variants[variant.m_Name] = variant;
}
NeedRIGHT();
break;
}
@@ -3806,12 +3828,35 @@ SCH_SHEET* SCH_IO_KICAD_SEXPR_PARSER::parseSheet()
case T_field:
{
NeedSYMBOL();
wxString fieldName = FromUTF8();
NeedRIGHT();
NeedSYMBOL();
wxString fieldValue = FromUTF8();
NeedRIGHT();
wxString fieldName;
wxString fieldValue;
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
if( token != T_LEFT )
Expecting( T_LEFT );
token = NextTok();
switch( token )
{
case T_name:
NeedSYMBOL();
fieldName = FromUTF8();
NeedRIGHT();
break;
case T_value:
NeedSYMBOL();
fieldValue = FromUTF8();
NeedRIGHT();
break;
default:
Expecting( "name or value" );
}
}
variant.m_Fields[fieldName] = fieldValue;
break;
}
@@ -3823,7 +3868,6 @@ SCH_SHEET* SCH_IO_KICAD_SEXPR_PARSER::parseSheet()
instance.m_Variants[variant.m_Name] = variant;
}
NeedRIGHT();
break;
}
+16 -8
View File
@@ -2660,19 +2660,25 @@ void SCH_PAINTER::draw( const SCH_SYMBOL* aSymbol, int aLayer )
std::optional<SCH_SHEET_PATH> optSheetPath;
wxString variantName;
if( m_schematic )
{
optSheetPath = m_schematic->CurrentSheet();
variantName = m_schematic->GetCurrentVariant();
wxLogTrace( traceSchPainter,
"SCH_PAINTER::draw symbol %s: Current sheet path='%s', size=%zu, empty=%d",
aSymbol->m_Uuid.AsString(),
optSheetPath->Path().AsString(),
optSheetPath->size(),
optSheetPath->empty() ? 1 : 0 );
"SCH_PAINTER::draw symbol %s: Current sheet path='%s', variant='%s', size=%zu, empty=%d",
aSymbol->m_Uuid.AsString(),
variantName.IsEmpty() ? GetDefaultVariantName() : variantName,
optSheetPath->Path().AsString(),
optSheetPath->size(),
optSheetPath->empty() ? 1 : 0 );
}
bool DNP = aSymbol->GetDNP( nullptr );
bool markExclusion = eeconfig()->m_Appearance.mark_sim_exclusions && aSymbol->GetExcludedFromSim( nullptr );
SCH_SHEET_PATH* sheetPath = optSheetPath ? &optSheetPath.value() : nullptr;
bool DNP = aSymbol->GetDNP( sheetPath, variantName );
bool markExclusion = eeconfig()->m_Appearance.mark_sim_exclusions && aSymbol->GetExcludedFromSim( sheetPath,
variantName );
if( m_schSettings.IsPrinting() && drawingShadows )
return;
@@ -3260,8 +3266,10 @@ void SCH_PAINTER::draw( const SCH_DIRECTIVE_LABEL* aLabel, int aLayer, bool aDim
void SCH_PAINTER::draw( const SCH_SHEET* aSheet, int aLayer )
{
SCH_SHEET_PATH currentPath = aSheet->Schematic()->CurrentSheet();
wxString currentVariant = aSheet->Schematic()->GetCurrentVariant();
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
bool DNP = aSheet->GetDNP();
bool DNP = aSheet->GetDNP( &currentPath, currentVariant );
bool markExclusion = eeconfig()->m_Appearance.mark_sim_exclusions
&& aSheet->GetExcludedFromSim();
+64
View File
@@ -935,6 +935,38 @@ wxString SCH_REFERENCE_LIST::Shorthand( std::vector<SCH_REFERENCE> aList,
}
bool SCH_REFERENCE::GetSymbolDNP( const wxString& aVariant ) const
{
wxCHECK( m_rootSymbol, false );
return m_rootSymbol->GetDNP( &m_sheetPath, aVariant );
}
bool SCH_REFERENCE::GetSymbolExcludedFromBOM( const wxString& aVariant ) const
{
wxCHECK( m_rootSymbol, false );
return m_rootSymbol->GetExcludedFromBOM( &m_sheetPath, aVariant );
}
bool SCH_REFERENCE::GetSymbolExcludedFromSim( const wxString& aVariant ) const
{
wxCHECK( m_rootSymbol, false );
return m_rootSymbol->GetExcludedFromSim( &m_sheetPath, aVariant );
}
bool SCH_REFERENCE::GetSymbolExcludedFromBoard() const
{
wxCHECK( m_rootSymbol, false );
return m_rootSymbol->GetExcludedFromBoard();
}
wxString SCH_REFERENCE::formatRefStr( int aNumber ) const
{
// To avoid a risk of duplicate, for power symbols the ref number is 0nnn instead of nnn.
@@ -946,6 +978,38 @@ wxString SCH_REFERENCE::formatRefStr( int aNumber ) const
}
void SCH_REFERENCE::SetSymbolDNP( bool aEnable, const wxString& aVariant )
{
wxCHECK( m_rootSymbol, /* void */ );
m_rootSymbol->SetDNP( aEnable, &m_sheetPath, aVariant );
}
void SCH_REFERENCE::SetSymbolExcludedFromBOM( bool aEnable, const wxString& aVariant )
{
wxCHECK( m_rootSymbol, /* void */ );
m_rootSymbol->SetExcludedFromBOM( aEnable, &m_sheetPath, aVariant );
}
void SCH_REFERENCE::SetSymbolExcludedFromSim( bool aEnable, const wxString& aVariant )
{
wxCHECK( m_rootSymbol, /* void */ );
m_rootSymbol->SetExcludedFromSim( aEnable, &m_sheetPath, aVariant );
}
void SCH_REFERENCE::SetSymbolExcludedFromBoard( bool aEnable )
{
wxCHECK( m_rootSymbol, /* void */ );
m_rootSymbol->SetExcludedFromBoard( aEnable );
}
#if defined( DEBUG )
void SCH_REFERENCE_LIST::Show( const char* aPrefix )
{
+10
View File
@@ -231,6 +231,16 @@ public:
m_numRefStr = formatRefStr( aNum );
}
bool GetSymbolDNP( const wxString& aVariant = wxEmptyString ) const;
bool GetSymbolExcludedFromBOM( const wxString& aVariant = wxEmptyString ) const;
bool GetSymbolExcludedFromSim( const wxString& aVariant = wxEmptyString ) const;
bool GetSymbolExcludedFromBoard() const;
void SetSymbolDNP( bool aEnable, const wxString& aVariant = wxEmptyString );
void SetSymbolExcludedFromBOM( bool aEnable, const wxString& aVariant = wxEmptyString );
void SetSymbolExcludedFromSim( bool aEnable, const wxString& aVariant = wxEmptyString );
void SetSymbolExcludedFromBoard( bool aEnable );
private:
wxString formatRefStr( int aNumber ) const;
+354 -7
View File
@@ -392,6 +392,18 @@ const SCH_FIELD* SCH_SHEET::GetField( FIELD_T aFieldType ) const
}
SCH_FIELD* SCH_SHEET::GetField( const wxString& aFieldName )
{
return FindField( m_fields, aFieldName );
}
const SCH_FIELD* SCH_SHEET::GetField( const wxString& aFieldName ) const
{
return FindField( m_fields, aFieldName );
}
int SCH_SHEET::GetNextFieldOrdinal() const
{
return NextFieldOrdinal( m_fields );
@@ -407,6 +419,114 @@ void SCH_SHEET::SetFields( const std::vector<SCH_FIELD>& aFields )
}
void SCH_SHEET::AddOptionalField( const SCH_FIELD& aField )
{
SCH_FIELD* field = GetField( aField.GetId() );
if( ( aField.GetId() == FIELD_T::SHEET_FILENAME ) || ( aField.GetId() == FIELD_T::SHEET_NAME ) )
return;
if( field )
*field = aField;
else
m_fields.emplace_back( aField );
}
void SCH_SHEET::SetFieldText( const wxString& aFieldName, const wxString& aFieldText, const SCH_SHEET_PATH* aPath,
const wxString& aVariantName )
{
wxCHECK( !aFieldName.IsEmpty(), /* void */ );
SCH_FIELD* field = GetField( aFieldName );
wxCHECK( field, /* void */ );
switch( field->GetId() )
{
case FIELD_T::SHEET_FILENAME:
{
// File names are stored using unix separators.
wxString tmp = aFieldText;
tmp.Replace( wxT( "\\" ), wxT( "/" ) );
GetField( FIELD_T::SHEET_FILENAME )->SetText( tmp );
break;
}
case FIELD_T::SHEET_NAME:
field->SetText( aFieldText );
break;
default:
if( aFieldText != field->GetText( aPath ) ) // Do not set the variant unless it's different than the default.
{
if( aVariantName.IsEmpty() )
{
field->SetText( aFieldText );
}
else
{
SCH_SHEET_INSTANCE* instance = getInstance( *aPath );
wxCHECK( instance, /* void */ );
if( instance->m_Variants.contains( aVariantName ) )
{
instance->m_Variants[aVariantName].m_Fields[aFieldName] = aFieldText;
}
else
{
SCH_SHEET_VARIANT newVariant( aVariantName );
newVariant.InitializeAttributes( *this );
newVariant.m_Fields[aFieldName] = aFieldText;
instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
}
}
}
break;
}
}
wxString SCH_SHEET::GetFieldText( const wxString& aFieldName, const SCH_SHEET_PATH* aPath,
const wxString& aVariantName ) const
{
wxCHECK( !aFieldName.IsEmpty(), wxEmptyString );
const SCH_FIELD* field = GetField( aFieldName );
wxCHECK( field, wxEmptyString );
switch( field->GetId() )
{
case FIELD_T::REFERENCE:
case FIELD_T::FOOTPRINT:
return field->GetText();
break;
default:
if( aVariantName.IsEmpty() )
{
return field->GetText();
}
else
{
const SCH_SHEET_INSTANCE* instance = getInstance( *aPath );
if( instance->m_Variants.contains( aVariantName )
&& instance->m_Variants.at( aVariantName ).m_Fields.contains( aFieldName ) )
return instance->m_Variants.at( aVariantName ).m_Fields.at( aFieldName );
}
break;
}
return field->GetText();
}
void SCH_SHEET::AddPin( SCH_SHEET_PIN* aSheetPin )
{
wxASSERT( aSheetPin != nullptr );
@@ -1313,7 +1433,16 @@ void SCH_SHEET::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS&
for( SCH_FIELD& field : m_fields )
field.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
if( GetDNP() )
SCH_SHEET_PATH instance;
wxString variantName;
if( Schematic() )
{
instance = Schematic()->CurrentSheet();
variantName = Schematic()->GetCurrentVariant();
}
if( GetDNP( &instance, variantName) )
{
COLOR_SETTINGS* colors = ::GetColorSettings( DEFAULT_THEME );
BOX2I bbox = GetBodyBoundingBox();
@@ -1466,6 +1595,30 @@ bool SCH_SHEET::getInstance( SCH_SHEET_INSTANCE& aInstance, const KIID_PATH& aSh
}
SCH_SHEET_INSTANCE* SCH_SHEET::getInstance( const KIID_PATH& aSheetPath )
{
for( SCH_SHEET_INSTANCE& instance : m_instances )
{
if( instance.m_Path == aSheetPath )
return &instance;
}
return nullptr;
}
const SCH_SHEET_INSTANCE* SCH_SHEET::getInstance( const KIID_PATH& aSheetPath ) const
{
for( const SCH_SHEET_INSTANCE& instance : m_instances )
{
if( instance.m_Path == aSheetPath )
return &instance;
}
return nullptr;
}
bool SCH_SHEET::HasRootInstance() const
{
for( const SCH_SHEET_INSTANCE& instance : m_instances )
@@ -1674,39 +1827,233 @@ double SCH_SHEET::Similarity( const SCH_ITEM& aOther ) const
}
void SCH_SHEET::AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SHEET_VARIANT& aVariant )
{
SCH_SHEET_INSTANCE* instance = getInstance( aInstance );
// The instance path must already exist.
if( !instance )
return;
instance->m_Variants.insert( std::make_pair( aVariant.m_Name, aVariant ) );
}
void SCH_SHEET::DeleteVariant( const SCH_SHEET_PATH& aInstance, const wxString& aVariantName )
{
SCH_SHEET_INSTANCE instance;
// The instance path must already exist.
if( !getInstance( instance, aInstance.Path() ) || !instance.m_Variants.contains( aVariantName ) )
return;
instance.m_Variants.erase( aVariantName );
}
void SCH_SHEET::SetDNP( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
{
if( !aInstance || aVariantName.IsEmpty() )
{
m_DNP = aEnable;
return;
}
SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
wxCHECK_MSG( instance, /* void */,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( aVariantName.IsEmpty() )
{
m_DNP = aEnable;
}
else
{
if( instance->m_Variants.contains( aVariantName ) && ( aEnable != instance->m_Variants[aVariantName].m_DNP ) )
{
instance->m_Variants[aVariantName].m_DNP = aEnable;
}
else
{
SCH_SHEET_VARIANT variant( aVariantName );
variant.InitializeAttributes( *this );
variant.m_DNP = aEnable;
AddVariant( *aInstance, variant );
}
}
}
bool SCH_SHEET::GetDNP( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
{
if( !aInstance || aVariantName.IsEmpty() )
return m_DNP;
SCH_SHEET_INSTANCE instance;
if( !getInstance( instance, aInstance->Path() ) )
return m_DNP;
if( aVariantName.IsEmpty() )
return m_DNP;
else if( instance.m_Variants.contains( aVariantName ) )
return instance.m_Variants[aVariantName].m_DNP;
// If the variant has not been defined, return the default DNP setting.
return m_DNP;
}
bool SCH_SHEET::GetDNPProp() const
{
return GetDNP( nullptr, Schematic()->GetCurrentVariant() );
return GetDNP( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
void SCH_SHEET::SetDNPProp( bool aEnable )
{
SetDNP( aEnable, nullptr, Schematic()->GetCurrentVariant() );
SetDNP( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
void SCH_SHEET::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
{
if( !aInstance || aVariantName.IsEmpty() )
{
m_excludedFromSim = aEnable;
return;
}
SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
wxCHECK_MSG( instance, /* void */,
wxString::Format( wxS( "Cannot get m_excludedFromSim attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( aVariantName.IsEmpty() )
{
m_excludedFromSim = aEnable;
}
else
{
if( instance->m_Variants.contains( aVariantName )
&& ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromSim ) )
{
instance->m_Variants[aVariantName].m_ExcludedFromSim = aEnable;
}
else
{
SCH_SHEET_VARIANT variant( aVariantName );
variant.InitializeAttributes( *this );
variant.m_ExcludedFromSim = aEnable;
AddVariant( *aInstance, variant );
}
}
}
bool SCH_SHEET::GetExcludedFromSim( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
{
if( !aInstance || aVariantName.IsEmpty() )
return m_excludedFromSim;
SCH_SHEET_INSTANCE instance;
if( !getInstance( instance, aInstance->Path() ) )
return m_excludedFromSim;
if( aVariantName.IsEmpty() )
return m_excludedFromSim;
else if( instance.m_Variants.contains( aVariantName ) )
return instance.m_Variants[aVariantName].m_ExcludedFromSim;
// If the variant has not been defined, return the default DNP setting.
return m_excludedFromSim;
}
bool SCH_SHEET::GetExcludedFromSimProp() const
{
return GetExcludedFromSim( nullptr, Schematic()->GetCurrentVariant() );
return GetExcludedFromSim( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
void SCH_SHEET::SetExcludedFromSimProp( bool aEnable )
{
SetExcludedFromSim( aEnable, nullptr, Schematic()->GetCurrentVariant() );
SetExcludedFromSim( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
void SCH_SHEET::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
{
if( !aInstance || aVariantName.IsEmpty() )
{
m_excludedFromBOM = aEnable;
return;
}
SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
wxCHECK_MSG( instance, /* void */,
wxString::Format( wxS( "Cannot get m_excludedFromBOM attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( aVariantName.IsEmpty() )
{
m_excludedFromBOM = aEnable;
}
else
{
if( instance->m_Variants.contains( aVariantName )
&& ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromBOM ) )
{
instance->m_Variants[aVariantName].m_ExcludedFromBOM = aEnable;
}
else
{
SCH_SHEET_VARIANT variant( aVariantName );
variant.InitializeAttributes( *this );
variant.m_ExcludedFromBOM = aEnable;
AddVariant( *aInstance, variant );
}
}
}
bool SCH_SHEET::GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
{
if( !aInstance || aVariantName.IsEmpty() )
return m_excludedFromBOM;
SCH_SHEET_INSTANCE instance;
if( !getInstance( instance, aInstance->Path() ) )
return m_excludedFromBOM;
if( aVariantName.IsEmpty() )
return m_excludedFromBOM;
else if( instance.m_Variants.contains( aVariantName ) )
return instance.m_Variants[aVariantName].m_ExcludedFromBOM;
// If the variant has not been defined, return the default DNP setting.
return m_excludedFromBOM;
}
bool SCH_SHEET::GetExcludedFromBOMProp() const
{
return GetExcludedFromBOM( nullptr, Schematic()->GetCurrentVariant() );
return GetExcludedFromBOM( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
void SCH_SHEET::SetExcludedFromBOMProp( bool aEnable )
{
SetExcludedFromBOM( aEnable, nullptr, Schematic()->GetCurrentVariant() );
SetExcludedFromBOM( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
+43 -20
View File
@@ -95,6 +95,16 @@ public:
SCH_FIELD* GetField( FIELD_T aFieldType );
const SCH_FIELD* GetField( FIELD_T aFieldNdx ) const;
/**
* Return a field in this sheet.
*
* @param aFieldName is the canonical name of the field.
*
* @return Both non-const and const versions return nullptr if the field is not found.
*/
SCH_FIELD* GetField( const wxString& aFieldName );
const SCH_FIELD* GetField( const wxString& aFieldName ) const;
/**
* Return the next ordinal for a user field for this sheet
*/
@@ -107,6 +117,24 @@ public:
*/
void SetFields( const std::vector<SCH_FIELD>& aFields );
/**
* Add an optional @aField to the list of fields.
*
* If @aField already exists in the field list, it replaces the existing field. If @aField does not exist,
* it is added to the field list.
*
* @note This has no affect if @aField is the sheet file name or sheet name fields.
*
* @param aField is the field to add.
*/
void AddOptionalField( const SCH_FIELD& aField );
void SetFieldText( const wxString& aFieldName, const wxString& aFieldText, const SCH_SHEET_PATH* aPath = nullptr,
const wxString& aVariantName = wxEmptyString );
wxString GetFieldText( const wxString& aFieldName, const SCH_SHEET_PATH* aPath = nullptr,
const wxString& aVariantName = wxEmptyString ) const;
wxString GetShownName( bool aAllowExtraText ) const
{
return GetField( FIELD_T::SHEET_NAME )->GetShownText( aAllowExtraText );
@@ -409,16 +437,9 @@ public:
* Set or clear the exclude from simulation flag.
*/
void SetExcludedFromSim( bool aExcludeFromSim, const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) override
{
m_excludedFromSim = aExcludeFromSim;
}
const wxString& aVariantName = wxEmptyString ) override;
bool GetExcludedFromSim( const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) const override
{
return m_excludedFromSim;
}
const wxString& aVariantName = wxEmptyString ) const override;
bool GetExcludedFromSimProp() const;
void SetExcludedFromSimProp( bool aEnable );
@@ -427,16 +448,9 @@ public:
* Set or clear the exclude from schematic bill of materials flag.
*/
void SetExcludedFromBOM( bool aExcludeFromBOM, const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) override
{
m_excludedFromBOM = aExcludeFromBOM;
}
const wxString& aVariantName = wxEmptyString ) override;
bool GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) const override
{
return m_excludedFromBOM;
}
const wxString& aVariantName = wxEmptyString ) const override;
bool GetExcludedFromBOMProp() const;
void SetExcludedFromBOMProp( bool aEnable );
@@ -451,9 +465,9 @@ public:
* Set or clear the 'Do Not Populate' flags
*/
bool GetDNP( const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) const override { return m_DNP; }
const wxString& aVariantName = wxEmptyString ) const override;
void SetDNP( bool aDNP, const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) override { m_DNP = aDNP; }
const wxString& aVariantName = wxEmptyString ) override;
bool GetDNPProp() const;
void SetDNPProp( bool aEnable );
@@ -509,6 +523,9 @@ public:
void AddInstance( const SCH_SHEET_INSTANCE& aInstance );
void AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SHEET_VARIANT& aVariant );
void DeleteVariant( const SCH_SHEET_PATH& aInstance, const wxString& aVariantName );
/**
* Check if the instance data of this sheet has any changes compared to \a aOther.
*
@@ -581,6 +598,12 @@ protected:
bool getInstance( SCH_SHEET_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
bool aTestFromEnd = false ) const;
SCH_SHEET_INSTANCE* getInstance( const KIID_PATH& aPath );
const SCH_SHEET_INSTANCE* getInstance( const KIID_PATH& aPath ) const;
SCH_SHEET_INSTANCE* getInstance( const SCH_SHEET_PATH& aPath ) { return getInstance( aPath.Path() ); }
const SCH_SHEET_INSTANCE* getInstance( const SCH_SHEET_PATH& aPath ) const { return getInstance( aPath.Path() ); }
/**
* Renumber the sheet pins in the sheet.
*
+8
View File
@@ -103,6 +103,14 @@ void SCH_SYMBOL_VARIANT::InitializeAttributes( const SCH_SYMBOL& aSymbol )
}
void SCH_SHEET_VARIANT::InitializeAttributes( const SCH_SHEET& aSheet )
{
m_DNP = aSheet.GetDNP();
m_ExcludedFromBOM = aSheet.GetExcludedFromBOM();
m_ExcludedFromSim = aSheet.GetExcludedFromSim();
}
namespace std
{
size_t hash<SCH_SHEET_PATH>::operator()( const SCH_SHEET_PATH& path ) const
+3 -3
View File
@@ -129,13 +129,13 @@ struct SCH_SYMBOL_INSTANCE
class SCH_SHEET_VARIANT : public VARIANT
{
public:
SCH_SHEET_VARIANT() :
VARIANT()
SCH_SHEET_VARIANT( const wxString& aName = wxEmptyString ) :
VARIANT( aName )
{}
virtual ~SCH_SHEET_VARIANT() = default;
void InitializeAttributes( const SCH_SHEET& aSymbol );
void InitializeAttributes( const SCH_SHEET& aSheet );
};
+197 -104
View File
@@ -713,6 +713,100 @@ void SCH_SYMBOL::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
}
void SCH_SYMBOL::SetFieldText( const wxString& aFieldName, const wxString& aFieldText, const SCH_SHEET_PATH* aPath,
const wxString& aVariantName )
{
wxCHECK( !aFieldName.IsEmpty(), /* void */ );
SCH_FIELD* field = GetField( aFieldName );
wxCHECK( field, /* void */ );
switch( field->GetId() )
{
case FIELD_T::REFERENCE:
wxCHECK( aPath, /* void */ );
SetRef( aPath, aFieldText );
break;
case FIELD_T::FOOTPRINT:
SetFootprintFieldText( aFieldText );
break;
default:
if( aFieldText != field->GetText( aPath ) ) // Do not set the variant unless it's different than the default.
{
if( aVariantName.IsEmpty() )
{
field->SetText( aFieldText );
}
else
{
SCH_SYMBOL_INSTANCE* instance = getInstance( *aPath );
wxCHECK( instance, /* void */ );
if( instance->m_Variants.contains( aVariantName ) )
{
instance->m_Variants[aVariantName].m_Fields[aFieldName] = aFieldText;
}
else
{
SCH_SYMBOL_VARIANT newVariant( aVariantName );
newVariant.InitializeAttributes( *this );
newVariant.m_Fields[aFieldName] = aFieldText;
instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
}
}
}
break;
}
}
wxString SCH_SYMBOL::GetFieldText( const wxString& aFieldName, const SCH_SHEET_PATH* aPath,
const wxString& aVariantName ) const
{
wxCHECK( !aFieldName.IsEmpty(), wxEmptyString );
const SCH_FIELD* field = GetField( aFieldName );
wxCHECK( field, wxEmptyString );
switch( field->GetId() )
{
case FIELD_T::REFERENCE:
wxCHECK( aPath, field->GetText() );
return GetRef( aPath, false );
break;
case FIELD_T::FOOTPRINT:
return GetFootprintFieldText( false, nullptr, false );
break;
default:
if( aVariantName.IsEmpty() )
{
return field->GetText();
}
else
{
const SCH_SYMBOL_INSTANCE* instance = getInstance( *aPath );
if( instance->m_Variants.contains( aVariantName )
&& instance->m_Variants.at( aVariantName ).m_Fields.contains( aFieldName ) )
return instance->m_Variants.at( aVariantName ).m_Fields.at( aFieldName );
}
break;
}
return field->GetText();
}
bool SCH_SYMBOL::IsAnnotated( const SCH_SHEET_PATH* aSheet ) const
{
KIID_PATH path = aSheet->Path();
@@ -800,30 +894,27 @@ void SCH_SYMBOL::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelect
void SCH_SYMBOL::SetDNP( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
{
if( !aInstance )
if( !aInstance || aVariantName.IsEmpty() )
{
m_DNP = aEnable;
return;
}
SCH_SYMBOL_INSTANCE instance;
SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), /* void */,
wxCHECK_MSG( instance, /* void */,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( aVariantName.IsEmpty() )
{
instance.m_DNP = aEnable;
// @todo: remove this when/if we allow per symbol instance DNP setting.
m_DNP = aEnable;
}
else
{
if( instance.m_Variants.contains( aVariantName ) )
if( instance->m_Variants.contains( aVariantName ) && ( aEnable != instance->m_Variants[aVariantName].m_DNP ) )
{
instance.m_Variants[aVariantName].m_DNP = aEnable;
instance->m_Variants[aVariantName].m_DNP = aEnable;
}
else
{
@@ -839,66 +930,47 @@ void SCH_SYMBOL::SetDNP( bool aEnable, const SCH_SHEET_PATH* aInstance, const wx
bool SCH_SYMBOL::GetDNP( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
{
if( !aInstance )
if( !aInstance || aVariantName.IsEmpty() )
return m_DNP;
SCH_SYMBOL_INSTANCE instance;
wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), m_DNP,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( aVariantName.IsEmpty() )
{
if( !GetInstance( instance, aInstance->Path() ) )
return m_DNP;
// @todo: uncomment this when/if we allow per symbol instance DNP setting.
// return instance.m_DNP;
}
else
{
wxCHECK_MSG( instance.m_Variants.contains( aVariantName ), false,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s' for variant '%s'." ),
aInstance->PathHumanReadable(), aVariantName ) );
if( aVariantName.IsEmpty() )
return m_DNP;
else if( instance.m_Variants.contains( aVariantName ) )
return instance.m_Variants[aVariantName].m_DNP;
}
}
void SCH_SYMBOL::SetDNP( bool aEnable, const SCH_SHEET_PATH& aInstance, const std::vector<wxString>& aVariantNames )
{
for( const wxString& variantName : aVariantNames )
SetDNP( aEnable, &aInstance, variantName );
return m_DNP;
}
void SCH_SYMBOL::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
{
if( !aInstance )
if( !aInstance || aVariantName.IsEmpty() )
{
m_excludedFromBOM = aEnable;
return;
}
SCH_SYMBOL_INSTANCE instance;
SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), /* void */,
wxCHECK_MSG( instance, /* void */,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( aVariantName.IsEmpty() )
{
instance.m_ExcludedFromBOM = aEnable;
// @todo: remove this when/if we allow per symbol instance exclude from BOM setting.
m_excludedFromBOM = aEnable;
}
else
{
if( instance.m_Variants.contains( aVariantName ) )
if( instance->m_Variants.contains( aVariantName )
&& ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromBOM ) )
{
instance.m_Variants[aVariantName].m_ExcludedFromBOM = aEnable;
instance->m_Variants[aVariantName].m_ExcludedFromBOM = aEnable;
}
else
{
@@ -914,66 +986,48 @@ void SCH_SYMBOL::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstan
bool SCH_SYMBOL::GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
{
if( !aInstance )
if( !aInstance || aVariantName.IsEmpty() )
return m_excludedFromBOM;
SCH_SYMBOL_INSTANCE instance;
wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), m_excludedFromBOM,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( !GetInstance( instance, aInstance->Path() ) )
return m_excludedFromBOM;
if( aVariantName.IsEmpty() )
{
return m_excludedFromBOM;
// @todo: uncomment this when/if we allow per symbol instance exclude from BOM setting.
// return instance.m_ExcludedFromBOM;
}
else
{
wxCHECK_MSG( instance.m_Variants.contains( aVariantName ), false,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s' variant '%s'." ),
aInstance->PathHumanReadable(), aVariantName ) );
else if( instance.m_Variants.contains( aVariantName ) )
return instance.m_Variants[aVariantName].m_ExcludedFromBOM;
}
}
void SCH_SYMBOL::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH& aInstance,
const std::vector<wxString>& aVariantNames )
{
for( const wxString& variantName : aVariantNames )
SetExcludedFromBOM( aEnable, &aInstance, variantName );
// If the variant has not been defined yet, return the default exclude from BOM setting.
return m_excludedFromBOM;
}
void SCH_SYMBOL::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
{
if( !aInstance )
if( !aInstance || aVariantName.IsEmpty() )
{
m_excludedFromSim = aEnable;
return;
}
SCH_SYMBOL_INSTANCE instance;
SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), /* void */,
wxCHECK_MSG( instance, /* void */,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( aVariantName.IsEmpty() )
{
instance.m_ExcludedFromSim = aEnable;
// @todo: remove this when/if we allow per symbol instance exclude from simulation setting.
m_excludedFromSim = aEnable;
}
else
{
if( instance.m_Variants.contains( aVariantName ) )
if( instance->m_Variants.contains( aVariantName )
&& ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromSim ) )
{
instance.m_Variants[aVariantName].m_ExcludedFromSim = aEnable;
instance->m_Variants[aVariantName].m_ExcludedFromSim = aEnable;
}
else
{
@@ -989,37 +1043,21 @@ void SCH_SYMBOL::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstan
bool SCH_SYMBOL::GetExcludedFromSim( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
{
if( !aInstance )
if( !aInstance || aVariantName.IsEmpty() )
return m_excludedFromSim;
SCH_SYMBOL_INSTANCE instance;
wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), m_excludedFromSim,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
aInstance->PathHumanReadable() ) );
if( !GetInstance( instance, aInstance->Path() ) )
return m_excludedFromSim;
if( aVariantName.IsEmpty() )
{
return m_excludedFromSim;
// @todo: uncooment this when/if we allow per symbol instance exclude from simulation setting.
// return instance.m_ExcludedFromSim;
}
else
{
wxCHECK_MSG( instance.m_Variants.contains( aVariantName ), false,
wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s' variant '%s'." ),
aInstance->PathHumanReadable(), aVariantName ) );
else if ( instance.m_Variants.contains( aVariantName ) )
return instance.m_Variants[aVariantName].m_ExcludedFromSim;
}
}
void SCH_SYMBOL::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH& aInstance,
const std::vector<wxString>& aVariantNames )
{
for( const wxString& variantName : aVariantNames )
SetExcludedFromSim( aEnable, &aInstance, variantName );
// If variant is not defined yet, return default exclude from simulation setting.
return m_excludedFromSim;
}
@@ -1030,18 +1068,48 @@ void SCH_SYMBOL::SetUnitSelection( int aUnitSelection )
}
const wxString SCH_SYMBOL::GetValue( bool aResolve, const SCH_SHEET_PATH* aPath, bool aAllowExtraText ) const
const wxString SCH_SYMBOL::GetValue( bool aResolve, const SCH_SHEET_PATH* aInstance,
bool aAllowExtraText, const wxString& aVariantName ) const
{
if( aResolve )
return GetField( FIELD_T::VALUE )->GetShownText( aPath, aAllowExtraText );
if( aVariantName.IsEmpty() )
{
if( aResolve )
return GetField( FIELD_T::VALUE )->GetShownText( aInstance, aAllowExtraText );
return GetField( FIELD_T::VALUE )->GetText();
return GetField( FIELD_T::VALUE )->GetText();
}
std::optional variant = GetVariant( *aInstance, aVariantName );
if( variant && variant->m_Fields.contains( GetField( FIELD_T::VALUE )->GetName() ) )
return variant->m_Fields[GetField( FIELD_T::VALUE )->GetName()];
return wxEmptyString;
}
void SCH_SYMBOL::SetValueFieldText( const wxString& aValue )
void SCH_SYMBOL::SetValueFieldText( const wxString& aValue, const SCH_SHEET_PATH* aInstance,
const wxString& aVariantName )
{
GetField( FIELD_T::VALUE )->SetText( aValue );
if( !aInstance || aVariantName.IsEmpty() )
{
GetField( FIELD_T::VALUE )->SetText( aValue );
return;
}
std::optional variant = GetVariant( *aInstance, aVariantName );
if( variant )
{
variant->m_Fields[GetField( FIELD_T::VALUE )->GetName()] = aValue;
}
else
{
SCH_SYMBOL_VARIANT newVariant( aVariantName );
newVariant.m_Fields[GetField( FIELD_T::VALUE )->GetName()] = aValue;
AddVariant( *aInstance, newVariant );
}
}
@@ -2982,11 +3050,12 @@ void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS&
}
}
if( m_DNP )
PlotDNP( aPlotter );
wxString variant = Schematic()->GetCurrentVariant();
SCH_SHEET_PATH* sheet = &Schematic()->CurrentSheet();
if( GetDNP( sheet, variant ) )
PlotDNP( aPlotter );
// Plot attributes to a hypertext menu
if( aPlotOpts.m_PDFPropertyPopups )
{
@@ -2994,7 +3063,7 @@ void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS&
for( const SCH_FIELD& field : GetFields() )
{
wxString text_field = field.GetShownText( sheet, false );
wxString text_field = field.GetShownText( sheet, false, 0, variant );
if( text_field.IsEmpty() )
continue;
@@ -3322,13 +3391,13 @@ std::optional<SCH_SYMBOL_VARIANT> SCH_SYMBOL::GetVariant( const SCH_SHEET_PATH&
void SCH_SYMBOL::AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SYMBOL_VARIANT& aVariant )
{
SCH_SYMBOL_INSTANCE instance;
SCH_SYMBOL_INSTANCE* instance = getInstance( aInstance );
// The instance path must already exist.
if( !GetInstance( instance, aInstance.Path() ) )
if( !instance )
return;
instance.m_Variants.emplace( std::make_pair( aVariant.m_Name, aVariant ) );
instance->m_Variants.insert( std::make_pair( aVariant.m_Name, aVariant ) );
}
@@ -3450,6 +3519,30 @@ void SCH_SYMBOL::BuildLocalPowerIconShape( std::vector<SCH_SHAPE>& aShapeList, c
}
SCH_SYMBOL_INSTANCE* SCH_SYMBOL::getInstance( const KIID_PATH& aSheetPath )
{
for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
{
if( instance.m_Path == aSheetPath )
return &instance;
}
return nullptr;
}
const SCH_SYMBOL_INSTANCE* SCH_SYMBOL::getInstance( const KIID_PATH& aSheetPath ) const
{
for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
{
if( instance.m_Path == aSheetPath )
return &instance;
}
return nullptr;
}
static struct SCH_SYMBOL_DESC
{
SCH_SYMBOL_DESC()
+25 -16
View File
@@ -476,9 +476,10 @@ public:
* @return the value for the instance on the given sheet.
*/
const wxString GetValue( bool aResolve, const SCH_SHEET_PATH* aPath,
bool aAllowExtraText ) const override;
bool aAllowExtraText, const wxString& aVariantName = wxEmptyString ) const override;
void SetValueFieldText( const wxString& aValue );
void SetValueFieldText( const wxString& aValue, const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString );
const wxString GetFootprintFieldText( bool aResolve, const SCH_SHEET_PATH* aPath,
bool aAllowExtraText ) const;
@@ -496,12 +497,12 @@ public:
wxString GetValueProp() const
{
return GetValue( false, &Schematic()->CurrentSheet(), false );
return GetValue( false, &Schematic()->CurrentSheet(), false, Schematic()->GetCurrentVariant() );
}
void SetValueProp( const wxString& aRef )
void SetValueProp( const wxString& aValue )
{
SetValueFieldText( aRef );
SetValueFieldText( aValue, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
int GetUnitProp() const
@@ -509,6 +510,12 @@ public:
return GetUnitSelection( &Schematic()->CurrentSheet() );
}
void SetFieldText( const wxString& aFieldName, const wxString& aFieldText, const SCH_SHEET_PATH* aPath = nullptr,
const wxString& aVariantName = wxEmptyString );
wxString GetFieldText( const wxString& aFieldName, const SCH_SHEET_PATH* aPath = nullptr,
const wxString& aVariantName = wxEmptyString ) const;
void SetUnitProp( int aUnit )
{
SetUnitSelection( &Schematic()->CurrentSheet(), aUnit );
@@ -678,44 +685,40 @@ public:
const wxString& aVariantName = wxEmptyString ) override;
virtual bool GetDNP( const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) const override;
void SetDNP( bool aEnable, const SCH_SHEET_PATH& aInstance, const std::vector<wxString>& aVariantNames );
bool GetDNPProp() const { return GetDNP( nullptr, Schematic()->GetCurrentVariant() ); }
bool GetDNPProp() const { return GetDNP( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() ); }
void SetDNPProp( bool aEnable ) { SetDNP( aEnable, nullptr, Schematic()->GetCurrentVariant() ); }
void SetDNPProp( bool aEnable ) { SetDNP( aEnable, &Schematic()->CurrentSheet(),
Schematic()->GetCurrentVariant() ); }
void SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) override;
bool GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) const override;
void SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH& aInstance,
const std::vector<wxString>& aVariantNames );
bool GetExcludedFromBOMProp() const
{
return GetExcludedFromBOM( nullptr, Schematic()->GetCurrentVariant() );
return GetExcludedFromBOM( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
void SetExcludedFromBOMProp( bool aEnable )
{
SetExcludedFromBOM( aEnable, nullptr, Schematic()->GetCurrentVariant() );
SetExcludedFromBOM( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
void SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) override;
bool GetExcludedFromSim( const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) const override;
void SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH& aInstance,
const std::vector<wxString>& aVariantNames );
bool GetExcludedFromSimProp() const
{
return GetExcludedFromSim( nullptr, Schematic()->GetCurrentVariant() );
return GetExcludedFromSim( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
void SetExcludedFromSimProp( bool aEnable )
{
SetExcludedFromSim( aEnable, nullptr, Schematic()->GetCurrentVariant() );
SetExcludedFromSim( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
}
/**
@@ -912,6 +915,12 @@ private:
void Init( const VECTOR2I& pos = VECTOR2I( 0, 0 ) );
SCH_SYMBOL_INSTANCE* getInstance( const KIID_PATH& aPath );
const SCH_SYMBOL_INSTANCE* getInstance( const KIID_PATH& aPath ) const;
SCH_SYMBOL_INSTANCE* getInstance( const SCH_SHEET_PATH& aPath ) { return getInstance( aPath.Path() ); }
const SCH_SYMBOL_INSTANCE* getInstance( const SCH_SHEET_PATH& aPath ) const { return getInstance( aPath.Path() ); }
private:
VECTOR2I m_pos;
LIB_ID m_lib_id; ///< Name and library the symbol was loaded from, i.e. 74xx:74LS00.
+16
View File
@@ -468,6 +468,11 @@ bool SCHEMATIC::ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* toke
*token = m_project->GetProjectName();
return true;
}
else if( token->IsSameAs( wxT( "VARIANTNAME" ) ) )
{
*token = m_currentVariant;
return true;
}
// aSheetPath->LastScreen() can be null during schematic loading
if( aSheetPath->LastScreen() && aSheetPath->LastScreen()->GetTitleBlock().TextVarResolver( token, m_project ) )
@@ -2112,6 +2117,17 @@ void SCHEMATIC::DeleteVariant( const wxString& aVariantName )
}
void SCHEMATIC::LoadVariants()
{
if( m_rootSheet->GetScreen() )
{
SCH_SCREENS screens( m_rootSheet );
std::set<wxString> variantNames = screens.GetVariantNames();
m_variantNames.insert( variantNames.begin(), variantNames.end() );
}
}
void SCHEMATIC::SaveToHistory( const wxString& aProjectPath, std::vector<wxString>& aFiles )
{
wxString projPath = m_project->GetProjectPath();
+8
View File
@@ -460,6 +460,14 @@ public:
void AddVariant( const wxString& aVariantName ) { m_variantNames.emplace( aVariantName ); }
/**
* This is a throw away method for variant testing.
*
* Once the schematic loading is properly fixed due to SetRoot() method breakage, this method should
* be removed.
*/
void LoadVariants();
/**
* True if a SCHEMATIC exists, false if not
*/
+2 -2
View File
@@ -143,7 +143,7 @@ public:
bool aIncludeUnit = false ) const = 0;
virtual const wxString GetValue( bool aResolve, const SCH_SHEET_PATH* aPath,
bool aAllowExtraText ) const = 0;
bool aAllowExtraText, const wxString& aVaraintName = wxEmptyString ) const = 0;
virtual void GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly ) const = 0;
@@ -190,7 +190,7 @@ public:
* Set or clear the exclude from schematic bill of materials flag.
*/
virtual void SetExcludedFromBOM( bool aExcludeFromBOM, const SCH_SHEET_PATH* aInstance = nullptr,
const wxString& aVariantName = wxEmptyString ) override
const wxString& aVariantName = wxEmptyString ) override
{
m_excludedFromBOM = aExcludeFromBOM;
}
+6 -2
View File
@@ -320,6 +320,8 @@ void SCH_EDIT_FRAME::onVariantSelected( wxCommandEvent& aEvent )
selectedVariant = m_currentVariantCtrl->GetString( selection );
Schematic().SetCurrentVariant( selectedVariant );
UpdateProperties();
HardRedraw();
}
@@ -328,7 +330,9 @@ void SCH_EDIT_FRAME::SetCurrentVariant( const wxString& aVariantName )
if( !m_currentVariantCtrl )
return;
int newSelection = m_currentVariantCtrl->FindString( aVariantName );
wxString name = aVariantName.IsEmpty() ? GetDefaultVariantName() : aVariantName;
int newSelection = m_currentVariantCtrl->FindString( name );
if( newSelection == wxNOT_FOUND )
return;
@@ -340,7 +344,7 @@ void SCH_EDIT_FRAME::SetCurrentVariant( const wxString& aVariantName )
if( currentSelection != wxNOT_FOUND )
selectedString = m_currentVariantCtrl->GetString( currentSelection );
if( selectedString != aVariantName )
if( selectedString != name )
{
m_currentVariantCtrl->SetSelection( newSelection );
Schematic().SetCurrentVariant( aVariantName );
@@ -0,0 +1,410 @@
{
"board": {
"3dviewports": [],
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_pairs": [],
"layer_presets": [],
"viewports": []
},
"boards": [],
"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_to_bus_conflict": "error",
"bus_to_net_conflict": "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",
"hier_label_mismatch": "error",
"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": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"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": "ignore",
"unannotated": "error",
"unconnected_wire_endpoint": "warning",
"undefined_netclass": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "variant_test.kicad_pro",
"version": 3
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"priority": 2147483647,
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
}
],
"meta": {
"version": 4
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 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": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
},
{
"group_by": true,
"label": "Exclude from BOM",
"name": "${EXCLUDE_FROM_BOM}",
"show": true
},
{
"group_by": true,
"label": "Exclude from Board",
"name": "${EXCLUDE_FROM_BOARD}",
"show": true
},
{
"group_by": true,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"include_excluded_from_bom": true,
"name": "Default Editing",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"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.375,
"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.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"space_save_all_events": true,
"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
},
"sheets": [
[
"054bba16-8cdf-4a21-a2a2-bd9ba5ee743f",
"Root"
]
],
"text_variables": {}
}
@@ -0,0 +1,209 @@
(kicad_sch
(version 20250114)
(generator "eeschema")
(generator_version "9.0")
(uuid "054bba16-8cdf-4a21-a2a2-bd9ba5ee743f")
(paper "A4")
(lib_symbols
(symbol "Device:R"
(pin_numbers
(hide yes)
)
(pin_names
(offset 0)
)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(property "Reference" "R"
(at 2.032 0 90)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Value" "R"
(at 0 0 90)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Footprint" ""
(at -1.778 0 90)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" "~"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" "Resistor"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_keywords" "R res resistor"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_fp_filters" "R_*"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(symbol "R_0_1"
(rectangle
(start -1.016 -2.54)
(end 1.016 2.54)
(stroke
(width 0.254)
(type default)
)
(fill
(type none)
)
)
)
(symbol "R_1_1"
(pin passive line
(at 0 3.81 270)
(length 1.27)
(name "~"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "1"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin passive line
(at 0 -3.81 90)
(length 1.27)
(name "~"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "2"
(effects
(font
(size 1.27 1.27)
)
)
)
)
)
(embedded_fonts no)
)
)
(symbol
(lib_id "Device:R")
(at 110.49 88.9 0)
(unit 1)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(dnp no)
(fields_autoplaced yes)
(uuid "c3f93c62-4b18-4940-a587-6e1147c4fd43")
(property "Reference" "R1"
(at 113.03 87.6299 0)
(effects
(font
(size 1.27 1.27)
)
(justify left)
)
)
(property "Value" "1K"
(at 113.03 90.1699 0)
(effects
(font
(size 1.27 1.27)
)
(justify left)
)
)
(property "Footprint" ""
(at 108.712 88.9 90)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" "~"
(at 110.49 88.9 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" "Resistor"
(at 110.49 88.9 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(pin "1"
(uuid "1e787b7c-7f54-4b81-9254-825bd71b3511")
)
(pin "2"
(uuid "07fa4c47-5960-4d30-8bfd-93c1e8ac9e63")
)
(instances
(project ""
(path "/054bba16-8cdf-4a21-a2a2-bd9ba5ee743f"
(reference "R1")
(unit 1)
)
)
)
)
(sheet_instances
(path "/"
(page "1")
)
)
(embedded_fonts no)
)
+68 -3
View File
@@ -27,17 +27,36 @@
*/
#include <qa_utils/wx_utils/unit_test_utils.h>
#include "eeschema_test_utils.h"
// Code under test
#include <sch_symbol.h>
#include <sch_edit_frame.h>
#include <wildcards_and_files_ext.h>
class TEST_SCH_SYMBOL_FIXTURE
class TEST_SCH_SYMBOL_FIXTURE : public KI_TEST::SCHEMATIC_TEST_FIXTURE
{
public:
TEST_SCH_SYMBOL_FIXTURE()
SCH_SYMBOL* GetFirstSymbol()
{
if( !m_schematic )
return nullptr;
SCH_SCREEN* screen = m_schematic->RootScreen();
if( !screen )
return nullptr;
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
if( symbol )
return symbol;
}
return nullptr;
}
///< #SCH_SYMBOL object with no extra data set.
@@ -77,4 +96,50 @@ BOOST_AUTO_TEST_CASE( Orientation )
}
/**
* Test symbol variant handling.
*/
BOOST_AUTO_TEST_CASE( SchSymbolVariantTest )
{
wxFileName fn;
fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
fn.AppendDir( wxS( "variant_test" ) );
fn.SetName( wxS( "variant_test" ) );
fn.SetExt( FILEEXT::KiCadSchematicFileExtension );
LoadSchematic( fn.GetFullPath() );
SCH_SYMBOL* symbol = GetFirstSymbol();
BOOST_CHECK( symbol );
// Test for an empty (non-existant) variant.
wxString variantName = wxS( "Variant1" );
std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
BOOST_CHECK( !variant );
// Test DNP property variant.
BOOST_CHECK( !symbol->GetDNP() );
symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
// Test exclude from BOM property variant.
BOOST_CHECK( !symbol->GetExcludedFromBOM() );
symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], variantName );
BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], variantName ) );
// Test exclude from simulation property variant.
BOOST_CHECK( !symbol->GetExcludedFromSim() );
symbol->SetExcludedFromSim( true, &m_schematic->Hierarchy()[0], variantName );
BOOST_CHECK( symbol->GetExcludedFromSim( &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" ) );
symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "10K" ), &m_schematic->Hierarchy()[0], variantName );
BOOST_CHECK( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
false, 0, variantName ) == wxS( "10K" ) );
// BOOST_CHECK( symbol->GetFieldText( FIELD_T::VALUE, &m_schematic->Hierarchy()[0], variantName ) == wxS( "10K" ) );
}
BOOST_AUTO_TEST_SUITE_END()