From c9cbafb560443bc1040e5fe8dd561946cc78dd84 Mon Sep 17 00:00:00 2001 From: Hannes Kuchelmeister Date: Thu, 17 Feb 2022 11:32:53 +0100 Subject: [PATCH] saving to light tmp file to speed up annotation --- src/constants.rs | 3 +- src/main.rs | 5 ++ src/state/mod.rs | 134 +++++++++++++++++++++++++++++++++++++---------- src/ui/mod.rs | 1 + 4 files changed, 113 insertions(+), 30 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 8187173..6d152a7 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -8,4 +8,5 @@ pub const NONE_STRING_OPTION: Option = None; pub const TOGGLE_NEIGHBOURS_TEXT_TOGGLED: &str = "Hide Neighbours"; pub const TOGGLE_NEIGHBOURS_TEXT: &str = "Show Neighbours"; -pub const SCALE_STEP: f64 = 1.0; \ No newline at end of file +pub const SCALE_STEP: f64 = 1.0; +pub const ANNOTATION_CACHE_FILE_ENDING: &str = "tmp_annotation"; diff --git a/src/main.rs b/src/main.rs index 6721968..f1352fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -132,6 +132,11 @@ fn build_ui(app: &Application) { image_ui.window.add_action(&skip_focus); image_ui.window.add_action(&back_focus); + let _sender = sender.clone(); + app.connect_shutdown(move |_| { + _sender.send(Message::Quit).unwrap(); + }); + image_ui.show(); receiver.attach(None, move |msg| { eprintln!("Received message: {:?}", msg); diff --git a/src/state/mod.rs b/src/state/mod.rs index 09de5d8..742f9d0 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -1,13 +1,13 @@ use std::fs; use std::io::Write; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::{collections::HashMap, time::Instant}; use gtk::{gio::File, prelude::FileExt}; use serde::{Deserialize, Serialize}; use serde_json::Value; -use crate::constants::NONE_STRING_OPTION; +use crate::constants::{ANNOTATION_CACHE_FILE_ENDING, NONE_STRING_OPTION}; #[derive(Debug)] pub enum Message { @@ -17,6 +17,7 @@ pub enum Message { PreviousImage, UI(UIMessage), OpenFile(File), + Quit, } // Messages that do not impact state @@ -36,8 +37,23 @@ pub struct State { stack_index: Option, focus_image_index: Option, file_name: Option, + annotation_cache: Vec, pub root_path: Option, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LightAnnotation { + stack_index: usize, + focus_image_index: usize, +} + +impl LightAnnotation { + pub fn new(stack_index: usize, focus_image_index: usize) -> Self { + LightAnnotation { + stack_index, + focus_image_index, + } + } +} impl State { pub fn new() -> Self { @@ -46,6 +62,7 @@ impl State { stack_index: None, focus_image_index: None, file_name: None, + annotation_cache: Vec::new(), root_path: None, } } @@ -58,6 +75,8 @@ impl State { match msg { Message::OpenFile(file) => { self.open(file); + self.integrate_tmp_file(); + self.delete_tmp_file(); } Message::NextImage => { self.skip(); @@ -67,9 +86,13 @@ impl State { } Message::MarkFocus => { self.mark_focus(); - self.save(); + self.save_tmp(); self.skip(); } + Message::Quit => { + self.save(); + self.delete_tmp_file(); + } Message::FocusLevelChange(lvl) => { self.set_focus_image_index(Some(*lvl)); } @@ -141,11 +164,47 @@ impl State { pub fn mark_focus(&mut self) { match (self.stack_index, self.focus_image_index) { (Some(stack_index), Some(_)) => { - self.stacks[stack_index].best_index = self.focus_image_index; + let best_index = self.focus_image_index; + self.stacks[stack_index].best_index = best_index; + if let Some(best_index) = best_index { + self.annotation_cache + .push(LightAnnotation::new(stack_index, best_index)) + } } (_, _) => {} } } + pub fn integrate_tmp_file(&mut self) { + self.get_file_path().map(|mut path| { + path.set_extension(ANNOTATION_CACHE_FILE_ENDING); + + if path.exists() { + let contents = + fs::read_to_string(path).expect("Something went wrong reading the file"); + + self.annotation_cache = serde_json::from_str(&contents).unwrap(); + self.integrate_annotation_cache(); + } else { + eprintln!("Tmp annotation file {:?} does not exist", path); + } + }); + } + fn integrate_annotation_cache(&mut self) { + self.annotation_cache.iter().for_each(|annotation| { + self.stacks.get_mut(annotation.stack_index).map(|x| { + x.best_index = Some(annotation.focus_image_index); + }); + }); + } + + pub fn delete_tmp_file(&mut self) { + self.get_file_path().map(|mut path| { + path.set_extension(ANNOTATION_CACHE_FILE_ENDING); + if path.exists() { + fs::remove_file(path).unwrap(); + } + }); + } pub fn open(&mut self, file: &File) { let filename = file.path().expect("Couldn't get file path"); @@ -183,40 +242,57 @@ impl State { } } - pub fn save(&self) { + fn save_file(path: PathBuf, content: &T) { + match fs::File::create(path) { + Ok(mut file) => { + let now = Instant::now(); + let contents = serde_json::to_string(content).expect("Could not serialize."); + let elapsed = now.elapsed(); + println!("Serialization: {:.2?}", elapsed); + + let now = Instant::now(); + match file.write(contents.as_bytes()) { + Ok(_) => {} + Err(e) => { + eprintln!( + "an error occured while saving annotation cache: {}", + e.to_string() + ); + } + } + let elapsed = now.elapsed(); + println!("Writing to file: {:.2?}", elapsed); + } + Err(e) => { + eprintln!("{}", e.to_string()); + } + }; + } + fn get_file_path(&self) -> Option { match (self.root_path.clone(), self.file_name.clone()) { (Some(root_path), Some(file_name)) => { - let path = Path::new(&root_path).join(Path::new(&file_name)); - match fs::File::create(path) { - Ok(mut file) => { - let now = Instant::now(); - let contents = - serde_json::to_string(&self.stacks).expect("Could not serialize data."); - let elapsed = now.elapsed(); - println!("Serialization: {:.2?}", elapsed); - - let now = Instant::now(); - match file.write(contents.as_bytes()) { - Ok(_) => {} - Err(e) => { - eprintln!("an error occured while saving: {}", e.to_string()); - } - } - let elapsed = now.elapsed(); - println!("Writing to file: {:.2?}", elapsed); - } - Err(e) => { - eprintln!("{}", e.to_string()); - } - }; + Some(Path::new(&root_path).join(Path::new(&file_name))) } (_, _) => { - // TODO: error dialogue eprintln!("No save path specified"); + None } } } + pub fn save_tmp(&self) { + self.get_file_path().map(|mut path| { + path.set_extension(ANNOTATION_CACHE_FILE_ENDING); + State::save_file(path, &self.annotation_cache); + }); + } + + pub fn save(&self) { + self.get_file_path().map(|path| { + State::save_file(path, &self.stacks); + }); + } + pub fn previous(&mut self) { let len = self.stacks.len(); if len == 0 { diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 14b4746..2ef4d40 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -275,6 +275,7 @@ impl ImageUI { } self.update_focus_scale(&state); } + Message::Quit => {} } } fn update_image(&self, annotation_image: &AnnotationImage, base_path: String) {