From ca1a10585abd9030cbf2a02089d3c5da6ec29f73 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Fri, 16 Feb 2024 10:56:10 +0100 Subject: [PATCH] Draft: fix wrong selection after commands (improved) The previous fix was not correct. Some commands would cause a crash and several files were missed. Forum topic reporting a crash: https://forum.freecad.org/viewtopic.php?t=85243 --- src/Mod/Draft/draftfunctions/offset.py | 4 ++-- src/Mod/Draft/draftguitools/gui_arcs.py | 5 ++-- .../Draft/draftguitools/gui_base_original.py | 24 +++++++++---------- src/Mod/Draft/draftguitools/gui_beziers.py | 12 +++++----- .../Draft/draftguitools/gui_circulararray.py | 9 +++---- src/Mod/Draft/draftguitools/gui_clone.py | 19 ++++++++------- src/Mod/Draft/draftguitools/gui_dimensions.py | 3 ++- src/Mod/Draft/draftguitools/gui_downgrade.py | 21 ++++++++-------- .../Draft/draftguitools/gui_draft2sketch.py | 15 ++++++------ src/Mod/Draft/draftguitools/gui_ellipses.py | 3 ++- .../Draft/draftguitools/gui_facebinders.py | 14 +++++------ src/Mod/Draft/draftguitools/gui_join.py | 6 ++--- src/Mod/Draft/draftguitools/gui_labels.py | 3 ++- src/Mod/Draft/draftguitools/gui_lines.py | 1 + src/Mod/Draft/draftguitools/gui_mirror.py | 5 ++-- src/Mod/Draft/draftguitools/gui_move.py | 3 ++- src/Mod/Draft/draftguitools/gui_offset.py | 1 + src/Mod/Draft/draftguitools/gui_orthoarray.py | 9 +++---- src/Mod/Draft/draftguitools/gui_polararray.py | 9 +++---- src/Mod/Draft/draftguitools/gui_polygons.py | 4 ++-- src/Mod/Draft/draftguitools/gui_rectangles.py | 6 ++--- src/Mod/Draft/draftguitools/gui_rotate.py | 3 ++- src/Mod/Draft/draftguitools/gui_scale.py | 3 ++- .../Draft/draftguitools/gui_shape2dview.py | 15 ++++++------ .../Draft/draftguitools/gui_shapestrings.py | 6 ++++- src/Mod/Draft/draftguitools/gui_splines.py | 1 + src/Mod/Draft/draftguitools/gui_split.py | 1 + src/Mod/Draft/draftguitools/gui_stretch.py | 5 ++-- .../Draft/draftguitools/gui_subelements.py | 14 ++++------- src/Mod/Draft/draftguitools/gui_texts.py | 5 ++-- src/Mod/Draft/draftguitools/gui_trimex.py | 7 +++--- src/Mod/Draft/draftguitools/gui_upgrade.py | 21 ++++++++-------- 32 files changed, 138 insertions(+), 119 deletions(-) diff --git a/src/Mod/Draft/draftfunctions/offset.py b/src/Mod/Draft/draftfunctions/offset.py index 8228a5a9a92c..3a9e8f227fa3 100644 --- a/src/Mod/Draft/draftfunctions/offset.py +++ b/src/Mod/Draft/draftfunctions/offset.py @@ -240,9 +240,9 @@ def getRadius(obj,delta): print("unsupported object") # TODO newobj = obj if copy and params.get_param("selectBaseObjects"): - gui_utils.select(newobj) - else: gui_utils.select(obj) + else: + gui_utils.select(newobj) if delete: App.ActiveDocument.removeObject(delete) return newobj diff --git a/src/Mod/Draft/draftguitools/gui_arcs.py b/src/Mod/Draft/draftguitools/gui_arcs.py index bcc33a90a110..ea68d0b99ec7 100644 --- a/src/Mod/Draft/draftguitools/gui_arcs.py +++ b/src/Mod/Draft/draftguitools/gui_arcs.py @@ -96,10 +96,11 @@ def finish(self, cont=False): Restart (continue) the command if `True`, or if `None` and `ui.continueMode` is `True`. """ - super().finish() + self.end_callbacks(self.call) if self.ui: self.linetrack.finalize() self.arctrack.finalize() + super().finish() if cont or (cont is None and self.ui and self.ui.continueMode): self.Activated() @@ -595,8 +596,8 @@ def finish(self, cont=False): `ui.continueMode` is `True`. """ App.activeDraftCommand = None - super().finish() self.tracker.finalize() + super().finish() if cont or (cont is None and Gui.Snapper.ui and Gui.Snapper.ui.continueMode): self.Activated() diff --git a/src/Mod/Draft/draftguitools/gui_base_original.py b/src/Mod/Draft/draftguitools/gui_base_original.py index 5f73a4121321..45777c35d4bb 100644 --- a/src/Mod/Draft/draftguitools/gui_base_original.py +++ b/src/Mod/Draft/draftguitools/gui_base_original.py @@ -141,6 +141,15 @@ def Activated(self, name="None", is_subtool=False): _toolmsg("{}".format(16*"-")) _toolmsg("GuiCommand: {}".format(self.featureName)) + def end_callbacks(self, call): + try: + self.view.removeEventCallback("SoEvent", call) + gui_utils.end_all_events() + except RuntimeError: + # the view has been deleted already + pass + call = None + def finish(self, cont=False): """Finish the current command. @@ -165,22 +174,11 @@ def finish(self, cont=False): if self.ui: self.ui.offUi() self.ui.sourceCmd = None + if hasattr(Gui, "Snapper"): + Gui.Snapper.off() if self.planetrack: self.planetrack.finalize() self.wp._restore() - if hasattr(Gui, "Snapper"): - Gui.Snapper.off() - if self.call: - try: - self.view.removeEventCallback("SoEvent", self.call) - # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: - QtCore.QCoreApplication.processEvents() - # It seems to work in most cases. If it does not, use this instead: - # gui_utils.end_all_events() - except RuntimeError: - # the view has been deleted already - pass - self.call = None if self.commitList: last_cmd = self.commitList[-1][1][-1] if last_cmd.find("recompute") >= 0: diff --git a/src/Mod/Draft/draftguitools/gui_beziers.py b/src/Mod/Draft/draftguitools/gui_beziers.py index 43567db9640a..b32a1e22928b 100644 --- a/src/Mod/Draft/draftguitools/gui_beziers.py +++ b/src/Mod/Draft/draftguitools/gui_beziers.py @@ -186,9 +186,9 @@ def finish(self, cont=False, closed=False): closed: bool, optional Close the curve if `True`. """ - if self.ui: - if hasattr(self, "bezcurvetrack"): - self.bezcurvetrack.finalize() + self.end_callbacks(self.call) + if self.ui and hasattr(self, "bezcurvetrack"): + self.bezcurvetrack.finalize() if self.obj: # remove temporary object, if any old = self.obj.Name @@ -433,9 +433,9 @@ def finish(self, cont=False, closed=False): """ params.set_param_view("EnableSelection", self.old_EnableSelection) - if self.ui: - if hasattr(self, "bezcurvetrack"): - self.bezcurvetrack.finalize() + self.end_callbacks(self.call) + if self.ui and hasattr(self, "bezcurvetrack"): + self.bezcurvetrack.finalize() if self.obj: # remove temporary object, if any old = self.obj.Name diff --git a/src/Mod/Draft/draftguitools/gui_circulararray.py b/src/Mod/Draft/draftguitools/gui_circulararray.py index ee947aa51fb8..d978420dac69 100644 --- a/src/Mod/Draft/draftguitools/gui_circulararray.py +++ b/src/Mod/Draft/draftguitools/gui_circulararray.py @@ -34,11 +34,11 @@ import FreeCADGui as Gui import Draft import Draft_rc # include resources, icons, ui files -import draftutils.todo as todo - +from draftguitools import gui_base +from draftutils import gui_utils +from draftutils import todo from draftutils.messages import _log from draftutils.translate import translate -from draftguitools import gui_base from drafttaskpanels import task_circulararray # The module is used to prevent complaints from code checkers (flake8) @@ -49,7 +49,7 @@ class CircularArray(gui_base.GuiCommandBase): """Gui command for the CircularArray tool.""" def __init__(self): - super(CircularArray, self).__init__() + super().__init__() self.command_name = "Circular array" self.location = None self.mouse_event = None @@ -128,6 +128,7 @@ def completed(self): self.callback_move) self.view.removeEventCallbackPivy(self.mouse_event, self.callback_click) + gui_utils.end_all_events() if Gui.Control.activeDialog(): Gui.Control.closeDialog() self.finish() diff --git a/src/Mod/Draft/draftguitools/gui_clone.py b/src/Mod/Draft/draftguitools/gui_clone.py index 262948dfb766..3f2b4a912bbe 100644 --- a/src/Mod/Draft/draftguitools/gui_clone.py +++ b/src/Mod/Draft/draftguitools/gui_clone.py @@ -60,7 +60,7 @@ class Clone(gui_base_original.Modifier): """Gui Command for the Clone tool.""" def __init__(self): - super(Clone, self).__init__() + super().__init__() self.moveAfterCloning = False def GetResources(self): @@ -73,14 +73,13 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Clone, self).Activated(name="Clone") + super().Activated(name="Clone") + if not self.ui: + return if not Gui.Selection.getSelection(): - if self.ui: - self.ui.selectUi(on_close_call=self.finish) - _msg(translate("draft", "Select an object to clone")) - self.call = self.view.addEventCallback( - "SoEvent", - gui_tool_utils.selectObject) + self.ui.selectUi(on_close_call=self.finish) + _msg(translate("draft", "Select an object to clone")) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() @@ -114,7 +113,9 @@ def proceed(self): def finish(self): """Terminate the operation of the tool.""" - super(Clone, self).finish() + if self.call is not None: + self.end_callbacks(self.call) + super().finish() if self.moveAfterCloning: todo.ToDo.delay(Gui.runCommand, "Draft_Move") diff --git a/src/Mod/Draft/draftguitools/gui_dimensions.py b/src/Mod/Draft/draftguitools/gui_dimensions.py index 80b895992141..9cf598fc2556 100644 --- a/src/Mod/Draft/draftguitools/gui_dimensions.py +++ b/src/Mod/Draft/draftguitools/gui_dimensions.py @@ -174,12 +174,13 @@ def selected_app_measure(self): def finish(self, cont=False): """Terminate the operation.""" + self.end_callbacks(self.call) self.cont = None self.dir = None - super().finish() if self.ui: self.dimtrack.finalize() self.arctrack.finalize() + super().finish() def angle_dimension_normal(self, edge1, edge2): rot = App.Rotation(DraftGeomUtils.vec(edge1), diff --git a/src/Mod/Draft/draftguitools/gui_downgrade.py b/src/Mod/Draft/draftguitools/gui_downgrade.py index 8a6b29d9b5a2..f9cc9c3ed163 100644 --- a/src/Mod/Draft/draftguitools/gui_downgrade.py +++ b/src/Mod/Draft/draftguitools/gui_downgrade.py @@ -60,19 +60,20 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Downgrade, self).Activated(name="Downgrade") - if self.ui: - if not Gui.Selection.getSelection(): - self.ui.selectUi(on_close_call=self.finish) - _msg(translate("draft", "Select an object to upgrade")) - self.call = self.view.addEventCallback( - "SoEvent", - gui_tool_utils.selectObject) - else: - self.proceed() + super().Activated(name="Downgrade") + if not self.ui: + return + if not Gui.Selection.getSelection(): + self.ui.selectUi(on_close_call=self.finish) + _msg(translate("draft", "Select an object to upgrade")) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) + else: + self.proceed() def proceed(self): """Proceed with execution of the command after selection.""" + if self.call is not None: + self.end_callbacks(self.call) if Gui.Selection.getSelection(): Gui.addModule("Draft") _cmd = 'Draft.downgrade' diff --git a/src/Mod/Draft/draftguitools/gui_draft2sketch.py b/src/Mod/Draft/draftguitools/gui_draft2sketch.py index c174cf877d75..df6d56c97d70 100644 --- a/src/Mod/Draft/draftguitools/gui_draft2sketch.py +++ b/src/Mod/Draft/draftguitools/gui_draft2sketch.py @@ -59,19 +59,20 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Draft2Sketch, self).Activated(name="Convert Draft/Sketch") + super().Activated(name="Convert Draft/Sketch") + if not self.ui: + return if not Gui.Selection.getSelection(): - if self.ui: - self.ui.selectUi(on_close_call=self.finish) - _msg(translate("draft", "Select an object to convert.")) - self.call = self.view.addEventCallback( - "SoEvent", - gui_tool_utils.selectObject) + self.ui.selectUi(on_close_call=self.finish) + _msg(translate("draft", "Select an object to convert.")) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() def proceed(self): """Proceed with the command if one object was selected.""" + if self.call is not None: + self.end_callbacks(self.call) sel = Gui.Selection.getSelection() allSketches = True allDraft = True diff --git a/src/Mod/Draft/draftguitools/gui_ellipses.py b/src/Mod/Draft/draftguitools/gui_ellipses.py index ec78f7f46889..12e405b9ce10 100644 --- a/src/Mod/Draft/draftguitools/gui_ellipses.py +++ b/src/Mod/Draft/draftguitools/gui_ellipses.py @@ -79,10 +79,11 @@ def finish(self, cont=False): Restart (continue) the command if `True`, or if `None` and `ui.continueMode` is `True`. """ - super().finish(self) + self.end_callbacks(self.call) if self.ui: self.rect.off() self.rect.finalize() + super().finish() if cont or (cont is None and self.ui and self.ui.continueMode): self.Activated() diff --git a/src/Mod/Draft/draftguitools/gui_facebinders.py b/src/Mod/Draft/draftguitools/gui_facebinders.py index fbb82bcac6a2..628ef41f3029 100644 --- a/src/Mod/Draft/draftguitools/gui_facebinders.py +++ b/src/Mod/Draft/draftguitools/gui_facebinders.py @@ -63,19 +63,19 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" super().Activated(name="Facebinder") - + if not self.ui: + return if not Gui.Selection.getSelection(): - if self.ui: - self.ui.selectUi(on_close_call=self.finish) - _msg(translate("draft", "Select faces from existing objects")) - self.call = self.view.addEventCallback( - "SoEvent", - gui_tool_utils.selectObject) + self.ui.selectUi(on_close_call=self.finish) + _msg(translate("draft", "Select faces from existing objects")) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() def proceed(self): """Proceed when a valid selection has been made.""" + if self.call is not None: + self.end_callbacks(self.call) if Gui.Selection.getSelection(): App.ActiveDocument.openTransaction("Create Facebinder") Gui.addModule("Draft") diff --git a/src/Mod/Draft/draftguitools/gui_join.py b/src/Mod/Draft/draftguitools/gui_join.py index 581dde0fde9f..dc5817606358 100644 --- a/src/Mod/Draft/draftguitools/gui_join.py +++ b/src/Mod/Draft/draftguitools/gui_join.py @@ -62,9 +62,7 @@ def Activated(self): if not Gui.Selection.getSelection(): self.ui.selectUi(on_close_call=self.finish) _msg(translate("draft", "Select an object to join")) - self.call = self.view.addEventCallback( - "SoEvent", - gui_tool_utils.selectObject) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() @@ -75,6 +73,8 @@ def proceed(self): visually share a point. This is due to the underlying `joinWires` method not handling the points correctly. """ + if self.call is not None: + self.end_callbacks(self.call) if Gui.Selection.getSelection(): self.print_selection() Gui.addModule("Draft") diff --git a/src/Mod/Draft/draftguitools/gui_labels.py b/src/Mod/Draft/draftguitools/gui_labels.py index 7dcd236d7027..1d4e79074eae 100644 --- a/src/Mod/Draft/draftguitools/gui_labels.py +++ b/src/Mod/Draft/draftguitools/gui_labels.py @@ -87,9 +87,10 @@ def setmode(self, i): def finish(self, cont=False): """Finish the command.""" - super().finish() + self.end_callbacks(self.call) if self.ghost: self.ghost.finalize() + super().finish() def create(self): """Create the actual object.""" diff --git a/src/Mod/Draft/draftguitools/gui_lines.py b/src/Mod/Draft/draftguitools/gui_lines.py index b69d4abdb347..e667a3757871 100644 --- a/src/Mod/Draft/draftguitools/gui_lines.py +++ b/src/Mod/Draft/draftguitools/gui_lines.py @@ -134,6 +134,7 @@ def finish(self, cont=False, closed=False): closed: bool, optional Close the line if `True`. """ + self.end_callbacks(self.call) self.removeTemporaryObject() if len(self.node) > 1: diff --git a/src/Mod/Draft/draftguitools/gui_mirror.py b/src/Mod/Draft/draftguitools/gui_mirror.py index 3608fe73ba8c..e710c85fba12 100644 --- a/src/Mod/Draft/draftguitools/gui_mirror.py +++ b/src/Mod/Draft/draftguitools/gui_mirror.py @@ -66,7 +66,7 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Mirror, self).Activated(name="Mirror") + super().Activated(name="Mirror") self.ghost = None if self.ui: if not Gui.Selection.getSelection(): @@ -94,9 +94,10 @@ def proceed(self): def finish(self, cont=False): """Terminate the operation of the tool.""" + self.end_callbacks(self.call) if self.ghost: self.ghost.finalize() - super(Mirror, self).finish() + super().finish() def mirror(self, p1, p2, copy=False): """Mirror the real shapes.""" diff --git a/src/Mod/Draft/draftguitools/gui_move.py b/src/Mod/Draft/draftguitools/gui_move.py index 9eca54ca1577..92d443be3bbb 100644 --- a/src/Mod/Draft/draftguitools/gui_move.py +++ b/src/Mod/Draft/draftguitools/gui_move.py @@ -108,9 +108,10 @@ def finish(self, cont=False): Restart (continue) the command if `True`, or if `None` and `ui.continueMode` is `True`. """ - super().finish() + self.end_callbacks(self.call) for ghost in self.ghosts: ghost.finalize() + super().finish() if cont or (cont is None and self.ui and self.ui.continueMode): todo.ToDo.delayAfter(self.Activated, []) diff --git a/src/Mod/Draft/draftguitools/gui_offset.py b/src/Mod/Draft/draftguitools/gui_offset.py index 91ae28970466..cbb93cceb1a7 100644 --- a/src/Mod/Draft/draftguitools/gui_offset.py +++ b/src/Mod/Draft/draftguitools/gui_offset.py @@ -264,6 +264,7 @@ def action(self, arg): def finish(self, cont=False): """Finish the offset operation.""" + self.end_callbacks(self.call) if self.running: if self.linetrack: self.linetrack.finalize() diff --git a/src/Mod/Draft/draftguitools/gui_orthoarray.py b/src/Mod/Draft/draftguitools/gui_orthoarray.py index 77f6e3768774..c91f95a722c8 100644 --- a/src/Mod/Draft/draftguitools/gui_orthoarray.py +++ b/src/Mod/Draft/draftguitools/gui_orthoarray.py @@ -34,11 +34,11 @@ import FreeCADGui as Gui import Draft import Draft_rc # include resources, icons, ui files -import draftutils.todo as todo - +from draftguitools import gui_base +from draftutils import gui_utils +from draftutils import todo from draftutils.messages import _log from draftutils.translate import translate -from draftguitools import gui_base from drafttaskpanels import task_orthoarray # The module is used to prevent complaints from code checkers (flake8) @@ -49,7 +49,7 @@ class OrthoArray(gui_base.GuiCommandBase): """Gui command for the OrthoArray tool.""" def __init__(self): - super(OrthoArray, self).__init__() + super().__init__() self.command_name = "Orthogonal array" # self.location = None self.mouse_event = None @@ -115,6 +115,7 @@ def completed(self): # self.callback_move) self.view.removeEventCallbackPivy(self.mouse_event, self.callback_click) + gui_utils.end_all_events() if Gui.Control.activeDialog(): Gui.Control.closeDialog() self.finish() diff --git a/src/Mod/Draft/draftguitools/gui_polararray.py b/src/Mod/Draft/draftguitools/gui_polararray.py index 8795d51cd54a..05a05b3046f4 100644 --- a/src/Mod/Draft/draftguitools/gui_polararray.py +++ b/src/Mod/Draft/draftguitools/gui_polararray.py @@ -34,11 +34,11 @@ import FreeCADGui as Gui import Draft import Draft_rc # include resources, icons, ui files -import draftutils.todo as todo - +from draftguitools import gui_base +from draftutils import gui_utils +from draftutils import todo from draftutils.messages import _log from draftutils.translate import translate -from draftguitools import gui_base from drafttaskpanels import task_polararray # The module is used to prevent complaints from code checkers (flake8) @@ -49,7 +49,7 @@ class PolarArray(gui_base.GuiCommandBase): """Gui command for the PolarArray tool.""" def __init__(self): - super(PolarArray, self).__init__() + super().__init__() self.command_name = "Polar array" self.location = None self.mouse_event = None @@ -128,6 +128,7 @@ def completed(self): self.callback_move) self.view.removeEventCallbackPivy(self.mouse_event, self.callback_click) + gui_utils.end_all_events() if Gui.Control.activeDialog(): Gui.Control.closeDialog() self.finish() diff --git a/src/Mod/Draft/draftguitools/gui_polygons.py b/src/Mod/Draft/draftguitools/gui_polygons.py index 536984de0124..8825002b41e4 100644 --- a/src/Mod/Draft/draftguitools/gui_polygons.py +++ b/src/Mod/Draft/draftguitools/gui_polygons.py @@ -86,10 +86,10 @@ def finish(self, cont=False): Restart (continue) the command if `True`, or if `None` and `ui.continueMode` is `True`. """ - super().finish(self) + self.end_callbacks(self.call) if self.ui: self.arctrack.finalize() - self.doc.recompute() + super().finish() if cont or (cont is None and self.ui and self.ui.continueMode): self.Activated() diff --git a/src/Mod/Draft/draftguitools/gui_rectangles.py b/src/Mod/Draft/draftguitools/gui_rectangles.py index d52bf45d2b0d..ecdb79c871f0 100644 --- a/src/Mod/Draft/draftguitools/gui_rectangles.py +++ b/src/Mod/Draft/draftguitools/gui_rectangles.py @@ -74,13 +74,11 @@ def finish(self, cont=False): Restart (continue) the command if `True`, or if `None` and `ui.continueMode` is `True`. """ - if self.ui and hasattr(self, "fillstate"): - self.ui.hasFill.setChecked(self.fillstate) - del self.fillstate - super().finish() + self.end_callbacks(self.call) if self.ui: self.rect.off() self.rect.finalize() + super().finish() if cont or (cont is None and self.ui and self.ui.continueMode): self.Activated() diff --git a/src/Mod/Draft/draftguitools/gui_rotate.py b/src/Mod/Draft/draftguitools/gui_rotate.py index 5ba46b13fa5b..aaa2defe86d5 100644 --- a/src/Mod/Draft/draftguitools/gui_rotate.py +++ b/src/Mod/Draft/draftguitools/gui_rotate.py @@ -262,11 +262,12 @@ def finish(self, cont=False): Restart (continue) the command if `True`, or if `None` and `ui.continueMode` is `True`. """ - super().finish() + self.end_callbacks(self.call) if self.arctrack: self.arctrack.finalize() for ghost in self.ghosts: ghost.finalize() + super().finish() if cont or (cont is None and self.ui and self.ui.continueMode): todo.ToDo.delayAfter(self.Activated, []) diff --git a/src/Mod/Draft/draftguitools/gui_scale.py b/src/Mod/Draft/draftguitools/gui_scale.py index c5bebd1c0aa0..f0628258a1ef 100644 --- a/src/Mod/Draft/draftguitools/gui_scale.py +++ b/src/Mod/Draft/draftguitools/gui_scale.py @@ -420,9 +420,10 @@ def numericInput(self, numx, numy, numz): def finish(self, cont=False): """Terminate the operation.""" - super().finish() + self.end_callbacks(self.call) for ghost in self.ghosts: ghost.finalize() + super().finish() Gui.addCommand('Draft_Scale', Scale()) diff --git a/src/Mod/Draft/draftguitools/gui_shape2dview.py b/src/Mod/Draft/draftguitools/gui_shape2dview.py index ae32163afe05..0d87fdb9b7d1 100644 --- a/src/Mod/Draft/draftguitools/gui_shape2dview.py +++ b/src/Mod/Draft/draftguitools/gui_shape2dview.py @@ -61,19 +61,20 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Shape2DView, self).Activated(name="Project 2D view") + super().Activated(name="Project 2D view") + if not self.ui: + return if not Gui.Selection.getSelection(): - if self.ui: - self.ui.selectUi(on_close_call=self.finish) - _msg(translate("draft", "Select an object to project")) - self.call = self.view.addEventCallback( - "SoEvent", - gui_tool_utils.selectObject) + self.ui.selectUi(on_close_call=self.finish) + _msg(translate("draft", "Select an object to project")) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() def proceed(self): """Proceed with the command if one object was selected.""" + if self.call is not None: + self.end_callbacks(self.call) faces = [] objs = [] vec = Gui.ActiveDocument.ActiveView.getViewDirection().negative() diff --git a/src/Mod/Draft/draftguitools/gui_shapestrings.py b/src/Mod/Draft/draftguitools/gui_shapestrings.py index 8e9257d55500..e092f8edf156 100644 --- a/src/Mod/Draft/draftguitools/gui_shapestrings.py +++ b/src/Mod/Draft/draftguitools/gui_shapestrings.py @@ -69,7 +69,7 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(ShapeString, self).Activated(name="ShapeString") + super().Activated(name="ShapeString") if self.ui: self.ui.sourceCmd = self self.task = ShapeStringTaskPanelCmd(self) @@ -77,6 +77,10 @@ def Activated(self): _toolmsg(translate("draft", "Pick ShapeString location point")) todo.ToDo.delay(Gui.Control.showDialog, self.task) + def finish(self): + self.end_callbacks(self.call) + super().finish() + Gui.addCommand('Draft_ShapeString', ShapeString()) diff --git a/src/Mod/Draft/draftguitools/gui_splines.py b/src/Mod/Draft/draftguitools/gui_splines.py index 2b7e93a4ce7d..fcefdfc50d12 100644 --- a/src/Mod/Draft/draftguitools/gui_splines.py +++ b/src/Mod/Draft/draftguitools/gui_splines.py @@ -155,6 +155,7 @@ def finish(self, cont=False, closed=False): closed: bool, optional Close the spline if `True`. """ + self.end_callbacks(self.call) if self.ui: self.bsplinetrack.finalize() if self.obj: diff --git a/src/Mod/Draft/draftguitools/gui_split.py b/src/Mod/Draft/draftguitools/gui_split.py index 681e87f51827..978142d0e795 100644 --- a/src/Mod/Draft/draftguitools/gui_split.py +++ b/src/Mod/Draft/draftguitools/gui_split.py @@ -90,6 +90,7 @@ def action(self, arg): def proceed(self, info): """Proceed with execution of the command after click on an edge.""" + self.end_callbacks(self.call) wire = App.ActiveDocument.getObject(info["Object"]) edge_index = int(info["Component"][4:]) diff --git a/src/Mod/Draft/draftguitools/gui_stretch.py b/src/Mod/Draft/draftguitools/gui_stretch.py index 3ce321ac47cb..3ccdf8c32657 100644 --- a/src/Mod/Draft/draftguitools/gui_stretch.py +++ b/src/Mod/Draft/draftguitools/gui_stretch.py @@ -66,7 +66,7 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Stretch, self).Activated(name="Stretch") + super().Activated(name="Stretch") self.rectracker = None self.nodetracker = None if self.ui: @@ -255,12 +255,13 @@ def numericInput(self, numx, numy, numz): def finish(self, cont=False): """Terminate the operation of the command. and clean up.""" + self.end_callbacks(self.call) if self.rectracker: self.rectracker.finalize() if self.nodetracker: for n in self.nodetracker: n.finalize() - super(Stretch, self).finish() + super().finish() def doStretch(self): """Do the actual stretching once the points are selected.""" diff --git a/src/Mod/Draft/draftguitools/gui_subelements.py b/src/Mod/Draft/draftguitools/gui_subelements.py index 6a217fb5fc5f..33912accc448 100644 --- a/src/Mod/Draft/draftguitools/gui_subelements.py +++ b/src/Mod/Draft/draftguitools/gui_subelements.py @@ -66,12 +66,13 @@ def Activated(self): if self.is_running: return self.finish() self.is_running = True - super(SubelementHighlight, self).Activated(name="Subelement highlight") + super().Activated(name="Subelement highlight") self.get_selection() def proceed(self): """Continue with the command.""" - self.remove_view_callback() + if self.call: + self.view.removeEventCallback("SoEvent", self.call) self.get_editable_objects_from_selection() if not self.editable_objects: return self.finish() @@ -83,9 +84,9 @@ def finish(self): Re-initialize by running __init__ again at the end. """ - super(SubelementHighlight, self).finish() - self.remove_view_callback() + self.end_callbacks(self.call) self.restore_editable_objects_graphics() + super().finish() self.__init__() def action(self, event): @@ -111,11 +112,6 @@ def get_selection(self): else: self.proceed() - def remove_view_callback(self): - """Remove the installed callback if it exists.""" - if self.call: - self.view.removeEventCallback("SoEvent", self.call) - def get_editable_objects_from_selection(self): """Get editable Draft objects for the selection.""" for obj in Gui.Selection.getSelection(): diff --git a/src/Mod/Draft/draftguitools/gui_texts.py b/src/Mod/Draft/draftguitools/gui_texts.py index 4ba938d29559..c88c0f29a016 100644 --- a/src/Mod/Draft/draftguitools/gui_texts.py +++ b/src/Mod/Draft/draftguitools/gui_texts.py @@ -62,7 +62,7 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Text, self).Activated(name="Text") + super().Activated(name="Text") if self.ui: self.text = '' self.ui.sourceCmd = self @@ -84,7 +84,8 @@ def finish(self, cont=False): Restart (continue) the command if `True`, or if `None` and `ui.continueMode` is `True`. """ - super(Text, self).finish(self) + self.end_callbacks(self.call) + super().finish(self) if cont or (cont is None and self.ui and self.ui.continueMode): self.Activated() diff --git a/src/Mod/Draft/draftguitools/gui_trimex.py b/src/Mod/Draft/draftguitools/gui_trimex.py index db8f084baa5e..aba0e16269e6 100644 --- a/src/Mod/Draft/draftguitools/gui_trimex.py +++ b/src/Mod/Draft/draftguitools/gui_trimex.py @@ -81,7 +81,7 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Trimex, self).Activated(name="Trimex") + super().Activated(name="Trimex") self.edges = [] self.placement = None self.ghost = [] @@ -545,7 +545,7 @@ def trimObjects(self, objectslist): def finish(self, cont=False): """Terminate the operation of the Trimex tool.""" - super(Trimex, self).finish() + self.end_callbacks(self.call) self.force = None if self.ui: if self.linetrack: @@ -559,7 +559,8 @@ def finish(self, cont=False): self.obj.ViewObject.LineColor = self.color if self.width: self.obj.ViewObject.LineWidth = self.width - gui_utils.select(self.obj) + gui_utils.select(self.obj) + super().finish() def numericRadius(self, dist): """Validate the entry fields in the user interface. diff --git a/src/Mod/Draft/draftguitools/gui_upgrade.py b/src/Mod/Draft/draftguitools/gui_upgrade.py index 6b6260002062..e57d9308d237 100644 --- a/src/Mod/Draft/draftguitools/gui_upgrade.py +++ b/src/Mod/Draft/draftguitools/gui_upgrade.py @@ -60,19 +60,20 @@ def GetResources(self): def Activated(self): """Execute when the command is called.""" - super(Upgrade, self).Activated(name="Upgrade") - if self.ui: - if not Gui.Selection.getSelection(): - self.ui.selectUi(on_close_call=self.finish) - _msg(translate("draft", "Select an object to upgrade")) - self.call = self.view.addEventCallback( - "SoEvent", - gui_tool_utils.selectObject) - else: - self.proceed() + super().Activated(name="Upgrade") + if not self.ui: + return + if not Gui.Selection.getSelection(): + self.ui.selectUi(on_close_call=self.finish) + _msg(translate("draft", "Select an object to upgrade")) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) + else: + self.proceed() def proceed(self): """Proceed with execution of the command after selection.""" + if self.call is not None: + self.end_callbacks(self.call) if Gui.Selection.getSelection(): Gui.addModule("Draft") _cmd = 'Draft.upgrade'