From e6c0046e3f193fb89e2cb5589d807910a1856c10 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Wed, 13 Oct 2021 14:39:47 +0300 Subject: [PATCH] - added a method to do cleanup after a Plugin close - in Distance Plugin added the cleanup after the Plugin is closed from the Tab close button - renamed the Distance Minimum Plugin to Object Distance; started to add new functionality on this Plugin: to calculate the distance between the bounding box centers too --- CHANGELOG.md | 5 +- appPlugins/ToolDblSided.py | 4 +- appPlugins/ToolDistance.py | 4 +- ...olDistanceMin.py => ToolObjectDistance.py} | 73 +++++++++++++++---- appPlugins/__init__.py | 2 +- appTool.py | 8 +- app_Main.py | 29 ++++++-- 7 files changed, 95 insertions(+), 30 deletions(-) rename appPlugins/{ToolDistanceMin.py => ToolObjectDistance.py} (88%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d6f11f1..c840de31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ CHANGELOG for FlatCAM beta - in Distance Plugin - the Dx, Dy, Angle and Distance values are updated real time (for non multi segment measurement) - in Distance Plugin - Distance value is now updated real time regardless of the Multi Point setting - in Distance Minimum Plugin - upgraded the UI +- added a method to do cleanup after a Plugin close +- in Distance Plugin added the cleanup after the Plugin is closed from the Tab close button +- renamed the Distance Minimum Plugin to Object Distance; started to add new functionality on this Plugin: to calculate the distance between the bounding box centers too 12.10.2021 @@ -1686,7 +1689,7 @@ RELEASE 8.994 - in Tools: Image, InvertGerber, Optimal, PcbWizard - moved the Tool UI in its own class - Tool Isolation - made sure that the app can load from Tools Database only tools marked for Isolation tool - Tool Isolation - on Tool start it will attempt to load the Preferences set tools by diameter from Tools Database. If it can't find one there it will add a default tool. -- in Tools: Transform, SUb, RulesCheck, DistanceMin, Distance - moved the Tool UI in its own class +- in Tools: Transform, SUb, RulesCheck, ObjectDistance, Distance - moved the Tool UI in its own class - some small fixes - fixed a borderline issue in CNCJob UI Autolevelling - Voronoi polygons calculations diff --git a/appPlugins/ToolDblSided.py b/appPlugins/ToolDblSided.py index f5ed7a24..14126763 100644 --- a/appPlugins/ToolDblSided.py +++ b/appPlugins/ToolDblSided.py @@ -449,7 +449,7 @@ class DblSidedTool(AppTool): 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, pos): + def on_plugin_mouse_click_release(self, pos): modifiers = QtWidgets.QApplication.keyboardModifiers() # if modifiers == QtCore.Qt.KeyboardModifier.ShiftModifier: # clip_val = self.app.clipboard.text() @@ -461,7 +461,7 @@ class DblSidedTool(AppTool): try: eval_clip_val = eval(clip_val) except Exception as err: - self.app.log.debug("DblSidedTool.on_mouse_plugin_click_release() --> %s" % str(err)) + self.app.log.debug("DblSidedTool.on_plugin_mouse_click_release() --> %s" % str(err)) return if alignment_holes == '' or alignment_holes is None: diff --git a/appPlugins/ToolDistance.py b/appPlugins/ToolDistance.py index 2998e348..2d01c2ab 100644 --- a/appPlugins/ToolDistance.py +++ b/appPlugins/ToolDistance.py @@ -675,8 +675,8 @@ class Distance(AppTool): return storage - # def set_meas_units(self, units): - # self.meas.units_label.setText("[" + self.app.options["units"].lower() + "]") + def on_plugin_cleanup(self): + self.on_exit() class DistanceUI: diff --git a/appPlugins/ToolDistanceMin.py b/appPlugins/ToolObjectDistance.py similarity index 88% rename from appPlugins/ToolDistanceMin.py rename to appPlugins/ToolObjectDistance.py index d5985f91..976a48e0 100644 --- a/appPlugins/ToolDistanceMin.py +++ b/appPlugins/ToolObjectDistance.py @@ -7,11 +7,12 @@ from PyQt6 import QtWidgets, QtCore from appTool import AppTool -from appGUI.GUIElements import FCEntry, FCLabel, FCButton, VerticalScrollArea, FCGridLayout, FCFrame +from appGUI.GUIElements import FCEntry, FCLabel, FCButton, VerticalScrollArea, FCGridLayout, FCFrame, FCComboBox2 from shapely.ops import nearest_points from shapely.geometry import Point, MultiPolygon from shapely.ops import unary_union +from copy import deepcopy import math import logging @@ -26,7 +27,7 @@ if '_' not in builtins.__dict__: log = logging.getLogger('base') -class DistanceMin(AppTool): +class ObjectDistance(AppTool): def __init__(self, app): AppTool.__init__(self, app) @@ -36,10 +37,13 @@ class DistanceMin(AppTool): self.units = self.app.app_units.lower() self.decimals = self.app.decimals + self.active = False + self.original_call_source = None + # ############################################################################# # ######################### Tool GUI ########################################## # ############################################################################# - self.ui = DistMinUI(layout=self.layout, app=self.app) + self.ui = ObjectDistanceUI(layout=self.layout, app=self.app) self.pluginName = self.ui.pluginName self.h_point = (0, 0) @@ -48,7 +52,9 @@ class DistanceMin(AppTool): self.ui.jump_hp_btn.clicked.connect(self.on_jump_to_half_point) def run(self, toggle=False): - self.app.defaults.report_usage("ToolDistanceMin()") + # if the plugin was already launched do not do it again + if self.active is True: + return if self.app.plugin_tab_locked is True: return @@ -61,8 +67,9 @@ class DistanceMin(AppTool): pass self.set_tool_ui() - self.app.inform.emit('MEASURING: %s' % - _("Select two objects and no more, to measure the distance between them ...")) + + # activate the plugin + self.activate_measure_tool() def install(self, icon=None, separator=None, **kwargs): AppTool.install(self, icon, separator, shortcut='Shift+M', **kwargs) @@ -90,7 +97,7 @@ class DistanceMin(AppTool): # focus on Tool Tab self.app.ui.notebook.setCurrentWidget(self.app.ui.plugin_tab) - self.app.ui.notebook.setTabText(2, _("Minimum Distance")) + self.app.ui.notebook.setTabText(2, _("Object Distance")) # Remove anything else in the appGUI self.app.ui.plugin_scroll_area.takeWidget() @@ -104,6 +111,9 @@ class DistanceMin(AppTool): self.units = self.app.app_units.lower() # initial view of the layout + self.init_plugin() + + def init_plugin(self): self.ui.start_entry.set_value('(0, 0)') self.ui.stop_entry.set_value('(0, 0)') @@ -115,7 +125,7 @@ class DistanceMin(AppTool): self.ui.jump_hp_btn.setDisabled(True) - log.debug("Minimum Distance Tool --> tool initialized") + self.active = True def activate_measure_tool(self): # ENABLE the Measuring TOOL @@ -123,6 +133,8 @@ class DistanceMin(AppTool): self.units = self.app.app_units.lower() + self.original_call_source = deepcopy(self.app.call_source) + if self.app.call_source == 'app': selected_objs = self.app.collection.get_selected() if len(selected_objs) != 2: @@ -184,7 +196,7 @@ class DistanceMin(AppTool): else: first_pos, last_pos = nearest_points(selected_objs[0].geo['solid'], selected_objs[1].geo['solid']) else: - first_pos, last_pos = 0, 0 + first_pos, last_pos = Point((0, 0)), Point((0, 0)) self.ui.start_entry.set_value("(%.*f, %.*f)" % (self.decimals, first_pos.x, self.decimals, first_pos.y)) self.ui.stop_entry.set_value("(%.*f, %.*f)" % (self.decimals, last_pos.x, self.decimals, last_pos.y)) @@ -228,19 +240,23 @@ class DistanceMin(AppTool): (_("Objects intersects or touch at"), "(%.*f, %.*f)" % (self.decimals, self.h_point[0], self.decimals, self.h_point[1]))) + self.active = False + def on_jump_to_half_point(self): self.app.on_jump_to(custom_location=self.h_point) self.app.inform.emit('[success] %s: %s' % (_("Jumped to the half point between the two selected objects"), "(%.*f, %.*f)" % (self.decimals, self.h_point[0], self.decimals, self.h_point[1]))) - # def set_meas_units(self, units): - # self.meas.units_label.setText("[" + self.app.options["units"].lower() + "]") + def on_plugin_cleanup(self): + self.active = False + self.app.call_source = self.original_call_source + self.app.inform.emit('%s' % _("Done.")) -class DistMinUI: +class ObjectDistanceUI: - pluginName = _("Minimum Distance") + pluginName = _("Object Distance") def __init__(self, layout, app): self.app = app @@ -252,6 +268,35 @@ class DistMinUI: title_label = FCLabel("%s
" % self.pluginName) self.layout.addWidget(title_label) + # ############################################################################################################# + # Parameters Frame + # ############################################################################################################# + self.param_label = FCLabel('%s' % _('Parameters')) + self.param_label.setToolTip( + _("Parameters used for this tool.") + ) + self.layout.addWidget(self.param_label) + + par_frame = FCFrame() + self.layout.addWidget(par_frame) + + param_grid = FCGridLayout(v_spacing=5, h_spacing=3) + par_frame.setLayout(param_grid) + + # Distance Type + + self.distance_type_label = FCLabel("%s:" % _("Type")) + self.distance_type_label.setToolTip( + _("The type of distance to be calculated.\n" + "- Nearest points - minimal distance between objects\n" + "- Center points - distance between the center of the bounding boxes") + ) + + self.distance_type_combo = FCComboBox2() + self.distance_type_combo.addItems([_("Nearest points"), _("Center points")]) + param_grid.addWidget(self.distance_type_label, 0, 0) + param_grid.addWidget(self.distance_type_combo, 0, 1) + # ############################################################################################################# # Coordinates Frame # ############################################################################################################# @@ -386,7 +431,7 @@ class DistMinUI: self.jump_hp_btn.setDisabled(True) self.layout.addWidget(self.jump_hp_btn) - FCGridLayout.set_common_column_size([coords_grid, res_grid], 0) + FCGridLayout.set_common_column_size([param_grid, coords_grid, res_grid], 0) self.layout.addStretch(1) # #################################### FINSIHED GUI ########################### diff --git a/appPlugins/__init__.py b/appPlugins/__init__.py index ffee9ea6..2986064a 100644 --- a/appPlugins/__init__.py +++ b/appPlugins/__init__.py @@ -10,7 +10,7 @@ from appPlugins.ToolFilm import Film from appPlugins.ToolImage import ToolImage from appPlugins.ToolDistance import Distance -from appPlugins.ToolDistanceMin import DistanceMin +from appPlugins.ToolObjectDistance import ObjectDistance from appPlugins.ToolMove import ToolMove diff --git a/appTool.py b/appTool.py index b232e8e1..8d2a3d94 100644 --- a/appTool.py +++ b/appTool.py @@ -295,11 +295,15 @@ class AppTool(QtWidgets.QWidget): s_storage.clear() s_storage.redraw() - def on_mouse_plugin_click_release(self, pos): + def on_plugin_mouse_click_release(self, pos): # this should be implemented in the descendants, the Plugin classes pass - def on_mouse_plugin_move(self, pos): + def on_plugin_mouse_move(self, pos): + # this should be implemented in the descendants, the Plugin classes + pass + + def on_plugin_cleanup(self): # this should be implemented in the descendants, the Plugin classes pass diff --git a/app_Main.py b/app_Main.py index d3bf2641..318e0a40 100644 --- a/app_Main.py +++ b/app_Main.py @@ -1866,7 +1866,7 @@ class App(QtCore.QObject): before=self.ui.menueditorigin, separator=False) - self.distance_min_tool = DistanceMin(self) + self.distance_min_tool = ObjectDistance(self) self.distance_min_tool.install(icon=QtGui.QIcon(self.resource_location + '/distance_min16.png'), pos=self.ui.menuedit, before=self.ui.menueditorigin, @@ -6760,6 +6760,19 @@ class App(QtCore.QObject): found_idx = idx break if found_idx: + # ######################################################################################################### + # first do the Plugin cleanup + # ######################################################################################################### + for plugin in self.app_plugins: + # execute this only for the current active plugin + if self.ui.notebook.tabText(found_idx) != plugin.pluginName: + continue + try: + plugin.on_plugin_cleanup() + except AttributeError: + # not all plugins have this implemented + # print("This does not have it", self.ui.notebook.tabText(tab_idx)) + pass self.ui.notebook.setCurrentWidget(self.ui.properties_tab) self.ui.notebook.removeTab(found_idx) @@ -7242,7 +7255,7 @@ class App(QtCore.QObject): self.pos_jump = event_pos self.ui.popMenu.mouse_is_panning = False - self.on_mouse_plugin_move(pos=event_pos) + self.on_plugin_mouse_move(pos=event_pos) if origin_click is None: # if the RMB is clicked and mouse is moving over plot then 'panning_action' is True @@ -7384,10 +7397,10 @@ class App(QtCore.QObject): 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(pos=pos) + self.on_plugin_mouse_click_release(pos=pos) return else: - self.on_mouse_plugin_click_release(pos=pos) + self.on_plugin_mouse_click_release(pos=pos) # the object selection on canvas will not work for App Tools or for Editors if self.call_source != 'app': @@ -7736,7 +7749,7 @@ class App(QtCore.QObject): tx=_("selected")) ) - def on_mouse_plugin_click_release(self, pos): + def on_plugin_mouse_click_release(self, pos): """ Handle specific tasks in the Plugins for the mouse click release @@ -7754,13 +7767,13 @@ class App(QtCore.QObject): if self.ui.notebook.tabText(tab_idx) != plugin.pluginName: continue try: - plugin.on_mouse_plugin_click_release(pos) + plugin.on_plugin_mouse_click_release(pos) except AttributeError: # not all plugins have this implemented # print("This does not have it", self.ui.notebook.tabText(tab_idx)) pass - def on_mouse_plugin_move(self, pos): + def on_plugin_mouse_move(self, pos): """ Handle specific tasks in the Plugins for the mouse move @@ -7778,7 +7791,7 @@ class App(QtCore.QObject): if self.ui.notebook.tabText(tab_idx) != plugin.pluginName: continue try: - plugin.on_mouse_plugin_move(pos) + plugin.on_plugin_mouse_move(pos) except AttributeError: # not all plugins have this implemented # print("This does not have it", self.ui.notebook.tabText(tab_idx))