diff --git a/FlatCAMApp.py b/FlatCAMApp.py
index 4dd26bdb..efa14441 100644
--- a/FlatCAMApp.py
+++ b/FlatCAMApp.py
@@ -336,6 +336,7 @@ class App(QtCore.QObject):
"global_tolerance": self.ui.general_defaults_form.general_app_group.tol_entry,
"global_open_style": self.ui.general_defaults_form.general_app_group.open_style_cb,
+ "global_delete_confirmation": self.ui.general_defaults_form.general_app_group.delete_conf_cb,
"global_compression_level": self.ui.general_defaults_form.general_app_group.compress_combo,
"global_save_compressed": self.ui.general_defaults_form.general_app_group.save_type_cb,
@@ -455,6 +456,12 @@ class App(QtCore.QObject):
"excellon_editor_circ_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_dir_radio,
"excellon_editor_circ_angle":
self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_angle_entry,
+ "excellon_editor_slot_direction":
+ self.ui.excellon_defaults_form.excellon_editor_group.slot_axis_radio,
+ "excellon_editor_slot_angle":
+ self.ui.excellon_defaults_form.excellon_editor_group.slot_angle_spinner,
+ "excellon_editor_slot_length":
+ self.ui.excellon_defaults_form.excellon_editor_group.slot_length_entry,
# Geometry General
"geometry_plot": self.ui.geometry_defaults_form.geometry_gen_group.plot_cb,
@@ -649,6 +656,7 @@ class App(QtCore.QObject):
"global_worker_number": 2,
"global_tolerance": 0.01,
"global_open_style": True,
+ "global_delete_confirmation": True,
"global_compression_level": 3,
"global_save_compressed": True,
@@ -800,6 +808,9 @@ class App(QtCore.QObject):
"excellon_editor_lin_angle": 0.0,
"excellon_editor_circ_dir": 'CW',
"excellon_editor_circ_angle": 12,
+ "excellon_editor_slot_direction": 'X',
+ "excellon_editor_slot_angle": 0.0,
+ "excellon_editor_slot_length": 5.0,
# Geometry General
"geometry_plot": True,
@@ -4894,33 +4905,51 @@ class App(QtCore.QObject):
"""
self.report_usage("on_delete()")
+ response = None
+ bt_ok = None
+
# Make sure that the deletion will happen only after the Editor is no longer active otherwise we might delete
# a geometry object before we update it.
if self.geo_editor.editor_active is False and self.exc_editor.editor_active is False:
- if self.collection.get_active():
- self.log.debug("App.on_delete()")
+ if self.defaults["global_delete_confirmation"] is True:
+ msgbox = QtWidgets.QMessageBox()
+ msgbox.setWindowTitle(_("Delete objects"))
+ msgbox.setWindowIcon(QtGui.QIcon('share/deleteshape32.png'))
+ # msgbox.setText(_("Delete FlatCAM objects ..."))
+ msgbox.setText(_("Are you sure you want to permanently delete\n"
+ "the selected objects?"))
+ bt_ok = msgbox.addButton(_('Ok'), QtWidgets.QMessageBox.AcceptRole)
+ bt_cancel = msgbox.addButton(_('Cancel'), QtWidgets.QMessageBox.RejectRole)
- while self.collection.get_active():
- obj_active = self.collection.get_active()
- # if the deleted object is FlatCAMGerber then make sure to delete the possible mark shapes
- if isinstance(obj_active, FlatCAMGerber):
- for el in obj_active.mark_shapes:
- obj_active.mark_shapes[el].clear(update=True)
- obj_active.mark_shapes[el].enabled = False
- obj_active.mark_shapes[el] = None
- elif isinstance(obj_active, FlatCAMCNCjob):
- try:
- obj_active.annotation.clear(update=True)
- obj_active.annotation.enabled = False
- except AttributeError:
- pass
- self.delete_first_selected()
+ msgbox.setDefaultButton(bt_ok)
+ msgbox.exec_()
+ response = msgbox.clickedButton()
- self.inform.emit(_("Object(s) deleted ..."))
- # make sure that the selection shape is deleted, too
- self.delete_selection_shape()
- else:
- self.inform.emit(_("Failed. No object(s) selected..."))
+ if response == bt_ok or self.defaults["global_delete_confirmation"] is False:
+ if self.collection.get_active():
+ self.log.debug("App.on_delete()")
+
+ while self.collection.get_active():
+ obj_active = self.collection.get_active()
+ # if the deleted object is FlatCAMGerber then make sure to delete the possible mark shapes
+ if isinstance(obj_active, FlatCAMGerber):
+ for el in obj_active.mark_shapes:
+ obj_active.mark_shapes[el].clear(update=True)
+ obj_active.mark_shapes[el].enabled = False
+ obj_active.mark_shapes[el] = None
+ elif isinstance(obj_active, FlatCAMCNCjob):
+ try:
+ obj_active.annotation.clear(update=True)
+ obj_active.annotation.enabled = False
+ except AttributeError:
+ pass
+ self.delete_first_selected()
+
+ self.inform.emit(_("Object(s) deleted ..."))
+ # make sure that the selection shape is deleted, too
+ self.delete_selection_shape()
+ else:
+ self.inform.emit(_("Failed. No object(s) selected..."))
else:
self.inform.emit(_("Save the work in Editor and try again ..."))
diff --git a/README.md b/README.md
index 29c43327..719c7b07 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
=================================================
+15.08.2019
+
+- added Edit -> Preferences GUI and storage for the Excellon Editor Add Slots
+- added a confirmation message for objects delete and a setting to activate it in Edit -> Preferences -> Global
+
14.08.2019
- fixed the loading of Excellon with slots and the saving of edited Excellon object in regard of slots, in Excellon Editor
diff --git a/flatcamEditors/FlatCAMExcEditor.py b/flatcamEditors/FlatCAMExcEditor.py
index 0fb03cb5..2a4119f7 100644
--- a/flatcamEditors/FlatCAMExcEditor.py
+++ b/flatcamEditors/FlatCAMExcEditor.py
@@ -1905,9 +1905,9 @@ class FlatCAMExcEditor(QtCore.QObject):
self.drill_direction_radio.set_value(self.app.defaults['excellon_editor_circ_dir'])
self.drill_angle_entry.set_value(float(self.app.defaults['excellon_editor_circ_angle']))
- self.slot_length_entry.set_value(1.0)
- self.slot_axis_radio.set_value('X')
- self.slot_angle_spinner.set_value(0.0)
+ self.slot_length_entry.set_value(float(self.app.defaults['excellon_editor_slot_length']))
+ self.slot_axis_radio.set_value(self.app.defaults['excellon_editor_slot_direction'])
+ self.slot_angle_spinner.set_value(float(self.app.defaults['excellon_editor_slot_angle']))
def build_ui(self, first_run=None):
diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py
index 2dbb0911..f557fe9c 100644
--- a/flatcamGUI/FlatCAMGUI.py
+++ b/flatcamGUI/FlatCAMGUI.py
@@ -4062,7 +4062,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
# to the main layout of this TAB
self.layout.addLayout(self.form_box)
- # Save compressed project CB
+ # Open behavior
self.open_style_cb = FCCheckBox(_('"Open" behavior'))
self.open_style_cb.setToolTip(
_("When checked the path for the last saved file is used when saving files,\n"
@@ -4073,6 +4073,15 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
# self.advanced_cb.setLayoutDirection(QtCore.Qt.RightToLeft)
self.layout.addWidget(self.open_style_cb)
+ # Delete confirmation
+ self.delete_conf_cb = FCCheckBox(_('Delete object confirmation'))
+ self.delete_conf_cb.setToolTip(
+ _("When checked the application will ask for user confirmation\n"
+ "whenever the Delete object(s) event is triggered, either by\n"
+ "menu shortcut or key shortcut.")
+ )
+ self.layout.addWidget(self.delete_conf_cb)
+
# Save compressed project CB
self.save_type_cb = FCCheckBox(_('Save Compressed Project'))
self.save_type_cb.setToolTip(
@@ -5245,6 +5254,54 @@ class ExcellonEditorPrefGroupUI(OptionsGroupUI):
grid0.addWidget(self.drill_circular_angle_label, 9, 0)
grid0.addWidget(self.drill_circular_angle_entry, 9, 1)
+ self.drill_array_circ_label = QtWidgets.QLabel(_('Slots:'))
+ grid0.addWidget(self.drill_array_circ_label, 10, 0, 1, 2)
+
+ # Slot length
+ self.slot_length_label = QtWidgets.QLabel(_('Length:'))
+ self.slot_length_label.setToolTip(
+ _("Length = The length of the slot.")
+ )
+ self.slot_length_label.setMinimumWidth(100)
+
+ self.slot_length_entry = LengthEntry()
+ grid0.addWidget(self.slot_length_label, 11, 0)
+ grid0.addWidget(self.slot_length_entry, 11, 1)
+
+ # Slot direction
+ self.slot_axis_label = QtWidgets.QLabel(_('Direction:'))
+ self.slot_axis_label.setToolTip(
+ _("Direction on which the slot is oriented:\n"
+ "- 'X' - horizontal axis \n"
+ "- 'Y' - vertical axis or \n"
+ "- 'Angle' - a custom angle for the slot inclination")
+ )
+ self.slot_axis_label.setMinimumWidth(100)
+
+ self.slot_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'},
+ {'label': _('Y'), 'value': 'Y'},
+ {'label': _('Angle'), 'value': 'A'}])
+ grid0.addWidget(self.slot_axis_label, 12, 0)
+ grid0.addWidget(self.slot_axis_radio, 12, 1)
+
+ # Slot custom angle
+ self.slot_angle_label = QtWidgets.QLabel(_('Angle:'))
+ self.slot_angle_label.setToolTip(
+ _("Angle at which the slot is placed.\n"
+ "The precision is of max 2 decimals.\n"
+ "Min value is: -359.99 degrees.\n"
+ "Max value is: 360.00 degrees.")
+ )
+ self.slot_angle_label.setMinimumWidth(100)
+
+ self.slot_angle_spinner = FCDoubleSpinner()
+ self.slot_angle_spinner.set_precision(2)
+ self.slot_angle_spinner.setWrapping(True)
+ self.slot_angle_spinner.setRange(-359.99, 360.00)
+ self.slot_angle_spinner.setSingleStep(1.0)
+ grid0.addWidget(self.slot_angle_label, 13, 0)
+ grid0.addWidget(self.slot_angle_spinner, 13, 1)
+
self.layout.addStretch()
diff --git a/share/slot26.png b/share/slot26.png
index 687efbbb..633a63bc 100644
Binary files a/share/slot26.png and b/share/slot26.png differ