IFC Header UI - display author and additional info in case if it's available

This commit is contained in:
Andrej730
2025-09-15 18:16:35 +05:00
parent 5a2ed576c4
commit 559636ef0b
5 changed files with 91 additions and 46 deletions
@@ -44,6 +44,7 @@ class ProjectData:
"library_file": cls.library_file(), "library_file": cls.library_file(),
"last_saved": cls.last_saved(), "last_saved": cls.last_saved(),
"total_elements": cls.total_elements(), "total_elements": cls.total_elements(),
"header_info": cls.header_info(),
} }
# After export_schema. # After export_schema.
cls.data["template_file"] = cls.template_file() cls.data["template_file"] = cls.template_file()
@@ -108,6 +109,12 @@ class ProjectData:
return len(ifc.by_type("IfcElement")) return len(ifc.by_type("IfcElement"))
return 0 return 0
@classmethod
def header_info(cls) -> Union[tool.Project.HeaderData, None]:
if not tool.Ifc.get():
return None
return tool.Project.get_header_data()
class ProjectLibraryData: class ProjectLibraryData:
data: dict[str, Any] = {} data: dict[str, Any] = {}
@@ -849,26 +849,8 @@ class EnableEditingHeader(bpy.types.Operator):
self.file = tool.Ifc.get() self.file = tool.Ifc.get()
props = tool.Project.get_project_props() props = tool.Project.get_project_props()
props.is_editing = True props.is_editing = True
header_data = tool.Project.get_header_data()
mvd = "".join(tool.Ifc.get().header.file_description.description) props.load_header_data(header_data)
if "[" in mvd:
props.mvd = mvd.split("[")[1][0:-1]
else:
props.mvd = ""
author = self.file.header.file_name.author
if author:
props.author_name = author[0]
if len(author) > 1:
props.author_email = author[1]
organisation = self.file.header.file_name.organization
if organisation:
props.organisation_name = organisation[0]
if len(organisation) > 1:
props.organisation_email = organisation[1]
props.authorisation = self.file.header.file_name.authorization or ""
return {"FINISHED"} return {"FINISHED"}
@@ -883,6 +865,9 @@ class EditHeader(bpy.types.Operator):
return tool.Ifc.get() return tool.Ifc.get()
def execute(self, context): def execute(self, context):
# NOTE: Though header entities are now generic `entity_instance`
# we still have a special undo system in place for this operator
# since general undo system tracks only elements with ids != 0.
IfcStore.begin_transaction(self) IfcStore.begin_transaction(self)
self.transaction_data = {} self.transaction_data = {}
self.transaction_data["old"] = self.record_state() self.transaction_data["old"] = self.record_state()
@@ -890,6 +875,7 @@ class EditHeader(bpy.types.Operator):
self.transaction_data["new"] = self.record_state() self.transaction_data["new"] = self.record_state()
IfcStore.add_transaction_operation(self) IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self) IfcStore.end_transaction(self)
bonsai.bim.handler.refresh_ui_data()
return result return result
def _execute(self, context): def _execute(self, context):
@@ -446,6 +446,14 @@ class BIMProjectProperties(PropertyGroup):
def get_library_element_index(self, lib_element: LibraryElement) -> int: def get_library_element_index(self, lib_element: LibraryElement) -> int:
return next(i for i in range(len(self.library_elements)) if self.library_elements[i] == lib_element) return next(i for i in range(len(self.library_elements)) if self.library_elements[i] == lib_element)
def load_header_data(self, header_data: tool.Project.HeaderData) -> None:
self.mvd = header_data.mvd
self.author_name = header_data.author_name
self.author_email = header_data.author_email
self.organisation_name = header_data.organization_name
self.organisation_email = header_data.organization_email
self.authorisation = header_data.authorization
if TYPE_CHECKING: if TYPE_CHECKING:
is_editing: bool is_editing: bool
is_loading: bool is_loading: bool
+22 -25
View File
@@ -266,33 +266,30 @@ class BIM_PT_project(Panel):
row.label(text="IFC Schema", icon="FILE_CACHE") row.label(text="IFC Schema", icon="FILE_CACHE")
row.label(text=ifc_file.schema) row.label(text=ifc_file.schema)
if pprops.is_editing: if not ProjectData.is_loaded:
row = self.layout.row(align=True) ProjectData.load()
row.prop(pprops, "mvd")
row = self.layout.row(align=True) headers_props_and_icons = [
row.prop(pprops, "author_name") ("mvd", "FILE_HIDDEN"),
row = self.layout.row(align=True) ("author_name", None),
row.prop(pprops, "author_email") ("author_email", None),
("organisation_name", None),
row = self.layout.row(align=True) ("organisation_email", None),
row.prop(pprops, "organisation_name") ("authorisation", None),
row = self.layout.row(align=True) ]
row.prop(pprops, "organisation_email") rna_props = pprops.bl_rna.properties
for prop_name, prop_icon in headers_props_and_icons:
row = self.layout.row(align=True) if pprops.is_editing:
row.prop(pprops, "authorisation") row = self.layout.row(align=True)
else: row.prop(pprops, prop_name)
row = self.layout.row(align=True)
row.label(text="IFC MVD", icon="FILE_HIDDEN")
if isinstance(ifc_file, ifcopenshell.sqlite):
mvd = ifc_file.mvd_str
else: else:
mvd = "".join(ifc_file.header.file_description.description) value = getattr(ProjectData.data["header_info"], prop_name)
if "[" in mvd: if not value:
mvd = mvd.split("[")[1][0:-1] continue
row.label(text=mvd) row = self.layout.row(align=True)
icon = {} if prop_icon is None else {"icon": prop_icon}
row.label(text=rna_props[prop_name].name, **icon)
row.label(text=value)
else: else:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text="File Not Loaded", icon="ERROR") row.label(text="File Not Loaded", icon="ERROR")
+48 -1
View File
@@ -36,7 +36,7 @@ from collections import defaultdict
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from ifcopenshell.api.project.append_asset import APPENDABLE_ASSET_TYPES from ifcopenshell.api.project.append_asset import APPENDABLE_ASSET_TYPES
from pathlib import Path from pathlib import Path
from typing import Optional, Union, TYPE_CHECKING from typing import NamedTuple, Optional, Union, TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from bonsai.bim.module.project.prop import BIMProjectProperties, MeasureToolSettings from bonsai.bim.module.project.prop import BIMProjectProperties, MeasureToolSettings
@@ -437,3 +437,50 @@ class Project(bonsai.core.tool.Project):
remove_root(rel) remove_root(rel)
else: else:
assert False, f"Shouldn't be here, {rel}" assert False, f"Shouldn't be here, {rel}"
class HeaderData(NamedTuple):
mvd: str
author_name: str
author_email: str
organization_name: str
organization_email: str
authorization: str
@classmethod
def get_header_data(cls) -> HeaderData:
if not (ifc_file := tool.Ifc.get()):
return {}
# MVD.
if isinstance(ifc_file, ifcopenshell.sqlite):
mvd = ifc_file.mvd_str
else:
mvd = "".join(ifc_file.header.file_description.description)
if f"[" in mvd:
mvd = mvd.split("[")[1][0:-1]
# Author.
author = ifc_file.header.file_name.author
author_name, author_email = "", ""
if author:
author_name = author[0]
if len(author) > 1:
author_email = author[1]
# Organization.
organization_name, organization_email = "", ""
organization = ifc_file.header.file_name.organization
if organization:
organization_name = organization[0]
if len(organization) > 1:
organization_email = organization[1]
authorization = ifc_file.header.file_name.authorization or ""
return cls.HeaderData(
mvd=mvd,
author_name=author_name,
author_email=author_email,
organization_name=organization_name,
organization_email=organization_email,
authorization=authorization,
)