From 7607aad8d86fd203bcddb97038b0bfa14fa5ed9b Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sat, 2 Feb 2019 23:56:08 +0200 Subject: [PATCH] - added protection against entering float numbers with comma separator instead of decimal dot separator in key points of FlatCAM (not everywhere) - added a choice of plotting the kind of geometry for the CNC plot (all, travel and cut kind of geometries) in CNCJob Selected Tab --- FlatCAMApp.py | 5 +- FlatCAMEditor.py | 7 + FlatCAMObj.py | 122 ++++++++++++++++-- ObjectUI.py | 37 ++++-- README.md | 2 + camlib.py | 23 +++- flatcamTools/ToolCalculators.py | 81 +++++++++++- flatcamTools/{ToolCutout.py => ToolCutOut.py} | 74 ++++++++--- flatcamTools/ToolDblSided.py | 49 +++---- flatcamTools/ToolFilm.py | 16 ++- flatcamTools/ToolNonCopperClear.py | 52 +++++++- flatcamTools/ToolPaint.py | 65 ++++++++-- flatcamTools/ToolPanelize.py | 81 ++++++++++-- flatcamTools/ToolTransform.py | 83 +++++++++--- flatcamTools/__init__.py | 3 +- 15 files changed, 571 insertions(+), 129 deletions(-) rename flatcamTools/{ToolCutout.py => ToolCutOut.py} (86%) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 5fd31fc9..513cc92c 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -93,7 +93,7 @@ class App(QtCore.QObject): # Version version = 8.906 - version_date = "2019/02/2" + version_date = "2019/02/3" beta = True # URL for update checks and statistics @@ -1432,7 +1432,7 @@ class App(QtCore.QObject): self.move_tool.install(icon=QtGui.QIcon('share/move16.png'), pos=self.ui.menuedit, before=self.ui.menueditorigin) - self.cutout_tool = ToolCutout(self) + self.cutout_tool = ToolCutOut(self) self.cutout_tool.install(icon=QtGui.QIcon('share/cut16.png'), pos=self.ui.menutool, before=self.measurement_tool.menuAction) @@ -1558,6 +1558,7 @@ class App(QtCore.QObject): elif isinstance(edited_obj, FlatCAMExcellon): obj_type = "Excellon" self.exc_editor.update_fcexcellon(edited_obj) + self.exc_editor.update_options(edited_obj) self.exc_editor.deactivate() # update the exc object options so it is including the bounding box values diff --git a/FlatCAMEditor.py b/FlatCAMEditor.py index 0df5e937..8a3d41ed 100644 --- a/FlatCAMEditor.py +++ b/FlatCAMEditor.py @@ -4471,6 +4471,13 @@ class FlatCAMExcEditor(QtCore.QObject): # Switch notebook to Selected page self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab) + def update_options(self, obj): + if not obj.options: + obj.options = {} + return True + else: + return False + def new_edited_excellon(self, outname): """ Creates a new Excellon object for the edited Excellon. Thread-safe. diff --git a/FlatCAMObj.py b/FlatCAMObj.py index f1fe3a18..2bfa74ac 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -2291,7 +2291,18 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): for tooluid_key, tooluid_value in self.tools.items(): if int(tooluid_key) == tool_uid: - tooluid_value['offset_value'] = self.ui.tool_offset_entry.get_value() + try: + tooluid_value['offset_value'] = float(self.ui.tool_offset_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + tooluid_value['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.") + return def ui_connect(self): @@ -2408,10 +2419,23 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): last_data = None last_solid_geometry = [] + # if a Tool diameter entered is a char instead a number the final message of Tool adding is changed + # because the Default value for Tool is used. + change_message = False + if dia is not None: tooldia = dia else: - tooldia = self.ui.addtool_entry.get_value() + try: + tooldia = float(self.ui.addtool_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + tooldia = float(self.ui.addtool_entry.get_value().replace(',', '.')) + except ValueError: + change_message = True + tooldia = float(self.app.defaults["geometry_cnctooldia"]) + if tooldia is None: self.build_ui() self.app.inform.emit("[error_notcl] Please enter the desired tool diameter in Float format.") @@ -2486,7 +2510,11 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): pass self.ser_attrs.append('tools') - self.app.inform.emit("[success] Tool added in Tool Table.") + if change_message is False: + self.app.inform.emit("[success] Tool added in Tool Table.") + else: + change_message = False + self.app.inform.emit("[error_notcl]Default Tool added. Wrong value format entered.") self.build_ui() def on_tool_copy(self, all=None): @@ -2556,7 +2584,18 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): self.ui_disconnect() current_row = current_item.row() - tool_dia = float('%.4f' % float(self.ui.geo_tools_table.item(current_row, 1).text())) + try: + d = float(self.ui.geo_tools_table.item(current_row, 1).text()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + 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.") + return + + tool_dia = float('%.4f' % d) tooluid = int(self.ui.geo_tools_table.item(current_row, 5).text()) self.tools[tooluid]['tooldia'] = tool_dia @@ -2823,7 +2862,17 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): tool_type_item = self.ui.geo_tools_table.cellWidget(row, 4).currentText() tooluid_item = int(self.ui.geo_tools_table.item(row, 5).text()) - offset_value_item = self.ui.tool_offset_entry.get_value() + try: + offset_value_item = float(self.ui.tool_offset_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + 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.") + return # this new dict will hold the actual useful data, another dict that is the value of key 'data' temp_tools = {} @@ -2965,7 +3014,16 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): # test to see if we have tools available in the tool table if self.ui.geo_tools_table.selectedItems(): for x in self.ui.geo_tools_table.selectedItems(): - tooldia = float(self.ui.geo_tools_table.item(x.row(), 1).text()) + try: + tooldia = float(self.ui.geo_tools_table.item(x.row(), 1).text()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + 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.") + return tooluid = int(self.ui.geo_tools_table.item(x.row(), 5).text()) for tooluid_key, tooluid_value in self.tools.items(): @@ -3119,7 +3177,17 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): tool_offset = 0.0 else: offset_str = 'custom' - offset_value = self.ui.tool_offset_entry.get_value() + try: + offset_value = float(self.ui.tool_offset_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + 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.") + return if offset_value: tool_offset = float(offset_value) else: @@ -3296,7 +3364,17 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): tool_offset = 0.0 else: offset_str = 'custom' - offset_value = self.ui.tool_offset_entry.get_value() + try: + offset_value = float(self.ui.tool_offset_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + 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.") + return if offset_value: tool_offset = float(offset_value) else: @@ -3649,7 +3727,18 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): tool_dia_copy[dia_key] = dia_value # convert the value in the Custom Tool Offset entry in UI - custom_offset = self.ui.tool_offset_entry.get_value() + try: + custom_offset = float(self.ui.tool_offset_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + custom_offset = float(self.ui.tool_offset_entry.get_value().replace(',', '.') + ) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + if custom_offset: custom_offset *= factor self.ui.tool_offset_entry.set_value(custom_offset) @@ -3998,10 +4087,15 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): # Fill form fields only on object create self.to_form() + # set the kind of geometries are plotted by default with plot2() from camlib.CNCJob + self.ui.cncplot_method_combo.set_value('all') + self.ui.updateplot_button.clicked.connect(self.on_updateplot_button_click) self.ui.export_gcode_button.clicked.connect(self.on_exportgcode_button_click) self.ui.modify_gcode_button.clicked.connect(self.on_modifygcode_button_click) + self.ui.cncplot_method_combo.activated_custom.connect(self.on_plot_kind_change) + def ui_connect(self): for row in range(self.ui.cnc_tools_table.rowCount()): self.ui.cnc_tools_table.cellWidget(row, 6).clicked.connect(self.on_plot_cb_click_table) @@ -4024,6 +4118,10 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): self.read_form() self.plot() + def on_plot_kind_change(self): + kind = self.ui.cncplot_method_combo.get_value() + self.plot(kind=kind) + def on_exportgcode_button_click(self, *args): self.app.report_usage("cncjob_on_exportgcode_button") @@ -4280,7 +4378,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): self.ui_connect() - def plot(self, visible=None): + def plot(self, visible=None, kind='all'): # Does all the required setup and returns False # if the 'ptint' option is set to False. @@ -4291,13 +4389,13 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): try: if self.multitool is False: # single tool usage - self.plot2(tooldia=self.options["tooldia"], obj=self, visible=visible) + self.plot2(tooldia=self.options["tooldia"], obj=self, visible=visible, kind=kind) else: # multiple tools usage for tooluid_key in self.cnc_tools: tooldia = float('%.4f' % float(self.cnc_tools[tooluid_key]['tooldia'])) gcode_parsed = self.cnc_tools[tooluid_key]['gcode_parsed'] - self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed) + self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed, kind=kind) self.shapes.redraw() except (ObjectDeleted, AttributeError): self.shapes.clear(update=True) diff --git a/ObjectUI.py b/ObjectUI.py index d16bf157..eb53edcf 100644 --- a/ObjectUI.py +++ b/ObjectUI.py @@ -708,6 +708,8 @@ class GeometryObjectUI(ObjectUI): self.geo_tools_table.setColumnWidth(0, 20) self.geo_tools_table.setHorizontalHeaderLabels(['#', 'Dia', 'Offset', 'Type', 'TT', '', 'P']) self.geo_tools_table.setColumnHidden(5, True) + # stylesheet = "::section{Background-color:rgb(239,239,245)}" + # self.geo_tools_table.horizontalHeader().setStyleSheet(stylesheet) self.geo_tools_table.horizontalHeaderItem(0).setToolTip( "This is the Tool Number.\n" @@ -758,7 +760,7 @@ class GeometryObjectUI(ObjectUI): "cut and negative for 'inside' cut." ) self.grid1.addWidget(self.tool_offset_lbl, 0, 0) - self.tool_offset_entry = FloatEntry() + self.tool_offset_entry = FCEntry() spacer_lbl = QtWidgets.QLabel(" ") spacer_lbl.setFixedWidth(80) @@ -777,7 +779,7 @@ class GeometryObjectUI(ObjectUI): self.addtool_entry_lbl.setToolTip( "Diameter for the new tool" ) - self.addtool_entry = FloatEntry() + self.addtool_entry = FCEntry() # hlay.addWidget(self.addtool_label) # hlay.addStretch() @@ -1067,15 +1069,26 @@ class CNCObjectUI(ObjectUI): self.plot_options_label = QtWidgets.QLabel("Plot Options:") self.custom_box.addWidget(self.plot_options_label) - # # Tool dia for plot - # tdlabel = QtWidgets.QLabel('Tool dia:') - # tdlabel.setToolTip( - # "Diameter of the tool to be\n" - # "rendered in the plot." - # ) - # grid0.addWidget(tdlabel, 1, 0) - # self.tooldia_entry = LengthEntry() - # grid0.addWidget(self.tooldia_entry, 1, 1) + self.cncplot_method_label = QtWidgets.QLabel("Plot kind:") + self.cncplot_method_label.setToolTip( + "This selects the kind of geometries on the canvas to plot.\n" + "Those can be either of type 'Travel' which means the moves\n" + "above the work piece or it can be of type 'Cut',\n" + "which means the moves that cut into the material." + ) + + self.cncplot_method_combo = RadioSet([ + {"label": "All", "value": "all"}, + {"label": "Travel", "value": "travel"}, + {"label": "Cut", "value": "cut"} + ], stretch=False) + + f_lay = QtWidgets.QFormLayout() + self.custom_box.addLayout(f_lay) + f_lay.addRow(self.cncplot_method_label, self.cncplot_method_combo) + + e1_lbl = QtWidgets.QLabel('') + self.custom_box.addWidget(e1_lbl) hlay = QtWidgets.QHBoxLayout() self.custom_box.addLayout(hlay) @@ -1115,6 +1128,8 @@ class CNCObjectUI(ObjectUI): self.cnc_tools_table.setColumnWidth(0, 20) self.cnc_tools_table.setHorizontalHeaderLabels(['#', 'Dia', 'Offset', 'Type', 'TT', '', 'P']) self.cnc_tools_table.setColumnHidden(5, True) + # stylesheet = "::section{Background-color:rgb(239,239,245)}" + # self.cnc_tools_table.horizontalHeader().setStyleSheet(stylesheet) # Update plot button self.updateplot_button = QtWidgets.QPushButton('Update Plot') diff --git a/README.md b/README.md index 7731a7f9..876357ef 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ CAD program, and create G-Code for Isolation routing. - code cleanup in Tools - some GUI structure optimization's +- added protection against entering float numbers with comma separator instead of decimal dot separator in key points of FlatCAM (not everywhere) +- added a choice of plotting the kind of geometry for the CNC plot (all, travel and cut kind of geometries) in CNCJob Selected Tab 1.02.2019 diff --git a/camlib.py b/camlib.py index 3b2981a5..c05a4169 100644 --- a/camlib.py +++ b/camlib.py @@ -5527,7 +5527,7 @@ class CNCjob(Geometry): def plot2(self, tooldia=None, dpi=75, margin=0.1, gcode_parsed=None, color={"T": ["#F0E24D4C", "#B5AB3A4C"], "C": ["#5E6CFFFF", "#4650BDFF"]}, - alpha={"T": 0.3, "C": 1.0}, tool_tolerance=0.0005, obj=None, visible=False): + alpha={"T": 0.3, "C": 1.0}, tool_tolerance=0.0005, obj=None, visible=False, kind='all'): """ Plots the G-code job onto the given axes. @@ -5548,7 +5548,15 @@ class CNCjob(Geometry): if tooldia == 0: for geo in gcode_parsed: - obj.add_shape(shape=geo['geom'], color=color[geo['kind'][0]][1], visible=visible) + if kind == 'all': + obj.add_shape(shape=geo['geom'], color=color[geo['kind'][0]][1], visible=visible) + elif kind == 'travel': + if geo['kind'][0] == 'T': + obj.add_shape(shape=geo['geom'], color=color['T'][1], visible=visible) + elif kind == 'cut': + if geo['kind'][0] == 'C': + obj.add_shape(shape=geo['geom'], color=color['C'][1], visible=visible) + else: text = [] pos = [] @@ -5559,8 +5567,17 @@ class CNCjob(Geometry): pos.append(geo['geom'].coords[0]) poly = geo['geom'].buffer(tooldia / 2.0).simplify(tool_tolerance) - obj.add_shape(shape=poly, color=color[geo['kind'][0]][1], face_color=color[geo['kind'][0]][0], + 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) + elif kind == 'travel': + if geo['kind'][0] == 'T': + obj.add_shape(shape=poly, color=color['T'][1], face_color=color['T'][0], + visible=visible, layer=2) + elif kind == 'cut': + if geo['kind'][0] == 'C': + obj.add_shape(shape=poly, color=color['C'][1], face_color=color['C'][0], + visible=visible, layer=1) obj.annotation.set(text=text, pos=pos, visible=obj.options['plot']) diff --git a/flatcamTools/ToolCalculators.py b/flatcamTools/ToolCalculators.py index 6923fb51..3f74a248 100644 --- a/flatcamTools/ToolCalculators.py +++ b/flatcamTools/ToolCalculators.py @@ -255,10 +255,37 @@ class ToolCalculator(FlatCAMTool): try: tip_diameter = float(self.tipDia_entry.get_value()) - half_tip_angle = float(self.tipAngle_entry.get_value()) / 2 + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + tip_diameter = float(self.tipDia_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + + try: + half_tip_angle = float(self.tipAngle_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + half_tip_angle = float(self.tipAngle_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + half_tip_angle /= 2 + + try: cut_depth = float(self.cutDepth_entry.get_value()) - except: - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + cut_depth = float(self.cutDepth_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return tool_diameter = tip_diameter + (2 * cut_depth * math.tan(math.radians(half_tip_angle))) self.effectiveToolDia_entry.set_value("%.4f" % tool_diameter) @@ -270,10 +297,50 @@ class ToolCalculator(FlatCAMTool): self.mm_entry.set_value('%.6f' % (float(self.inch_entry.get_value()) * 25.4)) def on_calculate_eplate(self): - length = float(self.pcblength_entry.get_value()) - width = float(self.pcbwidth_entry.get_value()) - density = float(self.cdensity_entry.get_value()) - copper = float(self.growth_entry.get_value()) + + try: + length = float(self.pcblength_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + length = float(self.pcblength_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + + try: + width = float(self.pcbwidth_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + width = float(self.pcbwidth_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + + try: + density = float(self.cdensity_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + density = float(self.cdensity_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + + try: + copper = float(self.growth_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + copper = float(self.growth_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return calculated_current = (length * width * density) * 0.0021527820833419 calculated_time = copper * 2.142857142857143 * float(20 / density) diff --git a/flatcamTools/ToolCutout.py b/flatcamTools/ToolCutOut.py similarity index 86% rename from flatcamTools/ToolCutout.py rename to flatcamTools/ToolCutOut.py index 9ad71bb3..7a796bff 100644 --- a/flatcamTools/ToolCutout.py +++ b/flatcamTools/ToolCutOut.py @@ -8,7 +8,7 @@ from GUIElements import IntEntry, RadioSet, LengthEntry from FlatCAMObj import FlatCAMGeometry, FlatCAMExcellon, FlatCAMGerber -class ToolCutout(FlatCAMTool): +class ToolCutOut(FlatCAMTool): toolName = "Cutout PCB" @@ -228,19 +228,37 @@ class ToolCutout(FlatCAMTool): try: dia = float(self.dia.get_value()) - except TypeError: - self.app.inform.emit("[warning_notcl] Tool diameter value is missing. Add it and retry.") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + dia = float(self.dia.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[warning_notcl] Tool diameter value is missing or wrong format. " + "Add it and retry.") + return + try: margin = float(self.margin.get_value()) - except TypeError: - self.app.inform.emit("[warning_notcl] Margin value is missing. Add it and retry.") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + margin = float(self.margin.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[warning_notcl] Margin value is missing or wrong format. " + "Add it and retry.") + return + try: gapsize = float(self.gapsize.get_value()) - except TypeError: - self.app.inform.emit("[warning_notcl] Gap size value is missing. Add it and retry.") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + gapsize = float(self.gapsize.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[warning_notcl] Gap size value is missing or wrong format. " + "Add it and retry.") + return + try: gaps = self.gaps.get_value() except TypeError: @@ -349,19 +367,37 @@ class ToolCutout(FlatCAMTool): try: dia = float(self.dia.get_value()) - except TypeError: - self.app.inform.emit("[warning_notcl] Tool diameter value is missing. Add it and retry.") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + dia = float(self.dia.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[warning_notcl] Tool diameter value is missing or wrong format. " + "Add it and retry.") + return + try: margin = float(self.margin.get_value()) - except TypeError: - self.app.inform.emit("[warning_notcl] Margin value is missing. Add it and retry.") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + margin = float(self.margin.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[warning_notcl] Margin value is missing or wrong format. " + "Add it and retry.") + return + try: gapsize = float(self.gapsize.get_value()) - except TypeError: - self.app.inform.emit("[warning_notcl] Gap size value is missing. Add it and retry.") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + gapsize = float(self.gapsize.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[warning_notcl] Gap size value is missing or wrong format. " + "Add it and retry.") + return + try: gaps = self.gaps_rect_radio.get_value() except TypeError: diff --git a/flatcamTools/ToolDblSided.py b/flatcamTools/ToolDblSided.py index 9538dbf6..9105e166 100644 --- a/flatcamTools/ToolDblSided.py +++ b/flatcamTools/ToolDblSided.py @@ -6,6 +6,7 @@ from shapely.geometry import Point from shapely import affinity from PyQt5 import QtCore + class DblSidedTool(FlatCAMTool): toolName = "2-Sided PCB" @@ -113,8 +114,8 @@ class DblSidedTool(FlatCAMTool): self.axloc_label = QtWidgets.QLabel("Axis Ref:") self.axloc_label.setToolTip( "The axis should pass through a point or cut\n " - "a specified box (in a Geometry object) in \n" - "the middle." + "a specified box (in a FlatCAM object) through \n" + "the center." ) # grid_lay.addRow("Axis Location:", self.axis_location) grid_lay.addWidget(self.axloc_label, 8, 0) @@ -127,19 +128,18 @@ class DblSidedTool(FlatCAMTool): self.point_box_container = QtWidgets.QVBoxLayout() self.pb_label = QtWidgets.QLabel("Point/Box:") self.pb_label.setToolTip( - "Specify the point (x, y) through which the mirror axis \n " - "passes or the Geometry object containing a rectangle \n" - "that the mirror axis cuts in half." + "If 'Point' is selected above it store the coordinates (x, y) through which\n" + "the mirroring axis passes.\n" + "If 'Box' is selected above, select here a FlatCAM object (Gerber, Exc or Geo).\n" + "Through the center of this object pass the mirroring axis selected above." ) - # grid_lay.addRow("Point/Box:", self.point_box_container) self.add_point_button = QtWidgets.QPushButton("Add") self.add_point_button.setToolTip( - "Add the point (x, y) through which the mirror axis \n " - "passes or the Object containing a rectangle \n" - "that the mirror axis cuts in half.\n" - "The point is captured by pressing SHIFT key\n" - "and left mouse clicking on canvas or you can enter them manually." + "Add the coordinates in format (x, y) through which the mirroring axis \n " + "selected in 'MIRROR AXIS' pass.\n" + "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(40) @@ -171,9 +171,9 @@ class DblSidedTool(FlatCAMTool): self.ah_label.setToolTip( "Alignment holes (x1, y1), (x2, y2), ... " "on one side of the mirror axis. For each set of (x, y) coordinates\n" - "entered here, a pair of drills will be created: one on the\n" - "coordinates entered and one in mirror position over the axis\n" - "selected above in the 'Mirror Axis'." + "entered here, a pair of drills will be created:\n\n" + "- one drill at the coordinates from the field\n" + "- one drill in mirror position over the axis selected above in the 'Mirror Axis'." ) self.layout.addWidget(self.ah_label) @@ -184,10 +184,13 @@ class DblSidedTool(FlatCAMTool): self.add_drill_point_button = QtWidgets.QPushButton("Add") self.add_drill_point_button.setToolTip( - "Add alignment drill holes coords (x1, y1), (x2, y2), ... \n" - "on one side of the mirror axis.\n" - "The point(s) can be captured by pressing SHIFT key\n" - "and left mouse clicking on canvas. Or you can enter them manually." + "Add alignment drill holes coords in the format: (x1, y1), (x2, y2), ... \n" + "on one side of the mirror axis.\n\n" + "The coordinates set can be obtained:\n" + "- press SHIFT key and left mouse clicking on canvas. Then click Add.\n" + "- press SHIFT key and left mouse clicking on canvas. Then CTRL+V in the field.\n" + "- 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(40) @@ -195,11 +198,10 @@ class DblSidedTool(FlatCAMTool): grid_lay1.addWidget(self.add_drill_point_button, 0, 3) ## Drill diameter for alignment holes - self.dt_label = QtWidgets.QLabel("Alignment Drill Creation:") + self.dt_label = QtWidgets.QLabel("Alignment Drill Diameter:") self.dt_label.setToolTip( - "Create a set of alignment drill holes\n" - "with the specified diameter,\n" - "at the specified coordinates." + "Diameter of the drill for the " + "alignment holes." ) self.layout.addWidget(self.dt_label) @@ -295,6 +297,9 @@ class DblSidedTool(FlatCAMTool): xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis] dia = self.drill_dia.get_value() + if dia is None: + self.app.inform.emit("[warning_notcl]No value or wrong format in Drill Dia entry. Add it and retry.") + return tools = {"1": {"C": dia}} # holes = self.alignment_holes.get_value() diff --git a/flatcamTools/ToolFilm.py b/flatcamTools/ToolFilm.py index 358083b0..e710a0cc 100644 --- a/flatcamTools/ToolFilm.py +++ b/flatcamTools/ToolFilm.py @@ -1,6 +1,6 @@ from FlatCAMTool import FlatCAMTool -from GUIElements import RadioSet, FloatEntry +from GUIElements import RadioSet, FCEntry from PyQt5 import QtGui, QtCore, QtWidgets @@ -99,7 +99,7 @@ class Film(FlatCAMTool): # Boundary for negative film generation - self.boundary_entry = FloatEntry() + self.boundary_entry = FCEntry() self.boundary_label = QtWidgets.QLabel("Border:") self.boundary_label.setToolTip( "Specify a border around the object.\n" @@ -172,7 +172,17 @@ class Film(FlatCAMTool): self.app.inform.emit("[error_notcl] No Box object selected. Load a Box object and retry.") return - border = float(self.boundary_entry.get_value()) + try: + border = float(self.boundary_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + border = float(self.boundary_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + if border is None: border = 0 diff --git a/flatcamTools/ToolNonCopperClear.py b/flatcamTools/ToolNonCopperClear.py index f23f8a2d..d857dc04 100644 --- a/flatcamTools/ToolNonCopperClear.py +++ b/flatcamTools/ToolNonCopperClear.py @@ -96,7 +96,7 @@ class NonCopperClear(FlatCAMTool, Gerber): self.addtool_entry_lbl.setToolTip( "Diameter for the new tool to add in the Tool Table" ) - self.addtool_entry = FloatEntry() + self.addtool_entry = FCEntry() # hlay.addWidget(self.addtool_label) # hlay.addStretch() @@ -150,7 +150,7 @@ class NonCopperClear(FlatCAMTool, Gerber): "due of too many paths." ) grid3.addWidget(nccoverlabel, 1, 0) - self.ncc_overlap_entry = FloatEntry() + self.ncc_overlap_entry = FCEntry() grid3.addWidget(self.ncc_overlap_entry, 1, 1) nccmarginlabel = QtWidgets.QLabel('Margin:') @@ -158,7 +158,7 @@ class NonCopperClear(FlatCAMTool, Gerber): "Bounding box margin." ) grid3.addWidget(nccmarginlabel, 2, 0) - self.ncc_margin_entry = FloatEntry() + self.ncc_margin_entry = FCEntry() grid3.addWidget(self.ncc_margin_entry, 2, 1) # Method @@ -430,7 +430,16 @@ class NonCopperClear(FlatCAMTool, Gerber): if dia: tool_dia = dia else: - tool_dia = self.addtool_entry.get_value() + try: + tool_dia = float(self.addtool_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + tool_dia = float(self.addtool_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return if tool_dia is None: self.build_ui() self.app.inform.emit("[warning_notcl] Please enter a tool diameter to add, in Float format.") @@ -487,7 +496,18 @@ class NonCopperClear(FlatCAMTool, Gerber): tool_dias.append(float('%.4f' % v[tool_v])) for row in range(self.tools_table.rowCount()): - new_tool_dia = float(self.tools_table.item(row, 1).text()) + + try: + new_tool_dia = float(self.tools_table.item(row, 1).text()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + tooluid = int(self.tools_table.item(row, 3).text()) # identify the tool that was edited and get it's tooluid @@ -553,10 +573,28 @@ class NonCopperClear(FlatCAMTool, Gerber): def on_ncc(self): - over = self.ncc_overlap_entry.get_value() + try: + over = float(self.ncc_overlap_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + over = float(self.ncc_overlap_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return over = over if over else self.app.defaults["tools_nccoverlap"] - margin = self.ncc_margin_entry.get_value() + try: + margin = float(self.ncc_margin_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + margin = float(self.ncc_margin_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return margin = margin if margin else self.app.defaults["tools_nccmargin"] connect = self.ncc_connect_cb.get_value() diff --git a/flatcamTools/ToolPaint.py b/flatcamTools/ToolPaint.py index fca21e4f..5f6009d1 100644 --- a/flatcamTools/ToolPaint.py +++ b/flatcamTools/ToolPaint.py @@ -93,7 +93,7 @@ class ToolPaint(FlatCAMTool, Gerber): self.addtool_entry_lbl.setToolTip( "Diameter for the new tool." ) - self.addtool_entry = FloatEntry() + self.addtool_entry = FCEntry() # hlay.addWidget(self.addtool_label) # hlay.addStretch() @@ -145,7 +145,7 @@ class ToolPaint(FlatCAMTool, Gerber): "due of too many paths." ) grid3.addWidget(ovlabel, 1, 0) - self.paintoverlap_entry = LengthEntry() + self.paintoverlap_entry = FCEntry() grid3.addWidget(self.paintoverlap_entry, 1, 1) # Margin @@ -156,7 +156,7 @@ class ToolPaint(FlatCAMTool, Gerber): "be painted." ) grid3.addWidget(marginlabel, 2, 0) - self.paintmargin_entry = LengthEntry() + self.paintmargin_entry = FCEntry() grid3.addWidget(self.paintmargin_entry, 2, 1) # Method @@ -486,7 +486,17 @@ class ToolPaint(FlatCAMTool, Gerber): if dia: tool_dia = dia else: - tool_dia = self.addtool_entry.get_value() + try: + tool_dia = float(self.addtool_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + tool_dia = float(self.addtool_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + if tool_dia is None: self.build_ui() self.app.inform.emit("[warning_notcl] Please enter a tool diameter to add, in Float format.") @@ -546,7 +556,16 @@ class ToolPaint(FlatCAMTool, Gerber): tool_dias.append(float('%.4f' % v[tool_v])) for row in range(self.tools_table.rowCount()): - new_tool_dia = float(self.tools_table.item(row, 1).text()) + try: + new_tool_dia = float(self.tools_table.item(row, 1).text()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return tooluid = int(self.tools_table.item(row, 3).text()) # identify the tool that was edited and get it's tooluid @@ -672,8 +691,17 @@ class ToolPaint(FlatCAMTool, Gerber): self.app.report_usage("geometry_on_paint_button") self.app.inform.emit("[warning_notcl]Click inside the desired polygon.") + try: + overlap = float(self.paintoverlap_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + overlap = float(self.paintoverlap_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return - overlap = self.paintoverlap_entry.get_value() connect = self.pathconnect_cb.get_value() contour = self.paintcontour_cb.get_value() select_method = self.selectmethod_combo.get_value() @@ -744,7 +772,17 @@ class ToolPaint(FlatCAMTool, Gerber): # poly = find_polygon(self.solid_geometry, inside_pt) poly = obj.find_polygon(inside_pt) paint_method = self.paintmethod_combo.get_value() - paint_margin = self.paintmargin_entry.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 # No polygon? if poly is None: @@ -878,10 +916,19 @@ class ToolPaint(FlatCAMTool, Gerber): :return: """ paint_method = self.paintmethod_combo.get_value() - paint_margin = self.paintmargin_entry.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 diff --git a/flatcamTools/ToolPanelize.py b/flatcamTools/ToolPanelize.py index a37d75bf..6dafc90f 100644 --- a/flatcamTools/ToolPanelize.py +++ b/flatcamTools/ToolPanelize.py @@ -82,7 +82,7 @@ class Panelize(FlatCAMTool): form_layout.addRow(self.box_combo_label, self.box_combo) ## Spacing Columns - self.spacing_columns = FloatEntry() + self.spacing_columns = FCEntry() self.spacing_columns_label = QtWidgets.QLabel("Spacing cols:") self.spacing_columns_label.setToolTip( "Spacing between columns of the desired panel.\n" @@ -91,7 +91,7 @@ class Panelize(FlatCAMTool): form_layout.addRow(self.spacing_columns_label, self.spacing_columns) ## Spacing Rows - self.spacing_rows = FloatEntry() + self.spacing_rows = FCEntry() self.spacing_rows_label = QtWidgets.QLabel("Spacing rows:") self.spacing_rows_label.setToolTip( "Spacing between rows of the desired panel.\n" @@ -100,7 +100,7 @@ class Panelize(FlatCAMTool): form_layout.addRow(self.spacing_rows_label, self.spacing_rows) ## Columns - self.columns = IntEntry() + self.columns = FCEntry() self.columns_label = QtWidgets.QLabel("Columns:") self.columns_label.setToolTip( "Number of columns of the desired panel" @@ -108,7 +108,7 @@ class Panelize(FlatCAMTool): form_layout.addRow(self.columns_label, self.columns) ## Rows - self.rows = IntEntry() + self.rows = FCEntry() self.rows_label = QtWidgets.QLabel("Rows:") self.rows_label.setToolTip( "Number of rows of the desired panel" @@ -126,7 +126,7 @@ class Panelize(FlatCAMTool): ) form_layout.addRow(self.constrain_cb) - self.x_width_entry = FloatEntry() + self.x_width_entry = FCEntry() self.x_width_lbl = QtWidgets.QLabel("Width (DX):") self.x_width_lbl.setToolTip( "The width (DX) within which the panel must fit.\n" @@ -134,7 +134,7 @@ class Panelize(FlatCAMTool): ) form_layout.addRow(self.x_width_lbl, self.x_width_entry) - self.y_height_entry = FloatEntry() + self.y_height_entry = FCEntry() self.y_height_lbl = QtWidgets.QLabel("Height (DY):") self.y_height_lbl.setToolTip( "The height (DY)within which the panel must fit.\n" @@ -237,20 +237,77 @@ class Panelize(FlatCAMTool): self.outname = name + '_panelized' - spacing_columns = self.spacing_columns.get_value() + try: + spacing_columns = float(self.spacing_columns.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + spacing_columns = float(self.spacing_columns.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return spacing_columns = spacing_columns if spacing_columns is not None else 0 - spacing_rows = self.spacing_rows.get_value() + try: + spacing_rows = float(self.spacing_rows.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + spacing_rows = float(self.spacing_rows.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return spacing_rows = spacing_rows if spacing_rows is not None else 0 - rows = self.rows.get_value() + try: + rows = int(self.rows.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + rows = float(self.rows.get_value().replace(',', '.')) + rows = int(rows) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return rows = rows if rows is not None else 1 - columns = self.columns.get_value() + try: + columns = int(self.columns.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + columns = float(self.columns.get_value().replace(',', '.')) + columns = int(columns) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return columns = columns if columns is not None else 1 - constrain_dx = self.x_width_entry.get_value() - constrain_dy = self.y_height_entry.get_value() + try: + constrain_dx = float(self.x_width_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + constrain_dx = float(self.x_width_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return + + try: + constrain_dy = float(self.y_height_entry.get_value()) + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + constrain_dy = float(self.y_height_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered, " + "use a number.") + return if 0 in {columns, rows}: self.app.inform.emit("[error_notcl]Columns or Rows are zero value. Change them to a positive integer.") diff --git a/flatcamTools/ToolTransform.py b/flatcamTools/ToolTransform.py index 4ef0568f..33c27c5a 100644 --- a/flatcamTools/ToolTransform.py +++ b/flatcamTools/ToolTransform.py @@ -377,9 +377,14 @@ class ToolTransform(FlatCAMTool): def on_rotate(self): try: value = float(self.rotate_entry.get_value()) - except Exception as e: - self.app.inform.emit("[error] Failed to rotate due of: %s" % str(e)) - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + value = float(self.rotate_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered for Rotate, " + "use a number.") + return self.app.worker_task.emit({'fcn': self.on_rotate_action, 'params': [value]}) # self.on_rotate_action(value) @@ -406,9 +411,15 @@ class ToolTransform(FlatCAMTool): def on_skewx(self): try: value = float(self.skewx_entry.get_value()) - except: - self.app.inform.emit("[warning_notcl] No value for Skew!") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + value = float(self.skewx_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered for Skew X, " + "use a number.") + return + # self.on_skew("X", value) axis = 'X' self.app.worker_task.emit({'fcn': self.on_skew, @@ -418,9 +429,15 @@ class ToolTransform(FlatCAMTool): def on_skewy(self): try: value = float(self.skewy_entry.get_value()) - except: - self.app.inform.emit("[warning_notcl] No value for Skew!") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + value = float(self.skewy_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered for Skew Y, " + "use a number.") + return + # self.on_skew("Y", value) axis = 'Y' self.app.worker_task.emit({'fcn': self.on_skew, @@ -430,9 +447,15 @@ class ToolTransform(FlatCAMTool): def on_scalex(self): try: xvalue = float(self.scalex_entry.get_value()) - except: - self.app.inform.emit("[warning_notcl] No value for Scale!") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + xvalue = float(self.scalex_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered for Scale X, " + "use a number.") + return + # scaling to zero has no sense so we remove it, because scaling with 1 does nothing if xvalue == 0: xvalue = 1 @@ -458,9 +481,15 @@ class ToolTransform(FlatCAMTool): xvalue = 1 try: yvalue = float(self.scaley_entry.get_value()) - except: - self.app.inform.emit("[warning_notcl] No value for Scale!") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + yvalue = float(self.scaley_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered for Scale Y, " + "use a number.") + return + # scaling to zero has no sense so we remove it, because scaling with 1 does nothing if yvalue == 0: yvalue = 1 @@ -481,9 +510,15 @@ class ToolTransform(FlatCAMTool): def on_offx(self): try: value = float(self.offx_entry.get_value()) - except: - self.app.inform.emit("[warning_notcl] No value for Offset!") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + value = float(self.offx_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered for Offset X, " + "use a number.") + return + # self.on_offset("X", value) axis = 'X' self.app.worker_task.emit({'fcn': self.on_offset, @@ -493,9 +528,15 @@ class ToolTransform(FlatCAMTool): def on_offy(self): try: value = float(self.offy_entry.get_value()) - except: - self.app.inform.emit("[warning_notcl] No value for Offset!") - return + except ValueError: + # try to convert comma to decimal point. if it's still not working error message and return + try: + value = float(self.offy_entry.get_value().replace(',', '.')) + except ValueError: + self.app.inform.emit("[error_notcl]Wrong value format entered for Offset Y, " + "use a number.") + return + # self.on_offset("Y", value) axis = 'Y' self.app.worker_task.emit({'fcn': self.on_offset, diff --git a/flatcamTools/__init__.py b/flatcamTools/__init__.py index d322132f..e5e1e84f 100644 --- a/flatcamTools/__init__.py +++ b/flatcamTools/__init__.py @@ -5,7 +5,8 @@ from flatcamTools.ToolPanelize import Panelize from flatcamTools.ToolFilm import Film from flatcamTools.ToolMove import ToolMove from flatcamTools.ToolDblSided import DblSidedTool -from flatcamTools.ToolCutout import ToolCutout + +from flatcamTools.ToolCutOut import ToolCutOut from flatcamTools.ToolCalculators import ToolCalculator from flatcamTools.ToolProperties import Properties from flatcamTools.ToolImage import ToolImage