Merge branch 'master' of ssh://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad

This commit is contained in:
wmayer 2012-02-05 00:55:43 +01:00
commit e94ec3ee99
8 changed files with 273 additions and 89 deletions

View File

@ -278,21 +278,30 @@ TaskDialogPython::TaskDialogPython(const Py::Object& o) : dlg(o)
}
}
else if (dlg.hasAttr(std::string("form"))) {
Py::Object widget(dlg.getAttr(std::string("form")));
Py::Module mainmod(PyImport_AddModule((char*)"sip"));
Py::Callable func = mainmod.getDict().getItem("unwrapinstance");
Py::Tuple arguments(1);
arguments[0] = widget; //PyQt pointer
Py::Object result = func.apply(arguments);
void* ptr = PyLong_AsVoidPtr(result.ptr());
QObject* object = reinterpret_cast<QObject*>(ptr);
if (object) {
QWidget* form = qobject_cast<QWidget*>(object);
if (form) {
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
form->windowIcon().pixmap(32), form->windowTitle(), true, 0);
taskbox->groupLayout()->addWidget(form);
Content.push_back(taskbox);
Py::Object f(dlg.getAttr(std::string("form")));
Py::List widgets;
if (f.isList()) {
widgets = f;
}
else {
widgets.append(f);
}
for (Py::List::iterator it = widgets.begin(); it != widgets.end(); ++it) {
Py::Module mainmod(PyImport_AddModule((char*)"sip"));
Py::Callable func = mainmod.getDict().getItem("unwrapinstance");
Py::Tuple arguments(1);
arguments[0] = *it; //PyQt pointer
Py::Object result = func.apply(arguments);
void* ptr = PyLong_AsVoidPtr(result.ptr());
QObject* object = reinterpret_cast<QObject*>(ptr);
if (object) {
QWidget* form = qobject_cast<QWidget*>(object);
if (form) {
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
form->windowIcon().pixmap(32), form->windowTitle(), true, 0);
taskbox->groupLayout()->addWidget(form);
Content.push_back(taskbox);
}
}
}
}

View File

@ -32,7 +32,8 @@ __url__ = "http://free-cad.sourceforge.net"
def makeWall(baseobj=None,width=None,height=None,align="Center",name="Wall"):
'''makeWall(obj,[width],[height],[align],[name]): creates a wall based on the
given object'''
given object, which can be a sketch, a draft object, a face or a solid. align
can be "Center","Left" or "Right"'''
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
_Wall(obj)
_ViewProviderWall(obj.ViewObject)
@ -55,6 +56,8 @@ def joinWalls(walls):
return None
if not isinstance(walls,list):
walls = [walls]
if not areSameWallTypes(walls):
return None
base = walls.pop()
if base.Base:
if base.Base.Shape.Faces:
@ -63,9 +66,8 @@ def joinWalls(walls):
sk = base.Base
else:
sk = Draft.makeSketch(base.Base,autoconstraints=True)
old = base.Base.name
base.Base = sk
FreeCAD.ActiveDocument.removeObject(old)
if sk:
base.Base = sk
for w in walls:
if w.Base:
if not base.Base.Shape.Faces:
@ -74,6 +76,24 @@ def joinWalls(walls):
FreeCAD.ActiveDocument.recompute()
return base
def areSameWallTypes(walls):
"returns True is all the walls in the given list have same height, width, and alignment"
for att in ["Width","Height","Align"]:
value = None
for w in walls:
if not hasattr(w,att):
return False
if not value:
value = getattr(w,att)
else:
if type(value) == float:
if round(value,Draft.precision()) != round(getattr(w,att),Draft.precision()):
return False
else:
if value != getattr(w,att):
return False
return True
class _CommandWall:
"the Arch Wall command definition"
def GetResources(self):
@ -83,6 +103,14 @@ class _CommandWall:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Wall","Creates a wall object from scratch or from a selected object (wire, face or solid)")}
def Activated(self):
global QtGui, QtCore
from PyQt4 import QtGui, QtCore
self.Width = 0.1
self.Height = 1
self.Align = "Center"
sel = FreeCADGui.Selection.getSelection()
done = False
self.existing = []
@ -98,41 +126,106 @@ class _CommandWall:
import DraftTrackers
self.points = []
self.tracker = DraftTrackers.boxTracker()
FreeCADGui.Snapper.getPoint(callback=self.getPoint)
FreeCADGui.Snapper.getPoint(callback=self.getPoint,extradlg=self.taskbox())
def getPoint(self,point):
def getPoint(self,point=None,obj=None):
"this function is called by the snapper when it has a 3D point"
pos = FreeCADGui.ActiveDocument.ActiveView.getCursorPos()
exi = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo(pos)
if exi:
exi = FreeCAD.ActiveDocument.getObject(exi['Object'])
if Draft.getType(exi) == "Wall":
if not exi in self.existing:
self.existing.append(exi)
if obj:
if Draft.getType(obj) == "Wall":
if not obj in self.existing:
self.existing.append(obj)
if point == None:
self.tracker.finalize()
return
self.points.append(point)
if len(self.points) == 1:
self.tracker.on()
FreeCADGui.Snapper.getPoint(last=self.points[0],callback=self.getPoint,movecallback=self.update)
FreeCADGui.Snapper.getPoint(last=self.points[0],callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox())
elif len(self.points) == 2:
import Part
l = Part.Line(self.points[0],self.points[1])
self.tracker.finalize()
FreeCAD.ActiveDocument.openTransaction("Wall")
if not self.existing:
s = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace")
s.addGeometry(l)
makeWall(s)
self.addDefault(l)
else:
w = joinWalls(self.existing)
w.Base.addGeometry(l)
self.tracker.finalize()
if w:
if areSameWallTypes([w,self]):
w.Base.addGeometry(l)
else:
self.addDefault(l)
else:
self.addDefault(l)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
def addDefault(self,l):
s = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace")
s.addGeometry(l)
makeWall(s,width=self.Width,height=self.Height,align=self.Align)
def update(self,point):
"this function is called by the Snapper when the mouse is moved"
self.tracker.update([self.points[0],point])
b = self.points[0]
n = FreeCAD.DraftWorkingPlane.axis
bv = point.sub(b)
dv = bv.cross(n)
dv = fcvec.scaleTo(dv,self.Width/2)
if self.Align == "Center":
self.tracker.update([b,point])
elif self.Align == "Left":
self.tracker.update([b.add(dv),point.add(dv)])
else:
dv = fcvec.neg(dv)
self.tracker.update([b.add(dv),point.add(dv)])
def taskbox(self):
"sets up a taskbox widget"
w = QtGui.QWidget()
w.setWindowTitle("Wall options")
lay0 = QtGui.QVBoxLayout(w)
lay1 = QtGui.QHBoxLayout()
lay0.addLayout(lay1)
label1 = QtGui.QLabel("Width")
lay1.addWidget(label1)
value1 = QtGui.QDoubleSpinBox()
value1.setDecimals(2)
value1.setValue(self.Width)
lay1.addWidget(value1)
lay2 = QtGui.QHBoxLayout()
lay0.addLayout(lay2)
label2 = QtGui.QLabel("Height")
lay2.addWidget(label2)
value2 = QtGui.QDoubleSpinBox()
value2.setDecimals(2)
value2.setValue(self.Height)
lay2.addWidget(value2)
lay3 = QtGui.QHBoxLayout()
lay0.addLayout(lay3)
label3 = QtGui.QLabel("Alignment")
lay3.addWidget(label3)
value3 = QtGui.QComboBox()
items = ["Center","Left","Right"]
value3.addItems(items)
value3.setCurrentIndex(items.index(self.Align))
lay3.addWidget(value3)
QtCore.QObject.connect(value1,QtCore.SIGNAL("valueChanged(double)"),self.setWidth)
QtCore.QObject.connect(value2,QtCore.SIGNAL("valueChanged(double)"),self.setHeight)
QtCore.QObject.connect(value3,QtCore.SIGNAL("currentIndexChanged(int)"),self.setAlign)
return w
def setWidth(self,d):
self.Width = d
self.tracker.width(d)
def setHeight(self,d):
self.Height = d
self.tracker.height(d)
def setAlign(self,i):
self.Align = ["Center","Left","Right"][i]
class _Wall(ArchComponent.Component):
"The Wall object"
def __init__(self,obj):
@ -162,6 +255,10 @@ class _Wall(ArchComponent.Component):
import Part
from draftlibs import fcgeo
flat = False
if hasattr(obj.ViewObject,"DisplayMode"):
flat = (obj.ViewObject.DisplayMode == "Flat 2D")
def getbase(wire):
"returns a full shape from a base wire"
@ -182,7 +279,9 @@ class _Wall(ArchComponent.Component):
dvec = fcvec.neg(dvec)
w2 = fcgeo.offsetWire(wire,dvec)
sh = fcgeo.bind(w1,w2)
if height:
# fixing self-intersections
sh.fix(0.1,0,1)
if height and (not flat):
norm = Vector(normal).multiply(height)
sh = sh.extrude(norm)
return sh
@ -258,4 +357,18 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent):
def getIcon(self):
return ":/icons/Arch_Wall_Tree.svg"
def getDisplayModes(self,vobj):
return ["Flat 2D"]
def setDisplayMode(self,mode):
self.Object.Proxy.createGeometry(self.Object)
if mode == "Flat 2D":
return "Flat Lines"
else:
return mode
def attach(self,vobj):
self.Object = vobj.Object
return
FreeCADGui.addCommand('Arch_Wall',_CommandWall())

View File

@ -136,8 +136,14 @@ class DraftLineEdit(QtGui.QLineEdit):
QtGui.QLineEdit.keyPressEvent(self, event)
class DraftTaskPanel:
def __init__(self,widget):
self.form = widget
def __init__(self,widget,extra=None):
if extra:
if isinstance(extra,list):
self.form = [widget] + extra
else:
self.form = [widget,extra]
else:
self.form = widget
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Cancel)
def accept(self):
@ -155,6 +161,7 @@ class DraftToolBar:
self.tray = None
self.sourceCmd = None
self.cancel = None
self.pointcallback = None
self.taskmode = Draft.getParam("UiMode")
self.paramcolor = Draft.getParam("color")>>8
self.color = QtGui.QColor(self.paramcolor)
@ -171,7 +178,7 @@ class DraftToolBar:
self.fillmode = Draft.getParam("fillmode")
if self.taskmode:
# only a dummy widget, since widgets are created on demand
# add only a dummy widget, since widgets are created on demand
self.baseWidget = QtGui.QWidget()
else:
# create the draft Toolbar
@ -250,6 +257,12 @@ class DraftToolBar:
if hide: chk.hide()
layout.addWidget(chk)
return chk
def _combo (self,name,layout,hide=True):
cb = QtGui.QComboBox(self.baseWidget)
cb.setObjectName(name)
if hide: cb.hide()
layout.addWidget(cb)
def setupToolBar(self,task=False):
"sets the draft toolbar up"
@ -463,19 +476,17 @@ class DraftToolBar:
# Interface modes
#---------------------------------------------------------------------------
def taskUi(self,title):
def taskUi(self,title,extra=None):
if self.taskmode:
self.isTaskOn = True
todo.delay(FreeCADGui.Control.closeDialog,None)
self.baseWidget = QtGui.QWidget()
self.setTitle(title)
self.layout = QtGui.QVBoxLayout(self.baseWidget)
self.setupToolBar(task=True)
self.retranslateUi(self.baseWidget)
self.panel = DraftTaskPanel(self.baseWidget)
self.panel = DraftTaskPanel(self.baseWidget,extra)
todo.delay(FreeCADGui.Control.showDialog,self.panel)
else:
self.setTitle(title)
self.setTitle(title)
def selectPlaneUi(self):
self.taskUi(translate("draft", "Select Plane"))
@ -510,9 +521,10 @@ class DraftToolBar:
self.labelx.setText(translate("draft", "Center X"))
self.continueCmd.show()
def pointUi(self,title=translate("draft","Point"),cancel=None):
def pointUi(self,title=translate("draft","Point"),cancel=None,extra=None,getcoords=None,rel=False):
if cancel: self.cancel = cancel
self.taskUi(title)
if getcoords: self.pointcallback = getcoords
self.taskUi(title,extra)
self.xValue.setEnabled(True)
self.yValue.setEnabled(True)
self.labelx.setText(translate("draft", "X"))
@ -522,9 +534,13 @@ class DraftToolBar:
self.xValue.show()
self.yValue.show()
self.zValue.show()
if rel: self.isRelative.show()
self.xValue.setFocus()
self.xValue.selectAll()
def extraUi(self):
pass
def offsetUi(self):
self.taskUi(translate("draft","Offset"))
self.radiusUi()
@ -536,6 +552,9 @@ class DraftToolBar:
def offUi(self):
todo.delay(FreeCADGui.Control.closeDialog,None)
self.cancel = None
self.sourceCmd = None
self.pointcallback = None
if self.taskmode:
self.isTaskOn = False
self.baseWidget = QtGui.QWidget()
@ -570,7 +589,7 @@ class DraftToolBar:
self.textValue.hide()
self.continueCmd.hide()
self.occOffset.hide()
def trimUi(self,title=translate("draft","Trim")):
self.taskUi(title)
self.radiusUi()
@ -792,7 +811,7 @@ class DraftToolBar:
def validatePoint(self):
"function for checking and sending numbers entered manually"
if self.sourceCmd != None:
if self.sourceCmd or self.pointcallback:
if (self.labelRadius.isVisible()):
try:
rad=float(self.radiusValue.text())
@ -815,22 +834,25 @@ class DraftToolBar:
except ValueError:
pass
else:
if self.isRelative.isVisible() and self.isRelative.isChecked():
if self.sourceCmd.node:
if self.sourceCmd.featureName == "Rectangle":
last = self.sourceCmd.node[0]
else:
last = self.sourceCmd.node[-1]
numx = last.x + numx
numy = last.y + numy
numz = last.z + numz
if FreeCAD.DraftWorkingPlane:
v = FreeCAD.Vector(numx,numy,numz)
v = FreeCAD.DraftWorkingPlane.getGlobalCoords(v)
numx = v.x
numy = v.y
numz = v.z
self.sourceCmd.numericInput(numx,numy,numz)
if self.pointcallback:
self.pointcallback(FreeCAD.Vector(numx,numy,numz),(self.isRelative.isVisible() and self.isRelative.isChecked()))
else:
if self.isRelative.isVisible() and self.isRelative.isChecked():
if self.sourceCmd.node:
if self.sourceCmd.featureName == "Rectangle":
last = self.sourceCmd.node[0]
else:
last = self.sourceCmd.node[-1]
numx = last.x + numx
numy = last.y + numy
numz = last.z + numz
if FreeCAD.DraftWorkingPlane:
v = FreeCAD.Vector(numx,numy,numz)
v = FreeCAD.DraftWorkingPlane.getGlobalCoords(v)
numx = v.x
numy = v.y
numz = v.z
self.sourceCmd.numericInput(numx,numy,numz)
def finish(self):
"finish button action"

View File

@ -68,6 +68,7 @@ class Snapper:
self.grid = None
self.constrainLine = None
self.trackLine = None
self.lastSnappedObject = None
# the snapmarker has "dot","circle" and "square" available styles
self.mk = {'passive':'circle',
@ -175,6 +176,8 @@ class Snapper:
obj = FreeCAD.ActiveDocument.getObject(info['Object'])
if not obj:
return cstr(point)
self.lastSnappedObject = obj
if hasattr(obj.ViewObject,"Selectable"):
if not obj.ViewObject.Selectable:
@ -531,6 +534,7 @@ class Snapper:
for v in self.views:
v.unsetCursor()
self.views = []
self.cursorMode = None
else:
if mode != self.cursorMode:
if not self.views:
@ -559,11 +563,9 @@ class Snapper:
self.extLine.off()
if self.grid:
self.grid.off()
if self.constrainLine:
self.constrainLine.off()
self.unconstrain()
self.radius = 0
self.setCursor()
self.cursorMode = None
def constrain(self,point,basepoint=None,axis=None):
'''constrain(point,basepoint=None,axis=None: Returns a
@ -627,11 +629,12 @@ class Snapper:
if self.constrainLine:
self.constrainLine.off()
def getPoint(self,last=None,callback=None,movecallback=None):
def getPoint(self,last=None,callback=None,movecallback=None,extradlg=None):
"""getPoint([last],[callback],[movecallback]) : 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 pass a function as callback, which will get called
"""getPoint([last],[callback],[movecallback],[extradlg]) : 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 pass a function as callback, which will get called
with the resulting point as argument, when a point is clicked, and optionally
another callback which gets called when the mouse is moved.
@ -642,7 +645,12 @@ class Snapper:
def cb(point):
if point:
print "got a 3D point: ",point
FreeCADGui.Snapper.getPoint(callback=cb)"""
FreeCADGui.Snapper.getPoint(callback=cb)
If the callback function accepts more than one argument, it will also receive
the last snapped object. Finally, a pyqt dialog can be passed as extra taskbox."""
import inspect
self.pt = None
self.ui = FreeCADGui.draftToolBar
@ -667,19 +675,33 @@ class Snapper:
if movecallback:
movecallback(self.pt)
def getcoords(point,relative=False):
self.pt = point
if relative and last:
v = FreeCAD.DraftWorkingPlane.getGlobalCoords(point)
self.pt = last.add(v)
accept()
def click(event_cb):
event = event_cb.getEvent()
if event.getButton() == 1:
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
accept()
def accept():
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick)
self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),self.callbackMove)
obj = FreeCADGui.Snapper.lastSnappedObject
FreeCADGui.Snapper.off()
self.ui.offUi()
if self.trackLine:
self.trackLine.off()
if callback:
if len(inspect.getargspec(callback).args) > 2:
callback(self.pt,obj)
else:
callback(self.pt)
self.pt = None
def cancel():
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick)
@ -691,8 +713,8 @@ class Snapper:
if callback:
callback(None)
# adding 2 callback functions
self.ui.pointUi(cancel=cancel)
# adding callback functions
self.ui.pointUi(cancel=cancel,getcoords=getcoords,extra=extradlg,rel=bool(last))
self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click)
self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move)

View File

@ -476,7 +476,7 @@ class Line(Creator):
if self.isWire:
msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n"))
else:
currentshape = self.obj.Shape
currentshape = self.obj.Shape.copy()
last = self.node[len(self.node)-2]
newseg = Part.Line(last,point).toShape()
newshape=currentshape.fuse(newseg)

View File

@ -680,7 +680,7 @@ class boxTracker(Tracker):
else:
return self.cube.width.getValue()
def heigth(self,h=None):
def height(self,h=None):
if h:
self.cube.depth.setValue(h)
self.update()

View File

@ -959,9 +959,19 @@ def getTangent(edge,frompoint=None):
def bind(w1,w2):
'''bind(wire1,wire2): binds 2 wires by their endpoints and
returns a face'''
w3 = Part.Line(w1.Vertexes[0].Point,w2.Vertexes[0].Point).toShape()
w4 = Part.Line(w1.Vertexes[-1].Point,w2.Vertexes[-1].Point).toShape()
return Part.Face(Part.Wire(w1.Edges+[w3]+w2.Edges+[w4]))
if w1.isClosed() and w2.isClosed():
d1 = w1.BoundBox.DiagonalLength
d2 = w2.BoundBox.DiagonalLength
if d1 > d2:
#w2.reverse()
return Part.Face([w1,w2])
else:
#w1.reverse()
return Part.Face([w2,w1])
else:
w3 = Part.Line(w1.Vertexes[0].Point,w2.Vertexes[0].Point).toShape()
w4 = Part.Line(w1.Vertexes[-1].Point,w2.Vertexes[-1].Point).toShape()
return Part.Face(Part.Wire(w1.Edges+[w3]+w2.Edges+[w4]))
def cleanFaces(shape):
"removes inner edges from coplanar faces"

View File

@ -95,6 +95,14 @@ class TaskCalendar:
def __init__(self):
self.form = QtGui.QCalendarWidget()
class TaskManyTaskBoxes:
"illustrates how to add several taskboxes"
def __init__(self):
widget1 = QtGui.QCalendarWidget()
widget2 = QtGui.QWidget()
widget2.setWindowTitle("My Test Box")
text = QtGui.QLabel("testBox",widget2)
self.form = [widget1,widget2]
def createTask():
Gui.Control.addTaskWatcher([TaskWatcher(), TaskLineEdit(), TaskWatcherFilter()])