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

more bug fixes
pull/338/head
Lex Neva 2018-09-29 13:22:05 -06:00 zatwierdzone przez GitHub
commit 5139c13fd7
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 108 dodań i 88 usunięć

Wyświetl plik

@ -60,4 +60,4 @@ locales:
.PHONY: style
style:
flake8 . --count --max-complexity=10 --max-line-length=150 --statistics --exclude=pyembroidery,__init__.py,simulator.py,params.py
flake8 . --count --max-complexity=10 --max-line-length=150 --statistics --exclude=pyembroidery,__init__.py

Wyświetl plik

@ -4,20 +4,18 @@ import os
import sys
import json
import traceback
import time
from threading import Thread, Event
from copy import copy
import wx
from wx.lib.scrolledpanel import ScrolledPanel
from collections import defaultdict
from functools import partial
from itertools import groupby
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, get_resource_dir
from ..utils import get_resource_dir
from ..simulator import EmbroiderySimulator
from ..commands import is_command
@ -39,7 +37,7 @@ def load_presets():
with open(presets_path(), 'r') as presets:
presets = json.load(presets)
return presets
except:
except IOError:
return {}
@ -64,14 +62,14 @@ def delete_preset(name):
save_presets(presets)
def confirm_dialog(parent, question, caption = 'ink/stitch'):
def confirm_dialog(parent, question, caption='ink/stitch'):
dlg = wx.MessageDialog(parent, question, caption, wx.YES_NO | wx.ICON_QUESTION)
result = dlg.ShowModal() == wx.ID_YES
dlg.Destroy()
return result
def info_dialog(parent, message, caption = 'ink/stitch'):
def info_dialog(parent, message, caption='ink/stitch'):
dlg = wx.MessageDialog(parent, message, caption, wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
@ -298,12 +296,12 @@ class ParamsTab(ScrolledPanel):
self.description.SetLabel(self.description_text)
self.description_container = box
self.Bind(wx.EVT_SIZE, self.resized)
sizer.Add(self.description, proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
sizer.Add(self.description, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
box.Add(sizer, proportion=0, flag=wx.ALL, border=5)
if self.toggle:
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.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)
@ -312,7 +310,7 @@ class ParamsTab(ScrolledPanel):
description = wx.StaticText(self, label=param.description)
description.SetToolTip(param.tooltip)
self.settings_grid.Add(description, proportion=1, flag=wx.EXPAND|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=5)
self.settings_grid.Add(description, proportion=1, flag=wx.EXPAND | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.TOP, border=5)
if param.type == 'boolean':
@ -336,7 +334,7 @@ class ParamsTab(ScrolledPanel):
self.param_inputs[param.name] = input
self.settings_grid.Add(input, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.LEFT, border=40)
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()}
@ -365,6 +363,7 @@ class ParamsTab(ScrolledPanel):
# end of class SatinPane
class SettingsFrame(wx.Frame):
def __init__(self, *args, **kwargs):
# begin wxGlade: MyFrame.__init__
@ -471,14 +470,14 @@ class SettingsFrame(wx.Frame):
stitch_plan=stitch_plan,
on_close=self.simulate_window_closed,
target_duration=5)
except:
except Exception:
error = traceback.format_exc()
try:
# a window may have been created, so we need to destroy it
# or the app will never exit
wx.Window.FindWindowByName("Preview").Destroy()
except:
wx.Window.FindWindowByName(_("Preview")).Destroy()
except Exception:
pass
info_dialog(self, error, _("Internal Error"))
@ -517,7 +516,7 @@ class SettingsFrame(wx.Frame):
patches.extend(copy(node).embroider(None))
except SystemExit:
raise
except:
except Exception:
# Ignore errors. This can be things like incorrect paths for
# satins or division by zero caused by incorrect param values.
pass
@ -578,7 +577,6 @@ class SettingsFrame(wx.Frame):
def overwrite_preset(self, event):
self.add_preset(event, overwrite=True)
def _load_preset(self, preset_name):
preset = self.check_and_load_preset(preset_name)
if not preset:
@ -587,7 +585,6 @@ class SettingsFrame(wx.Frame):
for tab in self.tabs:
tab.load_preset(preset)
def load_preset(self, event):
preset_name = self.get_preset_name()
if not preset_name:
@ -597,7 +594,6 @@ class SettingsFrame(wx.Frame):
event.Skip()
def delete_preset(self, event):
preset_name = self.get_preset_name()
if not preset_name:
@ -649,30 +645,32 @@ class SettingsFrame(wx.Frame):
def __do_layout(self):
# begin wxGlade: MyFrame.__do_layout
sizer_1 = wx.BoxSizer(wx.VERTICAL)
#self.sizer_3_staticbox.Lower()
# self.sizer_3_staticbox.Lower()
sizer_2 = wx.StaticBoxSizer(self.presets_box, wx.HORIZONTAL)
sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
for tab in self.tabs:
self.notebook.AddPage(tab, tab.name)
sizer_1.Add(self.notebook, 1, wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, 10)
sizer_2.Add(self.preset_chooser, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
sizer_2.Add(self.load_preset_button, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
sizer_2.Add(self.add_preset_button, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
sizer_2.Add(self.overwrite_preset_button, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
sizer_2.Add(self.delete_preset_button, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
sizer_1.Add(sizer_2, 0, flag=wx.EXPAND|wx.ALL, border=10)
sizer_3.Add(self.cancel_button, 0, wx.ALIGN_RIGHT|wx.RIGHT, 5)
sizer_3.Add(self.use_last_button, 0, wx.ALIGN_RIGHT|wx.RIGHT|wx.BOTTOM, 5)
sizer_3.Add(self.apply_button, 0, wx.ALIGN_RIGHT|wx.RIGHT|wx.BOTTOM, 5)
sizer_1.Add(self.notebook, 1, wx.EXPAND | wx.LEFT | wx.TOP | wx.RIGHT, 10)
sizer_2.Add(self.preset_chooser, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
sizer_2.Add(self.load_preset_button, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
sizer_2.Add(self.add_preset_button, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
sizer_2.Add(self.overwrite_preset_button, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
sizer_2.Add(self.delete_preset_button, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
sizer_1.Add(sizer_2, 0, flag=wx.EXPAND | wx.ALL, border=10)
sizer_3.Add(self.cancel_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 5)
sizer_3.Add(self.use_last_button, 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, 5)
sizer_3.Add(self.apply_button, 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, 5)
sizer_1.Add(sizer_3, 0, wx.ALIGN_RIGHT, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.Layout()
# end wxGlade
class NoValidObjects(Exception):
pass
class Params(InkstitchExtension):
def __init__(self, *args, **kwargs):
self.cancelled = False
@ -728,6 +726,41 @@ class Params(InkstitchExtension):
return groupby(sorted(params, key=by_group_and_sort_index), by_group)
def sort_tabs(self, tabs):
def tab_sort_key(tab):
parent = tab.parent_tab or tab
sort_key = (
# For Stroke and SatinColumn, place the one that's
# enabled first. Place dependent tabs first too.
parent.toggle and parent.toggle_checkbox.IsChecked(),
# If multiple tabs are enabled, make sure dependent
# tabs are grouped with the parent.
parent,
# Within parent/dependents, put the parent first.
tab == parent
)
return sort_key
tabs.sort(key=tab_sort_key, reverse=True)
def pair_tabs(self, tabs):
for tab in tabs:
if tab.toggle and tab.toggle.inverse:
for other_tab in tabs:
if other_tab != tab and other_tab.toggle.name == tab.toggle.name:
tab.pair(other_tab)
other_tab.pair(tab)
def assign_parents(self, tabs, parent_tab):
for tab in tabs:
if tab != parent_tab:
parent_tab.add_dependent_tab(tab)
tab.set_parent_tab(parent_tab)
def create_tabs(self, parent):
tabs = []
nodes_by_class = self.get_nodes_by_class()
@ -744,49 +777,21 @@ class Params(InkstitchExtension):
parent_tab = None
new_tabs = []
for group, params in self.group_params(params):
tab = ParamsTab(parent, id=wx.ID_ANY, name=group or cls.element_name, params=list(params), nodes=nodes)
tab_name = group or cls.element_name
tab = ParamsTab(parent, id=wx.ID_ANY, name=tab_name, params=list(params), nodes=nodes)
new_tabs.append(tab)
if group is None:
parent_tab = tab
for tab in new_tabs:
if tab != parent_tab:
parent_tab.add_dependent_tab(tab)
tab.set_parent_tab(parent_tab)
self.assign_parents(new_tabs, parent_tab)
tabs.extend(new_tabs)
for tab in tabs:
if tab.toggle and tab.toggle.inverse:
for other_tab in tabs:
if other_tab != tab and other_tab.toggle.name == tab.toggle.name:
tab.pair(other_tab)
other_tab.pair(tab)
def tab_sort_key(tab):
parent = tab.parent_tab or tab
sort_key = (
# For Stroke and SatinColumn, place the one that's
# enabled first. Place dependent tabs first too.
parent.toggle and parent.toggle_checkbox.IsChecked(),
# If multiple tabs are enabled, make sure dependent
# tabs are grouped with the parent.
parent,
# Within parent/dependents, put the parent first.
tab == parent
)
return sort_key
tabs.sort(key=tab_sort_key, reverse=True)
self.pair_tabs(tabs)
self.sort_tabs(tabs)
return tabs
def cancel(self):
self.cancelled = True

Wyświetl plik

@ -2,7 +2,7 @@ from ..utils.geometry import Point
class Stitch(Point):
def __init__(self, x, y, color=None, jump=False, stop=False, trim=False, color_change=False, fake_color_change=False, no_ties=False):
def __init__(self, x, y=None, color=None, jump=False, stop=False, trim=False, color_change=False, no_ties=False):
self.x = x
self.y = y
self.color = color
@ -10,20 +10,24 @@ class Stitch(Point):
self.trim = trim
self.stop = stop
self.color_change = color_change
self.fake_color_change = fake_color_change
self.no_ties = no_ties
# Allow creating a Stitch from a Point
if isinstance(x, Point):
point = x
self.x = point.x
self.y = point.y
def __repr__(self):
return "Stitch(%s, %s, %s, %s, %s, %s, %s, %s%s)" % (self.x,
self.y,
self.color,
"JUMP" if self.jump else " ",
"TRIM" if self.trim else " ",
"STOP" if self.stop else " ",
"NO TIES" if self.no_ties else " ",
"FAKE " if self.fake_color_change else "",
"COLOR CHANGE" if self.color_change else " "
)
return "Stitch(%s, %s, %s, %s, %s, %s, %s, %s)" % (self.x,
self.y,
self.color,
"JUMP" if self.jump else " ",
"TRIM" if self.trim else " ",
"STOP" if self.stop else " ",
"NO TIES" if self.no_ties else " ",
"COLOR CHANGE" if self.color_change else " "
)
def copy(self):
return Stitch(self.x, self.y, self.color, self.jump, self.stop, self.trim, self.color_change, self.no_ties)

Wyświetl plik

@ -1,26 +1,37 @@
from copy import deepcopy
from .stitch import Stitch
from ..utils import cut_path
from ..stitches import running_stitch
from ..svg import PIXELS_PER_MM
def add_tie(stitches, tie_path):
if stitches[-1].no_ties:
if len(tie_path) < 2 or stitches[0].no_ties:
# It's from a manual stitch block, so don't add tie stitches. The user
# will add them if they want them.
return
tie_path = cut_path(tie_path, 0.6)
tie_stitches = running_stitch(tie_path, 0.3)
tie_stitches = [Stitch(stitch.x, stitch.y) for stitch in tie_stitches]
to_previous = tie_path[1] - tie_path[0]
length = to_previous.length()
if length > 0.5 * PIXELS_PER_MM:
# Travel back one stitch, stopping halfway there.
# Then go forward one stitch, stopping halfway between
# again.
stitches.extend(deepcopy(tie_stitches[1:]))
stitches.extend(deepcopy(list(reversed(tie_stitches))[1:]))
# but travel at most 1.5mm
length = min(length, 1.5 * PIXELS_PER_MM)
direction = to_previous.unit()
for delta in (0.5, 1.0, 0.5, 0):
stitches.append(Stitch(tie_path[0] + delta * length * direction))
else:
# Too short to travel part of the way to the previous stitch; ust go
# back and forth to it a couple times.
for i in (1, 0, 1, 0):
stitches.append(deepcopy(tie_path[i]))
def add_tie_off(stitches):
add_tie(stitches, list(reversed(stitches)))
add_tie(stitches, stitches[-1:-3:-1])
def add_tie_in(stitches, upcoming_stitches):
@ -36,10 +47,7 @@ def add_ties(stitch_plan):
for i, stitch in enumerate(color_block.stitches):
is_special = stitch.trim or stitch.jump or stitch.color_change or stitch.stop
# see stop.py for an explanation of the fake color change
is_fake = stitch.fake_color_change
if is_special and not is_fake and not need_tie_in:
if is_special and not need_tie_in:
add_tie_off(new_stitches)
new_stitches.append(stitch)
need_tie_in = True

Wyświetl plik

@ -80,7 +80,10 @@ def convert_length(length):
@cache
def get_viewbox(svg):
return svg.get('viewBox').strip().replace(',', ' ').split()
viewbox = svg.get('viewBox')
if viewbox is None:
viewbox = "0 0 0 0"
return viewbox.strip().replace(',', ' ').split()
@cache