Added working wine version selection

This commit is contained in:
Observer KRypt0n_ 2022-07-15 17:17:34 +02:00
parent b6bfc4d2ec
commit 82a6e01200
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
6 changed files with 141 additions and 29 deletions

View file

@ -108,15 +108,6 @@ Adw.PreferencesPage general_page {
Adw.ComboRow wine_selected { Adw.ComboRow wine_selected {
title: "Selected version"; title: "Selected version";
model: Gtk.StringList {
strings [
"Wine-GE 7-16",
"Wine-GE 7-15",
"Proton-GE 7-15",
"Lutris 7-14"
]
};
} }
Adw.ActionRow { Adw.ActionRow {

View file

@ -2,7 +2,7 @@
{ {
"title": "Wine-GE-Proton", "title": "Wine-GE-Proton",
"subtitle": null, "subtitle": null,
"runners": [ "versions": [
{ {
"family": "Wine-GE-Proton", "family": "Wine-GE-Proton",
"name": "lutris-GE-Proton7-16-x86_64", "name": "lutris-GE-Proton7-16-x86_64",
@ -188,7 +188,7 @@
{ {
"title": "GE-Proton", "title": "GE-Proton",
"subtitle": "This version includes its own DXVK builds and you can use DXVK_ASYNC variable", "subtitle": "This version includes its own DXVK builds and you can use DXVK_ASYNC variable",
"runners": [ "versions": [
{ {
"family": "GE-Proton", "family": "GE-Proton",
"name": "GE-Proton7-20", "name": "GE-Proton7-20",
@ -398,7 +398,7 @@
{ {
"title": "Lutris", "title": "Lutris",
"subtitle": null, "subtitle": null,
"runners": [ "versions": [
{ {
"family": "Lutris", "family": "Lutris",
"name": "lutris-7.2-x86_64", "name": "lutris-7.2-x86_64",

View file

@ -12,6 +12,37 @@ impl List {
pub fn get() -> Result<Self, serde_json::Error> { pub fn get() -> Result<Self, serde_json::Error> {
Ok(serde_json::from_str(LIST)?) Ok(serde_json::from_str(LIST)?)
} }
/// List only downloaded DXVK versions in some specific folder
pub fn list_downloaded<T: ToString>(folder: T) -> std::io::Result<List> {
let mut vanilla = Vec::new();
let mut r#async = Vec::new();
let list = Self::get()?;
for entry in std::fs::read_dir(folder.to_string())? {
let name = entry?.file_name();
for (i, versions) in [&list.vanilla, &list.r#async].into_iter().enumerate() {
for version in versions {
if name == version.name.as_str() {
match i {
0 => vanilla.push(version.clone()),
1 => r#async.push(version.clone()),
_ => unreachable!()
}
break;
}
}
}
}
Ok(List {
vanilla,
r#async
})
}
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -21,3 +52,9 @@ pub struct Version {
pub uri: String, pub uri: String,
pub recommended: bool pub recommended: bool
} }
impl Version {
pub fn is_downloaded_in<T: ToString>(&self, folder: T) -> bool {
std::path::Path::new(&format!("{}/{}", folder.to_string(), self.name)).exists()
}
}

View file

@ -8,13 +8,36 @@ impl List {
pub fn get() -> Result<Vec<Group>, serde_json::Error> { pub fn get() -> Result<Vec<Group>, serde_json::Error> {
Ok(serde_json::from_str(LIST)?) Ok(serde_json::from_str(LIST)?)
} }
/// List only downloaded wine versions in some specific folder
pub fn list_downloaded<T: ToString>(folder: T) -> std::io::Result<Vec<Version>> {
let mut downloaded = Vec::new();
let list = Self::get()?;
for entry in std::fs::read_dir(folder.to_string())? {
let name = entry?.file_name();
for group in &list {
for version in &group.versions {
if name == version.name.as_str() {
downloaded.push(version.clone());
break;
}
}
}
}
Ok(downloaded)
}
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Group { pub struct Group {
pub title: String, pub title: String,
pub subtitle: Option<String>, pub subtitle: Option<String>,
pub runners: Vec<Version> pub versions: Vec<Version>
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -27,6 +50,12 @@ pub struct Version {
pub recommended: bool pub recommended: bool
} }
impl Version {
pub fn is_downloaded_in<T: ToString>(&self, folder: T) -> bool {
std::path::Path::new(&format!("{}/{}", folder.to_string(), self.name)).exists()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Files { pub struct Files {
pub wine: String, pub wine: String,

View file

@ -24,7 +24,7 @@ impl WineGroup {
let mut version_components = Vec::new(); let mut version_components = Vec::new();
for version in &group.runners { for version in &group.versions {
let component = WineRow::new(version.clone()); let component = WineRow::new(version.clone());
expander_row.add_row(&component.row); expander_row.add_row(&component.row);

View file

@ -136,7 +136,9 @@ impl AppWidgets {
#[derive(Debug, Clone, glib::Downgrade)] #[derive(Debug, Clone, glib::Downgrade)]
pub enum Actions { pub enum Actions {
DxvkPerformAction(Rc<usize>), DxvkPerformAction(Rc<usize>),
WinePerformAction(Rc<(usize, usize)>) WinePerformAction(Rc<(usize, usize)>),
UpdateWineComboRow,
SelectWineVersion(Rc<usize>)
} }
impl Actions { impl Actions {
@ -153,7 +155,9 @@ impl Actions {
/// ///
/// This must implement `Default` trait /// This must implement `Default` trait
#[derive(Debug, Default, glib::Downgrade)] #[derive(Debug, Default, glib::Downgrade)]
pub struct Values; pub struct Values {
downloaded_wine_versions: Rc<Option<Vec<wine::Version>>>
}
/// The main application structure /// The main application structure
/// ///
@ -187,9 +191,13 @@ impl App {
/// Add default events and values to the widgets /// Add default events and values to the widgets
fn init_events(self) -> Self { fn init_events(self) -> Self {
/*self.widgets.wine_selected.connect_selected_notify(|_| { self.widgets.wine_selected.connect_selected_notify(clone!(@strong self as this => move |combo_row| {
if let Some(model) = combo_row.model() {
});*/ if model.n_items() > 0 {
this.update(Actions::SelectWineVersion(Rc::new(combo_row.selected() as usize)));
}
}
}));
// Set wine recommended only switcher event // Set wine recommended only switcher event
self.widgets.wine_recommended_only.connect_state_notify(clone!(@strong self as this => move |switcher| { self.widgets.wine_recommended_only.connect_state_notify(clone!(@strong self as this => move |switcher| {
@ -244,15 +252,13 @@ impl App {
let this = self.clone(); let this = self.clone();
receiver.attach(None, move |action| { receiver.attach(None, move |action| {
let values = this.values.take(); let mut config = config::get().expect("Failed to load config");
// Some debug output // Some debug output
println!("[general page] [update] action: {:?}, values: {:?}", &action, &values); println!("[general page] [update] action: {:?}", &action);
match action { match action {
Actions::DxvkPerformAction(i) => { Actions::DxvkPerformAction(i) => {
let config = config::get().expect("Failed to load config");
let component = this.widgets.dxvk_components[*i].clone(); let component = this.widgets.dxvk_components[*i].clone();
if component.is_downloaded(&config.game.dxvk.builds) { if component.is_downloaded(&config.game.dxvk.builds) {
@ -273,8 +279,6 @@ impl App {
} }
Actions::WinePerformAction(version) => { Actions::WinePerformAction(version) => {
let config = config::get().expect("Failed to load config");
let component = this.widgets let component = this.widgets
.wine_components[version.0] .wine_components[version.0]
.version_components[version.1].clone(); .version_components[version.1].clone();
@ -285,19 +289,67 @@ impl App {
} }
component.update_state(&config.game.wine.builds); component.update_state(&config.game.wine.builds);
this.update(Actions::UpdateWineComboRow);
} }
else { else {
if let Ok(awaiter) = component.download(&config.game.wine.builds) { if let Ok(awaiter) = component.download(&config.game.wine.builds) {
awaiter.then(move |_| { awaiter.then(clone!(@strong this => move |_| {
component.update_state(&config.game.wine.builds); component.update_state(&config.game.wine.builds);
});
this.update(Actions::UpdateWineComboRow);
}));
} }
} }
} }
}
this.values.set(values); Actions::UpdateWineComboRow => {
let model = gtk::StringList::new(&["System"]);
let list = wine::List::list_downloaded(config.game.wine.builds)
.expect("Failed to list downloaded wine versions");
let mut selected = 0;
for (i, version) in (&list).into_iter().enumerate() {
model.append(version.title.as_str());
if let Some(curr) = &config.game.wine.selected {
if &version.name == curr {
selected = i as u32 + 1;
}
}
}
let mut values = this.values.take();
values.downloaded_wine_versions = Rc::new(Some(list));
this.values.set(values);
// We need to return app values before we call these methods
// because they'll invoke SelectWineVersion action so access
// downloaded_wine_versions value
this.widgets.wine_selected.set_model(Some(&model));
this.widgets.wine_selected.set_selected(selected);
}
Actions::SelectWineVersion(i) => {
let values = this.values.take();
if let Some(wine_versions) = &*values.downloaded_wine_versions {
match *i {
0 => config.game.wine.selected = None,
i => config.game.wine.selected = Some(wine_versions[i - 1].name.clone())
}
}
this.values.set(values);
config::update(config).expect("Failed to update config");
}
}
glib::Continue(true) glib::Continue(true)
}); });
@ -396,6 +448,9 @@ impl App {
} }
} }
// Update downloaded wine versions
self.update(Actions::UpdateWineComboRow);
Ok(()) Ok(())
} }
} }