home · contact · privacy
To Browser, add caching of metadata per file.
authorChristian Heller <c.heller@plomlompom.de>
Fri, 23 Aug 2024 23:36:25 +0000 (01:36 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 23 Aug 2024 23:36:25 +0000 (01:36 +0200)
browser.py

index d6925f6cddfcd542fd894b55681b51959d8b70d6..81b089b8b4874786adc83526a69caf2b88c26358 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/env python3
 from exiftool import ExifToolHelper  # type: ignore
+from json import dump as json_dump, load as json_load
+from os.path import exists as path_exists, join as path_join, abspath
 import gi  # type: ignore
 gi.require_version('Gtk', '4.0')
 gi.require_version('Gio', '2.0')
@@ -8,28 +10,30 @@ from gi.repository import Gtk, Gio, GObject  # type: ignore  # noqa: E402
 from stable.gen_params import GenParams  # noqa: E402
 
 
+IMG_DIR='.'
+
+
 class FileItem(GObject.GObject):
 
-    def __init__(self, name, last_mod):
+    def __init__(self, path, info, cache):
         super().__init__()
-        self.name = name
-        self.last_mod = last_mod
-        self._metadata = None
-
-    @property
-    def metadata(self):
-        if not self._metadata:
-            with ExifToolHelper() as et:
-                for d in et.get_tags([self.name], ['Comment']):
-                    for k, v in d.items():
-                        if k.endswith('Comment'):
-                            self._metadata = ''
-                            gen_params = GenParams.from_str(v)
-                            for k, v_ in gen_params.as_dict.items():
-                                self._metadata += f'\n{k}: {v_}'
-            if not self._metadata:
-                self._metadata = 'no SD comment'
-        return self._metadata
+        self.name = info.get_name()
+        self.last_mod_time = info.get_modification_date_time().format_iso8601()
+        self.full_path = path_join(path, self.name)
+        self.metadata = ''
+        if self.full_path in cache:
+            if self.last_mod_time in cache[self.full_path]:
+                self.metadata = cache[self.full_path][self.last_mod_time]
+
+    def set_metadata(self, et):
+        self.metadata = 'no SD comment'
+        for d in et.get_tags([self.name], ['Comment']):
+            for k, v in d.items():
+                if k.endswith('Comment'):
+                    self.metadata = ''
+                    gen_params = GenParams.from_str(v)
+                    for k, v_ in gen_params.as_dict.items():
+                        self.metadata += f'\n{k}: {v_}'
 
 
 class Window(Gtk.ApplicationWindow):
@@ -54,7 +58,8 @@ class Window(Gtk.ApplicationWindow):
         self.viewer.append(self.metadata)
         self.viewer.append(self.label_nothing_to_show)
 
-        self.dir = Gio.File.new_for_path('.')
+        img_dir_absolute = abspath(IMG_DIR)
+        self.dir = Gio.File.new_for_path(img_dir_absolute)
         self.list_store = Gio.ListStore(item_type=FileItem)
         self.selection = Gtk.SingleSelection.new(self.list_store)
         factory = Gtk.SignalListItemFactory()
@@ -65,6 +70,11 @@ class Window(Gtk.ApplicationWindow):
         box_outer.append(self.viewer)
         self.props.child = box_outer
 
+        if not path_exists('cache.json'):
+            with open('cache.json', 'w') as f:
+                json_dump({}, f)
+        with open('cache.json', 'r') as f:
+            cache = json_load(f)
         self.max_index = 0
         self.item = None
         self.selection.connect('selection-changed', self.update_selected)
@@ -78,14 +88,20 @@ class Window(Gtk.ApplicationWindow):
         to_sort = []
         for info in [info for info in enumerator
                      if info.get_content_type().startswith('image/')]:
-            item = FileItem(info.get_name(),
-                            info.get_modification_date_time().format_iso8601())
+            item = FileItem(img_dir_absolute, info, cache)
             to_sort += [item]
-        to_sort.sort(key=lambda i: i.last_mod)
+        with ExifToolHelper() as et:
+            for item in [item for item in to_sort if not item.metadata]:
+                if not item.metadata:
+                    item.set_metadata(et)
+                    cache[item.full_path] = {item.last_mod_time: item.metadata}
+        to_sort.sort(key=lambda i: i.last_mod_time)
         for file_item in to_sort:
             self.list_store.append(file_item)
         self.max_index = len(self.list_store) - 1
         self.update_selected()
+        with open('cache.json', 'w') as f:
+            json_dump(cache, f)
 
     def update_selected(self, *_args):
         self.item = self.selection.props.selected_item
@@ -96,7 +112,7 @@ class Window(Gtk.ApplicationWindow):
     def reload(self):
         self.viewer.remove(self.viewer.get_last_child())
         if self.item:
-            metadata = f'{self.item.name}: {self.item.metadata}'
+            metadata = f'{self.item.full_path}: {self.item.metadata}'
             self.metadata.props.label = metadata
             pic = Gtk.Picture.new_for_filename(self.item.name)
             self.viewer.append(pic)