kopia lustrzana https://github.com/inkstitch/inkstitch
177 wiersze
6.1 KiB
Python
177 wiersze
6.1 KiB
Python
from itertools import chain
|
|
import textwrap
|
|
|
|
import inkex
|
|
|
|
from ..commands import add_layer_commands
|
|
from ..elements.validation import ValidationWarning, ValidationError
|
|
from ..i18n import _
|
|
from ..svg import get_correction_transform
|
|
from ..svg.tags import (INKSCAPE_GROUPMODE, INKSCAPE_LABEL,
|
|
SODIPODI_ROLE, SVG_GROUP_TAG, SVG_PATH_TAG,
|
|
SVG_TEXT_TAG, SVG_TSPAN_TAG)
|
|
from .base import InkstitchExtension
|
|
|
|
|
|
class Troubleshoot(InkstitchExtension):
|
|
|
|
def effect(self):
|
|
if not self.get_elements():
|
|
return
|
|
|
|
self.create_troubleshoot_layer()
|
|
|
|
problem_types = set()
|
|
for element in self.elements:
|
|
for problem in chain(element.validation_errors(), element.validation_warnings()):
|
|
problem_types.add(type(problem))
|
|
self.insert_pointer(problem)
|
|
|
|
if problem_types:
|
|
self.add_descriptions(problem_types)
|
|
else:
|
|
svg = self.document.getroot()
|
|
svg.remove(self.troubleshoot_layer)
|
|
|
|
message = _("All selected shapes are valid!")
|
|
message += "\n\n"
|
|
message += _("Tip: If you are still having an issue with an object not being rendered, "
|
|
"you might need to convert it it to a path (Path -> Object to Path) or check if it is possibly in an ignored layer.")
|
|
|
|
inkex.errormsg(message)
|
|
|
|
def insert_pointer(self, problem):
|
|
correction_transform = get_correction_transform(self.troubleshoot_layer)
|
|
|
|
if isinstance(problem, ValidationWarning):
|
|
fill_color = "#ffdd00"
|
|
layer = self.warning_group
|
|
elif isinstance(problem, ValidationError):
|
|
fill_color = "#ff0000"
|
|
layer = self.error_group
|
|
|
|
pointer_style = "stroke:#ffffff;stroke-width:0.2;fill:%s;" % (fill_color)
|
|
text_style = "fill:%s;stroke:#ffffff;stroke-width:0.2;font-size:8px;text-align:center;text-anchor:middle" % (fill_color)
|
|
|
|
path = inkex.etree.Element(
|
|
SVG_PATH_TAG,
|
|
{
|
|
"id": self.uniqueId("inkstitch__invalid_pointer__"),
|
|
"d": "m %s,%s 4,20 h -8 l 4,-20" % (problem.position.x, problem.position.y),
|
|
"style": pointer_style,
|
|
INKSCAPE_LABEL: _('Invalid Pointer'),
|
|
"transform": correction_transform
|
|
}
|
|
)
|
|
layer.insert(0, path)
|
|
|
|
text = inkex.etree.Element(
|
|
SVG_TEXT_TAG,
|
|
{
|
|
INKSCAPE_LABEL: _('Description'),
|
|
"x": str(problem.position.x),
|
|
"y": str(float(problem.position.y) + 30),
|
|
"transform": correction_transform,
|
|
"style": text_style
|
|
}
|
|
)
|
|
layer.append(text)
|
|
|
|
tspan = inkex.etree.Element(SVG_TSPAN_TAG)
|
|
tspan.text = problem.name
|
|
text.append(tspan)
|
|
|
|
def create_troubleshoot_layer(self):
|
|
svg = self.document.getroot()
|
|
layer = svg.find(".//*[@id='__validation_layer__']")
|
|
|
|
if layer is None:
|
|
layer = inkex.etree.Element(
|
|
SVG_GROUP_TAG,
|
|
{
|
|
'id': '__validation_layer__',
|
|
INKSCAPE_LABEL: _('Troubleshoot'),
|
|
INKSCAPE_GROUPMODE: 'layer',
|
|
})
|
|
svg.append(layer)
|
|
|
|
else:
|
|
# Clear out everything from the last run
|
|
del layer[:]
|
|
|
|
add_layer_commands(layer, ["ignore_layer"])
|
|
|
|
error_group = inkex.etree.SubElement(
|
|
layer,
|
|
SVG_GROUP_TAG,
|
|
{
|
|
"id": '__validation_errors__',
|
|
INKSCAPE_LABEL: _("Errors"),
|
|
})
|
|
layer.append(error_group)
|
|
|
|
warning_group = inkex.etree.SubElement(
|
|
layer,
|
|
SVG_GROUP_TAG,
|
|
{
|
|
"id": '__validation_warnings__',
|
|
INKSCAPE_LABEL: _("Warnings"),
|
|
})
|
|
layer.append(warning_group)
|
|
|
|
self.troubleshoot_layer = layer
|
|
self.error_group = error_group
|
|
self.warning_group = warning_group
|
|
|
|
def add_descriptions(self, problem_types):
|
|
svg = self.document.getroot()
|
|
text_x = str(self.unittouu(svg.get('width')) + 5)
|
|
|
|
text_container = inkex.etree.Element(
|
|
SVG_TEXT_TAG,
|
|
{
|
|
"x": text_x,
|
|
"y": str(5),
|
|
"style": "fill:#000000;font-size:5px;line-height:1;"
|
|
}
|
|
)
|
|
self.troubleshoot_layer.append(text_container)
|
|
|
|
text = [
|
|
[_("Troubleshoot"), "font-weight: bold; font-size: 6px;"],
|
|
["", ""]
|
|
]
|
|
|
|
for problem in problem_types:
|
|
text_color = "#ff0000"
|
|
if issubclass(problem, ValidationWarning):
|
|
text_color = "#ffdd00"
|
|
|
|
text.append([problem.name, "font-weight: bold; fill:%s;" % text_color])
|
|
description_parts = textwrap.wrap(problem.description, 60)
|
|
for description in description_parts:
|
|
text.append([description, "font-size: 3px;"])
|
|
text.append(["", ""])
|
|
for step in problem.steps_to_solve:
|
|
text.append([step, "font-size: 4px;"])
|
|
text.append(["", ""])
|
|
|
|
explain_layer = _('It is possible, that one object contains more than one error, ' +
|
|
'yet there will be only one pointer per object. Run this function again, ' +
|
|
'when further errors occur. Remove pointers by deleting the layer named '
|
|
'"Troubleshoot" through the objects panel (Object -> Objects...).')
|
|
explain_layer_parts = textwrap.wrap(explain_layer, 60)
|
|
for description in explain_layer_parts:
|
|
text.append([description, "font-style: italic; font-size: 3px;"])
|
|
|
|
for text_line in text:
|
|
tspan = inkex.etree.Element(
|
|
SVG_TSPAN_TAG,
|
|
{
|
|
SODIPODI_ROLE: "line",
|
|
"style": text_line[1]
|
|
}
|
|
)
|
|
tspan.text = text_line[0]
|
|
text_container.append(tspan)
|