Fields Table: convert special strings like Quantity to named variables

Before, we did not actually prevent users from adding a field also named
Quantity to their symbols. This of course does not play nicely with the
assumptions that Quantity is a special column in the fields editor.

By making it a named variable, the user can safely add it to a symbol
and it will not be editable, and will also work in the fields table
editor as expected.
This commit is contained in:
Mike Williams 2023-08-01 10:13:56 -04:00
parent 3a82374719
commit 25e391719e
8 changed files with 43 additions and 20 deletions

View File

@ -124,6 +124,12 @@ wxString GetTextVars( const wxString& aSource )
} }
bool IsTextVar( const wxString& aSource )
{
return aSource.StartsWith( wxS( "${" ) );
}
// //
// Stolen from wxExpandEnvVars and then heavily optimized // Stolen from wxExpandEnvVars and then heavily optimized
// //

View File

@ -136,7 +136,7 @@ BOM_PRESET BOM_PRESET::GroupedByValue()
{ "Value", "Value", true, true }, { "Value", "Value", true, true },
{ "Datasheet", "Datasheet", true, false }, { "Datasheet", "Datasheet", true, false },
{ "Footprint", "Footprint", true, false }, { "Footprint", "Footprint", true, false },
{ "Quantity", "Qty", true, false }, { "${QUANTITY}", "Qty", true, false },
{ "${DNP}", "DNP", true, true }, { "${DNP}", "DNP", true, true },
}; };
@ -155,7 +155,7 @@ BOM_PRESET BOM_PRESET::GroupedByValueFootprint()
{ "Value", "Value", true, true }, { "Value", "Value", true, true },
{ "Datasheet", "Datasheet", true, false }, { "Datasheet", "Datasheet", true, false },
{ "Footprint", "Footprint", true, true }, { "Footprint", "Footprint", true, true },
{ "Quantity", "Qty", true, false }, { "${QUANTITY}", "Qty", true, false },
{ "${DNP}", "DNP", true, true }, { "${DNP}", "DNP", true, true },
}; };

View File

@ -335,14 +335,13 @@ void DIALOG_SYMBOL_FIELDS_TABLE::SetupColumnProperties()
attr->SetEditor( new GRID_CELL_URL_EDITOR( this, Prj().SchSearchS() ) ); attr->SetEditor( new GRID_CELL_URL_EDITOR( this, Prj().SchSearchS() ) );
m_grid->SetColAttr( col, attr ); m_grid->SetColAttr( col, attr );
} }
else if( m_dataModel->GetColFieldName( col ) == wxS( "Quantity" ) else if( m_dataModel->ColIsQuantity( col ) || m_dataModel->ColIsItemNumber( col ) )
|| m_dataModel->GetColFieldName( col ) == wxS( "Item Number" ) )
{ {
attr->SetReadOnly(); attr->SetReadOnly();
m_grid->SetColAttr( col, attr ); m_grid->SetColAttr( col, attr );
m_grid->SetColFormatNumber( col ); m_grid->SetColFormatNumber( col );
} }
else if( m_dataModel->GetColFieldName( col ).StartsWith( wxS( "${" ) ) ) else if( IsTextVar( m_dataModel->GetColFieldName( col ) ) )
{ {
attr->SetReadOnly(); attr->SetReadOnly();
m_grid->SetColAttr( col, attr ); m_grid->SetColAttr( col, attr );
@ -519,6 +518,12 @@ bool DIALOG_SYMBOL_FIELDS_TABLE::TransferDataFromWindow()
void DIALOG_SYMBOL_FIELDS_TABLE::AddField( const wxString& aFieldName, const wxString& aLabelValue, void DIALOG_SYMBOL_FIELDS_TABLE::AddField( const wxString& aFieldName, const wxString& aLabelValue,
bool show, bool groupBy, bool addedByUser ) bool show, bool groupBy, bool addedByUser )
{ {
// Users can add fields with variable names that match the special names in the grid,
// e.g. ${QUANTITY} so make sure we don't add them twice
for( int i = 0; i < m_fieldsCtrl->GetItemCount(); i++ )
if( m_fieldsCtrl->GetTextValue( i, FIELD_NAME_COLUMN ) == aFieldName )
return;
m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser ); m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser );
wxVector<wxVariant> fieldsCtrlRow; wxVector<wxVariant> fieldsCtrlRow;
@ -565,11 +570,11 @@ void DIALOG_SYMBOL_FIELDS_TABLE::LoadFieldNames()
TEMPLATE_FIELDNAME::GetDefaultFieldName( i, true ), show, groupBy ); TEMPLATE_FIELDNAME::GetDefaultFieldName( i, true ), show, groupBy );
} }
// Generated field that isn't in any symbol // Generated fields present only in the fields table
AddField( wxS( "Quantity" ), _( "Qty" ), true, false ); AddField( FIELDS_EDITOR_GRID_DATA_MODEL::QUANTITY_VARIABLE, _( "Qty" ), true, false );
AddField( wxS( "Item Number" ), _( "#" ), true, false ); AddField( FIELDS_EDITOR_GRID_DATA_MODEL::ITEM_NUMBER_VARIABLE, _( "#" ), true, false );
// User fields second // User fields next
std::set<wxString> userFieldNames; std::set<wxString> userFieldNames;
for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i ) for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )

View File

@ -288,8 +288,6 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
dataModel.AddColumn( TEMPLATE_FIELDNAME::GetDefaultFieldName( i ), dataModel.AddColumn( TEMPLATE_FIELDNAME::GetDefaultFieldName( i ),
TEMPLATE_FIELDNAME::GetDefaultFieldName( i, true ), false ); TEMPLATE_FIELDNAME::GetDefaultFieldName( i, true ), false );
dataModel.AddColumn( wxS( "Quantity" ), _( "Qty" ), false );
// User field names in symbols second // User field names in symbols second
std::set<wxString> userFieldNames; std::set<wxString> userFieldNames;

View File

@ -9,6 +9,8 @@
#include "fields_data_model.h" #include "fields_data_model.h"
const wxString FIELDS_EDITOR_GRID_DATA_MODEL::QUANTITY_VARIABLE = wxS( "${QUANTITY}" );
const wxString FIELDS_EDITOR_GRID_DATA_MODEL::ITEM_NUMBER_VARIABLE = wxS( "${ITEM_NUMBER}" );
void FIELDS_EDITOR_GRID_DATA_MODEL::AddColumn( const wxString& aFieldName, const wxString& aLabel, void FIELDS_EDITOR_GRID_DATA_MODEL::AddColumn( const wxString& aFieldName, const wxString& aLabel,
bool aAddedByUser ) bool aAddedByUser )
@ -27,7 +29,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::AddColumn( const wxString& aFieldName, const
m_dataStore[symbol->m_Uuid][aFieldName] = field->GetText(); m_dataStore[symbol->m_Uuid][aFieldName] = field->GetText();
// Handle fields with variables as names that are not present in the symbol // Handle fields with variables as names that are not present in the symbol
// by giving them the correct value // by giving them the correct value
else if( aFieldName.StartsWith( wxT( "${" ) ) ) else if( IsTextVar( aFieldName ) )
m_dataStore[symbol->m_Uuid][aFieldName] = aFieldName; m_dataStore[symbol->m_Uuid][aFieldName] = aFieldName;
else else
m_dataStore[symbol->m_Uuid][aFieldName] = wxEmptyString; m_dataStore[symbol->m_Uuid][aFieldName] = wxEmptyString;
@ -203,8 +205,11 @@ wxString FIELDS_EDITOR_GRID_DATA_MODEL::GetValue( const DATA_MODEL_ROW& group, i
void FIELDS_EDITOR_GRID_DATA_MODEL::SetValue( int aRow, int aCol, const wxString& aValue ) void FIELDS_EDITOR_GRID_DATA_MODEL::SetValue( int aRow, int aCol, const wxString& aValue )
{ {
if( ColIsReference( aCol ) || ColIsQuantity( aCol ) ) wxCHECK_RET( aCol >= 0 && aCol < (int) m_cols.size(), wxS( "Invalid column number" ) );
return; // Can't modify references or quantity
// Can't modify references or text variables column, e.g. ${QUANTITY}
if( ColIsReference( aCol ) || IsTextVar( m_cols[aCol].m_fieldName ) )
return;
DATA_MODEL_ROW& rowGroup = m_rows[aRow]; DATA_MODEL_ROW& rowGroup = m_rows[aRow];
@ -224,13 +229,13 @@ bool FIELDS_EDITOR_GRID_DATA_MODEL::ColIsReference( int aCol )
bool FIELDS_EDITOR_GRID_DATA_MODEL::ColIsQuantity( int aCol ) bool FIELDS_EDITOR_GRID_DATA_MODEL::ColIsQuantity( int aCol )
{ {
wxCHECK( aCol >= 0 && aCol < (int) m_cols.size(), false ); wxCHECK( aCol >= 0 && aCol < (int) m_cols.size(), false );
return m_cols[aCol].m_fieldName == wxS( "Quantity" ); return m_cols[aCol].m_fieldName == QUANTITY_VARIABLE;
} }
bool FIELDS_EDITOR_GRID_DATA_MODEL::ColIsItemNumber( int aCol ) bool FIELDS_EDITOR_GRID_DATA_MODEL::ColIsItemNumber( int aCol )
{ {
wxCHECK( aCol >= 0 && aCol < (int) m_cols.size(), false ); wxCHECK( aCol >= 0 && aCol < (int) m_cols.size(), false );
return m_cols[aCol].m_fieldName == wxS( "Item Number" ); return m_cols[aCol].m_fieldName == ITEM_NUMBER_VARIABLE;
} }
@ -373,7 +378,7 @@ wxString FIELDS_EDITOR_GRID_DATA_MODEL::getFieldShownText( const SCH_REFERENCE&
// Handle fields with variables as names that are not present in the symbol // Handle fields with variables as names that are not present in the symbol
// by giving them the correct value by resolving against the symbol // by giving them the correct value by resolving against the symbol
if( aFieldName.StartsWith( wxT( "${" ) ) ) if( IsTextVar( aFieldName ) )
{ {
int depth = 0; int depth = 0;
const SCH_SHEET_PATH& path = aRef.GetSheetPath(); const SCH_SHEET_PATH& path = aRef.GetSheetPath();
@ -584,7 +589,8 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyData(
for( const std::pair<wxString, wxString> srcData : fieldStore ) for( const std::pair<wxString, wxString> srcData : fieldStore )
{ {
if( srcData.first == _( "Quantity" ) ) // Skip special fields with variables as names (e.g. ${QUANTITY})
if( IsTextVar( srcData.first ) )
continue; continue;
const wxString& srcName = srcData.first; const wxString& srcName = srcData.first;
@ -680,7 +686,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyBomPreset( const BOM_PRESET& aPreset )
int col = GetFieldNameCol( field.name ); int col = GetFieldNameCol( field.name );
// Add any missing fields, if the user doesn't add any data // Add any missing fields, if the user doesn't add any data
// they won't be saved to the symbols anywa // they won't be saved to the symbols anyway
if( col == -1 ) if( col == -1 )
{ {
AddColumn( field.name, field.label, true ); AddColumn( field.name, field.label, true );

View File

@ -59,6 +59,9 @@ public:
m_symbolsList.SplitReferences(); m_symbolsList.SplitReferences();
} }
static const wxString QUANTITY_VARIABLE;
static const wxString ITEM_NUMBER_VARIABLE;
void AddColumn( const wxString& aFieldName, const wxString& aLabel, bool aAddedByUser ); void AddColumn( const wxString& aFieldName, const wxString& aLabel, bool aAddedByUser );
void RemoveColumn( int aCol ); void RemoveColumn( int aCol );
void RenameColumn( int aCol, const wxString& newName ); void RenameColumn( int aCol, const wxString& newName );

View File

@ -96,6 +96,11 @@ wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject );
*/ */
wxString GetTextVars( const wxString& aSource ); wxString GetTextVars( const wxString& aSource );
/**
* Returns true if the string is a text var, e.g starts with ${
*/
bool IsTextVar( const wxString& aSource );
/** /**
* Replace any environment and/or text variables in file-path uris (leaving network-path URIs * Replace any environment and/or text variables in file-path uris (leaving network-path URIs
* alone). * alone).

View File

@ -34,7 +34,7 @@ CLI::EXPORT_SCH_BOM_COMMAND::EXPORT_SCH_BOM_COMMAND() : EXPORT_PCB_BASE_COMMAND(
// Field output options // Field output options
m_argParser.add_argument( ARG_FIELDS ) m_argParser.add_argument( ARG_FIELDS )
.help( UTF8STDSTR( _( ARG_FIELDS_DESC ) ) ) .help( UTF8STDSTR( _( ARG_FIELDS_DESC ) ) )
.default_value( std::string( "Reference,Value,Footprint,Quantity,${DNP}" ) ); .default_value( std::string( "Reference,Value,Footprint,${QUANTITY},${DNP}" ) );
m_argParser.add_argument( ARG_LABELS ) m_argParser.add_argument( ARG_LABELS )
.help( UTF8STDSTR( _( ARG_LABELS_DESC ) ) ) .help( UTF8STDSTR( _( ARG_LABELS_DESC ) ) )