Better sorting of search results
This commit is contained in:
104
bpkg/__init__.py
104
bpkg/__init__.py
@@ -402,8 +402,17 @@ class USERPREF_PT_packages(bpy.types.Panel):
|
||||
return (userpref.active_section == 'PACKAGES')
|
||||
|
||||
def draw(self, context):
|
||||
|
||||
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()
|
||||
spl = main.split(.12)
|
||||
@@ -411,42 +420,66 @@ class USERPREF_PT_packages(bpy.types.Panel):
|
||||
pkgzone = spl.column()
|
||||
|
||||
sidebar.label(text="Category")
|
||||
sidebar.prop(context.window_manager, "addon_filter", text="")
|
||||
sidebar.prop(wm, "addon_filter", text="")
|
||||
|
||||
top = pkgzone.row()
|
||||
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.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
|
||||
#Also some caching of this would be nice, this only needs to be re-run when any of the filters change.
|
||||
def filter_package(package):# {{{
|
||||
"""Returns true if the given package matches all filters"""
|
||||
filterstr = bpy.context.window_manager.package_search
|
||||
category = bpy.context.window_manager.addon_filter
|
||||
blinfo = package['bl_info']
|
||||
#TODO: if filters are only added to, we can filter on existing filtered list rather than redoing whole list
|
||||
# def filters_changed(filters: dict) -> bool:
|
||||
# if filters['search'] != wm['package_last_used_filters'].get('search'):
|
||||
# return True
|
||||
# if filters['category'] != wm['package_last_used_filters'].get('category'):
|
||||
# return True
|
||||
# return False
|
||||
|
||||
def match_search() -> bool:
|
||||
if len(filterstr) == 0:
|
||||
return True
|
||||
if blinfo['name'].lower().__contains__(filterstr.lower()):
|
||||
def filtered(filters: dict, packages: list) -> list:
|
||||
"""Returns filtered and sorted list of packages which match filters defined in dict"""
|
||||
|
||||
#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 False
|
||||
|
||||
def match_category() -> bool:
|
||||
if category.upper() == 'ALL':
|
||||
def match_startswith(blinfo) -> bool:
|
||||
if blinfo['name'].lower().startswith(filters['search'].lower()):
|
||||
return True
|
||||
return False
|
||||
|
||||
def match_category(blinfo) -> bool:
|
||||
if filters['category'].lower() == 'all':
|
||||
return True
|
||||
if 'category' not in blinfo:
|
||||
return True
|
||||
if blinfo['category'].upper() == category.upper():
|
||||
return False
|
||||
if blinfo['category'].lower() == filters['category'].lower():
|
||||
return True
|
||||
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):# {{{
|
||||
"""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
|
||||
repo = context.user_preferences.addons[__package__].preferences['repo']
|
||||
except KeyError:
|
||||
center_message("Loading Repositories...")
|
||||
center_message(pkgzone, "Loading Repositories...")
|
||||
|
||||
import pathlib
|
||||
# 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
|
||||
|
||||
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
|
||||
|
||||
|
||||
for pkg in repo['packages']:
|
||||
if filter_package(pkg):
|
||||
row = pkgzone.row()
|
||||
draw_package(pkg, row)
|
||||
filters = {
|
||||
'category': bpy.context.window_manager.addon_filter,
|
||||
'search': bpy.context.window_manager.package_search,
|
||||
}
|
||||
# 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):
|
||||
@@ -623,6 +667,8 @@ def register():
|
||||
name="Install filter",
|
||||
default='AVAILABLE',
|
||||
)
|
||||
# bpy.types.WindowManager.package_last_used_filters = dict()
|
||||
# bpy.types.WindowManager.package_displayed_packages = []
|
||||
bpy.utils.register_class(PackageManagerPreferences)
|
||||
|
||||
|
||||
@@ -635,4 +681,6 @@ def unregister():
|
||||
bpy.utils.unregister_class(WM_OT_package_toggle_expand)
|
||||
del bpy.types.WindowManager.package_search
|
||||
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)
|
||||
|
Reference in New Issue
Block a user