mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 23:36:20 +00:00
Show ifc specs in file selector (#1980)
* Create simple parser for ifc header specs * Refactor logic to be usable with other file selectors * Fix parsing error
This commit is contained in:
@@ -97,3 +97,37 @@ def export_attributes(props, callback=None):
|
|||||||
continue # Our job is done
|
continue # Our job is done
|
||||||
attributes[prop.name] = prop.get_value()
|
attributes[prop.name] = prop.get_value()
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
|
|
||||||
|
class IFCHeaderSpecs:
|
||||||
|
def __init__(self, filepath: str):
|
||||||
|
# According to https://www.steptools.com/stds/step/IS_final_p21e3.html#clause-8
|
||||||
|
self.description = ""
|
||||||
|
self.implementation_level = ""
|
||||||
|
self.name = ""
|
||||||
|
self.time_stamp = ""
|
||||||
|
self.author = ""
|
||||||
|
self.organization = ""
|
||||||
|
self.preprocessor_version = ""
|
||||||
|
self.originating_system = ""
|
||||||
|
self.authorization = ""
|
||||||
|
self.schema_name = ""
|
||||||
|
with open(filepath) as ifc_file:
|
||||||
|
max_lines_to_parse = 50
|
||||||
|
for _ in range(max_lines_to_parse):
|
||||||
|
line = next(ifc_file)
|
||||||
|
if line.startswith("FILE_DESCRIPTION"):
|
||||||
|
for i, part in enumerate(line.split("'")):
|
||||||
|
if i == 1:
|
||||||
|
self.description = part
|
||||||
|
elif i == 3:
|
||||||
|
self.implementation_level = part
|
||||||
|
elif line.startswith("FILE_NAME"):
|
||||||
|
for i, part in enumerate(line.split("'")):
|
||||||
|
if i == 1:
|
||||||
|
self.name = part
|
||||||
|
elif i == 3:
|
||||||
|
self.time_stamp = part
|
||||||
|
elif line.startswith("FILE_SCHEMA"):
|
||||||
|
self.schema_name = line.split("'")[1]
|
||||||
|
break
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import blenderbim.tool as tool
|
|||||||
import blenderbim.core.context
|
import blenderbim.core.context
|
||||||
import blenderbim.core.owner
|
import blenderbim.core.owner
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
|
from blenderbim.bim.ui import IFCFileSelector
|
||||||
from blenderbim.bim import import_ifc
|
from blenderbim.bim import import_ifc
|
||||||
from blenderbim.bim import export_ifc
|
from blenderbim.bim import export_ifc
|
||||||
from ifcopenshell.api.context.data import Data as ContextData
|
from ifcopenshell.api.context.data import Data as ContextData
|
||||||
@@ -126,7 +127,7 @@ class CreateProject(bpy.types.Operator):
|
|||||||
IfcStore.file = data["file"]
|
IfcStore.file = data["file"]
|
||||||
|
|
||||||
|
|
||||||
class SelectLibraryFile(bpy.types.Operator):
|
class SelectLibraryFile(bpy.types.Operator, IFCFileSelector):
|
||||||
bl_idname = "bim.select_library_file"
|
bl_idname = "bim.select_library_file"
|
||||||
bl_label = "Select Library File"
|
bl_label = "Select Library File"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
@@ -539,7 +540,7 @@ class DisableEditingHeader(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class LoadProject(bpy.types.Operator):
|
class LoadProject(bpy.types.Operator, IFCFileSelector):
|
||||||
bl_idname = "bim.load_project"
|
bl_idname = "bim.load_project"
|
||||||
bl_label = "Load Project"
|
bl_label = "Load Project"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
@@ -549,7 +550,7 @@ class LoadProject(bpy.types.Operator):
|
|||||||
is_advanced: bpy.props.BoolProperty(name="Enable Advanced Mode", default=False)
|
is_advanced: bpy.props.BoolProperty(name="Enable Advanced Mode", default=False)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
if not os.path.exists(self.filepath) or "ifc" not in os.path.splitext(self.filepath)[1].lower():
|
if not self.is_existing_ifc_file():
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
context.scene.BIMProperties.ifc_file = self.filepath
|
context.scene.BIMProperties.ifc_file = self.filepath
|
||||||
context.scene.BIMProjectProperties.is_loading = True
|
context.scene.BIMProjectProperties.is_loading = True
|
||||||
@@ -561,6 +562,10 @@ class LoadProject(bpy.types.Operator):
|
|||||||
context.window_manager.fileselect_add(self)
|
context.window_manager.fileselect_add(self)
|
||||||
return {"RUNNING_MODAL"}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
self.layout.prop(self, "is_advanced")
|
||||||
|
IFCFileSelector.draw(self, context)
|
||||||
|
|
||||||
|
|
||||||
class UnloadProject(bpy.types.Operator):
|
class UnloadProject(bpy.types.Operator):
|
||||||
bl_idname = "bim.unload_project"
|
bl_idname = "bim.unload_project"
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ import json
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import blenderbim.bim.handler
|
import blenderbim.bim.handler
|
||||||
from pathlib import Path
|
|
||||||
from . import schema
|
from . import schema
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
|
from blenderbim.bim.ui import IFCFileSelector
|
||||||
from mathutils import Vector, Matrix, Euler
|
from mathutils import Vector, Matrix, Euler
|
||||||
from math import radians
|
from math import radians
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ class OpenUri(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class SelectIfcFile(bpy.types.Operator):
|
class SelectIfcFile(bpy.types.Operator, IFCFileSelector):
|
||||||
bl_idname = "bim.select_ifc_file"
|
bl_idname = "bim.select_ifc_file"
|
||||||
bl_label = "Select IFC File"
|
bl_label = "Select IFC File"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
@@ -47,11 +47,6 @@ class SelectIfcFile(bpy.types.Operator):
|
|||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
||||||
|
|
||||||
def is_existing_ifc_file(self, filepath=None):
|
|
||||||
if filepath is None:
|
|
||||||
filepath = self.filepath
|
|
||||||
return os.path.exists(filepath) and "ifc" in os.path.splitext(filepath)[1].lower()
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
if self.is_existing_ifc_file():
|
if self.is_existing_ifc_file():
|
||||||
context.scene.BIMProperties.ifc_file = self.filepath
|
context.scene.BIMProperties.ifc_file = self.filepath
|
||||||
@@ -61,25 +56,6 @@ class SelectIfcFile(bpy.types.Operator):
|
|||||||
context.window_manager.fileselect_add(self)
|
context.window_manager.fileselect_add(self)
|
||||||
return {"RUNNING_MODAL"}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
# Access filepath & Directory https://blender.stackexchange.com/a/207665
|
|
||||||
params = context.space_data.params
|
|
||||||
# Decode byte string https://stackoverflow.com/a/47737082/
|
|
||||||
directory = Path(params.directory.decode("utf-8"))
|
|
||||||
filepath = os.path.join(directory, params.filename)
|
|
||||||
if self.is_existing_ifc_file(filepath):
|
|
||||||
self.draw_ifc_specs(filepath)
|
|
||||||
|
|
||||||
def draw_ifc_specs(self, filepath):
|
|
||||||
with open(filepath) as ifc_file:
|
|
||||||
max_lines_to_parse = 50
|
|
||||||
for _ in range(max_lines_to_parse):
|
|
||||||
line = next(ifc_file)
|
|
||||||
if line.startswith("FILE_SCHEMA(('") and line.endswith("'));\n"):
|
|
||||||
schema = line.split("'")[1]
|
|
||||||
self.layout.label(text=f"File Schema : {schema}")
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
class SelectDataDir(bpy.types.Operator):
|
class SelectDataDir(bpy.types.Operator):
|
||||||
bl_idname = "bim.select_data_dir"
|
bl_idname = "bim.select_data_dir"
|
||||||
|
|||||||
@@ -18,9 +18,34 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import bpy
|
import bpy
|
||||||
|
from pathlib import Path
|
||||||
from . import ifc
|
from . import ifc
|
||||||
from bpy.types import Panel
|
from bpy.types import Panel
|
||||||
from bpy.props import StringProperty, IntProperty, BoolProperty
|
from bpy.props import StringProperty, IntProperty, BoolProperty
|
||||||
|
from blenderbim.bim.helper import IFCHeaderSpecs
|
||||||
|
|
||||||
|
|
||||||
|
class IFCFileSelector:
|
||||||
|
def is_existing_ifc_file(self, filepath=None):
|
||||||
|
if filepath is None:
|
||||||
|
filepath = self.filepath
|
||||||
|
return os.path.exists(filepath) and "ifc" in os.path.splitext(filepath)[1].lower()
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
# Access filepath & Directory https://blender.stackexchange.com/a/207665
|
||||||
|
params = context.space_data.params
|
||||||
|
# Decode byte string https://stackoverflow.com/a/47737082/
|
||||||
|
directory = Path(params.directory.decode("utf-8"))
|
||||||
|
filepath = os.path.join(directory, params.filename)
|
||||||
|
if self.is_existing_ifc_file(filepath):
|
||||||
|
box = self.layout.box()
|
||||||
|
box.label(text="IFC Header Specifications", icon="INFO")
|
||||||
|
ifc_specs = IFCHeaderSpecs(filepath)
|
||||||
|
for attr_name, attr_value in ifc_specs.__dict__.items():
|
||||||
|
if attr_value != "":
|
||||||
|
split = box.split()
|
||||||
|
split.label(text=attr_name.title().replace("_", " "))
|
||||||
|
split.label(text=str(attr_value))
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_section_plane(Panel):
|
class BIM_PT_section_plane(Panel):
|
||||||
@@ -163,7 +188,7 @@ class BIM_PT_collaboration_and_data_exchange(Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_geometry_and_spatial_structure(Panel):
|
class BIM_PT_geometry_and_spatial_structure(Panel):
|
||||||
bl_label = "IFC Geometry and Spatial Structure"
|
bl_label = "IFC Geometry and Spatial Structure"
|
||||||
@@ -174,7 +199,7 @@ class BIM_PT_geometry_and_spatial_structure(Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_4D5D(Panel):
|
class BIM_PT_4D5D(Panel):
|
||||||
bl_label = "IFC 4D/5D"
|
bl_label = "IFC 4D/5D"
|
||||||
@@ -196,7 +221,7 @@ class BIM_PT_structural(Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_misc(Panel):
|
class BIM_PT_misc(Panel):
|
||||||
bl_label = "IFC Misc."
|
bl_label = "IFC Misc."
|
||||||
@@ -207,7 +232,7 @@ class BIM_PT_misc(Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_quality_control(Panel):
|
class BIM_PT_quality_control(Panel):
|
||||||
bl_label = "IFC Quality Control"
|
bl_label = "IFC Quality Control"
|
||||||
@@ -230,7 +255,7 @@ class BIM_PT_geometry_and_spatial_structure_object(Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_object_attributes_properties_and_relationships(Panel):
|
class BIM_PT_object_attributes_properties_and_relationships(Panel):
|
||||||
bl_label = "IFC Object Attributes, Properties and Relationships"
|
bl_label = "IFC Object Attributes, Properties and Relationships"
|
||||||
|
|||||||
Reference in New Issue
Block a user