IfcCSV can now use the graphical filter query builder too.

This commit is contained in:
Dion Moult
2023-08-18 13:43:42 +10:00
parent 13eb8562e0
commit aed01b5703
6 changed files with 160 additions and 92 deletions
+63
View File
@@ -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
@@ -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
@@ -17,6 +17,7 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
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")
+30 -28
View File
@@ -16,8 +16,10 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
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")
@@ -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
@@ -17,6 +17,7 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
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)