mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-07-29 12:18:56 +00:00
feat: profile editor can add and remove env vars
This commit is contained in:
parent
13a1a951a9
commit
371f874e3b
3 changed files with 93 additions and 30 deletions
|
@ -4,33 +4,35 @@ use gtk::prelude::*;
|
||||||
use relm4::prelude::*;
|
use relm4::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EntryModel {
|
pub struct EnvVarModel {
|
||||||
name: String,
|
pub name: String,
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EntryModelInit {
|
pub struct EnvVarModelInit {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EntryModelMsg {
|
pub enum EnvVarModelMsg {
|
||||||
Changed(String),
|
Changed(String),
|
||||||
|
Delete,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EntryModelOutMsg {
|
pub enum EnvVarModelOutMsg {
|
||||||
Changed(String, String),
|
Changed(String, String),
|
||||||
|
Delete(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[relm4::factory(pub)]
|
#[relm4::factory(pub)]
|
||||||
impl FactoryComponent for EntryModel {
|
impl FactoryComponent for EnvVarModel {
|
||||||
type Init = EntryModelInit;
|
type Init = EnvVarModelInit;
|
||||||
type Input = EntryModelMsg;
|
type Input = EnvVarModelMsg;
|
||||||
type Output = EntryModelOutMsg;
|
type Output = EnvVarModelOutMsg;
|
||||||
type CommandOutput = ();
|
type CommandOutput = ();
|
||||||
type Widgets = EntryModelWidgets;
|
type Widgets = EnvVarModelWidgets;
|
||||||
type ParentInput = ProfileEditorMsg;
|
type ParentInput = ProfileEditorMsg;
|
||||||
type ParentWidget = adw::PreferencesGroup;
|
type ParentWidget = adw::PreferencesGroup;
|
||||||
|
|
||||||
|
@ -38,6 +40,16 @@ impl FactoryComponent for EntryModel {
|
||||||
root = adw::EntryRow {
|
root = adw::EntryRow {
|
||||||
set_title: &self.name,
|
set_title: &self.name,
|
||||||
set_text: &self.value,
|
set_text: &self.value,
|
||||||
|
add_suffix: del_btn = >k::Button {
|
||||||
|
set_icon_name: "edit-delete-symbolic",
|
||||||
|
set_tooltip_text: Some("Delete Environment Variable"),
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
add_css_class: "flat",
|
||||||
|
add_css_class: "circular",
|
||||||
|
connect_clicked[sender] => move |_| {
|
||||||
|
sender.input(Self::Input::Delete);
|
||||||
|
}
|
||||||
|
},
|
||||||
connect_changed[sender] => move |entry| {
|
connect_changed[sender] => move |entry| {
|
||||||
sender.input_sender().emit(Self::Input::Changed(entry.text().to_string()));
|
sender.input_sender().emit(Self::Input::Changed(entry.text().to_string()));
|
||||||
},
|
},
|
||||||
|
@ -52,12 +64,16 @@ impl FactoryComponent for EntryModel {
|
||||||
.output_sender()
|
.output_sender()
|
||||||
.emit(Self::Output::Changed(self.name.clone(), val));
|
.emit(Self::Output::Changed(self.name.clone(), val));
|
||||||
}
|
}
|
||||||
|
Self::Input::Delete => {
|
||||||
|
sender.output(Self::Output::Delete(self.name.clone()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||||
Some(match output {
|
Some(match output {
|
||||||
Self::Output::Changed(name, value) => ProfileEditorMsg::EntryChanged(name, value),
|
Self::Output::Changed(name, value) => ProfileEditorMsg::EnvVarChanged(name, value),
|
||||||
|
Self::Output::Delete(name) => ProfileEditorMsg::EnvVarDelete(name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
pub mod entry_row_factory;
|
pub mod env_var_row_factory;
|
||||||
pub mod switch_row_factory;
|
pub mod switch_row_factory;
|
||||||
pub mod path_row_factory;
|
pub mod path_row_factory;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::factories::{
|
use super::factories::{
|
||||||
entry_row_factory::{EntryModel, EntryModelInit},
|
env_var_row_factory::{EnvVarModel, EnvVarModelInit},
|
||||||
path_row_factory::{PathModel, PathModelInit},
|
path_row_factory::{PathModel, PathModelInit},
|
||||||
switch_row_factory::{SwitchModel, SwitchModelInit},
|
switch_row_factory::{SwitchModel, SwitchModelInit},
|
||||||
};
|
};
|
||||||
|
@ -24,7 +24,7 @@ pub struct ProfileEditor {
|
||||||
#[tracker::do_not_track]
|
#[tracker::do_not_track]
|
||||||
type_row: adw::ComboRow,
|
type_row: adw::ComboRow,
|
||||||
#[tracker::do_not_track]
|
#[tracker::do_not_track]
|
||||||
env_rows: FactoryVecDeque<EntryModel>,
|
env_rows: FactoryVecDeque<EnvVarModel>,
|
||||||
#[tracker::do_not_track]
|
#[tracker::do_not_track]
|
||||||
switch_rows: FactoryVecDeque<SwitchModel>,
|
switch_rows: FactoryVecDeque<SwitchModel>,
|
||||||
#[tracker::do_not_track]
|
#[tracker::do_not_track]
|
||||||
|
@ -34,12 +34,13 @@ pub struct ProfileEditor {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ProfileEditorMsg {
|
pub enum ProfileEditorMsg {
|
||||||
Present(Profile),
|
Present(Profile),
|
||||||
EntryChanged(String, String),
|
EnvVarChanged(String, String),
|
||||||
|
EnvVarDelete(String),
|
||||||
TextChanged(String, String),
|
TextChanged(String, String),
|
||||||
PathChanged(String, Option<String>),
|
PathChanged(String, Option<String>),
|
||||||
SwitchChanged(String, bool),
|
SwitchChanged(String, bool),
|
||||||
ComboChanged(String, String),
|
ComboChanged(String, String),
|
||||||
AddEnvVar,
|
AddEnvVar(String),
|
||||||
SaveProfile,
|
SaveProfile,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +108,7 @@ impl SimpleComponent for ProfileEditor {
|
||||||
|
|
||||||
self.env_rows.guard().clear();
|
self.env_rows.guard().clear();
|
||||||
for (k, v) in p.environment.iter() {
|
for (k, v) in p.environment.iter() {
|
||||||
self.env_rows.guard().push_back(EntryModelInit {
|
self.env_rows.guard().push_back(EnvVarModelInit {
|
||||||
name: k.clone(),
|
name: k.clone(),
|
||||||
value: v.clone(),
|
value: v.clone(),
|
||||||
});
|
});
|
||||||
|
@ -175,18 +176,31 @@ impl SimpleComponent for ProfileEditor {
|
||||||
sender.output(ProfileEditorOutMsg::SaveProfile(prof.clone()));
|
sender.output(ProfileEditorOutMsg::SaveProfile(prof.clone()));
|
||||||
self.win.as_ref().unwrap().close();
|
self.win.as_ref().unwrap().close();
|
||||||
} else {
|
} else {
|
||||||
self.win.as_ref().unwrap().add_toast(adw::Toast::builder().title("Profile failed validation").build());
|
self.win.as_ref().unwrap().add_toast(
|
||||||
|
adw::Toast::builder()
|
||||||
|
.title("Profile failed validation")
|
||||||
|
.build(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: rename to reflect this is only for env
|
Self::Input::EnvVarChanged(name, value) => {
|
||||||
// + make entryfactory take a signal to send to parent
|
|
||||||
Self::Input::EntryChanged(name, value) => {
|
|
||||||
self.profile
|
self.profile
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.environment
|
.environment
|
||||||
.insert(name, value);
|
.insert(name, value);
|
||||||
}
|
}
|
||||||
|
Self::Input::EnvVarDelete(name) => {
|
||||||
|
self.profile.as_mut().unwrap().environment.remove(&name);
|
||||||
|
let pos = self
|
||||||
|
.env_rows
|
||||||
|
.guard()
|
||||||
|
.iter()
|
||||||
|
.position(|evr| evr.name == name);
|
||||||
|
if pos.is_some() {
|
||||||
|
self.env_rows.guard().remove(pos.unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::Input::PathChanged(key, value) => {
|
Self::Input::PathChanged(key, value) => {
|
||||||
let prof = self.profile.as_mut().unwrap();
|
let prof = self.profile.as_mut().unwrap();
|
||||||
match key.as_str() {
|
match key.as_str() {
|
||||||
|
@ -224,8 +238,15 @@ impl SimpleComponent for ProfileEditor {
|
||||||
_ => panic!("Unknown profile text key"),
|
_ => panic!("Unknown profile text key"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Input::AddEnvVar => {
|
Self::Input::AddEnvVar(name) => {
|
||||||
println!("Add env var");
|
let prof = self.profile.as_mut().unwrap();
|
||||||
|
if !prof.environment.contains_key(&name) {
|
||||||
|
prof.environment.insert(name.clone(), "".to_string());
|
||||||
|
self.env_rows.guard().push_back(EnvVarModelInit {
|
||||||
|
name,
|
||||||
|
value: "".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,19 +256,45 @@ impl SimpleComponent for ProfileEditor {
|
||||||
root: &Self::Root,
|
root: &Self::Root,
|
||||||
sender: ComponentSender<Self>,
|
sender: ComponentSender<Self>,
|
||||||
) -> ComponentParts<Self> {
|
) -> ComponentParts<Self> {
|
||||||
let add_env_var_btn = gtk::Button::builder()
|
let add_env_popover = gtk::Popover::builder().build();
|
||||||
|
let add_env_popover_box = gtk::Box::builder()
|
||||||
|
.orientation(gtk::Orientation::Horizontal)
|
||||||
|
.css_classes(["linked"])
|
||||||
|
.build();
|
||||||
|
let add_env_name_entry = gtk::Entry::builder()
|
||||||
|
.placeholder_text("Env Var Name...")
|
||||||
|
.build();
|
||||||
|
let add_env_btn = gtk::Button::builder()
|
||||||
|
.css_classes(["suggested-action"])
|
||||||
|
.icon_name("list-add-symbolic")
|
||||||
|
.tooltip_text("Add Env Var")
|
||||||
|
.build();
|
||||||
|
{
|
||||||
|
let aeb_sender = sender.clone();
|
||||||
|
let entry = add_env_name_entry.clone();
|
||||||
|
let popover = add_env_popover.clone();
|
||||||
|
add_env_btn.connect_clicked(move |_| {
|
||||||
|
let name_gstr = entry.text();
|
||||||
|
let name = name_gstr.trim();
|
||||||
|
if !name.is_empty() {
|
||||||
|
popover.popdown();
|
||||||
|
entry.set_text("");
|
||||||
|
aeb_sender.input(Self::Input::AddEnvVar(name.to_string()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
add_env_popover_box.append(&add_env_name_entry);
|
||||||
|
add_env_popover_box.append(&add_env_btn);
|
||||||
|
add_env_popover.set_child(Some(&add_env_popover_box));
|
||||||
|
|
||||||
|
let add_env_var_btn = gtk::MenuButton::builder()
|
||||||
.icon_name(icon_name::PLUS)
|
.icon_name(icon_name::PLUS)
|
||||||
.tooltip_text("Add Environment Variable")
|
.tooltip_text("Add Environment Variable")
|
||||||
.css_classes(["flat"])
|
.css_classes(["flat"])
|
||||||
|
.popover(&add_env_popover)
|
||||||
.valign(gtk::Align::Start)
|
.valign(gtk::Align::Start)
|
||||||
.halign(gtk::Align::End)
|
.halign(gtk::Align::End)
|
||||||
.build();
|
.build();
|
||||||
{
|
|
||||||
let btn_sender = sender.clone();
|
|
||||||
add_env_var_btn.connect_clicked(move |_| {
|
|
||||||
btn_sender.input(Self::Input::AddEnvVar);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut model = Self {
|
let mut model = Self {
|
||||||
profile: None,
|
profile: None,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue