gallery_store_filtered: Gtk.FilterListModel
gallery_selection: Gtk.SingleSelection
include_dirs: bool
+ recurse_dirs: bool
per_row: int
metadata: Gtk.TextBuffer
sort_order: list
btn.connect('clicked', on_click)
parent_box.append(btn)
navbar = Gtk.Box(orientation=OR_H)
- add_button('folder_view', lambda _: self.toggle_side_box(), navbar)
+ add_button('sidebar', lambda _: self.toggle_side_box(), navbar)
add_button('reload', lambda _: self.load_directory(), navbar)
navbar.append(Gtk.Label(label=' per row: '))
add_button('less', lambda _: self.inc_per_row(-1), navbar)
btn = Gtk.CheckButton(label='show directories')
btn.connect('toggled', self.reset_include_dirs)
navbar.append(btn)
+ btn = Gtk.CheckButton(label='recurse directories')
+ btn.connect('toggled', self.reset_recurse)
+ navbar.append(btn)
return navbar
def init_gallery_widgets():
lambda _: self.update_file_selection())
self.gallery.connect(
'child-activated', lambda _, __: self.hit_file_selection())
- gallery_scroller = Gtk.ScrolledWindow(
- child=self.gallery, propagate_natural_height=True)
- gallery_scroller.get_vadjustment().connect(
+ scroller = Gtk.ScrolledWindow(propagate_natural_height=True)
+ scroller.get_vadjustment().connect(
'value-changed', lambda _: self.update_gallery_view())
- # attach a maximally expanded dummy that will be destroyed once we
- # bind self.gallery to a model; seems necessary to pre-stretch the
- # gallery_scroller's viewport for our first calculation (in the
- # first run of update_gallery) of what images to load into it
- self.gallery.append(Gtk.Box(hexpand=True, vexpand=True))
- return gallery_scroller
+ # We want our viewport at always maximum possible size (so we can
+ # safely calculate what's in it and what not), even if the gallery
+ # would be smaller. Therefore we frame the gallery in an expanding
+ # Fixed, to stretch out the viewport even if the gallery is small.
+ viewport_stretcher = Gtk.Fixed(hexpand=True, vexpand=True)
+ viewport_stretcher.put(self.gallery, 0, 0)
+ scroller.props.child = viewport_stretcher
+ return scroller
def init_metadata_box():
text_view = Gtk.TextView()
self.gallery_selection = Gtk.SingleSelection.new(
self.gallery_store_filtered)
self.include_dirs = False
+ self.recurse_dirs = False
self.per_row = 3
def init_key_control():
i = 0
while True:
gallery_item_at_i = self.gallery.get_child_at_index(i)
- item_path = gallery_item_at_i.props.child.item.full_path
if gallery_item_at_i is None:
break
+ item_path = gallery_item_at_i.props.child.item.full_path
if suggested_selection.full_path == item_path:
to_select = gallery_item_at_i
break
def update_gallery_view(self):
"""Load/unload gallery's file images based on viewport visibility."""
- viewport = self.gallery.get_parent()
+ viewport = self.gallery.get_parent().get_parent()
vp_height = viewport.get_height()
vp_width = viewport.get_width()
vp_top = viewport.get_vadjustment().get_value()
vp_bottom = vp_top + vp_height
- max_slot_width = vp_width / self.per_row - 6
- slot_size = min(vp_height, max_slot_width)
+ margin = 6
+ max_slot_width = vp_width / self.per_row - margin
+ prefered_slot_height = vp_height - margin
+ slot_size = min(prefered_slot_height, max_slot_width)
for i in range(self.gallery_store_filtered.get_n_items()):
slot = self.gallery.get_child_at_index(i).props.child
if isinstance(slot.item, DirItem):
slot.content.set_size_request(slot_size, slot_size)
continue
- slot_top = (i // self.per_row) * slot_size
+ slot_top = (i // self.per_row) * (slot_size + margin)
slot_bottom = slot_top + slot_size
in_viewport = (slot_bottom >= vp_top and slot_top <= vp_bottom)
if in_viewport:
def load_directory(self, update_gallery=True):
"""Load into gallery directory at self.img_dir_absolute."""
- def read_directory_into_gallery_items(cache):
- directory = Gio.File.new_for_path(self.img_dir_absolute)
+ def read_directory_into_gallery_items(cache, dir_path,
+ make_parent=False):
+ directory = Gio.File.new_for_path(dir_path)
query_attrs = 'standard::name,time::*'
- parent_path = abspath(path_join(self.img_dir_absolute, UPPER_DIR))
- parent_dir = directory.get_parent()
- parent_dir_info = parent_dir.query_info(
- query_attrs, Gio.FileQueryInfoFlags.NONE, None)
- parent_dir_item = DirItem(
- parent_path, parent_dir_info, is_parent=True)
- self.gallery_store.append(parent_dir_item)
+ if make_parent:
+ parent_path = abspath(path_join(dir_path, UPPER_DIR))
+ parent_dir = directory.get_parent()
+ parent_dir_info = parent_dir.query_info(
+ query_attrs, Gio.FileQueryInfoFlags.NONE, None)
+ parent_dir_item = DirItem(
+ parent_path, parent_dir_info, is_parent=True)
+ self.gallery_store.append(parent_dir_item)
query_attrs = query_attrs + ',standard::content-type'
enumerator = directory.enumerate_children(
query_attrs, Gio.FileQueryInfoFlags.NONE, None)
to_set_metadata_on = []
for info in enumerator:
- if self.include_dirs\
- and info.get_file_type() == Gio.FileType.DIRECTORY:
- self.gallery_store.append(DirItem(self.img_dir_absolute,
- info))
+ if info.get_file_type() == Gio.FileType.DIRECTORY:
+ if self.include_dirs:
+ self.gallery_store.append(DirItem(dir_path, info))
+ if self.recurse_dirs:
+ read_directory_into_gallery_items(
+ cache, path_join(dir_path, info.get_name()))
elif info.get_content_type()\
and info.get_content_type().startswith('image/'):
- item = ImgItem(self.img_dir_absolute, info, cache)
+ item = ImgItem(dir_path, info, cache)
if '' == item.model:
to_set_metadata_on += [item]
self.gallery_store.append(item)
json_dump({}, f)
with open(CACHE_PATH, 'r', encoding='utf8') as f:
cache = json_load(f)
- read_directory_into_gallery_items(cache)
+ read_directory_into_gallery_items(cache, self.img_dir_absolute, True)
with open(CACHE_PATH, 'w', encoding='utf8') as f:
json_dump(cache, f)
if update_gallery:
self.update_gallery(self.gallery_selection.props.selected_item,
sort=False)
+ def reset_recurse(self, button):
+ """By button's .active, de-/activate recursion on image collection."""
+ self.recurse_dirs = button.props.active
+ self.load_directory()
+
# movement
def move_sort(self, direction):