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')
|
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)
|
||||||
|
Reference in New Issue
Block a user