Files
gpx.studio/gpx-rs/src/engine/command/edit/metadata.rs
T

175 lines
4.9 KiB
Rust
Raw Normal View History

2026-10-26 18:51:56 +01:00
use crate::{
Apply, CommandError, Edit, Editor, File, Route, State, Track, TrackInfo, update_selected,
};
2026-10-03 16:40:17 +02:00
#[derive(Debug)]
pub struct Metadata<'a> {
pub name: &'a str,
pub desc: &'a str,
}
impl Apply for Metadata<'_> {
fn apply(mut self, state: &mut State) -> Result<(), CommandError> {
update_selected(state, &mut self);
Ok(())
}
}
2026-10-26 18:51:56 +01:00
impl Metadata<'_> {
fn set(&self, info: &mut TrackInfo) -> Edit {
info.name = Some(self.name.to_owned());
info.desc = Some(self.desc.to_owned());
Edit::Changed
}
}
2026-10-03 16:40:17 +02:00
impl Editor for Metadata<'_> {
fn file(&mut self, file: &mut File) -> Edit {
file.info.name = self.name.to_owned();
file.info.desc = Some(self.desc.to_owned());
2026-10-26 18:51:56 +01:00
// a single route or track is named like the file
match (file.rte.as_mut_slice(), file.trk.as_mut_slice()) {
([route], []) => route.info.name = Some(self.name.to_owned()),
([], [track]) => track.info.name = Some(self.name.to_owned()),
_ => {}
2026-10-04 11:00:46 +02:00
}
2026-10-03 16:40:17 +02:00
Edit::Changed
}
2026-10-26 18:51:56 +01:00
fn route(&mut self, route: &mut Route) -> Edit {
self.set(&mut route.info)
}
2026-10-03 16:40:17 +02:00
fn track(&mut self, track: &mut Track) -> Edit {
2026-10-26 18:51:56 +01:00
self.set(&mut track.info)
2026-10-03 16:40:17 +02:00
}
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
2026-10-04 11:00:46 +02:00
use crate::{New, NewTrack, Selection, engine::command::fixture::Fixture};
2026-10-03 16:40:17 +02:00
use super::*;
#[test]
fn test_metadata_applies_to_selected_file() {
let mut fx = Fixture::default();
2026-10-07 17:58:17 +02:00
New {
name: "first",
trackpoint: None,
}
.apply(&mut fx.state())
.unwrap();
New {
name: "second",
trackpoint: None,
}
.apply(&mut fx.state())
.unwrap(); // now selected
2026-10-03 16:40:17 +02:00
let selected = *fx.selected_files().iter().next().unwrap();
Metadata {
name: "renamed",
desc: "description",
}
.apply(&mut fx.state())
.unwrap();
for (id, file) in fx.files.iter() {
if *id == selected {
assert_eq!(file.info.name, "renamed");
assert_eq!(file.info.desc.as_deref(), Some("description"));
} else {
assert_eq!(file.info.name, "first");
assert_eq!(file.info.desc, None);
}
}
}
#[test]
fn test_metadata_applies_to_selected_track() {
let mut fx = Fixture::default();
let data = std::fs::read("data/with_tracks.gpx").unwrap();
2026-10-04 11:07:12 +02:00
crate::Load {
data: &data,
name: "file",
}
.apply(&mut fx.state())
.unwrap();
2026-10-03 16:40:17 +02:00
let file = fx.files.values().next().unwrap().clone();
fx.selection = Selection::Track {
file_id: file.id,
trk_ids: HashSet::from([file.trk[0].id]),
};
Metadata {
name: "renamed",
desc: "",
}
.apply(&mut fx.state())
.unwrap();
let after = &fx.files[&file.id];
assert_eq!(after.info.name, file.info.name);
assert_eq!(after.trk[0].info.name.as_deref(), Some("renamed"));
assert_eq!(after.trk[1].info, file.trk[1].info);
}
2026-10-04 11:00:46 +02:00
/// A new file with `nb_tracks` tracks (without name), selected.
fn file_with_tracks(fx: &mut Fixture, nb_tracks: usize) {
2026-10-07 17:58:17 +02:00
New {
name: "file",
trackpoint: None,
}
.apply(&mut fx.state())
.unwrap();
2026-10-04 11:00:46 +02:00
for _ in 0..nb_tracks {
NewTrack.apply(&mut fx.state()).unwrap();
}
}
fn rename(fx: &mut Fixture) {
Metadata {
name: "renamed",
desc: "",
}
.apply(&mut fx.state())
.unwrap();
}
#[test]
fn test_single_track_is_renamed_like_the_file() {
let mut fx = Fixture::default();
file_with_tracks(&mut fx, 1);
rename(&mut fx);
let file = fx.files.values().next().unwrap();
assert_eq!(file.info.name, "renamed");
assert_eq!(file.trk[0].info.name.as_deref(), Some("renamed"));
}
#[test]
fn test_single_track_with_a_name_is_renamed_too() {
let mut fx = Fixture::default();
file_with_tracks(&mut fx, 1);
let id = *fx.files.keys().next().unwrap();
std::rc::Rc::make_mut(fx.files.get_mut(&id).unwrap()).trk[0]
.info
.name = Some("track".to_owned());
rename(&mut fx);
let file = &fx.files[&id];
assert_eq!(file.info.name, "renamed");
assert_eq!(file.trk[0].info.name.as_deref(), Some("renamed"));
}
#[test]
fn test_several_tracks_are_not_renamed() {
let mut fx = Fixture::default();
file_with_tracks(&mut fx, 2);
rename(&mut fx);
let file = fx.files.values().next().unwrap();
assert_eq!(file.info.name, "renamed");
assert!(file.trk.iter().all(|trk| trk.info.name.is_none()));
}
2026-10-03 16:40:17 +02:00
}