from gi.repository import Gdk, Gtk, Gio # type: ignore # noqa: E402
from gi.repository import GObject, GLib # type: ignore # noqa: E402
# pylint: disable=no-name-in-module
-from stable.gen_params import (GenParams, # noqa: E402
- GEN_PARAMS, GEN_PARAMS_STR) # noqa: E402
+from stable.gen_params import (GenParams, GEN_PARAMS_FLOAT, # noqa: E402
+ GEN_PARAMS_INT, GEN_PARAMS_STR, # noqa: E402
+ GEN_PARAMS) # noqa: E402
IMG_DIR_DEFAULT = '.'
SORT_DEFAULT = 'guidance,n_steps,model,scheduler,prompt,seed,height,width'
sort_store: Gtk.ListStore
sort_selection: Gtk.SingleSelection
prev_key: list
+ filter_inputs = dict
def __init__(self, app, **kwargs):
super().__init__(**kwargs)
metadata_box.append(text_view)
return metadata_box
- def init_sort_orderer():
+ def init_sorter_and_filterer():
self.sort_order = [p.lower() for p in GEN_PARAMS]
new_sort_order = []
do_reverse = '-' in self.app.suggested_sort_order
self.sort_store = Gio.ListStore(item_type=SortLabelItem)
self.sort_selection = Gtk.SingleSelection.new(self.sort_store)
factory = Gtk.SignalListItemFactory()
- factory.connect('setup',
- lambda _, i: i.set_child(Gtk.Label(xalign=0)))
- factory.connect(
- 'bind',
- lambda _, i: i.props.child.set_text(i.props.item.name))
+
+ def setup_sort_order_item(_, item):
+ box = Gtk.Box(orientation=OR_H, halign=Gtk.Align.END)
+ box.append(Gtk.Label(hexpand=True))
+ box.append(Gtk.Entry.new())
+ box.get_last_child().props.placeholder_text = 'filter?'
+ item.set_child(box)
+
+ def bind_sort_order_item(_, item):
+
+ def on_filter_enter(entry):
+ text = entry.get_buffer().get_text()
+ if '' != text.rstrip():
+ self.filter_inputs[item.props.item.name] = text
+ else:
+ del self.filter_inputs[item.props.item.name]
+ self.update_gallery()
+
+ label = f'{item.props.item.name} '
+ item.props.item.filterer = item.props.child.get_last_child()
+ item.props.child.get_first_child().set_text(label)
+ filter_entry = item.props.child.get_last_child()
+ filter_text = self.filter_inputs.get(item.props.item.name, '')
+ filter_entry.get_buffer().set_text(filter_text, -1)
+ filter_entry.connect('activate', on_filter_enter)
+
+ factory.connect('setup', setup_sort_order_item)
+ factory.connect('bind', bind_sort_order_item)
selector = Gtk.ListView(model=self.sort_selection, factory=factory)
sort_box = Gtk.Box(orientation=OR_V)
sort_box.append(Gtk.Label(label='** sort order **'))
sort_box.append(selector)
+ self.filter_inputs = {}
return sort_box
def init_gallery_content():
self.gallery_store = Gio.ListStore(item_type=FileItem)
- list_filter = Gtk.CustomFilter.new(
- lambda x: self.include_dirs or isinstance(x, ImgItem))
+ list_filter = Gtk.CustomFilter.new(self.gallery_filter)
self.gallery_store_filtered = Gtk.FilterListModel(
model=self.gallery_store, filter=list_filter)
self.gallery_selection = Gtk.SingleSelection.new(
viewer.append(self.navbar)
viewer.append(init_gallery_widgets())
self.side_box = Gtk.Box(orientation=OR_V)
- self.side_box.append(init_sort_orderer())
+ self.side_box.append(init_sorter_and_filterer())
self.side_box.append(init_metadata_box())
box_outer = Gtk.Box(orientation=OR_H)
box_outer.append(self.side_box)
# navbar callables
+ def gallery_filter(self, item):
+ """Apply user-set filters to gallery."""
+
+ def number_filter(attr_name, filter_line, to_compare):
+ use_float = attr_name in GEN_PARAMS_FLOAT
+ constraint_strings = filter_line.split(',')
+ numbers_or = set()
+ unequal = set()
+ less_than = None
+ less_or_equal = None
+ more_or_equal = None
+ more_than = None
+ for constraint_string in constraint_strings:
+ toks = constraint_string.split()
+ if len(toks) == 1:
+ value = float(toks[0]) if use_float else int(toks[0])
+ numbers_or.add(value)
+ elif len(toks) == 2:
+ value = float(toks[1]) if use_float else int(toks[1])
+ if toks[0] == '!=':
+ unequal.add(value)
+ elif toks[0] == '<':
+ if less_than is None or less_than >= value:
+ less_than = value
+ elif toks[0] == '<=':
+ if less_or_equal is None or less_or_equal > value:
+ less_or_equal = value
+ elif toks[0] == '>=':
+ if more_or_equal is None or more_or_equal < value:
+ more_or_equal = value
+ elif toks[0] == '>':
+ if more_than is None or more_than <= value:
+ more_than = value
+ if to_compare in numbers_or:
+ print("return TRUE")
+ return True
+ if len(numbers_or) > 0 and (less_than == less_or_equal ==
+ more_or_equal == more_than):
+ return False
+ if to_compare in unequal:
+ return False
+ if (less_than is not None
+ and to_compare >= less_than)\
+ or (less_or_equal is not None
+ and to_compare > less_or_equal)\
+ or (more_or_equal is not None
+ and to_compare < more_or_equal)\
+ or (more_than is not None
+ and to_compare <= more_than):
+ return False
+ return True
+
+ if not self.include_dirs and isinstance(item, DirItem):
+ return False
+ for filter_attribute, value in self.filter_inputs.items():
+ if not hasattr(item, filter_attribute):
+ return False
+ to_compare = getattr(item, filter_attribute)
+ number_attributes = set(GEN_PARAMS_INT) | set(GEN_PARAMS_FLOAT)
+ if filter_attribute.upper() in number_attributes:
+ if not number_filter(filter_attribute, value, to_compare):
+ return False
+ elif value not in to_compare:
+ return False
+ return True
+
def load_directory(self, update_gallery=True):
"""Load into gallery directory at .app.img_dir_absolute."""
self.hit_file_selection()
def handle_keypress(self, keyval):
- """Handle keys, and if, return True to declare key handling done."""
+ """Handle keys if not in Entry, return True if key handling done."""
+ if isinstance(self.get_focus().get_parent(), Gtk.Entry):
+ return False
if Gdk.KEY_G == keyval:
self.move_selection_in_gallery(None, None, 1)
elif Gdk.KEY_h == keyval: