mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-02-03 14:30:50 +03:00
Added working wine version selection
This commit is contained in:
parent
b6bfc4d2ec
commit
82a6e01200
6 changed files with 141 additions and 29 deletions
assets
src
|
@ -108,15 +108,6 @@ Adw.PreferencesPage general_page {
|
|||
|
||||
Adw.ComboRow wine_selected {
|
||||
title: "Selected version";
|
||||
|
||||
model: Gtk.StringList {
|
||||
strings [
|
||||
"Wine-GE 7-16",
|
||||
"Wine-GE 7-15",
|
||||
"Proton-GE 7-15",
|
||||
"Lutris 7-14"
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"title": "Wine-GE-Proton",
|
||||
"subtitle": null,
|
||||
"runners": [
|
||||
"versions": [
|
||||
{
|
||||
"family": "Wine-GE-Proton",
|
||||
"name": "lutris-GE-Proton7-16-x86_64",
|
||||
|
@ -188,7 +188,7 @@
|
|||
{
|
||||
"title": "GE-Proton",
|
||||
"subtitle": "This version includes its own DXVK builds and you can use DXVK_ASYNC variable",
|
||||
"runners": [
|
||||
"versions": [
|
||||
{
|
||||
"family": "GE-Proton",
|
||||
"name": "GE-Proton7-20",
|
||||
|
@ -398,7 +398,7 @@
|
|||
{
|
||||
"title": "Lutris",
|
||||
"subtitle": null,
|
||||
"runners": [
|
||||
"versions": [
|
||||
{
|
||||
"family": "Lutris",
|
||||
"name": "lutris-7.2-x86_64",
|
||||
|
|
|
@ -12,6 +12,37 @@ impl List {
|
|||
pub fn get() -> Result<Self, serde_json::Error> {
|
||||
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)]
|
||||
|
@ -21,3 +52,9 @@ pub struct Version {
|
|||
pub uri: String,
|
||||
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> {
|
||||
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)]
|
||||
pub struct Group {
|
||||
pub title: String,
|
||||
pub subtitle: Option<String>,
|
||||
pub runners: Vec<Version>
|
||||
pub versions: Vec<Version>
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -27,6 +50,12 @@ pub struct Version {
|
|||
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)]
|
||||
pub struct Files {
|
||||
pub wine: String,
|
||||
|
|
|
@ -24,7 +24,7 @@ impl WineGroup {
|
|||
|
||||
let mut version_components = Vec::new();
|
||||
|
||||
for version in &group.runners {
|
||||
for version in &group.versions {
|
||||
let component = WineRow::new(version.clone());
|
||||
|
||||
expander_row.add_row(&component.row);
|
||||
|
|
|
@ -136,7 +136,9 @@ impl AppWidgets {
|
|||
#[derive(Debug, Clone, glib::Downgrade)]
|
||||
pub enum Actions {
|
||||
DxvkPerformAction(Rc<usize>),
|
||||
WinePerformAction(Rc<(usize, usize)>)
|
||||
WinePerformAction(Rc<(usize, usize)>),
|
||||
UpdateWineComboRow,
|
||||
SelectWineVersion(Rc<usize>)
|
||||
}
|
||||
|
||||
impl Actions {
|
||||
|
@ -153,7 +155,9 @@ impl Actions {
|
|||
///
|
||||
/// This must implement `Default` trait
|
||||
#[derive(Debug, Default, glib::Downgrade)]
|
||||
pub struct Values;
|
||||
pub struct Values {
|
||||
downloaded_wine_versions: Rc<Option<Vec<wine::Version>>>
|
||||
}
|
||||
|
||||
/// The main application structure
|
||||
///
|
||||
|
@ -187,9 +191,13 @@ impl App {
|
|||
|
||||
/// Add default events and values to the widgets
|
||||
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
|
||||
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();
|
||||
|
||||
receiver.attach(None, move |action| {
|
||||
let values = this.values.take();
|
||||
let mut config = config::get().expect("Failed to load config");
|
||||
|
||||
// Some debug output
|
||||
println!("[general page] [update] action: {:?}, values: {:?}", &action, &values);
|
||||
println!("[general page] [update] action: {:?}", &action);
|
||||
|
||||
match action {
|
||||
Actions::DxvkPerformAction(i) => {
|
||||
let config = config::get().expect("Failed to load config");
|
||||
|
||||
let component = this.widgets.dxvk_components[*i].clone();
|
||||
|
||||
if component.is_downloaded(&config.game.dxvk.builds) {
|
||||
|
@ -273,8 +279,6 @@ impl App {
|
|||
}
|
||||
|
||||
Actions::WinePerformAction(version) => {
|
||||
let config = config::get().expect("Failed to load config");
|
||||
|
||||
let component = this.widgets
|
||||
.wine_components[version.0]
|
||||
.version_components[version.1].clone();
|
||||
|
@ -285,19 +289,67 @@ impl App {
|
|||
}
|
||||
|
||||
component.update_state(&config.game.wine.builds);
|
||||
|
||||
this.update(Actions::UpdateWineComboRow);
|
||||
}
|
||||
|
||||
else {
|
||||
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);
|
||||
});
|
||||
|
||||
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)
|
||||
});
|
||||
|
@ -396,6 +448,9 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
// Update downloaded wine versions
|
||||
self.update(Actions::UpdateWineComboRow);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue