cadmus_core/view/settings_editor/kinds/
dictionary.rs1use super::{SettingData, SettingIdentity, SettingKind, WidgetKind};
4use crate::fl;
5use crate::settings::Settings;
6use crate::view::{EntryId, EntryKind, Event};
7
8pub struct DictionaryInfo {
17 pub lang: String,
19 pub is_installed: bool,
21 pub update_available: bool,
23 pub is_installing: bool,
25}
26
27impl SettingKind for DictionaryInfo {
28 fn identity(&self) -> SettingIdentity {
29 SettingIdentity::DictionaryInfo(self.lang.clone())
30 }
31
32 fn label(&self, _settings: &Settings) -> String {
33 self.lang.clone()
34 }
35
36 fn handle(
37 &self,
38 evt: &Event,
39 _settings: &mut Settings,
40 _bus: &mut crate::view::Bus,
41 ) -> (Option<String>, bool) {
42 match evt {
43 Event::Select(entry) => match entry {
44 EntryId::DownloadDictionary(lang) | EntryId::RedownloadDictionary(lang)
45 if lang == &self.lang =>
46 {
47 (Some(fl!("settings-dictionaries-downloading")), false)
48 }
49 _ => (None, false),
50 },
51 _ => (None, false),
52 }
53 }
54
55 fn fetch(&self, _settings: &Settings) -> SettingData {
56 if self.is_installing {
57 return SettingData {
58 value: fl!("settings-dictionaries-downloading"),
59 widget: WidgetKind::None,
60 };
61 }
62
63 if self.is_installed {
64 let mut entries = Vec::new();
65
66 if self.update_available {
67 entries.push(EntryKind::Command(
68 fl!("settings-dictionaries-update"),
69 EntryId::RedownloadDictionary(self.lang.clone()),
70 ));
71 } else {
72 entries.push(EntryKind::Command(
73 fl!("settings-dictionaries-re-download"),
74 EntryId::RedownloadDictionary(self.lang.clone()),
75 ));
76 }
77
78 entries.push(EntryKind::Command(
79 fl!("settings-dictionaries-delete"),
80 EntryId::DeleteDictionary(self.lang.clone()),
81 ));
82
83 let value = if self.update_available {
84 fl!("settings-dictionaries-update-available")
85 } else {
86 fl!("settings-dictionaries-installed")
87 };
88
89 SettingData {
90 value,
91 widget: WidgetKind::SubMenu(entries),
92 }
93 } else {
94 SettingData {
95 value: fl!("settings-dictionaries-download"),
96 widget: WidgetKind::ActionLabel(Event::Select(EntryId::DownloadDictionary(
97 self.lang.clone(),
98 ))),
99 }
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use crate::settings::Settings;
108 use crate::view::Bus;
109 use std::collections::VecDeque;
110
111 fn make_settings() -> Settings {
112 Settings::default()
113 }
114
115 mod fetch {
116 use super::*;
117
118 #[test]
119 fn uninstalled_yields_action_label_with_download_event() {
120 let info = DictionaryInfo {
121 lang: "en".to_string(),
122 is_installed: false,
123 update_available: false,
124 is_installing: false,
125 };
126 let data = info.fetch(&make_settings());
127
128 assert!(matches!(
129 data.widget,
130 WidgetKind::ActionLabel(Event::Select(EntryId::DownloadDictionary(ref l)))
131 if l == "en"
132 ));
133 }
134
135 #[test]
136 fn installed_yields_submenu_with_redownload_and_delete() {
137 let info = DictionaryInfo {
138 lang: "fr".to_string(),
139 is_installed: true,
140 update_available: false,
141 is_installing: false,
142 };
143 let data = info.fetch(&make_settings());
144
145 let WidgetKind::SubMenu(entries) = data.widget else {
146 panic!("expected SubMenu");
147 };
148 assert_eq!(entries.len(), 2);
149 assert!(matches!(
150 &entries[0],
151 EntryKind::Command(_, EntryId::RedownloadDictionary(l)) if l == "fr"
152 ));
153 assert!(matches!(
154 &entries[1],
155 EntryKind::Command(_, EntryId::DeleteDictionary(l)) if l == "fr"
156 ));
157 }
158
159 #[test]
160 fn update_available_yields_submenu_with_update_first() {
161 let info = DictionaryInfo {
162 lang: "de".to_string(),
163 is_installed: true,
164 update_available: true,
165 is_installing: false,
166 };
167 let data = info.fetch(&make_settings());
168
169 let WidgetKind::SubMenu(entries) = data.widget else {
170 panic!("expected SubMenu");
171 };
172 assert_eq!(entries.len(), 2);
173 assert!(matches!(
174 &entries[0],
175 EntryKind::Command(label, EntryId::RedownloadDictionary(l))
176 if l == "de" && label == "Update"
177 ));
178 assert!(matches!(
179 &entries[1],
180 EntryKind::Command(_, EntryId::DeleteDictionary(l)) if l == "de"
181 ));
182 assert_eq!(data.value, "Update Available");
183 }
184
185 #[test]
186 fn is_installing_yields_none_widget() {
187 let info = DictionaryInfo {
188 lang: "es".to_string(),
189 is_installed: false,
190 update_available: false,
191 is_installing: true,
192 };
193 let data = info.fetch(&make_settings());
194
195 assert!(matches!(data.widget, WidgetKind::None));
196 }
197
198 #[test]
199 fn is_installing_takes_priority_over_installed() {
200 let info = DictionaryInfo {
201 lang: "es".to_string(),
202 is_installed: true,
203 update_available: true,
204 is_installing: true,
205 };
206 let data = info.fetch(&make_settings());
207
208 assert!(matches!(data.widget, WidgetKind::None));
209 }
210 }
211
212 mod handle {
213 use super::*;
214
215 #[test]
216 fn download_event_returns_downloading_string() {
217 let info = DictionaryInfo {
218 lang: "en".to_string(),
219 is_installed: false,
220 update_available: false,
221 is_installing: false,
222 };
223 let mut settings = make_settings();
224 let mut bus: Bus = VecDeque::new();
225 let event = Event::Select(EntryId::DownloadDictionary("en".to_string()));
226
227 let (display, consumed) = info.handle(&event, &mut settings, &mut bus);
228
229 assert!(display.is_some());
230 assert!(!consumed);
231 }
232
233 #[test]
234 fn redownload_event_returns_downloading_string() {
235 let info = DictionaryInfo {
236 lang: "en".to_string(),
237 is_installed: true,
238 update_available: false,
239 is_installing: false,
240 };
241 let mut settings = make_settings();
242 let mut bus: Bus = VecDeque::new();
243 let event = Event::Select(EntryId::RedownloadDictionary("en".to_string()));
244
245 let (display, consumed) = info.handle(&event, &mut settings, &mut bus);
246
247 assert!(display.is_some());
248 assert!(!consumed);
249 }
250
251 #[test]
252 fn event_for_different_lang_returns_none() {
253 let info = DictionaryInfo {
254 lang: "en".to_string(),
255 is_installed: false,
256 update_available: false,
257 is_installing: false,
258 };
259 let mut settings = make_settings();
260 let mut bus: Bus = VecDeque::new();
261 let event = Event::Select(EntryId::DownloadDictionary("fr".to_string()));
262
263 let (display, _) = info.handle(&event, &mut settings, &mut bus);
264
265 assert!(display.is_none());
266 }
267
268 #[test]
269 fn unrelated_event_returns_none() {
270 let info = DictionaryInfo {
271 lang: "en".to_string(),
272 is_installed: false,
273 update_available: false,
274 is_installing: false,
275 };
276 let mut settings = make_settings();
277 let mut bus: Bus = VecDeque::new();
278
279 let (display, _) = info.handle(&Event::Select(EntryId::About), &mut settings, &mut bus);
280
281 assert!(display.is_none());
282 }
283 }
284}