"""
-class SortLabelItem(GObject.GObject):
- """Sort order list representation of sorter label."""
+class Sorter(GObject.GObject):
+ """Sort order box representation of sorting attribute."""
+ list_item: Gtk.Box
def __init__(self, name):
super().__init__()
self.name = name
+ def set_label(self, gallery_store, gallery_store_filtered):
+ """Set .list_item's label to .name and n of different values for it."""
+ diversities = [0, 0]
+ for i, store in enumerate([gallery_store_filtered, gallery_store]):
+ values = set()
+ for j in range(store.get_n_items()):
+ item = store.get_item(j)
+ if isinstance(item, ImgItem):
+ val = None
+ if hasattr(item, self.name):
+ val = getattr(item, self.name)
+ values.add(val)
+ diversities[i] = len(values)
+ label = f'{self.name} ({diversities[0]}/{diversities[1]}) '
+ self.list_item.get_first_child().set_text(label)
+
class FileItem(GObject.GObject):
"""Gallery representation of filesystem entry, base to DirItem, ImgItem."""
filter_inputs = dict
button_activate_sort: Gtk.Button
counter: Gtk.Label
- sort_attribute_diversities: dict
def __init__(self, app, **kwargs):
super().__init__(**kwargs)
return metadata_box
def init_sorter_and_filterer():
- self.sort_order = [p.lower() for p in GEN_PARAMS]
- self.sort_order += ['bookmarked']
- new_sort_order = []
- do_reverse = '-' in self.app.suggested_sort_order
- for pattern in self.app.suggested_sort_order:
- for name in [n for n in self.sort_order
- if n.startswith(pattern)]:
- self.sort_order.remove(name)
- new_sort_order += [name]
- self.sort_order = new_sort_order + self.sort_order
- if do_reverse:
- self.sort_order.reverse()
- self.sort_store = Gio.ListStore(item_type=SortLabelItem)
+ self.sort_store = Gio.ListStore(item_type=Sorter)
self.sort_selection = Gtk.SingleSelection.new(self.sort_store)
self.sort_selection.connect(
'selection-changed',
- lambda a, b, c: self.sort_selection.props.selected_item.box
- .props.child.get_parent().grab_focus())
+ lambda a, b, c: self.sort_selection.props.selected_item.
+ list_item.get_parent().grab_focus())
factory = Gtk.SignalListItemFactory()
- def setup_sort_order_item(_, item):
+ def setup_sort_order_item(_, list_item):
box = Gtk.Box(orientation=OR_H)
box.append(Gtk.Label(hexpand=True))
box.append(Gtk.Entry.new())
box.get_last_child().props.placeholder_text = 'filter?'
- item.set_child(box)
+ list_item.set_child(box)
- def bind_sort_order_item(_, item):
+ def bind_sort_order_item(_, list_item):
def on_filter_enter(entry):
entry.remove_css_class('temp')
text = entry.get_buffer().get_text()
if '' != text.rstrip():
- self.filter_inputs[item.props.item.name] = text
- elif item.props.item.name in self.filter_inputs:
- del self.filter_inputs[item.props.item.name]
+ self.filter_inputs[sorter.name] = text
+ elif sorter.name in self.filter_inputs:
+ del self.filter_inputs[sorter.name]
self.update_gallery()
- item.props.item.box = item
- sorter_name = item.props.item.name
- diversity = self.sort_attribute_diversities.get(sorter_name, 0)
- label = f'{sorter_name} ({diversity}) '
- 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, '')
+ sorter = list_item.props.item
+ sorter.list_item = list_item.props.child
+ sorter.set_label(self.gallery_store,
+ self.gallery_store_filtered)
+ sorter.filterer = sorter.list_item.get_last_child()
+ filter_entry = sorter.list_item.get_last_child()
+ filter_text = self.filter_inputs.get(sorter.name, '')
filter_buffer = filter_entry.get_buffer()
filter_buffer.set_text(filter_text, -1)
filter_entry.connect('activate', on_filter_enter)
'clicked', lambda _: self.activate_sort_order())
sort_box.append(self.button_activate_sort)
self.filter_inputs = {}
- self.sort_attribute_diversities = {}
return sort_box
def init_gallery_content():
json_dump(list(bookmarks), f)
self.update_file_selection()
self.update_gallery_view()
- self.update_sort_order_box(self.sort_order)
+ self.update_sort_order_box()
def update_gallery(self, suggested_selection=None):
"""Build gallery based on .per_row and .gallery_selection."""
return +1
# apply self.sort_order within DirItems and FileItems (separately)
ret = 0
- for key in self.sort_order:
+ for key in [sorter.name for sorter in self.app.sort_order]:
a_cmp = None
b_cmp = None
if hasattr(a, key):
to_select.activate()
else:
self.counter.set_text(' (nothing) ')
- self.update_sort_order_box(self.sort_order)
+ self.update_sort_order_box()
self.update_gallery_view()
def update_gallery_view(self, refocus=False):
total = self.gallery_selection.get_n_items()
self.counter.set_text(f' {idx} of {total} ')
- def update_sort_order_box(self, sort_order_source, cur_selection=0):
- """Rebuild .sort_store from .sort_order, update diversity counts."""
- values = {}
- for k in sort_order_source:
- values[k] = set()
- for i in range(self.gallery_store_filtered.get_n_items()):
- item = self.gallery.get_child_at_index(i).props.child.item
- if isinstance(item, ImgItem):
- for attr_name in values:
- val = None
- if hasattr(item, attr_name):
- val = getattr(item, attr_name)
- values[attr_name].add(val)
- for attr_name in values:
- self.sort_attribute_diversities[attr_name] = len(values[attr_name])
+ def update_sort_order_box(self, alt_order=None, cur_selection=0):
+ """Rebuild .sort_store from .sort_order or alt_order."""
+ sort_order = alt_order if alt_order else self.app.sort_order
self.sort_store.remove_all()
- for s in sort_order_source:
- self.sort_store.append(SortLabelItem(s))
+ for sorter in sort_order:
+ self.sort_store.append(sorter)
self.sort_selection.props.selected = cur_selection
def activate_sort_order(self):
- """Write sort order box order into self.sort_order, mark finalized."""
- self.sort_order = []
+ """Write sort order box order into .app.sort_order, mark finalized."""
+ self.app.sort_order = []
for i in range(self.sort_store.get_n_items()):
- sort_item = self.sort_store.get_item(i)
- sort_item.box.props.child.remove_css_class('temp')
- self.sort_order += [sort_item.name]
+ sorter = self.sort_store.get_item(i)
+ sorter.list_item.remove_css_class('temp')
+ self.app.sort_order += [sorter]
self.button_activate_sort.props.sensitive = False
old_selection = self.gallery_selection.props.selected_item
self.update_gallery(old_selection)
"""Move selected item in sort order view, ensure temporary state."""
tmp_sort_order = []
for i in range(self.sort_store.get_n_items()):
- tmp_sort_order += [self.sort_store.get_item(i).name]
+ tmp_sort_order += [self.sort_store.get_item(i)]
cur_idx = self.sort_selection.props.selected
selected = tmp_sort_order[cur_idx]
if direction == -1 and cur_idx > 0:
self.sort_selection.props.selected = cur_idx + direction
for i in range(self.sort_store.get_n_items()):
sort_item = self.sort_store.get_item(i)
- sort_item.box.props.child.add_css_class('temp')
+ sort_item.list_item.add_css_class('temp')
self.button_activate_sort.props.sensitive = True
def move_selection_in_sort_order(self, direction):
"""Move sort order selection by direction (-1 or +1)."""
- min_idx, max_idx = 0, len(self.sort_order) - 1
+ min_idx, max_idx = 0, len(self.app.sort_order) - 1
cur_idx = self.sort_selection.props.selected
if (1 == direction and cur_idx < max_idx)\
or (-1 == direction and cur_idx > min_idx):
class Application(Gtk.Application):
"""Image browser application class."""
img_dir_absolute: str
- suggested_sort_order: list[str]
+ sort_order: list[Sorter]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ def _build_sort_order(self, suggestion_fused):
+ suggestion = suggestion_fused.split(',')
+ names = [p.lower() for p in GEN_PARAMS] + ['bookmarked']
+ sort_order = []
+ for name in names:
+ sort_order += [Sorter(name)]
+ new_sort_order = []
+ do_reverse = '-' in suggestion
+ for pattern in suggestion:
+ for sorter in [sorter for sorter in sort_order
+ if sorter.name.startswith(pattern)]:
+ sort_order.remove(sorter)
+ new_sort_order += [sorter]
+ sort_order = new_sort_order + sort_order
+ if do_reverse:
+ sort_order.reverse()
+ return sort_order
+
def do_activate(self, *args, **kwargs):
"""Parse arguments, start window, and keep it open."""
parser = ArgumentParser()
parser.add_argument('-s', '--sort-order', default=SORT_DEFAULT)
opts = parser.parse_args()
self.img_dir_absolute = abspath(opts.directory)
- self.suggested_sort_order = opts.sort_order.split(',')
+ self.sort_order = self._build_sort_order(opts.sort_order)
win = MainWindow(self)
win.present()
self.hold()