diff --git a/Cargo.toml b/Cargo.toml index 553056b..d2b9d31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +directories = "5.0.1" eframe = "0.21.3" rfd = "0.11.4" serde = "1.0.163" diff --git a/src/config.rs b/src/config.rs index 1b61460..0131d17 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,30 +1,53 @@ -use toml; +use crate::infos::{LauncherInfo, WadInfo}; use serde_derive::{Deserialize, Serialize}; -use crate::infos::{WadInfo, LauncherInfo}; use std::path::PathBuf; +use toml; +use directories; #[derive(Serialize, Deserialize, Debug)] pub struct Config { - iwads: Option>, - pwads: Option>, - launchers: Option>, + pub iwads: Option>, + pub pwads: Option>, + pub launchers: Option>, +} + +impl Default for Config { + fn default() -> Self { + Config { + iwads: None, + pwads: None, + launchers: None, + } + } } pub fn load_config(path: &PathBuf) -> Result> { + if !path.exists() { + return Ok(Config::default()); + } let content = std::fs::read_to_string(&path)?; Ok(toml::from_str(&content)?) } pub fn save_config(path: &PathBuf, config: &Config) -> Result<(), Box> { + let prefix = path.parent().unwrap(); + std::fs::create_dir_all(prefix).unwrap(); let toml_string = toml::to_string(&config).unwrap(); Ok(std::fs::write(path, toml_string)?) } - + +pub fn default_save_filename() -> PathBuf { + let project = directories::ProjectDirs::from("party", "arfy", "rdl").unwrap(); + let mut full_path = PathBuf::new(); + full_path.push(project.config_dir()); + full_path.push("wads_and_stuff.toml"); + full_path +} #[cfg(test)] mod tests { use super::*; - + #[test] fn basic_iwad() { let config_str = "[[iwads]]\n\ @@ -47,12 +70,15 @@ path = \"/home/wads/doom1.9.wad\""; let config: Config = toml::from_str(&config_str).unwrap(); // I'm not 100% sure why I need all of these as_ref - assert_eq!(config.iwads.as_ref().unwrap().len(),2); - assert_eq!(config.iwads.as_ref().unwrap()[0].name,"DOOM2.WAD"); - assert_eq!(config.iwads.as_ref().unwrap()[1].name,"DOOM1.WAD1.9"); - assert_eq!(config.iwads.unwrap()[0].path, PathBuf::from("/home/wads/doom.wad")); + assert_eq!(config.iwads.as_ref().unwrap().len(), 2); + assert_eq!(config.iwads.as_ref().unwrap()[0].name, "DOOM2.WAD"); + assert_eq!(config.iwads.as_ref().unwrap()[1].name, "DOOM1.WAD1.9"); + assert_eq!( + config.iwads.unwrap()[0].path, + PathBuf::from("/home/wads/doom.wad") + ); } - + #[test] fn iwads_and_pwads() { let config_str = "[[iwads]] @@ -71,7 +97,10 @@ path = \"/home/pwads/aa.pk3\""; assert_eq!(config.iwads.as_ref().unwrap().len(), 2); assert_eq!(config.iwads.unwrap()[0].name, "DOOM2.WAD"); assert_eq!(config.pwads.as_ref().unwrap()[0].name, "Ancient Aliens"); - assert_eq!(config.pwads.unwrap()[0].path, PathBuf::from("/home/pwads/aa.pk3")); + assert_eq!( + config.pwads.unwrap()[0].path, + PathBuf::from("/home/pwads/aa.pk3") + ); } #[test] @@ -98,5 +127,4 @@ path = \"/home/pwads/aa.pk3\""; let new_config: Config = toml::from_str(&toml_as_str).unwrap(); assert_eq!(config.iwads.unwrap().len(), new_config.iwads.unwrap().len()); } - } diff --git a/src/infos.rs b/src/infos.rs index 9cce723..d35b1a2 100644 --- a/src/infos.rs +++ b/src/infos.rs @@ -6,13 +6,13 @@ use std::path::PathBuf; // and perhaps the path to string conversion too could be // removed from the GUI part -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct WadInfo { pub path: PathBuf, pub name: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct LauncherInfo { pub path: PathBuf, pub name: String, diff --git a/src/main.rs b/src/main.rs index 148fc60..b032f93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,18 @@ use eframe::egui; use std::path::PathBuf; +use config::{default_save_filename, save_config, load_config, Config}; use infos::{WadInfo, LauncherInfo}; pub mod config; pub mod infos; fn main() -> Result<(), eframe::Error> { - println!("Hello, world!"); - let options = eframe::NativeOptions { + let gui_options = eframe::NativeOptions { ..Default::default() }; eframe::run_native( "Rust Doom Launcher", - options, + gui_options, Box::new(|_cc| Box::::default()), ) } @@ -25,6 +25,8 @@ struct RustDoomLauncher { selected_iwad: Option, selected_pwads: Vec, name: String, + config_filename: PathBuf, + config_file_loaded: bool, } impl Default for RustDoomLauncher { @@ -37,12 +39,51 @@ impl Default for RustDoomLauncher { selected_iwad: None, selected_pwads: Vec::new(), name: "".to_string(), + config_filename: default_save_filename(), + config_file_loaded: false, + } + } +} + +impl RustDoomLauncher { + // There must be a better way than this - maybe for the RustDoomLauncher to + // have a config thing + fn get_config_file_stuff(&mut self) -> () { + let config = load_config(&self.config_filename).unwrap(); + if let Some(iwads) = config.iwads { + for iwad in iwads { + self.all_iwads.push(iwad.clone()); + } + } + if let Some(pwads) = config.pwads { + for pwad in pwads { + self.all_pwads.push(pwad.clone()); + } + } + if let Some(launchers) = config.launchers { + for launcher in launchers { + self.all_launchers.push(launcher.clone()); + } } } } impl eframe::App for RustDoomLauncher { + fn on_close_event(&mut self) -> bool { + let config = Config { + iwads: Some(self.all_iwads.clone()), + pwads: Some(self.all_pwads.clone()), + launchers: Some(self.all_launchers.clone()), + }; + save_config(&self.config_filename, &config); + true + } + fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + if self.config_file_loaded == false { + self.get_config_file_stuff(); + self.config_file_loaded = true; + } egui::containers::panel::CentralPanel::default().show(ctx, |ui| { ui.heading("RustDoomLauncher"); ui.horizontal_wrapped(|ui| {