diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 196d6e1ad6..94772be5cd 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -16,6 +16,7 @@ if bpy is not None: "cobie": None, "context": None, "covetool": None, + "csv": None, "debug": None, "geometry": None, "model": None, @@ -140,11 +141,6 @@ if bpy is not None: operator.RemovePropertyTemplate, operator.AddSectionPlane, operator.RemoveSectionPlane, - operator.AddCsvAttribute, - operator.RemoveCsvAttribute, - operator.ExportIfcCsv, - operator.ImportIfcCsv, - operator.EyedropIfcCsv, operator.ReloadIfcFile, operator.AddIfcFile, operator.RemoveIfcFile, @@ -255,7 +251,6 @@ if bpy is not None: ui.BIM_PT_document_information, ui.BIM_PT_constraints, ui.BIM_PT_search, - ui.BIM_PT_ifccsv, ui.BIM_PT_ifcclash, ui.BIM_PT_qa, ui.BIM_PT_library, diff --git a/src/ifcblenderexport/blenderbim/bim/module/csv/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/csv/__init__.py new file mode 100644 index 0000000000..f8e236dc26 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/csv/__init__.py @@ -0,0 +1,22 @@ +import bpy +from . import ui, prop, operator + +classes = ( + operator.AddCsvAttribute, + operator.RemoveCsvAttribute, + operator.ExportIfcCsv, + operator.ImportIfcCsv, + operator.EyedropIfcCsv, + prop.CsvProperties, + ui.BIM_PT_ifccsv, +) + + + +def register(): + bpy.types.Scene.CsvProperties = bpy.props.PointerProperty(type=prop.CsvProperties) + + +def unregister(): + del bpy.types.Scene.CsvProperties + diff --git a/src/ifcblenderexport/blenderbim/bim/module/csv/operator.py b/src/ifcblenderexport/blenderbim/bim/module/csv/operator.py new file mode 100644 index 0000000000..c3650146aa --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/csv/operator.py @@ -0,0 +1,91 @@ +import bpy +import ifccsv +import ifcopenshell +import os +import logging +import json +import webbrowser +import tempfile +from blenderbim.bim.ifc import IfcStore + + + +class AddCsvAttribute(bpy.types.Operator): + bl_idname = "bim.add_csv_attribute" + bl_label = "Add CSV Attribute" + + def execute(self, context): + attribute = bpy.context.scene.CsvProperties.csv_attributes.add() + return {"FINISHED"} + +class RemoveCsvAttribute(bpy.types.Operator): + bl_idname = "bim.remove_csv_attribute" + bl_label = "Remove CSV Attribute" + index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.scene.CsvProperties.csv_attributes.remove(self.index) + return {"FINISHED"} + +class ExportIfcCsv(bpy.types.Operator): + bl_idname = "bim.export_ifccsv" + bl_label = "Export IFC to CSV" + filename_ext = ".csv" + filepath: bpy.props.StringProperty(subtype="FILE_PATH") + + def invoke(self, context, event): + self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv") + WindowManager = context.window_manager + WindowManager.fileselect_add(self) + return {"RUNNING_MODAL"} + + def execute(self, context): + import ifccsv + + self.filepath = bpy.path.ensure_ext(self.filepath, ".csv") + ifc_file = ifcopenshell.open(bpy.context.scene.CsvProperties.csv_ifc_file) + selector = ifcopenshell.util.selector.Selector() + results = selector.parse(ifc_file, bpy.context.scene.CsvProperties.ifc_selector) + ifc_csv = ifccsv.IfcCsv() + ifc_csv.output = self.filepath + ifc_csv.attributes = [a.name for a in bpy.context.scene.CsvProperties.csv_attributes] + ifc_csv.selector = selector + if bpy.context.scene.CsvProperties.csv_delimiter == "CUSTOM": + ifc_csv.delimiter = bpy.context.scene.CsvProperties.csv_custom_delimiter + else: + ifc_csv.delimiter = bpy.context.scene.CsvProperties.csv_delimiter + ifc_csv.export(ifc_file, results) + return {"FINISHED"} + +class ImportIfcCsv(bpy.types.Operator): + bl_idname = "bim.import_ifccsv" + bl_label = "Import CSV to IFC" + filename_ext = ".csv" + filepath: bpy.props.StringProperty(subtype="FILE_PATH") + + def invoke(self, context, event): + self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv") + WindowManager = context.window_manager + WindowManager.fileselect_add(self) + return {"RUNNING_MODAL"} + + def execute(self, context): + import ifccsv + + ifc_csv = ifccsv.IfcCsv() + ifc_csv.output = self.filepath + ifc_csv.Import(bpy.context.scene.CsvProperties.csv_ifc_file) + return {"FINISHED"} + +class EyedropIfcCsv(bpy.types.Operator): + bl_idname = "bim.eyedrop_ifccsv" + bl_label = "Query Selected Items" + + def execute(self, context): + global_ids = [] + for obj in bpy.context.selected_objects: + if hasattr(obj, "BIMObjectProperties") and obj.BIMObjectProperties.attributes.get("GlobalId"): + global_ids.append("#" + obj.BIMObjectProperties.attributes.get("GlobalId").string_value) + bpy.context.scene.CsvProperties.ifc_selector = "|".join(global_ids) + return {"FINISHED"} + diff --git a/src/ifcblenderexport/blenderbim/bim/module/csv/prop.py b/src/ifcblenderexport/blenderbim/bim/module/csv/prop.py new file mode 100644 index 0000000000..24a9915f7a --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/csv/prop.py @@ -0,0 +1,27 @@ +import bpy +from blenderbim.bim.prop import StrProperty +from bpy.types import PropertyGroup +from bpy.props import ( + PointerProperty, + StringProperty, + EnumProperty, + BoolProperty, + IntProperty, + FloatProperty, + FloatVectorProperty, + CollectionProperty, +) + + +class CsvProperties(PropertyGroup): + csv_ifc_file: StringProperty(default="", name="CSV IFC File") + ifc_selector: StringProperty(default="", name="IFC Selector") + csv_attributes: CollectionProperty(name="CSV Attributes", type=StrProperty) + csv_delimiter: EnumProperty( + items=[(";", ";", ""), (",", ",", ""), (".", ".", ""), ("CUSTOM", "Custom", ""),], + name="IFC CSV Delimiter", + default=",", + ) + csv_custom_delimiter: StringProperty(default="", name="Custom Delimiter") + should_load_from_memory: BoolProperty(default=False, name="Load from Memory") + diff --git a/src/ifcblenderexport/blenderbim/bim/module/csv/ui.py b/src/ifcblenderexport/blenderbim/bim/module/csv/ui.py new file mode 100644 index 0000000000..f478682eb2 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/csv/ui.py @@ -0,0 +1,50 @@ +from bpy.types import Panel +from blenderbim.bim.ifc import IfcStore + + +class BIM_PT_ifccsv(Panel): + bl_label = "IFC CSV Import/Export" + bl_idname = "BIM_PT_ifccsv" + bl_options = {"DEFAULT_CLOSED"} + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + + def draw(self, context): + layout = self.layout + + scene = context.scene + props = scene.CsvProperties + + if IfcStore.get_file(): + row = layout.row() + row.prop(props, "should_load_from_memory") + + if not IfcStore.get_file() or not props.should_load_from_memory: + row = layout.row(align=True) + row.prop(props, "csv_ifc_file") + row.operator("bim.import_ifccsv", icon="FILE_FOLDER", text="") + row = layout.row(align=True) + row.prop(props, "ifc_selector") + row.operator("bim.eyedrop_ifccsv", icon="EYEDROPPER", text="") + + row = layout.row() + row.label(text="Add IFC attributes to filter", icon="FILE_BLANK") + row.operator("bim.add_csv_attribute") + + for index, attribute in enumerate(props.csv_attributes): + row = layout.row(align=True) + row.prop(attribute, "name", text="") + row.operator("bim.remove_csv_attribute", icon="X", text="").index = index + + row = layout.row(align=True) + row.prop(props, "csv_delimiter") + + if(props.csv_delimiter == 'CUSTOM'): + row = layout.row(align=True) + row.prop(props, "csv_custom_delimiter") + + row = layout.row(align=True) + row.operator("bim.export_ifccsv", icon="EXPORT") + row.operator("bim.import_ifccsv", icon="IMPORT") + diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index a5c284529d..448c9bf9ce 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -2457,90 +2457,6 @@ class RemoveSectionPlane(bpy.types.Operator): bpy.ops.object.delete({"selected_objects": [bpy.context.active_object]}) -class AddCsvAttribute(bpy.types.Operator): - bl_idname = "bim.add_csv_attribute" - bl_label = "Add CSV Attribute" - - def execute(self, context): - attribute = bpy.context.scene.BIMProperties.csv_attributes.add() - return {"FINISHED"} - - -class RemoveCsvAttribute(bpy.types.Operator): - bl_idname = "bim.remove_csv_attribute" - bl_label = "Remove CSV Attribute" - index: bpy.props.IntProperty() - - def execute(self, context): - bpy.context.scene.BIMProperties.csv_attributes.remove(self.index) - return {"FINISHED"} - - -class ExportIfcCsv(bpy.types.Operator): - bl_idname = "bim.export_ifccsv" - bl_label = "Export IFC to CSV" - filename_ext = ".csv" - filepath: bpy.props.StringProperty(subtype="FILE_PATH") - - def invoke(self, context, event): - self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv") - WindowManager = context.window_manager - WindowManager.fileselect_add(self) - return {"RUNNING_MODAL"} - - def execute(self, context): - import ifccsv - - self.filepath = bpy.path.ensure_ext(self.filepath, ".csv") - ifc_file = ifcopenshell.open(bpy.context.scene.BIMProperties.ifc_file) - selector = ifcopenshell.util.selector.Selector() - results = selector.parse(ifc_file, bpy.context.scene.BIMProperties.ifc_selector) - ifc_csv = ifccsv.IfcCsv() - ifc_csv.output = self.filepath - ifc_csv.attributes = [a.name for a in bpy.context.scene.BIMProperties.csv_attributes] - ifc_csv.selector = selector - if bpy.context.scene.BIMProperties.csv_delimiter == "CUSTOM": - ifc_csv.delimiter = bpy.context.scene.BIMProperties.csv_custom_delimiter - else: - ifc_csv.delimiter = bpy.context.scene.BIMProperties.csv_delimiter - ifc_csv.export(ifc_file, results) - return {"FINISHED"} - - -class ImportIfcCsv(bpy.types.Operator): - bl_idname = "bim.import_ifccsv" - bl_label = "Import CSV to IFC" - filename_ext = ".csv" - filepath: bpy.props.StringProperty(subtype="FILE_PATH") - - def invoke(self, context, event): - self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv") - WindowManager = context.window_manager - WindowManager.fileselect_add(self) - return {"RUNNING_MODAL"} - - def execute(self, context): - import ifccsv - - ifc_csv = ifccsv.IfcCsv() - ifc_csv.output = self.filepath - ifc_csv.Import(bpy.context.scene.BIMProperties.ifc_file) - return {"FINISHED"} - - -class EyedropIfcCsv(bpy.types.Operator): - bl_idname = "bim.eyedrop_ifccsv" - bl_label = "Query Selected Items" - - def execute(self, context): - global_ids = [] - for obj in bpy.context.selected_objects: - if hasattr(obj, "BIMObjectProperties") and obj.BIMObjectProperties.attributes.get("GlobalId"): - global_ids.append("#" + obj.BIMObjectProperties.attributes.get("GlobalId").string_value) - bpy.context.scene.BIMProperties.ifc_selector = "|".join(global_ids) - return {"FINISHED"} - - class ReloadIfcFile(bpy.types.Operator): bl_idname = "bim.reload_ifc_file" bl_label = "Reload IFC File" diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 7f06227817..9bd9cc1d49 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -1322,13 +1322,6 @@ class BIMProperties(PropertyGroup): name="Import Filter", ) ifc_selector: StringProperty(default="", name="IFC Selector") - csv_attributes: CollectionProperty(name="CSV Attributes", type=StrProperty) - csv_delimiter: EnumProperty( - items=[(";", ";", ""), (",", ",", ""), (".", ".", ""), ("CUSTOM", "Custom", ""),], - name="IFC CSV Delimiter", - default=";", - ) - csv_custom_delimiter: StringProperty(default="", name="Custom Delimiter") document_information: CollectionProperty(name="Document Information", type=DocumentInformation) active_document_information_index: IntProperty(name="Active Document Information Index") document_references: CollectionProperty(name="Document References", type=DocumentReference) diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 0adcd72b36..310884a844 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -1069,42 +1069,6 @@ class BIM_PT_search(Panel): row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA") -class BIM_PT_ifccsv(Panel): - bl_label = "IFC CSV Import/Export" - bl_idname = "BIM_PT_ifccsv" - bl_options = {"DEFAULT_CLOSED"} - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "scene" - - def draw(self, context): - layout = self.layout - - scene = context.scene - props = scene.BIMProperties - - row = layout.row(align=True) - row.prop(props, "ifc_selector") - row.operator("bim.eyedrop_ifccsv", icon="EYEDROPPER", text="") - - row = layout.row() - row.operator("bim.add_csv_attribute") - - for index, attribute in enumerate(props.csv_attributes): - row = layout.row(align=True) - row.prop(attribute, "name", text="") - row.operator("bim.remove_csv_attribute", icon="X", text="").index = index - - row = layout.row(align=True) - row.prop(props, "csv_delimiter") - row = layout.row(align=True) - row.prop(props, "csv_custom_delimiter") - - row = layout.row(align=True) - row.operator("bim.export_ifccsv", icon="EXPORT") - row.operator("bim.import_ifccsv", icon="IMPORT") - - class BIM_PT_qa(Panel): bl_label = "BIMTester Quality Auditing" bl_idname = "BIM_PT_qa"