mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Fix #7275: Make remove_drawing_from_sheet undoable
Blender's undo restores IFC state but not files on disk. remove_drawing_from_sheet no longer modifies the layout SVG. build_drawings() handles stale groups (reference removed from IFC) by skipping them in the output tree only. next_drawing_ location() filters stale groups when placing new drawings. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -132,9 +132,22 @@ class SheetBuilder:
|
||||
self.add_view_title(x, view_height + y + VIEW_TITLE_OFFSET_Y, view, layout_dir)
|
||||
layout_tree.write(layout_path)
|
||||
|
||||
@staticmethod
|
||||
def _ifc_entity_exists(ifc: ifcopenshell.file, entity_id: int) -> bool:
|
||||
try:
|
||||
ifc.by_id(entity_id)
|
||||
return True
|
||||
except RuntimeError:
|
||||
return False
|
||||
|
||||
def next_drawing_location(self, layout_root: ET.Element, next_width: float) -> list:
|
||||
titleblocks = layout_root.findall(f'{SVG}g[@data-type="titleblock"]')
|
||||
drawings = layout_root.findall(f'{SVG}g[@data-type="drawing"]')
|
||||
ifc = tool.Ifc.get()
|
||||
drawings = [
|
||||
g
|
||||
for g in layout_root.findall(f'{SVG}g[@data-type="drawing"]')
|
||||
if self._ifc_entity_exists(ifc, int(g.attrib.get("data-id", "0")))
|
||||
]
|
||||
|
||||
# how wide is the title block frame
|
||||
try:
|
||||
@@ -403,14 +416,20 @@ class SheetBuilder:
|
||||
|
||||
return svg
|
||||
|
||||
def build_drawings(self, root: ET.Element, sheet: ifcopenshell.entity_instance):
|
||||
def build_drawings(self, root: ET.Element, sheet: ifcopenshell.entity_instance) -> None:
|
||||
for view in root.findall(f'{SVG}g[@data-type="drawing"]'):
|
||||
drawing_id = int(view.attrib["data-id"])
|
||||
try:
|
||||
reference = tool.Ifc.get().by_id(int(view.attrib["data-id"]))
|
||||
drawing = tool.Ifc.get().by_guid(view.attrib["data-drawing"])
|
||||
except RuntimeError:
|
||||
# Perhaps the SVG has outdated content or is edited externally which we cannot control.
|
||||
# The layout SVG has a drawing group whose IFC reference no longer
|
||||
# exists. This is intentional: remove_drawing_from_sheet deliberately
|
||||
# leaves the group in the layout SVG so that Blender's undo can restore
|
||||
# the IFC reference and the group is still there to build from. Remove
|
||||
# it only from the in-memory tree so it doesn't appear in the output
|
||||
# sheet; the layout SVG file on disk is left untouched.
|
||||
root.remove(view)
|
||||
continue
|
||||
|
||||
images = view.findall(f"{SVG}image")
|
||||
|
||||
@@ -2838,13 +2838,12 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
|
||||
@classmethod
|
||||
def remove_drawing_from_sheet(cls, reference: ifcopenshell.entity_instance) -> None:
|
||||
import bonsai.bim.module.drawing.sheeter as sheeter
|
||||
|
||||
sheet = tool.Drawing.get_reference_document(reference)
|
||||
|
||||
sheet_builder = sheeter.SheetBuilder()
|
||||
sheet_builder.remove_drawing(reference, sheet)
|
||||
|
||||
# NOTE: The layout SVG is intentionally NOT modified here. Removing the
|
||||
# drawing group from the SVG file would make the change non-undoable
|
||||
# (Blender's undo restores IFC state but not files on disk). Instead,
|
||||
# build_drawings() detects and removes stale groups (those whose IFC
|
||||
# reference no longer exists) the next time the sheet is built, and also
|
||||
# writes the cleaned layout SVG back to disk at that point.
|
||||
ifcopenshell.api.document.remove_reference(tool.Ifc.get(), reference=reference)
|
||||
|
||||
tool.Drawing.import_sheets()
|
||||
|
||||
Reference in New Issue
Block a user