From 1768efcf4d455e18bdf96adf94d5769990e6d34a Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Sat, 30 Nov 2024 11:47:10 +0100 Subject: [PATCH 1/2] Draft: Fix finish behavior of Draft_Edit on doc close Forum topic: https://forum.freecad.org/viewtopic.php?p=794746#p794746 --- src/Mod/Draft/draftguitools/gui_edit.py | 41 ++++++++++++++++--------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_edit.py b/src/Mod/Draft/draftguitools/gui_edit.py index 86f08299ba..ff48b19db6 100644 --- a/src/Mod/Draft/draftguitools/gui_edit.py +++ b/src/Mod/Draft/draftguitools/gui_edit.py @@ -340,8 +340,11 @@ class Edit(gui_base_original.Modifier): self.running = False # delay resetting edit mode otherwise it doesn't happen from PySide import QtCore - QtCore.QTimer.singleShot(0, Gui.ActiveDocument.resetEdit) + QtCore.QTimer.singleShot(0, self.reset_edit) + def reset_edit(self): + if Gui.ActiveDocument is not None: + Gui.ActiveDocument.resetEdit() # ------------------------------------------------------------------------- # SCENE EVENTS CALLBACKS @@ -356,8 +359,12 @@ class Edit(gui_base_original.Modifier): """ remove selection callback if it exists """ - if self.selection_callback: - self.view.removeEventCallback("SoEvent", self.selection_callback) + try: + if self.selection_callback: + self.view.removeEventCallback("SoEvent", self.selection_callback) + except RuntimeError: + # the view has been deleted already + pass self.selection_callback = None def register_editing_callbacks(self): @@ -380,18 +387,22 @@ class Edit(gui_base_original.Modifier): """ remove callbacks used during editing if they exist """ - if self._keyPressedCB: - self.view.removeEventCallbackSWIG(coin.SoKeyboardEvent.getClassTypeId(), self._keyPressedCB) - self._keyPressedCB = None - #App.Console.PrintMessage("Draft edit keyboard callback unregistered \n") - if self._mouseMovedCB: - self.view.removeEventCallbackSWIG(coin.SoLocation2Event.getClassTypeId(), self._mouseMovedCB) - self._mouseMovedCB = None - #App.Console.PrintMessage("Draft edit location callback unregistered \n") - if self._mousePressedCB: - self.view.removeEventCallbackSWIG(coin.SoMouseButtonEvent.getClassTypeId(), self._mousePressedCB) - self._mousePressedCB = None - #App.Console.PrintMessage("Draft edit mouse button callback unregistered \n") + try: + if self._keyPressedCB: + self.view.removeEventCallbackSWIG(coin.SoKeyboardEvent.getClassTypeId(), self._keyPressedCB) + #App.Console.PrintMessage("Draft edit keyboard callback unregistered \n") + if self._mouseMovedCB: + self.view.removeEventCallbackSWIG(coin.SoLocation2Event.getClassTypeId(), self._mouseMovedCB) + #App.Console.PrintMessage("Draft edit location callback unregistered \n") + if self._mousePressedCB: + self.view.removeEventCallbackSWIG(coin.SoMouseButtonEvent.getClassTypeId(), self._mousePressedCB) + #App.Console.PrintMessage("Draft edit mouse button callback unregistered \n") + except RuntimeError: + # the view has been deleted already + pass + self._keyPressedCB = None + self._mouseMovedCB = None + self._mousePressedCB = None # ------------------------------------------------------------------------- # SCENE EVENT HANDLERS From 11c33d897a2af4bb7e909db5796a3e9b5a307270 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Sat, 30 Nov 2024 16:48:41 +0100 Subject: [PATCH 2/2] Include other Draft commands --- .../Draft/draftguitools/gui_circulararray.py | 14 +++-- src/Mod/Draft/draftguitools/gui_orthoarray.py | 12 +++-- src/Mod/Draft/draftguitools/gui_points.py | 18 ++++--- src/Mod/Draft/draftguitools/gui_polararray.py | 14 +++-- src/Mod/Draft/draftguitools/gui_snapper.py | 54 +++++++++++-------- .../drafttaskpanels/task_circulararray.py | 3 +- .../Draft/drafttaskpanels/task_orthoarray.py | 3 +- .../Draft/drafttaskpanels/task_polararray.py | 3 +- 8 files changed, 75 insertions(+), 46 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_circulararray.py b/src/Mod/Draft/draftguitools/gui_circulararray.py index d978420dac..3137c4beb6 100644 --- a/src/Mod/Draft/draftguitools/gui_circulararray.py +++ b/src/Mod/Draft/draftguitools/gui_circulararray.py @@ -124,11 +124,15 @@ class CircularArray(gui_base.GuiCommandBase): We should remove the callbacks that were added to the 3D view and then close the task panel. """ - self.view.removeEventCallbackPivy(self.location, - self.callback_move) - self.view.removeEventCallbackPivy(self.mouse_event, - self.callback_click) - gui_utils.end_all_events() + try: + self.view.removeEventCallbackPivy(self.location, self.callback_move) + self.view.removeEventCallbackPivy(self.mouse_event, self.callback_click) + gui_utils.end_all_events() + except RuntimeError: + # the view has been deleted already + pass + self.callback_move = None + self.callback_click = None if Gui.Control.activeDialog(): Gui.Control.closeDialog() self.finish() diff --git a/src/Mod/Draft/draftguitools/gui_orthoarray.py b/src/Mod/Draft/draftguitools/gui_orthoarray.py index c91f95a722..5b6ca08aba 100644 --- a/src/Mod/Draft/draftguitools/gui_orthoarray.py +++ b/src/Mod/Draft/draftguitools/gui_orthoarray.py @@ -111,11 +111,13 @@ class OrthoArray(gui_base.GuiCommandBase): We should remove the callbacks that were added to the 3D view and then close the task panel. """ - # self.view.removeEventCallbackPivy(self.location, - # self.callback_move) - self.view.removeEventCallbackPivy(self.mouse_event, - self.callback_click) - gui_utils.end_all_events() + try: + self.view.removeEventCallbackPivy(self.mouse_event, self.callback_click) + gui_utils.end_all_events() + except RuntimeError: + # the view has been deleted already + pass + self.callback_click = None if Gui.Control.activeDialog(): Gui.Control.closeDialog() self.finish() diff --git a/src/Mod/Draft/draftguitools/gui_points.py b/src/Mod/Draft/draftguitools/gui_points.py index c7b748f1de..33c0c3412d 100644 --- a/src/Mod/Draft/draftguitools/gui_points.py +++ b/src/Mod/Draft/draftguitools/gui_points.py @@ -143,13 +143,17 @@ class Point(gui_base_original.Creator): Restart (continue) the command if `True`, or if `None` and `ui.continueMode` is `True`. """ - if self.callbackClick: - self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) - if self.callbackMove: - self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) - if self.callbackClick or self.callbackMove: - # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: - gui_utils.end_all_events() + try: + if self.callbackClick: + self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) + if self.callbackMove: + self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) + if self.callbackClick or self.callbackMove: + # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: + gui_utils.end_all_events() + except RuntimeError: + # the view has been deleted already + pass self.callbackClick = None self.callbackMove = None super().finish() diff --git a/src/Mod/Draft/draftguitools/gui_polararray.py b/src/Mod/Draft/draftguitools/gui_polararray.py index 05a05b3046..89046d4e0c 100644 --- a/src/Mod/Draft/draftguitools/gui_polararray.py +++ b/src/Mod/Draft/draftguitools/gui_polararray.py @@ -124,11 +124,15 @@ class PolarArray(gui_base.GuiCommandBase): We should remove the callbacks that were added to the 3D view and then close the task panel. """ - self.view.removeEventCallbackPivy(self.location, - self.callback_move) - self.view.removeEventCallbackPivy(self.mouse_event, - self.callback_click) - gui_utils.end_all_events() + try: + self.view.removeEventCallbackPivy(self.location, self.callback_move) + self.view.removeEventCallbackPivy(self.mouse_event, self.callback_click) + gui_utils.end_all_events() + except RuntimeError: + # the view has been deleted already + pass + self.callback_move = None + self.callback_click = None if Gui.Control.activeDialog(): Gui.Control.closeDialog() self.finish() diff --git a/src/Mod/Draft/draftguitools/gui_snapper.py b/src/Mod/Draft/draftguitools/gui_snapper.py index 2890703230..34562ef80f 100644 --- a/src/Mod/Draft/draftguitools/gui_snapper.py +++ b/src/Mod/Draft/draftguitools/gui_snapper.py @@ -1385,13 +1385,17 @@ class Snapper: self.view = Draft.get3DView() # remove any previous leftover callbacks - if self.callbackClick: - self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) - if self.callbackMove: - self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) - if self.callbackClick or self.callbackMove: - # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: - gui_utils.end_all_events() + try: + if self.callbackClick: + self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) + if self.callbackMove: + self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) + if self.callbackClick or self.callbackMove: + # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: + gui_utils.end_all_events() + except RuntimeError: + # the view has been deleted already + pass self.callbackClick = None self.callbackMove = None @@ -1428,13 +1432,17 @@ class Snapper: accept() def accept(): - if self.callbackClick: - self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) - if self.callbackMove: - self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) - if self.callbackClick or self.callbackMove: - # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: - gui_utils.end_all_events() + try: + if self.callbackClick: + self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) + if self.callbackMove: + self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) + if self.callbackClick or self.callbackMove: + # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: + gui_utils.end_all_events() + except RuntimeError: + # the view has been deleted already + pass self.callbackClick = None self.callbackMove = None Gui.Snapper.off() @@ -1450,13 +1458,17 @@ class Snapper: self.pt = None def cancel(): - if self.callbackClick: - self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) - if self.callbackMove: - self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) - if self.callbackClick or self.callbackMove: - # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: - gui_utils.end_all_events() + try: + if self.callbackClick: + self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) + if self.callbackMove: + self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) + if self.callbackClick or self.callbackMove: + # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: + gui_utils.end_all_events() + except RuntimeError: + # the view has been deleted already + pass self.callbackClick = None self.callbackMove = None Gui.Snapper.off() diff --git a/src/Mod/Draft/drafttaskpanels/task_circulararray.py b/src/Mod/Draft/drafttaskpanels/task_circulararray.py index ab0519beaa..d669f15ab9 100644 --- a/src/Mod/Draft/drafttaskpanels/task_circulararray.py +++ b/src/Mod/Draft/drafttaskpanels/task_circulararray.py @@ -478,7 +478,8 @@ class TaskPanelCircularArray: the delayed functions, and perform cleanup. """ # App.ActiveDocument.commitTransaction() - Gui.ActiveDocument.resetEdit() + if Gui.ActiveDocument is not None: + Gui.ActiveDocument.resetEdit() # Runs the parent command to complete the call self.source_command.completed() diff --git a/src/Mod/Draft/drafttaskpanels/task_orthoarray.py b/src/Mod/Draft/drafttaskpanels/task_orthoarray.py index 512ecda10f..4b3bc4a765 100644 --- a/src/Mod/Draft/drafttaskpanels/task_orthoarray.py +++ b/src/Mod/Draft/drafttaskpanels/task_orthoarray.py @@ -386,7 +386,8 @@ class TaskPanelOrthoArray: the delayed functions, and perform cleanup. """ # App.ActiveDocument.commitTransaction() - Gui.ActiveDocument.resetEdit() + if Gui.ActiveDocument is not None: + Gui.ActiveDocument.resetEdit() # Runs the parent command to complete the call self.source_command.completed() diff --git a/src/Mod/Draft/drafttaskpanels/task_polararray.py b/src/Mod/Draft/drafttaskpanels/task_polararray.py index 3b55ba8f11..6a3b034281 100644 --- a/src/Mod/Draft/drafttaskpanels/task_polararray.py +++ b/src/Mod/Draft/drafttaskpanels/task_polararray.py @@ -431,7 +431,8 @@ class TaskPanelPolarArray: the delayed functions, and perform cleanup. """ # App.ActiveDocument.commitTransaction() - Gui.ActiveDocument.resetEdit() + if Gui.ActiveDocument is not None: + Gui.ActiveDocument.resetEdit() # Runs the parent command to complete the call self.source_command.completed()