aboutsummaryrefslogtreecommitdiffstats
path: root/tagit
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-02-17 08:29:26 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-02-17 08:29:26 +0100
commit906076a24fd3baca68e0381aca1953a05f5b45b7 (patch)
treedca85ff7f5f3357cdab4c51860ac5e0261d91b5d /tagit
parent580caf6f5c9b795f9c38b9c970efce12d006ce1d (diff)
downloadtagit-906076a24fd3baca68e0381aca1953a05f5b45b7.tar.gz
tagit-906076a24fd3baca68e0381aca1953a05f5b45b7.tar.bz2
tagit-906076a24fd3baca68e0381aca1953a05f5b45b7.zip
Fixes:
* Preview loading in browser * Search via bsfs.Graph.sorted to preserve order * Fixes in parsing.filter.to_string
Diffstat (limited to 'tagit')
-rw-r--r--tagit/actions/search.py2
-rw-r--r--tagit/parsing/filter/to_string.py4
-rw-r--r--tagit/widgets/browser.py78
3 files changed, 48 insertions, 36 deletions
diff --git a/tagit/actions/search.py b/tagit/actions/search.py
index ca36a51..630413f 100644
--- a/tagit/actions/search.py
+++ b/tagit/actions/search.py
@@ -128,7 +128,7 @@ class Search(Action, StorageAwareMixin, ConfigAwareMixin):
items = Cache.get(self._CACHE_CATEGORY, (query, sort), None)
if items is None:
# FIXME: mb/port: consider sort
- items = list(session.storage.get(ns.bsfs.File, query))
+ items = list(session.storage.sorted(ns.bsfs.File, query))
Cache.append(self._CACHE_CATEGORY, (query, sort), items)
# apply search order because it's cheaper to do it here rather
diff --git a/tagit/parsing/filter/to_string.py b/tagit/parsing/filter/to_string.py
index 0b1a3e1..a2815de 100644
--- a/tagit/parsing/filter/to_string.py
+++ b/tagit/parsing/filter/to_string.py
@@ -206,10 +206,10 @@ class ToString():
guids = {guid for sub in query for guid in get_guids(sub.value) }
elif self.matches(query, ast.filter.Not(matcher.Partial(ast.filter.Is))):
negated = True
- guids = get_guids(query.value)
+ guids = get_guids(query.expr.value)
elif self.matches(query, ast.filter.Not(ast.filter.Or(matcher.Rest(matcher.Partial(ast.filter.Is))))):
negated = True
- guids = {guid for sub in query for guid in get_guids(sub.value) }
+ guids = {guid for sub in query.expr for guid in get_guids(sub.value) }
if len(guids) == 0:
# no matches
diff --git a/tagit/widgets/browser.py b/tagit/widgets/browser.py
index bbc3748..28f7440 100644
--- a/tagit/widgets/browser.py
+++ b/tagit/widgets/browser.py
@@ -394,18 +394,30 @@ class Browser(GridLayout, StorageAwareMixin, ConfigAwareMixin):
if len(items) == 0: # FIXME: mb/port
return
+ resolution = self._cell_resolution()
+ previews = self._fetch_previews(items, resolution)
+ default = resource_find('no_preview.png')
+ for ent, child in zip(reversed(items), childs):
+ if ent in previews:
+ buf = previews[ent]
+ else:
+ buf = open(default, 'rb')
+ child.update(ent, buf, f'{ent}x{resolution}')
+
+ def _fetch_previews(self, items, resolution):
+ """Fetch previews matching *resolution* for *items*.
+ Return a dict with items as key and a BytesIO as value.
+ Items without valid asset are omitted from the dict.
+ """
# fetch previews
node_preview = reduce(operator.add, items).get(ns.bse.preview, node=True)
previews = {p for previews in node_preview.values() for p in previews}
- previews = reduce(operator.add, previews)
+ previews = reduce(operator.add, previews) # FIXME: empty previews
# fetch preview resolutions
res_preview = previews.get(ns.bsp.width, ns.bsp.height, node=True)
- # get target resolution
- resolution = self._cell_resolution()
- # get default preview
- default = resource_find('no_preview.png')
# select a preview for each item
- for ent, child in zip(reversed(items), childs):
+ chosen = {}
+ for ent in items:
try:
# get previews and their resolution for this ent
options = []
@@ -416,19 +428,21 @@ class Browser(GridLayout, StorageAwareMixin, ConfigAwareMixin):
height = res.get(ns.bsp.height, 0)
options.append((preview, Resolution(width, height)))
# select the best fitting preview
- chosen = rmatcher.by_area_min(resolution, options)
- # open the preview file, default if no asset is available
- thumb_data = chosen.asset(default=None) # FIXME: get all assets in one call
- if thumb_data is None:
- raise KeyError()
- thumb = io.BytesIO(thumb_data)
-
+ chosen[ent] = rmatcher.by_area_min(resolution, options)
except (KeyError, IndexError):
- # KeyError:
- # no viable resolution found
- thumb = open(default, 'rb')
- # update the image in the child widget
- child.update(ent, thumb, f'{ent}x{resolution}')
+ # skip objects w/o preview (KeyError in node_preview)
+ # skip objects w/o valid preview (IndexError in rmatcher)
+ pass
+
+ # fetch assets
+ assets = reduce(operator.add, chosen.values()).asset(node=True) # FIXME: empty chosen
+ # build ent -> asset mapping and convert raw data to io buffer
+ return {
+ ent: io.BytesIO(assets[thumb])
+ for ent, thumb
+ in chosen.items()
+ if thumb in assets
+ }
#def _preload_all(self):
# # prefer loading from start to end
@@ -436,26 +450,24 @@ class Browser(GridLayout, StorageAwareMixin, ConfigAwareMixin):
def _preload_items(self, items, resolution=None):
"""Load an item into the kivy *Cache* without displaying the image anywhere."""
- resolution = resolution if resolution is not None else self._cell_resolution()
-
def _buf_loader(buffer, fname):
# helper method to load the image from a raw buffer
with buffer as buf:
return ImageLoaderTagit(filename=fname, inline=True, rawdata=buf)
- for obj in items:
- try:
- buffer = obj.get('preview').best_match(resolution)
- source = f'{obj.guid}x{resolution}'
-
- Loader.image(source,
- nocache=False, mipmap=False,
- anim_delay=0,
- load_callback=partial(_buf_loader, buffer) # mb: pass load_callback
- )
-
- except PredicateNotSet:
- pass
+ resolution = resolution if resolution is not None else self._cell_resolution()
+ try:
+ foo = self._fetch_previews(items, resolution) # FIXME: _fetch_previews fails on empty previews/chosen
+ except TypeError:
+ return
+ for obj, buffer in foo.items():
+ guid = ','.join(obj.guids)
+ source = f'{guid}x{resolution}'
+ Loader.image(source,
+ nocache=False, mipmap=False,
+ anim_delay=0,
+ load_callback=partial(_buf_loader, buffer) # mb: pass load_callback
+ )
class BrowserAwareMixin(object):