[Draft] Improved Snapper Toolbar Behaviour

Changed snap toolbar behaviour:
- create a list of available snaps (Gui.Snapper.snaps)
- make it consistent with Snap Gui Commands (in gui_snaps module)
- create a list of active snaps (Gui.Snapper.active_snaps)
- refactor the isEnabled() method to allow it to check if the given snap is in Gui.Snapper.active_snaps and not if the snap toolbar button isChecked()
- updated and reordered the new list of gui snap commands in draftutils.init_tools and used it as a base to refactor the creation of draft toolbar
- updated all the draft snap gui tools to make them control the toolbar buttons directly
.


.


.
This commit is contained in:
carlopav
2020-03-21 10:09:34 +01:00
committed by Yorik van Havre
parent add624353d
commit 55e537d79d
4 changed files with 259 additions and 220 deletions

View File

@@ -1893,8 +1893,7 @@ class DraftToolBar:
return str(a)
def togglesnap(self):
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.toggle()
FreeCADGui.doCommand('FreeCADGui.runCommand("Draft_Snap_Lock")')
def togglenearsnap(self):
if hasattr(FreeCADGui,"Snapper"):

View File

@@ -39,19 +39,19 @@ import math
from pivy import coin
from PySide import QtCore, QtGui
import FreeCAD
import FreeCADGui
import FreeCAD as App
import FreeCADGui as Gui
import Draft
import DraftVecUtils
from FreeCAD import Vector
import draftguitools.gui_trackers as trackers
from draftutils.init_tools import get_draft_snap_commands
from draftutils.messages import _msg, _wrn
__title__ = "FreeCAD Draft Snap tools"
__author__ = "Yorik van Havre"
__url__ = "https://www.freecadweb.org"
class Snapper:
"""Classes to manage snapping in Draft and Arch.
@@ -117,6 +117,27 @@ class Snapper:
self.callbackMove = None
self.snapObjectIndex = 0
# snap keys, it's important tha they are in this order for
# saving in preferences and for properly restore the toolbar
self.snaps = ['Lock', # 0
'Near', # 1 former "passive" snap
'Extension', # 2
'Parallel', # 3
'Grid', # 4
"Endpoint", # 5
'Midpoint', # 6
'Perpendicular', # 7
'Angle', # 8
'Center', # 9
'Ortho', # 10
'Intersection', # 11
'Special', # 12
'Dimensions', # 13
'WorkingPlane' # 14
]
self.init_active_snaps()
# the snapmarker has "dot","circle" and "square" available styles
if self.snapStyle:
self.mk = coll.OrderedDict([('passive', 'empty'),
@@ -159,6 +180,19 @@ class Snapper:
('intersection', ':/icons/Snap_Intersection.svg'),
('special', ':/icons/Snap_Special.svg')])
def init_active_snaps(self):
"""
set self.active_snaps according to user prefs
"""
self.active_snaps = []
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
snap_modes = param.GetString("snapModes")
i = 0
for snap in snap_modes:
if bool(int(snap)):
self.active_snaps.append(self.snaps[i])
i += 1
def cstr(self, lastpoint, constrain, point):
"""Return constraints if needed."""
if constrain or self.mask:
@@ -197,8 +231,8 @@ class Snapper:
if not hasattr(self, "toolbar"):
self.makeSnapToolBar()
mw = FreeCADGui.getMainWindow()
bt = mw.findChild(QtGui.QToolBar, "Draft Snap")
mw = Gui.getMainWindow()
bt = mw.findChild(QtGui.QToolBar,"Draft Snap")
if not bt:
mw.addToolBar(self.toolbar)
else:
@@ -310,7 +344,7 @@ class Snapper:
subname = self.snapInfo['SubName']
obj = parent.getSubObject(subname, retType=1)
else:
obj = FreeCAD.ActiveDocument.getObject(self.snapInfo['Object'])
obj = App.ActiveDocument.getObject(self.snapInfo['Object'])
parent = obj
subname = self.snapInfo['Component']
if not obj:
@@ -434,9 +468,9 @@ class Snapper:
# calculating the nearest snap point
shortest = 1000000000000000000
origin = Vector(self.snapInfo['x'],
self.snapInfo['y'],
self.snapInfo['z'])
origin = App.Vector(self.snapInfo['x'],
self.snapInfo['y'],
self.snapInfo['z'])
winner = None
fp = point
for snap in snaps:
@@ -454,7 +488,7 @@ class Snapper:
if self.radius:
dv = point.sub(winner[2])
if (dv.Length > self.radius):
if (not oldActive) and self.isEnabled("passive"):
if (not oldActive) and self.isEnabled("Near"):
winner = self.snapToVertex(self.snapInfo)
# setting the cursors
@@ -482,8 +516,8 @@ class Snapper:
def toWP(self, point):
"""Project the given point on the working plane, if needed."""
if self.isEnabled("WorkingPlane"):
if hasattr(FreeCAD, "DraftWorkingPlane"):
return FreeCAD.DraftWorkingPlane.projectPoint(point)
if hasattr(App, "DraftWorkingPlane"):
return App.DraftWorkingPlane.projectPoint(point)
return point
def getApparentPoint(self, x, y):
@@ -491,14 +525,14 @@ class Snapper:
view = Draft.get3DView()
pt = view.getPoint(x, y)
if self.mask != "z":
if hasattr(FreeCAD, "DraftWorkingPlane"):
if hasattr(App,"DraftWorkingPlane"):
if view.getCameraType() == "Perspective":
camera = view.getCameraNode()
p = camera.getField("position").getValue()
dv = pt.sub(Vector(p[0], p[1], p[2]))
dv = pt.sub(App.Vector(p[0], p[1], p[2]))
else:
dv = view.getViewDirection()
return FreeCAD.DraftWorkingPlane.projectPoint(pt, dv)
return App.DraftWorkingPlane.projectPoint(pt, dv)
return pt
def snapToDim(self, obj):
@@ -526,7 +560,7 @@ class Snapper:
self.extLine.on()
self.setCursor(tsnap[1])
return tsnap[2], eline
if self.isEnabled("extension"):
if self.isEnabled("Extension"):
tsnap = self.snapToExtOrtho(last, constrain, eline)
if tsnap:
if (tsnap[0].sub(point)).Length < self.radius:
@@ -553,10 +587,10 @@ class Snapper:
self.setCursor(tsnap[1])
return tsnap[2], eline
for o in (self.lastObj[1], self.lastObj[0]):
if o and (self.isEnabled('extension')
or self.isEnabled('parallel')):
ob = FreeCAD.ActiveDocument.getObject(o)
for o in [self.lastObj[1], self.lastObj[0]]:
if o and (self.isEnabled('Extension')
or self.isEnabled('Parallel')):
ob = App.ActiveDocument.getObject(o)
if ob:
if ob.isDerivedFrom("Part::Feature"):
edges = ob.Shape.Edges
@@ -572,7 +606,7 @@ class Snapper:
np = self.getPerpendicular(e,point)
if not DraftGeomUtils.isPtOnEdge(np,e):
if (np.sub(point)).Length < self.radius:
if self.isEnabled('extension'):
if self.isEnabled('Extension'):
if np != e.Vertexes[0].Point:
p0 = e.Vertexes[0].Point
if self.tracker and not self.selectMode:
@@ -603,7 +637,7 @@ class Snapper:
self.lastExtensions[0] = ne
return np,ne
else:
if self.isEnabled('parallel'):
if self.isEnabled('Parallel'):
if last:
ve = DraftGeomUtils.vec(e)
if not DraftVecUtils.isNull(ve):
@@ -620,7 +654,7 @@ class Snapper:
def snapToCrossExtensions(self, point):
"""Snap to the intersection of the last 2 extension lines."""
if self.isEnabled('extension'):
if self.isEnabled('Extension'):
if len(self.lastExtensions) == 2:
np = DraftGeomUtils.findIntersection(self.lastExtensions[0], self.lastExtensions[1], True, True)
if np:
@@ -648,19 +682,19 @@ class Snapper:
return p
return None
def snapToPolar(self, point, last):
def snapToPolar(self,point,last):
"""Snap to polar lines from the given point."""
if self.isEnabled('ortho') and (not self.mask):
if self.isEnabled('Ortho') and (not self.mask):
if last:
vecs = []
if hasattr(FreeCAD, "DraftWorkingPlane"):
ax = [FreeCAD.DraftWorkingPlane.u,
FreeCAD.DraftWorkingPlane.v,
FreeCAD.DraftWorkingPlane.axis]
if hasattr(App,"DraftWorkingPlane"):
ax = [App.DraftWorkingPlane.u,
App.DraftWorkingPlane.v,
App.DraftWorkingPlane.axis]
else:
ax = [FreeCAD.Vector(1, 0, 0),
FreeCAD.Vector(0, 1, 0),
FreeCAD.Vector(0, 0, 1)]
ax = [App.Vector(1, 0, 0),
App.Vector(0, 1, 0),
App.Vector(0, 0, 1)]
for a in self.polarAngles:
if a == 90:
vecs.extend([ax[0], ax[0].negative()])
@@ -691,7 +725,7 @@ class Snapper:
"""Return a grid snap point if available."""
if self.grid:
if self.grid.Visible:
if self.isEnabled("grid"):
if self.isEnabled("Grid"):
np = self.grid.getClosestNode(point)
if np:
dv = point.sub(np)
@@ -707,7 +741,7 @@ class Snapper:
def snapToEndpoints(self, shape):
"""Return a list of endpoints snap locations."""
snaps = []
if self.isEnabled("endpoint"):
if self.isEnabled("Endpoint"):
if hasattr(shape, "Vertexes"):
for v in shape.Vertexes:
snaps.append([v.Point, 'endpoint', self.toWP(v.Point)])
@@ -725,7 +759,7 @@ class Snapper:
def snapToMidpoint(self, shape):
"""Return a list of midpoints snap locations."""
snaps = []
if self.isEnabled("midpoint"):
if self.isEnabled("Midpoint"):
if isinstance(shape, Part.Edge):
mp = DraftGeomUtils.findMidpoint(shape)
if mp:
@@ -735,7 +769,7 @@ class Snapper:
def snapToPerpendicular(self, shape, last):
"""Return a list of perpendicular snap locations."""
snaps = []
if self.isEnabled("perpendicular"):
if self.isEnabled("Perpendicular"):
if last:
if isinstance(shape, Part.Edge):
if DraftGeomUtils.geomType(shape) == "Line":
@@ -758,7 +792,7 @@ class Snapper:
def snapToOrtho(self, shape, last, constrain):
"""Return a list of ortho snap locations."""
snaps = []
if self.isEnabled("ortho"):
if self.isEnabled("Ortho"):
if constrain:
if isinstance(shape, Part.Edge):
if last:
@@ -774,7 +808,7 @@ class Snapper:
def snapToExtOrtho(self, last, constrain, eline):
"""Return an ortho X extension snap location."""
if self.isEnabled("extension") and self.isEnabled("ortho"):
if self.isEnabled("Extension") and self.isEnabled("Ortho"):
if constrain and last and self.constraintAxis and self.extLine:
tmpEdge1 = Part.LineSegment(last, last.add(self.constraintAxis)).toShape()
tmpEdge2 = Part.LineSegment(self.extLine.p1(), self.extLine.p2()).toShape()
@@ -800,15 +834,15 @@ class Snapper:
"""
if not self.holdPoints:
return None
if hasattr(FreeCAD, "DraftWorkingPlane"):
u = FreeCAD.DraftWorkingPlane.u
v = FreeCAD.DraftWorkingPlane.v
if hasattr(App, "DraftWorkingPlane"):
u = App.DraftWorkingPlane.u
v = App.DraftWorkingPlane.v
else:
u = FreeCAD.Vector(1, 0, 0)
v = FreeCAD.Vector(0, 1, 0)
u = App.Vector(1, 0, 0)
v = App.Vector(0, 1, 0)
if len(self.holdPoints) > 1:
# first try mid points
if self.isEnabled("midpoint"):
if self.isEnabled("Midpoint"):
l = list(self.holdPoints)
for p1, p2 in itertools.combinations(l, 2):
p3 = p1.add((p2.sub(p1)).multiply(0.5))
@@ -845,7 +879,7 @@ class Snapper:
def snapToExtPerpendicular(self, last):
"""Return a perpendicular X extension snap location."""
if self.isEnabled("extension") and self.isEnabled("perpendicular"):
if self.isEnabled("Extension") and self.isEnabled("Perpendicular"):
if last and self.extLine:
if self.extLine.p1() != self.extLine.p2():
tmpEdge = Part.LineSegment(self.extLine.p1(), self.extLine.p2()).toShape()
@@ -856,7 +890,7 @@ class Snapper:
def snapToElines(self, e1, e2):
"""Return a snap at the infinite intersection of the given edges."""
snaps = []
if self.isEnabled("intersection") and self.isEnabled("extension"):
if self.isEnabled("Intersection") and self.isEnabled("Extension"):
if e1 and e2:
# get the intersection points
pts = DraftGeomUtils.findIntersection(e1, e2, True, True)
@@ -868,7 +902,7 @@ class Snapper:
def snapToAngles(self, shape):
"""Return a list of angle snap locations."""
snaps = []
if self.isEnabled("angle"):
if self.isEnabled("Angle"):
rad = shape.Curve.Radius
pos = shape.Curve.Center
for i in (0, 30, 45, 60, 90,
@@ -885,7 +919,7 @@ class Snapper:
def snapToCenter(self, shape):
"""Return a list of center snap locations."""
snaps = []
if self.isEnabled("center"):
if self.isEnabled("Center"):
pos = shape.Curve.Center
c = self.toWP(pos)
if hasattr(shape.Curve, "Radius"):
@@ -906,7 +940,7 @@ class Snapper:
def snapToFace(self, shape):
"""Return a face center snap location."""
snaps = []
if self.isEnabled("center"):
if self.isEnabled("Center"):
pos = shape.CenterOfMass
c = self.toWP(pos)
snaps.append([pos, 'center', c])
@@ -915,10 +949,10 @@ class Snapper:
def snapToIntersection(self, shape):
"""Return a list of intersection snap locations."""
snaps = []
if self.isEnabled("intersection"):
if self.isEnabled("Intersection"):
# get the stored objects to calculate intersections
if self.lastObj[0]:
obj = FreeCAD.ActiveDocument.getObject(self.lastObj[0])
obj = App.ActiveDocument.getObject(self.lastObj[0])
if obj:
if obj.isDerivedFrom("Part::Feature") or (Draft.getType(obj) == "Axis"):
if (not self.maxEdges) or (len(obj.Shape.Edges) <= self.maxEdges):
@@ -947,7 +981,7 @@ class Snapper:
def snapToPolygon(self, obj):
"""Return a list of polygon center snap locations."""
snaps = []
if self.isEnabled("center"):
if self.isEnabled("Center"):
c = obj.Placement.Base
for edge in obj.Shape.Edges:
p1 = edge.Vertexes[0].Point
@@ -958,29 +992,16 @@ class Snapper:
snaps.append([v2, 'center', self.toWP(c)])
return snaps
def snapToVertex(self, info, active=False):
"""Return a vertex snap location."""
p = Vector(info['x'], info['y'], info['z'])
if active:
if self.isEnabled("passive"):
return [p, 'endpoint', self.toWP(p)]
else:
return []
elif self.isEnabled("passive"):
return [p, 'passive', p]
else:
return []
def snapToSpecials(self, obj, lastpoint=None, eline=None):
"""Return special snap locations, if any."""
snaps = []
if self.isEnabled("special"):
if self.isEnabled("Special"):
if (Draft.getType(obj) == "Wall"):
# special snapping for wall: snap to its base shape if it is linear
if obj.Base:
if not obj.Base.Shape.Solids:
for v in obj.Base.Shape.Vertexes:
snaps.append([v.Point, 'special', self.toWP(v.Point)])
elif (Draft.getType(obj) == "Structure"):
@@ -1040,13 +1061,13 @@ class Snapper:
def setCursor(self, mode=None):
"""Set or reset the cursor to the given mode or resets."""
if self.selectMode:
mw = FreeCADGui.getMainWindow()
mw = Gui.getMainWindow()
for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget):
if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget":
w.unsetCursor()
self.cursorMode = None
elif not mode:
mw = FreeCADGui.getMainWindow()
mw = Gui.getMainWindow()
for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget):
if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget":
w.unsetCursor()
@@ -1064,7 +1085,7 @@ class Snapper:
qp.drawPixmap(QtCore.QPoint(16, 8), tp)
qp.end()
cur = QtGui.QCursor(newicon, 8, 8)
mw = FreeCADGui.getMainWindow()
mw = Gui.getMainWindow()
for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget):
if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget":
w.setCursor(cur)
@@ -1121,7 +1142,7 @@ class Snapper:
"""Keep the current angle."""
if delta:
self.mask = delta
elif isinstance(self.mask, FreeCAD.Vector):
elif isinstance(self.mask, App.Vector):
self.mask = None
elif self.trackLine:
if self.trackLine.Visible:
@@ -1138,15 +1159,15 @@ class Snapper:
used as basepoint.
"""
# without the Draft module fully loaded, no axes system!"
if not hasattr(FreeCAD, "DraftWorkingPlane"):
if not hasattr(App, "DraftWorkingPlane"):
return point
point = Vector(point)
point = App.Vector(point)
# setup trackers if needed
if not self.constrainLine:
if self.snapStyle:
self.constrainLine = trackers.lineTracker(scolor=FreeCADGui.draftToolBar.getDefaultColor("snap"))
self.constrainLine = trackers.lineTracker(scolor=Gui.draftToolBar.getDefaultColor("snap"))
else:
self.constrainLine = trackers.lineTracker(dotted=True)
@@ -1162,23 +1183,23 @@ class Snapper:
if self.mask:
self.affinity = self.mask
if not self.affinity:
self.affinity = FreeCAD.DraftWorkingPlane.getClosestAxis(delta)
if isinstance(axis, FreeCAD.Vector):
self.affinity = App.DraftWorkingPlane.getClosestAxis(delta)
if isinstance(axis, App.Vector):
self.constraintAxis = axis
elif axis == "x":
self.constraintAxis = FreeCAD.DraftWorkingPlane.u
self.constraintAxis = App.DraftWorkingPlane.u
elif axis == "y":
self.constraintAxis = FreeCAD.DraftWorkingPlane.v
self.constraintAxis = App.DraftWorkingPlane.v
elif axis == "z":
self.constraintAxis = FreeCAD.DraftWorkingPlane.axis
self.constraintAxis = App.DraftWorkingPlane.axis
else:
if self.affinity == "x":
self.constraintAxis = FreeCAD.DraftWorkingPlane.u
self.constraintAxis = App.DraftWorkingPlane.u
elif self.affinity == "y":
self.constraintAxis = FreeCAD.DraftWorkingPlane.v
self.constraintAxis = App.DraftWorkingPlane.v
elif self.affinity == "z":
self.constraintAxis = FreeCAD.DraftWorkingPlane.axis
elif isinstance(self.affinity, FreeCAD.Vector):
self.constraintAxis = App.DraftWorkingPlane.axis
elif isinstance(self.affinity, App.Vector):
self.constraintAxis = self.affinity
else:
self.constraintAxis = None
@@ -1229,7 +1250,7 @@ class Snapper:
if point:
print "got a 3D point: ",point
FreeCADGui.Snapper.getPoint(callback=cb)
Gui.Snapper.getPoint(callback=cb)
If the callback function accepts more than one argument,
it will also receive the last snapped object. Finally, a qt widget
@@ -1243,7 +1264,7 @@ class Snapper:
self.pt = None
self.lastSnappedObject = None
self.holdPoints = []
self.ui = FreeCADGui.draftToolBar
self.ui = Gui.draftToolBar
self.view = Draft.get3DView()
# remove any previous leftover callbacks
@@ -1259,20 +1280,20 @@ class Snapper:
mousepos = event.getPosition()
ctrl = event.wasCtrlDown()
shift = event.wasShiftDown()
self.pt = FreeCADGui.Snapper.snap(mousepos, lastpoint=last,
active=ctrl, constrain=shift)
if hasattr(FreeCAD, "DraftWorkingPlane"):
self.pt = Gui.Snapper.snap(mousepos, lastpoint=last,
active=ctrl, constrain=shift)
if hasattr(App, "DraftWorkingPlane"):
self.ui.displayPoint(self.pt, last,
plane=FreeCAD.DraftWorkingPlane,
mask=FreeCADGui.Snapper.affinity)
plane = App.DraftWorkingPlane,
mask = App.Snapper.affinity)
if movecallback:
movecallback(self.pt, self.snapInfo)
def getcoords(point, relative=False):
"""Get the global coordinates from a point."""
self.pt = point
if relative and last and hasattr(FreeCAD, "DraftWorkingPlane"):
v = FreeCAD.DraftWorkingPlane.getGlobalCoords(point)
if relative and last and hasattr(App, "DraftWorkingPlane"):
v = App.DraftWorkingPlane.getGlobalCoords(point)
self.pt = last.add(v)
accept()
@@ -1289,8 +1310,8 @@ class Snapper:
self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove)
self.callbackClick = None
self.callbackMove = None
obj = FreeCADGui.Snapper.lastSnappedObject
FreeCADGui.Snapper.off()
obj = Gui.Snapper.lastSnappedObject
Gui.Snapper.off()
self.ui.offUi()
if callback:
if len(inspect.getargspec(callback).args) > 1:
@@ -1306,7 +1327,7 @@ class Snapper:
self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove)
self.callbackClick = None
self.callbackMove = None
FreeCADGui.Snapper.off()
Gui.Snapper.off()
self.ui.offUi()
if callback:
if len(inspect.getargspec(callback).args) > 1:
@@ -1332,121 +1353,90 @@ class Snapper:
def makeSnapToolBar(self):
"""Build the Snap toolbar."""
mw = FreeCADGui.getMainWindow()
mw = Gui.getMainWindow()
self.toolbar = QtGui.QToolBar(mw)
mw.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar)
self.toolbar.setObjectName("Draft Snap")
self.toolbar.setWindowTitle(QtCore.QCoreApplication.translate("Workbench", "Draft Snap"))
self.toolbarButtons = []
# grid button
self.gridbutton = QtGui.QAction(mw)
self.gridbutton.setIcon(QtGui.QIcon.fromTheme("Draft_Grid", QtGui.QIcon(":/icons/Draft_Grid.svg")))
self.gridbutton.setText(QtCore.QCoreApplication.translate("Draft_ToggleGrid", "Grid"))
self.gridbutton.setToolTip(QtCore.QCoreApplication.translate("Draft_ToggleGrid", "Toggles the Draft grid On/Off"))
self.gridbutton.setObjectName("GridButton")
self.gridbutton.setWhatsThis("Draft_ToggleGrid")
QtCore.QObject.connect(self.gridbutton, QtCore.SIGNAL("triggered()"), self.toggleGrid)
self.toolbar.addAction(self.gridbutton)
snap_gui_commands = get_draft_snap_commands()
self.init_draft_snap_buttons(snap_gui_commands, self.toolbar, "_Button")
self.restore_snap_buttons_state(self.toolbar,"_Button")
# master button
self.masterbutton = QtGui.QAction(mw)
self.masterbutton.setIcon(QtGui.QIcon.fromTheme("Snap_Lock", QtGui.QIcon(":/icons/Snap_Lock.svg")))
self.masterbutton.setText(QtCore.QCoreApplication.translate("Draft_Snap_Lock", "Lock"))
self.masterbutton.setToolTip(QtCore.QCoreApplication.translate("Draft_Snap_Lock", "Toggle On/Off"))
self.masterbutton.setObjectName("SnapButtonMain")
self.masterbutton.setWhatsThis("Draft_ToggleSnap")
self.masterbutton.setCheckable(True)
self.masterbutton.setChecked(True)
QtCore.QObject.connect(self.masterbutton,
QtCore.SIGNAL("toggled(bool)"), self.toggle)
self.toolbar.addAction(self.masterbutton)
for c,i in self.cursors.items():
if i:
b = QtGui.QAction(mw)
b.setIcon(QtGui.QIcon.fromTheme(i.replace(':/icons/', '').replace('.svg', ''), QtGui.QIcon(i)))
if c == "passive":
b.setText(QtCore.QCoreApplication.translate("Draft_Snap_Near", "Nearest"))
b.setToolTip(QtCore.QCoreApplication.translate("Draft_Snap_Near", "Nearest"))
else:
b.setText(QtCore.QCoreApplication.translate("Draft_Snap_"+c.capitalize(), c.capitalize()))
b.setToolTip(QtCore.QCoreApplication.translate("Draft_Snap_"+c.capitalize(), c.capitalize()))
b.setObjectName("SnapButton" + c)
b.setWhatsThis("Draft_" + c.capitalize())
b.setCheckable(True)
b.setChecked(True)
self.toolbar.addAction(b)
self.toolbarButtons.append(b)
QtCore.QObject.connect(b, QtCore.SIGNAL("toggled(bool)"),
self.saveSnapModes)
if not Draft.getParam("showSnapBar",True):
self.toolbar.hide()
# adding non-snap button
for n in ("Dimensions", "WorkingPlane"):
b = QtGui.QAction(mw)
b.setIcon(QtGui.QIcon.fromTheme("Snap_" + n, QtGui.QIcon(":/icons/Snap_"+n+".svg")))
b.setText(QtCore.QCoreApplication.translate("Draft_Snap_" + n,n))
b.setToolTip(QtCore.QCoreApplication.translate("Draft_Snap_" + n,n))
b.setObjectName("SnapButton" + n)
b.setWhatsThis("Draft_" + n)
def init_draft_snap_buttons(self, commands, context, button_suffix):
"""
Init Draft Snap toolbar buttons.
Parameters:
commands Snap command list,
use: get_draft_snap_commands():
context The toolbar or action group the buttons have
to be added to
button_suffix The suffix that have to be applied to the command name
to define the button name
"""
for gc in commands:
# setup toolbar buttons
command = 'Gui.runCommand("' + gc + '")'
b = QtGui.QAction(context)
b.setIcon(QtGui.QIcon(':/icons/' + gc[6:] + '.svg'))
b.setText(QtCore.QCoreApplication.translate("Draft_Snap", "Snap " + gc[11:]))
b.setToolTip(QtCore.QCoreApplication.translate("Draft_Snap", "Snap " + gc[11:]))
b.setObjectName(gc + button_suffix)
b.setWhatsThis("Draft_"+gc[11:].capitalize())
b.setCheckable(True)
b.setChecked(True)
self.toolbar.addAction(b)
QtCore.QObject.connect(b, QtCore.SIGNAL("toggled(bool)"),
self.saveSnapModes)
self.toolbarButtons.append(b)
context.addAction(b)
QtCore.QObject.connect(b,
QtCore.SIGNAL("triggered()"),
lambda f=Gui.doCommand,
arg=command:f(arg))
# set status tip where needed
for b in self.toolbar.actions():
for b in context.actions():
if len(b.statusTip()) == 0:
b.setStatusTip(b.toolTip())
# restoring states
t = Draft.getParam("snapModes", "111111111101111")
if t:
c = 0
for b in [self.masterbutton] + self.toolbarButtons:
if len(t) > c:
state = bool(int(t[c]))
b.setChecked(state)
def restore_snap_buttons_state(self, toolbar, button_suffix):
"""
Restore toolbar button's checked state according to
"snapModes" saved in preferences
"""
# set status tip where needed
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
snap_modes = param.GetString("snapModes")
for b in toolbar.actions():
if len(b.statusTip()) == 0:
b.setStatusTip(b.toolTip())
# restore toolbar buttons state
if snap_modes:
for a in toolbar.findChildren(QtGui.QAction):
snap = a.objectName()[11:].replace(button_suffix,"")
if snap in Gui.Snapper.snaps:
i = Gui.Snapper.snaps.index(snap)
state = bool(int(snap_modes[i]))
a.setChecked(state)
if state:
b.setToolTip(b.toolTip() + " (ON)")
a.setToolTip(a.toolTip()+" (ON)")
else:
b.setToolTip(b.toolTip() + " (OFF)")
c += 1
if not Draft.getParam("showSnapBar", True):
self.toolbar.hide()
a.setToolTip(a.toolTip()+" (OFF)")
def get_snap_toolbar(self):
"""retuns snap toolbar object"""
mw = Gui.getMainWindow()
if mw:
toolbar = mw.findChild(QtGui.QToolBar,"Draft Snap")
if toolbar:
return toolbar
return None
def toggleGrid(self):
"""Run Draft_ToggleGrid."""
FreeCADGui.runCommand("Draft_ToggleGrid")
def saveSnapModes(self):
"""Save the snap modes for next sessions."""
t = ''
for b in [self.masterbutton] + self.toolbarButtons:
t += str(int(b.isChecked()))
if b.isChecked():
b.setToolTip(b.toolTip().replace("OFF", "ON"))
else:
b.setToolTip(b.toolTip().replace("ON", "OFF"))
Draft.setParam("snapModes", t)
def toggle(self, checked=None):
"""Toggle the snap mode."""
if hasattr(self, "toolbarButtons"):
if checked is None:
self.masterbutton.toggle()
elif checked:
if hasattr(self, "savedButtonStates"):
for i in range(len(self.toolbarButtons)):
self.toolbarButtons[i].setEnabled(True)
self.toolbarButtons[i].setChecked(self.savedButtonStates[i])
else:
self.savedButtonStates = []
for i in range(len(self.toolbarButtons)):
self.savedButtonStates.append(self.toolbarButtons[i].isChecked())
self.toolbarButtons[i].setEnabled(False)
self.saveSnapModes()
"toggle FreeCAD Draft Grid"
Gui.runCommand("Draft_ToggleGrid")
def showradius(self):
"""Show the snap radius indicator."""
@@ -1456,32 +1446,66 @@ class Snapper:
self.radiusTracker.update(self.radius)
self.radiusTracker.on()
def isEnabled(self, but):
"""Return true if the given button is turned on."""
for b in self.toolbarButtons:
if str(b.objectName()) == "SnapButton" + but:
return (b.isEnabled() and b.isChecked())
return False
def isEnabled(self, snap):
"Returns true if the given snap is on"
if "Lock" in self.active_snaps and snap in self.active_snaps:
return True
else:
return False
def toggle_snap(self, snap, set_to = None):
"Sets the given snap on/off according to the given parameter"
if set_to: # set mode
if set_to is True:
if not snap in self.active_snaps:
self.active_snaps.append(snap)
status = True
elif set_to is False:
if snap in self.active_snaps:
self.active_snaps.remove(snap)
status = False
else: # toggle mode, default
if not snap in self.active_snaps:
self.active_snaps.append(snap)
status = True
elif snap in self.active_snaps:
self.active_snaps.remove(snap)
status = False
self.save_snap_state()
return status
def save_snap_state(self):
"""
save snap state to user preferences to be restored in next session
"""
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
snap_modes = ""
for snap in self.snaps:
if snap in self.active_snaps:
snap_modes += "1"
else:
snap_modes += "0"
param.SetString("snapModes",snap_modes)
def show(self):
"""Show the toolbar and the grid."""
if not hasattr(self, "toolbar"):
self.makeSnapToolBar()
mw = FreeCADGui.getMainWindow()
bt = mw.findChild(QtGui.QToolBar, "Draft Snap")
bt = self.get_snap_toolbar()
if not bt:
mw = FreeCADGui.getMainWindow()
mw.addToolBar(self.toolbar)
self.toolbar.setParent(mw)
self.toolbar.show()
self.toolbar.toggleViewAction().setVisible(True)
if FreeCADGui.ActiveDocument:
if Gui.ActiveDocument:
self.setTrackers()
if not FreeCAD.ActiveDocument.Objects:
if FreeCADGui.ActiveDocument.ActiveView:
if FreeCADGui.ActiveDocument.ActiveView.getCameraType() == 'Orthographic':
c = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()
if not App.ActiveDocument.Objects:
if Gui.ActiveDocument.ActiveView:
if Gui.ActiveDocument.ActiveView.getCameraType() == 'Orthographic':
c = Gui.ActiveDocument.ActiveView.getCameraNode()
if c.orientation.getValue().getValue() == (0.0, 0.0, 0.0, 1.0):
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
p = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
h = p.GetInt("defaultCameraHeight",0)
if h:
c.height.setValue(h)
@@ -1523,7 +1547,7 @@ class Snapper:
self.tracker = trackers.snapTracker()
self.trackLine = trackers.lineTracker()
if self.snapStyle:
c = FreeCADGui.draftToolBar.getDefaultColor("snap")
c = Gui.draftToolBar.getDefaultColor("snap")
self.extLine = trackers.lineTracker(scolor=c)
self.extLine2 = trackers.lineTracker(scolor=c)
else:

View File

@@ -28,12 +28,23 @@
# \brief Provide the Draft_Snap commands used by the snapping mechanism
# in Draft.
from PySide.QtCore import QT_TRANSLATE_NOOP
import draftguitools.gui_base as gui_base
import FreeCADGui as Gui
import draftguitools.gui_base as gui_base
from draftutils.translate import _tr
from PySide.QtCore import QT_TRANSLATE_NOOP
from draftutils.translate import _tr
class Draft_Snap_Lock(gui_base.GuiCommandSimplest):
"""GuiCommand for the Draft_Snap_Lock tool.
Activate or deactivate all snap methods at once.
"""
def __init__(self):
super().__init__(name=_tr("Main toggle snap"))
class Draft_Snap_Lock(gui_base.GuiCommandSimplest):
"""GuiCommand for the Draft_Snap_Lock tool.
@@ -63,6 +74,11 @@ class Draft_Snap_Lock(gui_base.GuiCommandSimplest):
if hasattr(Gui.Snapper, "masterbutton"):
Gui.Snapper.masterbutton.toggle()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "masterbutton"):
Gui.Snapper.masterbutton.toggle()
Gui.addCommand('Draft_Snap_Lock', Draft_Snap_Lock())
Gui.addCommand('Draft_Snap_Lock', Draft_Snap_Lock())

View File

@@ -115,15 +115,15 @@ def get_draft_utility_commands():
def get_draft_snap_commands():
"""Return the snapping commands list."""
return ['Draft_Snap_Lock', 'Draft_Snap_Midpoint',
'Draft_Snap_Perpendicular',
'Draft_Snap_Grid', 'Draft_Snap_Intersection',
'Draft_Snap_Parallel',
'Draft_Snap_Endpoint', 'Draft_Snap_Angle',
'Draft_Snap_Center',
'Draft_Snap_Extension', 'Draft_Snap_Near',
'Draft_Snap_Ortho', 'Draft_Snap_Special',
'Draft_Snap_Dimensions', 'Draft_Snap_WorkingPlane']
return ['Draft_Snap_Lock',
'Draft_Snap_Endpoint', 'Draft_Snap_Midpoint',
'Draft_Snap_Center', 'Draft_Snap_Angle',
'Draft_Snap_Intersection', 'Draft_Snap_Perpendicular',
'Draft_Snap_Extension', 'Draft_Snap_Parallel',
'Draft_Snap_Special', 'Draft_Snap_Near',
'Draft_Snap_Ortho', 'Draft_Snap_Grid',
'Draft_Snap_WorkingPlane', 'Draft_Snap_Dimensions',
]
def init_draft_toolbars(workbench):