From 4e94d0dc10acd52d17186c2240aa10806c74a17e Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 10 Apr 2023 22:30:21 +1000 Subject: [PATCH] Fix #2516. Add/build/remove/view/rename/copy sheet/drawing/schedule now all references and updates user configurable relative paths. --- .../blenderbim/bim/module/drawing/__init__.py | 11 +- .../blenderbim/bim/module/drawing/data.py | 2 +- .../blenderbim/bim/module/drawing/operator.py | 137 +++++++++++------- .../blenderbim/bim/module/drawing/prop.py | 29 +--- .../blenderbim/bim/module/drawing/sheeter.py | 76 +++++----- .../bim/module/drawing/svgwriter.py | 8 +- .../blenderbim/bim/module/drawing/ui.py | 14 +- src/blenderbim/blenderbim/bim/ui.py | 4 +- src/blenderbim/blenderbim/core/drawing.py | 64 +++++++- src/blenderbim/blenderbim/core/tool.py | 24 ++- src/blenderbim/blenderbim/tool/drawing.py | 34 ++++- src/blenderbim/test/core/test_drawing.py | 91 +++++++++++- src/blenderbim/test/tool/test_drawing.py | 6 +- 13 files changed, 350 insertions(+), 150 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/__init__.py b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py index d3bd242d3f..099c09826d 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py @@ -30,7 +30,9 @@ classes = ( operator.AddSchedule, operator.AddScheduleToSheet, operator.AddSheet, + operator.AddTextLiteral, operator.BuildSchedule, + operator.ChangeSheetTitleBlock, operator.CleanWireframes, operator.ContractSheet, operator.CreateDrawing, @@ -40,8 +42,6 @@ classes = ( operator.DisableEditingSchedules, operator.DisableEditingSheets, operator.DisableEditingText, - operator.AddTextLiteral, - operator.RemoveTextLiteral, operator.DuplicateDrawing, operator.EditAssignedProduct, operator.EditText, @@ -53,20 +53,21 @@ classes = ( operator.LoadDrawings, operator.LoadSchedules, operator.LoadSheets, + operator.OpenDrawing, operator.OpenSchedule, operator.OpenSheet, - operator.ChangeSheetTitleBlock, - operator.OpenView, operator.RemoveDrawing, operator.RemoveDrawingFromSheet, operator.RemoveDrawingStyle, operator.RemoveDrawingStyleAttribute, operator.RemoveSchedule, operator.RemoveSheet, + operator.RemoveTextLiteral, + operator.RenameSheet, operator.ResizeText, operator.SaveDrawingStyle, - operator.SelectDocIfcFile, operator.SelectAssignedProduct, + operator.SelectDocIfcFile, prop.Variable, prop.Drawing, prop.Schedule, diff --git a/src/blenderbim/blenderbim/bim/module/drawing/data.py b/src/blenderbim/blenderbim/bim/module/drawing/data.py index e861a57c2e..eb5ad290bc 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/data.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/data.py @@ -61,7 +61,7 @@ class SheetsData: @classmethod def total_sheets(cls): - return len([d for d in tool.Ifc.get().by_type("IfcDocumentInformation") if d.Scope == "DOCUMENTATION"]) + return len([d for d in tool.Ifc.get().by_type("IfcDocumentInformation") if d.Scope == "SHEET"]) class DrawingsData: diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index ba6b0e9140..80026ec1a2 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -245,7 +245,7 @@ class CreateDrawing(bpy.types.Operator): elif "" in line: continue outfile.write(line) - shutil.copyfile(underlay[0:-4] + ".png", svg_path[0:-4] + "-underlay.png") + shutil.copyfile(os.path.splitext(underlay)[0] + ".png", os.path.splitext(svg_path)[0] + "-underlay.png") if linework: with open(linework) as infile: should_skip = False @@ -739,29 +739,24 @@ class AddDrawingToSheet(bpy.types.Operator, Operator): sheet = tool.Ifc.get().by_id(active_sheet.ifc_definition_id) if not sheet.is_a("IfcDocumentInformation"): - return {"FINISHED"} + return - if tool.Ifc.get_schema() == "IFC2X3": - references = sheet.DocumentReferences or [] - else: - references = sheet.HasDocumentReferences or [] + references = tool.Drawing.get_document_references(sheet) has_drawing = False for reference in references: if reference.Location == drawing_reference.Location: has_drawing = True break - if has_drawing: - return {"FINISHED"} + return + + if not tool.Drawing.does_file_exist(tool.Drawing.get_document_uri(drawing_reference)): + self.report({"ERROR"}, "The drawing must be generated before adding to a sheet.") + return reference = tool.Ifc.run("document.add_reference", information=sheet) - if tool.Ifc.get_schema() == "IFC2X3": - references = sheet.DocumentReferences - id_attr = "ItemReference" - else: - references = sheet.HasDocumentReferences - id_attr = "Identification" + id_attr = "ItemReference" if tool.Ifc.get_schema() == "IFC2X3" else "Identification" attributes = { id_attr: str(len([r for r in references if r.Description in ("DRAWING", "SCHEDULE")]) + 1), "Location": drawing_reference.Location, @@ -773,16 +768,15 @@ class AddDrawingToSheet(bpy.types.Operator, Operator): sheet_builder.add_drawing(reference, drawing, sheet) tool.Drawing.import_sheets() - return {"FINISHED"} -class RemoveDrawingFromSheet(bpy.types.Operator): +class RemoveDrawingFromSheet(bpy.types.Operator, Operator): bl_idname = "bim.remove_drawing_from_sheet" bl_label = "Remove Drawing From Sheet" bl_options = {"REGISTER", "UNDO"} reference: bpy.props.IntProperty() - def execute(self, context): + def _execute(self, context): reference = tool.Ifc.get().by_id(self.reference) sheet = tool.Drawing.get_reference_document(reference) @@ -790,48 +784,55 @@ class RemoveDrawingFromSheet(bpy.types.Operator): sheet_builder.data_dir = context.scene.BIMProperties.data_dir sheet_builder.remove_drawing(reference, sheet) - drawing = tool.Drawing.get_reference_element(reference) - if drawing: - tool.Ifc.run("document.unassign_document", product=drawing, document=reference) - tool.Ifc.run("document.remove_reference", reference=reference) tool.Drawing.import_sheets() - return {"FINISHED"} -class CreateSheets(bpy.types.Operator): +class CreateSheets(bpy.types.Operator, Operator): bl_idname = "bim.create_sheets" bl_label = "Create Sheets" - # TODO: check undo redo + bl_options = {"REGISTER", "UNDO"} @classmethod def poll(cls, context): return context.scene.DocProperties.sheets and context.scene.BIMProperties.data_dir - def execute(self, context): + def _execute(self, context): scene = context.scene props = scene.DocProperties active_sheet = props.sheets[props.active_sheet_index] sheet = tool.Ifc.get().by_id(active_sheet.ifc_definition_id) if not sheet.is_a("IfcDocumentInformation"): - return {"FINISHED"} + return 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 + references = sheet_builder.build(sheet) + raster_references = [tool.Ifc.get_relative_uri(r) for r in references["RASTER"]] + # These variables will be made available to the evaluated commands - svg = sheet_builder.build(sheet) + svg = references["SHEET"] basename = os.path.basename(svg) path = os.path.dirname(svg) pdf = os.path.splitext(svg)[0] + ".pdf" eps = os.path.splitext(svg)[0] + ".eps" dxf = os.path.splitext(svg)[0] + ".dxf" - references = getattr(sheet, "HasDocumentReferences", getattr(sheet, "DocumentReferences", [])) - if not [r for r in references if r.Description == "SHEET"]: + has_sheet_reference = False + for reference in tool.Drawing.get_document_references(sheet): + if reference.Description == "SHEET": + has_sheet_reference = True + elif reference.Description == "RASTER": + if reference.Location in raster_references: + del raster_references[reference.Location] + else: + tool.Ifc.run("document.remove_reference", reference=reference) + + if not has_sheet_reference: reference = tool.Ifc.run("document.add_reference", information=sheet) tool.Ifc.run( "document.edit_reference", @@ -839,6 +840,14 @@ class CreateSheets(bpy.types.Operator): attributes={"Location": tool.Ifc.get_relative_uri(svg), "Description": "SHEET"}, ) + for raster_reference in raster_references: + reference = tool.Ifc.run("document.add_reference", information=sheet) + tool.Ifc.run( + "document.edit_reference", + reference=reference, + attributes={"Location": tool.Ifc.get_relative_uri(raster_reference), "Description": "RASTER"}, + ) + svg2pdf_command = context.preferences.addons["blenderbim"].preferences.svg2pdf_command svg2dxf_command = context.preferences.addons["blenderbim"].preferences.svg2dxf_command @@ -860,37 +869,43 @@ class CreateSheets(bpy.types.Operator): open_with_user_command(context.preferences.addons["blenderbim"].preferences.pdf_command, pdf) else: open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg) - return {"FINISHED"} -class ChangeSheetTitleBlock(bpy.types.Operator): +class ChangeSheetTitleBlock(bpy.types.Operator, Operator): bl_idname = "bim.change_sheet_title_block" bl_label = "Change Sheet Title Block" bl_description = "Change the title block of the active sheet" bl_options = {"REGISTER"} - def execute(self, context): + def _execute(self, context): scene = context.scene props = scene.DocProperties if not len(props.sheets): return {"CANCELLED"} + titleblock = scene.DocProperties.titleblock + active_sheet = props.sheets[props.active_sheet_index] sheet = tool.Ifc.get().by_id(active_sheet.ifc_definition_id) + for reference in tool.Drawing.get_document_references(sheet): + description = tool.Drawing.get_reference_description(reference) + if description == "TITLEBLOCK": + tool.Ifc.run( + "document.edit_reference", + reference=reference, + attributes={"Location": tool.Drawing.get_default_titleblock_path(titleblock)}, + ) + sheet_builder = sheeter.SheetBuilder() sheet_builder.data_dir = scene.BIMProperties.data_dir - titleblock = scene.DocProperties.titleblock sheet_builder.change_titleblock(sheet, titleblock) - self.report({"INFO"}, 'Title block changed for sheet "{}" to {}'.format(sheet.Name, titleblock)) - return {"FINISHED"} - -class OpenView(bpy.types.Operator): - bl_idname = "bim.open_view" - bl_label = "Open View" +class OpenDrawing(bpy.types.Operator): + bl_idname = "bim.open_drawing" + bl_label = "Open Drawing" view: bpy.props.StringProperty() bl_description = ( "Opens a .svg drawing based on currently active camera with default system viewer\n" @@ -1229,27 +1244,22 @@ class AddScheduleToSheet(bpy.types.Operator, Operator): if not sheet.is_a("IfcDocumentInformation"): return - if tool.Ifc.get_schema() == "IFC2X3": - references = sheet.DocumentReferences or [] - else: - references = sheet.HasDocumentReferences or [] + references = tool.Drawing.get_document_references(sheet) has_schedule = False for reference in references: if reference.Location == schedule_location: has_schedule = True break - if has_schedule: return + if not tool.Drawing.does_file_exist(tool.Ifc.resolve_uri(schedule_location)): + self.report({"ERROR"}, "The schedule must be generated before adding to a sheet.") + return + reference = tool.Ifc.run("document.add_reference", information=sheet) - if tool.Ifc.get_schema() == "IFC2X3": - references = sheet.DocumentReferences - id_attr = "ItemReference" - else: - references = sheet.HasDocumentReferences - id_attr = "Identification" + id_attr = "ItemReference" if tool.Ifc.get_schema() == "IFC2X3" else "Identification" attributes = { id_attr: str(len([r for r in references if r.Description in ("DRAWING", "SCHEDULE")]) + 1), "Location": schedule_location, @@ -1501,6 +1511,33 @@ class LoadSheets(bpy.types.Operator, Operator): self.report({"ERROR"}, "Some sheets svg files are missing:\n" + "\n".join(sheets_not_found)) +class RenameSheet(bpy.types.Operator, Operator): + bl_idname = "bim.rename_sheet" + bl_label = "Rename Sheet" + bl_options = {"REGISTER", "UNDO"} + identification: bpy.props.StringProperty() + name: bpy.props.StringProperty() + + def invoke(self, context, event): + self.props = context.scene.DocProperties + sheet = tool.Ifc.get().by_id(self.props.sheets[self.props.active_sheet_index].ifc_definition_id) + self.identification = sheet.Identification + self.name = sheet.Name + return context.window_manager.invoke_props_dialog(self) + + def draw(self, context): + row = self.layout.row() + row.prop(self, "identification", text="Identification") + row = self.layout.row() + row.prop(self, "name", text="Name") + + def _execute(self, context): + self.props = context.scene.DocProperties + sheet = tool.Ifc.get().by_id(self.props.sheets[self.props.active_sheet_index].ifc_definition_id) + core.rename_sheet(tool.Ifc, tool.Drawing, sheet=sheet, identification=self.identification, name=self.name) + tool.Drawing.import_sheets() + + class DisableEditingSheets(bpy.types.Operator, Operator): bl_idname = "bim.disable_editing_sheets" bl_label = "Disable Editing Sheets" diff --git a/src/blenderbim/blenderbim/bim/module/drawing/prop.py b/src/blenderbim/blenderbim/bim/module/drawing/prop.py index b8e68e4b7d..84ffb3cb22 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/prop.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/prop.py @@ -248,26 +248,9 @@ class Schedule(PropertyGroup): class Sheet(PropertyGroup): - def set_name(self, new): - old = self.get("name") - - if new == old: - return - sheet = tool.Ifc.get().by_id(self.ifc_definition_id) - old_path = Path(tool.Drawing.get_document_uri(sheet)) - core.update_sheet_name(tool.Ifc, tool.Drawing, sheet=sheet, name=new) - self["name"] = new - - new_path = Path(tool.Drawing.get_document_uri(sheet)) - if old and old_path.is_file(): - old_path.rename(new_path) - - def get_name(self): - return self.get("name") - ifc_definition_id: IntProperty(name="IFC Definition ID") identification: StringProperty(name="Identification") - name: StringProperty(name="Name", get=get_name, set=set_name) + name: StringProperty(name="Name") is_sheet: BoolProperty(name="Is Sheet", default=False) reference_type: StringProperty(name="Reference Type") is_expanded: BoolProperty(name="Is Expanded", default=False) @@ -354,11 +337,15 @@ class DocProperties(PropertyGroup): decorations_colour: FloatVectorProperty( name="Decorations Colour", subtype="COLOR", default=(1, 1, 1, 1), min=0.0, max=1.0, size=4 ) - docs_dir: StringProperty(default=os.path.join("docs") + os.path.sep, name="Default Docs Directory") sheets_dir: StringProperty(default=os.path.join("sheets") + os.path.sep, name="Default Sheets Directory") - titleblocks_dir: StringProperty(default=os.path.join("sheets", "titleblocks") + os.path.sep, name="Default Titleblocks Directory") + layouts_dir: StringProperty(default=os.path.join("layouts") + os.path.sep, name="Default Layouts Directory") + titleblocks_dir: StringProperty( + default=os.path.join("layouts", "titleblocks") + os.path.sep, name="Default Titleblocks Directory" + ) drawings_dir: StringProperty(default=os.path.join("drawings") + os.path.sep, name="Default Drawings Directory") - stylesheet_path: StringProperty(default=os.path.join("drawings", "assets", "default.css"), name="Default Stylesheet") + stylesheet_path: StringProperty( + default=os.path.join("drawings", "assets", "default.css"), name="Default Stylesheet" + ) markers_path: StringProperty(default=os.path.join("drawings", "assets", "markers.svg"), name="Default Markers") symbols_path: StringProperty(default=os.path.join("drawings", "assets", "symbols.svg"), name="Default Symbols") patterns_path: StringProperty(default=os.path.join("drawings", "assets", "patterns.svg"), name="Default Patterns") diff --git a/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py b/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py index fdffe1f40f..2c99331b71 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py @@ -34,8 +34,8 @@ class SheetBuilder: self.data_dir = None self.scale = "NTS" - def create(self, sheet_path, titleblock_name): - sheet_dir = os.path.dirname(sheet_path) + def create(self, layout_path, titleblock_name): + sheet_dir = os.path.dirname(layout_path) root = ET.Element("svg") root.attrib["xmlns"] = "http://www.w3.org/2000/svg" @@ -43,16 +43,16 @@ class SheetBuilder: root.attrib["id"] = "root" root.attrib["version"] = "1.1" - titleblock_path = os.path.join(self.data_dir, "templates", "titleblocks", titleblock_name + ".svg") - view_root = ET.parse(titleblock_path).getroot() + ootb_titleblock_path = os.path.join(self.data_dir, "templates", "titleblocks", titleblock_name + ".svg") + titleblock_path = tool.Ifc.resolve_uri(tool.Drawing.get_default_titleblock_path(titleblock_name)) + + view_root = ET.parse(ootb_titleblock_path).getroot() view_width = self.convert_to_mm(view_root.attrib.get("width")) view_height = self.convert_to_mm(view_root.attrib.get("height")) view = ET.SubElement(root, "g") view.attrib["data-type"] = "titleblock" titleblock = ET.SubElement(view, "image") - titleblock.attrib["xlink:href"] = os.path.relpath( - tool.Drawing.get_default_titleblock_path(titleblock_name), sheet_dir - ) + titleblock.attrib["xlink:href"] = os.path.relpath(titleblock_path, sheet_dir) titleblock.attrib["x"] = "0" titleblock.attrib["y"] = "0" titleblock.attrib["width"] = str(view_width) @@ -63,24 +63,22 @@ class SheetBuilder: root.attrib["viewBox"] = "0 0 {} {}".format(view_width, view_height) os.makedirs(sheet_dir, exist_ok=True) - os.makedirs(os.path.join(sheet_dir, "titleblocks"), exist_ok=True) - sheet_titleblock_path = os.path.join(sheet_dir, "titleblocks", titleblock_name + ".svg") - if not os.path.exists(sheet_titleblock_path): - shutil.copy(titleblock_path, sheet_titleblock_path) - with open(sheet_path, "w") as f: + os.makedirs(os.path.dirname(titleblock_path), exist_ok=True) + if not os.path.exists(titleblock_path): + shutil.copy(ootb_titleblock_path, titleblock_path) + + with open(layout_path, "w") as f: f.write(minidom.parseString(ET.tostring(root)).toprettyxml(indent=" ")) def add_drawing(self, reference, drawing, sheet): filename = drawing.Name sheet_path = tool.Drawing.get_document_uri(sheet) - sheet_name = os.path.splitext(os.path.basename(sheet_path))[0] sheet_dir = os.path.dirname(sheet_path) drawing_path = tool.Drawing.get_document_uri(tool.Drawing.get_drawing_reference(drawing)) - drawing_path = tool.Ifc.resolve_uri(drawing_path) underlay_path = os.path.splitext(drawing_path)[0] + "-underlay.png" - if not os.path.isfile(sheet_path): + if not os.path.exists(sheet_path) or not os.path.exists(drawing_path): raise FileNotFoundError ET.register_namespace("", "http://www.w3.org/2000/svg") @@ -190,18 +188,20 @@ class SheetBuilder: title.attrib["height"] = str(self.convert_to_mm(title_root.attrib.get("height"))) def build(self, sheet): - sheet_path = tool.Drawing.get_document_uri(sheet) - sheet_name = os.path.splitext(os.path.basename(sheet_path))[0] - self.sheet_dir = os.path.dirname(sheet_path) + self.references = {"SHEET": None, "RASTER": []} - docs_dir = tool.Ifc.resolve_uri(os.path.join(bpy.context.scene.DocProperties.docs_dir, sheet_name)) + layout_path = tool.Drawing.get_document_uri(sheet, "LAYOUT") + self.layout_dir = os.path.dirname(layout_path) - os.makedirs(docs_dir, exist_ok=True) + output_filename = tool.Ifc.resolve_uri(tool.Drawing.get_default_sheet_path(sheet[0], sheet.Name)) + self.sheets_dir = os.path.dirname(output_filename) + + os.makedirs(self.sheets_dir, exist_ok=True) ET.register_namespace("", "http://www.w3.org/2000/svg") ET.register_namespace("xlink", "http://www.w3.org/1999/xlink") - tree = ET.parse(sheet_path) + tree = ET.parse(layout_path) root = tree.getroot() self.defs = ET.Element("defs") @@ -211,12 +211,12 @@ class SheetBuilder: self.build_drawings(root, sheet) self.build_schedules(root) - output_filename = os.path.join(docs_dir, f"{sheet_name}.svg") - with open(output_filename, "wb") as output: tree.write(output) - return output_filename + self.references["SHEET"] = output_filename + + return self.references def build_titleblock(self, root, sheet): titleblock = root.findall('{http://www.w3.org/2000/svg}g[@data-type="titleblock"]')[0] @@ -232,8 +232,6 @@ class SheetBuilder: titleblock.remove(image) def build_drawings(self, root, sheet): - sheet_name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0] - for view in root.findall('{http://www.w3.org/2000/svg}g[@data-type="drawing"]'): reference = tool.Ifc.get().by_id(int(view.attrib["data-id"])) drawing = tool.Ifc.get().by_id(view.attrib["data-drawing"]) @@ -256,8 +254,10 @@ class SheetBuilder: view.append(self.parse_embedded_svg(foreground, {})) if background is not None: - background_path = os.path.join(self.data_dir, "sheets", self.get_href(background)) - shutil.copy(background_path, os.path.join(self.data_dir, "build", sheet_name)) + background_path = os.path.join(self.layout_dir, self.get_href(background)) + raster_path = os.path.join(self.sheets_dir, os.path.basename(background_path)) + shutil.copy(background_path, raster_path) + self.references["RASTER"].append(raster_path) if view_title is not None: foreground_path = self.get_href(foreground) @@ -322,7 +322,7 @@ class SheetBuilder: self.defs.append(clip_path) svg_path = self.get_href(image) - with open(os.path.join(self.sheet_dir, svg_path), "r") as template: + with open(os.path.join(self.layout_dir, svg_path), "r") as template: embedded = ET.fromstring(pystache.render(template.read(), data)) # viewBox should not be nested embedded.attrib["viewBox"] = "" @@ -339,23 +339,29 @@ class SheetBuilder: return group def change_titleblock(self, sheet, titleblock_name): + ootb_titleblock_path = os.path.join(self.data_dir, "templates", "titleblocks", titleblock_name + ".svg") + titleblock_path = tool.Drawing.get_default_titleblock_path(titleblock_name) + sheet_path = tool.Drawing.get_document_uri(sheet, "LAYOUT") + sheet_dir = os.path.dirname(sheet_path) + + os.makedirs(sheet_dir, exist_ok=True) + os.makedirs(os.path.join(sheet_dir, "titleblocks"), exist_ok=True) + if not os.path.exists(titleblock_path): + shutil.copy(ootb_titleblock_path, titleblock_path) + ET.register_namespace("", "http://www.w3.org/2000/svg") ET.register_namespace("xlink", "http://www.w3.org/1999/xlink") - titleblock_svg_path = os.path.join(self.data_dir, "templates", "titleblocks", f"{titleblock_name}.svg") - view_root = ET.parse(titleblock_svg_path).getroot() + view_root = ET.parse(ootb_titleblock_path).getroot() view_width = self.convert_to_mm(view_root.attrib.get("width")) view_height = self.convert_to_mm(view_root.attrib.get("height")) - sheet_dir = os.path.join(self.data_dir, "sheets") - sheet_name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0] - sheet_path = os.path.join(sheet_dir, sheet_name + ".svg") sheet_tree = ET.parse(sheet_path) root = sheet_tree.getroot() titleblock = sheet_tree.findall('{http://www.w3.org/2000/svg}g[@data-type="titleblock"]')[0] image = titleblock.findall("{http://www.w3.org/2000/svg}image[@{http://www.w3.org/1999/xlink}href]")[0] - image.attrib["{http://www.w3.org/1999/xlink}href"] = f"../templates/titleblocks/{titleblock_name}.svg" + image.attrib["{http://www.w3.org/1999/xlink}href"] = os.path.relpath(titleblock_path, sheet_dir) image.attrib["width"] = str(view_width) image.attrib["height"] = str(view_height) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py index 972aa415ab..8108a5f2a8 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py @@ -85,13 +85,7 @@ class SvgWriter: self.svg.save(pretty=True) def draw_underlay(self, image): - self.svg.add( - self.svg.image( - os.path.join("..", "diagrams", os.path.basename(image)), - width=self.width, - height=self.height, - ) - ) + self.svg.add(self.svg.image(os.path.basename(image), width=self.width, height=self.height)) return self def setup_drawing_resource_paths(self, element): diff --git a/src/blenderbim/blenderbim/bim/module/drawing/ui.py b/src/blenderbim/blenderbim/bim/module/drawing/ui.py index 0991580711..cb99a3574c 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/ui.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/ui.py @@ -84,7 +84,7 @@ class BIM_PT_camera(Panel): row = layout.row(align=True) row.operator("bim.create_drawing", text="Create Drawing", icon="OUTPUT") - op = row.operator("bim.open_view", icon="URL", text="") + op = row.operator("bim.open_drawing", icon="URL", text="") op.view = context.active_object.name.split("/")[1] @@ -185,7 +185,7 @@ class BIM_PT_drawings(Panel): ).drawing = active_drawing.ifc_definition_id col = row.column() col.alignment = "RIGHT" - op = row.operator("bim.open_view", icon="URL", text="") + op = row.operator("bim.open_drawing", icon="URL", text="") op.view = active_drawing.name op = row.operator("bim.activate_view", icon="OUTLINER_OB_CAMERA", text="") op.drawing = active_drawing.ifc_definition_id @@ -281,6 +281,7 @@ class BIM_PT_sheets(Panel): active_sheet = self.props.sheets[self.props.active_sheet_index] row = self.layout.row(align=True) row.alignment = "RIGHT" + row.operator("bim.rename_sheet", icon="GREASEPENCIL", text="") row.operator("bim.open_sheet", icon="URL", text="") row.operator("bim.add_drawing_to_sheet", icon="IMAGE_PLANE", text="") row.operator("bim.add_schedule_to_sheet", icon="PRESET_NEW", text="") @@ -510,7 +511,7 @@ class BIM_UL_sheets(bpy.types.UIList): layout.label(text="", translate=False) return - row = layout.row() + row = layout.row(align=True) if item.is_sheet: if item.is_expanded: row.operator( @@ -520,8 +521,8 @@ class BIM_UL_sheets(bpy.types.UIList): row.operator( "bim.expand_sheet", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT" ).sheet = item.ifc_definition_id - name = "{} - {}".format(item.identification or "X", item.name or "Unnamed") - row.prop(item, "name", text=item.identification or "X", emboss=False) + + row.label(text=f"{item.identification} - {item.name}") else: row.label(text="", icon="BLANK1") if item.reference_type == "DRAWING": @@ -530,6 +531,9 @@ class BIM_UL_sheets(bpy.types.UIList): row.label(text="", icon="LONGDISPLAY") elif item.reference_type == "TITLEBLOCK": row.label(text="", icon="MENU_PANEL") + elif item.reference_type == "REVISION": + row.label(text="", icon="RECOVER_LAST") + if item.identification: name = f"{item.identification} - {item.name or 'Unnamed'}" else: diff --git a/src/blenderbim/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py index ad1c9665cb..eb14bf4647 100644 --- a/src/blenderbim/blenderbim/bim/ui.py +++ b/src/blenderbim/blenderbim/bim/ui.py @@ -182,11 +182,11 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): row.prop(context.scene.BIMProperties, "data_dir") row.operator("bim.select_data_dir", icon="FILE_FOLDER", text="") - row = self.layout.row(align=True) - row.prop(context.scene.DocProperties, "docs_dir") row = self.layout.row(align=True) row.prop(context.scene.DocProperties, "sheets_dir") row = self.layout.row(align=True) + row.prop(context.scene.DocProperties, "layouts_dir") + row = self.layout.row(align=True) row.prop(context.scene.DocProperties, "titleblocks_dir") row = self.layout.row(align=True) row.prop(context.scene.DocProperties, "drawings_dir") diff --git a/src/blenderbim/blenderbim/core/drawing.py b/src/blenderbim/blenderbim/core/drawing.py index d792d92e11..568a6e6eab 100644 --- a/src/blenderbim/blenderbim/core/drawing.py +++ b/src/blenderbim/blenderbim/core/drawing.py @@ -78,7 +78,7 @@ def add_sheet(ifc, drawing, titleblock=None): ifc.run( "document.edit_reference", reference=layout, - attributes={"Location": drawing.get_default_sheet_path(identification, "UNTITLED"), "Description": "LAYOUT"}, + attributes={"Location": drawing.get_default_layout_path(identification, "UNTITLED"), "Description": "LAYOUT"}, ) ifc.run( "document.edit_reference", @@ -94,13 +94,37 @@ def open_sheet(drawing, sheet=None): def remove_sheet(ifc, drawing, sheet=None): + for reference in drawing.get_document_references(sheet): + if drawing.get_reference_description(reference) in ("LAYOUT", "SHEET", "REVISION", "RASTER"): + uri = ifc.resolve_uri(drawing.get_document_uri(reference)) + if drawing.does_file_exist(uri): + drawing.delete_file(uri) ifc.run("document.remove_information", information=sheet) drawing.import_sheets() -def update_sheet_name(ifc, drawing, sheet=None, name=None): - if drawing.get_name(sheet) != name: - ifc.run("document.edit_information", information=sheet, attributes={"Name": name}) +def rename_sheet(ifc, drawing, sheet=None, identification=None, name=None): + ifc.run( + "document.edit_information", information=sheet, attributes={"Identification": identification, "Name": name} + ) + for reference in drawing.get_document_references(sheet): + description = drawing.get_reference_description(reference) + if description == "SHEET": + old_location = drawing.get_reference_location(reference) + new_location = drawing.get_default_sheet_path(identification, name) + if old_location != new_location: + ifc.run("document.edit_reference", reference=reference, attributes={"Location": new_location}) + old_location = ifc.resolve_uri(old_location) + if drawing.does_file_exist(old_location): + drawing.move_file(old_location, ifc.resolve_uri(new_location)) + elif description == "LAYOUT": + old_location = drawing.get_reference_location(reference) + new_location = drawing.get_default_layout_path(identification, name) + if old_location != new_location: + ifc.run("document.edit_reference", reference=reference, attributes={"Location": new_location}) + old_location = ifc.resolve_uri(old_location) + if drawing.does_file_exist(old_location): + drawing.move_file(old_location, ifc.resolve_uri(new_location)) def load_schedules(drawing): @@ -213,6 +237,21 @@ def duplicate_drawing(ifc, drawing_tool, drawing=None, should_duplicate_annotati drawing_tool.copy_representation(annotation, new_annotation) ifc.run("group.unassign_group", group=group, product=new_annotation) ifc.run("group.assign_group", group=new_group, products=[new_annotation]) + + old_reference = drawing_tool.get_drawing_document(new_drawing) + ifc.run("document.unassign_document", product=new_drawing, document=old_reference) + + information = ifc.run("document.add_information") + uri = drawing_tool.get_default_drawing_path(drawing_name) + reference = ifc.run("document.add_reference", information=information) + if ifc.get_schema() == "IFC2X3": + attributes = {"DocumentId": "X", "Name": drawing_name, "Scope": "DRAWING"} + else: + attributes = {"Identification": "X", "Name": drawing_name, "Scope": "DRAWING"} + ifc.run("document.edit_information", information=information, attributes=attributes) + ifc.run("document.edit_reference", reference=reference, attributes={"Location": uri}) + ifc.run("document.assign_document", product=new_drawing, document=reference) + drawing_tool.import_drawings() return new_drawing @@ -230,7 +269,11 @@ def remove_drawing(ifc, drawing_tool, drawing=None): if reference_obj: drawing_tool.delete_object(reference_obj) ifc.run("root.remove_product", product=reference) - ifc.run("document.remove_information", information=drawing_tool.get_drawing_document(drawing)) + information = drawing_tool.get_reference_document(drawing_tool.get_drawing_document(drawing)) + uri = ifc.resolve_uri(drawing_tool.get_document_uri(information)) + if drawing_tool.does_file_exist(uri): + drawing_tool.delete_file(uri) + ifc.run("document.remove_information", information=information) ifc.run("root.remove_product", product=drawing) drawing_tool.import_drawings() @@ -245,6 +288,17 @@ def update_drawing_name(ifc, drawing_tool, drawing=None, name=None): if collection: drawing_tool.set_drawing_collection_name(group, collection) + reference = drawing_tool.get_drawing_document(drawing) + information = drawing_tool.get_reference_document(reference) + ifc.run("document.edit_information", information=information, attributes={"Name": name}) + old_location = drawing_tool.get_reference_location(reference) + new_location = drawing_tool.get_default_drawing_path(name) + if old_location != new_location: + ifc.run("document.edit_reference", reference=reference, attributes={"Location": new_location}) + old_location = ifc.resolve_uri(old_location) + if drawing_tool.does_file_exist(old_location): + drawing_tool.move_file(old_location, ifc.resolve_uri(new_location)) + def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None): context = drawing_tool.get_annotation_context(drawing_tool.get_drawing_target_view(drawing)) diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index d7b09664dd..042050899c 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -226,20 +226,22 @@ class Document: @interface class Drawing: def activate_view(cls, camera): pass + def add_literal_to_annotation(cls, obj, Literal='Literal', Path='RIGHT', BoxAlignment='bottom-left'): pass def copy_representation(cls, source, dest): pass def create_annotation_object(cls, drawing, object_type): pass - def setup_annotation_object(cls, obj, 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 + def delete_file(cls, uri): pass def delete_object(cls, obj): pass def disable_editing_assigned_product(cls, obj): pass def disable_editing_drawings(cls): pass def disable_editing_schedules(cls): pass def disable_editing_sheets(cls): pass def disable_editing_text(cls, obj): pass + def does_file_exist(cls, uri): pass def enable_editing(cls, obj): pass def enable_editing_assigned_product(cls, obj): pass def enable_editing_drawings(cls): pass @@ -257,21 +259,25 @@ class Drawing: def get_body_context(cls): pass def get_default_drawing_path(cls, name): pass def get_default_drawing_resource_path(cls, resource): pass + def get_default_layout_path(cls, identification, name): pass def get_default_sheet_path(cls, identification, name): pass - def get_document_uri(cls, document): pass + def get_default_sheet_path(cls, identification, name): pass + def get_default_titleblock_path(cls, name): pass + def get_document_references(cls, document): pass + def get_document_uri(cls, document, description=None): pass def get_drawing_collection(cls, drawing): pass def get_drawing_document(cls, drawing): pass def get_drawing_group(cls, drawing): pass - def get_path_filename(cls, uri): pass def get_drawing_references(cls, drawing): pass def get_drawing_target_view(cls, drawing): pass def get_group_elements(cls, group): pass def get_ifc_representation_class(cls, object_type): pass def get_name(cls, element): pass + def get_path_filename(cls, uri): pass + def get_reference_description(cls, reference): pass + def get_reference_document(cls, reference): pass + def get_reference_location(cls, reference): pass def get_text_literal(cls, obj): pass - def remove_literal_from_annotation(cls, obj, literal): pass - def synchronise_ifc_and_text_attributes(cls, obj): pass - def add_literal_to_annotation(cls, obj, Literal='Literal', Path='RIGHT', BoxAlignment='bottom-left'): pass def import_assigned_product(cls, obj): pass def import_drawings(cls): pass def import_schedules(cls): pass @@ -279,16 +285,20 @@ class Drawing: def import_text_attributes(cls, obj): pass def is_camera_orthographic(cls): pass def is_drawing_active(cls): pass + def move_file(cls, src, dest): pass def open_spreadsheet(cls, uri): pass def open_svg(cls, filepath): pass + def remove_literal_from_annotation(cls, obj, literal): pass def run_root_assign_class(cls, obj=None, ifc_class=None, predefined_type=None, should_add_representation=True, context=None, ifc_representation_class=None): pass def select_assigned_product(cls, drawing): pass def set_drawing_collection_name(cls, group, collection): pass def set_name(cls, element, name): pass + def setup_annotation_object(cls, obj, object_type): pass def show_decorations(cls): pass def sync_object_placement(cls, obj): pass - def update_text_value(cls, obj): pass + def synchronise_ifc_and_text_attributes(cls, obj): pass def update_text_size_pset(cls, obj): pass + def update_text_value(cls, obj): pass @interface diff --git a/src/blenderbim/blenderbim/tool/drawing.py b/src/blenderbim/blenderbim/tool/drawing.py index 7e14a6b223..2aa7263683 100644 --- a/src/blenderbim/blenderbim/tool/drawing.py +++ b/src/blenderbim/blenderbim/tool/drawing.py @@ -21,6 +21,7 @@ import re import bpy import math import bmesh +import shutil import logging import mathutils import webbrowser @@ -136,7 +137,7 @@ class Drawing(blenderbim.core.tool.Drawing): def create_svg_sheet(cls, document, titleblock): sheet_builder = sheeter.SheetBuilder() sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir - uri = cls.get_document_uri(document) + uri = cls.get_document_uri(document, "LAYOUT") sheet_builder.create(uri, titleblock) return uri @@ -583,8 +584,9 @@ class Drawing(blenderbim.core.tool.Drawing): continue for reference in cls.get_document_references(sheet): - if reference.Description == "LAYOUT": - continue # The layout itself is an internal detail and should not be visible to users + if reference.Description in ("SHEET", "LAYOUT", "RASTER"): + # These references are an internal detail and should not be visible to users + continue new = props.sheets.add() new.ifc_definition_id = reference.id() new.is_sheet = False @@ -726,6 +728,18 @@ class Drawing(blenderbim.core.tool.Drawing): # TODO below this point is highly experimental prototype code with no tests + @classmethod + def does_file_exist(cls, uri): + return os.path.exists(uri) + + @classmethod + def delete_file(cls, uri): + os.remove(uri) + + @classmethod + def move_file(cls, src, dest): + shutil.move(src, dest) + @classmethod def generate_drawing_name(cls, target_view, location_hint): if target_view in ("PLAN_VIEW", "REFLECTED_PLAN_VIEW") and location_hint: @@ -737,6 +751,12 @@ class Drawing(blenderbim.core.tool.Drawing): return location_hint + " " + target_view.split("_")[0] return target_view + @classmethod + def get_default_layout_path(cls, identification, name): + return os.path.join( + bpy.context.scene.DocProperties.layouts_dir, cls.sanitise_filename(f"{identification} - {name}.svg") + ) + @classmethod def get_default_sheet_path(cls, identification, name): return os.path.join( @@ -1176,6 +1196,14 @@ class Drawing(blenderbim.core.tool.Drawing): return document.DocumentReferences or [] return document.HasDocumentReferences or [] + @classmethod + def get_reference_description(cls, reference): + return reference.Description + + @classmethod + def get_reference_location(cls, reference): + return reference.Location + @classmethod def get_reference_element(cls, reference): if tool.Ifc.get_schema() == "IFC2X3": diff --git a/src/blenderbim/test/core/test_drawing.py b/src/blenderbim/test/core/test_drawing.py index 86b6e3c020..b744581d1a 100644 --- a/src/blenderbim/test/core/test_drawing.py +++ b/src/blenderbim/test/core/test_drawing.py @@ -84,14 +84,26 @@ class TestDisableEditingSheets: class TestAddSheet: def test_run(self, ifc, drawing): ifc.run("document.add_information").should_be_called().will_return("sheet") + ifc.run("document.add_reference", information="sheet").should_be_called().will_return("reference") drawing.generate_sheet_identification().should_be_called().will_return("identification") drawing.ensure_unique_identification("identification").should_be_called().will_return("u_identification") ifc.get_schema().should_be_called().will_return("IFC4") - drawing.get_default_sheet_path("u_identification", "UNTITLED").should_be_called().will_return("uri") + drawing.get_default_layout_path("u_identification", "UNTITLED").should_be_called().will_return("layout_path") + drawing.get_default_titleblock_path("titleblock").should_be_called().will_return("titleblock_path") ifc.run( "document.edit_information", information="sheet", - attributes={"Identification": "u_identification", "Name": "UNTITLED", "Scope": "DOCUMENTATION", "Location": "uri"}, + attributes={"Identification": "u_identification", "Name": "UNTITLED", "Scope": "SHEET"}, + ).should_be_called() + ifc.run( + "document.edit_reference", + reference="reference", + attributes={"Location": "layout_path", "Description": "LAYOUT"}, + ).should_be_called() + ifc.run( + "document.edit_reference", + reference="reference", + attributes={"Location": "titleblock_path", "Description": "TITLEBLOCK"}, ).should_be_called() drawing.create_svg_sheet("sheet", "titleblock").should_be_called() drawing.import_sheets().should_be_called() @@ -99,13 +111,26 @@ class TestAddSheet: def test_using_a_document_id_in_ifc2x3(self, ifc, drawing): ifc.run("document.add_information").should_be_called().will_return("sheet") + ifc.run("document.add_reference", information="sheet").should_be_called().will_return("reference") drawing.generate_sheet_identification().should_be_called().will_return("identification") drawing.ensure_unique_identification("identification").should_be_called().will_return("u_identification") ifc.get_schema().should_be_called().will_return("IFC2X3") + drawing.get_default_layout_path("u_identification", "UNTITLED").should_be_called().will_return("layout_path") + drawing.get_default_titleblock_path("titleblock").should_be_called().will_return("titleblock_path") ifc.run( "document.edit_information", information="sheet", - attributes={"DocumentId": "u_identification", "Name": "UNTITLED", "Scope": "DOCUMENTATION"}, + attributes={"DocumentId": "u_identification", "Name": "UNTITLED", "Scope": "SHEET"}, + ).should_be_called() + ifc.run( + "document.edit_reference", + reference="reference", + attributes={"Location": "layout_path", "Description": "LAYOUT"}, + ).should_be_called() + ifc.run( + "document.edit_reference", + reference="reference", + attributes={"Location": "titleblock_path", "Description": "TITLEBLOCK"}, ).should_be_called() drawing.create_svg_sheet("sheet", "titleblock").should_be_called() drawing.import_sheets().should_be_called() @@ -114,13 +139,19 @@ class TestAddSheet: class TestOpenSheet: def test_run(self, drawing): - drawing.get_document_uri("sheet").should_be_called().will_return("uri") + drawing.get_document_uri("sheet", "LAYOUT").should_be_called().will_return("uri") drawing.open_svg("uri").should_be_called() subject.open_sheet(drawing, sheet="sheet") class TestRemoveSheet: def test_run(self, ifc, drawing): + drawing.get_document_references("sheet").should_be_called().will_return(["reference"]) + drawing.get_reference_description("reference").should_be_called().will_return("LAYOUT") + drawing.get_document_uri("reference").should_be_called().will_return("relative_uri") + ifc.resolve_uri("relative_uri").should_be_called().will_return("absolute_uri") + drawing.does_file_exist("absolute_uri").should_be_called().will_return(True) + drawing.delete_file("absolute_uri").should_be_called() ifc.run("document.remove_information", information="sheet").should_be_called() drawing.import_sheets().should_be_called() subject.remove_sheet(ifc, drawing, sheet="sheet") @@ -254,7 +285,11 @@ class TestAddDrawing: ifc.run("document.add_information").should_be_called().will_return("information") ifc.run("document.add_reference", information="information").should_be_called().will_return("reference") ifc.get_schema().should_be_called().will_return("IFC4") - ifc.run("document.edit_information", information="information", attributes={"Identification": "X", "Name": "name", "Scope": "DRAWING"}).should_be_called() + ifc.run( + "document.edit_information", + information="information", + attributes={"Identification": "X", "Name": "name", "Scope": "DRAWING"}, + ).should_be_called() ifc.run("document.edit_reference", reference="reference", attributes={"Location": "uri"}).should_be_called() ifc.run("document.assign_document", product="element", document="reference").should_be_called() drawing.import_drawings().should_be_called() @@ -280,6 +315,24 @@ class TestDuplicateDrawing: drawing.copy_representation("annotation", "new_annotation").should_be_called() ifc.run("group.unassign_group", group="group", product="new_annotation").should_be_called() ifc.run("group.assign_group", group="new_group", products=["new_annotation"]).should_be_called() + + drawing.get_drawing_document("new_drawing").should_be_called().will_return("old_reference") + ifc.run("document.unassign_document", product="new_drawing", document="old_reference").should_be_called() + + ifc.run("document.add_information").should_be_called().will_return("information") + ifc.run("document.add_reference", information="information").should_be_called().will_return("reference") + ifc.get_schema().should_be_called().will_return("IFC4") + drawing.get_default_drawing_path("unique_name").should_be_called().will_return("drawing_path") + ifc.run( + "document.edit_information", + information="information", + attributes={"Identification": "X", "Name": "unique_name", "Scope": "DRAWING"}, + ).should_be_called() + ifc.run( + "document.edit_reference", reference="reference", attributes={"Location": "drawing_path"} + ).should_be_called() + ifc.run("document.assign_document", product="new_drawing", document="reference").should_be_called() + drawing.import_drawings().should_be_called() subject.duplicate_drawing(ifc, drawing, drawing="drawing", should_duplicate_annotations=True) @@ -296,7 +349,12 @@ class TestRemoveDrawing: ifc.get_object("reference").should_be_called().will_return("reference_obj") drawing.delete_object("reference_obj").should_be_called() ifc.run("root.remove_product", product="reference").should_be_called() - drawing.get_drawing_document("drawing").should_be_called().will_return("information") + drawing.get_drawing_document("drawing").should_be_called().will_return("reference") + drawing.get_reference_document("reference").should_be_called().will_return("information") + drawing.get_document_uri("information").should_be_called().will_return("relative_uri") + ifc.resolve_uri("relative_uri").should_be_called().will_return("absolute_uri") + drawing.does_file_exist("absolute_uri").should_be_called().will_return(True) + drawing.delete_file("absolute_uri").should_be_called() ifc.run("document.remove_information", information="information").should_be_called() ifc.run("root.remove_product", product="drawing").should_be_called() drawing.import_drawings().should_be_called() @@ -310,6 +368,13 @@ class TestUpdateDrawingName: drawing.get_name("group").should_be_called().will_return("name") drawing.get_drawing_collection("drawing").should_be_called().will_return("collection") drawing.set_drawing_collection_name("group", "collection").should_be_called() + + drawing.get_drawing_document("drawing").should_be_called().will_return("reference") + drawing.get_reference_document("reference").should_be_called().will_return("information") + ifc.run("document.edit_information", information="information", attributes={"Name": "name"}).should_be_called() + drawing.get_reference_location("reference").should_be_called().will_return("location") + drawing.get_default_drawing_path("name").should_be_called().will_return("location") + subject.update_drawing_name(ifc, drawing, drawing="drawing", name="name") def test_run(self, ifc, drawing): @@ -320,6 +385,20 @@ class TestUpdateDrawingName: ifc.run("attribute.edit_attributes", product="group", attributes={"Name": "name"}).should_be_called() drawing.get_drawing_collection("drawing").should_be_called().will_return("collection") drawing.set_drawing_collection_name("group", "collection").should_be_called() + + drawing.get_drawing_document("drawing").should_be_called().will_return("reference") + drawing.get_reference_document("reference").should_be_called().will_return("information") + ifc.run("document.edit_information", information="information", attributes={"Name": "name"}).should_be_called() + drawing.get_reference_location("reference").should_be_called().will_return("old_location") + drawing.get_default_drawing_path("name").should_be_called().will_return("new_location") + ifc.run( + "document.edit_reference", reference="reference", attributes={"Location": "new_location"} + ).should_be_called() + ifc.resolve_uri("old_location").should_be_called().will_return("old_uri") + drawing.does_file_exist("old_uri").should_be_called().will_return(True) + ifc.resolve_uri("new_location").should_be_called().will_return("new_uri") + drawing.move_file("old_uri", "new_uri").should_be_called() + subject.update_drawing_name(ifc, drawing, drawing="drawing", name="name") diff --git a/src/blenderbim/test/tool/test_drawing.py b/src/blenderbim/test/tool/test_drawing.py index 4e664fb9b6..92d02fadda 100644 --- a/src/blenderbim/test/tool/test_drawing.py +++ b/src/blenderbim/test/tool/test_drawing.py @@ -83,7 +83,7 @@ class TestDeleteDrawingElements(NewFile): def test_run(self): ifc = ifcopenshell.file() tool.Ifc.set(ifc) - obj = bpy.data.objects.new("Object", None) + obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh")) collection = bpy.data.collections.new("Collection") bpy.context.scene.collection.children.link(collection) collection.objects.link(obj) @@ -488,7 +488,7 @@ class TestImportSheets(NewFile): ifc = ifcopenshell.file() tool.Ifc.set(ifc) ifc.createIfcDocumentInformation(Identification="Y", Name="FOOBAZ") - document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="DOCUMENTATION") + document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="SHEET") subject.import_sheets() props = bpy.context.scene.DocProperties assert props.sheets[0].ifc_definition_id == document.id() @@ -499,7 +499,7 @@ class TestImportSheets(NewFile): ifc = ifcopenshell.file(schema="IFC2X3") tool.Ifc.set(ifc) ifc.createIfcDocumentInformation(DocumentId="Y", Name="FOOBAZ") - document = ifc.createIfcDocumentInformation(DocumentId="X", Name="FOOBAR", Scope="DOCUMENTATION") + document = ifc.createIfcDocumentInformation(DocumentId="X", Name="FOOBAR", Scope="SHEET") subject.import_sheets() props = bpy.context.scene.DocProperties assert props.sheets[0].ifc_definition_id == document.id()