Symbol Fields Table: BOM presets saved in JSON settings

This commit is contained in:
Mike Williams 2023-03-27 16:48:37 -04:00
parent 753ae21fd4
commit c5cc313da9
11 changed files with 476 additions and 171 deletions

View File

@ -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

View File

@ -0,0 +1,253 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 Mike Williams <mike@mikebwilliams.com>
* 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 <http://www.gnu.org/licenses/>.
*/
#include <settings/bom_settings.h>
#include <nlohmann/json.hpp>
#include <wx/translation.h>
namespace nlohmann
{
template <>
struct adl_serializer<wxString>
{
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<std::string>().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>( {
( 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>( {
( 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 };
}

View File

@ -30,6 +30,7 @@
#include <settings/json_settings_internals.h>
#include <settings/nested_settings.h>
#include <settings/parameters.h>
#include <settings/bom_settings.h>
#include <wx/config.h>
#include <wx/debug.h>
#include <wx/fileconf.h>
@ -565,6 +566,9 @@ template std::optional<unsigned long long> JSON_SETTINGS::Get<unsigned long long
template std::optional<std::string> JSON_SETTINGS::Get<std::string>( const std::string& aPath ) const;
template std::optional<nlohmann::json> JSON_SETTINGS::Get<nlohmann::json>( const std::string& aPath ) const;
template std::optional<KIGFX::COLOR4D> JSON_SETTINGS::Get<KIGFX::COLOR4D>( const std::string& aPath ) const;
template std::optional<BOM_FIELD> JSON_SETTINGS::Get<BOM_FIELD>( const std::string& aPath ) const;
template std::optional<BOM_PRESET> JSON_SETTINGS::Get<BOM_PRESET>( const std::string& aPath ) const;
template std::optional<BOM_FMT_PRESET> JSON_SETTINGS::Get<BOM_FMT_PRESET>( const std::string& aPath ) const;
template<typename ValueType>
@ -585,6 +589,9 @@ template void JSON_SETTINGS::Set<const char*>( const std::string& aPath, const c
template void JSON_SETTINGS::Set<std::string>( const std::string& aPath, std::string aValue );
template void JSON_SETTINGS::Set<nlohmann::json>( const std::string& aPath, nlohmann::json aValue );
template void JSON_SETTINGS::Set<KIGFX::COLOR4D>( const std::string& aPath, KIGFX::COLOR4D aValue );
template void JSON_SETTINGS::Set<BOM_FIELD>( const std::string& aPath, BOM_FIELD aValue );
template void JSON_SETTINGS::Set<BOM_PRESET>( const std::string& aPath, BOM_PRESET aValue );
template void JSON_SETTINGS::Set<BOM_FMT_PRESET>( const std::string& aPath, BOM_FMT_PRESET aValue );
void JSON_SETTINGS::registerMigration( int aOldSchemaVersion, int aNewSchemaVersion,

View File

@ -25,7 +25,7 @@
#include <gal/color4d.h>
#include <project/project_file.h>
#include <settings/parameters.h>
#include <settings/bom_settings.h>
template <typename ValueType>
void PARAM_LAMBDA<ValueType>::Load( JSON_SETTINGS* aSettings, bool aResetIfMissing ) const
@ -136,6 +136,8 @@ template class PARAM_LIST<double>;
template class PARAM_LIST<wxString>;
template class PARAM_LIST<KIGFX::COLOR4D>;
template class PARAM_LIST<FILE_INFO_PAIR>;
template class PARAM_LIST<BOM_PRESET>;
template class PARAM_LIST<BOM_FMT_PRESET>;
template <typename ValueType>

View File

@ -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<BOM_PRESET> presets;
for( const std::pair<const wxString, BOM_PRESET>& 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<void( SCH_SYMBOL&, SCH_SHEET_PATH & aPath )> 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<void*>( &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<const wxString, BOM_PRESET>& 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<BOM_FIELD> 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<void*>( &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 );

View File

@ -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;

View File

@ -78,14 +78,15 @@ int FIELDS_EDITOR_GRID_DATA_MODEL::GetFieldNameCol( wxString aFieldName )
}
const std::vector<wxString> FIELDS_EDITOR_GRID_DATA_MODEL::GetFieldsOrder()
const std::vector<BOM_FIELD> FIELDS_EDITOR_GRID_DATA_MODEL::GetFieldsOrdered()
{
std::vector<wxString> fields;
std::vector<BOM_FIELD> 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<wxString> 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

View File

@ -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<wxString> GetFieldsOrder();
const std::vector<BOM_FIELD> GetFieldsOrdered();
void SetFieldsOrder( const std::vector<wxString>& aNewOrder );
bool IsEmptyCell( int aRow, int aCol ) override

View File

@ -26,46 +26,19 @@
#include <macros.h>
#include <pgm_base.h>
#include <schematic_settings.h>
#include <settings/json_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h>
#include <settings/settings_manager.h>
#include <settings/bom_settings.h>
#include <sim/spice_settings.h>
#include <i18n_utility.h>
#include <wx/string.h>
const int schSettingsSchemaVersion = 1;
BOM_PRESET SCHEMATIC_SETTINGS::bomPresetGroupedByValue(
_HKI( "Grouped By Value and Footprint" ),
std::vector<wxString>( { "Reference", "Value", "Datasheet", "Footprint", "Quantity" } ),
std::vector<wxString>( { "Reference", "Value", "Datasheet", "Footprint", "Qty" } ),
std::vector<wxString>( { "Reference", "Value", "Datasheet", "Footprint", "Quantity" } ),
std::vector<wxString>( { "Value" } ), _( "Reference" ), true, _HKI( "" ), true );
BOM_PRESET SCHEMATIC_SETTINGS::bomPresetGroupedByValueFootprint(
_HKI( "Grouped By Value and Footprint" ),
std::vector<wxString>( { "Reference", "Value", "Datasheet", "Footprint", "Quantity" } ),
std::vector<wxString>( { "Reference", "Value", "Datasheet", "Footprint", "Qty" } ),
std::vector<wxString>( { "Reference", "Value", "Datasheet", "Footprint", "Quantity" } ),
std::vector<wxString>( { "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_PRESET>( "bom_settings", &m_BomSettings, BOM_PRESET::GroupedByValue() ) );
m_params.emplace_back(
new PARAM_LIST<BOM_PRESET>( "bom_presets", &m_BomPresets, {} ) );
m_params.emplace_back(
new PARAM<BOM_FMT_PRESET>( "bom_fmt_settings", &m_BomFmtSettings, BOM_FMT_PRESET::CSV() ) );
m_params.emplace_back(
new PARAM_LIST<BOM_FMT_PRESET>( "bom_fmt_settings", &m_BomFmtPresets, {} ) );
m_params.emplace_back( new PARAM<wxString>( "page_layout_descr_file",
&m_SchDrawingSheetFileName, "" ) );

View File

@ -24,75 +24,15 @@
#include <default_values.h>
#include <settings/nested_settings.h>
#include <settings/parameters.h>
#include <settings/bom_settings.h>
#include <template_fieldnames.h>
#include <nlohmann/json.hpp>
#include <utility>
class NGSPICE_SIMULATOR_SETTINGS;
struct BOM_PRESET
{
BOM_PRESET( const wxString& aName = wxEmptyString ) : name( aName ) {}
BOM_PRESET( const wxString& aName, const std::vector<wxString>& aFieldsOrdered,
const std::vector<wxString>& aFieldsLabels,
const std::vector<wxString>& aFieldsShow,
const std::vector<wxString>& 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<wxString> fieldsOrdered;
std::vector<wxString> fieldsLabels;
std::vector<wxString> fieldsShow;
std::vector<wxString> 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<BOM_PRESET> 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<BOM_FMT_PRESET> m_BomFmtPresets;

View File

@ -0,0 +1,98 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 Mike Williams <mike@mikebwilliams.com>
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _BOM_SETTINGS_H
#define _BOM_SETTINGS_H
#include <settings/json_settings.h>
#include <settings/parameters.h>
#include <i18n_utility.h>
// 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<BOM_FIELD> 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