From 9541e4550212e88aa6175cabc2f2141ea078e08b Mon Sep 17 00:00:00 2001 From: Mike Williams <mike@mikebwilliams.com> Date: Wed, 20 Sep 2023 10:54:37 -0400 Subject: [PATCH] BOM Exporter: allow using presets from the command line --- common/jobs/job_export_sch_bom.h | 4 + common/settings/bom_settings.cpp | 11 ++ .../dialogs/dialog_symbol_fields_table.cpp | 7 +- eeschema/eeschema_jobs_handler.cpp | 117 ++++++++++++++---- include/settings/bom_settings.h | 4 + kicad/cli/command_sch_export_bom.cpp | 15 +++ kicad/cli/command_sch_export_bom.h | 6 + 7 files changed, 134 insertions(+), 30 deletions(-) diff --git a/common/jobs/job_export_sch_bom.h b/common/jobs/job_export_sch_bom.h index 4465d6e917..6dd338e0ee 100644 --- a/common/jobs/job_export_sch_bom.h +++ b/common/jobs/job_export_sch_bom.h @@ -35,6 +35,10 @@ public: wxString m_filename; wxString m_outputFile; + // Preset options (from schematic) + wxString m_bomPresetName; + wxString m_bomFmtPresetName; + // Format options wxString m_fieldDelimiter; wxString m_stringDelimiter; diff --git a/common/settings/bom_settings.cpp b/common/settings/bom_settings.cpp index 068bea7d84..9ca939368d 100644 --- a/common/settings/bom_settings.cpp +++ b/common/settings/bom_settings.cpp @@ -170,6 +170,12 @@ BOM_PRESET BOM_PRESET::Attributes() return p; } +std::vector<BOM_PRESET> BOM_PRESET::BuiltInPresets() +{ + return { BOM_PRESET::GroupedByValue(), BOM_PRESET::GroupedByValueFootprint(), + BOM_PRESET::Attributes() }; +} + //Implementations for BOM_FMT_PRESET bool BOM_FMT_PRESET::operator==( const BOM_FMT_PRESET& rhs ) const { @@ -233,3 +239,8 @@ BOM_FMT_PRESET BOM_FMT_PRESET::Semicolons() _HKI( "Semicolons" ), true, wxS( ";" ), wxT( "'" ), wxT( "," ), wxT( "" ), false, false }; } + +std::vector<BOM_FMT_PRESET> BOM_FMT_PRESET::BuiltInPresets() +{ + return { BOM_FMT_PRESET::CSV(), BOM_FMT_PRESET::TSV(), BOM_FMT_PRESET::Semicolons() }; +} diff --git a/eeschema/dialogs/dialog_symbol_fields_table.cpp b/eeschema/dialogs/dialog_symbol_fields_table.cpp index b04923ac66..ca22c80367 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table.cpp +++ b/eeschema/dialogs/dialog_symbol_fields_table.cpp @@ -1387,9 +1387,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::loadDefaultBomPresets() m_bomPresetMRU.clear(); // Load the read-only defaults - for( const BOM_PRESET& preset : { BOM_PRESET::GroupedByValue(), - BOM_PRESET::GroupedByValueFootprint(), - BOM_PRESET::Attributes() } ) + for( const BOM_PRESET& preset : BOM_PRESET::BuiltInPresets() ) { m_bomPresets[preset.name] = preset; m_bomPresets[preset.name].readOnly = true; @@ -1805,8 +1803,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::loadDefaultBomFmtPresets() m_bomFmtPresetMRU.clear(); // Load the read-only defaults - for( const BOM_FMT_PRESET& preset : - { BOM_FMT_PRESET::CSV(), BOM_FMT_PRESET::TSV(), BOM_FMT_PRESET::Semicolons() } ) + for( const BOM_FMT_PRESET& preset : BOM_FMT_PRESET::BuiltInPresets() ) { m_bomFmtPresets[preset.name] = preset; m_bomFmtPresets[preset.name].readOnly = true; diff --git a/eeschema/eeschema_jobs_handler.cpp b/eeschema/eeschema_jobs_handler.cpp index 533ab3823e..d67e788984 100644 --- a/eeschema/eeschema_jobs_handler.cpp +++ b/eeschema/eeschema_jobs_handler.cpp @@ -343,30 +343,63 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob ) BOM_PRESET preset; - size_t i = 0; - for( wxString fieldName : aBomJob->m_fieldsOrdered ) + // Load a preset if one is specified + if( !aBomJob->m_bomPresetName.IsEmpty() ) { - struct BOM_FIELD field; + // Make sure the built-in presets are loaded + for( const BOM_PRESET& p : BOM_PRESET::BuiltInPresets() ) + sch->Settings().m_BomPresets.emplace_back( p ); - field.name = fieldName; - field.show = true; - field.groupBy = std::find( aBomJob->m_fieldsGroupBy.begin(), aBomJob->m_fieldsGroupBy.end(), - field.name ) - != aBomJob->m_fieldsGroupBy.end(); - field.label = - ( ( aBomJob->m_fieldsLabels.size() > i ) && !aBomJob->m_fieldsLabels[i].IsEmpty() ) - ? aBomJob->m_fieldsLabels[i] - : field.name; + // Find the preset + BOM_PRESET* schPreset = nullptr; - preset.fieldsOrdered.emplace_back( field ); - i++; + for( BOM_PRESET& p : sch->Settings().m_BomPresets ) + { + if( p.name == aBomJob->m_bomPresetName ) + { + schPreset = &p; + break; + } + } + + if( !schPreset ) + { + m_reporter->Report( + wxString::Format( _( "BOM preset '%s' not found" ), aBomJob->m_bomPresetName ), + RPT_SEVERITY_ERROR ); + + return CLI::EXIT_CODES::ERR_UNKNOWN; + } + + preset = *schPreset; } + else + { + size_t i = 0; + for( wxString fieldName : aBomJob->m_fieldsOrdered ) + { + struct BOM_FIELD field; - preset.sortAsc = aBomJob->m_sortAsc; - preset.sortField = aBomJob->m_sortField; - preset.filterString = aBomJob->m_filterString; - preset.groupSymbols = ( aBomJob->m_fieldsGroupBy.size() > 0 ); - preset.excludeDNP = aBomJob->m_excludeDNP; + field.name = fieldName; + field.show = true; + field.groupBy = std::find( aBomJob->m_fieldsGroupBy.begin(), + aBomJob->m_fieldsGroupBy.end(), field.name ) + != aBomJob->m_fieldsGroupBy.end(); + field.label = ( ( aBomJob->m_fieldsLabels.size() > i ) + && !aBomJob->m_fieldsLabels[i].IsEmpty() ) + ? aBomJob->m_fieldsLabels[i] + : field.name; + + preset.fieldsOrdered.emplace_back( field ); + i++; + } + + preset.sortAsc = aBomJob->m_sortAsc; + preset.sortField = aBomJob->m_sortField; + preset.filterString = aBomJob->m_filterString; + preset.groupSymbols = ( aBomJob->m_fieldsGroupBy.size() > 0 ); + preset.excludeDNP = aBomJob->m_excludeDNP; + } dataModel.ApplyBomPreset( preset ); @@ -391,12 +424,46 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob ) } BOM_FMT_PRESET fmt; - fmt.fieldDelimiter = aBomJob->m_fieldDelimiter; - fmt.stringDelimiter = aBomJob->m_stringDelimiter; - fmt.refDelimiter = aBomJob->m_refDelimiter; - fmt.refRangeDelimiter = aBomJob->m_refRangeDelimiter; - fmt.keepTabs = aBomJob->m_keepTabs; - fmt.keepLineBreaks = aBomJob->m_keepLineBreaks; + + // Load a format preset if one is specified + if( !aBomJob->m_bomFmtPresetName.IsEmpty() ) + { + // Make sure the built-in presets are loaded + for( const BOM_FMT_PRESET& p : BOM_FMT_PRESET::BuiltInPresets() ) + sch->Settings().m_BomFmtPresets.emplace_back( p ); + + // Find the preset + BOM_FMT_PRESET* schFmtPreset = nullptr; + + for( BOM_FMT_PRESET& p : sch->Settings().m_BomFmtPresets ) + { + if( p.name == aBomJob->m_bomFmtPresetName ) + { + schFmtPreset = &p; + break; + } + } + + if( !schFmtPreset ) + { + m_reporter->Report( wxString::Format( _( "BOM format preset '%s' not found" ), + aBomJob->m_bomFmtPresetName ), + RPT_SEVERITY_ERROR ); + + return CLI::EXIT_CODES::ERR_UNKNOWN; + } + + fmt = *schFmtPreset; + } + else + { + fmt.fieldDelimiter = aBomJob->m_fieldDelimiter; + fmt.stringDelimiter = aBomJob->m_stringDelimiter; + fmt.refDelimiter = aBomJob->m_refDelimiter; + fmt.refRangeDelimiter = aBomJob->m_refRangeDelimiter; + fmt.keepTabs = aBomJob->m_keepTabs; + fmt.keepLineBreaks = aBomJob->m_keepLineBreaks; + } bool res = f.Write( dataModel.Export( fmt ) ); diff --git a/include/settings/bom_settings.h b/include/settings/bom_settings.h index f21ce024c6..85ea4a245b 100644 --- a/include/settings/bom_settings.h +++ b/include/settings/bom_settings.h @@ -62,6 +62,8 @@ struct BOM_PRESET static BOM_PRESET GroupedByValue(); static BOM_PRESET GroupedByValueFootprint(); static BOM_PRESET Attributes(); + + static std::vector<BOM_PRESET> BuiltInPresets(); }; bool operator!=( const BOM_PRESET& lhs, const BOM_PRESET& rhs ); @@ -88,6 +90,8 @@ struct BOM_FMT_PRESET static BOM_FMT_PRESET CSV(); static BOM_FMT_PRESET TSV(); static BOM_FMT_PRESET Semicolons(); + + static std::vector<BOM_FMT_PRESET> BuiltInPresets(); }; bool operator!=( const BOM_FMT_PRESET& lhs, const BOM_FMT_PRESET& rhs ); diff --git a/kicad/cli/command_sch_export_bom.cpp b/kicad/cli/command_sch_export_bom.cpp index e20d297682..0623c450de 100644 --- a/kicad/cli/command_sch_export_bom.cpp +++ b/kicad/cli/command_sch_export_bom.cpp @@ -35,6 +35,17 @@ CLI::SCH_EXPORT_BOM_COMMAND::SCH_EXPORT_BOM_COMMAND() : COMMAND( "bom" ) m_argParser.add_description( UTF8STDSTR( _( "Generate a Bill of Material (BOM)" ) ) ); addCommonArgs( true, true, false, false ); + // Preset options + m_argParser.add_argument( ARG_PRESET ) + .help( UTF8STDSTR( _( ARG_PRESET_DESC ) ) ) + .default_value( std::string( "" ) ) + .metavar( "PRESET" ); + + m_argParser.add_argument( ARG_FMT_PRESET ) + .help( UTF8STDSTR( _( ARG_FMT_PRESET_DESC ) ) ) + .default_value( std::string( "" ) ) + .metavar( "FMT_PRESET" ); + // Field output options m_argParser.add_argument( ARG_FIELDS ) .help( UTF8STDSTR( _( ARG_FIELDS_DESC ) ) ) @@ -127,6 +138,10 @@ int CLI::SCH_EXPORT_BOM_COMMAND::doPerform( KIWAY& aKiway ) bomJob->m_filename = m_argInput; bomJob->m_outputFile = m_argOutput; + bomJob->m_bomPresetName = From_UTF8( m_argParser.get<std::string>( ARG_PRESET ).c_str() ); + bomJob->m_bomFmtPresetName = + From_UTF8( m_argParser.get<std::string>( ARG_FMT_PRESET ).c_str() ); + // Format options bomJob->m_fieldDelimiter = From_UTF8( m_argParser.get<std::string>( ARG_FIELD_DELIMITER ).c_str() ); diff --git a/kicad/cli/command_sch_export_bom.h b/kicad/cli/command_sch_export_bom.h index 906ed30e75..4a6871a274 100644 --- a/kicad/cli/command_sch_export_bom.h +++ b/kicad/cli/command_sch_export_bom.h @@ -25,6 +25,12 @@ namespace CLI { +// Options for selecting presets of the export, e.g. GroupedByValue and CSV +#define ARG_PRESET "--preset" +#define ARG_PRESET_DESC "Use a named BOM preset settings from the schematic, e.g. \"Grouped By Value\"." + +#define ARG_FMT_PRESET "--format-preset" +#define ARG_FMT_PRESET_DESC "Use a named BOM format preset settings from the schematic, e.g. CSV." // Options for setting the format of the export, e.g. CSV #define ARG_FIELD_DELIMITER "--field-delimiter"