Arch: Added IFC properties editor to edit mode of all Arch objects

This commit is contained in:
Yorik van Havre
2018-07-07 21:46:49 -03:00
parent e64657abe0
commit 04b47c702d
6 changed files with 1027 additions and 190 deletions

View File

@@ -71,7 +71,16 @@ IFCTYPES = ["IfcActuator", "IfcAirTerminal", "IfcAirTerminalBox", "IfcAirToAirHe
# Possible roles for FreeCAD BIM objects
IfcRoles = ['Undefined']+[''.join(map(lambda x: x if x.islower() else " "+x, t[3:]))[1:] for t in IFCTYPES]
import FreeCAD,Draft,ArchCommands,math
# Property types
SimplePropertyTypes = ["IfcInteger","IfcReal","IfcBoolean","IfcIdentifier","IfcText","IfcLabel","IfcLogical"]
MeasurePropertyTypes = ["IfcVolumeMeasure","IfcTimeMeasure","IfcThermodynamicTemperatureMeasure","IfcSolidAngleMeasure",
"IfcPositiveRatioMeasure","IfcRatioMeasure","IfcPositivePlaneAngleMeasure","IfcPlaneAngleMeasure",
"IfcParameterValue","IfcNumericMeasure","IfcMassMeasure","IfcPositiveLengthMeasure",
"IfcLengthMeasure","IfcElectricCurrentMeasure","IfcDescriptiveMeasure","IfcCountMeasure",
"IfcContextDependentMeasure","IfcAreaMeasure","IfcAmountOfSubstanceMeasure",
"IfcLuminousIntensityMeasure","IfcNormalisedRatioMeasure","IfcComplexNumber"]
import FreeCAD,Draft,ArchCommands,math,sys
from FreeCAD import Vector
if FreeCAD.GuiUp:
import FreeCADGui
@@ -200,197 +209,10 @@ def removeFromComponent(compobject,subobject):
ArchCommands.setAsSubcomponent(subobject)
class SelectionTaskPanel:
"""A temporary TaskPanel to wait for a selection"""
def __init__(self):
self.baseform = QtGui.QLabel()
self.baseform.setText(QtGui.QApplication.translate("Arch", "Please select a base object", None))
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Cancel)
def reject(self):
if hasattr(FreeCAD,"ArchObserver"):
FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver)
del FreeCAD.ArchObserver
return True
class ComponentTaskPanel:
'''The default TaskPanel for all Arch components'''
def __init__(self):
# the panel has a tree widget that contains categories
# for the subcomponents, such as additions, subtractions.
# the categories are shown only if they are not empty.
self.obj = None
self.attribs = ["Base","Additions","Subtractions","Objects","Components","Axes","Fixtures","Group","Hosts"]
self.baseform = QtGui.QWidget()
self.baseform.setObjectName("TaskPanel")
self.grid = QtGui.QGridLayout(self.baseform)
self.grid.setObjectName("grid")
self.title = QtGui.QLabel(self.baseform)
self.grid.addWidget(self.title, 0, 0, 1, 2)
self.form = self.baseform
# tree
self.tree = QtGui.QTreeWidget(self.baseform)
self.grid.addWidget(self.tree, 1, 0, 1, 2)
self.tree.setColumnCount(1)
self.tree.header().hide()
# buttons
self.addButton = QtGui.QPushButton(self.baseform)
self.addButton.setObjectName("addButton")
self.addButton.setIcon(QtGui.QIcon(":/icons/Arch_Add.svg"))
self.grid.addWidget(self.addButton, 3, 0, 1, 1)
self.addButton.setEnabled(False)
self.delButton = QtGui.QPushButton(self.baseform)
self.delButton.setObjectName("delButton")
self.delButton.setIcon(QtGui.QIcon(":/icons/Arch_Remove.svg"))
self.grid.addWidget(self.delButton, 3, 1, 1, 1)
self.delButton.setEnabled(False)
QtCore.QObject.connect(self.addButton, QtCore.SIGNAL("clicked()"), self.addElement)
QtCore.QObject.connect(self.delButton, QtCore.SIGNAL("clicked()"), self.removeElement)
QtCore.QObject.connect(self.tree, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.check)
QtCore.QObject.connect(self.tree, QtCore.SIGNAL("itemDoubleClicked(QTreeWidgetItem *,int)"), self.editObject)
self.update()
def isAllowedAlterSelection(self):
return True
def isAllowedAlterView(self):
return True
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok)
def check(self,wid,col):
if not wid.parent():
self.delButton.setEnabled(False)
if self.obj:
sel = FreeCADGui.Selection.getSelection()
if sel:
if not(self.obj in sel):
self.addButton.setEnabled(True)
else:
self.delButton.setEnabled(True)
self.addButton.setEnabled(False)
def getIcon(self,obj):
if hasattr(obj.ViewObject,"Proxy"):
if hasattr(obj.ViewObject.Proxy,"getIcon"):
return QtGui.QIcon(obj.ViewObject.Proxy.getIcon())
if obj.isDerivedFrom("Sketcher::SketchObject"):
return QtGui.QIcon(":/icons/Sketcher_Sketch.svg")
if obj.isDerivedFrom("App::DocumentObjectGroup"):
return QtGui.QApplication.style().standardIcon(QtGui.QStyle.SP_DirIcon)
return QtGui.QIcon(":/icons/Tree_Part.svg")
def update(self):
'fills the treewidget'
self.tree.clear()
dirIcon = QtGui.QApplication.style().standardIcon(QtGui.QStyle.SP_DirIcon)
for a in self.attribs:
setattr(self,"tree"+a,QtGui.QTreeWidgetItem(self.tree))
c = getattr(self,"tree"+a)
c.setIcon(0,dirIcon)
c.ChildIndicatorPolicy = 2
if self.obj:
if not hasattr(self.obj,a):
c.setHidden(True)
else:
c.setHidden(True)
if self.obj:
for attrib in self.attribs:
if hasattr(self.obj,attrib):
Oattrib = getattr(self.obj,attrib)
Tattrib = getattr(self,"tree"+attrib)
if Oattrib:
if attrib == "Base":
Oattrib = [Oattrib]
for o in Oattrib:
item = QtGui.QTreeWidgetItem()
item.setText(0,o.Label)
item.setToolTip(0,o.Name)
item.setIcon(0,self.getIcon(o))
Tattrib.addChild(item)
self.tree.expandItem(Tattrib)
self.retranslateUi(self.baseform)
def addElement(self):
it = self.tree.currentItem()
if it:
mod = None
for a in self.attribs:
if it.text(0) == getattr(self,"tree"+a).text(0):
mod = a
for o in FreeCADGui.Selection.getSelection():
addToComponent(self.obj,o,mod)
self.update()
def removeElement(self):
it = self.tree.currentItem()
if it:
comp = FreeCAD.ActiveDocument.getObject(str(it.toolTip(0)))
removeFromComponent(self.obj,comp)
self.update()
def accept(self):
FreeCAD.ActiveDocument.recompute()
FreeCADGui.ActiveDocument.resetEdit()
return True
def editObject(self,wid,col):
if wid.parent():
obj = FreeCAD.ActiveDocument.getObject(str(wid.toolTip(0)))
if obj:
self.obj.ViewObject.Transparency = 80
self.obj.ViewObject.Selectable = False
obj.ViewObject.show()
self.accept()
if obj.isDerivedFrom("Sketcher::SketchObject"):
FreeCADGui.activateWorkbench("SketcherWorkbench")
FreeCAD.ArchObserver = ArchSelectionObserver(self.obj,obj)
FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver)
FreeCADGui.ActiveDocument.setEdit(obj.Name,0)
def retranslateUi(self, TaskPanel):
self.baseform.setWindowTitle(QtGui.QApplication.translate("Arch", "Components", None))
self.delButton.setText(QtGui.QApplication.translate("Arch", "Remove", None))
self.addButton.setText(QtGui.QApplication.translate("Arch", "Add", None))
self.title.setText(QtGui.QApplication.translate("Arch", "Components of this object", None))
self.treeBase.setText(0,QtGui.QApplication.translate("Arch", "Base component", None))
self.treeAdditions.setText(0,QtGui.QApplication.translate("Arch", "Additions", None))
self.treeSubtractions.setText(0,QtGui.QApplication.translate("Arch", "Subtractions", None))
self.treeObjects.setText(0,QtGui.QApplication.translate("Arch", "Objects", None))
self.treeAxes.setText(0,QtGui.QApplication.translate("Arch", "Axes", None))
self.treeComponents.setText(0,QtGui.QApplication.translate("Arch", "Components", None))
self.treeFixtures.setText(0,QtGui.QApplication.translate("Arch", "Fixtures", None))
self.treeGroup.setText(0,QtGui.QApplication.translate("Arch", "Group", None))
self.treeHosts.setText(0,QtGui.QApplication.translate("Arch", "Hosts", None))
class Component:
"The default Arch Component object"
def __init__(self,obj):
@@ -1132,3 +954,494 @@ class ArchSelectionObserver:
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(self.watched)
FreeCADGui.runCommand(self.nextCommand)
class SelectionTaskPanel:
"""A temporary TaskPanel to wait for a selection"""
def __init__(self):
self.baseform = QtGui.QLabel()
self.baseform.setText(QtGui.QApplication.translate("Arch", "Please select a base object", None))
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Cancel)
def reject(self):
if hasattr(FreeCAD,"ArchObserver"):
FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver)
del FreeCAD.ArchObserver
return True
class ComponentTaskPanel:
'''The default TaskPanel for all Arch components'''
def __init__(self):
# the panel has a tree widget that contains categories
# for the subcomponents, such as additions, subtractions.
# the categories are shown only if they are not empty.
self.obj = None
self.attribs = ["Base","Additions","Subtractions","Objects","Components","Axes","Fixtures","Group","Hosts"]
self.baseform = QtGui.QWidget()
self.baseform.setObjectName("TaskPanel")
self.grid = QtGui.QGridLayout(self.baseform)
self.grid.setObjectName("grid")
self.title = QtGui.QLabel(self.baseform)
self.grid.addWidget(self.title, 0, 0, 1, 2)
self.form = self.baseform
# tree
self.tree = QtGui.QTreeWidget(self.baseform)
self.grid.addWidget(self.tree, 1, 0, 1, 2)
self.tree.setColumnCount(1)
self.tree.header().hide()
# buttons
self.addButton = QtGui.QPushButton(self.baseform)
self.addButton.setObjectName("addButton")
self.addButton.setIcon(QtGui.QIcon(":/icons/Arch_Add.svg"))
self.grid.addWidget(self.addButton, 3, 0, 1, 1)
self.addButton.setEnabled(False)
self.delButton = QtGui.QPushButton(self.baseform)
self.delButton.setObjectName("delButton")
self.delButton.setIcon(QtGui.QIcon(":/icons/Arch_Remove.svg"))
self.grid.addWidget(self.delButton, 3, 1, 1, 1)
self.delButton.setEnabled(False)
self.ifcButton = QtGui.QPushButton(self.baseform)
self.ifcButton.setObjectName("ifcButton")
self.ifcButton.setIcon(QtGui.QIcon(":/icons/IFC.svg"))
self.grid.addWidget(self.ifcButton, 4, 0, 1, 2)
self.ifcButton.hide()
QtCore.QObject.connect(self.addButton, QtCore.SIGNAL("clicked()"), self.addElement)
QtCore.QObject.connect(self.delButton, QtCore.SIGNAL("clicked()"), self.removeElement)
QtCore.QObject.connect(self.ifcButton, QtCore.SIGNAL("clicked()"), self.editIfcProperties)
QtCore.QObject.connect(self.tree, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.check)
QtCore.QObject.connect(self.tree, QtCore.SIGNAL("itemDoubleClicked(QTreeWidgetItem *,int)"), self.editObject)
self.update()
def isAllowedAlterSelection(self):
return True
def isAllowedAlterView(self):
return True
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok)
def check(self,wid,col):
if not wid.parent():
self.delButton.setEnabled(False)
if self.obj:
sel = FreeCADGui.Selection.getSelection()
if sel:
if not(self.obj in sel):
self.addButton.setEnabled(True)
else:
self.delButton.setEnabled(True)
self.addButton.setEnabled(False)
def getIcon(self,obj):
if hasattr(obj.ViewObject,"Proxy"):
if hasattr(obj.ViewObject.Proxy,"getIcon"):
return QtGui.QIcon(obj.ViewObject.Proxy.getIcon())
if obj.isDerivedFrom("Sketcher::SketchObject"):
return QtGui.QIcon(":/icons/Sketcher_Sketch.svg")
if obj.isDerivedFrom("App::DocumentObjectGroup"):
return QtGui.QApplication.style().standardIcon(QtGui.QStyle.SP_DirIcon)
return QtGui.QIcon(":/icons/Tree_Part.svg")
def update(self):
'fills the treewidget'
self.tree.clear()
dirIcon = QtGui.QApplication.style().standardIcon(QtGui.QStyle.SP_DirIcon)
for a in self.attribs:
setattr(self,"tree"+a,QtGui.QTreeWidgetItem(self.tree))
c = getattr(self,"tree"+a)
c.setIcon(0,dirIcon)
c.ChildIndicatorPolicy = 2
if self.obj:
if not hasattr(self.obj,a):
c.setHidden(True)
else:
c.setHidden(True)
if self.obj:
for attrib in self.attribs:
if hasattr(self.obj,attrib):
Oattrib = getattr(self.obj,attrib)
Tattrib = getattr(self,"tree"+attrib)
if Oattrib:
if attrib == "Base":
Oattrib = [Oattrib]
for o in Oattrib:
item = QtGui.QTreeWidgetItem()
item.setText(0,o.Label)
item.setToolTip(0,o.Name)
item.setIcon(0,self.getIcon(o))
Tattrib.addChild(item)
self.tree.expandItem(Tattrib)
if hasattr(self.obj,"IfcProperties"):
if isinstance(self.obj.IfcProperties,dict):
self.ifcButton.show()
self.retranslateUi(self.baseform)
def addElement(self):
it = self.tree.currentItem()
if it:
mod = None
for a in self.attribs:
if it.text(0) == getattr(self,"tree"+a).text(0):
mod = a
for o in FreeCADGui.Selection.getSelection():
addToComponent(self.obj,o,mod)
self.update()
def removeElement(self):
it = self.tree.currentItem()
if it:
comp = FreeCAD.ActiveDocument.getObject(str(it.toolTip(0)))
removeFromComponent(self.obj,comp)
self.update()
def accept(self):
FreeCAD.ActiveDocument.recompute()
FreeCADGui.ActiveDocument.resetEdit()
return True
def editObject(self,wid,col):
if wid.parent():
obj = FreeCAD.ActiveDocument.getObject(str(wid.toolTip(0)))
if obj:
self.obj.ViewObject.Transparency = 80
self.obj.ViewObject.Selectable = False
obj.ViewObject.show()
self.accept()
if obj.isDerivedFrom("Sketcher::SketchObject"):
FreeCADGui.activateWorkbench("SketcherWorkbench")
FreeCAD.ArchObserver = ArchSelectionObserver(self.obj,obj)
FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver)
FreeCADGui.ActiveDocument.setEdit(obj.Name,0)
def retranslateUi(self, TaskPanel):
self.baseform.setWindowTitle(QtGui.QApplication.translate("Arch", "Components", None))
self.delButton.setText(QtGui.QApplication.translate("Arch", "Remove", None))
self.addButton.setText(QtGui.QApplication.translate("Arch", "Add", None))
self.title.setText(QtGui.QApplication.translate("Arch", "Components of this object", None))
self.treeBase.setText(0,QtGui.QApplication.translate("Arch", "Base component", None))
self.treeAdditions.setText(0,QtGui.QApplication.translate("Arch", "Additions", None))
self.treeSubtractions.setText(0,QtGui.QApplication.translate("Arch", "Subtractions", None))
self.treeObjects.setText(0,QtGui.QApplication.translate("Arch", "Objects", None))
self.treeAxes.setText(0,QtGui.QApplication.translate("Arch", "Axes", None))
self.treeComponents.setText(0,QtGui.QApplication.translate("Arch", "Components", None))
self.treeFixtures.setText(0,QtGui.QApplication.translate("Arch", "Fixtures", None))
self.treeGroup.setText(0,QtGui.QApplication.translate("Arch", "Group", None))
self.treeHosts.setText(0,QtGui.QApplication.translate("Arch", "Hosts", None))
self.ifcButton.setText(QtGui.QApplication.translate("Arch", "Edit IFC properties", None))
def editIfcProperties(self):
if hasattr(self,"ifcEditor"):
if self.ifcEditor:
self.ifcEditor.hide()
del self.ifcEditor
if not self.obj:
return
if not hasattr(self.obj,"IfcProperties"):
return
if not isinstance(self.obj.IfcProperties,dict):
return
import Arch_rc,csv,os
# get presets
self.ptypes = SimplePropertyTypes + MeasurePropertyTypes
self.plabels = [''.join(map(lambda x: x if x.islower() else " "+x, t[3:]))[1:] for t in self.ptypes]
self.psetdefs = {}
psetspath = os.path.join(FreeCAD.getResourceDir(),"Mod","Arch","Presets","pset_definitions.csv")
if os.path.exists(psetspath):
with open(psetspath, "r") as csvfile:
reader = csv.reader(csvfile, delimiter=';')
for row in reader:
self.psetdefs[row[0]] = row[1:]
self.psetkeys = [''.join(map(lambda x: x if x.islower() else " "+x, t[5:]))[1:] for t in self.psetdefs.keys()]
self.psetkeys.sort()
self.ifcEditor = FreeCADGui.PySideUic.loadUi(":/ui/DialogIfcProperties.ui")
# center the dialog over FreeCAD window
mw = FreeCADGui.getMainWindow()
self.ifcEditor.move(mw.frameGeometry().topLeft() + mw.rect().center() - self.ifcEditor.rect().center())
self.ifcModel = QtGui.QStandardItemModel()
self.ifcEditor.treeProperties.setModel(self.ifcModel)
#self.ifcEditor.treeProperties.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
self.ifcEditor.treeProperties.setUniformRowHeights(True)
self.ifcEditor.treeProperties.setItemDelegate(IfcEditorDelegate(dialog=self,ptypes=self.ptypes,plabels=self.plabels))
self.ifcModel.setHorizontalHeaderLabels([QtGui.QApplication.translate("Arch", "Property", None),
QtGui.QApplication.translate("Arch", "Type", None),
QtGui.QApplication.translate("Arch", "Value", None)])
# set combos
self.ifcEditor.comboProperty.addItems([QtGui.QApplication.translate("Arch", "Add property...", None)]+self.plabels)
self.ifcEditor.comboPset.addItems([QtGui.QApplication.translate("Arch", "Add property set...", None),
QtGui.QApplication.translate("Arch", "New...", None)]+self.psetkeys)
# set UUID
if "IfcUID" in self.obj.IfcAttributes:
self.ifcEditor.labelUUID.setText(self.obj.IfcAttributes["IfcUID"])
# fill the tree
psets = {}
for pname,value in self.obj.IfcProperties.items():
# properties in IfcProperties dict are stored as "key":"pset;;type;;value" or "key":"type;;value"
value = value.split(";;")
if len(value) == 3:
pset = value[0]
ptype = value[1]
pvalue = value[2]
elif len(value) == 2:
pset = "Default property set"
ptype = value[0]
pvalue = value[1]
else:
continue
plabel = ptype
if ptype in self.ptypes:
plabel = self.plabels[self.ptypes.index(ptype)]
psets.setdefault(pset,[]).append([pname,plabel,pvalue])
for pset,plists in psets.items():
top = QtGui.QStandardItem(pset)
top.setDragEnabled(False)
top.setToolTip("PropertySet")
self.ifcModel.appendRow([top,QtGui.QStandardItem(),QtGui.QStandardItem()])
for plist in plists:
it1 = QtGui.QStandardItem(plist[0])
it1.setDropEnabled(False)
it2 = QtGui.QStandardItem(plist[1])
it2.setDropEnabled(False)
it3 = QtGui.QStandardItem(plist[2])
it3.setDropEnabled(False)
top.appendRow([it1,it2,it3])
top.sortChildren(0)
# span top levels
idx = self.ifcModel.invisibleRootItem().index()
for i in range(self.ifcModel.rowCount()):
if self.ifcModel.item(i,0).hasChildren():
self.ifcEditor.treeProperties.setFirstColumnSpanned(i, idx, True)
self.ifcEditor.treeProperties.expandAll()
QtCore.QObject.connect(self.ifcEditor.buttonBox, QtCore.SIGNAL("accepted()"), self.acceptIfcProperties)
QtCore.QObject.connect(self.ifcEditor.comboProperty, QtCore.SIGNAL("currentIndexChanged(int)"), self.addIfcProperty)
QtCore.QObject.connect(self.ifcEditor.comboPset, QtCore.SIGNAL("currentIndexChanged(int)"), self.addIfcPset)
QtCore.QObject.connect(self.ifcEditor.buttonDelete, QtCore.SIGNAL("clicked()"), self.removeIfcProperty)
self.ifcEditor.treeProperties.setSortingEnabled(True)
# set checkboxes
if "FlagForceBrep" in self.obj.IfcAttributes:
self.ifcEditor.checkBrep.setChecked(self.obj.IfcAttributes["FlagForceBrep"] == "True")
if "FlagParametric" in self.obj.IfcAttributes:
self.ifcEditor.checkParametric.setChecked(self.obj.IfcAttributes["FlagParametric"] == "True")
self.ifcEditor.show()
def acceptIfcProperties(self):
if hasattr(self,"ifcEditor") and self.ifcEditor:
self.ifcEditor.hide()
ifcdict = {}
for row in range(self.ifcModel.rowCount()):
pset = self.ifcModel.item(row,0).text()
if self.ifcModel.item(row,0).hasChildren():
for childrow in range(self.ifcModel.item(row,0).rowCount()):
prop = self.ifcModel.item(row,0).child(childrow,0).text()
ptype = self.ifcModel.item(row,0).child(childrow,1).text()
if not ptype.startswith("Ifc"):
ptype = self.ptypes[self.plabels.index(ptype)]
pvalue = self.ifcModel.item(row,0).child(childrow,2).text()
if sys.version_info.major >= 3:
ifcdict[prop] = pset+";;"+ptype+";;"+pvalue
else:
# keys cannot be unicode
ifcdict[prop.encode("utf8")] = pset+";;"+ptype+";;"+pvalue
ifcattrs = self.obj.IfcAttributes
ifcattrs["IfcUID"] = self.ifcEditor.labelUUID.text()
ifcattrs["FlagForceBrep"] = str(self.ifcEditor.checkBrep.isChecked())
ifcattrs["FlagParametric"] = str(self.ifcEditor.checkParametric.isChecked())
if (ifcdict != self.obj.IfcProperties) or (ifcattrs != self.obj.IfcAttributes):
FreeCAD.ActiveDocument.openTransaction("Change Ifc Properties")
if ifcdict != self.obj.IfcProperties:
self.obj.IfcProperties = ifcdict
if ifcattrs != self.obj.IfcAttributes:
self.obj.IfcAttributes = ifcattrs
FreeCAD.ActiveDocument.commitTransaction()
del self.ifcEditor
def addIfcProperty(self,idx=0,pset=None,prop=None,ptype=None):
if hasattr(self,"ifcEditor") and self.ifcEditor:
if not pset:
sel = self.ifcEditor.treeProperties.selectedIndexes()
if sel:
item = self.ifcModel.itemFromIndex(sel[0])
if item.toolTip() == "PropertySet":
pset = item
if pset:
if not prop:
prop = QtGui.QApplication.translate("Arch", "New property", None)
if not ptype:
if idx > 0:
ptype = self.plabels[idx-1]
if prop and ptype:
if ptype in self.ptypes:
ptype = self.plabels[self.ptypes.index(ptype)]
it1 = QtGui.QStandardItem(prop)
it1.setDropEnabled(False)
it2 = QtGui.QStandardItem(ptype)
it2.setDropEnabled(False)
it3 = QtGui.QStandardItem()
it3.setDropEnabled(False)
pset.appendRow([it1,it2,it3])
if idx != 0:
self.ifcEditor.comboProperty.setCurrentIndex(0)
def addIfcPset(self,idx=0):
if hasattr(self,"ifcEditor") and self.ifcEditor:
if idx == 1:
top = QtGui.QStandardItem(QtGui.QApplication.translate("Arch", "New property set", None))
top.setDragEnabled(False)
top.setToolTip("PropertySet")
self.ifcModel.appendRow([top,QtGui.QStandardItem(),QtGui.QStandardItem()])
elif idx > 1:
psetlabel = self.psetkeys[idx-2]
psetdef = "Pset_"+psetlabel.replace(" ","")
if psetdef in self.psetdefs:
top = QtGui.QStandardItem(psetdef)
top.setDragEnabled(False)
top.setToolTip("PropertySet")
self.ifcModel.appendRow([top,QtGui.QStandardItem(),QtGui.QStandardItem()])
for i in range(0,len(self.psetdefs[psetdef]),2):
self.addIfcProperty(pset=top,prop=self.psetdefs[psetdef][i],ptype=self.psetdefs[psetdef][i+1])
if idx != 0:
# span top levels
idx = self.ifcModel.invisibleRootItem().index()
for i in range(self.ifcModel.rowCount()):
if self.ifcModel.item(i,0).hasChildren():
self.ifcEditor.treeProperties.setFirstColumnSpanned(i, idx, True)
self.ifcEditor.treeProperties.expandAll()
self.ifcEditor.comboPset.setCurrentIndex(0)
def removeIfcProperty(self):
if hasattr(self,"ifcEditor") and self.ifcEditor:
sel = self.ifcEditor.treeProperties.selectedIndexes()
if sel:
if self.ifcModel.itemFromIndex(sel[0]).toolTip() == "PropertySet":
self.ifcModel.takeRow(sel[0].row())
else:
pset = self.ifcModel.itemFromIndex(sel[0].parent())
pset.takeRow(sel[0].row())
class IfcEditorDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent=None, dialog=None, ptypes=[], plabels=[], *args):
self.dialog = dialog
QtGui.QStyledItemDelegate.__init__(self, parent, *args)
self.ptypes = ptypes
self.plabels = plabels
def createEditor(self,parent,option,index):
if index.column() == 0: # property name
editor = QtGui.QLineEdit(parent)
elif index.column() == 1: # property type
editor = QtGui.QComboBox(parent)
else: # property value
ptype = index.sibling(index.row(),1).data()
if "Integer" in ptype:
editor = QtGui.QSpinBox(parent)
elif "Real" in ptype:
editor = QtGui.QDoubleSpinBox(parent)
editor.setDecimals(FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("Decimals",2))
elif ("Boolean" in ptype) or ("Logical" in ptype):
editor = QtGui.QComboBox(parent)
editor.addItems(["True","False"])
elif "Measure" in ptype:
editor = FreeCADGui.UiLoader().createWidget("Gui::InputField")
editor.setParent(parent)
else:
editor = QtGui.QLineEdit(parent)
editor.setObjectName("editor_"+ptype)
return editor
def setEditorData(self, editor, index):
if index.column() == 0:
editor.setText(index.data())
elif index.column() == 1:
editor.addItems(self.plabels)
if index.data() in self.plabels:
idx = self.plabels.index(index.data())
editor.setCurrentIndex(idx)
else:
if "Integer" in editor.objectName():
try:
editor.setValue(int(index.data()))
except:
editor.setValue(0)
elif "Real" in editor.objectName():
try:
editor.setValue(float(index.data()))
except:
editor.setValue(0)
elif ("Boolean" in editor.objectName()) or ("Logical" in editor.objectName()):
try:
editor.setCurrentIndex(["true","false"].index(index.data().lower()))
except:
editor.setCurrentIndex(1)
elif "Measure" in editor.objectName():
try:
editor.setText(index.data())
except:
editor.setValue(0)
else:
editor.setText(index.data())
def setModelData(self, editor, model, index):
if index.column() == 0:
model.setData(index,editor.text())
elif index.column() == 1:
if editor.currentIndex() > -1:
idx = editor.currentIndex()
data = self.plabels[idx]
model.setData(index,data)
else:
if ("Integer" in editor.objectName()) or ("Real" in editor.objectName()):
model.setData(index,str(editor.value()))
elif ("Boolean" in editor.objectName()) or ("Logical" in editor.objectName()):
model.setData(index,editor.currentText())
elif "Measure" in editor.objectName():
model.setData(index,editor.property("text"))
else:
model.setData(index,editor.text())
self.dialog.update()

View File

@@ -51,6 +51,7 @@ SET(Dice3DS_SRCS
SET(Arch_presets
Presets/profiles.csv
Presets/pset_definitions.csv
)
SOURCE_GROUP("" FILES ${Arch_SRCS})

File diff suppressed because one or more lines are too long

View File

@@ -103,6 +103,7 @@
<file>ui/DialogBimServerLogin.ui</file>
<file>ui/DialogDisplayText.ui</file>
<file>ui/ArchNest.ui</file>
<file>ui/DialogIfcProperties.ui</file>
<file>translations/Arch_af.qm</file>
<file>translations/Arch_de.qm</file>
<file>translations/Arch_fi.qm</file>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>289</width>
<height>548</height>
</rect>
</property>
<property name="windowTitle">
<string>IFC properties editor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>IFC UUID:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="labelUUID">
<property name="placeholderText">
<string>Leave this empty to generate one at export</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>List of IFC properties for this object. Double-click to edit, drag and drop to reorganize</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTreeView" name="treeProperties"/>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QComboBox" name="comboProperty"/>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="comboPset"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="buttonDelete">
<property name="text">
<string>Delete selected property/set</string>
</property>
<property name="icon">
<iconset theme="gtk-delete">
<normaloff>../../../../../../../.FreeCAD/Mod/BIM</normaloff>../../../../../../../.FreeCAD/Mod/BIM</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBrep">
<property name="text">
<string>Force exporting geometry as BREP</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkParametric">
<property name="text">
<string>Force export full FreeCAD parametric data</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1336,7 +1336,14 @@ def export(exportList,filename):
elif ptype == "IfcInteger":
pvalue = int(pvalue)
else:
pvalue = float(pvalue)
try:
pvalue = float(pvalue)
except:
try:
pvalue = FreeCAD.Units.Quantity(pvalue).Value
except:
pvalue = pvalue.encode("utf8")
if DEBUG:print(" warning: unable to export property as numeric value:",key,pvalue)
p = ifcfile.createIfcPropertySingleValue(str(key),None,ifcfile.create_entity(str(ptype),pvalue),None)
psets.setdefault(pset,[]).append(p)
for pname,props in psets.items():