UI: Replace list of workspace add-ons with a UIList #112684

Manually merged
Campbell Barton merged 6 commits from guishe/blender:workspace-addons into main 2024-01-22 03:35:06 +01:00
1 changed files with 15 additions and 13 deletions
Showing only changes of commit 3ea258d73f - Show all commits

View File

@ -68,7 +68,8 @@ class WORKSPACE_PT_addons(WorkSpaceButtonsPanel, Panel):
"addons",
context.workspace,
"active_addon",
rows=8)
rows=8,
guishe marked this conversation as resolved Outdated

*picky* use , & newline for trailing parenthesis.

\*picky\* use `,` & newline for trailing parenthesis.
)
# Detect unused
if unknown_addons:
layout.label(text="Unknown add-ons", icon='ERROR')
@ -92,37 +93,38 @@ def addon_category_name(addon):
class WORKSPACE_UL_addons_items(bpy.types.UIList):
@classmethod
def filter_addons_by_category_name(cls, pattern, bitflag, addons, reverse=False):
@staticmethod
guishe marked this conversation as resolved Outdated

Can be a static method using a _ prefix as it's for internal use only.

Can be a static method using a `_` prefix as it's for internal use only.
def _filter_addons_by_category_name(pattern, bitflag, addons, reverse=False):
"""
Set FILTER_ITEM for addons which category and name matches filter_name one (case-insensitive).
pattern is the filtering pattern.
return a list of flags based on given bit flag, or an empty list if no pattern is given
or list addons is empty.
"""
import fnmatch
if not pattern or not addons: # Empty pattern or list = no filtering!
return []
import fnmatch
import re

Compile the pattern for faster evaluation, since it doesn't need to compile the expression for every match.

pattern_re = re.compile(fnmatch.translate("*" + pattern.strip("*") + "*"))
...
if pattern_re.match(name): ...

Noticed Blender's UI logic also did this, updated: b177f27e6f

Compile the pattern for faster evaluation, since it doesn't need to compile the expression for every match. ``` pattern_re = re.compile(fnmatch.translate("*" + pattern.strip("*") + "*")) ... if pattern_re.match(name): ... ``` ---- Noticed Blender's UI logic also did this, updated: b177f27e6f50bd1ffa4f5ee7dd13f1ee5ce60021

I added re.IGNORECASE to re.compile(...,re.IGNORECASE), most UIList are case-insensitive and without that feels wrong

I added `re.IGNORECASE` to `re.compile(...,re.IGNORECASE)`, most UIList are case-insensitive and without that feels wrong
# Implicitly add heading/trailing wildcards.
pattern = "*" + pattern + "*"
pattern_regex = re.compile(fnmatch.translate("*" + pattern + "*"), re.IGNORECASE)
flags = [0] * len(addons)
guishe marked this conversation as resolved
Review

End sentences with a full-stop.

End sentences with a full-stop.
for i, addon in enumerate(addons):
guishe marked this conversation as resolved
Review

no need for bool(reverse), can be reverse.

no need for `bool(reverse)`, can be `reverse`.
name = addon_category_name(addon)
# This is similar to a logical xor
if bool(name and fnmatch.fnmatch(name, pattern)) is not bool(reverse):
# This is similar to a logical XOR.
if bool(name and pattern_regex.match(name)) is not reverse:
flags[i] |= bitflag
return flags
guishe marked this conversation as resolved Outdated
  • As this is an internal method use _ prefix.
  • Since cls isn't used this can be a staticmethod.
- As this is an internal method use `_` prefix. - Since `cls` isn't used this can be a `staticmethod`.
@classmethod
def sort_addons_by_category_name(cls, addons):
@staticmethod
def _sort_addons_by_category_name(addons):
"""
guishe marked this conversation as resolved Outdated

odd indentation, can be wrapped onto the previous line.

odd indentation, can be wrapped onto the previous line.
Re-order addons using their categories and names (case-insensitive).
return a list mapping org_idx -> new_idx,
or an empty list if no sorting has been done.
return a list mapping org_idx -> new_idx, or an empty list if no sorting has been done.
"""
_sort = [(idx, addon_category_name(addon)) for idx, addon in enumerate(addons)]
return bpy.types.UI_UL_list.sort_items_helper(_sort, lambda e: e[1].lower())
@ -134,7 +136,7 @@ class WORKSPACE_UL_addons_items(bpy.types.UIList):
# Filtering by category and name
if self.filter_name:
flags = self.filter_addons_by_category_name(
flags = self._filter_addons_by_category_name(
self.filter_name, self.bitflag_filter_item, addons, reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(addons)
@ -143,7 +145,7 @@ class WORKSPACE_UL_addons_items(bpy.types.UIList):
if not WORKSPACE_PT_addons.addon_map.get(addon.module):
flags[idx] = 0
if self.use_filter_sort_alpha:
indices = self.sort_addons_by_category_name(addons)
indices = self._sort_addons_by_category_name(addons)
return flags, indices
def draw_item(self, context, layout, _data, addon, icon, _active_data, _active_propname, _index):