diff --git a/src/edit.rs b/src/edit.rs index 1bab333..425eed7 100644 --- a/src/edit.rs +++ b/src/edit.rs @@ -1,4 +1,4 @@ -use std::{collections::BTreeMap, fs::OpenOptions, num::NonZeroU8, path::PathBuf}; +use std::{collections::BTreeMap, num::NonZeroU8}; use iced::{ theme, @@ -10,10 +10,11 @@ use iced::{ }; use iced_aw::{card, modal, number_input, selection_list}; use itertools::Itertools; +use serde::{Deserialize, Serialize}; use crate::{ - calc::calc_parser, BoxIter, Config, ContributionPoint, Message, Report, ReportDate, SaveFile, - Spendings, LIST_RULE, SECTION_RULE, TEXT_EMPH1, TEXT_EMPH2, TEXT_H1, TEXT_H2, + calc::calc_parser, BoxIter, Config, ContributionPoint, Message, Report, ReportDate, Spendings, + LIST_RULE, SECTION_RULE, TEXT_EMPH1, TEXT_EMPH2, TEXT_H1, TEXT_H2, }; struct AddFixed { @@ -778,7 +779,6 @@ pub struct EditState { recurring: BTreeMap, variable: BTreeMap)>, savings: BTreeMap, - save_file: PathBuf, earnings_1: f64, earnings_2: f64, average: NonZeroU8, @@ -850,15 +850,22 @@ macro_rules! msg2 { }; } +#[derive(Serialize, Deserialize, Default)] +pub(crate) struct EditSaveFile { + #[serde(flatten)] + pub current: Report, + #[serde(default)] + pub archive: BTreeMap, +} + impl EditState { - pub fn new(save_file: PathBuf) -> Self { + pub fn new() -> Self { Self { recurring: Default::default(), savings: Default::default(), variable: Default::default(), earnings_1: Default::default(), earnings_2: Default::default(), - save_file, average: NonZeroU8::MIN, date: None, } @@ -910,8 +917,8 @@ impl EditState { } } - pub(super) fn save(&self, archive: BTreeMap, pretty: bool) { - let mut save = SaveFile { + pub(super) fn save(&self, archive: BTreeMap) -> EditSaveFile { + let mut save = EditSaveFile { current: Default::default(), archive, }; @@ -923,20 +930,7 @@ impl EditState { None => save.current = self.report(), } - let tmp_path = format!(".glaurung-{}", std::process::id()); - let save_file = OpenOptions::new() - .create(true) - .write(true) - .truncate(true) - .open(&tmp_path) - .expect("Can't open temp save file"); - let to_writer = match pretty { - true => serde_json::to_writer_pretty, - false => serde_json::to_writer, - }; - to_writer(save_file, &save).expect("could not write save file"); - - std::fs::rename(tmp_path, &self.save_file).expect("could not save data"); + save } pub(super) fn update(&mut self, message: EditMessage) { diff --git a/src/main.rs b/src/main.rs index ffed6e2..611b6b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use std::{ collections::BTreeMap, - fs::File, + fs::{File, OpenOptions}, io::BufReader, num::NonZeroU8, ops::{Mul, MulAssign, Sub, SubAssign}, @@ -11,7 +11,7 @@ use anyhow::anyhow; use calc::calc_parser; use compare::Compare; use directories::ProjectDirs; -use edit::{EditMessage, EditState}; +use edit::{EditMessage, EditState, EditSaveFile}; use either::Either; use iced::{ font, subscription, @@ -203,7 +203,7 @@ pub(crate) trait Spendings { } #[derive(Serialize, Deserialize, Clone)] -struct Report { +pub(crate) struct Report { #[serde(default)] recurring: BTreeMap, #[serde(default)] @@ -283,7 +283,7 @@ impl Spendings for (ReportDate, Report) { } #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Hash)] -struct ReportDate { +pub(crate) struct ReportDate { pub year: u64, pub month: u8, } @@ -362,9 +362,7 @@ impl<'de> Deserialize<'de> for ReportDate { #[derive(Serialize, Deserialize, Default)] struct SaveFile { #[serde(flatten)] - current: Report, - #[serde(default)] - archive: BTreeMap, + edit: EditSaveFile, } #[derive(Default)] @@ -417,6 +415,8 @@ struct Glaurung { edit: EditState, view: CurrentView, + save_file: PathBuf, + compare_left: Option, compare_right: Option, @@ -436,6 +436,26 @@ impl Glaurung { .map(|rep| (e, Box::new((r, rep.clone())) as Box)), } } + + fn save(&self) { + let edit = self.edit.save(self.archive.clone()); + let save = SaveFile { edit }; + + let tmp_path = format!(".glaurung-{}", std::process::id()); + let save_file = OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(&tmp_path) + .expect("Can't open temp save file"); + let to_writer = match self.config.pretty_save { + true => serde_json::to_writer_pretty, + false => serde_json::to_writer, + }; + to_writer(save_file, &save).expect("could not write save file"); + + std::fs::rename(tmp_path, &self.save_file).expect("could not save data"); + } } impl Application for Glaurung { @@ -447,14 +467,15 @@ impl Application for Glaurung { fn new(config: Self::Flags) -> (Self, Command) { let mut this = Self { config: config.config, - edit: EditState::new(config.save_file), - archive: config.save.archive, + edit: EditState::new(), + save_file: config.save_file, + archive: config.save.edit.archive, view: CurrentView::Edit, compare_left: None, compare_right: None, }; - this.edit.load(None, config.save.current); + this.edit.load(None, config.save.edit.current); ( this, @@ -481,14 +502,12 @@ impl Application for Glaurung { Message::FontLoaded(r) => r.expect("could not load font"), Message::Event(ev) => { if let Event::Window(window::Event::CloseRequested) = ev { - self.edit - .save(self.archive.clone(), self.config.pretty_save); + self.save(); return window::close(); } } Message::Load(d) => { - self.edit - .save(self.archive.clone(), self.config.pretty_save); + self.save(); self.edit .load(Some(d), self.archive.get(&d).cloned().unwrap_or_default()); }