Skip to content

Commit e32d068

Browse files
committed
Implement saving settings
1 parent b2b305f commit e32d068

File tree

6 files changed

+144
-44
lines changed

6 files changed

+144
-44
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
test
55
releases
66
demo
7+
config.ini

InteractiveHtmlBom/config.py

Lines changed: 105 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
"""Config object"""
22

33
import argparse
4+
import os
5+
6+
from wx import FileConfig
47

58
import dialog.settings_dialog
69

710

811
class Config:
912
# Helper constants
13+
config_file = os.path.join(os.path.dirname(__file__), 'config.ini')
1014
bom_view_choices = ['bom-only', 'left-right', 'top-bottom']
1115
layer_view_choices = ['F', 'FB', 'B']
1216
default_sort_order = [
@@ -29,8 +33,8 @@ class Config:
2933
redraw_on_drag = True
3034
board_rotation = 0
3135
checkboxes = ','.join(default_checkboxes)
32-
bom_view = 1
33-
layer_view = 1
36+
bom_view = bom_view_choices[1]
37+
layer_view = layer_view_choices[1]
3438
open_browser = True
3539

3640
# General section
@@ -49,8 +53,88 @@ class Config:
4953
dnp_field = ''
5054

5155
def __init__(self):
52-
"""Init with defaults"""
53-
pass
56+
"""Init from config file if it exists."""
57+
if not os.path.isfile(self.config_file):
58+
return
59+
f = FileConfig(localFilename=self.config_file)
60+
61+
f.SetPath('/html_defaults')
62+
self.dark_mode = f.ReadBool('dark_mode', self.dark_mode)
63+
self.show_silkscreen = f.ReadBool(
64+
'show_silkscreen', self.show_silkscreen)
65+
self.highlight_pin1 = f.ReadBool('highlight_pin1', self.highlight_pin1)
66+
self.redraw_on_drag = f.ReadBool('redraw_on_drag', self.redraw_on_drag)
67+
self.board_rotation = f.ReadInt('board_rotation', self.board_rotation)
68+
self.checkboxes = f.Read('checkboxes', self.checkboxes)
69+
self.bom_view = f.Read('bom_view', self.bom_view)
70+
self.layer_view = f.Read('layer_view', self.layer_view)
71+
self.open_browser = f.ReadBool('open_browser', self.open_browser)
72+
73+
f.SetPath('/general')
74+
self.bom_dest_dir = f.Read('bom_dest_dir', self.bom_dest_dir)
75+
self.component_sort_order = f.Read(
76+
'component_sort_order',
77+
','.join(self.component_sort_order)
78+
).split(',')
79+
self.component_blacklist = f.Read(
80+
'component_blacklist',
81+
','.join(self.component_blacklist)
82+
).split(',')
83+
self.blacklist_virtual = f.ReadBool(
84+
'blacklist_virtual', self.blacklist_virtual)
85+
86+
f.SetPath('/extra_fields')
87+
self.extra_fields = f.Read(
88+
'extra_fields',
89+
','.join(self.extra_fields)
90+
).split(',')
91+
self.board_variant_field = f.Read(
92+
'board_variant_field', self.board_variant_field)
93+
self.board_variant_whitelist = f.Read(
94+
'board_variant_whitelist',
95+
','.join(self.board_variant_whitelist)
96+
).split(',')
97+
self.board_variant_blacklist = f.Read(
98+
'board_variant_blacklist',
99+
','.join(self.board_variant_blacklist)
100+
).split(',')
101+
self.dnp_field = f.Read('dnp_field', self.dnp_field)
102+
103+
def save(self):
104+
f = FileConfig(localFilename=self.config_file)
105+
106+
f.SetPath('/html_defaults')
107+
f.WriteBool('dark_mode', self.dark_mode)
108+
f.WriteBool('show_silkscreen', self.show_silkscreen)
109+
f.WriteBool('highlight_pin1', self.highlight_pin1)
110+
f.WriteBool('redraw_on_drag', self.redraw_on_drag)
111+
f.WriteInt('board_rotation', self.board_rotation)
112+
f.Write('checkboxes', self.checkboxes)
113+
f.Write('bom_view', self.bom_view)
114+
f.Write('layer_view', self.layer_view)
115+
f.WriteBool('open_browser', self.open_browser)
116+
117+
f.SetPath('/general')
118+
bom_dest_dir = self.bom_dest_dir
119+
if bom_dest_dir.startswith(self.netlist_initial_directory):
120+
bom_dest_dir = os.path.relpath(
121+
bom_dest_dir, self.netlist_initial_directory)
122+
f.Write('bom_dest_dir', bom_dest_dir)
123+
f.Write('component_sort_order',
124+
','.join(self.component_sort_order))
125+
f.Write('component_blacklist',
126+
','.join(self.component_blacklist))
127+
f.WriteBool('blacklist_virtual', self.blacklist_virtual)
128+
129+
f.SetPath('/extra_fields')
130+
f.Write('extra_fields', ','.join(self.extra_fields))
131+
f.Write('board_variant_field', self.board_variant_field)
132+
f.Write('board_variant_whitelist',
133+
','.join(self.board_variant_whitelist))
134+
f.Write('board_variant_blacklist',
135+
','.join(self.board_variant_blacklist))
136+
f.Write('dnp_field', self.dnp_field)
137+
f.Flush()
54138

55139
def set_from_dialog(self, dlg):
56140
# type: (dialog.settings_dialog.SettingsDialogPanel) -> None
@@ -96,8 +180,10 @@ def transfer_to_dialog(self, dlg):
96180
dlg.html.continuousRedrawCheckbox.value = self.redraw_on_drag
97181
dlg.html.boardRotationSlider.Value = self.board_rotation
98182
dlg.html.bomCheckboxesCtrl.Value = self.checkboxes
99-
dlg.html.bomDefaultView.Selection = self.bom_view
100-
dlg.html.layerDefaultView.Selection = self.layer_view
183+
dlg.html.bomDefaultView.Selection = self.bom_view_choices.index(
184+
self.bom_view)
185+
dlg.html.layerDefaultView.Selection = self.layer_view_choices.index(
186+
self.layer_view)
101187
dlg.html.openBrowserCheckbox.Value = self.open_browser
102188

103189
# General
@@ -114,14 +200,22 @@ def transfer_to_dialog(self, dlg):
114200
# Extra fields
115201
dlg.extra.netlistFilePicker.SetInitialDirectory(
116202
self.netlist_initial_directory)
117-
dlg.extra.extraFieldsList.SetCheckedStrings(self.extra_fields)
203+
204+
def safe_set_checked_strings(clb, strings):
205+
safe_strings = list(clb.GetStrings())
206+
clb.SetCheckedStrings([s for s in strings if s in safe_strings])
207+
208+
safe_set_checked_strings(dlg.extra.extraFieldsList, self.extra_fields)
118209
dlg.extra.boardVariantFieldBox.Value = self.board_variant_field
119-
dlg.extra.boardVariantWhitelist.SetCheckedStrings(
120-
self.board_variant_whitelist)
121-
dlg.extra.boardVariantBlacklist.SetCheckedStrings(
122-
self.board_variant_blacklist)
210+
dlg.extra.OnBoardVariantFieldChange(None)
211+
safe_set_checked_strings(dlg.extra.boardVariantWhitelist,
212+
self.board_variant_whitelist)
213+
safe_set_checked_strings(dlg.extra.boardVariantBlacklist,
214+
self.board_variant_blacklist)
123215
dlg.extra.dnpFieldBox.Value = self.dnp_field
124216

217+
dlg.finish_init()
218+
125219
# noinspection PyTypeChecker
126220
@classmethod
127221
def add_options(cls, parser):

InteractiveHtmlBom/dialog/dialog_base.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
4646
bSizer39 = wx.BoxSizer( wx.HORIZONTAL )
4747

4848
self.m_button41 = wx.Button( self, wx.ID_ANY, u"Save current settings", wx.DefaultPosition, wx.DefaultSize, 0|wx.BORDER_DEFAULT )
49-
self.m_button41.Enable( False )
50-
5149
bSizer39.Add( self.m_button41, 0, wx.ALL, 5 )
5250

5351

InteractiveHtmlBom/dialog/settings_dialog.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ def pop_error(msg):
1212

1313

1414
class SettingsDialog(dialog_base.SettingsDialogBase):
15-
def __init__(self, parent, extra_data_func):
16-
dialog_base.SettingsDialogBase.__init__(self, parent)
17-
self.panel = SettingsDialogPanel(self, extra_data_func)
15+
def __init__(self, extra_data_func, config_save_func):
16+
dialog_base.SettingsDialogBase.__init__(self, None)
17+
self.panel = SettingsDialogPanel(
18+
self, extra_data_func, config_save_func)
1819
best_size = self.panel.BestSize
1920
# hack for some gtk themes that incorrectly calculate best size
2021
best_size.IncBy(dx=0, dy=30)
@@ -27,31 +28,33 @@ def SetSizeHints(self, sz1, sz2):
2728

2829
def set_extra_data_path(self, extra_data_file):
2930
self.panel.extra.netlistFilePicker.Path = extra_data_file
30-
wx.CallAfter(self.panel.extra.OnNetlistFileChanged, None)
31+
self.panel.extra.OnNetlistFileChanged(None)
3132

3233

3334
# Implementing settings_dialog
3435
class SettingsDialogPanel(dialog_base.SettingsDialogPanel):
35-
def __init__(self, parent, extra_data_func):
36+
def __init__(self, parent, extra_data_func, config_save_func):
37+
self.config_save_func = config_save_func
3638
dialog_base.SettingsDialogPanel.__init__(self, parent)
3739
self.general = GeneralSettingsPanel(self.notebook)
3840
self.html = HtmlSettingsPanel(self.notebook)
3941
self.extra = ExtraFieldsPanel(self.notebook, extra_data_func)
4042
self.notebook.AddPage(self.general, "General")
4143
self.notebook.AddPage(self.html, "Html defaults")
4244
self.notebook.AddPage(self.extra, "Extra fields")
43-
self.html.OnBoardRotationSlider(None)
4445

4546
def OnExit(self, event):
4647
self.GetParent().EndModal(wx.ID_CANCEL)
4748

4849
def OnSaveSettings(self, event):
49-
# TODO: implement OnSaveSettings
50-
pass
50+
self.config_save_func(self)
5151

5252
def OnGenerateBom(self, event):
5353
self.GetParent().EndModal(wx.ID_OK)
5454

55+
def finish_init(self):
56+
self.html.OnBoardRotationSlider(None)
57+
5558

5659
# Implementing HtmlSettingsPanelBase
5760
class HtmlSettingsPanel(dialog_base.HtmlSettingsPanelBase):

InteractiveHtmlBom/generate_interactive_bom.py

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,29 @@ def main(pcb, config):
598598
open_file(bom_file)
599599

600600

601+
def run_with_dialog(board, config):
602+
def save_config(dialog_panel):
603+
config.set_from_dialog(dialog_panel)
604+
config.save()
605+
606+
dlg = dialog.SettingsDialog(
607+
extra_data_func=parse_schematic_data,
608+
config_save_func=save_config
609+
)
610+
try:
611+
pcb_file_name = board.GetFileName()
612+
config.netlist_initial_directory = os.path.dirname(pcb_file_name)
613+
extra_data_file = find_latest_schematic_data(pcb_file_name)
614+
if extra_data_file is not None:
615+
dlg.set_extra_data_path(extra_data_file)
616+
config.transfer_to_dialog(dlg.panel)
617+
if dlg.ShowModal() == wx.ID_OK:
618+
config.set_from_dialog(dlg.panel)
619+
main(board, config)
620+
finally:
621+
dlg.Destroy()
622+
623+
601624
class GenerateInteractiveBomPlugin(pcbnew.ActionPlugin):
602625

603626
def defaults(self):
@@ -624,22 +647,12 @@ def Run(self):
624647
logerror('Please save the board file before generating BOM.')
625648
return
626649

627-
dlg = dialog.SettingsDialog(None, extra_data_func=parse_schematic_data)
628-
try:
629-
config.netlist_initial_directory = os.path.dirname(pcb_file_name)
630-
extra_data_file = find_latest_schematic_data(pcb_file_name)
631-
if extra_data_file is not None:
632-
dlg.set_extra_data_path(extra_data_file)
633-
config.transfer_to_dialog(dlg.panel)
634-
if dlg.ShowModal() == wx.ID_OK:
635-
config.set_from_dialog(dlg.panel)
636-
main(pcbnew.GetBoard(), config)
637-
finally:
638-
dlg.Destroy()
650+
run_with_dialog(pcbnew.GetBoard(), config)
639651

640652

641653
if __name__ == "__main__":
642654
is_cli = True
655+
app = wx.App()
643656

644657
import argparse
645658

@@ -654,18 +667,9 @@ def Run(self):
654667
print("File %s does not exist." % args.file)
655668
exit(1)
656669
print("Loading %s" % args.file)
657-
app = wx.App()
658670
board = pcbnew.LoadBoard(os.path.abspath(args.file).decode('utf8'))
659671
if args.show_dialog:
660-
# Create simple app to show config dialog, infer config.
661-
dlg = dialog.SettingsDialog(None, extra_data_func=parse_schematic_data)
662-
config.netlist_initial_directory = os.path.dirname(args.file)
663-
config.transfer_to_dialog(dlg.panel)
664-
if dlg.ShowModal() == wx.ID_OK:
665-
config.set_from_dialog(dlg.panel)
666-
print config.get_html_config()
667-
main(board, config)
668-
dlg.Destroy()
672+
run_with_dialog(board, config)
669673
else:
670674
config.set_from_args(args)
671675
main(board, config)

settings_dialog.fbp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@
296296
<property name="dock">Dock</property>
297297
<property name="dock_fixed">0</property>
298298
<property name="docking">Left</property>
299-
<property name="enabled">0</property>
299+
<property name="enabled">1</property>
300300
<property name="fg"></property>
301301
<property name="floatable">1</property>
302302
<property name="focus"></property>

0 commit comments

Comments
 (0)