image_view: Handle target file gone correctly

Before, if the target file was gone, files_around just returned an empty
list of files, leading Loupe to think there are no images and showing
the empty state view.

This was frequently triggered by the "Replace original" function in
editing, since the tmp file was already gone, when the view moved to it.

Now, the correct error is shown, and scrolling to the other files is
possible.

Issue #585
This commit is contained in:
Sophie Herold 2026-08-06 13:47:39 +02:00
parent 79342bcd8d
commit f97558cb68
6 changed files with 21 additions and 11 deletions

View file

@ -107,7 +107,7 @@
{
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/glycin.git",
"commit": "b918acf0e6f9da4c051cad809f3c147678a93ab9"
"commit": "109bfc711ed6625e4206d4dbef56219cba5a5a88"
}
]
},

View file

@ -316,22 +316,30 @@ impl LpFileModel {
}
/// Returns `n` elements before and after given file
pub fn files_around(&self, file: &gio::File, n: usize) -> IndexMap<GString, gio::File> {
pub fn files_around(
&self,
file: &gio::File,
n: usize,
) -> Result<IndexMap<GString, gio::File>, ()> {
let Some(index) = self.index_of(file) else {
tracing::error!("URI not in model: {}", file.uri());
return IndexMap::new();
// This can happen when the file is deleted the moment the view moves to it.
// This frequently happens when the "Replace original" function is used in
// editing.
tracing::info!("URI not in model: {}", file.uri());
return Err(());
};
let reduce = n.saturating_sub(index);
self.imp()
Ok(self
.imp()
.files
.borrow()
.iter()
.skip(index.saturating_sub(n))
.take(2 * n + 1 - reduce)
.map(|(k, v)| (k.clone(), v.file.clone()))
.collect()
.collect())
}
/// Return first file

View file

@ -28,10 +28,9 @@ use chrono::prelude::*;
pub use file::FileInfo;
use glib::TimeZone;
use glycin::{Frame, FrameDetails, ImageDetails, MemoryFormat};
use gufo::common::cicp;
use gufo::common::datetime::DateTime;
use gufo::common::orientation::Orientation;
use gufo::common::physical_dimension;
use gufo::common::{cicp, physical_dimension};
use crate::deps::*;
use crate::util;

View file

@ -128,7 +128,7 @@ mod imp {
obj,
move |_| {
if obj.image().is_loaded() {
tracing::debug!("Showing image");
tracing::debug!("Revealing image");
obj.imp()
.stack
.set_visible_child(&*obj.imp().image_stack_page);

View file

@ -610,6 +610,10 @@ impl LpImageView {
let existing = sliding_view.pages();
let target = self.model().files_around(current_file, BUFFER);
let Ok(target) = target else {
return;
};
// remove old pages
for (uri, page) in &existing {
if !target.contains_key(uri) {

View file

@ -201,9 +201,8 @@ impl Unit {
}
mod imp {
use crate::util;
use super::*;
use crate::util;
#[derive(Debug, Default, CompositeTemplate, Properties)]
#[template(file = "print.ui")]