From 0cd5768fbdb68522e601fb8bd5ef93b324b462c4 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Fri, 29 Nov 2024 20:37:48 +0100 Subject: [PATCH] Draft: Draft_Fillet: fix error in #17945 (#18150) * Draft: Draft_Fillet: fix error in #17945 In #17945 the delete option of the command results in an error if subobjects are selected. * Command should not be available if there is no selection * Update copyright notice --- src/Mod/Draft/draftguitools/gui_fillets.py | 40 ++++++------- src/Mod/Draft/draftmake/make_fillet.py | 65 ++++++++++++---------- 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_fillets.py b/src/Mod/Draft/draftguitools/gui_fillets.py index 38c57ffb0a..74c47a1abf 100644 --- a/src/Mod/Draft/draftguitools/gui_fillets.py +++ b/src/Mod/Draft/draftguitools/gui_fillets.py @@ -54,19 +54,23 @@ class Fillet(gui_base_original.Creator): """Gui command for the Fillet tool.""" def __init__(self): - super(Fillet, self).__init__() + super().__init__() self.featureName = "Fillet" + def IsActive(self): + """Return True when this command should be available.""" + return bool(Gui.Selection.getSelection()) + def GetResources(self): """Set icon, menu and tooltip.""" return {"Pixmap": "Draft_Fillet", - "Accel":"F,I", + "Accel": "F,I", "MenuText": QT_TRANSLATE_NOOP("Draft_Fillet", "Fillet"), "ToolTip": QT_TRANSLATE_NOOP("Draft_Fillet", "Creates a fillet between two selected wires or edges.")} def Activated(self, name="Fillet"): """Execute when the command is called.""" - super(Fillet, self).Activated(name=name) + super().Activated(name=name) if self.ui: self.rad = 100 @@ -140,15 +144,7 @@ class Fillet(gui_base_original.Creator): def draw_arc(self, rad, chamfer, delete): """Process the selection and draw the actual object.""" sels = Gui.Selection.getSelectionEx("", 0) - objs = [] - objs_str = [] - doc = "FreeCAD.ActiveDocument." - for sel in sels: - for sub in sel.SubElementNames if sel.SubElementNames else [""]: - objs.append(sel.Object.getSubObject(sub)) - objs_str.append(doc + sel.Object.Name + ".getSubObject('" + sub + "')") - - edges = make_fillet._preprocess(objs, rad, chamfer) + edges, _ = make_fillet._preprocess(sels, rad, chamfer) if edges is None: _err(translate("draft", "Fillet cannot be created")) self.finish() @@ -156,20 +152,18 @@ class Fillet(gui_base_original.Creator): Gui.addModule("Draft") - _cmd = "Draft.make_fillet" - _cmd += "(" - _cmd += "[" + objs_str[0] + ", " + objs_str[1] + "], " - _cmd += "radius=" + str(rad) + cmd = "Draft.make_fillet(sels, radius=" + str(rad) if chamfer: - _cmd += ", chamfer=True" + cmd += ", chamfer=True" if delete: - _cmd += ", delete=True" - _cmd += ")" - _cmd_list = ["fillet = " + _cmd, - "Draft.autogroup(fillet)", - "FreeCAD.ActiveDocument.recompute()"] + cmd += ", delete=True" + cmd += ")" + cmd_list = ["sels = FreeCADGui.Selection.getSelectionEx('', 0)", + "fillet = " + cmd, + "Draft.autogroup(fillet)", + "FreeCAD.ActiveDocument.recompute()"] - self.commit(translate("draft", "Create fillet"), _cmd_list) + self.commit(translate("draft", "Create fillet"), cmd_list) self.finish() diff --git a/src/Mod/Draft/draftmake/make_fillet.py b/src/Mod/Draft/draftmake/make_fillet.py index 7576d3992d..5b874032e9 100644 --- a/src/Mod/Draft/draftmake/make_fillet.py +++ b/src/Mod/Draft/draftmake/make_fillet.py @@ -1,5 +1,6 @@ # *************************************************************************** # * Copyright (c) 2019 Eliud Cabrera Castillo * +# * Copyright (c) 2024 FreeCAD Project Association * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * @@ -47,43 +48,48 @@ DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils") ## \addtogroup draftmake # @{ -def _extract_edge(obj): - """Extract the 1st edge from an object or shape.""" - if hasattr(obj, "Shape"): - obj = obj.Shape - if hasattr(obj, "ShapeType") and obj.ShapeType in ("Wire", "Edge"): - return obj.Edges[0] - return None - - def _preprocess(objs, radius, chamfer): - """Check the inputs and return the edges for the fillet.""" - if len(objs) != 2: - _err(translate("draft", "Two objects are needed.")) - return None + """Check the inputs and return the edges for the fillet and the objects to be deleted.""" + edges = [] + del_objs = [] + if objs[0].isDerivedFrom("Gui::SelectionObject"): + for sel in objs: + for sub in sel.SubElementNames if sel.SubElementNames else [""]: + shape = sel.Object.getSubObject(sub) + if shape.ShapeType == "Edge": + edges.append(shape) + if sel.Object not in del_objs: + del_objs.append(sel.Object) + else: + for obj in objs: + if hasattr(obj, "Shape"): + shape = obj.Shape + del_objs.append(obj) + else: + shape = obj + if hasattr(shape, "ShapeType") and shape.ShapeType in ("Wire", "Edge"): + edges.append(shape.Edges[0]) - edge1 = _extract_edge(objs[0]) - edge2 = _extract_edge(objs[1]) + if len(edges) != 2: + _err(translate("draft", "Two edges are needed.")) + return None, None - if edge1 is None or edge2 is None: - _err(translate("draft", "One object is not valid.")) - return None - - edges = DraftGeomUtils.fillet([edge1, edge2], radius, chamfer) + edges = DraftGeomUtils.fillet(edges, radius, chamfer) if len(edges) < 3: _err(translate("draft", "Edges are not connected or radius is too large.")) - return None + return None, None - return edges + return edges, del_objs def make_fillet(objs, radius=100, chamfer=False, delete=False): - """Create a fillet between two lines or Part.Edges. + """Create a fillet between two edges. Parameters ---------- objs: list - List of two objects of type wire, or edges. + A list of two objects or shapes of type wire (1st edge is used) or edge, + or a 2 edge selection set:`FreeCADGui.Selection.getSelectionEx("", 0)`. radius: float, optional It defaults to 100. The curvature of the fillet. @@ -94,9 +100,8 @@ def make_fillet(objs, radius=100, chamfer=False, delete=False): with the value of the `radius`. delete: bool, optional - It defaults to `False`. If it is `True` it will delete - the pair of objects that are used to create the fillet. - Otherwise, the original objects will still be there. + It defaults to `False`. If `True` the source objects are deleted. + Ignored for shapes. Returns ------- @@ -105,7 +110,7 @@ def make_fillet(objs, radius=100, chamfer=False, delete=False): It returns `None` if it fails producing the object. """ - edges = _preprocess(objs, radius, chamfer) + edges, del_objs = _preprocess(objs, radius, chamfer) if edges is None: return @@ -124,8 +129,8 @@ def make_fillet(objs, radius=100, chamfer=False, delete=False): obj.FilletRadius = radius if delete: - doc.removeObject(objs[0].Name) - doc.removeObject(objs[1].Name) + for del_obj in del_objs: + doc.removeObject(del_obj.Name) if App.GuiUp: view_fillet.ViewProviderFillet(obj.ViewObject)