From a7053861b597a56d7e4c85eaa7f65dcd82b1903e Mon Sep 17 00:00:00 2001 From: yorikvanhavre Date: Fri, 23 Dec 2011 19:15:14 -0200 Subject: [PATCH 01/10] further work on DrawingPage --- src/Mod/Drawing/App/FeaturePage.cpp | 33 +++++++++++++++++++++++++++++ src/Mod/Drawing/App/FeaturePage.h | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Mod/Drawing/App/FeaturePage.cpp b/src/Mod/Drawing/App/FeaturePage.cpp index e5f33ba65..30559a857 100644 --- a/src/Mod/Drawing/App/FeaturePage.cpp +++ b/src/Mod/Drawing/App/FeaturePage.cpp @@ -56,6 +56,7 @@ FeaturePage::FeaturePage(void) ADD_PROPERTY_TYPE(PageResult ,(0),group,App::Prop_Output,"Resulting SVG document of that page"); ADD_PROPERTY_TYPE(Template ,(""),group,App::Prop_None ,"Template for the page"); + ADD_PROPERTY_TYPE(EditableTexts,(""),group,App::Prop_None,"Substitution values for the editable strings in the template"); } FeaturePage::~FeaturePage() @@ -129,6 +130,38 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) file.close(); ofile.close(); + // checking for freecad editable texts + boost::regex e ("(.*?)",boost::regex_constants::icase); + + // reading file contents + ifstream tfile (tempName.c_str()); + string tline; + string fragment; + + while (!tfile.eof()) { + getline (tfile,tline); + fragment += tline; + fragment += "--endOfLine--"; + } + + tfile.close(); + + //printf(fragment.c_str()); + + string::const_iterator start, end; + start = fragment.begin(); + end = fragment.end(); + //boost::smatch what; + boost::match_results what; + + cout << "Stored strings: " << EditableTexts.getValue(); + + while (boost::regex_search(start,end,what,e)) { + //cout << "match" << what.str() << endl; + cout << "new match:" << what[1] << " = " << what[2] << endl; + start = what[0].second; + } + PageResult.setValue(tempName.c_str()); //const char* text = "lskdfjlsd"; diff --git a/src/Mod/Drawing/App/FeaturePage.h b/src/Mod/Drawing/App/FeaturePage.h index e430c9e29..885bef6b8 100644 --- a/src/Mod/Drawing/App/FeaturePage.h +++ b/src/Mod/Drawing/App/FeaturePage.h @@ -47,7 +47,7 @@ public: App::PropertyFileIncluded PageResult; App::PropertyFile Template; - + App::PropertyStringList EditableTexts; /** @name methods overide Feature */ //@{ From 738371ef37946ceae47fa3d997d1e3998bbc116b Mon Sep 17 00:00:00 2001 From: yorikvanhavre Date: Sat, 24 Dec 2011 13:28:44 -0200 Subject: [PATCH 02/10] + extended DraftSnap (Git allows cool commit messages) The DraftSnap system gained an ortho X extension snap location, the ortho snap got fixed, and a new getPoint() method, which you can feed with a callback function to be called when a point has been clicked. --- src/Mod/Draft/DraftSnap.py | 415 ++++++++----------------------------- 1 file changed, 90 insertions(+), 325 deletions(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index cbcdb6842..73065e694 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -38,7 +38,17 @@ class Snapper: and arch module to manage object snapping. It is responsible for finding snap points and displaying snap markers. Usually You only need to invoke it's snap() function, all the rest is taken - care of.""" + care of. + + 3 functions are useful for the scriptwriter: snap(), constrain() + or getPoint() which is an all-in-one combo. + + The indivudual snapToXXX() functions return a snap definition in + the form [real_point,marker_type,visual_point], and are not + meant to be used directly, they are all called when necessary by + the general snap() function. + + """ def __init__(self): self.lastObj = [None,None] @@ -57,6 +67,7 @@ class Snapper: self.extLine = None self.grid = None self.constrainLine = None + self.trackLine = None # the snapmarker has "dot","circle" and "square" available styles self.mk = {'passive':'circle', @@ -98,6 +109,8 @@ class Snapper: self.unconstrain() return point + snaps = [] + # type conversion if needed if isinstance(screenpos,list): screenpos = tuple(screenpos) @@ -141,7 +154,7 @@ class Snapper: info = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo((screenpos[0],screenpos[1])) # checking if parallel to one of the edges of the last objects - point = self.snapToExtensions(point,lastpoint) + point = self.snapToExtensions(point,lastpoint,constrain) if not info: @@ -152,7 +165,6 @@ class Snapper: else: # we have an object to snap to - snaps = [] obj = FreeCAD.ActiveDocument.getObject(info['Object']) if not obj: @@ -241,8 +253,22 @@ class Snapper: # return the final point return cstr(winner[2]) - def snapToExtensions(self,point,last): + def snapToExtensions(self,point,last,constrain): "returns a point snapped to extension or parallel line to last object, if any" + + tsnap = self.snapToExtOrtho(last,constrain) + if tsnap: + if (tsnap[0].sub(point)).Length < self.radius: + if self.tracker: + self.tracker.setCoords(tsnap[2]) + self.tracker.setMarker(self.mk[tsnap[1]]) + self.tracker.on() + if self.extLine: + self.extLine.p2(tsnap[2]) + self.extLine.on() + self.setCursor(tsnap[1]) + return tsnap[2] + for o in [self.lastObj[1],self.lastObj[0]]: if o: ob = FreeCAD.ActiveDocument.getObject(o) @@ -333,24 +359,30 @@ class Snapper: def snapToOrtho(self,shape,last,constrain): "returns a list of ortho snap locations" snaps = [] - if constrain != None: + if constrain: if isinstance(shape,Part.Edge): if last: if isinstance(shape.Curve,Part.Line): - p1 = shape.Vertexes[0].Point - p2 = shape.Vertexes[-1].Point - if (constrain == 0): - if ((last.y > p1.y) and (last.y < p2.y) or (last.y > p2.y) and (last.y < p1.y)): - pc = (last.y-p1.y)/(p2.y-p1.y) - cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z))) - snaps.append([cp,'ortho',cp]) - elif (constrain == 1): - if ((last.x > p1.x) and (last.x < p2.x) or (last.x > p2.x) and (last.x < p1.x)): - pc = (last.x-p1.x)/(p2.x-p1.x) - cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z))) - snaps.append([cp,'ortho',cp]) + if self.constraintAxis: + tmpEdge = Part.Line(last,last.add(self.constraintAxis)).toShape() + # get the intersection points + pt = fcgeo.findIntersection(tmpEdge,shape,True,True) + if pt: + for p in pt: + snaps.append([p,'ortho',p]) return snaps + def snapToExtOrtho(self,last,constrain): + "returns an ortho X extension snap location" + if constrain and last and self.constraintAxis and self.extLine: + tmpEdge1 = Part.Line(last,last.add(self.constraintAxis)).toShape() + tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() + # get the intersection points + pt = fcgeo.findIntersection(tmpEdge1,tmpEdge2,True,True) + if pt: + return [pt[0],'ortho',pt[0]] + return None + def snapToAngles(self,shape): "returns a list of angle snap locations" snaps = [] @@ -511,316 +543,49 @@ class Snapper: self.affinity = None if self.constrainLine: self.constrainLine.off() - -# deprecated ################################################################## -# last snapped objects, for quick intersection calculation -lastObj = [0,0] + def getPoint(self,last=None,callback=None): + """getPoint([last],[callback]) : gets a 3D point from the screen. You can provide an existing point, + in that case additional snap options and a tracker are available. You can also passa function as + callback, which will get called with the resulting point as argument, when a point is clicked.""" + self.pt = None + self.ui = FreeCADGui.draftToolBar + self.view = FreeCADGui.ActiveDocument.ActiveView + + # setting a track line if we got an existing point + if last: + if not self.trackLine: + self.trackLine = DraftTrackers.lineTracker() + self.trackLine.p1(last) + self.trackLine.on() + + def move(event_cb): + event = event_cb.getEvent() + mousepos = event.getPosition() + ctrl = event.wasCtrlDown() + shift = event.wasShiftDown() + self.pt = FreeCADGui.Snapper.snap(mousepos,lastpoint=last,active=ctrl,constrain=shift) + self.ui.displayPoint(self.pt,last,plane=FreeCAD.DraftWorkingPlane,mask=FreeCADGui.Snapper.affinity) + if self.trackLine: + self.trackLine.p2(self.pt) -def snapPoint(target,point,cursor,ctrl=False): - ''' - Snap function used by the Draft tools - - Currently has two modes: passive and active. Pressing CTRL while - clicking puts you in active mode: - - - In passive mode (an open circle appears), your point is - snapped to the nearest point on any underlying geometry. - - - In active mode (ctrl pressed, a filled circle appears), your point - can currently be snapped to the following points: - - Nodes and midpoints of all Part shapes - - Nodes and midpoints of lines/wires - - Centers and quadrant points of circles - - Endpoints of arcs - - Intersection between line, wires segments, arcs and circles - - When constrained (SHIFT pressed), Intersections between - constraining axis and lines/wires - ''' - - def getConstrainedPoint(edge,last,constrain): - "check for constrained snappoint" - p1 = edge.Vertexes[0].Point - p2 = edge.Vertexes[-1].Point - ar = [] - if (constrain == 0): - if ((last.y > p1.y) and (last.y < p2.y) or (last.y > p2.y) and (last.y < p1.y)): - pc = (last.y-p1.y)/(p2.y-p1.y) - cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z))) - ar.append([cp,1,cp]) # constrainpoint - if (constrain == 1): - if ((last.x > p1.x) and (last.x < p2.x) or (last.x > p2.x) and (last.x < p1.x)): - pc = (last.x-p1.x)/(p2.x-p1.x) - cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z))) - ar.append([cp,1,cp]) # constrainpoint - return ar - - def getPassivePoint(info): - "returns a passive snap point" - cur = Vector(info['x'],info['y'],info['z']) - return [cur,2,cur] - - def getScreenDist(dist,cursor): - "returns a 3D distance from a screen pixels distance" - p1 = FreeCADGui.ActiveDocument.ActiveView.getPoint(cursor) - p2 = FreeCADGui.ActiveDocument.ActiveView.getPoint((cursor[0]+dist,cursor[1])) - return (p2.sub(p1)).Length - - def getGridSnap(target,point): - "returns a grid snap point if available" - if target.grid: - return target.grid.getClosestNode(point) - return None - - def getPerpendicular(edge,last): - "returns a point on an edge, perpendicular to the given point" - dv = last.sub(edge.Vertexes[0].Point) - nv = fcvec.project(dv,fcgeo.vec(edge)) - np = (edge.Vertexes[0].Point).add(nv) - return np - - # checking if alwaySnap setting is on - extractrl = False - if Draft.getParam("alwaysSnap"): - extractrl = ctrl - ctrl = True - - # setting Radius - radius = getScreenDist(Draft.getParam("snapRange"),cursor) - - # checking if parallel to one of the edges of the last objects - target.snap.off() - target.extsnap.off() - if (len(target.node) > 0): - for o in [lastObj[1],lastObj[0]]: - if o: - ob = target.doc.getObject(o) - if ob: - if ob.isDerivedFrom("Part::Feature"): - edges = ob.Shape.Edges - if len(edges)<10: - for e in edges: - if isinstance(e.Curve,Part.Line): - last = target.node[len(target.node)-1] - de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() - np = getPerpendicular(e,point) - if (np.sub(point)).Length < radius: - target.snap.coords.point.setValue((np.x,np.y,np.z)) - target.snap.setMarker("circle") - target.snap.on() - target.extsnap.p1(e.Vertexes[0].Point) - target.extsnap.p2(np) - target.extsnap.on() - point = np - else: - last = target.node[len(target.node)-1] - de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() - np = getPerpendicular(de,point) - if (np.sub(point)).Length < radius: - target.snap.coords.point.setValue((np.x,np.y,np.z)) - target.snap.setMarker("circle") - target.snap.on() - point = np - - # check if we snapped to something - snapped=target.view.getObjectInfo((cursor[0],cursor[1])) - - if (snapped == None): - # nothing has been snapped, check fro grid snap - gpt = getGridSnap(target,point) - if gpt: - if radius != 0: - dv = point.sub(gpt) - if dv.Length <= radius: - target.snap.coords.point.setValue((gpt.x,gpt.y,gpt.z)) - target.snap.setMarker("point") - target.snap.on() - return gpt - return point - else: - # we have something to snap - obj = target.doc.getObject(snapped['Object']) - if hasattr(obj.ViewObject,"Selectable"): - if not obj.ViewObject.Selectable: - return point - if not ctrl: - # are we in passive snap? - snapArray = [getPassivePoint(snapped)] - else: - snapArray = [] - comp = snapped['Component'] - if obj.isDerivedFrom("Part::Feature"): - if "Edge" in comp: - # get the stored objects to calculate intersections - intedges = [] - if lastObj[0]: - lo = target.doc.getObject(lastObj[0]) - if lo: - if lo.isDerivedFrom("Part::Feature"): - intedges = lo.Shape.Edges - - nr = int(comp[4:])-1 - edge = obj.Shape.Edges[nr] - for v in edge.Vertexes: - snapArray.append([v.Point,0,v.Point]) - if isinstance(edge.Curve,Part.Line): - # the edge is a line - midpoint = fcgeo.findMidpoint(edge) - snapArray.append([midpoint,1,midpoint]) - if (len(target.node) > 0): - last = target.node[len(target.node)-1] - snapArray.extend(getConstrainedPoint(edge,last,target.constrain)) - np = getPerpendicular(edge,last) - snapArray.append([np,1,np]) - - elif isinstance (edge.Curve,Part.Circle): - # the edge is an arc - rad = edge.Curve.Radius - pos = edge.Curve.Center - for i in [0,30,45,60,90,120,135,150,180,210,225,240,270,300,315,330]: - ang = math.radians(i) - cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) - snapArray.append([cur,1,cur]) - for i in [15,37.5,52.5,75,105,127.5,142.5,165,195,217.5,232.5,255,285,307.5,322.5,345]: - ang = math.radians(i) - cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) - snapArray.append([cur,0,pos]) - - for e in intedges: - # get the intersection points - pt = fcgeo.findIntersection(e,edge) - if pt: - for p in pt: - snapArray.append([p,3,p]) - elif "Vertex" in comp: - # directly snapped to a vertex - p = Vector(snapped['x'],snapped['y'],snapped['z']) - snapArray.append([p,0,p]) - elif comp == '': - # workaround for the new view provider - p = Vector(snapped['x'],snapped['y'],snapped['z']) - snapArray.append([p,2,p]) - else: - snapArray = [getPassivePoint(snapped)] - elif Draft.getType(obj) == "Dimension": - for pt in [obj.Start,obj.End,obj.Dimline]: - snapArray.append([pt,0,pt]) - elif Draft.getType(obj) == "Mesh": - for v in obj.Mesh.Points: - snapArray.append([v.Vector,0,v.Vector]) - if not lastObj[0]: - lastObj[0] = obj.Name - lastObj[1] = obj.Name - if (lastObj[1] != obj.Name): - lastObj[0] = lastObj[1] - lastObj[1] = obj.Name - - # calculating shortest distance - shortest = 1000000000000000000 - spt = Vector(snapped['x'],snapped['y'],snapped['z']) - newpoint = [Vector(0,0,0),0,Vector(0,0,0)] - for pt in snapArray: - if pt[0] == None: print "snapPoint: debug 'i[0]' is 'None'" - di = pt[0].sub(spt) - if di.Length < shortest: - shortest = di.Length - newpoint = pt - if radius != 0: - dv = point.sub(newpoint[2]) - if (not extractrl) and (dv.Length > radius): - newpoint = getPassivePoint(snapped) - target.snap.coords.point.setValue((newpoint[2].x,newpoint[2].y,newpoint[2].z)) - if (newpoint[1] == 1): - target.snap.setMarker("square") - elif (newpoint[1] == 0): - target.snap.setMarker("point") - elif (newpoint[1] == 3): - target.snap.setMarker("square") - else: - target.snap.setMarker("circle") - target.snap.on() - return newpoint[2] - -def constrainPoint (target,pt,mobile=False,sym=False): - ''' - Constrain function used by the Draft tools - On commands that need to enter several points (currently only line/wire), - you can constrain the next point to be picked to the last drawn point by - pressing SHIFT. The vertical or horizontal constraining depends on the - position of your mouse in relation to last point at the moment you press - SHIFT. if mobile=True, mobile behaviour applies. If sym=True, x alway = y - ''' - point = Vector(pt) - if len(target.node) > 0: - last = target.node[-1] - dvec = point.sub(last) - affinity = FreeCAD.DraftWorkingPlane.getClosestAxis(dvec) - if ((target.constrain == None) or mobile): - if affinity == "x": - dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.u) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(FreeCAD.DraftWorkingPlane.u) > 1: - l = -l - point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l))) - target.constrain = 0 #x direction - target.ui.xValue.setEnabled(True) - target.ui.yValue.setEnabled(False) - target.ui.zValue.setEnabled(False) - target.ui.xValue.setFocus() - elif affinity == "y": - dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.v) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(FreeCAD.DraftWorkingPlane.v) > 1: - l = -l - point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l))) - target.constrain = 1 #y direction - target.ui.xValue.setEnabled(False) - target.ui.yValue.setEnabled(True) - target.ui.zValue.setEnabled(False) - target.ui.yValue.setFocus() - elif affinity == "z": - dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.axis) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(FreeCAD.DraftWorkingPlane.axis) > 1: - l = -l - point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l))) - target.constrain = 2 #z direction - target.ui.xValue.setEnabled(False) - target.ui.yValue.setEnabled(False) - target.ui.zValue.setEnabled(True) - target.ui.zValue.setFocus() - else: target.constrain = 3 - elif (target.constrain == 0): - dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.u) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(FreeCAD.DraftWorkingPlane.u) > 1: - l = -l - point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l))) - elif (target.constrain == 1): - dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.v) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(FreeCAD.DraftWorkingPlane.u) > 1: - l = -l - point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l))) - elif (target.constrain == 2): - dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.axis) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(FreeCAD.DraftWorkingPlane.u) > 1: - l = -l - point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l))) - return point + def click(event_cb): + event = event_cb.getEvent() + if event.getState() == coin.SoMouseButtonEvent.DOWN: + self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick) + self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),self.callbackMove) + FreeCADGui.Snapper.off() + self.ui.offUi() + if self.trackLine: + self.trackLine.off() + if callback: + callback(self.pt) + self.pt = None + # adding 2 callback functions + self.ui.pointUi() + self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click) + self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move) + if not hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper = Snapper() From 1fc47ecc1a0b0d7e7cffda14f97a6b123dee1596 Mon Sep 17 00:00:00 2001 From: yorikvanhavre Date: Sat, 24 Dec 2011 13:35:01 -0200 Subject: [PATCH 03/10] + extended DraftSnap --- src/Mod/Draft/DraftSnap.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 73065e694..78f955ce3 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -547,7 +547,12 @@ class Snapper: def getPoint(self,last=None,callback=None): """getPoint([last],[callback]) : gets a 3D point from the screen. You can provide an existing point, in that case additional snap options and a tracker are available. You can also passa function as - callback, which will get called with the resulting point as argument, when a point is clicked.""" + callback, which will get called with the resulting point as argument, when a point is clicked: + + def cb(point): + print "got a 3D point: ",point + FreeCADGui.Snapper.getPoint(callback=cb) + """ self.pt = None self.ui = FreeCADGui.draftToolBar self.view = FreeCADGui.ActiveDocument.ActiveView From 9cf345ecfb0b2c6a54f7e6dc4773a9461143d1e8 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 24 Dec 2011 14:31:30 -0200 Subject: [PATCH 04/10] + small fix in DraftSnap --- src/Mod/Draft/DraftSnap.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 78f955ce3..f2f0b3d25 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -225,6 +225,9 @@ class Snapper: self.lastObj[0] = self.lastObj[1] self.lastObj[1] = obj.Name + if not snaps: + return point + # calculating the nearest snap point shortest = 1000000000000000000 origin = Vector(info['x'],info['y'],info['z']) From c6c12a1ecf1a24f063906a412cf2ef032713561b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 25 Dec 2011 17:02:12 -0200 Subject: [PATCH 05/10] added Start and End properties to 2-point Draft lines --- src/Mod/Arch/ArchWindow.py | 2 +- src/Mod/Draft/Draft.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 1ae3abdb9..91bc796c7 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -51,7 +51,7 @@ class _CommandWindow: def GetResources(self): return {'Pixmap' : 'Arch_Window', 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Window"), - 'Accel': "W, I", + 'Accel': "W, N", 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Creates a window object from scratch or from a selected object (wire, rectangle or sketch)")} def Activated(self): diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 3627f3338..0816e1428 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1931,6 +1931,10 @@ class _Wire: "The base object is the wire is formed from 2 objects") obj.addProperty("App::PropertyLink","Tool","Base", "The tool object is the wire is formed from 2 objects") + obj.addProperty("App::PropertyVector","Start","Base", + "The start point of this line") + obj.addProperty("App::PropertyVector","End","Base", + "The end point of this line") obj.Proxy = self obj.Closed = False self.Type = "Wire" @@ -1941,6 +1945,26 @@ class _Wire: def onChanged(self, fp, prop): if prop in ["Points","Closed","Base","Tool"]: self.createGeometry(fp) + if prop == "Points": + if fp.Start != fp.Points[0]: + fp.Start = fp.Points[0] + if fp.End != fp.Points[-1]: + fp.End = fp.Points[-1] + if len(fp.Points) > 2: + fp.setEditorMode('Start',2) + fp.setEditorMode('End',2) + elif prop == "Start": + pts = fp.Points + if pts: + if pts[0] != fp.Start: + pts[0] = fp.Start + fp.Points = pts + elif prop == "End": + pts = fp.Points + if len(pts) > 1: + if pts[-1] != fp.End: + pts[-1] = fp.End + fp.Points = pts def createGeometry(self,fp): plm = fp.Placement From 3e48193ada73ecccf89dc1ecc26af36713953d6f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 25 Dec 2011 17:49:30 -0200 Subject: [PATCH 06/10] fixed bug #549 - Undo of offset objects causes Draft tools to stop functioning --- src/Mod/Draft/DraftGui.py | 13 +++++++++++-- src/Mod/Draft/DraftTools.py | 25 ++++++------------------- src/Mod/Draft/DraftTrackers.py | 5 ++++- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index fc4e6f194..114d0078e 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -533,11 +533,10 @@ class DraftToolBar: self.radiusValue.selectAll() def offUi(self): + todo.delay(FreeCADGui.Control.closeDialog,None) if self.taskmode: self.isTaskOn = False - todo.delay(FreeCADGui.Control.closeDialog,None) self.baseWidget = QtGui.QWidget() - # print "UI turned off" else: self.setTitle(translate("draft", "None")) self.labelx.setText(translate("draft", "X")) @@ -637,6 +636,7 @@ class DraftToolBar: if not self.taskmode: self.labelx.setText(translate("draft", "Pick Object")) self.labelx.show() + self.makeDumbTask() def editUi(self): self.taskUi(translate("draft", "Edit")) @@ -701,6 +701,15 @@ class DraftToolBar: else: self.layout.setDirection(QtGui.QBoxLayout.LeftToRight) + def makeDumbTask(self): + "create a dumb taskdialog to prevent deleting the temp object" + class TaskPanel: + def __init__(self): + pass + def getStandardButtons(self): + return 0 + panel = TaskPanel() + FreeCADGui.Control.showDialog(panel) #--------------------------------------------------------------------------- # Processing functions diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index ac1610bf4..e9b55d6e1 100755 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -389,24 +389,11 @@ class Line(Creator): self.obj=self.doc.addObject("Part::Feature",self.featureName) # self.obj.ViewObject.Selectable = False Draft.formatObject(self.obj) - if not Draft.getParam("UiMode"): self.makeDumbTask() self.call = self.view.addEventCallback("SoEvent",self.action) msg(translate("draft", "Pick first point:\n")) - def makeDumbTask(self): - "create a dumb taskdialog to prevent deleting the temp object" - class TaskPanel: - def __init__(self): - pass - def getStandardButtons(self): - return 0 - panel = TaskPanel() - FreeCADGui.Control.showDialog(panel) - def finish(self,closed=False,cont=False): "terminates the operation and closes the poly if asked" - if not Draft.getParam("UiMode"): - FreeCADGui.Control.closeDialog() if self.obj: old = self.obj.Name todo.delay(self.doc.removeObject,old) @@ -1627,6 +1614,12 @@ class Modifier: def __init__(self): self.commitList = [] + + def IsActive(self): + if Draft.getSelection(): + return True + else: + return False def Activated(self,name="None"): if FreeCAD.activeDraftCommand: @@ -1655,12 +1648,6 @@ class Modifier: self.snap = snapTracker() self.extsnap = lineTracker(dotted=True) self.planetrack = PlaneTracker() - - def IsActive(self): - if FreeCADGui.ActiveDocument: - return True - else: - return False def finish(self): self.node = [] diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index da064ffd9..29494d6fb 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -503,7 +503,10 @@ class wireTracker(Tracker): def update(self,wire): if wire: - self.line.numVertices.setValue(len(wire.Vertexes)) + if self.closed: + self.line.numVertices.setValue(len(wire.Vertexes)+1) + else: + self.line.numVertices.setValue(len(wire.Vertexes)) for i in range(len(wire.Vertexes)): p=wire.Vertexes[i].Point self.coords.point.set1Value(i,[p.x,p.y,p.z]) From 59f14850058feb1f5b271dea508d411f451a9a6f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 29 Dec 2011 19:02:58 -0200 Subject: [PATCH 07/10] Added editable texts to DrawingPage - Editable texts can be added to templates by adding a freecad:editable="textName" attribute to SVG tags - Added EditableTexts property (stringlist) to FeaturePage objects - Instead of writing directly the SVG fragments to the temp file, they are scanned for editable texts, and if needed those are changed, then the final temp file is written, allowing for editable texts anywhere, even in FeatureView objects - On changing the Template, editable texts are picked and stored in the EditableTexts property. --- src/Mod/Drawing/App/FeaturePage.cpp | 90 +++++++++++++++++++---------- src/Mod/Drawing/App/FeaturePage.h | 1 - 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/Mod/Drawing/App/FeaturePage.cpp b/src/Mod/Drawing/App/FeaturePage.cpp index 30559a857..2779105e9 100644 --- a/src/Mod/Drawing/App/FeaturePage.cpp +++ b/src/Mod/Drawing/App/FeaturePage.cpp @@ -75,6 +75,36 @@ void FeaturePage::onChanged(const App::Property* prop) return; } } + if (prop == &Template) { + // getting editable texts from "freecad:editable" tags in SVG template + if (!this->isRestoring()) { + if (Template.getValue() != "") { + Base::FileInfo tfi(Template.getValue()); + if (tfi.isReadable()) { + string tline, tfrag; + ifstream tfile (tfi.filePath().c_str()); + while (!tfile.eof()) { + getline (tfile,tline); + tfrag += tline; + tfrag += "--endOfLine--"; + } + tfile.close(); + boost::regex e ("(.*?)"); + string::const_iterator tbegin, tend; + tbegin = tfrag.begin(); + tend = tfrag.end(); + boost::match_results twhat; + std::vector eds; + while (boost::regex_search(tbegin, tend, twhat, e)) { + printf(twhat[1].str().c_str()); + eds.push_back(twhat[2]); + tbegin = twhat[0].second; + } + EditableTexts.setValues(eds); + } + } + } + } App::DocumentObjectGroup::onChanged(prop); } @@ -104,7 +134,8 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) // make a temp file for FileIncluded Property string tempName = PageResult.getExchangeTempFile(); - ofstream ofile(tempName.c_str()); + ostringstream ofile; + string tempendl = "--endOfLine--"; while (!file.eof()) { @@ -112,7 +143,7 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) // check if the marker in the template is found if(line.find("") == string::npos) // if not - write through - ofile << line << endl; + ofile << line << tempendl; else { // get through the children and collect all the views @@ -121,46 +152,41 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) if ((*It)->getTypeId().isDerivedFrom(Drawing::FeatureView::getClassTypeId())) { Drawing::FeatureView *View = dynamic_cast(*It); ofile << View->ViewResult.getValue(); - ofile << endl << endl << endl; + ofile << tempendl << tempendl << tempendl; } } } } file.close(); - ofile.close(); - // checking for freecad editable texts - boost::regex e ("(.*?)",boost::regex_constants::icase); + // checking for freecad editable texts + string outfragment(ofile.str()); + if (EditableTexts.getSize() > 0) { + boost::regex e1 ("(.*?)"); + string::const_iterator begin, end; + begin = ofile.str().begin(); + end = ofile.str().end(); + boost::match_results what; + int count = 0; - // reading file contents - ifstream tfile (tempName.c_str()); - string tline; - string fragment; - - while (!tfile.eof()) { - getline (tfile,tline); - fragment += tline; - fragment += "--endOfLine--"; + while (boost::regex_search(begin, end, what, e1)) { + if (count < EditableTexts.getSize()) { + boost::regex e2 ("((.*?)()"); + outfragment = boost::regex_replace(outfragment, e2, "$1>"+EditableTexts.getValues()[count]+"$3"); + } + count ++; + begin = what[0].second; + } } - tfile.close(); - - //printf(fragment.c_str()); - - string::const_iterator start, end; - start = fragment.begin(); - end = fragment.end(); - //boost::smatch what; - boost::match_results what; - - cout << "Stored strings: " << EditableTexts.getValue(); - - while (boost::regex_search(start,end,what,e)) { - //cout << "match" << what.str() << endl; - cout << "new match:" << what[1] << " = " << what[2] << endl; - start = what[0].second; - } + // restoring linebreaks and saving the file + boost::regex e3 ("--endOfLine--"); + string fmt = "\\n"; + outfragment = boost::regex_replace(outfragment, e3, fmt); + ofstream outfinal(tempName.c_str()); + outfinal << outfragment; + outfinal.close(); PageResult.setValue(tempName.c_str()); diff --git a/src/Mod/Drawing/App/FeaturePage.h b/src/Mod/Drawing/App/FeaturePage.h index 885bef6b8..ed64c1b3b 100644 --- a/src/Mod/Drawing/App/FeaturePage.h +++ b/src/Mod/Drawing/App/FeaturePage.h @@ -68,5 +68,4 @@ protected: } //namespace Drawing - #endif From c6b0c869891e90dd585446a32ca78e4d7afe04a6 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 29 Dec 2011 19:33:46 -0200 Subject: [PATCH 08/10] added editable texts to the default A3 template --- src/Mod/Drawing/Templates/A3_Landscape.svg | 360 ++++++++++++--------- 1 file changed, 204 insertions(+), 156 deletions(-) diff --git a/src/Mod/Drawing/Templates/A3_Landscape.svg b/src/Mod/Drawing/Templates/A3_Landscape.svg index 050070bc6..4e2cdb854 100644 --- a/src/Mod/Drawing/Templates/A3_Landscape.svg +++ b/src/Mod/Drawing/Templates/A3_Landscape.svg @@ -1,7 +1,7 @@ + inkscape:output_extension="org.inkscape.output.svg.inkscape"> @@ -512,9 +511,60 @@ id="radialGradient3412" xlink:href="#defitem12" inkscape:collect="always" /> + + + + + + + + + + + + inkscape:zoom="1.7101889" + inkscape:cx="254.10366" + inkscape:cy="146.94782" + inkscape:window-x="0" + inkscape:window-y="20" + inkscape:current-layer="svg2" + showgrid="false" + inkscape:window-maximized="1" /> + + inkscape:label="Layer 1" + id="layer1" + transform="matrix(0.21138442,0,0,0.21138442,371.09182,256.75666)"> - + transform="matrix(0.8506406,0,0,0.8506406,187.82699,-0.1960013)" + id="g3813"> + style="fill:url(#radialGradient3817);fill-opacity:1;fill-rule:evenodd;stroke:#370700;stroke-width:1.91000152;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + d="m -216.13659,7.270763 0,55.5 12.375,0 0,-21.71875 8.75,0 0,-8.5625 -8.75,0 0,-9.241879 21.55514,0 0,-15.945621 -33.93014,-0.03125 z" + id="rect3663" + sodipodi:nodetypes="ccccccccccc" + inkscape:connector-curvature="0" /> - - - - - - - - - - - - - - - - - + style="fill:url(#radialGradient3661);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:1.91000152;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + d="m -161.05088,23.811562 -7.19826,4.129889 -3.17869,-1.103092 -3.03274,-7.750723 -4.77066,0.250699 -2.17602,8.014733 -3.04547,1.45841 -7.59591,-3.322815 -3.20831,3.565187 4.1299,7.198257 -1.12858,3.169376 -7.75073,3.032741 0.27618,4.779962 8.01474,2.176021 1.45841,3.045461 -3.34829,7.586615 3.56518,3.208306 7.19825,-4.129891 3.19487,1.137883 3.00726,7.741419 4.80544,-0.266883 2.15054,-8.024034 3.04547,-1.458412 7.61208,3.357607 3.20831,-3.565187 -4.12989,-7.198256 1.11239,-3.204168 7.74142,-3.00726 -0.24138,-4.796137 -8.02404,-2.150536 -1.45842,-3.045461 3.33212,-7.621406 -3.56517,-3.208305 z m -10.7808,11.804259 1.47765,0.857357 1.28022,1.160735 1.02494,1.385223 0.73729,1.540127 0.43349,1.660242 0.0718,1.701463 -0.24575,1.701021 -0.56084,1.61483 -0.89215,1.493834 -1.12594,1.264037 -1.38523,1.024933 -1.54013,0.737291 -1.66023,0.433483 -1.71077,0.09731 -1.70103,-0.245733 -1.61482,-0.560852 -1.49383,-0.892149 -1.25475,-1.151431 -1.03422,-1.359735 -0.73731,-1.540126 -0.42417,-1.685727 -0.0973,-1.710769 0.24573,-1.701025 0.56086,-1.614826 0.88284,-1.468351 1.13526,-1.28952 1.38522,-1.024934 1.54012,-0.737294 1.68572,-0.424174 1.70147,-0.07182 1.70102,0.245731 1.61483,0.560854 z" + id="path3659" + inkscape:connector-curvature="0" /> - Free - Free - CAD - CAD - - + + AUTHOR NAME + CREATION DATE + SUPERVISOR NAME + CHECK DATE + SCALE + WEIGHT + NUMBER + SHEET + TITLE + SUBTITLE + From 529b92cbfe8e188c7e8170bf80c5eec3ab4a95f3 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 29 Dec 2011 23:23:37 -0200 Subject: [PATCH 09/10] + small fixes to the Drawing Page --- src/Mod/Drawing/App/FeaturePage.cpp | 66 +++++++++++++++++------------ src/Mod/Drawing/App/FeaturePage.h | 1 + 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/Mod/Drawing/App/FeaturePage.cpp b/src/Mod/Drawing/App/FeaturePage.cpp index 2779105e9..bf1af14af 100644 --- a/src/Mod/Drawing/App/FeaturePage.cpp +++ b/src/Mod/Drawing/App/FeaturePage.cpp @@ -76,34 +76,11 @@ void FeaturePage::onChanged(const App::Property* prop) } } if (prop == &Template) { - // getting editable texts from "freecad:editable" tags in SVG template if (!this->isRestoring()) { - if (Template.getValue() != "") { - Base::FileInfo tfi(Template.getValue()); - if (tfi.isReadable()) { - string tline, tfrag; - ifstream tfile (tfi.filePath().c_str()); - while (!tfile.eof()) { - getline (tfile,tline); - tfrag += tline; - tfrag += "--endOfLine--"; - } - tfile.close(); - boost::regex e ("(.*?)"); - string::const_iterator tbegin, tend; - tbegin = tfrag.begin(); - tend = tfrag.end(); - boost::match_results twhat; - std::vector eds; - while (boost::regex_search(tbegin, tend, twhat, e)) { - printf(twhat[1].str().c_str()); - eds.push_back(twhat[2]); - tbegin = twhat[0].second; - } - EditableTexts.setValues(eds); - } - } + cout << "setting template " << Template.getValue() << endl; + EditableTexts.setValues(getEditableTexts()); } + else cout << "restoring" << endl; } App::DocumentObjectGroup::onChanged(prop); } @@ -199,3 +176,40 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) //} return App::DocumentObject::StdReturn; } + +std::vector FeaturePage::getEditableTexts(void) const { + //getting editable texts from "freecad:editable" tags in SVG template + + std::vector eds; + + if (Template.getValue() != "") { + Base::FileInfo tfi(Template.getValue()); + if (!tfi.isReadable()) { + // if there is a old absolute template file set use a redirect + tfi.setFile(App::Application::getResourceDir() + "Mod/Drawing/Templates/" + tfi.fileName()); + // try the redirect + if (!tfi.isReadable()) { + return eds; + } + } + string tline, tfrag; + ifstream tfile (tfi.filePath().c_str()); + while (!tfile.eof()) { + getline (tfile,tline); + tfrag += tline; + tfrag += "--endOfLine--"; + } + tfile.close(); + boost::regex e ("(.*?)"); + string::const_iterator tbegin, tend; + tbegin = tfrag.begin(); + tend = tfrag.end(); + boost::match_results twhat; + while (boost::regex_search(tbegin, tend, twhat, e)) { + printf(twhat[1].str().c_str()); + eds.push_back(twhat[2]); + tbegin = twhat[0].second; + } + } + return eds; +} diff --git a/src/Mod/Drawing/App/FeaturePage.h b/src/Mod/Drawing/App/FeaturePage.h index ed64c1b3b..3f74065b7 100644 --- a/src/Mod/Drawing/App/FeaturePage.h +++ b/src/Mod/Drawing/App/FeaturePage.h @@ -59,6 +59,7 @@ public: virtual const char* getViewProviderName(void) const { return "DrawingGui::ViewProviderDrawingPage"; } + virtual std::vector getEditableTexts(void) const; protected: void onChanged(const App::Property* prop); From a9d2f1c67832f1e75a3f3ab21c86015e86df95d7 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 30 Dec 2011 13:02:33 -0200 Subject: [PATCH 10/10] + more small fixes to DrawingPage --- src/Mod/Drawing/App/FeaturePage.cpp | 24 +++++++++++------------- src/Mod/Drawing/App/FeaturePage.h | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/Mod/Drawing/App/FeaturePage.cpp b/src/Mod/Drawing/App/FeaturePage.cpp index bf1af14af..684fe28cf 100644 --- a/src/Mod/Drawing/App/FeaturePage.cpp +++ b/src/Mod/Drawing/App/FeaturePage.cpp @@ -77,10 +77,8 @@ void FeaturePage::onChanged(const App::Property* prop) } if (prop == &Template) { if (!this->isRestoring()) { - cout << "setting template " << Template.getValue() << endl; - EditableTexts.setValues(getEditableTexts()); + EditableTexts.setValues(getEditableTextsFromTemplate()); } - else cout << "restoring" << endl; } App::DocumentObjectGroup::onChanged(prop); } @@ -142,13 +140,14 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) if (EditableTexts.getSize() > 0) { boost::regex e1 ("(.*?)"); string::const_iterator begin, end; - begin = ofile.str().begin(); - end = ofile.str().end(); + begin = outfragment.begin(); + end = outfragment.end(); boost::match_results what; int count = 0; while (boost::regex_search(begin, end, what, e1)) { if (count < EditableTexts.getSize()) { + // change values of editable texts boost::regex e2 ("((.*?)()"); outfragment = boost::regex_replace(outfragment, e2, "$1>"+EditableTexts.getValues()[count]+"$3"); } @@ -177,8 +176,8 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) return App::DocumentObject::StdReturn; } -std::vector FeaturePage::getEditableTexts(void) const { - //getting editable texts from "freecad:editable" tags in SVG template +std::vector FeaturePage::getEditableTextsFromTemplate(void) const { + //getting editable texts from "freecad:editable" attributes in SVG template std::vector eds; @@ -195,9 +194,9 @@ std::vector FeaturePage::getEditableTexts(void) const { string tline, tfrag; ifstream tfile (tfi.filePath().c_str()); while (!tfile.eof()) { - getline (tfile,tline); - tfrag += tline; - tfrag += "--endOfLine--"; + getline (tfile,tline); + tfrag += tline; + tfrag += "--endOfLine--"; } tfile.close(); boost::regex e ("(.*?)"); @@ -206,9 +205,8 @@ std::vector FeaturePage::getEditableTexts(void) const { tend = tfrag.end(); boost::match_results twhat; while (boost::regex_search(tbegin, tend, twhat, e)) { - printf(twhat[1].str().c_str()); - eds.push_back(twhat[2]); - tbegin = twhat[0].second; + eds.push_back(twhat[2]); + tbegin = twhat[0].second; } } return eds; diff --git a/src/Mod/Drawing/App/FeaturePage.h b/src/Mod/Drawing/App/FeaturePage.h index 3f74065b7..8f03c76d4 100644 --- a/src/Mod/Drawing/App/FeaturePage.h +++ b/src/Mod/Drawing/App/FeaturePage.h @@ -59,7 +59,7 @@ public: virtual const char* getViewProviderName(void) const { return "DrawingGui::ViewProviderDrawingPage"; } - virtual std::vector getEditableTexts(void) const; + virtual std::vector getEditableTextsFromTemplate(void) const; protected: void onChanged(const App::Property* prop);