BIM: prevent user to remove core properties

This commit is contained in:
Florian Foinant-Willig
2025-03-16 20:50:02 +01:00
committed by Kacper Donat
parent d5e2fdf8fd
commit 8a4c61ec5a
43 changed files with 568 additions and 551 deletions

View File

@@ -99,7 +99,7 @@ def show_classification(obj):
for rel in ref.ClassificationRefForObjects:
if element in rel.RelatedObjects:
if not "Classification" in obj.PropertiesList:
obj.addProperty("App::PropertyString", "Classification", "IFC")
obj.addProperty("App::PropertyString", "Classification", "IFC", locked=True)
sname = system.Name
cname = ref.Name or ref.Identification
obj.Classification = sname + " " + cname

View File

@@ -49,12 +49,12 @@ def add_geom_properties(obj):
ext = rep.Items[0]
if "ExtrusionDepth" not in obj.PropertiesList:
obj.addProperty(
"App::PropertyLength", "ExtrusionDepth", "Geometry"
"App::PropertyLength", "ExtrusionDepth", "Geometry", locked=True
)
obj.ExtrusionDepth = ext.Depth * scaling
if "ExtrusionDirection" not in obj.PropertiesList:
obj.addProperty(
"App::PropertyVector", "ExtrusionDirection", "Geometry"
"App::PropertyVector", "ExtrusionDirection", "Geometry", locked=True
)
obj.ExtrusionDirection = FreeCAD.Vector(
ext.ExtrudedDirection.DirectionRatios
@@ -64,12 +64,12 @@ def add_geom_properties(obj):
if ext.SweptArea.is_a("IfcRectangleProfileDef"):
if "RectangleLength" not in obj.PropertiesList:
obj.addProperty(
"App::PropertyLength", "RectangleLength", "Geometry"
"App::PropertyLength", "RectangleLength", "Geometry", locked=True
)
obj.RectangleLength = ext.SweptArea.XDim * scaling
if "RectangleWidth" not in obj.PropertiesList:
obj.addProperty(
"App::PropertyLength", "RectangleWidth", "Geometry"
"App::PropertyLength", "RectangleWidth", "Geometry", locked=True
)
obj.RectangleWidth = ext.SweptArea.YDim * scaling
@@ -81,6 +81,7 @@ def add_geom_properties(obj):
"App::PropertyVectorList",
"PolylinePoints",
"Geometry",
locked=True,
)
points = [
p.Coordinates for p in ext.SweptArea.OuterCurve.Points
@@ -103,14 +104,14 @@ def add_geom_properties(obj):
"WebThickness",
]:
if hasattr(ext.SweptArea, p):
obj.addProperty("App::PropertyLength", p, "Geometry")
obj.addProperty("App::PropertyLength", p, "Geometry", locked=True)
value = getattr(ext.SweptArea, p)
if not value:
value = 0
value = value * scaling
setattr(obj, p, value)
obj.addProperty(
"App::PropertyString", "ProfileName", "Geometry"
"App::PropertyString", "ProfileName", "Geometry", locked=True
)
obj.ProfileName = ext.SweptArea.ProfileName
@@ -129,6 +130,7 @@ def add_geom_properties(obj):
"App::PropertyPosition",
"AxisStart",
"Geometry",
locked=True,
)
obj.AxisStart = FreeCAD.Vector(
pol.Points[0].Coordinates
@@ -138,6 +140,7 @@ def add_geom_properties(obj):
"App::PropertyPosition",
"AxisEnd",
"Geometry",
locked=True,
)
obj.AxisEnd = FreeCAD.Vector(
pol.Points[1].Coordinates

View File

@@ -72,7 +72,7 @@ def show_material(obj):
if not material:
return
if not hasattr(obj, "Material"):
obj.addProperty("App::PropertyLink", "Material", "IFC")
obj.addProperty("App::PropertyLink", "Material", "IFC", locked=True)
project = ifc_tools.get_project(obj)
matobj = create_material(material, project, recursive=True)
obj.Material = matobj

View File

@@ -166,7 +166,7 @@ def show_psets(obj):
value = [value]
else:
print(pname, gname, obj.PropertiesList)
obj.addProperty(ftype, pname, gname, ttip)
obj.addProperty(ftype, pname, gname, ttip, locked=True)
if pname in obj.PropertiesList:
setattr(obj, pname, value)

View File

@@ -138,7 +138,7 @@ def convert_document(document, filename=None, shapemode=0, strategy=0, silent=Fa
"""
if "Proxy" not in document.PropertiesList:
document.addProperty("App::PropertyPythonObject", "Proxy")
document.addProperty("App::PropertyPythonObject", "Proxy", locked=True)
document.setPropertyStatus("Proxy", "Transient")
document.Proxy = ifc_objects.document_object()
ifcfile, project, full = setup_project(document, filename, shapemode, silent)
@@ -165,9 +165,9 @@ def setup_project(proj, filename, shapemode, silent):
full = False
d = "The path to the linked IFC file"
if "IfcFilePath" not in proj.PropertiesList:
proj.addProperty("App::PropertyFile", "IfcFilePath", "Base", d)
proj.addProperty("App::PropertyFile", "IfcFilePath", "Base", d, locked=True)
if "Modified" not in proj.PropertiesList:
proj.addProperty("App::PropertyBool", "Modified", "Base")
proj.addProperty("App::PropertyBool", "Modified", "Base", locked=True)
proj.setPropertyStatus("Modified", "Hidden")
if filename:
# opening existing file
@@ -185,7 +185,7 @@ def setup_project(proj, filename, shapemode, silent):
proj.Proxy.ifcfile = ifcfile
add_properties(proj, ifcfile, project, shapemode=shapemode)
if "Schema" not in proj.PropertiesList:
proj.addProperty("App::PropertyEnumeration", "Schema", "Base")
proj.addProperty("App::PropertyEnumeration", "Schema", "Base", locked=True)
# bug in FreeCAD - to avoid a crash, pre-populate the enum with one value
proj.Schema = [ifcfile.wrapped_data.schema_name()]
proj.Schema = ifcfile.wrapped_data.schema_name()
@@ -564,7 +564,7 @@ def add_object(document, otype=None, oname="IfcObject"):
obj = document.addObject("App::FeaturePython", oname, proxy, None, False)
if obj.ViewObject:
view_layer.ViewProviderLayer(obj.ViewObject)
obj.ViewObject.addProperty("App::PropertyBool", "HideChildren", "Layer")
obj.ViewObject.addProperty("App::PropertyBool", "HideChildren", "Layer", locked=True)
obj.ViewObject.HideChildren = True
elif otype == "group":
vproxy = ifc_viewproviders.ifc_vp_group()
@@ -610,9 +610,9 @@ def add_properties(
else:
obj.Label = "_" + ifcentity.is_a()
if isinstance(obj, FreeCAD.DocumentObject) and "Group" not in obj.PropertiesList:
obj.addProperty("App::PropertyLinkList", "Group", "Base")
obj.addProperty("App::PropertyLinkList", "Group", "Base", locked=True)
if "ShapeMode" not in obj.PropertiesList:
obj.addProperty("App::PropertyEnumeration", "ShapeMode", "Base")
obj.addProperty("App::PropertyEnumeration", "ShapeMode", "Base", locked=True)
shapemodes = [
"Shape",
"Coin",
@@ -625,7 +625,7 @@ def add_properties(
if not obj.isDerivedFrom("Part::Feature"):
obj.setPropertyStatus("ShapeMode", "Hidden")
if ifcentity.is_a("IfcProduct"):
obj.addProperty("App::PropertyLink", "Type", "IFC")
obj.addProperty("App::PropertyLink", "Type", "IFC", locked=True)
attr_defs = ifcentity.wrapped_data.declaration().as_entity().all_attributes()
try:
info_ifcentity = ifcentity.get_info()
@@ -650,7 +650,7 @@ def add_properties(
if attr == "Class":
# main enum property, not saved to file
if attr not in obj.PropertiesList:
obj.addProperty("App::PropertyEnumeration", attr, "IFC")
obj.addProperty("App::PropertyEnumeration", attr, "IFC", locked=True)
obj.setPropertyStatus(attr, "Transient")
# to avoid bug/crash: we populate first the property with only the
# class, then we add the sibling classes
@@ -659,7 +659,7 @@ def add_properties(
setattr(obj, attr, get_ifc_classes(obj, value))
# companion hidden propertym that gets saved to file
if "IfcClass" not in obj.PropertiesList:
obj.addProperty("App::PropertyString", "IfcClass", "IFC")
obj.addProperty("App::PropertyString", "IfcClass", "IFC", locked=True)
obj.setPropertyStatus("IfcClass", "Hidden")
setattr(obj, "IfcClass", value)
elif attr_def and "IfcLengthMeasure" in str(attr_def.type_of_attribute()):
@@ -668,17 +668,17 @@ def add_properties(
setattr(obj, attr, value * (1 / get_scale(ifcfile)))
elif isinstance(value, int):
if attr not in obj.PropertiesList:
obj.addProperty("App::PropertyInteger", attr, "IFC")
obj.addProperty("App::PropertyInteger", attr, "IFC", locked=True)
if attr == "StepId":
obj.setPropertyStatus(attr, "ReadOnly")
setattr(obj, attr, value)
elif isinstance(value, float):
if attr not in obj.PropertiesList:
obj.addProperty("App::PropertyFloat", attr, "IFC")
obj.addProperty("App::PropertyFloat", attr, "IFC", locked=True)
setattr(obj, attr, value)
elif data_type == "boolean":
if attr not in obj.PropertiesList:
obj.addProperty("App::PropertyBool", attr, "IFC")
obj.addProperty("App::PropertyBool", attr, "IFC", locked=True)
if not value or value in ["UNKNOWN", "FALSE"]:
value = False
elif not isinstance(value, bool):
@@ -688,15 +688,15 @@ def add_properties(
elif isinstance(value, ifcopenshell.entity_instance):
if links:
if attr not in obj.PropertiesList:
obj.addProperty("App::PropertyLink", attr, "IFC")
obj.addProperty("App::PropertyLink", attr, "IFC", locked=True)
elif isinstance(value, (list, tuple)) and value:
if isinstance(value[0], ifcopenshell.entity_instance):
if links:
if attr not in obj.PropertiesList:
obj.addProperty("App::PropertyLinkList", attr, "IFC")
obj.addProperty("App::PropertyLinkList", attr, "IFC", locked=True)
elif data_type == "enum":
if attr not in obj.PropertiesList:
obj.addProperty("App::PropertyEnumeration", attr, "IFC")
obj.addProperty("App::PropertyEnumeration", attr, "IFC", locked=True)
items = ifcopenshell.util.attribute.get_enum_items(attr_def)
if value not in items:
for v in ("UNDEFINED", "NOTDEFINED", "USERDEFINED"):
@@ -711,14 +711,14 @@ def add_properties(
setattr(obj, attr, value)
setattr(obj, attr, items)
elif attr in ["RefLongitude", "RefLatitude"]:
obj.addProperty("App::PropertyFloat", attr, "IFC")
obj.addProperty("App::PropertyFloat", attr, "IFC", locked=True)
if value is not None:
# convert from list of 4 ints
value = value[0] + value[1]/60. + value[2]/3600. + value[3]/3600.e6
setattr(obj, attr, value)
else:
if attr not in obj.PropertiesList:
obj.addProperty("App::PropertyString", attr, "IFC")
obj.addProperty("App::PropertyString", attr, "IFC", locked=True)
if value is not None:
setattr(obj, attr, str(value))
# annotation properties
@@ -726,14 +726,14 @@ def add_properties(
axisdata = ifc_export.get_axis(ifcentity)
if axisdata:
if "Placement" not in obj.PropertiesList:
obj.addProperty("App::PropertyPlacement", "Placement", "Base")
obj.addProperty("App::PropertyPlacement", "Placement", "Base", locked=True)
if "CustomText" in obj.PropertiesList:
obj.setPropertyStatus("CustomText", "Hidden")
obj.setExpression("CustomText", "AxisTag")
if "Length" not in obj.PropertiesList:
obj.addProperty("App::PropertyLength","Length","Axis")
obj.addProperty("App::PropertyLength","Length","Axis", locked=True)
if "Text" not in obj.PropertiesList:
obj.addProperty("App::PropertyStringList", "Text", "Base")
obj.addProperty("App::PropertyStringList", "Text", "Base", locked=True)
obj.Text = [text.Literal]
obj.Placement = ifc_export.get_placement(ifcentity.ObjectPlacement, ifcfile)
obj.Length = axisdata[1]
@@ -741,18 +741,18 @@ def add_properties(
sectionplane = ifc_export.get_sectionplane(ifcentity)
if sectionplane:
if "Placement" not in obj.PropertiesList:
obj.addProperty("App::PropertyPlacement", "Placement", "Base")
obj.addProperty("App::PropertyPlacement", "Placement", "Base", locked=True)
if "Depth" not in obj.PropertiesList:
obj.addProperty("App::PropertyLength","Depth","SectionPlane")
obj.addProperty("App::PropertyLength","Depth","SectionPlane", locked=True)
obj.Placement = sectionplane[0]
if len(sectionplane) > 3:
obj.Depth = sectionplane[3]
vobj = obj.ViewObject
if vobj:
if "DisplayLength" not in vobj.PropertiesList:
vobj.addProperty("App::PropertyLength","DisplayLength","SectionPlane")
vobj.addProperty("App::PropertyLength","DisplayLength","SectionPlane", locked=True)
if "DisplayHeight" not in vobj.PropertiesList:
vobj.addProperty("App::PropertyLength","DisplayHeight","SectionPlane")
vobj.addProperty("App::PropertyLength","DisplayHeight","SectionPlane", locked=True)
if len(sectionplane) > 1:
vobj.DisplayLength = sectionplane[1]
if len(sectionplane) > 2:
@@ -761,11 +761,11 @@ def add_properties(
dim = ifc_export.get_dimension(ifcentity)
if dim and len(dim) >= 3:
if "Start" not in obj.PropertiesList:
obj.addProperty("App::PropertyVectorDistance", "Start", "Base")
obj.addProperty("App::PropertyVectorDistance", "Start", "Base", locked=True)
if "End" not in obj.PropertiesList:
obj.addProperty("App::PropertyVectorDistance", "End", "Base")
obj.addProperty("App::PropertyVectorDistance", "End", "Base", locked=True)
if "Dimline" not in obj.PropertiesList:
obj.addProperty("App::PropertyVectorDistance", "Dimline", "Base")
obj.addProperty("App::PropertyVectorDistance", "Dimline", "Base", locked=True)
obj.Start = dim[1]
obj.End = dim[2]
if len(dim) > 3:
@@ -778,9 +778,9 @@ def add_properties(
text = ifc_export.get_text(ifcentity)
if text:
if "Placement" not in obj.PropertiesList:
obj.addProperty("App::PropertyPlacement", "Placement", "Base")
obj.addProperty("App::PropertyPlacement", "Placement", "Base", locked=True)
if "Text" not in obj.PropertiesList:
obj.addProperty("App::PropertyStringList", "Text", "Base")
obj.addProperty("App::PropertyStringList", "Text", "Base", locked=True)
obj.Text = [text.Literal]
obj.Placement = ifc_export.get_placement(ifcentity.ObjectPlacement, ifcfile)
elif ifcentity.is_a("IfcControl"):