From eb4bb58549499876b871dbf8c20c6e20d31902be Mon Sep 17 00:00:00 2001 From: Arthur Roberts Date: Sun, 4 Jun 2023 12:08:42 +0100 Subject: [PATCH] Added start of config stuff --- Cargo.toml | 5 ++- src/config.rs | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/infos.rs | 19 ++++++++++ src/main.rs | 33 ++++++++-------- 4 files changed, 140 insertions(+), 19 deletions(-) create mode 100644 src/config.rs create mode 100644 src/infos.rs diff --git a/Cargo.toml b/Cargo.toml index e3075c8..553056b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,7 @@ edition = "2021" [dependencies] eframe = "0.21.3" -rfd = "*" \ No newline at end of file +rfd = "0.11.4" +serde = "1.0.163" +serde_derive = "1.0.163" +toml = "0.7.4" diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..1b61460 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,102 @@ +use toml; +use serde_derive::{Deserialize, Serialize}; +use crate::infos::{WadInfo, LauncherInfo}; +use std::path::PathBuf; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Config { + iwads: Option>, + pwads: Option>, + launchers: Option>, +} + +pub fn load_config(path: &PathBuf) -> Result> { + let content = std::fs::read_to_string(&path)?; + Ok(toml::from_str(&content)?) +} + +pub fn save_config(path: &PathBuf, config: &Config) -> Result<(), Box> { + let toml_string = toml::to_string(&config).unwrap(); + Ok(std::fs::write(path, toml_string)?) +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn basic_iwad() { + let config_str = "[[iwads]]\n\ + name = \"DOOM2.WAD\"\n\ + path = \"/home/wads/doom.wad\"\n"; + let config: Result = toml::from_str(&config_str); + assert!(config.is_ok()); + let config = config.unwrap(); + assert_eq!(config.iwads.unwrap().len(), 1); + } + #[test] + fn basic_iwads() { + let config_str = "[[iwads]] +name = \"DOOM2.WAD\" +path = \"/home/wads/doom.wad\" + +[[iwads]] +name = \"DOOM1.WAD1.9\" +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")); + } + + #[test] + fn iwads_and_pwads() { + let config_str = "[[iwads]] +name = \"DOOM2.WAD\" +path = \"/home/wads/doom.wad\" + +[[iwads]] +name = \"DOOM1.WAD1.9\" +path = \"/home/wads/doom1.9.wad\" + +[[pwads]] +name = \"Ancient Aliens\" +path = \"/home/pwads/aa.pk3\""; + + let config: Config = toml::from_str(&config_str).unwrap(); + 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")); + } + + #[test] + fn iwads_back_and_forth() { + let iwad1 = WadInfo { + path: PathBuf::from("/home/wads/doom.wad"), + name: "DOOM.WAD".to_string(), + }; + let iwad2 = WadInfo { + path: PathBuf::from("/home/wads/doom2.wad"), + name: "DOOM2.WAD".to_string(), + }; + let iwads = vec![iwad1, iwad2]; + let launcher = LauncherInfo { + path: PathBuf::from("/home/bin/gzdoom/gzdoom"), + name: "GZDoom".to_string(), + }; + let config = Config { + iwads: Some(iwads), + launchers: Some(vec![launcher]), + pwads: None, + }; + let toml_as_str = toml::to_string(&config).unwrap(); + 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 new file mode 100644 index 0000000..9cce723 --- /dev/null +++ b/src/infos.rs @@ -0,0 +1,19 @@ +use serde_derive::{Deserialize, Serialize}; +use std::path::PathBuf; + +// TODO - write some impl stuff in here so the main GUI stuff +// is a little bit more decoupled from this. I think a Display +// and perhaps the path to string conversion too could be +// removed from the GUI part + +#[derive(Serialize, Deserialize, Debug)] +pub struct WadInfo { + pub path: PathBuf, + pub name: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct LauncherInfo { + pub path: PathBuf, + pub name: String, +} diff --git a/src/main.rs b/src/main.rs index a78c04b..148fc60 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,9 @@ use eframe::egui; use std::path::PathBuf; +use infos::{WadInfo, LauncherInfo}; + +pub mod config; +pub mod infos; fn main() -> Result<(), eframe::Error> { println!("Hello, world!"); @@ -13,16 +17,6 @@ fn main() -> Result<(), eframe::Error> { ) } -struct WadInfo { - path: PathBuf, - name: String, -} - -struct LauncherInfo { - path: PathBuf, - name: String, -} - struct RustDoomLauncher { all_launchers: Vec, all_iwads: Vec, @@ -102,7 +96,6 @@ impl eframe::App for RustDoomLauncher { }); ui.separator(); ui.vertical(|ui| { - // TODO add default name as the path or something ui.label("Add WADs etc"); ui.set_max_width(180.0); ui.horizontal(|ui| { @@ -110,7 +103,8 @@ impl eframe::App for RustDoomLauncher { ui.text_edit_singleline(&mut self.name) .labelled_by(name_label.id); }); - + // It kind of feels like the right place to use a closure - unsure whether I need + // to pass both of these vaules in, or what the story is here. let get_name = |path: &PathBuf, name: &String| { if self.name.is_empty() { // Check this perhaps? Unsure whether the FileDialog can actually @@ -125,7 +119,7 @@ impl eframe::App for RustDoomLauncher { if let Some(path) = rfd::FileDialog::new().pick_file() { self.all_launchers.push(LauncherInfo { name: get_name(&path, &self.name), - path: path + path, }); } } @@ -133,7 +127,7 @@ impl eframe::App for RustDoomLauncher { if let Some(path) = rfd::FileDialog::new().pick_file() { self.all_iwads.push(WadInfo { name: get_name(&path, &self.name), - path: path, + path, }); } } @@ -141,7 +135,7 @@ impl eframe::App for RustDoomLauncher { if let Some(path) = rfd::FileDialog::new().pick_file() { self.all_pwads.push(WadInfo { name: get_name(&path, &self.name), - path: path.clone(), + path, }); } } @@ -153,9 +147,12 @@ impl eframe::App for RustDoomLauncher { // but it'll at least do the highlighting when hovered nicely if let Some(l) = self.selected_launcher { if let Some(iwad) = self.all_launchers.get(l) { - if ui.add(egui::SelectableLabel::new(false, &iwad.name)).clicked() { - self.selected_launcher = None; - } + if ui + .add(egui::SelectableLabel::new(false, &iwad.name)) + .clicked() + { + self.selected_launcher = None; + } } else { self.selected_launcher = None; }