cadmus_core/view/settings_editor/kinds/
import.rs1use super::{SettingData, SettingIdentity, SettingKind, ToggleSettings, WidgetKind};
4use crate::fl;
5use crate::settings::{FileExtension, Settings};
6use crate::view::{Bus, EntryId, EntryKind, Event, ToggleEvent};
7
8pub struct ForceFullImport;
10
11impl SettingKind for ForceFullImport {
12 fn identity(&self) -> SettingIdentity {
13 SettingIdentity::ForceFullImport
14 }
15
16 fn label(&self, _settings: &Settings) -> String {
17 fl!("settings-import-force-full-import")
18 }
19
20 fn fetch(&self, _settings: &Settings) -> SettingData {
21 SettingData {
22 value: fl!("settings-general-trigger"),
23 widget: WidgetKind::ActionLabel(Event::Select(EntryId::RequestForceImport)),
24 }
25 }
26
27 fn handle(
28 &self,
29 _evt: &Event,
30 _settings: &mut Settings,
31 _bus: &mut Bus,
32 ) -> (Option<String>, bool) {
33 (None, false)
34 }
35}
36
37pub struct ImportSyncMetadata;
39
40impl SettingKind for ImportSyncMetadata {
41 fn identity(&self) -> SettingIdentity {
42 SettingIdentity::ImportSyncMetadata
43 }
44
45 fn label(&self, _settings: &Settings) -> String {
46 fl!("settings-import-sync-metadata")
47 }
48
49 fn fetch(&self, settings: &Settings) -> SettingData {
50 SettingData {
51 value: settings.import.sync_metadata.to_string(),
52 widget: WidgetKind::Toggle {
53 left_label: fl!("settings-general-toggle-on"),
54 right_label: fl!("settings-general-toggle-off"),
55 enabled: settings.import.sync_metadata,
56 tap_event: Event::Toggle(ToggleEvent::Setting(ToggleSettings::ImportSyncMetadata)),
57 },
58 }
59 }
60
61 fn handle(
62 &self,
63 evt: &Event,
64 settings: &mut Settings,
65 _bus: &mut Bus,
66 ) -> (Option<String>, bool) {
67 if let Event::Toggle(ToggleEvent::Setting(ToggleSettings::ImportSyncMetadata)) = evt {
68 settings.import.sync_metadata = !settings.import.sync_metadata;
69 return (Some(settings.import.sync_metadata.to_string()), true);
70 }
71 (None, false)
72 }
73}
74
75pub struct AllowedKindsSetting;
77
78impl SettingKind for AllowedKindsSetting {
79 fn identity(&self) -> SettingIdentity {
80 SettingIdentity::AllowedKinds
81 }
82
83 fn label(&self, _settings: &Settings) -> String {
84 fl!("settings-import-allowed-kinds")
85 }
86
87 fn fetch(&self, settings: &Settings) -> SettingData {
88 let entries = FileExtension::all()
89 .iter()
90 .copied()
91 .map(|kind| {
92 EntryKind::CheckBox(
93 kind.to_string().to_uppercase(),
94 EntryId::ToggleAllowedKind(kind),
95 settings.import.allowed_kinds.contains(&kind),
96 )
97 })
98 .collect();
99
100 SettingData {
101 value: kinds_summary(settings.import.allowed_kinds.len()),
102 widget: WidgetKind::SubMenu(entries),
103 }
104 }
105
106 fn handle(
107 &self,
108 evt: &Event,
109 settings: &mut Settings,
110 _bus: &mut Bus,
111 ) -> (Option<String>, bool) {
112 if let Event::Select(EntryId::ToggleAllowedKind(kind)) = evt {
113 if !settings.import.allowed_kinds.remove(kind) {
114 settings.import.allowed_kinds.insert(*kind);
115 }
116
117 return (
118 Some(kinds_summary(settings.import.allowed_kinds.len())),
119 true,
120 );
121 }
122
123 (None, false)
124 }
125
126 fn keep_menu_open(&self) -> bool {
127 true
128 }
129}
130
131fn kinds_summary(selected: usize) -> String {
132 format!("{selected} / {}", FileExtension::all().len())
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138 use crate::settings::{FileExtension, Settings};
139 use crate::view::{Bus, EntryKind, Event};
140 use std::collections::VecDeque;
141
142 mod force_full_import {
143 use super::*;
144
145 #[test]
146 fn identity_returns_force_full_import() {
147 let setting = ForceFullImport;
148 assert_eq!(setting.identity(), SettingIdentity::ForceFullImport);
149 }
150
151 #[test]
152 fn fetch_builds_action_label_requesting_force_import() {
153 let setting = ForceFullImport;
154 let settings = Settings::default();
155 let data = setting.fetch(&settings);
156
157 match data.widget {
158 WidgetKind::ActionLabel(Event::Select(EntryId::RequestForceImport)) => {}
159 other => panic!("expected ActionLabel(RequestForceImport), got {other:?}"),
160 }
161 }
162
163 #[test]
164 fn handle_ignores_events() {
165 let setting = ForceFullImport;
166 let mut settings = Settings::default();
167 let mut bus: Bus = VecDeque::new();
168
169 let result = setting.handle(&Event::Select(EntryId::About), &mut settings, &mut bus);
170
171 assert!(result.0.is_none());
172 assert!(!result.1);
173 }
174 }
175
176 mod import_sync_metadata {
177 use super::*;
178
179 #[test]
180 fn handle_toggle_disables_when_enabled() {
181 let setting = ImportSyncMetadata;
182 let mut settings = Settings::default();
183 settings.import.sync_metadata = true;
184 let mut bus: Bus = VecDeque::new();
185 let event = Event::Toggle(ToggleEvent::Setting(ToggleSettings::ImportSyncMetadata));
186
187 let result = setting.handle(&event, &mut settings, &mut bus);
188
189 assert!(result.0.is_some());
190 assert!(!settings.import.sync_metadata);
191 }
192
193 #[test]
194 fn handle_toggle_enables_when_disabled() {
195 let setting = ImportSyncMetadata;
196 let mut settings = Settings::default();
197 settings.import.sync_metadata = false;
198 let mut bus: Bus = VecDeque::new();
199 let event = Event::Toggle(ToggleEvent::Setting(ToggleSettings::ImportSyncMetadata));
200
201 let result = setting.handle(&event, &mut settings, &mut bus);
202
203 assert!(result.0.is_some());
204 assert!(settings.import.sync_metadata);
205 }
206
207 #[test]
208 fn handle_returns_none_for_wrong_event() {
209 let setting = ImportSyncMetadata;
210 let mut settings = Settings::default();
211 let mut bus: Bus = VecDeque::new();
212 use crate::view::EntryId;
213
214 let result = setting.handle(&Event::Select(EntryId::About), &mut settings, &mut bus);
215
216 assert!(result.0.is_none());
217 }
218
219 #[test]
220 fn handle_returns_none_for_wrong_toggle() {
221 let setting = ImportSyncMetadata;
222 let mut settings = Settings::default();
223 let mut bus: Bus = VecDeque::new();
224
225 let result = setting.handle(
226 &Event::Toggle(ToggleEvent::Setting(ToggleSettings::SleepCover)),
227 &mut settings,
228 &mut bus,
229 );
230
231 assert!(result.0.is_none());
232 }
233 }
234
235 mod allowed_kinds_setting {
236 use super::*;
237
238 #[test]
239 fn fetch_builds_checkbox_submenu_for_all_extensions() {
240 let setting = AllowedKindsSetting;
241 let settings = Settings::default();
242
243 let data = setting.fetch(&settings);
244
245 assert_eq!(
246 data.value,
247 kinds_summary(settings.import.allowed_kinds.len())
248 );
249 let WidgetKind::SubMenu(entries) = data.widget else {
250 panic!("expected submenu widget");
251 };
252 assert_eq!(entries.len(), FileExtension::all().len());
253 assert!(matches!(
254 entries.first(),
255 Some(EntryKind::CheckBox(_, EntryId::ToggleAllowedKind(_), _))
256 ));
257 }
258
259 #[test]
260 fn handle_toggle_adds_and_removes_extensions() {
261 let setting = AllowedKindsSetting;
262 let mut settings = Settings::default();
263 settings.import.allowed_kinds.remove(&FileExtension::Cbr);
264 let mut bus: Bus = VecDeque::new();
265
266 let add = setting.handle(
267 &Event::Select(EntryId::ToggleAllowedKind(FileExtension::Cbr)),
268 &mut settings,
269 &mut bus,
270 );
271 assert_eq!(
272 add.0,
273 Some(kinds_summary(settings.import.allowed_kinds.len()))
274 );
275 assert!(settings.import.allowed_kinds.contains(&FileExtension::Cbr));
276
277 let remove = setting.handle(
278 &Event::Select(EntryId::ToggleAllowedKind(FileExtension::Cbr)),
279 &mut settings,
280 &mut bus,
281 );
282 assert_eq!(
283 remove.0,
284 Some(kinds_summary(settings.import.allowed_kinds.len()))
285 );
286 assert!(!settings.import.allowed_kinds.contains(&FileExtension::Cbr));
287 }
288 }
289}