Skip to content

Commit 38719da

Browse files
committed
Add support for native variants from kicad 10
Fixes #540
1 parent 3c2b236 commit 38719da

6 files changed

Lines changed: 3458 additions & 3298 deletions

File tree

InteractiveHtmlBom/core/config.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ class Config:
8181
board_variant_blacklist = []
8282
dnp_field = ''
8383

84+
# this is cli only field
85+
kicad_variant = ''
86+
8487
@staticmethod
8588
def _split(s):
8689
"""Splits string by ',' and drops empty strings from resulting array"""
@@ -323,14 +326,21 @@ def safe_set_checked_strings(clb, strings):
323326
self.board_variant_blacklist)
324327
dlg.fields.dnpFieldBox.Value = self.dnp_field
325328

329+
if self.kicad_variant != '':
330+
dlg.fields.variantLabel.Show()
331+
dlg.fields.variantLabel.SetLabel(f'Current variant: {self.kicad_variant}')
332+
326333
dlg.finish_init()
327334

328335
@classmethod
329336
def add_options(cls, parser, version):
330337
# type: (argparse.ArgumentParser, str) -> None
331338
parser.add_argument('--show-dialog', action='store_true',
332-
help='Shows config dialog. All other flags '
333-
'will be ignored.')
339+
help='Shows config dialog. All flags except '
340+
'--kicad-variant will be ignored.')
341+
parser.add_argument('--kicad-variant', default='',
342+
help='KiCad board variant, empty is default '
343+
'variant. (Only for KiCad v10+)')
334344
parser.add_argument('--version', action='version', version=version)
335345
# Html
336346
parser.add_argument('--dark-mode', help='Default to dark mode.',
@@ -443,6 +453,8 @@ def set_from_args(self, args):
443453
# type: (argparse.Namespace) -> None
444454
import math
445455

456+
self.kicad_variant = args.kicad_variant
457+
446458
# Html
447459
self.dark_mode = args.dark_mode
448460
self.show_pads = not args.hide_pads

InteractiveHtmlBom/dialog/dialog_base.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33
###########################################################################
4-
## Python code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
4+
## Python code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
55
## http://www.wxformbuilder.org/
66
##
77
## PLEASE DO *NOT* EDIT THIS FILE!
@@ -413,6 +413,13 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
413413
self.extraDataFilePicker = wx.FilePickerCtrl( sbSizer7.GetStaticBox(), wx.ID_ANY, wx.EmptyString, u"Select a file", u"Netlist and xml files (*.net; *.xml)|*.net;*.xml", wx.DefaultPosition, wx.DefaultSize, wx.FLP_DEFAULT_STYLE|wx.FLP_FILE_MUST_EXIST|wx.FLP_OPEN|wx.FLP_SMALL|wx.FLP_USE_TEXTCTRL|wx.BORDER_SIMPLE )
414414
sbSizer7.Add( self.extraDataFilePicker, 0, wx.EXPAND|wx.BOTTOM|wx.RIGHT|wx.LEFT, 5 )
415415

416+
self.variantLabel = wx.StaticText( sbSizer7.GetStaticBox(), wx.ID_ANY, u"Current variant:", wx.DefaultPosition, wx.DefaultSize, 0 )
417+
self.variantLabel.Wrap( -1 )
418+
419+
self.variantLabel.Hide()
420+
421+
sbSizer7.Add( self.variantLabel, 0, wx.ALL, 5 )
422+
416423

417424
bSizer42.Add( sbSizer7, 0, wx.ALL|wx.EXPAND, 5 )
418425

InteractiveHtmlBom/dialog/settings_dialog.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,11 @@ def OnExtraDataFileChanged(self, event):
334334
self.extra_field_data = self.extra_data_func(
335335
extra_data_file, self.normalizeCaseCheckbox.Value)
336336
except Exception as e:
337+
import traceback
337338
pop_error(
338-
"Failed to parse file %s\n\n%s" % (extra_data_file, e))
339+
"Failed to parse file %s\n\n%s" % (
340+
extra_data_file,
341+
str(e) + '\n' + traceback.format_exc()))
339342
self.extraDataFilePicker.Path = ''
340343

341344
if self.extra_field_data is not None:

InteractiveHtmlBom/ecad/kicad.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ def __init__(self, file_name, config, logger, board=None):
3030
self.board = board
3131
if self.board is None:
3232
self.board = pcbnew.LoadBoard(self.file_name) # type: pcbnew.BOARD
33+
if not self.board:
34+
raise Exception('Failed to load board file')
35+
if hasattr(self.board, "SetCurrentVariant"):
36+
self.board.SetCurrentVariant(config.kicad_variant)
3337
if hasattr(self.board, 'GetModules'):
3438
# type: list[pcbnew.MODULE]
3539
self.footprints = list(self.board.GetModules())
@@ -48,8 +52,7 @@ def get_extra_field_data(self, file_name):
4852

4953
return ExtraFieldData(data[0], data[1])
5054

51-
@staticmethod
52-
def get_footprint_fields(f):
55+
def get_footprint_fields(self, f):
5356
# type: (pcbnew.FOOTPRINT) -> dict
5457
props = {}
5558
if hasattr(f, "GetProperties"):
@@ -62,6 +65,15 @@ def get_footprint_fields(f):
6265
if hasattr(f, "IsDNP"):
6366
if f.IsDNP():
6467
props["kicad_dnp"] = "DNP"
68+
if hasattr(f, 'GetVariant'):
69+
variant = f.GetVariant(self.config.kicad_variant)
70+
if variant:
71+
var_fields = variant.GetFields()
72+
for k in var_fields.keys():
73+
props[str(k)] = str(f.GetFieldShownText(str(k)))
74+
if variant.GetDNP():
75+
props["kicad_dnp"] = "DNP"
76+
6577
return props
6678

6779
def parse_extra_data_from_pcb(self):
@@ -742,8 +754,7 @@ def parse_netlist(net_info):
742754
nets = sorted([str(s) for s in nets])
743755
return nets
744756

745-
@staticmethod
746-
def footprint_to_component(footprint, extra_fields):
757+
def footprint_to_component(self, footprint, extra_fields):
747758
try:
748759
footprint_name = str(footprint.GetFPID().GetFootprintName())
749760
except AttributeError:
@@ -753,6 +764,10 @@ def footprint_to_component(footprint, extra_fields):
753764
if hasattr(pcbnew, 'FP_EXCLUDE_FROM_BOM'):
754765
if footprint.GetAttributes() & pcbnew.FP_EXCLUDE_FROM_BOM:
755766
attr = 'Virtual'
767+
if hasattr(footprint, 'GetExcludedFromBOMForVariant'):
768+
if footprint.GetExcludedFromBOMForVariant(
769+
self.config.kicad_variant):
770+
attr = 'Virtual'
756771
elif hasattr(pcbnew, 'MOD_VIRTUAL'):
757772
if footprint.GetAttributes() == pcbnew.MOD_VIRTUAL:
758773
attr = 'Virtual'
@@ -912,14 +927,17 @@ def Run(self):
912927
from ..errors import ParsingException
913928

914929
logger = ibom.Logger()
915-
board = pcbnew.GetBoard()
930+
board = pcbnew.GetBoard() # type: pcbnew.BOARD
916931
pcb_file_name = board.GetFileName()
917932

918933
if not pcb_file_name:
919934
logger.error('Please save the board file before generating BOM.')
920935
return
921936

922937
config = Config(version, os.path.dirname(pcb_file_name))
938+
if hasattr(board, 'GetCurrentVariant'):
939+
config.kicad_variant = board.GetCurrentVariant()
940+
923941
parser = PcbnewParser(pcb_file_name, config, logger, board)
924942

925943
try:

InteractiveHtmlBom/generate_interactive_bom.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def main():
6666
print("Loading %s" % args.file)
6767

6868
config = Config(version, os.path.dirname(os.path.abspath(args.file)))
69+
config.kicad_variant = args.kicad_variant
6970

7071
parser = get_parser_by_extension(
7172
os.path.abspath(args.file), config, logger)

0 commit comments

Comments
 (0)