From 40dcd393c6f242ee6f15195d4c4b1219d1e77abb Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 7 Jul 2025 13:00:04 +0500 Subject: [PATCH] Fix addresses not updating immediately in IfcPerson UI Found by @sboddy in #6869 Caused by trying to remove Blender entities from owner/data.py --- src/bonsai/bonsai/bim/module/owner/data.py | 21 +----- src/bonsai/bonsai/bim/module/owner/ui.py | 7 +- src/bonsai/bonsai/tool/owner.py | 77 ++++++++++------------ 3 files changed, 42 insertions(+), 63 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/owner/data.py b/src/bonsai/bonsai/bim/module/owner/data.py index c1bc7d8610..16d0969640 100644 --- a/src/bonsai/bonsai/bim/module/owner/data.py +++ b/src/bonsai/bonsai/bim/module/owner/data.py @@ -60,30 +60,15 @@ class RolesAddressesData: return results @classmethod - def get_address_list_attributes(cls, address: ifcopenshell.entity_instance) -> list[dict[str, Any]]: - results: list[dict[str, Any]] = [] - props = tool.Owner.get_owner_props() + def get_address_list_attributes(cls, address: ifcopenshell.entity_instance) -> list[str]: if address.is_a("IfcPostalAddress"): names = ["AddressLines"] elif address.is_a("IfcTelecomAddress"): names = ["TelephoneNumbers", "FacsimileNumbers", "ElectronicMailAddresses", "MessagingIDs"] else: assert False, f"Unexpected entity: {address}" - for name in names: - if name == "AddressLines": - items = [{"id": id, "prop": prop} for id, prop in enumerate(props.address_lines)] - elif name == "TelephoneNumbers": - items = [{"id": id, "prop": prop} for id, prop in enumerate(props.telephone_numbers)] - elif name == "FacsimileNumbers": - items = [{"id": id, "prop": prop} for id, prop in enumerate(props.facsimile_numbers)] - elif name == "ElectronicMailAddresses": - items = [{"id": id, "prop": prop} for id, prop in enumerate(props.electronic_mail_addresses)] - elif name == "MessagingIDs": - items = [{"id": id, "prop": prop} for id, prop in enumerate(props.messaging_ids)] - else: - assert False, f"Unexpected name: {name}" - results.append({"name": name, "items": items}) - return results + + return names class PeopleData(RolesAddressesData): diff --git a/src/bonsai/bonsai/bim/module/owner/ui.py b/src/bonsai/bonsai/bim/module/owner/ui.py index c786a383d0..8e00858684 100644 --- a/src/bonsai/bonsai/bim/module/owner/ui.py +++ b/src/bonsai/bonsai/bim/module/owner/ui.py @@ -72,12 +72,13 @@ def draw_addresses(box: bpy.types.UILayout, parent: dict[str, Any]) -> None: op = row.operator("bim.add_address_attribute", icon="ADD", text="") op.name = attribute["name"] - for item in attribute["items"]: + collection = tool.Owner.get_address_collection(attribute["name"]) + for i, item in enumerate(collection): row = box.row(align=True) - row.prop(item["prop"], "name", text="") + row.prop(item, "name", text="") op = row.operator("bim.remove_address_attribute", icon="REMOVE", text="") op.name = attribute["name"] - op.id = item["id"] + op.id = i else: row = box.row(align=True) row.label(text=address["label"]) diff --git a/src/bonsai/bonsai/tool/owner.py b/src/bonsai/bonsai/tool/owner.py index 788d0ddb12..8f57f9ce8a 100644 --- a/src/bonsai/bonsai/tool/owner.py +++ b/src/bonsai/bonsai/tool/owner.py @@ -26,7 +26,7 @@ from typing import Union, Any, TYPE_CHECKING, Literal, assert_never if TYPE_CHECKING: from bonsai.bim.module.owner.prop import BIMOwnerProperties - from bonsai.bim.prop import Attribute + from bonsai.bim.prop import Attribute, StrProperty class Owner(bonsai.core.tool.Owner): @@ -60,9 +60,28 @@ class Owner(bonsai.core.tool.Owner): props = cls.get_owner_props() props.active_address_id = address.id() + @classmethod + def get_address_collection_name(cls, attribute_name: AddressAttributeType) -> str: + blender_names: dict[tool.Owner.AddressAttributeType, str] = { + "AddressLines": "address_lines", + "TelephoneNumbers": "telephone_numbers", + "FacsimileNumbers": "facsimile_numbers", + "ElectronicMailAddresses": "electronic_mail_addresses", + "MessagingIDs": "messaging_ids", + } + return blender_names[attribute_name] + + @classmethod + def get_address_collection( + cls, attribute_name: AddressAttributeType + ) -> bpy.types.bpy_prop_collection_idprop[StrProperty]: + props = cls.get_owner_props() + blender_name = cls.get_address_collection_name(attribute_name) + return getattr(props, blender_name) + @classmethod def import_address_attributes(cls) -> None: - props = props = cls.get_owner_props() + props = cls.get_owner_props() props.address_attributes.clear() props.address_lines.clear() props.telephone_numbers.clear() @@ -73,21 +92,10 @@ class Owner(bonsai.core.tool.Owner): address = cls.get_address() def callback(name: str, prop, data: dict[str, Any]) -> None: - if name == "AddressLines": + if name in cls.ADDREESS_ATTRIBUTE_TYPES: + collection = cls.get_address_collection(name) for line in data[name] or []: - props.address_lines.add().name = line - elif name == "TelephoneNumbers": - for line in data[name] or []: - props.telephone_numbers.add().name = line - elif name == "FacsimileNumbers": - for line in data[name] or []: - props.facsimile_numbers.add().name = line - elif name == "ElectronicMailAddresses": - for line in data[name] or []: - props.electronic_mail_addresses.add().name = line - elif name == "MessagingIDs": - for line in data[name] or []: - props.messaging_ids.add().name = line + collection.add().name = line bonsai.bim.helper.import_attributes(address.is_a(), props.address_attributes, address.get_info(), callback) @@ -117,38 +125,23 @@ class Owner(bonsai.core.tool.Owner): AddressAttributeType = Literal[ "AddressLines", "TelephoneNumbers", "FacsimileNumbers", "ElectronicMailAddresses", "MessagingIDs" ] + ADDREESS_ATTRIBUTE_TYPES = ( + "AddressLines", + "TelephoneNumbers", + "FacsimileNumbers", + "ElectronicMailAddresses", + "MessagingIDs", + ) @classmethod def add_address_attribute(cls, name: AddressAttributeType) -> None: - props = cls.get_owner_props() - if name == "AddressLines": - props.address_lines.add() - elif name == "TelephoneNumbers": - props.telephone_numbers.add() - elif name == "FacsimileNumbers": - props.facsimile_numbers.add() - elif name == "ElectronicMailAddresses": - props.electronic_mail_addresses.add() - elif name == "MessagingIDs": - props.messaging_ids.add() - else: - assert_never(name) + collection = cls.get_address_collection(name) + collection.add() @classmethod def remove_address_attribute(cls, name: AddressAttributeType, id: int) -> None: - props = cls.get_owner_props() - if name == "AddressLines": - props.address_lines.remove(id) - elif name == "TelephoneNumbers": - props.telephone_numbers.remove(id) - elif name == "FacsimileNumbers": - props.facsimile_numbers.remove(id) - elif name == "ElectronicMailAddresses": - props.electronic_mail_addresses.remove(id) - elif name == "MessagingIDs": - props.messaging_ids.remove(id) - else: - assert_never(name) + collection = cls.get_address_collection(name) + collection.remove(id) @classmethod def set_organisation(cls, organisation: ifcopenshell.entity_instance) -> None: