From 09e47f43a9e54514aa910cc9e1487015fe58954a Mon Sep 17 00:00:00 2001 From: vocx-fc Date: Thu, 30 Apr 2020 23:33:12 -0500 Subject: [PATCH] Draft: add new Gui Command for Fillet --- src/Mod/Draft/CMakeLists.txt | 1 + src/Mod/Draft/DraftTools.py | 1 + src/Mod/Draft/draftguitools/gui_fillets.py | 204 +++++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 src/Mod/Draft/draftguitools/gui_fillets.py diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index 40f971ccfe..26f3176c17 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -153,6 +153,7 @@ SET(Draft_view_providers SET(Creator_tools draftguitools/gui_lines.py + draftguitools/gui_fillets.py draftguitools/gui_splines.py draftguitools/gui_beziers.py draftguitools/gui_rectangles.py diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 30f52b6018..c9f403ae7f 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -150,6 +150,7 @@ from draftguitools.gui_base_original import Creator from draftguitools.gui_lines import Line from draftguitools.gui_lines import Wire +from draftguitools.gui_fillets import Fillet from draftguitools.gui_splines import BSpline from draftguitools.gui_beziers import BezCurve from draftguitools.gui_beziers import CubicBezCurve diff --git a/src/Mod/Draft/draftguitools/gui_fillets.py b/src/Mod/Draft/draftguitools/gui_fillets.py new file mode 100644 index 0000000000..60597d0896 --- /dev/null +++ b/src/Mod/Draft/draftguitools/gui_fillets.py @@ -0,0 +1,204 @@ +# *************************************************************************** +# * (c) 2020 Eliud Cabrera Castillo * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * 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. * +# * * +# * FreeCAD 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 FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** +"""Provides tools for creating fillets between two lines. + +TODO: Currently this tool uses the DraftGui widgets. We want to avoid using +this big module because it creates manually the interface. +Instead we should provide its own .ui file and task panel, +similar to the Ortho Array tool. +""" +## @package gui_fillet +# \ingroup DRAFT +# \brief Provides tools for creating fillets between two lines. + +import PySide.QtCore as QtCore +from PySide.QtCore import QT_TRANSLATE_NOOP + +import FreeCADGui as Gui +import Draft +import Draft_rc +import draftutils.utils as utils +import draftguitools.gui_base_original as gui_base_original +import draftguitools.gui_tool_utils as gui_tool_utils +# import draftguitools.gui_trackers as trackers +from draftutils.messages import _msg, _err +from draftutils.translate import translate, _tr + +# The module is used to prevent complaints from code checkers (flake8) +True if Draft_rc.__name__ else False + + +class Fillet(gui_base_original.Creator): + """Gui command for the Fillet tool.""" + + def __init__(self): + super(Fillet, self).__init__() + self.featureName = "Fillet" + + def GetResources(self): + """Set icon, menu and tooltip.""" + _tip = "Creates a fillet between two selected wires or edges." + + return {'Pixmap': 'Draft_Fillet', + 'MenuText': QT_TRANSLATE_NOOP("Draft", "Fillet"), + 'ToolTip': QT_TRANSLATE_NOOP("Draft", _tip)} + + def Activated(self, name=translate("Draft", "Fillet")): + """Execute when the command is called.""" + super(Fillet, self).Activated(name=name) + + 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 defined in DraftGui to enter a radius. + 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() + + # TODO: change to Qt5 style + 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) + + # TODO: somehow we need to set up the trackers + # to show a preview of the fillet. + + # self.linetrack = trackers.lineTracker(dotted=True) + # self.arctrack = trackers.arcTracker() + # self.call = self.view.addEventCallback("SoEvent", self.action) + _msg(_tr("Enter radius.")) + + 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 = gui_tool_utils.getPoint(self, arg) + gui_tool_utils.redraw3DView() + + def set_delete(self): + """Execute as a callback when the delete checkbox changes.""" + self.delete = self.ui.check_delete.isChecked() + _msg(_tr("Delete original objects: ") + str(self.delete)) + + def set_chamfer(self): + """Execute as a callback when the chamfer checkbox changes.""" + self.chamfer = self.ui.check_chamfer.isChecked() + _msg(_tr("Chamfer mode: ") + str(self.chamfer)) + + def numericRadius(self, rad): + """Validate the entry radius in the user interface. + + This function is called by the toolbar or taskpanel interface + when a valid radius has been entered in the input field. + """ + self.rad = rad + self.draw_arc(rad, self.chamfer, self.delete) + self.finish() + + def draw_arc(self, rad, chamfer, delete): + """Process the selection and draw the actual object.""" + wires = Gui.Selection.getSelection() + + if not wires or len(wires) != 2: + _err(_tr("Two elements needed.")) + return + + for o in wires: + _msg(utils.get_type(o)) + + _test = translate("draft", "Test object") + _test_off = translate("draft", "Test object removed") + _cant = translate("draft", "Fillet cannot be created") + + _msg(4*"=" + _test) + arc = Draft.make_fillet(wires, rad) + if not arc: + _err(_cant) + return + self.doc.removeObject(arc.Name) + _msg(4*"=" + _test_off) + + _doc = 'FreeCAD.ActiveDocument.' + + _wires = '[' + _wires += _doc + wires[0].Name + ', ' + _wires += _doc + wires[1].Name + _wires += ']' + + Gui.addModule("Draft") + + _cmd = 'Draft.make_fillet' + _cmd += '(' + _cmd += _wires + ', ' + _cmd += 'radius=' + str(rad) + if chamfer: + _cmd += ', chamfer=' + str(chamfer) + if delete: + _cmd += ', delete=' + str(delete) + _cmd += ')' + _cmd_list = ['arc = ' + _cmd, + 'Draft.autogroup(arc)', + 'FreeCAD.ActiveDocument.recompute()'] + + self.commit(translate("draft", "Create fillet"), + _cmd_list) + + def finish(self, close=False): + """Terminate the operation.""" + super(Fillet, self).finish() + if self.ui: + # self.linetrack.finalize() + # self.arctrack.finalize() + self.doc.recompute() + + +Gui.addCommand('Draft_Fillet_new', Fillet())