More on template_list(), which is related to the specific problem:
To search in properties other than a PropertyGroup's .name, you can either write a custom filter function (see Ui List Template), or use a little hack: Concatenate all fields for search and use it as .name, but not draw it:
bl_info = {
"name": "Collection Menu",
"author": "CoDEmanX",
"version": (1, 0),
"blender": (2, 65, 0),
"location": "",
"description": "",
"warning": "",
"wiki_url": "",
"category": ""}
import bpy
coll_data = (
("Option A", "The first option, can be found by searching '1' as well"),
("Option B", "You can find this by searching for 'roflmao'"),
("Some text", "Some more descriptive explanation"),
("Blabla", "Talking stuff...")
)
class COLL_UL_search(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
# You should always start your row layout by a label (icon + text), or a non-embossed text field,
# this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
# Note "data" names should never be translated!
split = layout.split(0.3)
split.label(item.label)
split.label(item.description)
elif self.layout_type in {'GRID'}:
pass
class MyColl(bpy.types.PropertyGroup):
#name = bpy.props.StringProperty()
label = bpy.props.StringProperty()
description = bpy.props.StringProperty()
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
col = context.scene.col
idx = context.scene.col_idx
if idx >= len(col):
#context.scene.col_idx = len(col) - 1
text = "(index error)"
else:
text = col[idx].name
layout.template_list("COLL_UL_search", "", context.scene, "col", context.scene, "col_idx")
def collhack(scene):
bpy.app.handlers.scene_update_pre.remove(collhack)
try:
scene.col.clear()
except:
pass
for i, (label, description) in enumerate(coll_data, 1):
item = scene.col.add()
item.label = label
item.description = description
item.name = " ".join((str(i), label, description))
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.col = bpy.props.CollectionProperty(type=MyColl)
bpy.types.Scene.col_idx = bpy.props.IntProperty(default=0)
bpy.app.handlers.scene_update_pre.append(collhack)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.col
del bpy.types.Scene.col_idx
if __name__ == "__main__":
register()
And here's a complex, editable UIList that searches numbers, labels and descriptions:
import bpy
class MESH_UL_mylist(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
self.use_filter_show = True
if self.layout_type in {'DEFAULT', 'COMPACT'}:
split = layout.split(0.1)
split.label("%i." % (index + 1))
split = split.split(0.3)
split.prop(item, "label", text="", emboss=False)
split.prop(item, "description", text="", emboss=False)
elif self.layout_type in {'GRID'}:
pass
# Called once to filter/reorder items.
def filter_items(self, context, data, propname):
col = getattr(data, propname)
filter_name = self.filter_name.lower()
flt_flags = [self.bitflag_filter_item if any(
filter_name in filter_set for filter_set in (
str(i), item.label.lower(), item.description.lower()
)
)
else 0 for i, item in enumerate(col, 1)
]
if self.use_filter_sort_alpha:
flt_neworder = [x[1] for x in sorted(
zip(
[x[0] for x in sorted(enumerate(col), key=lambda x: x[1].label)],
range(len(col))
)
)
]
else:
flt_neworder = []
return flt_flags, flt_neworder
class MyColl(bpy.types.PropertyGroup):
#name = bpy.props.StringProperty()
label = bpy.props.StringProperty()
description = bpy.props.StringProperty()
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.template_list("MESH_UL_mylist", "", context.scene, "col", context.scene, "col_idx")
# Demo data
coll_data = (
("Option A", "The first option, can be found by searching '1' as well"),
("Option B", "You can find this by searching for 'roflmao'"),
("Some text", "Some more descriptive explanation"),
("Blabla", "Talking stuff...")
)
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.col = bpy.props.CollectionProperty(type=MyColl)
bpy.types.Scene.col_idx = bpy.props.IntProperty(default=0)
# Add demo data
scene = bpy.context.scene
#scene.col.clear()
if 1: #len(scene.col) < 1:
for label, description in coll_data:
item = scene.col.add()
item.label = label
item.description = description
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.col
del bpy.types.Scene.col_idx
if __name__ == "__main__":
register()
filter_itemsfunction in the UIList subclass, or concat the search fields and set it as.name(which is searched against). You can draw ID, label and description or whatever, but leave out the.nameproperty (implementation example added to my answer). – CodeManX Apr 22 '14 at 15:18template_list()examples to a new answer, as it's a bit off-topic. There's no need to update the.nameproperty just for searching, you can implement your own searching and sorting in a proper way by implementing thefilter_items()method. – CodeManX Apr 22 '14 at 23:49