From e2102cd2c7bb89987d70bc02b09ee296d1006824 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 1 Apr 2024 09:44:50 +1100 Subject: [PATCH] Fix #4306. Remove superseded selector UI. --- .../blenderbim/bim/module/diff/ui.py | 1 - .../blenderbim/bim/module/search/__init__.py | 14 -- .../blenderbim/bim/module/search/operator.py | 217 ------------------ .../blenderbim/bim/module/search/prop.py | 138 +---------- .../blenderbim/bim/module/search/ui.py | 150 ------------ 5 files changed, 1 insertion(+), 519 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/diff/ui.py b/src/blenderbim/blenderbim/bim/module/diff/ui.py index d91f0eb9a0..ae0646fc92 100644 --- a/src/blenderbim/blenderbim/bim/module/diff/ui.py +++ b/src/blenderbim/blenderbim/bim/module/diff/ui.py @@ -95,7 +95,6 @@ class BIM_PT_diff(Panel): row = layout.row(align=True) row.prop(props, "diff_filter_elements") - row.operator("bim.ifc_selector", icon="FILTER", text="") row = layout.row() row.operator("bim.execute_ifc_diff") diff --git a/src/blenderbim/blenderbim/bim/module/search/__init__.py b/src/blenderbim/blenderbim/bim/module/search/__init__.py index 606ed092c8..2abf6b132c 100644 --- a/src/blenderbim/blenderbim/bim/module/search/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/search/__init__.py @@ -24,21 +24,15 @@ classes = ( operator.ActivateIfcClassFilter, operator.AddFilter, operator.AddFilterGroup, - operator.AddToIfcGroup, operator.ColourByProperty, operator.EditFilterQuery, - operator.FilterModelElements, - operator.IfcSelector, operator.LoadColourscheme, - operator.LoadQuery, operator.LoadSearch, - operator.OpenQueryLibrary, operator.RemoveFilter, operator.RemoveFilterGroup, operator.ResetObjectColours, operator.SaveColourscheme, operator.SaveSearch, - operator.SaveSelectorQuery, operator.Search, operator.SelectByProperty, operator.SelectFilterElements, @@ -51,11 +45,6 @@ classes = ( prop.BIMFilterClasses, prop.BIMFilterBuildingStoreys, prop.BIMSearchProperties, - prop.SearchCollection, - prop.SearchQueryFilter, - prop.SearchQuery, - prop.SearchQueryGroup, - prop.IfcSelectorProperties, ui.BIM_PT_search, ui.BIM_PT_filter, ui.BIM_PT_colour_by_property, @@ -63,15 +52,12 @@ classes = ( ui.BIM_UL_colourscheme, ui.BIM_UL_ifc_class_filter, ui.BIM_UL_ifc_building_storey_filter, - ui.BIM_PT_IFCSelector, ) def register(): bpy.types.Scene.BIMSearchProperties = bpy.props.PointerProperty(type=prop.BIMSearchProperties) - bpy.types.Scene.IfcSelectorProperties = bpy.props.PointerProperty(type=prop.IfcSelectorProperties) def unregister(): del bpy.types.Scene.BIMSearchProperties - del bpy.types.Scene.IfcSelectorProperties diff --git a/src/blenderbim/blenderbim/bim/module/search/operator.py b/src/blenderbim/blenderbim/bim/module/search/operator.py index eb9278939b..132d61216a 100644 --- a/src/blenderbim/blenderbim/bim/module/search/operator.py +++ b/src/blenderbim/blenderbim/bim/module/search/operator.py @@ -623,223 +623,6 @@ class ShowAllElements(Operator): return {"FINISHED"} -class FilterModelElements(Operator): - """Filter model elements based on selection""" - - bl_idname = "bim.filter_model_elements" - bl_label = "Filter Model Elements" - option: StringProperty("select|isolate|hide") - - def execute(self, context): - selection_props = context.scene.IfcSelectorProperties - selection = ( - selection_props.selector_query_syntax - if selection_props.manual_override - else self.add_groups(selection_props) - ) - selection_props.selector_query_syntax = selection - r = core.search(tool.Search, tool.Spatial, query=selection, action=self.option) - if isinstance(r, str): - self.report({"WARNING"}, r) - return {"FINISHED"} - - def add_groups(self, selector: str) -> str: - selection = "" - for group_index, group in enumerate(selector.groups): - if group_index != 0: - selection += " | " - selection += "(" if len(selector.groups) > 1 else "" - selection = self.add_queries(selection, group) - - selection += ")" if len(selector.groups) > 1 else "" - return selection - - def add_queries(self, selection: str, group: str) -> str: - for query_index, query in enumerate(group.queries): - if query_index != 0: - selection += " & " if query.and_or == "and" else " | " - - if query.selector == "IFC Class": - active_option = query.active_option.split(": ")[1] - selection += f".{active_option}" - selection = self.add_filters(selection, query) - - elif query.selector == "GlobalId": - selection += f"#{query.value}" - - elif query.selector == "IfcElementType": - index = int(query.active_sub_option.split(":")[0]) - selection += f"* #{query.sub_options[index].global_id}" - - elif query.selector == "IfcSpatialElement": - index = int(query.active_sub_option.split(":")[0]) - selection += f"@ #{query.sub_options[index].global_id}" - return selection - - def add_filters(self, selection: str, query: str) -> str: - for f_index, f in enumerate(query.filters): - if f_index != 0: - selection += " & " if f.and_or == "and" else " | " - selection += f".{query.active_option}" - - if f.value in ("True", "False"): - value = f.value - elif f.value.isnumeric() and str(float(f.value))[0] == f.value[0]: - value = f.value - else: - value = f'"{f.value}"' - - selection += "[" - - if f.selector == "IfcPropertySet": - selection += f'{f.active_option.split(": ")[1]}.{f.active_sub_option.split(": ")[1]} {"!" if f.negation else ""}{f.comparison} {value}' - elif f.selector == "Attribute": - # we're using the prop_search functionality in blender which returns the index of the option. Sometimes the user can override this and enter a value that doesn't exist in the list. In this case there is no index and we need to handle it. @vulevukusej - pattern = re.compile(r"^[0-9]+:") - match = pattern.search(f.active_option) - selection += f'{f.active_option.split(": ")[1] if match else f.active_option} {"!" if f.negation else ""}{f.comparison} {value}' - selection += "]" - return selection - - -# This needs to be moved into ui code, I know ;) - vulevukusej -class IfcSelector(Operator): - """Select elements in model with IFC Selector""" - - bl_idname = "bim.ifc_selector" - bl_label = "Select elements with IFC Selector" - - def invoke(self, context, event): - return context.window_manager.invoke_props_dialog(self, width=800) - - @classmethod - def poll(cls, context): - return IfcStore.get_file() - - def execute(self, context): - return {"FINISHED"} - - def draw(self, context): - from . import ui - - ui.IfcSelectorUI.draw(context, self.layout) - - -class SaveSelectorQuery(Operator): - bl_idname = "bim.save_selector_query" - bl_label = "Save Selector Query" - save_name: StringProperty() - - def invoke(self, context, event): - return context.window_manager.invoke_props_dialog(self, width=400) - - def draw(self, context): - layout = self.layout - layout.prop(self, "save_name") - - def execute(self, context): - ifc_selector = context.scene.IfcSelectorProperties - new = ifc_selector.query_library.add() - new.name = self.save_name - new.query = ifc_selector.selector_query_syntax - return {"FINISHED"} - - -class OpenQueryLibrary(Operator): - """Open Query Library""" - - bl_idname = "bim.open_query_library" - bl_label = "Open Query Library" - - def invoke(self, context, event): - return context.window_manager.invoke_popup(self, width=400) - - def draw(self, context): - layout = self.layout - ifc_selector = context.scene.IfcSelectorProperties - - for index, query in enumerate(ifc_selector.query_library): - row = layout.row(align=True) - row.prop(query, "query", text=query.name) - op = row.operator("bim.load_query", icon="SORT_ASC", text="") - op.index = index - - row.context_pointer_set(name="bim_prop_group", data=ifc_selector) - op = row.operator("bim.edit_blender_collection", icon="REMOVE", text="") - op.option = "remove" - op.collection = "query_library" - op.index = index - - def execute(self, context): - return {"FINISHED"} - - -class LoadQuery(Operator): - bl_idname = "bim.load_query" - bl_label = "Load Query" - index: IntProperty() - - def invoke(self, context, event): - close_operator_panel(event) - return self.execute(context) - - def execute(self, context): - ifc_selector = context.scene.IfcSelectorProperties - ifc_selector.selector_query_syntax = ifc_selector.query_library[self.index].query - return {"FINISHED"} - - -class AddToIfcGroup(Operator): - bl_idname = "bim.add_to_ifc_group" - bl_label = "Add to IFC Group" - group_name: StringProperty(name="Group Name") - - def invoke(self, context, event): - bpy.ops.bim.load_groups() - return context.window_manager.invoke_props_dialog(self, width=400) - - def draw(self, context): - self.props = context.scene.BIMGroupProperties - row = self.layout.row() - row.operator("bim.add_group") - - self.layout.template_list( - "BIM_UL_groups", - "", - self.props, - "groups", - self.props, - "active_group_index", - ) - - if self.props.active_group_id: - for attribute in self.props.group_attributes: - if attribute.name in ["Name", "Description"]: - row = self.layout.row(align=True) - row.prop(attribute, "string_value", text=attribute.name) - - def execute(self, context): - active_group_index = self.props.active_group_index - ifc_definition_id = self.props.groups[active_group_index].ifc_definition_id - - bpy.ops.bim.enable_editing_group(group=ifc_definition_id) - - selector_query_syntax = context.scene.IfcSelectorProperties.selector_query_syntax - - for attribute in self.props.group_attributes: - if attribute.name == "Description": - if "*selector*" not in attribute.string_value: - attribute.string_value += f" *selector*{selector_query_syntax}*selector*" - else: - new_description = attribute.string_value.split("*selector*") - new_description[1] = selector_query_syntax - attribute.string_value = "*selector*".join(new_description) - - bpy.ops.bim.edit_group() - bpy.ops.bim.disable_group_editing_ui() - return {"FINISHED"} - - class SelectSimilar(Operator, tool.Ifc.Operator): bl_idname = "bim.select_similar" bl_label = "Select Similar" diff --git a/src/blenderbim/blenderbim/bim/module/search/prop.py b/src/blenderbim/blenderbim/bim/module/search/prop.py index 22d0e80173..2414cb8201 100644 --- a/src/blenderbim/blenderbim/bim/module/search/prop.py +++ b/src/blenderbim/blenderbim/bim/module/search/prop.py @@ -78,7 +78,7 @@ def update_is_container_selected(self, context): else: for obj in context.selected_objects: container = tool.Spatial.get_container(tool.Ifc.get_entity(obj)) - if (container and container.Name == self.name) or (not container and self.name== "None"): + if (container and container.Name == self.name) or (not container and self.name == "None"): obj.select_set(False) new = self.unselected_objects.add() new.obj = obj @@ -138,139 +138,3 @@ def get_classes(self, ifc_product): declarations = util.schema.get_subtypes(declaration) names = [d.name() for d in declarations] return [(c, c, "") for c in sorted(names)] - - -def load_sub_options(self, context): - if self.selector not in ["IfcClass"]: - self.load_option = "sub_options" - load_selection_options(self, context) - - -def load_selection_options(self, context): - ifc = IfcStore.file - load_option = self.load_option - op = getattr(self, load_option) - op.clear() - options = [] - - if load_option == "options": - self.sub_options.clear() - if self.selector == "IFC Class": - options = get_classes(self, "IfcElement") - options.append(("IfcSpace", "IfcSpace", "")) - elif self.selector == "IfcSpatialElement": - options = get_classes(self, "IfcSpatialElement") - elif self.selector == "IfcElementType": - options = get_classes(self, "IfcElementType") - elif self.selector == "GlobalId": - return - elif self.selector == "IfcPropertySet": - psets = Selector.parse(ifc, ".IfcPropertySet") - options = set([o.Name for o in psets]) - elif self.selector == "Attribute": - attributes = ["GlobalId", "Name", "Description", "ObjectType", "Tag", "PredefinedType"] - for a in attributes: - options.append((a, a, "")) - - elif load_option == "sub_options": - if self.selector in ["IfcSpatialElement", "IfcElementType"]: - active_option = self.active_option.split(": ")[1] - options = Selector.parse(ifc, f".{active_option}") - - elif self.selector == "IfcPropertySet": - options = set() - active_pset = self.active_option.split(": ")[1] - psets_in_file = Selector.parse(ifc, f'.IfcPropertySet[Name="{active_pset}"]') - for pset in psets_in_file: - for prop in pset.HasProperties: - options.add(prop.Name) - - for index, option in enumerate(options): - new = op.add() - if self.selector in ["IfcSpatialElement", "IfcElementType"]: - if self.load_option == "sub_options": - new.name = f"{index}: {option.Name}" - new.global_id = option.GlobalId - else: - new.name = f"{index}: {option[0]}" - elif self.selector == "IfcPropertySet": - new.name = f"{index}: {option}" - else: - new.name = f"{index}: {option[0]}" - self.load_option = "options" - - -def load_spatial_elements(self, context): - ifc = IfcStore.file - col_items = Selector.parse(ifc, f".{self.selected_spatial_element}") - collection = getattr(self, "sub_spatial_elements", None) - collection.clear() - for index, c in enumerate(col_items): - new = collection.add() - new.name = f"{index}-{c.Name}" - - -class SearchCollection(PropertyGroup): - name: StringProperty() - long_name: StringProperty() - global_id: StringProperty() - query: StringProperty() - - -class IfcSelector: - and_or: EnumProperty( - items=[(i, i, i) for i in ["and", "or"]], - ) - negation: BoolProperty(name="not") - comparison: EnumProperty( - items=[ - ("=", "equal to", ""), - ("*=", "contains", ""), - (">=", "greater than or equal to", ""), - ("<=", "lesser than or equal to", ""), - (">", "greater than", ""), - ("<", "less than", ""), - ], - ) - load_option: StringProperty( - default="options", description="controls whether or not options or sub_options are loaded" - ) - options: CollectionProperty(type=SearchCollection) - active_option: StringProperty(update=load_sub_options) - sub_options: CollectionProperty(type=SearchCollection) - active_sub_option: StringProperty() - value: StringProperty(description="generic 'value' that can be used in multiple scenarios") - - -class SearchQueryFilter(PropertyGroup, IfcSelector): - selector: EnumProperty( - items=[(i, i, i) for i in ["-", "IfcPropertySet", "Attribute"]], - name="Filter selection by", - update=load_selection_options, - default="-", - ) - - -class SearchQuery(PropertyGroup, IfcSelector): - filters: CollectionProperty(type=SearchQueryFilter) - selector: EnumProperty( - items=[(i, i, i) for i in ["-", "IFC Class", "IfcSpatialElement", "IfcElementType", "GlobalId"]], - name="Selector type", - update=load_selection_options, - default="-", - ) - - -class SearchQueryGroup(PropertyGroup, IfcSelector): - queries: CollectionProperty(type=SearchQuery) - - -class IfcSelectorProperties(PropertyGroup, IfcSelector): - groups: CollectionProperty(type=SearchQueryGroup) - selector_query_syntax: StringProperty() - - query_library: CollectionProperty(type=SearchCollection) - active_query: StringProperty() - - active_query: StringProperty() - manual_override: BoolProperty(default=False, description="Toggle to allow manual typing of query-syntax") diff --git a/src/blenderbim/blenderbim/bim/module/search/ui.py b/src/blenderbim/blenderbim/bim/module/search/ui.py index b8c733c848..6512ccbfa4 100644 --- a/src/blenderbim/blenderbim/bim/module/search/ui.py +++ b/src/blenderbim/blenderbim/bim/module/search/ui.py @@ -159,153 +159,3 @@ class BIM_UL_ifc_building_storey_filter(bpy.types.UIList): split = split.column() split.scale_x = 0.5 split.label(text=str(item.total)) - - -class BIM_PT_IFCSelector(Panel): - bl_label = "Selector" - bl_idname = "BIM_PT_ifc_selector" - bl_options = {"DEFAULT_CLOSED"} - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "scene" - bl_parent_id = "BIM_PT_tab_sandbox" - - def draw(self, context): - layout = self.layout - layout.operator("bim.ifc_selector") - - -# this doesn't inherit from Panel since it's just a class to abstract away UI code from the IfcSelector Operator -class IfcSelectorUI: - @classmethod - def draw(self, context, layout): - ifc_selector = context.scene.IfcSelectorProperties - row = layout.row() - - row.context_pointer_set(name="bim_prop_group", data=ifc_selector) - op = row.operator("bim.edit_blender_collection", text="Add selection group") - op.option = "add" - op.collection = "groups" - layout.separator() - - self.draw_query_group_ui(self, ifc_selector, layout) - - if len(ifc_selector.groups) != 0: - row = layout.row(align=True) - row.prop(ifc_selector, "selector_query_syntax", text="Query Syntax") - row.prop(ifc_selector, "manual_override", text="") - - select = row.operator("bim.filter_model_elements", text="", icon="RESTRICT_SELECT_OFF") - select.option = "select" - isolate = row.operator("bim.filter_model_elements", text="", icon="ZOOM_SELECTED") - isolate.option = "isolate" - hide = row.operator("bim.filter_model_elements", text="", icon="HIDE_ON") - hide.option = "hide" - unhide = row.operator("bim.filter_model_elements", text="", icon="HIDE_OFF") - unhide.option = "unhide" - - row = layout.row(align=True) - row.alignment = "CENTER" - row.operator("bim.save_selector_query", text="Save Query") - op = row.operator("bim.open_query_library", text="Load Query") - row.operator("bim.add_to_ifc_group", text="Add to IFC Group") - - row = layout.row(align=True) - row.operator("bim.show_scene_elements", text="Show All Elements", icon="HIDE_OFF") - - def draw_query_group_ui(self, ifc_selector, layout): - for index, group in enumerate(ifc_selector.groups): - row = layout.row() - row.alignment = "CENTER" - row.label(text="or") if index != 0 else None - - box = layout.box() - row = box.row(align=True) - row.alignment = "CENTER" - row.label(text=f"Group #{str(index+1)}") - row.context_pointer_set(name="bim_prop_group", data=group) - op = row.operator("bim.edit_blender_collection", text="Add query", icon="PLUS") - op.option = "add" - op.collection = "queries" - - row.context_pointer_set(name="bim_prop_group", data=ifc_selector) - op = row.operator("bim.edit_blender_collection", text="Remove selection group") - op.option = "remove" - op.collection = "groups" - op.index = index - - self.draw_query_ui(self, group, box) - - def draw_query_ui(self, group, box): - for index, query in enumerate(group.queries): - row = box.row() - row.alignment = "LEFT" - - row.prop(query, "and_or", text="") if index != 0 else None - if query.and_or == "or": - row = box.row() - row.alignment = "LEFT" - row.prop(query, "selector", text="") - - if query.selector in ["IFC Class", "IfcSpatialElement", "IfcElementType"]: - row.label(text="Equals") - row.prop_search(query, "active_option", query, "options", text="") - row.prop_search(query, "active_sub_option", query, "sub_options", text="") if len( - query.sub_options - ) != 0 else None - self.draw_filter_ui(self, box, query) - - elif query.selector in ["GlobalId", "Attribute"]: - row.prop(query, "negation", text="") - row.prop(query, "comparison", text="") - row.prop(query, "value", text="") - - row.context_pointer_set(name="bim_prop_group", data=group) - op = row.operator("bim.edit_blender_collection", icon="REMOVE", text="") - op.option = "remove" - op.collection = "queries" - op.index = index - - row.context_pointer_set(name="bim_prop_group", data=query) - op = ( - row.operator("bim.edit_blender_collection", text="Add filter") - if query.selector == "IFC Class" - else None - ) - if op: - op.option = "add" - op.collection = "filters" - - def draw_filter_ui(self, box, query): - for filter_index, f in enumerate(query.filters): - row = box.row() - row.alignment = "LEFT" - row.label(text=" ↪") - row.prop(f, "and_or", text="") if filter_index != 0 else None - if f.and_or == "or": - row = box.row() - row.alignment = "LEFT" - row.label(text=" ↪") - row.prop(f, "selector", text="") - - if f.selector == "Attribute": - row.prop_search(f, "active_option", f, "options", text="", results_are_suggestions=True) - row.prop( - f, - "negation", - ) - row.prop(f, "comparison", text="") - row.prop(f, "value", text="") - - elif f.selector == "IfcPropertySet": - row.prop_search(f, "active_option", f, "options", text="") - row.prop_search(f, "active_sub_option", f, "sub_options", text="") - row.prop(f, "negation") - row.prop(f, "comparison", text="") - row.prop(f, "value", text="") - - row.context_pointer_set(name="bim_prop_group", data=query) - op = row.operator("bim.edit_blender_collection", icon="REMOVE", text="") - op.option = "remove" - op.collection = "filters" - op.index = filter_index