diff --git a/lib/elements/clone.py b/lib/elements/clone.py index f430f9b3b..f408917d7 100644 --- a/lib/elements/clone.py +++ b/lib/elements/clone.py @@ -5,8 +5,6 @@ from math import atan, degrees -import inkex - from ..commands import is_command, is_command_symbol from ..i18n import _ from ..svg.path import get_node_transform @@ -128,7 +126,7 @@ class Clone(EmbroideryElement): return patches def get_clone_style(self, style_name, node, default=None): - style = inkex.styles.AttrFallbackStyle(node).get(style_name) or default + style = node.style[style_name] or default return style def center(self, source_node): diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 497ee4718..a30f16d4d 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -6,17 +6,18 @@ from copy import deepcopy from itertools import chain -from inkex import paths from shapely import affinity as shaffinity from shapely import geometry as shgeo from shapely.ops import nearest_points -from .element import EmbroideryElement, param -from .validation import ValidationError, ValidationWarning +from inkex import paths + from ..i18n import _ from ..stitch_plan import StitchGroup from ..svg import line_strings_to_csp, point_lists_to_csp from ..utils import Point, cache, collapse_duplicate_point, cut +from .element import EmbroideryElement, param +from .validation import ValidationError, ValidationWarning class SatinHasFillError(ValidationError): @@ -51,6 +52,15 @@ class UnequalPointsError(ValidationError): ] +class NotStitchableError(ValidationError): + name = _("Not stitchable satin column") + description = _("A satin column consists out of two rails and one or more rungs. This satin column may have a different setup.") + steps_to_solve = [ + _('Make sure your satin column is not a combination of multiple satin columns.'), + _('Go to our website and read how a satin column should look like https://inkstitch.org/docs/stitches/satin-column/'), + ] + + rung_message = _("Each rung should intersect both rails once.") @@ -422,6 +432,9 @@ class SatinColumn(EmbroideryElement): if not intersection.is_empty and not isinstance(intersection, shgeo.Point): yield TooManyIntersectionsError(rung.interpolate(0.5, normalized=True)) + if not self.to_stitch_groups(): + yield NotStitchableError(self.shape.centroid) + def reverse(self): """Return a new SatinColumn like this one but in the opposite direction. @@ -859,7 +872,7 @@ class SatinColumn(EmbroideryElement): points.append(Point(split_point.x, split_point.y)) return [points, split_count] - def to_stitch_groups(self, last_patch): + def to_stitch_groups(self, last_patch=None): # Stitch a variable-width satin column, zig-zagging between two paths. # The algorithm will draw zigzags between each consecutive pair of @@ -884,4 +897,7 @@ class SatinColumn(EmbroideryElement): else: patch += self.do_satin() + if not patch.stitches: + return [] + return [patch] diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 763167ad5..307c78b87 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -77,7 +77,8 @@ class Stroke(EmbroideryElement): default="1", sort_index=1) def repeats(self): - return self.get_int_param("repeats", 1) + repeats = self.get_int_param("repeats", 1) + return max(1, repeats) @property def paths(self): diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py index 4c5e1a716..b6e0d1d18 100644 --- a/lib/extensions/__init__.py +++ b/lib/extensions/__init__.py @@ -5,6 +5,7 @@ from lib.extensions.troubleshoot import Troubleshoot +from .apply_threadlist import ApplyThreadlist from .auto_satin import AutoSatin from .break_apart import BreakApart from .cleanup import Cleanup @@ -18,7 +19,6 @@ from .embroider_settings import EmbroiderSettings from .flip import Flip from .generate_palette import GeneratePalette from .global_commands import GlobalCommands -from .import_threadlist import ImportThreadlist from .input import Input from .install import Install from .install_custom_palette import InstallCustomPalette @@ -71,7 +71,7 @@ __all__ = extensions = [StitchPlanPreview, RemoveEmbroiderySettings, Cleanup, BreakApart, - ImportThreadlist, + ApplyThreadlist, InstallCustomPalette, GeneratePalette, PaletteSplitText, diff --git a/lib/extensions/import_threadlist.py b/lib/extensions/apply_threadlist.py similarity index 94% rename from lib/extensions/import_threadlist.py rename to lib/extensions/apply_threadlist.py index f7fe0bcc2..318615132 100644 --- a/lib/extensions/import_threadlist.py +++ b/lib/extensions/apply_threadlist.py @@ -14,7 +14,12 @@ from ..threads import ThreadCatalog from .base import InkstitchExtension -class ImportThreadlist(InkstitchExtension): +class ApplyThreadlist(InkstitchExtension): + ''' + Applies colors of a thread list to elements + Count of colors and elements should fit together + Use case: reapply colors to e.g. a dst file + ''' def __init__(self, *args, **kwargs): InkstitchExtension.__init__(self, *args, **kwargs) self.arg_parser.add_argument("-f", "--filepath", type=str, default="", dest="filepath") @@ -23,7 +28,7 @@ class ImportThreadlist(InkstitchExtension): def effect(self): # Remove selection, we want all the elements in the document - self.svg.selected.clear() + self.svg.selection.clear() if not self.get_elements(): return diff --git a/lib/extensions/auto_satin.py b/lib/extensions/auto_satin.py index 62fb15af7..dfb1a87e9 100644 --- a/lib/extensions/auto_satin.py +++ b/lib/extensions/auto_satin.py @@ -44,7 +44,7 @@ class AutoSatin(CommandsExtension): if not self.get_elements(): return - if not self.svg.selected: + if not self.svg.selection: # L10N auto-route satin columns extension inkex.errormsg(_("Please select one or more satin columns.")) return False diff --git a/lib/extensions/base.py b/lib/extensions/base.py index a065b5cca..75a07c5a8 100644 --- a/lib/extensions/base.py +++ b/lib/extensions/base.py @@ -121,7 +121,7 @@ class InkstitchExtension(inkex.Effect): return current_layer def no_elements_error(self): - if self.svg.selected: + if self.svg.selection: # l10n This was previously: "No embroiderable paths selected." inkex.errormsg(_("Ink/Stitch doesn't know how to work with any of the objects you've selected.") + "\n") else: @@ -156,8 +156,8 @@ class InkstitchExtension(inkex.Effect): if is_command(node) or node.get(CONNECTOR_TYPE): return [] - if self.svg.selected: - if node.get("id") in self.svg.selected: + if self.svg.selection: + if node.get("id") in self.svg.selection: selected = True else: # if the user didn't select anything that means we process everything @@ -188,14 +188,6 @@ class InkstitchExtension(inkex.Effect): self.no_elements_error() return False - def get_selected_in_order(self): - selected = [] - for i in self.options.ids: - path = '//*[@id="%s"]' % i - for node in self.document.xpath(path, namespaces=inkex.NSS): - selected.append(node) - return selected - def elements_to_stitch_groups(self, elements): patches = [] for element in elements: diff --git a/lib/extensions/break_apart.py b/lib/extensions/break_apart.py index b16c901d2..5bfd88a48 100644 --- a/lib/extensions/break_apart.py +++ b/lib/extensions/break_apart.py @@ -27,7 +27,7 @@ class BreakApart(InkstitchExtension): self.minimum_size = 5 def effect(self): # noqa: C901 - if not self.svg.selected: + if not self.svg.selection: inkex.errormsg(_("Please select one or more fill areas to break apart.")) return diff --git a/lib/extensions/cleanup.py b/lib/extensions/cleanup.py index 99b72a815..a38818b84 100644 --- a/lib/extensions/cleanup.py +++ b/lib/extensions/cleanup.py @@ -24,7 +24,7 @@ class Cleanup(InkstitchExtension): self.fill_threshold = self.options.fill_threshold self.stroke_threshold = self.options.stroke_threshold - self.svg.selected.clear() + self.svg.selection.clear() count = 0 svg = self.document.getroot() diff --git a/lib/extensions/convert_to_satin.py b/lib/extensions/convert_to_satin.py index 577cd7c05..9950b2e8a 100644 --- a/lib/extensions/convert_to_satin.py +++ b/lib/extensions/convert_to_satin.py @@ -31,7 +31,7 @@ class ConvertToSatin(InkstitchExtension): if not self.get_elements(): return - if not self.svg.selected: + if not self.svg.selection: inkex.errormsg(_("Please select at least one line to convert to a satin column.")) return diff --git a/lib/extensions/convert_to_stroke.py b/lib/extensions/convert_to_stroke.py index dfaef6153..5a2ab23c5 100644 --- a/lib/extensions/convert_to_stroke.py +++ b/lib/extensions/convert_to_stroke.py @@ -21,7 +21,7 @@ class ConvertToStroke(InkstitchExtension): self.arg_parser.add_argument("-k", "--keep_satin", type=inkex.Boolean, default=False, dest="keep_satin") def effect(self): - if not self.svg.selected or not self.get_elements(): + if not self.svg.selection or not self.get_elements(): inkex.errormsg(_("Please select at least one satin column to convert to a running stitch.")) return diff --git a/lib/extensions/cut_satin.py b/lib/extensions/cut_satin.py index fcd1ca065..3d38c7d87 100644 --- a/lib/extensions/cut_satin.py +++ b/lib/extensions/cut_satin.py @@ -16,7 +16,7 @@ class CutSatin(InkstitchExtension): if not self.get_elements(): return - if not self.svg.selected: + if not self.svg.selection: inkex.errormsg(_("Please select one or more satin columns to cut.")) return diff --git a/lib/extensions/cutwork_segmentation.py b/lib/extensions/cutwork_segmentation.py index 1b0c568e0..672aeade2 100644 --- a/lib/extensions/cutwork_segmentation.py +++ b/lib/extensions/cutwork_segmentation.py @@ -43,7 +43,7 @@ class CutworkSegmentation(InkstitchExtension): self.arg_parser.add_argument("-k", "--keep_original", type=inkex.Boolean, default=False, dest="keep_original") def effect(self): - if not self.svg.selected: + if not self.svg.selection: inkex.errormsg(_("Please select one or more stroke elements.")) return diff --git a/lib/extensions/duplicate_params.py b/lib/extensions/duplicate_params.py index 9fcdbf1c0..461106910 100644 --- a/lib/extensions/duplicate_params.py +++ b/lib/extensions/duplicate_params.py @@ -3,10 +3,9 @@ # Copyright (c) 2021 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -import inkex +from inkex import NSS, ShapeElement, errormsg from ..i18n import _ -from ..svg.tags import EMBROIDERABLE_TAGS, SVG_GROUP_TAG from .base import InkstitchExtension @@ -14,36 +13,29 @@ class DuplicateParams(InkstitchExtension): # Transfer inkstitch namespaced attributes from the first selected element to the rest of selection def effect(self): - objects = self.get_selected_in_order() + objects = self.svg.selection.get(ShapeElement) if len(objects) < 2: - inkex.errormsg(_("This function copies Ink/Stitch parameters from the first selected element to the rest of the selection. " - "Please select at least two elements.")) + errormsg(_("This function copies Ink/Stitch parameters from the first selected element to the rest of the selection. " + "Please select at least two elements.")) return - copy_from = objects[0] + copy_from = objects.first() copy_from_attribs = self.get_inkstitch_attributes(copy_from) - copy_to_selection = objects[1:] - self.copy_to = [] - - # extract copy_to group elements - for element in copy_to_selection: - if element.tag == SVG_GROUP_TAG: - for descendant in element.iterdescendants(EMBROIDERABLE_TAGS): - self.copy_to.append(descendant) - elif element.tag in EMBROIDERABLE_TAGS: - self.copy_to.append(element) + copy_to = objects # remove inkstitch params from copy_to elements - for element in self.copy_to: + for element in copy_to: + if element == copy_to.first(): + continue copy_to_attribs = self.get_inkstitch_attributes(element) for attrib in copy_to_attribs: element.pop(attrib) # paste inkstitch params from copy_from element to copy_to elements for attrib in copy_from_attribs: - for element in self.copy_to: + for element in copy_to: element.attrib[attrib] = copy_from_attribs[attrib] def get_inkstitch_attributes(self, node): - return {k: v for k, v in node.attrib.iteritems() if inkex.NSS['inkstitch'] in k} + return {k: v for k, v in node.attrib.iteritems() if NSS['inkstitch'] in k} diff --git a/lib/extensions/flip.py b/lib/extensions/flip.py index 743f1701b..893dc038f 100644 --- a/lib/extensions/flip.py +++ b/lib/extensions/flip.py @@ -24,7 +24,7 @@ class Flip(InkstitchExtension): if not self.get_elements(): return - if not self.svg.selected: + if not self.svg.selection: inkex.errormsg(_("Please select one or more satin columns to flip.")) return diff --git a/lib/extensions/lettering.py b/lib/extensions/lettering.py index 35509eb64..658f2bc73 100644 --- a/lib/extensions/lettering.py +++ b/lib/extensions/lettering.py @@ -9,10 +9,11 @@ import sys from base64 import b64decode import appdirs -import inkex import wx import wx.adv +import inkex + from ..elements import nodes_to_elements from ..gui import PresetsPanel, SimulatorPreview, info_dialog from ..i18n import _ @@ -272,12 +273,15 @@ class LetteringFrame(wx.Frame): font.render_text(self.settings.text, destination_group, back_and_forth=self.settings.back_and_forth, trim=self.settings.trim) except FontError as e: if raise_error: - inkex.errormsg("Error: Text cannot be applied to the document.\n%s" % e) + inkex.errormsg(_("Error: Text cannot be applied to the document.\n%s") % e) return else: pass - if self.settings.scale != 100: + # destination_group isn't always the text scaling group (but also the parent group) + # the text scaling group label is dependend on the user language, so it would break in international file exchange if we used it + # scaling (correction transform) on the parent group is already applied, so let's use that for recognition + if self.settings.scale != 100 and not destination_group.get('transform', None): destination_group.attrib['transform'] = 'scale(%s)' % (self.settings.scale / 100.0) def generate_patches(self, abort_early=None): @@ -395,10 +399,10 @@ class Lettering(CommandsExtension): self.cancelled = True def get_or_create_group(self): - if self.svg.selected: + if self.svg.selection: groups = set() - for node in self.svg.selected.values(): + for node in self.svg.selection: if node.tag == SVG_GROUP_TAG and INKSTITCH_LETTERING in node.attrib: groups.add(node) diff --git a/lib/extensions/object_commands.py b/lib/extensions/object_commands.py index 851d4a347..a3ad61285 100644 --- a/lib/extensions/object_commands.py +++ b/lib/extensions/object_commands.py @@ -17,7 +17,7 @@ class ObjectCommands(CommandsExtension): if not self.get_elements(): return - if not self.svg.selected: + if not self.svg.selection: inkex.errormsg(_("Please select one or more objects to which to attach commands.")) return diff --git a/lib/extensions/palette_split_text.py b/lib/extensions/palette_split_text.py index 6c024cedb..3257d6949 100644 --- a/lib/extensions/palette_split_text.py +++ b/lib/extensions/palette_split_text.py @@ -22,22 +22,21 @@ class PaletteSplitText(InkstitchExtension): line_height = self.options.line_height - for text in self.svg.selected: - if type(text) == inkex.elements.TextElement: - parent = text.getparent() - content = text.get_text() - lines = content.split('\n') - lines.reverse() - style = text.get('style') - x = text.get('x') - y = text.get('y') - y = float(y) + (len(lines) - 1) * line_height - for line in lines: - element = inkex.TextElement() - element.text = line - element.set('style', style) - element.set('x', x) - element.set('y', str(y)) - y = float(y) - line_height - parent.insert(0, element) - parent.remove(text) + for text in self.svg.selection.get(inkex.elements.TextElement): + parent = text.getparent() + content = text.get_text() + lines = content.split('\n') + lines.reverse() + style = text.get('style') + x = text.get('x') + y = text.get('y') + y = float(y) + (len(lines) - 1) * line_height + for line in lines: + element = inkex.TextElement() + element.text = line + element.set('style', style) + element.set('x', x) + element.set('y', str(y)) + y = float(y) - line_height + parent.insert(0, element) + parent.remove(text) diff --git a/lib/extensions/print_pdf.py b/lib/extensions/print_pdf.py index 16ca3a089..63c3c699a 100644 --- a/lib/extensions/print_pdf.py +++ b/lib/extensions/print_pdf.py @@ -301,7 +301,7 @@ class Print(InkstitchExtension): # objects. It's almost certain they meant to print the whole design. # If they really wanted to print just a few objects, they could set # the rest invisible temporarily. - self.svg.selected.clear() + self.svg.selection.clear() if not self.get_elements(): return diff --git a/lib/extensions/remove_embroidery_settings.py b/lib/extensions/remove_embroidery_settings.py index 31c15cd9c..d8e6cb0e0 100644 --- a/lib/extensions/remove_embroidery_settings.py +++ b/lib/extensions/remove_embroidery_settings.py @@ -3,11 +3,10 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -from inkex import NSS, Boolean +from inkex import NSS, Boolean, ShapeElement from ..commands import find_commands from ..svg.svg import find_elements -from ..svg.tags import EMBROIDERABLE_TAGS, SVG_GROUP_TAG from .base import InkstitchExtension @@ -36,7 +35,7 @@ class RemoveEmbroiderySettings(InkstitchExtension): self.remove_element(print_setting) def remove_params(self): - if not self.svg.selected: + if not self.svg.selection: xpath = ".//svg:path|.//svg:circle|.//svg:rect|.//svg:ellipse" elements = find_elements(self.svg, xpath) self.remove_inkstitch_attributes(elements) @@ -45,7 +44,7 @@ class RemoveEmbroiderySettings(InkstitchExtension): self.remove_inkstitch_attributes(elements) def remove_commands(self): - if not self.svg.selected: + if not self.svg.selection: # remove intact command groups xpath = ".//svg:g[starts-with(@id,'command_group')]" groups = find_elements(self.svg, xpath) @@ -58,7 +57,7 @@ class RemoveEmbroiderySettings(InkstitchExtension): group = command.connector.getparent() group.getparent().remove(group) - if not self.svg.selected: + if not self.svg.selection: # remove standalone commands and ungrouped object commands standalone_commands = ".//svg:use[starts-with(@xlink:href, '#inkstitch_')]|.//svg:path[starts-with(@id, 'command_connector')]" self.remove_elements(standalone_commands) @@ -68,14 +67,7 @@ class RemoveEmbroiderySettings(InkstitchExtension): self.remove_elements(symbols) def get_selected_elements(self): - elements = [] - for node in self.svg.selected.values(): - if node.tag == SVG_GROUP_TAG: - for child in node.iterdescendants(EMBROIDERABLE_TAGS): - elements.append(child) - else: - elements.append(node) - return elements + return self.svg.selection.get(ShapeElement) def remove_elements(self, xpath): elements = find_elements(self.svg, xpath) diff --git a/lib/extensions/reorder.py b/lib/extensions/reorder.py index be478e39b..83ecfe264 100644 --- a/lib/extensions/reorder.py +++ b/lib/extensions/reorder.py @@ -3,6 +3,9 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. +from inkex import errormsg + +from ..i18n import _ from .base import InkstitchExtension @@ -11,10 +14,15 @@ class Reorder(InkstitchExtension): # were selected. def effect(self): - objects = self.get_selected_in_order() + objects = self.svg.selection - for obj in objects[1:]: - obj.getparent().remove(obj) + if not objects: + errormsg(_("Please select at least to elements to reorder.")) + return + + for obj in objects: + if not obj == objects.first(): + obj.getparent().remove(obj) insert_parent = objects[0].getparent() insert_pos = insert_parent.index(objects[0]) diff --git a/lib/extensions/selection_to_pattern.py b/lib/extensions/selection_to_pattern.py index b426e5db9..8b41ff860 100644 --- a/lib/extensions/selection_to_pattern.py +++ b/lib/extensions/selection_to_pattern.py @@ -17,7 +17,7 @@ class SelectionToPattern(InkstitchExtension): if not self.get_elements(): return - if not self.svg.selected: + if not self.svg.selection: inkex.errormsg(_("Please select at least one object to be marked as a pattern.")) return diff --git a/lib/extensions/troubleshoot.py b/lib/extensions/troubleshoot.py index c4b386d99..f7d979e75 100644 --- a/lib/extensions/troubleshoot.py +++ b/lib/extensions/troubleshoot.py @@ -128,7 +128,7 @@ class Troubleshoot(InkstitchExtension): self.warning_group = warning_group self.type_warning_group = type_warning_group - def add_descriptions(self, problem_types): + def add_descriptions(self, problem_types): # noqa: C901 svg = self.document.getroot() # We could use svg.viewport_width, but then we would need to do unit conversions, @@ -174,6 +174,8 @@ class Troubleshoot(InkstitchExtension): text.append([problem.name, "font-weight: bold; fill: %s;" % text_color]) text.append([problem.description, "font-size: 3px;"]) text.append(["", ""]) + if problem.steps_to_solve: + text.append([_("Possible solutions"), "font-weight: bold; text-decoration: underline; font-size: 4px;"]) for step in problem.steps_to_solve: text.append([step, "font-size: 4px;"]) text.append(["", ""]) diff --git a/lib/lettering/font.py b/lib/lettering/font.py index 104e4b29d..24ca86bfe 100644 --- a/lib/lettering/font.py +++ b/lib/lettering/font.py @@ -87,14 +87,14 @@ class Font(object): def _load_metadata(self): try: - with open(os.path.join(self.path, "font.json"), encoding="utf-8") as metadata_file: + with open(os.path.join(self.path, "font.json"), encoding="utf-8-sig") as metadata_file: self.metadata = json.load(metadata_file) except IOError: pass def _load_license(self): try: - with open(os.path.join(self.path, "LICENSE"), encoding="utf-8") as license_file: + with open(os.path.join(self.path, "LICENSE"), encoding="utf-8-sig") as license_file: self.license = license_file.read() except IOError: pass diff --git a/lib/stitch_plan/stitch_plan.py b/lib/stitch_plan/stitch_plan.py index 74caa54af..4593781ae 100644 --- a/lib/stitch_plan/stitch_plan.py +++ b/lib/stitch_plan/stitch_plan.py @@ -3,9 +3,14 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -from .ties import add_ties -from .color_block import ColorBlock +from sys import exit + +from inkex import errormsg + +from ..i18n import _ from ..svg import PIXELS_PER_MM +from .color_block import ColorBlock +from .ties import add_ties def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties=False): # noqa: C901 @@ -17,6 +22,11 @@ def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties= * adds jump-stitches between stitch_group if necessary """ + if not stitch_groups: + errormsg(_("There is no selected stitchable element. Please run " + "Extensions > Ink/Stitch > Troubleshoot > Troubleshoot objects in case you have expected a stitchout.")) + exit(1) + if collapse_len is None: collapse_len = 3.0 collapse_len = collapse_len * PIXELS_PER_MM diff --git a/lib/svg/path.py b/lib/svg/path.py index 53cf80f2c..c33a7a8fa 100644 --- a/lib/svg/path.py +++ b/lib/svg/path.py @@ -24,7 +24,7 @@ def compose_parent_transforms(node, mat): trans = node.get('transform') if trans: - mat = inkex.transforms.Transform(trans) * mat + mat = inkex.transforms.Transform(trans) @ mat if node.getparent() is not None: if node.getparent().tag in [SVG_GROUP_TAG, SVG_LINK_TAG]: mat = compose_parent_transforms(node.getparent(), mat) @@ -47,7 +47,7 @@ def get_node_transform(node): # add in the transform implied by the viewBox viewbox_transform = get_viewbox_transform(node.getroottree().getroot()) - transform = viewbox_transform * transform + transform = viewbox_transform @ transform return transform diff --git a/lib/svg/units.py b/lib/svg/units.py index f229c2c3a..e8a21c181 100644 --- a/lib/svg/units.py +++ b/lib/svg/units.py @@ -149,7 +149,7 @@ def get_viewbox_transform(node): sx = sy = max(sx, sy) if 'slice' in aspect_ratio else min(sx, sy) scale_transform = inkex.transforms.Transform("scale(%f, %f)" % (sx, sy)) - transform = transform * scale_transform + transform = transform @ scale_transform except ZeroDivisionError: pass diff --git a/templates/import_threadlist.xml b/templates/apply_threadlist.xml similarity index 74% rename from templates/import_threadlist.xml rename to templates/apply_threadlist.xml index 7da3b7f66..58776cb58 100644 --- a/templates/import_threadlist.xml +++ b/templates/apply_threadlist.xml @@ -1,12 +1,12 @@ - Import Threadlist - org.inkstitch.import_threadlist - import_threadlist + Apply Threadlist + org.inkstitch.apply_threadlist + apply_threadlist - - + + {%- for item in threadcatalog %} diff --git a/templates/commands_scale_symbols.xml b/templates/commands_scale_symbols.xml index 1d789543e..98d170032 100644 --- a/templates/commands_scale_symbols.xml +++ b/templates/commands_scale_symbols.xml @@ -8,7 +8,9 @@ all - + + + diff --git a/templates/object_commands_toggle_visibility.xml b/templates/object_commands_toggle_visibility.xml index 084b731e8..b3580b2ac 100644 --- a/templates/object_commands_toggle_visibility.xml +++ b/templates/object_commands_toggle_visibility.xml @@ -7,7 +7,9 @@ all - + + +