Drop usage of gtk-macros

This commit is contained in:
Bilal Elmoussaoui 2023-03-19 12:10:10 +01:00
parent a8607acea9
commit ed01da7f0c
6 changed files with 146 additions and 139 deletions

7
Cargo.lock generated
View file

@ -235,7 +235,6 @@ dependencies = [
"gettext-rs",
"gst-plugin-gtk4",
"gstreamer",
"gtk-macros",
"gtk4",
"hex",
"image 0.24.5",
@ -1571,12 +1570,6 @@ dependencies = [
"system-deps",
]
[[package]]
name = "gtk-macros"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da5bf7748fd4cd0b2490df8debcc911809dbcbee4ece9531b96c29a9c729de5a"
[[package]]
name = "gtk4"
version = "0.6.4"

View file

@ -14,7 +14,6 @@ gettext-rs = {version = "0.7", features = ["gettext-system"]}
gst = {package = "gstreamer", version = "0.20"}
gst4gtk = { package = "gst-plugin-gtk4", version = "0.10", features = ["wayland", "x11egl", "x11glx"]}
gtk = {package = "gtk4", version = "0.6", features = ["v4_10"]}
gtk-macros = "0.3"
search-provider = "0.5"
hex = { version = "0.4.3", features = [ "serde" ] }
tracing = "0.1"

View file

@ -2,7 +2,9 @@
<interface>
<template parent="AdwBin" class="CameraPage">
<property name="child">
<object class="Camera" id="camera"/>
<object class="Camera" id="camera">
<signal name="close" handler="on_camera_close" swapped="true" />
</object>
</property>
<child>
<object class="GtkShortcutController">

View file

@ -20,9 +20,11 @@ use crate::{utils::spawn_tokio, widgets::Camera};
mod imp {
use super::*;
#[derive(Debug, Default, CompositeTemplate)]
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
#[template(resource = "/com/belmoussaoui/Authenticator/preferences_camera_page.ui")]
#[properties(wrapper_type = super::CameraPage)]
pub struct CameraPage {
#[property(get, set, construct_only)]
pub actions: OnceCell<gio::SimpleActionGroup>,
#[template_child]
pub camera: TemplateChild<Camera>,
@ -36,6 +38,7 @@ mod imp {
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
klass.bind_template_instance_callbacks();
}
fn instance_init(obj: &InitializingObject<Self>) {
@ -43,7 +46,19 @@ mod imp {
}
}
impl ObjectImpl for CameraPage {}
impl ObjectImpl for CameraPage {
fn properties() -> &'static [glib::ParamSpec] {
Self::derived_properties()
}
fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
self.derived_set_property(id, value, pspec)
}
fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value {
self.derived_property(id, pspec)
}
}
impl WidgetImpl for CameraPage {}
impl BinImpl for CameraPage {}
@ -54,12 +69,10 @@ glib::wrapper! {
@extends gtk::Widget, adw::Bin;
}
#[gtk::template_callbacks]
impl CameraPage {
pub fn new(actions: gio::SimpleActionGroup) -> Self {
let page = glib::Object::new::<Self>();
page.imp().actions.set(actions).unwrap();
page.setup_widget();
page
pub fn new(actions: &gio::SimpleActionGroup) -> Self {
glib::Object::builder().property("actions", actions).build()
}
pub async fn scan_from_camera(&self) -> Result<String> {
@ -171,12 +184,8 @@ impl CameraPage {
}
}
fn setup_widget(&self) {
let imp = self.imp();
let actions = imp.actions.get().unwrap();
imp.camera.connect_close(clone!(@weak actions => move |_| {
actions.activate_action("close_page", None);
}));
#[template_callback]
fn on_camera_close(&self) {
self.actions().activate_action("close_page", None);
}
}

View file

@ -3,15 +3,15 @@ use std::cell::{Cell, RefCell};
use gettextrs::gettext;
use gtk::{
gio,
glib::{self, clone, subclass::InitializingObject},
glib::{self, clone},
prelude::*,
subclass::prelude::*,
};
use gtk_macros::{action, get_action};
use crate::{config, models::keyring, utils::spawn_tokio, widgets::ErrorRevealer};
mod imp {
use glib::subclass::InitializingObject;
use once_cell::sync::OnceCell;
use super::*;
@ -20,6 +20,7 @@ mod imp {
#[properties(wrapper_type = super::PasswordPage)]
#[template(resource = "/com/belmoussaoui/Authenticator/preferences_password_page.ui")]
pub struct PasswordPage {
#[property(get, set, construct_only)]
pub actions: OnceCell<gio::SimpleActionGroup>,
#[property(get, set, construct)]
pub has_set_password: Cell<bool>,
@ -68,6 +69,7 @@ mod imp {
fn constructed(&self) {
self.parent_constructed();
let page = self.obj();
page.setup_actions();
self.status_page.set_icon_name(Some(config::APP_ID));
page.reset_validation();
// Reset the validation whenever the password state changes
@ -94,11 +96,8 @@ glib::wrapper! {
#[gtk::template_callbacks]
impl PasswordPage {
pub fn new(actions: gio::SimpleActionGroup) -> Self {
let page = glib::Object::new::<Self>();
page.imp().actions.set(actions).unwrap();
page.setup_actions();
page
pub fn new(actions: &gio::SimpleActionGroup) -> Self {
glib::Object::builder().property("actions", actions).build()
}
#[template_callback]
@ -115,7 +114,12 @@ impl PasswordPage {
password_repeat == password && password != ""
};
get_action!(imp.actions.get().unwrap(), @save_password).set_enabled(is_valid);
let save_password_action = self
.actions()
.lookup_action("save_password")
.and_downcast::<gio::SimpleAction>()
.unwrap();
save_password_action.set_enabled(is_valid);
}
// Called when either the user sets/resets the password to bind/unbind the
@ -131,39 +135,35 @@ impl PasswordPage {
}
fn setup_actions(&self) {
let imp = self.imp();
let actions = imp.actions.get().unwrap();
action!(
actions,
"save_password",
clone!(@weak self as page => move |_, _| {
let actions = self.actions();
let save_password = gio::ActionEntry::builder("save_password")
.activate(clone!(@weak self as page => move |_, _, _| {
let ctx = glib::MainContext::default();
ctx.spawn_local(clone!(@weak page => async move {
page.save().await;
}));
})
);
action!(
actions,
"reset_password",
clone!(@weak self as page => move |_,_| {
}))
.build();
let reset_password = gio::ActionEntry::builder("reset_password")
.activate(clone!(@weak self as page => move |_, _, _| {
let ctx = glib::MainContext::default();
ctx.spawn_local(clone!(@weak page => async move {
page.reset_password().await;
}));
})
);
get_action!(actions, @save_password).set_enabled(false);
}))
.build();
actions.add_action_entries([save_password, reset_password]);
self.bind_property(
"has-set-password",
&get_action!(actions, @reset_password),
"enabled",
)
.sync_create()
.build();
let save_password_action = actions
.lookup_action("save_password")
.and_downcast::<gio::SimpleAction>()
.unwrap();
save_password_action.set_enabled(false);
let reset_password_action = actions.lookup_action("reset_password").unwrap();
self.bind_property("has-set-password", &reset_password_action, "enabled")
.sync_create()
.build();
}
async fn reset_password(&self) {
@ -183,11 +183,15 @@ impl PasswordPage {
spawn_tokio(async move { keyring::reset_password().await.is_ok() }).await;
if password_was_reset {
let imp = self.imp();
let actions = imp.actions.get().unwrap();
let actions = self.actions();
actions.activate_action("close_page", None);
get_action!(actions, @close_page).activate(None);
get_action!(actions, @save_password).set_enabled(false);
let save_password_action = actions
.lookup_action("save_password")
.and_downcast::<gio::SimpleAction>()
.unwrap();
save_password_action.set_enabled(false);
self.set_has_set_password(false);
}
}
@ -202,7 +206,7 @@ impl PasswordPage {
async fn save(&self) {
let imp = self.imp();
let actions = imp.actions.get().unwrap();
let actions = self.actions();
let current_password = imp.current_password_entry.text();
let password = imp.password_entry.text();
@ -221,9 +225,14 @@ impl PasswordPage {
spawn_tokio(async move { keyring::set_password(&password).await.is_ok() }).await;
if password_was_set {
self.reset();
get_action!(actions, @save_password).set_enabled(false);
let save_password_action = actions
.lookup_action("save_password")
.and_downcast::<gio::SimpleAction>()
.unwrap();
save_password_action.set_enabled(false);
self.set_has_set_password(true);
get_action!(actions, @close_page).activate(None);
actions.activate_action("close_page", None);
}
}
}

View file

@ -2,7 +2,6 @@ use adw::prelude::*;
use gettextrs::gettext;
use glib::clone;
use gtk::{gio, glib, subclass::prelude::*};
use gtk_macros::{action, get_action, spawn};
use once_cell::sync::OnceCell;
use super::{camera_page::CameraPage, password_page::PasswordPage};
@ -69,8 +68,8 @@ mod imp {
Self {
has_set_password: Cell::default(), // Synced from the application
camera_page: CameraPage::new(actions.clone()),
password_page: PasswordPage::new(actions.clone()),
camera_page: CameraPage::new(&actions),
password_page: PasswordPage::new(&actions),
actions,
model: OnceCell::default(),
backup_actions: gio::SimpleActionGroup::new(),
@ -249,13 +248,11 @@ impl PreferencesWindow {
imp.backup_group.add(&row);
}
let model = imp.model.get().unwrap().clone();
action!(
imp.backup_actions,
&T::identifier(),
clone!(@weak self as win, @weak model => move |_, _| {
let action = gio::ActionEntry::builder(&T::identifier())
.activate(clone!(@weak self as win => move |_, _,_| {
let ctx = glib::MainContext::default();
ctx.spawn_local(clone!(@weak win, @weak model => async move {
ctx.spawn_local(clone!(@weak win => async move {
let model = win.model();
if let Ok(file) = win.select_file(filters, Operation::Backup).await {
let key = T::ENCRYPTABLE.then(|| {
win.encyption_key(Operation::Backup, &T::identifier())
@ -265,8 +262,9 @@ impl PreferencesWindow {
}
}
}));
})
);
}))
.build();
imp.backup_actions.add_action_entries([action]);
}
fn register_restore<T: Restorable>(&self, filters: &'static [&str]) {
@ -351,13 +349,12 @@ impl PreferencesWindow {
imp.restore_group.add(&row);
}
if T::SCANNABLE {
action!(
imp.restore_actions,
&format!("{}.camera", T::identifier()),
clone!(@weak self as win, @weak imp.camera_page as camera_page => move |_, _| {
get_action!(win.imp().actions, @show_camera_page).activate(None);
spawn!(async move {
match camera_page.scan_from_camera().await {
let camera_action = gio::ActionEntry::builder(&format!("{}.camera", T::identifier()))
.activate(clone!(@weak self as win=> move |_, _, _| {
win.imp().actions.activate_action("show_camera_page", None);
let ctx = glib::MainContext::default();
ctx.spawn_local(clone!(@weak win => async move {
match win.imp().camera_page.scan_from_camera().await {
Ok(code) => match T::restore_from_data(code.as_bytes(), None) {
Ok(items) => win.restore_items::<T, T::Item>(items),
Err(error) => {
@ -366,7 +363,7 @@ impl PreferencesWindow {
"scanned QR code: {}",
), error);
get_action!(win.imp().actions, @close_page).activate(None);
win.imp().actions.activate_action("close_page", None);
win.add_toast(adw::Toast::new(&gettext("Unable to restore accounts")));
},
@ -377,47 +374,44 @@ impl PreferencesWindow {
error,
);
get_action!(win.imp().actions, @close_page).activate(None);
win.imp().actions.activate_action("close_page", None);
win.add_toast(adw::Toast::new(&gettext("Something went wrong")));
},
}
});
})
);
action!(
imp.restore_actions,
&format!("{}.screenshot", T::identifier()),
clone!(@weak self as win, @weak imp.camera_page as camera_page => move |_, _| {
spawn!(async move {
match camera_page.scan_from_screenshot().await {
Ok(code) => match T::restore_from_data(code.as_bytes(), None) {
Ok(items) => {
win.restore_items::<T, T::Item>(items);
},
Err(error) => {
tracing::error!(concat!(
"Encountered an error while trying to restore from a ",
"scanned QR code: {}",
), error);
win.add_toast(adw::Toast::new(&gettext("Unable to restore accounts")));
},
}));
})).build();
let screenshot_action = gio::ActionEntry::builder(&format!("{}.screenshot", T::identifier()))
.activate(clone!(@weak self as win => move |_, _, _| {
let ctx = glib::MainContext::default();
ctx.spawn_local(clone!(@weak win => async move {
match win.imp().camera_page.scan_from_screenshot().await {
Ok(code) => match T::restore_from_data(code.as_bytes(), None) {
Ok(items) => {
win.restore_items::<T, T::Item>(items);
},
Err(error) => {
tracing::error!("Encountered an error while trying to scan from the screenshot: {}", error);
tracing::error!(concat!(
"Encountered an error while trying to restore from a ",
"scanned QR code: {}",
), error);
win.add_toast(adw::Toast::new(&gettext("Couldn't find a QR code")));
win.add_toast(adw::Toast::new(&gettext("Unable to restore accounts")));
},
}
});
})
);
},
Err(error) => {
tracing::error!("Encountered an error while trying to scan from the screenshot: {}", error);
win.add_toast(adw::Toast::new(&gettext("Couldn't find a QR code")));
},
}
}));
})).build();
imp.restore_actions
.add_action_entries([camera_action, screenshot_action]);
} else {
action!(
imp.restore_actions,
&T::identifier(),
clone!(@weak self as win => move |_, _| {
let action = gio::ActionEntry::builder(&T::identifier())
.activate(clone!(@weak self as win => move |_, _, _| {
let ctx = glib::MainContext::default();
ctx.spawn_local(clone!(@weak win => async move {
if let Ok(file) = win.select_file(filters, Operation::Restore).await {
@ -435,9 +429,11 @@ impl PreferencesWindow {
}
}
}));
})
);
}
}))
.build();
imp.restore_actions.add_action_entries([action]);
};
}
fn encyption_key(&self, mode: Operation, identifier: &str) -> Option<glib::GString> {
@ -453,10 +449,10 @@ impl PreferencesWindow {
}
fn restore_items<T: Restorable<Item = Q>, Q: RestorableItem>(&self, items: Vec<Q>) {
let model = self.imp().model.get().unwrap();
let model = self.model();
items
.iter()
.map(move |item| item.restore(model))
.map(move |item| item.restore(&model))
.for_each(|item| {
if let Err(err) = item {
tracing::warn!("Failed to restore item {}", err);
@ -522,28 +518,27 @@ impl PreferencesWindow {
win.set_search_enabled(true);
}));
action!(
imp.actions,
"show_camera_page",
clone!(@weak self as win, @weak imp.camera_page as camera_page => move |_, _| {
win.present_subpage(&camera_page);
})
);
action!(
imp.actions,
"show_password_page",
clone!(@weak self as win, @weak imp.password_page as password_page => move |_, _| {
win.present_subpage(&password_page);
})
);
action!(
imp.actions,
"close_page",
clone!(@weak self as win, @weak imp.camera_page as camera_page => move |_, _| {
let show_camera_page = gio::ActionEntry::builder("show_camera_page")
.activate(clone!(@weak self as win => move |_, _, _| {
win.present_subpage(&win.imp().camera_page);
}))
.build();
let show_password_page = gio::ActionEntry::builder("show_password_page")
.activate(clone!(@weak self as win => move |_, _, _| {
win.present_subpage(&win.imp().password_page);
}))
.build();
let close_page = gio::ActionEntry::builder("close_page")
.activate(clone!(@weak self as win => move |_, _, _| {
win.close_subpage();
camera_page.imp().camera.stop();
})
);
win.imp().camera_page.imp().camera.stop();
}))
.build();
imp.actions
.add_action_entries([show_camera_page, show_password_page, close_page]);
self.insert_action_group("preferences", Some(&imp.actions));
self.insert_action_group("backup", Some(&imp.backup_actions));