Add BIM workbench to .pre-commit-config.yaml (#21591)

* Add BIM workbench to .pre-commit-config.yaml

* pre-commit: ignore translations

* pre-commit: add additional ignore pattern

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Furgo
2025-10-13 13:07:48 +02:00
committed by GitHub
parent 210190cdd7
commit 6345b824e5
197 changed files with 21982 additions and 13836 deletions

View File

@@ -22,9 +22,9 @@
# * *
# ***************************************************************************
__title__ = "FreeCAD Arch External Reference"
__title__ = "FreeCAD Arch External Reference"
__author__ = "Yorik van Havre"
__url__ = "https://www.freecad.org"
__url__ = "https://www.freecad.org"
## @package ArchReference
# \ingroup ARCH
@@ -50,15 +50,16 @@ if FreeCAD.GuiUp:
from draftutils.translate import translate
else:
# \cond
def translate(ctxt,txt):
def translate(ctxt, txt):
return txt
def QT_TRANSLATE_NOOP(ctxt,txt):
def QT_TRANSLATE_NOOP(ctxt, txt):
return txt
# \endcond
class ArchReference:
"""The Arch Reference object"""
def __init__(self, obj):
@@ -68,30 +69,35 @@ class ArchReference:
ArchReference.setProperties(self, obj)
self.reload = True
def setProperties(self, obj):
pl = obj.PropertiesList
if not "File" in pl:
t = QT_TRANSLATE_NOOP("App::Property","The base file this component is built upon")
obj.addProperty("App::PropertyFile","File","Reference",t, locked=True)
t = QT_TRANSLATE_NOOP("App::Property", "The base file this component is built upon")
obj.addProperty("App::PropertyFile", "File", "Reference", t, locked=True)
if not "Part" in pl:
t = QT_TRANSLATE_NOOP("App::Property","The part to use from the base file")
obj.addProperty("App::PropertyString","Part","Reference",t, locked=True)
t = QT_TRANSLATE_NOOP("App::Property", "The part to use from the base file")
obj.addProperty("App::PropertyString", "Part", "Reference", t, locked=True)
if not "ReferenceMode" in pl:
t = QT_TRANSLATE_NOOP("App::Property","The way the referenced objects are included in the current document. 'Normal' includes the shape, 'Transient' discards the shape when the object is switched off (smaller filesize), 'Lightweight' does not import the shape but only the OpenInventor representation")
obj.addProperty("App::PropertyEnumeration","ReferenceMode","Reference",t, locked=True)
obj.ReferenceMode = ["Normal","Transient","Lightweight"]
t = QT_TRANSLATE_NOOP(
"App::Property",
"The way the referenced objects are included in the current document. 'Normal' includes the shape, 'Transient' discards the shape when the object is switched off (smaller filesize), 'Lightweight' does not import the shape but only the OpenInventor representation",
)
obj.addProperty(
"App::PropertyEnumeration", "ReferenceMode", "Reference", t, locked=True
)
obj.ReferenceMode = ["Normal", "Transient", "Lightweight"]
if "TransientReference" in pl:
if obj.TransientReference:
obj.ReferenceMode = "Transient"
obj.removeProperty("TransientReference")
t = translate("Arch", "TransientReference property to ReferenceMode")
FreeCAD.Console.PrintMessage(translate("Arch","Upgrading")+" "+obj.Label+" "+t+"\n")
FreeCAD.Console.PrintMessage(
translate("Arch", "Upgrading") + " " + obj.Label + " " + t + "\n"
)
if not "FuseArch" in pl:
t = QT_TRANSLATE_NOOP("App::Property","Fuse objects of same material")
obj.addProperty("App::PropertyBool","FuseArch", "Reference", t, locked=True)
t = QT_TRANSLATE_NOOP("App::Property", "Fuse objects of same material")
obj.addProperty("App::PropertyBool", "FuseArch", "Reference", t, locked=True)
def onDocumentRestored(self, obj):
@@ -101,20 +107,17 @@ class ArchReference:
if obj.ViewObject and obj.ViewObject.Proxy:
obj.ViewObject.Proxy.loadInventor(obj)
def dumps(self):
return None
def loads(self, state):
self.Type = "Reference"
def onChanged(self, obj, prop):
if prop in ["File","Part"]:
if prop in ["File", "Part"]:
self.reload = True
elif prop == "ReferenceMode":
if obj.ReferenceMode == "Normal":
@@ -130,19 +133,20 @@ class ArchReference:
elif obj.ReferenceMode == "Lightweight":
self.reload = False
import Part
pl = obj.Placement
obj.Shape = Part.Shape()
obj.Placement = pl
if obj.ViewObject and obj.ViewObject.Proxy:
obj.ViewObject.Proxy.loadInventor(obj)
def execute(self, obj):
import Part
pl = obj.Placement
filename = self.getFile(obj)
if filename and self.reload and obj.ReferenceMode in ["Normal","Transient"]:
if filename and self.reload and obj.ReferenceMode in ["Normal", "Transient"]:
self.parts = self.getPartsList(obj)
if self.parts:
if filename.lower().endswith(".fcstd"):
@@ -156,21 +160,21 @@ class ArchReference:
shapedata = f.read()
f.close()
shapedata = shapedata.decode("utf8")
shape = self.cleanShape(shapedata,obj,self.parts[obj.Part][2])
shape = self.cleanShape(shapedata, obj, self.parts[obj.Part][2])
self.shapes.append(shape)
obj.Shape = shape
if not pl.isIdentity():
obj.Placement = pl
else:
t = translate("Arch","Part not found in file")
FreeCAD.Console.PrintError(t+"\n")
t = translate("Arch", "Part not found in file")
FreeCAD.Console.PrintError(t + "\n")
else:
for part in self.parts.values():
f = zdoc.open(part[1])
shapedata = f.read()
f.close()
shapedata = shapedata.decode("utf8")
shape = self.cleanShape(shapedata,obj)
shape = self.cleanShape(shapedata, obj)
self.shapes.append(shape)
if self.shapes:
obj.Shape = Part.makeCompound(self.shapes)
@@ -182,8 +186,10 @@ class ArchReference:
from nativeifc import ifc_tools
from nativeifc import ifc_generator
except:
t = translate("Arch","NativeIFC not available - unable to process IFC files")
FreeCAD.Console.PrintError(t+"\n")
t = translate(
"Arch", "NativeIFC not available - unable to process IFC files"
)
FreeCAD.Console.PrintError(t + "\n")
return
elements = self.getIFCElements(obj, ifcfile)
shape, colors = ifc_generator.generate_shape(ifcfile, elements, cached=True)
@@ -208,6 +214,7 @@ class ArchReference:
doc = obj.Document
oldobjs = list(doc.Objects)
import Import
Import.readDXF(filename, doc.Name, True, loc + "/RefDxfImport")
newobjs = [o for o in doc.Objects if o not in oldobjs]
shapes = [o.Shape for o in newobjs if o.isDerivedFrom("Part::Feature")]
@@ -220,16 +227,14 @@ class ArchReference:
doc.removeObject(n)
self.reload = False
def getIFCElements(self, obj, ifcfile):
"""returns IFC elements for this object"""
try:
from nativeifc import ifc_generator
except:
t = translate("Arch","NativeIFC not available - unable to process IFC files")
FreeCAD.Console.PrintError(t+"\n")
t = translate("Arch", "NativeIFC not available - unable to process IFC files")
FreeCAD.Console.PrintError(t + "\n")
return
if obj.Part:
element = ifcfile[int(obj.Part)]
@@ -239,12 +244,11 @@ class ArchReference:
elements = ifc_generator.filter_types(elements)
return elements
def cleanShape(self, shapedata, obj, materials=None):
"""cleans the imported shape"""
import Part
shape = Part.Shape()
shape.importBrepFromString(shapedata)
if obj.FuseArch and materials:
@@ -263,8 +267,8 @@ class ArchReference:
break
else:
shapes.append(edge)
#print("solids:",len(shape.Solids),"mattable:",materials)
for key,solindexes in materials.items():
# print("solids:",len(shape.Solids),"mattable:",materials)
for key, solindexes in materials.items():
if key == "Undefined":
# do not join objects with no defined material
for solindex in [int(i) for i in solindexes.split(",")]:
@@ -282,13 +286,11 @@ class ArchReference:
try:
shape = shape.removeSplitter()
except Exception:
t = translate("Arch","Error removing splitter")
FreeCAD.Console.PrintError(obj.Label+": "+t+"\n")
t = translate("Arch", "Error removing splitter")
FreeCAD.Console.PrintError(obj.Label + ": " + t + "\n")
return shape
def exists(self,filepath):
def exists(self, filepath):
"""case-insensitive version of os.path.exists. Returns the actual file path or None"""
if os.path.exists(filepath):
@@ -301,9 +303,7 @@ class ArchReference:
return p + e.upper()
return None
def getFile(self,obj,filename=None):
def getFile(self, obj, filename=None):
"""gets a valid file, if possible"""
if not filename:
@@ -318,7 +318,7 @@ class ArchReference:
# search for the file in the current directory if not found
basename = os.path.basename(filename)
currentdir = os.path.dirname(obj.Document.FileName)
altfile = os.path.join(currentdir,basename)
altfile = os.path.join(currentdir, basename)
if altfile == obj.Document.FileName:
return None
elif self.exists(altfile):
@@ -328,16 +328,14 @@ class ArchReference:
altfile = None
subdirs = self.splitall(os.path.dirname(filename))
for i in range(len(subdirs)):
subpath = [currentdir]+subdirs[-i:]+[basename]
subpath = [currentdir] + subdirs[-i:] + [basename]
altfile = os.path.join(*subpath)
if self.exists(altfile):
return self.exists(altfile)
return None
return self.exists(filename)
def getPartsList(self, obj, filename=None):
"""returns a list of Part-based objects in a file"""
filename = self.getFile(obj, filename)
@@ -350,19 +348,15 @@ class ArchReference:
elif filename.lower().endswith(".dxf"):
return self.getPartsListDXF(obj, filename)
def getPartsListDXF(self, obj, filename):
"""returns a list of Part-based objects in a DXF file"""
# support layers
#with open(filename) as f:
# with open(filename) as f:
# txt = f.read()
return {}
def getPartsListIFC(self, obj, filename):
"""returns a list of Part-based objects in a IFC file"""
ifcfile = self.getIfcFile(filename)
@@ -378,9 +372,7 @@ class ArchReference:
res[str(s.id())] = [name, s, None]
return res
def getPartsListFCSTD(self, obj, filename):
"""returns a list of Part-based objects in a FCStd file"""
parts = {}
@@ -395,35 +387,35 @@ class ArchReference:
for line in docf:
line = line.decode("utf8")
if "<Object name=" in line:
n = re.findall(r'name=\"(.*?)\"',line)
n = re.findall(r"name=\"(.*?)\"", line)
if n:
name = n[0]
elif "<Property name=\"Label\"" in line:
elif '<Property name="Label"' in line:
writemode = True
elif writemode and "<String value=" in line:
n = re.findall(r'value=\"(.*?)\"',line)
n = re.findall(r"value=\"(.*?)\"", line)
if n:
label = n[0]
writemode = False
elif "<Property name=\"Shape\" type=\"Part::PropertyPartShape\"" in line:
elif '<Property name="Shape" type="Part::PropertyPartShape"' in line:
writemode = True
elif writemode and "<Part" in line and "file=" in line:
n = re.findall(r'file=\"(.*?)\"',line)
n = re.findall(r"file=\"(.*?)\"", line)
if n:
part = n[0]
writemode = False
elif "<Property name=\"MaterialsTable\" type=\"App::PropertyMap\"" in line:
elif '<Property name="MaterialsTable" type="App::PropertyMap"' in line:
writemode = True
elif writemode and "<Item key=" in line:
n = re.findall(r'key=\"(.*?)\"',line)
v = re.findall(r'value=\"(.*?)\"',line)
n = re.findall(r"key=\"(.*?)\"", line)
v = re.findall(r"value=\"(.*?)\"", line)
if n and v:
materials[n[0]] = v[0]
elif writemode and "</Map>" in line:
writemode = False
elif "</Object>" in line:
if name and label and part:
parts[name] = [label,part,materials]
parts[name] = [label, part, materials]
name = None
label = None
part = None
@@ -431,24 +423,20 @@ class ArchReference:
writemode = False
return parts
def getIfcFile(self, filename):
"""Gets an IfcOpenShell object"""
try:
import ifcopenshell
except:
t = translate("Arch","NativeIFC not available - unable to process IFC files")
FreeCAD.Console.PrintError(t+"\n")
t = translate("Arch", "NativeIFC not available - unable to process IFC files")
FreeCAD.Console.PrintError(t + "\n")
return None
if not getattr(self, "ifcfile", None):
self.ifcfile = ifcopenshell.open(filename)
return self.ifcfile
def getColors(self, obj):
"""returns the Shape Appearance of the referenced object(s)"""
filename = self.getFile(obj)
@@ -477,7 +465,6 @@ class ArchReference:
return totalcolors
def _getColorsPart(self, filename, part):
zdoc = zipfile.ZipFile(filename)
if not "GuiDocument.xml" in zdoc.namelist():
@@ -490,21 +477,21 @@ class ArchReference:
writemode3 = False
for line in docf:
line = line.decode("utf8")
if ("<ViewProvider name=\"" + part + "\"") in line:
if ('<ViewProvider name="' + part + '"') in line:
writemode1 = True
elif writemode1 and ("<Property name=\"DiffuseColor\"" in line):
elif writemode1 and ('<Property name="DiffuseColor"' in line):
writemode1 = False
writemode2 = True
elif writemode1 and ("<Property name=\"ShapeAppearance\"" in line):
elif writemode1 and ('<Property name="ShapeAppearance"' in line):
writemode1 = False
writemode3 = True
elif writemode2 and ("<ColorList file=" in line):
n = re.findall(r'file=\"(.*?)\"',line)
n = re.findall(r"file=\"(.*?)\"", line)
if n:
colorfile = n[0]
break
elif writemode3 and ("<MaterialList file=" in line):
n = re.findall(r'file=\"(.*?)\"',line)
n = re.findall(r"file=\"(.*?)\"", line)
if n:
colorfile = n[0]
break
@@ -521,11 +508,11 @@ class ArchReference:
if writemode2:
# Old DiffuseColor support:
for i in range(1, int(len(buf)/4)):
for i in range(1, int(len(buf) / 4)):
# ShapeAppearance material with default v0.21 properties:
material = FreeCAD.Material()
color = self._processColor(buf, i*4)
material.DiffuseColor = color[:3] + (255, )
color = self._processColor(buf, i * 4)
material.DiffuseColor = color[:3] + (255,)
material.Transparency = color[3] / 255.0
colors.append(material)
@@ -542,7 +529,7 @@ class ArchReference:
# - transparency
# - Tail of file: unknown repetition of bytes
for face_idx in range(buf[0]):
face_buf = buf[face_idx*24+4:face_idx*24+28]
face_buf = buf[face_idx * 24 + 4 : face_idx * 24 + 28]
# ShapeAppearance material with default v0.21 properties:
material = FreeCAD.Material()
material.AmbientColor = self._processColor(face_buf, 0)
@@ -555,19 +542,15 @@ class ArchReference:
return colors
def _processColor(self, buf, i):
"""returns a tuple with 4 ints (0-255)"""
return (buf[i+3], buf[i+2], buf[i+1], buf[i])
return (buf[i + 3], buf[i + 2], buf[i + 1], buf[i])
def _processNumber(self, buf, i):
"""returns a float"""
return struct.unpack("f", buf[i:i+4])[0]
def splitall(self,path):
return struct.unpack("f", buf[i : i + 4])[0]
def splitall(self, path):
"""splits a path between its components"""
allparts = []
@@ -576,7 +559,7 @@ class ArchReference:
if parts[0] == path: # sentinel for absolute paths
allparts.insert(0, parts[0])
break
elif parts[1] == path: # sentinel for relative paths
elif parts[1] == path: # sentinel for relative paths
allparts.insert(0, parts[1])
break
else:
@@ -586,94 +569,85 @@ class ArchReference:
class ViewProviderArchReference:
"""A View Provider for the Arch Reference object"""
def __init__(self,vobj):
def __init__(self, vobj):
vobj.Proxy = self
self.setProperties(vobj)
def setProperties(self,vobj):
def setProperties(self, vobj):
pl = vobj.PropertiesList
if not "TimeStamp" in pl:
t = QT_TRANSLATE_NOOP("App::Property","The latest time stamp of the linked file")
vobj.addProperty("App::PropertyFloat","TimeStamp","Reference",t, locked=True)
vobj.setEditorMode("TimeStamp",2)
t = QT_TRANSLATE_NOOP("App::Property", "The latest time stamp of the linked file")
vobj.addProperty("App::PropertyFloat", "TimeStamp", "Reference", t, locked=True)
vobj.setEditorMode("TimeStamp", 2)
if not "UpdateColors" in pl:
t = QT_TRANSLATE_NOOP("App::Property","If true, the colors from the linked file will be kept updated")
vobj.addProperty("App::PropertyBool","UpdateColors","Reference",t, locked=True)
t = QT_TRANSLATE_NOOP(
"App::Property", "If true, the colors from the linked file will be kept updated"
)
vobj.addProperty("App::PropertyBool", "UpdateColors", "Reference", t, locked=True)
vobj.UpdateColors = True
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Reference.svg"
def attach(self,vobj):
def attach(self, vobj):
self.Object = vobj.Object
# Check for file change every minute
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.checkChanges)
s = params.get_param_arch("ReferenceCheckInterval")
self.timer.start(1000*s)
self.timer.start(1000 * s)
def dumps(self):
return None
def loads(self,state):
def loads(self, state):
return None
def updateData(self,obj,prop):
if (prop == "Shape"):
if hasattr(obj.ViewObject,"UpdateColors") and obj.ViewObject.UpdateColors:
def updateData(self, obj, prop):
if prop == "Shape":
if hasattr(obj.ViewObject, "UpdateColors") and obj.ViewObject.UpdateColors:
if obj.Shape and not obj.Shape.isNull():
colors = obj.Proxy.getColors(obj)
if colors:
obj.ViewObject.ShapeAppearance = colors
def checkChanges(self):
"checks if the linked file has changed"
if hasattr(self,"Object") and self.Object:
if hasattr(self, "Object") and self.Object:
try:
f = self.Object.File
except ReferenceError:
f = None
if hasattr(self,"timer"):
if hasattr(self, "timer"):
self.timer.stop()
del self.timer
if f:
filename = self.Object.Proxy.getFile(self.Object)
if filename:
st_mtime = os.stat(filename).st_mtime
if hasattr(self.Object.ViewObject,"TimeStamp"):
if hasattr(self.Object.ViewObject, "TimeStamp"):
if self.Object.ViewObject.TimeStamp:
if self.Object.ViewObject.TimeStamp != st_mtime:
self.Object.Proxy.reload = True
self.Object.touch()
self.Object.ViewObject.TimeStamp = st_mtime
def onChanged(self,vobj,prop):
def onChanged(self, vobj, prop):
if prop == "ShapeColor":
# prevent ShapeColor from overriding DiffuseColor
if hasattr(vobj,"DiffuseColor") and hasattr(vobj,"UpdateColors"):
if hasattr(vobj, "DiffuseColor") and hasattr(vobj, "UpdateColors"):
if vobj.DiffuseColor and vobj.UpdateColors:
vobj.DiffuseColor = vobj.DiffuseColor
elif prop == "Visibility":
@@ -682,23 +656,22 @@ class ViewProviderArchReference:
vobj.Object.Proxy.reload = True
vobj.Object.Proxy.execute(vobj.Object)
else:
if hasattr(vobj.Object,"ReferenceMode"):
if hasattr(vobj.Object, "ReferenceMode"):
if vobj.Object.ReferenceMode == "Transient":
vobj.Object.Proxy.reload = False
import Part
pl = vobj.Object.Placement
vobj.Object.Shape = Part.Shape()
vobj.Object.Placement = pl
def onDelete(self, obj, doc):
def onDelete(self,obj,doc):
if hasattr(self,"timer"):
if hasattr(self, "timer"):
self.timer.stop()
del self.timer
return True
def setEdit(self, vobj, mode):
if mode != 0:
return None
@@ -707,7 +680,6 @@ class ViewProviderArchReference:
FreeCADGui.Control.showDialog(taskd)
return True
def unsetEdit(self, vobj, mode):
if mode != 0:
return None
@@ -715,62 +687,47 @@ class ViewProviderArchReference:
FreeCADGui.Control.closeDialog()
return True
def setupContextMenu(self, vobj, menu):
if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench':
if FreeCADGui.activeWorkbench().name() != "BIMWorkbench":
return
actionEdit = QtGui.QAction(translate("Arch", "Edit"),
menu)
QtCore.QObject.connect(actionEdit,
QtCore.SIGNAL("triggered()"),
self.edit)
actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu)
QtCore.QObject.connect(actionEdit, QtCore.SIGNAL("triggered()"), self.edit)
menu.addAction(actionEdit)
actionOnReload = QtGui.QAction(QtGui.QIcon(":/icons/view-refresh.svg"),
translate("Arch", "Reload reference"),
menu)
QtCore.QObject.connect(actionOnReload,
QtCore.SIGNAL("triggered()"),
self.onReload)
actionOnReload = QtGui.QAction(
QtGui.QIcon(":/icons/view-refresh.svg"), translate("Arch", "Reload reference"), menu
)
QtCore.QObject.connect(actionOnReload, QtCore.SIGNAL("triggered()"), self.onReload)
menu.addAction(actionOnReload)
actionOnOpen = QtGui.QAction(QtGui.QIcon(":/icons/document-open.svg"),
translate("Arch", "Open reference"),
menu)
QtCore.QObject.connect(actionOnOpen,
QtCore.SIGNAL("triggered()"),
self.onOpen)
actionOnOpen = QtGui.QAction(
QtGui.QIcon(":/icons/document-open.svg"), translate("Arch", "Open reference"), menu
)
QtCore.QObject.connect(actionOnOpen, QtCore.SIGNAL("triggered()"), self.onOpen)
menu.addAction(actionOnOpen)
def edit(self):
FreeCADGui.ActiveDocument.setEdit(self.Object, 0)
def onReload(self):
"reloads the reference object"
if hasattr(self,"Object") and self.Object:
if hasattr(self, "Object") and self.Object:
self.Object.Proxy.reload = True
self.Object.touch()
FreeCAD.ActiveDocument.recompute()
def onOpen(self):
"opens the reference file"
if hasattr(self,"Object") and self.Object:
if hasattr(self, "Object") and self.Object:
if self.Object.File:
FreeCAD.openDocument(self.Object.File)
def loadInventor(self, obj):
"loads an openinventor file and replace the root node of this object"
filename = obj.Proxy.getFile(obj)
@@ -783,20 +740,21 @@ class ViewProviderArchReference:
# check inventor contents
ivstring = self.getInventorString(obj)
if not ivstring:
t = translate("Arch","Unable to get lightWeight node for object referenced in")
FreeCAD.Console.PrintWarning(t+" "+obj.Label+"\n")
t = translate("Arch", "Unable to get lightWeight node for object referenced in")
FreeCAD.Console.PrintWarning(t + " " + obj.Label + "\n")
return
from pivy import coin
inputnode = coin.SoInput()
inputnode.setBuffer(ivstring)
lwnode = coin.SoDB.readAll(inputnode)
if not isinstance(lwnode,coin.SoSeparator):
t = translate("Arch","Invalid lightWeight node for object referenced in")
FreeCAD.Console.PrintError(t+" "+obj.Label+"\n")
if not isinstance(lwnode, coin.SoSeparator):
t = translate("Arch", "Invalid lightWeight node for object referenced in")
FreeCAD.Console.PrintError(t + " " + obj.Label + "\n")
return
if lwnode.getNumChildren() < 2:
t = translate("Arch","Invalid lightWeight node for object referenced in")
FreeCAD.Console.PrintError(t+" "+obj.Label+"\n")
t = translate("Arch", "Invalid lightWeight node for object referenced in")
FreeCAD.Console.PrintError(t + " " + obj.Label + "\n")
return
flatlines = lwnode
shaded = lwnode.getChild(0)
@@ -805,11 +763,15 @@ class ViewProviderArchReference:
# check node contents
rootnode = obj.ViewObject.RootNode
if rootnode.getNumChildren() < 3:
FreeCAD.Console.PrintError(translate("Arch","Invalid root node in")+" "+obj.Label+"\n")
FreeCAD.Console.PrintError(
translate("Arch", "Invalid root node in") + " " + obj.Label + "\n"
)
return
switch = rootnode.getChild(2)
if switch.getNumChildren() != 4:
FreeCAD.Console.PrintError(translate("Arch","Invalid root node in")+" "+obj.Label+"\n")
FreeCAD.Console.PrintError(
translate("Arch", "Invalid root node in") + " " + obj.Label + "\n"
)
return
# keep a copy of the original nodes
@@ -818,45 +780,45 @@ class ViewProviderArchReference:
self.orig_wireframe = switch.getChild(2).copy()
# replace root node of object
switch.replaceChild(0,flatlines)
switch.replaceChild(1,shaded)
switch.replaceChild(2,wireframe)
def unloadInventor(self,obj):
switch.replaceChild(0, flatlines)
switch.replaceChild(1, shaded)
switch.replaceChild(2, wireframe)
def unloadInventor(self, obj):
"restore original nodes"
if (not hasattr(self,"orig_flatlines")) or (not self.orig_flatlines):
if (not hasattr(self, "orig_flatlines")) or (not self.orig_flatlines):
return
if (not hasattr(self,"orig_shaded")) or (not self.orig_shaded):
if (not hasattr(self, "orig_shaded")) or (not self.orig_shaded):
return
if (not hasattr(self,"orig_wireframe")) or (not self.orig_wireframe):
if (not hasattr(self, "orig_wireframe")) or (not self.orig_wireframe):
return
# check node contents
rootnode = obj.ViewObject.RootNode
if rootnode.getNumChildren() < 3:
FreeCAD.Console.PrintError(translate("Arch","Invalid root node in")+" "+obj.Label+"\n")
FreeCAD.Console.PrintError(
translate("Arch", "Invalid root node in") + " " + obj.Label + "\n"
)
return
switch = rootnode.getChild(2)
if switch.getNumChildren() != 4:
FreeCAD.Console.PrintError(translate("Arch","Invalid root node in")+" "+obj.Label+"\n")
FreeCAD.Console.PrintError(
translate("Arch", "Invalid root node in") + " " + obj.Label + "\n"
)
return
# replace root node of object
switch.replaceChild(0,self.orig_flatlines)
switch.replaceChild(1,self.orig_shaded)
switch.replaceChild(2,self.orig_wireframe)
switch.replaceChild(0, self.orig_flatlines)
switch.replaceChild(1, self.orig_shaded)
switch.replaceChild(2, self.orig_wireframe)
# discard old content
self.orig_flatlines = None
self.orig_shaded = None
self.orig_wireframe = None
def getInventorString(self,obj):
def getInventorString(self, obj):
"locates and loads an iv file saved together with an object, if existing"
filename = obj.Proxy.getFile(obj)
@@ -876,11 +838,11 @@ class ViewProviderArchReference:
line = line.decode("utf8")
if ("<Object name=" in line) and (part in line):
writemode1 = True
elif writemode1 and ("<Property name=\"SavedInventor\"" in line):
elif writemode1 and ('<Property name="SavedInventor"' in line):
writemode1 = False
writemode2 = True
elif writemode2 and ("<FileIncluded file=" in line):
n = re.findall(r'file=\"(.*?)\"',line)
n = re.findall(r"file=\"(.*?)\"", line)
if n:
ivfile = n[0]
break
@@ -892,20 +854,18 @@ class ViewProviderArchReference:
buf = f.read()
buf = buf.decode("utf8")
f.close()
buf = buf.replace("lineWidth 2","lineWidth "+str(int(obj.ViewObject.LineWidth)))
buf = buf.replace("lineWidth 2", "lineWidth " + str(int(obj.ViewObject.LineWidth)))
return buf
def setIFCNode(self, obj, filename):
"""Sets the coin node of this object from an IFC file"""
try:
from nativeifc import ifc_tools
from nativeifc import ifc_generator
except:
t = translate("Arch","NativeIFC not available - unable to process IFC files")
FreeCAD.Console.PrintError(t+"\n")
t = translate("Arch", "NativeIFC not available - unable to process IFC files")
FreeCAD.Console.PrintError(t + "\n")
return
ifcfile = obj.Proxy.getIfcFile(filename)
elements = obj.Proxy.getIFCElements(obj, ifcfile)
@@ -922,47 +882,45 @@ class ViewProviderArchReference:
class ArchReferenceTaskPanel:
"""The editmode TaskPanel for Reference objects"""
'''The editmode TaskPanel for Reference objects'''
def __init__(self,obj):
def __init__(self, obj):
self.obj = obj
self.filename = None
self.form = QtGui.QWidget()
self.form.setWindowTitle(translate("Arch","External reference"))
self.form.setWindowTitle(translate("Arch", "External reference"))
layout = QtGui.QVBoxLayout(self.form)
label1 = QtGui.QLabel(translate("Arch","External file")+":")
label1 = QtGui.QLabel(translate("Arch", "External file") + ":")
layout.addWidget(label1)
self.fileButton = QtGui.QPushButton(self.form)
self.openButton = QtGui.QPushButton(self.form)
self.openButton.setText(translate("Arch","Open"))
self.openButton.setText(translate("Arch", "Open"))
if not self.obj.File:
self.openButton.setEnabled(False)
l2 = QtGui.QHBoxLayout()
layout.addLayout(l2)
l2.addWidget(self.fileButton)
l2.addWidget(self.openButton)
label2 = QtGui.QLabel(translate("Arch","Part to use:"))
label2 = QtGui.QLabel(translate("Arch", "Part to use:"))
layout.addWidget(label2)
if self.obj.File:
self.fileButton.setText(os.path.basename(self.obj.File))
else:
self.fileButton.setText(translate("Arch","Choose File"))
self.fileButton.setText(translate("Arch", "Choose File"))
self.partCombo = QtGui.QComboBox(self.form)
self.partCombo.setEnabled(False)
layout.addWidget(self.partCombo)
if hasattr(self.obj.Proxy,"parts"):
if hasattr(self.obj.Proxy, "parts"):
parts = self.obj.Proxy.parts
else:
parts = self.obj.Proxy.getPartsList(self.obj)
if parts:
self.partCombo.setEnabled(True)
sortedkeys = sorted(parts)
self.partCombo.addItem(translate("Arch","None (Use whole object)"),"")
self.partCombo.addItem(translate("Arch", "None (Use whole object)"), "")
for k in sortedkeys:
self.partCombo.addItem(parts[k][0],k)
self.partCombo.addItem(parts[k][0], k)
if self.obj.Part:
if self.obj.Part in sortedkeys:
self.partCombo.setCurrentIndex(sortedkeys.index(self.obj.Part) + 1)
@@ -986,7 +944,7 @@ class ArchReferenceTaskPanel:
self.obj.Part = self.partCombo.itemData(i)
else:
self.obj.Part = ""
QtCore.QTimer.singleShot(0,FreeCAD.ActiveDocument.recompute)
QtCore.QTimer.singleShot(0, FreeCAD.ActiveDocument.recompute)
if self.filename and self.obj.Label == "External Reference":
self.obj.Label = os.path.basename(self.filename)
FreeCADGui.ActiveDocument.resetEdit()
@@ -1011,22 +969,21 @@ class ArchReferenceTaskPanel:
pass
else:
filters += " *.ifc"
filters = translate("Arch","Reference files")+" ("+filters+")"
f = QtGui.QFileDialog.getOpenFileName(self.form,
translate("Arch","Choose reference file"),
loc,
filters)
filters = translate("Arch", "Reference files") + " (" + filters + ")"
f = QtGui.QFileDialog.getOpenFileName(
self.form, translate("Arch", "Choose reference file"), loc, filters
)
if f:
self.filename = f[0]
self.fileButton.setText(os.path.basename(self.filename))
parts = self.obj.Proxy.getPartsList(self.obj,self.filename)
parts = self.obj.Proxy.getPartsList(self.obj, self.filename)
self.partCombo.clear()
if parts:
self.partCombo.setEnabled(True)
sortedkeys = sorted(parts)
self.partCombo.addItem(translate("Arch","None (Use whole object)"),"")
self.partCombo.addItem(translate("Arch", "None (Use whole object)"), "")
for k in sortedkeys:
self.partCombo.addItem(parts[k][0],k)
self.partCombo.addItem(parts[k][0], k)
if self.obj.Part:
if self.obj.Part in sortedkeys:
self.partCombo.setCurrentIndex(sortedkeys.index(self.obj.Part) + 1)