diff --git a/src/bonsai/bonsai/bim/module/tester/operator.py b/src/bonsai/bonsai/bim/module/tester/operator.py index f7ff1aa744..822ffd571c 100644 --- a/src/bonsai/bonsai/bim/module/tester/operator.py +++ b/src/bonsai/bonsai/bim/module/tester/operator.py @@ -135,6 +135,7 @@ class IfcTesterNamespace(socketio.AsyncNamespace): try: request_id = data.get("id") ids_string = data.get("ids") + props = tool.Tester.get_tester_props() if not request_id: await self.emit("error", {"error": "No request ID provided"}, room=sid) @@ -176,7 +177,7 @@ class IfcTesterNamespace(socketio.AsyncNamespace): json_report = json_reporter.to_string() # HTML report - html_reporter = ifctester.reporter.Html(ids) + html_reporter = ifctester.reporter.Html(ids, hide_skipped=props.hide_skipped_specs) html_reporter.report() html_report = html_reporter.to_string() @@ -267,7 +268,7 @@ class ExecuteIfcTester(bpy.types.Operator): start = time.time() if props.generate_html_report: - engine = ifctester.reporter.Html(specs) + engine = ifctester.reporter.Html(specs, props.hide_skipped_specs) engine.report() output_path = output.as_posix() engine.to_file(output_path) diff --git a/src/bonsai/bonsai/bim/module/tester/prop.py b/src/bonsai/bonsai/bim/module/tester/prop.py index 824542c96d..fb20a0d4cd 100644 --- a/src/bonsai/bonsai/bim/module/tester/prop.py +++ b/src/bonsai/bonsai/bim/module/tester/prop.py @@ -82,6 +82,7 @@ class IfcTesterProperties(PropertyGroup): webapp_server_port: IntProperty(name="Webapp Server Port", default=0) webapp_is_running: BoolProperty(default=False, name="Webapp Is Running", options=set()) websocket_server_port: IntProperty(name="WebSocket Server Port", default=0) + hide_skipped_specs: BoolProperty(default=False, name="Hide skipped Specifications", options=set()) if TYPE_CHECKING: specs: MultipleFileSelect diff --git a/src/bonsai/bonsai/bim/module/tester/ui.py b/src/bonsai/bonsai/bim/module/tester/ui.py index 73d1bbc102..66648f4e43 100644 --- a/src/bonsai/bonsai/bim/module/tester/ui.py +++ b/src/bonsai/bonsai/bim/module/tester/ui.py @@ -62,7 +62,8 @@ class BIM_PT_tester(Panel): row.prop(props, "generate_ods_report") row = self.layout.row() row.prop(props, "flag") - + row = self.layout.row() + row.prop(props, "hide_skipped_specs") if not tool.Ifc.get() or not props.should_load_from_memory: row = self.layout.row(align=True) props.ifc_files.layout_file_select(row, "*.ifc;*.ifczip;*.ifcxml", "IFC File(s)") @@ -104,6 +105,9 @@ class BIM_PT_tester(Panel): def draw_editable_ui(self, context: bpy.types.Context) -> None: props = tool.Tester.get_tester_props() specification = TesterData.data["specification"] + is_skipped = specification["total_checks"] == 0 and specification["cardinality"] == "optional" + if props.hide_skipped_specs and is_skipped: + return n_requirements = len(specification["requirements"]) @@ -179,6 +183,34 @@ class BIM_UL_tester_specifications(UIList): row.label(text=item.name, icon="CHECKMARK" if item.status else "CANCEL") row.label(text=item.description) + def filter_items(self, context: bpy.types.Context, data: IfcTesterProperties, propname: str): + items = getattr(data, propname) + filter_flags = [self.bitflag_filter_item] * len(items) + + props = tool.Tester.get_tester_props() + if props.hide_skipped_specs: + for idx, item in enumerate(items): + report = tool.Tester.report[idx] + if report["total_checks"] != 0: + filter_flags[idx] |= self.bitflag_filter_item + else: + filter_flags[idx] &= ~self.bitflag_filter_item + + filter_name = self.filter_name + if filter_name: + name_filtered = bpy.types.UI_UL_list.filter_items_by_name( + filter_name, + self.bitflag_filter_item, + items, + "name", + ) + if len(name_filtered) == len(filter_flags): + for idx, flag in enumerate(name_filtered): + if flag == 0: + filter_flags[idx] &= ~self.bitflag_filter_item + + return filter_flags, [] + class BIM_UL_tester_failed_entities(UIList): def draw_item( diff --git a/src/ifctester/ifctester/reporter.py b/src/ifctester/ifctester/reporter.py index 90e0b7fc53..059b8123db 100644 --- a/src/ifctester/ifctester/reporter.py +++ b/src/ifctester/ifctester/reporter.py @@ -55,6 +55,7 @@ class Results(TypedDict): date: str filepath: str filename: str + hide_skipped: bool specifications: list[ResultsSpecification] status: bool total_specifications: int @@ -236,9 +237,10 @@ class Txt(Console): class Json(Reporter): - def __init__(self, ids: Ids): + def __init__(self, ids: Ids,hide_skipped = False): super().__init__(ids) self.results = Results() + self.results["hide_skipped"] = hide_skipped def report(self) -> Results: self.results["title"] = self.ids.info.get("title", "Untitled IDS") @@ -435,14 +437,14 @@ class Json(Reporter): class Html(Json): - def __init__(self, ids: Ids): + def __init__(self, ids: Ids, hide_skipped: bool = False): self.entity_limit = 100 super().__init__(ids) + self.results["hide_skipped"] = hide_skipped def report(self) -> None: super().report() for spec in self.results["specifications"]: - print("checking", spec["cardinality"]) if spec["cardinality"] == "optional" and spec["total_checks"] == 0: spec["is_skipped"] = True spec["is_prohibited"] = spec["cardinality"] == "prohibited" diff --git a/src/ifctester/ifctester/templates/report.html b/src/ifctester/ifctester/templates/report.html index 4d94acb163..456e90e5f4 100644 --- a/src/ifctester/ifctester/templates/report.html +++ b/src/ifctester/ifctester/templates/report.html @@ -34,6 +34,9 @@ } body { font-family: 'Arial', sans-serif; padding: 10px 40px; } section { padding: 15px; border-radius: 5px; border: 1px solid #eee; margin-bottom: 15px; } + {{#hide_skipped}} + .specification.is-skipped { display: none; } + {{/hide_skipped}} section>h2 { margin-top: 0px; } span.time { color: #999; font-style: italic; float: right; } span.step-time { float: right; color: #555; font-size: 0.8em; font-style: italic; } @@ -96,7 +99,7 @@