heic2jpg

git clone git://archive.git.mtrnord.blog/MTRNord/heic2jpg.git
Log | Files | Refs | README | LICENSE

select_folder.rs (4070B)


      1 use gettextrs::gettext;
      2 use gtk::prelude::*;
      3 use relm4::{
      4     adw, gtk, Component, ComponentController, ComponentParts, ComponentSender, Controller,
      5     SimpleComponent,
      6 };
      7 use relm4_components::open_dialog::*;
      8 use std::path::PathBuf;
      9 
     10 #[derive(Debug, PartialEq)]
     11 pub(crate) enum InOut {
     12     Input,
     13     Output,
     14 }
     15 
     16 #[derive(Debug)]
     17 pub(crate) struct SelectFolder {
     18     open_dialog: Controller<OpenDialog>,
     19     folder: Option<PathBuf>,
     20     description: String,
     21     button_label: String,
     22     direction: InOut,
     23 }
     24 
     25 #[derive(Debug)]
     26 pub(crate) enum SelectFolderMsg {
     27     OpenRequest,
     28     OpenResponse(PathBuf),
     29     Ignore,
     30 }
     31 
     32 #[derive(Debug)]
     33 pub(crate) enum SelectFolderOut {
     34     FolderSelected(PathBuf),
     35     AbortLast,
     36 }
     37 
     38 #[relm4::component(pub)]
     39 impl SimpleComponent for SelectFolder {
     40     type Init = InOut;
     41     type Input = SelectFolderMsg;
     42     type Output = SelectFolderOut;
     43 
     44     view! {
     45         adw::StatusPage {
     46             set_hexpand: true,
     47             set_vexpand: true,
     48             set_title: &gettext("Select Folder"),
     49             set_description: Some(&model.description),
     50             set_icon_name: Some("mouse-click"),
     51 
     52             gtk::Box {
     53                 set_halign: gtk::Align::Center,
     54                 set_orientation: gtk::Orientation::Horizontal,
     55                 set_spacing: 24,
     56 
     57                 gtk::Button {
     58                     set_halign: gtk::Align::Center,
     59                     set_label: &model.button_label,
     60                     add_css_class: "suggested-action",
     61                     add_css_class: "pill",
     62                     connect_clicked[sender] => move |_| {
     63                         sender.input(SelectFolderMsg::OpenRequest);
     64                     }
     65                 },
     66 
     67                 // If this is the output folder selector, add an Restart button
     68                 gtk::Button {
     69                     set_visible: model.direction == InOut::Output,
     70                     set_halign: gtk::Align::Center,
     71                     set_label: &gettext("Restart"),
     72                     add_css_class: "destructive-action",
     73                     connect_clicked[sender] => move |_| {
     74                         let _ = sender.output(SelectFolderOut::AbortLast);
     75                     }
     76                 }
     77             }
     78         }
     79     }
     80 
     81     fn init(
     82         init: Self::Init,
     83         root: Self::Root,
     84         sender: ComponentSender<Self>,
     85     ) -> ComponentParts<Self> {
     86         let (description, button_label) = match init {
     87             InOut::Input => (
     88                 gettext("Select the folder where the Heic files can be found"),
     89                 gettext("Select input directory"),
     90             ),
     91             InOut::Output => (
     92                 gettext("Select the folder where the JPG files are meant to be saved"),
     93                 gettext("Select output directory"),
     94             ),
     95         };
     96 
     97         let dialog_settings = OpenDialogSettings {
     98             folder_mode: true,
     99             ..Default::default()
    100         };
    101 
    102         let open_dialog = OpenDialog::builder()
    103             .transient_for_native(&root)
    104             .launch(dialog_settings)
    105             .forward(sender.input_sender(), |response| match response {
    106                 OpenDialogResponse::Accept(path) => SelectFolderMsg::OpenResponse(path),
    107                 OpenDialogResponse::Cancel => SelectFolderMsg::Ignore,
    108             });
    109 
    110         let model = Self {
    111             open_dialog,
    112             folder: None,
    113             description: description.to_string(),
    114             button_label: button_label.to_string(),
    115             direction: init,
    116         };
    117 
    118         let widgets = view_output!();
    119         ComponentParts { model, widgets }
    120     }
    121 
    122     fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
    123         match message {
    124             SelectFolderMsg::OpenRequest => self.open_dialog.emit(OpenDialogMsg::Open),
    125             SelectFolderMsg::OpenResponse(path) => {
    126                 self.folder = Some(path.clone());
    127                 let _ = sender.output(SelectFolderOut::FolderSelected(path.clone()));
    128             }
    129             SelectFolderMsg::Ignore => {}
    130         }
    131     }
    132 }