use adw::prelude::*; use gtk::gio; use relm4::prelude::*; use crate::subtitles::{MetadataCollection, StreamIndex}; use crate::track_selector::{ TrackInfo, TrackSelector, TrackSelectorInit, TrackSelectorMsg, TrackSelectorOutput, }; #[derive(Clone, Copy, Default, Debug)] pub struct SubtitleSettings { pub primary_track_ix: Option, pub secondary_track_ix: Option, pub show_secondary: bool, pub show_machine_translation: bool, } pub struct SubtitleSelectionDialog { parent_window: adw::ApplicationWindow, dialog: adw::PreferencesDialog, primary_selector: Controller, secondary_selector: Controller, settings: SubtitleSettings, } #[derive(Debug)] pub enum SubtitleSelectionDialogMsg { Show, Close, // ui messages PrimaryTrackChanged(StreamIndex), SecondaryTrackChanged(StreamIndex), ShowSecondaryChanged(bool), ShowMachineTranslationChanged(bool), } #[derive(Debug)] pub enum SubtitleSelectionDialogOutput { ApplySubtitleSettings(SubtitleSettings), } #[relm4::component(pub)] impl SimpleComponent for SubtitleSelectionDialog { type Init = (adw::ApplicationWindow, MetadataCollection); type Input = SubtitleSelectionDialogMsg; type Output = SubtitleSelectionDialogOutput; view! { #[root] adw::PreferencesDialog { set_title: "Subtitle Settings", add: &page, connect_closed => SubtitleSelectionDialogMsg::Close, }, #[name(page)] adw::PreferencesPage { adw::PreferencesGroup { model.primary_selector.widget(), adw::ExpanderRow { set_title: "Show secondary subtitles", set_subtitle: "Enable this if there exist subtitles a language you already know", set_show_enable_switch: true, #[watch] set_enable_expansion: model.settings.show_secondary, connect_enable_expansion_notify[sender] => move |expander_row| { sender.input(SubtitleSelectionDialogMsg::ShowSecondaryChanged(expander_row.enables_expansion())) }, add_row: model.secondary_selector.widget(), }, adw::ExpanderRow { set_title: "Show machine translations", set_subtitle: "This is useful in case there are no subtitles in your native language or you prefer a more direct translation of the primary subtitles", set_show_enable_switch: true, #[watch] set_enable_expansion: model.settings.show_machine_translation, connect_enable_expansion_notify[sender] => move |expander_row| { sender.input(SubtitleSelectionDialogMsg::ShowMachineTranslationChanged(expander_row.enables_expansion())) }, // TODO add row for language selection }, } }, } fn init( init: Self::Init, root: Self::Root, sender: ComponentSender, ) -> ComponentParts { let (parent_window, metadata) = init; let primary_selector = TrackSelector::builder() .launch(TrackSelectorInit { title: "Primary subtitle track", subtitle: Some("Select your target language here"), }) .forward(sender.input_sender(), |output| match output { TrackSelectorOutput::Changed(ix) => { SubtitleSelectionDialogMsg::PrimaryTrackChanged(ix) } }); let secondary_selector = TrackSelector::builder() .launch(TrackSelectorInit { title: "Secondary subtitle track", subtitle: Some("Pick a language you already know"), }) .forward(sender.input_sender(), |output| match output { TrackSelectorOutput::Changed(ix) => { SubtitleSelectionDialogMsg::SecondaryTrackChanged(ix) } }); let model = Self { parent_window, dialog: root.clone(), primary_selector, secondary_selector, settings: Default::default(), }; let widgets = view_output!(); let track_list_model = gio::ListStore::new::(); for (&stream_index, track_metadata) in metadata.subtitles.iter() { let track_info = TrackInfo::new( stream_index, track_metadata.language.map(|lang| lang.to_name()), track_metadata.title.clone(), ); track_list_model.append(&track_info); } model .primary_selector .sender() .send(TrackSelectorMsg::SetListModel(track_list_model.clone())) .unwrap(); model .secondary_selector .sender() .send(TrackSelectorMsg::SetListModel(track_list_model.clone())) .unwrap(); ComponentParts { model, widgets } } fn update(&mut self, msg: Self::Input, sender: ComponentSender) { match msg { SubtitleSelectionDialogMsg::Show => { self.dialog.present(Some(&self.parent_window)); } SubtitleSelectionDialogMsg::Close => sender .output(SubtitleSelectionDialogOutput::ApplySubtitleSettings( self.settings, )) .unwrap(), SubtitleSelectionDialogMsg::PrimaryTrackChanged(stream_ix) => { self.settings.primary_track_ix = Some(stream_ix); } SubtitleSelectionDialogMsg::SecondaryTrackChanged(stream_ix) => { self.settings.secondary_track_ix = Some(stream_ix); } SubtitleSelectionDialogMsg::ShowSecondaryChanged(val) => { self.settings.show_secondary = val; } SubtitleSelectionDialogMsg::ShowMachineTranslationChanged(val) => { self.settings.show_machine_translation = val; } } } }