Added working wine version selection
This commit is contained in:
parent
b6bfc4d2ec
commit
82a6e01200
6 changed files with 141 additions and 29 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,20 +289,68 @@ 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);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue