From 87dd3b2243850d7fa65d3428726aeb085cb73700 Mon Sep 17 00:00:00 2001 From: Bilal Elmoussaoui Date: Sun, 25 Dec 2022 09:27:05 +0100 Subject: [PATCH] Replace some of the deprecated APIs --- Cargo.toml | 2 +- src/widgets/accounts/details.rs | 29 +++++++------ src/widgets/preferences/window.rs | 69 ++++++++++++++----------------- src/widgets/providers/page.rs | 45 ++++++++------------ src/widgets/window.rs | 2 +- 5 files changed, 65 insertions(+), 82 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7e1a87f..eff230b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ diesel_migrations = {version = "2.0", features = ["sqlite"]} gettext-rs = {version = "0.7", features = ["gettext-system"]} gst = {package = "gstreamer", version = "0.19"} gst4gtk = { package = "gst-plugin-gtk4", version = "0.9"} -gtk = {package = "gtk4", version = "0.5"} +gtk = {package = "gtk4", version = "0.5", features = ["v4_10"]} gtk-macros = "0.3" search-provider = "0.4" hex = { version = "0.4.3", features = [ "serde" ] } diff --git a/src/widgets/accounts/details.rs b/src/widgets/accounts/details.rs index 7804ff9..36ed74f 100644 --- a/src/widgets/accounts/details.rs +++ b/src/widgets/accounts/details.rs @@ -1,8 +1,8 @@ +use adw::prelude::*; use gettextrs::gettext; use gtk::{ gdk, glib::{self, clone}, - prelude::*, subclass::prelude::*, CompositeTemplate, }; @@ -161,21 +161,24 @@ impl AccountDetailsPage { fn delete_account(&self) { let parent = self.root().unwrap().downcast::().unwrap(); - let dialog = gtk::MessageDialog::builder() - .message_type(gtk::MessageType::Warning) - .buttons(gtk::ButtonsType::YesNo) - .text(&gettext("Are you sure you want to delete the account?")) - .secondary_text(&gettext("This action is irreversible")) + let dialog = adw::MessageDialog::builder() + .heading(&gettext("Are you sure you want to delete the account?")) + .body(&gettext("This action is irreversible")) .modal(true) .transient_for(&parent) .build(); - dialog.connect_response(clone!(@weak self as page => move |dialog, response| { - if response == gtk::ResponseType::Yes { - let account = page.imp().account.borrow().as_ref().unwrap().clone(); - page.emit_by_name::<()>("removed", &[&account]); - } - dialog.close(); - })); + dialog.add_responses(&[("no", &gettext("No")), ("yes", &gettext("Yes"))]); + dialog.set_response_appearance("yes", adw::ResponseAppearance::Destructive); + dialog.connect_response( + None, + clone!(@weak self as page => move |dialog, response| { + if response == "yes" { + let account = page.imp().account.borrow().as_ref().unwrap().clone(); + page.emit_by_name::<()>("removed", &[&account]); + } + dialog.close(); + }), + ); dialog.show(); } diff --git a/src/widgets/preferences/window.rs b/src/widgets/preferences/window.rs index 5023068..9640f55 100644 --- a/src/widgets/preferences/window.rs +++ b/src/widgets/preferences/window.rs @@ -39,7 +39,6 @@ mod imp { pub actions: gio::SimpleActionGroup, pub backup_actions: gio::SimpleActionGroup, pub restore_actions: gio::SimpleActionGroup, - pub file_chooser: RefCell>, pub camera_page: CameraPage, pub password_page: PasswordPage, #[template_child] @@ -82,7 +81,6 @@ mod imp { backup_group: TemplateChild::default(), restore_group: TemplateChild::default(), dark_mode_group: TemplateChild::default(), - file_chooser: RefCell::default(), key_entries: RefCell::default(), } } @@ -279,17 +277,16 @@ impl PreferencesWindow { imp.backup_actions, &T::identifier(), clone!(@weak self as win, @weak model => move |_, _| { - let dialog = win.select_file(filters, Operation::Backup); - dialog.connect_response(clone!(@weak model, @weak win => move |d, response| { - if response == gtk::ResponseType::Accept { + let ctx = glib::MainContext::default(); + ctx.spawn_local(clone!(@weak win, @weak model => async move { + if let Ok(Some(file)) = win.select_file(filters, Operation::Backup).await { let key = T::ENCRYPTABLE.then(|| { win.encyption_key(Operation::Backup, &T::identifier()) }).flatten(); - if let Err(err) = T::backup(&model, &d.file().unwrap(), key.as_deref()) { + if let Err(err) = T::backup(&model, &file, key.as_deref()) { tracing::warn!("Failed to create a backup {}", err); } } - d.destroy(); })); }) ); @@ -444,14 +441,14 @@ impl PreferencesWindow { imp.restore_actions, &T::identifier(), clone!(@weak self as win => move |_, _| { - let dialog = win.select_file(filters, Operation::Restore); - dialog.connect_response(clone!(@weak win => move |d, response| { - if response == gtk::ResponseType::Accept { + let ctx = glib::MainContext::default(); + ctx.spawn_local(clone!(@weak win => async move { + if let Ok(Some(file)) = win.select_file(filters, Operation::Restore).await { let key = T::ENCRYPTABLE.then(|| { win.encyption_key(Operation::Restore, &T::identifier()) }).flatten(); - match T::restore_from_file(&d.file().unwrap(), key.as_deref()) { + match T::restore_from_file(&file, key.as_deref()) { Ok(items) => { win.restore_items::(items); }, @@ -460,7 +457,6 @@ impl PreferencesWindow { } } } - d.destroy(); })); }) ); @@ -493,42 +489,37 @@ impl PreferencesWindow { self.close(); } - fn select_file( + async fn select_file( &self, filters: &'static [&str], operation: Operation, - ) -> gtk::FileChooserNative { - let native = match operation { - Operation::Backup => gtk::FileChooserNative::new( - Some(&gettext("Backup")), - gtk::Window::NONE, - gtk::FileChooserAction::Save, - Some(&gettext("Select")), - Some(&gettext("Cancel")), - ), - Operation::Restore => gtk::FileChooserNative::new( - Some(&gettext("Restore")), - gtk::Window::NONE, - gtk::FileChooserAction::Open, - Some(&gettext("Select")), - Some(&gettext("Cancel")), - ), - }; - - native.set_modal(true); - native.set_transient_for(Some(self)); - + ) -> Result, glib::Error> { + let filters_model = gio::ListStore::new(gtk::FileFilter::static_type()); filters.iter().for_each(|f| { let filter = gtk::FileFilter::new(); filter.add_mime_type(f); filter.set_name(Some(f)); - native.add_filter(&filter); + filters_model.append(&filter); }); - // Hold a reference to the file chooser - self.imp().file_chooser.replace(Some(native.clone())); - native.show(); - native + match operation { + Operation::Backup => { + let dialog = gtk::FileDialog::builder() + .modal(true) + .filters(&filters_model) + .title(&gettext("Backup")) + .build(); + dialog.save_future(Some(self), gio::File::NONE, None).await + } + Operation::Restore => { + let dialog = gtk::FileDialog::builder() + .modal(true) + .filters(&filters_model) + .title(&gettext("Restore")) + .build(); + dialog.open_future(Some(self), gio::File::NONE).await + } + } } fn setup_actions(&self) { diff --git a/src/widgets/providers/page.rs b/src/widgets/providers/page.rs index becfac4..023cce1 100644 --- a/src/widgets/providers/page.rs +++ b/src/widgets/providers/page.rs @@ -1,6 +1,6 @@ use adw::prelude::*; use gettextrs::gettext; -use glib::{clone, translate::IntoGlib}; +use glib::translate::IntoGlib; use gtk::{gdk_pixbuf, gio, glib, subclass::prelude::*, CompositeTemplate}; use crate::{ @@ -55,8 +55,6 @@ mod imp { #[template_child] pub delete_button: TemplateChild, pub selected_provider: RefCell>, - // We need to hold a reference to the native file chooser - pub file_chooser: RefCell>, pub selected_image: RefCell>, #[template_child] pub back_btn: TemplateChild, @@ -94,7 +92,6 @@ mod imp { methods_model, algorithms_model, selected_provider: RefCell::default(), - file_chooser: RefCell::default(), selected_image: RefCell::default(), } } @@ -119,8 +116,8 @@ mod imp { klass.install_action("providers.reset_image", None, move |page, _, _| { page.reset_image(); }); - klass.install_action("providers.select_image", None, move |page, _, _| { - page.open_select_image(); + klass.install_action_async("providers.select_image", None, |page, _, _| async move { + page.open_select_image().await; }); } @@ -304,34 +301,26 @@ impl ProviderPage { Ok(()) } - fn open_select_image(&self) { - let imp = self.imp(); + async fn open_select_image(&self) { let parent = self.root().unwrap().downcast::().unwrap(); - let file_chooser = gtk::FileChooserNative::builder() - .accept_label(&gettext("Select")) - .cancel_label(&gettext("Cancel")) - .modal(true) - .action(gtk::FileChooserAction::Open) - .transient_for(&parent) - .build(); - let images_filter = gtk::FileFilter::new(); images_filter.set_name(Some(&gettext("Image"))); images_filter.add_pixbuf_formats(); - file_chooser.add_filter(&images_filter); + let model = gio::ListStore::new(gtk::FileFilter::static_type()); + model.append(&images_filter); - file_chooser.connect_response(clone!(@weak self as page => move |dialog, response| { - if response == gtk::ResponseType::Accept { - let file = dialog.file().unwrap(); - page.set_image(file); - } - page.imp().file_chooser.replace(None); - dialog.destroy(); - })); + let file_chooser = gtk::FileDialog::builder() + .modal(true) + .filters(&model) + .build(); - file_chooser.show(); - imp.file_chooser.replace(Some(file_chooser)); + if let Ok(Some(file)) = file_chooser + .open_future(Some(&parent), gio::File::NONE) + .await + { + self.set_image(file); + }; } fn set_image(&self, file: gio::File) { @@ -367,7 +356,7 @@ impl ProviderPage { // save action Note that we don't validate the urls other than: does `url` // crate can parse it or not #[template_callback] - fn entry_validate(&self, _entry: gtk::Entry) { + fn entry_validate(&self, _entry: adw::EntryRow) { let imp = self.imp(); let provider_name = imp.name_entry.text(); diff --git a/src/widgets/window.rs b/src/widgets/window.rs index 73914d5..43c9665 100644 --- a/src/widgets/window.rs +++ b/src/widgets/window.rs @@ -173,7 +173,7 @@ impl Window { app.add_window(&window); if config::PROFILE == "Devel" { - window.style_context().add_class("devel"); + window.add_css_class("devel"); } window.init(model, app); window.setup_actions(app);