diff --git a/src/application.rs b/src/application.rs index f64d93a..d2ff30b 100644 --- a/src/application.rs +++ b/src/application.rs @@ -73,7 +73,7 @@ mod imp { let application = self.obj(); for file in files { let win = LpWindow::new(&*application); - win.set_image_from_file(file); + win.image_view().set_image_from_file(file.clone()); } } } diff --git a/src/file_model.rs b/src/file_model.rs index 57b083a..5b235aa 100644 --- a/src/file_model.rs +++ b/src/file_model.rs @@ -70,12 +70,18 @@ impl Default for LpFileModel { impl LpFileModel { /// Create with a single element - pub fn from_file(file: &gio::File) -> Self { + pub fn from_file(file: gio::File) -> Self { + Self::from_files(vec![file]) + } + + pub fn from_files(files: Vec) -> Self { let model = Self::default(); { let mut vec = model.imp().files.borrow_mut(); - vec.insert(file.uri(), file.clone()); + for file in files { + vec.insert(file.uri(), file); + } } model diff --git a/src/widgets/image_view.rs b/src/widgets/image_view.rs index b90c651..d92fb25 100644 --- a/src/widgets/image_view.rs +++ b/src/widgets/image_view.rs @@ -227,15 +227,35 @@ glib::wrapper! { #[gtk::template_callbacks] impl LpImageView { - pub fn set_image_from_file(&self, file: &gio::File) { + pub fn set_image_from_file(&self, file: gio::File) { // Add image to recently used file. Does not work in Flatpaks: // gtk::RecentManager::default().add_item(&file.uri()); - if let Err(err) = self.load_file(file) { - log::error!("Failed to load path: {err}"); - self.activate_action("win.show-toast", Some(&(err.to_string(), 1).to_variant())) - .unwrap(); + self.load_file(file); + } + + pub fn set_images_from_files(&self, files: Vec) { + let recent_manager = gtk::RecentManager::default(); + for file in files.iter() { + recent_manager.add_item(&file.uri()); + } + self.load_files(files); + } + + fn load_files(&self, files: Vec) { + let sliding_view = self.sliding_view(); + + if let Some(first) = files.first().cloned() { + let model = LpFileModel::from_files(files); + self.set_model(model); + let page = LpImagePage::from_file(&first); + + sliding_view.clear(); + sliding_view.append(&page); + self.update_sliding_view(&first); + } else { + log::error!("File list was empty"); } } @@ -243,8 +263,7 @@ impl LpImageView { // that holds a `gio::File` for each child within the same directory as the // file we pass. This model will update with changes to the directory, // and in turn we'll update our `adw::Carousel`. - fn load_file(&self, file: &gio::File) -> anyhow::Result<()> { - let sliding_view = self.sliding_view(); + fn load_file(&self, file: gio::File) { let directory = file.parent(); let is_same_directory = if let (Some(d1), Some(d2)) = (&directory, self.model().directory()) @@ -256,18 +275,15 @@ impl LpImageView { if is_same_directory { log::debug!("Re-using old model and navigating to the current file"); - self.navigate_to_file(file); - return Ok(()); + self.navigate_to_file(&file); + return; } - let model = LpFileModel::from_file(file); + let model = LpFileModel::from_file(file.clone()); self.set_model(model); log::debug!("New model created"); - let page = LpImagePage::from_file(file); - - sliding_view.clear(); - sliding_view.append(&page); + self.update_sliding_view(&file); // List other files in directory if let Some(directory) = directory { @@ -282,8 +298,6 @@ impl LpImageView { obj.update_sliding_view(&file); })); } - - Ok(()) } /// Move forward or backwards diff --git a/src/window.rs b/src/window.rs index 97c08cd..4af38a5 100644 --- a/src/window.rs +++ b/src/window.rs @@ -325,38 +325,26 @@ mod imp { // We've added type annotations here, and written it as `let list: gdk::FileList = ...`, // but you might also see places where type arguments are used. // This line could have been written as `let list = value.get::().unwrap()`. - let list: gdk::FileList = match value.get() { - Ok(list) => list, + let mut files = match value.get::() { + Ok(list) => list.files(), Err(err) => { log::error!("Issue with drop value: {err}"); return false; } }; - // TODO: Handle this like EOG and make a "directory" out of the given files - let file = list.files().get(0).unwrap().clone(); - let info = util::query_attributes( - &file, - vec![ - gio::FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - gio::FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, - ], - ) - .expect("Could not query file info"); - - if info - .content_type() - .map(|t| t.to_string()) - .filter(|t| t.starts_with("image/")) - .is_some() { - obj.set_image_from_file(&file); + if files.len() > 1 { + obj.image_view().set_images_from_files(files); + } else if let Some(file) = files.pop() { + obj.image_view().set_image_from_file(file); } else { - obj.show_toast( - gettext_f("“{}” is not a valid image.", &[&info.display_name()]), - adw::ToastPriority::High, - ); + log::error!("Dropped FileList was empty"); + return false; } + // Maybe one day this will actually work + obj.present(); + true }), ); @@ -434,7 +422,7 @@ impl LpWindow { .build(); if let Ok(file) = chooser.open_future(Some(self)).await { - self.set_image_from_file(&file); + self.image_view().set_image_from_file(file); } else { log::debug!("File dialog canceled or file not readable"); } @@ -506,7 +494,7 @@ impl LpWindow { spawn(async move { let result = crate::util::untrash(&path).await; match result { - Ok(()) => win.image_view().set_image_from_file(&gio::File::for_path(&path)), + Ok(()) => win.image_view().set_image_from_file(gio::File::for_path(&path)), Err(err) => { log::error!("Failed to untrash {path:?}: {err}"); win.show_toast( @@ -569,7 +557,7 @@ impl LpWindow { } } - fn image_view(&self) -> LpImageView { + pub fn image_view(&self) -> LpImageView { self.imp().image_view.clone() } @@ -582,14 +570,6 @@ impl LpWindow { imp.toast_overlay.add_toast(toast); } - pub fn set_image_from_file(&self, file: &gio::File) { - let imp = self.imp(); - - log::debug!("Loading file: {}", file.uri()); - imp.image_view.set_image_from_file(file); - self.set_actions_enabled(true); - } - pub fn set_actions_enabled(&self, enabled: bool) { self.action_set_enabled("win.open-with", enabled); self.action_set_enabled("win.set-background", enabled);