mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-01-15 17:20:08 +00:00
save uncompleted state
This commit is contained in:
parent
fcceb5af1c
commit
4b5e260792
@ -68,9 +68,6 @@ impl Widget {
|
|||||||
let form = form.clone();
|
let form = form.clone();
|
||||||
let alert_dialog = alert_dialog.clone();
|
let alert_dialog = alert_dialog.clone();
|
||||||
move || {
|
move || {
|
||||||
// Update form with it children components
|
|
||||||
form.update();
|
|
||||||
|
|
||||||
// Deactivate apply button if the form values could not be processed
|
// Deactivate apply button if the form values could not be processed
|
||||||
alert_dialog.set_response_enabled(RESPONSE_APPLY.0, form.is_applicable());
|
alert_dialog.set_response_enabled(RESPONSE_APPLY.0, form.is_applicable());
|
||||||
}
|
}
|
||||||
@ -96,14 +93,13 @@ impl Widget {
|
|||||||
this.set_response_enabled(response, false);
|
this.set_response_enabled(response, false);
|
||||||
|
|
||||||
// Result
|
// Result
|
||||||
callback(form.list.selected_item().value_enum())
|
callback(form.list.selected().value_enum())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show dialog with new preset
|
/// Show dialog with new preset
|
||||||
pub fn present(&self, parent: Option<&impl IsA<gtk::Widget>>) {
|
pub fn present(&self, parent: Option<&impl IsA<gtk::Widget>>) {
|
||||||
self.form.update();
|
|
||||||
self.alert_dialog.present(parent)
|
self.alert_dialog.present(parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,13 @@ use gtk::{prelude::BoxExt, Box, Orientation};
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Form {
|
pub struct Form {
|
||||||
// pub action: Rc<Action>,
|
// pub widget_action: Rc<Action>,
|
||||||
pub drop: Rc<Drop>,
|
// pub drop: Rc<Drop>,
|
||||||
pub exit: Rc<Exit>,
|
// pub exit: Rc<Exit>,
|
||||||
pub file: Rc<File>,
|
pub file: Rc<File>,
|
||||||
pub list: Rc<List>,
|
pub list: Rc<List>,
|
||||||
pub name: Rc<Name>,
|
pub name: Rc<Name>,
|
||||||
pub save: Rc<Save>,
|
// pub save: Rc<Save>,
|
||||||
pub g_box: Box,
|
pub g_box: Box,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,14 +32,14 @@ impl Form {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(profile: Rc<Profile>, action: Rc<Action>, auth_url: &str) -> Self {
|
pub fn new(profile: Rc<Profile>, widget_action: Rc<Action>, auth_url: &str) -> Self {
|
||||||
// Init components
|
// Init components
|
||||||
let file = Rc::new(File::new(action.clone()));
|
let list = Rc::new(List::new(profile.clone(), auth_url));
|
||||||
let list = Rc::new(List::new(profile.clone(), action.clone(), auth_url));
|
let file = Rc::new(File::new(widget_action.clone()));
|
||||||
let name = Rc::new(Name::new(action.clone()));
|
let name = Rc::new(Name::new(widget_action.clone()));
|
||||||
let save = Rc::new(Save::new(profile.clone()));
|
let save = Rc::new(Save::new(profile.clone(), list.clone()));
|
||||||
let drop = Rc::new(Drop::new(profile.clone(), action.clone(), list.clone()));
|
let drop = Rc::new(Drop::new(profile.clone(), list.clone()));
|
||||||
let exit = Rc::new(Exit::new(profile.clone(), action.clone(), list.clone()));
|
let exit = Rc::new(Exit::new(profile.clone(), list.clone()));
|
||||||
|
|
||||||
// Init main container
|
// Init main container
|
||||||
let g_box = Box::builder().orientation(Orientation::Vertical).build();
|
let g_box = Box::builder().orientation(Orientation::Vertical).build();
|
||||||
@ -51,15 +51,49 @@ impl Form {
|
|||||||
g_box.append(&drop.button);
|
g_box.append(&drop.button);
|
||||||
g_box.append(&save.button);
|
g_box.append(&save.button);
|
||||||
|
|
||||||
|
// Connect events
|
||||||
|
list.dropdown.connect_selected_notify({
|
||||||
|
let list = list.clone();
|
||||||
|
let name = name.clone();
|
||||||
|
let file = file.clone();
|
||||||
|
// let drop = drop.clone();
|
||||||
|
// let exit = exit.clone();
|
||||||
|
// let save = save.clone();
|
||||||
|
move |_| {
|
||||||
|
// Get selected item
|
||||||
|
let item = list.selected();
|
||||||
|
|
||||||
|
// Update name entry visibility
|
||||||
|
name.set_visible(matches!(item.value_enum(), Value::GeneratePem));
|
||||||
|
|
||||||
|
// Update file choose button visibility
|
||||||
|
file.set_visible(matches!(item.value_enum(), Value::ImportPem));
|
||||||
|
|
||||||
|
// Update ID-related components
|
||||||
|
match item.value_enum() {
|
||||||
|
Value::ProfileIdentityGeminiId(_) => {
|
||||||
|
drop.set_visible(true);
|
||||||
|
exit.set_visible(true);
|
||||||
|
save.set_visible(true);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
drop.set_visible(false);
|
||||||
|
exit.set_visible(false);
|
||||||
|
save.set_visible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Return activated `Self`
|
// Return activated `Self`
|
||||||
Self {
|
Self {
|
||||||
// action,
|
// widget_action,
|
||||||
drop,
|
// drop,
|
||||||
exit,
|
// exit,
|
||||||
file,
|
file,
|
||||||
list,
|
list,
|
||||||
name,
|
name,
|
||||||
save,
|
// save,
|
||||||
g_box,
|
g_box,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,38 +102,11 @@ impl Form {
|
|||||||
|
|
||||||
/// Validate `Self` components match current selection
|
/// Validate `Self` components match current selection
|
||||||
pub fn is_applicable(&self) -> bool {
|
pub fn is_applicable(&self) -> bool {
|
||||||
match self.list.selected_item().value_enum() {
|
match self.list.selected().value_enum() {
|
||||||
Value::GeneratePem => self.name.is_valid(),
|
Value::GeneratePem => self.name.is_valid(),
|
||||||
Value::ImportPem => self.file.is_valid(),
|
Value::ImportPem => self.file.is_valid(),
|
||||||
Value::ProfileIdentityGeminiId(_) => !self.list.selected_item().is_active(),
|
Value::ProfileIdentityGeminiId(_) => !self.list.selected().is_active(),
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self) {
|
|
||||||
// Get selected item
|
|
||||||
let item = self.list.selected_item();
|
|
||||||
|
|
||||||
// Update name entry visibility
|
|
||||||
self.name
|
|
||||||
.update(matches!(item.value_enum(), Value::GeneratePem));
|
|
||||||
|
|
||||||
// Update file choose button visibility
|
|
||||||
self.file
|
|
||||||
.update(matches!(item.value_enum(), Value::ImportPem));
|
|
||||||
|
|
||||||
// Update ID-related components
|
|
||||||
match item.value_enum() {
|
|
||||||
Value::ProfileIdentityGeminiId(value) => {
|
|
||||||
self.drop.update(Some(value));
|
|
||||||
self.exit.update(Some(value));
|
|
||||||
self.save.update(Some(value));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.drop.update(None);
|
|
||||||
self.exit.update(None);
|
|
||||||
self.save.update(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use super::Action;
|
use super::list::{item::Value, List};
|
||||||
use super::List;
|
|
||||||
use crate::profile::Profile;
|
use crate::profile::Profile;
|
||||||
use adw::{
|
use adw::{
|
||||||
prelude::{AdwDialogExt, AlertDialogExt, AlertDialogExtManual},
|
prelude::{AdwDialogExt, AlertDialogExt, AlertDialogExtManual},
|
||||||
@ -9,7 +8,7 @@ use gtk::{
|
|||||||
prelude::{ButtonExt, WidgetExt},
|
prelude::{ButtonExt, WidgetExt},
|
||||||
Button,
|
Button,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::rc::Rc;
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
|
|
||||||
@ -23,7 +22,6 @@ const RESPONSE_CANCEL: (&str, &str) = ("cancel", "Cancel");
|
|||||||
const RESPONSE_CONFIRM: (&str, &str) = ("confirm", "Confirm");
|
const RESPONSE_CONFIRM: (&str, &str) = ("confirm", "Confirm");
|
||||||
|
|
||||||
pub struct Drop {
|
pub struct Drop {
|
||||||
profile_identity_gemini_id: Rc<RefCell<Option<i64>>>,
|
|
||||||
pub button: Button,
|
pub button: Button,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,10 +29,7 @@ impl Drop {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(profile: Rc<Profile>, action: Rc<Action>, list: Rc<List>) -> Self {
|
pub fn new(profile: Rc<Profile>, list: Rc<List>) -> Self {
|
||||||
// Init selected option holder
|
|
||||||
let profile_identity_gemini_id = Rc::new(RefCell::new(None::<i64>));
|
|
||||||
|
|
||||||
// Init main widget
|
// Init main widget
|
||||||
let button = Button::builder()
|
let button = Button::builder()
|
||||||
.label(LABEL)
|
.label(LABEL)
|
||||||
@ -45,13 +40,11 @@ impl Drop {
|
|||||||
|
|
||||||
// Init events
|
// Init events
|
||||||
button.connect_clicked({
|
button.connect_clicked({
|
||||||
let action = action.clone();
|
|
||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
let profile_identity_gemini_id = profile_identity_gemini_id.clone();
|
let list = list.clone();
|
||||||
move |_| {
|
move |_| {
|
||||||
// Get selected identity from holder
|
match list.selected().value_enum() {
|
||||||
match profile_identity_gemini_id.borrow().as_ref() {
|
Value::ProfileIdentityGeminiId(profile_identity_gemini_id) => {
|
||||||
Some(profile_identity_gemini_id) => {
|
|
||||||
// Init sub-widget
|
// Init sub-widget
|
||||||
let alert_dialog = AlertDialog::builder()
|
let alert_dialog = AlertDialog::builder()
|
||||||
.heading(HEADING)
|
.heading(HEADING)
|
||||||
@ -76,13 +69,14 @@ impl Drop {
|
|||||||
|
|
||||||
// Connect confirmation event
|
// Connect confirmation event
|
||||||
alert_dialog.connect_response(Some(RESPONSE_CONFIRM.0), {
|
alert_dialog.connect_response(Some(RESPONSE_CONFIRM.0), {
|
||||||
let action = action.clone();
|
|
||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
let list = list.clone();
|
let list = list.clone();
|
||||||
let profile = profile.clone();
|
let profile = profile.clone();
|
||||||
let profile_identity_gemini_id = *profile_identity_gemini_id;
|
move |_, _| match profile
|
||||||
move |_, _| {
|
.identity
|
||||||
match profile.identity.gemini.delete(profile_identity_gemini_id) {
|
.gemini
|
||||||
|
.delete(profile_identity_gemini_id)
|
||||||
|
{
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
if list.remove(profile_identity_gemini_id).is_some() {
|
if list.remove(profile_identity_gemini_id).is_some() {
|
||||||
button.set_css_classes(&["success"]);
|
button.set_css_classes(&["success"]);
|
||||||
@ -90,7 +84,6 @@ impl Drop {
|
|||||||
} else {
|
} else {
|
||||||
button.set_css_classes(&["error"]);
|
button.set_css_classes(&["error"]);
|
||||||
button.set_label("List item not found")
|
button.set_label("List item not found")
|
||||||
// @TODO unexpected
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -98,39 +91,23 @@ impl Drop {
|
|||||||
button.set_label(&e.to_string())
|
button.set_label(&e.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
action.update.activate()
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show dialog
|
// Show dialog
|
||||||
alert_dialog.present(Some(&button))
|
alert_dialog.present(Some(&button))
|
||||||
}
|
}
|
||||||
None => todo!(), // unexpected
|
_ => todo!(), // unexpected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return activated `Self`
|
// Return activated `Self`
|
||||||
Self {
|
Self { button }
|
||||||
profile_identity_gemini_id,
|
|
||||||
button,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Update `profile_identity_gemini_id` holder,
|
pub fn set_visible(&self, is_visible: bool) {
|
||||||
/// toggle visibility depending on given value
|
self.button.set_visible(is_visible)
|
||||||
pub fn update(&self, profile_identity_gemini_id: Option<i64>) {
|
|
||||||
self.button.set_visible(match profile_identity_gemini_id {
|
|
||||||
Some(value) => {
|
|
||||||
self.profile_identity_gemini_id.replace(Some(value));
|
|
||||||
true
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.profile_identity_gemini_id.replace(None);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use super::Action;
|
use super::list::{item::Value, List};
|
||||||
use super::List;
|
|
||||||
use crate::profile::Profile;
|
use crate::profile::Profile;
|
||||||
use adw::{
|
use adw::{
|
||||||
prelude::{AdwDialogExt, AlertDialogExt, AlertDialogExtManual},
|
prelude::{AdwDialogExt, AlertDialogExt, AlertDialogExtManual},
|
||||||
@ -9,7 +8,7 @@ use gtk::{
|
|||||||
prelude::{ButtonExt, WidgetExt},
|
prelude::{ButtonExt, WidgetExt},
|
||||||
Button,
|
Button,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::rc::Rc;
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
|
|
||||||
@ -23,7 +22,6 @@ const RESPONSE_CANCEL: (&str, &str) = ("cancel", "Cancel");
|
|||||||
const RESPONSE_CONFIRM: (&str, &str) = ("confirm", "Confirm");
|
const RESPONSE_CONFIRM: (&str, &str) = ("confirm", "Confirm");
|
||||||
|
|
||||||
pub struct Exit {
|
pub struct Exit {
|
||||||
profile_identity_gemini_id: Rc<RefCell<Option<i64>>>,
|
|
||||||
pub button: Button,
|
pub button: Button,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,10 +29,7 @@ impl Exit {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(profile: Rc<Profile>, action: Rc<Action>, list: Rc<List>) -> Self {
|
pub fn new(profile: Rc<Profile>, list: Rc<List>) -> Self {
|
||||||
// Init selected option holder
|
|
||||||
let profile_identity_gemini_id = Rc::new(RefCell::new(None::<i64>));
|
|
||||||
|
|
||||||
// Init main widget
|
// Init main widget
|
||||||
let button = Button::builder()
|
let button = Button::builder()
|
||||||
.label(LABEL)
|
.label(LABEL)
|
||||||
@ -45,13 +40,11 @@ impl Exit {
|
|||||||
|
|
||||||
// Init events
|
// Init events
|
||||||
button.connect_clicked({
|
button.connect_clicked({
|
||||||
let action = action.clone();
|
|
||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
let profile_identity_gemini_id = profile_identity_gemini_id.clone();
|
|
||||||
move |_| {
|
move |_| {
|
||||||
// Get selected identity from holder
|
// Get selected identity from holder
|
||||||
match profile_identity_gemini_id.borrow().as_ref() {
|
match list.selected().value_enum() {
|
||||||
Some(profile_identity_gemini_id) => {
|
Value::ProfileIdentityGeminiId(profile_identity_gemini_id) => {
|
||||||
// Init sub-widget
|
// Init sub-widget
|
||||||
let alert_dialog = AlertDialog::builder()
|
let alert_dialog = AlertDialog::builder()
|
||||||
.heading(HEADING)
|
.heading(HEADING)
|
||||||
@ -76,66 +69,44 @@ impl Exit {
|
|||||||
|
|
||||||
// Connect confirmation event
|
// Connect confirmation event
|
||||||
alert_dialog.connect_response(Some(RESPONSE_CONFIRM.0), {
|
alert_dialog.connect_response(Some(RESPONSE_CONFIRM.0), {
|
||||||
let action = action.clone();
|
|
||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
let list = list.clone();
|
let list = list.clone();
|
||||||
let profile = profile.clone();
|
let profile = profile.clone();
|
||||||
let profile_identity_gemini_id = *profile_identity_gemini_id;
|
move |_, _| match profile
|
||||||
move |_, _| {
|
|
||||||
match profile
|
|
||||||
.identity
|
.identity
|
||||||
.gemini
|
.gemini
|
||||||
.auth
|
.auth
|
||||||
.remove_ref(profile_identity_gemini_id)
|
.remove_ref(profile_identity_gemini_id)
|
||||||
{
|
{
|
||||||
Ok(_) => {
|
Ok(_) => match list.update(profile_identity_gemini_id) {
|
||||||
if list.remove(profile_identity_gemini_id).is_some() {
|
Some(_) => {
|
||||||
button.set_css_classes(&["success"]);
|
button.set_css_classes(&["success"]);
|
||||||
button.set_label("Identity successfully disconnected")
|
button.set_label("Identity successfully disconnected");
|
||||||
} else {
|
|
||||||
button.set_css_classes(&["error"]);
|
|
||||||
button.set_label("List item not found")
|
|
||||||
// @TODO unexpected
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
None => todo!(),
|
||||||
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
button.set_css_classes(&["error"]);
|
button.set_css_classes(&["error"]);
|
||||||
button.set_label(&e.to_string())
|
button.set_label(&e.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
action.update.activate()
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show dialog
|
// Show dialog
|
||||||
alert_dialog.present(Some(&button))
|
alert_dialog.present(Some(&button))
|
||||||
}
|
}
|
||||||
None => todo!(), // unexpected
|
_ => todo!(), // unexpected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return activated `Self`
|
// Return activated `Self`
|
||||||
Self {
|
Self { button }
|
||||||
profile_identity_gemini_id,
|
|
||||||
button,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Update `profile_identity_gemini_id` holder,
|
pub fn set_visible(&self, is_visible: bool) {
|
||||||
/// toggle visibility depending on given value
|
self.button.set_visible(is_visible)
|
||||||
pub fn update(&self, profile_identity_gemini_id: Option<i64>) {
|
|
||||||
self.button.set_visible(match profile_identity_gemini_id {
|
|
||||||
Some(value) => {
|
|
||||||
self.profile_identity_gemini_id.replace(Some(value));
|
|
||||||
true
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.profile_identity_gemini_id.replace(None);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ impl File {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(action: Rc<Action>) -> Self {
|
pub fn new(widget_action: Rc<Action>) -> Self {
|
||||||
// Init PEM
|
// Init PEM
|
||||||
let pem = Rc::new(RefCell::new(None));
|
let pem = Rc::new(RefCell::new(None));
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ impl File {
|
|||||||
button.connect_clicked({
|
button.connect_clicked({
|
||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
let pem = pem.clone();
|
let pem = pem.clone();
|
||||||
let update = action.update.clone();
|
let widget_action = widget_action.clone();
|
||||||
move |_| {
|
move |_| {
|
||||||
// Lock open button (prevent double click)
|
// Lock open button (prevent double click)
|
||||||
button.set_sensitive(false);
|
button.set_sensitive(false);
|
||||||
@ -63,7 +63,7 @@ impl File {
|
|||||||
.open(None::<&Window>, None::<&Cancellable>, {
|
.open(None::<&Window>, None::<&Cancellable>, {
|
||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
let pem = pem.clone();
|
let pem = pem.clone();
|
||||||
let update = update.clone();
|
let widget_action = widget_action.clone();
|
||||||
move |result| {
|
move |result| {
|
||||||
match result {
|
match result {
|
||||||
Ok(file) => match file.path() {
|
Ok(file) => match file.path() {
|
||||||
@ -89,7 +89,7 @@ impl File {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
button.set_sensitive(true); // unlock
|
button.set_sensitive(true); // unlock
|
||||||
update.activate()
|
widget_action.update.activate()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -102,12 +102,8 @@ impl File {
|
|||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Change visibility status
|
/// Change visibility status
|
||||||
/// * grab focus on `is_visible`
|
pub fn set_visible(&self, is_visible: bool) {
|
||||||
pub fn update(&self, is_visible: bool) {
|
|
||||||
self.button.set_visible(is_visible);
|
self.button.set_visible(is_visible);
|
||||||
if is_visible {
|
|
||||||
self.button.grab_focus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
|
@ -3,7 +3,6 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use item::Item;
|
use item::Item;
|
||||||
|
|
||||||
use super::Action;
|
|
||||||
use crate::profile::Profile;
|
use crate::profile::Profile;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gdk::Cursor,
|
gdk::Cursor,
|
||||||
@ -18,22 +17,23 @@ use gtk::{
|
|||||||
pub struct List {
|
pub struct List {
|
||||||
pub dropdown: DropDown,
|
pub dropdown: DropDown,
|
||||||
list_store: ListStore,
|
list_store: ListStore,
|
||||||
|
// profile: Rc<Profile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl List {
|
impl List {
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(profile: Rc<Profile>, action: Rc<Action>, auth_url: &str) -> Self {
|
pub fn new(profile: Rc<Profile>, auth_url: &str) -> Self {
|
||||||
// Init model
|
// Init model
|
||||||
let list_store = ListStore::new::<Item>();
|
let list_store = ListStore::new::<Item>();
|
||||||
|
|
||||||
|
list_store.remove_all();
|
||||||
|
|
||||||
list_store.append(&Item::new_guest_session());
|
list_store.append(&Item::new_guest_session());
|
||||||
list_store.append(&Item::new_generate_pem());
|
list_store.append(&Item::new_generate_pem());
|
||||||
list_store.append(&Item::new_import_pem());
|
list_store.append(&Item::new_import_pem());
|
||||||
|
|
||||||
// Append identities from profile database
|
|
||||||
// * memory cache synced also and could be faster @TODO
|
|
||||||
match profile.identity.gemini.database.records() {
|
match profile.identity.gemini.database.records() {
|
||||||
Ok(identities) => {
|
Ok(identities) => {
|
||||||
for identity in identities {
|
for identity in identities {
|
||||||
@ -132,41 +132,52 @@ impl List {
|
|||||||
.factory(&factory)
|
.factory(&factory)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Connect events
|
|
||||||
dropdown.connect_selected_notify(move |_| action.update.activate());
|
|
||||||
|
|
||||||
// Return activated `Self`
|
// Return activated `Self`
|
||||||
Self {
|
Self {
|
||||||
list_store,
|
|
||||||
dropdown,
|
dropdown,
|
||||||
|
list_store,
|
||||||
|
// profile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Find list item by `value` (stores ID)
|
/// Find list item by `profile_identity_gemini_id`
|
||||||
/// * return `position` found
|
/// * return `position` found
|
||||||
pub fn find(&self, value: i64) -> Option<u32> {
|
pub fn find(&self, profile_identity_gemini_id: i64) -> Option<u32> {
|
||||||
self.list_store
|
self.list_store.find_with_equal_func(|this| {
|
||||||
.find_with_equal_func(|this| value == this.clone().downcast::<Item>().unwrap().value())
|
profile_identity_gemini_id == this.downcast_ref::<Item>().unwrap().value()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove list item by `value` (stores ID)
|
/// Remove list item by `profile_identity_gemini_id` (stores ID)
|
||||||
/// * return `position` of removed list item
|
/// * return `position` of removed list item
|
||||||
pub fn remove(&self, value: i64) -> Option<u32> {
|
pub fn remove(&self, profile_identity_gemini_id: i64) -> Option<u32> {
|
||||||
match self.find(value) {
|
match self.find(profile_identity_gemini_id) {
|
||||||
Some(position) => {
|
Some(position) => {
|
||||||
self.list_store.remove(position);
|
self.list_store.remove(position);
|
||||||
Some(position)
|
Some(position)
|
||||||
}
|
}
|
||||||
None => None,
|
None => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update list item by `profile_identity_gemini_id` (stores ID)
|
||||||
|
/// * return `position` of updated list item
|
||||||
|
pub fn update(&self, profile_identity_gemini_id: i64) -> Option<u32> {
|
||||||
|
match self.find(profile_identity_gemini_id) {
|
||||||
|
Some(position) => {
|
||||||
|
// @TODO
|
||||||
|
Some(position)
|
||||||
|
}
|
||||||
|
None => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
|
|
||||||
/// Get selected `Item` GObject
|
/// Get selected `Item` GObject
|
||||||
pub fn selected_item(&self) -> Item {
|
pub fn selected(&self) -> Item {
|
||||||
self.dropdown
|
self.dropdown
|
||||||
.selected_item()
|
.selected_item()
|
||||||
.and_downcast::<Item>()
|
.and_downcast::<Item>()
|
||||||
|
@ -19,7 +19,7 @@ impl Name {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(action: Rc<Action>) -> Self {
|
pub fn new(widget_action: Rc<Action>) -> Self {
|
||||||
// Init main gobject
|
// Init main gobject
|
||||||
let entry = Entry::builder()
|
let entry = Entry::builder()
|
||||||
.margin_top(MARGIN)
|
.margin_top(MARGIN)
|
||||||
@ -29,7 +29,7 @@ impl Name {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Init events
|
// Init events
|
||||||
entry.connect_changed(move |_| action.update.activate());
|
entry.connect_changed(move |_| widget_action.update.activate());
|
||||||
|
|
||||||
// Return activated `Self`
|
// Return activated `Self`
|
||||||
Self { entry }
|
Self { entry }
|
||||||
@ -39,7 +39,7 @@ impl Name {
|
|||||||
|
|
||||||
/// Change visibility status
|
/// Change visibility status
|
||||||
/// * grab focus on `is_visible`
|
/// * grab focus on `is_visible`
|
||||||
pub fn update(&self, is_visible: bool) {
|
pub fn set_visible(&self, is_visible: bool) {
|
||||||
self.entry.set_visible(is_visible);
|
self.entry.set_visible(is_visible);
|
||||||
if is_visible {
|
if is_visible {
|
||||||
self.entry.grab_focus();
|
self.entry.grab_focus();
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
mod certificate;
|
mod certificate;
|
||||||
use certificate::Certificate;
|
use certificate::Certificate;
|
||||||
|
|
||||||
|
use super::list::{item::Value, List};
|
||||||
use crate::profile::Profile;
|
use crate::profile::Profile;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gio::{Cancellable, ListStore},
|
gio::{Cancellable, ListStore},
|
||||||
prelude::{ButtonExt, FileExt, WidgetExt},
|
prelude::{ButtonExt, FileExt, WidgetExt},
|
||||||
Button, FileDialog, FileFilter, Window,
|
Button, FileDialog, FileFilter, Window,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, fs::File, io::Write, rc::Rc};
|
use std::{fs::File, io::Write, rc::Rc};
|
||||||
|
|
||||||
const LABEL: &str = "Export";
|
const LABEL: &str = "Export";
|
||||||
const TOOLTIP_TEXT: &str = "Export selected identity to file";
|
const TOOLTIP_TEXT: &str = "Export selected identity to file";
|
||||||
const MARGIN: i32 = 8;
|
const MARGIN: i32 = 8;
|
||||||
|
|
||||||
pub struct Save {
|
pub struct Save {
|
||||||
profile_identity_gemini_id: Rc<RefCell<Option<i64>>>,
|
|
||||||
pub button: Button,
|
pub button: Button,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,10 +22,7 @@ impl Save {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(profile: Rc<Profile>) -> Self {
|
pub fn new(profile: Rc<Profile>, list: Rc<List>) -> Self {
|
||||||
// Init selected option holder
|
|
||||||
let profile_identity_gemini_id = Rc::new(RefCell::new(None));
|
|
||||||
|
|
||||||
// Init main widget
|
// Init main widget
|
||||||
let button = Button::builder()
|
let button = Button::builder()
|
||||||
.label(LABEL)
|
.label(LABEL)
|
||||||
@ -36,17 +33,16 @@ impl Save {
|
|||||||
|
|
||||||
// Init events
|
// Init events
|
||||||
button.connect_clicked({
|
button.connect_clicked({
|
||||||
let profile_identity_gemini_id = profile_identity_gemini_id.clone();
|
|
||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
move |_| {
|
move |_| {
|
||||||
// Get selected identity from holder
|
// Get selected identity from holder
|
||||||
match profile_identity_gemini_id.borrow().as_ref() {
|
match list.selected().value_enum() {
|
||||||
Some(profile_identity_gemini_id) => {
|
Value::ProfileIdentityGeminiId(profile_identity_gemini_id) => {
|
||||||
// Lock open button (prevent double click)
|
// Lock open button (prevent double click)
|
||||||
button.set_sensitive(false);
|
button.set_sensitive(false);
|
||||||
|
|
||||||
// Create PEM file based on option ID selected
|
// Create PEM file based on option ID selected
|
||||||
match Certificate::new(profile.clone(), *profile_identity_gemini_id) {
|
match Certificate::new(profile.clone(), profile_identity_gemini_id) {
|
||||||
Ok(certificate) => {
|
Ok(certificate) => {
|
||||||
// Init file filters related with PEM extension
|
// Init file filters related with PEM extension
|
||||||
let filters = ListStore::new::<FileFilter>();
|
let filters = ListStore::new::<FileFilter>();
|
||||||
@ -121,32 +117,18 @@ impl Save {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => todo!(), // unexpected
|
_ => todo!(), // unexpected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return activated `Self`
|
// Return activated `Self`
|
||||||
Self {
|
Self { button }
|
||||||
profile_identity_gemini_id,
|
|
||||||
button,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Update `profile_identity_gemini_id` holder,
|
pub fn set_visible(&self, is_visible: bool) {
|
||||||
/// toggle visibility depending on given value
|
self.button.set_visible(is_visible)
|
||||||
pub fn update(&self, profile_identity_gemini_id: Option<i64>) {
|
|
||||||
self.button.set_visible(match profile_identity_gemini_id {
|
|
||||||
Some(value) => {
|
|
||||||
self.profile_identity_gemini_id.replace(Some(value));
|
|
||||||
true
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.profile_identity_gemini_id.replace(None);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user