From c23e1dd7baf6488c986cd9dbee3ffaac0406fbaa Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Thu, 5 Nov 2020 16:53:08 -0600 Subject: [PATCH] Release handler in commands where not needed Fixes #0004478: Active constraint tool blocks sidebar tasks from working. Many commands are interrupted by the existence of a handler. Rather than having these commands silently cancel, purge the handler if a command executes that does not need it. When right-clicking on an item in the Constraint Task sidebar, any current operation is cancelled and the FreeCAD selection is synced with the selected items in the constraints QListWidget. This allows all of the menu items in the context menu to function properly: if the selection is not synced, anything that relies on the FreeCAD selection (like Delete) will sillently fail. --- src/Mod/Sketcher/Gui/CommandConstraints.cpp | 16 ++++++++ src/Mod/Sketcher/Gui/CommandConstraints.h | 3 ++ src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 40 ++++++++++++++++++- .../Sketcher/Gui/TaskSketcherConstrains.cpp | 17 ++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 5ae595805f..2dab96b05b 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -255,6 +255,22 @@ bool SketcherGui::IsPointAlreadyOnCurve(int GeoIdCurve, int GeoIdPoint, Sketcher return Obj->isPointOnCurve(GeoIdCurve, p.x, p.y); } +bool SketcherGui::ReleaseHandler(Gui::Document* doc) { + if (doc) { + if (doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId())) { + SketcherGui::ViewProviderSketch* vp = static_cast (doc->getInEdit()); + + if (static_cast(doc->getInEdit()) + ->getSketchMode() == ViewProviderSketch::STATUS_SKETCH_UseHandler) { + + vp->purgeHandler(); + return true; + } + } + } + return false; +} + /// Makes a simple tangency constraint using extra point + tangent via point /// ellipse => an ellipse /// geom2 => any of an ellipse, an arc of ellipse, a circle, or an arc (of circle) diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.h b/src/Mod/Sketcher/Gui/CommandConstraints.h index e4896da6bc..281872feac 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.h +++ b/src/Mod/Sketcher/Gui/CommandConstraints.h @@ -51,6 +51,9 @@ bool isConstructionPoint(const Sketcher::SketchObject* Obj, int GeoId); bool IsPointAlreadyOnCurve(int GeoIdCurve, int GeoIdPoint, Sketcher::PointPos PosIdPoint, Sketcher::SketchObject* Obj); +/// Release any currently-active handler for the document. +/// Returns true if a handler was released, and false if not +bool ReleaseHandler(Gui::Document* doc); // These functions are declared here to promote code reuse from other modules diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index e301533298..53c53ec6e2 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -62,8 +62,10 @@ bool isSketcherAcceleratorActive(Gui::Document *doc, bool actsOnSelection) if (doc) { // checks if a Sketch Viewprovider is in Edit and is in no special mode if (doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId())) { - if (static_cast(doc->getInEdit()) - ->getSketchMode() == ViewProviderSketch::STATUS_NONE) { + auto mode = static_cast(doc->getInEdit()) + ->getSketchMode(); + if (mode == ViewProviderSketch::STATUS_NONE || + mode == ViewProviderSketch::STATUS_SKETCH_UseHandler) { if (!actsOnSelection) return true; else if (Gui::Selection().countObjectsOfType(Sketcher::SketchObject::getClassTypeId()) > 0) @@ -108,6 +110,11 @@ CmdSketcherCloseShape::CmdSketcherCloseShape() void CmdSketcherCloseShape::activated(int iMsg) { Q_UNUSED(iMsg); + + // Cancel any in-progress operation + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + SketcherGui::ReleaseHandler(doc); + // get the selection std::vector selection; selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); @@ -213,6 +220,11 @@ CmdSketcherConnect::CmdSketcherConnect() void CmdSketcherConnect::activated(int iMsg) { Q_UNUSED(iMsg); + + // Cancel any in-progress operation + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + SketcherGui::ReleaseHandler(doc); + // get the selection std::vector selection; selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); @@ -293,6 +305,11 @@ CmdSketcherSelectConstraints::CmdSketcherSelectConstraints() void CmdSketcherSelectConstraints::activated(int iMsg) { Q_UNUSED(iMsg); + + // Cancel any in-progress operation + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + SketcherGui::ReleaseHandler(doc); + // get the selection std::vector selection; selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); @@ -361,6 +378,7 @@ void CmdSketcherSelectOrigin::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); // ViewProviderSketch * vp = static_cast(Gui::Application::Instance->getViewProvider(docobj)); @@ -404,6 +422,7 @@ void CmdSketcherSelectVerticalAxis::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); @@ -445,6 +464,7 @@ void CmdSketcherSelectHorizontalAxis::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); @@ -485,6 +505,7 @@ void CmdSketcherSelectRedundantConstraints::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); @@ -536,6 +557,7 @@ void CmdSketcherSelectConflictingConstraints::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); std::string doc_name = Obj->getDocument()->getName(); @@ -587,6 +609,7 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg) Q_UNUSED(iMsg); std::vector selection = Gui::Selection().getSelectionEx(); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); @@ -706,6 +729,7 @@ void CmdSketcherSelectElementsWithDoFs::activated(int iMsg) Q_UNUSED(iMsg); getSelection().clearSelection(); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); @@ -804,6 +828,11 @@ CmdSketcherRestoreInternalAlignmentGeometry::CmdSketcherRestoreInternalAlignment void CmdSketcherRestoreInternalAlignmentGeometry::activated(int iMsg) { Q_UNUSED(iMsg); + + // Cancel any in-progress operation + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + SketcherGui::ReleaseHandler(doc); + // get the selection std::vector selection; selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); @@ -893,6 +922,11 @@ CmdSketcherSymmetry::CmdSketcherSymmetry() void CmdSketcherSymmetry::activated(int iMsg) { Q_UNUSED(iMsg); + + // Cancel any in-progress operation + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + SketcherGui::ReleaseHandler(doc); + // get the selection std::vector selection; selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); @@ -1930,6 +1964,7 @@ void CmdSketcherDeleteAllGeometry::activated(int iMsg) if (ret == QMessageBox::Yes) { getSelection().clearSelection(); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); @@ -1989,6 +2024,7 @@ void CmdSketcherDeleteAllConstraints::activated(int iMsg) if (ret == QMessageBox::Yes) { getSelection().clearSelection(); Gui::Document * doc= getActiveGuiDocument(); + ReleaseHandler(doc); SketcherGui::ViewProviderSketch* vp = static_cast(doc->getInEdit()); Sketcher::SketchObject* Obj= vp->getSketchObject(); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp index d82e3197b0..05bf9971e9 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp @@ -42,6 +42,7 @@ #include "ViewProviderSketch.h" #include +#include #include #include @@ -443,6 +444,22 @@ void ConstraintView::contextMenuEvent (QContextMenuEvent* event) QListWidgetItem* item = currentItem(); QList items = selectedItems(); + // Cancel any in-progress operation + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + bool didRelease = SketcherGui::ReleaseHandler(doc); + + // Sync the FreeCAD selection with the selection in the ConstraintView widget + if (didRelease) { + Gui::Selection().clearSelection(); + for (auto&& it : items) { + auto ci = static_cast(it); + std::string constraint_name = Sketcher::PropertyConstraintList::getConstraintName(ci->ConstraintNbr); + std::string doc_name = ci->sketchView->getSketchObject()->getDocument()->getName(); + std::string obj_name = ci->sketchView->getSketchObject()->getNameInDocument(); + Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), constraint_name.c_str()); + } + } + bool isQuantity = false; bool isToggleDriving = false; bool isActive = true;