home · contact · privacy
Re-design sort order selection.
authorChristian Heller <c.heller@plomlompom.de>
Tue, 27 Aug 2024 11:49:55 +0000 (13:49 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 27 Aug 2024 11:49:55 +0000 (13:49 +0200)
browser.py

index 081829700bdb1fcda26bee37defe0de139932a0e..266a620d1729b004f2d85569f757b468113d7eca 100755 (executable)
@@ -19,6 +19,13 @@ CACHE_PATH = 'cache.json'
 SORT_KEY_RANDOM = 'randomize'
 
 
+class SortLabelItem(GObject.GObject):
+
+    def __init__(self, name):
+        super().__init__()
+        self.name = name
+
+
 class FileItem(GObject.GObject):
 
     def __init__(self, path, info):
@@ -107,6 +114,14 @@ class Window(Gtk.ApplicationWindow):
                                       propagate_natural_width=True)
         self.dir_box.append(scrolled)
 
+        self.dir_box.append(Gtk.Label(label='** sort order **'))
+        self.sort_order = [p.lower() for p in GEN_PARAMS]
+        self.sort_order += ['last_mod_time', 'name']
+        self.sort_store = Gio.ListStore(item_type=SortLabelItem)
+        self.sort_selection = Gtk.SingleSelection.new(self.sort_store)
+        selector = Gtk.ListView(model=self.sort_selection, factory=factory)
+        self.dir_box.append(selector)
+
         box_outer = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
         box_outer.append(self.dir_box)
         box_outer.append(self.viewer)
@@ -114,41 +129,9 @@ class Window(Gtk.ApplicationWindow):
 
         self.item_img, self.item_dir = None, None
         self.unsorted_dirs, self.unsorted_files = [], []
-        self.sort_order = []
         self.img_dir_absolute = abspath(IMG_DIR)
         self.reload_dir()
-        self.add_sort('last_mod_time')
-
-    def add_sort(self, sort_key):
-        if SORT_KEY_RANDOM == sort_key:
-            self.sort_order = []
-        elif sort_key in self.sort_order:
-            self.sort_order.remove(sort_key)
-        self.sort_order += [sort_key]
-        while self.box_sort_order.get_last_child():
-            self.box_sort_order.remove(self.box_sort_order.get_last_child())
-        self.box_sort_order.append(Gtk.Label(label='sort order: '))
-        for key in self.sort_order:
-            old_sorter = Gtk.Box()
-            old_sorter.append(Gtk.Label(label=f'[{key}] -> '))
-            self.box_sort_order.append(old_sorter)
-
-        def add_sorter(sort_key_, group):
-            radio = Gtk.CheckButton(label=sort_key_, group=group)
-            radio.connect('toggled', lambda _: self.add_sort(sort_key_))
-            vbox.append(radio)
-            return radio
-
-        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-        popover_menu = Gtk.Popover()
-        sorter = Gtk.MenuButton(label='next?', popover=popover_menu)
-        radio1 = add_sorter('last_mod_time', None)
-        for name in ['name'] + list(GEN_PARAMS):
-            add_sorter(name.lower(), radio1)
-        add_sorter(SORT_KEY_RANDOM, radio1)
-        popover_menu.props.child = vbox
-        self.box_sort_order.append(sorter)
-        self.sort()
+        self.update_sort_list()
 
     def on_selector_activate(self, _, __):
         if isinstance(self.selection.props.selected_item, DirItem):
@@ -209,20 +192,6 @@ class Window(Gtk.ApplicationWindow):
             self.metadata.props.label = None
             self.viewer.append(self.label_nothing_to_show)
 
-    def move_selection(self, increment, absolute_position):
-        cur_index = self.selection.props.selected
-        if len(self.unsorted_files) > 2:
-            self.min_index = len(self.unsorted_dirs) + 1
-        else:
-            self.min_index = 0
-        if 0 == absolute_position:
-            self.selection.props.selected = self.min_index
-        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 > self.min_index):
-            self.selection.props.selected = cur_index + increment
-
     def reload_dir(self):
         self.dir = Gio.File.new_for_path(self.img_dir_absolute)
         old_dir_path = self.item_dir.full_path if self.item_dir else ''
@@ -232,7 +201,6 @@ class Window(Gtk.ApplicationWindow):
                 json_dump({}, f)
         with open(CACHE_PATH, 'r', encoding='utf8') as f:
             cache = json_load(f)
-        self.max_index = 0
         query_attrs = 'standard::name,standard::type,time::*'
         self.item_img, self.item_dir = None, None
         parent_path = abspath(path_join(self.img_dir_absolute, '..'))
@@ -264,20 +232,75 @@ class Window(Gtk.ApplicationWindow):
             for item in [item for item
                          in self.unsorted_files if '' == item.model]:
                 item.set_metadata(et, cache)
-        self.max_index = len(self.unsorted_files + self.unsorted_dirs)
         self.sort()
         with open(CACHE_PATH, 'w', encoding='utf8') as f:
             json_dump(cache, f)
 
-    def handle_keypress(self, _keyval, keycode, _state, _user_data, _win):
+    def move_selection_in_sort_order(self, direction):
+        self.move_selection(self.sort_selection, direction, None,
+                            0, len(self.sort_order) - 1)
+
+    def move_selection_in_directory(self, direction, absolute_position):
+        max_index = len(self.unsorted_files + self.unsorted_dirs)
+        if len(self.unsorted_files) > 2:
+            min_index = len(self.unsorted_dirs) + 1
+        else:
+            min_index = 0
+        self.move_selection(self.selection, direction, absolute_position,
+                            min_index, max_index)
+
+    def move_selection(self, selection, increment, absolute_position,
+                       min_index, max_index):
+        cur_index = selection.props.selected
+        if 0 == absolute_position:
+            selection.props.selected = min_index
+        elif -1 == absolute_position:
+            selection.props.selected = max_index
+        elif (1 == increment and cur_index < max_index)\
+                or (-1 == increment and cur_index > min_index):
+            selection.props.selected = cur_index + increment
+
+    def move_sort(self, direction):
+        current_i = self.sort_selection.props.selected
+        selected = self.sort_order[current_i]
+        if direction == -1 and current_i > 0:
+            prev_i = current_i - 1
+            old_prev = self.sort_order[prev_i]
+            self.sort_order[prev_i] = selected
+            self.sort_order[current_i] = old_prev
+        elif direction == 1 and current_i < (len(self.sort_order) - 1):
+            next_i = current_i + 1
+            old_next = self.sort_order[next_i]
+            self.sort_order[next_i] = selected
+            self.sort_order[current_i] = old_next
+        else:
+            return
+        self.update_sort_list(current_i + direction)
+
+    def update_sort_list(self, start_position=0):
+        self.sort_store.remove_all()
+        for s in self.sort_order:
+            self.sort_store.append(SortLabelItem(s))
+        self.sort_selection.props.selected = start_position
+        self.sort()
+
+    def handle_keypress(self, _keyval, keycode, state, _user_data, _win):
         if ord('G') == keycode:
-            self.move_selection(None, -1)
+            self.move_selection_in_directory(None, -1)
         elif ord('j') == keycode:
-            self.move_selection(1, None)
+            self.move_selection_in_directory(1, None)
         elif ord('k') == keycode:
-            self.move_selection(-1, None)
+            self.move_selection_in_directory(-1, None)
         elif ord('g') == keycode and 'g' == self.prev_key[0]:
-            self.move_selection(None, 0)
+            self.move_selection_in_directory(None, 0)
+        elif ord('n') == keycode:
+            self.move_selection_in_sort_order(-1)
+        elif ord('N') == keycode:
+            self.move_sort(-1)
+        elif ord('m') == keycode:
+            self.move_selection_in_sort_order(1)
+        elif ord('M') == keycode:
+            self.move_sort(1)
         else:
             self.prev_key[0] = chr(keycode)