From 6bcf00ef31ce2c427719cbcc0dd26b9e9a4d563a Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Thu, 28 Apr 2022 19:57:47 +1000 Subject: [PATCH] #1153 Reimplement ability to build SVG tables from referenced ODS documents --- .../blenderbim/bim/module/drawing/operator.py | 15 +++----- .../blenderbim/bim/module/drawing/sheeter.py | 11 +++--- .../blenderbim/bim/module/drawing/ui.py | 2 +- src/blenderbim/blenderbim/core/drawing.py | 7 +++- src/blenderbim/blenderbim/core/tool.py | 3 +- src/blenderbim/blenderbim/tool/drawing.py | 34 ++++++++++------- src/blenderbim/test/core/test_drawing.py | 4 +- src/blenderbim/test/tool/test_drawing.py | 37 ++++++++++++------- 8 files changed, 65 insertions(+), 48 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index 008a8f3d1e..02c919eb90 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -624,7 +624,7 @@ class CreateSheets(bpy.types.Operator): props = scene.DocProperties active_sheet = props.sheets[props.active_sheet_index] sheet = tool.Ifc.get().by_id(active_sheet.ifc_definition_id) - name = tool.Drawing.get_sheet_filename(sheet) + name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0] sheet_builder = sheeter.SheetBuilder() sheet_builder.data_dir = scene.BIMProperties.data_dir sheet_builder.build(sheet) @@ -956,18 +956,13 @@ class OpenSchedule(bpy.types.Operator, Operator): core.open_schedule(tool.Drawing, schedule=tool.Ifc.get().by_id(self.schedule)) -class BuildSchedule(bpy.types.Operator): +class BuildSchedule(bpy.types.Operator, Operator): bl_idname = "bim.build_schedule" bl_label = "Build Schedule" + schedule: bpy.props.IntProperty() - def execute(self, context): - props = context.scene.DocProperties - schedule = props.active_schedule - schedule_creator = scheduler.Scheduler() - outfile = os.path.join(context.scene.BIMProperties.data_dir, "schedules", schedule.name + ".svg") - schedule_creator.schedule(schedule.file, outfile) - open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, outfile) - return {"FINISHED"} + def _execute(self, context): + core.build_schedule(tool.Drawing, schedule=tool.Ifc.get().by_id(self.schedule)) class AddScheduleToSheet(bpy.types.Operator): diff --git a/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py b/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py index 2a8229b660..e90d7a9c6a 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py @@ -31,8 +31,7 @@ class SheetBuilder: self.data_dir = None self.scale = "NTS" - def create(self, name, titleblock_name): - sheet_path = os.path.join(self.data_dir, "sheets", f"{name}.svg") + def create(self, sheet_path, titleblock_name): root = ET.Element("svg") root.attrib["xmlns"] = "http://www.w3.org/2000/svg" root.attrib["xmlns:xlink"] = "http://www.w3.org/1999/xlink" @@ -62,7 +61,7 @@ class SheetBuilder: def add_drawing(self, drawing, sheet): filename = drawing.Name - sheet_name = tool.Drawing.get_sheet_filename(sheet) + sheet_name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0] sheet_dir = os.path.join(self.data_dir, "sheets") drawing_dir = os.path.join(self.data_dir, "diagrams") sheet_path = os.path.join(sheet_dir, sheet_name + ".svg") @@ -112,7 +111,7 @@ class SheetBuilder: sheet_tree.write(sheet_path) def remove_drawing(self, drawing, sheet): - sheet_name = tool.Drawing.get_sheet_filename(sheet) + sheet_name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0] sheet_dir = os.path.join(self.data_dir, "sheets") sheet_path = os.path.join(sheet_dir, sheet_name + ".svg") @@ -168,7 +167,7 @@ class SheetBuilder: title.attrib["height"] = str(self.convert_to_mm(title_root.attrib.get("height"))) def build(self, sheet): - sheet_name = tool.Drawing.get_sheet_filename(sheet) + sheet_name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0] os.makedirs(os.path.join(self.data_dir, "build", sheet_name), exist_ok=True) sheet_path = os.path.join(self.data_dir, "sheets", f"{sheet_name}.svg") @@ -193,7 +192,7 @@ class SheetBuilder: titleblock.remove(image) def build_drawings(self, root, sheet): - sheet_name = tool.Drawing.get_sheet_filename(sheet) + sheet_name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0] references = tool.Drawing.get_document_references(sheet) drawing_references = {tool.Drawing.get_reference_element(r): r for r in references} diff --git a/src/blenderbim/blenderbim/bim/module/drawing/ui.py b/src/blenderbim/blenderbim/bim/module/drawing/ui.py index 085780c5a6..8c3335d945 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/ui.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/ui.py @@ -217,7 +217,7 @@ class BIM_PT_schedules(Panel): row = self.layout.row(align=True) row.alignment = "RIGHT" row.operator("bim.open_schedule", icon="URL", text="").schedule = active_schedule.ifc_definition_id - row.operator("bim.build_schedule", icon="LINENUMBERS_ON", text="") + row.operator("bim.build_schedule", icon="LINENUMBERS_ON", text="").schedule = active_schedule.ifc_definition_id row.operator("bim.remove_schedule", icon="X", text="").schedule = active_schedule.ifc_definition_id self.layout.template_list("BIM_UL_generic", "", self.props, "schedules", self.props, "active_schedule_index") diff --git a/src/blenderbim/blenderbim/core/drawing.py b/src/blenderbim/blenderbim/core/drawing.py index fe9e4ef74e..10b02438cf 100644 --- a/src/blenderbim/blenderbim/core/drawing.py +++ b/src/blenderbim/blenderbim/core/drawing.py @@ -81,7 +81,7 @@ def add_sheet(ifc, drawing, titleblock=None): def open_sheet(drawing, sheet=None): - drawing.open_svg(drawing.get_sheet_filename(sheet)) + drawing.open_svg(drawing.get_document_uri(sheet)) def remove_sheet(ifc, drawing, sheet=None): @@ -208,6 +208,11 @@ def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None) drawing_tool.enable_editing(obj) +def build_schedule(drawing, schedule=None): + drawing.create_svg_schedule(schedule) + drawing.open_svg(drawing.get_document_uri(schedule)) + + def sync_references(ifc, collector, drawing_tool, drawing=None): if not drawing_tool.has_linework(drawing): return diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index ef8440f7c5..29129a2ec5 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -156,6 +156,7 @@ class Document: class Drawing: def create_annotation_object(cls, object_type): pass def create_camera(cls, name, matrix): pass + def create_svg_schedule(cls, schedule): pass def create_svg_sheet(cls, document, titleblock): pass def delete_collection(cls, collection): pass def delete_drawing_elements(cls, elements): pass @@ -179,6 +180,7 @@ class Drawing: def generate_sheet_identification(cls): pass def get_annotation_context(cls, target_view): pass def get_body_context(cls): pass + def get_document_uri(cls, document): pass def get_drawing_collection(cls, drawing): pass def get_drawing_group(cls, drawing): pass def get_drawing_target_view(cls, drawing): pass @@ -186,7 +188,6 @@ class Drawing: def get_ifc_representation_class(cls, object_type): pass def get_name(cls, element): pass def get_schedule_location(cls, schedule): pass - def get_sheet_filename(cls, document): pass def get_text_literal(cls, obj): pass def get_text_product(cls, element): pass def import_drawings(cls): pass diff --git a/src/blenderbim/blenderbim/tool/drawing.py b/src/blenderbim/blenderbim/tool/drawing.py index b3cbb92028..ad7b472eed 100644 --- a/src/blenderbim/blenderbim/tool/drawing.py +++ b/src/blenderbim/blenderbim/tool/drawing.py @@ -29,6 +29,7 @@ import blenderbim.core.geometry import blenderbim.tool as tool import ifcopenshell.util.representation import blenderbim.bim.module.drawing.sheeter as sheeter +import blenderbim.bim.module.drawing.scheduler as scheduler import blenderbim.bim.module.drawing.annotation as annotation import blenderbim.bim.module.drawing.helper as helper @@ -72,11 +73,16 @@ class Drawing(blenderbim.core.tool.Drawing): bpy.context.scene.collection.objects.link(camera) return camera + @classmethod + def create_svg_schedule(cls, schedule): + schedule_creator = scheduler.Scheduler() + schedule_creator.schedule(cls.get_schedule_location(schedule), cls.get_document_uri(schedule)) + @classmethod def create_svg_sheet(cls, document, titleblock): sheet_builder = sheeter.SheetBuilder() sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir - sheet_builder.create(cls.get_sheet_filename(document), titleblock) + sheet_builder.create(cls.get_document_uri(document), titleblock) @classmethod def delete_collection(cls, collection): @@ -173,6 +179,18 @@ class Drawing(blenderbim.core.tool.Drawing): def get_body_context(cls): return ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW") + @classmethod + def get_document_uri(cls, document): + if hasattr(document, "Identification"): + name = document.Identification or "X" + else: + name = document.DocumentId or "X" + name += " - " + (document.Name or "Unnamed") + if document.Scope == "DOCUMENTATION": + return os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", name + ".svg") + elif document.Scope == "SCHEDULE": + return os.path.join(bpy.context.scene.BIMProperties.data_dir, "schedules", name + ".svg") + @classmethod def get_drawing_collection(cls, drawing): obj = tool.Ifc.get_object(drawing) @@ -211,15 +229,6 @@ class Drawing(blenderbim.core.tool.Drawing): return schedule.DocumentReferences[0].Location return schedule.Location - @classmethod - def get_sheet_filename(cls, document): - if hasattr(document, "Identification"): - name = document.Identification or "X" - else: - name = document.DocumentId or "X" - name += " - " + (document.Name or "Unnamed") - return name - @classmethod def generate_drawing_matrix(cls, target_view, location_hint): x = 0 if location_hint == 0 else bpy.context.scene.cursor.matrix[0][3] @@ -367,10 +376,9 @@ class Drawing(blenderbim.core.tool.Drawing): ) @classmethod - def open_svg(cls, filename): + def open_svg(cls, uri): cls.open_with_user_command( - bpy.context.preferences.addons["blenderbim"].preferences.svg_command, - os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", filename + ".svg"), + bpy.context.preferences.addons["blenderbim"].preferences.svg_command, uri ) @classmethod diff --git a/src/blenderbim/test/core/test_drawing.py b/src/blenderbim/test/core/test_drawing.py index f6484cab03..19e69f1f97 100644 --- a/src/blenderbim/test/core/test_drawing.py +++ b/src/blenderbim/test/core/test_drawing.py @@ -114,8 +114,8 @@ class TestAddSheet: class TestOpenSheet: def test_run(self, drawing): - drawing.get_sheet_filename("sheet").should_be_called().will_return("filename") - drawing.open_svg("filename").should_be_called() + drawing.get_document_uri("sheet").should_be_called().will_return("uri") + drawing.open_svg("uri").should_be_called() subject.open_sheet(drawing, sheet="sheet") diff --git a/src/blenderbim/test/tool/test_drawing.py b/src/blenderbim/test/tool/test_drawing.py index 32b9967418..fbe28d318d 100644 --- a/src/blenderbim/test/tool/test_drawing.py +++ b/src/blenderbim/test/tool/test_drawing.py @@ -51,7 +51,7 @@ class TestCreateCamera(NewFile): class TestCreateSvgSheet(NewFile): def test_run(self): ifc = ifcopenshell.file() - document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR") + document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="DOCUMENTATION") subject.create_svg_sheet(document, "A1") assert os.path.isfile(os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", "X - FOOBAR.svg")) @@ -221,6 +221,26 @@ class TestGetBodyContext(NewFile): assert subject.get_body_context() == context +class TestGetDocumentUri(NewFile): + def test_get_sheet_uri(self): + ifc = ifcopenshell.file() + document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="DOCUMENTATION") + result = subject.get_document_uri(document) + assert result == os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", "X - FOOBAR.svg") + + def test_get_schedule_uri(self): + ifc = ifcopenshell.file() + document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="SCHEDULE") + result = subject.get_document_uri(document) + assert result == os.path.join(bpy.context.scene.BIMProperties.data_dir, "schedules", "X - FOOBAR.svg") + + def test_run_ifc2x3(self): + ifc = ifcopenshell.file(schema="IFC2X3") + document = ifc.createIfcDocumentInformation(DocumentId="X", Name="FOOBAR", Scope="DOCUMENTATION") + result = subject.get_document_uri(document) + assert result == os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", "X - FOOBAR.svg") + + class TestGetDrawingCollection(NewFile): def test_run(self): ifc = ifcopenshell.file() @@ -288,21 +308,10 @@ class TestGetScheduleLocation(NewFile): def test_run_ifc2x3(self): ifc = ifcopenshell.file(schema="IFC2X3") + tool.Ifc.set(ifc) reference = ifc.createIfcDocumentReference(Location="uri") schedule = ifc.createIfcDocumentInformation(DocumentReferences=[reference]) - subject.get_sheet_filename(schedule) == "uri" - - -class TestGetSheetFilename(NewFile): - def test_run(self): - ifc = ifcopenshell.file() - document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="DOCUMENTATION") - subject.get_sheet_filename(document) == "X - FOOBAR" - - def test_run_ifc2x3(self): - ifc = ifcopenshell.file(schema="IFC2X3") - document = ifc.createIfcDocumentInformation(DocumentId="X", Name="FOOBAR", Scope="DOCUMENTATION") - subject.get_sheet_filename(document) == "X - FOOBAR" + subject.get_schedule_location(schedule) == "uri" class TestGenerateDrawingMatrix(NewFile):