diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 386eb24868..7744b5267c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -446,6 +446,7 @@ set( COMMON_SRCS tool/zoom_tool.cpp settings/app_settings.cpp + settings/bom_settings.cpp settings/color_settings.cpp settings/cvpcb_settings.cpp settings/common_settings.cpp diff --git a/common/settings/bom_settings.cpp b/common/settings/bom_settings.cpp new file mode 100644 index 0000000000..ea7ed5a085 --- /dev/null +++ b/common/settings/bom_settings.cpp @@ -0,0 +1,253 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 Mike Williams + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include +#include +#include + +namespace nlohmann +{ +template <> +struct adl_serializer +{ + static void to_json( json& j, const wxString& s ) { j = s.ToUTF8(); } + + static void from_json( const json& j, wxString& s ) + { + s = wxString::FromUTF8( j.get().c_str() ); + } +}; +} + + +// Implementations for BOM_FMT_PRESET +bool BOM_FIELD::operator==( const BOM_FIELD& rhs ) const +{ + return this->name == rhs.name && this->label == rhs.label && this->show == rhs.show + && this->groupBy == rhs.groupBy; +} + + +const bool operator!=( const BOM_FIELD& lhs, const BOM_FIELD& rhs ) +{ + return !( lhs == rhs ); +} + + +const bool operator<( const BOM_FIELD& lhs, const BOM_FIELD& rhs ) +{ + return lhs.name < rhs.name; +} + + +void to_json( nlohmann::json& j, const BOM_FIELD& f ) +{ + j = nlohmann::json{ + { "name", f.name }, { "label", f.label }, { "show", f.show }, { "group_by", f.groupBy } + }; +} + + +void from_json( const nlohmann::json& j, BOM_FIELD& f ) +{ + j.at( "name" ).get_to( f.name ); + j.at( "label" ).get_to( f.label ); + j.at( "show" ).get_to( f.show ); + j.at( "group_by" ).get_to( f.groupBy ); +} + + +const bool operator!=( const BOM_PRESET& lhs, const BOM_PRESET& rhs ) +{ + return !( lhs == rhs ); +} + + +const bool operator<( const BOM_PRESET& lhs, const BOM_PRESET& rhs ) +{ + return lhs.name < rhs.name; +} + + +void to_json( nlohmann::json& j, const BOM_PRESET& p ) +{ + j = nlohmann::json{ { "name", p.name }, + { "sort_field", p.sortField }, + { "sort_asc", p.sortAsc }, + { "filter_string", p.filterString }, + { "group_symbols", p.groupSymbols } }; + + if( p.fieldsOrdered.size() > 0 ) + j["fields_ordered"] = p.fieldsOrdered; +} + + +void from_json( const nlohmann::json& j, BOM_PRESET& f ) +{ + j.at( "name" ).get_to( f.name ); + j.at( "fields_ordered" ).get_to( f.fieldsOrdered ); + j.at( "sort_field" ).get_to( f.sortField ); + j.at( "sort_asc" ).get_to( f.sortAsc ); + j.at( "filter_string" ).get_to( f.filterString ); + j.at( "group_symbols" ).get_to( f.groupSymbols ); +} + + +// Implementations for BOM_PRESET +bool BOM_PRESET::operator==( const BOM_PRESET& rhs ) const +{ + return this->name == rhs.name && this->readOnly == rhs.readOnly + && this->fieldsOrdered == rhs.fieldsOrdered && this->sortField == rhs.sortField + && this->sortAsc == rhs.sortAsc && this->groupSymbols == rhs.groupSymbols; +} + + +BOM_PRESET BOM_PRESET::GroupedByValue() +{ + BOM_PRESET p = { .name = _HKI( "Grouped By Value" ), + .readOnly = true, + .sortField = _( "Reference" ), + .sortAsc = true, + .groupSymbols = true }; + + p.fieldsOrdered = std::vector( { + ( BOM_FIELD ){ + .name = "Reference", .label = "Reference", .show = true, .groupBy = false }, + ( BOM_FIELD ){ + .name = "Value", .label = "Value", .show = true, .groupBy = true }, + ( BOM_FIELD ){ + .name = "Datasheet", .label = "Datasheet", .show = true, .groupBy = false }, + ( BOM_FIELD ){ + .name = "Footprint", .label = "Footprint", .show = true, .groupBy = false }, + ( BOM_FIELD ){ + .name = "Quantity", .label = "Qty", .show = true, .groupBy = false }, + } ); + + return p; +} + + +BOM_PRESET BOM_PRESET::GroupedByValueFootprint() +{ + BOM_PRESET p = { .name = _HKI( "Grouped By Value and Footprint" ), + .readOnly = true, + .sortField = _( "Reference" ), + .sortAsc = true, + .groupSymbols = true }; + + p.fieldsOrdered = std::vector( { + ( BOM_FIELD ){ + .name = "Reference", .label = "Reference", .show = true, .groupBy = false }, + ( BOM_FIELD ){ + .name = "Value", .label = "Value", .show = true, .groupBy = true }, + ( BOM_FIELD ){ + .name = "Datasheet", .label = "Datasheet", .show = true, .groupBy = false }, + ( BOM_FIELD ){ + .name = "Footprint", .label = "Footprint", .show = true, .groupBy = true }, + ( BOM_FIELD ){ + .name = "Quantity", .label = "Qty", .show = true, .groupBy = false }, + } ); + + return p; +} + + +//Implementations for BOM_FMT_PRESET +bool BOM_FMT_PRESET::operator==( const BOM_FMT_PRESET& rhs ) const +{ + return this->name == rhs.name && this->readOnly == rhs.readOnly + && this->fieldDelimiter == rhs.fieldDelimiter + && this->stringDelimiter == rhs.stringDelimiter && this->refDelimiter == rhs.refDelimiter + && this->refRangeDelimiter == rhs.refRangeDelimiter && this->keepTabs == rhs.keepTabs + && this->keepLineBreaks == rhs.keepLineBreaks; +} + + +const bool operator!=( const BOM_FMT_PRESET& lhs, const BOM_FMT_PRESET& rhs ) +{ + return !( lhs == rhs ); +} + + +const bool operator<( const BOM_FMT_PRESET& lhs, const BOM_FMT_PRESET& rhs ) +{ + return lhs.name < rhs.name; +} + + +void to_json( nlohmann::json& j, const BOM_FMT_PRESET& p ) +{ + j = nlohmann::json{ { "name", p.name }, + { "field_delimiter", p.fieldDelimiter }, + { "string_delimiter", p.stringDelimiter }, + { "ref_delimiter", p.refDelimiter }, + { "ref_range_delimiter", p.refRangeDelimiter }, + { "keep_tabs", p.keepTabs }, + { "keep_line_breaks", p.keepLineBreaks } }; +} + + +void from_json( const nlohmann::json& j, BOM_FMT_PRESET& f ) +{ + j.at( "name" ).get_to( f.name ); + j.at( "field_delimiter" ).get_to( f.fieldDelimiter ); + j.at( "string_delimiter" ).get_to( f.stringDelimiter ); + j.at( "ref_delimiter" ).get_to( f.refDelimiter ); + j.at( "ref_range_delimiter" ).get_to( f.refRangeDelimiter ); + j.at( "keep_tabs" ).get_to( f.keepTabs ); + j.at( "keep_line_breaks" ).get_to( f.keepLineBreaks ); +} + + +BOM_FMT_PRESET BOM_FMT_PRESET::CSV() +{ + return ( BOM_FMT_PRESET ){ .name = _HKI( "CSV" ), + .readOnly = true, + .fieldDelimiter = wxS( "," ), + .stringDelimiter = wxT( "\"" ), + .refDelimiter = wxT( "," ), + .refRangeDelimiter = wxT( "" ), + .keepTabs = false, + .keepLineBreaks = false }; +} + +BOM_FMT_PRESET BOM_FMT_PRESET::TSV() +{ + return ( BOM_FMT_PRESET ){ .name = _HKI( "TSV" ), + .readOnly = true, + .fieldDelimiter = wxS( "\t" ), + .stringDelimiter = wxT( "" ), + .refDelimiter = wxT( "," ), + .refRangeDelimiter = wxT( "" ), + .keepTabs = false, + .keepLineBreaks = false }; +} + +BOM_FMT_PRESET BOM_FMT_PRESET::Semicolons() +{ + return ( BOM_FMT_PRESET ){ .name = _HKI( "Semicolons" ), + .readOnly = true, + .fieldDelimiter = wxS( ";" ), + .stringDelimiter = wxT( "'" ), + .refDelimiter = wxT( "," ), + .refRangeDelimiter = wxT( "" ), + .keepTabs = false, + .keepLineBreaks = false }; +} diff --git a/common/settings/json_settings.cpp b/common/settings/json_settings.cpp index 5c2e177d7d..557653f309 100644 --- a/common/settings/json_settings.cpp +++ b/common/settings/json_settings.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -565,6 +566,9 @@ template std::optional JSON_SETTINGS::Get JSON_SETTINGS::Get( const std::string& aPath ) const; template std::optional JSON_SETTINGS::Get( const std::string& aPath ) const; template std::optional JSON_SETTINGS::Get( const std::string& aPath ) const; +template std::optional JSON_SETTINGS::Get( const std::string& aPath ) const; +template std::optional JSON_SETTINGS::Get( const std::string& aPath ) const; +template std::optional JSON_SETTINGS::Get( const std::string& aPath ) const; template @@ -585,6 +589,9 @@ template void JSON_SETTINGS::Set( const std::string& aPath, const c template void JSON_SETTINGS::Set( const std::string& aPath, std::string aValue ); template void JSON_SETTINGS::Set( const std::string& aPath, nlohmann::json aValue ); template void JSON_SETTINGS::Set( const std::string& aPath, KIGFX::COLOR4D aValue ); +template void JSON_SETTINGS::Set( const std::string& aPath, BOM_FIELD aValue ); +template void JSON_SETTINGS::Set( const std::string& aPath, BOM_PRESET aValue ); +template void JSON_SETTINGS::Set( const std::string& aPath, BOM_FMT_PRESET aValue ); void JSON_SETTINGS::registerMigration( int aOldSchemaVersion, int aNewSchemaVersion, diff --git a/common/settings/parameters.cpp b/common/settings/parameters.cpp index ee8a9f61d6..781b6b0e28 100644 --- a/common/settings/parameters.cpp +++ b/common/settings/parameters.cpp @@ -25,7 +25,7 @@ #include #include #include - +#include template void PARAM_LAMBDA::Load( JSON_SETTINGS* aSettings, bool aResetIfMissing ) const @@ -136,6 +136,8 @@ template class PARAM_LIST; template class PARAM_LIST; template class PARAM_LIST; template class PARAM_LIST; +template class PARAM_LIST; +template class PARAM_LIST; template diff --git a/eeschema/dialogs/dialog_symbol_fields_table.cpp b/eeschema/dialogs/dialog_symbol_fields_table.cpp index da1fbe13ce..3ab67aedfe 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table.cpp +++ b/eeschema/dialogs/dialog_symbol_fields_table.cpp @@ -238,12 +238,12 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent ) // Load our BOM view presets SetUserBomPresets( m_schSettings.m_BomPresets ); - ApplyBomPreset( SCHEMATIC_SETTINGS::bomPresetGroupedByValueFootprint ); + ApplyBomPreset( m_schSettings.m_BomSettings ); syncBomPresetSelection(); // Load BOM export format presets SetUserBomFmtPresets( m_schSettings.m_BomFmtPresets ); - ApplyBomFmtPreset( SCHEMATIC_SETTINGS::bomFmtPresetCSV ); + ApplyBomFmtPreset( m_schSettings.m_BomFmtSettings ); syncBomFmtPresetSelection(); m_grid->SelectRow( 0 ); @@ -442,6 +442,18 @@ bool DIALOG_SYMBOL_FIELDS_TABLE::TransferDataFromWindow() if( !wxDialog::TransferDataFromWindow() ) return false; + // Save our BOM presets + std::vector presets; + + for( const std::pair& pair : m_bomPresets ) + { + if( !pair.second.readOnly ) + presets.emplace_back( pair.second ); + } + + m_schSettings.m_BomPresets = presets; + + SCH_SHEET_PATH currentSheet = m_parent->GetCurrentSheet(); std::function changeHandler = @@ -563,7 +575,8 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnAddField( wxCommandEvent& event ) std::string key( fieldName.ToUTF8() ); - m_parent->Schematic().Settings().m_BomSettings.fieldsOrdered.emplace_back( key ); + m_parent->Schematic().Settings().m_BomSettings.fieldsOrdered.emplace_back( + ( BOM_FIELD ){ .name = key, .label = key, .show = true, .groupBy = false } ); AddField( fieldName, fieldName, true, false, true ); wxGridTableMessage msg( m_dataModel, wxGRIDTABLE_NOTIFY_COLS_APPENDED, 1 ); @@ -834,7 +847,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnColMove( wxGridEvent& aEvent ) m_dataModel->MoveColumn( origPos, newPos ); - m_schSettings.m_BomSettings.fieldsOrdered = m_dataModel->GetFieldsOrder(); + m_schSettings.m_BomSettings.fieldsOrdered = m_dataModel->GetFieldsOrdered(); // "Unmove" the column since we've moved the column internally m_grid->ResetColPos(); @@ -1201,8 +1214,8 @@ void DIALOG_SYMBOL_FIELDS_TABLE::loadDefaultBomPresets() m_bomPresetMRU.clear(); // Load the read-only defaults - for( const BOM_PRESET& preset : { SCHEMATIC_SETTINGS::bomPresetGroupedByValue, - SCHEMATIC_SETTINGS::bomPresetGroupedByValueFootprint } ) + for( const BOM_PRESET& preset : { BOM_PRESET::GroupedByValue(), + BOM_PRESET::GroupedByValueFootprint() } ) { m_bomPresets[preset.name] = preset; m_bomPresets[preset.name].readOnly = true; @@ -1226,7 +1239,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::rebuildBomPresetsWidget() m_cbBomPresets->Append( wxGetTranslation( pair.first ), static_cast( &pair.second ) ); - if( pair.first == SCHEMATIC_SETTINGS::bomPresetGroupedByValueFootprint.name ) + if( pair.first == BOM_PRESET::GroupedByValue().name ) default_idx = idx; idx++; @@ -1247,20 +1260,36 @@ void DIALOG_SYMBOL_FIELDS_TABLE::rebuildBomPresetsWidget() void DIALOG_SYMBOL_FIELDS_TABLE::syncBomPresetSelection() { + // We need to check for matching an existing preset all the places we also + // need to update the settings, so do it here. + m_schSettings.m_BomSettings.fieldsOrdered = m_dataModel->GetFieldsOrdered(); + BOM_PRESET& current = m_parent->Schematic().Settings().m_BomSettings; auto it = std::find_if( m_bomPresets.begin(), m_bomPresets.end(), [&]( const std::pair& aPair ) { - return ( aPair.second.fieldsOrdered == current.fieldsOrdered - && aPair.second.fieldsLabels == current.fieldsLabels - && aPair.second.fieldsShow == current.fieldsShow - && aPair.second.fieldsGroupBy == current.fieldsGroupBy - && aPair.second.sortField == current.sortField - && aPair.second.sortAsc == current.sortAsc - && aPair.second.fieldsOrdered == current.fieldsOrdered - && aPair.second.filterString == current.filterString - && aPair.second.groupSymbols == current.groupSymbols ); + const BOM_PRESET& preset = aPair.second; + + // Check the simple settings first + if( !( preset.sortField == current.sortField + && preset.sortAsc == current.sortAsc + && preset.filterString == current.filterString + && preset.groupSymbols == current.groupSymbols ) ) + return false; + + // Only compare shown or grouped fields + std::vector A, B; + + for( auto field : preset.fieldsOrdered ) + if( field.show || field.groupBy ) + A.emplace_back( field ); + + for( auto field : current.fieldsOrdered ) + if( field.show || field.groupBy ) + B.emplace_back( field ); + + return A == B; } ); if( it != m_bomPresets.end() ) @@ -1356,14 +1385,13 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onBomPresetChanged( wxCommandEvent& aEvent ) if( !exists ) { - m_bomPresets[name] = BOM_PRESET( name, m_schSettings.m_BomSettings.fieldsOrdered, - m_schSettings.m_BomSettings.fieldsLabels, - m_schSettings.m_BomSettings.fieldsShow, - m_schSettings.m_BomSettings.fieldsGroupBy, - m_schSettings.m_BomSettings.sortField, - m_schSettings.m_BomSettings.sortAsc, - m_schSettings.m_BomSettings.filterString, - m_schSettings.m_BomSettings.groupSymbols ); + m_bomPresets[name] = + ( BOM_PRESET ){ .name = name, + .fieldsOrdered = m_schSettings.m_BomSettings.fieldsOrdered, + .sortField = m_schSettings.m_BomSettings.sortField, + .sortAsc = m_schSettings.m_BomSettings.sortAsc, + .filterString = m_schSettings.m_BomSettings.filterString, + .groupSymbols = m_schSettings.m_BomSettings.groupSymbols }; } BOM_PRESET* preset = &m_bomPresets[name]; @@ -1376,9 +1404,6 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onBomPresetChanged( wxCommandEvent& aEvent ) else { preset->fieldsOrdered = m_schSettings.m_BomSettings.fieldsOrdered; - preset->fieldsLabels = m_schSettings.m_BomSettings.fieldsLabels; - preset->fieldsShow = m_schSettings.m_BomSettings.fieldsShow; - preset->fieldsGroupBy = m_schSettings.m_BomSettings.fieldsGroupBy; preset->sortField = m_schSettings.m_BomSettings.sortField; preset->sortAsc = m_schSettings.m_BomSettings.sortAsc; preset->filterString = m_schSettings.m_BomSettings.filterString; @@ -1597,8 +1622,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::loadDefaultBomFmtPresets() // Load the read-only defaults for( const BOM_FMT_PRESET& preset : - { SCHEMATIC_SETTINGS::bomFmtPresetCSV, SCHEMATIC_SETTINGS::bomFmtPresetSemicolons, - SCHEMATIC_SETTINGS::bomFmtPresetTSV } ) + { BOM_FMT_PRESET::CSV(), BOM_FMT_PRESET::TSV(), BOM_FMT_PRESET::Semicolons() } ) { m_bomFmtPresets[preset.name] = preset; m_bomFmtPresets[preset.name].readOnly = true; @@ -1622,7 +1646,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::rebuildBomFmtPresetsWidget() m_cbBomFmtPresets->Append( wxGetTranslation( pair.first ), static_cast( &pair.second ) ); - if( pair.first == SCHEMATIC_SETTINGS::bomFmtPresetCSV.name ) + if( pair.first == BOM_FMT_PRESET::CSV().name ) default_idx = idx; idx++; @@ -1751,13 +1775,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onBomFmtPresetChanged( wxCommandEvent& aEvent ) if( !exists ) { - m_bomFmtPresets[name] = - BOM_FMT_PRESET( name, m_schSettings.m_BomFmtSettings.fieldDelimiter, - m_schSettings.m_BomFmtSettings.stringDelimiter, - m_schSettings.m_BomFmtSettings.refDelimiter, - m_schSettings.m_BomFmtSettings.refRangeDelimiter, - m_schSettings.m_BomFmtSettings.keepTabs, - m_schSettings.m_BomFmtSettings.keepLineBreaks ); + m_bomFmtPresets[name] = m_schSettings.m_BomFmtSettings; } BOM_FMT_PRESET* preset = &m_bomFmtPresets[name]; @@ -1769,12 +1787,8 @@ void DIALOG_SYMBOL_FIELDS_TABLE::onBomFmtPresetChanged( wxCommandEvent& aEvent ) } else { - preset->fieldDelimiter = m_schSettings.m_BomFmtSettings.fieldDelimiter; - preset->stringDelimiter = m_schSettings.m_BomFmtSettings.stringDelimiter; - preset->refDelimiter = m_schSettings.m_BomFmtSettings.refDelimiter; - preset->refRangeDelimiter = m_schSettings.m_BomFmtSettings.refRangeDelimiter; - preset->keepTabs = m_schSettings.m_BomFmtSettings.keepTabs; - preset->keepLineBreaks = m_schSettings.m_BomFmtSettings.keepLineBreaks; + *preset = m_schSettings.m_BomFmtSettings; + preset->name = name; index = m_cbBomFmtPresets->FindString( name ); m_bomFmtPresetMRU.Remove( name ); diff --git a/eeschema/eeschema_jobs_handler.cpp b/eeschema/eeschema_jobs_handler.cpp index 6daf9ae15b..91c1f36a01 100644 --- a/eeschema/eeschema_jobs_handler.cpp +++ b/eeschema/eeschema_jobs_handler.cpp @@ -308,10 +308,26 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob ) } BOM_PRESET preset; - preset.fieldsOrdered = aBomJob->m_fieldsOrdered; - preset.fieldsLabels = aBomJob->m_fieldsLabels; - preset.fieldsShow = aBomJob->m_fieldsOrdered; - preset.fieldsGroupBy = aBomJob->m_fieldsGroupBy; + + size_t i = 0; + for( wxString fieldName : aBomJob->m_fieldsOrdered ) + { + struct BOM_FIELD field; + + 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.groupSymbols = aBomJob->m_groupSymbols; diff --git a/eeschema/fields_data_model.cpp b/eeschema/fields_data_model.cpp index e56fcd080e..9274f97629 100644 --- a/eeschema/fields_data_model.cpp +++ b/eeschema/fields_data_model.cpp @@ -78,14 +78,15 @@ int FIELDS_EDITOR_GRID_DATA_MODEL::GetFieldNameCol( wxString aFieldName ) } -const std::vector FIELDS_EDITOR_GRID_DATA_MODEL::GetFieldsOrder() +const std::vector FIELDS_EDITOR_GRID_DATA_MODEL::GetFieldsOrdered() { - std::vector fields; + std::vector fields; for( auto col : m_cols ) - { - fields.emplace_back( col.m_fieldName ); - } + fields.emplace_back( ( struct BOM_FIELD ){ .name = col.m_fieldName, + .label = col.m_label, + .show = col.m_show, + .groupBy = col.m_group } ); return fields; } @@ -597,40 +598,34 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyBomPreset( const BOM_PRESET& aPreset ) SetGroupColumn( i, false ); } - // Set columns that are present and shown - for( size_t i = 0; i < aPreset.fieldsOrdered.size(); i++ ) - { - const wxString& fieldName = aPreset.fieldsOrdered[i]; - const wxString& label = - i < aPreset.fieldsLabels.size() ? aPreset.fieldsLabels[i] : fieldName; + std::vector order; - int col = GetFieldNameCol( fieldName ); + // Set columns that are present and shown + for( BOM_FIELD field : aPreset.fieldsOrdered ) + { + order.emplace_back( field.name ); + + int col = GetFieldNameCol( field.name ); // Add any missing fields, if the user doesn't add any data // they won't be saved to the symbols anywa if( col == -1 ) - AddColumn( fieldName, label, true ); + AddColumn( field.name, field.label, true ); else - SetColLabelValue( col, label ); + SetColLabelValue( col, field.label ); - SetShowColumn( col, true ); + SetGroupColumn( col, field.groupBy ); + SetShowColumn( col, field.show ); } // Set grouping columns SetGroupingEnabled( aPreset.groupSymbols ); - for( auto fieldName : aPreset.fieldsGroupBy ) - { - int col = GetFieldNameCol( fieldName ); - - if( col != -1 ) - SetGroupColumn( col, true ); - } - - SetFieldsOrder( aPreset.fieldsOrdered ); + SetFieldsOrder( order ); // Set our sorting int sortCol = GetFieldNameCol( aPreset.sortField ); + if( sortCol != -1 ) SetSorting( sortCol, aPreset.sortAsc ); else diff --git a/eeschema/fields_data_model.h b/eeschema/fields_data_model.h index d3453a5aff..fe022bcbb7 100644 --- a/eeschema/fields_data_model.h +++ b/eeschema/fields_data_model.h @@ -10,6 +10,7 @@ // The internal field name (untranslated) #define FIELD_NAME_COLUMN 4 +struct BOM_FIELD; struct BOM_PRESET; struct BOM_FMT_PRESET; @@ -89,7 +90,7 @@ public: int GetFieldNameCol( wxString aFieldName ); - const std::vector GetFieldsOrder(); + const std::vector GetFieldsOrdered(); void SetFieldsOrder( const std::vector& aNewOrder ); bool IsEmptyCell( int aRow, int aCol ) override diff --git a/eeschema/schematic_settings.cpp b/eeschema/schematic_settings.cpp index 74dfc02e18..3176dd63ae 100644 --- a/eeschema/schematic_settings.cpp +++ b/eeschema/schematic_settings.cpp @@ -26,46 +26,19 @@ #include #include #include +#include #include #include #include +#include #include #include +#include const int schSettingsSchemaVersion = 1; -BOM_PRESET SCHEMATIC_SETTINGS::bomPresetGroupedByValue( - _HKI( "Grouped By Value and Footprint" ), - std::vector( { "Reference", "Value", "Datasheet", "Footprint", "Quantity" } ), - std::vector( { "Reference", "Value", "Datasheet", "Footprint", "Qty" } ), - std::vector( { "Reference", "Value", "Datasheet", "Footprint", "Quantity" } ), - std::vector( { "Value" } ), _( "Reference" ), true, _HKI( "" ), true ); - - -BOM_PRESET SCHEMATIC_SETTINGS::bomPresetGroupedByValueFootprint( - _HKI( "Grouped By Value and Footprint" ), - std::vector( { "Reference", "Value", "Datasheet", "Footprint", "Quantity" } ), - std::vector( { "Reference", "Value", "Datasheet", "Footprint", "Qty" } ), - std::vector( { "Reference", "Value", "Datasheet", "Footprint", "Quantity" } ), - std::vector( { "Value", "Footprint" } ), _( "Reference" ), true, _HKI( "" ), - true ); - - -BOM_FMT_PRESET SCHEMATIC_SETTINGS::bomFmtPresetCSV( _HKI( "CSV" ), wxS( "," ), wxT( "\"" ), - wxT( "," ), wxT( "" ), false, false ); - - -BOM_FMT_PRESET SCHEMATIC_SETTINGS::bomFmtPresetTSV( _HKI( "TSV" ), wxS( "\t" ), wxT( "" ), - wxT( "," ), wxT( "" ), false, false ); - - -BOM_FMT_PRESET SCHEMATIC_SETTINGS::bomFmtPresetSemicolons( _HKI( "Semicolons" ), wxS( ";" ), - wxT( "'" ), wxT( "," ), wxT( "" ), false, - false ); - - SCHEMATIC_SETTINGS::SCHEMATIC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : NESTED_SETTINGS( "schematic", schSettingsSchemaVersion, aParent, aPath ), m_DefaultLineWidth( DEFAULT_LINE_WIDTH_MILS * schIUScale.IU_PER_MILS ), @@ -218,6 +191,16 @@ SCHEMATIC_SETTINGS::SCHEMATIC_SETTINGS( JSON_SETTINGS* aParent, const std::strin m_TemplateFieldNames.AddTemplateFieldNames( cfg->m_Drawing.field_names ); }, {} ) ); + m_params.emplace_back( + new PARAM( "bom_settings", &m_BomSettings, BOM_PRESET::GroupedByValue() ) ); + m_params.emplace_back( + new PARAM_LIST( "bom_presets", &m_BomPresets, {} ) ); + + m_params.emplace_back( + new PARAM( "bom_fmt_settings", &m_BomFmtSettings, BOM_FMT_PRESET::CSV() ) ); + m_params.emplace_back( + new PARAM_LIST( "bom_fmt_settings", &m_BomFmtPresets, {} ) ); + m_params.emplace_back( new PARAM( "page_layout_descr_file", &m_SchDrawingSheetFileName, "" ) ); diff --git a/eeschema/schematic_settings.h b/eeschema/schematic_settings.h index 87359f2e26..23ed5bdd97 100644 --- a/eeschema/schematic_settings.h +++ b/eeschema/schematic_settings.h @@ -24,75 +24,15 @@ #include #include +#include +#include #include +#include #include class NGSPICE_SIMULATOR_SETTINGS; -struct BOM_PRESET -{ - BOM_PRESET( const wxString& aName = wxEmptyString ) : name( aName ) {} - - BOM_PRESET( const wxString& aName, const std::vector& aFieldsOrdered, - const std::vector& aFieldsLabels, - const std::vector& aFieldsShow, - const std::vector& aFieldsGroupBy, const wxString& aSortField, - bool aSortAscending, const wxString& aFilterString, bool aGroupSymbols ) : - name( aName ), - fieldsOrdered( aFieldsOrdered ), fieldsLabels( aFieldsLabels ), - fieldsShow( aFieldsShow ), fieldsGroupBy( aFieldsGroupBy ), sortField( aSortField ), - sortAsc( aSortAscending ), filterString( aFilterString ), groupSymbols( aGroupSymbols ) - { - } - - wxString name; - bool readOnly = false; - std::vector fieldsOrdered; - std::vector fieldsLabels; - std::vector fieldsShow; - std::vector fieldsGroupBy; - wxString sortField; - bool sortAsc = true; - wxString filterString; - bool groupSymbols = false; -}; - - -struct BOM_FMT_PRESET -{ - BOM_FMT_PRESET( const wxString& aName = wxEmptyString ) : - name( aName ), readOnly( false ), fieldDelimiter( wxS( "\"" ) ), - stringDelimiter( wxS( "\"" ) ), refDelimiter( "," ), refRangeDelimiter( "" ), - keepTabs( true ), keepLineBreaks( true ) - { - } - - BOM_FMT_PRESET( const wxString& aName, const wxString& aFieldDelimiter, - const wxString& aStringDelimiter, const wxString& aRefDelimiter, - const wxString& aRefRangeDelimiter, bool removeTabs, bool removeLineBreaks ) : - name( aName ), - readOnly( false ), - fieldDelimiter( aFieldDelimiter ), - stringDelimiter( aStringDelimiter ), - refDelimiter( aRefDelimiter ), - refRangeDelimiter( aRefRangeDelimiter ), - keepTabs( removeTabs ), - keepLineBreaks( removeLineBreaks ) - { - } - - wxString name; - bool readOnly; - wxString fieldDelimiter; - wxString stringDelimiter; - wxString refDelimiter; - wxString refRangeDelimiter; - bool keepTabs; - bool keepLineBreaks; -}; - - /** * These settings were stored in SCH_BASE_FRAME previously. * The backing store is currently the project file. @@ -152,15 +92,10 @@ public: TEMPLATES m_TemplateFieldNames; /// List of stored BOM presets - static BOM_PRESET bomPresetGroupedByValue; - static BOM_PRESET bomPresetGroupedByValueFootprint; BOM_PRESET m_BomSettings; std::vector m_BomPresets; /// List of stored BOM format presets - static BOM_FMT_PRESET bomFmtPresetCSV; - static BOM_FMT_PRESET bomFmtPresetSemicolons; - static BOM_FMT_PRESET bomFmtPresetTSV; BOM_FMT_PRESET m_BomFmtSettings; std::vector m_BomFmtPresets; diff --git a/include/settings/bom_settings.h b/include/settings/bom_settings.h new file mode 100644 index 0000000000..e43e716cf6 --- /dev/null +++ b/include/settings/bom_settings.h @@ -0,0 +1,98 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 Mike Williams + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef _BOM_SETTINGS_H +#define _BOM_SETTINGS_H + + +#include +#include +#include + +// A single field within a BOM, e.g. Reference, Value, Footprint +struct BOM_FIELD +{ + wxString name; + wxString label; + bool show = false; + bool groupBy = false; + + bool operator==( const BOM_FIELD& rhs ) const; +}; + +const bool operator!=( const BOM_FIELD& lhs, const BOM_FIELD& rhs ); +const bool operator<( const BOM_FIELD& lhs, const BOM_FIELD& rhs ); + +void to_json( nlohmann::json& j, const BOM_FIELD& f ); +void from_json( const nlohmann::json& j, BOM_FIELD& f ); + + +// A complete preset defining a BOM "View" with a list of all the fields to show, +// group by, order, filtering settings, etc. +struct BOM_PRESET +{ + wxString name; + bool readOnly = false; + std::vector fieldsOrdered; + wxString sortField; + bool sortAsc = true; + wxString filterString; + bool groupSymbols = false; + + bool operator==( const BOM_PRESET& rhs ) const; + + static BOM_PRESET GroupedByValue(); + static BOM_PRESET GroupedByValueFootprint(); +}; + +const bool operator!=( const BOM_PRESET& lhs, const BOM_PRESET& rhs ); +const bool operator<( const BOM_PRESET& lhs, const BOM_PRESET& rhs ); + +void to_json( nlohmann::json& j, const BOM_PRESET& f ); +void from_json( const nlohmann::json& j, BOM_PRESET& f ); + + +// A formatting preset, like CSV (Comma Separated Values) +struct BOM_FMT_PRESET +{ + wxString name; + bool readOnly = false; + wxString fieldDelimiter; + wxString stringDelimiter; + wxString refDelimiter; + wxString refRangeDelimiter; + bool keepTabs = false; + bool keepLineBreaks = false; + + bool operator==( const BOM_FMT_PRESET& rhs ) const; + + static BOM_FMT_PRESET CSV(); + static BOM_FMT_PRESET TSV(); + static BOM_FMT_PRESET Semicolons(); +}; + +const bool operator!=( const BOM_FMT_PRESET& lhs, const BOM_FMT_PRESET& rhs ); +const bool operator<( const BOM_FMT_PRESET& lhs, const BOM_FMT_PRESET& rhs ); + +void to_json( nlohmann::json& j, const BOM_FMT_PRESET& f ); +void from_json( const nlohmann::json& j, BOM_FMT_PRESET& f ); + + +#endif