diff --git a/src/bonsai/bonsai/core/drawing.py b/src/bonsai/bonsai/core/drawing.py index 2a1f760570..26794fad22 100644 --- a/src/bonsai/bonsai/core/drawing.py +++ b/src/bonsai/bonsai/core/drawing.py @@ -475,6 +475,11 @@ def remove_drawing( def update_drawing_name( ifc: type[tool.Ifc], drawing_tool: type[tool.Drawing], drawing: ifcopenshell.entity_instance, name: str ) -> None: + # A drawing's Name is used to derive its SVG filename, so two drawings + # sharing a name would resolve to the same file and overwrite each other + # (and tangle the sheet references). Uniquify the name on rename, just like + # new drawings do, ignoring this drawing's own current name. + name = drawing_tool.ensure_unique_drawing_name(name, ignore=drawing) if drawing_tool.get_name(drawing) != name: ifc.run("attribute.edit_attributes", product=drawing, attributes={"Name": name}) diff --git a/src/bonsai/bonsai/core/tool.py b/src/bonsai/bonsai/core/tool.py index 8a77d36661..52014676ff 100644 --- a/src/bonsai/bonsai/core/tool.py +++ b/src/bonsai/bonsai/core/tool.py @@ -357,7 +357,7 @@ class Drawing: def ensure_annotation_in_drawing_plane(cls, obj, camera=None): pass def ensure_drawings_parent_document(cls): pass def ensure_drawings_parent_group(cls): pass - def ensure_unique_drawing_name(cls, name): pass + def ensure_unique_drawing_name(cls, name, ignore=None): pass def ensure_unique_identification(cls, identification): pass def export_font_size(cls, obj): pass def export_symbol(cls, obj): pass diff --git a/src/bonsai/bonsai/tool/drawing.py b/src/bonsai/bonsai/tool/drawing.py index d08faa0229..1760782717 100644 --- a/src/bonsai/bonsai/tool/drawing.py +++ b/src/bonsai/bonsai/tool/drawing.py @@ -617,8 +617,14 @@ class Drawing(bonsai.core.tool.Drawing): props.is_editing_product = True @classmethod - def ensure_unique_drawing_name(cls, name: str) -> str: - names = [e.Name for e in tool.Ifc.get().by_type("IfcAnnotation") if e.ObjectType == "DRAWING"] + def ensure_unique_drawing_name( + cls, name: str, ignore: Optional[ifcopenshell.entity_instance] = None + ) -> str: + names = [ + e.Name + for e in tool.Ifc.get().by_type("IfcAnnotation") + if e.ObjectType == "DRAWING" and e != ignore + ] while name in names: name += "-X" return name diff --git a/src/bonsai/test/core/test_drawing.py b/src/bonsai/test/core/test_drawing.py index 914ddbbb54..79dd56ff7d 100644 --- a/src/bonsai/test/core/test_drawing.py +++ b/src/bonsai/test/core/test_drawing.py @@ -533,6 +533,7 @@ class TestRemoveDrawing: class TestUpdateDrawingName: def test_do_not_update_if_name_unchanged(self, ifc, drawing): + drawing.ensure_unique_drawing_name("name", ignore="drawing").should_be_called().will_return("name") drawing.get_name("drawing").should_be_called().will_return("name") drawing.set_camera_name("drawing", "name").should_be_called() drawing.get_drawing_group("drawing").should_be_called().will_return("group") @@ -549,6 +550,7 @@ class TestUpdateDrawingName: subject.update_drawing_name(ifc, drawing, drawing="drawing", name="name") def test_run(self, ifc, drawing): + drawing.ensure_unique_drawing_name("name", ignore="drawing").should_be_called().will_return("name") drawing.get_name("drawing").should_be_called().will_return("oldname") ifc.run("attribute.edit_attributes", product="drawing", attributes={"Name": "name"}).should_be_called() drawing.set_camera_name("drawing", "name").should_be_called() diff --git a/src/bonsai/test/tool/test_drawing.py b/src/bonsai/test/tool/test_drawing.py index 580b326822..030822a81f 100644 --- a/src/bonsai/test/tool/test_drawing.py +++ b/src/bonsai/test/tool/test_drawing.py @@ -385,10 +385,12 @@ class TestEnsureUniqueDrawingName(NewFile): ifc = ifcopenshell.file() tool.Ifc.set(ifc) assert subject.ensure_unique_drawing_name("FOOBAR") == "FOOBAR" - ifc.createIfcAnnotation(Name="FOOBAR", ObjectType="DRAWING") + foobar = ifc.createIfcAnnotation(Name="FOOBAR", ObjectType="DRAWING") assert subject.ensure_unique_drawing_name("FOOBAR") == "FOOBAR-X" ifc.createIfcAnnotation(Name="FOOBAR-X", ObjectType="DRAWING") assert subject.ensure_unique_drawing_name("FOOBAR") == "FOOBAR-X-X" + # A drawing may keep its own name (e.g. when re-applying it on rename). + assert subject.ensure_unique_drawing_name("FOOBAR", ignore=foobar) == "FOOBAR" class TestEnsureUniqueIdentification(NewFile):