From 088016843da0759fce5f29e16c53fdf670d6f72e Mon Sep 17 00:00:00 2001 From: Philip Kristoffersen Date: Sat, 2 Oct 2021 13:45:52 +0200 Subject: [PATCH] Reading and writing settings through UI --- Cargo.lock | 1 + Cargo.toml | 3 +- src/egs/get_manifests.rs | 53 ++++++----- src/egs/mod.rs | 1 + src/egs/settings.rs | 4 +- src/itch/itch_platform.rs | 2 +- src/itch/settings.rs | 4 +- src/legendary/settings.rs | 4 +- src/main.rs | 170 ++++++++++++++++++++++++++++------ src/origin/origin_platform.rs | 2 +- src/origin/settings.rs | 4 +- src/settings.rs | 21 ++--- src/steam/settings.rs | 4 +- src/steamgriddb/settings.rs | 4 +- 14 files changed, 195 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eca361d..827477f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,6 +100,7 @@ dependencies = [ "steam_shortcuts_util", "steamgriddb_api", "tokio", + "toml", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 57ddec7..c4fb0bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,10 +18,11 @@ fltk = { version = "^1.2", features = ["fltk-bundled"], optional = true } nom = "^7.0.*" nom_locate = "^3.0.*" flate2 = "^1.0.22" +toml = { version = "^0.5.8", optional = true } [build-dependencies] fl2rust = { version = "0.4", optional = true } [features] # default = ["ui"] -ui = ["fltk", "fl2rust"] +ui = ["fltk", "fl2rust", "toml"] diff --git a/src/egs/get_manifests.rs b/src/egs/get_manifests.rs index a659c64..877fe9d 100644 --- a/src/egs/get_manifests.rs +++ b/src/egs/get_manifests.rs @@ -4,7 +4,7 @@ use std::env::{self}; use std::fs::{DirEntry, File}; use std::io::BufReader; -use std::path::Path; +use std::path::{Path, PathBuf}; use failure::*; @@ -64,31 +64,38 @@ fn get_manifest_dir_path( }); } } else { - #[cfg(target_os = "linux")] - { - //No path defined for epic gamestore, and we cannot guess on linux - Err(PathNotDefined) + let path = get_default_location(); + + match path { + Some(path) => Ok(path.to_str().unwrap().to_string()), + None => Err(PathNotDefined), } + } +} - #[cfg(target_os = "windows")] - { - let key = "SYSTEMDRIVE"; - let system_drive = - env::var(key).expect("We are on windows, we must know what the SYSTEMDRIVE is"); +pub fn get_default_location() -> Option { + #[cfg(target_os = "linux")] + { + //No path defined for epic gamestore, and we cannot guess on linux + None + } - let path = Path::new(format!("{}\\",system_drive).as_str()) - .join("ProgramData") - .join("Epic") - .join("EpicGamesLauncher") - .join("Data") - .join("Manifests"); - if path.exists() { - return Ok(path.to_str().unwrap().to_string()); - } else { - return Err(PathNotFound { - path: path.to_str().unwrap().to_string(), - }); - } + #[cfg(target_os = "windows")] + { + let key = "SYSTEMDRIVE"; + let system_drive = + env::var(key).expect("We are on windows, we must know what the SYSTEMDRIVE is"); + + let path = Path::new(format!("{}\\", system_drive).as_str()) + .join("ProgramData") + .join("Epic") + .join("EpicGamesLauncher") + .join("Data") + .join("Manifests"); + if path.exists() { + Some(path) + } else { + None } } } diff --git a/src/egs/mod.rs b/src/egs/mod.rs index 72d1fe4..09a9e8d 100644 --- a/src/egs/mod.rs +++ b/src/egs/mod.rs @@ -5,5 +5,6 @@ mod epic_platform; pub(crate) use manifest_item::*; use get_manifests::get_egs_manifests; +pub use get_manifests::get_default_location; pub use settings::EpicGamesLauncherSettings; pub use epic_platform::*; \ No newline at end of file diff --git a/src/egs/settings.rs b/src/egs/settings.rs index 949d401..ced0e99 100644 --- a/src/egs/settings.rs +++ b/src/egs/settings.rs @@ -1,6 +1,6 @@ -use serde::Deserialize; +use serde::{Serialize,Deserialize}; -#[derive(Debug, Deserialize,Clone)] +#[derive(Debug,Serialize, Deserialize,Clone)] pub struct EpicGamesLauncherSettings { pub enabled: bool, pub location: Option, diff --git a/src/itch/itch_platform.rs b/src/itch/itch_platform.rs index 0464152..de64429 100644 --- a/src/itch/itch_platform.rs +++ b/src/itch/itch_platform.rs @@ -79,7 +79,7 @@ fn dbpath_to_game(paths: &DbPaths<'_>) -> Option { } #[cfg(target_os = "linux")] -fn get_default_location() -> String { +pub fn get_default_location() -> String { //If we don't have a home drive we have to just die let home = std::env::var("HOME").expect("Expected a home variable to be defined"); format!("{}/.config/itch/", home) diff --git a/src/itch/settings.rs b/src/itch/settings.rs index 2115f89..6ef8ef4 100644 --- a/src/itch/settings.rs +++ b/src/itch/settings.rs @@ -1,6 +1,6 @@ -use serde::Deserialize; +use serde::{Serialize,Deserialize}; -#[derive(Debug, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct ItchSettings { pub enabled: bool, pub location: Option, diff --git a/src/legendary/settings.rs b/src/legendary/settings.rs index fdab6eb..7b14eb8 100644 --- a/src/legendary/settings.rs +++ b/src/legendary/settings.rs @@ -1,6 +1,6 @@ -use serde::Deserialize; +use serde::{Serialize,Deserialize}; -#[derive(Debug, Deserialize, Clone)] +#[derive(Debug, Deserialize, Serialize,Clone)] pub struct LegendarySettings { pub enabled: bool, pub executable: Option, diff --git a/src/main.rs b/src/main.rs index a1cf7af..8d070e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,13 @@ use crate::{ origin::OriginPlatform, steamgriddb::{download_images, CachedSearch}, }; -use std::{fs::File, io::Write, path::Path}; +use std::{ + cell::{Ref, RefCell}, + fs::File, + io::Write, + path::Path, + rc::Rc, +}; mod egs; mod itch; mod legendary; @@ -12,6 +18,7 @@ mod platform; mod settings; mod steam; mod steamgriddb; +use egs::get_default_location; #[cfg(feature = "ui")] use fltk::{app, prelude::*, window::Window}; #[cfg(feature = "ui")] @@ -31,41 +38,144 @@ use steam_shortcuts_util::{shortcut::ShortcutOwned, shortcuts_to_bytes, Shortcut async fn main() -> Result<(), Box> { #[cfg(feature = "ui")] { - let settings = Settings::new()?; + { + let app = app::App::default().with_scheme(app::Scheme::Gtk); - let app = app::App::default().with_scheme(app::Scheme::Gtk); - let mut ui = mainview::UserInterface::make_window(); + let settings = Rc::new(RefCell::new(Settings::new()?)); + let mut ui = mainview::UserInterface::make_window(); + update_ui_with_settings(&mut ui, &settings.clone().borrow()); + { + let save_ui = ui.clone(); + let mut save_button = ui.save_settings_button.clone(); + let save_settings = settings.clone(); + save_button.set_callback(move |cb| { + update_settings_with_ui_values(&mut save_settings.borrow_mut(), &save_ui); + save_settings_to_file(&save_settings.borrow()); + cb.set_label("Saved"); + }); + } + { + let mut synch_bytton = ui.synchronize_button.clone(); + let synch_ui = ui.clone(); + let sync_settings = settings.clone(); + synch_bytton.set_callback(move |cb| { + update_settings_with_ui_values(&mut sync_settings.borrow_mut(), &synch_ui); + run_sync(&sync_settings.borrow()); + cb.set_label("Synched"); + }); + } - ui.enable_steamgrid_db_checkbox - .set_value(settings.steamgrid_db.enabled); - ui.steamgrid_db_auth_key_input.set_value( - &settings - .steamgrid_db - .auth_key - .clone() - .unwrap_or(String::from("")), - ); - - ui.enable_legendary_checkbox - .set_value(settings.legendary.enabled); - ui.legendary_executable_input.set_value( - &settings - .legendary - .executable - .unwrap_or(String::from("legendary")), - ); - - ui.enable_egs_checkbox - .set_value(settings.epic_games.enabled); - app.run().unwrap(); + app.run().unwrap(); + } + Ok(()) + } + #[cfg(not(feature = "ui"))] + { + let settings = Settings::new()?; + run_sync(&settings).await } - - run_sync().await } -async fn run_sync() -> Result<(), Box> { - let settings = Settings::new()?; +fn empty_or_whitespace(input: String) -> Option { + if input.trim().is_empty() { + None + } else { + Some(input) + } +} +fn update_settings_with_ui_values(settings: &mut Settings, ui: &mainview::UserInterface) { + // Steam location + settings.steam.location = empty_or_whitespace(ui.steam_location_input.value()); + + // Steamgrid db + settings.steamgrid_db.enabled = ui.enable_steamgrid_db_checkbox.value(); + settings.steamgrid_db.auth_key = empty_or_whitespace(ui.steamgrid_db_auth_key_input.value()); + + // Legendary + settings.legendary.enabled = ui.enable_legendary_checkbox.value(); + settings.legendary.executable = empty_or_whitespace(ui.legendary_executable_input.value()); + + // Origin + settings.origin.enabled = ui.enable_origin_checkbox.value(); + settings.origin.path = empty_or_whitespace(ui.origin_folder_input.value()); + + // Epic + settings.epic_games.enabled = ui.enable_egs_checkbox.value(); + settings.epic_games.location = empty_or_whitespace(ui.epic_location_input.value()); + + // Itch + settings.itch.enabled = ui.enable_itch_checkbox.value(); + settings.itch.location = empty_or_whitespace(ui.itch_locatoin_input.value()); +} + +fn save_settings_to_file(settings: &Settings) { + let toml = toml::to_string(&settings).unwrap(); + std::fs::write("config.toml", toml).unwrap(); +} + +fn update_ui_with_settings(ui: &mut mainview::UserInterface, settings: &Settings) { + ui.enable_steamgrid_db_checkbox + .set_value(settings.steamgrid_db.enabled); + ui.steamgrid_db_auth_key_input.set_value( + &settings + .steamgrid_db + .auth_key + .clone() + .unwrap_or(String::from("")), + ); + ui.enable_legendary_checkbox + .set_value(settings.legendary.enabled); + ui.legendary_executable_input.set_value( + settings + .legendary + .executable + .clone() + .unwrap_or(String::from("legendary")) + .as_str(), + ); + ui.enable_egs_checkbox + .set_value(settings.epic_games.enabled); + let default_egs = get_default_location(); + let default_egs = default_egs + .map(|p| p.to_str().unwrap().to_owned()) + .unwrap_or(String::from("")); + let egs_location = settings + .epic_games + .location + .clone() + .unwrap_or(String::from(default_egs)); + ui.epic_location_input.set_value(&egs_location); + ui.enable_egs_checkbox + .set_value(settings.epic_games.enabled); + ui.enable_itch_checkbox.set_value(settings.itch.enabled); + let mut default_itch_location = itch::get_default_location(); + if !Path::new(&default_itch_location).exists() { + default_itch_location = String::from(""); + } + ui.enable_itch_checkbox.set_value(settings.itch.enabled); + ui.itch_locatoin_input.set_value( + &settings + .itch + .location + .clone() + .unwrap_or(default_itch_location), + ); + ui.enable_origin_checkbox.set_value(settings.origin.enabled); + let mut default_origin_location = origin::get_default_location(); + if !Path::new(&default_origin_location).exists() { + default_origin_location = String::from(""); + } + ui.origin_folder_input.set_value( + &settings + .origin + .path + .clone() + .unwrap_or(default_origin_location), + ); +} + +async fn run_sync(settings: &Settings) -> Result<(), Box> { let userinfo_shortcuts = get_shortcuts_paths(&settings.steam)?; println!("Found {} user(s)", userinfo_shortcuts.len()); for user in userinfo_shortcuts.iter() { diff --git a/src/origin/origin_platform.rs b/src/origin/origin_platform.rs index 09fdb48..b9cc95d 100644 --- a/src/origin/origin_platform.rs +++ b/src/origin/origin_platform.rs @@ -93,7 +93,7 @@ fn parse_id_from_file(i: &str) -> nom::IResult<&str, &str> { } #[cfg(target_os = "linux")] -fn get_default_location() -> String { +pub fn get_default_location() -> String { //TODO implement this for linux: // https://www.toptensoftware.com/blog/running-ea-origin-games-under-linux-via-steam-and-proton/ diff --git a/src/origin/settings.rs b/src/origin/settings.rs index fd2d699..b8ecdd2 100644 --- a/src/origin/settings.rs +++ b/src/origin/settings.rs @@ -1,6 +1,6 @@ -use serde::Deserialize; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize,Clone)] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct OriginSettings { pub enabled: bool, diff --git a/src/settings.rs b/src/settings.rs index 1d09a57..c05bd22 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,10 +1,13 @@ -use crate::{egs::EpicGamesLauncherSettings, itch::ItchSettings, legendary::LegendarySettings, origin::OriginSettings, steam::SteamSettings, steamgriddb::SteamGridDbSettings}; +use crate::{ + egs::EpicGamesLauncherSettings, itch::ItchSettings, legendary::LegendarySettings, + origin::OriginSettings, steam::SteamSettings, steamgriddb::SteamGridDbSettings, +}; use config::{Config, ConfigError, Environment, File}; -use serde::Deserialize; -use std::{env}; +use serde::{Deserialize, Serialize}; +use std::env; -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct Settings { pub debug: bool, pub epic_games: EpicGamesLauncherSettings, @@ -21,16 +24,6 @@ impl Settings { let default_str = include_str!("defaultconfig.toml"); s.merge(File::from_str(default_str, config::FileFormat::Toml))?; - - #[cfg(target_os = "linux")] - let enable_legendary = true; - #[cfg(target_os = "linux")] - let enable_epic = false; - - #[cfg(target_os = "windows")] - let enable_legendary = false; - #[cfg(target_os = "windows")] - let enable_epic = true; // Start off by merging in the "default" configuration file s.merge(File::with_name("config.toml").required(false))?; diff --git a/src/steam/settings.rs b/src/steam/settings.rs index f722e7c..749eed7 100644 --- a/src/steam/settings.rs +++ b/src/steam/settings.rs @@ -1,6 +1,6 @@ -use serde::Deserialize; +use serde::{Serialize,Deserialize}; -#[derive(Debug, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct SteamSettings{ pub location: Option, } \ No newline at end of file diff --git a/src/steamgriddb/settings.rs b/src/steamgriddb/settings.rs index 1eac065..5754aa4 100644 --- a/src/steamgriddb/settings.rs +++ b/src/steamgriddb/settings.rs @@ -1,6 +1,6 @@ -use serde::Deserialize; +use serde::{Serialize,Deserialize}; -#[derive(Debug, Deserialize)] +#[derive(Debug,Serialize, Deserialize)] pub struct SteamGridDbSettings { pub enabled: bool, pub auth_key: Option,