window: Use shortcuts instead of accels
Application level accels will also work if AdwDialogs are open. Therefore, use shortcuts wherever possible.
This commit is contained in:
parent
e129e842a6
commit
57d8bba071
12 changed files with 562 additions and 223 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
|
@ -1398,6 +1398,7 @@ dependencies = [
|
||||||
"libgweather",
|
"libgweather",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"strum",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1767,6 +1768,12 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"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]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.17"
|
version = "1.0.17"
|
||||||
|
|
@ -1886,6 +1893,28 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
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]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ libgweather = "4.4.0"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
once_cell = "1.16.0"
|
once_cell = "1.16.0"
|
||||||
url = "2.3.1"
|
url = "2.3.1"
|
||||||
|
strum = { version = "0.26.2", features = ["derive"] }
|
||||||
|
|
||||||
[dependencies.ashpd]
|
[dependencies.ashpd]
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
@ -36,7 +37,7 @@ features = ["gtk4_wayland"]
|
||||||
[dependencies.gtk]
|
[dependencies.gtk]
|
||||||
package = "gtk4"
|
package = "gtk4"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
features = ["v4_12", "xml_validation"]
|
features = ["v4_14", "xml_validation"]
|
||||||
|
|
||||||
[dependencies.gio]
|
[dependencies.gio]
|
||||||
package = "gio"
|
package = "gio"
|
||||||
|
|
|
||||||
|
|
@ -140,13 +140,13 @@
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkShortcutsShortcut">
|
<object class="GtkShortcutsShortcut">
|
||||||
<property name="title" translatable="yes" context="shortcut window">Rotate Clockwise</property>
|
<property name="title" translatable="yes" context="shortcut window">Rotate Clockwise</property>
|
||||||
<property name="action-name">win.rotate_cw</property>
|
<property name="action-name">win.rotate-cw</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkShortcutsShortcut">
|
<object class="GtkShortcutsShortcut">
|
||||||
<property name="title" translatable="yes" context="shortcut window">Rotate Counterclockwise</property>
|
<property name="title" translatable="yes" context="shortcut window">Rotate Counterclockwise</property>
|
||||||
<property name="action-name">win.rotate_ccw</property>
|
<property name="action-name">win.rotate-ccw</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|
@ -275,4 +275,4 @@
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ src/metadata/mod.rs
|
||||||
src/util/gettext.rs
|
src/util/gettext.rs
|
||||||
src/util/mod.rs
|
src/util/mod.rs
|
||||||
src/widgets/drag_overlay.rs
|
src/widgets/drag_overlay.rs
|
||||||
|
src/widgets/error_details.rs
|
||||||
|
src/widgets/error_details.ui
|
||||||
src/widgets/image.rs
|
src/widgets/image.rs
|
||||||
src/widgets/image/background_color.rs
|
src/widgets/image/background_color.rs
|
||||||
src/widgets/image/drag.rs
|
src/widgets/image/drag.rs
|
||||||
|
|
@ -43,4 +45,5 @@ src/widgets/shy_bin.rs
|
||||||
src/widgets/sliding_view.rs
|
src/widgets/sliding_view.rs
|
||||||
src/window.rs
|
src/window.rs
|
||||||
src/window.ui
|
src/window.ui
|
||||||
|
src/window/actions.rs
|
||||||
src/window/controls.rs
|
src/window/controls.rs
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
|
|
||||||
|
use crate::config;
|
||||||
use crate::deps::*;
|
use crate::deps::*;
|
||||||
use crate::window::LpWindow;
|
use crate::window::LpWindow;
|
||||||
use crate::{about, config};
|
|
||||||
|
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -128,12 +128,6 @@ impl LpApplication {
|
||||||
// that implements gio::ActionMap. Here we build the application's actions and
|
// that implements gio::ActionMap. Here we build the application's actions and
|
||||||
// add them with add_action_entries().
|
// add them with add_action_entries().
|
||||||
let actions = [
|
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")
|
gio::ActionEntryBuilder::new("help")
|
||||||
.activate(|app: &Self, _, _| app.show_help())
|
.activate(|app: &Self, _, _| app.show_help())
|
||||||
.build(),
|
.build(),
|
||||||
|
|
@ -152,65 +146,8 @@ impl LpApplication {
|
||||||
|
|
||||||
self.set_accels_for_action("app.help", &["F1"]);
|
self.set_accels_for_action("app.help", &["F1"]);
|
||||||
self.set_accels_for_action("app.quit", &["<Ctrl>Q"]);
|
self.set_accels_for_action("app.quit", &["<Ctrl>Q"]);
|
||||||
self.set_accels_for_action("app.new-window", &["<Ctrl>N"]);
|
|
||||||
|
|
||||||
self.set_accels_for_action("win.open", &["<Ctrl>O"]);
|
|
||||||
self.set_accels_for_action("win.print", &["<Ctrl>P"]);
|
|
||||||
self.set_accels_for_action("win.copy", &["<Ctrl>C"]);
|
|
||||||
self.set_accels_for_action("win.trash", &["Delete", "KP_Delete"]);
|
|
||||||
self.set_accels_for_action("win.delete", &["<Shift>Delete", "<Shift>KP_Delete"]);
|
|
||||||
self.set_accels_for_action("win.show-help-overlay", &["<Ctrl>question"]);
|
|
||||||
self.set_accels_for_action("win.leave-fullscreen", &["Escape"]);
|
|
||||||
self.set_accels_for_action("win.toggle-properties", &["F9", "<Alt>Return"]);
|
|
||||||
self.set_accels_for_action("win.toggle-fullscreen", &["F11"]);
|
|
||||||
self.set_accels_for_action("win.set-background", &["<Ctrl>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", "<Ctrl>1", "<Ctrl>KP_1"],
|
|
||||||
);
|
|
||||||
self.set_accels_for_action(
|
|
||||||
"win.zoom-to-exact(2.0)",
|
|
||||||
&["2", "KP_2", "<Ctrl>2", "<Ctrl>KP_2"],
|
|
||||||
);
|
|
||||||
self.set_accels_for_action("win.zoom-best-fit", &["0", "KP_0", "<Ctrl>0", "<Ctrl>KP_0"]);
|
|
||||||
self.set_accels_for_action(
|
|
||||||
"win.zoom-in-cursor",
|
|
||||||
&[
|
|
||||||
"<Ctrl>plus",
|
|
||||||
"plus",
|
|
||||||
"<Ctrl>equal",
|
|
||||||
"equal",
|
|
||||||
"<Ctrl>KP_Add",
|
|
||||||
"KP_Add",
|
|
||||||
],
|
|
||||||
);
|
|
||||||
self.set_accels_for_action(
|
|
||||||
"win.zoom-out-cursor",
|
|
||||||
&["<Ctrl>minus", "minus", "<Ctrl>KP_Subtract", "KP_Subtract"],
|
|
||||||
);
|
|
||||||
|
|
||||||
self.set_accels_for_action("win.pan-left", &["<Ctrl>Left"]);
|
|
||||||
self.set_accels_for_action("win.pan-right", &["<Ctrl>Right"]);
|
|
||||||
self.set_accels_for_action("win.pan-up", &["<Ctrl>Up"]);
|
|
||||||
self.set_accels_for_action("win.pan-down", &["<Ctrl>Down"]);
|
|
||||||
|
|
||||||
self.set_accels_for_action("win.rotate_cw", &["<Ctrl>R"]);
|
|
||||||
self.set_accels_for_action("win.rotate_ccw", &["<Ctrl><Shift>R"]);
|
|
||||||
|
|
||||||
self.set_accels_for_action("window.close", &["<Ctrl>W"]);
|
self.set_accels_for_action("window.close", &["<Ctrl>W"]);
|
||||||
}
|
self.set_accels_for_action("app.new-window", &["<Ctrl>N"]);
|
||||||
|
|
||||||
pub async fn show_about(&self) {
|
|
||||||
let about = about::dialog().await;
|
|
||||||
let window = self.active_window().unwrap();
|
|
||||||
|
|
||||||
about.present(&window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_help(&self) {
|
pub fn show_help(&self) {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use glib::{clone, Properties};
|
|
||||||
use gtk::prelude::*;
|
|
||||||
use gtk::CompositeTemplate;
|
use gtk::CompositeTemplate;
|
||||||
|
|
||||||
use crate::deps::*;
|
use crate::deps::*;
|
||||||
use crate::util::gettext::*;
|
|
||||||
use crate::widgets::LpImage;
|
|
||||||
|
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
<property name="vexpand">true</property>
|
<property name="vexpand">true</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkTextView" id="message">
|
<object class="GtkTextView" id="message">
|
||||||
|
<property name="editable">false</property>
|
||||||
<property name="wrap-mode">word-char</property>
|
<property name="wrap-mode">word-char</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
|
||||||
|
|
@ -193,11 +193,11 @@ impl LpImagePage {
|
||||||
let image = self.image();
|
let image = self.image();
|
||||||
|
|
||||||
if image.is_unsupported() {
|
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
|
// Translators: {} is replace with a version number
|
||||||
gettext_f(
|
gettext_f(
|
||||||
"No image loaders available. Mabye the “glycin-loaders” package with compatibility version “{}+” is not installed.",
|
"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 {
|
} else {
|
||||||
let mime_type = image.metadata().mime_type().unwrap_or_default();
|
let mime_type = image.metadata().mime_type().unwrap_or_default();
|
||||||
let content_type = gio::content_type_from_mime_type(&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_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() {
|
} else if let Some(err) = image.error() {
|
||||||
imp.error_more_info
|
imp.error_more_info
|
||||||
.connect_clicked(glib::clone!(@weak self as obj => move |_| {
|
.connect_clicked(glib::clone!(@weak self as obj => move |_| {
|
||||||
|
|
@ -230,7 +233,9 @@ impl LpImagePage {
|
||||||
imp.error_page.set_description(Some(&gettext(
|
imp.error_page.set_description(Some(&gettext(
|
||||||
"Either the image file is corrupted or it contains unsupported elements.",
|
"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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@
|
||||||
<object class="GtkButton">
|
<object class="GtkButton">
|
||||||
<property name="icon-name">object-rotate-left-symbolic</property>
|
<property name="icon-name">object-rotate-left-symbolic</property>
|
||||||
<property name="tooltip-text" translatable="yes">Rotate Left</property>
|
<property name="tooltip-text" translatable="yes">Rotate Left</property>
|
||||||
<property name="action-name">win.rotate_ccw</property>
|
<property name="action-name">win.rotate-ccw</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="flat" />
|
<class name="flat" />
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
<object class="GtkButton">
|
<object class="GtkButton">
|
||||||
<property name="icon-name">object-rotate-right-symbolic</property>
|
<property name="icon-name">object-rotate-right-symbolic</property>
|
||||||
<property name="tooltip-text" translatable="yes">Rotate Right</property>
|
<property name="tooltip-text" translatable="yes">Rotate Right</property>
|
||||||
<property name="action-name">win.rotate_cw</property>
|
<property name="action-name">win.rotate-cw</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="flat" />
|
<class name="flat" />
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
181
src/window.rs
181
src/window.rs
|
|
@ -25,11 +25,13 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
mod actions;
|
||||||
mod controls;
|
mod controls;
|
||||||
|
|
||||||
use std::cell::{Cell, OnceCell, RefCell};
|
use std::cell::{Cell, OnceCell, RefCell};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use actions::*;
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
|
|
@ -39,7 +41,7 @@ use crate::application::LpApplication;
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::deps::*;
|
use crate::deps::*;
|
||||||
use crate::util::gettext::*;
|
use crate::util::gettext::*;
|
||||||
use crate::util::{Direction, Position};
|
use crate::util::Direction;
|
||||||
use crate::widgets::{LpDragOverlay, LpImage, LpImageView, LpPropertiesView};
|
use crate::widgets::{LpDragOverlay, LpImage, LpImageView, LpPropertiesView};
|
||||||
|
|
||||||
/// 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
|
||||||
|
|
@ -138,148 +140,16 @@ mod imp {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set up actions
|
klass.add_binding_action(
|
||||||
klass.install_action("win.toggle-fullscreen", None, move |win, _, _| {
|
gdk::Key::question,
|
||||||
win.toggle_fullscreen(!win.is_fullscreened());
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
});
|
"win.show-help-overlay",
|
||||||
|
|
||||||
klass.install_action("win.next", None, move |win, _, _| {
|
|
||||||
win.imp().image_view.navigate(Direction::Forward, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.previous", None, move |win, _, _| {
|
|
||||||
win.imp().image_view.navigate(Direction::Back, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.image-right", None, move |win, _, _| {
|
|
||||||
if win.direction() == gtk::TextDirection::Rtl {
|
|
||||||
win.imp().image_view.navigate(Direction::Back, true);
|
|
||||||
} else {
|
|
||||||
win.imp().image_view.navigate(Direction::Forward, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.image-right-instant", None, move |win, _, _| {
|
|
||||||
if win.direction() == gtk::TextDirection::Rtl {
|
|
||||||
win.imp().image_view.navigate(Direction::Back, false);
|
|
||||||
} else {
|
|
||||||
win.imp().image_view.navigate(Direction::Forward, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.image-left", None, move |win, _, _| {
|
|
||||||
if win.direction() == gtk::TextDirection::Rtl {
|
|
||||||
win.imp().image_view.navigate(Direction::Forward, true);
|
|
||||||
} else {
|
|
||||||
win.imp().image_view.navigate(Direction::Back, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.image-left-instant", None, move |win, _, _| {
|
|
||||||
if win.direction() == gtk::TextDirection::Rtl {
|
|
||||||
win.imp().image_view.navigate(Direction::Forward, false);
|
|
||||||
} else {
|
|
||||||
win.imp().image_view.navigate(Direction::Back, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.first", None, move |win, _, _| {
|
|
||||||
win.imp().image_view.jump(Position::First);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.last", None, move |win, _, _| {
|
|
||||||
win.imp().image_view.jump(Position::Last);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.zoom-out-cursor", None, move |win, _, _| {
|
|
||||||
win.zoom_out_cursor();
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.zoom-out-center", None, move |win, _, _| {
|
|
||||||
win.zoom_out_center();
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.zoom-in-cursor", None, move |win, _, _| {
|
|
||||||
win.zoom_in_cursor();
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.zoom-in-center", None, move |win, _, _| {
|
|
||||||
win.zoom_in_center();
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action(
|
|
||||||
"win.zoom-to-exact",
|
|
||||||
Some(VariantTy::DOUBLE),
|
|
||||||
move |win, _, level| {
|
|
||||||
win.zoom_to_exact(level.unwrap().get().unwrap());
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
klass.install_action("win.zoom-best-fit", None, move |win, _, _| {
|
// Set up actions
|
||||||
win.zoom_best_fit();
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.pan-up", None, move |win, _, _| {
|
ActionPartGlobal::init_actions_and_bindings(klass);
|
||||||
win.pan(>k::PanDirection::Up);
|
Action::init_actions_and_bindings(klass);
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.pan-down", None, move |win, _, _| {
|
|
||||||
win.pan(>k::PanDirection::Down);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.pan-left", None, move |win, _, _| {
|
|
||||||
win.pan(>k::PanDirection::Left);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.pan-right", None, move |win, _, _| {
|
|
||||||
win.pan(>k::PanDirection::Right);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.leave-fullscreen", None, move |win, _, _| {
|
|
||||||
win.toggle_fullscreen(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.toggle-properties", None, move |win, _, _| {
|
|
||||||
win.imp()
|
|
||||||
.properties_button
|
|
||||||
.set_active(!win.imp().properties_button.is_active());
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action_async("win.open", None, |win, _, _| async move {
|
|
||||||
win.pick_file().await;
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action_async("win.open-with", None, |win, _, _| async move {
|
|
||||||
win.open_with().await;
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.rotate_cw", None, |win, _, _| {
|
|
||||||
win.rotate_image(90.0);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.rotate_ccw", None, |win, _, _| {
|
|
||||||
win.rotate_image(-90.0);
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action_async("win.set-background", None, |win, _, _| async move {
|
|
||||||
win.set_background().await;
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.print", None, move |win, _, _| {
|
|
||||||
win.print();
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action("win.copy-image", None, move |win, _, _| {
|
|
||||||
win.copy_image();
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action_async("win.trash", None, |win, _, _| async move {
|
|
||||||
win.trash().await;
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action_async("win.delete", None, |win, _, _| async move {
|
|
||||||
win.delete().await;
|
|
||||||
});
|
|
||||||
|
|
||||||
klass.install_action(
|
klass.install_action(
|
||||||
"win.show-toast",
|
"win.show-toast",
|
||||||
|
|
@ -445,6 +315,10 @@ mod imp {
|
||||||
obj.schedule_hide_controls();
|
obj.schedule_hide_controls();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Activate global shortcuts only if no dialog is open
|
||||||
|
obj.connect_visible_dialog_notify(|obj| obj.update_accel_status());
|
||||||
|
obj.connect_is_active_notify(|obj| obj.update_accel_status());
|
||||||
|
|
||||||
self.status_page
|
self.status_page
|
||||||
.set_icon_name(Some(&format!("{}-symbolic", config::APP_ID)));
|
.set_icon_name(Some(&format!("{}-symbolic", config::APP_ID)));
|
||||||
|
|
||||||
|
|
@ -791,8 +665,8 @@ impl LpWindow {
|
||||||
"win.set-background",
|
"win.set-background",
|
||||||
"win.toggle-fullscreen",
|
"win.toggle-fullscreen",
|
||||||
"win.print",
|
"win.print",
|
||||||
"win.rotate_cw",
|
"win.rotate-cw",
|
||||||
"win.rotate_ccw",
|
"win.rotate-ccw",
|
||||||
"win.copy-image",
|
"win.copy-image",
|
||||||
"win.zoom-best-fit",
|
"win.zoom-best-fit",
|
||||||
"win.zoom-to-exact",
|
"win.zoom-to-exact",
|
||||||
|
|
@ -992,4 +866,27 @@ impl LpWindow {
|
||||||
};
|
};
|
||||||
imp.toolbar_view.set_top_bar_style(toolbar_style);
|
imp.toolbar_view.set_top_bar_style(toolbar_style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_accel_status(&self) {
|
||||||
|
let Some(application) = self.application() else {
|
||||||
|
log::error!("No application for window found");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only change status if active window
|
||||||
|
if self.is_active() {
|
||||||
|
if self.visible_dialog().is_some() {
|
||||||
|
// If AdwDialog is visible, remove global accels that are for the main window
|
||||||
|
ActionPartGlobal::remove_accels(&application);
|
||||||
|
} else {
|
||||||
|
// Add accels if viewing main window
|
||||||
|
ActionPartGlobal::add_accels(&application);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn show_about(&self) {
|
||||||
|
let about = crate::about::dialog().await;
|
||||||
|
about.present(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes">_About Image Viewer</attribute>
|
<attribute name="label" translatable="yes">_About Image Viewer</attribute>
|
||||||
<attribute name="action">app.about</attribute>
|
<attribute name="action">win.about</attribute>
|
||||||
</item>
|
</item>
|
||||||
</section>
|
</section>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
@ -104,7 +104,7 @@
|
||||||
<object class="GtkButton">
|
<object class="GtkButton">
|
||||||
<property name="icon-name">object-rotate-left-symbolic</property>
|
<property name="icon-name">object-rotate-left-symbolic</property>
|
||||||
<property name="tooltip-text" translatable="yes">Rotate Left</property>
|
<property name="tooltip-text" translatable="yes">Rotate Left</property>
|
||||||
<property name="action-name">win.rotate_ccw</property>
|
<property name="action-name">win.rotate-ccw</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="flat" />
|
<class name="flat" />
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -114,7 +114,7 @@
|
||||||
<object class="GtkButton">
|
<object class="GtkButton">
|
||||||
<property name="icon-name">object-rotate-right-symbolic</property>
|
<property name="icon-name">object-rotate-right-symbolic</property>
|
||||||
<property name="tooltip-text" translatable="yes">Rotate Right</property>
|
<property name="tooltip-text" translatable="yes">Rotate Right</property>
|
||||||
<property name="action-name">win.rotate_cw</property>
|
<property name="action-name">win.rotate-cw</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="flat" />
|
<class name="flat" />
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
470
src/window/actions.rs
Normal file
470
src/window/actions.rs
Normal file
|
|
@ -0,0 +1,470 @@
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use adw::subclass::prelude::*;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::deps::*;
|
||||||
|
use crate::util::{Direction, Position};
|
||||||
|
|
||||||
|
/// Actions that need some global accels
|
||||||
|
///
|
||||||
|
/// The app level accels are needed for arrow key bindings. Because the arrow
|
||||||
|
/// keys are usually used for widget navigation, it's not possible to overwrite
|
||||||
|
/// them on key-binding level.
|
||||||
|
#[derive(strum::Display, strum::AsRefStr, strum::EnumIter)]
|
||||||
|
pub enum ActionPartGlobal {
|
||||||
|
#[strum(to_string = "win.image-left-instant")]
|
||||||
|
ImageLeftInstant,
|
||||||
|
#[strum(to_string = "win.image-right-instant")]
|
||||||
|
ImageRightInstant,
|
||||||
|
// Pan
|
||||||
|
#[strum(to_string = "win.pan-up")]
|
||||||
|
PanUp,
|
||||||
|
#[strum(to_string = "win.pan-right")]
|
||||||
|
PanRight,
|
||||||
|
#[strum(to_string = "win.pan-down")]
|
||||||
|
PanDown,
|
||||||
|
#[strum(to_string = "win.pan-left")]
|
||||||
|
PanLeft,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActionPartGlobal {
|
||||||
|
pub fn add_accels(application: >k::Application) {
|
||||||
|
for action in Self::iter() {
|
||||||
|
match action {
|
||||||
|
ActionPartGlobal::ImageRightInstant => {
|
||||||
|
application.set_accels_for_action(&action, &["Right"])
|
||||||
|
}
|
||||||
|
ActionPartGlobal::ImageLeftInstant => {
|
||||||
|
application.set_accels_for_action(&action, &["Left"])
|
||||||
|
}
|
||||||
|
ActionPartGlobal::PanUp => {
|
||||||
|
application.set_accels_for_action(&action, &["<Ctrl>Up"])
|
||||||
|
}
|
||||||
|
ActionPartGlobal::PanRight => {
|
||||||
|
application.set_accels_for_action(&action, &["<Ctrl>Right"])
|
||||||
|
}
|
||||||
|
ActionPartGlobal::PanDown => {
|
||||||
|
application.set_accels_for_action(&action, &["<Ctrl>Down"])
|
||||||
|
}
|
||||||
|
ActionPartGlobal::PanLeft => {
|
||||||
|
application.set_accels_for_action(&action, &["<Ctrl>Left"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_accels(application: >k::Application) {
|
||||||
|
for action in Self::iter() {
|
||||||
|
application.set_accels_for_action(&action, &[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_actions_and_bindings(klass: &mut <super::imp::LpWindow as ObjectSubclass>::Class) {
|
||||||
|
for action in Self::iter() {
|
||||||
|
match action {
|
||||||
|
ActionPartGlobal::ImageLeftInstant => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
if win.direction() == gtk::TextDirection::Rtl {
|
||||||
|
win.imp().image_view.navigate(Direction::Forward, false);
|
||||||
|
} else {
|
||||||
|
win.imp().image_view.navigate(Direction::Back, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::Page_Down,
|
||||||
|
gdk::ModifierType::empty(),
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionPartGlobal::ImageRightInstant => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
if win.direction() == gtk::TextDirection::Rtl {
|
||||||
|
win.imp().image_view.navigate(Direction::Back, false);
|
||||||
|
} else {
|
||||||
|
win.imp().image_view.navigate(Direction::Forward, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::Page_Up,
|
||||||
|
gdk::ModifierType::empty(),
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pan
|
||||||
|
ActionPartGlobal::PanUp => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.pan(>k::PanDirection::Up);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ActionPartGlobal::PanRight => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.pan(>k::PanDirection::Right);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ActionPartGlobal::PanDown => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.pan(>k::PanDirection::Down);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ActionPartGlobal::PanLeft => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.pan(>k::PanDirection::Left);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(strum::Display, strum::AsRefStr, strum::EnumIter)]
|
||||||
|
pub enum Action {
|
||||||
|
// Navigation
|
||||||
|
#[strum(to_string = "win.image-left")]
|
||||||
|
ImageLeft,
|
||||||
|
#[strum(to_string = "win.image-right")]
|
||||||
|
ImageRight,
|
||||||
|
#[strum(to_string = "win.previous")]
|
||||||
|
Previous,
|
||||||
|
#[strum(to_string = "win.next")]
|
||||||
|
Next,
|
||||||
|
#[strum(to_string = "win.first")]
|
||||||
|
First,
|
||||||
|
#[strum(to_string = "win.last")]
|
||||||
|
Last,
|
||||||
|
// Zoom/Rotate
|
||||||
|
#[strum(to_string = "win.rotate-cw")]
|
||||||
|
RotateCw,
|
||||||
|
#[strum(to_string = "win.rotate-ccw")]
|
||||||
|
RotateCcw,
|
||||||
|
#[strum(to_string = "win.zoom-out-center")]
|
||||||
|
ZoomOutCenter,
|
||||||
|
#[strum(to_string = "win.zoom-in-center")]
|
||||||
|
ZoomInCenter,
|
||||||
|
#[strum(to_string = "win.zoom-out-cursor")]
|
||||||
|
ZoomOutCursor,
|
||||||
|
#[strum(to_string = "win.zoom-in-cursor")]
|
||||||
|
ZoomInCursor,
|
||||||
|
#[strum(to_string = "win.zoom-best-fit")]
|
||||||
|
ZoomBestFit,
|
||||||
|
#[strum(to_string = "win.zoom-to-exact-1")]
|
||||||
|
ZoomToExact1,
|
||||||
|
#[strum(to_string = "win.zoom-to-exact-2")]
|
||||||
|
ZoomToExact2,
|
||||||
|
// Misc
|
||||||
|
#[strum(to_string = "win.open")]
|
||||||
|
Open,
|
||||||
|
#[strum(to_string = "win.open-with")]
|
||||||
|
OpenWith,
|
||||||
|
#[strum(to_string = "win.print")]
|
||||||
|
Print,
|
||||||
|
#[strum(to_string = "win.copy-image")]
|
||||||
|
CopyImage,
|
||||||
|
#[strum(to_string = "win.set-background")]
|
||||||
|
SetBackground,
|
||||||
|
#[strum(to_string = "win.toggle-fullscreen")]
|
||||||
|
ToggleFullscreen,
|
||||||
|
#[strum(to_string = "win.leave-fullscreen")]
|
||||||
|
LeaveFullscreen,
|
||||||
|
#[strum(to_string = "win.trash")]
|
||||||
|
Trash,
|
||||||
|
#[strum(to_string = "win.delete")]
|
||||||
|
Delete,
|
||||||
|
#[strum(to_string = "win.toggle-properties")]
|
||||||
|
ToggleProperties,
|
||||||
|
#[strum(to_string = "win.about")]
|
||||||
|
About,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Action {
|
||||||
|
pub fn init_actions_and_bindings(klass: &mut <super::imp::LpWindow as ObjectSubclass>::Class) {
|
||||||
|
for action in Self::iter() {
|
||||||
|
match action {
|
||||||
|
// Navigation
|
||||||
|
Action::ImageLeft => klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
if win.direction() == gtk::TextDirection::Rtl {
|
||||||
|
win.imp().image_view.navigate(Direction::Forward, true);
|
||||||
|
} else {
|
||||||
|
win.imp().image_view.navigate(Direction::Back, true);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
Action::ImageRight => klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
if win.direction() == gtk::TextDirection::Rtl {
|
||||||
|
win.imp().image_view.navigate(Direction::Back, true);
|
||||||
|
} else {
|
||||||
|
win.imp().image_view.navigate(Direction::Forward, true);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
Action::Previous => klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.imp().image_view.navigate(Direction::Back, true);
|
||||||
|
}),
|
||||||
|
|
||||||
|
Action::Next => klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.imp().image_view.navigate(Direction::Forward, true);
|
||||||
|
}),
|
||||||
|
|
||||||
|
Action::First => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.imp().image_view.jump(Position::First);
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::Home, gdk::ModifierType::empty(), &action);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::Last => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.imp().image_view.jump(Position::Last);
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::End, gdk::ModifierType::empty(), &action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotation/Zoom
|
||||||
|
Action::RotateCw => {
|
||||||
|
klass.install_action(&action, None, |win, _, _| {
|
||||||
|
win.rotate_image(90.0);
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::r, gdk::ModifierType::CONTROL_MASK, &action);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::RotateCcw => {
|
||||||
|
klass.install_action(&action, None, |win, _, _| {
|
||||||
|
win.rotate_image(-90.0);
|
||||||
|
});
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::r,
|
||||||
|
gdk::ModifierType::CONTROL_MASK.union(gdk::ModifierType::SHIFT_MASK),
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ZoomOutCenter => klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.zoom_out_center();
|
||||||
|
}),
|
||||||
|
|
||||||
|
Action::ZoomInCenter => klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.zoom_in_center();
|
||||||
|
}),
|
||||||
|
|
||||||
|
Action::ZoomOutCursor => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.zoom_out_cursor();
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::minus, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::minus,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::KP_Subtract,
|
||||||
|
gdk::ModifierType::empty(),
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::KP_Subtract,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ZoomInCursor => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.zoom_in_cursor();
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::equal, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::equal,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
klass.add_binding_action(gdk::Key::plus, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::plus,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
klass.add_binding_action(gdk::Key::KP_Add, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::KP_Add,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ZoomBestFit => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.zoom_best_fit();
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::_0, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::_0,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
klass.add_binding_action(gdk::Key::KP_0, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::KP_0,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ZoomToExact1 => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.zoom_to_exact(1.);
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::_1, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(gdk::Key::KP_1, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::_1,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::KP_1,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ZoomToExact2 => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.zoom_to_exact(2.);
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::_2, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(gdk::Key::KP_2, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::_2,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::KP_2,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
Action::Open => {
|
||||||
|
klass.install_action_async(&action, None, |win, _, _| async move {
|
||||||
|
win.pick_file().await;
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::O, gdk::ModifierType::CONTROL_MASK, &action);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::OpenWith => {
|
||||||
|
klass.install_action_async(&action, None, |win, _, _| async move {
|
||||||
|
win.open_with().await;
|
||||||
|
});
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::O,
|
||||||
|
gdk::ModifierType::CONTROL_MASK.union(gdk::ModifierType::SHIFT_MASK),
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::Print => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.print();
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::P, gdk::ModifierType::CONTROL_MASK, &action);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::CopyImage => klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.copy_image();
|
||||||
|
}),
|
||||||
|
Action::SetBackground => {
|
||||||
|
klass.install_action_async(&action, None, |win, _, _| async move {
|
||||||
|
win.set_background().await;
|
||||||
|
});
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::F8,
|
||||||
|
gdk::ModifierType::CONTROL_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ToggleFullscreen => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.toggle_fullscreen(!win.is_fullscreened());
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::F11, gdk::ModifierType::empty(), &action);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::LeaveFullscreen => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.toggle_fullscreen(false);
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::Escape, gdk::ModifierType::empty(), &action);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::Trash => {
|
||||||
|
klass.install_action_async(&action, None, |win, _, _| async move {
|
||||||
|
win.trash().await;
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::Delete, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::KP_Delete,
|
||||||
|
gdk::ModifierType::empty(),
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::Delete => {
|
||||||
|
klass.install_action_async(&action, None, |win, _, _| async move {
|
||||||
|
win.delete().await;
|
||||||
|
});
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::Delete,
|
||||||
|
gdk::ModifierType::SHIFT_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::KP_Delete,
|
||||||
|
gdk::ModifierType::SHIFT_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ToggleProperties => {
|
||||||
|
klass.install_action(&action, None, move |win, _, _| {
|
||||||
|
win.imp()
|
||||||
|
.properties_button
|
||||||
|
.set_active(!win.imp().properties_button.is_active());
|
||||||
|
});
|
||||||
|
klass.add_binding_action(gdk::Key::F9, gdk::ModifierType::empty(), &action);
|
||||||
|
klass.add_binding_action(
|
||||||
|
gdk::Key::Return,
|
||||||
|
gdk::ModifierType::ALT_MASK,
|
||||||
|
&action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::About => {
|
||||||
|
klass.install_action_async(&action, None, |win, _, _| async move {
|
||||||
|
win.show_about().await
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for ActionPartGlobal {
|
||||||
|
type Target = str;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Action {
|
||||||
|
type Target = str;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue