Skip to main content

cadmus_core/view/settings_editor/kinds/
import.rs

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