diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py
index 5b73dadd2a..b71c0caf04 100644
--- a/src/blenderbim/blenderbim/bim/helper.py
+++ b/src/blenderbim/blenderbim/bim/helper.py
@@ -273,6 +273,69 @@ def convert_property_group_from_si(property_group, skip_props=()):
setattr(property_group, prop_name, prop_value)
+def draw_filter(layout, props, data, module):
+ if not data.is_loaded:
+ data.load()
+
+ row = layout.row(align=True)
+ row.label(text=f"{len(data.data['saved_searches'])} Saved Searches")
+
+ if data.data["saved_searches"]:
+ row.operator("bim.load_search", text="", icon="IMPORT").module = module
+ row.operator("bim.save_search", text="", icon="EXPORT").module = module
+
+ row = layout.row(align=True)
+ row.operator("bim.add_filter_group", text="Add Search Group", icon="ADD").module = module
+
+ for i, filter_group in enumerate(props.filter_groups):
+ box = layout.box()
+
+ row = box.row(align=True)
+ row.prop(props, "facet", text="")
+ op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
+ op.type = props.facet
+ op.index = i
+ op.module = module
+
+ for j, ifc_filter in enumerate(filter_group.filters):
+ if ifc_filter.type == "entity":
+ row = box.row(align=True)
+ row.prop(ifc_filter, "value", text="", icon="FILE_3D")
+ elif ifc_filter.type == "attribute":
+ row = box.row(align=True)
+ row.prop(ifc_filter, "name", text="", icon="COPY_ID")
+ row.prop(ifc_filter, "value", text="")
+ elif ifc_filter.type == "type":
+ row = box.row(align=True)
+ row.prop(ifc_filter, "value", text="", icon="FILE_VOLUME")
+ elif ifc_filter.type == "material":
+ row = box.row(align=True)
+ row.prop(ifc_filter, "value", text="", icon="MATERIAL")
+ elif ifc_filter.type == "property":
+ row = box.row(align=True)
+ row.prop(ifc_filter, "pset", text="", icon="PROPERTIES")
+ row.prop(ifc_filter, "name", text="")
+ row.prop(ifc_filter, "value", text="")
+ elif ifc_filter.type == "classification":
+ row = box.row(align=True)
+ row.prop(ifc_filter, "value", text="", icon="OUTLINER")
+ elif ifc_filter.type == "location":
+ row = box.row(align=True)
+ row.prop(ifc_filter, "name", text="", icon="PACKAGE")
+ elif ifc_filter.type == "instance":
+ row = box.row(align=True)
+ row.prop(ifc_filter, "value", text="", icon="GRIP")
+ op = row.operator("bim.remove_filter", text="", icon="X")
+ op.group_index = i
+ op.index = j
+ op.module = module
+
+ row = box.row()
+ op = row.operator("bim.remove_filter_group", icon="X")
+ op.index = i
+ op.module = module
+
+
# TODO this should move into ifcopenshell.util
diff --git a/src/blenderbim/blenderbim/bim/module/csv/operator.py b/src/blenderbim/blenderbim/bim/module/csv/operator.py
index 569e5e2820..a364c9594b 100644
--- a/src/blenderbim/blenderbim/bim/module/csv/operator.py
+++ b/src/blenderbim/blenderbim/bim/module/csv/operator.py
@@ -149,7 +149,10 @@ class ExportIfcCsv(bpy.types.Operator):
ifc_file = IfcStore.get_file()
else:
ifc_file = ifcopenshell.open(props.csv_ifc_file)
- results = ifcopenshell.util.selector.filter_elements(ifc_file, props.ifc_selector)
+ results = ifcopenshell.util.selector.filter_elements(
+ ifc_file, tool.Search.export_filter_query(props.filter_groups)
+ )
+
ifc_csv = ifccsv.IfcCsv()
attributes = [a.name for a in props.csv_attributes]
sep = props.csv_custom_delimiter if props.csv_delimiter == "CUSTOM" else props.csv_delimiter
diff --git a/src/blenderbim/blenderbim/bim/module/csv/prop.py b/src/blenderbim/blenderbim/bim/module/csv/prop.py
index 8259d56b32..6535001a9f 100644
--- a/src/blenderbim/blenderbim/bim/module/csv/prop.py
+++ b/src/blenderbim/blenderbim/bim/module/csv/prop.py
@@ -17,6 +17,7 @@
# along with BlenderBIM Add-on. If not, see .
import bpy
+from blenderbim.bim.module.search.prop import BIMFilterGroup
from blenderbim.bim.prop import StrProperty
from bpy.types import PropertyGroup
from bpy.props import (
@@ -34,6 +35,19 @@ from bpy.props import (
class CsvProperties(PropertyGroup):
csv_ifc_file: StringProperty(default="", name="IFC File")
ifc_selector: StringProperty(default="", name="IFC Selector")
+ filter_groups: CollectionProperty(type=BIMFilterGroup, name="Filter Groups")
+ facet: EnumProperty(
+ items=[
+ ("entity", "Class", "", "FILE_3D", 0),
+ ("attribute", "Attribute", "", "COPY_ID", 1),
+ ("property", "Property", "", "PROPERTIES", 2),
+ ("material", "Material", "", "MATERIAL", 3),
+ ("classification", "Classification", "", "OUTLINER", 4),
+ ("location", "Location", "", "PACKAGE", 5),
+ ("type", "Type", "", "FILE_VOLUME", 6),
+ ("instance", "GlobalId", "", "GRIP", 7),
+ ],
+ )
csv_attributes: CollectionProperty(name="CSV Attributes", type=StrProperty)
null_value: StringProperty(default="N/A", name="Null Value")
csv_delimiter: EnumProperty(
@@ -56,4 +70,5 @@ class CsvProperties(PropertyGroup):
default="csv",
)
csv_custom_delimiter: StringProperty(default="", name="Custom Delimiter")
+ should_show_settings: BoolProperty(default=False, name="Show Settings")
should_load_from_memory: BoolProperty(default=False, name="Load from Memory")
diff --git a/src/blenderbim/blenderbim/bim/module/csv/ui.py b/src/blenderbim/blenderbim/bim/module/csv/ui.py
index f5bd4d4a94..2760894288 100644
--- a/src/blenderbim/blenderbim/bim/module/csv/ui.py
+++ b/src/blenderbim/blenderbim/bim/module/csv/ui.py
@@ -16,8 +16,10 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see .
+import blenderbim.bim.helper
from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore
+from blenderbim.bim.module.search.data import SearchData
class BIM_PT_ifccsv(Panel):
@@ -36,48 +38,48 @@ class BIM_PT_ifccsv(Panel):
props = scene.CsvProperties
if IfcStore.get_file():
- row = layout.row()
+ row = layout.row(align=True)
row.prop(props, "should_load_from_memory")
+ row.operator("bim.import_csv_attributes", icon="IMPORT", text="")
+ row.operator("bim.export_csv_attributes", icon="EXPORT", text="")
+ row.prop(props, "should_show_settings", icon="PREFERENCES", text="")
+ else:
+ row = layout.row(align=True)
+ row.alignment = "RIGHT"
+ row.operator("bim.import_csv_attributes", icon="IMPORT", text="")
+ row.operator("bim.export_csv_attributes", icon="EXPORT", text="")
+ row.prop(props, "should_show_settings", icon="PREFERENCES", text="")
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.select_csv_ifc_file", icon="FILE_FOLDER", text="")
- row = layout.row(align=True)
- row.prop(props, "ifc_selector")
- row.operator("bim.eyedrop_ifccsv", icon="EYEDROPPER", text="")
- layout.separator()
+ if props.should_show_settings:
+ row = layout.row(align=True)
+ row.prop(props, "format")
+
+ if props.format == "csv":
+ 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.prop(props, "null_value")
+
+ blenderbim.bim.helper.draw_filter(self.layout, props, SearchData, "csv")
row = layout.row(align=True)
row.operator("bim.add_csv_attribute", icon="ADD")
- row.operator("bim.remove_all_csv_attributes", icon="CANCEL")
- row = layout.row(align=True)
- row.operator("bim.import_csv_attributes", icon="IMPORT")
- row.operator("bim.export_csv_attributes", icon="EXPORT")
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, "format")
-
- if props.format == 'csv':
- 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.prop(props, "null_value")
-
- row = layout.row()
- split = row.split(factor=0.5)
- c = split.column()
- c.operator("bim.export_ifccsv", icon="EXPORT", text="Export IFC to " + props.format.upper())
- c = split.column()
- c.operator("bim.import_ifccsv", icon="IMPORT")
+ row.operator("bim.export_ifccsv", icon="EXPORT", text="Export IFC to " + props.format.upper())
+ row.operator("bim.import_ifccsv", icon="IMPORT")
diff --git a/src/blenderbim/blenderbim/bim/module/search/operator.py b/src/blenderbim/blenderbim/bim/module/search/operator.py
index 9803359c8a..b8a11c7ebd 100644
--- a/src/blenderbim/blenderbim/bim/module/search/operator.py
+++ b/src/blenderbim/blenderbim/bim/module/search/operator.py
@@ -61,9 +61,14 @@ colour_list = [
class AddFilterGroup(Operator):
bl_idname = "bim.add_filter_group"
bl_label = "Add Filter Group"
+ module: StringProperty()
def execute(self, context):
- context.scene.BIMSearchProperties.filter_groups.add()
+ if self.module == "search":
+ props = context.scene.BIMSearchProperties
+ elif self.module == "csv":
+ props = context.scene.CsvProperties
+ props.filter_groups.add()
return {"FINISHED"}
@@ -71,9 +76,13 @@ class RemoveFilterGroup(Operator):
bl_idname = "bim.remove_filter_group"
bl_label = "Remove Filter Group"
index: IntProperty()
+ module: StringProperty()
def execute(self, context):
- props = context.scene.BIMSearchProperties
+ if self.module == "search":
+ props = context.scene.BIMSearchProperties
+ elif self.module == "csv":
+ props = context.scene.CsvProperties
props.filter_groups.remove(self.index)
return {"FINISHED"}
@@ -83,9 +92,13 @@ class RemoveFilter(Operator):
bl_label = "Remove Filter Group"
group_index: IntProperty()
index: IntProperty()
+ module: StringProperty()
def execute(self, context):
- props = context.scene.BIMSearchProperties
+ if self.module == "search":
+ props = context.scene.BIMSearchProperties
+ elif self.module == "csv":
+ props = context.scene.CsvProperties
props.filter_groups[self.group_index].filters.remove(self.index)
return {"FINISHED"}
@@ -95,9 +108,14 @@ class AddFilter(Operator):
bl_label = "Add Filter"
index: IntProperty()
type: StringProperty()
+ module: StringProperty()
def execute(self, context):
- new = context.scene.BIMSearchProperties.filter_groups[self.index].filters.add()
+ if self.module == "search":
+ props = context.scene.BIMSearchProperties
+ elif self.module == "csv":
+ props = context.scene.CsvProperties
+ new = props.filter_groups[self.index].filters.add()
new.type = self.type
return {"FINISHED"}
@@ -127,13 +145,22 @@ class SaveSearch(Operator, tool.Ifc.Operator):
bl_description = "Save search filter to an IFC group"
bl_options = {"REGISTER", "UNDO"}
name: StringProperty(name="Name")
+ module: StringProperty()
def _execute(self, context):
if not self.name:
return
- query = tool.Search.export_filter_query(context.scene.BIMSearchProperties.filter_groups)
- results = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
+ if self.module == "search":
+ props = context.scene.BIMSearchProperties
+ elif self.module == "csv":
+ props = context.scene.CsvProperties
+
+ try:
+ query = tool.Search.export_filter_query(props.filter_groups)
+ results = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
+ except:
+ return
description = json.dumps({"type": "BBIM_Search", "query": query})
group = [g for g in tool.Ifc.get().by_type("IfcGroup") if g.Name == self.name]
@@ -141,7 +168,12 @@ class SaveSearch(Operator, tool.Ifc.Operator):
group = group[0]
else:
group = ifcopenshell.api.run("group.add_group", tool.Ifc.get(), Name=self.name, Description=description)
- ifcopenshell.api.run("group.assign_group", tool.Ifc.get(), products=results, group=group)
+ if results:
+ ifcopenshell.api.run("group.assign_group", tool.Ifc.get(), products=list(results), group=group)
+
+ def draw(self, context):
+ row = self.layout.row()
+ row.prop(self, "name")
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
@@ -152,11 +184,15 @@ class LoadSearch(Operator, tool.Ifc.Operator):
bl_label = "Load Search"
bl_description = "Load search filter from an IFC group"
bl_options = {"REGISTER", "UNDO"}
+ module: StringProperty()
def _execute(self, context):
- props = context.scene.BIMSearchProperties
- group = tool.Ifc.get().by_id(int(props.saved_searches))
- query = tool.Search.import_filter_query(group, context.scene.BIMSearchProperties.filter_groups)
+ if self.module == "search":
+ props = context.scene.BIMSearchProperties
+ elif self.module == "csv":
+ props = context.scene.CsvProperties
+ group = tool.Ifc.get().by_id(int(context.scene.BIMSearchProperties.saved_searches))
+ query = tool.Search.import_filter_query(group, props.filter_groups)
def draw(self, context):
props = context.scene.BIMSearchProperties
diff --git a/src/blenderbim/blenderbim/bim/module/search/ui.py b/src/blenderbim/blenderbim/bim/module/search/ui.py
index ce715e971a..706f5952e9 100644
--- a/src/blenderbim/blenderbim/bim/module/search/ui.py
+++ b/src/blenderbim/blenderbim/bim/module/search/ui.py
@@ -17,6 +17,7 @@
# along with BlenderBIM Add-on. If not, see .
import bpy
+import blenderbim.bim.helper
from bpy.types import Panel
from blenderbim.bim.module.search.data import SearchData, ColourByPropertyData, SelectSimilarData
@@ -35,59 +36,7 @@ class BIM_PT_search(Panel):
props = context.scene.BIMSearchProperties
- row = self.layout.row(align=True)
- row.label(text=f"{len(SearchData.data['saved_searches'])} Saved Searches")
-
- if SearchData.data["saved_searches"]:
- row.operator("bim.load_search", text="", icon="IMPORT")
- row.operator("bim.save_search", text="", icon="EXPORT")
-
- row = self.layout.row(align=True)
- row.operator("bim.add_filter_group", text="Add Search Group", icon="ADD")
-
- for i, filter_group in enumerate(props.filter_groups):
- box = self.layout.box()
-
- row = box.row(align=True)
- row.prop(props, "facet", text="")
- op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
- op.type = props.facet
- op.index = i
-
- for j, ifc_filter in enumerate(filter_group.filters):
- if ifc_filter.type == "entity":
- row = box.row(align=True)
- row.prop(ifc_filter, "value", text="", icon="FILE_3D")
- elif ifc_filter.type == "attribute":
- row = box.row(align=True)
- row.prop(ifc_filter, "name", text="", icon="COPY_ID")
- row.prop(ifc_filter, "value", text="")
- elif ifc_filter.type == "type":
- row = box.row(align=True)
- row.prop(ifc_filter, "value", text="", icon="FILE_VOLUME")
- elif ifc_filter.type == "material":
- row = box.row(align=True)
- row.prop(ifc_filter, "value", text="", icon="MATERIAL")
- elif ifc_filter.type == "property":
- row = box.row(align=True)
- row.prop(ifc_filter, "pset", text="", icon="PROPERTIES")
- row.prop(ifc_filter, "name", text="")
- row.prop(ifc_filter, "value", text="")
- elif ifc_filter.type == "classification":
- row = box.row(align=True)
- row.prop(ifc_filter, "value", text="", icon="OUTLINER")
- elif ifc_filter.type == "location":
- row = box.row(align=True)
- row.prop(ifc_filter, "name", text="", icon="PACKAGE")
- elif ifc_filter.type == "instance":
- row = box.row(align=True)
- row.prop(ifc_filter, "value", text="", icon="GRIP")
- op = row.operator("bim.remove_filter", text="", icon="X")
- op.group_index = i
- op.index = j
-
- row = box.row()
- row.operator("bim.remove_filter_group", icon="X").index = i
+ blenderbim.bim.helper.draw_filter(self.layout, props, SearchData, "search")
if len(props.filter_groups):
row = self.layout.row(align=True)