BIM: Quantities support for nativeIFC objects (#18689)

* BIM: Quantities support for nativeIFC objects

* BIM: Added nativeIFC support for schedules
This commit is contained in:
Yorik van Havre
2025-01-06 17:55:50 +01:00
committed by GitHub
parent fccb75e364
commit f7a39fc313
19 changed files with 1407 additions and 80221 deletions

View File

@@ -696,6 +696,20 @@ def makeRoof(baseobj=None,
return obj
def makeSchedule():
"""makeSchedule(): Creates a schedule object in the active document"""
import ArchSchedule
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Schedule")
obj.Label = translate("Arch","Schedule")
ArchSchedule._ArchSchedule(obj)
if FreeCAD.GuiUp:
ArchSchedule._ViewProviderArchSchedule(obj.ViewObject)
if hasattr(obj,"CreateSpreadsheet") and obj.CreateSpreadsheet:
obj.Proxy.getSpreadSheet(obj, force=True)
return obj
def makeSectionPlane(objectslist=None,name=None):
"""makeSectionPlane([objectslist],[name]) : Creates a Section plane objects including the

View File

@@ -746,7 +746,7 @@ def getHost(obj,strict=True):
return par
return None
def pruneIncluded(objectslist,strict=False):
def pruneIncluded(objectslist,strict=False,silent=False):
"""pruneIncluded(objectslist,[strict]): removes from a list of Arch objects, those that are subcomponents of
another shape-based object, leaving only the top-level shapes. If strict is True, the object
is removed only if the parent is also part of the selection."""
@@ -793,7 +793,7 @@ def pruneIncluded(objectslist,strict=False):
toplevel = True
if toplevel:
newlist.append(obj)
else:
elif not silent:
FreeCAD.Console.PrintWarning("pruning "+obj.Label+"\n")
return newlist

View File

@@ -49,7 +49,8 @@ __author__ = "Yorik van Havre"
__url__ = "https://www.freecad.org"
verbose = True # change this for silent recomputes
PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM")
VERBOSE = True # change this for silent recomputes
@@ -94,28 +95,33 @@ class _ArchSchedule:
self.setSchedulePropertySpreadsheet(sp, obj)
obj.removeProperty("Result")
from draftutils.messages import _wrn
if "Description" in obj.PropertiesList:
if obj.getTypeOfProperty("Description") == "App::PropertyStringList":
obj.Operation = obj.Description
obj.removeProperty("Description")
_wrn("v0.21, " + sp.Label + ", " + translate("Arch", "renamed property 'Description' to 'Operation'"))
_wrn("v0.21, " + obj.Label + ", " + translate("Arch", "removed property 'Result', and added property 'AutoUpdate'"))
if sp is not None:
_wrn("v0.21, " + sp.Label + ", " + translate("Arch", "added property 'Schedule'"))
def setProperties(self,obj):
if not "Description" in obj.PropertiesList:
obj.addProperty("App::PropertyStringList","Description", "Arch",QT_TRANSLATE_NOOP("App::Property","The description column"))
if not "Operation" in obj.PropertiesList:
obj.addProperty("App::PropertyStringList","Operation", "Schedule",QT_TRANSLATE_NOOP("App::Property","The operation column"))
if not "Value" in obj.PropertiesList:
obj.addProperty("App::PropertyStringList","Value", "Arch",QT_TRANSLATE_NOOP("App::Property","The values column"))
obj.addProperty("App::PropertyStringList","Value", "Schedule",QT_TRANSLATE_NOOP("App::Property","The values column"))
if not "Unit" in obj.PropertiesList:
obj.addProperty("App::PropertyStringList","Unit", "Arch",QT_TRANSLATE_NOOP("App::Property","The units column"))
obj.addProperty("App::PropertyStringList","Unit", "Schedule",QT_TRANSLATE_NOOP("App::Property","The units column"))
if not "Objects" in obj.PropertiesList:
obj.addProperty("App::PropertyStringList","Objects", "Arch",QT_TRANSLATE_NOOP("App::Property","The objects column"))
obj.addProperty("App::PropertyStringList","Objects", "Schedule",QT_TRANSLATE_NOOP("App::Property","The objects column"))
if not "Filter" in obj.PropertiesList:
obj.addProperty("App::PropertyStringList","Filter", "Arch",QT_TRANSLATE_NOOP("App::Property","The filter column"))
obj.addProperty("App::PropertyStringList","Filter", "Schedule",QT_TRANSLATE_NOOP("App::Property","The filter column"))
if not "CreateSpreadsheet" in obj.PropertiesList:
obj.addProperty("App::PropertyBool", "CreateSpreadsheet", "Arch",QT_TRANSLATE_NOOP("App::Property","If True, a spreadsheet containing the results is recreated when needed"))
obj.addProperty("App::PropertyBool", "CreateSpreadsheet", "Schedule",QT_TRANSLATE_NOOP("App::Property","If True, a spreadsheet containing the results is recreated when needed"))
if not "DetailedResults" in obj.PropertiesList:
obj.addProperty("App::PropertyBool", "DetailedResults", "Arch",QT_TRANSLATE_NOOP("App::Property","If True, additional lines with each individual object are added to the results"))
obj.addProperty("App::PropertyBool", "DetailedResults", "Schedule",QT_TRANSLATE_NOOP("App::Property","If True, additional lines with each individual object are added to the results"))
if not "AutoUpdate" in obj.PropertiesList:
obj.addProperty("App::PropertyBool", "AutoUpdate", "Arch",QT_TRANSLATE_NOOP("App::Property","If True, the schedule and the associated spreadsheet are updated whenever the document is recomputed"))
obj.addProperty("App::PropertyBool", "AutoUpdate", "Schedule",QT_TRANSLATE_NOOP("App::Property","If True, the schedule and the associated spreadsheet are updated whenever the document is recomputed"))
obj.AutoUpdate = True
# To add the doc observer:
@@ -191,7 +197,7 @@ class _ArchSchedule:
# clearAll removes the custom property, we need to re-add it:
self.setSchedulePropertySpreadsheet(sp, obj)
# set headers
sp.set("A1","Description")
sp.set("A1","Operation")
sp.set("B1","Value")
sp.set("C1","Unit")
sp.setStyle('A1:C1', 'bold', 'add')
@@ -209,26 +215,26 @@ class _ArchSchedule:
# verify the data
if not obj.Description:
if not obj.Operation:
# empty description column
return
for p in [obj.Value,obj.Unit,obj.Objects,obj.Filter]:
# different number of items in each column
if len(obj.Description) != len(p):
if len(obj.Operation) != len(p):
return
self.data = {} # store all results in self.data, so it lives even without spreadsheet
li = 1 # row index - starts at 2 to leave 2 blank rows for the title
self.li = 1 # row index - starts at 2 to leave 2 blank rows for the title
for i in range(len(obj.Description)):
li += 1
if not obj.Description[i]:
for i in range(len(obj.Operation)):
self.li += 1
if not obj.Operation[i]:
# blank line
continue
# write description
self.data["A"+str(li)] = obj.Description[i]
if verbose:
l= "OPERATION: "+obj.Description[i]
self.data["A"+str(self.li)] = obj.Operation[i]
if VERBOSE:
l= "OPERATION: "+obj.Operation[i]
print("")
print (l)
print (len(l)*"=")
@@ -237,6 +243,10 @@ class _ArchSchedule:
objs = obj.Objects[i]
val = obj.Value[i]
unit = obj.Unit[i]
details = obj.DetailedResults
ifcfile = None
elts = None
if val:
import Draft,Arch
if objs:
@@ -244,143 +254,316 @@ class _ArchSchedule:
objs = [FreeCAD.ActiveDocument.getObject(o) for o in objs]
objs = [o for o in objs if o is not None]
else:
if hasattr(getattr(FreeCAD.ActiveDocument, "Proxy", None), "ifcfile"):
ifcfile = FreeCAD.ActiveDocument.Proxy.ifcfile
objs = FreeCAD.ActiveDocument.Objects
if len(objs) == 1:
if hasattr(objs[0], "StepId"):
from nativeifc import ifc_tools
ifcfile = ifc_tools.get_ifcfile(objs[0])
# remove object itself if the object is a group
if objs[0].isDerivedFrom("App::DocumentObjectGroup"):
objs = objs[0].Group
objs = Draft.get_group_contents(objs)
objs = Arch.pruneIncluded(objs,strict=True)
objs = Arch.pruneIncluded(objs,strict=True,silent=True)
# Remove all schedules and spreadsheets:
objs = [o for o in objs if Draft.get_type(o) not in ["Schedule", "Spreadsheet::Sheet"]]
# filter elements
if obj.Filter[i]:
# apply filters
nobjs = []
for o in objs:
props = [p.upper() for p in o.PropertiesList]
ok = True
for f in obj.Filter[i].split(";"):
args = [a.strip() for a in f.strip().split(":")]
if args[0][0] == "!":
inv = True
prop = args[0][1:].upper()
else:
inv = False
prop = args[0].upper()
fval = args[1].upper()
if prop == "TYPE":
prop = "IFCTYPE"
if inv:
if prop in props:
csprop = o.PropertiesList[props.index(prop)]
if fval in getattr(o,csprop).upper():
ok = False
else:
if not (prop in props):
ok = False
else:
csprop = o.PropertiesList[props.index(prop)]
if not (fval in getattr(o,csprop).upper()):
ok = False
if ok:
nobjs.append(o)
objs = nobjs
if ifcfile:
elts = self.get_ifc_elements(ifcfile, obj.Filter[i])
else:
objs = self.apply_filter(objs, obj.Filter[i])
# perform operation: count or retrieve property
if val.upper() == "COUNT":
val = len(objs)
if verbose:
print (val, ",".join([o.Label for o in objs]))
self.data["B"+str(li)] = str(val)
if obj.DetailedResults:
# additional blank line...
li += 1
self.data["A"+str(li)] = " "
else:
vals = val.split(".")
if vals[0][0].islower():
# old-style: first member is not a property
vals = vals[1:]
sumval = 0
if ifcfile:
if elts:
self.update_from_elts(elts, val, unit, details)
elif objs:
self.update_from_objs(objs, val, unit, details)
# get unit
tp = None
unit = None
q = None
if obj.Unit[i]:
unit = obj.Unit[i]
unit = unit.replace("^","") # get rid of existing power symbol
unit = unit.replace("2","^2")
unit = unit.replace("3","^3")
unit = unit.replace("²","^2")
unit = unit.replace("³","^3")
if "2" in unit:
tp = FreeCAD.Units.Area
elif "3" in unit:
tp = FreeCAD.Units.Volume
elif "deg" in unit:
tp = FreeCAD.Units.Angle
else:
tp = FreeCAD.Units.Length
# format value
dv = params.get_param("Decimals",path="Units")
fs = "{:."+str(dv)+"f}" # format string
for o in objs:
if verbose:
l = o.Name+" ("+o.Label+"):"
print (l+(40-len(l))*" ",end="")
try:
d = o
for v in vals:
d = getattr(d,v)
if hasattr(d,"Value"):
d = d.Value
except Exception:
FreeCAD.Console.PrintWarning(translate("Arch","Unable to retrieve value from object")+": "+o.Name+"."+".".join(vals)+"\n")
else:
if verbose:
if tp and unit:
v = fs.format(FreeCAD.Units.Quantity(d,tp).getValueAs(unit).Value)
print(v,unit)
else:
print(fs.format(d))
if obj.DetailedResults:
li += 1
self.data["A"+str(li)] = o.Name+" ("+o.Label+")"
if tp and unit:
q = FreeCAD.Units.Quantity(d,tp)
self.data["B"+str(li)] = str(q.getValueAs(unit).Value)
self.data["C"+str(li)] = unit
else:
self.data["B"+str(li)] = str(d)
if not sumval:
sumval = d
else:
sumval += d
val = sumval
if tp:
q = FreeCAD.Units.Quantity(val,tp)
# write data
if obj.DetailedResults:
li += 1
self.data["A"+str(li)] = "TOTAL"
if q and unit:
self.data["B"+str(li)] = str(q.getValueAs(unit).Value)
self.data["C"+str(li)] = unit
else:
self.data["B"+str(li)] = str(val)
if verbose:
if tp and unit:
v = fs.format(FreeCAD.Units.Quantity(val,tp).getValueAs(unit).Value)
print("TOTAL:"+34*" "+v+" "+unit)
else:
v = fs.format(val)
print("TOTAL:"+34*" "+v)
self.setSpreadsheetData(obj)
self.save_ifc_props(obj)
def apply_filter(self, objs, filters):
"""Applies the given filters to the given list of objects"""
nobjs = []
for o in objs:
props = [p.upper() for p in o.PropertiesList]
ok = True
for f in filters.split(";"):
args = [a.strip() for a in f.strip().split(":")]
if args[0][0] == "!":
inv = True
prop = args[0][1:].upper()
else:
inv = False
prop = args[0].upper()
fval = args[1].upper()
if prop == "TYPE":
prop = "IFCTYPE"
if inv:
if prop in props:
csprop = o.PropertiesList[props.index(prop)]
if fval in getattr(o,csprop).upper():
ok = False
else:
if not (prop in props):
ok = False
else:
csprop = o.PropertiesList[props.index(prop)]
if not (fval in getattr(o,csprop).upper()):
ok = False
if ok:
nobjs.append(o)
return nobjs
def get_ifc_elements(self, ifcfile, filters):
"""Retrieves IFC elements corresponding to the given filters"""
elts = []
for el in ifcfile.by_type("IfcProduct"):
ok = True
for f in filters.split(";"):
args = [a.strip() for a in f.strip().split(":")]
if args[0][0] == "!":
inv = True
prop = args[0][1:]
else:
inv = False
prop = args[0]
fval = args[1]
if prop.upper() in ["CLASS", "IFCCLASS", "IFCTYPE"]:
prop = "is_a"
if inv:
if prop == "is_a":
if not fval.upper().startswith("IFC"):
fval = "Ifc" + fval
fval = fval.replace(" ","")
if el.is_a(fval):
ok = False
else:
if prop in dir(el):
rval = getattr(el, prop)
if hasattr(rval, "id"):
if fval.startswith("#"):
fval = int(fval[1:])
if rval == fval:
ok = False
else:
if prop == "is_a":
if not fval.upper().startswith("IFC"):
fval = "Ifc" + fval
fval = fval.replace(" ","")
if not el.is_a(fval):
ok = False
else:
if prop in dir(el):
rval = getattr(el, prop)
if hasattr(rval, "id"):
if fval.startswith("#"):
fval = int(fval[1:])
if rval != fval:
ok = False
else:
ok = False
if ok:
elts.append(el)
return elts
def update_from_objs(self, objs, val, unit, details):
"""Updates the spreadsheet data from FreeCAD objects"""
if val.upper() == "COUNT":
val = len(objs)
if VERBOSE:
print (val, ",".join([o.Label for o in objs]))
self.data["B"+str(self.li)] = str(val)
if details:
# additional blank line...
self.li += 1
self.data["A"+str(self.li)] = " "
else:
vals = val.split(".")
if vals[0][0].islower():
# old-style: first member is not a property
vals = vals[1:]
sumval = 0
# get unit
tp = None
unit = None
q = None
if unit:
unit = unit.replace("^","") # get rid of existing power symbol
unit = unit.replace("2","^2")
unit = unit.replace("3","^3")
unit = unit.replace("²","^2")
unit = unit.replace("³","^3")
if "2" in unit:
tp = FreeCAD.Units.Area
elif "3" in unit:
tp = FreeCAD.Units.Volume
elif "deg" in unit:
tp = FreeCAD.Units.Angle
else:
tp = FreeCAD.Units.Length
# format value
dv = params.get_param("Decimals",path="Units")
fs = "{:."+str(dv)+"f}" # format string
for o in objs:
if VERBOSE:
l = o.Name+" ("+o.Label+"):"
print (l+(40-len(l))*" ",end="")
try:
d = o
for v in vals:
d = getattr(d,v)
if hasattr(d,"Value"):
d = d.Value
except Exception:
t = translate("Arch","Unable to retrieve value from object")
FreeCAD.Console.PrintWarning(t+": "+o.Name+"."+".".join(vals)+"\n")
else:
if VERBOSE:
if tp and unit:
v = fs.format(FreeCAD.Units.Quantity(d,tp).getValueAs(unit).Value)
print(v,unit)
elif isinstance(d, str):
if d.replace('.', '', 1).isdigit():
print(fs.format(d))
else:
print(d)
else:
print(fs.format(d))
if details:
self.li += 1
self.data["A"+str(self.li)] = o.Name+" ("+o.Label+")"
if tp and unit:
q = FreeCAD.Units.Quantity(d,tp)
self.data["B"+str(self.li)] = str(q.getValueAs(unit).Value)
self.data["C"+str(self.li)] = unit
else:
self.data["B"+str(self.li)] = str(d)
if sumval:
sumval += d
else:
sumval = d
val = sumval
if tp:
q = FreeCAD.Units.Quantity(val,tp)
# write data
if details:
self.li += 1
self.data["A"+str(self.li)] = "TOTAL"
if q and unit:
self.data["B"+str(self.li)] = str(q.getValueAs(unit).Value)
self.data["C"+str(self.li)] = unit
else:
self.data["B"+str(self.li)] = str(val)
if VERBOSE:
if tp and unit:
v = fs.format(FreeCAD.Units.Quantity(val,tp).getValueAs(unit).Value)
print("TOTAL:"+34*" "+v+" "+unit)
elif isinstance(val, str):
if val.replace('.', '', 1).isdigit():
v = fs.format(val)
print("TOTAL:"+34*" "+v)
else:
print("TOTAL:"+34*" "+val)
else:
v = fs.format(val)
print("TOTAL:"+34*" "+v)
def update_from_elts(self, elts, val, unit, details):
"""Updates the spreadsheet data from IFC elements"""
if val.upper() == "COUNT":
val = len(elts)
if VERBOSE:
print ("COUNT:", val, "(", ",".join(["#"+str(e.id()) for e in elts]), ")")
self.data["B"+str(self.li)] = str(val)
if details:
# additional blank line...
self.li += 1
self.data["A"+str(self.li)] = " "
else:
total = 0
for el in elts:
if val in dir(el):
elval = getattr(el, val, "")
if isinstance(elval, tuple):
if len(elval) == 1:
elval = elval[0]
elif len(elval) == 0:
elval = ""
if hasattr(elval, "is_a") and elval.is_a("IfcRelationship"):
for att in dir(elval):
if att.startswith("Relating"):
targ = getattr(elval, att)
if targ != el:
elval = targ
break
elif att.startswith("Related"):
if not elval in getattr(elval, att):
elval = str(getattr(elval, att))
break
if details:
self.li += 1
name = el.Name if el.Name else ""
self.data["A"+str(self.li)] = "#" + str(el.id()) + name
self.data["B"+str(self.li)] = str(elval)
if VERBOSE:
print("#"+str(el.id())+"."+val+" = "+str(elval))
if isinstance(elval, str) and elval.replace('.', '', 1).isdigit():
total += float(elval)
elif isinstance(elval, (int, float)):
total += elval
if total:
if details:
self.li += 1
self.data["A"+str(self.li)] = "TOTAL"
self.data["B"+str(self.li)] = str(total)
if VERBOSE:
print("TOTAL:",str(total))
def create_ifc(self, obj, ifcfile, export=False):
"""Creates an IFC element for this object"""
from nativeifc import ifc_tools # lazy loading
proj = ifcfile.by_type("IfcProject")[0]
elt = ifc_tools.api_run("root.create_entity", ifcfile, ifc_class="IfcControl")
ifc_tools.set_attribute(ifcfile, elt, "Name", obj.Label)
ifc_tools.api_run("project.assign_declaration", ifcfile, definitions=[elt], relating_context=proj)
if not export:
ifc_tools.add_properties(obj, ifcfile, elt)
return elt
def save_ifc_props(self, obj, ifcfile=None, elt=None):
"""Saves the object data to IFC"""
from nativeifc import ifc_psets # lazy loading
ifc_psets.edit_pset(obj, "Operation", "::".join(obj.Operation), ifcfile=ifcfile, element=elt)
ifc_psets.edit_pset(obj, "Value", "::".join(obj.Value), ifcfile=ifcfile, element=elt)
ifc_psets.edit_pset(obj, "Unit", "::".join(obj.Unit), ifcfile=ifcfile, element=elt)
ifc_psets.edit_pset(obj, "Objects", "::".join(obj.Objects), ifcfile=ifcfile, element=elt)
ifc_psets.edit_pset(obj, "Filter", "::".join(obj.Filter), ifcfile=ifcfile, element=elt)
def export_ifc(self, obj, ifcfile):
"""Exports the object to IFC (does not modify the FreeCAD object)."""
elt = self.create_ifc(obj, ifcfile, export=True)
self.save_ifc_props(obj, ifcfile, elt)
return elt
def dumps(self):
@@ -417,8 +600,16 @@ class _ViewProviderArchSchedule:
return None
self.taskd = ArchScheduleTaskPanel(vobj.Object)
if not self.taskd.form.isVisible():
from PySide import QtCore
QtCore.QTimer.singleShot(100, self.showEditor)
return True
def showEditor(self):
if hasattr(self, "taskd"):
self.taskd.form.show()
def unsetEdit(self, vobj, mode):
if mode != 0:
return None
@@ -507,30 +698,37 @@ class ArchScheduleTaskPanel:
h = params.get_param_arch("ScheduleDialogHeight")
self.form.resize(w,h)
# restore default states
self.form.checkAutoUpdate.setChecked(PARAMS.GetBool("ScheduleAutoUpdate", False))
# set delegate - Not using custom delegates for now...
#self.form.list.setItemDelegate(ScheduleDelegate())
#self.form.list.setEditTriggers(QtGui.QAbstractItemView.DoubleClicked)
# connect slots
QtCore.QObject.connect(self.form.buttonAdd, QtCore.SIGNAL("clicked()"), self.add)
QtCore.QObject.connect(self.form.buttonDel, QtCore.SIGNAL("clicked()"), self.remove)
QtCore.QObject.connect(self.form.buttonClear, QtCore.SIGNAL("clicked()"), self.clear)
QtCore.QObject.connect(self.form.buttonImport, QtCore.SIGNAL("clicked()"), self.importCSV)
QtCore.QObject.connect(self.form.buttonExport, QtCore.SIGNAL("clicked()"), self.export)
QtCore.QObject.connect(self.form.buttonSelect, QtCore.SIGNAL("clicked()"), self.select)
QtCore.QObject.connect(self.form.buttonBox, QtCore.SIGNAL("accepted()"), self.accept)
QtCore.QObject.connect(self.form.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
QtCore.QObject.connect(self.form, QtCore.SIGNAL("rejected()"), self.reject)
self.form.buttonAdd.clicked.connect(self.add)
self.form.buttonDel.clicked.connect(self.remove)
self.form.buttonClear.clicked.connect(self.clear)
self.form.buttonImport.clicked.connect(self.importCSV)
self.form.buttonExport.clicked.connect(self.export)
self.form.buttonSelect.clicked.connect(self.select)
self.form.buttonBox.accepted.connect(self.accept)
self.form.buttonBox.rejected.connect(self.reject)
self.form.rejected.connect(self.reject)
self.form.list.clearContents()
if self.obj:
for p in [obj.Value,obj.Unit,obj.Objects,obj.Filter]:
if len(obj.Description) != len(p):
return
self.form.list.setRowCount(len(obj.Description))
#for p in [obj.Value,obj.Unit,obj.Objects,obj.Filter]:
# if len(obj.Operation) != len(p):
# return
self.form.list.setRowCount(len(obj.Operation))
for i in range(5):
for j in range(len(obj.Description)):
item = QtGui.QTableWidgetItem([obj.Description,obj.Value,obj.Unit,obj.Objects,obj.Filter][i][j])
for j in range(len(obj.Operation)):
try:
text = [obj.Operation,obj.Value,obj.Unit,obj.Objects,obj.Filter][i][j]
except:
text = ""
item = QtGui.QTableWidgetItem(text)
self.form.list.setItem(j,i,item)
self.form.lineEditName.setText(self.obj.Label)
self.form.checkSpreadsheet.setChecked(self.obj.CreateSpreadsheet)
@@ -646,7 +844,7 @@ class ArchScheduleTaskPanel:
import csv
with open(filename, 'w') as csvfile:
csvfile = csv.writer(csvfile,delimiter=delimiter)
csvfile.writerow([translate("Arch","Description"),translate("Arch","Value"),translate("Arch","Unit")])
csvfile.writerow([translate("Arch","Operation"),translate("Arch","Value"),translate("Arch","Unit")])
if self.obj.DetailedResults:
csvfile.writerow(["","",""])
for i in self.getRows():
@@ -664,7 +862,7 @@ class ArchScheduleTaskPanel:
"""Exports the results as a Markdown file"""
with open(filename, 'w') as mdfile:
mdfile.write("| "+translate("Arch","Description")+" | "+translate("Arch","Value")+" | "+translate("Arch","Unit")+" |\n")
mdfile.write("| "+translate("Arch","Operation")+" | "+translate("Arch","Value")+" | "+translate("Arch","Unit")+" |\n")
mdfile.write("| --- | --- | --- |\n")
if self.obj.DetailedResults:
mdfile.write("| | | |\n")
@@ -704,6 +902,9 @@ class ArchScheduleTaskPanel:
params.set_param_arch("ScheduleDialogWidth",self.form.width())
params.set_param_arch("ScheduleDialogHeight",self.form.height())
# store default states
PARAMS.SetBool("ScheduleAutoUpdate", self.form.checkAutoUpdate.isChecked())
# commit values
self.writeValues()
self.form.hide()
@@ -723,13 +924,8 @@ class ArchScheduleTaskPanel:
"""commits values and recalculate"""
if not self.obj:
self.obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Schedule")
self.obj.Label = translate("Arch","Schedule")
_ArchSchedule(self.obj)
if FreeCAD.GuiUp:
_ViewProviderArchSchedule(self.obj.ViewObject)
if hasattr(self.obj,"CreateSpreadsheet") and self.obj.CreateSpreadsheet:
self.obj.Proxy.getSpreadSheet(self.obj, force=True)
import Arch
self.obj = Arch.makeSchedule()
lists = [ [], [], [], [], [] ]
for i in range(self.form.list.rowCount()):
for j in range(5):
@@ -739,7 +935,7 @@ class ArchScheduleTaskPanel:
else:
lists[j].append("")
FreeCAD.ActiveDocument.openTransaction("Edited Schedule")
self.obj.Description = lists[0]
self.obj.Operation = lists[0]
self.obj.Value = lists[1]
self.obj.Unit = lists[2]
self.obj.Objects = lists[3]

View File

@@ -78,6 +78,7 @@ SET(Dice3DS_SRCS
SET(Arch_presets
Presets/profiles.csv
Presets/pset_definitions.csv
Presets/qto_definitions.csv
Presets/ifc_products_IFC2X3.json
Presets/ifc_products_IFC4.json
Presets/ifc_types_IFC2X3.json

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,115 @@
Qto_ActuatorBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_AirTerminalBaseQuantities;GrossWeight;IfcQuantityWeight;Perimeter;IfcQuantityLength;TotalSurfaceArea;IfcQuantityArea
Qto_AirTerminalBoxTypeBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_AirToAirHeatRecoveryBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_AlarmBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ArealStratumBaseQuantities;Area;IfcQuantityArea;Length;IfcQuantityLength;PlanLength;IfcQuantityLength
Qto_AudioVisualApplianceBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_BeamBaseQuantities;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_BodyGeometryValidation;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;SurfaceGenusBeforeFeatures;IfcQuantityCount;SurfaceGenusAfterFeatures;IfcQuantityCount
Qto_BoilerBaseQuantities;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight;TotalSurfaceArea;IfcQuantityArea
Qto_BuildingBaseQuantities;Height;IfcQuantityLength;EavesHeight;IfcQuantityLength;FootPrintArea;IfcQuantityArea;GrossFloorArea;IfcQuantityArea;NetFloorArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
Qto_BuildingElementProxyQuantities;NetSurfaceArea;IfcQuantityArea;NetVolume;IfcQuantityVolume
Qto_BuildingStoreyBaseQuantities;GrossHeight;IfcQuantityLength;NetHeight;IfcQuantityLength;GrossPerimeter;IfcQuantityLength;GrossFloorArea;IfcQuantityArea;NetFloorArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
Qto_BurnerBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_CableCarrierFittingBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_CableCarrierSegmentBaseQuantities;GrossWeight;IfcQuantityWeight;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea
Qto_CableFittingBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_CableSegmentBaseQuantities;GrossWeight;IfcQuantityWeight;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea
Qto_ChillerBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ChimneyBaseQuantities;Length;IfcQuantityLength
Qto_CoilBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ColumnBaseQuantities;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_CommunicationsApplianceBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_CompressorBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_CondenserBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ConduitSegmentBaseQuantities;InnerDiameter;IfcQuantityLength;OuterDiameter;IfcQuantityLength
Qto_ConstructionEquipmentResourceBaseQuantities;UsageTime;IfcQuantityTime;OperatingTime;IfcQuantityTime
Qto_ConstructionMaterialResourceBaseQuantities;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_ControllerBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_CooledBeamBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_CoolingTowerBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_CourseBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Thickness;IfcQuantityLength;Volume;IfcQuantityVolume;GrossVolume;IfcQuantityVolume;Weight;IfcQuantityWeight
Qto_CoveringBaseQuantities;Width;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea
Qto_CurtainWallQuantities;Length;IfcQuantityLength;Height;IfcQuantityLength;Width;IfcQuantityLength;GrossSideArea;IfcQuantityArea;NetSideArea;IfcQuantityArea
Qto_DamperBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_DistributionBoardBaseQuantities;GrossWeight;IfcQuantityWeight;NumberOfCircuits;IfcQuantityCount
Qto_DistributionChamberElementBaseQuantities;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;Depth;IfcQuantityLength
Qto_DoorBaseQuantities;Width;IfcQuantityLength;Height;IfcQuantityLength;Perimeter;IfcQuantityLength;Area;IfcQuantityArea
Qto_DuctFittingBaseQuantities;Length;IfcQuantityLength;GrossCrossSectionArea;IfcQuantityArea;NetCrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossWeight;IfcQuantityWeight
Qto_DuctSegmentBaseQuantities;Length;IfcQuantityLength;GrossCrossSectionArea;IfcQuantityArea;NetCrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossWeight;IfcQuantityWeight
Qto_DuctSilencerBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_EarthworksCutBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Depth;IfcQuantityLength;UndisturbedVolume;IfcQuantityVolume;LooseVolume;IfcQuantityVolume;Weight;IfcQuantityWeight
Qto_EarthworksFillBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Depth;IfcQuantityLength;CompactedVolume;IfcQuantityVolume;LooseVolume;IfcQuantityVolume
Qto_ElectricApplianceBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ElectricFlowStorageDeviceBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ElectricGeneratorBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ElectricMotorBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ElectricTimeControlBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_EvaporativeCoolerBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_EvaporatorBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_FacilityPartBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;Area;IfcQuantityArea;Volume;IfcQuantityVolume
Qto_FanBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_FilterBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_FireSuppressionTerminalBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_FlowInstrumentBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_FlowMeterBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_FootingBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_HeatExchangerBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_HumidifierBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ImpactProtectionDeviceBaseQuantities;Weight;IfcQuantityWeight
Qto_InterceptorBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_JunctionBoxBaseQuantities;GrossWeight;IfcQuantityWeight;NumberOfGangs;IfcQuantityCount;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength
Qto_KerbBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;Depth;IfcQuantityLength;Volume;IfcQuantityVolume;Weight;IfcQuantityWeight
Qto_LaborResourceBaseQuantities;StandardWork;IfcQuantityTime;OvertimeWork;IfcQuantityTime
Qto_LampBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_LightFixtureBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_LinearStratumBaseQuantities;Diameter;IfcQuantityLength;Length;IfcQuantityLength
Qto_MarineFacilityBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;Area;IfcQuantityArea;Volume;IfcQuantityVolume
Qto_MemberBaseQuantities;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_MotorConnectionBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_OpeningElementBaseQuantities;Width;IfcQuantityLength;Height;IfcQuantityLength;Depth;IfcQuantityLength;Area;IfcQuantityArea;Volume;IfcQuantityVolume
Qto_OutletBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_PavementBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Depth;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
Qto_PictorialSignQuantities;Area;IfcQuantityArea;SignArea;IfcQuantityArea
Qto_PileBaseQuantities;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_PipeFittingBaseQuantities;Length;IfcQuantityLength;GrossCrossSectionArea;IfcQuantityArea;NetCrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_PipeSegmentBaseQuantities;Length;IfcQuantityLength;GrossCrossSectionArea;IfcQuantityArea;NetCrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight;FootPrintArea;IfcQuantityArea
Qto_PlateBaseQuantities;Width;IfcQuantityLength;Perimeter;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_ProjectionElementBaseQuantities;Area;IfcQuantityArea;Volume;IfcQuantityVolume
Qto_ProtectiveDeviceBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ProtectiveDeviceTrippingUnitBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_PumpBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_RailBaseQuantities;Length;IfcQuantityLength;Volume;IfcQuantityVolume;Weight;IfcQuantityWeight
Qto_RailingBaseQuantities;Length;IfcQuantityLength
Qto_RampFlightBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
Qto_ReinforcedSoilBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Depth;IfcQuantityLength;Area;IfcQuantityArea;Volume;IfcQuantityVolume
Qto_ReinforcingElementBaseQuantities;Count;IfcQuantityCount;Length;IfcQuantityLength;Weight;IfcQuantityWeight
Qto_RoofBaseQuantities;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;ProjectedArea;IfcQuantityArea
Qto_SanitaryTerminalBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_SensorBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_SignBaseQuantities;Height;IfcQuantityLength;Width;IfcQuantityLength;Thickness;IfcQuantityLength;Weight;IfcQuantityWeight
Qto_SignalBaseQuantities;Weight;IfcQuantityWeight
Qto_SiteBaseQuantities;GrossPerimeter;IfcQuantityLength;GrossArea;IfcQuantityArea
Qto_SlabBaseQuantities;Width;IfcQuantityLength;Length;IfcQuantityLength;Depth;IfcQuantityLength;Perimeter;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_SleeperBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength
Qto_SolarDeviceBaseQuantities;GrossWeight;IfcQuantityWeight;GrossArea;IfcQuantityArea
Qto_SpaceBaseQuantities;Height;IfcQuantityLength;FinishCeilingHeight;IfcQuantityLength;FinishFloorHeight;IfcQuantityLength;GrossPerimeter;IfcQuantityLength;NetPerimeter;IfcQuantityLength;GrossFloorArea;IfcQuantityArea;NetFloorArea;IfcQuantityArea;GrossWallArea;IfcQuantityArea;NetWallArea;IfcQuantityArea;GrossCeilingArea;IfcQuantityArea;NetCeilingArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
Qto_SpaceHeaterBaseQuantities;Length;IfcQuantityLength;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_SpatialZoneBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength
Qto_StackTerminalBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_StairFlightBaseQuantities;Length;IfcQuantityLength;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
Qto_SurfaceFeatureBaseQuantities;Area;IfcQuantityArea;Length;IfcQuantityLength
Qto_SwitchingDeviceBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_TankBaseQuantities;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight;TotalSurfaceArea;IfcQuantityArea
Qto_TransformerBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_TubeBundleBaseQuantities;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_UnitaryControlElementBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_UnitaryEquipmentBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_ValveBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_VehicleBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength
Qto_VibrationIsolatorBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_VolumetricStratumBaseQuantities;Area;IfcQuantityArea;Mass;IfcQuantityWeight;PlanArea;IfcQuantityArea;Volume;IfcQuantityVolume
Qto_WallBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;GrossFootPrintArea;IfcQuantityArea;NetFootPrintArea;IfcQuantityArea;GrossSideArea;IfcQuantityArea;NetSideArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
Qto_WasteTerminalBaseQuantities;GrossWeight;IfcQuantityWeight
Qto_WindowBaseQuantities;Width;IfcQuantityLength;Height;IfcQuantityLength;Perimeter;IfcQuantityLength;Area;IfcQuantityArea
1 Qto_ActuatorBaseQuantities;GrossWeight;IfcQuantityWeight
2 Qto_AirTerminalBaseQuantities;GrossWeight;IfcQuantityWeight;Perimeter;IfcQuantityLength;TotalSurfaceArea;IfcQuantityArea
3 Qto_AirTerminalBoxTypeBaseQuantities;GrossWeight;IfcQuantityWeight
4 Qto_AirToAirHeatRecoveryBaseQuantities;GrossWeight;IfcQuantityWeight
5 Qto_AlarmBaseQuantities;GrossWeight;IfcQuantityWeight
6 Qto_ArealStratumBaseQuantities;Area;IfcQuantityArea;Length;IfcQuantityLength;PlanLength;IfcQuantityLength
7 Qto_AudioVisualApplianceBaseQuantities;GrossWeight;IfcQuantityWeight
8 Qto_BeamBaseQuantities;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
9 Qto_BodyGeometryValidation;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;SurfaceGenusBeforeFeatures;IfcQuantityCount;SurfaceGenusAfterFeatures;IfcQuantityCount
10 Qto_BoilerBaseQuantities;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight;TotalSurfaceArea;IfcQuantityArea
11 Qto_BuildingBaseQuantities;Height;IfcQuantityLength;EavesHeight;IfcQuantityLength;FootPrintArea;IfcQuantityArea;GrossFloorArea;IfcQuantityArea;NetFloorArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
12 Qto_BuildingElementProxyQuantities;NetSurfaceArea;IfcQuantityArea;NetVolume;IfcQuantityVolume
13 Qto_BuildingStoreyBaseQuantities;GrossHeight;IfcQuantityLength;NetHeight;IfcQuantityLength;GrossPerimeter;IfcQuantityLength;GrossFloorArea;IfcQuantityArea;NetFloorArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
14 Qto_BurnerBaseQuantities;GrossWeight;IfcQuantityWeight
15 Qto_CableCarrierFittingBaseQuantities;GrossWeight;IfcQuantityWeight
16 Qto_CableCarrierSegmentBaseQuantities;GrossWeight;IfcQuantityWeight;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea
17 Qto_CableFittingBaseQuantities;GrossWeight;IfcQuantityWeight
18 Qto_CableSegmentBaseQuantities;GrossWeight;IfcQuantityWeight;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea
19 Qto_ChillerBaseQuantities;GrossWeight;IfcQuantityWeight
20 Qto_ChimneyBaseQuantities;Length;IfcQuantityLength
21 Qto_CoilBaseQuantities;GrossWeight;IfcQuantityWeight
22 Qto_ColumnBaseQuantities;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
23 Qto_CommunicationsApplianceBaseQuantities;GrossWeight;IfcQuantityWeight
24 Qto_CompressorBaseQuantities;GrossWeight;IfcQuantityWeight
25 Qto_CondenserBaseQuantities;GrossWeight;IfcQuantityWeight
26 Qto_ConduitSegmentBaseQuantities;InnerDiameter;IfcQuantityLength;OuterDiameter;IfcQuantityLength
27 Qto_ConstructionEquipmentResourceBaseQuantities;UsageTime;IfcQuantityTime;OperatingTime;IfcQuantityTime
28 Qto_ConstructionMaterialResourceBaseQuantities;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
29 Qto_ControllerBaseQuantities;GrossWeight;IfcQuantityWeight
30 Qto_CooledBeamBaseQuantities;GrossWeight;IfcQuantityWeight
31 Qto_CoolingTowerBaseQuantities;GrossWeight;IfcQuantityWeight
32 Qto_CourseBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Thickness;IfcQuantityLength;Volume;IfcQuantityVolume;GrossVolume;IfcQuantityVolume;Weight;IfcQuantityWeight
33 Qto_CoveringBaseQuantities;Width;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea
34 Qto_CurtainWallQuantities;Length;IfcQuantityLength;Height;IfcQuantityLength;Width;IfcQuantityLength;GrossSideArea;IfcQuantityArea;NetSideArea;IfcQuantityArea
35 Qto_DamperBaseQuantities;GrossWeight;IfcQuantityWeight
36 Qto_DistributionBoardBaseQuantities;GrossWeight;IfcQuantityWeight;NumberOfCircuits;IfcQuantityCount
37 Qto_DistributionChamberElementBaseQuantities;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;Depth;IfcQuantityLength
38 Qto_DoorBaseQuantities;Width;IfcQuantityLength;Height;IfcQuantityLength;Perimeter;IfcQuantityLength;Area;IfcQuantityArea
39 Qto_DuctFittingBaseQuantities;Length;IfcQuantityLength;GrossCrossSectionArea;IfcQuantityArea;NetCrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossWeight;IfcQuantityWeight
40 Qto_DuctSegmentBaseQuantities;Length;IfcQuantityLength;GrossCrossSectionArea;IfcQuantityArea;NetCrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossWeight;IfcQuantityWeight
41 Qto_DuctSilencerBaseQuantities;GrossWeight;IfcQuantityWeight
42 Qto_EarthworksCutBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Depth;IfcQuantityLength;UndisturbedVolume;IfcQuantityVolume;LooseVolume;IfcQuantityVolume;Weight;IfcQuantityWeight
43 Qto_EarthworksFillBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Depth;IfcQuantityLength;CompactedVolume;IfcQuantityVolume;LooseVolume;IfcQuantityVolume
44 Qto_ElectricApplianceBaseQuantities;GrossWeight;IfcQuantityWeight
45 Qto_ElectricFlowStorageDeviceBaseQuantities;GrossWeight;IfcQuantityWeight
46 Qto_ElectricGeneratorBaseQuantities;GrossWeight;IfcQuantityWeight
47 Qto_ElectricMotorBaseQuantities;GrossWeight;IfcQuantityWeight
48 Qto_ElectricTimeControlBaseQuantities;GrossWeight;IfcQuantityWeight
49 Qto_EvaporativeCoolerBaseQuantities;GrossWeight;IfcQuantityWeight
50 Qto_EvaporatorBaseQuantities;GrossWeight;IfcQuantityWeight
51 Qto_FacilityPartBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;Area;IfcQuantityArea;Volume;IfcQuantityVolume
52 Qto_FanBaseQuantities;GrossWeight;IfcQuantityWeight
53 Qto_FilterBaseQuantities;GrossWeight;IfcQuantityWeight
54 Qto_FireSuppressionTerminalBaseQuantities;GrossWeight;IfcQuantityWeight
55 Qto_FlowInstrumentBaseQuantities;GrossWeight;IfcQuantityWeight
56 Qto_FlowMeterBaseQuantities;GrossWeight;IfcQuantityWeight
57 Qto_FootingBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
58 Qto_HeatExchangerBaseQuantities;GrossWeight;IfcQuantityWeight
59 Qto_HumidifierBaseQuantities;GrossWeight;IfcQuantityWeight
60 Qto_ImpactProtectionDeviceBaseQuantities;Weight;IfcQuantityWeight
61 Qto_InterceptorBaseQuantities;GrossWeight;IfcQuantityWeight
62 Qto_JunctionBoxBaseQuantities;GrossWeight;IfcQuantityWeight;NumberOfGangs;IfcQuantityCount;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength
63 Qto_KerbBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;Depth;IfcQuantityLength;Volume;IfcQuantityVolume;Weight;IfcQuantityWeight
64 Qto_LaborResourceBaseQuantities;StandardWork;IfcQuantityTime;OvertimeWork;IfcQuantityTime
65 Qto_LampBaseQuantities;GrossWeight;IfcQuantityWeight
66 Qto_LightFixtureBaseQuantities;GrossWeight;IfcQuantityWeight
67 Qto_LinearStratumBaseQuantities;Diameter;IfcQuantityLength;Length;IfcQuantityLength
68 Qto_MarineFacilityBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;Area;IfcQuantityArea;Volume;IfcQuantityVolume
69 Qto_MemberBaseQuantities;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;NetSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
70 Qto_MotorConnectionBaseQuantities;GrossWeight;IfcQuantityWeight
71 Qto_OpeningElementBaseQuantities;Width;IfcQuantityLength;Height;IfcQuantityLength;Depth;IfcQuantityLength;Area;IfcQuantityArea;Volume;IfcQuantityVolume
72 Qto_OutletBaseQuantities;GrossWeight;IfcQuantityWeight
73 Qto_PavementBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Depth;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
74 Qto_PictorialSignQuantities;Area;IfcQuantityArea;SignArea;IfcQuantityArea
75 Qto_PileBaseQuantities;Length;IfcQuantityLength;CrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossSurfaceArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
76 Qto_PipeFittingBaseQuantities;Length;IfcQuantityLength;GrossCrossSectionArea;IfcQuantityArea;NetCrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
77 Qto_PipeSegmentBaseQuantities;Length;IfcQuantityLength;GrossCrossSectionArea;IfcQuantityArea;NetCrossSectionArea;IfcQuantityArea;OuterSurfaceArea;IfcQuantityArea;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight;FootPrintArea;IfcQuantityArea
78 Qto_PlateBaseQuantities;Width;IfcQuantityLength;Perimeter;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
79 Qto_ProjectionElementBaseQuantities;Area;IfcQuantityArea;Volume;IfcQuantityVolume
80 Qto_ProtectiveDeviceBaseQuantities;GrossWeight;IfcQuantityWeight
81 Qto_ProtectiveDeviceTrippingUnitBaseQuantities;GrossWeight;IfcQuantityWeight
82 Qto_PumpBaseQuantities;GrossWeight;IfcQuantityWeight
83 Qto_RailBaseQuantities;Length;IfcQuantityLength;Volume;IfcQuantityVolume;Weight;IfcQuantityWeight
84 Qto_RailingBaseQuantities;Length;IfcQuantityLength
85 Qto_RampFlightBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
86 Qto_ReinforcedSoilBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Depth;IfcQuantityLength;Area;IfcQuantityArea;Volume;IfcQuantityVolume
87 Qto_ReinforcingElementBaseQuantities;Count;IfcQuantityCount;Length;IfcQuantityLength;Weight;IfcQuantityWeight
88 Qto_RoofBaseQuantities;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;ProjectedArea;IfcQuantityArea
89 Qto_SanitaryTerminalBaseQuantities;GrossWeight;IfcQuantityWeight
90 Qto_SensorBaseQuantities;GrossWeight;IfcQuantityWeight
91 Qto_SignBaseQuantities;Height;IfcQuantityLength;Width;IfcQuantityLength;Thickness;IfcQuantityLength;Weight;IfcQuantityWeight
92 Qto_SignalBaseQuantities;Weight;IfcQuantityWeight
93 Qto_SiteBaseQuantities;GrossPerimeter;IfcQuantityLength;GrossArea;IfcQuantityArea
94 Qto_SlabBaseQuantities;Width;IfcQuantityLength;Length;IfcQuantityLength;Depth;IfcQuantityLength;Perimeter;IfcQuantityLength;GrossArea;IfcQuantityArea;NetArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
95 Qto_SleeperBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength
96 Qto_SolarDeviceBaseQuantities;GrossWeight;IfcQuantityWeight;GrossArea;IfcQuantityArea
97 Qto_SpaceBaseQuantities;Height;IfcQuantityLength;FinishCeilingHeight;IfcQuantityLength;FinishFloorHeight;IfcQuantityLength;GrossPerimeter;IfcQuantityLength;NetPerimeter;IfcQuantityLength;GrossFloorArea;IfcQuantityArea;NetFloorArea;IfcQuantityArea;GrossWallArea;IfcQuantityArea;NetWallArea;IfcQuantityArea;GrossCeilingArea;IfcQuantityArea;NetCeilingArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
98 Qto_SpaceHeaterBaseQuantities;Length;IfcQuantityLength;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
99 Qto_SpatialZoneBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength
100 Qto_StackTerminalBaseQuantities;GrossWeight;IfcQuantityWeight
101 Qto_StairFlightBaseQuantities;Length;IfcQuantityLength;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume
102 Qto_SurfaceFeatureBaseQuantities;Area;IfcQuantityArea;Length;IfcQuantityLength
103 Qto_SwitchingDeviceBaseQuantities;GrossWeight;IfcQuantityWeight
104 Qto_TankBaseQuantities;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight;TotalSurfaceArea;IfcQuantityArea
105 Qto_TransformerBaseQuantities;GrossWeight;IfcQuantityWeight
106 Qto_TubeBundleBaseQuantities;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
107 Qto_UnitaryControlElementBaseQuantities;GrossWeight;IfcQuantityWeight
108 Qto_UnitaryEquipmentBaseQuantities;GrossWeight;IfcQuantityWeight
109 Qto_ValveBaseQuantities;GrossWeight;IfcQuantityWeight
110 Qto_VehicleBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength
111 Qto_VibrationIsolatorBaseQuantities;GrossWeight;IfcQuantityWeight
112 Qto_VolumetricStratumBaseQuantities;Area;IfcQuantityArea;Mass;IfcQuantityWeight;PlanArea;IfcQuantityArea;Volume;IfcQuantityVolume
113 Qto_WallBaseQuantities;Length;IfcQuantityLength;Width;IfcQuantityLength;Height;IfcQuantityLength;GrossFootPrintArea;IfcQuantityArea;NetFootPrintArea;IfcQuantityArea;GrossSideArea;IfcQuantityArea;NetSideArea;IfcQuantityArea;GrossVolume;IfcQuantityVolume;NetVolume;IfcQuantityVolume;GrossWeight;IfcQuantityWeight;NetWeight;IfcQuantityWeight
114 Qto_WasteTerminalBaseQuantities;GrossWeight;IfcQuantityWeight
115 Qto_WindowBaseQuantities;Width;IfcQuantityLength;Height;IfcQuantityLength;Perimeter;IfcQuantityLength;Area;IfcQuantityArea

File diff suppressed because one or more lines are too long

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>852</width>
<height>471</height>
<width>680</width>
<height>512</height>
</rect>
</property>
<property name="windowTitle">
@@ -40,6 +40,16 @@
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QComboBox" name="comboQto"/>
</item>
<item>
<widget class="QPushButton" name="buttonApply">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
@@ -53,11 +63,26 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonRefresh">
<property name="text">
<string>Refresh</string>
</property>
<property name="icon">
<iconset theme="reload">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonSelectAll">
<property name="text">
<string>Select all</string>
</property>
<property name="icon">
<iconset theme="edit-select-all">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>

View File

@@ -25,13 +25,15 @@
"""This module contains FreeCAD commands for the BIM workbench"""
import os
import csv
import FreeCAD
import FreeCADGui
QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP
translate = FreeCAD.Qt.translate
PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM")
qprops = [
QPROPS = [
"Length",
"Width",
"Height",
@@ -39,8 +41,8 @@ qprops = [
"HorizontalArea",
"VerticalArea",
"Volume",
] # quantities columns
trqprops = [
]
TR_QPROPS = [
translate("BIM", "Length"),
translate("BIM", "Width"),
translate("BIM", "Height"),
@@ -49,6 +51,15 @@ trqprops = [
translate("BIM", "Vertical Area"),
translate("BIM", "Volume"),
]
QTO_TYPES = {
"IfcQuantityArea": "App::PropertyArea",
"IfcQuantityCount": "App::PropertyInteger",
"IfcQuantityLength": "App::PropertyLength",
"IfcQuantityNumber": "App::PropertyInteger",
"IfcQuantityTime": "App::PropertyTime",
"IfcQuantityVolume": "App::PropertyVolume",
"IfcQuantityWeight": "App::PropertyWeight",
}
class BIM_IfcQuantities:
@@ -74,6 +85,7 @@ class BIM_IfcQuantities:
# build objects list
self.objectslist = {}
self.ifcqtolist = {}
for obj in FreeCAD.ActiveDocument.Objects:
role = self.getRole(obj)
if role:
@@ -95,17 +107,22 @@ class BIM_IfcQuantities:
# load the form and set the tree model up
self.form = FreeCADGui.PySideUic.loadUi(":/ui/dialogIfcQuantities.ui")
self.form.setWindowIcon(QtGui.QIcon(":/icons/BIM_IfcQuantities.svg"))
w = PARAMS.GetInt("BimIfcQuantitiesDialogWidth", 680)
h = PARAMS.GetInt("BimIfcQuantitiesDialogHeight", 512)
self.form.resize(w, h)
self.get_qtos()
# quantities tab
self.qmodel = QtGui.QStandardItemModel()
self.form.quantities.setModel(self.qmodel)
self.form.quantities.setUniformRowHeights(True)
self.form.quantities.setItemDelegate(QtGui.QStyledItemDelegate())
self.quantitiesDrawn = False
self.qmodel.dataChanged.connect(self.setChecked)
self.form.buttonBox.accepted.connect(self.accept)
self.form.quantities.clicked.connect(self.onClickTree)
self.form.onlyVisible.stateChanged.connect(self.update)
self.form.buttonRefresh.clicked.connect(self.update)
self.form.buttonApply.clicked.connect(self.add_qto)
# center the dialog over FreeCAD window
mw = FreeCADGui.getMainWindow()
@@ -132,137 +149,256 @@ class BIM_IfcQuantities:
def decamelize(self, s):
return "".join([" " + c if c.isupper() else c for c in s]).strip(" ")
def get_qtos(self):
"populates the qtos combo box"
def read_csv(csvfile):
result = {}
if os.path.exists(csvfile):
with open(csvfile, "r") as f:
reader = csv.reader(f, delimiter=";")
for row in reader:
result[row[0]] = row[1:]
return result
self.qtodefs = {}
qtopath = os.path.join(
FreeCAD.getResourceDir(), "Mod", "BIM", "Presets", "qto_definitions.csv"
)
custompath = os.path.join(FreeCAD.getUserAppDataDir(), "BIM", "CustomQtos.csv")
self.qtodefs = read_csv(qtopath)
self.qtodefs.update(read_csv(custompath))
self.qtokeys = [
"".join(map(lambda x: x if x.islower() else " " + x, t[4:]))[1:]
for t in self.qtodefs.keys()
]
self.qtokeys.sort()
self.form.comboQto.addItems(
[translate("BIM", "Add quantity set..."),]
+ self.qtokeys
)
def add_qto(self):
"Adds a standard qto set to the todo list"
index = self.form.comboQto.currentIndex()
if index <= 0:
return
if len(FreeCADGui.Selection.getSelection()) != 1:
return
obj = FreeCADGui.Selection.getSelection()[0]
qto = list(self.qtodefs.keys())[index-1]
self.ifcqtolist.setdefault(obj.Name, []).append(qto)
self.update_line(obj.Name, qto)
FreeCAD.Console.PrintMessage(translate("BIM", "Adding quantity set")+": "+qto+"\n")
def apply_qto(self, obj, qto):
"Adds a standard qto set to the object"
val = self.qtodefs[qto]
qset = None
if hasattr(obj, "StepId"):
from nativeifc import ifc_tools
ifcfile = ifc_tools.get_ifcfile(obj)
element = ifc_tools.get_ifc_element(obj)
if not ifcfile or not element:
return
qset = ifc_tools.api_run("pset.add_qto", ifcfile, product=element, name=qto)
for i in range(0, len(val), 2):
qname = val[i]
qtype = QTO_TYPES[val[i+1]]
if not qname in obj.PropertiesList:
obj.addProperty(qtype, qname, "Quantities", val[i+1])
qval = 0
i = self.get_row(obj.Name)
if i > -1:
for j, p in enumerate(QPROPS):
it = self.qmodel.item(i, j+1)
t = it.text()
if t:
t = t.replace("²","^2").replace("³","^3")
qval = FreeCAD.Units.Quantity(t).Value
if qval:
setattr(obj, qname, qval)
if hasattr(obj, "StepId") and qset:
ifc_tools.api_run("pset.edit_qto", ifcfile, qto=qset, properties={qname: qval})
def update(self, index=None):
"updates the tree widgets in all tabs"
"""updates the tree widgets in all tabs. Index is not used,
it is just there to match a qt slot requirement"""
from PySide import QtCore, QtGui
import Draft
# quantities tab - only fill once
# quantities tab
if not self.quantitiesDrawn:
self.qmodel.setHorizontalHeaderLabels(
[translate("BIM", "Label")] + trqprops
)
quantheaders = self.form.quantities.header() # QHeaderView instance
if hasattr(quantheaders, "setClickable"): # qt4
quantheaders.setClickable(True)
else: # qt5
quantheaders.setSectionsClickable(True)
quantheaders.sectionClicked.connect(self.quantHeaderClicked)
self.qmodel.clear()
self.qmodel.setHorizontalHeaderLabels(
[translate("BIM", "Label")] + TR_QPROPS
)
self.form.quantities.setColumnWidth(0, 200) # TODO remember width
quantheaders = self.form.quantities.header() # QHeaderView instance
quantheaders.setSectionsClickable(True)
quantheaders.sectionClicked.connect(self.quantHeaderClicked)
# sort by type
# sort by type
groups = {}
for name, role in self.objectslist.items():
groups.setdefault(role, []).append(name)
for names in groups.values():
suffix = ""
for name in names:
if "+array" in name:
name = name.split("+array")[0]
suffix = " (duplicate)"
obj = FreeCAD.ActiveDocument.getObject(name)
if obj:
if (
not self.form.onlyVisible.isChecked()
) or obj.ViewObject.isVisible():
if obj.isDerivedFrom("Part::Feature") and not (
Draft.getType(obj) == "Site"
):
it1 = QtGui.QStandardItem(obj.Label + suffix)
it1.setToolTip(name + suffix)
it1.setEditable(False)
if QtCore.QFileInfo(
":/icons/Arch_" + obj.Proxy.Type + "_Tree.svg"
).exists():
icon = QtGui.QIcon(
":/icons/Arch_" + obj.Proxy.Type + "_Tree.svg"
)
else:
icon = QtGui.QIcon(":/icons/Arch_Component.svg")
it1.setIcon(icon)
props = []
for prop in qprops:
it = QtGui.QStandardItem()
val = None
if prop == "Volume":
if obj.Shape and hasattr(obj.Shape, "Volume"):
val = FreeCAD.Units.Quantity(
obj.Shape.Volume, FreeCAD.Units.Volume
)
it.setText(
val.getUserPreferred()[0].replace(
"^3", "³"
)
)
it.setCheckable(True)
else:
if hasattr(obj, prop) and (
not "Hidden" in obj.getEditorMode(prop)
groups = {}
for name, role in self.objectslist.items():
groups.setdefault(role, []).append(name)
for names in groups.values():
suffix = ""
for name in names:
if "+array" in name:
name = name.split("+array")[0]
suffix = " (duplicate)"
obj = FreeCAD.ActiveDocument.getObject(name)
if obj:
if (
not self.form.onlyVisible.isChecked()
) or obj.ViewObject.isVisible():
if obj.isDerivedFrom("Part::Feature") and not (
Draft.getType(obj) == "Site"
):
it1 = QtGui.QStandardItem(obj.Label + suffix)
it1.setToolTip(name + suffix)
it1.setEditable(False)
it1.setIcon(obj.ViewObject.Icon)
props = []
for prop in QPROPS:
it = QtGui.QStandardItem()
val = None
if hasattr(obj, prop) and (
"Hidden" not in obj.getEditorMode(prop)
):
val = self.get_text(obj, prop)
it.setText(val)
it.setCheckable(True)
if val != None:
d = None
if hasattr(obj, "IfcAttributes"):
d = obj.IfcAttributes
elif hasattr(obj, "IfcData"):
d = obj.IfcData
if d:
if ("Export" + prop in d) and (
d["Export" + prop] == "True"
):
val = getattr(obj, prop)
it.setText(
val.getUserPreferred()[0].replace(
"^2", "²"
)
)
it.setCheckable(True)
if val != None:
d = None
if hasattr(obj, "IfcAttributes"):
d = obj.IfcAttributes
elif hasattr(obj, "IfcData"):
d = obj.IfcData
if d:
if ("Export" + prop in d) and (
d["Export" + prop] == "True"
):
it.setCheckState(QtCore.Qt.Checked)
if val == 0:
it.setIcon(
QtGui.QIcon(
os.path.join(
os.path.dirname(__file__),
"icons",
"warning.svg",
)
)
)
if prop in [
"Area",
"HorizontalArea",
"VerticalArea",
"Volume",
]:
it.setEditable(False)
props.append(it)
self.qmodel.appendRow([it1] + props)
self.quantitiesDrawn = True
it.setCheckState(QtCore.Qt.Checked)
elif self.has_qto(obj, prop):
it.setCheckState(QtCore.Qt.Checked)
if val == 0:
it.setIcon(QtGui.QIcon(":/icons/warning.svg"))
self.set_editable(it, prop)
props.append(it)
self.qmodel.appendRow([it1] + props)
def has_qto(self, obj, prop):
"""Says if the given object has the given prop in a qto set"""
if not "StepId" in obj.PropertiesList:
return False
from nativeifc import ifc_tools
element = ifc_tools.get_ifc_element(obj)
if not element:
return False
for rel in getattr(element, "IsDefinedBy", []):
pset = rel.RelatingPropertyDefinition
if pset.is_a("IfcElementQuantity"):
if pset.Name in self.qtodefs:
if prop in self.qtodefs[pset.Name]:
return True
return False
def get_text(self, obj, prop):
"""Gets the text from a property"""
val = getattr(obj, prop, "0")
txt = val.getUserPreferred()[0].replace("^2", "²").replace("^3", "³")
return txt
def get_row(self, name):
"""Returns the row number correspinding to the given object name"""
for i in range(self.qmodel.rowCount()):
if self.qmodel.item(i).toolTip().split(" ")[0] == name:
return i
return -1
def update_line(self, name, qto):
"""Updates a single line of the table, without updating
the actual object"""
from PySide import QtCore, QtGui
i = self.get_row(name)
if i == -1:
return
obj = FreeCAD.ActiveDocument.getObject(name)
qto_val = self.qtodefs[qto]
for j, p in enumerate(QPROPS):
it = self.qmodel.item(i, j+1)
if p in obj.PropertiesList:
val = self.get_text(obj, p)
it.setText(val)
self.set_editable(it, p)
it.setCheckable(True)
elif p in qto_val:
it.setText("0")
it.setCheckable(True)
it.setCheckState(QtCore.Qt.Checked)
self.set_editable(it, p)
def set_editable(self, it, prop):
"""Checks if the given prop should be editable, and sets it"""
if prop in ["Area", "HorizontalArea", "VerticalArea", "Volume"]:
it.setEditable(False)
else:
it.setEditable(True)
def getRole(self, obj):
"""gets the IFC class of this object"""
if hasattr(obj, "IfcType"):
return obj.IfcType
elif hasattr(obj, "IfcRole"):
return obj.IfcRole
elif hasattr(obj, "IfcClass"):
return obj.IfcClass
else:
return None
def accept(self):
"""OK pressed"""
PARAMS.SetInt("BimIfcQuantitiesDialogWidth", self.form.width())
PARAMS.SetInt("BimIfcQuantitiesDialogHeight", self.form.height())
self.form.hide()
changed = False
if self.ifcqtolist:
if not changed:
FreeCAD.ActiveDocument.openTransaction(
"Change quantities"
)
changed = True
for key, val in self.ifcqtolist.items():
obj = FreeCAD.ActiveDocument.getObject(key)
if obj:
for qto in val:
self.apply_qto(obj, qto)
for row in range(self.qmodel.rowCount()):
name = self.qmodel.item(row, 0).toolTip()
obj = FreeCAD.ActiveDocument.getObject(name)
if obj:
for i in range(len(qprops)):
for i in range(len(QPROPS)):
item = self.qmodel.item(row, i + 1)
val = item.text()
sav = bool(item.checkState())
if i < 3: # Length, Width, Height, value can be changed
if hasattr(obj, qprops[i]):
if getattr(obj, qprops[i]).getUserPreferred()[0] != val:
setattr(obj, qprops[i], val)
if hasattr(obj, QPROPS[i]):
if getattr(obj, QPROPS[i]).getUserPreferred()[0] != val:
setattr(obj, QPROPS[i], val)
if not changed:
FreeCAD.ActiveDocument.openTransaction(
"Change quantities"
@@ -277,10 +413,10 @@ class BIM_IfcQuantities:
att = "IfcData"
if d:
if sav:
if (not "Export" + qprops[i] in d) or (
d["Export" + qprops[i]] == "False"
if (not "Export" + QPROPS[i] in d) or (
d["Export" + QPROPS[i]] == "False"
):
d["Export" + qprops[i]] = "True"
d["Export" + QPROPS[i]] = "True"
setattr(obj, att, d)
if not changed:
FreeCAD.ActiveDocument.openTransaction(
@@ -288,16 +424,16 @@ class BIM_IfcQuantities:
)
changed = True
else:
if "Export" + qprops[i] in d:
if d["Export" + qprops[i]] == "True":
d["Export" + qprops[i]] = "False"
if "Export" + QPROPS[i] in d:
if d["Export" + QPROPS[i]] == "True":
d["Export" + QPROPS[i]] = "False"
setattr(obj, att, d)
if not changed:
FreeCAD.ActiveDocument.openTransaction(
"Change quantities"
)
changed = True
else:
elif "StepId" not in obj.PropertiesList:
FreeCAD.Console.PrintError(
translate(
"BIM", "Cannot save quantities settings for object %1"

View File

@@ -272,14 +272,17 @@ def export(exportList, filename, colors=None, preferences=None):
objectslist = Draft.get_group_contents(exportList, walls=True,
addgroups=True)
# separate 2D objects
# separate 2D and special objects. Special objects provide their own IFC export method
annotations = []
specials = []
for obj in objectslist:
if obj.isDerivedFrom("Part::Part2DObject"):
annotations.append(obj)
elif obj.isDerivedFrom("App::Annotation") or (Draft.getType(obj) in ["DraftText","Text","Dimension","LinearDimension","AngularDimension"]):
annotations.append(obj)
elif hasattr(obj, "Proxy") and hasattr(obj.Proxy, "export_ifc"):
specials.append(obj)
elif obj.isDerivedFrom("Part::Feature"):
if obj.Shape and (not obj.Shape.Solids) and obj.Shape.Edges:
if not obj.Shape.Faces:
@@ -290,6 +293,7 @@ def export(exportList, filename, colors=None, preferences=None):
# clean objects list of unwanted types
objectslist = [obj for obj in objectslist if obj not in annotations]
objectslist = [obj for obj in objectslist if obj not in specials]
objectslist = Arch.pruneIncluded(objectslist,strict=True)
objectslist = [obj for obj in objectslist if Draft.getType(obj) not in ["Dimension","Material","MaterialContainer","WorkingPlaneProxy"]]
if preferences['FULL_PARAMETRIC']:
@@ -1296,6 +1300,14 @@ def export(exportList, filename, colors=None, preferences=None):
ann = create_annotation(anno, ifcfile, context, history, preferences)
annos[anno.Name] = ann
# specials. Specials should take care of register themselves where needed under the project
specs = {}
for spec in specials:
if preferences['DEBUG']: print("exporting special object:",spec.Label)
elt = spec.Proxy.export_ifc(spec, ifcfile)
specs[spec.Name] = elt
# groups
sortedgroups = []

View File

@@ -187,6 +187,8 @@ def get_object_type(ifcentity, objecttype=None):
objecttype = "text"
elif ifcentity.is_a("IfcGridAxis"):
objecttype = "axis"
elif ifcentity.is_a("IfcControl"):
objecttype = "schedule"
return objecttype

View File

@@ -84,6 +84,8 @@ class ifc_object:
obj.ViewObject.signalChangeIcon()
elif hasattr(obj, prop) and obj.getGroupOfProperty(prop) == "Geometry":
self.edit_geometry(obj, prop)
elif hasattr(obj, prop) and obj.getGroupOfProperty(prop) == "Quantities":
self.edit_quantity(obj, prop)
elif hasattr(obj, prop) and obj.getGroupOfProperty(prop) not in NON_PSETS:
# Treat all property groups outside the default ones as Psets
# print("DEBUG: editinog pset prop",prop)
@@ -353,6 +355,11 @@ class ifc_object:
# Not doing anything right now because an unset Type property could screw the ifc file
pass
def edit_quantity(self, obj, prop):
"""Edits the given quantity"""
pass # TODO implement
def get_section_data(self, obj):
"""Returns two things: a list of objects and a cut plane"""

View File

@@ -24,7 +24,6 @@
import os
import FreeCAD
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/NativeIFC")
@@ -197,8 +196,10 @@ class ifc_observer:
return
del self.docname
del self.objname
if obj.isDerivedFrom("Part::Feature") or "IfcType" in obj.PropertiesList:
FreeCAD.Console.PrintLog("Converting" + obj.Label + "to IFC\n")
if obj.isDerivedFrom("Part::Feature") \
or "IfcType" in obj.PropertiesList \
or "CreateSpreadsheet" in obj.PropertiesList:
FreeCAD.Console.PrintLog("Converting " + obj.Label + " to IFC\n")
from nativeifc import ifc_geometry # lazy loading
from nativeifc import ifc_tools # lazy loading

View File

@@ -105,34 +105,35 @@ def show_psets(obj):
ttip = (
ptype + ":" + oname
) # setting IfcType:PropName as a tooltip to desambiguate
while pname in obj.PropertiesList:
#while pname in obj.PropertiesList:
# print("DEBUG: property", pname, "(", value, ") already exists in", obj.Label)
pname += "_"
# pname += "_"
ftype = None
if ptype in [
"IfcPositiveLengthMeasure",
"IfcLengthMeasure",
"IfcNonNegativeLengthMeasure",
]:
obj.addProperty("App::PropertyDistance", pname, gname, ttip)
ftype = "App::PropertyDistance"
elif ptype in ["IfcVolumeMeasure"]:
obj.addProperty("App::PropertyVolume", pname, gname, ttip)
ftype = "App::PropertyVolume"
elif ptype in ["IfcPositivePlaneAngleMeasure", "IfcPlaneAngleMeasure"]:
obj.addProperty("App::PropertyAngle", pname, gname, ttip)
ftype = "App::PropertyAngle"
value = float(value)
while value > 360:
value = value - 360
elif ptype in ["IfcMassMeasure"]:
obj.addProperty("App::PropertyMass", pname, gname, ttip)
ftype = "App::PropertyMass"
elif ptype in ["IfcAreaMeasure"]:
obj.addProperty("App::PropertyArea", pname, gname, ttip)
ftype = "App::PropertyArea"
elif ptype in ["IfcCountMeasure", "IfcInteger"]:
obj.addProperty("App::PropertyInteger", pname, gname, ttip)
ftype = "App::PropertyInteger"
value = int(value.strip("."))
elif ptype in ["IfcReal"]:
obj.addProperty("App::PropertyFloat", pname, gname, ttip)
ftype = "App::PropertyFloat"
value = float(value)
elif ptype in ["IfcBoolean", "IfcLogical"]:
obj.addProperty("App::PropertyBool", pname, gname, ttip)
ftype = "App::PropertyBool"
if value in [".T."]:
value = True
else:
@@ -144,14 +145,30 @@ def show_psets(obj):
"IfcDuration",
"IfcTimeStamp",
]:
obj.addProperty("App::PropertyTime", pname, gname, ttip)
ftype = "App::PropertyTime"
elif isinstance(value, str) and "::" in value:
# FreeCAD-specific: split strings by :: delimiter
ftype = "App::PropertyStringList"
value = value.split("::")
else:
obj.addProperty("App::PropertyString", pname, gname, ttip)
ftype = "App::PropertyString"
# print("DEBUG: setting",pname, ptype, value)
setattr(obj, pname, value)
if ftype:
if pname in obj.PropertiesList \
and obj.getGroupOfProperty(pname) == gname:
if obj.getTypeOfProperty(pname) == ftype:
pass
if ftype == "App::PropertyString" \
and obj.getTypeOfProperty(pname) == "App::PropertyStringList":
value = [value]
else:
print(pname, gname, obj.PropertiesList)
obj.addProperty(ftype, pname, gname, ttip)
if pname in obj.PropertiesList:
setattr(obj, pname, value)
def edit_pset(obj, prop, value=None, force=False):
def edit_pset(obj, prop, value=None, force=False, ifcfile=None, element=None):
"""Edits the corresponding property. If force is True,
the property is created even if it has no value"""
@@ -159,8 +176,14 @@ def edit_pset(obj, prop, value=None, force=False):
ptype = obj.getDocumentationOfProperty(prop)
if value is None:
value = getattr(obj, prop)
ifcfile = ifc_tools.get_ifcfile(obj)
element = ifc_tools.get_ifc_element(obj)
if not ifcfile:
ifcfile = ifc_tools.get_ifcfile(obj)
if not ifcfile:
return
if not element:
element = ifc_tools.get_ifc_element(obj)
if not element:
return
pset_exist = get_psets(element)
target_prop = None
value_exist = None
@@ -242,7 +265,7 @@ def edit_pset(obj, prop, value=None, force=False):
"IFC: property changed for "
+ obj.Label
+ " ("
+ str(obj.StepId)
+ str(element.id())
+ "): "
+ str(target_prop)
+ ": "
@@ -356,3 +379,7 @@ def remove_property(obj, prop):
# delete the pset too
FreeCAD.Console.PrintMessage(translate("BIM","Removing property set")+": "+psetname)
ifc_tools.api_run("pset.remove_pset", ifcfile, product=element, pset=pset)
# Quantity types
# https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/ifcsharedbldgelements/content.html#6.1.5-Quantity-Sets

View File

@@ -46,6 +46,7 @@ from nativeifc import ifc_import
from nativeifc import ifc_layers
from nativeifc import ifc_status
from nativeifc import ifc_export
from nativeifc import ifc_psets
from draftviewproviders import view_layer
from PySide import QtCore
@@ -443,7 +444,7 @@ def get_ifcfile(obj):
if getattr(project, "Proxy", None):
if hasattr(project.Proxy, "ifcfile"):
return project.Proxy.ifcfile
if project.IfcFilePath:
if getattr(project, "IfcFilePath", None):
ifcfile = ifcopenshell.open(project.IfcFilePath)
if hasattr(project, "Proxy"):
if project.Proxy is None:
@@ -453,7 +454,7 @@ def get_ifcfile(obj):
project.Proxy.ifcfile = ifcfile
return ifcfile
else:
FreeCAD.Console.PrintError("Error: No IFC file attached to this project")
FreeCAD.Console.PrintError("Error: No IFC file attached to this project: "+project.Label)
return None
@@ -508,11 +509,14 @@ def add_object(document, otype=None, oname="IfcObject"):
'dimension',
'sectionplane',
'axis',
'schedule'
or anything else for a standard IFC object"""
if not document:
return None
if otype == "sectionplane":
if otype == "schedule":
obj = Arch.makeSchedule()
elif otype == "sectionplane":
obj = Arch.makeSectionPlane()
obj.Proxy = ifc_objects.ifc_object(otype)
elif otype == "axis":
@@ -746,6 +750,8 @@ def add_properties(
obj.addProperty("App::PropertyStringList", "Text", "Base")
obj.Text = [text.Literal]
obj.Placement = ifc_export.get_placement(ifcentity.ObjectPlacement, ifcfile)
elif ifcentity.is_a("IfcControl"):
ifc_psets.show_psets(obj)
# link Label2 and Description
if "Description" in obj.PropertiesList and hasattr(obj, "setExpression"):
@@ -1150,6 +1156,7 @@ def aggregate(obj, parent, mode=None):
if not ifcfile:
return
product = None
new = False
stepid = getattr(obj, "StepId", None)
if stepid:
# obj might be dragging at this point and has no project anymore
@@ -1163,7 +1170,6 @@ def aggregate(obj, parent, mode=None):
# this object already has an associated IFC product
print("DEBUG:", obj.Label, "is already part of the IFC document")
newobj = obj
new = False
else:
ifcclass = None
if mode == "opening":
@@ -1173,12 +1179,16 @@ def aggregate(obj, parent, mode=None):
product = ifc_export.create_annotation(obj, ifcfile)
if Draft.get_type(obj) in ["DraftText","Text"]:
objecttype = "text"
elif "CreateSpreadsheet" in obj.PropertiesList:
obj.Proxy.create_ifc(obj, ifcfile)
newobj = obj
else:
product = ifc_export.create_product(obj, parent, ifcfile, ifcclass)
if product:
shapemode = getattr(parent, "ShapeMode", DEFAULT_SHAPEMODE)
newobj = create_object(product, obj.Document, ifcfile, shapemode, objecttype)
new = True
create_relationship(obj, newobj, parent, product, ifcfile, mode)
create_relationship(obj, newobj, parent, product, ifcfile, mode)
base = getattr(obj, "Base", None)
if base:
# make sure the base is used only by this object before deleting
@@ -1524,6 +1534,12 @@ def get_orphan_elements(ifcfile):
products = [
p for p in products if not hasattr(p, "VoidsElements") or not p.VoidsElements
]
# add control elements
proj = ifcfile.by_type("IfcProject")[0]
for rel in proj.Declares:
for ctrl in getattr(rel,"RelatedDefinitions", []):
if ctrl.is_a("IfcControl"):
products.append(ctrl)
groups = []
for o in products:
for rel in getattr(o, "HasAssignments", []):

View File

@@ -20,56 +20,119 @@
# * *
# ***************************************************************************
"""This script retrieves a list of standard property sets from the IFC4 official documentation website
and stores them into a pset_dfinitions.xml files in the current directory. Warning, this can take
a certain time (there are more than 400 definitions to retrieve)"""
"""This script retrieves a list of standard property sets from the IFC4 official
documentation website and stores them into 1) a pset_definitions.csv and 2)
a qto_definitions.csv files in the directory ../Presets."""
import codecs, os, re
import os
from zipfile import ZipFile
from urllib.request import urlopen
import xml.sax
MAXTRIES = 3
IFC_DOCS_ROOT_URL = "https://standards.buildingsmart.org/IFC/DEV/IFC4_2/FINAL/HTML/"
# read the pset list
print("Getting psets list...")
u = urlopen(
IFC_DOCS_ROOT_URL + "annex/annex-b/alphabeticalorder_psets.htm"
)
p = u.read().decode('utf-8')
u.close()
psets = re.findall(r">Pset_(.*?)</a>", p)
URL = "https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/annex-a-psd.zip"
# retrieve xml data from each Pset type
psetdefs = ""
failed = []
for i, pset in enumerate(psets):
print(i + 1, "/", len(psets), ": Retrieving Pset", pset)
for j in range(MAXTRIES):
try:
u = urlopen(
IFC_DOCS_ROOT_URL + "psd/Pset_"
+ pset
+ ".xml"
)
p = u.read().decode('utf-8')
u.close()
except:
print(" Connection failed. trying one more time...")
QTO_TYPES = {
"Q_AREA": "IfcQuantityArea",
"Q_COUNT": "IfcQuantityCount",
"Q_LENGTH": "IfcQuantityLength",
"Q_NUMBER": "IfcQuantityNumber",
"Q_TIME": "IfcQuantityTime",
"Q_VOLUME": "IfcQuantityVolume",
"Q_WEIGHT": "IfcQuantityWeight",
}
class PropertyDefHandler(xml.sax.ContentHandler):
"A XML handler to process pset definitions"
# this creates a dictionary where each key is a Pset name,
# and each value is a list of [property,type] lists
def __init__(self, pset):
super().__init__()
self.line = pset.strip(".xml") + ";"
self.currentprop = None
self.currenttype = None
self.charbuffer = []
self.writing = False
self.prop = False
self.qtotype = False
# Call when raw text is read (the property name)
def characters(self, data):
if self.writing:
self.charbuffer.append(data)
# Call when an element starts
def startElement(self, tag, attributes):
if tag in ["PropertyDef", "QtoDef"]:
self.prop = True
elif tag == "Name":
self.writing = True
elif tag == "DataType":
self.currenttype = attributes["type"]
elif tag == "QtoType":
self.qtotype = True
self.writing = True
# Call when an elements ends
def endElement(self, tag):
if tag in ["Name", "QtoType"]:
if self.prop:
self.currentprop = "".join(self.charbuffer)
elif self.qtotype:
self.currenttype = "".join(self.charbuffer)
self.writing = False
self.prop = False
self.qtotype = False
self.charbuffer = []
elif tag in ["PropertyDef", "QtoDef"]:
if self.currentprop and self.currenttype:
if self.currenttype in QTO_TYPES:
self.currenttype = QTO_TYPES[self.currenttype]
self.line += self.currentprop + ";" + self.currenttype + ";"
self.currentprop = None
self.currenttype = None
# MAIN
print("Getting psets xml definitions...")
with open("psd.zip","wb") as f:
u = urlopen(URL)
p = u.read()
f.write(p)
print("Reading xml definitions...")
psets = []
qtos = []
with ZipFile("psd.zip", 'r') as z:
for entry in z.namelist():
print("Parsing",entry)
xml_data = z.read(entry).decode(encoding="utf-8")
handler = PropertyDefHandler(entry)
xml.sax.parseString(xml_data, handler)
if entry.startswith("Pset"):
psets.append(handler.line)
else:
break
else:
print(" Unable to retrieve ", pset, ". Skipping...")
failed.append(pset)
psetdefs += p
psetdefs = psetdefs.replace('<?xml version="1.0" encoding="utf-8"?>', "")
psetdefs = '<?xml version="1.0" encoding="utf-8"?>\n<Root>\n' + psetdefs + "</Root>"
qtos.append(handler.line)
f = codecs.open("pset_definitions.xml", "wb", "utf-8")
f.write(psetdefs)
f.close()
print(
"All done! writing "
+ os.path.join(os.path.abspath(os.curdir), "pset_definitions.xml")
)
if failed:
print("The following psets failed and were not retrieved:", failed)
print("Saving files...")
with open("../Presets/pset_definitions.csv", "w") as f:
for l in psets:
f.write(l.strip(";") + "\n")
with open("../Presets/qto_definitions.csv", "w") as f:
for l in qtos:
f.write(l.strip(";") + "\n")
os.remove("psd.zip")

View File

@@ -1,102 +0,0 @@
# ***************************************************************************
# * *
# * Copyright (c) 2018 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
"""This script converts a xml file containing pset definitions to a csv file.
Python3 only!! (py2 csv doesn't support utf8"""
import xml.sax, os
class PropertyDefHandler(xml.sax.ContentHandler):
"A XML handler to process pset definitions"
# this creates a dictionary where each key is a Pset name,
# and each value is a list of [property,type] lists
def __init__(self):
super().__init__()
self.psets = {}
self.currentpset = None
self.currentprop = None
self.currenttype = None
self.currentlist = []
self.charbuffer = []
self.writing = False
# Call when raw text is read
def characters(self, data):
if self.writing:
self.charbuffer.append(data)
# Call when an element starts
def startElement(self, tag, attributes):
if tag == "Name":
self.writing = True
if tag == "DataType":
self.currenttype = attributes["type"]
# Call when an elements ends
def endElement(self, tag):
if tag == "Name":
if not self.currentpset:
self.currentpset = "".join(self.charbuffer)
else:
if not self.currentprop:
self.currentprop = "".join(self.charbuffer)
self.writing = False
self.charbuffer = []
elif tag == "PropertyDef":
if self.currentprop and self.currenttype:
self.currentlist.append([self.currentprop, self.currenttype])
self.currentprop = None
self.currenttype = None
elif tag == "PropertySetDef":
if self.currentpset and self.currentlist:
self.psets[self.currentpset] = self.currentlist
self.currentpset = None
self.currentlist = []
defpath = "pset_definitions.xml"
outpath = "pset_definitions.csv"
if os.path.exists(defpath):
handler = PropertyDefHandler()
parser = xml.sax.make_parser()
# parser.setFeature(xml.sax.handler.feature_namespaces, 0)
parser.setContentHandler(handler)
parser.parse(defpath)
psets = handler.psets
import csv
with open(outpath, "w", encoding="utf-8") as csvfile:
csvfile = csv.writer(csvfile, delimiter=";")
for key, values in psets.items():
r = [key]
for value in values:
r.extend(value)
csvfile.writerow(r)
print("successfully exported ", outpath)

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff