home · contact · privacy
Add basic flagging/bookmarking to browser.py.
authorChristian Heller <c.heller@plomlompom.de>
Thu, 12 Sep 2024 15:47:30 +0000 (17:47 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 12 Sep 2024 15:47:30 +0000 (17:47 +0200)
browser.py

index fcb8ad15dfcc336679bbb8b6b8d8816ea56f9b32..905f02b515b39cdb5da1286f73235d31bb240278 100755 (executable)
@@ -17,20 +17,18 @@ from stable.gen_params import (GenParams,  GEN_PARAMS_FLOAT,  # noqa: E402
                                GEN_PARAMS)  # noqa: E402
 
 IMG_DIR_DEFAULT = '.'
-SORT_DEFAULT = 'guidance,n_steps,model,scheduler,prompt,seed,height,width'
+SORT_DEFAULT = 'width,height,bookmarked,scheduler,seed,guidance,n_steps,'\
+        'model,prompt'
 UPPER_DIR = '..'
 CACHE_PATH = 'cache.json'
+BOOKMARKS_PATH = 'bookmarks.json'
 
 OR_H = Gtk.Orientation.HORIZONTAL
 OR_V = Gtk.Orientation.VERTICAL
 
-DEBUGGING_CSS = """
-:focus { outline: none; box-shadow: none; background: blue; }
-flowboxchild:selected { outline: none; box-shadow: none; background: green; }
-flowboxchild:hover{ outline: none; box-shadow: none; background: yellow; }
-flowboxchild:active { outline: none; box-shadow: none; background: red; }
-"""
 CSS = """
+.bookmarked { background: green; }
+.bookmarked:selected { background: #00aaaa; }
 .temp { background: #aaaa00; }
 """
 
@@ -51,6 +49,7 @@ class FileItem(GObject.GObject):
         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.bookmarked = False
 
 
 class DirItem(FileItem):
@@ -167,6 +166,7 @@ class MainWindow(Gtk.Window):
 
         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:
@@ -248,17 +248,26 @@ class MainWindow(Gtk.Window):
             self.add_controller(key_ctl)
             self.prev_key = [0]
 
+        def ensure_db_files():
+            if not path_exists(CACHE_PATH):
+                with open(CACHE_PATH, 'w', encoding='utf8') as f:
+                    json_dump({}, f)
+            if not path_exists(BOOKMARKS_PATH):
+                with open(BOOKMARKS_PATH, 'w', encoding='utf8') as f:
+                    json_dump([], f)
+
+        def setup_css():
+            css_provider = Gtk.CssProvider()
+            css_provider.load_from_data(CSS)
+            Gtk.StyleContext.add_provider_for_display(
+                    self.get_display(), css_provider,
+                    Gtk.STYLE_PROVIDER_PRIORITY_USER)
+
         self.block_once_hit_file_selection = False
         self.block_file_selection_updates = False
         self.force_width, self.force_height = 0, 0
 
-        css_provider = Gtk.CssProvider()
-        # css_provider.load_from_data(DEBUGGING_CSS)
-        css_provider.load_from_data(CSS)
-        Gtk.StyleContext.add_provider_for_display(
-                self.get_display(), css_provider,
-                Gtk.STYLE_PROVIDER_PRIORITY_USER)
-
+        setup_css()
         viewer = Gtk.Box(orientation=OR_V)
         self.navbar = init_navbar()
         viewer.append(self.navbar)
@@ -273,6 +282,7 @@ class MainWindow(Gtk.Window):
         self.connect('notify::default-width', lambda _, __: self.on_resize())
         self.connect('notify::default-height', lambda _, __: self.on_resize())
 
+        ensure_db_files()
         init_key_control()
         init_gallery_content()
         self.load_directory(update_gallery=False)
@@ -292,6 +302,22 @@ class MainWindow(Gtk.Window):
 
     # various gallery management tasks
 
+    def bookmark(self):
+        """Toggle bookmark on selected gallery item."""
+        selected_item = self.gallery_selection.props.selected_item
+        with open(BOOKMARKS_PATH, 'r', encoding='utf8') as f:
+            bookmarks = json_load(f)
+        if selected_item.bookmarked:
+            selected_item.bookmarked = False
+            bookmarks.remove(selected_item.full_path)
+        else:
+            selected_item.bookmarked = True
+            bookmarks += [selected_item.full_path]
+        with open(BOOKMARKS_PATH, 'w', encoding='utf8') as f:
+            json_dump(list(bookmarks), f)
+        self.update_file_selection()
+        self.update_gallery_view()
+
     def update_gallery(self, suggested_selection=None, sort=True):
         """Build gallery based on .per_row and .gallery_selection."""
 
@@ -359,7 +385,13 @@ class MainWindow(Gtk.Window):
             self.block_once_hit_file_selection = True
             to_select.activate()
         else:
-            self.counter.set_text(f' (nothing) ')
+            self.counter.set_text(' (nothing) ')
+        with open(BOOKMARKS_PATH, 'r', encoding='utf8') as f:
+            bookmarks = json_load(f)
+        for i in range(self.gallery_store_filtered.get_n_items()):
+            slot = self.gallery_store.get_item(i)
+            if slot.full_path in bookmarks:
+                slot.bookmarked = True
         self.update_gallery_view()
 
     def update_gallery_view(self, refocus=False):
@@ -382,6 +414,10 @@ class MainWindow(Gtk.Window):
             if isinstance(slot.item, DirItem):
                 slot.content.set_size_request(slot_size, slot_size)
                 continue
+            if slot.item.bookmarked:
+                slot.props.parent.add_css_class('bookmarked')
+            else:
+                slot.props.parent.remove_css_class('bookmarked')
             slot_top = (i // self.per_row) * (slot_size + margin)
             slot_bottom = slot_top + slot_size
             in_vp = (slot_bottom >= vp_top and slot_top <= vp_bottom)
@@ -454,7 +490,9 @@ class MainWindow(Gtk.Window):
                     params_strs = [f'{k}: {getattr(selected_item, k.lower())}'
                                    for k in GEN_PARAMS]
                     title = f'{selected_item.full_path}'
-                    self.metadata.set_text('\n'.join([title] + params_strs))
+                    bookmarked = 'BOOKMARK' if selected_item.bookmarked else ''
+                    self.metadata.set_text(
+                            '\n'.join([title, bookmarked] + params_strs))
                     return
             self.metadata.set_text('')
 
@@ -548,7 +586,8 @@ class MainWindow(Gtk.Window):
             if not hasattr(item, filter_attribute):
                 return False
             to_compare = getattr(item, filter_attribute)
-            number_attributes = set(GEN_PARAMS_INT) | set(GEN_PARAMS_FLOAT)
+            number_attributes = set(GEN_PARAMS_INT) | set(GEN_PARAMS_FLOAT) | {
+                    'BOOKMARKED'}
             if filter_attribute.upper() in number_attributes:
                 if not number_filter(filter_attribute, value, to_compare):
                     return False
@@ -596,9 +635,6 @@ class MainWindow(Gtk.Window):
         self.block_file_selection_updates = True
         self.gallery_store.remove_all()
         self.block_file_selection_updates = False
-        if not path_exists(CACHE_PATH):
-            with open(CACHE_PATH, 'w', encoding='utf8') as f:
-                json_dump({}, f)
         with open(CACHE_PATH, 'r', encoding='utf8') as f:
             cache = json_load(f)
         read_directory_into_gallery_items(cache, self.app.img_dir_absolute,
@@ -709,6 +745,8 @@ class MainWindow(Gtk.Window):
             self.move_selection_in_sort_order(1)
         elif Gdk.KEY_S == keyval:
             self.move_sort(1)
+        elif Gdk.KEY_b == keyval:
+            self.bookmark()
         else:
             self.prev_key[0] = keyval
             return False