diff --git a/Cargo.lock b/Cargo.lock
index e47f24a..14da230 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1398,6 +1398,7 @@ dependencies = [
"libgweather",
"log",
"once_cell",
+ "strum",
"url",
]
@@ -1767,6 +1768,12 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "rustversion"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0"
+
[[package]]
name = "ryu"
version = "1.0.17"
@@ -1886,6 +1893,28 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+[[package]]
+name = "strum"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.50",
+]
+
[[package]]
name = "syn"
version = "1.0.109"
diff --git a/Cargo.toml b/Cargo.toml
index 808d619..2020c20 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,6 +28,7 @@ libgweather = "4.4.0"
log = "0.4.17"
once_cell = "1.16.0"
url = "2.3.1"
+strum = { version = "0.26.2", features = ["derive"] }
[dependencies.ashpd]
version = "0.8.0"
@@ -36,7 +37,7 @@ features = ["gtk4_wayland"]
[dependencies.gtk]
package = "gtk4"
version = "0.8.0"
-features = ["v4_12", "xml_validation"]
+features = ["v4_14", "xml_validation"]
[dependencies.gio]
package = "gio"
diff --git a/data/resources/gtk/help-overlay.ui b/data/resources/gtk/help-overlay.ui
index 9d831ad..5f79ad9 100644
--- a/data/resources/gtk/help-overlay.ui
+++ b/data/resources/gtk/help-overlay.ui
@@ -140,13 +140,13 @@
@@ -275,4 +275,4 @@
-
\ No newline at end of file
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index fc42903..93c0a5a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -17,6 +17,8 @@ src/metadata/mod.rs
src/util/gettext.rs
src/util/mod.rs
src/widgets/drag_overlay.rs
+src/widgets/error_details.rs
+src/widgets/error_details.ui
src/widgets/image.rs
src/widgets/image/background_color.rs
src/widgets/image/drag.rs
@@ -43,4 +45,5 @@ src/widgets/shy_bin.rs
src/widgets/sliding_view.rs
src/window.rs
src/window.ui
+src/window/actions.rs
src/window/controls.rs
diff --git a/src/application.rs b/src/application.rs
index f3b8612..01dbbab 100644
--- a/src/application.rs
+++ b/src/application.rs
@@ -23,9 +23,9 @@
use adw::prelude::*;
use adw::subclass::prelude::*;
+use crate::config;
use crate::deps::*;
use crate::window::LpWindow;
-use crate::{about, config};
mod imp {
use super::*;
@@ -128,12 +128,6 @@ impl LpApplication {
// that implements gio::ActionMap. Here we build the application's actions and
// add them with add_action_entries().
let actions = [
- gio::ActionEntryBuilder::new("about")
- .activate(|app: &Self, _, _| {
- let app = app.clone();
- glib::spawn_future_local(async move { app.show_about().await });
- })
- .build(),
gio::ActionEntryBuilder::new("help")
.activate(|app: &Self, _, _| app.show_help())
.build(),
@@ -152,65 +146,8 @@ impl LpApplication {
self.set_accels_for_action("app.help", &["F1"]);
self.set_accels_for_action("app.quit", &["Q"]);
- self.set_accels_for_action("app.new-window", &["N"]);
-
- self.set_accels_for_action("win.open", &["O"]);
- self.set_accels_for_action("win.print", &["P"]);
- self.set_accels_for_action("win.copy", &["C"]);
- self.set_accels_for_action("win.trash", &["Delete", "KP_Delete"]);
- self.set_accels_for_action("win.delete", &["Delete", "KP_Delete"]);
- self.set_accels_for_action("win.show-help-overlay", &["question"]);
- self.set_accels_for_action("win.leave-fullscreen", &["Escape"]);
- self.set_accels_for_action("win.toggle-properties", &["F9", "Return"]);
- self.set_accels_for_action("win.toggle-fullscreen", &["F11"]);
- self.set_accels_for_action("win.set-background", &["F8"]);
-
- self.set_accels_for_action("win.image-left-instant", &["Left", "Page_Down"]);
- self.set_accels_for_action("win.image-right-instant", &["Right", "Page_Up"]);
- self.set_accels_for_action("win.first", &["Home"]);
- self.set_accels_for_action("win.last", &["End"]);
-
- self.set_accels_for_action(
- "win.zoom-to-exact(1.0)",
- &["1", "KP_1", "1", "KP_1"],
- );
- self.set_accels_for_action(
- "win.zoom-to-exact(2.0)",
- &["2", "KP_2", "2", "KP_2"],
- );
- self.set_accels_for_action("win.zoom-best-fit", &["0", "KP_0", "0", "KP_0"]);
- self.set_accels_for_action(
- "win.zoom-in-cursor",
- &[
- "plus",
- "plus",
- "equal",
- "equal",
- "KP_Add",
- "KP_Add",
- ],
- );
- self.set_accels_for_action(
- "win.zoom-out-cursor",
- &["minus", "minus", "KP_Subtract", "KP_Subtract"],
- );
-
- self.set_accels_for_action("win.pan-left", &["Left"]);
- self.set_accels_for_action("win.pan-right", &["Right"]);
- self.set_accels_for_action("win.pan-up", &["Up"]);
- self.set_accels_for_action("win.pan-down", &["Down"]);
-
- self.set_accels_for_action("win.rotate_cw", &["R"]);
- self.set_accels_for_action("win.rotate_ccw", &["R"]);
-
self.set_accels_for_action("window.close", &["W"]);
- }
-
- pub async fn show_about(&self) {
- let about = about::dialog().await;
- let window = self.active_window().unwrap();
-
- about.present(&window);
+ self.set_accels_for_action("app.new-window", &["N"]);
}
pub fn show_help(&self) {
diff --git a/src/widgets/error_details.rs b/src/widgets/error_details.rs
index c1bb345..093fa56 100644
--- a/src/widgets/error_details.rs
+++ b/src/widgets/error_details.rs
@@ -1,12 +1,8 @@
use adw::prelude::*;
use adw::subclass::prelude::*;
-use glib::{clone, Properties};
-use gtk::prelude::*;
use gtk::CompositeTemplate;
use crate::deps::*;
-use crate::util::gettext::*;
-use crate::widgets::LpImage;
mod imp {
use super::*;
diff --git a/src/widgets/error_details.ui b/src/widgets/error_details.ui
index 499ea44..77552af 100644
--- a/src/widgets/error_details.ui
+++ b/src/widgets/error_details.ui
@@ -34,6 +34,7 @@
true
diff --git a/src/widgets/image_page.rs b/src/widgets/image_page.rs
index 98e68ff..0f3db88 100644
--- a/src/widgets/image_page.rs
+++ b/src/widgets/image_page.rs
@@ -193,11 +193,11 @@ impl LpImagePage {
let image = self.image();
if image.is_unsupported() {
- let message = if glycin::supported_mime_types().await.len() == 0 {
+ let message = if glycin::supported_mime_types().await.is_empty() {
// Translators: {} is replace with a version number
gettext_f(
"No image loaders available. Mabye the “glycin-loaders” package with compatibility version “{}+” is not installed.",
- [ format!("{}+", glycin::COMPAT_VERSION.to_string())])
+ [ format!("{}+", glycin::COMPAT_VERSION)])
} else {
let mime_type = image.metadata().mime_type().unwrap_or_default();
let content_type = gio::content_type_from_mime_type(&mime_type).unwrap_or_default();
@@ -221,6 +221,9 @@ impl LpImagePage {
};
imp.error_page.set_description(Some(&message));
+ imp.error_more_info.set_visible(false);
+
+ imp.stack.set_visible_child(&*imp.error_page);
} else if let Some(err) = image.error() {
imp.error_more_info
.connect_clicked(glib::clone!(@weak self as obj => move |_| {
@@ -230,7 +233,9 @@ impl LpImagePage {
imp.error_page.set_description(Some(&gettext(
"Either the image file is corrupted or it contains unsupported elements.",
)));
+
+ imp.error_more_info.set_visible(true);
+ imp.stack.set_visible_child(&*imp.error_page);
}
- imp.stack.set_visible_child(&*imp.error_page);
}
}
diff --git a/src/widgets/image_page.ui b/src/widgets/image_page.ui
index 90f0036..ec8abad 100644
--- a/src/widgets/image_page.ui
+++ b/src/widgets/image_page.ui
@@ -103,7 +103,7 @@