@@ -38,8 +38,9 @@ class Config:
38
38
html_config_fields = [
39
39
'dark_mode' , 'show_pads' , 'show_fabrication' , 'show_silkscreen' ,
40
40
'highlight_pin1' , 'redraw_on_drag' , 'board_rotation' , 'checkboxes' ,
41
- 'bom_view' , 'layer_view' , 'extra_fields'
41
+ 'bom_view' , 'layer_view'
42
42
]
43
+ default_show_group_fields = ["Value" , "Footprint" ]
43
44
44
45
# Defaults
45
46
@@ -70,7 +71,8 @@ class Config:
70
71
# Extra fields section
71
72
extra_data_file = None
72
73
netlist_initial_directory = '' # This is relative to pcb file directory
73
- extra_fields = []
74
+ show_fields = default_show_group_fields
75
+ group_fields = default_show_group_fields
74
76
normalize_field_case = False
75
77
board_variant_field = ''
76
78
board_variant_whitelist = []
@@ -79,7 +81,7 @@ class Config:
79
81
80
82
@staticmethod
81
83
def _split (s ):
82
- """Splits string by ',' and drops empty strings from resulting array. """
84
+ """Splits string by ',' and drops empty strings from resulting array"""
83
85
return [a .replace ('\\ ,' , ',' ) for a in re .split (r'(?<!\\),' , s ) if a ]
84
86
85
87
@staticmethod
@@ -99,9 +101,9 @@ def load_from_ini(self):
99
101
self .dark_mode = f .ReadBool ('dark_mode' , self .dark_mode )
100
102
self .show_pads = f .ReadBool ('show_pads' , self .show_pads )
101
103
self .show_fabrication = f .ReadBool (
102
- 'show_fabrication' , self .show_fabrication )
104
+ 'show_fabrication' , self .show_fabrication )
103
105
self .show_silkscreen = f .ReadBool (
104
- 'show_silkscreen' , self .show_silkscreen )
106
+ 'show_silkscreen' , self .show_silkscreen )
105
107
self .highlight_pin1 = f .ReadBool ('highlight_pin1' , self .highlight_pin1 )
106
108
self .redraw_on_drag = f .ReadBool ('redraw_on_drag' , self .redraw_on_drag )
107
109
self .board_rotation = f .ReadInt ('board_rotation' , self .board_rotation )
@@ -115,32 +117,33 @@ def load_from_ini(self):
115
117
self .bom_dest_dir = f .Read ('bom_dest_dir' , self .bom_dest_dir )
116
118
self .bom_name_format = f .Read ('bom_name_format' , self .bom_name_format )
117
119
self .component_sort_order = self ._split (f .Read (
118
- 'component_sort_order' ,
119
- ',' .join (self .component_sort_order )))
120
+ 'component_sort_order' ,
121
+ ',' .join (self .component_sort_order )))
120
122
self .component_blacklist = self ._split (f .Read (
121
- 'component_blacklist' ,
122
- ',' .join (self .component_blacklist )))
123
+ 'component_blacklist' ,
124
+ ',' .join (self .component_blacklist )))
123
125
self .blacklist_virtual = f .ReadBool (
124
- 'blacklist_virtual' , self .blacklist_virtual )
126
+ 'blacklist_virtual' , self .blacklist_virtual )
125
127
self .blacklist_empty_val = f .ReadBool (
126
- 'blacklist_empty_val' , self .blacklist_empty_val )
128
+ 'blacklist_empty_val' , self .blacklist_empty_val )
127
129
self .include_tracks = f .ReadBool ('include_tracks' , self .include_tracks )
128
130
self .include_nets = f .ReadBool ('include_nets' , self .include_nets )
129
131
130
- f .SetPath ('/extra_fields' )
131
- self .extra_fields = self ._split (f .Read (
132
- 'extra_fields' ,
133
- self ._join (self .extra_fields )))
132
+ f .SetPath ('/fields' )
133
+ self .show_fields = self ._split (f .Read (
134
+ 'show_fields' , self ._join (self .show_fields )))
135
+ self .group_fields = self ._split (f .Read (
136
+ 'group_fields' , self ._join (self .group_fields )))
134
137
self .normalize_field_case = f .ReadBool (
135
- 'normalize_field_case' , self .normalize_field_case )
138
+ 'normalize_field_case' , self .normalize_field_case )
136
139
self .board_variant_field = f .Read (
137
- 'board_variant_field' , self .board_variant_field )
140
+ 'board_variant_field' , self .board_variant_field )
138
141
self .board_variant_whitelist = self ._split (f .Read (
139
- 'board_variant_whitelist' ,
140
- ',' . join (self .board_variant_whitelist )))
142
+ 'board_variant_whitelist' ,
143
+ self . _join (self .board_variant_whitelist )))
141
144
self .board_variant_blacklist = self ._split (f .Read (
142
- 'board_variant_blacklist' ,
143
- ',' . join (self .board_variant_blacklist )))
145
+ 'board_variant_blacklist' ,
146
+ self . _join (self .board_variant_blacklist )))
144
147
self .dnp_field = f .Read ('dnp_field' , self .dnp_field )
145
148
146
149
def save (self ):
@@ -164,7 +167,7 @@ def save(self):
164
167
bom_dest_dir = self .bom_dest_dir
165
168
if bom_dest_dir .startswith (self .netlist_initial_directory ):
166
169
bom_dest_dir = os .path .relpath (
167
- bom_dest_dir , self .netlist_initial_directory )
170
+ bom_dest_dir , self .netlist_initial_directory )
168
171
f .Write ('bom_dest_dir' , bom_dest_dir )
169
172
f .Write ('bom_name_format' , self .bom_name_format )
170
173
f .Write ('component_sort_order' ,
@@ -176,14 +179,15 @@ def save(self):
176
179
f .WriteBool ('include_tracks' , self .include_tracks )
177
180
f .WriteBool ('include_nets' , self .include_nets )
178
181
179
- f .SetPath ('/extra_fields' )
180
- f .Write ('extra_fields' , self ._join (self .extra_fields ))
182
+ f .SetPath ('/fields' )
183
+ f .Write ('show_fields' , self ._join (self .show_fields ))
184
+ f .Write ('group_fields' , self ._join (self .group_fields ))
181
185
f .WriteBool ('normalize_field_case' , self .normalize_field_case )
182
186
f .Write ('board_variant_field' , self .board_variant_field )
183
187
f .Write ('board_variant_whitelist' ,
184
- ',' . join (self .board_variant_whitelist ))
188
+ self . _join (self .board_variant_whitelist ))
185
189
f .Write ('board_variant_blacklist' ,
186
- ',' . join (self .board_variant_blacklist ))
190
+ self . _join (self .board_variant_blacklist ))
187
191
f .Write ('dnp_field' , self .dnp_field )
188
192
f .Flush ()
189
193
@@ -216,19 +220,20 @@ def set_from_dialog(self, dlg):
216
220
self .include_tracks = dlg .general .includeTracksCheckbox .IsChecked ()
217
221
self .include_nets = dlg .general .includeNetsCheckbox .IsChecked ()
218
222
219
- # Extra fields
220
- self .extra_data_file = dlg .extra .extraDataFilePicker .Path
221
- self .extra_fields = list (dlg .extra .extraFieldsList .GetCheckedStrings ())
222
- self .normalize_field_case = dlg .extra .normalizeCaseCheckbox .Value
223
- self .board_variant_field = dlg .extra .boardVariantFieldBox .Value
224
- if self .board_variant_field == dlg .extra .NONE_STRING :
223
+ # Fields
224
+ self .extra_data_file = dlg .fields .extraDataFilePicker .Path
225
+ self .show_fields = dlg .fields .GetShowFields ()
226
+ self .group_fields = dlg .fields .GetGroupFields ()
227
+ self .normalize_field_case = dlg .fields .normalizeCaseCheckbox .Value
228
+ self .board_variant_field = dlg .fields .boardVariantFieldBox .Value
229
+ if self .board_variant_field == dlg .fields .NONE_STRING :
225
230
self .board_variant_field = ''
226
231
self .board_variant_whitelist = list (
227
- dlg .extra .boardVariantWhitelist .GetCheckedStrings ())
232
+ dlg .fields .boardVariantWhitelist .GetCheckedStrings ())
228
233
self .board_variant_blacklist = list (
229
- dlg .extra .boardVariantBlacklist .GetCheckedStrings ())
230
- self .dnp_field = dlg .extra .dnpFieldBox .Value
231
- if self .dnp_field == dlg .extra .NONE_STRING :
234
+ dlg .fields .boardVariantBlacklist .GetCheckedStrings ())
235
+ self .dnp_field = dlg .fields .dnpFieldBox .Value
236
+ if self .dnp_field == dlg .fields .NONE_STRING :
232
237
self .dnp_field = ''
233
238
234
239
def transfer_to_dialog (self , dlg ):
@@ -243,9 +248,9 @@ def transfer_to_dialog(self, dlg):
243
248
dlg .html .boardRotationSlider .Value = self .board_rotation
244
249
dlg .html .bomCheckboxesCtrl .Value = self .checkboxes
245
250
dlg .html .bomDefaultView .Selection = self .bom_view_choices .index (
246
- self .bom_view )
251
+ self .bom_view )
247
252
dlg .html .layerDefaultView .Selection = self .layer_view_choices .index (
248
- self .layer_view )
253
+ self .layer_view )
249
254
dlg .html .compressionCheckbox .Value = self .compression
250
255
dlg .html .openBrowserCheckbox .Value = self .open_browser
251
256
@@ -255,7 +260,7 @@ def transfer_to_dialog(self, dlg):
255
260
dlg .general .bomDirPicker .Path = self .bom_dest_dir
256
261
else :
257
262
dlg .general .bomDirPicker .Path = os .path .join (
258
- self .netlist_initial_directory , self .bom_dest_dir )
263
+ self .netlist_initial_directory , self .bom_dest_dir )
259
264
dlg .general .fileNameFormatTextControl .Value = self .bom_name_format
260
265
dlg .general .componentSortOrderBox .SetItems (self .component_sort_order )
261
266
dlg .general .blacklistBox .SetItems (self .component_blacklist )
@@ -264,28 +269,28 @@ def transfer_to_dialog(self, dlg):
264
269
dlg .general .includeTracksCheckbox .Value = self .include_tracks
265
270
dlg .general .includeNetsCheckbox .Value = self .include_nets
266
271
267
- # Extra fields
268
- dlg .extra .extraDataFilePicker .SetInitialDirectory (
269
- self .netlist_initial_directory )
272
+ # Fields
273
+ dlg .fields .extraDataFilePicker .SetInitialDirectory (
274
+ self .netlist_initial_directory )
270
275
271
276
def safe_set_checked_strings (clb , strings ):
272
- safe_strings = list (clb .GetStrings ())
273
- if safe_strings :
274
- present_strings = [s for s in strings if s in safe_strings ]
275
- not_present_strings = [s for s in safe_strings if s not in strings ]
277
+ current = list (clb .GetStrings ())
278
+ if current :
279
+ present_strings = [s for s in strings if s in current ]
280
+ not_present_strings = [s for s in current if s not in strings ]
276
281
clb .Clear ()
277
282
clb .InsertItems (present_strings + not_present_strings , 0 )
278
283
clb .SetCheckedStrings (present_strings )
279
284
280
- safe_set_checked_strings ( dlg .extra . extraFieldsList , self .extra_fields )
281
- dlg .extra .normalizeCaseCheckbox .Value = self .normalize_field_case
282
- dlg .extra .boardVariantFieldBox .Value = self .board_variant_field
283
- dlg .extra .OnBoardVariantFieldChange (None )
284
- safe_set_checked_strings (dlg .extra .boardVariantWhitelist ,
285
+ dlg .fields . SetCheckedFields ( self . show_fields , self .group_fields )
286
+ dlg .fields .normalizeCaseCheckbox .Value = self .normalize_field_case
287
+ dlg .fields .boardVariantFieldBox .Value = self .board_variant_field
288
+ dlg .fields .OnBoardVariantFieldChange (None )
289
+ safe_set_checked_strings (dlg .fields .boardVariantWhitelist ,
285
290
self .board_variant_whitelist )
286
- safe_set_checked_strings (dlg .extra .boardVariantBlacklist ,
291
+ safe_set_checked_strings (dlg .fields .boardVariantBlacklist ,
287
292
self .board_variant_blacklist )
288
- dlg .extra .dnpFieldBox .Value = self .dnp_field
293
+ dlg .fields .dnpFieldBox .Value = self .dnp_field
289
294
290
295
dlg .finish_init ()
291
296
@@ -350,24 +355,31 @@ def add_options(self, parser, file_name_format_hint):
350
355
parser .add_argument ('--blacklist' ,
351
356
default = ',' .join (self .component_blacklist ),
352
357
help = 'List of comma separated blacklisted '
353
- 'components or prefixes with *. E.g. "X1,MH*"' )
358
+ 'components or prefixes with *. '
359
+ 'E.g. "X1,MH*"' )
354
360
parser .add_argument ('--no-blacklist-virtual' , action = 'store_true' ,
355
361
help = 'Do not blacklist virtual components.' )
356
362
parser .add_argument ('--blacklist-empty-val' , action = 'store_true' ,
357
363
help = 'Blacklist components with empty value.' )
358
364
359
- # Extra fields section
365
+ # Fields section
360
366
parser .add_argument ('--netlist-file' ,
361
367
help = '(Deprecated) Path to netlist or xml file.' )
362
368
parser .add_argument ('--extra-data-file' ,
363
369
help = 'Path to netlist or xml file.' )
364
370
parser .add_argument ('--extra-fields' ,
365
- default = self ._join (self .extra_fields ),
366
- help = 'Comma separated list of extra fields to '
367
- 'pull from netlist or xml file.' )
371
+ help = 'Passing --extra-fields "X,Y" is a shortcut '
372
+ 'for --show-fields and --group-fields '
373
+ 'with values "Value,Footprint,X,Y"' )
374
+ parser .add_argument ('--show-fields' ,
375
+ default = self ._join (self .show_fields ),
376
+ help = 'List of fields to show in the BOM.' )
377
+ parser .add_argument ('--group-fields' ,
378
+ default = self ._join (self .group_fields ),
379
+ help = 'Fields that components will be grouped by.' )
368
380
parser .add_argument ('--normalize-field-case' ,
369
381
help = 'Normalize extra field name case. E.g. "MPN" '
370
- 'and "mpn" will be considered the same field.' ,
382
+ ', "mpn" will be considered the same field.' ,
371
383
action = 'store_true' )
372
384
parser .add_argument ('--variant-field' ,
373
385
help = 'Name of the extra field that stores board '
@@ -380,8 +392,8 @@ def add_options(self, parser, file_name_format_hint):
380
392
'exclude from the BOM.' )
381
393
parser .add_argument ('--dnp-field' , default = self .dnp_field ,
382
394
help = 'Name of the extra field that indicates '
383
- 'do not populate status. Components with this '
384
- 'field not empty will be blacklisted .' )
395
+ 'do not populate status. Components with '
396
+ 'this field not empty will be excluded .' )
385
397
386
398
def set_from_args (self , args ):
387
399
# type: (argparse.Namespace) -> None
@@ -411,9 +423,15 @@ def set_from_args(self, args):
411
423
self .include_tracks = args .include_tracks
412
424
self .include_nets = args .include_nets
413
425
414
- # Extra
426
+ # Fields
415
427
self .extra_data_file = args .extra_data_file or args .netlist_file
416
- self .extra_fields = self ._split (args .extra_fields )
428
+ if args .extra_fields is not None :
429
+ self .show_fields = self .default_show_group_fields + \
430
+ self ._split (args .extra_fields )
431
+ self .group_fields = self .show_fields
432
+ else :
433
+ self .show_fields = self ._split (args .show_fields )
434
+ self .group_fields = self ._split (args .group_fields )
417
435
self .normalize_field_case = args .normalize_field_case
418
436
self .board_variant_field = args .variant_field
419
437
self .board_variant_whitelist = self ._split (args .variants_whitelist )
@@ -423,7 +441,5 @@ def set_from_args(self, args):
423
441
def get_html_config (self ):
424
442
import json
425
443
d = {f : getattr (self , f ) for f in self .html_config_fields }
426
- # Temporary until currently hardcoded columns are made configurable
427
- d ["fields" ] = ["References" ] + self .extra_fields + \
428
- ["Value" , "Footprint" , "Quantity" ]
444
+ d ["fields" ] = self .show_fields
429
445
return json .dumps (d )
0 commit comments