commit
f7818d50d6
101
FlatCAMApp.py
101
FlatCAMApp.py
|
@ -97,7 +97,7 @@ class App(QtCore.QObject):
|
|||
# Version and VERSION DATE ###########
|
||||
# ####################################
|
||||
version = 8.93
|
||||
version_date = "2019/08/31"
|
||||
version_date = "2019/08/10"
|
||||
beta = True
|
||||
|
||||
# current date now
|
||||
|
@ -513,6 +513,7 @@ class App(QtCore.QObject):
|
|||
"tools_nccconnect": self.ui.tools_defaults_form.tools_ncc_group.ncc_connect_cb,
|
||||
"tools_ncccontour": self.ui.tools_defaults_form.tools_ncc_group.ncc_contour_cb,
|
||||
"tools_nccrest": self.ui.tools_defaults_form.tools_ncc_group.ncc_rest_cb,
|
||||
"tools_nccref": self.ui.tools_defaults_form.tools_ncc_group.reference_radio,
|
||||
|
||||
# CutOut Tool
|
||||
"tools_cutouttooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry,
|
||||
|
@ -852,6 +853,7 @@ class App(QtCore.QObject):
|
|||
"tools_nccconnect": True,
|
||||
"tools_ncccontour": True,
|
||||
"tools_nccrest": False,
|
||||
"tools_nccref": 'itself',
|
||||
|
||||
"tools_cutouttooldia": 0.00393701,
|
||||
"tools_cutoutkind": "single",
|
||||
|
@ -2841,6 +2843,7 @@ class App(QtCore.QObject):
|
|||
self.inform.emit(_("[ERROR_NOTCL] Failed to parse defaults file."))
|
||||
return
|
||||
self.defaults.update(defaults_from_file)
|
||||
self.on_preferences_edited()
|
||||
self.inform.emit(_("[success] Imported Defaults from %s") % filename)
|
||||
|
||||
def on_export_preferences(self):
|
||||
|
@ -2875,6 +2878,10 @@ class App(QtCore.QObject):
|
|||
f = open(filename, 'w')
|
||||
defaults_file_content = f.read()
|
||||
f.close()
|
||||
except PermissionError:
|
||||
self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return
|
||||
except IOError:
|
||||
App.log.debug('Creating a new preferences file ...')
|
||||
f = open(filename, 'w')
|
||||
|
@ -4669,10 +4676,13 @@ class App(QtCore.QObject):
|
|||
with open(filename, 'w') as f:
|
||||
for line in my_gcode:
|
||||
f.write(line)
|
||||
|
||||
except FileNotFoundError:
|
||||
self.inform.emit(_("[WARNING] No such file or directory"))
|
||||
return
|
||||
except PermissionError:
|
||||
self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return
|
||||
|
||||
# Just for adding it to the recent files list.
|
||||
if self.defaults["global_open_style"] is False:
|
||||
|
@ -5691,13 +5701,12 @@ class App(QtCore.QObject):
|
|||
self.plotcanvas.vispy_canvas.view.camera.pan_button_setting = self.defaults['global_pan_button']
|
||||
|
||||
self.pos_canvas = self.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
||||
self.pos = (self.pos_canvas[0], self.pos_canvas[1])
|
||||
self.app_cursor.enabled = False
|
||||
|
||||
if self.grid_status() == True:
|
||||
if self.grid_status():
|
||||
self.pos = self.geo_editor.snap(self.pos_canvas[0], self.pos_canvas[1])
|
||||
self.app_cursor.enabled = True
|
||||
else:
|
||||
self.pos = (self.pos_canvas[0], self.pos_canvas[1])
|
||||
self.app_cursor.enabled = False
|
||||
|
||||
try:
|
||||
modifiers = QtWidgets.QApplication.keyboardModifiers()
|
||||
|
@ -5750,7 +5759,7 @@ class App(QtCore.QObject):
|
|||
if self.rel_point1 is not None:
|
||||
try: # May fail in case mouse not within axes
|
||||
pos_canvas = self.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
||||
if self.grid_status():
|
||||
if self.grid_status() == True:
|
||||
pos = self.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
||||
self.app_cursor.enabled = True
|
||||
# Update cursor
|
||||
|
@ -6154,6 +6163,12 @@ class App(QtCore.QObject):
|
|||
face_color = kwargs['face_color']
|
||||
else:
|
||||
face_color = self.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)
|
||||
|
@ -6163,7 +6178,7 @@ class App(QtCore.QObject):
|
|||
sel_rect = Polygon([pt1, pt2, pt3, pt4])
|
||||
|
||||
color_t = Color(face_color)
|
||||
color_t.alpha = 0.3
|
||||
color_t.alpha = face_alpha
|
||||
self.move_tool.sel_shapes.add(sel_rect, color=color, face_color=color_t, update=True,
|
||||
layer=0, tolerance=None)
|
||||
|
||||
|
@ -7109,8 +7124,14 @@ class App(QtCore.QObject):
|
|||
# Parse the xml through a xml parser just to add line feeds
|
||||
# and to make it look more pretty for the output
|
||||
svgcode = parse_xml_string(svg_elem)
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(svgcode.toprettyxml())
|
||||
try:
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(svgcode.toprettyxml())
|
||||
except PermissionError:
|
||||
self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return 'fail'
|
||||
|
||||
if self.defaults["global_open_style"] is False:
|
||||
self.file_opened.emit("SVG", filename)
|
||||
self.file_saved.emit("SVG", filename)
|
||||
|
@ -7213,8 +7234,13 @@ class App(QtCore.QObject):
|
|||
# Parse the xml through a xml parser just to add line feeds
|
||||
# and to make it look more pretty for the output
|
||||
doc = parse_xml_string(svg_elem)
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(doc.toprettyxml())
|
||||
try:
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(doc.toprettyxml())
|
||||
except PermissionError:
|
||||
self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return 'fail'
|
||||
|
||||
self.progress.emit(100)
|
||||
if self.defaults["global_open_style"] is False:
|
||||
|
@ -7329,8 +7355,14 @@ class App(QtCore.QObject):
|
|||
# Parse the xml through a xml parser just to add line feeds
|
||||
# and to make it look more pretty for the output
|
||||
doc = parse_xml_string(svg_elem)
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(doc.toprettyxml())
|
||||
try:
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(doc.toprettyxml())
|
||||
except PermissionError:
|
||||
self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return 'fail'
|
||||
|
||||
self.progress.emit(100)
|
||||
if self.defaults["global_open_style"] is False:
|
||||
self.file_opened.emit("SVG", filename)
|
||||
|
@ -7371,15 +7403,20 @@ class App(QtCore.QObject):
|
|||
file_string = StringIO(obj.source_file)
|
||||
time_string = "{:%A, %d %B %Y at %H:%M}".format(datetime.now())
|
||||
|
||||
with open(filename, 'w') as file:
|
||||
file.writelines('G04*\n')
|
||||
file.writelines('G04 %s (RE)GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s*\n' %
|
||||
(obj.kind.upper(), str(self.version), str(self.version_date)))
|
||||
file.writelines('G04 Filename: %s*\n' % str(obj_name))
|
||||
file.writelines('G04 Created on : %s*\n' % time_string)
|
||||
try:
|
||||
with open(filename, 'w') as file:
|
||||
file.writelines('G04*\n')
|
||||
file.writelines('G04 %s (RE)GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s*\n' %
|
||||
(obj.kind.upper(), str(self.version), str(self.version_date)))
|
||||
file.writelines('G04 Filename: %s*\n' % str(obj_name))
|
||||
file.writelines('G04 Created on : %s*\n' % time_string)
|
||||
|
||||
for line in file_string:
|
||||
file.writelines(line)
|
||||
for line in file_string:
|
||||
file.writelines(line)
|
||||
except PermissionError:
|
||||
self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return 'fail'
|
||||
|
||||
def export_excellon(self, obj_name, filename, use_thread=True):
|
||||
"""
|
||||
|
@ -7481,8 +7518,14 @@ class App(QtCore.QObject):
|
|||
exported_excellon += excellon_code
|
||||
exported_excellon += footer
|
||||
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(exported_excellon)
|
||||
try:
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(exported_excellon)
|
||||
except PermissionError:
|
||||
self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return 'fail'
|
||||
|
||||
if self.defaults["global_open_style"] is False:
|
||||
self.file_opened.emit("Excellon", filename)
|
||||
self.file_saved.emit("Excellon", filename)
|
||||
|
@ -7598,8 +7641,14 @@ class App(QtCore.QObject):
|
|||
exported_gerber += gerber_code
|
||||
exported_gerber += footer
|
||||
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(exported_gerber)
|
||||
try:
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(exported_gerber)
|
||||
except PermissionError:
|
||||
self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return 'fail'
|
||||
|
||||
if self.defaults["global_open_style"] is False:
|
||||
self.file_opened.emit("Gerber", filename)
|
||||
self.file_saved.emit("Gerber", filename)
|
||||
|
|
231
FlatCAMObj.py
231
FlatCAMObj.py
|
@ -24,8 +24,8 @@ if '_' not in builtins.__dict__:
|
|||
_ = gettext.gettext
|
||||
|
||||
|
||||
# Interrupts plotting process if FlatCAMObj has been deleted
|
||||
class ObjectDeleted(Exception):
|
||||
# Interrupts plotting process if FlatCAMObj has been deleted
|
||||
pass
|
||||
|
||||
|
||||
|
@ -364,10 +364,13 @@ class FlatCAMObj(QtCore.QObject):
|
|||
|
||||
@property
|
||||
def drawing_tolerance(self):
|
||||
return self._drawing_tolerance if self.units == 'MM' or not self.units else self._drawing_tolerance / 25.4
|
||||
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
|
||||
tol = self._drawing_tolerance if self.units == 'MM' or not self.units else self._drawing_tolerance / 25.4
|
||||
return tol
|
||||
|
||||
@drawing_tolerance.setter
|
||||
def drawing_tolerance(self, value):
|
||||
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
|
||||
self._drawing_tolerance = value if self.units == 'MM' or not self.units else value / 25.4
|
||||
|
||||
def clear(self, update=False):
|
||||
|
@ -2666,9 +2669,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
|||
job_obj.z_pdepth = float(self.options["z_pdepth"].replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
'[ERROR_NOTCL] Wrong value format for self.defaults["z_pdepth"] or self.options["z_pdepth"]'
|
||||
))
|
||||
_('[ERROR_NOTCL] Wrong value format for self.defaults["z_pdepth"] or self.options["z_pdepth"]'))
|
||||
|
||||
try:
|
||||
job_obj.feedrate_probe = float(self.options["feedrate_probe"])
|
||||
|
@ -2678,11 +2679,8 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
|||
job_obj.feedrate_rapid = float(self.options["feedrate_probe"].replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
'[ERROR_NOTCL] Wrong value format for self.defaults["feedrate_probe"] '
|
||||
'or self.options["feedrate_probe"]'
|
||||
)
|
||||
)
|
||||
_('[ERROR_NOTCL] Wrong value format for self.defaults["feedrate_probe"] '
|
||||
'or self.options["feedrate_probe"]'))
|
||||
|
||||
# There could be more than one drill size...
|
||||
# job_obj.tooldia = # TODO: duplicate variable!
|
||||
|
@ -2736,10 +2734,8 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
|||
else:
|
||||
coords_xy = [float(eval(coord)) for coord in self.app.defaults["excellon_toolchangexy"].split(",")]
|
||||
if len(coords_xy) < 2:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
||||
"in the format (x, y) \nbut now there is only one value, not two. "
|
||||
))
|
||||
self.app.inform.emit(_("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
||||
"in the format (x, y) \nbut now there is only one value, not two. "))
|
||||
return 'fail'
|
||||
coords_xy[0] *= factor
|
||||
coords_xy[1] *= factor
|
||||
|
@ -2913,7 +2909,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
geo_final.options[option] = geo.options[option]
|
||||
except Exception as e:
|
||||
log.warning("Failed to copy option.", option)
|
||||
log.warning("Failed to copy option %s. Error: %s" % (str(option), str(e)))
|
||||
|
||||
# Expand lists
|
||||
if type(geo) is list:
|
||||
|
@ -3022,14 +3018,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
|
||||
if "cnctooldia" not in self.options:
|
||||
self.options["cnctooldia"] = self.app.defaults["geometry_cnctooldia"]
|
||||
# try:
|
||||
# self.options["cnctooldia"] = [
|
||||
# float(eval(dia)) for dia in str(self.app.defaults["geometry_cnctooldia"]).split(",")
|
||||
# ]
|
||||
# except Exception as e:
|
||||
# log.error("At least one tool diameter needed. Verify in Edit -> Preferences -> Geometry General -> "
|
||||
# "Tool dia. %s" % str(e))
|
||||
# return
|
||||
|
||||
self.options["startz"] = self.app.defaults["geometry_startz"]
|
||||
|
||||
|
@ -3143,14 +3131,14 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
self.ui.geo_tools_table.setCellWidget(row_no, 3, type_item)
|
||||
self.ui.geo_tools_table.setCellWidget(row_no, 4, tool_type_item)
|
||||
|
||||
# ## REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY # ##
|
||||
# ## REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY ###
|
||||
self.ui.geo_tools_table.setItem(row_no, 5, tool_uid_item) # Tool unique ID
|
||||
self.ui.geo_tools_table.setCellWidget(row_no, 6, plot_item)
|
||||
|
||||
try:
|
||||
self.ui.tool_offset_entry.set_value(tooluid_value['offset_value'])
|
||||
except Exception as e:
|
||||
log.debug("build_ui() --> Could not set the 'offset_value' key in self.tools")
|
||||
log.debug("build_ui() --> Could not set the 'offset_value' key in self.tools. Error: %s" % str(e))
|
||||
|
||||
# make the diameter column editable
|
||||
for row in range(tool_idx):
|
||||
|
@ -3436,31 +3424,14 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
self.ui.tool_offset_entry.get_value().replace(',', '.')
|
||||
)
|
||||
except ValueError:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."
|
||||
)
|
||||
)
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
|
||||
def ui_connect(self):
|
||||
# on any change to the widgets that matter it will be called self.gui_form_to_storage which will save the
|
||||
# changes in geometry UI
|
||||
for i in range(self.ui.grid3.count()):
|
||||
# try:
|
||||
# # works for CheckBoxes
|
||||
# self.ui.grid3.itemAt(i).widget().stateChanged.connect(self.gui_form_to_storage)
|
||||
# except Exception as e:
|
||||
# # works for ComboBoxes
|
||||
# try:
|
||||
# self.ui.grid3.itemAt(i).widget().currentIndexChanged.connect(self.gui_form_to_storage)
|
||||
# except Exception as e2:
|
||||
# # works for Entry
|
||||
# try:
|
||||
# self.ui.grid3.itemAt(i).widget().editingFinished.connect(self.gui_form_to_storage)
|
||||
# except Exception as e3:
|
||||
# pass
|
||||
|
||||
current_widget = self.ui.grid3.itemAt(i).widget()
|
||||
if isinstance(current_widget, FCCheckBox):
|
||||
current_widget.stateChanged.connect(self.gui_form_to_storage)
|
||||
|
@ -3494,20 +3465,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
# on any change to the widgets that matter it will be called self.gui_form_to_storage which will save the
|
||||
# changes in geometry UI
|
||||
for i in range(self.ui.grid3.count()):
|
||||
# try:
|
||||
# # works for CheckBoxes
|
||||
# self.ui.grid3.itemAt(i).widget().stateChanged.disconnect(self.gui_form_to_storage)
|
||||
# except Exception as e:
|
||||
# # works for ComboBoxes
|
||||
# try:
|
||||
# self.ui.grid3.itemAt(i).widget().currentIndexChanged.disconnect(self.gui_form_to_storage)
|
||||
# except Exception as e2:
|
||||
# # works for Entry
|
||||
# try:
|
||||
# self.ui.grid3.itemAt(i).widget().editingFinished.disconnect(self.gui_form_to_storage)
|
||||
# except Exception as e3:
|
||||
# pass
|
||||
|
||||
current_widget = self.ui.grid3.itemAt(i).widget()
|
||||
if isinstance(current_widget, FCCheckBox):
|
||||
try:
|
||||
|
@ -3673,14 +3630,10 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
self.ser_attrs.append('tools')
|
||||
|
||||
if change_message is False:
|
||||
self.app.inform.emit(_(
|
||||
"[success] Tool added in Tool Table."
|
||||
))
|
||||
self.app.inform.emit(_("[success] Tool added in Tool Table."))
|
||||
else:
|
||||
change_message = False
|
||||
self.app.inform.emit(_(
|
||||
"[WARNING_NOTCL] Default Tool added. Wrong value format entered."
|
||||
))
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Default Tool added. Wrong value format entered."))
|
||||
self.build_ui()
|
||||
|
||||
# if there is no tool left in the Tools Table, enable the parameters GUI
|
||||
|
@ -3712,9 +3665,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
max_uid += 1
|
||||
self.tools[int(max_uid)] = deepcopy(self.tools[tooluid_copy])
|
||||
except AttributeError:
|
||||
self.app.inform.emit(_(
|
||||
"[WARNING_NOTCL] Failed. Select a tool to copy."
|
||||
))
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Failed. Select a tool to copy."))
|
||||
self.build_ui()
|
||||
return
|
||||
except Exception as e:
|
||||
|
@ -3722,9 +3673,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
# deselect the table
|
||||
# self.ui.geo_tools_table.clearSelection()
|
||||
else:
|
||||
self.app.inform.emit(_(
|
||||
"[WARNING_NOTCL] Failed. Select a tool to copy."
|
||||
))
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Failed. Select a tool to copy."))
|
||||
self.build_ui()
|
||||
return
|
||||
else:
|
||||
|
@ -3746,14 +3695,12 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
# we do this HACK to make sure the tools attribute to be serialized is updated in the self.ser_attrs list
|
||||
try:
|
||||
self.ser_attrs.remove('tools')
|
||||
except Exception as e:
|
||||
except ValueError:
|
||||
pass
|
||||
self.ser_attrs.append('tools')
|
||||
|
||||
self.build_ui()
|
||||
self.app.inform.emit(_(
|
||||
"[success] Tool was copied in Tool Table."
|
||||
))
|
||||
self.app.inform.emit(_("[success] Tool was copied in Tool Table."))
|
||||
|
||||
def on_tool_edit(self, current_item):
|
||||
|
||||
|
@ -3767,10 +3714,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
d = float(self.ui.geo_tools_table.item(current_row, 1).text().replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."
|
||||
))
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
|
||||
tool_dia = float('%.4f' % d)
|
||||
|
@ -3781,12 +3726,10 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
self.ser_attrs.remove('tools')
|
||||
self.ser_attrs.append('tools')
|
||||
except TypeError:
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
|
||||
self.app.inform.emit(_(
|
||||
"[success] Tool was edited in Tool Table."
|
||||
))
|
||||
self.app.inform.emit(_("[success] Tool was edited in Tool Table."))
|
||||
self.build_ui()
|
||||
|
||||
def on_tool_delete(self, all=None):
|
||||
|
@ -3895,7 +3838,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
# populate the form with the data from the tool associated with the row parameter
|
||||
try:
|
||||
item = self.ui.geo_tools_table.item(current_row, 5)
|
||||
if item is not None:
|
||||
if type(item) is not None:
|
||||
tooluid = int(item.text())
|
||||
else:
|
||||
return
|
||||
|
@ -3913,7 +3856,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
else:
|
||||
return
|
||||
except Exception as e:
|
||||
log.debug("Tool missing. Add a tool in Geo Tool Table. %s" % str(e))
|
||||
log.debug("Tool missing in ui_update_v_shape(). Add a tool in Geo Tool Table. %s" % str(e))
|
||||
return
|
||||
|
||||
try:
|
||||
|
@ -3958,10 +3901,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
vdia = float(self.ui.tipdia_entry.get_value().replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."
|
||||
))
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
|
||||
try:
|
||||
|
@ -3971,10 +3912,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
half_vangle = float(self.ui.tipangle_entry.get_value().replace(',', '.')) / 2
|
||||
except ValueError:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."
|
||||
))
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
|
||||
row = self.ui.geo_tools_table.currentRow()
|
||||
|
@ -4091,10 +4030,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
offset_value_item = float(self.ui.tool_offset_entry.get_value().replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."
|
||||
))
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
|
||||
# this new dict will hold the actual useful data, another dict that is the value of key 'data'
|
||||
|
@ -4212,6 +4149,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
else:
|
||||
for x in self.ui.geo_tools_table.selectedItems():
|
||||
r = []
|
||||
txt = ''
|
||||
|
||||
# the last 2 columns for single-geo geometry are irrelevant and create problems reading
|
||||
# so we don't read them
|
||||
for column in range(0, self.ui.geo_tools_table.columnCount() - 2):
|
||||
|
@ -4277,8 +4216,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
|
||||
try:
|
||||
if self.special_group:
|
||||
self.app.inform.emit(_(
|
||||
"[WARNING_NOTCL] This Geometry can't be processed because it is %s geometry."
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] This Geometry can't be processed because it is %s geometry."
|
||||
) % str(self.special_group))
|
||||
return
|
||||
except AttributeError:
|
||||
|
@ -4294,10 +4232,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
tooldia = float(self.ui.geo_tools_table.item(x.row(), 1).text().replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR_NOTCL] Wrong Tool Dia value format entered, "
|
||||
"use a number."
|
||||
))
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong Tool Dia value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
tooluid = int(self.ui.geo_tools_table.item(x.row(), 5).text())
|
||||
|
||||
|
@ -4321,9 +4257,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
self.ui.geo_tools_table.clearSelection()
|
||||
|
||||
else:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR_NOTCL] Failed. No tool selected in the tool table ..."
|
||||
))
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Failed. No tool selected in the tool table ..."))
|
||||
|
||||
def mtool_gen_cncjob(self, segx=None, segy=None, use_thread=True):
|
||||
"""
|
||||
|
@ -4359,7 +4293,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
ymax = self.options['ymax']
|
||||
except Exception as e:
|
||||
log.debug("FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s\n" % str(e))
|
||||
msg = _("[ERROR] An internal error has ocurred. See shell.\n")
|
||||
msg = _("[ERROR] An internal error has occurred. See shell.\n")
|
||||
msg += _('FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s') % str(e)
|
||||
msg += traceback.format_exc()
|
||||
self.app.inform.emit(msg)
|
||||
|
@ -4369,7 +4303,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
# RUNNING ON SEPARATE THREAD!
|
||||
def job_init_single_geometry(job_obj, app_obj):
|
||||
log.debug("Creating a CNCJob out of a single-geometry")
|
||||
|
||||
assert isinstance(job_obj, FlatCAMCNCjob), \
|
||||
"Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj)
|
||||
|
||||
|
@ -4395,10 +4328,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
job_obj.z_pdepth = float(self.options["z_pdepth"].replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
'[ERROR_NOTCL] Wrong value format for self.defaults["z_pdepth"] or self.options["z_pdepth"]'
|
||||
))
|
||||
self.app.inform.emit(_('[ERROR_NOTCL] Wrong value format for self.defaults["z_pdepth"] '
|
||||
'or self.options["z_pdepth"]'))
|
||||
|
||||
try:
|
||||
job_obj.feedrate_probe = float(self.options["feedrate_probe"])
|
||||
|
@ -4407,11 +4338,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
job_obj.feedrate_rapid = float(self.options["feedrate_probe"].replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
'[ERROR_NOTCL] Wrong value format for self.defaults["feedrate_probe"] '
|
||||
'or self.options["feedrate_probe"]'
|
||||
))
|
||||
self.app.inform.emit(_('[ERROR_NOTCL] Wrong value format for self.defaults["feedrate_probe"] '
|
||||
'or self.options["feedrate_probe"]'))
|
||||
|
||||
for tooluid_key in self.sel_tools:
|
||||
tool_cnt += 1
|
||||
|
@ -4507,20 +4435,15 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
offset_value = float(self.ui.tool_offset_entry.get_value().replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(_(
|
||||
"[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."
|
||||
))
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
if offset_value:
|
||||
tool_offset = float(offset_value)
|
||||
else:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
"[WARNING] Tool Offset is selected in Tool Table but no value is provided.\n"
|
||||
"Add a Tool Offset or change the Offset Type."
|
||||
)
|
||||
)
|
||||
self.app.inform.emit(_("[WARNING] Tool Offset is selected in Tool Table but "
|
||||
"no value is provided.\n"
|
||||
"Add a Tool Offset or change the Offset Type."))
|
||||
return
|
||||
dia_cnc_dict.update({
|
||||
'offset_value': tool_offset
|
||||
|
@ -4543,7 +4466,9 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
|
||||
app_obj.progress.emit(40)
|
||||
|
||||
tol = float(self.app.defaults['global_tolerance'])
|
||||
# it seems that the tolerance needs to be a lot lower value than 0.01 and it was hardcoded initially
|
||||
# to a value of 0.0005 which is 20 times less than 0.01
|
||||
tol = float(self.app.defaults['global_tolerance']) / 20
|
||||
res = job_obj.generate_from_geometry_2(
|
||||
self, tooldia=tooldia_val, offset=tool_offset, tolerance=tol,
|
||||
z_cut=z_cut, z_move=z_move,
|
||||
|
@ -4582,7 +4507,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
# RUNNING ON SEPARATE THREAD!
|
||||
def job_init_multi_geometry(job_obj, app_obj):
|
||||
log.debug("Creating a CNCJob out of a multi-geometry")
|
||||
|
||||
assert isinstance(job_obj, FlatCAMCNCjob), \
|
||||
"Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj)
|
||||
|
||||
|
@ -4610,10 +4534,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
job_obj.z_pdepth = float(self.options["z_pdepth"].replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
'[ERROR_NOTCL] Wrong value format for self.defaults["z_pdepth"] or self.options["z_pdepth"]'
|
||||
))
|
||||
self.app.inform.emit(_('[ERROR_NOTCL] Wrong value format for self.defaults["z_pdepth"] '
|
||||
'or self.options["z_pdepth"]'))
|
||||
|
||||
try:
|
||||
job_obj.feedrate_probe = float(self.options["feedrate_probe"])
|
||||
|
@ -4622,11 +4544,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
job_obj.feedrate_rapid = float(self.options["feedrate_probe"].replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
'[ERROR_NOTCL] Wrong value format for self.defaults["feedrate_probe"] '
|
||||
'or self.options["feedrate_probe"]'
|
||||
))
|
||||
self.app.inform.emit(_('[ERROR_NOTCL] Wrong value format for self.defaults["feedrate_probe"] '
|
||||
'or self.options["feedrate_probe"]'))
|
||||
|
||||
# make sure that trying to make a CNCJob from an empty file is not creating an app crash
|
||||
if not self.solid_geometry:
|
||||
|
@ -4635,9 +4554,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
if self.tools[tooluid_key]['solid_geometry'] is None:
|
||||
a += 1
|
||||
if a == len(self.tools):
|
||||
self.app.inform.emit(_(
|
||||
'[ERROR_NOTCL] Cancelled. Empty file, it has no geometry...'
|
||||
))
|
||||
self.app.inform.emit(_('[ERROR_NOTCL] Cancelled. Empty file, it has no geometry...'))
|
||||
return 'fail'
|
||||
|
||||
for tooluid_key in self.sel_tools:
|
||||
|
@ -4750,9 +4667,9 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
if offset_value:
|
||||
tool_offset = float(offset_value)
|
||||
else:
|
||||
self.app.inform.emit(_(
|
||||
"[WARNING] Tool Offset is selected in Tool Table but no value is provided.\n"
|
||||
"Add a Tool Offset or change the Offset Type."))
|
||||
self.app.inform.emit(_("[WARNING] Tool Offset is selected in Tool Table but "
|
||||
"no value is provided.\n"
|
||||
"Add a Tool Offset or change the Offset Type."))
|
||||
return
|
||||
dia_cnc_dict.update({
|
||||
'offset_value': tool_offset
|
||||
|
@ -4769,9 +4686,11 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
app_obj.progress.emit(40)
|
||||
|
||||
spindledir = self.app.defaults['geometry_spindledir']
|
||||
|
||||
tool_solid_geometry = self.tools[current_uid]['solid_geometry']
|
||||
tol = float(self.app.defaults['global_tolerance'])
|
||||
|
||||
# it seems that the tolerance needs to be a lot lower value than 0.01 and it was hardcoded initially
|
||||
# to a value of 0.0005 which is 20 times less than 0.01
|
||||
tol = float(self.app.defaults['global_tolerance']) / 20
|
||||
res = job_obj.generate_from_multitool_geometry(
|
||||
tool_solid_geometry, tooldia=tooldia_val, offset=tool_offset,
|
||||
tolerance=tol, z_cut=z_cut, z_move=z_move,
|
||||
|
@ -4921,10 +4840,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
job_obj.z_pdepth = float(self.options["z_pdepth"].replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
'[ERROR_NOTCL] Wrong value format for self.defaults["z_pdepth"] or self.options["z_pdepth"]'
|
||||
))
|
||||
self.app.inform.emit(_('[ERROR_NOTCL] Wrong value format for self.defaults["z_pdepth"] '
|
||||
'or self.options["z_pdepth"]'))
|
||||
|
||||
try:
|
||||
job_obj.feedrate_probe = float(self.options["feedrate_probe"])
|
||||
|
@ -4933,18 +4850,17 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
try:
|
||||
job_obj.feedrate_rapid = float(self.options["feedrate_probe"].replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(
|
||||
_(
|
||||
'[ERROR_NOTCL] Wrong value format for self.defaults["feedrate_probe"] '
|
||||
'or self.options["feedrate_probe"]'
|
||||
))
|
||||
self.app.inform.emit(_('[ERROR_NOTCL] Wrong value format for self.defaults["feedrate_probe"] '
|
||||
'or self.options["feedrate_probe"]'))
|
||||
|
||||
job_obj.options['xmin'] = self.options['xmin']
|
||||
job_obj.options['ymin'] = self.options['ymin']
|
||||
job_obj.options['xmax'] = self.options['xmax']
|
||||
job_obj.options['ymax'] = self.options['ymax']
|
||||
|
||||
tol = float(self.app.defaults['global_tolerance'])
|
||||
# it seems that the tolerance needs to be a lot lower value than 0.01 and it was hardcoded initially
|
||||
# to a value of 0.0005 which is 20 times less than 0.01
|
||||
tol = float(self.app.defaults['global_tolerance']) / 20
|
||||
job_obj.generate_from_geometry_2(self, tooldia=tooldia, offset=offset, tolerance=tol,
|
||||
z_cut=z_cut, z_move=z_move,
|
||||
feedrate=feedrate, feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
|
||||
|
@ -5887,12 +5803,15 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||
with open(filename, 'w') as f:
|
||||
for line in lines:
|
||||
f.write(line)
|
||||
|
||||
except FileNotFoundError:
|
||||
self.app.inform.emit(_(
|
||||
"[WARNING_NOTCL] No such file or directory"
|
||||
))
|
||||
return
|
||||
except PermissionError:
|
||||
self.app.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return 'fail'
|
||||
elif to_file is False:
|
||||
# Just for adding it to the recent files list.
|
||||
if self.app.defaults["global_open_style"] is False:
|
||||
|
|
22
README.md
22
README.md
|
@ -9,6 +9,26 @@ CAD program, and create G-Code for Isolation routing.
|
|||
|
||||
=================================================
|
||||
|
||||
10.08.2019
|
||||
|
||||
- added new feature in NCC Tool: now another object can be used as reference for the area extent to be cleared of copper
|
||||
- fixed issue in the latest feature in NCC Tool: now it works also with reference objects made out of LineStrings (tool 'Path' in Geometry Editor)
|
||||
- translation files updated for the new strings (Google Translate)
|
||||
- RELEASE 8.93
|
||||
|
||||
9.08.2019
|
||||
|
||||
- added Exception handing for the case when the user is trying to save & overwrite a file already opened in another file
|
||||
- finished added 'Area' type of Paint in Paint Tool
|
||||
- fixed bug that created a choppy geometry for CNCJob when working in INCH
|
||||
- fixed bug that did not asked the user to save the preferences after importing a new set of preferences, after the user is trying to close the Preferences tab window
|
||||
|
||||
7.08.2019
|
||||
|
||||
- replaced setFixedWidth calls with setMinimumWidth
|
||||
- recoded the camlib.Geometry.isolation_geometry() function
|
||||
- started to work on Paint Area in Paint Tool
|
||||
|
||||
6.08.2019
|
||||
|
||||
- fixed bug that crashed the app after creating a new geometry, if a new object is loaded and the new geometry is deleted and then trying to select the just loaded new object
|
||||
|
@ -20,7 +40,7 @@ CAD program, and create G-Code for Isolation routing.
|
|||
5.08.2019
|
||||
|
||||
- made sure that if using an negative Gerber isolation diameter, the resulting Geometry object will use a tool with positive diameter
|
||||
- fixed bug that when isolating a Gerber file made out of a single polygon, an Recurrsion Exception was issued together with inability to create tbe isolation
|
||||
- fixed bug that when isolating a Gerber file made out of a single polygon, an RecursionException was issued together with inability to create tbe isolation
|
||||
- when applying a new language if there are any changes in the current project, the app will offer to save the project before the reboot
|
||||
|
||||
3.08.2019
|
||||
|
|
61
camlib.py
61
camlib.py
|
@ -555,19 +555,21 @@ class Geometry(object):
|
|||
geo_iso = self.follow_geometry
|
||||
else:
|
||||
if corner is None:
|
||||
if type(self.solid_geometry) is list and len(self.solid_geometry) == 1:
|
||||
geo_iso = self.solid_geometry[0].buffer(offset, int(int(self.geo_steps_per_circle) / 4))
|
||||
else:
|
||||
try:
|
||||
__ = iter(self.solid_geometry)
|
||||
for el in self.solid_geometry:
|
||||
geo_iso.append(el.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
|
||||
except TypeError:
|
||||
geo_iso = self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4))
|
||||
else:
|
||||
if type(self.solid_geometry) is list and len(self.solid_geometry) == 1:
|
||||
geo_iso = self.solid_geometry.buffer[0](offset, int(int(self.geo_steps_per_circle) / 4),
|
||||
join_style=corner)
|
||||
else:
|
||||
try:
|
||||
__ = iter(self.solid_geometry)
|
||||
for el in self.solid_geometry:
|
||||
geo_iso.append(el.buffer(offset, int(int(self.geo_steps_per_circle) / 4),
|
||||
join_style=corner))
|
||||
except TypeError:
|
||||
geo_iso = self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4),
|
||||
join_style=corner)
|
||||
|
||||
# end of replaced block
|
||||
if follow:
|
||||
|
@ -5751,11 +5753,11 @@ class CNCjob(Geometry):
|
|||
if pt != geo.coords[0] and pt == geo.coords[-1]:
|
||||
geo.coords = list(geo.coords)[::-1]
|
||||
|
||||
#---------- Single depth/pass --------
|
||||
# ---------- Single depth/pass --------
|
||||
if not multidepth:
|
||||
self.gcode += self.create_gcode_single_pass(geo, extracut, tolerance)
|
||||
|
||||
#--------- Multi-pass ---------
|
||||
# --------- Multi-pass ---------
|
||||
else:
|
||||
self.gcode += self.create_gcode_multi_pass(geo, extracut, tolerance,
|
||||
postproc=p, current_point=current_pt)
|
||||
|
@ -5850,8 +5852,8 @@ class CNCjob(Geometry):
|
|||
# solid geometry it's obvious we can't do the offset
|
||||
if -offset > ((c - a) / 2) or -offset > ((d - b) / 2):
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] The Tool Offset value is too negative to use "
|
||||
"for the current_geometry.\n"
|
||||
"Raise the value (in module) and try again."))
|
||||
"for the current_geometry.\n"
|
||||
"Raise the value (in module) and try again."))
|
||||
return 'fail'
|
||||
# hack: make offset smaller by 0.0000000001 which is insignificant difference but allow the job
|
||||
# to continue
|
||||
|
@ -5899,7 +5901,7 @@ class CNCjob(Geometry):
|
|||
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
|
||||
if len(self.xy_toolchange) < 2:
|
||||
self.app.inform.emit(_("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
||||
"in the format (x, y) \nbut now there is only one value, not two. "))
|
||||
"in the format (x, y) \nbut now there is only one value, not two. "))
|
||||
return 'fail'
|
||||
except Exception as e:
|
||||
log.debug("camlib.CNCJob.generate_from_geometry_2() --> %s" % str(e))
|
||||
|
@ -5910,19 +5912,19 @@ class CNCjob(Geometry):
|
|||
|
||||
if self.z_cut is None:
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Cut_Z parameter is None or zero. Most likely a bad combinations of "
|
||||
"other parameters."))
|
||||
"other parameters."))
|
||||
return 'fail'
|
||||
|
||||
if self.z_cut > 0:
|
||||
self.app.inform.emit(_("[WARNING] The Cut Z parameter has positive value. "
|
||||
"It is the depth value to cut into material.\n"
|
||||
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
|
||||
"therefore the app will convert the value to negative."
|
||||
"Check the resulting CNC code (Gcode etc)."))
|
||||
"It is the depth value to cut into material.\n"
|
||||
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
|
||||
"therefore the app will convert the value to negative."
|
||||
"Check the resulting CNC code (Gcode etc)."))
|
||||
self.z_cut = -self.z_cut
|
||||
elif self.z_cut == 0:
|
||||
self.app.inform.emit(_("[WARNING] The Cut Z parameter is zero. "
|
||||
"There will be no cut, skipping %s file") % geometry.options['name'])
|
||||
"There will be no cut, skipping %s file") % geometry.options['name'])
|
||||
return 'fail'
|
||||
|
||||
if self.z_move is None:
|
||||
|
@ -5931,14 +5933,14 @@ class CNCjob(Geometry):
|
|||
|
||||
if self.z_move < 0:
|
||||
self.app.inform.emit(_("[WARNING] The Travel Z parameter has negative value. "
|
||||
"It is the height value to travel between cuts.\n"
|
||||
"The Z Travel parameter needs to have a positive value, assuming it is a typo "
|
||||
"therefore the app will convert the value to positive."
|
||||
"Check the resulting CNC code (Gcode etc)."))
|
||||
"It is the height value to travel between cuts.\n"
|
||||
"The Z Travel parameter needs to have a positive value, assuming it is a typo "
|
||||
"therefore the app will convert the value to positive."
|
||||
"Check the resulting CNC code (Gcode etc)."))
|
||||
self.z_move = -self.z_move
|
||||
elif self.z_move == 0:
|
||||
self.app.inform.emit(_("[WARNING] The Z Travel parameter is zero. "
|
||||
"This is dangerous, skipping %s file") % self.options['name'])
|
||||
"This is dangerous, skipping %s file") % self.options['name'])
|
||||
return 'fail'
|
||||
|
||||
# ## Index first and last points in paths
|
||||
|
@ -6015,11 +6017,11 @@ class CNCjob(Geometry):
|
|||
if pt != geo.coords[0] and pt == geo.coords[-1]:
|
||||
geo.coords = list(geo.coords)[::-1]
|
||||
|
||||
#---------- Single depth/pass --------
|
||||
# ---------- Single depth/pass --------
|
||||
if not multidepth:
|
||||
self.gcode += self.create_gcode_single_pass(geo, extracut, tolerance)
|
||||
|
||||
#--------- Multi-pass ---------
|
||||
# --------- Multi-pass ---------
|
||||
else:
|
||||
self.gcode += self.create_gcode_multi_pass(geo, extracut, tolerance,
|
||||
postproc=p, current_point=current_pt)
|
||||
|
@ -6240,7 +6242,8 @@ class CNCjob(Geometry):
|
|||
gcode_multi_pass += self.linear2gcode(geometry, tolerance=tolerance, z_cut=depth, up=False)
|
||||
else:
|
||||
if geometry.is_ring:
|
||||
gcode_multi_pass += self.linear2gcode_extra(geometry, tolerance=tolerance, z_cut=depth, up=False)
|
||||
gcode_multi_pass += self.linear2gcode_extra(geometry, tolerance=tolerance, z_cut=depth,
|
||||
up=False)
|
||||
else:
|
||||
gcode_multi_pass += self.linear2gcode(geometry, tolerance=tolerance, z_cut=depth, up=False)
|
||||
|
||||
|
@ -6414,7 +6417,6 @@ class CNCjob(Geometry):
|
|||
current['G'] = int(gobj['G'])
|
||||
|
||||
if 'X' in gobj or 'Y' in gobj:
|
||||
# TODO: I think there is a problem here, current['X] (and the rest of current[...] are not initialized
|
||||
if 'X' in gobj:
|
||||
x = gobj['X']
|
||||
# current['X'] = x
|
||||
|
@ -6505,6 +6507,9 @@ class CNCjob(Geometry):
|
|||
:param color: Color specification.
|
||||
:param alpha: Transparency specification.
|
||||
:param tool_tolerance: Tolerance when drawing the toolshape.
|
||||
:param obj
|
||||
:param visible
|
||||
:param kind
|
||||
:return: None
|
||||
"""
|
||||
# units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
|
||||
|
@ -6556,7 +6561,7 @@ class CNCjob(Geometry):
|
|||
|
||||
if kind == 'all':
|
||||
obj.add_shape(shape=poly, color=color[geo['kind'][0]][1], face_color=color[geo['kind'][0]][0],
|
||||
visible=visible, layer=1 if geo['kind'][0] == 'C' else 2)
|
||||
visible=visible, layer=1 if geo['kind'][0] == 'C' else 2)
|
||||
elif kind == 'travel':
|
||||
if geo['kind'][0] == 'T':
|
||||
obj.add_shape(shape=poly, color=color['T'][1], face_color=color['T'][0],
|
||||
|
|
|
@ -641,16 +641,16 @@ class TransformEditorTool(FlatCAMTool):
|
|||
self.transform_lay.addWidget(title_label)
|
||||
|
||||
self.empty_label = QtWidgets.QLabel("")
|
||||
self.empty_label.setFixedWidth(50)
|
||||
self.empty_label.setMinimumWidth(50)
|
||||
|
||||
self.empty_label1 = QtWidgets.QLabel("")
|
||||
self.empty_label1.setFixedWidth(70)
|
||||
self.empty_label1.setMinimumWidth(70)
|
||||
self.empty_label2 = QtWidgets.QLabel("")
|
||||
self.empty_label2.setFixedWidth(70)
|
||||
self.empty_label2.setMinimumWidth(70)
|
||||
self.empty_label3 = QtWidgets.QLabel("")
|
||||
self.empty_label3.setFixedWidth(70)
|
||||
self.empty_label3.setMinimumWidth(70)
|
||||
self.empty_label4 = QtWidgets.QLabel("")
|
||||
self.empty_label4.setFixedWidth(70)
|
||||
self.empty_label4.setMinimumWidth(70)
|
||||
self.transform_lay.addWidget(self.empty_label)
|
||||
|
||||
# Rotate Title
|
||||
|
|
|
@ -2604,7 +2604,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.pad_array_size_label.setToolTip(
|
||||
_("Specify how many pads to be in the array.")
|
||||
)
|
||||
self.pad_array_size_label.setFixedWidth(100)
|
||||
self.pad_array_size_label.setMinimumWidth(100)
|
||||
|
||||
self.pad_array_size_entry = LengthEntry()
|
||||
self.array_form.addRow(self.pad_array_size_label, self.pad_array_size_entry)
|
||||
|
@ -2626,7 +2626,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
"- 'Y' - vertical axis or \n"
|
||||
"- 'Angle' - a custom angle for the array inclination")
|
||||
)
|
||||
self.pad_axis_label.setFixedWidth(100)
|
||||
self.pad_axis_label.setMinimumWidth(100)
|
||||
|
||||
self.pad_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'},
|
||||
{'label': _('Y'), 'value': 'Y'},
|
||||
|
@ -2638,7 +2638,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.pad_pitch_label.setToolTip(
|
||||
_("Pitch = Distance between elements of the array.")
|
||||
)
|
||||
self.pad_pitch_label.setFixedWidth(100)
|
||||
self.pad_pitch_label.setMinimumWidth(100)
|
||||
|
||||
self.pad_pitch_entry = LengthEntry()
|
||||
self.linear_form.addRow(self.pad_pitch_label, self.pad_pitch_entry)
|
||||
|
@ -2650,7 +2650,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
"Min value is: -359.99 degrees.\n"
|
||||
"Max value is: 360.00 degrees.")
|
||||
)
|
||||
self.linear_angle_label.setFixedWidth(100)
|
||||
self.linear_angle_label.setMinimumWidth(100)
|
||||
|
||||
self.linear_angle_spinner = FCDoubleSpinner()
|
||||
self.linear_angle_spinner.set_precision(2)
|
||||
|
@ -2669,7 +2669,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
_("Direction for circular array."
|
||||
"Can be CW = clockwise or CCW = counter clockwise.")
|
||||
)
|
||||
self.pad_direction_label.setFixedWidth(100)
|
||||
self.pad_direction_label.setMinimumWidth(100)
|
||||
|
||||
self.circular_form = QtWidgets.QFormLayout()
|
||||
self.circular_box.addLayout(self.circular_form)
|
||||
|
@ -2683,7 +2683,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.pad_angle_label.setToolTip(
|
||||
_("Angle at which each element in circular array is placed.")
|
||||
)
|
||||
self.pad_angle_label.setFixedWidth(100)
|
||||
self.pad_angle_label.setMinimumWidth(100)
|
||||
|
||||
self.pad_angle_entry = LengthEntry()
|
||||
self.circular_form.addRow(self.pad_angle_label, self.pad_angle_entry)
|
||||
|
@ -4719,16 +4719,16 @@ class TransformEditorTool(FlatCAMTool):
|
|||
self.transform_lay.addWidget(title_label)
|
||||
|
||||
self.empty_label = QtWidgets.QLabel("")
|
||||
self.empty_label.setFixedWidth(50)
|
||||
self.empty_label.setMinimumWidth(50)
|
||||
|
||||
self.empty_label1 = QtWidgets.QLabel("")
|
||||
self.empty_label1.setFixedWidth(70)
|
||||
self.empty_label1.setMinimumWidth(70)
|
||||
self.empty_label2 = QtWidgets.QLabel("")
|
||||
self.empty_label2.setFixedWidth(70)
|
||||
self.empty_label2.setMinimumWidth(70)
|
||||
self.empty_label3 = QtWidgets.QLabel("")
|
||||
self.empty_label3.setFixedWidth(70)
|
||||
self.empty_label3.setMinimumWidth(70)
|
||||
self.empty_label4 = QtWidgets.QLabel("")
|
||||
self.empty_label4.setFixedWidth(70)
|
||||
self.empty_label4.setMinimumWidth(70)
|
||||
self.transform_lay.addWidget(self.empty_label)
|
||||
|
||||
# Rotate Title
|
||||
|
@ -4747,7 +4747,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
"Positive numbers for CW motion.\n"
|
||||
"Negative numbers for CCW motion.")
|
||||
)
|
||||
self.rotate_label.setFixedWidth(50)
|
||||
self.rotate_label.setMinimumWidth(50)
|
||||
|
||||
self.rotate_entry = FCEntry()
|
||||
# self.rotate_entry.setFixedWidth(60)
|
||||
|
@ -4760,7 +4760,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected shapes.")
|
||||
)
|
||||
self.rotate_button.setFixedWidth(60)
|
||||
self.rotate_button.setMinimumWidth(60)
|
||||
|
||||
form_child.addWidget(self.rotate_entry)
|
||||
form_child.addWidget(self.rotate_button)
|
||||
|
@ -4784,7 +4784,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
_("Angle for Skew action, in degrees.\n"
|
||||
"Float number between -360 and 359.")
|
||||
)
|
||||
self.skewx_label.setFixedWidth(50)
|
||||
self.skewx_label.setMinimumWidth(50)
|
||||
self.skewx_entry = FCEntry()
|
||||
self.skewx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.skewx_entry.setFixedWidth(60)
|
||||
|
@ -4795,14 +4795,14 @@ class TransformEditorTool(FlatCAMTool):
|
|||
_("Skew/shear the selected shape(s).\n"
|
||||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected shapes."))
|
||||
self.skewx_button.setFixedWidth(60)
|
||||
self.skewx_button.setMinimumWidth(60)
|
||||
|
||||
self.skewy_label = QtWidgets.QLabel(_("Angle Y:"))
|
||||
self.skewy_label.setToolTip(
|
||||
_("Angle for Skew action, in degrees.\n"
|
||||
"Float number between -360 and 359.")
|
||||
)
|
||||
self.skewy_label.setFixedWidth(50)
|
||||
self.skewy_label.setMinimumWidth(50)
|
||||
self.skewy_entry = FCEntry()
|
||||
self.skewy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.skewy_entry.setFixedWidth(60)
|
||||
|
@ -4813,7 +4813,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
_("Skew/shear the selected shape(s).\n"
|
||||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected shapes."))
|
||||
self.skewy_button.setFixedWidth(60)
|
||||
self.skewy_button.setMinimumWidth(60)
|
||||
|
||||
form1_child_1.addWidget(self.skewx_entry)
|
||||
form1_child_1.addWidget(self.skewx_button)
|
||||
|
@ -4840,7 +4840,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
self.scalex_label.setToolTip(
|
||||
_("Factor for Scale action over X axis.")
|
||||
)
|
||||
self.scalex_label.setFixedWidth(50)
|
||||
self.scalex_label.setMinimumWidth(50)
|
||||
self.scalex_entry = FCEntry()
|
||||
self.scalex_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.scalex_entry.setFixedWidth(60)
|
||||
|
@ -4851,13 +4851,13 @@ class TransformEditorTool(FlatCAMTool):
|
|||
_("Scale the selected shape(s).\n"
|
||||
"The point of reference depends on \n"
|
||||
"the Scale reference checkbox state."))
|
||||
self.scalex_button.setFixedWidth(60)
|
||||
self.scalex_button.setMinimumWidth(60)
|
||||
|
||||
self.scaley_label = QtWidgets.QLabel(_("Factor Y:"))
|
||||
self.scaley_label.setToolTip(
|
||||
_("Factor for Scale action over Y axis.")
|
||||
)
|
||||
self.scaley_label.setFixedWidth(50)
|
||||
self.scaley_label.setMinimumWidth(50)
|
||||
self.scaley_entry = FCEntry()
|
||||
self.scaley_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.scaley_entry.setFixedWidth(60)
|
||||
|
@ -4868,7 +4868,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
_("Scale the selected shape(s).\n"
|
||||
"The point of reference depends on \n"
|
||||
"the Scale reference checkbox state."))
|
||||
self.scaley_button.setFixedWidth(60)
|
||||
self.scaley_button.setMinimumWidth(60)
|
||||
|
||||
self.scale_link_cb = FCCheckBox()
|
||||
self.scale_link_cb.set_value(True)
|
||||
|
@ -4876,7 +4876,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
self.scale_link_cb.setToolTip(
|
||||
_("Scale the selected shape(s)\n"
|
||||
"using the Scale Factor X for both axis."))
|
||||
self.scale_link_cb.setFixedWidth(50)
|
||||
self.scale_link_cb.setMinimumWidth(50)
|
||||
|
||||
self.scale_zero_ref_cb = FCCheckBox()
|
||||
self.scale_zero_ref_cb.set_value(True)
|
||||
|
@ -4915,7 +4915,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
self.offx_label.setToolTip(
|
||||
_("Value for Offset action on X axis.")
|
||||
)
|
||||
self.offx_label.setFixedWidth(50)
|
||||
self.offx_label.setMinimumWidth(50)
|
||||
self.offx_entry = FCEntry()
|
||||
self.offx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.offx_entry.setFixedWidth(60)
|
||||
|
@ -4927,13 +4927,13 @@ class TransformEditorTool(FlatCAMTool):
|
|||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected shapes.\n")
|
||||
)
|
||||
self.offx_button.setFixedWidth(60)
|
||||
self.offx_button.setMinimumWidth(60)
|
||||
|
||||
self.offy_label = QtWidgets.QLabel(_("Value Y:"))
|
||||
self.offy_label.setToolTip(
|
||||
_("Value for Offset action on Y axis.")
|
||||
)
|
||||
self.offy_label.setFixedWidth(50)
|
||||
self.offy_label.setMinimumWidth(50)
|
||||
self.offy_entry = FCEntry()
|
||||
self.offy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.offy_entry.setFixedWidth(60)
|
||||
|
@ -4945,7 +4945,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected shapes.\n")
|
||||
)
|
||||
self.offy_button.setFixedWidth(60)
|
||||
self.offy_button.setMinimumWidth(60)
|
||||
|
||||
form3_child_1.addWidget(self.offx_entry)
|
||||
form3_child_1.addWidget(self.offx_button)
|
||||
|
@ -4975,7 +4975,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
_("Flip the selected shape(s) over the X axis.\n"
|
||||
"Does not create a new shape.")
|
||||
)
|
||||
self.flipx_button.setFixedWidth(60)
|
||||
self.flipx_button.setMinimumWidth(60)
|
||||
|
||||
self.flipy_button = FCButton()
|
||||
self.flipy_button.set_value(_("Flip on Y"))
|
||||
|
@ -4983,7 +4983,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
_("Flip the selected shape(s) over the X axis.\n"
|
||||
"Does not create a new shape.")
|
||||
)
|
||||
self.flipy_button.setFixedWidth(60)
|
||||
self.flipy_button.setMinimumWidth(60)
|
||||
|
||||
self.flip_ref_cb = FCCheckBox()
|
||||
self.flip_ref_cb.set_value(True)
|
||||
|
@ -4999,7 +4999,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
"Or enter the coords in format (x, y) in the\n"
|
||||
"Point Entry field and click Flip on X(Y)")
|
||||
)
|
||||
self.flip_ref_cb.setFixedWidth(50)
|
||||
self.flip_ref_cb.setMinimumWidth(50)
|
||||
|
||||
self.flip_ref_label = QtWidgets.QLabel(_("Point:"))
|
||||
self.flip_ref_label.setToolTip(
|
||||
|
@ -5007,7 +5007,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
"The 'x' in (x, y) will be used when using Flip on X and\n"
|
||||
"the 'y' in (x, y) will be used when using Flip on Y.")
|
||||
)
|
||||
self.flip_ref_label.setFixedWidth(50)
|
||||
self.flip_ref_label.setMinimumWidth(50)
|
||||
self.flip_ref_entry = EvalEntry2("(0, 0)")
|
||||
self.flip_ref_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.flip_ref_entry.setFixedWidth(60)
|
||||
|
@ -5019,7 +5019,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
"left click on canvas together with pressing\n"
|
||||
"SHIFT key. Then click Add button to insert.")
|
||||
)
|
||||
self.flip_ref_button.setFixedWidth(60)
|
||||
self.flip_ref_button.setMinimumWidth(60)
|
||||
|
||||
form4_child_hlay.addStretch()
|
||||
form4_child_hlay.addWidget(self.flipx_button)
|
||||
|
|
|
@ -1656,12 +1656,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.buttonPreview = QtWidgets.QPushButton(_('Print Preview'))
|
||||
self.buttonPrint = QtWidgets.QPushButton(_('Print Code'))
|
||||
self.buttonFind = QtWidgets.QPushButton(_('Find in Code'))
|
||||
self.buttonFind.setFixedWidth(100)
|
||||
self.buttonPreview.setFixedWidth(100)
|
||||
self.buttonFind.setMinimumWidth(100)
|
||||
self.buttonPreview.setMinimumWidth(100)
|
||||
self.entryFind = FCEntry()
|
||||
self.entryFind.setMaximumWidth(200)
|
||||
self.buttonReplace = QtWidgets.QPushButton(_('Replace With'))
|
||||
self.buttonReplace.setFixedWidth(100)
|
||||
self.buttonReplace.setMinimumWidth(100)
|
||||
self.entryReplace = FCEntry()
|
||||
self.entryReplace.setMaximumWidth(200)
|
||||
self.sel_all_cb = QtWidgets.QCheckBox(_('All'))
|
||||
|
@ -3255,9 +3255,9 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
|
|||
self.setLayout(self.layout)
|
||||
|
||||
self.tools_ncc_group = ToolsNCCPrefGroupUI()
|
||||
self.tools_ncc_group.setMinimumWidth(200)
|
||||
self.tools_ncc_group.setMinimumWidth(220)
|
||||
self.tools_paint_group = ToolsPaintPrefGroupUI()
|
||||
self.tools_paint_group.setMinimumWidth(200)
|
||||
self.tools_paint_group.setMinimumWidth(220)
|
||||
|
||||
self.tools_cutout_group = ToolsCutoutPrefGroupUI()
|
||||
self.tools_cutout_group.setMinimumWidth(220)
|
||||
|
@ -3417,7 +3417,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
self.pf_color_alpha_slider.setSingleStep(1)
|
||||
|
||||
self.pf_color_alpha_spinner = FCSpinner()
|
||||
self.pf_color_alpha_spinner.setFixedWidth(70)
|
||||
self.pf_color_alpha_spinner.setMinimumWidth(70)
|
||||
self.pf_color_alpha_spinner.setMinimum(0)
|
||||
self.pf_color_alpha_spinner.setMaximum(255)
|
||||
|
||||
|
@ -3467,7 +3467,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
self.sf_color_alpha_slider.setSingleStep(1)
|
||||
|
||||
self.sf_color_alpha_spinner = FCSpinner()
|
||||
self.sf_color_alpha_spinner.setFixedWidth(70)
|
||||
self.sf_color_alpha_spinner.setMinimumWidth(70)
|
||||
self.sf_color_alpha_spinner.setMinimum(0)
|
||||
self.sf_color_alpha_spinner.setMaximum(255)
|
||||
|
||||
|
@ -3517,7 +3517,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
self.alt_sf_color_alpha_slider.setSingleStep(1)
|
||||
|
||||
self.alt_sf_color_alpha_spinner = FCSpinner()
|
||||
self.alt_sf_color_alpha_spinner.setFixedWidth(70)
|
||||
self.alt_sf_color_alpha_spinner.setMinimumWidth(70)
|
||||
self.alt_sf_color_alpha_spinner.setMinimum(0)
|
||||
self.alt_sf_color_alpha_spinner.setMaximum(255)
|
||||
|
||||
|
@ -4291,7 +4291,7 @@ class GerberExpPrefGroupUI(OptionsGroupUI):
|
|||
self.format_whole_entry = IntEntry()
|
||||
self.format_whole_entry.setMaxLength(1)
|
||||
self.format_whole_entry.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.format_whole_entry.setFixedWidth(30)
|
||||
self.format_whole_entry.setMinimumWidth(30)
|
||||
self.format_whole_entry.setToolTip(
|
||||
_("This numbers signify the number of digits in\n"
|
||||
"the whole part of Gerber coordinates.")
|
||||
|
@ -4305,7 +4305,7 @@ class GerberExpPrefGroupUI(OptionsGroupUI):
|
|||
self.format_dec_entry = IntEntry()
|
||||
self.format_dec_entry.setMaxLength(1)
|
||||
self.format_dec_entry.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.format_dec_entry.setFixedWidth(30)
|
||||
self.format_dec_entry.setMinimumWidth(30)
|
||||
self.format_dec_entry.setToolTip(
|
||||
_("This numbers signify the number of digits in\n"
|
||||
"the decimal part of Gerber coordinates.")
|
||||
|
@ -4439,7 +4439,7 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
self.excellon_format_upper_in_entry = IntEntry()
|
||||
self.excellon_format_upper_in_entry.setMaxLength(1)
|
||||
self.excellon_format_upper_in_entry.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.excellon_format_upper_in_entry.setFixedWidth(30)
|
||||
self.excellon_format_upper_in_entry.setMinimumWidth(30)
|
||||
self.excellon_format_upper_in_entry.setToolTip(
|
||||
_("This numbers signify the number of digits in\n"
|
||||
"the whole part of Excellon coordinates.")
|
||||
|
@ -4453,7 +4453,7 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
self.excellon_format_lower_in_entry = IntEntry()
|
||||
self.excellon_format_lower_in_entry.setMaxLength(1)
|
||||
self.excellon_format_lower_in_entry.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.excellon_format_lower_in_entry.setFixedWidth(30)
|
||||
self.excellon_format_lower_in_entry.setMinimumWidth(30)
|
||||
self.excellon_format_lower_in_entry.setToolTip(
|
||||
_("This numbers signify the number of digits in\n"
|
||||
"the decimal part of Excellon coordinates.")
|
||||
|
@ -4472,7 +4472,7 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
self.excellon_format_upper_mm_entry = IntEntry()
|
||||
self.excellon_format_upper_mm_entry.setMaxLength(1)
|
||||
self.excellon_format_upper_mm_entry.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.excellon_format_upper_mm_entry.setFixedWidth(30)
|
||||
self.excellon_format_upper_mm_entry.setMinimumWidth(30)
|
||||
self.excellon_format_upper_mm_entry.setToolTip(
|
||||
_("This numbers signify the number of digits in\n"
|
||||
"the whole part of Excellon coordinates.")
|
||||
|
@ -4486,7 +4486,7 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
self.excellon_format_lower_mm_entry = IntEntry()
|
||||
self.excellon_format_lower_mm_entry.setMaxLength(1)
|
||||
self.excellon_format_lower_mm_entry.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.excellon_format_lower_mm_entry.setFixedWidth(30)
|
||||
self.excellon_format_lower_mm_entry.setMinimumWidth(30)
|
||||
self.excellon_format_lower_mm_entry.setToolTip(
|
||||
_("This numbers signify the number of digits in\n"
|
||||
"the decimal part of Excellon coordinates.")
|
||||
|
@ -4778,7 +4778,7 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI):
|
|||
# Adding the Excellon Format Defaults Button
|
||||
self.excellon_defaults_button = QtWidgets.QPushButton()
|
||||
self.excellon_defaults_button.setText(str(_("Defaults")))
|
||||
self.excellon_defaults_button.setFixedWidth(80)
|
||||
self.excellon_defaults_button.setMinimumWidth(80)
|
||||
grid4.addWidget(self.excellon_defaults_button, 0, 0, QtCore.Qt.AlignRight)
|
||||
|
||||
self.layout.addStretch()
|
||||
|
@ -4945,7 +4945,7 @@ class ExcellonExpPrefGroupUI(OptionsGroupUI):
|
|||
self.format_whole_entry = IntEntry()
|
||||
self.format_whole_entry.setMaxLength(1)
|
||||
self.format_whole_entry.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.format_whole_entry.setFixedWidth(30)
|
||||
self.format_whole_entry.setMinimumWidth(30)
|
||||
self.format_whole_entry.setToolTip(
|
||||
_("This numbers signify the number of digits in\n"
|
||||
"the whole part of Excellon coordinates.")
|
||||
|
@ -4959,7 +4959,7 @@ class ExcellonExpPrefGroupUI(OptionsGroupUI):
|
|||
self.format_dec_entry = IntEntry()
|
||||
self.format_dec_entry.setMaxLength(1)
|
||||
self.format_dec_entry.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.format_dec_entry.setFixedWidth(30)
|
||||
self.format_dec_entry.setMinimumWidth(30)
|
||||
self.format_dec_entry.setToolTip(
|
||||
_("This numbers signify the number of digits in\n"
|
||||
"the decimal part of Excellon coordinates.")
|
||||
|
@ -5074,7 +5074,7 @@ class ExcellonEditorPrefGroupUI(OptionsGroupUI):
|
|||
self.drill_array_size_label.setToolTip(
|
||||
_("Specify how many drills to be in the array.")
|
||||
)
|
||||
# self.drill_array_size_label.setFixedWidth(100)
|
||||
# self.drill_array_size_label.setMinimumWidth(100)
|
||||
|
||||
self.drill_array_size_entry = LengthEntry()
|
||||
|
||||
|
@ -5092,7 +5092,7 @@ class ExcellonEditorPrefGroupUI(OptionsGroupUI):
|
|||
"- 'Y' - vertical axis or \n"
|
||||
"- 'Angle' - a custom angle for the array inclination")
|
||||
)
|
||||
# self.drill_axis_label.setFixedWidth(100)
|
||||
# self.drill_axis_label.setMinimumWidth(100)
|
||||
self.drill_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'},
|
||||
{'label': _('Y'), 'value': 'Y'},
|
||||
{'label': _('Angle'), 'value': 'A'}])
|
||||
|
@ -5105,7 +5105,7 @@ class ExcellonEditorPrefGroupUI(OptionsGroupUI):
|
|||
self.drill_pitch_label.setToolTip(
|
||||
_("Pitch = Distance between elements of the array.")
|
||||
)
|
||||
# self.drill_pitch_label.setFixedWidth(100)
|
||||
# self.drill_pitch_label.setMinimumWidth(100)
|
||||
self.drill_pitch_entry = LengthEntry()
|
||||
|
||||
grid0.addWidget(self.drill_pitch_label, 5, 0)
|
||||
|
@ -5875,6 +5875,19 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
|
|||
self.ncc_rest_cb = FCCheckBox()
|
||||
grid0.addWidget(self.ncc_rest_cb, 6, 1)
|
||||
|
||||
# ## Reference
|
||||
self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
|
||||
{'label': _('Box'), 'value': 'box'}])
|
||||
reference_label = QtWidgets.QLabel(_("Reference:"))
|
||||
reference_label.setToolTip(
|
||||
_("When choosing the 'Itself' option the non copper clearing extent\n"
|
||||
"is based on the object that is copper cleared.\n "
|
||||
"Choosing the 'Box' option will do non copper clearing within the box\n"
|
||||
"specified by another object different than the one that is copper cleared.")
|
||||
)
|
||||
grid0.addWidget(reference_label, 7, 0)
|
||||
grid0.addWidget(self.reference_radio, 7, 1)
|
||||
|
||||
self.layout.addStretch()
|
||||
|
||||
|
||||
|
@ -6126,8 +6139,8 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
|
|||
grid0.addWidget(selectlabel, 6, 0)
|
||||
self.selectmethod_combo = RadioSet([
|
||||
{"label": _("Single"), "value": "single"},
|
||||
{"label": _("All"), "value": "all"},
|
||||
# {"label": "Rectangle", "value": "rectangle"}
|
||||
{"label": _("Area"), "value": "area"},
|
||||
{"label": _("All"), "value": "all"}
|
||||
])
|
||||
grid0.addWidget(self.selectmethod_combo, 6, 1)
|
||||
|
||||
|
|
|
@ -1634,7 +1634,7 @@ class Dialog_box(QtWidgets.QWidget):
|
|||
self.ok = False
|
||||
|
||||
dialog_box = QtWidgets.QInputDialog()
|
||||
dialog_box.setFixedWidth(290)
|
||||
dialog_box.setMinimumWidth(290)
|
||||
self.setWindowIcon(icon)
|
||||
|
||||
self.location, self.ok = dialog_box.getText(self, title, label, text="0, 0")
|
||||
|
|
|
@ -101,7 +101,7 @@ class ObjectUI(QtWidgets.QWidget):
|
|||
self.scale_button.setToolTip(
|
||||
_("Perform scaling operation.")
|
||||
)
|
||||
self.scale_button.setFixedWidth(70)
|
||||
self.scale_button.setMinimumWidth(70)
|
||||
self.scale_grid.addWidget(self.scale_button, 0, 2)
|
||||
|
||||
# ### Offset ####
|
||||
|
@ -128,7 +128,7 @@ class ObjectUI(QtWidgets.QWidget):
|
|||
self.offset_button.setToolTip(
|
||||
_("Perform the offset operation.")
|
||||
)
|
||||
self.offset_button.setFixedWidth(70)
|
||||
self.offset_button.setMinimumWidth(70)
|
||||
self.offset_grid.addWidget(self.offset_button, 0, 2)
|
||||
|
||||
layout.addStretch()
|
||||
|
@ -148,7 +148,7 @@ class GerberObjectUI(ObjectUI):
|
|||
self.custom_box.addLayout(grid0)
|
||||
|
||||
self.plot_options_label = QtWidgets.QLabel(_("<b>Plot Options:</b>"))
|
||||
self.plot_options_label.setFixedWidth(90)
|
||||
self.plot_options_label.setMinimumWidth(90)
|
||||
|
||||
grid0.addWidget(self.plot_options_label, 0, 0)
|
||||
|
||||
|
@ -157,7 +157,7 @@ class GerberObjectUI(ObjectUI):
|
|||
self.solid_cb.setToolTip(
|
||||
_("Solid color polygons.")
|
||||
)
|
||||
self.solid_cb.setFixedWidth(50)
|
||||
self.solid_cb.setMinimumWidth(50)
|
||||
grid0.addWidget(self.solid_cb, 0, 1)
|
||||
|
||||
# Multicolored CB
|
||||
|
@ -165,7 +165,7 @@ class GerberObjectUI(ObjectUI):
|
|||
self.multicolored_cb.setToolTip(
|
||||
_("Draw polygons in different colors.")
|
||||
)
|
||||
self.multicolored_cb.setFixedWidth(55)
|
||||
self.multicolored_cb.setMinimumWidth(55)
|
||||
grid0.addWidget(self.multicolored_cb, 0, 2)
|
||||
|
||||
# Plot CB
|
||||
|
@ -173,7 +173,7 @@ class GerberObjectUI(ObjectUI):
|
|||
self.plot_cb.setToolTip(
|
||||
_("Plot (show) this object.")
|
||||
)
|
||||
self.plot_cb.setFixedWidth(59)
|
||||
self.plot_cb.setMinimumWidth(59)
|
||||
grid0.addWidget(self.plot_cb, 0, 3)
|
||||
|
||||
# ## Object name
|
||||
|
@ -193,7 +193,7 @@ class GerberObjectUI(ObjectUI):
|
|||
self.apertures_table_label.setToolTip(
|
||||
_("Apertures Table for the Gerber Object.")
|
||||
)
|
||||
self.apertures_table_label.setFixedWidth(90)
|
||||
self.apertures_table_label.setMinimumWidth(90)
|
||||
|
||||
hlay_plot.addWidget(self.apertures_table_label)
|
||||
|
||||
|
@ -264,7 +264,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"feature, use a negative value for\n"
|
||||
"this parameter.")
|
||||
)
|
||||
tdlabel.setFixedWidth(90)
|
||||
tdlabel.setMinimumWidth(90)
|
||||
grid1.addWidget(tdlabel, 0, 0)
|
||||
self.iso_tool_dia_entry = LengthEntry()
|
||||
grid1.addWidget(self.iso_tool_dia_entry, 0, 1)
|
||||
|
@ -274,7 +274,7 @@ class GerberObjectUI(ObjectUI):
|
|||
_("Width of the isolation gap in\n"
|
||||
"number (integer) of tool widths.")
|
||||
)
|
||||
passlabel.setFixedWidth(90)
|
||||
passlabel.setMinimumWidth(90)
|
||||
grid1.addWidget(passlabel, 1, 0)
|
||||
self.iso_width_entry = IntEntry()
|
||||
grid1.addWidget(self.iso_width_entry, 1, 1)
|
||||
|
@ -285,7 +285,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"Example:\n"
|
||||
"A value here of 0.25 means an overlap of 25% from the tool diameter found above.")
|
||||
)
|
||||
overlabel.setFixedWidth(90)
|
||||
overlabel.setMinimumWidth(90)
|
||||
grid1.addWidget(overlabel, 2, 0)
|
||||
self.iso_overlap_entry = FloatEntry()
|
||||
grid1.addWidget(self.iso_overlap_entry, 2, 1)
|
||||
|
@ -337,7 +337,7 @@ class GerberObjectUI(ObjectUI):
|
|||
self.custom_box.addLayout(hlay_1)
|
||||
|
||||
self.padding_area_label = QtWidgets.QLabel('')
|
||||
self.padding_area_label.setFixedWidth(90)
|
||||
self.padding_area_label.setMinimumWidth(90)
|
||||
hlay_1.addWidget(self.padding_area_label)
|
||||
|
||||
self.generate_iso_button = QtWidgets.QPushButton(_('FULL Geo'))
|
||||
|
@ -346,7 +346,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"for isolation routing. It contains both\n"
|
||||
"the interiors and exteriors geometry.")
|
||||
)
|
||||
self.generate_iso_button.setFixedWidth(90)
|
||||
self.generate_iso_button.setMinimumWidth(90)
|
||||
hlay_1.addWidget(self.generate_iso_button, alignment=Qt.AlignLeft)
|
||||
|
||||
# hlay_1.addStretch()
|
||||
|
@ -357,7 +357,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"for isolation routing containing\n"
|
||||
"only the exteriors geometry.")
|
||||
)
|
||||
# self.generate_ext_iso_button.setFixedWidth(100)
|
||||
# self.generate_ext_iso_button.setMinimumWidth(100)
|
||||
hlay_1.addWidget(self.generate_ext_iso_button)
|
||||
|
||||
self.generate_int_iso_button = QtWidgets.QPushButton(_('Int Geo'))
|
||||
|
@ -366,7 +366,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"for isolation routing containing\n"
|
||||
"only the interiors geometry.")
|
||||
)
|
||||
# self.generate_ext_iso_button.setFixedWidth(90)
|
||||
# self.generate_ext_iso_button.setMinimumWidth(90)
|
||||
hlay_1.addWidget(self.generate_int_iso_button)
|
||||
|
||||
# when the follow checkbox is checked then the exteriors and interiors isolation generation buttons
|
||||
|
@ -383,7 +383,7 @@ class GerberObjectUI(ObjectUI):
|
|||
_("Create a Geometry object with\n"
|
||||
"toolpaths to cut all non-copper regions.")
|
||||
)
|
||||
self.clearcopper_label.setFixedWidth(90)
|
||||
self.clearcopper_label.setMinimumWidth(90)
|
||||
grid2.addWidget(self.clearcopper_label, 0, 0)
|
||||
|
||||
self.generate_ncc_button = QtWidgets.QPushButton(_('NCC Tool'))
|
||||
|
@ -431,7 +431,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"objects with this minimum\n"
|
||||
"distance.")
|
||||
)
|
||||
bmlabel.setFixedWidth(90)
|
||||
bmlabel.setMinimumWidth(90)
|
||||
grid4.addWidget(bmlabel, 0, 0)
|
||||
self.noncopper_margin_entry = LengthEntry()
|
||||
grid4.addWidget(self.noncopper_margin_entry, 0, 1)
|
||||
|
@ -441,7 +441,7 @@ class GerberObjectUI(ObjectUI):
|
|||
self.noncopper_rounded_cb.setToolTip(
|
||||
_("Resulting geometry will have rounded corners.")
|
||||
)
|
||||
self.noncopper_rounded_cb.setFixedWidth(90)
|
||||
self.noncopper_rounded_cb.setMinimumWidth(90)
|
||||
grid4.addWidget(self.noncopper_rounded_cb, 1, 0)
|
||||
|
||||
self.generate_noncopper_button = QtWidgets.QPushButton(_('Generate Geo'))
|
||||
|
@ -463,7 +463,7 @@ class GerberObjectUI(ObjectUI):
|
|||
_("Distance of the edges of the box\n"
|
||||
"to the nearest polygon.")
|
||||
)
|
||||
bbmargin.setFixedWidth(90)
|
||||
bbmargin.setMinimumWidth(90)
|
||||
grid5.addWidget(bbmargin, 0, 0)
|
||||
self.bbmargin_entry = LengthEntry()
|
||||
grid5.addWidget(self.bbmargin_entry, 0, 1)
|
||||
|
@ -475,7 +475,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"their radius is equal to\n"
|
||||
"the margin.")
|
||||
)
|
||||
self.bbrounded_cb.setFixedWidth(90)
|
||||
self.bbrounded_cb.setMinimumWidth(90)
|
||||
grid5.addWidget(self.bbrounded_cb, 1, 0)
|
||||
|
||||
self.generate_bb_button = QtWidgets.QPushButton(_('Generate Geo'))
|
||||
|
@ -957,7 +957,7 @@ class GeometryObjectUI(ObjectUI):
|
|||
self.tool_offset_entry = FloatEntry()
|
||||
self.tool_offset_entry.setValidator(QtGui.QDoubleValidator(-9999.9999, 9999.9999, 4))
|
||||
spacer_lbl = QtWidgets.QLabel(" ")
|
||||
spacer_lbl.setFixedWidth(80)
|
||||
spacer_lbl.setMinimumWidth(80)
|
||||
|
||||
self.grid1.addWidget(self.tool_offset_entry, 0, 1)
|
||||
self.grid1.addWidget(spacer_lbl, 0, 2)
|
||||
|
|
|
@ -269,7 +269,7 @@ class ShapeCollectionVisual(CompoundVisual):
|
|||
# Add data to process pool if pool exists
|
||||
try:
|
||||
self.results[key] = self.pool.map_async(_update_shape_buffers, [self.data[key]])
|
||||
except:
|
||||
except Exception as e:
|
||||
self.data[key] = _update_shape_buffers(self.data[key])
|
||||
|
||||
if update:
|
||||
|
|
|
@ -58,7 +58,7 @@ class CutOut(FlatCAMTool):
|
|||
"What is selected here will dictate the kind\n"
|
||||
"of objects that will populate the 'Object' combobox.")
|
||||
)
|
||||
self.type_obj_combo_label.setFixedWidth(60)
|
||||
self.type_obj_combo_label.setMinimumWidth(60)
|
||||
form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo)
|
||||
|
||||
# Object to be cutout
|
||||
|
@ -158,7 +158,7 @@ class CutOut(FlatCAMTool):
|
|||
"- 2tb - 2*top + 2*bottom\n"
|
||||
"- 8 - 2*left + 2*right +2*top + 2*bottom")
|
||||
)
|
||||
gaps_label.setFixedWidth(60)
|
||||
gaps_label.setMinimumWidth(60)
|
||||
|
||||
self.gaps = FCComboBox()
|
||||
gaps_items = ['LR', 'TB', '4', '2LR', '2TB', '8']
|
||||
|
@ -232,7 +232,7 @@ class CutOut(FlatCAMTool):
|
|||
self.man_object_label.setToolTip(
|
||||
_("Geometry object used to create the manual cutout.")
|
||||
)
|
||||
self.man_object_label.setFixedWidth(60)
|
||||
self.man_object_label.setMinimumWidth(60)
|
||||
# e_lab_0 = QtWidgets.QLabel('')
|
||||
|
||||
form_layout_3.addRow(self.man_object_label, self.man_object_combo)
|
||||
|
|
|
@ -55,7 +55,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
"the specified axis. Does not create a new \n"
|
||||
"object, but modifies it.")
|
||||
)
|
||||
self.mirror_gerber_button.setFixedWidth(60)
|
||||
self.mirror_gerber_button.setMinimumWidth(60)
|
||||
|
||||
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
||||
grid_lay.addWidget(self.botlay_label, 0, 0)
|
||||
|
@ -79,7 +79,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
"the specified axis. Does not create a new \n"
|
||||
"object, but modifies it.")
|
||||
)
|
||||
self.mirror_exc_button.setFixedWidth(60)
|
||||
self.mirror_exc_button.setMinimumWidth(60)
|
||||
|
||||
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
||||
grid_lay.addWidget(self.excobj_label, 2, 0)
|
||||
|
@ -103,7 +103,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
"the specified axis. Does not create a new \n"
|
||||
"object, but modifies it.")
|
||||
)
|
||||
self.mirror_geo_button.setFixedWidth(60)
|
||||
self.mirror_geo_button.setMinimumWidth(60)
|
||||
|
||||
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
||||
grid_lay.addWidget(self.geoobj_label, 4, 0)
|
||||
|
@ -164,15 +164,15 @@ class DblSidedTool(FlatCAMTool):
|
|||
"The (x, y) coordinates are captured by pressing SHIFT key\n"
|
||||
"and left mouse button click on canvas or you can enter the coords manually.")
|
||||
)
|
||||
self.add_point_button.setFixedWidth(60)
|
||||
self.add_point_button.setMinimumWidth(60)
|
||||
|
||||
grid_lay2.addWidget(self.pb_label, 10, 0)
|
||||
grid_lay2.addLayout(self.point_box_container, 11, 0)
|
||||
grid_lay2.addWidget(self.add_point_button, 11, 1)
|
||||
|
||||
self.point_entry = EvalEntry()
|
||||
|
||||
self.point_box_container.addWidget(self.point_entry)
|
||||
|
||||
self.box_combo = QtWidgets.QComboBox()
|
||||
self.box_combo.setModel(self.app.collection)
|
||||
self.box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||
|
@ -214,7 +214,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
"- press SHIFT key and left mouse clicking on canvas. Then RMB click in the field and click Paste.\n"
|
||||
"- by entering the coords manually in the format: (x1, y1), (x2, y2), ...")
|
||||
)
|
||||
self.add_drill_point_button.setFixedWidth(60)
|
||||
self.add_drill_point_button.setMinimumWidth(60)
|
||||
|
||||
grid_lay3.addWidget(self.alignment_holes, 0, 0)
|
||||
grid_lay3.addWidget(self.add_drill_point_button, 0, 1)
|
||||
|
@ -255,7 +255,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
self.reset_button.setToolTip(
|
||||
_("Resets all the fields.")
|
||||
)
|
||||
self.reset_button.setFixedWidth(60)
|
||||
self.reset_button.setMinimumWidth(60)
|
||||
hlay2.addWidget(self.reset_button)
|
||||
|
||||
self.layout.addStretch()
|
||||
|
|
|
@ -235,6 +235,51 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
self.ncc_rest_cb = FCCheckBox()
|
||||
grid3.addWidget(self.ncc_rest_cb, 6, 1)
|
||||
|
||||
# ## Reference
|
||||
self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
|
||||
{'label': _('Box'), 'value': 'box'}])
|
||||
self.reference_label = QtWidgets.QLabel(_("Reference:"))
|
||||
self.reference_label.setToolTip(
|
||||
_("- 'Itself': the non copper clearing extent\n"
|
||||
"is based on the object that is copper cleared.\n "
|
||||
"- 'Box': will do non copper clearing within the box\n"
|
||||
"specified by the object selected in the Ref. Object combobox.")
|
||||
)
|
||||
grid3.addWidget(self.reference_label, 7, 0)
|
||||
grid3.addWidget(self.reference_radio, 7, 1)
|
||||
|
||||
grid4 = QtWidgets.QGridLayout()
|
||||
self.tools_box.addLayout(grid4)
|
||||
|
||||
self.box_combo_type_label = QtWidgets.QLabel(_("Ref. Type:"))
|
||||
self.box_combo_type_label.setToolTip(
|
||||
_("The type of FlatCAM object to be used as non copper clearing reference.\n"
|
||||
"It can be Gerber, Excellon or Geometry.")
|
||||
)
|
||||
self.box_combo_type = QtWidgets.QComboBox()
|
||||
self.box_combo_type.addItem(_("Gerber Reference Box Object"))
|
||||
self.box_combo_type.addItem(_("Excellon Reference Box Object"))
|
||||
self.box_combo_type.addItem(_("Geometry Reference Box Object"))
|
||||
|
||||
grid4.addWidget(self.box_combo_type_label, 0, 0)
|
||||
grid4.addWidget(self.box_combo_type, 0, 1)
|
||||
|
||||
self.box_combo_label = QtWidgets.QLabel(_("Ref. Object:"))
|
||||
self.box_combo_label.setToolTip(
|
||||
_("The FlatCAM object to be used as non copper clearing reference.")
|
||||
)
|
||||
self.box_combo = QtWidgets.QComboBox()
|
||||
self.box_combo.setModel(self.app.collection)
|
||||
self.box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||
self.box_combo.setCurrentIndex(1)
|
||||
grid4.addWidget(self.box_combo_label, 1, 0)
|
||||
grid4.addWidget(self.box_combo, 1, 1)
|
||||
|
||||
self.box_combo.hide()
|
||||
self.box_combo_label.hide()
|
||||
self.box_combo_type.hide()
|
||||
self.box_combo_type_label.hide()
|
||||
|
||||
self.generate_ncc_button = QtWidgets.QPushButton(_('Generate Geometry'))
|
||||
self.generate_ncc_button.setToolTip(
|
||||
_("Create the Geometry Object\n"
|
||||
|
@ -251,6 +296,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
self.obj_name = ""
|
||||
self.ncc_obj = None
|
||||
|
||||
self.bound_obj_name = ""
|
||||
self.bound_obj = None
|
||||
|
||||
self.tools_box.addStretch()
|
||||
|
||||
self.addtool_btn.clicked.connect(self.on_tool_add)
|
||||
|
@ -258,6 +306,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
self.deltool_btn.clicked.connect(self.on_tool_delete)
|
||||
self.generate_ncc_button.clicked.connect(self.on_ncc)
|
||||
|
||||
self.box_combo_type.currentIndexChanged.connect(self.on_combo_box_type)
|
||||
self.reference_radio.group_toggle_fn = self.on_toggle_reference
|
||||
|
||||
def install(self, icon=None, separator=None, **kwargs):
|
||||
FlatCAMTool.install(self, icon, separator, shortcut='ALT+N', **kwargs)
|
||||
|
||||
|
@ -293,6 +344,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
self.ncc_connect_cb.set_value(self.app.defaults["tools_nccconnect"])
|
||||
self.ncc_contour_cb.set_value(self.app.defaults["tools_ncccontour"])
|
||||
self.ncc_rest_cb.set_value(self.app.defaults["tools_nccrest"])
|
||||
self.reference_radio.set_value(self.app.defaults["tools_nccref"])
|
||||
|
||||
self.tools_table.setupContextMenu()
|
||||
self.tools_table.addContextMenu(
|
||||
|
@ -365,8 +417,12 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
'solid_geometry': []
|
||||
}
|
||||
})
|
||||
|
||||
self.obj_name = ""
|
||||
self.ncc_obj = None
|
||||
self.bound_obj_name = ""
|
||||
self.bound_obj = None
|
||||
|
||||
self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"]
|
||||
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
|
||||
|
||||
|
@ -464,6 +520,23 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
def on_combo_box_type(self):
|
||||
obj_type = self.box_combo_type.currentIndex()
|
||||
self.box_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
|
||||
self.box_combo.setCurrentIndex(0)
|
||||
|
||||
def on_toggle_reference(self):
|
||||
if self.reference_radio.get_value() == "itself":
|
||||
self.box_combo.hide()
|
||||
self.box_combo_label.hide()
|
||||
self.box_combo_type.hide()
|
||||
self.box_combo_type_label.hide()
|
||||
else:
|
||||
self.box_combo.show()
|
||||
self.box_combo_label.show()
|
||||
self.box_combo_type.show()
|
||||
self.box_combo_type_label.show()
|
||||
|
||||
def on_tool_add(self, dia=None, muted=None):
|
||||
|
||||
self.ui_disconnect()
|
||||
|
@ -647,7 +720,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
margin = margin if margin else self.app.defaults["tools_nccmargin"]
|
||||
margin = margin if margin is not None else float(self.app.defaults["tools_nccmargin"])
|
||||
|
||||
connect = self.ncc_connect_cb.get_value()
|
||||
connect = connect if connect else self.app.defaults["tools_nccconnect"]
|
||||
|
@ -661,6 +734,23 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
pol_method = self.ncc_method_radio.get_value()
|
||||
pol_method = pol_method if pol_method else self.app.defaults["tools_nccmethod"]
|
||||
|
||||
if self.reference_radio.get_value() == 'itself':
|
||||
self.bound_obj_name = self.object_combo.currentText()
|
||||
# Get source object.
|
||||
try:
|
||||
self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name)
|
||||
except Exception as e:
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name)
|
||||
return "Could not retrieve object: %s" % self.obj_name
|
||||
else:
|
||||
self.bound_obj_name = self.box_combo.currentText()
|
||||
# Get source object.
|
||||
try:
|
||||
self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name)
|
||||
except Exception as e:
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name)
|
||||
return "Could not retrieve object: %s" % self.obj_name
|
||||
|
||||
self.obj_name = self.object_combo.currentText()
|
||||
# Get source object.
|
||||
try:
|
||||
|
@ -671,10 +761,15 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
# Prepare non-copper polygons
|
||||
try:
|
||||
bounding_box = self.ncc_obj.solid_geometry.envelope.buffer(distance=margin,
|
||||
join_style=base.JOIN_STYLE.mitre)
|
||||
except AttributeError:
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] No Gerber file available."))
|
||||
if not isinstance(self.bound_obj.solid_geometry, MultiPolygon):
|
||||
env_obj = cascaded_union(self.bound_obj.solid_geometry)
|
||||
env_obj = env_obj.convex_hull
|
||||
else:
|
||||
env_obj = self.bound_obj.solid_geometry.convex_hull
|
||||
bounding_box = env_obj.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
|
||||
except Exception as e:
|
||||
log.debug("NonCopperClear.on_ncc() --> %s" % str(e))
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] No object available."))
|
||||
return
|
||||
|
||||
# calculate the empty area by subtracting the solid_geometry from the object bounding box geometry
|
||||
|
@ -682,6 +777,10 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
if type(empty) is Polygon:
|
||||
empty = MultiPolygon([empty])
|
||||
|
||||
if empty.is_empty:
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Could not get the extent of the area to be non copper cleared."))
|
||||
return
|
||||
|
||||
# clear non copper using standard algorithm
|
||||
if clearing_method is False:
|
||||
self.clear_non_copper(
|
||||
|
|
|
@ -245,8 +245,8 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
# grid3 = QtWidgets.QGridLayout()
|
||||
self.selectmethod_combo = RadioSet([
|
||||
{"label": _("Single"), "value": "single"},
|
||||
{"label": _("All"), "value": "all"},
|
||||
# {"label": "Rectangle", "value": "rectangle"}
|
||||
{"label": _("Area"), "value": "area"},
|
||||
{"label": _("All"), "value": "all"}
|
||||
])
|
||||
grid3.addWidget(self.selectmethod_combo, 7, 1)
|
||||
|
||||
|
@ -269,6 +269,9 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
self.units = ''
|
||||
self.paint_tools = {}
|
||||
self.tooluid = 0
|
||||
self.first_click = False
|
||||
self.cursor_pos = None
|
||||
|
||||
# store here the default data for Geometry Data
|
||||
self.default_data = {}
|
||||
self.default_data.update({
|
||||
|
@ -353,6 +356,10 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
self.addtool_btn.setDisabled(True)
|
||||
self.deltool_btn.setDisabled(True)
|
||||
self.tools_table.setContextMenuPolicy(Qt.NoContextMenu)
|
||||
if self.selectmethod_combo.get_value() == 'area':
|
||||
# disable rest-machining for single polygon painting
|
||||
self.rest_cb.set_value(False)
|
||||
self.rest_cb.setDisabled(True)
|
||||
else:
|
||||
self.rest_cb.setDisabled(False)
|
||||
self.addtool_entry.setDisabled(False)
|
||||
|
@ -433,7 +440,6 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
self.tools_table.setContextMenuPolicy(Qt.NoContextMenu)
|
||||
|
||||
def build_ui(self):
|
||||
|
||||
try:
|
||||
# if connected, disconnect the signal from the slot on item_changed as it creates issues
|
||||
self.tools_table.itemChanged.disconnect()
|
||||
|
@ -787,7 +793,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
connect=connect,
|
||||
contour=contour)
|
||||
|
||||
if select_method == "single":
|
||||
elif select_method == "single":
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Click inside the desired polygon."))
|
||||
|
||||
# use the first tool in the tool table; get the diameter
|
||||
|
@ -815,6 +821,79 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
|
||||
self.app.plotcanvas.vis_connect('mouse_press', doit)
|
||||
|
||||
elif select_method == "area":
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Click the start point of the paint area."))
|
||||
|
||||
# use the first tool in the tool table; get the diameter
|
||||
tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
|
||||
|
||||
# To be called after clicking on the plot.
|
||||
def on_mouse_press(event):
|
||||
# do paint single only for left mouse clicks
|
||||
if event.button == 1:
|
||||
if not self.first_click:
|
||||
self.first_click = True
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Click the end point of the paint area."))
|
||||
|
||||
self.cursor_pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
||||
if self.app.grid_status():
|
||||
self.cursor_pos = self.app.geo_editor.snap(self.cursor_pos[0], self.cursor_pos[1])
|
||||
else:
|
||||
self.app.inform.emit(_("Done."))
|
||||
self.first_click = False
|
||||
self.app.delete_selection_shape()
|
||||
|
||||
curr_pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
||||
if self.app.grid_status():
|
||||
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
|
||||
|
||||
x0, y0 = self.cursor_pos[0], self.cursor_pos[1]
|
||||
x1, y1 = curr_pos[0], curr_pos[1]
|
||||
pt1 = (x0, y0)
|
||||
pt2 = (x1, y0)
|
||||
pt3 = (x1, y1)
|
||||
pt4 = (x0, y1)
|
||||
sel_rect = Polygon([pt1, pt2, pt3, pt4])
|
||||
|
||||
self.paint_poly_area(obj=self.paint_obj,
|
||||
sel_obj= sel_rect,
|
||||
outname=o_name,
|
||||
overlap=overlap,
|
||||
connect=connect,
|
||||
contour=contour)
|
||||
|
||||
self.app.plotcanvas.vis_disconnect('mouse_press', on_mouse_press)
|
||||
self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move)
|
||||
|
||||
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
|
||||
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
|
||||
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
||||
|
||||
# called on mouse move
|
||||
def on_mouse_move(event):
|
||||
curr_pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
||||
self.app.app_cursor.enabled = False
|
||||
|
||||
if self.app.grid_status():
|
||||
self.app.app_cursor.enabled = True
|
||||
# Update cursor
|
||||
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
|
||||
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
|
||||
symbol='++', edge_color='black', size=20)
|
||||
|
||||
if self.first_click:
|
||||
self.app.delete_selection_shape()
|
||||
self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
|
||||
coords=(curr_pos[0], curr_pos[1]),
|
||||
face_alpha=0.0)
|
||||
|
||||
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
|
||||
self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
|
||||
self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
||||
|
||||
self.app.plotcanvas.vis_connect('mouse_press', on_mouse_press)
|
||||
self.app.plotcanvas.vis_connect('mouse_move', on_mouse_move)
|
||||
|
||||
def paint_poly(self, obj, inside_pt, tooldia, overlap, outname=None, connect=True, contour=True):
|
||||
"""
|
||||
Paints a polygon selected by clicking on its interior.
|
||||
|
@ -1276,5 +1355,323 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
# Background
|
||||
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
||||
|
||||
def paint_poly_area(self, obj, sel_obj, overlap, outname=None, connect=True, contour=True):
|
||||
"""
|
||||
Paints all polygons in this object that are within the sel_obj object
|
||||
|
||||
:param obj: painted object
|
||||
:param sel_obj: paint only what is inside this object bounds
|
||||
:param overlap:
|
||||
:param outname:
|
||||
:param connect: Connect lines to avoid tool lifts.
|
||||
:param contour: Paint around the edges.
|
||||
:return:
|
||||
"""
|
||||
paint_method = self.paintmethod_combo.get_value()
|
||||
|
||||
try:
|
||||
paint_margin = float(self.paintmargin_entry.get_value())
|
||||
except ValueError:
|
||||
# try to convert comma to decimal point. if it's still not working error message and return
|
||||
try:
|
||||
paint_margin = float(self.paintmargin_entry.get_value().replace(',', '.'))
|
||||
except ValueError:
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||
"use a number."))
|
||||
return
|
||||
|
||||
proc = self.app.proc_container.new(_("Painting polygon..."))
|
||||
name = outname if outname else self.obj_name + "_paint"
|
||||
over = overlap
|
||||
conn = connect
|
||||
cont = contour
|
||||
|
||||
def recurse(geometry, reset=True):
|
||||
"""
|
||||
Creates a list of non-iterable linear geometry objects.
|
||||
Results are placed in self.flat_geometry
|
||||
|
||||
:param geometry: Shapely type or list or list of list of such.
|
||||
:param reset: Clears the contents of self.flat_geometry.
|
||||
"""
|
||||
|
||||
if geometry is None:
|
||||
return
|
||||
|
||||
if reset:
|
||||
self.flat_geometry = []
|
||||
|
||||
# ## If iterable, expand recursively.
|
||||
try:
|
||||
for geo in geometry:
|
||||
if geo is not None:
|
||||
recurse(geometry=geo, reset=False)
|
||||
|
||||
# ## Not iterable, do the actual indexing and add.
|
||||
except TypeError:
|
||||
if isinstance(geometry, LinearRing):
|
||||
g = Polygon(geometry)
|
||||
self.flat_geometry.append(g)
|
||||
else:
|
||||
self.flat_geometry.append(geometry)
|
||||
|
||||
return self.flat_geometry
|
||||
|
||||
# Initializes the new geometry object
|
||||
def gen_paintarea(geo_obj, app_obj):
|
||||
assert isinstance(geo_obj, FlatCAMGeometry), \
|
||||
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
|
||||
tool_dia = None
|
||||
|
||||
sorted_tools = []
|
||||
for row in range(self.tools_table.rowCount()):
|
||||
sorted_tools.append(float(self.tools_table.item(row, 1).text()))
|
||||
sorted_tools.sort(reverse=True)
|
||||
|
||||
geo_to_paint = []
|
||||
for poly in obj.solid_geometry:
|
||||
new_pol = poly.intersection(sel_obj)
|
||||
geo_to_paint.append(new_pol)
|
||||
|
||||
try:
|
||||
a, b, c, d = self.paint_bounds(geo_to_paint)
|
||||
geo_obj.options['xmin'] = a
|
||||
geo_obj.options['ymin'] = b
|
||||
geo_obj.options['xmax'] = c
|
||||
geo_obj.options['ymax'] = d
|
||||
except Exception as e:
|
||||
log.debug("ToolPaint.paint_poly.gen_paintarea() bounds error --> %s" % str(e))
|
||||
return
|
||||
|
||||
total_geometry = []
|
||||
current_uid = int(1)
|
||||
geo_obj.solid_geometry = []
|
||||
for tool_dia in sorted_tools:
|
||||
# find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry
|
||||
for k, v in self.paint_tools.items():
|
||||
if float('%.4f' % v['tooldia']) == float('%.4f' % tool_dia):
|
||||
current_uid = int(k)
|
||||
break
|
||||
|
||||
for geo in recurse(geo_to_paint):
|
||||
try:
|
||||
# Polygons are the only really paintable geometries, lines in theory have no area to be painted
|
||||
if not isinstance(geo, Polygon):
|
||||
continue
|
||||
poly_buf = geo.buffer(-paint_margin)
|
||||
|
||||
if paint_method == "seed":
|
||||
# Type(cp) == FlatCAMRTreeStorage | None
|
||||
cp = self.clear_polygon2(poly_buf,
|
||||
tooldia=tool_dia,
|
||||
steps_per_circle=self.app.defaults["geometry_circle_steps"],
|
||||
overlap=over,
|
||||
contour=cont,
|
||||
connect=conn)
|
||||
|
||||
elif paint_method == "lines":
|
||||
# Type(cp) == FlatCAMRTreeStorage | None
|
||||
cp = self.clear_polygon3(poly_buf,
|
||||
tooldia=tool_dia,
|
||||
steps_per_circle=self.app.defaults["geometry_circle_steps"],
|
||||
overlap=over,
|
||||
contour=cont,
|
||||
connect=conn)
|
||||
|
||||
else:
|
||||
# Type(cp) == FlatCAMRTreeStorage | None
|
||||
cp = self.clear_polygon(poly_buf,
|
||||
tooldia=tool_dia,
|
||||
steps_per_circle=self.app.defaults["geometry_circle_steps"],
|
||||
overlap=over,
|
||||
contour=cont,
|
||||
connect=conn)
|
||||
|
||||
if cp is not None:
|
||||
total_geometry += list(cp.get_objects())
|
||||
except Exception as e:
|
||||
log.debug("Could not Paint the polygons. %s" % str(e))
|
||||
self.app.inform.emit(
|
||||
_("[ERROR] Could not do Paint All. Try a different combination of parameters. "
|
||||
"Or a different Method of paint\n%s") % str(e))
|
||||
return
|
||||
|
||||
# add the solid_geometry to the current too in self.paint_tools dictionary and then reset the
|
||||
# temporary list that stored that solid_geometry
|
||||
self.paint_tools[current_uid]['solid_geometry'] = deepcopy(total_geometry)
|
||||
|
||||
self.paint_tools[current_uid]['data']['name'] = name
|
||||
total_geometry[:] = []
|
||||
|
||||
geo_obj.options["cnctooldia"] = str(tool_dia)
|
||||
# this turn on the FlatCAMCNCJob plot for multiple tools
|
||||
geo_obj.multigeo = True
|
||||
geo_obj.multitool = True
|
||||
geo_obj.tools.clear()
|
||||
geo_obj.tools = dict(self.paint_tools)
|
||||
|
||||
# test if at least one tool has solid_geometry. If no tool has solid_geometry we raise an Exception
|
||||
has_solid_geo = 0
|
||||
for tooluid in geo_obj.tools:
|
||||
if geo_obj.tools[tooluid]['solid_geometry']:
|
||||
has_solid_geo += 1
|
||||
if has_solid_geo == 0:
|
||||
self.app.inform.emit(_("[ERROR] There is no Painting Geometry in the file.\n"
|
||||
"Usually it means that the tool diameter is too big for the painted geometry.\n"
|
||||
"Change the painting parameters and try again."))
|
||||
return
|
||||
|
||||
# Experimental...
|
||||
# print("Indexing...", end=' ')
|
||||
# geo_obj.make_index()
|
||||
|
||||
self.app.inform.emit(_("[success] Paint All Done."))
|
||||
|
||||
# Initializes the new geometry object
|
||||
def gen_paintarea_rest_machining(geo_obj, app_obj):
|
||||
assert isinstance(geo_obj, FlatCAMGeometry), \
|
||||
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
|
||||
|
||||
tool_dia = None
|
||||
sorted_tools = []
|
||||
for row in range(self.tools_table.rowCount()):
|
||||
sorted_tools.append(float(self.tools_table.item(row, 1).text()))
|
||||
sorted_tools.sort(reverse=True)
|
||||
|
||||
cleared_geo = []
|
||||
current_uid = int(1)
|
||||
geo_obj.solid_geometry = []
|
||||
|
||||
try:
|
||||
a, b, c, d = obj.bounds()
|
||||
geo_obj.options['xmin'] = a
|
||||
geo_obj.options['ymin'] = b
|
||||
geo_obj.options['xmax'] = c
|
||||
geo_obj.options['ymax'] = d
|
||||
except Exception as e:
|
||||
log.debug("ToolPaint.paint_poly.gen_paintarea() bounds error --> %s" % str(e))
|
||||
return
|
||||
|
||||
for tool_dia in sorted_tools:
|
||||
for geo in recurse(obj.solid_geometry):
|
||||
try:
|
||||
geo = Polygon(geo) if not isinstance(geo, Polygon) else geo
|
||||
poly_buf = geo.buffer(-paint_margin)
|
||||
cp = None
|
||||
|
||||
if paint_method == "standard":
|
||||
# Type(cp) == FlatCAMRTreeStorage | None
|
||||
cp = self.clear_polygon(poly_buf, tooldia=tool_dia,
|
||||
steps_per_circle=self.app.defaults["geometry_circle_steps"],
|
||||
overlap=over, contour=cont, connect=conn)
|
||||
|
||||
elif paint_method == "seed":
|
||||
# Type(cp) == FlatCAMRTreeStorage | None
|
||||
cp = self.clear_polygon2(poly_buf, tooldia=tool_dia,
|
||||
steps_per_circle=self.app.defaults["geometry_circle_steps"],
|
||||
overlap=over, contour=cont, connect=conn)
|
||||
|
||||
elif paint_method == "lines":
|
||||
# Type(cp) == FlatCAMRTreeStorage | None
|
||||
cp = self.clear_polygon3(poly_buf, tooldia=tool_dia,
|
||||
steps_per_circle=self.app.defaults["geometry_circle_steps"],
|
||||
overlap=over, contour=cont, connect=conn)
|
||||
|
||||
if cp is not None:
|
||||
cleared_geo += list(cp.get_objects())
|
||||
|
||||
except Exception as e:
|
||||
log.debug("Could not Paint the polygons. %s" % str(e))
|
||||
self.app.inform.emit(
|
||||
_("[ERROR] Could not do Paint All. Try a different combination of parameters. "
|
||||
"Or a different Method of paint\n%s") % str(e))
|
||||
return
|
||||
|
||||
# find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry
|
||||
for k, v in self.paint_tools.items():
|
||||
if float('%.4f' % v['tooldia']) == float('%.4f' % tool_dia):
|
||||
current_uid = int(k)
|
||||
break
|
||||
|
||||
# add the solid_geometry to the current too in self.paint_tools dictionary and then reset the
|
||||
# temporary list that stored that solid_geometry
|
||||
self.paint_tools[current_uid]['solid_geometry'] = deepcopy(cleared_geo)
|
||||
|
||||
self.paint_tools[current_uid]['data']['name'] = name
|
||||
cleared_geo[:] = []
|
||||
|
||||
geo_obj.options["cnctooldia"] = str(tool_dia)
|
||||
# this turn on the FlatCAMCNCJob plot for multiple tools
|
||||
geo_obj.multigeo = True
|
||||
geo_obj.multitool = True
|
||||
geo_obj.tools.clear()
|
||||
geo_obj.tools = dict(self.paint_tools)
|
||||
|
||||
# test if at least one tool has solid_geometry. If no tool has solid_geometry we raise an Exception
|
||||
has_solid_geo = 0
|
||||
for tooluid in geo_obj.tools:
|
||||
if geo_obj.tools[tooluid]['solid_geometry']:
|
||||
has_solid_geo += 1
|
||||
if has_solid_geo == 0:
|
||||
self.app.inform.emit(_("[ERROR_NOTCL] There is no Painting Geometry in the file.\n"
|
||||
"Usually it means that the tool diameter is too big for the painted geometry.\n"
|
||||
"Change the painting parameters and try again."))
|
||||
return
|
||||
|
||||
# Experimental...
|
||||
# print("Indexing...", end=' ')
|
||||
# geo_obj.make_index()
|
||||
|
||||
self.app.inform.emit(_("[success] Paint All with Rest-Machining done."))
|
||||
|
||||
def job_thread(app_obj):
|
||||
try:
|
||||
if self.rest_cb.isChecked():
|
||||
app_obj.new_object("geometry", name, gen_paintarea_rest_machining)
|
||||
else:
|
||||
app_obj.new_object("geometry", name, gen_paintarea)
|
||||
except Exception as e:
|
||||
proc.done()
|
||||
traceback.print_stack()
|
||||
return
|
||||
proc.done()
|
||||
# focus on Selected Tab
|
||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
||||
|
||||
self.app.inform.emit(_("Polygon Paint started ..."))
|
||||
|
||||
# Promise object with the new name
|
||||
self.app.collection.promise(name)
|
||||
|
||||
# Background
|
||||
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
||||
|
||||
@staticmethod
|
||||
def paint_bounds(geometry):
|
||||
def bounds_rec(o):
|
||||
if type(o) is list:
|
||||
minx = Inf
|
||||
miny = Inf
|
||||
maxx = -Inf
|
||||
maxy = -Inf
|
||||
|
||||
for k in o:
|
||||
try:
|
||||
minx_, miny_, maxx_, maxy_ = bounds_rec(k)
|
||||
except Exception as e:
|
||||
log.debug("ToolPaint.bounds() --> %s" % str(e))
|
||||
return
|
||||
|
||||
minx = min(minx, minx_)
|
||||
miny = min(miny, miny_)
|
||||
maxx = max(maxx, maxx_)
|
||||
maxy = max(maxy, maxy_)
|
||||
return minx, miny, maxx, maxy
|
||||
else:
|
||||
# it's a Shapely object, return it's bounds
|
||||
return o.bounds
|
||||
|
||||
return bounds_rec(geometry)
|
||||
|
||||
def reset_fields(self):
|
||||
self.object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
|
||||
|
|
|
@ -1396,6 +1396,10 @@ class SolderPaste(FlatCAMTool):
|
|||
except FileNotFoundError:
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] No such file or directory"))
|
||||
return
|
||||
except PermissionError:
|
||||
self.app.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return 'fail'
|
||||
|
||||
if self.app.defaults["global_open_style"] is False:
|
||||
self.app.file_opened.emit("gcode", filename)
|
||||
|
|
|
@ -44,16 +44,16 @@ class ToolTransform(FlatCAMTool):
|
|||
self.transform_lay.addWidget(title_label)
|
||||
|
||||
self.empty_label = QtWidgets.QLabel("")
|
||||
self.empty_label.setFixedWidth(70)
|
||||
self.empty_label.setMinimumWidth(70)
|
||||
|
||||
self.empty_label1 = QtWidgets.QLabel("")
|
||||
self.empty_label1.setFixedWidth(70)
|
||||
self.empty_label1.setMinimumWidth(70)
|
||||
self.empty_label2 = QtWidgets.QLabel("")
|
||||
self.empty_label2.setFixedWidth(70)
|
||||
self.empty_label2.setMinimumWidth(70)
|
||||
self.empty_label3 = QtWidgets.QLabel("")
|
||||
self.empty_label3.setFixedWidth(70)
|
||||
self.empty_label3.setMinimumWidth(70)
|
||||
self.empty_label4 = QtWidgets.QLabel("")
|
||||
self.empty_label4.setFixedWidth(70)
|
||||
self.empty_label4.setMinimumWidth(70)
|
||||
self.transform_lay.addWidget(self.empty_label)
|
||||
|
||||
# ## Rotate Title
|
||||
|
@ -72,7 +72,7 @@ class ToolTransform(FlatCAMTool):
|
|||
"Positive numbers for CW motion.\n"
|
||||
"Negative numbers for CCW motion.")
|
||||
)
|
||||
self.rotate_label.setFixedWidth(70)
|
||||
self.rotate_label.setMinimumWidth(70)
|
||||
|
||||
self.rotate_entry = FCEntry()
|
||||
# self.rotate_entry.setFixedWidth(70)
|
||||
|
@ -85,7 +85,7 @@ class ToolTransform(FlatCAMTool):
|
|||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected objects.")
|
||||
)
|
||||
self.rotate_button.setFixedWidth(90)
|
||||
self.rotate_button.setMinimumWidth(90)
|
||||
|
||||
form_child.addWidget(self.rotate_entry)
|
||||
form_child.addWidget(self.rotate_button)
|
||||
|
@ -109,7 +109,7 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Angle for Skew action, in degrees.\n"
|
||||
"Float number between -360 and 359.")
|
||||
)
|
||||
self.skewx_label.setFixedWidth(70)
|
||||
self.skewx_label.setMinimumWidth(70)
|
||||
self.skewx_entry = FCEntry()
|
||||
self.skewx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.skewx_entry.setFixedWidth(70)
|
||||
|
@ -120,14 +120,14 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Skew/shear the selected object(s).\n"
|
||||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected objects."))
|
||||
self.skewx_button.setFixedWidth(90)
|
||||
self.skewx_button.setMinimumWidth(90)
|
||||
|
||||
self.skewy_label = QtWidgets.QLabel(_("Angle Y:"))
|
||||
self.skewy_label.setToolTip(
|
||||
_("Angle for Skew action, in degrees.\n"
|
||||
"Float number between -360 and 359.")
|
||||
)
|
||||
self.skewy_label.setFixedWidth(70)
|
||||
self.skewy_label.setMinimumWidth(70)
|
||||
self.skewy_entry = FCEntry()
|
||||
self.skewy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.skewy_entry.setFixedWidth(70)
|
||||
|
@ -138,7 +138,7 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Skew/shear the selected object(s).\n"
|
||||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected objects."))
|
||||
self.skewy_button.setFixedWidth(90)
|
||||
self.skewy_button.setMinimumWidth(90)
|
||||
|
||||
form1_child_1.addWidget(self.skewx_entry)
|
||||
form1_child_1.addWidget(self.skewx_button)
|
||||
|
@ -165,7 +165,7 @@ class ToolTransform(FlatCAMTool):
|
|||
self.scalex_label.setToolTip(
|
||||
_("Factor for Scale action over X axis.")
|
||||
)
|
||||
self.scalex_label.setFixedWidth(70)
|
||||
self.scalex_label.setMinimumWidth(70)
|
||||
self.scalex_entry = FCEntry()
|
||||
self.scalex_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.scalex_entry.setFixedWidth(70)
|
||||
|
@ -176,13 +176,13 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Scale the selected object(s).\n"
|
||||
"The point of reference depends on \n"
|
||||
"the Scale reference checkbox state."))
|
||||
self.scalex_button.setFixedWidth(90)
|
||||
self.scalex_button.setMinimumWidth(90)
|
||||
|
||||
self.scaley_label = QtWidgets.QLabel(_("Factor Y:"))
|
||||
self.scaley_label.setToolTip(
|
||||
_("Factor for Scale action over Y axis.")
|
||||
)
|
||||
self.scaley_label.setFixedWidth(70)
|
||||
self.scaley_label.setMinimumWidth(70)
|
||||
self.scaley_entry = FCEntry()
|
||||
self.scaley_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.scaley_entry.setFixedWidth(70)
|
||||
|
@ -193,7 +193,7 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Scale the selected object(s).\n"
|
||||
"The point of reference depends on \n"
|
||||
"the Scale reference checkbox state."))
|
||||
self.scaley_button.setFixedWidth(90)
|
||||
self.scaley_button.setMinimumWidth(90)
|
||||
|
||||
self.scale_link_cb = FCCheckBox()
|
||||
self.scale_link_cb.set_value(True)
|
||||
|
@ -201,7 +201,7 @@ class ToolTransform(FlatCAMTool):
|
|||
self.scale_link_cb.setToolTip(
|
||||
_("Scale the selected object(s)\n"
|
||||
"using the Scale Factor X for both axis."))
|
||||
self.scale_link_cb.setFixedWidth(70)
|
||||
self.scale_link_cb.setMinimumWidth(70)
|
||||
|
||||
self.scale_zero_ref_cb = FCCheckBox()
|
||||
self.scale_zero_ref_cb.set_value(True)
|
||||
|
@ -239,7 +239,7 @@ class ToolTransform(FlatCAMTool):
|
|||
self.offx_label.setToolTip(
|
||||
_("Value for Offset action on X axis.")
|
||||
)
|
||||
self.offx_label.setFixedWidth(70)
|
||||
self.offx_label.setMinimumWidth(70)
|
||||
self.offx_entry = FCEntry()
|
||||
self.offx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.offx_entry.setFixedWidth(70)
|
||||
|
@ -250,13 +250,13 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Offset the selected object(s).\n"
|
||||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected objects.\n"))
|
||||
self.offx_button.setFixedWidth(90)
|
||||
self.offx_button.setMinimumWidth(90)
|
||||
|
||||
self.offy_label = QtWidgets.QLabel(_("Value Y:"))
|
||||
self.offy_label.setToolTip(
|
||||
_("Value for Offset action on Y axis.")
|
||||
)
|
||||
self.offy_label.setFixedWidth(70)
|
||||
self.offy_label.setMinimumWidth(70)
|
||||
self.offy_entry = FCEntry()
|
||||
self.offy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.offy_entry.setFixedWidth(70)
|
||||
|
@ -267,7 +267,7 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Offset the selected object(s).\n"
|
||||
"The point of reference is the middle of\n"
|
||||
"the bounding box for all selected objects.\n"))
|
||||
self.offy_button.setFixedWidth(90)
|
||||
self.offy_button.setMinimumWidth(90)
|
||||
|
||||
form3_child_1.addWidget(self.offx_entry)
|
||||
form3_child_1.addWidget(self.offx_button)
|
||||
|
@ -297,7 +297,7 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Flip the selected object(s) over the X axis.\n"
|
||||
"Does not create a new object.\n ")
|
||||
)
|
||||
self.flipx_button.setFixedWidth(100)
|
||||
self.flipx_button.setMinimumWidth(100)
|
||||
|
||||
self.flipy_button = FCButton()
|
||||
self.flipy_button.set_value(_("Flip on Y"))
|
||||
|
@ -305,7 +305,7 @@ class ToolTransform(FlatCAMTool):
|
|||
_("Flip the selected object(s) over the X axis.\n"
|
||||
"Does not create a new object.\n ")
|
||||
)
|
||||
self.flipy_button.setFixedWidth(90)
|
||||
self.flipy_button.setMinimumWidth(90)
|
||||
|
||||
self.flip_ref_cb = FCCheckBox()
|
||||
self.flip_ref_cb.set_value(True)
|
||||
|
@ -320,7 +320,7 @@ class ToolTransform(FlatCAMTool):
|
|||
"Then click Add button to insert coordinates.\n"
|
||||
"Or enter the coords in format (x, y) in the\n"
|
||||
"Point Entry field and click Flip on X(Y)"))
|
||||
self.flip_ref_cb.setFixedWidth(70)
|
||||
self.flip_ref_cb.setMinimumWidth(70)
|
||||
|
||||
self.flip_ref_label = QtWidgets.QLabel(_("Point:"))
|
||||
self.flip_ref_label.setToolTip(
|
||||
|
@ -328,7 +328,7 @@ class ToolTransform(FlatCAMTool):
|
|||
"The 'x' in (x, y) will be used when using Flip on X and\n"
|
||||
"the 'y' in (x, y) will be used when using Flip on Y and")
|
||||
)
|
||||
self.flip_ref_label.setFixedWidth(70)
|
||||
self.flip_ref_label.setMinimumWidth(70)
|
||||
self.flip_ref_entry = EvalEntry2("(0, 0)")
|
||||
self.flip_ref_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
# self.flip_ref_entry.setFixedWidth(70)
|
||||
|
@ -339,7 +339,7 @@ class ToolTransform(FlatCAMTool):
|
|||
_("The point coordinates can be captured by\n"
|
||||
"left click on canvas together with pressing\n"
|
||||
"SHIFT key. Then click Add button to insert."))
|
||||
self.flip_ref_button.setFixedWidth(90)
|
||||
self.flip_ref_button.setMinimumWidth(90)
|
||||
|
||||
form4_child_hlay.addStretch()
|
||||
form4_child_hlay.addWidget(self.flipx_button)
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue