Add search bar with simple filter function to the type manager

This commit is contained in:
Gorgious56
2025-01-10 09:44:12 +01:00
parent a6e953a550
commit aafb6fc426
4 changed files with 46 additions and 30 deletions
+24 -22
View File
@@ -57,20 +57,22 @@ class AuthoringData:
cls.data["ifc_element_type"] = cls.ifc_element_type
cls.data["ifc_classes"] = cls.ifc_classes()
cls.data["ifc_class_current"] = cls.ifc_class_current()
cls.data["relating_type_id"] = cls.relating_type_id() # only after .ifc_classes()
cls.data["relating_type_id_current"] = cls.relating_type_id_current() # only after .ifc_classes()
cls.data["relating_type_name"] = cls.relating_type_name() # only after .relating_type_id()
cls.data["relating_type_description"] = cls.relating_type_description() # only after .relating_type_id()
cls.data["predefined_type"] = cls.predefined_type() # only after .relating_type_id()
# Only after .ifc_classes()
# Make sure .ifc_classes() was run before next lines
cls.data["filtered_type_elements"] = cls.filtered_type_elements()
# Make sure .filtered_type_elements() was run before next lines
cls.data["relating_type_id"] = cls.relating_type_id()
# Make sure .relating_type_id() was run before next lines
cls.data["relating_type_id_current"] = cls.relating_type_id_current()
cls.data["relating_type_name"] = cls.relating_type_name()
cls.data["relating_type_description"] = cls.relating_type_description()
cls.data["predefined_type"] = cls.predefined_type()
cls.data["total_types"] = cls.total_types()
cls.data["total_pages"] = cls.total_pages()
cls.data["total_pages"] = cls.total_pages() # Only after .total_types()
cls.data["next_page"] = cls.next_page()
cls.data["prev_page"] = cls.prev_page()
cls.data["paginated_relating_types"] = cls.paginated_relating_types()
cls.data["type_thumbnail"] = cls.type_thumbnail() # Only after .relating_type_id()
cls.data["type_thumbnail"] = cls.type_thumbnail()
cls.data["is_voidable_element"] = cls.is_voidable_element()
cls.data["has_visible_openings"] = cls.has_visible_openings()
cls.data["has_visible_boundaries"] = cls.has_visible_boundaries()
@@ -114,13 +116,11 @@ class AuthoringData:
@classmethod
def total_types(cls):
ifc_class = cls.data["ifc_class_current"]
return len(tool.Ifc.get().by_type(ifc_class)) if ifc_class else 0
return len(cls.data["filtered_type_elements"])
@classmethod
def total_pages(cls):
ifc_class = cls.data["ifc_class_current"]
total_types = len(tool.Ifc.get().by_type(ifc_class)) if ifc_class else 0
total_types = cls.data["total_types"]
return math.ceil(total_types / cls.types_per_page)
@classmethod
@@ -134,12 +134,19 @@ class AuthoringData:
return cls.props.type_page - 1
@classmethod
def paginated_relating_types(cls):
def filtered_type_elements(cls):
ifc_class = cls.data["ifc_class_current"]
if not ifc_class:
return []
elements = list(tool.Ifc.get().by_type(ifc_class))
if cls.props.search_name:
elements = [e for e in elements if cls.props.search_name.lower() in (e.Name or "Unnamed").lower()]
return natsorted(elements, key=lambda s: (s.Name or "Unnamed").lower())
@classmethod
def paginated_relating_types(cls):
results = []
elements = natsorted(tool.Ifc.get().by_type(ifc_class), key=lambda e: e.Name or "Unnamed")
elements = cls.data["filtered_type_elements"]
elements = elements[(cls.props.type_page - 1) * cls.types_per_page : cls.props.type_page * cls.types_per_page]
for element in elements:
predefined_type = ifcopenshell.util.element.get_predefined_type(element)
@@ -266,13 +273,8 @@ class AuthoringData:
@classmethod
def relating_type_id(cls):
results = []
ifc_class = cls.data["ifc_class_current"]
if ifc_class:
elements = natsorted(tool.Ifc.get().by_type(ifc_class), key=lambda s: (s.Name or "Unnamed").lower())
results.extend(elements)
return [(str(e.id()), e.Name or "Unnamed", e.Description or "") for e in results]
return []
elements = cls.data["filtered_type_elements"]
return [(str(e.id()), e.Name or "Unnamed", e.Description or "") for e in elements]
@classmethod
def relating_type_id_current(cls):
@@ -566,7 +566,9 @@ class LoadTypeThumbnails(bpy.types.Operator, tool.Ifc.Operator):
processing = set()
# Only process at most one paginated class at a time.
# Large projects have hundreds of types which can lead to unnecessary lag.
queue = sorted(tool.Ifc.get().by_type(self.ifc_class), key=lambda e: e.Name or "Unnamed")
if not AuthoringData.is_loaded:
AuthoringData.load()
queue = AuthoringData.data["filtered_type_elements"]
if self.limit:
queue = queue[self.offset : self.offset + self.limit]
else:
@@ -97,11 +97,26 @@ def update_slab_direction_decorator(self, context):
SlabDirectionDecorator.uninstall()
def update_search_name(self, context):
AuthoringData.load()
# Total number of pages may decrease when using the search bar :
if self.type_page > AuthoringData.data["total_pages"]:
self.type_page = AuthoringData.data["total_pages"]
bpy.ops.bim.load_type_thumbnails(ifc_class=self.ifc_class)
class BIMModelProperties(PropertyGroup):
ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="Construction Class", update=update_ifc_class)
relating_type_id: bpy.props.EnumProperty(
items=get_relating_type_id, name="Relating Type", update=update_relating_type_id
)
search_name: bpy.props.StringProperty(
name="Search Name",
default="",
description="Use this property to filter the list of available types",
update=update_search_name,
options={"SKIP_SAVE", "TEXTEDIT_UPDATE"},
)
menu_relating_type_id: bpy.props.IntProperty()
icon_id: bpy.props.IntProperty()
updating: bpy.props.BoolProperty(default=False)
+4 -7
View File
@@ -108,12 +108,10 @@ class LaunchTypeManager(bpy.types.Operator):
def draw(self, context):
props = context.scene.BIMModelProperties
row = self.layout.row(align=True)
text = f"{AuthoringData.data['total_types']} {AuthoringData.data['ifc_element_type']}"
if AuthoringData.data["total_types"] > 1:
text = f"{AuthoringData.data['total_types']} {AuthoringData.data['ifc_element_type']}s"
else:
text = f"{AuthoringData.data['total_types']} {AuthoringData.data['ifc_element_type']}"
text += "s"
row.label(text=text, icon="FILE_VOLUME")
# prop_with_search(row, props, "ifc_class", text="", should_click_ok_to_validate=True)
row.menu("BIM_MT_type_manager_menu", text="", icon="PREFERENCES")
row = self.layout.row(align=True)
row.operator("bim.launch_add_element", text=f"Create New {AuthoringData.data['ifc_element_type']}", icon="ADD")
@@ -121,9 +119,6 @@ class LaunchTypeManager(bpy.types.Operator):
columns = self.layout.column_flow(columns=3)
row = columns.row(align=True)
row.alignment = "CENTER"
### In case you want something here in the future
###
row = columns.row(align=True)
row.alignment = "RIGHT"
@@ -136,6 +131,8 @@ class LaunchTypeManager(bpy.types.Operator):
op = row.operator("bim.change_type_page", icon="TRIA_RIGHT", text="")
op.page = AuthoringData.data["next_page"]
self.layout.prop(props, "search_name", icon="VIEWZOOM", text="")
flow = self.layout.grid_flow(row_major=True, columns=3, even_columns=True, even_rows=True, align=True)
for relating_type in AuthoringData.data["paginated_relating_types"]: