util/root: Add window_inspect() to avoid unwraps

This commit is contained in:
Sophie Herold 2025-12-09 21:55:07 +01:00
parent 7b45009eed
commit cfd33fa2dd
3 changed files with 41 additions and 18 deletions

View file

@ -35,6 +35,7 @@ pub trait ParentWindow: WidgetExt {
result.unwrap() result.unwrap()
} }
#[track_caller]
fn try_window(&self) -> Option<LpWindow> { fn try_window(&self) -> Option<LpWindow> {
let result = self.root().and_downcast(); let result = self.root().and_downcast();
@ -49,18 +50,25 @@ pub trait ParentWindow: WidgetExt {
result result
} }
#[track_caller]
fn window_show_toast(&self, text: &str, priority: adw::ToastPriority) { fn window_show_toast(&self, text: &str, priority: adw::ToastPriority) {
if let Some(window) = self.try_window() { if let Some(window) = self.try_window() {
window.show_toast(text, priority); window.show_toast(text, priority);
} }
} }
#[track_caller]
fn window_add_toast(&self, toast: adw::Toast) { fn window_add_toast(&self, toast: adw::Toast) {
if let Some(window) = self.try_window() { if let Some(window) = self.try_window() {
window.add_toast(toast); window.add_toast(toast);
} }
} }
#[track_caller]
fn window_inspect(&self, f: impl FnOnce(&LpWindow)) {
self.try_window().inspect(f);
}
fn edit_window(&self) -> LpEditWindow { fn edit_window(&self) -> LpEditWindow {
let parent = self.parent().unwrap(); let parent = self.parent().unwrap();

View file

@ -438,7 +438,7 @@ mod imp {
// Maybe one day this will actually work // Maybe one day this will actually work
log::debug!("Trying to focus window after drag and drop"); log::debug!("Trying to focus window after drag and drop");
obj.window().present(); obj.window_inspect(|w| w.present());
true true
} }
@ -539,7 +539,10 @@ impl LpImageWindow {
.as_ref(), .as_ref(),
); );
if let Ok(selected) = chooser.open_multiple_future(Some(&self.window())).await { if let Ok(selected) = chooser
.open_multiple_future(self.try_window().as_ref())
.await
{
let images: Vec<_> = selected let images: Vec<_> = selected
.into_iter() .into_iter()
.filter_map(|files| { .filter_map(|files| {
@ -560,7 +563,7 @@ impl LpImageWindow {
if let Some(ref file) = imp.image_view.current_file() { if let Some(ref file) = imp.image_view.current_file() {
let launcher = gtk::FileLauncher::new(Some(file)); let launcher = gtk::FileLauncher::new(Some(file));
launcher.set_always_ask(true); launcher.set_always_ask(true);
if let Err(e) = launcher.launch_future(Some(&self.window())).await { if let Err(e) = launcher.launch_future(self.try_window().as_ref()).await {
if !e.matches(gtk::DialogError::Dismissed) { if !e.matches(gtk::DialogError::Dismissed) {
log::error!("Could not open image in external program: {}", e); log::error!("Could not open image in external program: {}", e);
} }
@ -592,7 +595,11 @@ impl LpImageWindow {
/// Returns true if some text in metadata is currently selected /// Returns true if some text in metadata is currently selected
fn has_metadata_selected(&self) -> bool { fn has_metadata_selected(&self) -> bool {
if let Some(focus_widget) = GtkWindowExt::focus(&self.window()) { let Some(window) = self.try_window() else {
return false;
};
if let Some(focus_widget) = GtkWindowExt::focus(&window) {
if focus_widget.is_ancestor(&*self.imp().properties_view) { if focus_widget.is_ancestor(&*self.imp().properties_view) {
if let Ok(label) = focus_widget.downcast::<gtk::Label>() { if let Ok(label) = focus_widget.downcast::<gtk::Label>() {
return label.selection_bounds().is_some(); return label.selection_bounds().is_some();
@ -848,7 +855,7 @@ impl LpImageWindow {
imp.stack.set_visible_child(&*imp.status_page); imp.stack.set_visible_child(&*imp.status_page);
imp.status_page.grab_focus(); imp.status_page.grab_focus();
// Leave fullscreen since status page has no controls to leave it // Leave fullscreen since status page has no controls to leave it
self.window().set_fullscreened(false); self.window_inspect(|w| w.set_fullscreened(false));
} }
imp.properties_button.set_sensitive(has_image); imp.properties_button.set_sensitive(has_image);
@ -878,7 +885,7 @@ impl LpImageWindow {
.and_then(|x| x.metadata().file_name()) .and_then(|x| x.metadata().file_name())
.unwrap_or_else(|| gettext("Image Viewer")); .unwrap_or_else(|| gettext("Image Viewer"));
self.window().set_title(Some(&title)); self.window_inspect(|x| x.set_title(Some(&title)));
} }
pub fn image_size_available(&self) { pub fn image_size_available(&self) {
@ -910,12 +917,14 @@ impl LpImageWindow {
if current_page.is_some_and(|page| page.image().error().is_some()) { if current_page.is_some_and(|page| page.image().error().is_some()) {
log::debug!("Showing window because loading image failed"); log::debug!("Showing window because loading image failed");
self.window().present(); self.window_inspect(|w| w.present());
} }
} }
fn on_fullscreen_changed(&self) { fn on_fullscreen_changed(&self) {
let icon = if self.window().is_fullscreen() { let is_fullscreen = self.try_window().map_or(false, |w| w.is_fullscreen());
let icon = if is_fullscreen {
"view-restore-symbolic" "view-restore-symbolic"
} else { } else {
"view-fullscreen-symbolic" "view-fullscreen-symbolic"
@ -924,7 +933,7 @@ impl LpImageWindow {
self.update_headerbar_style(); self.update_headerbar_style();
if !self.window().is_fullscreen() { if !is_fullscreen {
self.set_cursor(None); self.set_cursor(None);
self.show_controls(); self.show_controls();
} }
@ -939,18 +948,23 @@ impl LpImageWindow {
} }
fn is_content_extended_to_top(&self) -> bool { fn is_content_extended_to_top(&self) -> bool {
self.window().is_fullscreen() && !self.imp().properties_button.is_active() self.try_window().map_or(false, |w| w.is_fullscreen())
&& !self.imp().properties_button.is_active()
} }
fn update_accel_status(&self) { fn update_accel_status(&self) {
let Some(application) = self.window().application() else { let Some(window) = self.try_window() else {
return;
};
let Some(application) = window.application() else {
log::error!("No application for window found"); log::error!("No application for window found");
return; return;
}; };
// Only change status if active window // Only change status if active window
if self.window().is_active() { if window.is_active() {
if self.window().visible_dialog().is_some() || !self.is_mapped() { if window.visible_dialog().is_some() || !self.is_mapped() {
// If AdwDialog is visible, remove global accels that are for the main window // If AdwDialog is visible, remove global accels that are for the main window
// Same for this not being visible, so potentially editing view is open // Same for this not being visible, so potentially editing view is open
ActionPartGlobal::remove_accels(&application); ActionPartGlobal::remove_accels(&application);

View file

@ -239,14 +239,13 @@ impl Action {
Action::ToggleFullscreen => { Action::ToggleFullscreen => {
klass.install_action(&action, None, move |obj, _, _| { klass.install_action(&action, None, move |obj, _, _| {
let win = obj.window(); obj.window_inspect(|w| w.toggle_fullscreen(!w.is_fullscreen()));
win.toggle_fullscreen(!win.is_fullscreen());
}); });
} }
Action::LeaveFullscreen => { Action::LeaveFullscreen => {
klass.install_action(&action, None, move |obj, _, _| { klass.install_action(&action, None, move |obj, _, _| {
obj.window().toggle_fullscreen(false); obj.window_inspect(|w| w.toggle_fullscreen(false));
}); });
} }
@ -272,7 +271,9 @@ impl Action {
Action::About => { Action::About => {
klass.install_action_async(&action, None, |obj, _, _| async move { klass.install_action_async(&action, None, |obj, _, _| async move {
obj.window().show_about().await if let Some(window) = obj.try_window() {
window.show_about().await
}
}); });
} }
@ -288,7 +289,7 @@ impl Action {
Action::Edit => { Action::Edit => {
klass.install_action_async(&action, None, move |obj, _, _| async move { klass.install_action_async(&action, None, move |obj, _, _| async move {
obj.window().show_edit(); obj.window_inspect(|w| w.show_edit());
}); });
} }
} }