rvlib/tools/
attributes.rs1use tracing::info;
2
3use super::Manipulate;
4use crate::{
5 annotations_accessor_mut,
6 events::Events,
7 file_util::PathPair,
8 history::History,
9 make_tool_transform,
10 result::trace_ok_err,
11 tools_data::attributes_data::{set_attrmap_val, AttrMap, AttrVal},
12 tools_data_accessors,
13 world::World,
14 world_annotations_accessor,
15};
16use std::mem;
17const MISSING_DATA_MSG: &str = "Missing data for Attributes";
18pub const ACTOR_NAME: &str = "Attributes";
19annotations_accessor_mut!(ACTOR_NAME, attributes_mut, "Attribute didn't work", AttrMap);
20world_annotations_accessor!(ACTOR_NAME, attributes, "Attribute didn't work", AttrMap);
21tools_data_accessors!(
22 ACTOR_NAME,
23 MISSING_DATA_MSG,
24 attributes_data,
25 AttributesToolData,
26 attributes,
27 attributes_mut
28);
29
30fn propagate_annos(
31 mut annos: AttrMap,
32 attr_names: &[String],
33 to_propagate: &[(usize, AttrVal)],
34) -> AttrMap {
35 for (attr_idx, val) in to_propagate {
36 if let Some(attr_val) = annos.get_mut(&attr_names[*attr_idx]) {
37 *attr_val = val.clone();
38 }
39 }
40 annos
41}
42
43fn propagate_buffer(
44 mut attribute_buffer: Vec<String>,
45 to_propagate: &[(usize, AttrVal)],
46) -> Vec<String> {
47 for (attr_idx, val) in to_propagate {
48 attribute_buffer[*attr_idx] = val.to_string();
49 }
50 attribute_buffer
51}
52fn file_change(mut world: World) -> World {
53 let annos = get_annos_mut(&mut world).map(mem::take);
54 let data = get_specific_mut(&mut world);
55
56 if let (Some(data), Some(mut annos)) = (data, annos) {
57 for (attr_name, attr_val) in data.attr_names().iter().zip(data.attr_vals().iter()) {
58 if !annos.contains_key(attr_name) {
59 set_attrmap_val(&mut annos, attr_name, attr_val);
60 }
61 }
62
63 let attr_buffers: Vec<String> = data
65 .attr_names()
66 .iter()
67 .map(|attr_name| annos.get(attr_name).unwrap().to_string())
68 .collect();
69 let attr_buffers = propagate_buffer(attr_buffers, &data.to_propagate_attr_val);
70 for (i, buffer) in attr_buffers.into_iter().enumerate() {
71 *data.attr_value_buffer_mut(i) = buffer;
72 }
73
74 annos = propagate_annos(annos, data.attr_names(), &data.to_propagate_attr_val);
75
76 if let Some(annos_) = get_annos_mut(&mut world) {
77 *annos_ = annos;
78 }
79 }
80 let current = get_annos(&world).cloned();
81 if let Some(data) = get_specific_mut(&mut world) {
82 data.current_attr_map = current;
83 }
84 world
85}
86#[derive(Clone, Copy, Debug)]
87pub struct Attributes;
88
89impl Manipulate for Attributes {
90 fn new() -> Self
91 where
92 Self: Sized,
93 {
94 Self
95 }
96
97 fn on_activate(&mut self, mut world: World) -> World {
98 let data = get_data_mut(&mut world);
99 if let Some(data) = trace_ok_err(data) {
100 data.menu_active = true;
101 }
102 file_change(world)
103 }
104 fn on_deactivate(&mut self, mut world: World) -> World {
105 let data = get_data_mut(&mut world);
106 if let Some(data) = trace_ok_err(data) {
107 data.menu_active = false;
108 }
109 world
110 }
111 fn on_filechange(&mut self, world: World, history: History) -> (World, History) {
112 (file_change(world), history)
113 }
114 fn events_tf(
115 &mut self,
116 mut world: World,
117 history: History,
118 _event: &Events,
119 ) -> (World, History) {
120 let is_addition_triggered = get_specific(&world).map(|d| d.options.is_addition_triggered);
121 if is_addition_triggered == Some(true) {
122 let attr_map_tmp = get_annos_mut(&mut world).map(mem::take);
123 let data = get_specific_mut(&mut world);
124
125 if let (Some(mut attr_map_tmp), Some(data)) = (attr_map_tmp, data) {
126 let new_attr_name = data.new_attr_name.clone();
127 if data.attr_names().contains(&new_attr_name) {
128 tracing::error!(
129 "New attribute {new_attr_name} could not be created, already exists"
130 );
131 } else {
132 let new_attr_val = data.new_attr_val.clone();
133 for (_, (val_map, _)) in data.anno_iter_mut() {
134 set_attrmap_val(val_map, &new_attr_name, &new_attr_val);
135 }
136 set_attrmap_val(&mut attr_map_tmp, &new_attr_name, &new_attr_val);
137 if let Some(a) = get_annos_mut(&mut world) {
138 a.clone_from(&attr_map_tmp);
139 }
140 if let Some(data) = get_specific_mut(&mut world) {
141 data.current_attr_map = Some(attr_map_tmp);
142 data.push(new_attr_name, new_attr_val);
143 }
144 }
145 }
146 if let Some(is_add_triggered_out) =
147 get_specific_mut(&mut world).map(|d| &mut d.options.is_addition_triggered)
148 {
149 *is_add_triggered_out = false;
150 }
151 }
152 let attr_data = get_specific_mut(&mut world);
153 if let Some(attr_data) = attr_data {
154 if let Some(rename_src_idx) = attr_data.options.rename_src_idx {
155 let from_name = &attr_data.attr_names()[rename_src_idx].clone();
156 let to_name = &attr_data.new_attr_name.clone();
157 tracing::info!("Rename attribute {from_name} to {to_name}");
158 attr_data.rename(from_name, to_name);
159 attr_data.options.rename_src_idx = None;
160 }
161 }
162 let is_update_triggered = get_specific(&world).map(|d| d.options.is_update_triggered);
163 if is_update_triggered == Some(true) {
164 info!("update attr");
165 let current_from_menu_clone =
166 get_specific(&world).and_then(|d| d.current_attr_map.clone());
167 if let (Some(mut cfm), Some(anno)) =
168 (current_from_menu_clone, get_annos_mut(&mut world))
169 {
170 *anno = mem::take(&mut cfm);
171 }
172 if let Some(update_current_attr_map) =
173 get_specific_mut(&mut world).map(|d| &mut d.options.is_update_triggered)
174 {
175 *update_current_attr_map = false;
176 }
177 }
178 if let Some(removal_idx) = get_specific(&world).map(|d| d.options.removal_idx) {
179 let data = get_specific_mut(&mut world);
180 if let (Some(data), Some(removal_idx)) = (data, removal_idx) {
181 data.remove_attr(removal_idx);
182 }
183 if let Some(removal_idx) =
184 get_specific_mut(&mut world).map(|d| &mut d.options.removal_idx)
185 {
186 *removal_idx = None;
187 }
188 }
189 let is_export_triggered = get_specific(&world).map(|d| d.options.is_export_triggered);
190 if is_export_triggered == Some(true) {
191 let ssh_cfg = world.data.meta_data.ssh_cfg.clone();
192 let attr_data = get_specific(&world);
193 let export_only_opened_folder =
194 attr_data.map(|d| d.options.export_only_opened_folder) == Some(true);
195 let key_filter = if export_only_opened_folder {
196 world
197 .data
198 .meta_data
199 .opened_folder
200 .as_ref()
201 .map(PathPair::path_relative)
202 } else {
203 None
204 };
205 let annos_str = get_specific(&world)
206 .and_then(|d| trace_ok_err(d.serialize_annotations(key_filter)));
207 if let (Some(annos_str), Some(data)) = (annos_str, get_specific(&world)) {
208 if trace_ok_err(data.export_path.conn.write(
209 &annos_str,
210 &data.export_path.path,
211 ssh_cfg.as_ref(),
212 ))
213 .is_some()
214 {
215 info!("exported annotations to {:?}", data.export_path.path);
216 }
217 }
218 if let Some(is_export_triggered) =
219 get_specific_mut(&mut world).map(|d| &mut d.options.is_export_triggered)
220 {
221 *is_export_triggered = false;
222 }
223 }
224 make_tool_transform!(self, world, history, event, [])
225 }
226}