Skip to content

Commit

Permalink
[SCH Print][Added] Option to specify a custom page layout (WKS)
Browse files Browse the repository at this point in the history
- sheet_reference_layout
- Also added a workaround for people using backslashes (i.e. Windows+WSL)

See #607
  • Loading branch information
set-soft committed Apr 12, 2024
1 parent 185ab1a commit 4492611
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 49 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
footprints using variants (See #574)
- Quick Start: D/ERC are also included for KiCad 8 (with dont_stop: true)
- Navigate Results: Includes the new D/ERC
- SCH print:
- Option to specify a custom page layout (WKS)
- Workaround for people using backslashes (i.e. Windows+WSL) (See #607)

### Fixed
- Netlist generation problems with components on the PCB but not in schematic.
Expand Down
20 changes: 20 additions & 0 deletions docs/samples/generic_plot.kibot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,10 @@ outputs:
# [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
# A short-cut to use for simple cases where a variant is an overkill
pre_transform: '_none'
# [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
# This option works only when you print the toplevel sheet of a project and the project
# file is available
sheet_reference_layout: ''
# [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
# If it starts with `+` the text is concatenated
title: ''
Expand Down Expand Up @@ -1300,6 +1304,10 @@ outputs:
# [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
# A short-cut to use for simple cases where a variant is an overkill
pre_transform: '_none'
# [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
# This option works only when you print the toplevel sheet of a project and the project
# file is available
sheet_reference_layout: ''
# [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
# If it starts with `+` the text is concatenated
title: ''
Expand Down Expand Up @@ -2932,6 +2940,10 @@ outputs:
# [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
# A short-cut to use for simple cases where a variant is an overkill
pre_transform: '_none'
# [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
# This option works only when you print the toplevel sheet of a project and the project
# file is available
sheet_reference_layout: ''
# [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
# If it starts with `+` the text is concatenated
title: ''
Expand Down Expand Up @@ -3158,6 +3170,10 @@ outputs:
# [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
# A short-cut to use for simple cases where a variant is an overkill
pre_transform: '_none'
# [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
# This option works only when you print the toplevel sheet of a project and the project
# file is available
sheet_reference_layout: ''
# [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
# If it starts with `+` the text is concatenated
title: ''
Expand Down Expand Up @@ -3713,6 +3729,10 @@ outputs:
# [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
# A short-cut to use for simple cases where a variant is an overkill
pre_transform: '_none'
# [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
# This option works only when you print the toplevel sheet of a project and the project
# file is available
sheet_reference_layout: ''
# [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
# If it starts with `+` the text is concatenated
title: ''
Expand Down
5 changes: 5 additions & 0 deletions docs/source/Changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ Added
- Quick Start: D/ERC are also included for KiCad 8 (with dont_stop:
true)
- Navigate Results: Includes the new D/ERC
- SCH print:

- Option to specify a custom page layout (WKS)
- Workaround for people using backslashes (i.e. Windows+WSL) (See
#607)

Fixed
~~~~~
Expand Down
3 changes: 3 additions & 0 deletions docs/source/configuration/outputs/dxf_sch_print.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Parameters:
- ``pre_transform`` :index:`: <pair: output - dxf_sch_print - options; pre_transform>` [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
A short-cut to use for simple cases where a variant is an overkill.

- ``sheet_reference_layout`` :index:`: <pair: output - dxf_sch_print - options; sheet_reference_layout>` [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
This option works only when you print the toplevel sheet of a project and the project
file is available.
- ``title`` :index:`: <pair: output - dxf_sch_print - options; title>` [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated.
- ``variant`` :index:`: <pair: output - dxf_sch_print - options; variant>` [string=''] Board variant to apply.
Expand Down
3 changes: 3 additions & 0 deletions docs/source/configuration/outputs/hpgl_sch_print.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ Parameters:
- ``pre_transform`` :index:`: <pair: output - hpgl_sch_print - options; pre_transform>` [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
A short-cut to use for simple cases where a variant is an overkill.

- ``sheet_reference_layout`` :index:`: <pair: output - hpgl_sch_print - options; sheet_reference_layout>` [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
This option works only when you print the toplevel sheet of a project and the project
file is available.
- ``title`` :index:`: <pair: output - hpgl_sch_print - options; title>` [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated.
- ``variant`` :index:`: <pair: output - hpgl_sch_print - options; variant>` [string=''] Board variant to apply.
Expand Down
3 changes: 3 additions & 0 deletions docs/source/configuration/outputs/pdf_sch_print.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ Parameters:
- ``pre_transform`` :index:`: <pair: output - pdf_sch_print - options; pre_transform>` [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
A short-cut to use for simple cases where a variant is an overkill.

- ``sheet_reference_layout`` :index:`: <pair: output - pdf_sch_print - options; sheet_reference_layout>` [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
This option works only when you print the toplevel sheet of a project and the project
file is available.
- ``title`` :index:`: <pair: output - pdf_sch_print - options; title>` [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated.
- ``variant`` :index:`: <pair: output - pdf_sch_print - options; variant>` [string=''] Board variant to apply.
Expand Down
3 changes: 3 additions & 0 deletions docs/source/configuration/outputs/ps_sch_print.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Parameters:
- ``pre_transform`` :index:`: <pair: output - ps_sch_print - options; pre_transform>` [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
A short-cut to use for simple cases where a variant is an overkill.

- ``sheet_reference_layout`` :index:`: <pair: output - ps_sch_print - options; sheet_reference_layout>` [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
This option works only when you print the toplevel sheet of a project and the project
file is available.
- ``title`` :index:`: <pair: output - ps_sch_print - options; title>` [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated.
- ``variant`` :index:`: <pair: output - ps_sch_print - options; variant>` [string=''] Board variant to apply.
Expand Down
3 changes: 3 additions & 0 deletions docs/source/configuration/outputs/svg_sch_print.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ Parameters:
- ``pre_transform`` :index:`: <pair: output - svg_sch_print - options; pre_transform>` [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
A short-cut to use for simple cases where a variant is an overkill.

- ``sheet_reference_layout`` :index:`: <pair: output - svg_sch_print - options; sheet_reference_layout>` [string=''] Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
This option works only when you print the toplevel sheet of a project and the project
file is available.
- ``title`` :index:`: <pair: output - svg_sch_print - options; title>` [string=''] Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated.
- ``variant`` :index:`: <pair: output - svg_sch_print - options; variant>` [string=''] Board variant to apply.
Expand Down
53 changes: 35 additions & 18 deletions kibot/kicad/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,32 +625,38 @@ def load_3d_aliases():
KiConf.aliases_3D[name] = value
logger.debugl(1, 'Finished loading 3D aliases')

def fix_page_layout_k6_key(key, data, dest_dir):
def fix_page_layout_k6_key(key, data, dest_dir, forced):
if key in data:
section = data[key]
pl = section.get('page_layout_descr_file', None)
if pl:
fname = KiConf.expand_env(pl)
if os.path.isfile(fname):
dest = os.path.join(dest_dir, key+'.kicad_wks')
logger.debug('Copying {} -> {}'.format(fname, dest))
copy2(fname, dest)
data[key]['page_layout_descr_file'] = key+'.kicad_wks'
return dest
if forced:
data[key]['page_layout_descr_file'] = forced
logger.debug(f'Replacing page layout {pl} -> {forced}')
else:
GS.exit_with_error('Missing page layout file: '+fname, MISSING_WKS)
fname = KiConf.expand_env(pl)
if os.path.isfile(fname):
dest = os.path.join(dest_dir, key+'.kicad_wks')
logger.debug('Copying {} -> {}'.format(fname, dest))
copy2(fname, dest)
data[key]['page_layout_descr_file'] = key+'.kicad_wks'
logger.debug(f'Replacing page layout {pl} -> {key}.kicad_wks')
return dest
else:
GS.exit_with_error('Missing page layout file: '+fname, MISSING_WKS)
return None

def fix_page_layout_k6(project, dry):
def fix_page_layout_k6(project, dry, force_sch, force_pcb):
# Get the current definitions
dest_dir = os.path.dirname(project)
with open(project, 'rt') as f:
pro_text = f.read()
data = json.loads(pro_text)
layouts = [None, None]
if not dry:
layouts[1] = KiConf.fix_page_layout_k6_key('pcbnew', data, dest_dir)
layouts[0] = KiConf.fix_page_layout_k6_key('schematic', data, dest_dir)
layouts[1] = KiConf.fix_page_layout_k6_key('pcbnew', data, dest_dir, force_pcb)
layouts[0] = KiConf.fix_page_layout_k6_key('schematic', data, dest_dir, force_sch)
logger.debug(f'Saving modified project to {project}')
with open(project, 'wt') as f:
f.write(json.dumps(data, sort_keys=True, indent=2))
else:
Expand All @@ -662,7 +668,7 @@ def fix_page_layout_k6(project, dry):
layouts[1] = KiConf.expand_env(aux.get('page_layout_descr_file', None), ref_dir=dest_dir)
return layouts

def fix_page_layout_k5(project, dry):
def fix_page_layout_k5(project, dry, force_sch, force_pcb):
order = 1
dest_dir = os.path.dirname(project)
with open(project, 'rt') as f:
Expand All @@ -676,7 +682,11 @@ def fix_page_layout_k5(project, dry):
is_pcb_new = False
if line.startswith('PageLayoutDescrFile='):
fname = line[20:].strip()
if fname:
if force_sch and not is_pcb_new:
dest = force_sch
elif force_pcb and is_pcb_new:
dest = force_pcb
elif fname:
fname = KiConf.expand_env(fname)
if os.path.isfile(fname):
dest = os.path.join(dest_dir, str(order)+'.kicad_wks')
Expand All @@ -691,19 +701,26 @@ def fix_page_layout_k5(project, dry):
GS.exit_with_error('Missing page layout file: '+fname, MISSING_WKS)
else:
dest = ''
if dest or fname:
logger.debug(f'Replacing page layout {fname} -> {dest}')
lns[c] = f'PageLayoutDescrFile={dest}\n'
if not dry:
logger.debug(f'Saving modified project to {project}')
with open(project, 'wt') as f:
lns = f.writelines(lns)
return layouts

def fix_page_layout(project, dry=False):
def fix_page_layout(project, dry=False, force_sch=None, force_pcb=None):
""" When we copy the project the page layouts must be also copied.
After copying the project to another destination we have wrong relative references to the WKSs.
We copy these files and patch the project so the files are named in a simple way.
In addition we can use this function to force the names of the page layouts. """
if not project:
return None, None
KiConf.init(GS.pcb_file)
KiConf.init(GS.pcb_file or GS.sch_file)
if GS.ki5:
return KiConf.fix_page_layout_k5(project, dry)
return KiConf.fix_page_layout_k6(project, dry)
return KiConf.fix_page_layout_k5(project, dry, force_sch, force_pcb)
return KiConf.fix_page_layout_k6(project, dry, force_sch, force_pcb)

def expand_env(name, used_extra=None, ref_dir=None):
if used_extra is None:
Expand Down
101 changes: 70 additions & 31 deletions kibot/out_any_sch_print.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# Project: KiBot (formerly KiPlot)
import os
from tempfile import mkdtemp
from .error import KiPlotConfigurationError
from .gs import GS
from .out_base import VariantOptions
from .macros import macros, document, output_class # noqa: F401
Expand All @@ -29,6 +30,10 @@ def __init__(self):
self.title = ''
""" Text used to replace the sheet title. %VALUE expansions are allowed.
If it starts with `+` the text is concatenated """
self.sheet_reference_layout = ''
""" Worksheet file (.kicad_wks) to use. Leave empty to use the one specified in the project.
This option works only when you print the toplevel sheet of a project and the project
file is available """
super().__init__()
self.add_to_doc('variant', "Not fitted components are crossed")
self._expand_id = 'schematic'
Expand All @@ -41,34 +46,68 @@ def get_targets(self, out_dir):
def run(self, name):
super().run(name)
command = self.ensure_tool('KiAuto')
if self.title:
self.set_title(self.title, sch=True)
if self._comps or self.title:
# Save it to a temporal dir
sch_dir = mkdtemp(prefix='tmp-kibot-'+self._expand_ext+'_sch_print-')
GS.copy_project_sch(sch_dir)
fname = GS.sch.save_variant(sch_dir)
sch_file = os.path.join(sch_dir, fname)
self._files_to_remove.append(sch_dir)
else:
sch_file = GS.sch_file
fmt = 'hpgl' if self._expand_ext == 'plt' else self._expand_ext
cmd = [command, 'export', '--file_format', fmt, '-o', name]
if self.monochrome:
cmd.append('--monochrome')
if not self.frame:
cmd.append('--no_frame')
if self.all_pages:
cmd.append('--all_pages')
if self.color_theme:
cmd.extend(['--color_theme', self.color_theme])
if self.background_color:
cmd.append('--background_color')
if hasattr(self, '_origin'):
cmd.extend(['--hpgl_origin', str(self._origin)])
if hasattr(self, 'pen_size'):
cmd.extend(['--hpgl_pen_size', str(self.pen_size)])
cmd.extend([sch_file, os.path.dirname(name)])
self.exec_with_retry(self.add_extra_options(cmd), self._exit_error)
if self.title:
self.restore_title(sch=True)

# This code has two purposes:
# 1. Allow specifying a different worksheet
# 2. Fix \ in the worksheet
# For this we temporarily adjust the project
prj = None
if GS.pro_file and GS.pro_basename == GS.sch_basename:
ori_wks = ''
wks = GS.fix_page_layout(GS.pro_file, dry=True)
# We have a project and is the project for the schematic
if self.sheet_reference_layout:
# The user wants a different worksheet
new_wks = os.path.join(GS.pro_dir, self.sheet_reference_layout)
if not os.path.isfile(new_wks):
raise KiPlotConfigurationError(f'Missing `{new_wks}` worksheet')
else:
ori_wks = new_wks = wks[0]
if not os.path.isfile(new_wks):
# Try replacing backslashes
try_wks = new_wks.replace('\\', '/')
if not os.path.isfile(try_wks):
raise KiPlotConfigurationError(f'Missing `{new_wks}` worksheet')
new_wks = try_wks
if ori_wks != new_wks:
prj = GS.read_pro()
GS.fix_page_layout(GS.pro_file, dry=False, force_sch=os.path.relpath(new_wks, GS.pro_dir),
force_pcb=os.path.relpath(wks[1], GS.pro_dir))
elif self.sheet_reference_layout:
raise KiPlotConfigurationError('Using `sheet_reference_layout` but no project available')

try:
if self.title:
self.set_title(self.title, sch=True)
if self._comps or self.title:
# Save it to a temporal dir
sch_dir = mkdtemp(prefix='tmp-kibot-'+self._expand_ext+'_sch_print-')
GS.copy_project_sch(sch_dir)
fname = GS.sch.save_variant(sch_dir)
sch_file = os.path.join(sch_dir, fname)
self._files_to_remove.append(sch_dir)
else:
sch_file = GS.sch_file
fmt = 'hpgl' if self._expand_ext == 'plt' else self._expand_ext
cmd = [command, 'export', '--file_format', fmt, '-o', name]
if self.monochrome:
cmd.append('--monochrome')
if not self.frame:
cmd.append('--no_frame')
if self.all_pages:
cmd.append('--all_pages')
if self.color_theme:
cmd.extend(['--color_theme', self.color_theme])
if self.background_color:
cmd.append('--background_color')
if hasattr(self, '_origin'):
cmd.extend(['--hpgl_origin', str(self._origin)])
if hasattr(self, 'pen_size'):
cmd.extend(['--hpgl_pen_size', str(self.pen_size)])
cmd.extend([sch_file, os.path.dirname(name)])
self.exec_with_retry(self.add_extra_options(cmd), self._exit_error)
if self.title:
self.restore_title(sch=True)
finally:
if prj:
GS.write_pro(prj)

0 comments on commit 4492611

Please sign in to comment.