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