diff --git a/src/profile.rs b/src/profile.rs index 972d2ae..f8429fc 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -28,6 +28,7 @@ pub struct Profile { /** Install prefix */ pub prefix: String, pub can_be_built: bool, + pub editable: bool, } impl Display for Profile { @@ -121,6 +122,7 @@ mod tests { environment: env, prefix: String::from("/home/user/rex2prefix"), can_be_built: true, + editable: true, }; let fpath = String::from("./target/testout/testprofile.json"); p.dump_profile(&fpath); diff --git a/src/profiles/system_valve_index.rs b/src/profiles/system_valve_index.rs index 1fa2798..3928717 100644 --- a/src/profiles/system_valve_index.rs +++ b/src/profiles/system_valve_index.rs @@ -21,5 +21,6 @@ pub fn system_valve_index_profile() -> Profile { environment, prefix: SYSTEM_PREFIX.into(), can_be_built: false, + editable: false, } } diff --git a/src/profiles/valve_index.rs b/src/profiles/valve_index.rs index 88e60e8..1736495 100644 --- a/src/profiles/valve_index.rs +++ b/src/profiles/valve_index.rs @@ -24,5 +24,6 @@ pub fn valve_index_profile() -> Profile { environment, prefix, can_be_built: true, + editable: false, } } diff --git a/src/profiles/wivrn.rs b/src/profiles/wivrn.rs index 4e3ba97..5ffd1f4 100644 --- a/src/profiles/wivrn.rs +++ b/src/profiles/wivrn.rs @@ -21,5 +21,6 @@ pub fn wivrn_profile() -> Profile { environment, prefix, can_be_built: true, + editable: false, } } diff --git a/src/ui/main_view.rs b/src/ui/main_view.rs index 9915d5e..ae82034 100644 --- a/src/ui/main_view.rs +++ b/src/ui/main_view.rs @@ -12,6 +12,8 @@ use crate::ui::app::{ }; use crate::ui::profile_editor::ProfileEditorInit; use gtk::prelude::*; +use relm4::adw::traits::MessageDialogExt; +use relm4::adw::ResponseAppearance; use relm4::prelude::*; use relm4::{ComponentParts, ComponentSender, SimpleComponent}; use relm4_icons::icon_name; @@ -32,6 +34,8 @@ pub struct MainView { runtime_switcher_box: Controller, #[tracker::do_not_track] profile_editor: Controller, + #[tracker::do_not_track] + profile_not_editable_dialog: adw::MessageDialog, } #[derive(Debug)] @@ -45,6 +49,7 @@ pub enum MainViewMsg { ProfileSelected(u32), UpdateSelectedProfile(Profile), EditProfile, + DuplicateProfile, } #[derive(Debug)] @@ -231,7 +236,15 @@ impl SimpleComponent for MainView { )); } Self::Input::EditProfile => { - self.profile_editor.emit(ProfileEditorMsg::Present(self.selected_profile.clone())); + if self.selected_profile.editable { + self.profile_editor + .emit(ProfileEditorMsg::Present(self.selected_profile.clone())); + } else { + self.profile_not_editable_dialog.present(); + } + } + Self::Input::DuplicateProfile => { + println!("dup") } } } @@ -241,6 +254,30 @@ impl SimpleComponent for MainView { root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { + let profile_not_editable_dialog = adw::MessageDialog::builder() + .modal(true) + // .transient_for(root.root().unwrap().upcast_ref::()) + .heading("This profile is not editable") + .body(concat!( + "You can duplicate it and edit the new copy. ", + "Do you want to duplicate the current profile?" + )) + .hide_on_close(true) + .build(); + profile_not_editable_dialog.add_response("no", "_No"); + profile_not_editable_dialog.add_response("yes", "_Yes"); + profile_not_editable_dialog.set_response_appearance("no", ResponseAppearance::Destructive); + profile_not_editable_dialog.set_response_appearance("yes", ResponseAppearance::Suggested); + + { + let pne_sender = sender.clone(); + profile_not_editable_dialog.connect_response(None, move |_, res| { + if res == "yes" { + pne_sender.input(Self::Input::DuplicateProfile); + } + }); + } + let mut model = Self { xrservice_active: false, enable_debug_view: init.config.debug_view_enabled, @@ -257,8 +294,11 @@ impl SimpleComponent for MainView { selected_profile: init.selected_profile.clone(), }) .detach(), - profile_editor: ProfileEditor::builder().launch(ProfileEditorInit {}).detach(), + profile_editor: ProfileEditor::builder() + .launch(ProfileEditorInit {}) + .detach(), selected_profile: init.selected_profile.clone(), + profile_not_editable_dialog, tracker: 0, }; let widgets = view_output!(); diff --git a/src/ui/profile_editor.rs b/src/ui/profile_editor.rs index 04c55b1..3d4c410 100644 --- a/src/ui/profile_editor.rs +++ b/src/ui/profile_editor.rs @@ -5,13 +5,20 @@ use gtk::prelude::*; use relm4::{factory::FactoryVecDeque, prelude::*}; use relm4_icons::icon_name; +#[tracker::track] pub struct ProfileEditor { profile: Option, + + #[tracker::do_not_track] win: Option, + #[tracker::do_not_track] name_row: adw::EntryRow, + #[tracker::do_not_track] env_rows: FactoryVecDeque, + #[tracker::do_not_track] switch_rows: FactoryVecDeque, + #[tracker::do_not_track] path_rows: FactoryVecDeque, } @@ -36,6 +43,11 @@ impl SimpleComponent for ProfileEditor { adw::PreferencesWindow { set_hide_on_close: true, set_modal: true, + #[track = "model.changed(Self::profile())"] + set_title: match model.profile.as_ref() { + Some(p) => Some(p.name.as_str()), + None => None, + }, add: mainpage = &adw::PreferencesPage { add: maingrp = &adw::PreferencesGroup { set_title: "Profile Info", @@ -49,13 +61,14 @@ impl SimpleComponent for ProfileEditor { } fn update(&mut self, message: Self::Input, sender: ComponentSender) { + self.reset(); + match message { Self::Input::Present(prof) => { - let win = self.win.as_ref().unwrap(); let p = prof.clone(); - win.set_title(Some(p.name.as_str())); self.name_row.set_text(p.name.as_str()); + self.env_rows.guard().clear(); for (k, v) in p.environment.iter() { self.env_rows.guard().push_back(EntryModelInit { @@ -111,8 +124,9 @@ impl SimpleComponent for ProfileEditor { value: p.mercury_path }); - self.profile = Some(prof); - win.present(); + self.set_profile(Some(prof.clone())); + + self.win.as_ref().unwrap().present(); } Self::Input::SaveProfile => {} Self::Input::EntryChanged(name, value) => { @@ -173,7 +187,8 @@ impl SimpleComponent for ProfileEditor { // .description("") .build(), sender.input_sender(), - ) + ), + tracker: 0, }; let widgets = view_output!();