inkstitch/lib/extensions/select_elements.py

166 wiersze
7.1 KiB
Python

# Authors: see git history
#
# Copyright (c) 2022 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
import os
import subprocess
import sys
from inkex import Boolean
from ..elements import Clone, FillStitch, Polyline, SatinColumn, Stroke
from ..utils import get_bundled_dir
from .base import InkstitchExtension
class SelectElements(InkstitchExtension):
def add_arguments(self, pars):
self.arg_parser.add_argument("--options", type=str, dest="notebook")
pars.add_argument("--stitch-type", type=str, dest="stitch_type")
pars.add_argument("--info", type=str, dest="info")
pars.add_argument("--select-running-stitch", type=Boolean, dest="running", default=False)
pars.add_argument("--running-stitch-condition", type=str, dest="running_stitch_condition", default="all")
pars.add_argument("--select-ripples", type=Boolean, dest="ripples", default=False)
pars.add_argument("--select-zigzag", type=Boolean, dest="zigzag", default=False)
pars.add_argument("--select-manual", type=Boolean, dest="manual", default=False)
pars.add_argument("--select-polyline", type=Boolean, dest="poly", default=False)
pars.add_argument("--select-satin", type=Boolean, dest="satin", default=False)
pars.add_argument("--satin-underlay", type=str, dest="satin_underlay", default="all")
pars.add_argument("--select-e", type=Boolean, dest="e", default=False)
pars.add_argument("--select-auto-fill", type=Boolean, dest="fill", default=False)
pars.add_argument("--select-contour-fill", type=Boolean, dest="contour", default=False)
pars.add_argument("--select-guided-fill", type=Boolean, dest="guided", default=False)
pars.add_argument("--select-meander-fill", type=Boolean, dest="meander", default=False)
pars.add_argument("--select-circular-fill", type=Boolean, dest="circular", default=False)
pars.add_argument("--select-legacy-fill", type=Boolean, dest="legacy", default=False)
pars.add_argument("--fill-underlay", type=str, dest="fill_underlay", default="all")
pars.add_argument("--select-clone", type=Boolean, dest="clone", default=False)
pars.add_argument("--python-path", type=str, dest="python_path", default='')
def effect(self):
py_path, file_path = self._get_paths()
id_list = self._get_id_list()
subprocess.Popen(
[py_path, 'select_elements.py', id_list],
cwd=file_path,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
def _get_paths(self):
file_path = get_bundled_dir("dbus")
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
if sys.platform == "linux":
py_path = "python3"
elif sys.platform.startswith("win"):
# sadly we cannot access python interpreters, so we have to guess the file path in windows
# and we could be very wrong
py_path = 'c:/program files/inkscape/bin/python.exe'
elif sys.platform == "darwin":
py_path = '/Applications/Inkscape.app/Contents/Resources/bin/python3'
py_path = 'python3'
else:
# we are running a local install
py_path = sys.executable
# For some reason we cannot use the subprocess method wait() to finish the process properly
# and we'll get a warning. It will break functionality of the selection.
# There is most possibly a better way than to just ignore the warning?!?
with open(os.devnull, 'w') as null:
sys.stderr = null
sys.stdout = null
# custom python path
if self.options.python_path:
py_path = self.options.python_path
return py_path, file_path
def _get_id_list(self):
if not self.get_elements():
return ''
ids = set()
for element in self.elements:
if isinstance(element, Stroke) and self._select_stroke(element):
ids.add(element.id)
elif isinstance(element, Polyline) and self.options.poly:
ids.add(element.id)
elif isinstance(element, FillStitch) and self._select_fill(element):
ids.add(element.id)
elif isinstance(element, SatinColumn) and self._select_satin(element):
ids.add(element.id)
elif isinstance(element, Clone) and self.options.clone:
ids.add(element.id)
return ','.join(ids)
def _select_stroke(self, element):
select = False
method = element.stroke_method
if self.options.running and method == 'running_stitch' and self._running_condition(element):
select = True
if self.options.ripples and method == 'ripple_stitch':
select = True
elif self.options.zigzag and method == 'zigzag_stitch':
select = True
elif self.options.manual and method == 'manual_stitch':
select = True
return select
def _select_fill(self, element):
select = False
if not self._select_fill_underlay(element):
return False
method = element.fill_method
if self.options.fill and method == 'auto_fill':
select = True
elif self.options.contour and method == 'contour_fill':
select = True
elif self.options.guided and method == 'guided_fill':
select = True
elif self.options.meander and method == 'meander_fill':
select = True
elif self.options.circular and method == 'circular_fill':
select = True
elif self.options.legacy and method == 'legacy_fill':
select = True
return select
def _running_condition(self, element):
element_id = element.node.get_id() or ''
conditions = {'all': True, 'autorun-top': element_id.startswith('autorun'), 'autorun-underpath': element_id.startswith('underpath')}
return conditions[self.options.running_stitch_condition]
def _select_fill_underlay(self, element):
underlay = {'all': True, 'no': not element.fill_underlay, 'yes': element.fill_underlay}
return underlay[self.options.fill_underlay]
def _select_satin(self, element):
select = False
if not self._select_satin_underlay(element):
return False
method = element.satin_method
if self.options.satin and method == "satin_column":
select = True
elif self.options.e and method == "e_stitch":
select = True
return select
def _select_satin_underlay(self, element):
underlay = {'all': None, 'no': None, 'center': None, 'contour': None, 'zigzag': None}
underlay['center'] = element.center_walk_underlay
underlay['contour'] = element.contour_underlay
underlay['zigzag'] = element.zigzag_underlay
underlay['no'] = not any(underlay.values())
underlay['all'] = True
return underlay[self.options.satin_underlay]
if __name__ == '__main__':
SelectElements().run()