diff --git a/FlatCAMApp.py b/FlatCAMApp.py index ce968f96..8ae0ad2a 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -410,6 +410,8 @@ class App(QtCore.QObject): "global_compression_level": 3, "global_save_compressed": True, + "global_machinist_setting": False, + # Global GUI Preferences "global_gridx": 0.0393701, "global_gridy": 0.0393701, @@ -966,6 +968,7 @@ class App(QtCore.QObject): "global_save_compressed": self.ui.general_defaults_form.general_app_group.save_type_cb, "global_bookmarks_limit": self.ui.general_defaults_form.general_app_group.bm_limit_spinner, + "global_machinist_setting": self.ui.general_defaults_form.general_app_group.machinist_cb, # General GUI Preferences "global_gridx": self.ui.general_defaults_form.general_gui_group.gridx_entry, @@ -4836,6 +4839,10 @@ class App(QtCore.QObject): self.ui.general_defaults_form.general_gui_set_group.textbox_font_size_spinner.get_value() ) settings.setValue('toolbar_lock', self.ui.lock_action.isChecked()) + settings.setValue( + 'machinist', + 1 if self.ui.general_defaults_form.general_app_group.machinist_cb.get_value() else 0 + ) # This will write the setting to the platform specific storage. del settings @@ -6723,6 +6730,11 @@ class App(QtCore.QObject): tb_fsize = self.ui.general_defaults_form.general_gui_set_group.textbox_font_size_spinner.get_value() settings.setValue('textbox_font_size', tb_fsize) + settings.setValue( + 'machinist', + 1 if self.ui.general_defaults_form.general_app_group.machinist_cb.get_value() else 0 + ) + # This will write the setting to the platform specific storage. del settings diff --git a/FlatCAMObj.py b/FlatCAMObj.py index f8c63c48..67e95a84 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -4862,16 +4862,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): elif dia_cnc_dict['offset'].lower() == 'out': tool_offset = tooldia_val / 2 elif dia_cnc_dict['offset'].lower() == 'custom': - 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] %s' % - _("Wrong value format entered, use a number.")) - return + offset_value = float(self.ui.tool_offset_entry.get_value()) if offset_value: tool_offset = float(offset_value) else: @@ -5075,27 +5066,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): job_obj.segx = segx job_obj.segy = segy - try: - job_obj.z_pdepth = float(self.options["z_pdepth"]) - except ValueError: - # try to convert comma to decimal point. if it's still not working error message and return - try: - job_obj.z_pdepth = float(self.options["z_pdepth"].replace(',', '.')) - except ValueError: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _('Wrong value format for self.defaults["z_pdepth"] or ' - 'self.options["z_pdepth"]')) - - try: - job_obj.feedrate_probe = float(self.options["feedrate_probe"]) - except ValueError: - # try to convert comma to decimal point. if it's still not working error message and return - try: - job_obj.feedrate_probe = float(self.options["feedrate_probe"].replace(',', '.')) - except ValueError: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _('Wrong value format for self.defaults["feedrate_probe"] ' - 'or self.options["feedrate_probe"]')) + job_obj.z_pdepth = float(self.options["z_pdepth"]) + job_obj.feedrate_probe = float(self.options["feedrate_probe"]) job_obj.options['xmin'] = self.options['xmin'] job_obj.options['ymin'] = self.options['ymin'] diff --git a/FlatCAMPostProc.py b/FlatCAMPostProc.py index 853b0090..ff80c59b 100644 --- a/FlatCAMPostProc.py +++ b/FlatCAMPostProc.py @@ -18,7 +18,7 @@ postprocessors = {} class ABCPostProcRegister(ABCMeta): - # handles postprocessors registration on instantation + # handles postprocessors registration on instantiation def __new__(cls, clsname, bases, attrs): newclass = super(ABCPostProcRegister, cls).__new__(cls, clsname, bases, attrs) if object not in bases: diff --git a/README.md b/README.md index 573b75b4..e1d754a3 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ CAD program, and create G-Code for Isolation routing. ================================================= +5.11.2019 + +- added a new setting named 'Allow Machinist Unsafe Settings' that will allow the Travel Z and Cut Z to take both positive and negative values + 4.11.2019 - wip diff --git a/camlib.py b/camlib.py index 4fc10b8a..75217825 100644 --- a/camlib.py +++ b/camlib.py @@ -7,7 +7,7 @@ # ########################################################## ## -from PyQt5 import QtWidgets +from PyQt5 import QtWidgets, QtCore from io import StringIO import numpy as np @@ -2143,6 +2143,12 @@ class CNCjob(Geometry): "excellon_optimization_type": "B", } + settings = QtCore.QSettings("Open Source", "FlatCAM") + if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) + else: + machinist_setting = 0 + def __init__(self, units="in", kind="generic", tooldia=0.0, z_cut=-0.002, z_move=0.1, @@ -2368,21 +2374,21 @@ class CNCjob(Geometry): self.exc_drills = deepcopy(exobj.drills) self.exc_tools = deepcopy(exobj.tools) - if drillz > 0: - self.app.inform.emit('[WARNING] %s' % - _("The Cut Z parameter has positive value. " - "It is the depth value to drill 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 = -drillz - elif drillz == 0: - self.app.inform.emit('[WARNING] %s: %s' % - (_("The Cut Z parameter is zero. There will be no cut, skipping file"), - exobj.options['name'])) - return 'fail' - else: - self.z_cut = drillz + self.z_cut = drillz + if self.machinist_setting == 0: + if drillz > 0: + self.app.inform.emit('[WARNING] %s' % + _("The Cut Z parameter has positive value. " + "It is the depth value to drill 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 = -drillz + elif drillz == 0: + self.app.inform.emit('[WARNING] %s: %s' % + (_("The Cut Z parameter is zero. There will be no cut, skipping file"), + exobj.options['name'])) + return 'fail' self.z_toolchange = toolchangez @@ -2512,8 +2518,7 @@ class CNCjob(Geometry): measured_up_to_zero_distance = 0.0 measured_lift_distance = 0.0 - self.app.inform.emit('%s...' % - _("Starting G-Code")) + self.app.inform.emit('%s...' % _("Starting G-Code")) current_platform = platform.architecture()[0] if current_platform == '64bit': @@ -2667,8 +2672,7 @@ class CNCjob(Geometry): old_disp_number = disp_number else: - self.app.inform.emit('[ERROR_NOTCL] %s...' % - _('G91 coordinates not implemented')) + self.app.inform.emit('[ERROR_NOTCL] %s...' % _('G91 coordinates not implemented')) return 'fail' else: log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> " @@ -2814,8 +2818,7 @@ class CNCjob(Geometry): old_disp_number = disp_number else: - self.app.inform.emit('[ERROR_NOTCL] %s...' % - _('G91 coordinates not implemented')) + self.app.inform.emit('[ERROR_NOTCL] %s...' % _('G91 coordinates not implemented')) return 'fail' else: log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> " @@ -2920,8 +2923,7 @@ class CNCjob(Geometry): self.app.proc_container.update_view_text(' %d%%' % disp_number) old_disp_number = disp_number else: - self.app.inform.emit('[ERROR_NOTCL] %s...' % - _('G91 coordinates not implemented')) + self.app.inform.emit('[ERROR_NOTCL] %s...' % _('G91 coordinates not implemented')) return 'fail' else: log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> " @@ -2998,10 +3000,10 @@ class CNCjob(Geometry): self.tooldia = float(tooldia) if tooldia else None self.z_cut = float(z_cut) if z_cut else None - self.z_move = float(z_move) if z_move else None + self.z_move = float(z_move) if z_move is not None else None self.feedrate = float(feedrate) if feedrate else None - self.z_feedrate = float(feedrate_z) if feedrate_z else None + self.z_feedrate = float(feedrate_z) if feedrate_z is not None else None self.feedrate_rapid = float(feedrate_rapid) if feedrate_rapid else None self.spindlespeed = int(spindlespeed) if spindlespeed else None @@ -3009,13 +3011,13 @@ class CNCjob(Geometry): self.dwell = dwell self.dwelltime = float(dwelltime) if dwelltime else None - self.startz = float(startz) if startz else None - self.z_end = float(endz) if endz else None + self.startz = float(startz) if startz is not None else None + self.z_end = float(endz) if endz is not None else None self.z_depthpercut = float(depthpercut) if depthpercut else None self.multidepth = multidepth - self.z_toolchange = float(toolchangez) if toolchangez else None + self.z_toolchange = float(toolchangez) if toolchangez is not None else None # it servers in the postprocessor file self.tool = tool_no @@ -3040,46 +3042,47 @@ class CNCjob(Geometry): if self.z_cut is None: self.app.inform.emit('[ERROR_NOTCL] %s' % _("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] %s' % - _("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).")) - self.z_cut = -self.z_cut - elif self.z_cut == 0: - self.app.inform.emit('[WARNING] %s: %s' % - (_("The Cut Z parameter is zero. There will be no cut, skipping file"), - self.options['name'])) - return 'fail' + if self.machinist_setting == 0: + if self.z_cut > 0: + self.app.inform.emit('[WARNING] %s' % + _("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).")) + self.z_cut = -self.z_cut + elif self.z_cut == 0: + self.app.inform.emit('[WARNING] %s: %s' % + (_("The Cut Z parameter is zero. There will be no cut, skipping file"), + self.options['name'])) + return 'fail' + + if self.z_move is None: + self.app.inform.emit('[ERROR_NOTCL] %s' % + _("Travel Z parameter is None or zero.")) + return 'fail' + + if self.z_move < 0: + self.app.inform.emit('[WARNING] %s' % + _("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).")) + self.z_move = -self.z_move + elif self.z_move == 0: + self.app.inform.emit('[WARNING] %s: %s' % + (_("The Z Travel parameter is zero. This is dangerous, skipping file"), + self.options['name'])) + return 'fail' # made sure that depth_per_cut is no more then the z_cut if abs(self.z_cut) < self.z_depthpercut: self.z_depthpercut = abs(self.z_cut) - if self.z_move is None: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _("Travel Z parameter is None or zero.")) - return 'fail' - - if self.z_move < 0: - self.app.inform.emit('[WARNING] %s' % - _("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).")) - self.z_move = -self.z_move - elif self.z_move == 0: - self.app.inform.emit('[WARNING] %s: %s' % - (_("The Z Travel parameter is zero. This is dangerous, skipping file"), - self.options['name'])) - return 'fail' - # ## Index first and last points in paths # What points to index. def get_pts(o): @@ -3352,11 +3355,11 @@ class CNCjob(Geometry): except ValueError: self.tooldia = [float(el) for el in tooldia.split(',') if el != ''] if tooldia else None - self.z_cut = float(z_cut) if z_cut else None - self.z_move = float(z_move) if z_move else None + self.z_cut = float(z_cut) if z_cut is not None else None + self.z_move = float(z_move) if z_move is not None else None self.feedrate = float(feedrate) if feedrate else None - self.z_feedrate = float(feedrate_z) if feedrate_z else None + self.z_feedrate = float(feedrate_z) if feedrate_z is not None else None self.feedrate_rapid = float(feedrate_rapid) if feedrate_rapid else None self.spindlespeed = int(spindlespeed) if spindlespeed else None @@ -3364,11 +3367,11 @@ class CNCjob(Geometry): self.dwell = dwell self.dwelltime = float(dwelltime) if dwelltime else None - self.startz = float(startz) if startz else None - self.z_end = float(endz) if endz else None + self.startz = float(startz) if startz is not None else None + self.z_end = float(endz) if endz is not None else None self.z_depthpercut = float(depthpercut) if depthpercut else None self.multidepth = multidepth - self.z_toolchange = float(toolchangez) if toolchangez else None + self.z_toolchange = float(toolchangez) if toolchangez is not None else None try: if toolchangexy == '': @@ -3387,44 +3390,45 @@ class CNCjob(Geometry): self.pp_geometry_name = pp_geometry_name if pp_geometry_name else 'default' self.f_plunge = self.app.defaults["geometry_f_plunge"] - if self.z_cut is None: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _("Cut_Z parameter is None or zero. Most likely a bad combinations of " - "other parameters.")) - return 'fail' + if self.machinist_setting == 0: + if self.z_cut is None: + self.app.inform.emit('[ERROR_NOTCL] %s' % + _("Cut_Z parameter is None or zero. Most likely a bad combinations of " + "other parameters.")) + return 'fail' - if self.z_cut > 0: - self.app.inform.emit('[WARNING] %s' % - _("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).")) - self.z_cut = -self.z_cut - elif self.z_cut == 0: - self.app.inform.emit('[WARNING] %s: %s' % - (_("The Cut Z parameter is zero. There will be no cut, skipping file"), - geometry.options['name'])) - return 'fail' + if self.z_cut > 0: + self.app.inform.emit('[WARNING] %s' % + _("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).")) + self.z_cut = -self.z_cut + elif self.z_cut == 0: + self.app.inform.emit('[WARNING] %s: %s' % + (_("The Cut Z parameter is zero. There will be no cut, skipping file"), + geometry.options['name'])) + return 'fail' - if self.z_move is None: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _("Travel Z parameter is None or zero.")) - return 'fail' + if self.z_move is None: + self.app.inform.emit('[ERROR_NOTCL] %s' % + _("Travel Z parameter is None or zero.")) + return 'fail' - if self.z_move < 0: - self.app.inform.emit('[WARNING] %s' % - _("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).")) - self.z_move = -self.z_move - elif self.z_move == 0: - self.app.inform.emit('[WARNING] %s: %s' % - (_("The Z Travel parameter is zero. " - "This is dangerous, skipping file"), self.options['name'])) - return 'fail' + if self.z_move < 0: + self.app.inform.emit('[WARNING] %s' % + _("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).")) + self.z_move = -self.z_move + elif self.z_move == 0: + self.app.inform.emit('[WARNING] %s: %s' % + (_("The Z Travel parameter is zero. " + "This is dangerous, skipping file"), self.options['name'])) + return 'fail' # made sure that depth_per_cut is no more then the z_cut if abs(self.z_cut) < self.z_depthpercut: @@ -3586,12 +3590,9 @@ class CNCjob(Geometry): self.gcode += self.doformat(p.spindle_stop_code) self.gcode += self.doformat(p.lift_code, x=current_pt[0], y=current_pt[1]) self.gcode += self.doformat(p.end_code, x=0, y=0) - self.app.inform.emit('%s... %s %s' % - (_("Finished G-Code generation"), - str(path_count), - _(" paths traced.") - ) - ) + self.app.inform.emit( + '%s... %s %s' % (_("Finished G-Code generation"), str(path_count), _(" paths traced.")) + ) return self.gcode diff --git a/flatcamGUI/GUIElements.py b/flatcamGUI/GUIElements.py index 2fbbc58a..d7394745 100644 --- a/flatcamGUI/GUIElements.py +++ b/flatcamGUI/GUIElements.py @@ -12,7 +12,7 @@ # ########################################################## from PyQt5 import QtGui, QtCore, QtWidgets -from PyQt5.QtCore import Qt, pyqtSlot +from PyQt5.QtCore import Qt, pyqtSlot, QSettings from PyQt5.QtWidgets import QTextEdit, QCompleter, QAction from PyQt5.QtGui import QKeySequence, QTextCursor diff --git a/flatcamGUI/ObjectUI.py b/flatcamGUI/ObjectUI.py index c04a0212..4db16297 100644 --- a/flatcamGUI/ObjectUI.py +++ b/flatcamGUI/ObjectUI.py @@ -22,6 +22,12 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QtCore.QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 + class ObjectUI(QtWidgets.QWidget): """ @@ -754,7 +760,12 @@ class ExcellonObjectUI(ObjectUI): grid1.addWidget(cutzlabel, 0, 0) self.cutz_entry = FCDoubleSpinner() self.cutz_entry.set_precision(self.decimals) - self.cutz_entry.setRange(-9999.9999, -0.000001) + + if machinist_setting == 0: + self.cutz_entry.setRange(-9999.9999, -0.000001) + else: + self.cutz_entry.setRange(-9999.9999, 9999.9999) + self.cutz_entry.setSingleStep(0.1) grid1.addWidget(self.cutz_entry, 0, 1) @@ -768,7 +779,12 @@ class ExcellonObjectUI(ObjectUI): grid1.addWidget(travelzlabel, 1, 0) self.travelz_entry = FCDoubleSpinner() self.travelz_entry.set_precision(self.decimals) - self.travelz_entry.setRange(0.0, 9999.9999) + + if machinist_setting == 0: + self.travelz_entry.setRange(0.00001, 9999.9999) + else: + self.travelz_entry.setRange(-9999.9999, 9999.9999) + self.travelz_entry.setSingleStep(0.1) grid1.addWidget(self.travelz_entry, 1, 1) @@ -790,7 +806,12 @@ class ExcellonObjectUI(ObjectUI): grid1.addWidget(toolchzlabel, 3, 0) self.toolchangez_entry = FCDoubleSpinner() self.toolchangez_entry.set_precision(self.decimals) - self.toolchangez_entry.setRange(0.0, 9999.9999) + + if machinist_setting == 0: + self.toolchangez_entry.setRange(0.0, 9999.9999) + else: + self.toolchangez_entry.setRange(-9999.9999, 9999.9999) + self.toolchangez_entry.setSingleStep(0.1) grid1.addWidget(self.toolchangez_entry, 3, 1) @@ -815,7 +836,12 @@ class ExcellonObjectUI(ObjectUI): grid1.addWidget(self.eendz_label, 5, 0) self.eendz_entry = FCDoubleSpinner() self.eendz_entry.set_precision(self.decimals) - self.eendz_entry.setRange(0.0, 9999.9999) + + if machinist_setting == 0: + self.eendz_entry.setRange(0.0, 9999.9999) + else: + self.eendz_entry.setRange(-9999.9999, 9999.9999) + self.eendz_entry.setSingleStep(0.1) grid1.addWidget(self.eendz_entry, 5, 1) @@ -1166,7 +1192,6 @@ class GeometryObjectUI(ObjectUI): self.grid1.addWidget(self.tool_offset_lbl, 0, 0) self.grid1.addWidget(self.tool_offset_entry, 0, 1, 1, 2) - self.addtool_entry_lbl = QtWidgets.QLabel('%s:' % _('Tool Dia')) self.addtool_entry_lbl.setToolTip( _("Diameter for the new tool") @@ -1279,7 +1304,12 @@ class GeometryObjectUI(ObjectUI): ) self.cutz_entry = FCDoubleSpinner() self.cutz_entry.set_precision(self.decimals) - self.cutz_entry.setRange(-9999.9999, -0.00001) + + if machinist_setting == 0: + self.cutz_entry.setRange(-9999.9999, -0.00001) + else: + self.cutz_entry.setRange(-9999.9999, 9999.9999) + self.cutz_entry.setSingleStep(0.1) self.grid3.addWidget(cutzlabel, 3, 0) @@ -1319,7 +1349,12 @@ class GeometryObjectUI(ObjectUI): ) self.travelz_entry = FCDoubleSpinner() self.travelz_entry.set_precision(self.decimals) - self.travelz_entry.setRange(0, 9999.9999) + + if machinist_setting == 0: + self.travelz_entry.setRange(0.00001, 9999.9999) + else: + self.travelz_entry.setRange(-9999.9999, 9999.9999) + self.travelz_entry.setSingleStep(0.1) self.grid3.addWidget(travelzlabel, 5, 0) @@ -1342,7 +1377,12 @@ class GeometryObjectUI(ObjectUI): ) self.toolchangez_entry = FCDoubleSpinner() self.toolchangez_entry.set_precision(self.decimals) - self.toolchangez_entry.setRange(0, 9999.9999) + + if machinist_setting == 0: + self.toolchangez_entry.setRange(0, 9999.9999) + else: + self.toolchangez_entry.setRange(-9999.9999, 9999.9999) + self.toolchangez_entry.setSingleStep(0.1) self.grid3.addWidget(self.toolchangeg_cb, 6, 0, 1, 2) @@ -1369,7 +1409,12 @@ class GeometryObjectUI(ObjectUI): ) self.gendz_entry = FCDoubleSpinner() self.gendz_entry.set_precision(self.decimals) - self.gendz_entry.setRange(0, 9999.9999) + + if machinist_setting == 0: + self.gendz_entry.setRange(0, 9999.9999) + else: + self.gendz_entry.setRange(-9999.9999, 9999.9999) + self.gendz_entry.setSingleStep(0.1) self.grid3.addWidget(self.endzlabel, 9, 0) diff --git a/flatcamGUI/PreferencesUI.py b/flatcamGUI/PreferencesUI.py index ec326c53..546567ea 100644 --- a/flatcamGUI/PreferencesUI.py +++ b/flatcamGUI/PreferencesUI.py @@ -18,6 +18,12 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QtCore.QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 + class OptionsGroupUI(QtWidgets.QGroupBox): def __init__(self, title, parent=None): @@ -1166,6 +1172,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): self.proj_ois = OptionalInputSection(self.save_type_cb, [self.compress_label, self.compress_spinner], True) + # Bookmarks Limit in the Help Menu self.bm_limit_spinner = FCSpinner() self.bm_limit_label = QtWidgets.QLabel('%s:' % _('Bookmarks limit')) self.bm_limit_label.setToolTip( @@ -1177,6 +1184,18 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): grid0.addWidget(self.bm_limit_label, 18, 0) grid0.addWidget(self.bm_limit_spinner, 18, 1) + # Machinist settings that allow unsafe settings + self.machinist_cb = FCCheckBox(_("Allow Machinist Unsafe Settings")) + self.machinist_cb.setToolTip( + _("If checked, some of the application settings will be allowed\n" + "to have values that are usually unsafe to use.\n" + "Like Z travel negative values or Z Cut positive values.\n" + "It will applied at the next application start.\n" + "<>: Don't change this unless you know what you are doing !!!") + ) + + grid0.addWidget(self.machinist_cb, 19, 0, 1, 2) + self.layout.addStretch() if sys.platform != 'win32': @@ -2154,7 +2173,12 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI): ) grid2.addWidget(cutzlabel, 0, 0) self.cutz_entry = FCDoubleSpinner() - self.cutz_entry.set_range(-9999, -0.000001) + + if machinist_setting == 0: + self.cutz_entry.set_range(-9999.9999, -0.000001) + else: + self.cutz_entry.set_range(-9999.9999, 9999.9999) + self.cutz_entry.setSingleStep(0.1) self.cutz_entry.set_precision(4) grid2.addWidget(self.cutz_entry, 0, 1) @@ -2168,7 +2192,11 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI): grid2.addWidget(travelzlabel, 1, 0) self.travelz_entry = FCDoubleSpinner() self.travelz_entry.set_precision(4) - self.travelz_entry.set_range(0, 999) + + if machinist_setting == 0: + self.travelz_entry.set_range(0.0001, 9999.9999) + else: + self.travelz_entry.set_range(-9999.9999, 9999.9999) grid2.addWidget(self.travelz_entry, 1, 1) @@ -2190,7 +2218,11 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI): grid2.addWidget(toolchangezlabel, 3, 0) self.toolchangez_entry = FCDoubleSpinner() self.toolchangez_entry.set_precision(4) - self.toolchangez_entry.set_range(0, 999) + + if machinist_setting == 0: + self.toolchangez_entry.set_range(0.0001, 9999.9999) + else: + self.toolchangez_entry.set_range(-9999.9999, 9999.9999) grid2.addWidget(self.toolchangez_entry, 3, 1) @@ -2202,7 +2234,11 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI): ) self.eendz_entry = FCDoubleSpinner() self.eendz_entry.set_precision(4) - self.eendz_entry.set_range(0, 999) + + if machinist_setting == 0: + self.eendz_entry.set_range(0.0000, 9999.9999) + else: + self.eendz_entry.set_range(-9999.9999, 9999.9999) grid2.addWidget(endzlabel, 4, 0) grid2.addWidget(self.eendz_entry, 4, 1) @@ -2975,7 +3011,12 @@ class GeometryOptPrefGroupUI(OptionsGroupUI): "below the copper surface.") ) self.cutz_entry = FCDoubleSpinner() - self.cutz_entry.set_range(-999.999, -0.000001) + + if machinist_setting == 0: + self.cutz_entry.set_range(-9999.9999, -0.000001) + else: + self.cutz_entry.set_range(-9999.9999, 9999.9999) + self.cutz_entry.set_precision(4) self.cutz_entry.setSingleStep(0.1) self.cutz_entry.setWrapping(True) @@ -3023,7 +3064,12 @@ class GeometryOptPrefGroupUI(OptionsGroupUI): "moving without cutting.") ) self.travelz_entry = FCDoubleSpinner() - self.travelz_entry.set_range(0, 99999) + + if machinist_setting == 0: + self.travelz_entry.set_range(0.0001, 9999.9999) + else: + self.travelz_entry.set_range(-9999.9999, 9999.9999) + self.travelz_entry.set_precision(4) self.travelz_entry.setSingleStep(0.1) self.travelz_entry.setWrapping(True) @@ -3052,7 +3098,12 @@ class GeometryOptPrefGroupUI(OptionsGroupUI): ) ) self.toolchangez_entry = FCDoubleSpinner() - self.toolchangez_entry.set_range(0, 99999) + + if machinist_setting == 0: + self.toolchangez_entry.set_range(0.000, 9999.9999) + else: + self.toolchangez_entry.set_range(-9999.9999, 9999.9999) + self.toolchangez_entry.set_precision(4) self.toolchangez_entry.setSingleStep(0.1) self.toolchangez_entry.setWrapping(True) @@ -3067,7 +3118,12 @@ class GeometryOptPrefGroupUI(OptionsGroupUI): "the last move at the end of the job.") ) self.gendz_entry = FCDoubleSpinner() - self.gendz_entry.set_range(0, 99999) + + if machinist_setting == 0: + self.gendz_entry.set_range(0.000, 9999.9999) + else: + self.gendz_entry.set_range(-9999.9999, 9999.9999) + self.gendz_entry.set_precision(4) self.gendz_entry.setSingleStep(0.1) self.gendz_entry.setWrapping(True)