diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ad11fa9..8c4d275f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ CHANGELOG for FlatCAM beta 14.07.2020 - Drilling Tool - now there is an Excellon preference that control the autoload of tools from the Tools Database +- Tools Database - remade the UI +- made sure that the serializable attributes are added correctly and only once (self.ser_attrs) 13.07.2020 diff --git a/appDatabase.py b/appDatabase.py index b425b883..142dfba9 100644 --- a/appDatabase.py +++ b/appDatabase.py @@ -941,15 +941,15 @@ class ToolsDB2UI: def __init__(self, app, grid_layout): self.app = app self.decimals = self.app.decimals - + settings = QtCore.QSettings("Open Source", "FlatCAM") if settings.contains("machinist"): self.machinist_setting = settings.value('machinist', type=int) else: self.machinist_setting = 0 - + g_lay = grid_layout - + tree_layout = QtWidgets.QVBoxLayout() g_lay.addLayout(tree_layout, 0, 0) @@ -995,31 +995,18 @@ class ToolsDB2UI: self.tool_description_box.setTitle(_("Tool Description")) self.tool_description_box.setFixedWidth(250) - # Geometry Basic box - self.basic_box = QtWidgets.QGroupBox() - self.basic_box.setStyleSheet(""" + # Milling box + self.milling_box = QtWidgets.QGroupBox() + self.milling_box.setStyleSheet(""" QGroupBox { font-size: 16px; font-weight: bold; } """) - self.basic_vlay = QtWidgets.QVBoxLayout() - self.basic_box.setTitle(_("Basic Geo Parameters")) - self.basic_box.setFixedWidth(250) - - # Geometry Advanced box - self.advanced_box = QtWidgets.QGroupBox() - self.advanced_box.setStyleSheet(""" - QGroupBox - { - font-size: 16px; - font-weight: bold; - } - """) - self.advanced_vlay = QtWidgets.QVBoxLayout() - self.advanced_box.setTitle(_("Advanced Geo Parameters")) - self.advanced_box.setFixedWidth(250) + self.milling_vlay = QtWidgets.QVBoxLayout() + self.milling_box.setTitle(_("Milling Parameters")) + self.milling_box.setFixedWidth(250) # NCC TOOL BOX self.ncc_box = QtWidgets.QGroupBox() @@ -1075,28 +1062,37 @@ class ToolsDB2UI: # Layout Constructor self.tool_description_box.setLayout(self.description_vlay) - self.basic_box.setLayout(self.basic_vlay) - self.advanced_box.setLayout(self.advanced_vlay) + self.milling_box.setLayout(self.milling_vlay) self.ncc_box.setLayout(self.ncc_vlay) self.paint_box.setLayout(self.paint_vlay) self.iso_box.setLayout(self.iso_vlay) self.drill_box.setLayout(self.drill_vlay) - geo_vlay = QtWidgets.QVBoxLayout() - geo_vlay.addWidget(self.tool_description_box) - geo_vlay.addWidget(self.basic_box) - geo_vlay.addWidget(self.advanced_box) - geo_vlay.addStretch() + descript_vlay = QtWidgets.QVBoxLayout() + descript_vlay.addWidget(self.tool_description_box) + descript_vlay.addStretch() - tools_vlay = QtWidgets.QVBoxLayout() - tools_vlay.addWidget(self.ncc_box) - tools_vlay.addWidget(self.paint_box) - tools_vlay.addWidget(self.iso_box) - tools_vlay.addWidget(self.drill_box) - tools_vlay.addStretch() + milling_vlay = QtWidgets.QVBoxLayout() + milling_vlay.addWidget(self.milling_box) + milling_vlay.addStretch() + + tools1_vlay = QtWidgets.QVBoxLayout() + tools1_vlay.addWidget(self.drill_box) + tools1_vlay.addWidget(self.iso_box) + tools1_vlay.addStretch() + + tools2_vlay = QtWidgets.QVBoxLayout() + tools2_vlay.addWidget(self.paint_box) + tools2_vlay.addWidget(self.ncc_box) + tools2_vlay.addStretch() + + param_hlay.addLayout(descript_vlay) + param_hlay.addLayout(tools1_vlay) + param_hlay.addLayout(tools2_vlay) + + # always visible, always to be included last + param_hlay.addLayout(milling_vlay) - param_hlay.addLayout(geo_vlay) - param_hlay.addLayout(tools_vlay) param_hlay.addStretch() # ########################################################################### @@ -1109,7 +1105,7 @@ class ToolsDB2UI: self.description_vlay.addStretch() # Tool Name - self.name_label = QtWidgets.QLabel('%s:' % _('Tool Name')) + self.name_label = QtWidgets.QLabel('%s:' % _('Name')) self.name_label.setToolTip( _("Tool name.\n" "This is not used in the app, it's function\n" @@ -1122,7 +1118,7 @@ class ToolsDB2UI: self.grid_tool.addWidget(self.name_entry, 0, 1) # Tool Dia - self.dia_label = QtWidgets.QLabel('%s:' % _('Tool Dia')) + self.dia_label = QtWidgets.QLabel('%s:' % _('Diameter')) self.dia_label.setToolTip( _("Tool Diameter.")) @@ -1134,26 +1130,13 @@ class ToolsDB2UI: self.grid_tool.addWidget(self.dia_label, 1, 0) self.grid_tool.addWidget(self.dia_entry, 1, 1) - # Tool Object Type - self.tool_object_label = QtWidgets.QLabel('%s:' % _('Object Type')) - self.tool_object_label.setToolTip( - _("The kind of application object where the tool is to be used.")) - - self.object_type_combo = FCComboBox() - self.object_type_combo.addItems([_("General"), _("Milling"), _("Drilling")]) - self.object_type_combo.setObjectName('gdb_object_type') - - self.grid_tool.addWidget(self.tool_object_label, 2, 0) - self.grid_tool.addWidget(self.object_type_combo, 2, 1) - # Tool Tolerance - self.tol_label = QtWidgets.QLabel("%s:" % _("Tolerance")) + self.tol_label = QtWidgets.QLabel("%s:" % _("Diameter Tolerance")) self.tol_label.setToolTip( - _("Tool tolerance. If there is a tool in the Excellon object with\n" - "the value within the limits then this tool from DB will be used.\n" - "This behavior is enabled in the Drilling Tool.") + _("Tool tolerance. If there is a tool in the targeted tools table with\n" + "the value within the limits then this tool from DB will be used.") ) - self.grid_tool.addWidget(self.tol_label, 4, 0, 1, 2) + self.grid_tool.addWidget(self.tol_label, 2, 0, 1, 2) # Tolerance Min Limit self.min_limit_label = QtWidgets.QLabel('%s:' % _("Min")) @@ -1166,8 +1149,8 @@ class ToolsDB2UI: self.tol_min_entry.setSingleStep(0.1) self.tol_min_entry.setObjectName("gdb_tol_min") - self.grid_tool.addWidget(self.min_limit_label, 6, 0) - self.grid_tool.addWidget(self.tol_min_entry, 6, 1) + self.grid_tool.addWidget(self.min_limit_label, 4, 0) + self.grid_tool.addWidget(self.tol_min_entry, 4, 1) # Tolerance Min Limit self.max_limit_label = QtWidgets.QLabel('%s:' % _("Max")) @@ -1180,20 +1163,32 @@ class ToolsDB2UI: self.tol_max_entry.setSingleStep(0.1) self.tol_max_entry.setObjectName("gdb_tol_max") - self.grid_tool.addWidget(self.max_limit_label, 7, 0) - self.grid_tool.addWidget(self.tol_max_entry, 7, 1) + self.grid_tool.addWidget(self.max_limit_label, 6, 0) + self.grid_tool.addWidget(self.tol_max_entry, 6, 1) + + # Tool Object Type + self.tool_op_label = QtWidgets.QLabel('%s:' % _('Operation')) + self.tool_op_label.setToolTip( + _("The kind of Application Tool where this tool is to be used.")) + + self.tool_op_combo = FCComboBox() + self.tool_op_combo.addItems([_("General"), _("Milling"), _("Drilling"), _('Isolation'), _('Paint'), _('NCC')]) + self.tool_op_combo.setObjectName('gdb_tool_target') + + self.grid_tool.addWidget(self.tool_op_label, 8, 0) + self.grid_tool.addWidget(self.tool_op_combo, 8, 1) # ########################################################################### - # ############### BASIC GEOMETRY UI form #################################### + # ############### MILLING UI form #################################### # ########################################################################### self.grid0 = QtWidgets.QGridLayout() - self.basic_vlay.addLayout(self.grid0) + self.milling_vlay.addLayout(self.grid0) self.grid0.setColumnStretch(0, 0) self.grid0.setColumnStretch(1, 1) - self.basic_vlay.addStretch() + self.milling_vlay.addStretch() # Tool Shape - self.shape_label = QtWidgets.QLabel('%s:' % _('Tool Shape')) + self.shape_label = QtWidgets.QLabel('%s:' % _('Shape')) self.shape_label.setToolTip( _("Tool Shape. \n" "Can be:\n" @@ -1208,141 +1203,38 @@ class ToolsDB2UI: self.grid0.addWidget(self.shape_label, 2, 0) self.grid0.addWidget(self.shape_combo, 2, 1) - # Cut Z - self.cutz_label = QtWidgets.QLabel('%s:' % _("Cut Z")) - self.cutz_label.setToolTip( - _("Cutting Depth.\n" - "The depth at which to cut into material.")) + # V-Dia + self.vdia_label = QtWidgets.QLabel('%s:' % _("V-Dia")) + self.vdia_label.setToolTip( + _("V-Dia.\n" + "Diameter of the tip for V-Shape Tools.")) - self.cutz_entry = FCDoubleSpinner() - self.cutz_entry.set_range(-9999.9999, 9999.9999) - self.cutz_entry.set_precision(self.decimals) - self.cutz_entry.setObjectName('gdb_cutz') + self.vdia_entry = FCDoubleSpinner() + self.vdia_entry.set_range(0.0000, 9999.9999) + self.vdia_entry.set_precision(self.decimals) + self.vdia_entry.setObjectName('gdb_vdia') - self.grid0.addWidget(self.cutz_label, 4, 0) - self.grid0.addWidget(self.cutz_entry, 4, 1) + self.grid0.addWidget(self.vdia_label, 4, 0) + self.grid0.addWidget(self.vdia_entry, 4, 1) - # Multi Depth - self.multidepth_label = QtWidgets.QLabel('%s:' % _("MultiDepth")) - self.multidepth_label.setToolTip( - _("Multi Depth.\n" - "Selecting this will allow cutting in multiple passes,\n" - "each pass adding a DPP parameter depth.")) + # V-Angle + self.vangle_label = QtWidgets.QLabel('%s:' % _("V-Angle")) + self.vangle_label.setToolTip( + _("V-Agle.\n" + "Angle at the tip for the V-Shape Tools.")) - self.multidepth_cb = FCCheckBox() - self.multidepth_cb.setObjectName('gdb_multidepth') + self.vangle_entry = FCDoubleSpinner() + self.vangle_entry.set_range(-360.0, 360.0) + self.vangle_entry.set_precision(self.decimals) + self.vangle_entry.setObjectName('gdb_vangle') - self.grid0.addWidget(self.multidepth_label, 5, 0) - self.grid0.addWidget(self.multidepth_cb, 5, 1) + self.grid0.addWidget(self.vangle_label, 6, 0) + self.grid0.addWidget(self.vangle_entry, 6, 1) - # Depth Per Pass - self.dpp_label = QtWidgets.QLabel('%s:' % _("DPP")) - self.dpp_label.setToolTip( - _("DPP. Depth per Pass.\n" - "The value used to cut into material on each pass.")) - - self.multidepth_entry = FCDoubleSpinner() - self.multidepth_entry.set_range(-9999.9999, 9999.9999) - self.multidepth_entry.set_precision(self.decimals) - self.multidepth_entry.setObjectName('gdb_multidepth_entry') - - self.grid0.addWidget(self.dpp_label, 7, 0) - self.grid0.addWidget(self.multidepth_entry, 7, 1) - - # Travel Z - self.travelz_label = QtWidgets.QLabel('%s:' % _("Travel Z")) - self.travelz_label.setToolTip( - _("Clearance Height.\n" - "Height at which the milling bit will travel between cuts,\n" - "above the surface of the material, avoiding all fixtures.")) - - self.travelz_entry = FCDoubleSpinner() - self.travelz_entry.set_range(-9999.9999, 9999.9999) - self.travelz_entry.set_precision(self.decimals) - self.travelz_entry.setObjectName('gdb_travel') - - self.grid0.addWidget(self.travelz_label, 9, 0) - self.grid0.addWidget(self.travelz_entry, 9, 1) - - # Feedrate X-Y - self.frxy_label = QtWidgets.QLabel('%s:' % _("Feedrate X-Y")) - self.frxy_label.setToolTip( - _("Feedrate X-Y. Feedrate\n" - "The speed on XY plane used while cutting into material.")) - - self.frxy_entry = FCDoubleSpinner() - self.frxy_entry.set_range(-999999.9999, 999999.9999) - self.frxy_entry.set_precision(self.decimals) - self.frxy_entry.setObjectName('gdb_frxy') - - self.grid0.addWidget(self.frxy_label, 12, 0) - self.grid0.addWidget(self.frxy_entry, 12, 1) - - # Feedrate Z - self.frz_label = QtWidgets.QLabel('%s:' % _("Feedrate Z")) - self.frz_label.setToolTip( - _("Feedrate Z\n" - "The speed on Z plane.")) - - self.frz_entry = FCDoubleSpinner() - self.frz_entry.set_range(-999999.9999, 999999.9999) - self.frz_entry.set_precision(self.decimals) - self.frz_entry.setObjectName('gdb_frz') - - self.grid0.addWidget(self.frz_label, 14, 0) - self.grid0.addWidget(self.frz_entry, 14, 1) - - # Spindle Spped - self.spindle_label = QtWidgets.QLabel('%s:' % _("Spindle Speed")) - self.spindle_label.setToolTip( - _("Spindle Speed.\n" - "If it's left empty it will not be used.\n" - "The speed of the spindle in RPM.")) - - self.spindle_entry = FCDoubleSpinner() - self.spindle_entry.set_range(-999999.9999, 999999.9999) - self.spindle_entry.set_precision(self.decimals) - self.spindle_entry.setObjectName('gdb_spindle') - - self.grid0.addWidget(self.spindle_label, 15, 0) - self.grid0.addWidget(self.spindle_entry, 15, 1) - - # Dwell - self.dwell_label = QtWidgets.QLabel('%s:' % _("Dwell")) - self.dwell_label.setToolTip( - _("Dwell.\n" - "Check this if a delay is needed to allow\n" - "the spindle motor to reach it's set speed.")) - - self.dwell_cb = FCCheckBox() - self.dwell_cb.setObjectName('gdb_dwell') - - self.grid0.addWidget(self.dwell_label, 16, 0) - self.grid0.addWidget(self.dwell_cb, 16, 1) - - # Dwell Time - self.dwelltime_label = QtWidgets.QLabel('%s:' % _("Dwelltime")) - self.dwelltime_label.setToolTip( - _("Dwell Time.\n" - "A delay used to allow the motor spindle reach it's set speed.")) - - self.dwelltime_entry = FCDoubleSpinner() - self.dwelltime_entry.set_range(0.0000, 9999.9999) - self.dwelltime_entry.set_precision(self.decimals) - self.dwelltime_entry.setObjectName('gdb_dwelltime') - - self.grid0.addWidget(self.dwelltime_label, 17, 0) - self.grid0.addWidget(self.dwelltime_entry, 17, 1) - - # ########################################################################### - # ############### ADVANCED GEOMETRY UI form ################################# - # ########################################################################### - - self.grid1 = QtWidgets.QGridLayout() - self.advanced_vlay.addLayout(self.grid1) - self.grid1.setColumnStretch(0, 0) - self.grid1.setColumnStretch(1, 1) - self.advanced_vlay.addStretch() + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.grid0.addWidget(separator_line, 8, 0, 1, 2) # Tool Type self.type_label = QtWidgets.QLabel('%s:' % _("Tool Type")) @@ -1357,8 +1249,8 @@ class ToolsDB2UI: self.type_combo.addItems(["Iso", "Rough", "Finish"]) self.type_combo.setObjectName('gdb_type') - self.grid1.addWidget(self.type_label, 0, 0) - self.grid1.addWidget(self.type_combo, 0, 1) + self.grid0.addWidget(self.type_label, 10, 0) + self.grid0.addWidget(self.type_combo, 10, 1) # Tool Offset self.tooloffset_label = QtWidgets.QLabel('%s:' % _('Tool Offset')) @@ -1374,8 +1266,8 @@ class ToolsDB2UI: self.tooloffset_combo.addItems(["Path", "In", "Out", "Custom"]) self.tooloffset_combo.setObjectName('gdb_tool_offset') - self.grid1.addWidget(self.tooloffset_label, 2, 0) - self.grid1.addWidget(self.tooloffset_combo, 2, 1) + self.grid0.addWidget(self.tooloffset_label, 12, 0) + self.grid0.addWidget(self.tooloffset_combo, 12, 1) # Custom Offset self.custom_offset_label = QtWidgets.QLabel('%s:' % _("Custom Offset")) @@ -1388,52 +1280,69 @@ class ToolsDB2UI: self.custom_offset_entry.set_precision(self.decimals) self.custom_offset_entry.setObjectName('gdb_custom_offset') - self.grid1.addWidget(self.custom_offset_label, 5, 0) - self.grid1.addWidget(self.custom_offset_entry, 5, 1) + self.grid0.addWidget(self.custom_offset_label, 14, 0) + self.grid0.addWidget(self.custom_offset_entry, 14, 1) - # V-Dia - self.vdia_label = QtWidgets.QLabel('%s:' % _("V-Dia")) - self.vdia_label.setToolTip( - _("V-Dia.\n" - "Diameter of the tip for V-Shape Tools.")) + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.grid0.addWidget(separator_line, 16, 0, 1, 2) - self.vdia_entry = FCDoubleSpinner() - self.vdia_entry.set_range(0.0000, 9999.9999) - self.vdia_entry.set_precision(self.decimals) - self.vdia_entry.setObjectName('gdb_vdia') + # Cut Z + self.cutz_label = QtWidgets.QLabel('%s:' % _("Cut Z")) + self.cutz_label.setToolTip( + _("Cutting Depth.\n" + "The depth at which to cut into material.")) - self.grid1.addWidget(self.vdia_label, 7, 0) - self.grid1.addWidget(self.vdia_entry, 7, 1) + self.cutz_entry = FCDoubleSpinner() + self.cutz_entry.set_range(-9999.9999, 9999.9999) + self.cutz_entry.set_precision(self.decimals) + self.cutz_entry.setObjectName('gdb_cutz') - # V-Angle - self.vangle_label = QtWidgets.QLabel('%s:' % _("V-Angle")) - self.vangle_label.setToolTip( - _("V-Agle.\n" - "Angle at the tip for the V-Shape Tools.")) + self.grid0.addWidget(self.cutz_label, 18, 0) + self.grid0.addWidget(self.cutz_entry, 18, 1) - self.vangle_entry = FCDoubleSpinner() - self.vangle_entry.set_range(-360.0, 360.0) - self.vangle_entry.set_precision(self.decimals) - self.vangle_entry.setObjectName('gdb_vangle') + # Multi Depth + self.multidepth_label = QtWidgets.QLabel('%s:' % _("MultiDepth")) + self.multidepth_label.setToolTip( + _("Multi Depth.\n" + "Selecting this will allow cutting in multiple passes,\n" + "each pass adding a DPP parameter depth.")) - self.grid1.addWidget(self.vangle_label, 8, 0) - self.grid1.addWidget(self.vangle_entry, 8, 1) + self.multidepth_cb = FCCheckBox() + self.multidepth_cb.setObjectName('gdb_multidepth') - # Feedrate Rapids - self.frapids_label = QtWidgets.QLabel('%s:' % _("FR Rapids")) - self.frapids_label.setToolTip( - _("FR Rapids. Feedrate Rapids\n" - "Speed used while moving as fast as possible.\n" - "This is used only by some devices that can't use\n" - "the G0 g-code command. Mostly 3D printers.")) + self.grid0.addWidget(self.multidepth_label, 20, 0) + self.grid0.addWidget(self.multidepth_cb, 20, 1) - self.frapids_entry = FCDoubleSpinner() - self.frapids_entry.set_range(0.0000, 9999.9999) - self.frapids_entry.set_precision(self.decimals) - self.frapids_entry.setObjectName('gdb_frapids') + # Depth Per Pass + self.dpp_label = QtWidgets.QLabel('%s:' % _("DPP")) + self.dpp_label.setToolTip( + _("DPP. Depth per Pass.\n" + "The value used to cut into material on each pass.")) - self.grid1.addWidget(self.frapids_label, 10, 0) - self.grid1.addWidget(self.frapids_entry, 10, 1) + self.multidepth_entry = FCDoubleSpinner() + self.multidepth_entry.set_range(-9999.9999, 9999.9999) + self.multidepth_entry.set_precision(self.decimals) + self.multidepth_entry.setObjectName('gdb_multidepth_entry') + + self.grid0.addWidget(self.dpp_label, 22, 0) + self.grid0.addWidget(self.multidepth_entry, 22, 1) + + # Travel Z + self.travelz_label = QtWidgets.QLabel('%s:' % _("Travel Z")) + self.travelz_label.setToolTip( + _("Clearance Height.\n" + "Height at which the milling bit will travel between cuts,\n" + "above the surface of the material, avoiding all fixtures.")) + + self.travelz_entry = FCDoubleSpinner() + self.travelz_entry.set_range(-9999.9999, 9999.9999) + self.travelz_entry.set_precision(self.decimals) + self.travelz_entry.setObjectName('gdb_travel') + + self.grid0.addWidget(self.travelz_label, 24, 0) + self.grid0.addWidget(self.travelz_entry, 24, 1) # Extra Cut self.ecut_label = QtWidgets.QLabel('%s:' % _("ExtraCut")) @@ -1447,8 +1356,8 @@ class ToolsDB2UI: self.ecut_cb = FCCheckBox() self.ecut_cb.setObjectName('gdb_ecut') - self.grid1.addWidget(self.ecut_label, 12, 0) - self.grid1.addWidget(self.ecut_cb, 12, 1) + self.grid0.addWidget(self.ecut_label, 26, 0) + self.grid0.addWidget(self.ecut_cb, 26, 1) # Extra Cut Length self.ecut_length_label = QtWidgets.QLabel('%s:' % _("E-Cut Length")) @@ -1465,8 +1374,104 @@ class ToolsDB2UI: self.ecut_length_entry.set_precision(self.decimals) self.ecut_length_entry.setObjectName('gdb_ecut_length') - self.grid1.addWidget(self.ecut_length_label, 13, 0) - self.grid1.addWidget(self.ecut_length_entry, 13, 1) + self.grid0.addWidget(self.ecut_length_label, 28, 0) + self.grid0.addWidget(self.ecut_length_entry, 28, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.grid0.addWidget(separator_line, 30, 0, 1, 2) + + # Feedrate X-Y + self.frxy_label = QtWidgets.QLabel('%s:' % _("Feedrate X-Y")) + self.frxy_label.setToolTip( + _("Feedrate X-Y. Feedrate\n" + "The speed on XY plane used while cutting into material.")) + + self.frxy_entry = FCDoubleSpinner() + self.frxy_entry.set_range(-999999.9999, 999999.9999) + self.frxy_entry.set_precision(self.decimals) + self.frxy_entry.setObjectName('gdb_frxy') + + self.grid0.addWidget(self.frxy_label, 32, 0) + self.grid0.addWidget(self.frxy_entry, 32, 1) + + # Feedrate Z + self.frz_label = QtWidgets.QLabel('%s:' % _("Feedrate Z")) + self.frz_label.setToolTip( + _("Feedrate Z\n" + "The speed on Z plane.")) + + self.frz_entry = FCDoubleSpinner() + self.frz_entry.set_range(-999999.9999, 999999.9999) + self.frz_entry.set_precision(self.decimals) + self.frz_entry.setObjectName('gdb_frz') + + self.grid0.addWidget(self.frz_label, 34, 0) + self.grid0.addWidget(self.frz_entry, 34, 1) + + # Feedrate Rapids + self.frapids_label = QtWidgets.QLabel('%s:' % _("FR Rapids")) + self.frapids_label.setToolTip( + _("FR Rapids. Feedrate Rapids\n" + "Speed used while moving as fast as possible.\n" + "This is used only by some devices that can't use\n" + "the G0 g-code command. Mostly 3D printers.")) + + self.frapids_entry = FCDoubleSpinner() + self.frapids_entry.set_range(0.0000, 9999.9999) + self.frapids_entry.set_precision(self.decimals) + self.frapids_entry.setObjectName('gdb_frapids') + + self.grid0.addWidget(self.frapids_label, 36, 0) + self.grid0.addWidget(self.frapids_entry, 36, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.grid0.addWidget(separator_line, 38, 0, 1, 2) + + # Spindle Spped + self.spindle_label = QtWidgets.QLabel('%s:' % _("Spindle Speed")) + self.spindle_label.setToolTip( + _("Spindle Speed.\n" + "If it's left empty it will not be used.\n" + "The speed of the spindle in RPM.")) + + self.spindle_entry = FCDoubleSpinner() + self.spindle_entry.set_range(-999999.9999, 999999.9999) + self.spindle_entry.set_precision(self.decimals) + self.spindle_entry.setObjectName('gdb_spindle') + + self.grid0.addWidget(self.spindle_label, 40, 0) + self.grid0.addWidget(self.spindle_entry, 40, 1) + + # Dwell + self.dwell_label = QtWidgets.QLabel('%s:' % _("Dwell")) + self.dwell_label.setToolTip( + _("Dwell.\n" + "Check this if a delay is needed to allow\n" + "the spindle motor to reach it's set speed.")) + + self.dwell_cb = FCCheckBox() + self.dwell_cb.setObjectName('gdb_dwell') + + self.grid0.addWidget(self.dwell_label, 42, 0) + self.grid0.addWidget(self.dwell_cb, 42, 1) + + # Dwell Time + self.dwelltime_label = QtWidgets.QLabel('%s:' % _("Dwelltime")) + self.dwelltime_label.setToolTip( + _("Dwell Time.\n" + "A delay used to allow the motor spindle reach it's set speed.")) + + self.dwelltime_entry = FCDoubleSpinner() + self.dwelltime_entry.set_range(0.0000, 9999.9999) + self.dwelltime_entry.set_precision(self.decimals) + self.dwelltime_entry.setObjectName('gdb_dwelltime') + + self.grid0.addWidget(self.dwelltime_label, 44, 0) + self.grid0.addWidget(self.dwelltime_entry, 44, 1) # ########################################################################### # ############### NCC UI form ############################################### @@ -2149,7 +2154,7 @@ class ToolsDB2(QtWidgets.QWidget): # ############################################################################## self.form_fields = { - "object_type": self.ui.object_type_combo, + "tool_target": self.ui.tool_op_combo, "tol_min": self.ui.tol_min_entry, "tol_max": self.ui.tol_max_entry, # Basic @@ -2221,7 +2226,7 @@ class ToolsDB2(QtWidgets.QWidget): } self.name2option = { - "gdb_object_type": "object_type", + "gdb_tool_target": "tool_target", "gdb_tol_min": "tol_min", "gdb_tol_max": "tol_max", @@ -2319,7 +2324,7 @@ class ToolsDB2(QtWidgets.QWidget): self.ui.tree_widget.itemDoubleClicked.connect(self.on_item_double_clicked) - self.ui.object_type_combo.currentIndexChanged.connect(self.on_object_type_changed) + self.ui.tool_op_combo.currentIndexChanged.connect(self.on_object_type_changed) self.setup_db_ui() @@ -2454,22 +2459,25 @@ class ToolsDB2(QtWidgets.QWidget): self.storage_to_form(self.db_tool_dict['1']) # Enable appGUI - self.ui.tool_description_box.setEnabled(True) - self.ui.basic_box.setEnabled(True) - self.ui.advanced_box.setEnabled(True) - self.ui.ncc_box.setEnabled(True) - self.ui.paint_box.setEnabled(True) - self.ui.iso_box.setEnabled(True) - self.ui.drill_box.setEnabled(True) + try: + self.on_object_type_changed(val=self.db_tool_dict['1']['data']['tool_target']) + except KeyError: + self.on_object_type_changed(val=_("General")) self.ui.tree_widget.setCurrentItem(self.ui.tree_widget.topLevelItem(0)) # self.ui.tree_widget.setFocus() else: # Disable appGUI + self.ui.tool_description_box.show() + self.ui.milling_box.show() + self.ui.ncc_box.show() + self.ui.paint_box.show() + self.ui.iso_box.show() + self.ui.drill_box.show() + self.ui.tool_description_box.setEnabled(False) - self.ui.basic_box.setEnabled(False) - self.ui.advanced_box.setEnabled(False) + self.ui.milling_box.setEnabled(False) self.ui.ncc_box.setEnabled(False) self.ui.paint_box.setEnabled(False) self.ui.iso_box.setEnabled(False) @@ -2482,35 +2490,49 @@ class ToolsDB2(QtWidgets.QWidget): def on_object_type_changed(self, index=None, val=None): if val is None: - object_type = self.ui.object_type_combo.get_value() + tool_target = self.ui.tool_op_combo.get_value() else: - object_type = val + tool_target = val self.ui.tool_description_box.setEnabled(True) if self.db_tool_dict: - if object_type == _("General"): - self.ui.basic_box.setEnabled(True) - self.ui.advanced_box.setEnabled(True) + if tool_target == _("General"): + self.ui.milling_box.setEnabled(True) self.ui.ncc_box.setEnabled(True) self.ui.paint_box.setEnabled(True) self.ui.iso_box.setEnabled(True) self.ui.drill_box.setEnabled(True) - if object_type == _("Milling"): - self.ui.basic_box.setEnabled(True) - self.ui.advanced_box.setEnabled(True) - self.ui.ncc_box.setEnabled(False) - self.ui.paint_box.setEnabled(False) - self.ui.iso_box.setEnabled(False) - self.ui.drill_box.setEnabled(False) + self.ui.milling_box.show() + self.ui.ncc_box.show() + self.ui.paint_box.show() + self.ui.iso_box.show() + self.ui.drill_box.show() + else: + self.ui.ncc_box.hide() + self.ui.paint_box.hide() + self.ui.iso_box.hide() + self.ui.drill_box.hide() - if object_type == _("Drilling"): - self.ui.basic_box.setEnabled(False) - self.ui.advanced_box.setEnabled(False) - self.ui.ncc_box.setEnabled(False) - self.ui.paint_box.setEnabled(False) - self.ui.iso_box.setEnabled(False) - self.ui.drill_box.setEnabled(True) + if tool_target == _("Milling"): + self.ui.milling_box.setEnabled(True) + self.ui.milling_box.show() + + if tool_target == _("Drilling"): + self.ui.drill_box.setEnabled(True) + self.ui.drill_box.show() + + if tool_target == _("Isolation"): + self.ui.iso_box.setEnabled(True) + self.ui.iso_box.show() + + if tool_target == _("Paint"): + self.ui.paint_box.setEnabled(True) + self.ui.paint_box.show() + + if tool_target == _("NCC"): + self.ui.ncc_box.setEnabled(True) + self.ui.ncc_box.show() def on_tool_add(self): """ @@ -2542,7 +2564,7 @@ class ToolsDB2(QtWidgets.QWidget): "startz": self.app.defaults["geometry_startz"], "endz": float(self.app.defaults["geometry_endz"]), - "object_type": _("General"), + "tool_target": _("General"), "tol_min": 0.0, "tol_max": 0.0, @@ -2632,7 +2654,7 @@ class ToolsDB2(QtWidgets.QWidget): self.ui.tree_widget.setCurrentItem(last_item) last_item.setSelected(True) - self.on_object_type_changed(val=dict_elem['data']['object_type']) + self.on_object_type_changed(val=dict_elem['data']['tool_target']) self.app.inform.emit('[success] %s' % _("Tool added to DB.")) def on_tool_copy(self): @@ -2966,8 +2988,8 @@ class ToolsDB2(QtWidgets.QWidget): elif wdg_name == "gdb_shape": self.db_tool_dict[tool_id]['tool_type'] = val else: - if wdg_name == "gdb_object_type": - self.db_tool_dict[tool_id]['data']['object_type'] = val + if wdg_name == "gdb_tool_target": + self.db_tool_dict[tool_id]['data']['tool_target'] = val elif wdg_name == "gdb_tol_min": self.db_tool_dict[tool_id]['data']['tol_min'] = val elif wdg_name == "gdb_tol_max": diff --git a/appObjects/FlatCAMGeometry.py b/appObjects/FlatCAMGeometry.py index dbf67354..29fc7668 100644 --- a/appObjects/FlatCAMGeometry.py +++ b/appObjects/FlatCAMGeometry.py @@ -161,7 +161,7 @@ class GeometryObject(FlatCAMObj, Geometry): # Attributes to be included in serialization # Always append to it because it carries contents # from predecessors. - self.ser_attrs += ['options', 'kind', 'tools', 'multigeo'] + self.ser_attrs += ['options', 'kind', 'multigeo', 'fill_color', 'outline_color', 'alpha_level'] def build_ui(self): self.ui_disconnect() diff --git a/appObjects/FlatCAMGerber.py b/appObjects/FlatCAMGerber.py index 8ca63ec2..7c161f48 100644 --- a/appObjects/FlatCAMGerber.py +++ b/appObjects/FlatCAMGerber.py @@ -41,66 +41,6 @@ class GerberObject(FlatCAMObj, Gerber): ui_type = GerberObjectUI - @staticmethod - def merge(grb_list, grb_final): - """ - Merges the geometry of objects in geo_list into - the geometry of geo_final. - - :param grb_list: List of GerberObject Objects to join. - :param grb_final: Destination GeometryObject object. - :return: None - """ - - if grb_final.solid_geometry is None: - grb_final.solid_geometry = [] - grb_final.follow_geometry = [] - - if not grb_final.apertures: - grb_final.apertures = {} - - if type(grb_final.solid_geometry) is not list: - grb_final.solid_geometry = [grb_final.solid_geometry] - grb_final.follow_geometry = [grb_final.follow_geometry] - - for grb in grb_list: - - # Expand lists - if type(grb) is list: - GerberObject.merge(grb_list=grb, grb_final=grb_final) - else: # If not list, just append - for option in grb.options: - if option != 'name': - try: - grb_final.options[option] = grb.options[option] - except KeyError: - log.warning("Failed to copy option.", option) - - try: - for geos in grb.solid_geometry: - grb_final.solid_geometry.append(geos) - grb_final.follow_geometry.append(geos) - except TypeError: - grb_final.solid_geometry.append(grb.solid_geometry) - grb_final.follow_geometry.append(grb.solid_geometry) - - for ap in grb.apertures: - if ap not in grb_final.apertures: - grb_final.apertures[ap] = grb.apertures[ap] - else: - # create a list of integers out of the grb.apertures keys and find the max of that value - # then, the aperture duplicate is assigned an id value incremented with 1, - # and finally made string because the apertures dict keys are strings - max_ap = str(max([int(k) for k in grb_final.apertures.keys()]) + 1) - grb_final.apertures[max_ap] = {} - grb_final.apertures[max_ap]['geometry'] = [] - - for k, v in grb.apertures[ap].items(): - grb_final.apertures[max_ap][k] = deepcopy(v) - - grb_final.solid_geometry = MultiPolygon(grb_final.solid_geometry) - grb_final.follow_geometry = MultiPolygon(grb_final.follow_geometry) - def __init__(self, name): self.decimals = self.app.decimals @@ -1515,6 +1455,66 @@ class GerberObject(FlatCAMObj, Gerber): return gerber_code + @staticmethod + def merge(grb_list, grb_final): + """ + Merges the geometry of objects in geo_list into + the geometry of geo_final. + + :param grb_list: List of GerberObject Objects to join. + :param grb_final: Destination GeometryObject object. + :return: None + """ + + if grb_final.solid_geometry is None: + grb_final.solid_geometry = [] + grb_final.follow_geometry = [] + + if not grb_final.apertures: + grb_final.apertures = {} + + if type(grb_final.solid_geometry) is not list: + grb_final.solid_geometry = [grb_final.solid_geometry] + grb_final.follow_geometry = [grb_final.follow_geometry] + + for grb in grb_list: + + # Expand lists + if type(grb) is list: + GerberObject.merge(grb_list=grb, grb_final=grb_final) + else: # If not list, just append + for option in grb.options: + if option != 'name': + try: + grb_final.options[option] = grb.options[option] + except KeyError: + log.warning("Failed to copy option.", option) + + try: + for geos in grb.solid_geometry: + grb_final.solid_geometry.append(geos) + grb_final.follow_geometry.append(geos) + except TypeError: + grb_final.solid_geometry.append(grb.solid_geometry) + grb_final.follow_geometry.append(grb.solid_geometry) + + for ap in grb.apertures: + if ap not in grb_final.apertures: + grb_final.apertures[ap] = grb.apertures[ap] + else: + # create a list of integers out of the grb.apertures keys and find the max of that value + # then, the aperture duplicate is assigned an id value incremented with 1, + # and finally made string because the apertures dict keys are strings + max_ap = str(max([int(k) for k in grb_final.apertures.keys()]) + 1) + grb_final.apertures[max_ap] = {} + grb_final.apertures[max_ap]['geometry'] = [] + + for k, v in grb.apertures[ap].items(): + grb_final.apertures[max_ap][k] = deepcopy(v) + + grb_final.solid_geometry = MultiPolygon(grb_final.solid_geometry) + grb_final.follow_geometry = MultiPolygon(grb_final.follow_geometry) + def mirror(self, axis, point): Gerber.mirror(self, axis=axis, point=point) self.replotApertures.emit() diff --git a/appParsers/ParseExcellon.py b/appParsers/ParseExcellon.py index d2b61252..3c09c5e7 100644 --- a/appParsers/ParseExcellon.py +++ b/appParsers/ParseExcellon.py @@ -118,7 +118,7 @@ class Excellon(Geometry): # Attributes to be included in serialization # Always append to it because it carries contents # from Geometry. - self.ser_attrs += ['tools', 'zeros', 'excellon_format_upper_mm', 'excellon_format_lower_mm', + self.ser_attrs += ['zeros', 'excellon_format_upper_mm', 'excellon_format_lower_mm', 'excellon_format_upper_in', 'excellon_format_lower_in', 'excellon_units', 'source_file'] # ### Patterns #### diff --git a/appParsers/ParseGerber.py b/appParsers/ParseGerber.py index f002c745..7be1a31c 100644 --- a/appParsers/ParseGerber.py +++ b/appParsers/ParseGerber.py @@ -142,12 +142,6 @@ class Gerber(Geometry): self.source_file = '' - # Attributes to be included in serialization - # Always append to it because it carries contents - # from Geometry. - self.ser_attrs += ['int_digits', 'frac_digits', 'apertures', - 'aperture_macros', 'solid_geometry', 'source_file'] - # ### Parser patterns ## ## # FS - Format Specification # The format of X and Y must be the same! @@ -234,6 +228,11 @@ class Gerber(Geometry): self.use_buffer_for_union = self.app.defaults["gerber_use_buffer_for_union"] + # Attributes to be included in serialization + # Always append to it because it carries contents + # from Geometry. + self.ser_attrs += ['apertures', 'int_digits', 'frac_digits', 'aperture_macros', 'solid_geometry', 'source_file'] + def aperture_parse(self, apertureId, apertureType, apParameters): """ Parse gerber aperture definition into dictionary of apertures. diff --git a/app_Main.py b/app_Main.py index 2401f182..bf717936 100644 --- a/app_Main.py +++ b/app_Main.py @@ -10181,9 +10181,11 @@ class App(QtCore.QObject): pass # Serialize the whole project - d = {"objs": [obj.to_dict() for obj in self.collection.get_list()], - "options": self.options, - "version": self.version} + d = { + "objs": [obj.to_dict() for obj in self.collection.get_list()], + "options": self.options, + "version": self.version + } if self.defaults["global_save_compressed"] is True: with lzma.open(filename, "w", preset=int(self.defaults['global_compression_level'])) as f: diff --git a/camlib.py b/camlib.py index e4257581..d6484d27 100644 --- a/camlib.py +++ b/camlib.py @@ -478,9 +478,6 @@ class Geometry(object): # Final geometry: MultiLineString or list (of LineString or Points) self.follow_geometry = None - # Attributes to be included in serialization - self.ser_attrs = ["units", 'solid_geometry', 'follow_geometry'] - # Flattened geometry (list of paths only) self.flat_geometry = [] @@ -503,6 +500,9 @@ class Geometry(object): from appGUI.PlotCanvasLegacy import ShapeCollectionLegacy self.temp_shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='camlib.geometry') + # Attributes to be included in serialization + self.ser_attrs = ["units", 'solid_geometry', 'follow_geometry', 'tools'] + def plot_temp_shapes(self, element, color='red'): try: