editing: Handle errors

This commit is contained in:
Sophie Herold 2024-12-18 13:36:20 +01:00
parent 5b51237203
commit 8345640757
5 changed files with 57 additions and 30 deletions

View file

@ -20,9 +20,13 @@ use std::cell::{Cell, OnceCell};
use adw::prelude::*; use adw::prelude::*;
use adw::subclass::prelude::*; use adw::subclass::prelude::*;
use adw::{glib, gtk}; use adw::{glib, gtk};
use glycin::Operation;
use crate::editing::preview::EditingError;
use crate::util::gettext::*;
use crate::widgets::edit::LpEditCropSelection; use crate::widgets::edit::LpEditCropSelection;
use crate::widgets::LpEditWindow; use crate::widgets::error_details::ErrorType;
use crate::widgets::{LpEditWindow, LpImage};
#[derive(Debug, Clone, Copy, Default, glib::Enum)] #[derive(Debug, Clone, Copy, Default, glib::Enum)]
#[enum_type(name = "LpAspectRatio")] #[enum_type(name = "LpAspectRatio")]
@ -53,10 +57,8 @@ pub enum LpOrientation {
} }
mod imp { mod imp {
use glycin::Operation;
use super::*; use super::*;
use crate::widgets::LpImage;
#[derive(Debug, Default, gtk::CompositeTemplate, glib::Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, glib::Properties)]
#[properties(wrapper_type = super::LpEditCrop)] #[properties(wrapper_type = super::LpEditCrop)]
#[template(file = "crop.ui")] #[template(file = "crop.ui")]
@ -94,16 +96,16 @@ mod imp {
klass.install_property_action("edit-crop.aspect-ratio", "aspect_ratio"); klass.install_property_action("edit-crop.aspect-ratio", "aspect_ratio");
klass.install_property_action("edit-crop.orientation", "orientation"); klass.install_property_action("edit-crop.orientation", "orientation");
klass.install_action("edit-crop.mirror", None, |obj, _, _| { klass.install_action("edit-crop.mirror", None, |obj, _, _| {
obj.imp().apply_mirror(); obj.handle_error(obj.imp().apply_mirror());
}); });
klass.install_action("edit-crop.rotate-cw", None, |obj, _, _| { klass.install_action("edit-crop.rotate-cw", None, |obj, _, _| {
obj.imp().apply_rotate_cw(); obj.handle_error(obj.imp().apply_rotate_cw());
}); });
klass.install_action("edit-crop.rotate-ccw", None, |obj, _, _| { klass.install_action("edit-crop.rotate-ccw", None, |obj, _, _| {
obj.imp().apply_rotate_ccw(); obj.handle_error(obj.imp().apply_rotate_ccw());
}); });
klass.install_action("edit-crop.reset", None, |obj, _, _| { klass.install_action("edit-crop.reset", None, |obj, _, _| {
obj.imp().apply_reset(); obj.handle_error(obj.imp().apply_reset());
}); });
} }
@ -127,7 +129,7 @@ mod imp {
#[weak] #[weak]
obj, obj,
move |_| { move |_| {
obj.imp().apply_crop(); obj.handle_error(obj.imp().apply_crop());
} }
)); ));
@ -240,50 +242,60 @@ mod imp {
self.selection.reset(x, y, width, height); self.selection.reset(x, y, width, height);
} }
fn apply_crop(&self) { fn apply_crop(&self) -> Result<(), EditingError> {
if let Some(crop) = self.crop_area_image_coord() { if let Some(crop) = self.crop_area_image_coord() {
let edit_window = self.obj().edit_window(); let edit_window = self.obj().edit_window();
edit_window.add_operation(Operation::Clip(crop)); edit_window.add_operation(Operation::Clip(crop));
self.image.set_operations(edit_window.operations()); self.image.set_operations(edit_window.operations())?;
self.reset_selection(); self.reset_selection();
} }
Ok(())
} }
fn apply_mirror(&self) { fn apply_mirror(&self) -> Result<(), EditingError> {
let edit_window = self.obj().edit_window(); let edit_window = self.obj().edit_window();
edit_window.add_operation(Operation::MirrorHorizontally); edit_window.add_operation(Operation::MirrorHorizontally);
self.image.set_operations(edit_window.operations()); self.image.set_operations(edit_window.operations())?;
self.reset_selection(); self.reset_selection();
Ok(())
} }
fn apply_rotate_cw(&self) { fn apply_rotate_cw(&self) -> Result<(), EditingError> {
let edit_window = self.obj().edit_window(); let edit_window = self.obj().edit_window();
edit_window.add_operation(Operation::Rotate(gufo_common::orientation::Rotation::_90)); edit_window.add_operation(Operation::Rotate(gufo_common::orientation::Rotation::_90));
self.image.set_operations(edit_window.operations()); self.image.set_operations(edit_window.operations())?;
self.reset_selection(); self.reset_selection();
Ok(())
} }
fn apply_rotate_ccw(&self) { fn apply_rotate_ccw(&self) -> Result<(), EditingError> {
let edit_window = self.obj().edit_window(); let edit_window = self.obj().edit_window();
edit_window.add_operation(Operation::Rotate(gufo_common::orientation::Rotation::_270)); edit_window.add_operation(Operation::Rotate(gufo_common::orientation::Rotation::_270));
self.image.set_operations(edit_window.operations()); self.image.set_operations(edit_window.operations())?;
self.reset_selection(); self.reset_selection();
Ok(())
} }
fn apply_reset(&self) { fn apply_reset(&self) -> Result<(), EditingError> {
let obj = self.obj(); let obj = self.obj();
self.image.set_operations(None); self.image.set_operations(None)?;
obj.edit_window().set_operations(None); obj.edit_window().set_operations(None);
self.reset_selection(); self.reset_selection();
Ok(())
} }
} }
} }
@ -304,4 +316,14 @@ impl LpEditCrop {
pub fn selection(&self) -> LpEditCropSelection { pub fn selection(&self) -> LpEditCropSelection {
self.imp().selection.clone() self.imp().selection.clone()
} }
fn handle_error(&self, res: Result<(), EditingError>) {
if let Err(err) = res {
self.edit_window().window().show_error(
&gettext("Failed to Edit Image"),
&format!("Failed to edit image: {err}"),
ErrorType::General,
);
}
}
} }

View file

@ -29,9 +29,8 @@ use crate::util::gettext::*;
mod imp { mod imp {
use crate::widgets::error_details::ErrorType;
use super::*; use super::*;
use crate::widgets::error_details::ErrorType;
#[derive(Debug, Default, gtk::CompositeTemplate, glib::Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, glib::Properties)]
#[properties(wrapper_type = super::LpEditWindow)] #[properties(wrapper_type = super::LpEditWindow)]

View file

@ -18,6 +18,7 @@
use tiling::RenderOptions; use tiling::RenderOptions;
use super::*; use super::*;
use crate::editing::preview::EditingError;
impl imp::LpImage { impl imp::LpImage {
pub(super) fn apply_operations( pub(super) fn apply_operations(
@ -44,14 +45,16 @@ impl imp::LpImage {
} }
impl LpImage { impl LpImage {
pub fn set_operations(&self, operations: Option<Arc<glycin::Operations>>) { pub fn set_operations(
&self,
operations: Option<Arc<glycin::Operations>>,
) -> Result<(), EditingError> {
let imp = self.imp(); let imp = self.imp();
if operations.is_none() { imp.overwrite_dimensions.set(None);
imp.overwrite_dimensions.set(None);
}
imp.operations.replace(operations); imp.operations.replace(operations);
// Let dimension rewrite by calculating the new image
let tmp_snapshot = gtk::Snapshot::new(); let tmp_snapshot = gtk::Snapshot::new();
imp.active_frame_buffer().add_to_snapshot( imp.active_frame_buffer().add_to_snapshot(
&tmp_snapshot, &tmp_snapshot,
@ -64,12 +67,14 @@ impl LpImage {
); );
if let Some(node) = tmp_snapshot.to_node() { if let Some(node) = tmp_snapshot.to_node() {
imp.apply_operations(node, &gtk::Snapshot::new()); imp.apply_operations(node, &gtk::Snapshot::new())?;
} else { } else {
log::error!("Render node is empty"); log::error!("Render node is empty");
} }
imp.configure_best_fit(); imp.configure_best_fit();
self.queue_draw(); self.queue_draw();
Ok(())
} }
} }

View file

@ -131,7 +131,9 @@ impl WidgetImpl for imp::LpImage {
let tmp_snapshot = gtk::Snapshot::new(); let tmp_snapshot = gtk::Snapshot::new();
frame_buffer.add_to_snapshot(&tmp_snapshot, applicable_zoom, &render_options); frame_buffer.add_to_snapshot(&tmp_snapshot, applicable_zoom, &render_options);
if let Some(node) = tmp_snapshot.to_node() { if let Some(node) = tmp_snapshot.to_node() {
self.apply_operations(node, snapshot); if let Err(err) = self.apply_operations(node, snapshot) {
log::error!("Failed to apply operations to node: {err}");
}
} else { } else {
log::error!("Render node is empty"); log::error!("Render node is empty");
} }

View file

@ -23,15 +23,14 @@ use gio::glib::VariantTy;
use gtk::CompositeTemplate; use gtk::CompositeTemplate;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use super::error_details::ErrorType;
use super::LpErrorDetails;
use crate::config; use crate::config;
use crate::deps::*; use crate::deps::*;
use crate::util::gettext::*; use crate::util::gettext::*;
use crate::util::Direction; use crate::util::Direction;
use crate::widgets::{LpEditWindow, LpImageView, LpImageWindow}; use crate::widgets::{LpEditWindow, LpImageView, LpImageWindow};
use super::error_details::ErrorType;
use super::LpErrorDetails;
/// Show window after X milliseconds even if image dimensions are not known yet /// Show window after X milliseconds even if image dimensions are not known yet
const SHOW_WINDOW_AFTER: u64 = 2000; const SHOW_WINDOW_AFTER: u64 = 2000;