diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt
index 7534672003..01b3605e68 100644
--- a/src/Mod/Path/CMakeLists.txt
+++ b/src/Mod/Path/CMakeLists.txt
@@ -57,9 +57,10 @@ SET(PathScripts_SRCS
PathScripts/PathPreferencesPathDressup.py
PathScripts/PathPreferencesPathJob.py
PathScripts/PathProfileBase.py
+ PathScripts/PathProfileEdges.py
+ PathScripts/PathProfileEdgesGui.py
PathScripts/PathProfileFaces.py
PathScripts/PathProfileFacesGui.py
- PathScripts/PathProfileEdges.py
PathScripts/PathSanity.py
PathScripts/PathSelection.py
PathScripts/PathSimpleCopy.py
diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc
index efc9742cfd..ac791c3ce0 100644
--- a/src/Mod/Path/Gui/Resources/Path.qrc
+++ b/src/Mod/Path/Gui/Resources/Path.qrc
@@ -66,6 +66,7 @@
panels/PageHeightsEdit.ui
panels/PageOpContourEdit.ui
panels/PageOpPocketEdit.ui
+ panels/PageOpProfileEdgesEdit.ui
panels/PageOpProfileFacesEdit.ui
panels/PocketEdit.ui
panels/PointEdit.ui
diff --git a/src/Mod/Path/Gui/Resources/panels/PageOpContourEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageOpContourEdit.ui
index 18af8df671..c5634c1ce5 100644
--- a/src/Mod/Path/Gui/Resources/panels/PageOpContourEdit.ui
+++ b/src/Mod/Path/Gui/Resources/panels/PageOpContourEdit.ui
@@ -7,14 +7,14 @@
0
0
424
- 428
+ 263
Form
-
- -
+
+
-
QFrame::StyledPanel
@@ -36,50 +36,82 @@
- -
-
-
- Direction
+
-
+
+
+
-
+
+
+ Direction
+
+
+
+ -
+
+
-
+
+ CW
+
+
+ -
+
+ CCW
+
+
+
+
+ -
+
+
+ Extra Offset
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
-
+
+
+ Use Start Point
+
+
+
+ -
+
+
+ Use Compensation
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
-
-
- -
-
-
-
-
- CW
-
-
- -
-
- CCW
-
-
-
-
- -
-
-
- Use Start Point
+
+
+ 20
+ 1
+
-
-
- -
-
-
- Use Compensation
-
-
-
- -
-
-
- Extra Offset
-
-
-
- -
-
+
diff --git a/src/Mod/Path/Gui/Resources/panels/PageOpProfileEdgesEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageOpProfileEdgesEdit.ui
new file mode 100644
index 0000000000..914e41eb09
--- /dev/null
+++ b/src/Mod/Path/Gui/Resources/panels/PageOpProfileEdgesEdit.ui
@@ -0,0 +1,148 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 400
+ 298
+
+
+
+ Form
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ Tool Controller
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
-
+
+
+ Cut Side
+
+
+
+ -
+
+
-
+
+ Outside
+
+
+ -
+
+ Inside
+
+
+
+
+ -
+
+
+ Direction
+
+
+
+ -
+
+
-
+
+ CW
+
+
+ -
+
+ CCW
+
+
+
+
+ -
+
+
+ Extra Offset
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
-
+
+
+ Use Compensation
+
+
+
+ -
+
+
+ Use Start Point
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ Gui::InputField
+ QLineEdit
+
+
+
+
+
+
diff --git a/src/Mod/Path/Gui/Resources/panels/PageOpProfileFacesEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageOpProfileFacesEdit.ui
index 44f8fa3791..3f32a4c7d8 100644
--- a/src/Mod/Path/Gui/Resources/panels/PageOpProfileFacesEdit.ui
+++ b/src/Mod/Path/Gui/Resources/panels/PageOpProfileFacesEdit.ui
@@ -7,7 +7,7 @@
0
0
446
- 419
+ 342
diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py
index ed349176ed..9b32ce62b4 100644
--- a/src/Mod/Path/InitGui.py
+++ b/src/Mod/Path/InitGui.py
@@ -67,8 +67,8 @@ class PathWorkbench (Workbench):
from PathScripts import PathPlane
from PathScripts import PathPocketGui
from PathScripts import PathPost
+ from PathScripts import PathProfileEdgesGui
from PathScripts import PathProfileFacesGui
- from PathScripts import PathProfileEdges
from PathScripts import PathSanity
from PathScripts import PathSimpleCopy
from PathScripts import PathStock
@@ -83,7 +83,7 @@ class PathWorkbench (Workbench):
projcmdlist = ["Path_Job", "Path_Post", "Path_Inspect", "Path_Sanity"]
toolcmdlist = ["Path_ToolLibraryEdit"]
prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_ToolLenOffset", "Path_Comment", "Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_Shape"]
- twodopcmdlist = ["Path_Contour", "Path_Profile", "Path_Profile_Edges", "Path_Pocket", "Path_Drilling", "Path_Engrave", "Path_MillFace", "Path_Helix"]
+ twodopcmdlist = ["Path_Contour", "Path_Profile_Faces", "Path_Profile_Edges", "Path_Pocket", "Path_Drilling", "Path_Engrave", "Path_MillFace", "Path_Helix"]
threedopcmdlist = ["Path_Surfacing"]
modcmdlist = ["Path_Copy", "Path_CompoundExtended", "Path_Array", "Path_SimpleCopy" ]
dressupcmdlist = ["PathDressup_Dogbone", "PathDressup_DragKnife", "PathDressup_Tag", "PathDressup_RampEntry"]
diff --git a/src/Mod/Path/PathScripts/PathAreaOpGui.py b/src/Mod/Path/PathScripts/PathAreaOpGui.py
index e48f5b63d0..f14b377d70 100644
--- a/src/Mod/Path/PathScripts/PathAreaOpGui.py
+++ b/src/Mod/Path/PathScripts/PathAreaOpGui.py
@@ -529,7 +529,7 @@ def SetupOperation(name,
toolTip):
res = CommandResources(name, objFactory, opPageClass, pixmap, menuText, accelKey, toolTip)
- FreeCADGui.addCommand("Path_%s" % name, CommandPathOp(res))
+ FreeCADGui.addCommand("Path_%s" % name.replace(' ', '_'), CommandPathOp(res))
FreeCADGui.addCommand('Set_StartPoint', _CommandSetStartPoint())
diff --git a/src/Mod/Path/PathScripts/PathProfileEdges.py b/src/Mod/Path/PathScripts/PathProfileEdges.py
index ea1e3f8240..6162090815 100644
--- a/src/Mod/Path/PathScripts/PathProfileEdges.py
+++ b/src/Mod/Path/PathScripts/PathProfileEdges.py
@@ -23,18 +23,19 @@
# ***************************************************************************
import FreeCAD
-import Path
import Part
-from PathScripts import PathUtils
-from PathScripts.PathUtils import depth_params
-from DraftGeomUtils import findWires
-from DraftGeomUtils import isReallyClosed
+import Path
+import PathScripts.PathAreaOp as PathAreaOp
+import PathScripts.PathProfileBase as PathProfileBase
+import PathScripts.PathUtils as PathUtils
import PathScripts.PathLog as PathLog
-from PathScripts.PathUtils import waiting_effects
+
+from DraftGeomUtils import findWires
+from PySide import QtCore
"""Path Profile from Edges Object and Command"""
-if False:
+if True:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
@@ -42,7 +43,7 @@ else:
if FreeCAD.GuiUp:
import FreeCADGui
- from PySide import QtCore, QtGui
+ from PySide import QtGui
# Qt tanslation handling
@@ -56,213 +57,21 @@ __url__ = "http://www.freecadweb.org"
"""Path Profile object and FreeCAD command for operating on sets of edges"""
-class ObjectProfile:
+class ObjectProfile(PathProfileBase.ObjectProfile):
- def __init__(self, obj):
- obj.addProperty("App::PropertyLinkSubList", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The base geometry of this toolpath"))
- obj.addProperty("App::PropertyBool", "Active", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Make False, to prevent operation from generating code"))
- obj.addProperty("App::PropertyString", "Comment", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "An optional comment for this profile"))
- obj.addProperty("App::PropertyString", "UserLabel", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "User Assigned Label"))
+ def baseObject(self):
+ return super(self.__class__, self)
- # Tool Properties
- obj.addProperty("App::PropertyLink", "ToolController", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The tool controller that will be used to calculate the path"))
+ def opFeatures(self, obj):
+ return self.baseObject().opFeatures(obj) | PathAreaOp.FeatureBaseEdges
- # Depth Properties
- obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Starting Depth of Tool- first cut depth in Z"))
- obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Final Depth of Tool- lowest value in Z"))
- obj.addProperty("App::PropertyDistance", "StepDown", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Incremental Step Down of Tool"))
-
- # Heights
- obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Rapid Safety Height between locations"))
- obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "The height needed to clear clamps and obstructions"))
-
- # Start Point Properties
- obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "The start point of this path"))
- obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if specifying a Start Point"))
-
- # Profile Properties
- obj.addProperty("App::PropertyEnumeration", "Side", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut"))
- obj.Side = ['Outside', 'Inside'] # side of profile that cutter is on in relation to direction of profile
- obj.addProperty("App::PropertyEnumeration", "Direction", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "The direction that the toolpath should go around the part ClockWise CW or CounterClockWise CCW"))
- obj.Direction = ['CW', 'CCW'] # this is the direction that the profile runs
- obj.addProperty("App::PropertyBool", "UseComp", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if using Cutter Radius Compensation"))
-
- obj.addProperty("App::PropertyDistance", "OffsetExtra", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Extra value to stay away from final profile- good for roughing toolpath"))
- obj.addProperty("App::PropertyEnumeration", "JoinType", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Controls how tool moves around corners. Default=Round"))
- obj.JoinType = ['Round', 'Square', 'Miter'] # this is the direction that the Contour runs
- obj.addProperty("App::PropertyFloat", "MiterLimit", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Maximum distance before a miter join is truncated"))
-
-
- # Debug Parameters
- obj.addProperty("App::PropertyString", "AreaParams", "Path")
- obj.setEditorMode('AreaParams', 2) # hide
- obj.addProperty("App::PropertyString", "PathParams", "Path")
- obj.setEditorMode('PathParams', 2) # hide
- obj.addProperty("Part::PropertyPartShape", "removalshape", "Path")
- obj.setEditorMode('removalshape', 2) # hide
-
- if FreeCAD.GuiUp:
- _ViewProviderProfile(obj.ViewObject)
-
- obj.Proxy = self
-
- def __getstate__(self):
- return None
-
- def __setstate__(self, state):
- return None
-
- def onChanged(self, obj, prop):
- if prop == "UseComp":
- if not obj.UseComp:
- obj.setEditorMode('Side', 2)
- else:
- obj.setEditorMode('Side', 0)
- if prop in ['AreaParams', 'PathParams', 'removalshape']:
- obj.setEditorMode(prop, 2)
-
- obj.setEditorMode('MiterLimit', 2)
- if obj.JoinType == 'Miter':
- obj.setEditorMode('MiterLimit', 0)
-
-
- def addprofilebase(self, obj, ss, sub=""):
- baselist = obj.Base
- if len(baselist) == 0: # When adding the first base object, guess at heights
- try:
- bb = ss.Shape.BoundBox # parent boundbox
- subobj = ss.Shape.getElement(sub)
- fbb = subobj.BoundBox # feature boundbox
- obj.StartDepth = bb.ZMax
- obj.ClearanceHeight = bb.ZMax + 5.0
- obj.SafeHeight = bb.ZMax + 3.0
-
- if fbb.ZMax == fbb.ZMin and fbb.ZMax == bb.ZMax: # top face
- obj.FinalDepth = bb.ZMin
- elif fbb.ZMax > fbb.ZMin and fbb.ZMax == bb.ZMax: # vertical face, full cut
- obj.FinalDepth = fbb.ZMin
- elif fbb.ZMax > fbb.ZMin and fbb.ZMin > bb.ZMin: # internal vertical wall
- obj.FinalDepth = fbb.ZMin
- elif fbb.ZMax == fbb.ZMin and fbb.ZMax > bb.ZMin: # face/shelf
- obj.FinalDepth = fbb.ZMin
- else: # catch all
- obj.FinalDepth = bb.ZMin
- except:
- obj.StartDepth = 5.0
- obj.ClearanceHeight = 10.0
- obj.SafeHeight = 8.0
-
- item = (ss, sub)
- if item in baselist:
- FreeCAD.Console.PrintWarning("this object already in the list" + "\n")
- else:
- baselist.append(item)
- obj.Base = baselist
-
- @waiting_effects
- def _buildPathArea(self, obj, baseobject, start=None, getsim=False):
+ def opShapes(self, obj, commandlist):
PathLog.track()
- profile = Path.Area()
- profile.setPlane(Part.makeCircle(10))
- profile.add(baseobject)
- profileparams = {'Fill': 0,
- 'Coplanar': 0,
- 'Offset': 0.0,
- 'SectionCount': -1}
-
- if obj.UseComp:
- if obj.Side == 'Inside':
- profileparams['Offset'] = 0 - self.radius+obj.OffsetExtra.Value
- else:
- profileparams['Offset'] = self.radius+obj.OffsetExtra.Value
-
- jointype = ['Round', 'Square', 'Miter']
- profileparams['JoinType'] = jointype.index(obj.JoinType)
-
- if obj.JoinType == 'Miter':
- profileparams['MiterLimit'] = obj.MiterLimit
-
- profile.setParams(**profileparams)
- obj.AreaParams = str(profile.getParams())
-
- PathLog.debug("About to profile with params: {}".format(profile.getParams()))
-
- heights = [i for i in self.depthparams]
- sections = profile.makeSections(mode=0, project=True, heights=heights)
- shapelist = [sec.getShape() for sec in sections]
-
- params = {'shapes': shapelist,
- 'feedrate': self.horizFeed,
- 'feedrate_v': self.vertFeed,
- 'verbose': False,
- 'resume_height': obj.StepDown.Value,
- 'retraction': obj.ClearanceHeight.Value}
-
- if obj.Direction == 'CCW':
- params['orientation'] = 0
- else:
- params['orientation'] = 1
-
- if obj.UseStartPoint is True and obj.StartPoint is not None:
- params['start'] = obj.StartPoint
-
- pp = Path.fromShapes(**params)
- PathLog.debug("Generating Path with params: {}".format(params))
-
- # store the params for debugging. Don't need the shape.
- obj.PathParams = str({key: value for key, value in params.items() if key != 'shapes'})
-
- simobj = None
- if getsim:
- profileparams['Thicken'] = True
- profileparams['ToolRadius'] = self.radius - self.radius * .005
- profile.setParams(**profileparams)
- sec = profile.makeSections(mode=0, project=False, heights=heights)[-1].getShape()
- simobj = sec.extrude(FreeCAD.Vector(0, 0, baseobject.BoundBox.ZMax))
-
- return pp, simobj
-
- def execute(self, obj, getsim=False):
- commandlist = []
- sim = None
-
- if not obj.Active:
- path = Path.Path("(inactive operation)")
- obj.Path = path
- obj.ViewObject.Visibility = False
+ job = PathUtils.findParentJob(obj)
+ if not job or not job.Base:
return
-
- parentJob = PathUtils.findParentJob(obj)
- if parentJob is None:
- return
- baseobject = parentJob.Base
- if baseobject is None:
- return
-
- self.depthparams = depth_params(
- clearance_height=obj.ClearanceHeight.Value,
- safe_height=obj.SafeHeight.Value,
- start_depth=obj.StartDepth.Value,
- step_down=obj.StepDown.Value,
- z_finish_step=0.0,
- final_depth=obj.FinalDepth.Value,
- user_depths=None)
-
- toolLoad = obj.ToolController
- if toolLoad is None or toolLoad.ToolNumber == 0:
- FreeCAD.Console.PrintError("No Tool Controller is selected. We need a tool to build a Path.")
- else:
- self.vertFeed = toolLoad.VertFeed.Value
- self.horizFeed = toolLoad.HorizFeed.Value
- self.vertRapid = toolLoad.VertRapid.Value
- self.horizRapid = toolLoad.HorizRapid.Value
- tool = toolLoad.Proxy.getTool(toolLoad)
- if not tool or tool.Diameter == 0:
- FreeCAD.Console.PrintError("No Tool found or diameter is zero. We need a tool to build a Path.")
- return
- else:
- self.radius = tool.Diameter/2
+ baseobject = job.Base
commandlist.append(Path.Command("(" + obj.Label + ")"))
@@ -271,6 +80,7 @@ class ObjectProfile:
else:
commandlist.append(Path.Command("(Uncompensated Tool Path)"))
+ shapes = []
if obj.Base:
wires = []
@@ -289,373 +99,10 @@ class ObjectProfile:
newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), f.Placement.Rotation)
f.Placement = newPlace
env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, depthparams=self.depthparams)
+ shapes.append((env, False))
+ return shapes
- try:
- (pp, sim) = self._buildPathArea(obj, baseobject=env, start=obj.StartPoint, getsim=getsim)
- commandlist.extend(pp.Commands)
-
- except Exception as e:
- FreeCAD.Console.PrintError(e)
- FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
-
- # Let's finish by rapid to clearance...just for safety
- commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))
-
- path = Path.Path(commandlist)
- obj.Path = path
- return sim
-
-
-class _ViewProviderProfile:
-
- def __init__(self, vobj):
- vobj.Proxy = self
-
- def attach(self, vobj):
- self.Object = vobj.Object
- return
-
- def deleteObjectsOnReject(self):
- return hasattr(self, 'deleteOnReject') and self.deleteOnReject
-
- def setEdit(self, vobj, mode=0):
- FreeCADGui.Control.closeDialog()
- taskd = TaskPanel(vobj.Object, self.deleteObjectsOnReject())
- taskd.obj = vobj.Object
- FreeCADGui.Control.showDialog(taskd)
- taskd.setupUi()
- self.deleteOnReject = False
- return True
-
- def getIcon(self):
- return ":/icons/Path-Profile.svg"
-
- def __getstate__(self):
- return None
-
- def __setstate__(self, state):
- return None
-
-
-class _CommandSetStartPoint:
- def GetResources(self):
- return {'Pixmap': 'Path-StartPoint',
- 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Profile", "Pick Start Point"),
- 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Profile", "Pick Start Point")}
-
- def IsActive(self):
- return FreeCAD.ActiveDocument is not None
-
- def setpoint(self, point, o):
- obj = FreeCADGui.Selection.getSelection()[0]
- obj.StartPoint.x = point.x
- obj.StartPoint.y = point.y
-
- def Activated(self):
-
- FreeCADGui.Snapper.getPoint(callback=self.setpoint)
-
-
-class _CommandSetEndPoint:
- def GetResources(self):
- return {'Pixmap': 'Path-EndPoint',
- 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Profile", "Pick End Point"),
- 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Profile", "Pick End Point")}
-
- def IsActive(self):
- return FreeCAD.ActiveDocument is not None
-
- def setpoint(self, point, o):
- obj = FreeCADGui.Selection.getSelection()[0]
- obj.EndPoint.x = point.x
- obj.EndPoint.y = point.y
-
- def Activated(self):
-
- FreeCADGui.Snapper.getPoint(callback=self.setpoint)
-
-
-class CommandPathProfileEdges:
- def GetResources(self):
- return {'Pixmap': 'Path-Profile-Edges',
- 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathProfile", "Edge Profile"),
- 'Accel': "P, F",
- 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathProfile", "Profile based on Edges")}
-
- def IsActive(self):
- if FreeCAD.ActiveDocument is not None:
- for o in FreeCAD.ActiveDocument.Objects:
- if o.Name[:3] == "Job":
- return True
- return False
-
- def Activated(self):
- ztop = 10.0
- zbottom = 0.0
-
- FreeCAD.ActiveDocument.openTransaction(translate("Path", "Create a Profile based on edge selection"))
- FreeCADGui.addModule("PathScripts.PathProfile")
- FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "Edge Profile")')
- FreeCADGui.doCommand('PathScripts.PathProfileEdges.ObjectProfile(obj)')
- FreeCADGui.doCommand('obj.ViewObject.Proxy.deleteOnReject = True')
-
- FreeCADGui.doCommand('obj.Active = True')
-
- FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop + 10.0))
- FreeCADGui.doCommand('obj.StepDown = 1.0')
- FreeCADGui.doCommand('obj.StartDepth= ' + str(ztop))
- FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom))
-
- FreeCADGui.doCommand('obj.SafeHeight = ' + str(ztop + 2.0))
- FreeCADGui.doCommand('obj.Side = "Inside"')
- FreeCADGui.doCommand('obj.OffsetExtra = 0.0')
- FreeCADGui.doCommand('obj.Direction = "CW"')
- FreeCADGui.doCommand('obj.UseComp = True')
-
- FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
- FreeCADGui.doCommand('obj.ToolController = PathScripts.PathUtils.findToolController(obj)')
-
- FreeCAD.ActiveDocument.commitTransaction()
- FreeCAD.ActiveDocument.recompute()
- FreeCADGui.doCommand('obj.ViewObject.startEditing()')
-
-
-class TaskPanel:
- def __init__(self, obj, deleteOnReject):
- FreeCAD.ActiveDocument.openTransaction(translate("Path_ProfileEdges", "ProfileEdges Operation"))
- self.form = FreeCADGui.PySideUic.loadUi(":/panels/ProfileEdgesEdit.ui")
- self.deleteOnReject = deleteOnReject
- self.obj = obj
- self.isDirty = True
-
- def accept(self):
- FreeCADGui.Control.closeDialog()
- FreeCADGui.ActiveDocument.resetEdit()
- FreeCAD.ActiveDocument.commitTransaction()
- FreeCADGui.Selection.removeObserver(self.s)
- if self.isDirty:
- FreeCAD.ActiveDocument.recompute()
-
- def reject(self):
- FreeCADGui.Control.closeDialog()
- FreeCADGui.ActiveDocument.resetEdit()
- FreeCAD.ActiveDocument.abortTransaction()
- FreeCADGui.Selection.removeObserver(self.s)
- if self.deleteOnReject:
- FreeCAD.ActiveDocument.openTransaction(translate("Path_ProfileEdges", "Uncreate ProfileEdges Operation"))
- FreeCAD.ActiveDocument.removeObject(self.obj.Name)
- FreeCAD.ActiveDocument.commitTransaction()
- FreeCAD.ActiveDocument.recompute()
-
- def clicked(self, button):
- if button == QtGui.QDialogButtonBox.Apply:
- self.getFields()
- self.obj.Proxy.execute(self.obj)
- self.isDirty = False
-
- def getFields(self):
- if self.obj:
-
- if hasattr(self.obj, "StartDepth"):
- self.obj.StartDepth = FreeCAD.Units.Quantity(self.form.startDepth.text()).Value
- if hasattr(self.obj, "FinalDepth"):
- self.obj.FinalDepth = FreeCAD.Units.Quantity(self.form.finalDepth.text()).Value
- if hasattr(self.obj, "StepDown"):
- self.obj.StepDown = FreeCAD.Units.Quantity(self.form.stepDown.text()).Value
- if hasattr(self.obj, "SafeHeight"):
- self.obj.SafeHeight = FreeCAD.Units.Quantity(self.form.safeHeight.text()).Value
- if hasattr(self.obj, "ClearanceHeight"):
- self.obj.ClearanceHeight = FreeCAD.Units.Quantity(self.form.clearanceHeight.text()).Value
- if hasattr(self.obj, "OffsetExtra"):
- self.obj.OffsetExtra = FreeCAD.Units.Quantity(self.form.extraOffset.text()).Value
- if hasattr(self.obj, "UseComp"):
- self.obj.UseComp = self.form.useCompensation.isChecked()
- if hasattr(self.obj, "Side"):
- self.obj.Side = str(self.form.cutSide.currentText())
- if hasattr(self.obj, "Direction"):
- self.obj.Direction = str(self.form.direction.currentText())
- if hasattr(self.obj, "UseStartPoint"):
- self.obj.UseStartPoint = self.form.useStartPoint.isChecked()
-
- if hasattr(self.obj, "ToolController"):
- PathLog.debug("name: {}".format(self.form.uiToolController.currentText()))
- tc = PathUtils.findToolController(self.obj, self.form.uiToolController.currentText())
- self.obj.ToolController = tc
-
- self.isDirty = True
-
- def setFields(self):
- self.form.startDepth.setText(FreeCAD.Units.Quantity(self.obj.StartDepth.Value, FreeCAD.Units.Length).UserString)
- self.form.finalDepth.setText(FreeCAD.Units.Quantity(self.obj.FinalDepth.Value, FreeCAD.Units.Length).UserString)
- self.form.stepDown.setText(FreeCAD.Units.Quantity(self.obj.StepDown.Value, FreeCAD.Units.Length).UserString)
- self.form.safeHeight.setText(FreeCAD.Units.Quantity(self.obj.SafeHeight.Value, FreeCAD.Units.Length).UserString)
- self.form.clearanceHeight.setText(FreeCAD.Units.Quantity(self.obj.ClearanceHeight.Value, FreeCAD.Units.Length).UserString)
- self.form.extraOffset.setText(FreeCAD.Units.Quantity(self.obj.OffsetExtra.Value, FreeCAD.Units.Length).UserString)
- self.form.useCompensation.setChecked(self.obj.UseComp)
- self.form.useStartPoint.setChecked(self.obj.UseStartPoint)
-
- controllers = PathUtils.getToolControllers(self.obj)
- labels = [c.Label for c in controllers]
- self.form.uiToolController.blockSignals(True)
- self.form.uiToolController.addItems(labels)
- self.form.uiToolController.blockSignals(False)
- if self.obj.ToolController is not None:
- index = self.form.uiToolController.findText(
- self.obj.ToolController.Label, QtCore.Qt.MatchFixedString)
- PathLog.debug("searching for TC label {}. Found Index: {}".format(self.obj.ToolController.Label, index))
- if index >= 0:
- self.form.uiToolController.blockSignals(True)
- self.form.uiToolController.setCurrentIndex(index)
- self.form.uiToolController.blockSignals(False)
- else:
- self.obj.ToolController = PathUtils.findToolController(self.obj)
-
- index = self.form.cutSide.findText(
- self.obj.Side, QtCore.Qt.MatchFixedString)
- if index >= 0:
- self.form.cutSide.blockSignals(True)
- self.form.cutSide.setCurrentIndex(index)
- self.form.cutSide.blockSignals(False)
-
- index = self.form.direction.findText(
- self.obj.Direction, QtCore.Qt.MatchFixedString)
- if index >= 0:
- self.form.direction.setCurrentIndex(index)
- self.form.baseList.blockSignals(True)
- for i in self.obj.Base:
- for sub in i[1]:
- self.form.baseList.addItem(i[0].Name + "." + sub)
- self.form.baseList.blockSignals(False)
-
- def open(self):
- self.s = SelObserver()
- # install the function mode resident
- FreeCADGui.Selection.addObserver(self.s)
-
- def addBase(self):
- # check that the selection contains exactly what we want
- selection = FreeCADGui.Selection.getSelectionEx()
-
- if len(selection) != 1:
- FreeCAD.Console.PrintError(translate("PathProject", "Please select only Edges from the Base model\n"))
- return
- sel = selection[0]
- if not sel.HasSubObjects:
- FreeCAD.Console.PrintError(translate("PathProject", "Please select one or more edges from the Base model\n"))
- return
- if not selection[0].SubObjects[0].ShapeType == "Edge":
- FreeCAD.Console.PrintError(translate("PathProject", "Please select one or more edges from the Base model\n"))
- return
- try:
- theWire = Part.Wire(sel.SubObjects)
- except:
- FreeCAD.Console.PrintError(translate("PathProject", "The selected edges don't form a closed loop\n"))
- return
- if not isReallyClosed(theWire):
- FreeCAD.Console.PrintError(translate("PathProject", "The selected edges don't form a closed loop\n"))
- return
-
- for i in sel.SubElementNames:
- self.obj.Proxy.addprofilebase(self.obj, sel.Object, i)
-
- self.setFields() # defaults may have changed. Reload.
- self.form.baseList.clear()
-
- for i in self.obj.Base:
- for sub in i[1]:
- self.form.baseList.addItem(i[0].Name + "." + sub)
-
- def deleteBase(self):
- dlist = self.form.baseList.selectedItems()
- newlist = []
- for d in dlist:
- for i in self.obj.Base:
- if i[0].Name != d.text().partition(".")[0] or i[1] != d.text().partition(".")[2]:
- newlist.append(i)
- self.form.baseList.takeItem(self.form.baseList.row(d))
- self.obj.Base = newlist
- self.obj.Proxy.execute(self.obj)
- FreeCAD.ActiveDocument.recompute()
-
- def itemActivated(self):
- FreeCADGui.Selection.clearSelection()
- slist = self.form.baseList.selectedItems()
- for i in slist:
- objstring = i.text().partition(".")
- obj = FreeCAD.ActiveDocument.getObject(objstring[0])
- if objstring[2] != "":
- FreeCADGui.Selection.addSelection(obj, objstring[2])
- else:
- FreeCADGui.Selection.addSelection(obj)
-
- FreeCADGui.updateGui()
-
- def reorderBase(self):
- newlist = []
- for i in range(self.form.baseList.count()):
- s = self.form.baseList.item(i).text()
- objstring = s.partition(".")
-
- obj = FreeCAD.ActiveDocument.getObject(objstring[0])
- item = (obj, str(objstring[2]))
- newlist.append(item)
- self.obj.Base = newlist
-
- self.obj.Proxy.execute(self.obj)
- FreeCAD.ActiveDocument.recompute()
-
- def getStandardButtons(self):
- return int(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel)
-
- def setupUi(self):
-
- # Connect Signals and Slots
- # Base Controls
- self.form.baseList.itemSelectionChanged.connect(self.itemActivated)
- self.form.addBase.clicked.connect(self.addBase)
- self.form.deleteBase.clicked.connect(self.deleteBase)
- self.form.reorderBase.clicked.connect(self.reorderBase)
- self.form.uiToolController.currentIndexChanged.connect(self.getFields)
-
- # Depths
- self.form.startDepth.editingFinished.connect(self.getFields)
- self.form.finalDepth.editingFinished.connect(self.getFields)
- self.form.stepDown.editingFinished.connect(self.getFields)
-
- # Heights
- self.form.safeHeight.editingFinished.connect(self.getFields)
- self.form.clearanceHeight.editingFinished.connect(self.getFields)
-
- # operation
- self.form.cutSide.currentIndexChanged.connect(self.getFields)
- self.form.direction.currentIndexChanged.connect(self.getFields)
- self.form.useCompensation.clicked.connect(self.getFields)
- self.form.extraOffset.editingFinished.connect(self.getFields)
- self.form.useStartPoint.clicked.connect(self.getFields)
-
- self.setFields()
-
- sel = FreeCADGui.Selection.getSelectionEx()
- if len(sel) != 0 and sel[0].HasSubObjects:
- self.addBase()
-
-
-class SelObserver:
- def __init__(self):
- import PathScripts.PathSelection as PST
- PST.eselect()
-
- def __del__(self):
- import PathScripts.PathSelection as PST
- PST.clear()
-
- def addSelection(self, doc, obj, sub, pnt):
- FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
- FreeCADGui.updateGui()
-
-
-if FreeCAD.GuiUp:
- # register the FreeCAD command
- FreeCADGui.addCommand('Path_Profile_Edges', CommandPathProfileEdges())
-
-FreeCAD.Console.PrintLog("Loading PathProfileEdges... done\n")
+def Create(name):
+ obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
+ proxy = ObjectProfile(obj)
+ return obj
diff --git a/src/Mod/Path/PathScripts/PathProfileEdgesGui.py b/src/Mod/Path/PathScripts/PathProfileEdgesGui.py
new file mode 100644
index 0000000000..c4be5ff2f5
--- /dev/null
+++ b/src/Mod/Path/PathScripts/PathProfileEdgesGui.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+
+# ***************************************************************************
+# * *
+# * Copyright (c) 2017 sliptonic *
+# * *
+# * 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 *
+# * *
+# ***************************************************************************
+
+import FreeCAD
+import FreeCADGui
+import Path
+import PathScripts.PathAreaOpGui as PathAreaOpGui
+import PathScripts.PathLog as PathLog
+import PathScripts.PathProfileEdges as PathProfileEdges
+import PathScripts.PathSelection as PathSelection
+
+from PathScripts import PathUtils
+from PySide import QtCore, QtGui
+
+def translate(context, text, disambig=None):
+ return QtCore.QCoreApplication.translate(context, text, disambig)
+
+class TaskPanelOpPage(PathAreaOpGui.TaskPanelPage):
+
+ def getForm(self):
+ return FreeCADGui.PySideUic.loadUi(":/panels/PageOpProfileEdgesEdit.ui")
+
+ def getFields(self, obj):
+ self.obj.OffsetExtra = FreeCAD.Units.Quantity(self.form.extraOffset.text()).Value
+ self.obj.UseComp = self.form.useCompensation.isChecked()
+ self.obj.UseStartPoint = self.form.useStartPoint.isChecked()
+ self.obj.Side = str(self.form.cutSide.currentText())
+ self.obj.Direction = str(self.form.direction.currentText())
+
+ tc = PathUtils.findToolController(self.obj, self.form.toolController.currentText())
+ self.obj.ToolController = tc
+
+ def setFields(self, obj):
+ self.form.extraOffset.setText(FreeCAD.Units.Quantity(self.obj.OffsetExtra.Value, FreeCAD.Units.Length).UserString)
+ self.form.useCompensation.setChecked(self.obj.UseComp)
+ self.form.useStartPoint.setChecked(self.obj.UseStartPoint)
+
+ self.selectInComboBox(self.obj.Side, self.form.cutSide)
+ self.selectInComboBox(self.obj.Direction, self.form.direction)
+ self.setupToolController(self.obj, self.form.toolController)
+
+ def getSignalsForUpdate(self, obj):
+ signals = []
+ signals.append(self.form.cutSide.currentIndexChanged)
+ signals.append(self.form.direction.currentIndexChanged)
+ signals.append(self.form.useCompensation.clicked)
+ signals.append(self.form.useStartPoint.clicked)
+ signals.append(self.form.extraOffset.editingFinished)
+ return signals
+
+
+
+PathAreaOpGui.SetupOperation('Profile Edges',
+ PathProfileEdges.Create,
+ TaskPanelOpPage,
+ 'Path-Profile',
+ QtCore.QT_TRANSLATE_NOOP("PathProfile", "Edge Profile"),
+ "P, F",
+ QtCore.QT_TRANSLATE_NOOP("PathProfile", "Profile based on face or faces"))
+
+FreeCAD.Console.PrintLog("Loading PathProfileEdgesGui... done\n")
diff --git a/src/Mod/Path/PathScripts/PathProfileFacesGui.py b/src/Mod/Path/PathScripts/PathProfileFacesGui.py
index 7665f2c60c..c1b8aaa285 100644
--- a/src/Mod/Path/PathScripts/PathProfileFacesGui.py
+++ b/src/Mod/Path/PathScripts/PathProfileFacesGui.py
@@ -78,7 +78,7 @@ class TaskPanelOpPage(PathAreaOpGui.TaskPanelPage):
signals.append(self.form.processCircles.clicked)
return signals
-PathAreaOpGui.SetupOperation('Profile',
+PathAreaOpGui.SetupOperation('Profile Faces',
PathProfileFaces.Create,
TaskPanelOpPage,
'Path-Profile',
@@ -86,4 +86,4 @@ PathAreaOpGui.SetupOperation('Profile',
"P, F",
QtCore.QT_TRANSLATE_NOOP("PathProfile", "Profile based on face or faces"))
-FreeCAD.Console.PrintLog("Loading PathProfileGui... done\n")
+FreeCAD.Console.PrintLog("Loading PathProfileFacesGui... done\n")
diff --git a/src/Mod/Path/PathScripts/PathSelection.py b/src/Mod/Path/PathScripts/PathSelection.py
index d1611ac37c..b42b8f01b9 100644
--- a/src/Mod/Path/PathScripts/PathSelection.py
+++ b/src/Mod/Path/PathScripts/PathSelection.py
@@ -162,9 +162,10 @@ def surfaceselect():
def select(op):
opsel = {}
- opsel['Profile'] = profileselect
- opsel['Pocket'] = pocketselect
opsel['Contour'] = contourselect
+ opsel['Pocket'] = pocketselect
+ opsel['Profile Edges'] = eselect
+ opsel['Profile Faces'] = profileselect
opsel['Surface'] = surfaceselect
return opsel[op]