From 3557b15034c49573dc05953854a71eee443f8e94 Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Tue, 28 Jun 2022 18:52:52 -0400 Subject: [PATCH] image_view: Rework model loading and page navigation Rework the model loading to not care about the edges. Now we only care about where we are in the model and the number of buffer pages. This algorithm handles the edges without special casing. --- src/widgets/image_view.rs | 115 +++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 50 deletions(-) diff --git a/src/widgets/image_view.rs b/src/widgets/image_view.rs index d75b976..686a217 100644 --- a/src/widgets/image_view.rs +++ b/src/widgets/image_view.rs @@ -29,7 +29,7 @@ use anyhow::{bail, Context}; use ashpd::desktop::wallpaper; use ashpd::WindowIdentifier; use once_cell::sync::Lazy; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use crate::file_model::LpFileModel; use crate::thumbnail::Thumbnail; @@ -38,7 +38,7 @@ use crate::widgets::LpImagePage; // Maximum number of pages to load // at any given time -const N_PAGES: u32 = 3; +const N_PAGES: u32 = 2; mod imp { use super::*; @@ -51,6 +51,7 @@ mod imp { pub model: RefCell>, pub filename: RefCell>, + pub prev_index: Cell, } #[glib::object_subclass] @@ -187,42 +188,27 @@ impl LpImageView { if let Some(model) = imp.model.borrow().as_ref() { let index = model.index_of(file).unwrap() as u32; + log::debug!("Currently at file {index} in the directory"); imp.filename.replace(util::get_file_display_name(file)); carousel.append(&LpImagePage::from_file(file)); - // Here we need to check if we're at the start or end of our directory. - // If we are, we try to add two files to the other side. Otherwise, - // add one file on each end of the current file. - let iterations = if index == 0 || index == model.n_items() - 1 { - 2 - } else { - 1 - }; - - let mut next_file = file.clone(); - for i in 0..iterations { - log::debug!("Loop to find next files: {}", i); - if let Some(f) = model.next(&next_file) { - log::debug!("Adding next image URI: {}", f.uri()); - carousel.append(&LpImagePage::from_file(&f)); - next_file = f; - } else { - // Return early if there are no files in this direction; - break; + for i in 1..=N_PAGES { + if let Some(file) = model.item(index + i).and_then(|o| o.downcast().ok()) { + carousel.append(&LpImagePage::from_file(&file)) } } - let mut prev_file = file.clone(); - for i in 0..iterations { - log::debug!("Loop to find prior files: {}", i); - if let Some(f) = model.previous(&prev_file) { - log::debug!("Adding previous image URI: {}", f.uri()); - carousel.prepend(&LpImagePage::from_file(&f)); - prev_file = f; - } else { - break; + for i in 1..=N_PAGES { + if let Some(file) = index + .checked_sub(i) + .and_then(|i| model.item(i)) + .and_then(|o| o.downcast().ok()) + { + carousel.prepend(&LpImagePage::from_file(&file)) } } + + imp.prev_index.set(index); } } @@ -257,33 +243,62 @@ impl LpImageView { } #[template_callback] - fn page_changed_cb(&self, index: u32, carousel: &adw::Carousel) { + fn page_changed_cb(&self, _index: u32, carousel: &adw::Carousel) { let imp = self.imp(); let b = imp.model.borrow(); let model = b.as_ref().unwrap(); let current = self.current_page().and_then(|p| p.file()).unwrap(); - imp.filename.replace(util::get_file_display_name(¤t)); - self.notify("filename"); - self.update_action_state(¤t); - // We've moved forward - if index + 1 == N_PAGES { - if let Some(ref next) = model.next(¤t) { - log::debug!("Next URI: {}", next.uri()); - // Remove the page at index 0, add a new page at the end - carousel.remove(&carousel.nth_page(0)); - carousel.append(&LpImagePage::from_file(next)); - } - } + let model_index = model.index_of(¤t).unwrap() as u32; + let prev_index = imp.prev_index.get(); - // We've moved backward - if index == 0 { - if let Some(ref prev) = model.previous(¤t) { - log::debug!("Previous URI: {}", prev.uri()); - // Remove the page at the front, add a new page at the back - carousel.remove(&carousel.nth_page(carousel.n_pages() - 1)); - carousel.prepend(&LpImagePage::from_file(prev)); + if model_index != prev_index { + imp.filename.replace(util::get_file_display_name(¤t)); + self.notify("filename"); + self.update_action_state(¤t); + + // We've moved forward + if let Some(diff) = model_index.checked_sub(prev_index) { + for i in 0..diff { + if prev_index + .checked_sub(N_PAGES) + .and_then(|r| r.checked_sub(i)) + .is_some() + { + carousel.remove(&carousel.nth_page(0)); + } + + let s = prev_index + N_PAGES + i + 1; + if s <= model.n_items() { + if let Some(ref file) = + model.item(s).and_then(|o| o.downcast::().ok()) + { + carousel.append(&LpImagePage::from_file(file)); + } + } + } } + + // We've moved backward + if let Some(diff) = prev_index.checked_sub(model_index) { + for i in 0..diff { + let s = prev_index + N_PAGES + i + 1; + if s <= model.n_items() { + carousel.remove(&carousel.nth_page(carousel.n_pages() - 1)); + } + + if let Some(ref file) = prev_index + .checked_sub(N_PAGES) + .and_then(|d| d.checked_sub(i + 1)) + .and_then(|d| model.item(d)) + .and_then(|i| i.downcast::().ok()) + { + carousel.prepend(&LpImagePage::from_file(file)); + } + } + } + + imp.prev_index.set(model_index); } }