flatcam/appTool.py

302 lines
9.5 KiB
Python

# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
# ########################################################## ##
from PyQt5 import QtCore, QtWidgets
from shapely.geometry import Polygon, LineString
import gettext
import appTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
class AppTool(QtWidgets.QWidget):
toolName = "FlatCAM Generic Tool"
def __init__(self, app, parent=None):
"""
:param app: The application this tool will run in.
:type app: app_Main.App
:param parent: Qt Parent
:return: AppTool
"""
QtWidgets.QWidget.__init__(self, parent)
self.app = app
self.decimals = self.app.decimals
# self.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
self.layout = QtWidgets.QVBoxLayout()
self.setLayout(self.layout)
self.menuAction = None
def install(self, icon=None, separator=None, shortcut=None, **kwargs):
before = None
# 'pos' is the menu where the Action has to be installed
# if no 'pos' kwarg is provided then by default our Action will be installed in the menutool
# as it previously was
if 'pos' in kwargs:
pos = kwargs['pos']
else:
pos = self.app.ui.menutool
# 'before' is the Action in the menu stated by 'pos' kwarg, before which we want our Action to be installed
# if 'before' kwarg is not provided, by default our Action will be added in the last place.
if 'before' in kwargs:
before = (kwargs['before'])
# create the new Action
self.menuAction = QtWidgets.QAction(self)
# if provided, add an icon to this Action
if icon is not None:
self.menuAction.setIcon(icon)
# set the text name of the Action, which will be displayed in the menu
if shortcut is None:
self.menuAction.setText(self.toolName)
else:
self.menuAction.setText(self.toolName + '\t%s' % shortcut)
# add a ToolTip to the new Action
# self.menuAction.setToolTip(self.toolTip) # currently not available
# insert the action in the position specified by 'before' and 'pos' kwargs
pos.insertAction(before, self.menuAction)
# if separator parameter is True add a Separator after the newly created Action
if separator is True:
pos.addSeparator()
self.menuAction.triggered.connect(self.run)
def run(self):
if self.app.tool_tab_locked is True:
return
# Remove anything else in the appGUI
self.app.ui.tool_scroll_area.takeWidget()
# Put ourselves in the appGUI
self.app.ui.tool_scroll_area.setWidget(self)
# Switch notebook to tool page
self.app.ui.notebook.setCurrentWidget(self.app.ui.tool_tab)
# Set the tool name as the widget object name
self.app.ui.tool_scroll_area.widget().setObjectName(self.toolName)
self.show()
def draw_tool_selection_shape(self, old_coords, coords, **kwargs):
"""
:param old_coords: old coordinates
:param coords: new coordinates
:param kwargs:
:return:
"""
if 'shapes_storage' in kwargs:
s_storage = kwargs['shapes_storage']
else:
s_storage = self.app.tool_shapes
if 'color' in kwargs:
color = kwargs['color']
else:
color = self.app.defaults['global_sel_line']
if 'face_color' in kwargs:
face_color = kwargs['face_color']
else:
face_color = self.app.defaults['global_sel_fill']
if 'face_alpha' in kwargs:
face_alpha = kwargs['face_alpha']
else:
face_alpha = 0.3
x0, y0 = old_coords
x1, y1 = coords
pt1 = (x0, y0)
pt2 = (x1, y0)
pt3 = (x1, y1)
pt4 = (x0, y1)
sel_rect = Polygon([pt1, pt2, pt3, pt4])
# color_t = Color(face_color)
# color_t.alpha = face_alpha
color_t = face_color[:-2] + str(hex(int(face_alpha * 255)))[2:]
s_storage.add(sel_rect, color=color, face_color=color_t, update=True, layer=0, tolerance=None)
if self.app.is_legacy is True:
s_storage.redraw()
def draw_selection_shape_polygon(self, points, **kwargs):
"""
:param points: a list of points from which to create a Polygon
:param kwargs:
:return:
"""
if 'shapes_storage' in kwargs:
s_storage = kwargs['shapes_storage']
else:
s_storage = self.app.tool_shapes
if 'color' in kwargs:
color = kwargs['color']
else:
color = self.app.defaults['global_sel_line']
if 'face_color' in kwargs:
face_color = kwargs['face_color']
else:
face_color = self.app.defaults['global_sel_fill']
if 'face_alpha' in kwargs:
face_alpha = kwargs['face_alpha']
else:
face_alpha = 0.3
if len(points) < 3:
sel_rect = LineString(points)
else:
sel_rect = Polygon(points)
# color_t = Color(face_color)
# color_t.alpha = face_alpha
color_t = face_color[:-2] + str(hex(int(face_alpha * 255)))[2:]
s_storage.add(sel_rect, color=color, face_color=color_t, update=True, layer=0, tolerance=None)
if self.app.is_legacy is True:
s_storage.redraw()
def delete_tool_selection_shape(self, **kwargs):
"""
:param kwargs:
:return:
"""
if 'shapes_storage' in kwargs:
s_storage = kwargs['shapes_storage']
else:
s_storage = self.app.tool_shapes
s_storage.clear()
s_storage.redraw()
def draw_moving_selection_shape_poly(self, points, data, **kwargs):
"""
:param points:
:param data:
:param kwargs:
:return:
"""
if 'shapes_storage' in kwargs:
s_storage = kwargs['shapes_storage']
else:
s_storage = self.app.move_tool.sel_shapes
if 'color' in kwargs:
color = kwargs['color']
else:
color = self.app.defaults['global_sel_line']
if 'face_color' in kwargs:
face_color = kwargs['face_color']
else:
face_color = self.app.defaults['global_sel_fill']
if 'face_alpha' in kwargs:
face_alpha = kwargs['face_alpha']
else:
face_alpha = 0.3
temp_points = [x for x in points]
try:
if data != temp_points[-1]:
temp_points.append(data)
except IndexError:
return
l_points = len(temp_points)
if l_points == 2:
geo = LineString(temp_points)
elif l_points > 2:
geo = Polygon(temp_points)
else:
return
color_t = face_color[:-2] + str(hex(int(face_alpha * 255)))[2:]
color_t_error = "#00000000"
if geo.is_valid and not geo.is_empty:
s_storage.add(geo, color=color, face_color=color_t, update=True, layer=0, tolerance=None)
elif not geo.is_valid:
s_storage.add(geo, color="red", face_color=color_t_error, update=True, layer=0, tolerance=None)
if self.app.is_legacy is True:
s_storage.redraw()
def delete_moving_selection_shape(self, **kwargs):
"""
:param kwargs:
:return:
"""
if 'shapes_storage' in kwargs:
s_storage = kwargs['shapes_storage']
else:
s_storage = self.app.move_tool.sel_shapes
s_storage.clear()
s_storage.redraw()
def confirmation_message(self, accepted, minval, maxval):
if accepted is False:
self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%.*f, %.*f]' % (_("Edited value is out of range"),
self.decimals,
minval,
self.decimals,
maxval), False)
else:
self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
def confirmation_message_int(self, accepted, minval, maxval):
if accepted is False:
self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%d, %d]' %
(_("Edited value is out of range"), minval, maxval), False)
else:
self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
def sizeHint(self):
"""
I've overloaded this just in case I will need to make changes in the future to enforce dimensions
:return:
"""
default_hint_size = super(AppTool, self).sizeHint()
return QtCore.QSize(default_hint_size.width(), default_hint_size.height())