move TypePriv inside imp

This commit is contained in:
Bilal Elmoussaoui 2020-12-09 06:09:29 +01:00
parent 882d4db477
commit aaee00a511
6 changed files with 587 additions and 621 deletions

View file

@ -4,213 +4,222 @@ use crate::models::ProvidersModel;
use crate::widgets::{PreferencesWindow, ProvidersDialog, Window};
use gettextrs::gettext;
use gio::prelude::*;
use glib::subclass::prelude::*;
use glib::{subclass, WeakRef};
use gio::subclass::ObjectSubclass;
use gtk::prelude::*;
use gtk::subclass::prelude::{ApplicationImpl, ApplicationImplExt, GtkApplicationImpl};
use std::cell::{Cell, RefCell};
use std::env;
pub struct ApplicationPrivate {
window: RefCell<Option<WeakRef<Window>>>,
model: ProvidersModel,
locked: Cell<bool>,
can_be_locked: Cell<bool>,
}
static PROPERTIES: [subclass::Property; 2] = [
subclass::Property("locked", |name| {
glib::ParamSpec::boolean(name, "locked", "locked", false, glib::ParamFlags::READWRITE)
}),
subclass::Property("can-be-locked", |name| {
glib::ParamSpec::boolean(
name,
"can_be_locked",
"can be locked",
false,
glib::ParamFlags::READWRITE,
)
}),
];
impl ObjectSubclass for ApplicationPrivate {
const NAME: &'static str = "Application";
type ParentType = gtk::Application;
type Type = super::Application;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
mod imp {
use super::*;
use glib::subclass::prelude::*;
use glib::{subclass, WeakRef};
use gtk::subclass::prelude::{ApplicationImpl, ApplicationImplExt, GtkApplicationImpl};
use std::cell::{Cell, RefCell};
glib_object_subclass!();
fn class_init(klass: &mut Self::Class) {
klass.install_properties(&PROPERTIES);
pub struct Application {
pub window: RefCell<Option<WeakRef<Window>>>,
pub model: ProvidersModel,
pub locked: Cell<bool>,
pub can_be_locked: Cell<bool>,
}
fn new() -> Self {
let model = ProvidersModel::new();
static PROPERTIES: [subclass::Property; 2] = [
subclass::Property("locked", |name| {
glib::ParamSpec::boolean(name, "locked", "locked", false, glib::ParamFlags::READWRITE)
}),
subclass::Property("can-be-locked", |name| {
glib::ParamSpec::boolean(
name,
"can_be_locked",
"can be locked",
false,
glib::ParamFlags::READWRITE,
)
}),
];
impl ObjectSubclass for Application {
const NAME: &'static str = "Application";
type ParentType = gtk::Application;
type Type = super::Application;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
Self {
window: RefCell::new(None),
model,
can_be_locked: Cell::new(false),
locked: Cell::new(false),
glib_object_subclass!();
fn class_init(klass: &mut Self::Class) {
klass.install_properties(&PROPERTIES);
}
}
}
impl ObjectImpl for ApplicationPrivate {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
fn new() -> Self {
let model = ProvidersModel::new();
match *prop {
subclass::Property("locked", ..) => {
let locked = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.locked.set(locked);
Self {
window: RefCell::new(None),
model,
can_be_locked: Cell::new(false),
locked: Cell::new(false),
}
subclass::Property("can-be-locked", ..) => {
let can_be_locked = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.can_be_locked.set(can_be_locked);
}
}
impl ObjectImpl for Application {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("locked", ..) => {
let locked = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.locked.set(locked);
}
subclass::Property("can-be-locked", ..) => {
let can_be_locked = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.can_be_locked.set(can_be_locked);
}
_ => unimplemented!(),
}
}
fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("locked", ..) => self.locked.get().to_value(),
subclass::Property("can-be-locked", ..) => self.can_be_locked.get().to_value(),
_ => unimplemented!(),
}
_ => unimplemented!(),
}
}
fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
let prop = &PROPERTIES[id];
impl GtkApplicationImpl for Application {}
impl ApplicationImpl for Application {
fn startup(&self, app: &Self::Type) {
self.parent_startup(app);
match *prop {
subclass::Property("locked", ..) => self.locked.get().to_value(),
subclass::Property("can-be-locked", ..) => self.can_be_locked.get().to_value(),
_ => unimplemented!(),
}
}
}
libhandy::functions::init();
impl GtkApplicationImpl for ApplicationPrivate {}
impl ApplicationImpl for ApplicationPrivate {
fn startup(&self, app: &Self::Type) {
self.parent_startup(app);
let app = app.downcast_ref::<super::Application>().unwrap();
if let Some(ref display) = gdk::Display::get_default() {
let p = gtk::CssProvider::new();
gtk::CssProvider::load_from_resource(
&p,
"/com/belmoussaoui/Authenticator/style.css",
);
gtk::StyleContext::add_provider_for_display(display, &p, 500);
let theme = gtk::IconTheme::get_for_display(display).unwrap();
theme.add_resource_path("/com/belmoussaoui/Authenticator/icons/");
}
libhandy::functions::init();
action!(app, "quit", clone!(@weak app => move |_, _| app.quit()));
let app = app.downcast_ref::<Application>().unwrap();
if let Some(ref display) = gdk::Display::get_default() {
let p = gtk::CssProvider::new();
gtk::CssProvider::load_from_resource(&p, "/com/belmoussaoui/Authenticator/style.css");
gtk::StyleContext::add_provider_for_display(display, &p, 500);
let theme = gtk::IconTheme::get_for_display(display).unwrap();
theme.add_resource_path("/com/belmoussaoui/Authenticator/icons/");
action!(
app,
"preferences",
clone!(@weak app, @weak self.model as model => move |_,_| {
let active_window = app.get_active_window().unwrap();
let win = active_window.downcast_ref::<Window>().unwrap();
let preferences = PreferencesWindow::new(model);
preferences.connect_local("restore-completed", false, clone!(@weak win => move |_| {
win.providers().refilter();
None
}));
preferences.set_transient_for(Some(&active_window));
preferences.show();
})
);
// About
action!(
app,
"about",
clone!(@weak app => move |_, _| {
let window = app.get_active_window().unwrap();
let about_dialog = gtk::AboutDialogBuilder::new()
.program_name(&gettext("Authenticator"))
.modal(true)
.version(config::VERSION)
.comments(&gettext("Generate Two-Factor codes"))
.website("https://gitlab.gnome.org/World/Authenticator")
.authors(vec!["Bilal Elmoussaoui".to_string()])
.artists(vec!["Alexandros Felekidis".to_string(), "Tobias Bernard".to_string()])
.translator_credits(&gettext("translator-credits"))
.logo_icon_name(config::APP_ID)
.license_type(gtk::License::Gpl30)
.transient_for(&window)
.build();
about_dialog.show();
})
);
action!(
app,
"providers",
clone!(@weak app, @weak self.model as model => move |_, _| {
let window = app.get_active_window().unwrap();
let providers = ProvidersDialog::new(model);
providers.set_transient_for(Some(&window));
providers.show();
})
);
action!(
app,
"lock",
clone!(@weak app => move |_, _| {
app.set_locked(true);
})
);
app.bind_property("can-be-locked", &get_action!(app, @lock), "enabled")
.flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE)
.build();
app.bind_property("locked", &get_action!(app, @preferences), "enabled")
.flags(glib::BindingFlags::INVERT_BOOLEAN | glib::BindingFlags::SYNC_CREATE)
.build();
app.bind_property("locked", &get_action!(app, @providers), "enabled")
.flags(glib::BindingFlags::INVERT_BOOLEAN | glib::BindingFlags::SYNC_CREATE)
.build();
}
action!(app, "quit", clone!(@weak app => move |_, _| app.quit()));
fn activate(&self, app: &Self::Type) {
if let Some(ref win) = *self.window.borrow() {
let window = win.upgrade().unwrap();
window.present();
return;
}
action!(
app,
"preferences",
clone!(@weak app, @weak self.model as model => move |_,_| {
let active_window = app.get_active_window().unwrap();
let win = active_window.downcast_ref::<Window>().unwrap();
let preferences = PreferencesWindow::new(model);
preferences.connect_local("restore-completed", false, clone!(@weak win => move |_| {
win.providers().refilter();
None
}));
preferences.set_transient_for(Some(&active_window));
preferences.show();
})
);
// About
action!(
app,
"about",
clone!(@weak app => move |_, _| {
let window = app.get_active_window().unwrap();
let about_dialog = gtk::AboutDialogBuilder::new()
.program_name(&gettext("Authenticator"))
.modal(true)
.version(config::VERSION)
.comments(&gettext("A Two-Factor Authentication application"))
.website("https://gitlab.gnome.org/World/Authenticator")
.authors(vec!["Bilal Elmoussaoui".to_string()])
.artists(vec!["Alexandros Felekidis".to_string(), "Tobias Bernard".to_string()])
.translator_credits(&gettext("translator-credits"))
.logo_icon_name(config::APP_ID)
.license_type(gtk::License::Gpl30)
.transient_for(&window)
.build();
about_dialog.show();
})
);
action!(
app,
"providers",
clone!(@weak app, @weak self.model as model => move |_, _| {
let window = app.get_active_window().unwrap();
let providers = ProvidersDialog::new(model);
providers.set_transient_for(Some(&window));
providers.show();
})
);
action!(
app,
"lock",
clone!(@weak app => move |_, _| {
app.set_locked(true);
})
);
app.bind_property("can-be-locked", &get_action!(app, @lock), "enabled")
.flags(glib::BindingFlags::DEFAULT | glib::BindingFlags::SYNC_CREATE)
.build();
app.bind_property("locked", &get_action!(app, @preferences), "enabled")
.flags(glib::BindingFlags::INVERT_BOOLEAN | glib::BindingFlags::SYNC_CREATE)
.build();
app.bind_property("locked", &get_action!(app, @providers), "enabled")
.flags(glib::BindingFlags::INVERT_BOOLEAN | glib::BindingFlags::SYNC_CREATE)
.build();
}
fn activate(&self, app: &Self::Type) {
if let Some(ref win) = *self.window.borrow() {
let window = win.upgrade().unwrap();
let app = app.downcast_ref::<super::Application>().unwrap();
let window = app.create_window();
window.present();
return;
self.window.replace(Some(window.downgrade()));
Keyring::ensure_unlocked()
.expect("Authenticator couldn't reach a secret service provider or unlock it");
let has_set_password = Keyring::has_set_password().unwrap_or_else(|_| false);
app.set_resource_base_path(Some("/com/belmoussaoui/Authenticator"));
app.set_accels_for_action("app.quit", &["<primary>q"]);
app.set_accels_for_action("app.lock", &["<primary>l"]);
app.set_accels_for_action("app.providers", &["<primary>p"]);
app.set_accels_for_action("app.preferences", &["<primary>comma"]);
app.set_accels_for_action("win.show-help-overlay", &["<primary>question"]);
app.set_accels_for_action("win.search", &["<primary>f"]);
app.set_accels_for_action("win.add-account", &["<primary>n"]);
app.set_accels_for_action("add.scan-qr", &["<primary>t"]);
app.set_locked(has_set_password);
app.set_can_be_locked(has_set_password);
}
let app = app.downcast_ref::<Application>().unwrap();
let window = app.create_window();
window.present();
self.window.replace(Some(window.downgrade()));
Keyring::ensure_unlocked()
.expect("Authenticator couldn't reach a secret service provider or unlock it");
let has_set_password = Keyring::has_set_password().unwrap_or_else(|_| false);
app.set_resource_base_path(Some("/com/belmoussaoui/Authenticator"));
app.set_accels_for_action("app.quit", &["<primary>q"]);
app.set_accels_for_action("app.lock", &["<primary>l"]);
app.set_accels_for_action("app.providers", &["<primary>p"]);
app.set_accels_for_action("app.preferences", &["<primary>comma"]);
app.set_accels_for_action("win.show-help-overlay", &["<primary>question"]);
app.set_accels_for_action("win.search", &["<primary>f"]);
app.set_accels_for_action("win.add-account", &["<primary>n"]);
app.set_accels_for_action("add.scan-qr", &["<primary>t"]);
app.set_locked(has_set_password);
app.set_can_be_locked(has_set_password);
}
}
glib_wrapper! {
pub struct Application(ObjectSubclass<ApplicationPrivate>)
pub struct Application(ObjectSubclass<imp::Application>)
@extends gio::Application, gtk::Application, gio::ActionMap;
}
@ -236,7 +245,7 @@ impl Application {
}
pub fn locked(&self) -> bool {
let self_ = ApplicationPrivate::from_instance(self);
let self_ = imp::Application::from_instance(self);
return self_.locked.get();
}
@ -251,7 +260,7 @@ impl Application {
}
fn create_window(&self) -> Window {
let self_ = ApplicationPrivate::from_instance(self);
let self_ = imp::Application::from_instance(self);
let window = Window::new(self_.model.clone(), &self.clone());
window

View file

@ -9,8 +9,7 @@ use anyhow::Result;
use byteorder::{BigEndian, ReadBytesExt};
use core::cmp::Ordering;
use diesel::{BelongingToDsl, ExpressionMethods, QueryDsl, RunQueryDsl};
use gio::FileExt;
use glib::subclass::{self, prelude::*};
use gio::{subclass::ObjectSubclass, FileExt};
use glib::{Cast, ObjectExt, StaticType, ToValue};
use once_cell::sync::OnceCell;
use qrcode::QrCode;
@ -38,164 +37,150 @@ pub struct DiAccount {
pub provider_id: i32,
}
pub struct AccountPriv {
pub id: Cell<i32>,
pub otp: RefCell<String>,
pub name: RefCell<String>,
pub counter: Cell<i32>,
pub token: OnceCell<String>,
pub token_id: RefCell<String>,
pub provider: RefCell<Option<Provider>>,
}
mod imp {
use super::*;
use glib::subclass::{self, prelude::*};
static PROPERTIES: [subclass::Property; 6] = [
subclass::Property("id", |name| {
glib::ParamSpec::int(
name,
"id",
"Id",
0,
i32::MAX,
0,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("counter", |name| {
glib::ParamSpec::int(
name,
"counter",
"Counter",
0,
i32::MAX,
0,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("name", |name| {
glib::ParamSpec::string(name, "name", "Name", None, glib::ParamFlags::READWRITE)
}),
subclass::Property("token-id", |name| {
glib::ParamSpec::string(
name,
"token-id",
"token id",
None,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("otp", |name| {
glib::ParamSpec::string(
name,
"otp",
"The One Time Password",
None,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("provider", |name| {
glib::ParamSpec::object(
name,
"provider",
"The account provider",
Provider::static_type(),
glib::ParamFlags::READWRITE,
)
}),
];
impl ObjectSubclass for AccountPriv {
const NAME: &'static str = "Account";
type Type = super::Account;
type ParentType = glib::Object;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
fn class_init(klass: &mut Self::Class) {
klass.install_properties(&PROPERTIES);
static PROPERTIES: [subclass::Property; 6] = [
subclass::Property("id", |name| {
glib::ParamSpec::int(
name,
"id",
"Id",
0,
i32::MAX,
0,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("counter", |name| {
glib::ParamSpec::int(
name,
"counter",
"Counter",
0,
i32::MAX,
0,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("name", |name| {
glib::ParamSpec::string(name, "name", "Name", None, glib::ParamFlags::READWRITE)
}),
subclass::Property("token-id", |name| {
glib::ParamSpec::string(
name,
"token-id",
"token id",
None,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("otp", |name| {
glib::ParamSpec::string(
name,
"otp",
"The One Time Password",
None,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("provider", |name| {
glib::ParamSpec::object(
name,
"provider",
"The account provider",
Provider::static_type(),
glib::ParamFlags::READWRITE,
)
}),
];
pub struct Account {
pub id: Cell<i32>,
pub otp: RefCell<String>,
pub name: RefCell<String>,
pub counter: Cell<i32>,
pub token: OnceCell<String>,
pub token_id: RefCell<String>,
pub provider: RefCell<Option<Provider>>,
}
fn new() -> Self {
Self {
id: Cell::new(0),
counter: Cell::new(1),
name: RefCell::new("".to_string()),
otp: RefCell::new("".to_string()),
token_id: RefCell::new("".to_string()),
provider: RefCell::new(None),
token: OnceCell::new(),
impl ObjectSubclass for Account {
const NAME: &'static str = "Account";
type Type = super::Account;
type ParentType = glib::Object;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
fn class_init(klass: &mut Self::Class) {
klass.install_properties(&PROPERTIES);
}
}
}
impl ObjectImpl for AccountPriv {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("id", ..) => {
let id = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.id.replace(id);
fn new() -> Self {
Self {
id: Cell::new(0),
counter: Cell::new(1),
name: RefCell::new("".to_string()),
otp: RefCell::new("".to_string()),
token_id: RefCell::new("".to_string()),
provider: RefCell::new(None),
token: OnceCell::new(),
}
subclass::Property("name", ..) => {
let name = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.name.replace(name);
}
subclass::Property("counter", ..) => {
let counter = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.counter.replace(counter);
}
subclass::Property("otp", ..) => {
let otp = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.otp.replace(otp);
}
subclass::Property("token-id", ..) => {
let token_id = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.token_id.replace(token_id);
}
subclass::Property("provider", ..) => {
let provider = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.provider.replace(provider);
}
_ => unimplemented!(),
}
}
fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
let prop = &PROPERTIES[id];
impl ObjectImpl for Account {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("id", ..) => self.id.get().to_value(),
subclass::Property("name", ..) => self.name.borrow().to_value(),
subclass::Property("counter", ..) => self.counter.get().to_value(),
subclass::Property("otp", ..) => self.otp.borrow().to_value(),
subclass::Property("token-id", ..) => self.token_id.borrow().to_value(),
subclass::Property("provider", ..) => self.provider.borrow().to_value(),
_ => unimplemented!(),
match *prop {
subclass::Property("id", ..) => {
let id = value.get().unwrap().unwrap();
self.id.replace(id);
}
subclass::Property("name", ..) => {
let name = value.get().unwrap().unwrap();
self.name.replace(name);
}
subclass::Property("counter", ..) => {
let counter = value.get().unwrap().unwrap();
self.counter.replace(counter);
}
subclass::Property("otp", ..) => {
let otp = value.get().unwrap().unwrap();
self.otp.replace(otp);
}
subclass::Property("token-id", ..) => {
let token_id = value.get().unwrap().unwrap();
self.token_id.replace(token_id);
}
subclass::Property("provider", ..) => {
let provider = value.get().unwrap();
self.provider.replace(provider);
}
_ => unimplemented!(),
}
}
fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("id", ..) => self.id.get().to_value(),
subclass::Property("name", ..) => self.name.borrow().to_value(),
subclass::Property("counter", ..) => self.counter.get().to_value(),
subclass::Property("otp", ..) => self.otp.borrow().to_value(),
subclass::Property("token-id", ..) => self.token_id.borrow().to_value(),
subclass::Property("provider", ..) => self.provider.borrow().to_value(),
_ => unimplemented!(),
}
}
}
}
glib_wrapper! {
pub struct Account(ObjectSubclass<AccountPriv>);
pub struct Account(ObjectSubclass<imp::Account>);
}
impl Account {
@ -274,8 +259,8 @@ impl Account {
.expect("Created account is of wrong type");
let token = Keyring::token(token_id).unwrap().unwrap();
let priv_ = AccountPriv::from_instance(&account);
priv_.token.set(token);
let self_ = imp::Account::from_instance(&account);
self_.token.set(token);
account.init();
account
@ -326,9 +311,9 @@ impl Account {
fn increment_counter(&self) -> Result<()> {
// For security reasons, never re-use the same counter for HOTP
let priv_ = AccountPriv::from_instance(self);
let self_ = imp::Account::from_instance(self);
let new_value = self.counter() + 1;
priv_.counter.set(new_value);
self_.counter.set(new_value);
let db = database::connection();
let conn = db.get()?;
@ -343,8 +328,8 @@ impl Account {
pub fn copy_otp(&self) {
let display = gdk::Display::get_default().unwrap();
let clipboard = display.get_clipboard();
let priv_ = AccountPriv::from_instance(self);
clipboard.set_text(&priv_.otp.borrow());
let self_ = imp::Account::from_instance(self);
clipboard.set_text(&self_.otp.borrow());
// Indirectly increment the counter once the token was copied
if self.provider().method() == OTPMethod::HOTP {
@ -353,8 +338,8 @@ impl Account {
}
pub fn id(&self) -> i32 {
let priv_ = AccountPriv::from_instance(self);
priv_.id.get()
let self_ = imp::Account::from_instance(self);
self_.id.get()
}
pub fn provider(&self) -> Provider {
@ -363,23 +348,23 @@ impl Account {
}
pub fn counter(&self) -> i32 {
let priv_ = AccountPriv::from_instance(self);
priv_.counter.get()
let self_ = imp::Account::from_instance(self);
self_.counter.get()
}
pub fn name(&self) -> String {
let priv_ = AccountPriv::from_instance(self);
priv_.name.borrow().clone()
let self_ = imp::Account::from_instance(self);
self_.name.borrow().clone()
}
pub fn token(&self) -> String {
let priv_ = AccountPriv::from_instance(self);
priv_.token.get().unwrap().clone()
let self_ = imp::Account::from_instance(self);
self_.token.get().unwrap().clone()
}
pub fn token_id(&self) -> String {
let priv_ = AccountPriv::from_instance(self);
priv_.token_id.borrow().clone()
let self_ = imp::Account::from_instance(self);
self_.token_id.borrow().clone()
}
pub fn otp_uri(&self) -> OTPUri {

View file

@ -6,10 +6,9 @@ use anyhow::Result;
use core::cmp::Ordering;
use diesel::{QueryDsl, RunQueryDsl};
use gio::prelude::*;
use gio::FileExt;
use glib::subclass::{self, prelude::*};
use gio::subclass::ObjectSubclass;
use glib::{Cast, StaticType, ToValue};
use gtk::FilterListModelExt;
use gtk::prelude::*;
use std::cell::{Cell, RefCell};
use std::str::FromStr;
use std::string::ToString;
@ -44,252 +43,231 @@ pub struct DiProvider {
pub algorithm: String,
pub method: String,
}
mod imp {
use super::*;
use glib::subclass::{self, prelude::*};
pub struct ProviderPriv {
pub id: Cell<i32>,
pub name: RefCell<String>,
pub period: Cell<i32>,
pub method: RefCell<String>,
pub default_counter: Cell<i32>,
pub algorithm: RefCell<String>,
pub digits: Cell<i32>,
pub website: RefCell<Option<String>>,
pub help_url: RefCell<Option<String>>,
pub image_uri: RefCell<Option<String>>,
pub accounts: AccountsModel,
pub filter_model: gtk::FilterListModel,
}
static PROPERTIES: [subclass::Property; 11] = [
subclass::Property("id", |name| {
glib::ParamSpec::int(
name,
"id",
"Id",
0,
i32::MAX,
0,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("name", |name| {
glib::ParamSpec::string(name, "name", "Name", None, glib::ParamFlags::READWRITE)
}),
subclass::Property("accounts", |name| {
glib::ParamSpec::object(
name,
"accounts",
"accounts",
AccountsModel::static_type(),
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("period", |name| {
glib::ParamSpec::int(
name,
"period",
"Period",
0,
1000,
30,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("digits", |name| {
glib::ParamSpec::int(
name,
"digits",
"Digits",
0,
1000,
6,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("default-counter", |name| {
glib::ParamSpec::int(
name,
"default_counter",
"default_counter",
0,
i32::MAX,
1,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("algorithm", |name| {
glib::ParamSpec::string(
name,
"algorithm",
"Algorithm",
Some(&Algorithm::default().to_string()),
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("method", |name| {
glib::ParamSpec::string(
name,
"method",
"Method",
Some(&OTPMethod::default().to_string()),
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("website", |name| {
glib::ParamSpec::string(
name,
"website",
"Website",
None,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("help-url", |name| {
glib::ParamSpec::string(
name,
"help url",
"Help URL",
None,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("image-uri", |name| {
glib::ParamSpec::string(
name,
"image uri",
"Image URI",
None,
glib::ParamFlags::READWRITE,
)
}),
];
impl ObjectSubclass for ProviderPriv {
const NAME: &'static str = "Provider";
type Type = super::Provider;
type ParentType = glib::Object;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
fn class_init(klass: &mut Self::Class) {
klass.install_properties(&PROPERTIES);
static PROPERTIES: [subclass::Property; 11] = [
subclass::Property("id", |name| {
glib::ParamSpec::int(
name,
"id",
"Id",
0,
i32::MAX,
0,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("name", |name| {
glib::ParamSpec::string(name, "name", "Name", None, glib::ParamFlags::READWRITE)
}),
subclass::Property("accounts", |name| {
glib::ParamSpec::object(
name,
"accounts",
"accounts",
AccountsModel::static_type(),
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("period", |name| {
glib::ParamSpec::int(
name,
"period",
"Period",
0,
1000,
30,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("digits", |name| {
glib::ParamSpec::int(
name,
"digits",
"Digits",
0,
1000,
6,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("default-counter", |name| {
glib::ParamSpec::int(
name,
"default_counter",
"default_counter",
0,
i32::MAX,
1,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("algorithm", |name| {
glib::ParamSpec::string(
name,
"algorithm",
"Algorithm",
Some(&Algorithm::default().to_string()),
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("method", |name| {
glib::ParamSpec::string(
name,
"method",
"Method",
Some(&OTPMethod::default().to_string()),
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("website", |name| {
glib::ParamSpec::string(
name,
"website",
"Website",
None,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("help-url", |name| {
glib::ParamSpec::string(
name,
"help url",
"Help URL",
None,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("image-uri", |name| {
glib::ParamSpec::string(
name,
"image uri",
"Image URI",
None,
glib::ParamFlags::READWRITE,
)
}),
];
pub struct Provider {
pub id: Cell<i32>,
pub name: RefCell<String>,
pub period: Cell<i32>,
pub method: RefCell<String>,
pub default_counter: Cell<i32>,
pub algorithm: RefCell<String>,
pub digits: Cell<i32>,
pub website: RefCell<Option<String>>,
pub help_url: RefCell<Option<String>>,
pub image_uri: RefCell<Option<String>>,
pub accounts: AccountsModel,
pub filter_model: gtk::FilterListModel,
}
fn new() -> Self {
let model = AccountsModel::new();
Self {
id: Cell::new(0),
default_counter: Cell::new(1),
algorithm: RefCell::new(Algorithm::default().to_string()),
digits: Cell::new(6),
name: RefCell::new("".to_string()),
website: RefCell::new(None),
help_url: RefCell::new(None),
image_uri: RefCell::new(None),
method: RefCell::new(OTPMethod::default().to_string()),
period: Cell::new(30),
filter_model: gtk::FilterListModel::new(Some(&model), gtk::NONE_FILTER),
accounts: model,
impl ObjectSubclass for Provider {
const NAME: &'static str = "Provider";
type Type = super::Provider;
type ParentType = glib::Object;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
fn class_init(klass: &mut Self::Class) {
klass.install_properties(&PROPERTIES);
}
}
}
impl ObjectImpl for ProviderPriv {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("id", ..) => {
let id = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.id.replace(id);
fn new() -> Self {
let model = AccountsModel::new();
Self {
id: Cell::new(0),
default_counter: Cell::new(1),
algorithm: RefCell::new(Algorithm::default().to_string()),
digits: Cell::new(6),
name: RefCell::new("".to_string()),
website: RefCell::new(None),
help_url: RefCell::new(None),
image_uri: RefCell::new(None),
method: RefCell::new(OTPMethod::default().to_string()),
period: Cell::new(30),
filter_model: gtk::FilterListModel::new(Some(&model), gtk::NONE_FILTER),
accounts: model,
}
subclass::Property("name", ..) => {
let name = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.name.replace(name);
}
subclass::Property("period", ..) => {
let period = value
.get_some()
.expect("type conformity checked by `Object::set_property`");
self.period.replace(period);
}
subclass::Property("method", ..) => {
let method = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.method.replace(method);
}
subclass::Property("digits", ..) => {
let digits = value
.get_some()
.expect("type conformity checked by `Object::set_property`");
self.digits.replace(digits);
}
subclass::Property("algorithm", ..) => {
let algorithm = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.algorithm.replace(algorithm);
}
subclass::Property("default-counter", ..) => {
let default_counter = value
.get_some()
.expect("type conformity checked by `Object::set_property`");
self.default_counter.replace(default_counter);
}
subclass::Property("website", ..) => {
let website = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.website.replace(website);
}
subclass::Property("help-url", ..) => {
let help_url = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.help_url.replace(help_url);
}
subclass::Property("image-uri", ..) => {
let image_uri = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.image_uri.replace(image_uri);
}
_ => unimplemented!(),
}
}
fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
let prop = &PROPERTIES[id];
impl ObjectImpl for Provider {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("id", ..) => self.id.get().to_value(),
subclass::Property("name", ..) => self.name.borrow().to_value(),
subclass::Property("period", ..) => self.period.get().to_value(),
subclass::Property("method", ..) => self.method.borrow().to_value(),
subclass::Property("digits", ..) => self.digits.get().to_value(),
subclass::Property("algorithm", ..) => self.algorithm.borrow().to_value(),
subclass::Property("default-counter", ..) => self.default_counter.get().to_value(),
subclass::Property("website", ..) => self.website.borrow().to_value(),
subclass::Property("help-url", ..) => self.help_url.borrow().to_value(),
subclass::Property("image-uri", ..) => self.image_uri.borrow().to_value(),
_ => unimplemented!(),
match *prop {
subclass::Property("id", ..) => {
let id = value.get().unwrap().unwrap();
self.id.replace(id);
}
subclass::Property("name", ..) => {
let name = value.get().unwrap().unwrap();
self.name.replace(name);
}
subclass::Property("period", ..) => {
let period = value.get_some().unwrap();
self.period.replace(period);
}
subclass::Property("method", ..) => {
let method = value.get().unwrap().unwrap();
self.method.replace(method);
}
subclass::Property("digits", ..) => {
let digits = value.get_some().unwrap();
self.digits.replace(digits);
}
subclass::Property("algorithm", ..) => {
let algorithm = value.get().unwrap().unwrap();
self.algorithm.replace(algorithm);
}
subclass::Property("default-counter", ..) => {
let default_counter = value.get_some().unwrap();
self.default_counter.replace(default_counter);
}
subclass::Property("website", ..) => {
let website = value.get().unwrap();
self.website.replace(website);
}
subclass::Property("help-url", ..) => {
let help_url = value.get().unwrap();
self.help_url.replace(help_url);
}
subclass::Property("image-uri", ..) => {
let image_uri = value.get().unwrap();
self.image_uri.replace(image_uri);
}
_ => unimplemented!(),
}
}
fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("id", ..) => self.id.get().to_value(),
subclass::Property("name", ..) => self.name.borrow().to_value(),
subclass::Property("period", ..) => self.period.get().to_value(),
subclass::Property("method", ..) => self.method.borrow().to_value(),
subclass::Property("digits", ..) => self.digits.get().to_value(),
subclass::Property("algorithm", ..) => self.algorithm.borrow().to_value(),
subclass::Property("default-counter", ..) => self.default_counter.get().to_value(),
subclass::Property("website", ..) => self.website.borrow().to_value(),
subclass::Property("help-url", ..) => self.help_url.borrow().to_value(),
subclass::Property("image-uri", ..) => self.image_uri.borrow().to_value(),
_ => unimplemented!(),
}
}
}
}
glib_wrapper! {
pub struct Provider(ObjectSubclass<ProviderPriv>);
pub struct Provider(ObjectSubclass<imp::Provider>);
}
impl Provider {
@ -412,48 +390,48 @@ impl Provider {
}
pub fn id(&self) -> i32 {
let priv_ = ProviderPriv::from_instance(self);
priv_.id.get()
let self_ = imp::Provider::from_instance(self);
self_.id.get()
}
pub fn name(&self) -> String {
let priv_ = ProviderPriv::from_instance(self);
priv_.name.borrow().clone()
let self_ = imp::Provider::from_instance(self);
self_.name.borrow().clone()
}
pub fn digits(&self) -> i32 {
let priv_ = ProviderPriv::from_instance(self);
priv_.digits.get()
let self_ = imp::Provider::from_instance(self);
self_.digits.get()
}
pub fn default_counter(&self) -> i32 {
let priv_ = ProviderPriv::from_instance(self);
priv_.default_counter.get()
let self_ = imp::Provider::from_instance(self);
self_.default_counter.get()
}
pub fn period(&self) -> i32 {
let priv_ = ProviderPriv::from_instance(self);
priv_.period.get()
let self_ = imp::Provider::from_instance(self);
self_.period.get()
}
pub fn algorithm(&self) -> Algorithm {
let priv_ = ProviderPriv::from_instance(self);
Algorithm::from_str(&priv_.algorithm.borrow().clone()).unwrap()
let self_ = imp::Provider::from_instance(self);
Algorithm::from_str(&self_.algorithm.borrow().clone()).unwrap()
}
pub fn method(&self) -> OTPMethod {
let priv_ = ProviderPriv::from_instance(self);
OTPMethod::from_str(&priv_.method.borrow().clone()).unwrap()
let self_ = imp::Provider::from_instance(self);
OTPMethod::from_str(&self_.method.borrow().clone()).unwrap()
}
pub fn website(&self) -> Option<String> {
let priv_ = ProviderPriv::from_instance(self);
priv_.website.borrow().clone()
let self_ = imp::Provider::from_instance(self);
self_.website.borrow().clone()
}
pub fn help_url(&self) -> Option<String> {
let priv_ = ProviderPriv::from_instance(self);
priv_.help_url.borrow().clone()
let self_ = imp::Provider::from_instance(self);
self_.help_url.borrow().clone()
}
pub fn set_image_uri(&self, uri: &str) -> Result<()> {
@ -470,8 +448,8 @@ impl Provider {
}
pub fn image_uri(&self) -> Option<String> {
let priv_ = ProviderPriv::from_instance(self);
priv_.image_uri.borrow().clone()
let self_ = imp::Provider::from_instance(self);
self_.image_uri.borrow().clone()
}
pub fn open_help(&self) {
@ -481,43 +459,43 @@ impl Provider {
}
pub fn has_account(&self, account: &Account) -> Option<u32> {
let priv_ = ProviderPriv::from_instance(self);
priv_.accounts.find_by_id(account.id())
let self_ = imp::Provider::from_instance(self);
self_.accounts.find_by_id(account.id())
}
pub fn has_accounts(&self) -> bool {
let priv_ = ProviderPriv::from_instance(self);
priv_.accounts.get_n_items() != 0
let self_ = imp::Provider::from_instance(self);
self_.accounts.get_n_items() != 0
}
pub fn add_account(&self, account: &Account) {
let priv_ = ProviderPriv::from_instance(self);
priv_.accounts.insert(account);
let self_ = imp::Provider::from_instance(self);
self_.accounts.insert(account);
}
pub fn accounts_model(&self) -> &AccountsModel {
let priv_ = ProviderPriv::from_instance(self);
&priv_.accounts
let self_ = imp::Provider::from_instance(self);
&self_.accounts
}
pub fn accounts(&self) -> &gtk::FilterListModel {
let priv_ = ProviderPriv::from_instance(self);
&priv_.filter_model
let self_ = imp::Provider::from_instance(self);
&self_.filter_model
}
pub fn filter(&self, text: String) {
let priv_ = ProviderPriv::from_instance(self);
let self_ = imp::Provider::from_instance(self);
let filter = gtk::CustomFilter::new(Some(Box::new(move |obj| {
let account = obj.downcast_ref::<Account>().unwrap();
account.name().contains(&text)
})));
priv_.filter_model.set_filter(Some(&filter));
self_.filter_model.set_filter(Some(&filter));
}
pub fn remove_account(&self, account: Account) {
let priv_ = ProviderPriv::from_instance(self);
if let Some(pos) = priv_.accounts.find_by_id(account.id()) {
priv_.accounts.remove(pos);
let self_ = imp::Provider::from_instance(self);
if let Some(pos) = self_.accounts.find_by_id(account.id()) {
self_.accounts.remove(pos);
}
}
}

View file

@ -74,9 +74,7 @@ mod imp {
match *prop {
subclass::Property("account", ..) => {
let account = value
.get()
.expect("type conformity checked by `Object::set_property`");
let account = value.get().unwrap();
self.account.replace(account);
}
_ => unimplemented!(),

View file

@ -85,9 +85,7 @@ mod imp {
match *prop {
subclass::Property("provider", ..) => {
let provider = value
.get()
.expect("type conformity checked by `Object::set_property`");
let provider = value.get().unwrap();
self.provider.replace(provider);
}
_ => unimplemented!(),

View file

@ -75,9 +75,7 @@ mod imp {
match *prop {
subclass::Property("provider", ..) => {
let provider = value
.get()
.expect("type conformity checked by `Object::set_property`");
let provider = value.get().unwrap();
self.provider.replace(provider);
}
_ => unimplemented!(),