From 93aa24c6d2fdc962ed3f0615b4752c5481ebb340 Mon Sep 17 00:00:00 2001 From: Carlos Dias <57261862+c4rlosdias@users.noreply.github.com> Date: Sun, 2 Jul 2023 20:25:51 -0300 Subject: [PATCH 1/9] Update operator.py missing output file format in arguments --- src/blenderbim/blenderbim/bim/module/csv/operator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blenderbim/blenderbim/bim/module/csv/operator.py b/src/blenderbim/blenderbim/bim/module/csv/operator.py index 02b7fabe41..5b74ec3ec9 100644 --- a/src/blenderbim/blenderbim/bim/module/csv/operator.py +++ b/src/blenderbim/blenderbim/bim/module/csv/operator.py @@ -152,7 +152,7 @@ class ExportIfcCsv(bpy.types.Operator): ifc_csv = ifccsv.IfcCsv() attributes = [a.name for a in props.csv_attributes] sep = props.csv_custom_delimiter if props.csv_delimiter == "CUSTOM" else props.csv_delimiter - ifc_csv.export(ifc_file, results, attributes, output=self.filepath, format=args.format, delimiter=sep) + ifc_csv.export(ifc_file, results, attributes, output=self.filepath, format="csv", delimiter=sep) return {"FINISHED"} From 700d8a3b9c482e1ff5d009a97f5c2245650c9bac Mon Sep 17 00:00:00 2001 From: c4rlosdias Date: Mon, 3 Jul 2023 10:22:08 -0300 Subject: [PATCH 2/9] Add extra formats to output file --- .../blenderbim/bim/module/csv/operator.py | 12 +++++++----- src/blenderbim/blenderbim/bim/module/csv/prop.py | 9 +++++++++ src/blenderbim/blenderbim/bim/module/csv/ui.py | 14 +++++++++----- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/csv/operator.py b/src/blenderbim/blenderbim/bim/module/csv/operator.py index 5b74ec3ec9..71dabc5b21 100644 --- a/src/blenderbim/blenderbim/bim/module/csv/operator.py +++ b/src/blenderbim/blenderbim/bim/module/csv/operator.py @@ -128,12 +128,14 @@ class ExportCsvAttributes(bpy.types.Operator): class ExportIfcCsv(bpy.types.Operator): bl_idname = "bim.export_ifccsv" - bl_label = "Export IFC to CSV" - filename_ext = ".csv" + bl_label = "Export IFC" + #filename_ext = ".csv" filepath: bpy.props.StringProperty(subtype="FILE_PATH") + def invoke(self, context, event): - self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv") + props = context.scene.CsvProperties + self.filepath = bpy.path.ensure_ext(bpy.data.filepath, f".{props.format}") WindowManager = context.window_manager WindowManager.fileselect_add(self) return {"RUNNING_MODAL"} @@ -142,7 +144,7 @@ class ExportIfcCsv(bpy.types.Operator): import ifccsv props = context.scene.CsvProperties - self.filepath = bpy.path.ensure_ext(self.filepath, ".csv") + self.filepath = bpy.path.ensure_ext(self.filepath, f".{props.format}") if props.should_load_from_memory: ifc_file = IfcStore.get_file() else: @@ -152,7 +154,7 @@ class ExportIfcCsv(bpy.types.Operator): ifc_csv = ifccsv.IfcCsv() attributes = [a.name for a in props.csv_attributes] sep = props.csv_custom_delimiter if props.csv_delimiter == "CUSTOM" else props.csv_delimiter - ifc_csv.export(ifc_file, results, attributes, output=self.filepath, format="csv", delimiter=sep) + ifc_csv.export(ifc_file, results, attributes, output=self.filepath, format=props.format, delimiter=sep) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/csv/prop.py b/src/blenderbim/blenderbim/bim/module/csv/prop.py index bb04c1b500..4cdbe3ba7c 100644 --- a/src/blenderbim/blenderbim/bim/module/csv/prop.py +++ b/src/blenderbim/blenderbim/bim/module/csv/prop.py @@ -45,5 +45,14 @@ class CsvProperties(PropertyGroup): name="IFC CSV Delimiter", default=",", ) + format: EnumProperty( + items=[ + ("csv", "csv", ""), + ("xlsx", "xlsx", ""), + ("ods", "ods", ""), + ], + name="Output format", + default="csv", + ) csv_custom_delimiter: StringProperty(default="", name="Custom Delimiter") should_load_from_memory: BoolProperty(default=False, name="Load from Memory") diff --git a/src/blenderbim/blenderbim/bim/module/csv/ui.py b/src/blenderbim/blenderbim/bim/module/csv/ui.py index cdae4f8ab7..7c1df7a4d2 100644 --- a/src/blenderbim/blenderbim/bim/module/csv/ui.py +++ b/src/blenderbim/blenderbim/bim/module/csv/ui.py @@ -60,17 +60,21 @@ class BIM_PT_ifccsv(Panel): row = layout.row(align=True) row.prop(attribute, "name", text="") row.operator("bim.remove_csv_attribute", icon="X", text="").index = index - + row = layout.row(align=True) - row.prop(props, "csv_delimiter") + row.prop(props, "format") - if props.csv_delimiter == "CUSTOM": + if props.format == 'csv': row = layout.row(align=True) - row.prop(props, "csv_custom_delimiter") + row.prop(props, "csv_delimiter") + + if props.csv_delimiter == "CUSTOM": + row = layout.row(align=True) + row.prop(props, "csv_custom_delimiter") row = layout.row() split = row.split(factor=0.5) c = split.column() - c.operator("bim.export_ifccsv", icon="EXPORT") + c.operator("bim.export_ifccsv", icon="EXPORT", text="Export IFC to " + props.format.upper()) c = split.column() c.operator("bim.import_ifccsv", icon="IMPORT") From 772414451e339fd93fc7b59e0a74d1c9cd922143 Mon Sep 17 00:00:00 2001 From: c4rlosdias Date: Fri, 14 Jul 2023 12:04:22 -0300 Subject: [PATCH 3/9] update ifctester - 2023_07_14 --- src/blenderbim/blenderbim/__init__.py | 1 + src/blenderbim/blenderbim/bim/handler.py | 2 +- .../blenderbim/bim/module/tester/__init__.py | 3 ++ .../blenderbim/bim/module/tester/operator.py | 30 +++++++++++- .../blenderbim/bim/module/tester/prop.py | 21 ++++++++- .../blenderbim/bim/module/tester/ui.py | 47 ++++++++++++++++--- 6 files changed, 94 insertions(+), 10 deletions(-) diff --git a/src/blenderbim/blenderbim/__init__.py b/src/blenderbim/blenderbim/__init__.py index 44ef0f8a24..517bc3b7c8 100644 --- a/src/blenderbim/blenderbim/__init__.py +++ b/src/blenderbim/blenderbim/__init__.py @@ -44,3 +44,4 @@ if sys.modules.get("bpy", None): def unregister(): blenderbim.bim.unregister() + \ No newline at end of file diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index 41fd7e6f24..b56c001690 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -267,7 +267,7 @@ def viewport_shading_changed_callback(area): bpy.context.scene.BIMStylesProperties.active_style_type = "External" -if getattr(bpy.types, "SCENE_PT_scene"): +if (bpy.types, "SCENE_PT_scene"): class Override_SCENE_PT_scene(bpy.types.SCENE_PT_scene): bl_idname = "SCENE_PT_scene_override" diff --git a/src/blenderbim/blenderbim/bim/module/tester/__init__.py b/src/blenderbim/blenderbim/bim/module/tester/__init__.py index aae027b711..4a0cef605d 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/tester/__init__.py @@ -23,8 +23,11 @@ classes = ( operator.ExecuteIfcTester, operator.SelectSpecs, operator.SelectIfcTesterIfcFile, + operator.SelectSpecification, + prop.Specification, prop.IfcTesterProperties, ui.BIM_PT_tester, + ui.BIM_UL_tester ) diff --git a/src/blenderbim/blenderbim/bim/module/tester/operator.py b/src/blenderbim/blenderbim/bim/module/tester/operator.py index 591567a338..c49b2348a7 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/operator.py +++ b/src/blenderbim/blenderbim/bim/module/tester/operator.py @@ -21,6 +21,7 @@ import bpy import time import tempfile import webbrowser +import json import ifctester import ifctester.ids import ifctester.reporter @@ -53,13 +54,30 @@ class ExecuteIfcTester(bpy.types.Operator): print("Finished loading:", time.time() - start) start = time.time() specs.validate(ifc) + print("Finished validating:", time.time() - start) start = time.time() engine = ifctester.reporter.Html(specs) - engine.report() + engine.report() engine.to_file(output) webbrowser.open("file://" + output) + + report = None + report = ifctester.reporter.Json(specs).report()['specifications'] + if report: + props.has_report = True + print(report) + props.specifications.clear() + for spec in report: + new = props.specifications.add() + new.name = spec['name'] + new.status = spec['status'] + new.sucess = spec['total_sucess'] + new.description = spec['requirements'][0]['description'] + new.failed_entities = len(spec['requirements'][0]['failed_entities']) + + return {"FINISHED"} @@ -95,3 +113,13 @@ class SelectIfcTesterIfcFile(bpy.types.Operator): def invoke(self, context, event): context.window_manager.fileselect_add(self) return {"RUNNING_MODAL"} + +class SelectSpecification(bpy.types.Operator): + bl_idname = "bim.select_specification" + bl_label = "Select Specification" + bl_options = {"REGISTER", "UNDO"} + spec: bpy.props.IntProperty() + + def execute(self, context): + context.scene.IfcTesterProperties.entities = self.spec + return {"FINISHED"} \ No newline at end of file diff --git a/src/blenderbim/blenderbim/bim/module/tester/prop.py b/src/blenderbim/blenderbim/bim/module/tester/prop.py index 09866feed1..948dc19f4e 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/prop.py +++ b/src/blenderbim/blenderbim/bim/module/tester/prop.py @@ -28,13 +28,32 @@ from bpy.props import ( FloatVectorProperty, CollectionProperty, ) - +import bpy.props def purge(): pass +def get_failure_entities(): + return + + +class Specification(PropertyGroup): + name: StringProperty(name="Name") + failed_entities: IntProperty(name="Failed Entities") + description : StringProperty(name="Description") + status : BoolProperty(default=False, name="Status") + sucess : IntProperty(name="Total sucess") + ifc_definition_id: IntProperty(name="IFC Definition ID") class IfcTesterProperties(PropertyGroup): specs: StringProperty(default="", name="IDS File") + report: StringProperty(default="", name="JSON report") ifc_file: StringProperty(default="", name="IFC File") should_load_from_memory: BoolProperty(default=False, name="Load from Memory") + active_specification_index: IntProperty(name="Active Specification Index") + specifications: CollectionProperty(name="Specifications", type=Specification) + named_specifications: EnumProperty(items=[("11111", "11111", "11")], name="Named Unit Types") + has_report : BoolProperty(default=False, name="") + entities : IntProperty(name="Failed Entities") + + diff --git a/src/blenderbim/blenderbim/bim/module/tester/ui.py b/src/blenderbim/blenderbim/bim/module/tester/ui.py index 59a0d12281..130308de32 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/ui.py +++ b/src/blenderbim/blenderbim/bim/module/tester/ui.py @@ -17,7 +17,7 @@ # along with BlenderBIM Add-on. If not, see . import blenderbim.tool as tool -from bpy.types import Panel +from bpy.types import Panel, UIList class BIM_PT_tester(Panel): @@ -32,20 +32,53 @@ class BIM_PT_tester(Panel): def draw(self, context): self.layout.use_property_split = True - props = context.scene.IfcTesterProperties + self.props = context.scene.IfcTesterProperties if tool.Ifc.get(): row = self.layout.row() - row.prop(props, "should_load_from_memory") + row.prop(self.props, "should_load_from_memory") - if not tool.Ifc.get() or not props.should_load_from_memory: + if not tool.Ifc.get() or not self.props.should_load_from_memory: row = self.layout.row(align=True) - row.prop(props, "ifc_file") + row.prop(self.props, "ifc_file") row.operator("bim.select_ifctester_ifc_file", icon="FILE_FOLDER", text="") row = self.layout.row(align=True) - row.prop(props, "specs") + row.prop(self.props, "specs") row.operator("bim.select_specs", icon="FILE_FOLDER", text="") row = self.layout.row() - row.operator("bim.execute_ifc_tester") + result = row.operator("bim.execute_ifc_tester") + + if self.props.has_report: + self.layout.template_list( + "BIM_UL_tester", + "", + self.props, + "specifications", + self.props, + "active_specification_index", + ) + + self.draw_editable_ui(context) + + def draw_editable_ui(self, context): + props = context.scene.IfcTesterProperties + row = self.layout.row() + row.label(text="Failed entities: " + str(props.entities)) + + + +class BIM_UL_tester(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + props = context.scene.IfcTesterProperties + if item: + icon = "MOD_MESHDEFORM" + row = layout.row(align=True) + row.label(text=item.name or "Unnamed", icon=icon) + if item.status: + row.label(text="PASS") + else: + row.label(text="FAIL") + op = row.operator("bim.select_specification", text="", icon="VIEWZOOM") + op.spec = item.failed_entities \ No newline at end of file From 31bb220d3851fabd53e6ebe18b6c811d89f412b0 Mon Sep 17 00:00:00 2001 From: c4rlosdias Date: Sun, 16 Jul 2023 20:46:26 -0300 Subject: [PATCH 4/9] Update 2023_07_16 --- .../blenderbim/bim/module/tester/__init__.py | 7 ++- .../blenderbim/bim/module/tester/operator.py | 34 +++++++----- .../blenderbim/bim/module/tester/prop.py | 25 +++++---- .../blenderbim/bim/module/tester/ui.py | 54 ++++++++++++++++--- 4 files changed, 89 insertions(+), 31 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/tester/__init__.py b/src/blenderbim/blenderbim/bim/module/tester/__init__.py index 4a0cef605d..c0532915e0 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/tester/__init__.py @@ -23,11 +23,13 @@ classes = ( operator.ExecuteIfcTester, operator.SelectSpecs, operator.SelectIfcTesterIfcFile, - operator.SelectSpecification, + operator.SelectRequirement, + prop.FailedEntities, prop.Specification, prop.IfcTesterProperties, ui.BIM_PT_tester, - ui.BIM_UL_tester + ui.BIM_UL_tester_specifications, + ui.BIM_UL_tester_failed_entities ) @@ -37,3 +39,4 @@ def register(): def unregister(): del bpy.types.Scene.IfcTesterProperties + diff --git a/src/blenderbim/blenderbim/bim/module/tester/operator.py b/src/blenderbim/blenderbim/bim/module/tester/operator.py index c49b2348a7..460623d496 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/operator.py +++ b/src/blenderbim/blenderbim/bim/module/tester/operator.py @@ -67,16 +67,13 @@ class ExecuteIfcTester(bpy.types.Operator): report = ifctester.reporter.Json(specs).report()['specifications'] if report: props.has_report = True - print(report) + props.report = json.dumps(report) props.specifications.clear() + c=0 for spec in report: - new = props.specifications.add() - new.name = spec['name'] - new.status = spec['status'] - new.sucess = spec['total_sucess'] - new.description = spec['requirements'][0]['description'] - new.failed_entities = len(spec['requirements'][0]['failed_entities']) - + new_spec = props.specifications.add() + new_spec.name = spec['name'] + new_spec.status = spec['status'] return {"FINISHED"} @@ -114,12 +111,25 @@ class SelectIfcTesterIfcFile(bpy.types.Operator): context.window_manager.fileselect_add(self) return {"RUNNING_MODAL"} -class SelectSpecification(bpy.types.Operator): - bl_idname = "bim.select_specification" + +class SelectRequirement(bpy.types.Operator): + bl_idname = "bim.select_requirement" bl_label = "Select Specification" bl_options = {"REGISTER", "UNDO"} - spec: bpy.props.IntProperty() + spec_index: bpy.props.IntProperty() + req_index: bpy.props.IntProperty() def execute(self, context): - context.scene.IfcTesterProperties.entities = self.spec + props = context.scene.IfcTesterProperties + props.has_entities = True + report = json.loads(props.report) + props.failed_entities.clear() + failed_entities = report[self.spec_index]['requirements'] [self.req_index]['failed_entities'] + print(failed_entities) + for e in failed_entities: + new_entity = props.failed_entities.add() + new_entity.reason = e['reason'] + new_entity.element = e['element'] + + return {"FINISHED"} \ No newline at end of file diff --git a/src/blenderbim/blenderbim/bim/module/tester/prop.py b/src/blenderbim/blenderbim/bim/module/tester/prop.py index 948dc19f4e..d6fa425fab 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/prop.py +++ b/src/blenderbim/blenderbim/bim/module/tester/prop.py @@ -28,7 +28,6 @@ from bpy.props import ( FloatVectorProperty, CollectionProperty, ) -import bpy.props def purge(): pass @@ -37,23 +36,29 @@ def get_failure_entities(): return + class Specification(PropertyGroup): name: StringProperty(name="Name") - failed_entities: IntProperty(name="Failed Entities") - description : StringProperty(name="Description") status : BoolProperty(default=False, name="Status") - sucess : IntProperty(name="Total sucess") - ifc_definition_id: IntProperty(name="IFC Definition ID") + +class FailedEntities(PropertyGroup): + reason: StringProperty(name="Reason") + element: StringProperty(name="Element") + class IfcTesterProperties(PropertyGroup): - specs: StringProperty(default="", name="IDS File") - report: StringProperty(default="", name="JSON report") + specs: StringProperty(default="", name="IDS File") ifc_file: StringProperty(default="", name="IFC File") should_load_from_memory: BoolProperty(default=False, name="Load from Memory") - active_specification_index: IntProperty(name="Active Specification Index") + + active_specification_index: IntProperty(name="Active Specification Index") + active_requirement_index: IntProperty(name="Active Requirement Index") + active_failed_entity_index: IntProperty(name="Active Failed Entity Index") + report: StringProperty(default="", name="JSON report") specifications: CollectionProperty(name="Specifications", type=Specification) - named_specifications: EnumProperty(items=[("11111", "11111", "11")], name="Named Unit Types") + failed_entities: CollectionProperty(name="FailedEntities", type=FailedEntities) has_report : BoolProperty(default=False, name="") - entities : IntProperty(name="Failed Entities") + has_entities : BoolProperty(default=False, name="") + diff --git a/src/blenderbim/blenderbim/bim/module/tester/ui.py b/src/blenderbim/blenderbim/bim/module/tester/ui.py index 130308de32..56bc32d3d1 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/ui.py +++ b/src/blenderbim/blenderbim/bim/module/tester/ui.py @@ -18,6 +18,7 @@ import blenderbim.tool as tool from bpy.types import Panel, UIList +import json class BIM_PT_tester(Panel): @@ -52,7 +53,7 @@ class BIM_PT_tester(Panel): if self.props.has_report: self.layout.template_list( - "BIM_UL_tester", + "BIM_UL_tester_specifications", "", self.props, "specifications", @@ -64,21 +65,60 @@ class BIM_PT_tester(Panel): def draw_editable_ui(self, context): props = context.scene.IfcTesterProperties - row = self.layout.row() - row.label(text="Failed entities: " + str(props.entities)) + i = props.active_specification_index + dic_report = json.loads(props.report) + total_successes = dic_report[i]['total_successes'] + total = dic_report[i]['total'] + percentage = dic_report[i]['percentage'] + n_requirements = len(dic_report[i]['requirements']) + + row = self.layout.row() + row.label(text = f"Passed: {total_successes}/{total} ({percentage}%)") + row = self.layout.row() + row.label(text = f"Requirements ({n_requirements}):") + c=1 + box = self.layout.box() + for req in dic_report[i]['requirements']: + row = box.row(align=True) + row.label(text=f" {c}. {req['description']}") + if req['status']: + row.label(text="PASS") + else: + row.label(text="FAIL") + op = row.operator("bim.select_requirement", text="", icon="RESTRICT_SELECT_OFF") + op.spec_index = i + op.req_index = c - 1 + c += 1 + if props.has_entities: + self.layout.template_list( + "BIM_UL_tester_failed_entities", + "", + self.props, + "failed_entities", + self.props, + "active_failed_entity_index", + ) -class BIM_UL_tester(UIList): +class BIM_UL_tester_specifications(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): props = context.scene.IfcTesterProperties if item: - icon = "MOD_MESHDEFORM" + icon = "WORDWRAP_ON" row = layout.row(align=True) row.label(text=item.name or "Unnamed", icon=icon) if item.status: row.label(text="PASS") else: row.label(text="FAIL") - op = row.operator("bim.select_specification", text="", icon="VIEWZOOM") - op.spec = item.failed_entities \ No newline at end of file + +class BIM_UL_tester_failed_entities(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + props = context.scene.IfcTesterProperties + if item: + icon = "WORDWRAP_ON" + row = layout.row(align=True) + row.label(text=item.reason) + row.label(text=eval(item.element).Name) + From 7bc23c996b47786b9fa9d77cdc402538ddde8fa5 Mon Sep 17 00:00:00 2001 From: c4rlosdias Date: Mon, 17 Jul 2023 17:07:45 -0300 Subject: [PATCH 5/9] Add select entities (2023_07_17) --- .../blenderbim/bim/module/tester/__init__.py | 1 + .../blenderbim/bim/module/tester/operator.py | 20 ++++++++++++++--- .../blenderbim/bim/module/tester/ui.py | 22 +++++++++++++------ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/tester/__init__.py b/src/blenderbim/blenderbim/bim/module/tester/__init__.py index c0532915e0..8daea23cf1 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/tester/__init__.py @@ -24,6 +24,7 @@ classes = ( operator.SelectSpecs, operator.SelectIfcTesterIfcFile, operator.SelectRequirement, + operator.SelectEntity, prop.FailedEntities, prop.Specification, prop.IfcTesterProperties, diff --git a/src/blenderbim/blenderbim/bim/module/tester/operator.py b/src/blenderbim/blenderbim/bim/module/tester/operator.py index 460623d496..3c29a40fb6 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/operator.py +++ b/src/blenderbim/blenderbim/bim/module/tester/operator.py @@ -54,6 +54,7 @@ class ExecuteIfcTester(bpy.types.Operator): print("Finished loading:", time.time() - start) start = time.time() specs.validate(ifc) + print(specs) print("Finished validating:", time.time() - start) start = time.time() @@ -127,9 +128,22 @@ class SelectRequirement(bpy.types.Operator): failed_entities = report[self.spec_index]['requirements'] [self.req_index]['failed_entities'] print(failed_entities) for e in failed_entities: - new_entity = props.failed_entities.add() - new_entity.reason = e['reason'] + new_entity = props.failed_entities.add() new_entity.element = e['element'] + new_entity.reason = e['reason'] + return {"FINISHED"} +class SelectEntity(bpy.types.Operator): + bl_idname = "bim.select_entity" + bl_label = "Select Entity" + bl_options = {"REGISTER", "UNDO"} + ifc_id: bpy.props.IntProperty() + + def execute(self, context): + bpy.ops.object.select_all(action='DESELECT') + for obj in context.scene.objects: + if obj.BIMObjectProperties.ifc_definition_id == self.ifc_id: + obj.select_set(True) + bpy.context.view_layer.objects.active = obj + return {"FINISHED"} - return {"FINISHED"} \ No newline at end of file diff --git a/src/blenderbim/blenderbim/bim/module/tester/ui.py b/src/blenderbim/blenderbim/bim/module/tester/ui.py index 56bc32d3d1..aee0f1a900 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/ui.py +++ b/src/blenderbim/blenderbim/bim/module/tester/ui.py @@ -83,14 +83,16 @@ class BIM_PT_tester(Panel): row = box.row(align=True) row.label(text=f" {c}. {req['description']}") if req['status']: - row.label(text="PASS") + row.label(text="PASS", icon="CHECKMARK") else: - row.label(text="FAIL") - op = row.operator("bim.select_requirement", text="", icon="RESTRICT_SELECT_OFF") - op.spec_index = i - op.req_index = c - 1 + row.label(text="FAIL", icon="CANCEL") + op = row.operator("bim.select_requirement", text="", icon="LONGDISPLAY") + op.spec_index = i + op.req_index = c - 1 c += 1 if props.has_entities: + row = self.layout.row() + row.label(text = "Failed entities :") self.layout.template_list( "BIM_UL_tester_failed_entities", "", @@ -116,9 +118,15 @@ class BIM_UL_tester_specifications(UIList): class BIM_UL_tester_failed_entities(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): props = context.scene.IfcTesterProperties + ifc_file = tool.Ifc.get() if item: icon = "WORDWRAP_ON" - row = layout.row(align=True) + ifc_id = int(item.element[1:item.element.find('=')]) + entity = ifc_file.by_id(ifc_id) + row = layout.row(align=True) + row.label(text=f'{entity.Name} [{entity.is_a()}]') row.label(text=item.reason) - row.label(text=eval(item.element).Name) + op = row.operator("bim.select_entity", text="", icon="RESTRICT_SELECT_OFF") + op.ifc_id = entity.id() + From d851614cbbe63b40f585cf33b02acac2899ea52e Mon Sep 17 00:00:00 2001 From: c4rlosdias Date: Tue, 18 Jul 2023 09:21:47 -0300 Subject: [PATCH 6/9] Add bug fixes --- .../blenderbim/bim/module/tester/operator.py | 8 ++++--- .../blenderbim/bim/module/tester/prop.py | 2 ++ .../blenderbim/bim/module/tester/ui.py | 24 +++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/tester/operator.py b/src/blenderbim/blenderbim/bim/module/tester/operator.py index 3c29a40fb6..55cb3acf97 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/operator.py +++ b/src/blenderbim/blenderbim/bim/module/tester/operator.py @@ -122,15 +122,17 @@ class SelectRequirement(bpy.types.Operator): def execute(self, context): props = context.scene.IfcTesterProperties - props.has_entities = True report = json.loads(props.report) - props.failed_entities.clear() + props.old_index = self.spec_index failed_entities = report[self.spec_index]['requirements'] [self.req_index]['failed_entities'] - print(failed_entities) + props.n_entities = len(failed_entities) + props.has_entities = True if props.n_entities > 0 else False + props.failed_entities.clear() for e in failed_entities: new_entity = props.failed_entities.add() new_entity.element = e['element'] new_entity.reason = e['reason'] + return {"FINISHED"} class SelectEntity(bpy.types.Operator): diff --git a/src/blenderbim/blenderbim/bim/module/tester/prop.py b/src/blenderbim/blenderbim/bim/module/tester/prop.py index d6fa425fab..1d3bf03c21 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/prop.py +++ b/src/blenderbim/blenderbim/bim/module/tester/prop.py @@ -53,12 +53,14 @@ class IfcTesterProperties(PropertyGroup): active_specification_index: IntProperty(name="Active Specification Index") active_requirement_index: IntProperty(name="Active Requirement Index") + old_index: IntProperty(name="", default=0) active_failed_entity_index: IntProperty(name="Active Failed Entity Index") report: StringProperty(default="", name="JSON report") specifications: CollectionProperty(name="Specifications", type=Specification) failed_entities: CollectionProperty(name="FailedEntities", type=FailedEntities) has_report : BoolProperty(default=False, name="") has_entities : BoolProperty(default=False, name="") + n_entities : IntProperty(name="", default=0) diff --git a/src/blenderbim/blenderbim/bim/module/tester/ui.py b/src/blenderbim/blenderbim/bim/module/tester/ui.py index aee0f1a900..1708774393 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/ui.py +++ b/src/blenderbim/blenderbim/bim/module/tester/ui.py @@ -49,9 +49,9 @@ class BIM_PT_tester(Panel): row.operator("bim.select_specs", icon="FILE_FOLDER", text="") row = self.layout.row() - result = row.operator("bim.execute_ifc_tester") + row.operator("bim.execute_ifc_tester") - if self.props.has_report: + if self.props.has_report and self.props.should_load_from_memory: self.layout.template_list( "BIM_UL_tester_specifications", "", @@ -64,7 +64,7 @@ class BIM_PT_tester(Panel): self.draw_editable_ui(context) def draw_editable_ui(self, context): - props = context.scene.IfcTesterProperties + props = context.scene.IfcTesterProperties i = props.active_specification_index dic_report = json.loads(props.report) @@ -77,22 +77,23 @@ class BIM_PT_tester(Panel): row.label(text = f"Passed: {total_successes}/{total} ({percentage}%)") row = self.layout.row() row.label(text = f"Requirements ({n_requirements}):") - c=1 + c=0 box = self.layout.box() for req in dic_report[i]['requirements']: row = box.row(align=True) - row.label(text=f" {c}. {req['description']}") + row.label(text=f" {c+1}. {req['description']}") if req['status']: row.label(text="PASS", icon="CHECKMARK") else: row.label(text="FAIL", icon="CANCEL") op = row.operator("bim.select_requirement", text="", icon="LONGDISPLAY") op.spec_index = i - op.req_index = c - 1 + op.req_index = c c += 1 - if props.has_entities: + + if props.old_index == i and props.n_entities > 0: row = self.layout.row() - row.label(text = "Failed entities :") + row.label(text = f"Failed entities [{props.n_entities}]:") self.layout.template_list( "BIM_UL_tester_failed_entities", "", @@ -101,15 +102,14 @@ class BIM_PT_tester(Panel): self.props, "active_failed_entity_index", ) + class BIM_UL_tester_specifications(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): - props = context.scene.IfcTesterProperties if item: - icon = "WORDWRAP_ON" row = layout.row(align=True) - row.label(text=item.name or "Unnamed", icon=icon) + row.label(text=item.name, icon="WORDWRAP_ON") if item.status: row.label(text="PASS") else: @@ -117,10 +117,8 @@ class BIM_UL_tester_specifications(UIList): class BIM_UL_tester_failed_entities(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): - props = context.scene.IfcTesterProperties ifc_file = tool.Ifc.get() if item: - icon = "WORDWRAP_ON" ifc_id = int(item.element[1:item.element.find('=')]) entity = ifc_file.by_id(ifc_id) row = layout.row(align=True) From 36b45b744d961475bb39a95656bdb9f78de2df6e Mon Sep 17 00:00:00 2001 From: c4rlosdias Date: Tue, 18 Jul 2023 13:35:43 -0300 Subject: [PATCH 7/9] add export bcf to ifctester (2023_07_18) --- .../blenderbim/bim/module/tester/__init__.py | 1 + .../blenderbim/bim/module/tester/operator.py | 25 +++++++++++++++++-- .../blenderbim/bim/module/tester/ui.py | 4 +++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/tester/__init__.py b/src/blenderbim/blenderbim/bim/module/tester/__init__.py index 8daea23cf1..98480fa660 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/tester/__init__.py @@ -25,6 +25,7 @@ classes = ( operator.SelectIfcTesterIfcFile, operator.SelectRequirement, operator.SelectEntity, + operator.ExportBcf, prop.FailedEntities, prop.Specification, prop.IfcTesterProperties, diff --git a/src/blenderbim/blenderbim/bim/module/tester/operator.py b/src/blenderbim/blenderbim/bim/module/tester/operator.py index 55cb3acf97..6926009602 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/operator.py +++ b/src/blenderbim/blenderbim/bim/module/tester/operator.py @@ -54,7 +54,6 @@ class ExecuteIfcTester(bpy.types.Operator): print("Finished loading:", time.time() - start) start = time.time() specs.validate(ifc) - print(specs) print("Finished validating:", time.time() - start) start = time.time() @@ -63,7 +62,7 @@ class ExecuteIfcTester(bpy.types.Operator): engine.report() engine.to_file(output) webbrowser.open("file://" + output) - + report = None report = ifctester.reporter.Json(specs).report()['specifications'] if report: @@ -148,4 +147,26 @@ class SelectEntity(bpy.types.Operator): obj.select_set(True) bpy.context.view_layer.objects.active = obj return {"FINISHED"} + +class ExportBcf(bpy.types.Operator): + bl_idname = "bim.export_bcf" + bl_label = "Export BCF" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + props = context.scene.IfcTesterProperties + with tempfile.TemporaryDirectory() as dirpath: + output = os.path.join(dirpath, "{}.bcf".format(props.specs)) + if props.should_load_from_memory and tool.Ifc.get(): + ifc = tool.Ifc.get() + else: + ifc = ifcopenshell.open(props.ifc_file) + specs = ifctester.ids.open(props.specs) + specs.validate(ifc) + bcf_reporter = ifctester.reporter.Bcf(specs) + bcf_reporter.report() + bcf_reporter.to_file(output) + print("Finished exporting:") + + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/tester/ui.py b/src/blenderbim/blenderbim/bim/module/tester/ui.py index feaffa30aa..1a7f466192 100644 --- a/src/blenderbim/blenderbim/bim/module/tester/ui.py +++ b/src/blenderbim/blenderbim/bim/module/tester/ui.py @@ -62,6 +62,10 @@ class BIM_PT_tester(Panel): ) self.draw_editable_ui(context) + + if self.props.has_report: + row = self.layout.row() + row.operator("bim.export_bcf", text="Export BCF", icon="EXPORT") def draw_editable_ui(self, context): props = context.scene.IfcTesterProperties From d2c22b0b0cf00b02743836ac8bbed01d5b6246e9 Mon Sep 17 00:00:00 2001 From: Carlos Dias <57261862+c4rlosdias@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:27:30 -0300 Subject: [PATCH 8/9] Update handler.py --- src/blenderbim/blenderbim/bim/handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index af272745e3..27e9f34c7a 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -257,7 +257,7 @@ def viewport_shading_changed_callback(area): bpy.context.scene.BIMStylesProperties.active_style_type = "External" -if (bpy.types, "SCENE_PT_scene"): +if getattr(bpy.types, "SCENE_PT_scene"): class Override_SCENE_PT_scene(bpy.types.SCENE_PT_scene): bl_idname = "SCENE_PT_scene_override" From a23a66edc268cc1e4f80938dd5959b15378b83cd Mon Sep 17 00:00:00 2001 From: Carlos Dias <57261862+c4rlosdias@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:28:37 -0300 Subject: [PATCH 9/9] Update __init__.py --- src/blenderbim/blenderbim/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/blenderbim/blenderbim/__init__.py b/src/blenderbim/blenderbim/__init__.py index 517bc3b7c8..44ef0f8a24 100644 --- a/src/blenderbim/blenderbim/__init__.py +++ b/src/blenderbim/blenderbim/__init__.py @@ -44,4 +44,3 @@ if sys.modules.get("bpy", None): def unregister(): blenderbim.bim.unregister() - \ No newline at end of file