diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index d5353eddb110..73ae6aabf955 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -76,10 +76,6 @@ from DraftLayer import ViewProviderLayer as _ViewProviderVisGroup from DraftLayer import makeLayer -# import DraftFillet -# Fillet = DraftFillet.Fillet -# makeFillet = DraftFillet.makeFillet - # --------------------------------------------------------------------------- # General functions # --------------------------------------------------------------------------- diff --git a/src/Mod/Draft/DraftFillet.py b/src/Mod/Draft/DraftFillet.py index 020f283b2b33..10491986b875 100644 --- a/src/Mod/Draft/DraftFillet.py +++ b/src/Mod/Draft/DraftFillet.py @@ -1,319 +1,76 @@ -"""This module provides the Draft fillet tool. +# *************************************************************************** +# * Copyright (c) 2020 Eliud Cabrera Castillo * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** +"""Provides the Fillet class for objects created with a prototype version. + +The original Fillet object and Gui Command was introduced +in the development cycle of 0.19, in commit d5ca09c77b, 2019-08-22. + +However, when this class was implemented, the reorganization +of the workbench was not advanced. + +When the reorganization was on its way it was clear that this tool +also needed to be broken into different modules; however, this was done +only at the end of the reorganization. + +In commit 01df7c0a63, 2020-02-10, the Gui Command was removed from +the graphical interface so that the user cannot create this object +graphically any more. The object class was still kept +so that previous objects created between August 2019 and February 2020 +would open correctly. + +Now in this module the older class is redirected to the new class +in order to migrate the object. + +A new Gui Command in `draftguitools` and new make function in `draftmake` +are now used to create `Fillet` objects. Therefore, this module +is only required to migrate old objects created in that time +with the 0.19 development version. + +Since this module is only used to migrate older objects, it is only temporary, +and will be removed after one year of the original introduction of the tool, +that is, in August 2020. """ ## @package DraftFillet # \ingroup DRAFT -# \brief This module provides the Draft fillet tool. +# \brief Provides Fillet class for objects created with a prototype version. +# +# This module is only required to migrate old objects created +# from August 2019 to February 2020. It will be removed definitely +# in August 2020, as the new Fillet object should be available. -import FreeCAD -from FreeCAD import Console as FCC -import Draft -import DraftGeomUtils -import Part +import draftobjects.fillet -if FreeCAD.GuiUp: - import FreeCADGui - from PySide.QtCore import QT_TRANSLATE_NOOP - from PySide import QtCore - import DraftTools - import draftguitools.gui_trackers as trackers - from DraftGui import translate -else: - def QT_TRANSLATE_NOOP(context, text): - return text +# ----------------------------------------------------------------------------- +# Removed definitions +# def _extract_edges(objs): - def translate(context, text): - return text +# def makeFillet(objs, radius=100, chamfer=False, delete=False): +# class Fillet(Draft._DraftObject): -def _extract_edges(objs): - """Extract the edges from the given objects (Draft lines or Edges). +# class CommandFillet(DraftTools.Creator): +# ----------------------------------------------------------------------------- - objs : list of Draft Lines or Part.Edges - The list of edges from which to create the fillet. - """ - o1, o2 = objs - if hasattr(o1, "PropertiesList"): - if "Proxy" in o1.PropertiesList: - if hasattr(o1.Proxy, "Type"): - if o1.Proxy.Type in ("Wire", "Fillet"): - e1 = o1.Shape.Edges[0] - elif "Shape" in o1.PropertiesList: - if o1.Shape.ShapeType in ("Wire", "Edge"): - e1 = o1.Shape - elif hasattr(o1, "ShapeType"): - if o1.ShapeType in "Edge": - e1 = o1 - - if hasattr(o1, "Label"): - FCC.PrintMessage("o1: " + o1.Label) - else: - FCC.PrintMessage("o1: 1") - FCC.PrintMessage(", length: " + str(e1.Length) + "\n") - - if hasattr(o2, "PropertiesList"): - if "Proxy" in o2.PropertiesList: - if hasattr(o2.Proxy, "Type"): - if o2.Proxy.Type in ("Wire", "Fillet"): - e2 = o2.Shape.Edges[0] - elif "Shape" in o2.PropertiesList: - if o2.Shape.ShapeType in ("Wire", "Edge"): - e2 = o2.Shape - elif hasattr(o2, "ShapeType"): - if o2.ShapeType in "Edge": - e2 = o2 - - if hasattr(o2, "Label"): - FCC.PrintMessage("o2: " + o2.Label) - else: - FCC.PrintMessage("o2: 2") - FCC.PrintMessage(", length: " + str(e2.Length) + "\n") - - return e1, e2 - - -def makeFillet(objs, radius=100, chamfer=False, delete=False): - """Create a fillet between two lines or edges. - - Parameters - ---------- - objs : list - List of two objects of type wire, or edges. - radius : float, optional - It defaults to 100 mm. The curvature of the fillet. - chamfer : bool, optional - It defaults to `False`. If it is `True` it no longer produces - a rounded fillet but a chamfer (straight edge) - 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. - - Returns - ------- - Part::Part2DObject - The object of type `'Fillet'`. - It returns `None` if it fails producing the object. - """ - if len(objs) != 2: - FCC.PrintError("makeFillet: " - + translate("draft", "two elements needed") + "\n") - return None - - e1, e2 = _extract_edges(objs) - - edges = DraftGeomUtils.fillet([e1, e2], radius, chamfer) - if len(edges) < 3: - FCC.PrintError("makeFillet: " - + translate("draft", "radius too large")) - FCC.PrintError(", r=" + str(radius) + "\n") - return None - - _d = translate("draft", "length: ") - FCC.PrintMessage("e1, " + _d + str(edges[0].Length) + "\n") - FCC.PrintMessage("e2, " + _d + str(edges[1].Length) + "\n") - FCC.PrintMessage("e3, " + _d + str(edges[2].Length) + "\n") - - try: - wire = Part.Wire(edges) - except Part.OCCError: - return None - - obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython", - "Fillet") - Fillet(obj) - obj.Shape = wire - obj.Length = wire.Length - obj.Start = wire.Vertexes[0].Point - obj.End = wire.Vertexes[-1].Point - obj.FilletRadius = radius - - if delete: - FreeCAD.ActiveDocument.removeObject(objs[0].Name) - FreeCAD.ActiveDocument.removeObject(objs[1].Name) - _r = translate("draft", "removed original objects") - FCC.PrintMessage("makeFillet: " + _r + "\n") - if FreeCAD.GuiUp: - Draft._ViewProviderWire(obj.ViewObject) - Draft.formatObject(obj) - Draft.select(obj) - return obj - - -class Fillet(Draft._DraftObject): - """The fillet object""" - - def __init__(self, obj): - Draft._DraftObject.__init__(self, obj, "Fillet") - obj.addProperty("App::PropertyVectorDistance", "Start", "Draft", QT_TRANSLATE_NOOP("App::Property", "The start point of this line")) - obj.addProperty("App::PropertyVectorDistance", "End", "Draft", QT_TRANSLATE_NOOP("App::Property", "The end point of this line")) - obj.addProperty("App::PropertyLength", "Length", "Draft", QT_TRANSLATE_NOOP("App::Property", "The length of this line")) - obj.addProperty("App::PropertyLength", "FilletRadius", "Draft", QT_TRANSLATE_NOOP("App::Property", "Radius to use to fillet the corners")) - obj.setEditorMode("Start", 1) - obj.setEditorMode("End", 1) - obj.setEditorMode("Length", 1) - # Change to 0 to make it editable - obj.setEditorMode("FilletRadius", 1) - - def execute(self, obj): - if hasattr(obj, "Length"): - obj.Length = obj.Shape.Length - if hasattr(obj, "Start"): - obj.Start = obj.Shape.Vertexes[0].Point - if hasattr(obj, "End"): - obj.End = obj.Shape.Vertexes[-1].Point - - def onChanged(self, obj, prop): - # Change the radius of fillet. NOT IMPLEMENTED. - if prop in "FilletRadius": - pass - - -class CommandFillet(DraftTools.Creator): - """The Fillet GUI command definition""" - - def __init__(self): - DraftTools.Creator.__init__(self) - self.featureName = "Fillet" - - def GetResources(self): - return {'Pixmap': 'Draft_Fillet.svg', - 'MenuText': QT_TRANSLATE_NOOP("draft", "Fillet"), - 'ToolTip': QT_TRANSLATE_NOOP("draft", "Creates a fillet between two wires or edges.") - } - - def Activated(self, name=translate("draft", "Fillet")): - DraftTools.Creator.Activated(self, name) - if not self.doc: - FCC.PrintWarning(translate("draft", "No active document") + "\n") - return - if self.ui: - self.rad = 100 - self.chamfer = False - self.delete = False - label = translate("draft", "Fillet radius") - tooltip = translate("draft", "Radius of fillet") - - # Call the Task panel for a radius - # The graphical widgets are defined in DraftGui - self.ui.taskUi(title=name, icon="Draft_Fillet") - self.ui.radiusUi() - self.ui.sourceCmd = self - self.ui.labelRadius.setText(label) - self.ui.radiusValue.setToolTip(tooltip) - self.ui.setRadiusValue(self.rad, "Length") - self.ui.check_delete = self.ui._checkbox("isdelete", - self.ui.layout, - checked=self.delete) - self.ui.check_delete.setText(translate("draft", - "Delete original objects")) - self.ui.check_delete.show() - self.ui.check_chamfer = self.ui._checkbox("ischamfer", - self.ui.layout, - checked=self.chamfer) - self.ui.check_chamfer.setText(translate("draft", - "Create chamfer")) - self.ui.check_chamfer.show() - - QtCore.QObject.connect(self.ui.check_delete, - QtCore.SIGNAL("stateChanged(int)"), - self.set_delete) - QtCore.QObject.connect(self.ui.check_chamfer, - QtCore.SIGNAL("stateChanged(int)"), - self.set_chamfer) - self.linetrack = trackers.lineTracker(dotted=True) - self.arctrack = trackers.arcTracker() - # self.call = self.view.addEventCallback("SoEvent", self.action) - FCC.PrintMessage(translate("draft", "Enter radius") + "\n") - - def action(self, arg): - """Scene event handler. CURRENTLY NOT USED. - - Here the displaying of the trackers (previews) - should be implemented by considering the current value of the - `ui.radiusValue`. - """ - if arg["Type"] == "SoKeyboardEvent": - if arg["Key"] == "ESCAPE": - self.finish() - elif arg["Type"] == "SoLocation2Event": - self.point, ctrlPoint, info = DraftTools.getPoint(self, arg) - DraftTools.redraw3DView() - - def set_delete(self): - """This function is called when the delete checkbox changes""" - self.delete = self.ui.check_delete.isChecked() - FCC.PrintMessage(translate("draft", "Delete original objects: ") - + str(self.delete) + "\n") - - def set_chamfer(self): - """This function is called when the chamfer checkbox changes""" - self.chamfer = self.ui.check_chamfer.isChecked() - FCC.PrintMessage(translate("draft", "Chamfer mode: ") - + str(self.chamfer) + "\n") - - def numericRadius(self, rad): - """This function is called when a valid radius is entered""" - self.rad = rad - self.draw_arc(rad, self.chamfer, self.delete) - self.finish() - - def draw_arc(self, rad, chamfer, delete): - """Processes the selection and draws the actual object""" - wires = FreeCADGui.Selection.getSelection() - _two = translate("draft", "two elements needed") - if not wires: - FCC.PrintError("CommandFillet: " + _two + "\n") - return - if len(wires) != 2: - FCC.PrintError("CommandFillet: " + _two + "\n") - return - - for o in wires: - FCC.PrintMessage("CommandFillet: " + Draft.getType(o) + "\n") - - _test = translate("draft", "Test object") - _test_off = translate("draft", "Test object removed") - _cant = translate("draft", "fillet cannot be created") - - FCC.PrintMessage(4*"=" + _test + "\n") - arc = makeFillet(wires, rad) - if not arc: - FCC.PrintError("CommandFillet: " + _cant + "\n") - return - self.doc.removeObject(arc.Name) - FCC.PrintMessage(4*"=" + _test_off + "\n") - - doc = 'FreeCAD.ActiveDocument.' - _wires = '[' + doc + wires[0].Name + ', ' + doc + wires[1].Name + ']' - - FreeCADGui.addModule("DraftFillet") - name = translate("draft", "Create fillet") - - args = _wires + ', radius=' + str(rad) - if chamfer: - args += ', chamfer=' + str(chamfer) - if delete: - args += ', delete=' + str(delete) - func = ['arc = DraftFillet.makeFillet(' + args + ')'] - func.append('Draft.autogroup(arc)') - - # Here we could remove the old objects, but the makeFillet() - # command already includes an option to remove them. - # Therefore, the following is not necessary - # rems = [doc + 'removeObject("' + o.Name + '")' for o in wires] - # func.extend(rems) - func.append('FreeCAD.ActiveDocument.recompute()') - self.commit(name, func) - - def finish(self, close=False): - """Terminates the operation.""" - DraftTools.Creator.finish(self) - if self.ui: - self.linetrack.finalize() - self.arctrack.finalize() - self.doc.recompute() - - -if FreeCAD.GuiUp: - FreeCADGui.addCommand('Draft_Fillet', CommandFillet()) +# When an old object is opened it will reconstruct the object +# by searching for the class `DraftFillet.Fillet`. +# So we redirect this class to the new class in the new module. +# This migrates the old object to the new object. +Fillet = draftobjects.fillet.Fillet diff --git a/src/Mod/Draft/draftguitools/gui_fillets.py b/src/Mod/Draft/draftguitools/gui_fillets.py index 60597d08960f..f8619665e775 100644 --- a/src/Mod/Draft/draftguitools/gui_fillets.py +++ b/src/Mod/Draft/draftguitools/gui_fillets.py @@ -201,4 +201,4 @@ def finish(self, close=False): self.doc.recompute() -Gui.addCommand('Draft_Fillet_new', Fillet()) +Gui.addCommand('Draft_Fillet', Fillet()) diff --git a/src/Mod/Draft/drafttests/draft_test_objects.py b/src/Mod/Draft/drafttests/draft_test_objects.py index b9f35296c02f..487c151a2d86 100644 --- a/src/Mod/Draft/drafttests/draft_test_objects.py +++ b/src/Mod/Draft/drafttests/draft_test_objects.py @@ -35,11 +35,11 @@ import FreeCAD as App import Draft -from FreeCAD import Vector + from draftutils.messages import _msg, _wrn +from FreeCAD import Vector if App.GuiUp: - import DraftFillet import FreeCADGui as Gui @@ -141,13 +141,7 @@ def create_test_file(file_name="draft_test_objects", line_h_2.ViewObject.DrawStyle = "Dotted" App.ActiveDocument.recompute() - try: - DraftFillet.makeFillet([line_h_1, line_h_2], 400) - except Exception: - _wrn("Fillet could not be created") - _wrn("Possible cause: at this moment it may need the interface") - rect = Draft.makeRectangle(500, 100) - rect.Placement.Base = Vector(14000, 500) + Draft.make_fillet([line_h_1, line_h_2], 400) t_xpos += 900 _t = Draft.makeText(["Fillet"], Vector(t_xpos, t_ypos, 0)) diff --git a/src/Mod/Draft/drafttests/test_creation.py b/src/Mod/Draft/drafttests/test_creation.py index b6a91c3f4406..47ca0514d353 100644 --- a/src/Mod/Draft/drafttests/test_creation.py +++ b/src/Mod/Draft/drafttests/test_creation.py @@ -88,16 +88,10 @@ def test_fillet(self): L2 = Draft.makeLine(b, c) self.doc.recompute() - if not App.GuiUp: - aux._no_gui("DraftFillet") - self.assertTrue(True) - return - - import DraftFillet radius = 4 _msg(" Fillet") _msg(" radius={}".format(radius)) - obj = DraftFillet.makeFillet([L1, L2], radius) + obj = Draft.make_fillet([L1, L2], radius) self.assertTrue(obj, "'{}' failed".format(operation)) def test_circle(self): diff --git a/src/Mod/Draft/draftutils/init_tools.py b/src/Mod/Draft/draftutils/init_tools.py index 7fb51e2161d8..4464d9b7c169 100644 --- a/src/Mod/Draft/draftutils/init_tools.py +++ b/src/Mod/Draft/draftutils/init_tools.py @@ -38,7 +38,7 @@ def get_draft_drawing_commands(): """Return the drawing commands list.""" - return ["Draft_Line", "Draft_Wire", "Draft_Fillet", "Draft_Fillet_new", + return ["Draft_Line", "Draft_Wire", "Draft_Fillet", "Draft_ArcTools", "Draft_Circle", "Draft_Ellipse", "Draft_Rectangle", "Draft_Polygon", "Draft_BSpline", "Draft_BezierTools",