mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +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)
|
self.add_view_title(x, view_height + y + VIEW_TITLE_OFFSET_Y, view, layout_dir)
|
||||||
layout_tree.write(layout_path)
|
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:
|
def next_drawing_location(self, layout_root: ET.Element, next_width: float) -> list:
|
||||||
titleblocks = layout_root.findall(f'{SVG}g[@data-type="titleblock"]')
|
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
|
# how wide is the title block frame
|
||||||
try:
|
try:
|
||||||
@@ -403,14 +416,20 @@ class SheetBuilder:
|
|||||||
|
|
||||||
return svg
|
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"]'):
|
for view in root.findall(f'{SVG}g[@data-type="drawing"]'):
|
||||||
drawing_id = int(view.attrib["data-id"])
|
drawing_id = int(view.attrib["data-id"])
|
||||||
try:
|
try:
|
||||||
reference = tool.Ifc.get().by_id(int(view.attrib["data-id"]))
|
reference = tool.Ifc.get().by_id(int(view.attrib["data-id"]))
|
||||||
drawing = tool.Ifc.get().by_guid(view.attrib["data-drawing"])
|
drawing = tool.Ifc.get().by_guid(view.attrib["data-drawing"])
|
||||||
except RuntimeError:
|
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
|
continue
|
||||||
|
|
||||||
images = view.findall(f"{SVG}image")
|
images = view.findall(f"{SVG}image")
|
||||||
|
|||||||
@@ -2838,13 +2838,12 @@ class Drawing(bonsai.core.tool.Drawing):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_drawing_from_sheet(cls, reference: ifcopenshell.entity_instance) -> None:
|
def remove_drawing_from_sheet(cls, reference: ifcopenshell.entity_instance) -> None:
|
||||||
import bonsai.bim.module.drawing.sheeter as sheeter
|
# NOTE: The layout SVG is intentionally NOT modified here. Removing the
|
||||||
|
# drawing group from the SVG file would make the change non-undoable
|
||||||
sheet = tool.Drawing.get_reference_document(reference)
|
# (Blender's undo restores IFC state but not files on disk). Instead,
|
||||||
|
# build_drawings() detects and removes stale groups (those whose IFC
|
||||||
sheet_builder = sheeter.SheetBuilder()
|
# reference no longer exists) the next time the sheet is built, and also
|
||||||
sheet_builder.remove_drawing(reference, sheet)
|
# writes the cleaned layout SVG back to disk at that point.
|
||||||
|
|
||||||
ifcopenshell.api.document.remove_reference(tool.Ifc.get(), reference=reference)
|
ifcopenshell.api.document.remove_reference(tool.Ifc.get(), reference=reference)
|
||||||
|
|
||||||
tool.Drawing.import_sheets()
|
tool.Drawing.import_sheets()
|
||||||
|
|||||||
Reference in New Issue
Block a user