kopia lustrzana https://github.com/inkstitch/inkstitch
commit
7b8af2ed57
6
Makefile
6
Makefile
|
@ -11,9 +11,9 @@ dist: distclean locales inx
|
|||
cp -a images/examples dist/inkstitch
|
||||
cp -a palettes dist/inkstitch
|
||||
cp -a symbols dist/inkstitch
|
||||
mkdir -p dist/inkstitch/bin/locales
|
||||
cp -a locales/* dist/inkstitch/bin/locales
|
||||
cp -a print dist/inkstitch/bin/
|
||||
cp -a icons dist/inkstitch/bin
|
||||
cp -a locales dist/inkstitch/bin
|
||||
cp -a print dist/inkstitch/bin
|
||||
if [ "$$BUILD" = "windows" ]; then \
|
||||
cd dist; zip -r ../inkstitch-$(VERSION)-win32.zip *; \
|
||||
else \
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 15 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 734 B |
|
@ -8,7 +8,7 @@ from .fill import Fill
|
|||
|
||||
|
||||
class AutoFill(Fill):
|
||||
element_name = _("Auto-Fill")
|
||||
element_name = _("AutoFill")
|
||||
|
||||
@property
|
||||
@param('auto_fill', _('Automatically routed fill stitching'), type='toggle', default=True)
|
||||
|
@ -55,7 +55,7 @@ class AutoFill(Fill):
|
|||
def fill_underlay_angle(self):
|
||||
underlay_angle = self.get_float_param("fill_underlay_angle")
|
||||
|
||||
if underlay_angle:
|
||||
if underlay_angle is not None:
|
||||
return math.radians(underlay_angle)
|
||||
else:
|
||||
return self.angle + math.pi / 2.0
|
||||
|
|
|
@ -197,7 +197,11 @@ class EmbroideryElement(object):
|
|||
# In a path, each element in the 3-tuple is itself a tuple of (x, y).
|
||||
# Tuples all the way down. Hasn't anyone heard of using classes?
|
||||
|
||||
return cubicsuperpath.parsePath(self.node.get("d"))
|
||||
d = self.node.get("d", "")
|
||||
if not d:
|
||||
self.fatal(_("Object %(id)s has an empty 'd' attribute. Please delete this object from your document.") % dict(id=self.node.get("id")))
|
||||
|
||||
return cubicsuperpath.parsePath(d)
|
||||
|
||||
@cache
|
||||
def parse_path(self):
|
||||
|
@ -264,5 +268,7 @@ class EmbroideryElement(object):
|
|||
return patches
|
||||
|
||||
def fatal(self, message):
|
||||
print >> sys.stderr, "error:", message
|
||||
# L10N used when showing an error message to the user such as "satin column: One or more of the rungs doesn't
|
||||
# intersect both rails."
|
||||
print >> sys.stderr, self.node.get("id") + ":", _("error:"), message
|
||||
sys.exit(1)
|
||||
|
|
|
@ -120,7 +120,10 @@ class Fill(EmbroideryElement):
|
|||
poly_ary.sort(key=lambda point_list: shgeo.Polygon(point_list).area, reverse=True)
|
||||
|
||||
polygon = shgeo.MultiPolygon([(poly_ary[0], poly_ary[1:])])
|
||||
# print >> sys.stderr, "polygon valid:", polygon.is_valid
|
||||
|
||||
if not polygon.is_valid:
|
||||
self.fatal(_("shape is not valid. This can happen if the border crosses over itself."))
|
||||
|
||||
return polygon
|
||||
|
||||
def to_patches(self, last_patch):
|
||||
|
|
|
@ -39,7 +39,7 @@ class Embroider(InkstitchExtension):
|
|||
|
||||
def get_output_path(self):
|
||||
if self.options.output_file:
|
||||
output_path = os.path.join(self.options.path, self.options.output_file)
|
||||
output_path = os.path.join(os.path.expanduser(os.path.expandvars(self.options.path)), self.options.output_file)
|
||||
else:
|
||||
csv_filename = '%s.%s' % (self.get_base_file_name(), self.options.output_format)
|
||||
output_path = os.path.join(self.options.path, csv_filename)
|
||||
|
|
|
@ -56,6 +56,13 @@ class InstallerFrame(wx.Frame):
|
|||
self.path_input.SetValue(dialog.GetPath())
|
||||
|
||||
def install_button_clicked(self, event):
|
||||
if sys.platform == "win32":
|
||||
# On windows, the default icon shows as a broken image. No idea
|
||||
# why. Workaround: don't show an icon.
|
||||
style = wx.ICON_NONE
|
||||
else:
|
||||
style = 0
|
||||
|
||||
try:
|
||||
self.install_addons('palettes')
|
||||
self.install_addons('symbols')
|
||||
|
@ -63,12 +70,12 @@ class InstallerFrame(wx.Frame):
|
|||
wx.MessageDialog(self,
|
||||
_('Inkscape add-on installation failed') + ': \n' + traceback.format_exc(),
|
||||
_('Installation Failed'),
|
||||
wx.OK).ShowModal()
|
||||
wx.OK | style).ShowModal()
|
||||
else:
|
||||
wx.MessageDialog(self,
|
||||
_('Inkscape add-on files have been installed. Please restart Inkscape to load the new add-ons.'),
|
||||
_('Installation Completed'),
|
||||
wx.OK).ShowModal()
|
||||
wx.OK | style).ShowModal()
|
||||
|
||||
self.Destroy()
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ from .base import InkstitchExtension
|
|||
from ..i18n import _
|
||||
from ..stitch_plan import patches_to_stitch_plan
|
||||
from ..elements import EmbroideryElement, Fill, AutoFill, Stroke, SatinColumn
|
||||
from ..utils import save_stderr, restore_stderr
|
||||
from ..utils import save_stderr, restore_stderr, get_resource_dir
|
||||
from ..simulator import EmbroiderySimulator
|
||||
from ..commands import is_command
|
||||
|
||||
|
@ -112,10 +112,14 @@ class ParamsTab(ScrolledPanel):
|
|||
else:
|
||||
self.toggle = None
|
||||
|
||||
self.settings_grid = wx.FlexGridSizer(rows=0, cols=3, hgap=10, vgap=10)
|
||||
self.settings_grid.AddGrowableCol(0, 1)
|
||||
self.param_change_indicators = {}
|
||||
|
||||
self.settings_grid = wx.FlexGridSizer(rows=0, cols=4, hgap=10, vgap=15)
|
||||
self.settings_grid.AddGrowableCol(1, 2)
|
||||
self.settings_grid.SetFlexibleDirection(wx.HORIZONTAL)
|
||||
|
||||
self.pencil_icon = wx.Image(os.path.join(get_resource_dir("icons"), "pencil_20x20.png")).ConvertToBitmap()
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
|
||||
|
@ -218,7 +222,11 @@ class ParamsTab(ScrolledPanel):
|
|||
self.on_change_hook = callable
|
||||
|
||||
def changed(self, event):
|
||||
self.changed_inputs.add(event.GetEventObject())
|
||||
input = event.GetEventObject()
|
||||
self.changed_inputs.add(input)
|
||||
|
||||
param = self.inputs_to_params[input]
|
||||
self.enable_change_indicator(param)
|
||||
event.Skip()
|
||||
|
||||
if self.on_change_hook:
|
||||
|
@ -235,9 +243,7 @@ class ParamsTab(ScrolledPanel):
|
|||
self.update_toggle_state()
|
||||
|
||||
def save_preset(self, storage):
|
||||
preset = storage[self.name] = {}
|
||||
for name, input in self.param_inputs.iteritems():
|
||||
preset[name] = input.GetValue()
|
||||
storage[self.name] = self.get_values()
|
||||
|
||||
def update_description(self):
|
||||
if len(self.nodes) == 1:
|
||||
|
@ -296,13 +302,17 @@ class ParamsTab(ScrolledPanel):
|
|||
box.Add(sizer, proportion=0, flag=wx.ALL, border=5)
|
||||
|
||||
if self.toggle:
|
||||
box.Add(self.toggle_checkbox, proportion=0, flag=wx.BOTTOM, border=10)
|
||||
toggle_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
toggle_sizer.Add(self.create_change_indicator(self.toggle.name), proportion = 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border=5)
|
||||
toggle_sizer.Add(self.toggle_checkbox, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
|
||||
box.Add(toggle_sizer, proportion=0, flag=wx.BOTTOM, border=10)
|
||||
|
||||
for param in self.params:
|
||||
self.settings_grid.Add(self.create_change_indicator(param.name), proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
|
||||
|
||||
description = wx.StaticText(self, label=param.description)
|
||||
description.SetToolTip(param.tooltip)
|
||||
|
||||
self.settings_grid.Add(description, proportion=1, flag=wx.EXPAND|wx.RIGHT, border=40)
|
||||
self.settings_grid.Add(description, proportion=1, flag=wx.EXPAND|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=5)
|
||||
|
||||
if param.type == 'boolean':
|
||||
|
||||
|
@ -316,7 +326,7 @@ class ParamsTab(ScrolledPanel):
|
|||
|
||||
input.Bind(wx.EVT_CHECKBOX, self.changed)
|
||||
elif len(param.values) > 1:
|
||||
input = wx.ComboBox(self, wx.ID_ANY, choices=sorted(param.values), style=wx.CB_DROPDOWN)
|
||||
input = wx.ComboBox(self, wx.ID_ANY, choices=sorted(str(value) for value in param.values), style=wx.CB_DROPDOWN)
|
||||
input.Bind(wx.EVT_COMBOBOX, self.changed)
|
||||
input.Bind(wx.EVT_TEXT, self.changed)
|
||||
else:
|
||||
|
@ -326,14 +336,33 @@ class ParamsTab(ScrolledPanel):
|
|||
|
||||
self.param_inputs[param.name] = input
|
||||
|
||||
self.settings_grid.Add(input, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL)
|
||||
self.settings_grid.Add(input, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.LEFT, border=40)
|
||||
self.settings_grid.Add(wx.StaticText(self, label=param.unit or ""), proportion=1, flag=wx.ALIGN_CENTER_VERTICAL)
|
||||
|
||||
self.inputs_to_params = {v: k for k, v in self.param_inputs.iteritems()}
|
||||
|
||||
box.Add(self.settings_grid, proportion=1, flag=wx.ALL, border=10)
|
||||
self.SetSizer(box)
|
||||
|
||||
self.Layout()
|
||||
|
||||
def create_change_indicator(self, param):
|
||||
indicator = wx.Button(self, style=wx.BORDER_NONE | wx.BU_NOTEXT, size=(28, 28))
|
||||
indicator.SetToolTip(_('Click to force this parameter to be saved when you click "Apply and Quit"'))
|
||||
indicator.Bind(wx.EVT_BUTTON, lambda event: self.enable_change_indicator(param))
|
||||
|
||||
self.param_change_indicators[param] = indicator
|
||||
return indicator
|
||||
|
||||
def enable_change_indicator(self, param):
|
||||
self.param_change_indicators[param].SetBitmapLabel(self.pencil_icon)
|
||||
self.param_change_indicators[param].SetToolTip(_('This parameter will be saved when you click "Apply and Quit"'))
|
||||
|
||||
self.changed_inputs.add(self.param_inputs[param])
|
||||
|
||||
if self.on_change_hook():
|
||||
self.on_change_hook(self)
|
||||
|
||||
# end of class SatinPane
|
||||
|
||||
class SettingsFrame(wx.Frame):
|
||||
|
@ -686,7 +715,7 @@ class Params(InkstitchExtension):
|
|||
getter = 'get_param'
|
||||
|
||||
values = filter(lambda item: item is not None,
|
||||
(getattr(node, getter)(param.name, str(param.default)) for node in nodes))
|
||||
(getattr(node, getter)(param.name, param.default) for node in nodes))
|
||||
|
||||
return values
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import sys
|
||||
import pyembroidery
|
||||
import simpletransform
|
||||
|
||||
from .i18n import _
|
||||
from .utils import Point
|
||||
from .svg import PIXELS_PER_MM, get_doc_size, get_viewbox_transform
|
||||
from .commands import global_command
|
||||
|
@ -92,4 +94,10 @@ def write_embroidery_file(file_path, stitch_plan, svg):
|
|||
settings['max_jump'] = float('inf')
|
||||
settings['explicit_trim'] = False
|
||||
|
||||
pyembroidery.write(pattern, file_path, settings)
|
||||
try:
|
||||
pyembroidery.write(pattern, file_path, settings)
|
||||
except IOError as e:
|
||||
# L10N low-level file error. %(error)s is (hopefully?) translated by
|
||||
# the user's system automatically.
|
||||
print >> sys.stderr, _("Error writing to %(path)s: %(error)s") % dict(path=file_path, error=e.message)
|
||||
sys.exit(1)
|
||||
|
|
|
@ -472,7 +472,8 @@ def connect_points(shape, start, end, running_stitch_length, row_spacing):
|
|||
# most cases. 1.4 is chosen as approximately the length of the
|
||||
# stitch connecting two rows if the side of the shape is at a 45
|
||||
# degree angle to the rows of stitches (sqrt(2)).
|
||||
if abs(end_projection - start_projection) < row_spacing * 1.4:
|
||||
direct_distance = abs(end_projection - start_projection)
|
||||
if direct_distance < row_spacing * 1.4 and direct_distance < running_stitch_length:
|
||||
return [InkstitchPoint(end.x, end.y)]
|
||||
|
||||
# The outline path has a "natural" starting point. Think of this as
|
||||
|
|
|
@ -8,3 +8,10 @@ def get_bundled_dir(name):
|
|||
return realpath(os.path.join(sys._MEIPASS, "..", name))
|
||||
else:
|
||||
return realpath(os.path.join(dirname(realpath(__file__)), '..', '..', name))
|
||||
|
||||
|
||||
def get_resource_dir(name):
|
||||
if getattr(sys, 'frozen', None) is not None:
|
||||
return realpath(os.path.join(sys._MEIPASS, name))
|
||||
else:
|
||||
return realpath(os.path.join(dirname(realpath(__file__)), '..', '..', name))
|
||||
|
|
97
messages.po
97
messages.po
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2018-09-12 20:30-0400\n"
|
||||
"POT-Creation-Date: 2018-09-12 20:51-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -107,7 +107,7 @@ msgid "%(command)s: %(description)s"
|
|||
msgstr ""
|
||||
|
||||
#: lib/elements/auto_fill.py:11
|
||||
msgid "Auto-Fill"
|
||||
msgid "AutoFill"
|
||||
msgstr ""
|
||||
|
||||
#: lib/elements/auto_fill.py:14
|
||||
|
@ -178,11 +178,25 @@ msgid ""
|
|||
"shapes."
|
||||
msgstr ""
|
||||
|
||||
#: lib/elements/element.py:230
|
||||
#: lib/elements/element.py:202
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Object %(id)s has an empty 'd' attribute. Please delete this object from"
|
||||
" your document."
|
||||
msgstr ""
|
||||
|
||||
#: lib/elements/element.py:234
|
||||
#, python-format
|
||||
msgid "%(id)s has more than one command of type '%(command)s' linked to it"
|
||||
msgstr ""
|
||||
|
||||
#. used when showing an error message to the user such as "satin column: One or
|
||||
#. more of the rungs doesn't
|
||||
#. intersect both rails."
|
||||
#: lib/elements/element.py:273
|
||||
msgid "error:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/elements/fill.py:12
|
||||
msgid "Fill"
|
||||
msgstr ""
|
||||
|
@ -250,6 +264,10 @@ msgid ""
|
|||
" it bigger or delete it."
|
||||
msgstr ""
|
||||
|
||||
#: lib/elements/fill.py:125
|
||||
msgid "shape is not valid. This can happen if the border crosses over itself."
|
||||
msgstr ""
|
||||
|
||||
#: lib/elements/satin_column.py:10
|
||||
msgid "Satin Column"
|
||||
msgstr ""
|
||||
|
@ -487,7 +505,7 @@ msgstr ""
|
|||
msgid "Install"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/install.py:40 lib/extensions/params.py:379
|
||||
#: lib/extensions/install.py:40 lib/extensions/params.py:408
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
|
@ -495,25 +513,25 @@ msgstr ""
|
|||
msgid "Choose Inkscape directory"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/install.py:64
|
||||
#: lib/extensions/install.py:71
|
||||
msgid "Inkscape add-on installation failed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/install.py:65
|
||||
#: lib/extensions/install.py:72
|
||||
msgid "Installation Failed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/install.py:69
|
||||
#: lib/extensions/install.py:76
|
||||
msgid ""
|
||||
"Inkscape add-on files have been installed. Please restart Inkscape to "
|
||||
"load the new add-ons."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/install.py:70
|
||||
#: lib/extensions/install.py:77
|
||||
msgid "Installation Completed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/install.py:107
|
||||
#: lib/extensions/install.py:114
|
||||
msgid "Ink/Stitch Add-ons Installer"
|
||||
msgstr ""
|
||||
|
||||
|
@ -543,94 +561,104 @@ msgstr ""
|
|||
msgid "Please choose one or more commands to attach."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:244
|
||||
#: lib/extensions/params.py:250
|
||||
msgid "These settings will be applied to 1 object."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:246
|
||||
#: lib/extensions/params.py:252
|
||||
#, python-format
|
||||
msgid "These settings will be applied to %d objects."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:249
|
||||
#: lib/extensions/params.py:255
|
||||
msgid ""
|
||||
"Some settings had different values across objects. Select a value from "
|
||||
"the dropdown or enter a new one."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:253
|
||||
#: lib/extensions/params.py:259
|
||||
#, python-format
|
||||
msgid "Disabling this tab will disable the following %d tabs."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:255
|
||||
#: lib/extensions/params.py:261
|
||||
msgid "Disabling this tab will disable the following tab."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:258
|
||||
#: lib/extensions/params.py:264
|
||||
#, python-format
|
||||
msgid "Enabling this tab will disable %s and vice-versa."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:288
|
||||
#: lib/extensions/params.py:294
|
||||
msgid "Inkscape objects"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:345
|
||||
#: lib/extensions/params.py:351
|
||||
msgid ""
|
||||
"Click to force this parameter to be saved when you click \"Apply and "
|
||||
"Quit\""
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:359
|
||||
msgid "This parameter will be saved when you click \"Apply and Quit\""
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:374
|
||||
msgid "Embroidery Params"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:362
|
||||
#: lib/extensions/params.py:391
|
||||
msgid "Presets"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:367
|
||||
#: lib/extensions/params.py:396
|
||||
msgid "Load"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:370
|
||||
#: lib/extensions/params.py:399
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:373
|
||||
#: lib/extensions/params.py:402
|
||||
msgid "Overwrite"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:376
|
||||
#: lib/extensions/params.py:405
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:383
|
||||
#: lib/extensions/params.py:412
|
||||
msgid "Use Last Settings"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:386
|
||||
#: lib/extensions/params.py:415
|
||||
msgid "Apply and Quit"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:439
|
||||
#: lib/extensions/params.py:468
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:455
|
||||
#: lib/extensions/params.py:484
|
||||
msgid "Internal Error"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:508
|
||||
#: lib/extensions/params.py:537
|
||||
msgid "Please enter or select a preset name first."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:508 lib/extensions/params.py:514
|
||||
#: lib/extensions/params.py:542
|
||||
#: lib/extensions/params.py:537 lib/extensions/params.py:543
|
||||
#: lib/extensions/params.py:571
|
||||
msgid "Preset"
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:514
|
||||
#: lib/extensions/params.py:543
|
||||
#, python-format
|
||||
msgid "Preset \"%s\" not found."
|
||||
msgstr ""
|
||||
|
||||
#: lib/extensions/params.py:542
|
||||
#: lib/extensions/params.py:571
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Preset \"%s\" already exists. Please use another name or press "
|
||||
|
@ -670,6 +698,13 @@ msgstr ""
|
|||
msgid "Generate INX files"
|
||||
msgstr ""
|
||||
|
||||
#. low-level file error. %(error)s is (hopefully?) translated by
|
||||
#. the user's system automatically.
|
||||
#: lib/output.py:102
|
||||
#, python-format
|
||||
msgid "Error writing to %(path)s: %(error)s"
|
||||
msgstr ""
|
||||
|
||||
#. command label at bottom of simulator window
|
||||
#: lib/simulator.py:12
|
||||
msgid "STITCH"
|
||||
|
|
Ładowanie…
Reference in New Issue