Better sorting of search results

This commit is contained in:
Ellwood Zwovic
2017-07-18 17:30:42 -07:00
parent 6193437636
commit 19c1f3a8ac

View File

@@ -402,8 +402,17 @@ class USERPREF_PT_packages(bpy.types.Panel):
return (userpref.active_section == 'PACKAGES') return (userpref.active_section == 'PACKAGES')
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
wm = context.window_manager
# try:
# wm['package_last_used_filters']
# except KeyError:
# wm['package_last_used_filters'] = {}
# try:
# wm['package_displayed_packages']
# except KeyError:
# wm['package_displayed_packages'] = []
main = layout.row() main = layout.row()
spl = main.split(.12) spl = main.split(.12)
@@ -411,42 +420,66 @@ class USERPREF_PT_packages(bpy.types.Panel):
pkgzone = spl.column() pkgzone = spl.column()
sidebar.label(text="Category") sidebar.label(text="Category")
sidebar.prop(context.window_manager, "addon_filter", text="") sidebar.prop(wm, "addon_filter", text="")
top = pkgzone.row() top = pkgzone.row()
spl = top.split(.6) spl = top.split(.6)
spl.prop(context.window_manager, "package_search", text="", icon='VIEWZOOM') spl.prop(wm, "package_search", text="", icon='VIEWZOOM')
spl_r = spl.row() spl_r = spl.row()
spl_r.prop(context.window_manager, "package_install_filter", expand=True) spl_r.prop(wm, "package_install_filter", expand=True)
#TODO: more advanced filter/sorting; sort matches which match the filter string from the start higher #TODO: if filters are only added to, we can filter on existing filtered list rather than redoing whole list
#Also some caching of this would be nice, this only needs to be re-run when any of the filters change. # def filters_changed(filters: dict) -> bool:
def filter_package(package):# {{{ # if filters['search'] != wm['package_last_used_filters'].get('search'):
"""Returns true if the given package matches all filters""" # return True
filterstr = bpy.context.window_manager.package_search # if filters['category'] != wm['package_last_used_filters'].get('category'):
category = bpy.context.window_manager.addon_filter # return True
blinfo = package['bl_info'] # return False
def match_search() -> bool: def filtered(filters: dict, packages: list) -> list:
if len(filterstr) == 0: """Returns filtered and sorted list of packages which match filters defined in dict"""
return True
if blinfo['name'].lower().__contains__(filterstr.lower()): #TODO: using lower() for case-insensitive comparison doesn't work in some languages
def match_contains(blinfo) -> bool:
if blinfo['name'].lower().__contains__(filters['search'].lower()):
return True return True
return False return False
def match_category() -> bool: def match_startswith(blinfo) -> bool:
if category.upper() == 'ALL': if blinfo['name'].lower().startswith(filters['search'].lower()):
return True
return False
def match_category(blinfo) -> bool:
if filters['category'].lower() == 'all':
return True return True
if 'category' not in blinfo: if 'category' not in blinfo:
return True return False
if blinfo['category'].upper() == category.upper(): if blinfo['category'].lower() == filters['category'].lower():
return True return True
return False return False
if match_search() and match_category():
return True
return False# }}} # use two lists as a simple way of putting matches from the start on top
contains = []
startswith = []
for pkg in packages:
blinfo = pkg['bl_info']
if match_category(blinfo):
if len(filters['search']) == 0:
startswith.append(pkg)
continue
if match_startswith(blinfo):
startswith.append(pkg)
continue
if match_contains(blinfo):
contains.append(pkg)
continue
return startswith + contains
def draw_package(pkg, layout):# {{{ def draw_package(pkg, layout):# {{{
"""Draws the given package""" """Draws the given package"""
@@ -533,7 +566,7 @@ class USERPREF_PT_packages(bpy.types.Panel):
#TODO either store repos in windowmanager and reload from disk every time, or store them in the .blend. Not both #TODO either store repos in windowmanager and reload from disk every time, or store them in the .blend. Not both
repo = context.user_preferences.addons[__package__].preferences['repo'] repo = context.user_preferences.addons[__package__].preferences['repo']
except KeyError: except KeyError:
center_message("Loading Repositories...") center_message(pkgzone, "Loading Repositories...")
import pathlib import pathlib
# TODO: read repository synchronously for now; can't run an operator to do async monitoring from draw code # TODO: read repository synchronously for now; can't run an operator to do async monitoring from draw code
@@ -544,14 +577,25 @@ class USERPREF_PT_packages(bpy.types.Panel):
return return
if repo is None: if repo is None:
center_message("No repository found. Add one in the addon preferences.") center_message(pkgzone, "No repository found. Add one in the addon preferences.")
return return
for pkg in repo['packages']: filters = {
if filter_package(pkg): 'category': bpy.context.window_manager.addon_filter,
row = pkgzone.row() 'search': bpy.context.window_manager.package_search,
draw_package(pkg, row) }
# if filters_changed(filters):
# self.log.debug("Re-executing filters")
# wm['package_displayed_packages'] = filtered(filters, repo['packages'])
filtered_packages = filtered(filters, repo['packages'])
# for key, item in filters.items():
# wm['package_last_used_filters'][key] = item
for pkg in filtered_packages:
row = pkgzone.row()
draw_package(pkg, row)
class WM_OT_package_toggle_expand(bpy.types.Operator): class WM_OT_package_toggle_expand(bpy.types.Operator):
@@ -623,6 +667,8 @@ def register():
name="Install filter", name="Install filter",
default='AVAILABLE', default='AVAILABLE',
) )
# bpy.types.WindowManager.package_last_used_filters = dict()
# bpy.types.WindowManager.package_displayed_packages = []
bpy.utils.register_class(PackageManagerPreferences) bpy.utils.register_class(PackageManagerPreferences)
@@ -635,4 +681,6 @@ def unregister():
bpy.utils.unregister_class(WM_OT_package_toggle_expand) bpy.utils.unregister_class(WM_OT_package_toggle_expand)
del bpy.types.WindowManager.package_search del bpy.types.WindowManager.package_search
del bpy.types.WindowManager.package_install_filter del bpy.types.WindowManager.package_install_filter
# del bpy.types.WindowManager.package_displayed_packages
# del bpy.types.WindowManager.package_last_used_filters
bpy.utils.unregister_class(PackageManagerPreferences) bpy.utils.unregister_class(PackageManagerPreferences)