- in 2Sided Plugin clicking LMB and also pressing CTRL+Shift will add the click coordinates to the Drll Alignment Coordinates

- added support for all Plugins to handle the LMB click release event without connect/reconnect of the mouse events
- code refactoring in app_Main file
This commit is contained in:
Marius Stanciu
2021-10-04 17:42:18 +03:00
parent f4636ec71b
commit 411f410025
3 changed files with 221 additions and 115 deletions

View File

@@ -12,6 +12,9 @@ CHANGELOG for FlatCAM beta
- fixed a typo in the Object UI
- in 2Sided Plugin advanced mode fixed the bounds calculation: if no object is selected on canvas then the object selected in Source Object is used
- in 2Sided Plugin added a new typ of alignment drills: manual. This mode will no longer add pairs of drill holes mirrored against reference but only add in place drill holes
- in 2Sided Plugin clicking LMB and also pressing CTRL+Shift will add the click coordinates to the Drll Alignment Coordinates
- added support for all Plugins to handle the LMB click release event without connect/reconnect of the mouse events
- code refactoring in app_Main file
3.10.2021

View File

@@ -118,7 +118,6 @@ class DblSidedTool(AppTool):
self.ui.object_type_combo.currentIndexChanged.connect(self.on_object_type)
self.ui.add_point_button.clicked.connect(self.on_point_add)
self.ui.add_drill_point_button.clicked.connect(self.on_drill_add)
self.ui.delete_drill_point_button.clicked.connect(self.on_drill_delete_last)
self.ui.box_type_radio.activated_custom.connect(self.on_combo_box_type)
@@ -433,21 +432,35 @@ class DblSidedTool(AppTool):
self.app.delete_selection_shape()
self.ui.axis_location.set_value('point')
# set the reference point for mirror
self.ui.point_entry.set_value(center_pt_coords)
self.on_exit()
self.app.inform.emit('[success] %s' % _("Mirror reference point set."))
break
elif event.button == right_button and self.app.event_is_dragging is False:
self.on_exit(cancelled=True)
def on_mouse_plugin_click_release(self):
modifiers = QtWidgets.QApplication.keyboardModifiers()
# if modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier:
# clip_val = self.app.clipboard.text()
# self.ui.point_entry.set_value(clip_val)
if modifiers == QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier:
clip_val = self.app.clipboard.text().replace("[", '').replace("]", '')
self.ui.alignment_holes.set_value(clip_val)
else:
return
self.drill_values = clip_val
def on_exit(self, cancelled=None):
self.app.call_source = "app"
self.app.ui.notebook.setDisabled(False)
self.disconnect_events()
if cancelled is True:
self.app.delete_selection_shape()
self.disconnect_events()
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled by user request."))
def disconnect_events(self):
@@ -506,11 +519,6 @@ class DblSidedTool(AppTool):
(self.decimals, self.app.pos[0], self.decimals, self.app.pos[1])
self.ui.point_entry.set_value(val)
def on_drill_add(self):
self.drill_values += (self.app.defaults["global_point_clipboard_format"] %
(self.decimals, self.app.pos[0], self.decimals, self.app.pos[1])) + ','
self.ui.alignment_holes.set_value(self.drill_values)
def on_drill_delete_last(self):
drill_values_without_last_tupple = self.drill_values.rpartition('(')[0]
self.drill_values = drill_values_without_last_tupple
@@ -897,13 +905,6 @@ class DsidedUI:
"The (x, y) coordinates are captured by pressing SHIFT key\n"
"and left mouse button click on canvas or you can enter the coordinates manually.")
)
# self.add_point_button.setStyleSheet("""
# QPushButton
# {
# font-weight: bold;
# }
# """)
# self.add_point_button.setMinimumWidth(60)
pr_hlay.addWidget(self.point_entry, stretch=1)
pr_hlay.addWidget(self.add_point_button)
@@ -1072,41 +1073,21 @@ class DsidedUI:
"- one drill in mirror position over the axis selected above in the 'Align Axis'.")
)
grid4.addWidget(self.ah_label, 8, 0, 1, 2)
self.alignment_holes = NumericalEvalTupleEntry(border_color='#0069A9')
self.alignment_holes.setPlaceholderText(_("Drill coordinates"))
grid4.addWidget(self.ah_label, 8, 0, 1, 2)
grid4.addWidget(self.alignment_holes, 9, 0, 1, 2)
self.add_drill_point_button = FCButton(_("Add"))
self.add_drill_point_button.setIcon(QtGui.QIcon(self.app.resource_location + '/plus16.png'))
self.add_drill_point_button.setToolTip(
_("Add alignment drill holes coordinates in the format: (x1, y1), (x2, y2), ... \n"
"on one side of the alignment 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.setStyleSheet("""
# QPushButton
# {
# font-weight: bold;
# }
# """)
self.delete_drill_point_button = FCButton(_("Delete Last"))
self.delete_drill_point_button = QtWidgets.QToolButton()
self.delete_drill_point_button.setIcon(QtGui.QIcon(self.app.resource_location + '/trash32.png'))
self.delete_drill_point_button.setToolTip(
_("Delete the last coordinates tuple in the list.")
)
drill_hlay = QtWidgets.QHBoxLayout()
drill_hlay.addWidget(self.add_drill_point_button)
drill_hlay.addWidget(self.delete_drill_point_button)
grid4.addLayout(drill_hlay, 10, 0, 1, 2)
hlay = QtWidgets.QHBoxLayout()
hlay.addWidget(self.alignment_holes)
hlay.addWidget(self.delete_drill_point_button)
grid4.addLayout(hlay, 9, 0, 1, 2)
FCGridLayout.set_common_column_size([obj_grid, grid_bounds, grid_mirror, grid_box_ref, grid4], 0)

View File

@@ -1231,6 +1231,9 @@ class App(QtCore.QObject):
self.corners_tool = None
self.etch_tool = None
# when this list will get populated will contain a list of references to all the Plugins in this APp
self.app_plugins = []
# always install tools only after the shell is initialized because the self.inform.emit() depends on shell
try:
self.install_tools()
@@ -1988,6 +1991,46 @@ class App(QtCore.QObject):
self.pcb_wizard_tool.install(icon=QtGui.QIcon(self.resource_location + '/drill32.png'),
pos=self.ui.menufileimport)
# create a list of plugins references
self.app_plugins = [
self.dblsidedtool,
self.distance_tool,
self.distance_min_tool,
self.panelize_tool,
self.film_tool,
self.paste_tool,
self.calculator_tool,
self.rules_tool,
self.sub_tool,
self.move_tool,
self.cutout_tool,
self.ncclear_tool,
self.paint_tool,
self.isolation_tool,
self.follow_tool,
self.drilling_tool,
self.milling_tool,
self.levelling_tool,
self.optimal_tool,
self.transform_tool,
self.report_tool,
self.pdf_tool,
self.image_tool,
self.pcb_wizard_tool,
self.cal_exc_tool,
self.qrcode_tool,
self.copper_thieving_tool,
self.fiducial_tool,
self.extract_tool,
self.align_objects_tool,
self.punch_tool,
self.invert_tool,
self.corners_tool,
self.etch_tool
]
self.log.debug("Tools are installed.")
def remove_tools(self):
@@ -2012,10 +2055,17 @@ class App(QtCore.QObject):
self.log.debug("init_tools()")
# delete the data currently in the Tools Tab and the Tab itself
widget = QtWidgets.QTabWidget.widget(self.ui.notebook, 2)
found_idx = None
for tab_idx in range(self.ui.notebook.count()):
if self.ui.notebook.widget(tab_idx).objectName() == "plugin_tab":
found_idx = tab_idx
print(found_idx)
break
remove_idx = found_idx if found_idx else 2
widget = QtWidgets.QTabWidget.widget(self.ui.notebook, remove_idx)
if widget is not None:
widget.deleteLater()
self.ui.notebook.removeTab(2)
self.ui.notebook.removeTab(remove_idx)
# rebuild the Tools Tab
# self.ui.plugin_tab = QtWidgets.QWidget()
@@ -2677,7 +2727,7 @@ class App(QtCore.QObject):
break
if found_idx:
self.ui.notebook.setCurrentWidget(self.ui.properties_tab)
self.ui.notebook.removeTab(2)
self.ui.notebook.removeTab(found_idx)
if edited_obj.kind == 'geometry':
obj_type = "Geometry"
@@ -6701,7 +6751,7 @@ class App(QtCore.QObject):
break
if found_idx:
self.ui.notebook.setCurrentWidget(self.ui.properties_tab)
self.ui.notebook.removeTab(2)
self.ui.notebook.removeTab(found_idx)
# HACK: the content was removed but let's create it again
self.ui.plugin_tab = QtWidgets.QWidget()
@@ -6759,7 +6809,7 @@ class App(QtCore.QObject):
self.app_obj.object_changed.emit(obj)
self.inform.emit('[success] %s.' % _("Flip on Y axis done"))
except Exception as e:
self.app.inform.emit('[ERROR_NOTCL] %s: %s.' % (_("Action was not executed"), str(e)))
self.inform.emit('[ERROR_NOTCL] %s: %s.' % (_("Action was not executed"), str(e)))
return
def on_flipx(self):
@@ -6805,7 +6855,7 @@ class App(QtCore.QObject):
self.app_obj.object_changed.emit(obj)
self.inform.emit('[success] %s.' % _("Flip on X axis done"))
except Exception as e:
self.app.inform.emit('[ERROR_NOTCL] %s: %s.' % (_("Action was not executed"), str(e)))
self.inform.emit('[ERROR_NOTCL] %s: %s.' % (_("Action was not executed"), str(e)))
return
def on_rotate(self, silent=False, preset=None):
@@ -7310,49 +7360,32 @@ class App(QtCore.QObject):
# if the released mouse button was RMB then test if it was a panning motion or not, if not it was a context
# canvas menu
if event.button == right_button and self.ui.popMenu.mouse_is_panning is False: # right click
self.ui.popMenu.mouse_is_panning = False
if self.inhibit_context_menu is False:
self.cursor = QtGui.QCursor()
self.populate_cmenu_grids()
self.ui.popMenu.popup(self.cursor.pos())
self.on_mouse_context_menu()
# if the released mouse button was LMB then test if we had a right-to-left selection or a left-to-right
# selection and then select a type of selection ("enclosing" or "touching")
if event.button == 1: # left click
modifiers = QtWidgets.QApplication.keyboardModifiers()
# If the SHIFT key is pressed when LMB is clicked then the coordinates are copied to clipboard
if modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier:
# do not auto open the Project Tab
self.click_noproject = True
key_modifier = QtWidgets.QApplication.keyboardModifiers()
shift_modifier_key = QtCore.Qt.KeyboardModifier.ShiftModifier
ctrl_modifier_key = QtCore.Qt.KeyboardModifier.ControlModifier
ctrl_shift_modifier_key = ctrl_modifier_key | shift_modifier_key
self.clipboard.setText(
self.defaults["global_point_clipboard_format"] %
(self.decimals, self.pos[0], self.decimals, self.pos[1])
)
self.inform.emit('[success] %s' % _("Coordinates copied to clipboard."))
if key_modifier == shift_modifier_key or key_modifier == ctrl_shift_modifier_key:
self.on_mouse_and_key_modifiers(position=self.pos, modifiers=key_modifier)
self.on_mouse_plugin_click_release()
return
else:
self.on_mouse_plugin_click_release()
# the object selection on canvas does not work for App Tools or for Editors
# the object selection on canvas will not work for App Tools or for Editors
if self.call_source != 'app':
return
if self.doubleclick is True:
self.doubleclick = False
if self.collection.get_selected():
self.ui.notebook.setCurrentWidget(self.ui.properties_tab)
if self.ui.splitter.sizes()[0] == 0:
self.ui.splitter.setSizes([1, 1])
try:
# delete the selection shape(S) as it may be in the way
self.delete_selection_shape()
self.delete_hover_shape()
except Exception as e:
self.log.error(
"FlatCAMApp.on_mouse_click_release_over_plot() double click --> Error: %s" % str(e))
self.on_mouse_double_click()
return
else:
# WORKAROUND for LEGACY MODE
if self.is_legacy is True:
# if there is no move on canvas then we have no dragging selection
@@ -7367,22 +7400,19 @@ class App(QtCore.QObject):
self.log.error(
"FlatCAMApp.on_mouse_click_release_over_plot() select area --> Error: %s" % str(e))
return
else:
key_modifier = QtWidgets.QApplication.keyboardModifiers()
if key_modifier == QtCore.Qt.KeyboardModifier.ShiftModifier:
if key_modifier == shift_modifier_key:
mod_key = 'Shift'
elif key_modifier == QtCore.Qt.KeyboardModifier.ControlModifier:
elif key_modifier == ctrl_modifier_key:
mod_key = 'Control'
else:
mod_key = None
try:
if self.command_active is None:
# If the CTRL key is pressed when the LMB is clicked then if the object is selected it will
# deselect, and if it's not selected then it will be selected
# If there is no active command (self.command_active is None) then we check if we clicked
# on a object by checking the bounding limits against mouse click position
if mod_key == self.defaults["global_mselect_key"]:
# If the modifier key is pressed when the LMB is clicked then if the object is selected it will
# deselect, and if it's not selected then it will be selected
self.select_objects(key='multisel')
else:
# If there is no active command (self.command_active is None) then we check if
@@ -7395,6 +7425,79 @@ class App(QtCore.QObject):
"FlatCAMApp.on_mouse_click_release_over_plot() select click --> Error: %s" % str(e))
return
def on_mouse_double_click(self):
"""
Called when mouse double clicking on canvas.
:return:
"""
self.doubleclick = False
if self.collection.get_selected():
self.ui.notebook.setCurrentWidget(self.ui.properties_tab)
if self.ui.splitter.sizes()[0] == 0:
self.ui.splitter.setSizes([1, 1])
try:
# delete the selection shape(S) as it may be in the way
self.delete_selection_shape()
self.delete_hover_shape()
except Exception as e:
self.log.error(
"FlatCAMApp.on_mouse_click_release_over_plot() double click --> Error: %s" % str(e))
def on_mouse_and_key_modifiers(self, position, modifiers):
"""
Called when the mouse is left-clicked on canvas and simultaneously a key modifier
(Ctrl, AAlt, Shift) is pressed.
:param position: A tupple made of the clicked position x, y coordinates
:param modifiers: Key modifiers (Ctrl, Alt, Shift or a combination of them)
:return:
"""
# If the SHIFT key is pressed when LMB is clicked then the coordinates are copied to clipboard
if modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier:
# do not auto open the Project Tab
self.click_noproject = True
self.clipboard.setText(
self.defaults["global_point_clipboard_format"] %
(self.decimals,position[0], self.decimals, position[1])
)
self.inform.emit('[success] %s' % _("Coordinates copied to clipboard."))
elif modifiers == QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier:
try:
old_clipb = eval(self.clipboard.text())
except Exception as err:
# self.log.error("App.on_mouse_and_key_modifiers() --> %s" % str(err))
old_clipb = None
clip_pos_val = (
self.dec_format(position[0], self.decimals),
self.dec_format(position[1], self.decimals)
)
clip_text = "(%s, %s)" % (str(clip_pos_val[0]), str(clip_pos_val[1]))
if old_clipb is None or old_clipb == '':
self.clipboard.setText(clip_text)
else:
if isinstance(old_clipb, list):
old_clipb.append(clip_pos_val)
else:
old_clipb = [old_clipb, clip_pos_val]
self.clipboard.setText(str(old_clipb))
self.inform.emit('[success] %s' % _("Coordinates copied to clipboard."))
def on_mouse_context_menu(self):
"""
Display a context menu when mouse right-clicking on canvas.
:return:
"""
if self.inhibit_context_menu is False:
self.cursor = QtGui.QCursor()
self.populate_cmenu_grids()
self.ui.popMenu.popup(self.cursor.pos())
def selection_area_handler(self, start_pos, end_pos, sel_type):
"""
Called when the mouse selects by dragging left mouse button on canvas.
@@ -7613,6 +7716,25 @@ class App(QtCore.QObject):
tx=_("selected"))
)
def on_mouse_plugin_click_release(self):
"""
Handle specific tasks in the Plugins for the mouse click release
:return:
"""
if self.ui.notebook.currentWidget().objectName() == "plugin_tab":
tab_idx = self.ui.notebook.currentIndex()
for plugin in self.app_plugins:
# execute this only for the current active plugin
if self.ui.notebook.tabText(tab_idx) == plugin.pluginName:
try:
plugin.on_mouse_plugin_click_release()
except AttributeError:
# not all plugins have this implemented
# print("This does not have it", self.ui.notebook.tabText(tab_idx))
pass
def delete_hover_shape(self):
self.hover_shapes.clear()
self.hover_shapes.redraw()