#!/usr/bin/env python3
-from os import scandir
-from os.path import splitext
from exiftool import ExifToolHelper # type: ignore
import gi # type: ignore
gi.require_version('Gtk', '4.0')
+gi.require_version('Gio', '2.0')
# pylint: disable=wrong-import-position
-from gi.repository import Gtk # type: ignore # noqa: E402
+from gi.repository import Gtk, Gio, GObject # type: ignore # noqa: E402
from stable.gen_params import GenParams # noqa: E402
+class FileItem(GObject.GObject):
+
+ def __init__(self, name, last_mod):
+ 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
+
+
class Window(Gtk.ApplicationWindow):
def __init__(self, **kwargs):
super().__init__(**kwargs)
box_buttons = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
- btn_close = Gtk.Button(label='close')
- btn_close.connect('clicked', lambda _: self.close())
- box_buttons.append(btn_close)
- btn = Gtk.Button(label='oldest')
- btn.connect('clicked', self.oldest)
- box_buttons.append(btn)
- btn = Gtk.Button(label='older')
- btn.connect('clicked', self.older)
- box_buttons.append(btn)
- btn = Gtk.Button(label='newer')
- btn.connect('clicked', self.newer)
- box_buttons.append(btn)
- btn = Gtk.Button(label='newest')
- btn.connect('clicked', self.newest)
- box_buttons.append(btn)
+ for args in (('oldest', lambda _: self.move_selection(None, 0)),
+ ('older', lambda _: self.move_selection(-1, None)),
+ ('newer', lambda _: self.move_selection(1, None)),
+ ('newest', lambda _: self.move_selection(None, -1))):
+ btn = Gtk.Button(label=args[0])
+ btn.connect('clicked', args[1])
+ box_buttons.append(btn)
self.metadata = Gtk.Label()
self.label_nothing_to_show = Gtk.Label(label='nothing to show')
- self.box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
- self.box_outer.append(box_buttons)
- self.box_outer.append(self.metadata)
- self.box_outer.append(self.label_nothing_to_show)
- self.props.child = self.box_outer
-
- self.entries = []
- self.current_index = -1
- self.newest(None)
-
- def _reload(self, set_max=False):
- self.entries = [e for e in scandir('.')
- if e.is_file()
- and splitext(e)[1] in {'.png', '.jpg', '.jpeg'}]
- self.entries.sort(key=lambda e: e.stat().st_mtime)
- if set_max or self.current_index + 1 > len(self.entries):
- self.current_index = len(self.entries) - 1
- self.box_outer.remove(self.box_outer.get_last_child())
- if self.current_index >= 0:
- path = self.entries[self.current_index].path
- metadata = 'no SD comment'
- with ExifToolHelper() as et:
- for d in et.get_tags([path], ['Comment']):
- for k, v in d.items():
- if k.endswith('Comment'):
- metadata = ''
- gen_params = GenParams.from_str(v)
- for k, v_ in gen_params.as_dict.items():
- metadata += f'\n{k}: {v_}'
- self.metadata.props.label = f'{path}: {metadata}'
- pic = Gtk.Picture.new_for_filename(path)
- self.box_outer.append(pic)
+ self.viewer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+ self.viewer.append(box_buttons)
+ self.viewer.append(self.metadata)
+ self.viewer.append(self.label_nothing_to_show)
+
+ self.dir = Gio.File.new_for_path('.')
+ self.list_store = Gio.ListStore(item_type=FileItem)
+ self.selection = Gtk.SingleSelection.new(self.list_store)
+ factory = Gtk.SignalListItemFactory()
+ self.selector = Gtk.ListView(model=self.selection, factory=factory)
+
+ box_outer = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
+ box_outer.append(self.selector)
+ box_outer.append(self.viewer)
+ self.props.child = box_outer
+
+ self.max_index = 0
+ self.item = None
+ self.selection.connect('selection-changed', self.update_selected)
+ factory.connect('setup',
+ lambda _, i: i.set_child(Gtk.Label()))
+ factory.connect('bind',
+ lambda _, i: i.props.child.set_text(i.props.item.name))
+ query_attrs = 'standard::name,standard::content-type,time::*'
+ enumerator = self.dir.enumerate_children(
+ query_attrs, Gio.FileQueryInfoFlags.NONE, None)
+ 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())
+ to_sort += [item]
+ to_sort.sort(key=lambda i: i.last_mod)
+ for file_item in to_sort:
+ self.list_store.append(file_item)
+ self.max_index = len(self.list_store) - 1
+ self.update_selected()
+
+ def update_selected(self, *_args):
+ self.item = self.selection.props.selected_item
+ self.reload()
+ self.selector.scroll_to(self.selection.props.selected,
+ Gtk.ListScrollFlags.NONE, None)
+
+ def reload(self):
+ self.viewer.remove(self.viewer.get_last_child())
+ if self.item:
+ metadata = f'{self.item.name}: {self.item.metadata}'
+ self.metadata.props.label = metadata
+ pic = Gtk.Picture.new_for_filename(self.item.name)
+ self.viewer.append(pic)
else:
self.metadata.props.label = None
- self.box_outer.append(self.label_nothing_to_show)
-
- def oldest(self, _widget):
- self.current_index = 0
- self._reload()
-
- def older(self, _widget):
- if self.current_index > 0:
- self.current_index -= 1
- self._reload()
-
- def newer(self, _widget):
- self.current_index += 1
- self._reload()
-
- def newest(self, _widget):
- self._reload(set_max=True)
+ self.viewer.append(self.label_nothing_to_show)
+
+ def move_selection(self, increment, absolute_position):
+ cur_index = self.selection.props.selected
+ if 0 == absolute_position:
+ self.selection.props.selected = 0
+ elif -1 == absolute_position:
+ self.selection.props.selected = self.max_index
+ elif (1 == increment and cur_index < self.max_index)\
+ or (-1 == increment and cur_index > 0):
+ self.selection.props.selected = cur_index + increment
def on_activate(app_):