Merge pull request #301 from inkstitch/lexelby/bug-fixes

bug fixes
pull/325/head
Lex Neva 2018-09-12 21:32:15 -04:00 zatwierdzone przez GitHub
commit 7b8af2ed57
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
13 zmienionych plików z 153 dodań i 57 usunięć

Wyświetl plik

@ -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 \

BIN
icons/pencil.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 734 B

Wyświetl plik

@ -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

Wyświetl plik

@ -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)

Wyświetl plik

@ -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):

Wyświetl plik

@ -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)

Wyświetl plik

@ -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()

Wyświetl plik

@ -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

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -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))

Wyświetl plik

@ -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"