feat: finished editable profiles; profile prop to pull or not on build; profile props to set alternate component repos

This commit is contained in:
Gabriele Musco 2023-06-25 15:25:15 +02:00
parent 371f874e3b
commit 5382ff92d2
No known key found for this signature in database
GPG key ID: 1068D795C80E51DE
21 changed files with 418 additions and 112 deletions

View file

@ -6,9 +6,10 @@ set -ev
GIT_URL=$1
REPO_DIR=$2
DO_PULL=$3
_usage() {
echo "Usage: $0 GIT_URL REPO_DIR"
echo "Usage: $0 GIT_URL REPO_DIR [DO_PULL]"
exit 1
}
@ -20,12 +21,19 @@ if [[ -z $GIT_URL ]]; then
_usage
fi
if [[ -z $DO_PULL ]]; then
DO_PULL=1
fi
if [[ -d "$REPO_DIR" ]]; then
if [[ ! -d "$REPO_DIR/.git" ]]; then
echo "Error: $REPO_DIR exists but is not a git repository"
exit 1
rmdir "$REPO_DIR"
git clone "$GIT_URL" "$REPO_DIR" --recurse-submodules
else
if [[ "$DO_PULL" -eq 1 ]]; then
git -C "$REPO_DIR" pull
fi
fi
git -C "$REPO_DIR" pull
else
git clone "$GIT_URL" "$REPO_DIR" --recurse-submodules
fi

View file

@ -9,13 +9,22 @@ exit 1
#
# PREFIX=$2
#
# if [[ -z $REPO_DIR ]] || [[ -z $PREFIX ]]; then
# echo "Usage: $0 REPO_DIR PREFIX"
# DO_PULL=$3
#
# REPO_URL=$4
#
# if [[ -z $REPO_DIR ]] || [[ -z $PREFIX ]] || [[ -z $DO_PULL ]]; then
# echo "Usage: $0 REPO_DIR PREFIX DO_PULL [REPO_URL]"
# exit 1
# fi
#
# "$(dirname -- "$0")/_clone_or_pull.sh" "https://github.com/cntools/libsurvive" "$REPO_DIR"
# if [[ -z $REPO_URL ]]; then
# REPO_URL="https://gitlab.freedesktop.org/mateosss/basalt"
# fi
#
# "$(dirname -- "$0")/_clone_or_pull.sh" "$REPO_URL" "$REPO_DIR" "$DO_PULL"
#
# cd "$REPO_DIR"
# rm -rf build
# mkdir -p build
# cd build

View file

@ -6,14 +6,23 @@ REPO_DIR=$1
PREFIX=$2
if [[ -z $REPO_DIR ]] || [[ -z $PREFIX ]]; then
echo "Usage: $0 REPO_DIR PREFIX"
DO_PULL=$3
REPO_URL=$4
if [[ -z $REPO_DIR ]] || [[ -z $PREFIX ]] || [[ -z $DO_PULL ]]; then
echo "Usage: $0 REPO_DIR PREFIX DO_PULL [REPO_URL]"
exit 1
fi
"$(dirname -- "$0")/_clone_or_pull.sh" "https://github.com/cntools/libsurvive" "$REPO_DIR"
if [[ -z $REPO_URL ]]; then
REPO_URL="https://github.com/cntools/libsurvive"
fi
"$(dirname -- "$0")/_clone_or_pull.sh" "$REPO_URL" "$REPO_DIR" "$DO_PULL"
cd "$REPO_DIR"
rm -rf build
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release \
@ -23,6 +32,5 @@ cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="${PREFIX}" \
-DCMAKE_INSTALL_LIBDIR="${PREFIX}/lib" \
..
make clean
make -j$(nproc)
make install

View file

@ -8,14 +8,23 @@ REPO_DIR=$1
PREFIX=$2
if [[ -z $REPO_DIR ]] || [[ -z $PREFIX ]]; then
echo "Usage: $0 REPO_DIR PREFIX"
DO_PULL=$3
REPO_URL=$4
if [[ -z $REPO_DIR ]] || [[ -z $PREFIX ]] || [[ -z $DO_PULL ]]; then
echo "Usage: $0 REPO_DIR PREFIX DO_PULL [REPO_URL]"
exit 1
fi
"$(dirname -- "$0")/_clone_or_pull.sh" "https://gitlab.freedesktop.org/monado/monado" "$REPO_DIR"
if [[ -z $REPO_URL ]]; then
REPO_URL="https://gitlab.freedesktop.org/monado/monado"
fi
"$(dirname -- "$0")/_clone_or_pull.sh" "$REPO_URL" "$REPO_DIR" "$DO_PULL"
cd "$REPO_DIR"
rm -rf build
mkdir -p build
cd build
export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig"
@ -25,6 +34,5 @@ cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_FLAGS="-Wl,-rpath ${PREFIX}/lib" \
-DCMAKE_CXX_FLAGS="-Wl,-rpath ${PREFIX}/lib" \
..
make clean
make -j$(nproc)
make install

View file

@ -6,9 +6,23 @@ set -ev
REPO_DIR=$1
"$(dirname -- "$0")/_clone_or_pull.sh" "https://gitlab.com/znixian/OpenOVR.git" "$REPO_DIR"
DO_PULL=$2
REPO_URL=$3
if [[ -z $REPO_DIR ]] || [[ -z $DO_PULL ]]; then
echo "Usage: $0 REPO_DIR DO_PULL [REPO_URL]"
exit 1
fi
if [[ -z $REPO_URL ]]; then
REPO_URL="https://gitlab.com/znixian/OpenOVR.git"
fi
"$(dirname -- "$0")/_clone_or_pull.sh" "$REPO_URL" "$REPO_DIR" "$DO_PULL"
cd "$REPO_DIR"
rm -rf build
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..

View file

@ -8,14 +8,23 @@ REPO_DIR=$1
PREFIX=$2
if [[ -z $REPO_DIR ]] || [[ -z $PREFIX ]]; then
echo "Usage: $0 REPO_DIR PREFIX"
DO_PULL=$3
REPO_URL=$4
if [[ -z $REPO_DIR ]] || [[ -z $PREFIX ]] || [[ -z $DO_PULL ]]; then
echo "Usage: $0 REPO_DIR PREFIX DO_PULL [REPO_URL]"
exit 1
fi
"$(dirname -- "$0")/_clone_or_pull.sh" "https://github.com/Meumeu/WiVRn" "$REPO_DIR"
if [[ -z $REPO_URL ]]; then
REPO_URL="https://github.com/Meumeu/WiVRn"
fi
"$(dirname -- "$0")/_clone_or_pull.sh" "$REPO_URL" "$REPO_DIR" "$DO_PULL"
cd "$REPO_DIR"
rm -rf build
mkdir -p build
cd build
cmake -B build-server -DCMAKE_BUILD_TYPE=Release \

View file

@ -1,17 +1,24 @@
use expect_dialog::ExpectDialog;
use crate::{constants::PKG_DATA_DIR, profile::Profile, runner::Runner};
pub fn get_build_basalt_runner(profile: Profile) -> Runner {
let mut args = vec![
profile
.basalt_path
.expect_dialog("Missing basalt path for given profile"),
profile.prefix,
match profile.pull_on_build {
true => "1".into(),
false => "0".into(),
},
];
if profile.basalt_repo.is_some() {
args.push(profile.basalt_repo.unwrap());
}
let runner = Runner::new(
None,
format!("{sysdata}/scripts/build_basalt.sh", sysdata = PKG_DATA_DIR),
vec![
profile
.basalt_path
.expect_dialog("Missing basalt path for given profile"),
profile.prefix,
],
args,
);
runner
}

View file

@ -1,16 +1,27 @@
use crate::{profile::Profile, runner::Runner, constants::PKG_DATA_DIR};
use crate::{constants::PKG_DATA_DIR, profile::Profile, runner::Runner};
use expect_dialog::ExpectDialog;
pub fn get_build_libsurvive_runner(profile: Profile) -> Runner {
let mut args = vec![
profile
.libsurvive_path
.expect_dialog("Missing libsurvive path for given profile"),
profile.prefix,
match profile.pull_on_build {
true => "1".into(),
false => "0".into(),
},
];
if profile.libsurvive_repo.is_some() {
args.push(profile.libsurvive_repo.unwrap());
}
let runner = Runner::new(
None,
format!("{sysdata}/scripts/build_libsurvive.sh", sysdata = PKG_DATA_DIR),
vec![
profile
.libsurvive_path
.expect_dialog("Missing libsurvive path for given profile"),
profile.prefix,
],
format!(
"{sysdata}/scripts/build_libsurvive.sh",
sysdata = PKG_DATA_DIR
),
args,
);
runner
}

View file

@ -1,13 +1,21 @@
use crate::{runner::Runner, profile::Profile, constants::PKG_DATA_DIR};
use crate::{constants::PKG_DATA_DIR, profile::Profile, runner::Runner};
pub fn get_build_monado_runner(profile: Profile) -> Runner {
let mut args = vec![
profile.xrservice_path,
profile.prefix,
match profile.pull_on_build {
true => "1".into(),
false => "0".into(),
},
];
if profile.xrservice_repo.is_some() {
args.push(profile.xrservice_repo.unwrap());
}
let runner = Runner::new(
None,
format!("{sysdata}/scripts/build_monado.sh", sysdata = PKG_DATA_DIR),
vec![
profile.xrservice_path,
profile.prefix,
]
args,
);
runner
}

View file

@ -1,12 +1,23 @@
use crate::{profile::Profile, runner::Runner, constants::PKG_DATA_DIR};
use crate::{constants::PKG_DATA_DIR, profile::Profile, runner::Runner};
pub fn get_build_opencomposite_runner(profile: Profile) -> Runner {
let mut args = vec![
profile.opencomposite_path,
match profile.pull_on_build {
true => "1".into(),
false => "0".into(),
},
];
if profile.opencomposite_repo.is_some() {
args.push(profile.opencomposite_repo.unwrap());
}
let runner = Runner::new(
None,
format!("{sysdata}/scripts/build_opencomposite.sh", sysdata = PKG_DATA_DIR),
vec![
profile.opencomposite_path,
]
format!(
"{sysdata}/scripts/build_opencomposite.sh",
sysdata = PKG_DATA_DIR
),
args,
);
runner
}

View file

@ -1,14 +1,21 @@
use crate::{profile::Profile, runner::Runner, constants::PKG_DATA_DIR};
use crate::{constants::PKG_DATA_DIR, profile::Profile, runner::Runner};
pub fn get_build_wivrn_runner(profile: Profile) -> Runner {
let mut args = vec![
profile.xrservice_path,
profile.prefix,
match profile.pull_on_build {
true => "1".into(),
false => "0".into(),
},
];
if profile.xrservice_repo.is_some() {
args.push(profile.xrservice_repo.unwrap());
}
let runner = Runner::new(
None,
format!("{sysdata}/scripts/build_wivrn.sh", sysdata = PKG_DATA_DIR),
vec![
profile.xrservice_path,
profile.prefix,
]
args,
);
runner
}

View file

@ -56,11 +56,17 @@ pub struct Profile {
pub libsurvive_enabled: bool,
pub basalt_enabled: bool,
pub mercury_enabled: bool,
pub xrservice_repo: Option<String>,
pub opencomposite_repo: Option<String>,
pub libsurvive_repo: Option<String>,
pub basalt_repo: Option<String>,
pub mercury_repo: Option<String>,
pub environment: HashMap<String, String>,
/** Install prefix */
pub prefix: String,
pub can_be_built: bool,
pub editable: bool,
pub pull_on_build: bool,
}
impl Display for Profile {
@ -89,6 +95,12 @@ impl Default for Profile {
data = get_data_dir()
),
can_be_built: true,
pull_on_build: true,
xrservice_repo: None,
opencomposite_repo: None,
libsurvive_repo: None,
basalt_repo: None,
mercury_repo: None,
editable: true,
}
}
@ -203,8 +215,8 @@ mod tests {
mercury_enabled: false,
environment: env,
prefix: String::from("/home/user/rex2prefix"),
can_be_built: true,
editable: true,
..Default::default()
};
let fpath = String::from("./target/testout/testprofile.json");
p.dump_profile(&fpath);

View file

@ -23,5 +23,6 @@ pub fn system_valve_index_profile() -> Profile {
prefix: SYSTEM_PREFIX.into(),
can_be_built: false,
editable: false,
..Default::default()
}
}

View file

@ -26,5 +26,6 @@ pub fn valve_index_profile() -> Profile {
prefix,
can_be_built: true,
editable: false,
..Default::default()
}
}

View file

@ -23,5 +23,6 @@ pub fn wivrn_profile() -> Profile {
prefix,
can_be_built: true,
editable: false,
..Default::default()
}
}

View file

@ -0,0 +1,83 @@
use crate::ui::profile_editor::ProfileEditorMsg;
use adw::prelude::*;
use gtk::prelude::*;
use relm4::prelude::*;
#[derive(Debug)]
pub struct EntryModel {
key: String,
name: String,
value: String,
}
pub struct EntryModelInit {
pub key: String,
pub name: String,
pub value: String,
}
#[derive(Debug)]
pub enum EntryModelMsg {
Changed(String),
}
#[derive(Debug)]
pub enum EntryModelOutMsg {
Changed(String, String),
}
#[relm4::factory(pub)]
impl FactoryComponent for EntryModel {
type Init = EntryModelInit;
type Input = EntryModelMsg;
type Output = EntryModelOutMsg;
type CommandOutput = ();
type Widgets = EntryModelWidgets;
type ParentInput = ProfileEditorMsg;
type ParentWidget = adw::PreferencesGroup;
view! {
root = adw::EntryRow {
set_title: &self.name,
set_text: &self.value,
add_suffix: clear_btn = &gtk::Button {
set_icon_name: "edit-clear-symbolic",
set_tooltip_text: Some("Clear"),
set_valign: gtk::Align::Center,
add_css_class: "flat",
add_css_class: "circular",
connect_clicked[root] => move |_| {
root.set_text("");
}
},
connect_changed[sender] => move |entry| {
sender.input_sender().emit(Self::Input::Changed(entry.text().to_string()));
},
}
}
fn update(&mut self, message: Self::Input, sender: FactorySender<Self>) {
match message {
Self::Input::Changed(val) => {
self.value = val.clone();
sender
.output_sender()
.emit(Self::Output::Changed(self.key.clone(), val));
}
}
}
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
Some(match output {
Self::Output::Changed(key, value) => ProfileEditorMsg::EntryChanged(key, value),
})
}
fn init_model(init: Self::Init, index: &Self::Index, sender: FactorySender<Self>) -> Self {
Self {
key: init.key,
name: init.name,
value: init.value,
}
}
}

View file

@ -1,3 +1,4 @@
pub mod env_var_row_factory;
pub mod switch_row_factory;
pub mod path_row_factory;
pub mod entry_row_factory;

View file

@ -52,7 +52,7 @@ impl FactoryComponent for PathModel {
set_valign: gtk::Align::Center,
add_css_class: "flat",
add_css_class: "circular",
set_icon_name: "edit-clear",
set_icon_name: "edit-clear-symbolic",
set_tooltip_text: Some("Clear Path"),
connect_clicked[sender] => move |_| {
sender.input(Self::Input::Changed(None));

View file

@ -261,6 +261,7 @@ impl SimpleComponent for MainView {
.unwrap()
.clone()
.set_selected(index);
self.set_selected_profile(self.profiles.get(index as usize).unwrap().clone());
}
Self::Input::ProfileSelected(position) => {
sender.output(MainViewOutMsg::ProfileSelected(

View file

@ -1,4 +1,5 @@
use super::factories::{
entry_row_factory::{EntryModel, EntryModelInit},
env_var_row_factory::{EnvVarModel, EnvVarModelInit},
path_row_factory::{PathModel, PathModelInit},
switch_row_factory::{SwitchModel, SwitchModelInit},
@ -24,11 +25,15 @@ pub struct ProfileEditor {
#[tracker::do_not_track]
type_row: adw::ComboRow,
#[tracker::do_not_track]
pull_on_build_switch: Option<gtk::Switch>,
#[tracker::do_not_track]
env_rows: FactoryVecDeque<EnvVarModel>,
#[tracker::do_not_track]
switch_rows: FactoryVecDeque<SwitchModel>,
#[tracker::do_not_track]
path_rows: FactoryVecDeque<PathModel>,
#[tracker::do_not_track]
repo_rows: FactoryVecDeque<EntryModel>,
}
#[derive(Debug)]
@ -36,7 +41,7 @@ pub enum ProfileEditorMsg {
Present(Profile),
EnvVarChanged(String, String),
EnvVarDelete(String),
TextChanged(String, String),
EntryChanged(String, String),
PathChanged(String, Option<String>),
SwitchChanged(String, bool),
ComboChanged(String, String),
@ -69,13 +74,25 @@ impl SimpleComponent for ProfileEditor {
},
add: mainpage = &adw::PreferencesPage {
add: maingrp = &adw::PreferencesGroup {
set_title: "Profile Info",
set_title: "General",
model.name_row.clone(),
model.type_row.clone(),
adw::ActionRow {
set_title: "Update on Build",
add_suffix: pull_on_build_switch = &gtk::Switch {
set_valign: gtk::Align::Center,
connect_state_set[sender] => move |_, state| {
sender.input(Self::Input::SwitchChanged("pull_on_build".into(), state));
gtk::Inhibit(false)
}
},
set_activatable_widget: Some(&pull_on_build_switch),
}
},
add: model.env_rows.widget(),
add: model.switch_rows.widget(),
add: model.path_rows.widget(),
add: model.repo_rows.widget(),
add: save_grp = &adw::PreferencesGroup {
add: save_box = &gtk::Box {
set_orientation: gtk::Orientation::Vertical,
@ -106,65 +123,106 @@ impl SimpleComponent for ProfileEditor {
self.type_row.set_selected(prof.xrservice_type.as_number());
self.env_rows.guard().clear();
for (k, v) in p.environment.iter() {
self.env_rows.guard().push_back(EnvVarModelInit {
name: k.clone(),
value: v.clone(),
self.pull_on_build_switch.as_ref().unwrap().set_active(prof.pull_on_build);
{
let mut guard = self.env_rows.guard();
guard.clear();
for (k, v) in p.environment.iter() {
guard.push_back(EnvVarModelInit {
name: k.clone(),
value: v.clone(),
});
}
}
{
let mut guard = self.switch_rows.guard();
guard.clear();
guard.push_back(SwitchModelInit {
name: "Libsurvive".into(),
description: Some("Lighthouse based spacial tracking".into()),
key: "libsurvive_enabled".into(),
value: p.libsurvive_enabled,
});
guard.push_back(SwitchModelInit {
name: "Basalt".into(),
description: Some("Camera based SLAM tracking".into()),
key: "basalt_enabled".into(),
value: p.basalt_enabled,
});
guard.push_back(SwitchModelInit {
name: "Mercury".into(),
description: Some("Camera based hand tracking".into()),
key: "mercury_enabled".into(),
value: p.mercury_enabled,
});
}
self.switch_rows.guard().clear();
self.switch_rows.guard().push_back(SwitchModelInit {
name: "Libsurvive".into(),
description: Some("Lighthouse based spacial tracking".into()),
key: "libsurvive_enabled".into(),
value: p.libsurvive_enabled,
});
self.switch_rows.guard().push_back(SwitchModelInit {
name: "Basalt".into(),
description: Some("Camera based SLAM tracking".into()),
key: "basalt_enabled".into(),
value: p.basalt_enabled,
});
self.switch_rows.guard().push_back(SwitchModelInit {
name: "Mercury".into(),
description: Some("Camera based hand tracking".into()),
key: "mercury_enabled".into(),
value: p.mercury_enabled,
});
{
let mut guard = self.path_rows.guard();
guard.clear();
guard.push_back(PathModelInit {
name: "XR Service Path".into(),
key: "xrservice_path".into(),
value: Some(p.xrservice_path),
});
guard.push_back(PathModelInit {
name: "OpenComposite Path".into(),
key: "opencomposite_path".into(),
value: Some(p.opencomposite_path),
});
guard.push_back(PathModelInit {
name: "Libsurvive Path".into(),
key: "libsurvive_path".into(),
value: p.libsurvive_path,
});
guard.push_back(PathModelInit {
name: "Basalt Path".into(),
key: "basalt_path".into(),
value: p.basalt_path,
});
guard.push_back(PathModelInit {
name: "Mercury Path".into(),
key: "mercury_path".into(),
value: p.mercury_path,
});
guard.push_back(PathModelInit {
name: "Install Prefix".into(),
key: "prefix".into(),
value: Some(p.prefix),
});
}
self.path_rows.guard().clear();
self.path_rows.guard().push_back(PathModelInit {
name: "XR Service Path".into(),
key: "xrservice_path".into(),
value: Some(p.xrservice_path),
});
self.path_rows.guard().push_back(PathModelInit {
name: "OpenComposite Path".into(),
key: "opencomposite_path".into(),
value: Some(p.opencomposite_path),
});
self.path_rows.guard().push_back(PathModelInit {
name: "Libsurvive Path".into(),
key: "libsurvive_path".into(),
value: p.libsurvive_path,
});
self.path_rows.guard().push_back(PathModelInit {
name: "Basalt Path".into(),
key: "basalt_path".into(),
value: p.basalt_path,
});
self.path_rows.guard().push_back(PathModelInit {
name: "Mercury Path".into(),
key: "mercury_path".into(),
value: p.mercury_path,
});
self.path_rows.guard().push_back(PathModelInit {
name: "Install Prefix".into(),
key: "prefix".into(),
value: Some(p.prefix),
});
{
let mut guard = self.repo_rows.guard();
guard.clear();
guard.push_back(EntryModelInit {
key: "xrservice_repo".into(),
name: "XR Service Repo".into(),
value: p.xrservice_repo.unwrap_or("".into()),
});
guard.push_back(EntryModelInit {
key: "opencomposite_repo".into(),
name: "OpenComposite Repo".into(),
value: p.opencomposite_repo.unwrap_or("".into()),
});
guard.push_back(EntryModelInit {
key: "libsurvive_repo".into(),
name: "Libsurvive Repo".into(),
value: p.libsurvive_repo.unwrap_or("".into()),
});
guard.push_back(EntryModelInit {
key: "basalt_repo".into(),
name: "Basalt Repo".into(),
value: p.basalt_repo.unwrap_or("".into()),
});
guard.push_back(EntryModelInit {
key: "mercury_repo".into(),
name: "Mercury Repo".into(),
value: p.mercury_repo.unwrap_or("".into()),
});
}
self.set_profile(Some(prof.clone()));
@ -221,13 +279,44 @@ impl SimpleComponent for ProfileEditor {
"libsurvive_enabled" => prof.libsurvive_enabled = value,
"basalt_enabled" => prof.basalt_enabled = value,
"mercury_enabled" => prof.mercury_enabled = value,
"pull_on_build" => prof.pull_on_build = value,
_ => panic!("Unknown profile switch key"),
}
}
Self::Input::TextChanged(key, value) => {
Self::Input::EntryChanged(key, value) => {
let prof = self.profile.as_mut().unwrap();
match key.as_str() {
"name" => prof.name = value,
"xrservice_repo" => {
prof.xrservice_repo = match value.trim() {
"" => None,
s => Some(s.to_string()),
}
}
"opencomposite_repo" => {
prof.opencomposite_repo = match value.trim() {
"" => None,
s => Some(s.to_string()),
}
}
"libsurvive_repo" => {
prof.libsurvive_repo = match value.trim() {
"" => None,
s => Some(s.to_string()),
}
}
"basalt_repo" => {
prof.basalt_repo = match value.trim() {
"" => None,
s => Some(s.to_string()),
}
}
"mercury_repo" => {
prof.mercury_repo = match value.trim() {
"" => None,
s => Some(s.to_string()),
}
}
_ => panic!("Unknown profile text key"),
}
}
@ -315,6 +404,7 @@ impl SimpleComponent for ProfileEditor {
.as_slice(),
))
.build(),
pull_on_build_switch: None,
env_rows: FactoryVecDeque::new(
adw::PreferencesGroup::builder()
.title("Environment Variables")
@ -337,13 +427,20 @@ impl SimpleComponent for ProfileEditor {
.build(),
sender.input_sender(),
),
repo_rows: FactoryVecDeque::new(
adw::PreferencesGroup::builder()
.title("Repositories")
.description("Change the repositories from which various components are pulled.\n\nLeave empty to use the default repository.")
.build(),
sender.input_sender(),
),
tracker: 0,
};
{
let name_sender = sender.clone();
model.name_row.connect_changed(move |nr| {
name_sender.input(Self::Input::TextChanged(
name_sender.input(Self::Input::EntryChanged(
"name".to_string(),
nr.text().to_string(),
));
@ -366,6 +463,7 @@ impl SimpleComponent for ProfileEditor {
let widgets = view_output!();
model.win = Some(widgets.win.clone());
model.pull_on_build_switch = Some(widgets.pull_on_build_switch.clone());
ComponentParts { model, widgets }
}

View file

@ -1,4 +1,5 @@
{
"uuid": "demo",
"name": "Demo profile",
"xrservice_path": "/home/user/monado",
"xrservice_type": "Monado",
@ -15,5 +16,12 @@
"SURVIVE_GLOBALSCENESOLVER": "0"
},
"prefix": "/home/user/rex2prefix",
"can_be_built": true
"can_be_built": true,
"editable": true,
"pull_on_build": true,
"xrservice_repo": null,
"opencomposite_repo": null,
"libsurvive_repo": null,
"basalt_repo": null,
"mercury_repo": null
}