chore: remove withclones macro and use glib::clone instead

This commit is contained in:
Gabriele Musco 2023-12-23 11:52:17 +00:00
commit 9b5d74594b
8 changed files with 297 additions and 374 deletions

View file

@ -42,12 +42,13 @@ use crate::profiles::openhmd::openhmd_profile;
use crate::profiles::survive::survive_profile; use crate::profiles::survive::survive_profile;
use crate::profiles::wivrn::wivrn_profile; use crate::profiles::wivrn::wivrn_profile;
use crate::profiles::wmr::wmr_profile; use crate::profiles::wmr::wmr_profile;
use crate::stateless_action;
use crate::ui::build_window::{BuildWindowMsg, BuildWindowOutMsg}; use crate::ui::build_window::{BuildWindowMsg, BuildWindowOutMsg};
use crate::ui::debug_view::DebugViewInit; use crate::ui::debug_view::DebugViewInit;
use crate::ui::libsurvive_setup_window::LibsurviveSetupMsg; use crate::ui::libsurvive_setup_window::LibsurviveSetupMsg;
use crate::ui::main_view::{MainView, MainViewInit, MainViewOutMsg}; use crate::ui::main_view::{MainView, MainViewInit, MainViewOutMsg};
use crate::xr_devices::XRDevice; use crate::xr_devices::XRDevice;
use crate::{stateless_action, withclones}; use gtk::glib::clone;
use gtk::prelude::*; use gtk::prelude::*;
use relm4::actions::{AccelsPlus, ActionGroupName, RelmAction, RelmActionGroup}; use relm4::actions::{AccelsPlus, ActionGroupName, RelmAction, RelmActionGroup};
use relm4::adw::traits::MessageDialogExt; use relm4::adw::traits::MessageDialogExt;
@ -724,71 +725,76 @@ impl SimpleComponent for App {
let mut actions = RelmActionGroup::<AppActionGroup>::new(); let mut actions = RelmActionGroup::<AppActionGroup>::new();
{ stateless_action!(
withclones![sender]; actions,
stateless_action!(actions, BuildProfileAction, { BuildProfileAction,
clone!(@strong sender => move |_| {
sender.input_sender().emit(Msg::BuildProfile(false, false)); sender.input_sender().emit(Msg::BuildProfile(false, false));
}); })
} );
{ stateless_action!(
withclones![sender]; actions,
stateless_action!(actions, BuildProfileCleanAction, { BuildProfileCleanAction,
clone!(@strong sender => move |_| {
sender.input_sender().emit(Msg::BuildProfile(true, false)); sender.input_sender().emit(Msg::BuildProfile(true, false));
}); })
} );
{ stateless_action!(
withclones![sender]; actions,
stateless_action!(actions, BuildProfileDebugAction, { BuildProfileDebugAction,
clone!(@strong sender => move |_| {
sender.input_sender().emit(Msg::BuildProfile(false, true)); sender.input_sender().emit(Msg::BuildProfile(false, true));
}); })
} );
{ stateless_action!(
withclones![sender]; actions,
stateless_action!(actions, BuildProfileCleanDebugAction, { BuildProfileCleanDebugAction,
clone!(@strong sender => move |_| {
sender.input_sender().emit(Msg::BuildProfile(true, true)); sender.input_sender().emit(Msg::BuildProfile(true, true));
}); })
} );
{ stateless_action!(
withclones![sender]; actions,
stateless_action!(actions, ConfigFbtAction, { ConfigFbtAction,
clone!(@strong sender => move |_| {
sender.input_sender().emit(Msg::ConfigFbt); sender.input_sender().emit(Msg::ConfigFbt);
}); })
} );
{ {
let abd_sender = model.about_dialog.sender().clone(); let abd_sender = model.about_dialog.sender().clone();
stateless_action!(actions, AboutAction, { stateless_action!(actions, AboutAction, move |_| {
abd_sender.send(()).unwrap(); abd_sender.send(()).unwrap();
}); });
} }
{ stateless_action!(
withclones![sender]; actions,
stateless_action!(actions, QuitAction, { QuitAction,
clone!(@strong sender => move |_| {
sender.input(Msg::Quit); sender.input(Msg::Quit);
}); })
} );
{ stateless_action!(
withclones![sender]; actions,
stateless_action!(actions, DebugOpenDataAction, { DebugOpenDataAction,
clone!(@strong sender => move |_| {
sender.input(Msg::DebugOpenData); sender.input(Msg::DebugOpenData);
}); })
} );
{ stateless_action!(
withclones![sender]; actions,
stateless_action!(actions, DebugOpenPrefixAction, { DebugOpenPrefixAction,
clone!(@strong sender => move |_| {
sender.input(Msg::DebugOpenPrefix); sender.input(Msg::DebugOpenPrefix);
}); })
} );
{
withclones![sender];
actions.add_action(RelmAction::<DebugViewToggleAction>::new_stateful( actions.add_action(RelmAction::<DebugViewToggleAction>::new_stateful(
&model.enable_debug_view, &model.enable_debug_view,
move |_, state| { clone!(@strong sender => move |_, state| {
let s = *state; let s = *state;
*state = !s; *state = !s;
sender.input(Msg::EnableDebugViewChanged(*state)); sender.input(Msg::EnableDebugViewChanged(*state));
}, }),
)) ));
}
root.insert_action_group(AppActionGroup::NAME, Some(&actions.into_action_group())); root.insert_action_group(AppActionGroup::NAME, Some(&actions.into_action_group()));
@ -804,13 +810,13 @@ impl SimpleComponent for App {
model.config.clone(), model.config.clone(),
)); ));
{ glib::timeout_add_local(
withclones![sender]; Duration::from_millis(1000),
glib::timeout_add_local(Duration::from_millis(1000), move || { clone!(@strong sender => move || {
sender.input(Msg::ClockTicking); sender.input(Msg::ClockTicking);
glib::ControlFlow::Continue glib::ControlFlow::Continue
}); }),
} );
model.split_view = Some(widgets.split_view.clone()); model.split_view = Some(widgets.split_view.clone());

View file

@ -1,7 +1,7 @@
use crate::log_level::LogLevel; use crate::log_level::LogLevel;
use crate::log_parser::MonadoLog; use crate::log_parser::MonadoLog;
use crate::ui::app::{DebugOpenDataAction, DebugOpenPrefixAction}; use crate::ui::app::{DebugOpenDataAction, DebugOpenPrefixAction};
use crate::withclones; use gtk::glib::clone;
use gtk::prelude::*; use gtk::prelude::*;
use relm4::prelude::*; use relm4::prelude::*;
use relm4::{ComponentSender, SimpleComponent}; use relm4::{ComponentSender, SimpleComponent};
@ -270,24 +270,18 @@ impl SimpleComponent for DebugView {
if let Some(btn) = log_level_dropdown.first_child() { if let Some(btn) = log_level_dropdown.first_child() {
btn.add_css_class("flat"); btn.add_css_class("flat");
} }
{ log_level_dropdown.connect_selected_notify(clone!(@strong sender => move |dd| {
withclones![sender];
log_level_dropdown.connect_selected_notify(move |dd| {
sender.input(Self::Input::LogLevelChanged( sender.input(Self::Input::LogLevelChanged(
*LogLevel::iter() *LogLevel::iter()
.as_slice() .as_slice()
.get(dd.selected() as usize) .get(dd.selected() as usize)
.unwrap(), .unwrap(),
)); ));
}); }));
}
{ adw::StyleManager::default().connect_dark_notify(clone!(@strong sender => move |_| {
withclones![sender];
adw::StyleManager::default().connect_dark_notify(move |_| {
sender.input(Self::Input::SetColorScheme); sender.input(Self::Input::SetColorScheme);
}); }));
}
Self::set_color_scheme(&textbuf); Self::set_color_scheme(&textbuf);
let mut model = Self { let mut model = Self {

View file

@ -2,9 +2,9 @@ use crate::{
file_builders::monado_config_v0::{TrackerRole, XrtTrackerRole}, file_builders::monado_config_v0::{TrackerRole, XrtTrackerRole},
ui::fbt_config_editor::FbtConfigEditorMsg, ui::fbt_config_editor::FbtConfigEditorMsg,
ui::preference_rows::{combo_row, entry_row}, ui::preference_rows::{combo_row, entry_row},
withclones,
}; };
use adw::prelude::*; use adw::prelude::*;
use gtk::glib::clone;
use relm4::{factory::AsyncFactoryComponent, prelude::*, AsyncFactorySender}; use relm4::{factory::AsyncFactoryComponent, prelude::*, AsyncFactorySender};
#[derive(Debug)] #[derive(Debug)]
@ -54,27 +54,29 @@ impl AsyncFactoryComponent for TrackerRoleModel {
} }
}, },
add: { add: {
withclones![sender];
let tr = self.tracker_role.clone(); let tr = self.tracker_role.clone();
&entry_row("Device serial", self.tracker_role.device_serial.as_str(), move |row| { &entry_row(
"Device serial",
self.tracker_role.device_serial.as_str(),
clone!(@strong sender => move |row| {
let mut ntr = tr.clone(); let mut ntr = tr.clone();
ntr.device_serial = row.text().to_string(); ntr.device_serial = row.text().to_string();
sender.input(Self::Input::Changed(ntr)); sender.input(Self::Input::Changed(ntr));
}) })
)
}, },
add: { add: {
withclones![sender];
let tr = self.tracker_role.clone(); let tr = self.tracker_role.clone();
&combo_row("Tracker role", None, &tr.role.clone().to_picker_string(), &combo_row("Tracker role", None, &tr.role.clone().to_picker_string(),
XrtTrackerRole::iter() XrtTrackerRole::iter()
.map(XrtTrackerRole::to_picker_string) .map(XrtTrackerRole::to_picker_string)
.map(String::from) .map(String::from)
.collect::<Vec<String>>(), .collect::<Vec<String>>(),
move |row| { clone!(@strong sender => move |row| {
let mut ntr = tr.clone(); let mut ntr = tr.clone();
ntr.role = XrtTrackerRole::from_number(&row.selected()); ntr.role = XrtTrackerRole::from_number(&row.selected());
sender.input(Self::Input::Changed(ntr)); sender.input(Self::Input::Changed(ntr));
} })
) )
}, },
} }

View file

@ -4,9 +4,9 @@ use crate::{
dump_monado_config_v0, get_monado_config_v0, MonadoConfigV0, TrackerRole, dump_monado_config_v0, get_monado_config_v0, MonadoConfigV0, TrackerRole,
}, },
ui::factories::tracker_role_group_factory::TrackerRoleModelInit, ui::factories::tracker_role_group_factory::TrackerRoleModelInit,
withclones,
}; };
use adw::prelude::*; use adw::prelude::*;
use gtk::glib::clone;
use relm4::{factory::AsyncFactoryVecDeque, prelude::*}; use relm4::{factory::AsyncFactoryVecDeque, prelude::*};
#[tracker::track] #[tracker::track]
@ -113,18 +113,12 @@ impl SimpleComponent for FbtConfigEditor {
.label("Save") .label("Save")
.css_classes(["suggested-action"]) .css_classes(["suggested-action"])
.build(); .build();
{ add_btn.connect_clicked(clone!(@strong sender => move |_| {
withclones![sender];
add_btn.connect_clicked(move |_| {
sender.input(Self::Input::TrackerRoleNew); sender.input(Self::Input::TrackerRoleNew);
}); }));
}; save_btn.connect_clicked(clone!(@strong sender => move |_| {
{
withclones![sender];
save_btn.connect_clicked(move |_| {
sender.input(Self::Input::Save); sender.input(Self::Input::Save);
}); }));
};
let mut model = Self { let mut model = Self {
win: None, win: None,

View file

@ -1,7 +1,4 @@
use crate::{ use crate::profile::{LighthouseDriver, Profile};
profile::{LighthouseDriver, Profile},
withclones,
};
use super::{ use super::{
job::{CmdWorkerData, FuncWorkerOut, WorkerJob}, job::{CmdWorkerData, FuncWorkerOut, WorkerJob},
@ -92,7 +89,7 @@ impl Worker for InternalJobWorker {
let mut job = self.jobs.pop_front().unwrap(); let mut job = self.jobs.pop_front().unwrap();
match &mut job { match &mut job {
WorkerJob::Cmd(data) => { WorkerJob::Cmd(data) => {
withclones![data]; let data = data.clone();
if let Ok(mut cmd) = Command::new(data.command) if let Ok(mut cmd) = Command::new(data.command)
.args(data.args) .args(data.args)
.envs(data.environment) .envs(data.environment)

View file

@ -1,13 +1,6 @@
#[macro_export]
macro_rules! withclones {
($($var:ident),+) => {
$(let $var = $var.clone();)+
};
}
#[macro_export] #[macro_export]
macro_rules! stateless_action { macro_rules! stateless_action {
($group:ident, $name:ident, $ex:expr) => { ($group:ident, $name:ident, $fun:expr) => {
$group.add_action(RelmAction::<$name>::new_stateless(move |_| $ex)); $group.add_action(RelmAction::<$name>::new_stateless($fun));
}; };
} }

View file

@ -1,8 +1,7 @@
use crate::withclones;
use adw::prelude::*; use adw::prelude::*;
use gtk::{ use gtk::{
gio, gio,
glib::{self, GString}, glib::{self, clone, GString},
}; };
use relm4::prelude::*; use relm4::prelude::*;
@ -94,23 +93,17 @@ pub fn path_row<F: Fn(Option<String>) + 'static + Clone>(
.valign(gtk::Align::Center) .valign(gtk::Align::Center)
.build(); .build();
row.add_suffix(&clear_btn); row.add_suffix(&clear_btn);
{ clear_btn.connect_clicked(clone!(@strong path_label, @strong cb => move |_| {
withclones![path_label, cb];
clear_btn.connect_clicked(move |_| {
path_label.set_label("(None)"); path_label.set_label("(None)");
cb(None) cb(None)
}); }));
}
let filedialog = gtk::FileDialog::builder() let filedialog = gtk::FileDialog::builder()
.modal(true) .modal(true)
.title(format!("Select Path for {}", title)) .title(format!("Select Path for {}", title))
.build(); .build();
{ row.connect_activated(clone!(@strong path_label => move |_| {
withclones![path_label]; filedialog.select_folder(root_win.as_ref(), gio::Cancellable::NONE, clone!(@strong path_label, @strong cb => move |res| {
row.connect_activated(move |_| {
withclones![path_label, cb];
filedialog.select_folder(root_win.as_ref(), gio::Cancellable::NONE, move |res| {
if let Ok(file) = res { if let Ok(file) = res {
if let Some(path) = file.path() { if let Some(path) = file.path() {
let path_s = path.to_str().unwrap().to_string(); let path_s = path.to_str().unwrap().to_string();
@ -118,9 +111,8 @@ pub fn path_row<F: Fn(Option<String>) + 'static + Clone>(
cb(Some(path_s)) cb(Some(path_s))
} }
} }
}) }))
}); }));
}
row row
} }

View file

@ -6,9 +6,9 @@ use crate::{
env_var_descriptions::env_var_descriptions_as_paragraph, env_var_descriptions::env_var_descriptions_as_paragraph,
profile::{LighthouseDriver, Profile, XRServiceType}, profile::{LighthouseDriver, Profile, XRServiceType},
ui::preference_rows::{combo_row, entry_row, path_row, switch_row}, ui::preference_rows::{combo_row, entry_row, path_row, switch_row},
withclones,
}; };
use adw::prelude::*; use adw::prelude::*;
use gtk::glib::clone;
use relm4::{factory::AsyncFactoryVecDeque, prelude::*}; use relm4::{factory::AsyncFactoryVecDeque, prelude::*};
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
@ -80,35 +80,30 @@ impl SimpleComponent for ProfileEditor {
set_vexpand: true, set_vexpand: true,
add: maingrp = &adw::PreferencesGroup { add: maingrp = &adw::PreferencesGroup {
set_title: "General", set_title: "General",
add: { add: &entry_row(
withclones![prof]; "Profile Name",
&entry_row("Profile Name", model.profile.borrow().name.as_str(), move |row| { model.profile.borrow().name.as_str(),
clone!(@strong prof => move |row| {
prof.borrow_mut().name = row.text().to_string(); prof.borrow_mut().name = row.text().to_string();
}) })
}, ),
add: { add: &switch_row(
withclones![prof];
&switch_row(
"Update on Build", None, "Update on Build", None,
model.profile.borrow().pull_on_build, model.profile.borrow().pull_on_build,
move |_, state| { clone!(@strong prof => move |_, state| {
prof.borrow_mut().pull_on_build = state; prof.borrow_mut().pull_on_build = state;
gtk::glib::Propagation::Proceed gtk::glib::Propagation::Proceed
} })
) ),
}, add: &path_row(
add: {
withclones![prof];
&path_row(
"Install Prefix", "Install Prefix",
None, None,
Some(model.profile.borrow().prefix.clone()), Some(model.profile.borrow().prefix.clone()),
Some(init.root_win.clone()), Some(init.root_win.clone()),
move |n_path| { clone!(@strong prof => move |n_path| {
prof.borrow_mut().prefix = n_path.unwrap_or_default() prof.borrow_mut().prefix = n_path.unwrap_or_default()
}, }),
) ),
},
}, },
add: xrservicegrp = &adw::PreferencesGroup { add: xrservicegrp = &adw::PreferencesGroup {
set_title: "XR Service", set_title: "XR Service",
@ -119,34 +114,26 @@ impl SimpleComponent for ProfileEditor {
"For launch options, you can insert %command% as ", "For launch options, you can insert %command% as ",
"a placeholder for the actual XR Service command.", "a placeholder for the actual XR Service command.",
)), )),
add: { add: &combo_row(
withclones![prof];
&combo_row(
"XR Service Type", "XR Service Type",
Some("Monado is for PCVR headsets, while WiVRn is for Andorid standalone headsets"), Some("Monado is for PCVR headsets, while WiVRn is for Andorid standalone headsets"),
model.profile.borrow().xrservice_type.to_string().as_str(), model.profile.borrow().xrservice_type.to_string().as_str(),
XRServiceType::iter() XRServiceType::iter()
.map(XRServiceType::to_string) .map(XRServiceType::to_string)
.collect::<Vec<String>>(), .collect::<Vec<String>>(),
move |row| { clone!(@strong prof => move |row| {
prof.borrow_mut().xrservice_type = prof.borrow_mut().xrservice_type =
XRServiceType::from_number(row.selected()); XRServiceType::from_number(row.selected());
}, }),
) ),
}, add: &entry_row(
add: {
withclones![prof];
&entry_row(
"XR Service Launch Options", "XR Service Launch Options",
model.profile.borrow().xrservice_launch_options.as_str(), model.profile.borrow().xrservice_launch_options.as_str(),
move |row| { clone!(@strong prof => move |row| {
prof.borrow_mut().xrservice_launch_options = row.text().trim().to_string(); prof.borrow_mut().xrservice_launch_options = row.text().trim().to_string();
} })
) ),
}, add: &combo_row(
add: {
withclones![prof];
&combo_row(
"Lighthouse Driver", "Lighthouse Driver",
Some(concat!( Some(concat!(
"Driver for lighhouse tracked XR devices (ie: Valve Index, HTC Vive...). Only applicable for Monado.\n\n", "Driver for lighhouse tracked XR devices (ie: Valve Index, HTC Vive...). Only applicable for Monado.\n\n",
@ -158,188 +145,145 @@ impl SimpleComponent for ProfileEditor {
LighthouseDriver::iter() LighthouseDriver::iter()
.map(LighthouseDriver::to_string) .map(LighthouseDriver::to_string)
.collect::<Vec<String>>(), .collect::<Vec<String>>(),
move |row| { clone!(@strong prof => move |row| {
prof.borrow_mut().lighthouse_driver = prof.borrow_mut().lighthouse_driver =
LighthouseDriver::from_number(row.selected()); LighthouseDriver::from_number(row.selected());
} })
) ),
}, add: &path_row(
add: {
withclones![prof];
&path_row(
"XR Service Path", "XR Service Path",
None, None,
Some(model.profile.borrow().xrservice_path.clone()), Some(model.profile.borrow().xrservice_path.clone()),
Some(init.root_win.clone()), Some(init.root_win.clone()),
move |n_path| { clone!(@strong prof => move |n_path| {
prof.borrow_mut().xrservice_path = n_path.unwrap_or_default() prof.borrow_mut().xrservice_path = n_path.unwrap_or_default()
}, }),
) ),
}, add: &entry_row(
add: {
withclones![prof];
&entry_row(
"XR Service Repo", "XR Service Repo",
model.profile.borrow().xrservice_repo.clone().unwrap_or_default().as_str(), model.profile.borrow().xrservice_repo.clone().unwrap_or_default().as_str(),
move |row| { clone!(@strong prof => move |row| {
let n_val = row.text().to_string(); let n_val = row.text().to_string();
prof.borrow_mut().xrservice_repo = (!n_val.is_empty()).then_some(n_val); prof.borrow_mut().xrservice_repo = (!n_val.is_empty()).then_some(n_val);
} })
) ),
},
}, },
add: model.xrservice_cmake_flags_rows.widget(), add: model.xrservice_cmake_flags_rows.widget(),
add: opencompgrp = &adw::PreferencesGroup { add: opencompgrp = &adw::PreferencesGroup {
set_title: "OpenComposite", set_title: "OpenComposite",
set_description: Some("OpenVR driver built on top of OpenXR\n\nWhen specifying a repository, you can set a specific git ref (branch, tag, commit...) by appending a '#' followed by the ref"), set_description: Some("OpenVR driver built on top of OpenXR\n\nWhen specifying a repository, you can set a specific git ref (branch, tag, commit...) by appending a '#' followed by the ref"),
add: { add: &path_row(
withclones![prof];
&path_row(
"OpenComposite Path", None, "OpenComposite Path", None,
Some(model.profile.borrow().opencomposite_path.clone()), Some(model.profile.borrow().opencomposite_path.clone()),
Some(init.root_win.clone()), Some(init.root_win.clone()),
move |n_path| { clone!(@strong prof => move |n_path| {
prof.borrow_mut().opencomposite_path = n_path.unwrap_or_default(); prof.borrow_mut().opencomposite_path = n_path.unwrap_or_default();
} })
) ),
}, add: &entry_row(
add: {
withclones![prof];
&entry_row(
"OpenComposite Repo", "OpenComposite Repo",
model.profile.borrow().opencomposite_repo.clone().unwrap_or_default().as_str(), model.profile.borrow().opencomposite_repo.clone().unwrap_or_default().as_str(),
move |row| { clone!(@strong prof => move |row| {
let n_val = row.text().to_string(); let n_val = row.text().to_string();
prof.borrow_mut().opencomposite_repo = (!n_val.is_empty()).then_some(n_val); prof.borrow_mut().opencomposite_repo = (!n_val.is_empty()).then_some(n_val);
} })
) ),
},
}, },
add: libsurvivegrp = &adw::PreferencesGroup { add: libsurvivegrp = &adw::PreferencesGroup {
set_title: "Libsurvive", set_title: "Libsurvive",
set_description: Some("Lighthouse tracking driver\n\nWhen specifying a repository, you can set a specific git ref (branch, tag, commit...) by appending a '#' followed by the ref"), set_description: Some("Lighthouse tracking driver\n\nWhen specifying a repository, you can set a specific git ref (branch, tag, commit...) by appending a '#' followed by the ref"),
add: { add: &switch_row(
withclones![prof];
&switch_row(
"Enable Libsurvive", None, "Enable Libsurvive", None,
model.profile.borrow().features.libsurvive.enabled, model.profile.borrow().features.libsurvive.enabled,
move |_, state| { clone!(@strong prof => move |_, state| {
prof.borrow_mut().features.libsurvive.enabled = state; prof.borrow_mut().features.libsurvive.enabled = state;
gtk::glib::Propagation::Proceed gtk::glib::Propagation::Proceed
} })
) ),
}, add: &path_row(
add: {
withclones![prof];
&path_row(
"Libsurvive Path", None, "Libsurvive Path", None,
model.profile.borrow().features.libsurvive.path.clone(), model.profile.borrow().features.libsurvive.path.clone(),
Some(init.root_win.clone()), Some(init.root_win.clone()),
move |n_path| { clone!(@strong prof => move |n_path| {
prof.borrow_mut().features.libsurvive.path = n_path; prof.borrow_mut().features.libsurvive.path = n_path;
} })
) ),
}, add: &entry_row(
add: {
withclones![prof];
&entry_row(
"Libsurvive Repo", "Libsurvive Repo",
model.profile.borrow().features.libsurvive.repo.clone().unwrap_or_default().as_str(), model.profile.borrow().features.libsurvive.repo.clone().unwrap_or_default().as_str(),
move |row| { clone!(@strong prof => move |row| {
let n_val = row.text().to_string(); let n_val = row.text().to_string();
prof.borrow_mut().features.libsurvive.repo = (!n_val.is_empty()).then_some(n_val); prof.borrow_mut().features.libsurvive.repo = (!n_val.is_empty()).then_some(n_val);
} })
) ),
},
}, },
add: openhmdgrp = &adw::PreferencesGroup { add: openhmdgrp = &adw::PreferencesGroup {
set_title: "OpenHMD", set_title: "OpenHMD",
set_description: Some("Legacy driver for older Oculus HMDs\n\nWhen specifying a repository, you can set a specific git ref (branch, tag, commit...) by appending a '#' followed by the ref"), set_description: Some("Legacy driver for older Oculus HMDs\n\nWhen specifying a repository, you can set a specific git ref (branch, tag, commit...) by appending a '#' followed by the ref"),
add: { add: &switch_row(
withclones![prof];
&switch_row(
"Enable OpenHMD", None, "Enable OpenHMD", None,
model.profile.borrow().features.openhmd.enabled, model.profile.borrow().features.openhmd.enabled,
move |_, state| { clone!(@strong prof => move |_, state| {
prof.borrow_mut().features.openhmd.enabled = state; prof.borrow_mut().features.openhmd.enabled = state;
gtk::glib::Propagation::Proceed gtk::glib::Propagation::Proceed
} })
) ),
}, add: &path_row(
add: {
withclones![prof];
&path_row(
"OpenHMD Path", None, "OpenHMD Path", None,
model.profile.borrow().features.openhmd.path.clone(), model.profile.borrow().features.openhmd.path.clone(),
Some(init.root_win.clone()), Some(init.root_win.clone()),
move |n_path| { clone!(@strong prof => move |n_path| {
prof.borrow_mut().features.openhmd.path = n_path; prof.borrow_mut().features.openhmd.path = n_path;
} })
) ),
}, add: &entry_row(
add: {
withclones![prof];
&entry_row(
"OpenHMD Repo", "OpenHMD Repo",
model.profile.borrow().features.openhmd.repo.clone().unwrap_or_default().as_str(), model.profile.borrow().features.openhmd.repo.clone().unwrap_or_default().as_str(),
move |row| { clone!(@strong prof => move |row| {
let n_val = row.text().to_string(); let n_val = row.text().to_string();
prof.borrow_mut().features.openhmd.repo = (!n_val.is_empty()).then_some(n_val); prof.borrow_mut().features.openhmd.repo = (!n_val.is_empty()).then_some(n_val);
} })
) ),
},
}, },
add: basaltgrp = &adw::PreferencesGroup { add: basaltgrp = &adw::PreferencesGroup {
set_title: "Basalt", set_title: "Basalt",
set_description: Some("Camera based SLAM tracking driver\n\nWhen specifying a repository, you can set a specific git ref (branch, tag, commit...) by appending a '#' followed by the ref"), set_description: Some("Camera based SLAM tracking driver\n\nWhen specifying a repository, you can set a specific git ref (branch, tag, commit...) by appending a '#' followed by the ref"),
add: { add: &switch_row(
withclones![prof];
&switch_row(
"Enable Basalt", None, "Enable Basalt", None,
model.profile.borrow().features.basalt.enabled, model.profile.borrow().features.basalt.enabled,
move |_, state| { clone!(@strong prof => move |_, state| {
prof.borrow_mut().features.basalt.enabled = state; prof.borrow_mut().features.basalt.enabled = state;
gtk::glib::Propagation::Proceed gtk::glib::Propagation::Proceed
} })
) ),
}, add: &path_row(
add: {
withclones![prof];
&path_row(
"Basalt Path", None, "Basalt Path", None,
model.profile.borrow().features.basalt.path.clone(), model.profile.borrow().features.basalt.path.clone(),
Some(init.root_win.clone()), Some(init.root_win.clone()),
move |n_path| { clone!(@strong prof => move |n_path| {
prof.borrow_mut().features.basalt.path = n_path; prof.borrow_mut().features.basalt.path = n_path;
} })
) ),
}, add: &entry_row(
add: {
withclones![prof];
&entry_row(
"Basalt Repo", "Basalt Repo",
model.profile.borrow().features.basalt.repo.clone().unwrap_or_default().as_str(), model.profile.borrow().features.basalt.repo.clone().unwrap_or_default().as_str(),
move |row| { clone!(@strong prof => move |row| {
let n_val = row.text().to_string(); let n_val = row.text().to_string();
prof.borrow_mut().features.basalt.repo = n_val.is_empty().then_some(n_val); prof.borrow_mut().features.basalt.repo = n_val.is_empty().then_some(n_val);
} })
) ),
},
}, },
add: mercurygrp = &adw::PreferencesGroup { add: mercurygrp = &adw::PreferencesGroup {
set_title: "Mercury", set_title: "Mercury",
set_description: Some("Camera and OpenCV based hand tracking driver"), set_description: Some("Camera and OpenCV based hand tracking driver"),
add: { add: &switch_row(
withclones![prof];
&switch_row(
"Enable Mercury", None, "Enable Mercury", None,
model.profile.borrow().features.mercury_enabled, model.profile.borrow().features.mercury_enabled,
move |_, state| { clone!(@strong prof => move |_, state| {
prof.borrow_mut().features.mercury_enabled = state; prof.borrow_mut().features.mercury_enabled = state;
gtk::glib::Propagation::Proceed gtk::glib::Propagation::Proceed
} })
) ),
},
}, },
add: model.env_rows.widget(), add: model.env_rows.widget(),
} }
@ -465,8 +409,8 @@ impl SimpleComponent for ProfileEditor {
.halign(gtk::Align::End) .halign(gtk::Align::End)
.build(); .build();
withclones![sender, name_entry, popover]; add_btn.connect_clicked(
add_btn.connect_clicked(move |_| { clone!(@strong sender, @strong name_entry, @strong popover => move |_| {
let key_gstr = name_entry.text(); let key_gstr = name_entry.text();
let key = key_gstr.trim(); let key = key_gstr.trim();
if !key.is_empty() { if !key.is_empty() {
@ -474,7 +418,8 @@ impl SimpleComponent for ProfileEditor {
name_entry.set_text(""); name_entry.set_text("");
sender.input($event(key.to_string())); sender.input($event(key.to_string()));
} }
}); })
);
btn btn
}}; }};
} }